ユーザ用ツール

サイト用ツール


ue4:buildsystem

UnrealBuildTool (UBT)

Unreal Engine 4 の BuildSystem は非常に複雑です。 その中心になるのが C# で記述された UnrealBuildTool になります。

各 Module の Build file (Makefile 相当) も *.Build.cs と言う名前の C# で書かれています。

主に2つの機能があります。

  • IDE 向け Project File の生成
  • ビルドの実行

Project File の生成は Debug など IDE を利用するためのものであって、ビルドそのものには利用していません。 ビルド自体は UnrealBuildTool が行います。

  1. フォルダ Tree の検索
  2. 依存解析と cache 作成
  3. ビルドステップの実行
    1. 依存する必要なツールのビルド (UnrealHeaderTool)
    2. UnrealHeaderTool を使ったプリプロセス
    3. Executor からコンパイラの呼び出し (もしくは分散 Build System 呼び出し)

内部構造

Executor

コンパイラを呼び出すためのフロントエンドです。 分散ビルドを行う場合、それぞれ対応した Executor が選択されます。 デフォルトは ParallelExecutor です。

Executor 説明
LocalExecutor Network を使わずに PC の Local CPU だけでビルドします。並列ビルドしますが、HT が有効な場合すべての Thread が使われないという問題があります。設定で変更可能ですが、デフォルトだと本来の速度よりもビルド速度が落ちているので注意。今はほとんど使われていません。
ParallelExecutor Local CPU 用の新しい Executor で、LocalExecutor よりも高速です。設定不要ですべての CPU core とすべての Thread を使います。
XGE 有料の分散ビルドツール IncrediBuild を install している場合に使用します。CPU/Thread 数に応じたライセンスが必要です。
HybridExecutor XGE と同じですが、分散ビルドと同時に Local の CPU も最大限活用します。IncrediBuild のライセンスよりも CPU core 数が多い場合に有効かもしれません。未確認
SNDBS SONY の分散ビルドツール SN-DBS を install している場合に使用します。
Distcc macOS 上で分散ビルドツールの Distcc を用いる場合にこの Executor を使います。

自分で独自の分散ビルドツールを開発する場合は、専用の Executor を実装することになります。 Executor の選択は System/ActionGraph.cs の内部にあります。

Build.cs の読み込み

Build.cs は必要に応じて動的にコンパイルが行われ、dll として読み込まれます。(参照)

  • *.Build.cs や *.Target.cs がまとめて dll に変換される
  • Intermediate/Build/BuildRules/*.dll に保存

例えば UE4 Engine の場合、Engine/Intermediate/Buld/BuildRules/UE4Rules.dll になります。 dll は必要なときしか作られないため cache としても機能します。

cl-filter.exe とは何か

古い UnrealBuildTool では *.cpp や *.h の依存解析を自前で行っていました。 最新版ではコンパイラの機能を利用して #include の解析を行っています。

  1. 依存解析ファイルがない場合、cl.exe や clang を使って #include の抽出
  2. 依存解析結果を元に build が必要なソースコードを絞り込む
  3. 必要なソースコードのコンパイルを実行し、同時に #include 解析結果を取得
  4. 以降は 3のみ繰り返す

clang/gcc は -MD や -MF などのオプションで、依存解析結果のみ指定したファイルに保存することができます。 コンパイラのエラーメッセージと混同してしまうことがありません。

VisualStudio (cl.exe) には依存解析のみ別ファイルに出力する機能がありません。 コンパイラのエラーメッセージと区別なく、同じ標準出力に出力します。

UE4 では cl.exe の依存解析結果を分離するためのツールとして Engine/Build/Windows/cl-filter/cl-filter.exe を使用しています。 標準出力から依存解析部分のみ抽出して、別のファイルに保存する機能を持っています。

UnrealBuildTool の Makefile

UnrealBuildTool 内部では、異なる意味の Makefile という用語がいくつか存在します。 ひとつは Linux 向けの Projectfile である Makefile で、他に全 Platform で共通で用いられる Makefile (TargetMakefile) があります。

TargetMakefile は *.cpp / *.h の依存解析結果を保存しておくための cache ファイルです。 保存される場所は下記の通り。

  • Intermediate/Build/<Platform>/<Target>/<Configuration>/Makefile.bin

例えば Windows 上で Game Project である MyProject の場合

  • MyProject/Intermediate/Build/Win64/MyProjectEditor/Development/Makefile.bin

Unity Build

UnrealBuildTool はデフォルトで UnityBuild を行います。設定で無効化することができます。

UnityBuild を有効にすると複数のソースコードを単一のファイルにまとめてコンパイルを行います。ビルド時間を大幅に短縮することができます。

  • ソースファイルの数が減ることによってコンパイラ起動のオーバーヘッドを減らすことが可能です。
  • 複数のソースコードをまとめることによって、共通で参照しているヘッダファイルの読み込みや解析が一度で済むようになります。
  • LTCG を off にしてもある程度複数ファイルにまたがった最適化が行われます。

欠点もいくつかあります。

コンパイル粒度が大きくなる

本来単一ファイルのコンパイルだけで済む小さい修正でも、周辺のファイルも含めて再コンパイルが行われることになります。 なおデフォルトで AdaptiveUnityBuild が有効になっているためリビルド範囲は動的に調整が入ります。

エラーが報告されない場合がある

#include し忘れによるシンボル参照エラーがあっても、コンパイルが通ってしまう場合があります。 他のファイルで #include されているかもしれないからです。 Unity Build が行われる単位は変化するので、以前はビルドが通っていても再ビルドしたらエラーが出ていて戸惑うこともあります。

File Scope の Local シンボルが衝突する可能性がある

File Scope が完全な Local になりません。 File Scope に記述した static 変数や無名の namespace block が他のファイルからも見えるので、衝突する場合があります。


UnrealHeaderTool (UHT) とは

C++ で UE4 の開発を行っている方には説明するまでもないですが *.generated.h を生成するためのプリプロセッサです。 C/C++ 言語のプリプロセッサの前に走ります。

  1. UnrealHeaderTool が *.h の UCLASS(), UFUNCTION(), UPROPERTY() などを解析。*.generated.h を生成する。
  2. C++ 言語のプリプロセッサが # で始まる行(#define, #include など)やコメント行の処理、マクロ展開を行う。ソースコードを生成する。
  3. 生成された C++ ソースコードのコンパイル

上記のように C++</nowki> のプリプロセッサの前に走るので、UHT が解析するコマンドにはブロックコメントや #if ~、define マクロが意味を持ちません。 例えば下記の UFUNCTION() はどちらも <nowiki>C/C++ 言語的にはコメントアウトされていますが UHT では有効になります。#if ~ #endif block でも同じです。

/*
UFUNCTION( ~ )
int32  GetParameterA();
*/
 
#if 0
UFUNCTION()
int32  GetParameterB();
#endif

また下記のように UHT が解析する行に define したマクロを使用しても展開されません。“CATEGORY_NAME” という Category になってしまいます。

#define CATEGORY_NAME "Camera"
 
~
 
UFUNCTION(BlueprintCallable, Category=CATEOGRY_NAME)
void  SetCameraType( int32 type );
 
UFUNCTION(BlueprintCallable, Category=CATEOGRY_NAME)
int32  GetCameraType() const;

UnrealAutomationTool (UAT) とは

UE4 のパッケージの作成には、cpp のコンパイル以外にも必要な手順がいくつか存在します。 また、それぞれ専用のツールが存在しています。

  1. UnrealBuildTool, ShaderCompileWorker, UnrealPak, Lightmass などツールのビルド : UnrealAutomationTool が行う。
  2. ソースコード cpp のビルド : UnrealBuildTool が行う。内部で UnrealHeaderTool のビルドや呼び出しも行う。
  3. Contents の cook : UE4Editor 本体が行う
  4. パッケージの生成 : pak 生成に UnrealPak を使う
  5. Deploy や起動

これらの手順をまとめて実行するためのツールが UnrealAutomationTool (UAT) です。

本来のビルドツールだと、ソースコードのビルドとリソースの変換やパッケージ化などの生成手段に区別がありません。 たとえば make なら、Makefile 内部でソースコードのコンパイルだけでなくリソースの変換やパッケージ化など一連の処理をまとめて実行できます。

つまり汎用的なビルドツールだと UBT と UAT 相当のツールは兼用されます。 UE4 では、それぞれの手順ごとに専用のツールが用いられているので複雑です。

ちなみに UAT 自体のビルドは Engine/Build/BatchFiles/RunUAT.bat 内部で行われています。

空の Engine/Build/InstalledBuild.txt ファイルを作っておくと InstalledBuild mode になります。 UAT が外部ツールをビルドするのを回避することができます。


UnrealBuildTool の設定

BuildConfiguration.xml

UnrealBuildTool の共通の設定は BuildConfiguration.xml ファイルに記述しておくことができます。 Project / Module 単位の個別の設定は *.Build.cs や *.Target.cs で設定することもできます。

BuildConfiguration.xml の置き場所は下記のとおりです。

  1. $ENGINE_DIR/Engine/Saved/UnrealBuildTool/BuildConfiguration.xml
  2. $USER_DIR/AppData/Unreal Engine/UnrealBuildTool/BuildConfiguration.xml
  3. $USER_DIR/Documents/Unreal Engine/UnrealBuildTool/BuildConfiguration.xml
  • USER_DIR = C:/Users/<USER>/

Compiler の指定

Windows で使用する VisualStudio の Version を選択できます。 4.25 からは BuildConfiguration.xml で設定するように変更されています。4.24 以前はコマンドラインオプション -2017, -2019 が有効でした。(参照)

Project File 生成時の VisualStudio 指定の例

<?xml version="1.0" encoding="utf-8"?>
<Configuration xmlns="https://www.unrealengine.com/BuildConfiguration">
   <ProjectFileGenerator>
     <Format>VisualStudio2017</Format>
   </ProjectFileGenerator>
</Configuration>

実際にコンパイルに使用する VisualStudio 選択の例

<?xml version="1.0" encoding="utf-8"?>
<Configuration xmlns="https://www.unrealengine.com/BuildConfiguration">
   <WindowsPlatform>
     <Compiler>VisualStudio2017</Compiler>
   </WindowsPlatform>
</Configuration>

Compiler の指定は通常は不要です。ProjectFileGenerator の選択だけで良く、Compiler は自動的に決まります。 唯一の例外が Windows 上で Clang を使用する場合です。 Windows 上で LLVM (clang) を install している場合は、下記の設定により Compiler として clang (clang-cl) を使用することができます。

<?xml version="1.0" encoding="utf-8"?>
<Configuration xmlns="https://www.unrealengine.com/BuildConfiguration">
   <WindowsPlatform>
     <Compiler>Clang</Compiler>
   </WindowsPlatform>
</Configuration>

もちろん対応していない Compiler を使うと Engine のビルドではエラーが出ます。 特定の Module で clang が必要になった場合に、build.cs 内部で指定するのが本来の使い方だと思われます。


UnrealHeaderTool Build の回避方法

Source Code 版 Engine を使用していると、UnrealBuildTool は本来不要なはずの UnrealHeaderTool を何度もビルドしてしまう場合があります。

  • Makefile.bin が存在しない
  • Makefile.bin のバージョンが古い
  • *.uproject file の更新
  • BuildConfigration.xml の更新
  • UnrealBuldTool.exe の更新

などの条件において、Makefile.bin だけでなく UHT 自体をビルドしようとします。 UHT は C++ で書かれているため VisualStudio が install されていないとエラーになります。

Windows 向けにビルドを行う場合は VisualStudio が必要なのですが、他の Platform 向けに出力する場合はその限りではありません。 例えば Android の場合、Android SDK (Android NDK) 自体に toolchain 一式が含まれているので単独でビルドを行うことができます。 実際に Binary 配布版 UE4 (おそらく InstalledBuild 版も同じ) では VisualStudio がなくてもビルドすることができます。

Source Code 版 UE4 でも、UBT 実行時のコマンドラインオプション -NoBuildUHT または下記の設定によって UHT のリビルドを回避することができます。

<?xml version="1.0" encoding="utf-8"?>
<Configuration xmlns="https://www.unrealengine.com/BuildConfiguration">
   <UEBuildConfiguration>
      <bDoNotBuildUHT>true</bDoNotBuildUHT>
   </UEBuildConfiguration>
</Configuration>

例えばチームで開発作業を行っていると、プログラマのみ VisualStudio を所有しておりプランナーやグラフィックデザイナーは VisualStudio を持っていない場合があります。 生成した Windows 向けの *.exe はもちろん共有が必要ですが、上記の方法を使えば各種実機(Android,他コンソール)向けに出力する場合、各自でビルドを行うことができます。

使用方法の例

  1. Target 向けのバイナリを直接作っておきます。
    • UnrealBuildTool.exe MyProject Android Development -Project=“<フルパス>/MyProject/MyProject.uproject” -WaitMutex -NoBuildUHT
  2. ビルドします。
  • UE4Editor 上から実機で起動する場合
    1. プレイボタンのサブメニューから、リストに並んでいる Android Device を選びます。
    • エラーが出る場合は次の ProjectLauncher を使う方法を試してください。
  • UE4Editor 上で ProjectLauncher を使う場合
    1. カスタム起動プロファイルに [+] ボタンで新規追加
    2. 「ビルド」の項目を “ビルドしない” に変更
    3. 「クック」を “バイザブック” に変更
      1. クックしたプラットフォームを “Android_ASTC” に変更 (または適切なもの)
    4. 「パッケージ」を “ローカル環境にパッケージ化および格納”
      • パッケージ化が不要なら “パッケージ化しないでください”
    5. 「デプロイ」を “デプロイしないでください”
      • パッケージ化ではなく起動したい場合は “デバイスにコピー” に変更します。
    6. 右上の矢印で戻る
    7. 今追加したカスタム起動プロファイルの右端にある起動 (“このプロファイルを起動する”) ボタンを押してビルド開始
ue4/buildsystem.txt · 最終更新: 2020/08/23 01:58 by oga