UE4 C++ビルドエラー対応覚書

この記事は何?

この記事はUnreal Engine 4 Advent Calender 2019その2の6日目の記事です。

qiita.com

UE4 C++でのコンパイルビルド時のエラーの対応メモです。 慣れればエラーを見てどんな問題が起こっているのかわかるのですが、慣れていないと原因がわかりづらいです。

そんなエラー文からどのような対応をすればよいのかのメモになります。

2020/01/14:少し追記しました。

クラス名.cpp(1): error : Expected クラス名.h to be first header included.

UCLASSのcppはクラス名.hを最初にインクルードしないといけないというエラー。 最初のインクルード(#include するファイル)をクラス名のものに変更する。 (このファイルに使うクラス名は、接頭詞U,F,A,Iなどを外したものです)

#include "クラス名.h"

関数名 inconsistent dll linkage

なんとか_APIがそのクラス, 関数, 変数を定義したモジュールとあってない。コピペしたときとかにクラス名だけしか変更してなくて起こりがち。

class MYMODULE_API UMyActor : public AActor
//    ^^^^^^^^^^^^
//     ここに注目
//
// この場合、MyModuleというモジュール名(プラグイン名)の中で定義されていないといけない

~関数が未定義 error LNK2019: unresolved external symbol 関数名

関数の実装が見つからないエラー。

Build.csに必要なモジュールがDependencyに追加されていない。 Build.cs以外にuprojectのAdditionalDependenciesに追加されているパターンもあるので、他のプロジェクトから移植する際にはBuild.cs以外にも.uprojectの設定も気をつける。

または定義されていない関数がどこかで呼ばれている可能性もあり。(他のプロジェクトからコピペしたときや、外部公開されていない関数などを呼んでしまった場合に上記とエラー理由と勘違いして起こりがち?)

解決策の例:

PrivateDependencyModuleNames.AddRange(
new string[]
{
 "UnrealEd",
  "LevelEditor",
  "CoreUObject",
  "Engine",
  "Slate",
  "SlateCore",
// こういうところに指定の関数が定義されているモジュール、プラグインを追加する

関数名の前にあるクラス名をUE4APIリファレンス(Unreal Engine API Reference | Unreal Engine Documentation)で検索して、そのクラスのReferencesのModuleに書いてあるモジュール名を追加するとだいたい解決すると思います。

error LNK2019: unresolved external symbol "declspec(dllimport) private: static class UClass * cdecl クラス名::GetPrivateStaticClass(void)

 Privateなクラスを使おうとしたときに出るエラー。(Privateフォルダ以下にあるファイルで定義されているUCLASS) もしくは、Publicであっても外部モジュールの_APIが無いクラスを使おうとしたときとか、DependencyModule足りない場合でも起こる。

その対象のクラスはアクセス権がないので、Privateフォルダにある場合、編集できる領域ならPublicフォルダに移動したり、Publicアクセス権で出たならなんとか_APIを追加する、編集できない場合には他の代替クラスを使用しましょう。 エンジン内にあるクラスのときには、クラス丸ごとコピーして自身のプロジェクトで使う方法もあります。それで使うことが可能ならエンジン改造せずに済むので有効です。

UnrealBuildTool : error : Expecting to find a type to be declared in a module rules named 'モジュールA名' in モジュールB名ModuleRules, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null. This type must derive from the 'ModuleRules' type defined by Unreal Build Tool.

Build.csのModuleRuleを継承しているクラス名がModuleA名と同じではない……ときに出たエラー。あまり見たことはないのでそういう制限によるエラーではないかもです。(IMPLEMENT_MODULEの名前とクラス名が違うからかも?) UnrealBuildToolではクラス名とModule名を同じにする必要がある。

class FMyModule : public ModuleRule
// この場合、MyModuleというモジュール名でないといけない

もしくは、Target.csに追加しているモジュール名が、存在しないモジュール名になっているのが原因かも?

.gen.cpp(23): error C4430: missing type specifier - int assumed. Note: C++ does not support default-int

37>.gen.cpp(23): error C2146: syntax error: missing ';' before identifier 'UClass'
37>.gen.cpp(110): error C2065: 'Z_Construct_UClass_クラス名_NoRegister': undeclared identifier
37>.gen.cpp(151): error C2065: 'Z_Construct_UClass_クラス名_NoRegister': undeclared identifier

コンパイラが型を理解していない。

たとえばクラス名がALevelSequenceActorだった場合、エラーの行数に飛ぶと、 LEVELSEQUENCE_API UClass* Z_Construct_UClass_ALevelSequenceActor_NoRegister(); となっています。 なので、LEVELSEQUENCE_APIの対象モジュールをPublicDependencyやPrivateDependencyに追加して解決します。対象モジュールというのが、今回の例だとLevelSequenceモジュールです。

PublicDependencyModuleNames.AddRange(new string[] { "LevelSequence" });

Please verify that you have sufficient rights to run this command.

VisualStudioをアップデートしたときに起こったエラー。 プリコンパイルヘッダーとかがアップデート前のコンパイラコンパイルしたものが残っていたりして失敗しているみたいです。

リビルドすると治ります。

UnrealBuildTool : error : Unhandled exception: System.IO.DirectoryNotFoundException: パス '\Plugins\HogeHogePlugin\Intermediate\Build\Win64\UE4Editor\Inc\HogeHoge' の一部が見つかりませんでした。

プラグインの中にgenerated.h されるクラスが1つも存在しなくてIncフォルダ内のコード生成が通らなかったため、フォルダが見つからずエラーになってます。 なにか1つUCLASSかUSTRUCTを対象プラグインのコード内で作成して、GENERATED_BODYされるようにしてみましょう。

HogeHoge.generated.h(16): error C2007: #define syntax

#define syntax がたくさん出たときの対処法。対象の行に飛んでみると、なんとかRPC_WRAPPERSやらなんとかINCLASS_NO_PURE_DECLSの部分に飛びます。 これは、フォルダ名の先頭に数字がついているものを使っていると、#defineの定義が失敗してビルドエラーになってしまいます。uprojectを入れているフォルダ名を、数字を先頭にしないか、英字のみにしてみましょう。 (おそらく日本語フォルダ名でも同じエラーが出る)

終わりに

UE4独自の守らなくてはいけないこと、対処法などは調べて対応していくうちに理解していけると思います。 頑張って覚えて楽しいUE4 C++ライフを過ごしましょう。(宣伝:同人誌でUnreal C++本とボイチェン本書いているのでよければどうぞ

明日はNaotsunさんの「自作ブレンドアニメーションノードを作る」です。よろしくお願いします。