SwiftPM ライブラリとシステムモジュールを作る方法

SwiftPMでは2種類のパッケージを作れます。

  • ライブラリ
    一般的なライブラリを作成します。
    例えばAlamofireKingfisherなどのようなライブラリを作りたい場合はこちらになります。

  • システムモジュール
    外部ライブラリなどをモジュール化できます。
    libxml2やCommonCryptoなどをモジュール化する場合はこちらになります。

ライブラリを作る

作業ディレクトリ作成

$ mkdir SamplePackage
$ cd $_
$ swift package init --type library // swift package init でもOK
Creating library package: SamplePackage
Creating Package.swift
Creating .gitignore
Creating Sources/
Creating Sources/SamplePackage.swift
Creating Tests/
Creating Tests/LinuxMain.swift
Creating Tests/SamplePackageTests/
Creating Tests/SamplePackageTests/SamplePackageTests.swift

依存パッケージ設定

ライブラリは依存パッケージを持つことができます。
これにより例えばAlamofireを内部で利用するライブラリなどが作れます。

Package.swiftに依存関係を指定します。

import PackageDescription

let package = Package(
    name: "SamplePackage",
    dependencies: [
        .Package(url: "git@github.com:Alamofire/Alamofire.git", majorVersion: 4)
    ]
)

依存パッケージがなければ何も指定しません。

除外設定

ディレクトリに関係のないファイルやディレクトリ(ドキュメントなど)があるとビルドに失敗することがあります。
その場合、関係のないものをパッケージから除外するよう exclude で指定する必要があります。

import PackageDescription

let package = Package(
name: "SamplePackage",
exclude: ["Docs"]
)

コーディング

Sources/SamplePackage.swift にコードを記述します。
公開したいプロトコル・クラス・構造体・関数などはアクセス修飾子publicまたはopenを指定してください。

テストコードはTests/SamplePackageTests/SamplePackageTests.swiftに記述します。

ビルド

$ swift build

テスト

$ swift test

公開

SwiftPMのパッケージとして公開するにはGitHubにリポジトリを作成し、タグを作ります。

$ git init
$ git add .
$ git remote add origin [GitHub URL]
$ git commit -m "Initial commit"
$ git tag 1.0.0
$ git push origin master --tags

タグ名は下記フォーマットに従う必要があります。
このフォーマットに従っていないとSwiftPMでは利用できません。

"major.minor.patch[-prereleaseIdentifiers][+buildMetadata]"

補足

複数モジュールを含むライブラリを作る

Sourcesディレクトリ内にサブディレクトリを作ると別モジュールになります。

Sources/Foo/Widget.swift
Sources/Bar/Bazzer.swift

このディレクトリ構成ではモジュールFooBarが作成されるのでパッケージを使う側は、
Widget.swiftの内容にアクセスするにはimport Fooする必要があり、
Bazzer.swiftの内容にアクセスするにはimport Barする必要があります。

Objective-Cでコードを書く

ディレクトリ構成に制限がありますが、SwiftだけでなくC言語やObjective-Cなども使えます。
(対応言語:C / C++ / Objective-C / Objective-C++)
基本的な構成の例は下記の通りです。

Sources/Baz/m.c
Sources/Baz/include/m.h

この例ではモジュールBazが作成され、import BazすることでC言語で書いた関数などにアクセスできるようになります。

詳細はドキュメント“C language targets”で確認してください。

システムモジュールを作る

libxml2をモジュール化する方法を紹介します。

作業ディレクトリ作成

$ mkdir SwiftClibxml2
$ cd $_
$ swift package init --type system-module
Creating system-module package: CommonCrypto
Creating Package.swift
Creating .gitignore
Creating module.modulemap

コーディング

import PackageDescription

let package = Package(
    name: "SwiftClibxml2",
    pkgConfig: "libxml-2.0",
    providers: [
        .Brew("libxml2"),
        .Apt("libxml2-dev")
    ]
)
module SwiftClibxml2 [system] {
    header "libxml2.h"
    link "xml2"
    export *
}
#import <libxml2/libxml/tree.h>
#import <libxml2/libxml/parser.h>
#import <libxml2/libxml/HTMLtree.h>
#import <libxml2/libxml/HTMLparser.h>
#import <libxml2/libxml/xpath.h>
#import <libxml2/libxml/xpathInternals.h>

Providers

libxml2を使うにはシステムにlibxml2がインストールされている必要があります。
これはPackageの引数providersに指定することでユーザーに教えることができます。

providers: [
.Brew("libxml2"), // homebrew
.Apt("libxml2-dev") // apt-get
]

インストールされていないときは下記のようなメッセージが表示されます。

note: you may be able to install libxml-2.0 using your system-packager:

brew install libxml2

公開する

ライブラリと同じ方法で公開します。

参考

Swift Package Manager Documentation