tech.guitarrapc.cóm

Technical updates

Azure DevOpsの Microsoft-hosted Agent で HoloLens ビルドを行う(MRTK/MRTKv2)

前回、Azure DevOps で HoloLens のビルド環境を行うこと、Microsoft-hosted Agent が今ならいいということを書きました。

tech.guitarrapc.com

今回は、MRTKとMRTKv2 を Microsoft-hosted Agent で現実的にビルドすることを考えてみましょう。 内容としては、次の記事が近いです。

withmr.nextscape.net

この記事では、MRTKv1とMRTKv2 それぞれについてリポジトリとAzure Devops Pipeline の YAMLを示しつつ、現実にビルドしていくことに必要なことをカバーします。

目次

Unity のビルドエラーがわからない

Windows上でUnityのバッチビルドをしたときに困るのが、Unity ビルドの経過、ログが標準出力に出ないことです。*1

結果Unity 内部でどのようなエラーが起こってもエラーの詳細がわからないので、記事にあるUnityBuildTask@2 を使う方法は現実的ではありません。*2

コンパイルエラーでどこでコンパイルエラー出たかわからないとか絶望です。

そのため、Unity Tools for Azure DevOps でUnity ビルドを行うのは厳しいものがあります。

- task: UnityBuildTask@2
  displayName: 'Unity Build WindowsStoreApps'
  name: 'unityBuild'
  inputs:
    buildTarget: 'WindowsStoreApps'
    unityEditorsPathMode: 'unityHub'
    unityProjectPath: '$(unityProjectPath)'
    commandLineArgumentsMode: 'default'

marketplace.visualstudio.com

代わりに「Unityビルド呼び出しつつlogファイルに吐いたログを読み込んで標準出力に吐く」ラッパーアプリケーションを用意する方法をよく採用されています。

chiepomme.gitbook.io

お手伝い先で必要になり一年前に作り使っていただいているのが UnityBuildRunner です。*3

github.com

dotnet global tool として公開してあるので、dotnet tool install -g UnityBuildRunner でWindows/Mac問わずサクッとインストールできます。

使い方は単純です。Unity のバッチビルドは次のフォーマットです。

Unity.exe [args]

この引数をUnityBuildRunnerにそのまま渡せばokです。 加えてタイムアウトにも対応してあります。

UnityBuildRunner [-UnityPath|-unityPath|-u] [-timeout|-t 00:60:00] [-version] [-help] [args]

たとえば、MRTKv2 でビルドするならこのように書けます。

UnityBuildRunner -UnityPath "C:\Program Files\Unity\Hub\Editor\2018.3.13f1\Editor\Unity.exe" -quit -batchmode -projectPath パス -buildTarget WSAPlayer -logfile Editor.log -executeMethod Microsoft.MixedReality.Toolkit.Build.Editor.UnityPlayerBuildTools.StartCommandLineBuild

Unityパスは環境変数から読むこともできるので次のようにも書けます。

set unityPath=C:\Program Files\Unity\Hub\Editor\2018.3.13f1\Editor\Unity.exe
UnityBuildRunner -quit -batchmode -projectPath パス -buildTarget WSAPlayer -logfile Editor.log -executeMethod Microsoft.MixedReality.Toolkit.Build.Editor.UnityPlayerBuildTools.StartCommandLineBuild

f:id:guitarrapc_tech:20190626163832p:plain
https://github.com/guitarrapc/UnityBuildRunner を使ったWindowsでのUnityビルド

MRTKv1 のビルドを行う

MRTK のビルドは、HoloToolkit.Unity.BuildDeployTools.BuildSLN メソッドを使います。*4

MRTKv2を使ったビルドとYAML定義を含んだリポジトリです。

github.com

Azure DevOps でのビルド結果も示します。

dev.azure.com

ビルドのYAML定義を見てみましょう。

gist.github.com

途中のコメントを外すとsln一式がartifacts から取得できます。

# if you want to build locally
# - task: PublishPipelineArtifact@0
#   displayName: 'Publish Pipeline Artifact'
#   inputs:
#     artifactName: 'UWP_Sln'
#     targetPath: 'UWP'

ちなみにMRTKv1 のシンプルなシーンをビルドしてみると、ビルドに30min、長い。

f:id:guitarrapc_tech:20190626170711p:plain
MRTKv1 の Azure DevOps Microsoft-host Agent でのビルド

プロジェクト固有の情報を知らずビルドするコツとして、VSビルド時にslnファイルを指定するのではなくslnのあるフォルダを指定 + / と書くことでslnビルドできます。/ がないとsln が見つからないので注意です。

MRTKv2 のビルドを行う

MRTKv2 は、Windows SDK 18362 が必要ですが、これがHosted Agent に来てビルドできるようになったのは6/25です。 Sprint 153 で追加対応が来てから、自分たちのAgent にくるまで約2週間かかりました。

MRTKv2のビルドは、Microsoft.MixedReality.Toolkit.Build.Editor.UnityPlayerBuildTools.StartCommandLineBuild メソッドを使います。 相変わらずDevelopment ビルドの指定ができないのがアレなのでラッパーを書くことになるでしょう。

MRTKv1を使ったビルドとYAML定義を含んだリポジトリです。

github.com

Azure DevOps でのビルド結果も示します。

dev.azure.com

ビルド定義のYAMLは次のようになります。

gist.github.com

途中のコメントを外すとsln一式がartifacts から取得できます。

# if you want to build locally
#- task: PublishPipelineArtifact@0
#  displayName: 'Publish Pipeline Artifact'
#  inputs:
#    artifactName: 'sln'
#    targetPath: 'Builds/WSAPlayer'

MRTKv2 のサンプルシーンをビルドしてみると、ビルドに30min、長い。

f:id:guitarrapc_tech:20190626170812p:plain
MRTKv2 の Azure DevOps Microsoft-host Agent でのビルド

プロジェクト固有の情報を知らずビルドするコツとして、VSビルド時にslnファイルを指定するのではなくslnのあるフォルダを指定 と書くことでslnビルドできます。先ほどと違い、/ で終わるとsln が見つからないので注意です。

学び

Unityのインストールにかかる時間

Microsft-hosted Agent にはUnity がインストールされていません。 そのためこのYAML ではUnityを都度インストールしています。

このUnityの準備にかかる時間をリードタイムとしてみると、10min 程度かかります。 毎ビルドで10min かかるのはアレでもあり、その程度で済むならいいかもしれません。((よくない)))

Output変数が定義されたタスクの変数はnameを指定することでとれるようになる

UnityGetProjectVersionTask@1 で取得したUnityバージョンを変数に出力します。 これを使うことでUnityプロジェクトのバージョンを知ることなく、同じYAMLをどのUnityバージョンでも変わらず使えます。

さて、UI と違って YAML では reference variable の設定はサポートされていません。 しかしTASKで出力変数が設定されている場合は、name をつけることで取得できます。

- task: DinomiteStudios.64e90d50-a9c0-11e8-a356-d3eab7857116.custom-unity-get-project-version-task.UnityGetProjectVersionTask@1
  displayName: 'Unity Get Project Version'
  name: unitygetprojectversion

これで、後段のstep において $(unitygetprojectversion.projectVersion) で参照できます。 教えてもらって気づきました、これはむりげー。

*1:macOS/Linux では、-logFile を無引数で与えることでログが標準出力に出ます

*2:MRTKv1 で私の環境ではビルドが60min 立っても終わらない状況も発生しました

*3:↑の記事より前に作ったのですが、結果似たことしててあぁって感じです。悲しい

*4:Unity BatchビルドはDevelopment 指定が引数でできないのがアレなので、たいがいラッパーを書いている気がします。