🎨

GitHub ActionsでMSBuildによるビルドを行う

2021/02/04に公開

タイトルの通り、GitHub Actionsのワークフローにてmsbuildコマンドを実行する方法です。

C++プロジェクト等、Windows上でのビルドが求められるシーンで活躍すると思います。また、例えばvcpkgを使用したい場合もWindowsではmsbuildが必要になってきます。

WindowsのGitHubホストランナーについて

GitHub Actionsの強みの1つに、Windowsのランナーの充実ぶりがあると思います。
https://docs.github.com/ja/actions/reference/specifications-for-github-hosted-runners
https://github.com/actions/virtual-environments/blob/main/images/win/Windows2019-Readme.md

Visual Studioが全部盛りに近い構成でインストール済みで、多くの用途に合致するはずです。知る限りでは従来これを満たすのは無料ではAppVeyorのみでしたが[1]、GitHub Actionsが引導を渡したかもしれません。AppVeyor最大の悩みだったタスク起動までの遅さともおさらばです[2]

Windows環境を使用したCIはあまり盛んではない印象がありますが、今後広がることを期待して以下書き残しています。

microsoft/setup-msbuild

ローカル環境でもそうだと思いますが、通常はPATHが通っていないのでそのままではコマンドプロンプトからmsbuildを実行できません。本記事は以下の紹介で終わってしまいます。
https://github.com/microsoft/setup-msbuild

少し古い記事ではwarrenbuckley/Setup-MSBuild を使うものが散見されますが、現在ではMicrosoft公式が用意したこれを使いましょう。

name: MSBuild

on:
  pull_request:
    types: [synchronize, opened]
    
jobs:
  build:
    runs-on: windows-2019
    steps:
      - name: Checkout
        uses: actions/checkout@v2

      - name: Add msbuild to PATH
        uses: microsoft/setup-msbuild@v1.0.2

      - run: |
          msbuild -version

アクションのログへの出力例です。

Microsoft (R) Build Engine version 16.8.3+39993bd9d for .NET Framework
Copyright (C) Microsoft Corporation. All rights reserved.

16.8.3.61104

msbuildを使用する一例: OpenCVのビルド

めでたしめでたし・・・では短いので、私が使用した一例もご紹介して終わりにします。

OpenCVをGitHub ActionsのWindowsランナーでビルドします。

https://github.com/shimat/opencv_files

OpenCV向けの特別な話が多くなってしまいますが、エッセンスはほかでも使えるかと思います。

プラットフォームごとに実行を分ける

OpenCVのビルドはかなり長時間かかるため、ターゲットプラットフォームをx64x86で平行させたりすると効果的です。GitHub Actionsではmatrixを使うのが1つの手です。

jobs:
  build:
    strategy:
      matrix:
        arch: ["x86", "x64"]	
    runs-on: windows-2019
    steps:
      ...

依存ライブラリの準備

  • Windows ServerにはMedia Foundationがインストールされていないので導入します。
  • vcpkgを使って依存ライブラリ (Tesseract) を導入し[3]、VisualStudioインテグレーションも有効にします。前述の通り、vcpkgではmsbuildを使用するので、PATHを通した後に行います。
    • vcpkgパッケージのインストールはビルドが走って遅いので、キャッシュするのが有効とされます。本記事では割愛しています。
    steps:
      - name: Checkout
        uses: actions/checkout@v2

      - name: Install Server-Media-Foundation
        shell: powershell
        run: |
          Install-WindowsFeature Server-Media-Foundation

      - name: Add msbuild to PATH
        uses: microsoft/setup-msbuild@v1.0.2

      - name: Vcpkg
        run: |
          vcpkg install tesseract:${{matrix.arch}}-windows-static
          vcpkg integrate install

CMake, MSBuild

cmakeはWindowsのランナーにも導入済みなので即使えます。cmakeのオプションは本題ではないので端折っています(実際は40~50行くらい)。OpenCVのソースコードを取ってくるところも省略しています。

      - name: CMake
        shell: powershell
        run: |
          if (${{matrix.arch}} -eq "x64") {
            $msbuildPlatform = "x64"
          } else {
            $msbuildPlatform = "Win32"
          }
	  
	  $buildDirectory = "build_win_${{matrix.arch}}"
          mkdir $buildDirectory -Force -ErrorAction Stop | Out-Null
          cd $buildDirectory
	  
	  cmake -G "Visual Studio 16 2019" `
          -A $msbuildPlatform `
          -D CMAKE_BUILD_TYPE=Release `
          -D CMAKE_INSTALL_PREFIX=install `
          -D BUILD_SHARED_LIBS=OFF `
          -D OPENCV_EXTRA_MODULES_PATH=../opencv_contrib/modules `
	  ../opencv 
	  
      - name: MSBuild
        run: |
	  cd build_win_${{matrix.arch}}
	  msbuild INSTALL.vcxproj /t:build /p:configuration=Release /p:platform=$msbuildPlatform -maxcpucount

ビルドの出力をアーティファクトとして保存

      - name: Upload artifacts
        uses: actions/upload-artifact@v1
        with:
          name: artifacts_win-${{matrix.arch}}
          path: build_win_${{matrix.arch}}/install

おわりに

  • microsoft/setup-msbuild によりMSBuildが使えるようになります。
  • Windows限定のワークフローもGitHub Actionsでは書きやすいです。費用はUbuntuの2倍高い計算ですが、publicでは無料ですし、その他問題にならないシーンでは活用を広げたいですね。
  • いままでありがとうAppVeyor。安らかに眠れ。
脚注
  1. CircleCIも少し前から可能になりましたが、やや弱めに見えます。 https://circleci.com/docs/ja/2.0/hello-world-windows/#windows-イメージにプリインストールされているソフトウェア ↩︎

  2. このようにWindowsランナーへの投資も熱心なのは、GitHubがMicrosoftになった影響があるかもしれませんね。 ↩︎

  3. vcpkgをCIで使う場合は本来は要注意です。GitHubランナーの更新に伴いvcpkgも更新され、vcpkgの各パッケージも更新されていくので、メジャーバージョンが変わってある日から急に問題が出たりするかもしれません。 ↩︎

Discussion