Swift コンパイラーのビルド環境を Linux に作ってみる
Swift プログラミング
サクッと簡単にではあるのですけど、Ubuntu Linux 上に Swift コンパイラーをビルドする環境を構築してみた様子を綴っておきます。
だいぶ前に構築したきり、あまり触れることのなかった Open Source 版の Swift ビルド環境でしたけど、また少し触ってみようかなって思って、振り返りも兼ねて最初から構築し直してみることにしました。今回利用する環境は Ubuntu Linux 16.04.2 LTS です。
今回、試す上で参考にさせて頂いた資料は、Apple Swift Open Source の swift/README.md と、@rintaroさん の Swift コンパイラ開発環境構築 、そして @eduraaaさん の Inside Of Swift です。とっても素敵な資料たち、どうもありがとうございます!
ビルド環境構築
まずは、公式の swift/README.md に沿って Swift のビルド環境を整えてみます。
環境構築に必要なパッケージをインストールする
今回は Linux 環境へのビルド環境構築なので、まずは次のようにして、それに必要なパッケージをインストールします。
sudo apt-get install git cmake ninja-build clang python uuid-dev libicu-dev icu-devtools libbsd-dev libedit-dev libxml2-dev libsqlite3-dev swig libpython-dev libncurses5-dev pkg-config libblocksruntime-dev libcurl4-openssl-dev autoconf libtool systemtap-sdt-dev tzdata
ソースコードの保存場所を作る
そして Swift ソースコードを入れるためのディレクトリーをどこかに作成します。今回は /home/tomohiro
に作成しようと思うので、次のようにして、そのディレクトリーに移動して swift-source
を作成します。
cd /home/tomohiro
mkdir swift-source
そうしたら、先ほど作成したディレクトリーに移動しておきます。
cd swift-source/
ここに Swift コンパイラーをビルドするために必要なソースコードを取得していきます。
ソースコードセットを取得する
Swift コンパイラーは幾つかのリポジトリーにあるソースコードを使って構成されているので、それらをすべて取得する必要があります。それを自動で行えるスクリプトが apple/swift リポジトリー内に utils/update-checkout スクリプトとして用意されているので、その Swift リポジトリーをクローンしてそのスクリプトを実行します。
git clone git@github.com:apple/swift.git
./swift/utils/update-checkout --clone-with-ssh
ネットワークの調子で大きく変わると思うのですけど、とりあえず apple/swift
リポジトリーのクローンにかかった時間は、自分の試した環境では 11 分ほどでした。そんな環境で update-checkout
は 35 分ほどで終わりました。
時点のソースコードの合計容量は 1.8GB ほどでした。
取得されたソースコードたち
このようにして取得してみると、
現在、swift-source
ディレクトリーには次のサブディレクトリーが作成されていました。それぞれの用途などを分かる範囲で調べてみると、次のようになっている様子です。
名称 | 用途 | リポジトリー |
---|---|---|
clang | C 言語系のコンパイラーでフロントエンドを担当するもの | apple/swift-clang.git |
compiler-rt | 主に Clang や LLVM で使われる コンパイラーランタイムライブラリ ? | apple/swift-compiler-rt.git |
lldb | Swift 言語と REPL をサポートした LLDB(デバッガー) | apple/swift-lldb.git |
ninja | 速度重視のコンパクトなビルドシステム(make コマンドみたいなものの様子) | ninja-build/ninja.git |
swift-corelibs-foundation | Swift コアライブラリーのひとつに位置付けられている Foundation フレームワーク(macOS や iOS の Cocoa/Cocoa Touch フレームワークでお馴染み) | apple/swift-corelibs-foundation.git |
swift-corelibs-xctest | Swift コアライブラリーのひとつに位置付けられている XCTest フレームワーク(Xcode でお馴染みの単体テスト) | apple/swift-corelibs-xctest.git |
swiftpm | Swift 用のパッケージマネージャー(CocoaPods や Carthage みたいなもの) | apple/swift-package-manager.git |
cmark | CommonMark という Markdown ライクな軽量マークアップ言語 | apple/swift-cmark.git |
llbuild | Xcode 9 や Swift Package Manager で使われる、低レベルのビルドシステムのライブラリーセット | apple/swift-llbuild.git |
llvm | 最適化機能やバイナリ生成機能などを備えたコンパイラー基盤(ミドルエンドとバックエンドを担当) | apple/swift-llvm.git |
swift | Swift 言語コンパイラー | apple/swift.git |
swift-corelibs-libdispatch | Swift コアライブラリーのひとつに位置付けられている Dispatch フレームワーク(並列処理機能、GCD) | apple/swift-corelibs-libdispatch.git |
swift-integration-tests | 生成された Swift スナップショットが正しく生成されたかどうかを検証するための自動テスト? | apple/swift-integration-tests.git |
swift-xcode-playground-support | Swift ツールチェインが Xcode と通信するためのログ収集や通信手段を提供(Xcode Playground で使用) | apple/swift-xcode-playground-support.git |
どのリポジトリーがどんなフォルダー名で取得されるかは utils/update-checkout-config.json
に記載されています。ここでは "branch-scheme" によって、どのブランチからソースコードを取得するかも記載されていて、スキームは update-checkout
実行時にも切り替えられるようになっています。
Swift コンパイラーをビルドする
ライブラリーセットを取得したら、Swift リポジトリーにある utils/build-script を使って、次のようにすることでビルドできます。
./utils/build-script --release-debuginfo
こうすることで Swift コンパイラーがビルドできます。Ubuntu Linux 環境では、ビルドされたコンパイラーは swift-source/build/Ninja-RelWithDebInfoAssert/swift-linux-x86_64
ディレクトリーの bin
ディレクトリー内に生成されました。
時点のソースコードを --release-debuginfo
でビルドすると、合計 55GB ほどの生成物が ./build
ディレクトリーに生成される様子でした。ちなみに --release
でビルドした場合は 3.2GB ほどになりました。
部分的なビルド
いったん全てのビルドを終えると、以降はターゲットを指定してビルドすることも可能になるそうです。たとえば Swift コンパイラーだけをビルドしたい場合は ビルドしたファイルが生成されたディレクトリー内で 次のようにします。
ninja swift
たとえば Linux 環境で -release-debuginfo
を添えてビルドした場合は、ビルドの出力ディレクトリーが swift-source/build/Ninja-RelWithDebInfoAssert/swift-linux-x86_64
になっているので、そのディレクトリーに移動してから上記のコマンドを実行するか、以下のようにディレクトリーを指定して ninja
を実行します。
ninja -C /home/tomohiro/swift-source/build/Ninja-RelWithDebInfoAssert/swift-linux-x86_64 swift
どんなターゲットが存在しているかは、ビルドディレクトリーの中に生成されている build.ninja
ファイル内の # Target aliases.
の行以下に build ターゲット名: phony ...
という形で記されている様子でした。
ビルドの所要時間
ビルドにかかる時間は環境性能に大きく依存するようで、全てのターゲットをビルドしたときの環境と時間をまとめると、次のような感じでした。ちなみにメモリーは 32GB あれば大丈夫そうな印象です。
OS | CPU | メモリー | ビルド時間 |
---|---|---|---|
Linux | Core i7 6950X 3.0GHz × 20 | 128GB | 約 17 分 |
Linux | Core i7 6800K 3.4GHz × 12 | 128GB | 約 21 分 |
macOS | Core i7 3.6GHz × 8 (iMac Retina 4K 21.5-inch 2017 ) | 32GB | 約 60 分 |
macOS | Core i5 2.7GHz × 8 (iMac 21.5-inch Late 2013 ) | 16GB | 約 97 分 |
コンパイラーオプション
公式の README では、ビルドオプションとして --release-debuginfo
が添えられていました。これについては自分がまだよくわかっていないのですけど、Swift とその構成部品を RelWithDebInfo
指定でビルドすることで、最適化等が図られた上でデバッグ情報が添えられるビルドモード…なのでしょうか。
公式 README.md には、上記の --release-debuginfo
に加えて、--debug-swift
や --debug-swift-stdlib
などを添えることで、部品ごとに Debug
ビルドを行う指定もできる様子です。
なお --debug
で、全てをデバッグビルドできるようになっていますけど、ビルドに多くの時間が必要になるとのことでした。まだ分からないですけれど、ひとまずは --release-debuginfo
指定でビルドしておく感じで良いのかもしれません。
Xcode 用のプロジェクトは作れない
これは Linux 環境の場合 に限られるはずなのですけど、Xcode 用のプロジェクトを生成するためのオプション --xcode
を指定しての utils/build-script
は実行できない様子でした。実行してみると、次のエラーメッセージが表示されます。
CMake Error: Could not create named generator Xcode
ひとまずここまで
これでひとまず Linux 環境で Open Source 版の Swift を入手してビルドする方法の初歩的なところを試すことができました。
この辺りについては、以前に Swift 愛好会 vol19 と 第72回 Cocoa勉強会関西 で簡単ながら発表した資料もあるので添付しておきます。
まとめ
最後に Swift ビルド環境についてまとめておきます。
- 環境は macOS または Ubuntu linux
- CPU はコア数が多いほどビルド時間が短縮される
- メモリーは 32GB あれば不足することは少なそう(64GB あると安心)
- ディスク容量は、ビルドも含めると 200GB は欲しい
--debug
と--release-debuginfo
の両方でビルドすると、それだけで 100GB を超えるrelease
ビルドだけなら 20GB くらいあれば十分な気もしますけど、枯渇すると面倒