generated.hをincludeするヘッダファイルに#ifdefなどのプリプロセッサを使うことはできますか

お世話になっております。

デバッグ目的のコードなどをあとでShippingビルドするときに削除できるように、#ifdefで囲っていたのですが、クラス宣言がifdefで囲われると、そのプリプロセッサが有効であってもgenerated.hが生成されずincludeがエラーになるように見えます。

単純な例ですと、以下のようにコードを記述します。

 #if 1
 
 #include "GameFramework/CheatManager.h"
 #include "MyCommand.generated.h"
 
 UCLASS()
 class MY_API UMyCommand : public UCheatManager
 {
   GENERATED_BODY()
 
 };
 
#endif

if 1なので絶対に有効なコードですが、このままビルドすると

fatal error C1083: include ファイルを開けません。‘MyCommand.generated.h’:No such file or directory

とエラーになってしまいます。 #ifdefの位置をincludeの前にしても後にしても同じです。

generated.hのincludeが必要なファイルに、#ifdef系のプリプロセッサを記述する方法はありますでしょうか。

よろしくお願いいたします。

そのgenerated.hというフィアルを生成するUnrealHeaderToolというツールはC++のすべてを対応する物ではなく、C++の一部の小さいサブセットを対応する物で、#ifなどを対応していないと思います。プリプロセッサ的に#include、CPPのマクロとNULLぐらいしか対応していません。つまり、UCLASSやUSTRUCTの定義にそれ以外のプリプロセッサを使えません。

代わりにそのUMyCommandのヘッダーファイルをincludeする.cppファイルの#include MyCommand.hの文を#if UE_BUILD_SHIPPINGで消すことは出来ると思います。CPPファイルにincludeされていないならコンパイルされないはずです。

他の方法としては…

例えば、御社のPlayerControllerのEnableCheatsはShippingBuildの場合に無効に出来ます:

void AMyPlayerController::EnableCheats()
{
#if !(UE_BUILD_SHIPPING || UE_BUILD_TEST)
	AddCheats(true);
#endif
}

そして、御社のプロジェクトのGameModeのAllowCheatsの関数を以下のようにすればと思います:

bool AMyGameMode::AllowCheats(APlayerController* P)
{
#if (UE_BUILD_SHIPPING || UE_BUILD_TEST)
	return false;
#else
	return ( GetNetMode() == NM_Standalone || GIsEditor ); // Always allow cheats in editor (PIE now supports networking)
#endif
}

よろしくお願いします。

了解いたしました。

そうなると、デバッグ用でもUCLASS内関数やクラスの定義はプロジェクトから削除しない限り最後まで残るので、シンボル情報解析などされても問題の無い名前をつけるように注意しておく必要がありますね。

ありがとうございました。

最終的なShippingビルドに含みたくない定義を持っているヘッダーファイルをインクルードする場所を#ifで囲まれると、C++のトランスレーションユニットに含まないはずですので、最終的なビルドに入らないと思います。

よろしくお願いします。

はい、もう今後はこのBranchではShippingしかビルドしないと決めてしまえばデバッグコードの削除はできますが、同じコードで最後までDevelopビルドも使い続けようとすると注意が必要そうです。