最近 Windows でも Swift コンパイラ, libdispatch, foundation がビルドできるようなり、簡単なプログラムを動かせるようになってきたのでその方法を紹介します。
環境構築
- OS: Windows 10 1809
- PC: 速いやつ
- ビルドには結構時間がかかります。下のスペックのマシンで 1 時間以上かかります。
- Core i7 8700K (6コア, 12 スレッド, 全コア 4.3GHz にオーバークロック), メモリ 48GB, SATA SSD
- ビルドには結構時間がかかります。下のスペックのマシンで 1 時間以上かかります。
- ストレージの空き: 40GB
開発者モードを有効にする
「Windows の設定」から「更新とセキュリティ」の「開発者向け」を開き、「開発者モード」を有効にします。
Visual Studio をインストールする
https://visualstudio.microsoft.com/vs/community/ から Visual Studio 2017 Community Edition をダウンロードしてインストールします。インストール時のオプションは「C++ によるデスクトップ開発」と「ユニバーサル Windows プラットフォーム開発」を有効にしてください。
Git for Windows をインストールする
https://gitforwindows.org/ から Windows 用の Git をダウンロードしてインストールします。オプションは全てデフォルトのままにしてください。
Python をインストールする
https://www.python.org/downloads/windows/ からバージョン 2.7 系の「Windows x86-64 MSI installer」をダウンロードしてインストールします。インストール時のオプションは「Add python.exe to Path」を有効にしてください。
インストールしたら一度再起動します。
ソースコードのチェックアウト
Swift や llvm、そのほかのライブラリのソースコードをチェックアウトします。ここでは全て C:\swift に置くことにします。コマンドプロンプトを開いて次のように入力してください
C:
cd \
mkdir swift
cd swift
git clone https://github.com/apple/swift-cmark cmark
git clone https://github.com/apple/swift-clang clang
git clone https://github.com/apple/swift-llvm llvm
git clone https://github.com/apple/swift-compiler-rt compiler-rt
git clone https://github.com/apple/swift
git clone https://github.com/apple/swift-corelibs-libdispatch
git clone https://github.com/apple/swift-corelibs-foundation
git clone https://github.com/apple/swift-corelibs-xctest
git clone https://github.com/apple/swift-lldb lldb
git clone https://github.com/curl/curl.git curl
git clone https://gitlab.gnome.org/GNOME/libxml2.git libxml2
git clone https://compnerd@dev.azure.com/compnerd/windows-swift/_git/windows-swift
powershell -Command "Invoke-WebRequest -Uri http://download.icu-project.org/files/icu4c/63.1/icu4c-63_1-Win64-MSVC2017.zip -Outfile %TEMP%\icu.zip; Expand-Archive -Path %TEMP%\icu.zip"
チェックアウトしたタイミングによってはビルドできないことも多いので、初めは次のようにして私が試したコミットと合わせておくのが無難でしょう。
git -C clang checkout b1f4baeb56
git -C cmark checkout 32fa496
git -C compiler-rt checkout 166077175
git -C curl checkout 4331a3b8f
git -C libxml2 checkout 8161b463
git -C lldb checkout e4b0ffcff6
git -C llvm checkout ab94816b593
git -C swift checkout 8fcd4e6ee3
git -C swift-corelibs-foundation checkout a733b6b5
git -C swift-corelibs-libdispatch checkout 9d485ca
git -C swift-corelibs-xctest checkout 10140f4
git -C windows-swift checkout c45ba86
ビルド
シンボリックリンクの作成
ビルド中に必要になるシンボリックリンクを作成します。この操作には管理者権限が必要になります。コマンドプロンプトを右クリックして管理者権限で開いてください。
ここで次のコマンドを実行します。
"C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Auxiliary\Build\vcvars64.bat"
mklink "%UniversalCRTSdkDir%\Include\%UCRTVersion%\ucrt\module.modulemap" C:\swift\swift\stdlib\public\Platform\ucrt.modulemap
mklink "%UniversalCRTSdkDir%\Include\%UCRTVersion%\um\module.modulemap" C:\swift\swift\stdlib\public\Platform\winsdk.modulemap
mklink "%VCToolsInstallDir%\include\module.modulemap" C:\swift\swift\stdlib\public\Platform\visualc.modulemap
mklink "%VCToolsInstallDir%\include\visualc.apinotes" C:\swift\swift\stdlib\public\Platform\visualc.apinotes
これ以降管理者権限のコマンドプロンプトは使用しないので閉じて構いません。
ビルド環境の設定
通常のコマンドプロンプトに戻りビルド中に必要になる環境変数を設定します。ビルドしたものインストール先は DIST により C:\swift\dist にしていますが、必要に応じて変更してください。
set SWIFT=C:\swift
set BUILD=%SWIFT%\build
set ICU=%SWIFT%\icu
set DIST=%SWIFT%\dist
set WINCMAKE=%SWIFT%\windows-swift\cmake\caches\Windows-x86_64.cmake
set CNERDCMAKE=%SWIFT%\windows-swift\cmake\caches\org.compnerd.dt.cmake
call "C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Auxiliary\Build\vcvars64.bat"
call "C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\Common7\Tools\VsDevCmd.bat" -arch=amd64
set PATH=%ICU%\bin64;%BUILD%\llvm\bin;%BUILD%\foundation;%BUILD%\xctest;%PATH%
LLVM
mkdir "%BUILD%\llvm"
pushd "%BUILD%\llvm"
cmake -G Ninja^
-DCMAKE_BUILD_TYPE=RelWithDebInfo^
-DCMAKE_C_COMPILER=cl^
-DCMAKE_CXX_COMPILER=cl^
-DCMAKE_INSTALL_PREFIX="%DIST%"^
-DLLVM_DEFAULT_TARGET_TRIPLE=x86_64-unknown-windows-msvc^
-DLLVM_ENABLE_ASSERTIONS=YES^
-DLLVM_ENABLE_PDB=YES^
-C "%WINCMAKE%"^
-C "%CNERDCMAKE%"^
%SWIFT%\llvm
popd
ninja -C "%BUILD%\llvm"
cmark
mkdir "%BUILD%\cmark"
pushd "%BUILD%\cmark"
cmake -G Ninja^
-DCMAKE_BUILD_TYPE=RelWithDebInfo^
-DCMAKE_C_COMPILER=cl^
-DCMAKE_CXX_COMPILER=cl^
-DCMARK_TESTS=NO^
-C "%WINCMAKE%"^
"%SWIFT%\cmark"
popd
ninja -C "%BUILD%\cmark"
swift
このプロセスは終盤、非常にメモリを使用します。メモリ不足でビルドが失敗する場合は ninja に -j 2 等と指定して同時実行数を減らしましょう。時間がかかるようになりますが、失敗はしなくなります。
mkdir "%BUILD%\swift"
pushd "%BUILD%\swift"
cmake -G Ninja^
-DCMAKE_BUILD_TYPE=RelWithDebInfo^
-DCMAKE_C_COMPILER=clang-cl^
-DCMAKE_CXX_COMPILER=clang-cl^
-DCMAKE_INSTALL_PREFIX="%DIST%"^
-DClang_DIR="%BUILD%\llvm\lib\cmake\clang"^
-DSWIFT_PATH_TO_CMARK_BUILD="%BUILD%\cmark"^
-DSWIFT_PATH_TO_CMARK_SOURCE="%SWIFT%\cmark"^
-DSWIFT_PATH_TO_LIBDISPATCH_SOURCE="%SWIFT%\swift-corelibs-libdispatch"^
-DLLVM_DIR="%BUILD%\llvm\lib\cmake\llvm"^
-DSWIFT_INCLUDE_DOCS=NO^
-DSWIFT_WINDOWS_x86_64_ICU_UC_INCLUDE="%ICU%/include"^
-DSWIFT_WINDOWS_x86_64_ICU_UC="%ICU%/lib64/icuuc.lib"^
-DSWIFT_WINDOWS_x86_64_ICU_I18N_INCLUDE="%ICU%/include"^
-DSWIFT_WINDOWS_x86_64_ICU_I18N="%ICU%/lib64/icuin.lib"^
-DSWIFT_BUILD_STATIC_STDLIB=NO^
-DSWIFT_BUILD_STATIC_SDK_OVERLAY=NO^
-DLLVM_INSTALL_TOOLCHAIN_ONLY=YES^
-DSWIFT_BUILD_SOURCEKIT=YES^
-DSWIFT_ENABLE_SOURCEKIT_TESTS=NO^
-DSWIFT_INSTALL_COMPONENTS="autolink-driver;compiler;clang-resource-dir-symlink;stdlib;sdk-overlay;editor-integration;tools;sourcekit-inproc;swift-remote-mirror;swift-remote-mirror-headers"^
-C "%WINCMAKE%"^
"%SWIFT%\swift"
popd
ninja -C "%BUILD%\swift"
lldb
mkdir "%BUILD%\lldb"
pushd "%BUILD%\lldb"
cmake -G Ninja^
-DCMAKE_BUILD_TYPE=Release^
-DCMAKE_CXX_COMPILER=clang-cl^
-DCMAKE_C_COMPILER=clang-cl^
-DCMAKE_INSTALL_PREFIX="%DIST%"^
-DLLDB_PATH_TO_CLANG_BUILD="%BUILD%\llvm"^
-DLLDB_PATH_TO_LLVM_BUILD="%BUILD%\llvm"^
-DLLDB_PATH_TO_SWIFT_BUILD="%BUILD%\swift"^
-DLLDB_PATH_TO_SWIFT_SOURCE="%SWIFT%\swift"^
-DLLVM_ENABLE_ASSERTIONS=YES^
-C "%WINCMAKE%"^
"%SWIFT%\lldb"
popd
ninja -C "%BUILD%\lldb"
libdispatch
mkdir "%BUILD%\libdispatch"
pushd "%BUILD%\libdispatch"
cmake -G Ninja^
-DCMAKE_BUILD_TYPE=Debug^
-DCMAKE_C_COMPILER=clang-cl^
-DCMAKE_CXX_COMPILER=clang-cl^
-DCMAKE_SWIFT_COMPILER="%BUILD%\swift\bin\swiftc.exe"^
-DCMAKE_INSTALL_PREFIX="%DIST%"^
-DBUILD_SHARED_LIBS=YES^
-DENABLE_TESTING=NO^
-DCMAKE_C_COMPILER_TARGET=x86_64-unknown-windows-msvc^
-DENABLE_SWIFT=YES^
-C "%WINCMAKE%"^
"%SWIFT%\swift-corelibs-libdispatch"
popd
ninja -C "%BUILD%\libdispatch"
curl
pushd "%SWIFT%\curl"
call buildconf.bat
pushd winbuild
nmake /f Makefile.vc mode=static VC=15 MACHINE=x64
popd
popd
libxml2
pushd "%SWIFT%\libxml2\win32"
cscript configure.js iconv=no
nmake /f Makefile.msvc
popd
core-foundation
途中、止まっているように見えますが辛抱強く待ちましょう。
mkdir "%BUILD%\foundation"
pushd "%BUILD%\foundation"
cmake -G Ninja^
-DCMAKE_BUILD_TYPE=Debug^
-DCMAKE_C_COMPILER=clang-cl^
-DCMAKE_SWIFT_COMPILER="%BUILD%\swift\bin\swiftc.exe"^
-DCURL_LIBRARY="%SWIFT%/curl/builds/libcurl-vc15-x64-release-static-ipv6-sspi-winssl/lib/libcurl_a.lib"^
-DCURL_INCLUDE_DIR="%SWIFT%/curl/builds/libcurl-vc15-x64-release-static-ipv6-sspi-winssl/include"^
-DENABLE_TESTING=NO^
-DICU_ROOT="%ICU%"^
-DLIBXML2_LIBRARY="%SWIFT%/libxml2/win32/bin.msvc/libxml2_a.lib"^
-DLIBXML2_INCLUDE_DIR="%SWIFT%/libxml2/include"^
-DFOUNDATION_PATH_TO_LIBDISPATCH_SOURCE="%SWIFT%\swift-corelibs-libdispatch"^
-DFOUNDATION_PATH_TO_LIBDISPATCH_BUILD="%BUILD%\libdispatch"^
-DCMAKE_INSTALL_PREFIX="%DIST%"^
-C "%WINCMAKE%"^
"%SWIFT%\swift-corelibs-foundation"
popd
ninja -C "%BUILD%\foundation"
xctest
mkdir "%BUILD%\xctest"
pushd "%BUILD%\xctest"
cmake -G Ninja^
-DBUILD_SHARED_LIBS=YES^
-DCMAKE_BUILD_TYPE=Debug^
-DCMAKE_SWIFT_COMPILER="%BUILD%\swift\bin\swiftc.exe"^
-DXCTEST_PATH_TO_COREFOUNDATION_BUILD="%BUILD%\foundation\CoreFoundation-prefix"^
-DXCTEST_PATH_TO_FOUNDATION_BUILD="%BUILD%\foundation"^
-DXCTEST_PATH_TO_LIBDISPATCH_SOURCE="%SWIFT%\swift-corelibs-libdispatch"^
-DXCTEST_PATH_TO_LIBDISPATCH_BUILD="%BUILD%\libdispatch"^
-DLIT_COMMAND="%SWIFT%\llvm\utils\lit\lit.py"^
-DPYTHON_EXECUTABLE="C:\Python27\python.exe"^
-DCMAKE_INSTALL_PREFIX="%DIST%"^
-C "%WINCMAKE%"^
"%SWIFT%\swift-corelibs-xctest"
popd
ninja -C "%BUILD%\xctest"
インストール
途中、Foundation がエラーを吐きますが、無視して構いません。
ninja -C "%BUILD%\llvm" install
ninja -C "%BUILD%\swift" install
ninja -C "%BUILD%\lldb" install
ninja -C "%BUILD%\libdispatch" install
ninja -C "%BUILD%\foundation" install
ninja -C "%BUILD%\xctest" install
Swift プログラムのコンパイル
では Swift プログラムをコンパイルしてみましょう。まずコンパイラとコンパイルしたプログラムの実行に必要なディレクトリにパスを通します。
set PATH=%DIST%\bin;%DIST%\lib\swift\windows;%PATH%
こんなコードを用意しました。
// hello.swift
import Foundation
let f = DateFormatter()
f.dateStyle = .full
let now = Date()
print("Hello Swift!")
print("It's \(f.string(from: now))!")
このコードをコンパイルするには次のオプションをつけてコンパイラを起動します。
swiftc -Xcc -DDEPLOYMENT_TARGET_WINDOWS^
-Xlinker /NODEFAULTLIB:libcmt^
-Xlinker /LIBPATH:C:\swift\build\foundation^
-Xlinker /LIBPATH:C:\swift\build\libdispatch^
-Xlinker /LIBPATH:C:\swift\build\libdispatch\src^
-Xlinker user32.lib^
-o hello.exe^
hello.swift
そうすればコンパイルできて次のように実行できるはずです!