Azure Pipelinesでzlibをマルチプラットフォームに自動ビルドする
KAGURAの自動ビルドをAzure Pipelinesで実現できるかどうか、検討しています。前回は、CMakeを使ってC++のコードを複数環境向け(Ubuntu、Windows、macOS)にビルドできることまで確認しました。
複数のエージェントがMicrosoftによって用意されていて、設定ファイルを変更するだけで、ビルド環境を変えることができましたが、ビルドのたびに設定ファイルを書き換えるわけにはいかないので、一度に複数の環境でビルドを走らせてほしいです。
今回は、zlibをビルドしてみます。なぜzlibかというと、KAGURAでも使用しているライブラリで、CMakeに対応し、比較的小さいライブラリであり、zlibほど多くの人に使われているライブラリのビルドが通らないなんてことは考えにくいからです。
ローカルでビルド
まずは、ローカルのUbuntu(WSL)環境でビルドできることを確認しておきます。ビルド手順はこのような流れになります。
- zlibソースコードのダウンロード
- ダウンロードファイルのチェック
- ファイルの展開
- CMakeの実行
- ビルド
- テスト
- インストール
Bash上で、次のようなコマンドを実行します。
# Download curl -sLO https://www.zlib.net/zlib-1.2.11.tar.gz # Verify SHA256 echo "c3e5e9fdd5004dcb542feda5ee4f0ff0744628baf8ed2dd5d66f8ca1197cb1a1 *zlib-1.2.11.tar.gz" | shasum -a 256 --check # Extract tar -xvf zlib-1.2.11.tar.gz mkdir build cd build # Run CMake cmake -DCMAKE_INSTALL_PREFIX=../dist ../zlib-1.2.11 # Build cmake --build ./ --config Release # Test ctest --build-config Release # Install cmake --build ./ --config Release --target install
成功するとdistフォルダにビルド結果が出力されています。
dist ├── include │ ├── zconf.h │ └── zlib.h ├── lib │ ├── libz.a │ ├── libz.so -> libz.so.1 │ ├── libz.so.1 -> libz.so.1.2.11 │ └── libz.so.1.2.11 └── share ├── man │ └── man3 │ └── zlib.3 └── pkgconfig └── zlib.pc
Azure Pipelinesでビルド
上と同じことを実行するAzure Pipelinesの設定ファイルはこのようになります。
# azure-pipelines.yml trigger: - master pool: vmImage: 'ubuntu-16.04' #vmImage: 'vs2017-win2016' #vmImage: 'macOS-10.13' steps: - script: | curl -sLO https://www.zlib.net/zlib-1.2.11.tar.gz echo "c3e5e9fdd5004dcb542feda5ee4f0ff0744628baf8ed2dd5d66f8ca1197cb1a1 *zlib-1.2.11.tar.gz" | shasum -a 256 --check tar -xvf zlib-1.2.11.tar.gz displayName: Download zlib - task: CMake@1 inputs: cmakeArgs: > -DCMAKE_INSTALL_PREFIX=$(Build.ArtifactStagingDirectory) $(Build.SourcesDirectory)/zlib-1.2.11 - task: CMake@1 inputs: cmakeArgs: > --build ./ --config Release - script: ctest --build-config Release workingDirectory: build displayName: Test - task: CMake@1 inputs: cmakeArgs: > --build ./ --config Release --target install - task: PublishBuildArtifacts@1 inputs: pathtoPublish: $(Build.ArtifactStagingDirectory) artifactName: zlib-1.2.11
これを実行すると、できました!
さて、Windows環境でビルドを実行するには、設定ファイルのvmImage
をvs2017-win2016
変更するだけ・・・と言いたいところですが、問題が発生しました。
shasum
コマンドなんて無いと。そりゃそうです、Windowsなんだもの。その前のcurl
が通っていることのほうがびっくりです。
そこで、PowerShellを使ってみます。
curl
はInvoke-WebRequest
に置き換えます。PowerShellにおけるcurl
はInvoke-WebRequest
のエイリアスであり、bashのcurl
とは挙動が違うので、そのまま使えません。shasum
はGet-FileHash
に置き換え。tar
はそのまま使えます。
# PowerShell Invoke-WebRequest -Uri https://www.zlib.net/zlib-1.2.11.tar.gz -O zlib-1.2.11.tar.gz if ((Get-FileHash zlib-1.2.11.tar.gz -Algorithm SHA256).Hash -ne "c3e5e9fdd5004dcb542feda5ee4f0ff0744628baf8ed2dd5d66f8ca1197cb1a1") { exit 1 } tar -xvf zlib-1.2.11.tar.gz
azure-pipelines.ymlに組み込みます。variables
で変数を定義し、少し整理しました。
# azure-pipelines.yml (変更) variables: DOWNLOAD_URL: https://www.zlib.net/zlib-1.2.11.tar.gz DOWNLOAD_FILE: zlib-1.2.11.tar.gz DOWNLOAD_SHA256: c3e5e9fdd5004dcb542feda5ee4f0ff0744628baf8ed2dd5d66f8ca1197cb1a1 - powershell: | Invoke-WebRequest -Uri $env:DOWNLOAD_URL -O $env:DOWNLOAD_FILE if ((Get-FileHash $env:DOWNLOAD_FILE -Algorithm SHA256).Hash -ne $env:DOWNLOAD_SHA256) { exit 1 } tar -xvf $env:DOWNLOAD_FILE displayName: Download zlib
Windowsでもビルドできました!
そして、なんと同じ設定でUbuntuでもmacOSでもビルドできました!!PowerShellは今やUbuntuやmacOSでも使えるのです。
複数環境で一括ビルド
ここからが今日の本題です。vmImage
を毎回書き換えずに、複数環境のビルドを実行するにはどうしたらいいでしょうか。
パイプラインは1つ以上のジョブで構成されています。ジョブは1つ以上のステップで構成されます。ここではじめてジョブというものが出てきましたが、これまでのシンプルなパイプラインではジョブが1つしかないため、ジョブの記述を省略できていたのでした。
# azure-pipelines.yml trigger: - master jobs: - job: 'ubuntu1604' pool: vmImage: 'ubuntu-16.04' steps: - script: echo Ubuntu-16.04 - job: 'win2016_vs2017' pool: vmImage: 'vs2017-win2016' steps: - script: echo vs2017-win2016 - job: 'macos1013' pool: vmImage: 'macOS-10.13' steps: - script: echo macOS-10.13
このように、ジョブごとに異なるvmImage
を設定することができます。
ビルドステップは共通化してあるので、別のymlファイルに切り出します。
# build-zlib.yml steps: - powershell: | Invoke-WebRequest -Uri $env:DOWNLOAD_URL -O $env:DOWNLOAD_FILE if ((Get-FileHash $env:DOWNLOAD_FILE -Algorithm SHA256).Hash -ne $env:DOWNLOAD_SHA256) { exit 1 } tar -xvf $env:DOWNLOAD_FILE displayName: Download zlib - task: CMake@1 inputs: cmakeArgs: > -DCMAKE_INSTALL_PREFIX=$(Build.ArtifactStagingDirectory) $(Build.SourcesDirectory)/zlib-1.2.11 - task: CMake@1 inputs: cmakeArgs: > --build ./ --config Release - script: ctest --build-config Release workingDirectory: build displayName: Test - task: CMake@1 inputs: cmakeArgs: > --build ./ --config Release --target install - task: PublishBuildArtifacts@1 inputs: pathtoPublish: $(Build.ArtifactStagingDirectory) artifactName: zlib-1.2.11_$(Agent.OS)
このbuild-zlib.ymlをテンプレートとして各ジョブで読み込みます。
# azure-pipelines.yml trigger: - master variables: DOWNLOAD_URL: https://www.zlib.net/zlib-1.2.11.tar.gz DOWNLOAD_FILE: zlib-1.2.11.tar.gz DOWNLOAD_SHA256: c3e5e9fdd5004dcb542feda5ee4f0ff0744628baf8ed2dd5d66f8ca1197cb1a1 jobs: - job: 'ubuntu1604' pool: vmImage: 'ubuntu-16.04' steps: - template: build-zlib.yml - job: 'win2016_vs2017' pool: vmImage: 'vs2017-win2016' steps: - template: build-zlib.yml - job: 'macos1013' pool: vmImage: 'macOS-10.13' steps: - template: build-zlib.yml
できました!
まとめ
- Azure Pipelineでzlibをビルドすることができました。この調子で外部ライブラリをビルドすることができそうです。
- 複数環境で共通の処理はPowerShellを使うとよさそうです。
- ジョブを複数使って、複数環境のビルドを一度に行うことができました。
外部ライブラリのビルドができるようになったので、次回は、ビルド済みの外部ライブラリを本体のビルドで読み込むにはどうしたらいいのか調べてみたいと思います。