UE4之宏与预编译指令定义
在UBT中添加宏定义
UnrealEngine\Engine\Source\Programs\UnrealBuildTool\Configuration\ModuleRules.cs
UnrealEngine\Engine\Source\Programs\UnrealBuildTool\Configuration\UEBuildPlatform.cs
UnrealEngine\Engine\Source\Programs\UnrealBuildTool\Configuration\UEBuildTarget.cs
UnrealEngine\Engine\Source\Programs\UnrealBuildTool\Platform\Android\UEBuildAndroid.cs
UnrealEngine\Engine\Source\Programs\UnrealBuildTool\Platform\IOS\UEBuildIOS.cs
UnrealEngine\Engine\Source\Runtime\Core\Core.Build.cs
Definitions文件
Definitions文件是编译时存放所有定义的宏
编译编辑器(Debug)时,这些宏会被写入Intermediate\Build\Win64\UE4Editor\Debug\<Module>\Definitions.<Module>.h中
编译win64的cook版本(Debug)时,这些宏会被写入Intermediate\Build\Win64\<MyGame>\Debug\<Module>\Definitions.<Module>.h中
编译Android的cook版本(Debug)时,这些宏会被写入Intermediate\Build\Android\<MyGame>\Debug\<Module>\Definitions.<Module>.h中
编译IOS的cook版本(Debug)时,这些宏会被写入Intermediate\Build\IOS\<MyGame>\Debug\<Module>\Definitions.<Module>.h中
ue4.26在vs2019缺省用c++14编译
注:Intermediate\ProjectFiles\*vcxproj工程文件的生成代码在G:\svn\UnrealEngine\Engine\Source\Programs\UnrealBuildTool\ProjectFiles\VisualStudio\VCProject.cs
使用__cplusplus宏在代码中判断c++标准库版本:
if (__cplusplus == 201703L) { UE_LOG(LogTemp, Log, TEXT("C++17.")); } else if (__cplusplus == 201402L) { UE_LOG(LogTemp, Log, TEXT("C++14.")); } else if (__cplusplus == 201103L) { UE_LOG(LogTemp, Log, TEXT("C++11.")); } else if (__cplusplus == 199711L) { UE_LOG(LogTemp, Log, TEXT("C++98.")); } else { UE_LOG(LogTemp, Log, TEXT("pre-standard C++.")); }
基础宏
UnrealEngine\Engine\Source\Runtime\Core\Public\HAL\PreprocessorHelpers.h
UnrealEngine\Engine\Source\Runtime\Core\Public\Misc\Build.h
UnrealEngine\Engine\Source\Runtime\Core\Public\HAL\Platform.h
宏 | 说明 |
ENGINE_MAJOR_VERSION | UE4.26.1下,该宏为4 |
ENGINE_MINOR_VERSION | UE4.26.1下,该宏为26 |
ENGINE_PATCH_VERSION | UE4.26.1下,该宏为1 |
WITH_EDITOR | 编辑器中或Standalone,该宏都为1 |
WITH_EDITORONLY_DATA |
在windows、macos、unix平台的编辑器、Client下该宏为1,DS下该宏为0 其他Android、IOS等平台,该宏为0 与WITH_EDITOR相比,能被UHT识别,可用来包裹UPROPERTY成员变量和UFUNCTION成员函数。
UHT在针对WITH_EDITOR、WITH_EDITORONLY_DATA也做了一些特殊处理。详见:UHT里的条件宏处理逻辑 |
WITH_ENGINE | 是否需要编译引擎代码 |
UE_SERVER |
TargetType为Server cook DS版本,该宏为1。编辑器中,该宏为0 宏UE_SERVER为1时,宏USE_NULL_RHI也为1 |
UE_GAME |
TargetType为Client或Game cook 游戏版本,该宏为1。编辑器中,该宏为0 |
UE_CLIENT |
TargetType为Client |
UE_EDITOR | TargetType为Editor |
UE_APP_NAME | 当前App的名称 如:#define UE_APP_NAME "MyTest1" |
PLATFORM_WINDOWS | 在windows开发机上,编辑器、standalone、cook win64版本,该宏都为1 |
PLATFORM_HOLOLENS | Hololens平台 |
PLATFORM_DESKTOP | 在桌面开发机(windows、mac、linux)上,编辑器、standalone、cook pc版本,该宏都为1 |
PLATFORM_ANDROID | 编译Android版本时,该宏为1 |
PLATFORM_ANDROID_ARM64 | 编译Android ARM64版本时,该宏为1 |
PLATFORM_APPLE | 是否为苹果平台,mac、ios该宏为1 |
PLATFORM_IOS | 编译IOS版本时,该宏为1 |
PLATFORM_LINUX PLATFORM_UNIX |
编译Linux/Unix DS版本时,该宏为1 注:这2个宏等价 |
PLATFORM_MAC | 在macos开发机上,该宏为1 |
PLATFROM_SWITCH | Switch平台 |
SWITCHRHI | 使用SwitchRHI来作为渲染 |
PLATFORM_SUPPORTS_MULTITHREADED_GC | 是否支持多线程GC。在HoloLen平台该宏为0,其他平台为1 |
PLATFORM_CAN_SUPPORT_EDITORONLY_DATA | 平台是否支持编辑器数据。在windows、macos、unix平台该宏为1,其他平台为0 |
WITH_EDITORONLY_DATA |
在windows、macos、unix平台的编辑器、Client下该宏为1,DS下该宏为0 其他Android、IOS等平台,该宏为0 |
PLATFORM_IS_ANSI_MALLOC_THREADSAFE | Ansi Malloc线程安全。在windows、macos、unix、ios平台该宏为1,其他平台为0 |
PLATFORM_ALLOW_NULL_RHI | IOS平台该宏为1,其他平台为0 |
IS_MONOLITHIC |
宏为1,即:代码会编译到一个模块中 如:cook后的pc和手机版本 宏为0,即:代码会编译到多个dll或dylib中 如:在编辑器或standalone下 |
IS_PROGRAM |
TargetType为TargetType.Program 是否为一个独立的可执行程序(如:ShaderCompileWorker、UnrealPak等)。 编译Android/IOS时,该宏为0 |
UE_BUILD_DEBUG | 编译Debug版本 |
UE_BUILD_DEVELOPMENT | 编译Development版本 |
UE_BUILD_TEST | 编译Test版本 |
UE_BUILD_SHIPPING | 编译Shipping版本 |
NO_LOGGING |
是否打印log。Debug/Development该宏为0,Shipping/Test版下该宏为!USE_LOGGING_IN_SHIPPING 注:USE_LOGGING_IN_SHIPPING的开启可通过Target.cs中的bUseLoggingInShipping控制 |
ALLOW_CONSOLE |
是否能输出到Console上。Debug/Development/Test该宏为1,Shipping版下该宏为ALLOW_CONSOLE_IN_SHIPPING |
ALLOW_DEBUG_FILES |
是否允许输出各种调试相关的文件(如:DumpFPSChart、DumpMaterialStats、DumpShaderStats、DumpMemReport等)到磁盘。 Debug/Development/Test该宏为1,Shipping版下该宏为0 |
WITH_PROFILEGPU |
是否允许GPU Profile。Debug/Development该宏为1。 Test需要再额外开启ALLOW_PROFILEGPU_IN_TEST宏,该宏才为1。 Shipping需要再额外开启ALLOW_PROFILEGPU_IN_SHIPPING宏,该宏才为1。 |
WITH_RPC_REGISTRY |
是否允许RPC Registry。Debug/Development/Test该宏为1。 Shipping需要再额外开启USE_RPC_REGISTRY_IN_SHIPPING宏,该宏才为1。 |
CSV_PROFILER |
是否启用CSV Profiler。Debug/Development/Test该宏为1。 Shipping需要再额外开启CSV_PROFILER_ENABLE_IN_SHIPPING宏,该宏才为1。 |
ENABLE_METAL_GPUEVENTS |
是否开启Metal GPU Event。Debug/Development该宏为1,Shipping该宏为0。 Test需要再额外开启ENABLE_METAL_GPUEVENTS_IN_TEST宏,该宏才为1。 |
ENABLE_METAL_GPUPROFILE |
宏ENABLE_METAL_GPUEVENTS开启时,该宏也会对应开启。 |
USE_CHECKS_IN_SHIPPING |
是否在Shipping中使用check。缺省为0 |
USE_ENSURES_IN_SHIPPING | 是否在Shipping中使用ensure。缺省为0 |
PRESERVE_LOG_BACKUPS_IN_SHIPPING | 是否在Shipping中启用log备份(注:Debug/Development/Test会一直启用log备份)。缺省为1 |
USE_NETWORK_PROFILER | 是否允许网络Profiler。Debug/Development该宏为1,Test/Shipping版下该宏为0 |
FORCE_USE_STATS | 强制开启STATS宏。缺省为0。在编译shipping时,可将该宏设为1,让shipping包拥有STATS能力。 |
ENABLE_STATNAMEDEVENTS | 使用系统的埋点 |
ENABLE_STATNAMEDEVENTS_UOBJECT | 为UObject对象使用系统的埋点 |
ENABLE_RHI_VALIDATION | 启用RHI有效性检查。Debug/Development该宏为1,Test/Shipping版下该宏为0 |
DISABLE_CHEAT_CVARS |
是否禁用Cheat变量。注:开启Cheat变量,可方便开发者对功能进行快速测试。 Debug/Development该宏为0,Shipping该宏为1。 Test该宏缺省为0,开启ALLOW_CHEAT_CVARS_IN_TEST宏,该宏才为0。 |
USE_HANG_DETECTION |
启用时,会使用FThreadHeartBeat线程进行挂起检测。 Android/IOS平台不支持检测,具体详见:AllowThreadHeartBeat()函数 |
USE_HITCH_DETECTION | 卡顿检测 |
AGGRESSIVE_MEMORY_SAVING | 是否开启激进内存节省。缺省为0 |
PSO_TRACK_CACHE_STATS | 开启pso追踪统计 |
GET_DEVICE_ID_UNAVAILABLE |
是否允许获取Device ID(该宏为1,会始终返回一个空的Device ID字符串)。缺省为0 |
WITH_PHYSX |
为1,表示使用PhysX引擎 |
PHYSICS_INTERFACE_PHYSX |
为1,表示使用PhysX引擎 |
WITH_IMMEDIATE_PHYSX |
是否启用Immediate PhysX。缺省该宏为0 |
WITH_APEX |
为1,表示使用Apex框架 |
WITH_APEX_CLOTHING |
为1,表示使用Apex Clothing |
WITH_CLOTH_COLLISION_DETECTION |
为1,表示使用布料碰撞检测 |
WITH_PHYSX_COOKING |
为1,表示使用PhysX Cooking。注:即使在运行时,Apex也需要PhysX Cooking |
WITH_NVCLOTH |
为1,表示使用NvCloth库 |
WITH_CHAOS |
为1,表示使用Chaos引擎 |
WITH_CHAOS_CLOTHING |
为1,表示使用Chaos Clothing |
UE_ENABLE_ICU |
为1,表示使用ICU(International Components for Unicode)库。 ICU库提供了处理Unicode字符、字符串和文本的功能,包括字符集转换、字符串比较、正则表达式、日期和时间格式化等 为0,表示使用操作系统提供的Unicode支持。 这可能会导致一些Unicode相关的问题,例如无法正确处理某些字符集、无法正确比较字符串等。 |
预编译相关的宏
宏 | 说明 |
DISABLE_DEPRECATION | 不打印如下信息:The DEPRECATED macro has been deprecated in favor of UE_DEPRECATED(). |
PRAGMA_POP | #pragma warning (pop) |
EMIT_CUSTOM_WARNING_AT_LINE | 在某行打印一句警告 |
PRAGMA_DISABLE_DEPRECATION_WARNINGS PRAGMA_ENABLE_DEPRECATION_WARNINGS |
禁止c/c++ deprecation警告 |
PRAGMA_DISABLE_SHADOW_VARIABLE_WARNINGS PRAGMA_ENABLE_SHADOW_VARIABLE_WARNINGS |
禁止影子变量警告 |
PRAGMA_DISABLE_UNSAFE_TYPECAST_WARNINGS PRAGMA_ENABLE_UNSAFE_TYPECAST_WARNINGS |
禁止不安全类型转换警告 |
PRAGMA_DISABLE_UNDEFINED_IDENTIFIER_WARNINGS PRAGMA_ENABLE_UNDEFINED_IDENTIFIER_WARNINGS |
禁止未定义宏警告 |
PRAGMA_DISABLE_MISSING_VIRTUAL_DESTRUCTOR_WARNINGS PRAGMA_ENABLE_MISSING_VIRTUAL_DESTRUCTOR_WARNINGS |
禁止非虚析构函数警告 |
PRAGMA_DISABLE_REORDER_WARNINGS PRAGMA_ENABLE_REORDER_WARNINGS |
禁止成员变量按声明顺序依次初始化警告 |
PRAGMA_DISABLE_REGISTER_WARNINGS PRAGMA_ENABLE_REGISTER_WARNINGS |
禁止使用register存储类关键字警告 注:C++ 语言中已弃用或删除 auto 和 register 存储类关键字 |
PRAGMA_PUSH_PLATFORM_DEFAULT_PACKING PRAGMA_POP_PLATFORM_DEFAULT_PACKING |
恢复系统平台默认对齐字节数 |
THIRD_PARTY_INCLUDES_START THIRD_PARTY_INCLUDES_END |
包含第三方头文件 注:会disable很多warning |
不同平台下,该宏的实现详见如下文件
UnrealEngine\Engine\Source\Runtime\Core\Public\Android\AndroidPlatformCompilerPreSetup.h UnrealEngine\Engine\Source\Runtime\Core\Public\Apple\ApplePlatformCompilerPreSetup.h UnrealEngine\Engine\Source\Runtime\Core\Public\Clang\ClangPlatformCompilerPreSetup.h UnrealEngine\Engine\Source\Runtime\Core\Public\GenericPlatform\GenericPlatformCompilerPreSetup.h UnrealEngine\Engine\Source\Runtime\Core\Public\HoloLens\HoloLensPlatformCompilerPreSetup.h UnrealEngine\Engine\Source\Runtime\Core\Public\IOS\IOSPlatformCompilerPreSetup.h UnrealEngine\Engine\Source\Runtime\Core\Public\Linux\LinuxPlatformCompilerPreSetup.h UnrealEngine\Engine\Source\Runtime\Core\Public\Lumin\LuminPlatformCompilerPreSetup.h UnrealEngine\Engine\Source\Runtime\Core\Public\Mac\MacPlatformCompilerPreSetup.h UnrealEngine\Engine\Source\Runtime\Core\Public\Unix\UnixPlatformCompilerPreSetup.h UnrealEngine\Engine\Source\Runtime\Core\Public\Windows\WindowsPlatformCompilerPreSetup.h
编译用命令行文件
TargetCode.response内容如下:
/D_CRT_STDIO_LEGACY_WIDE_SPECIFIERS=1 /D_SILENCE_STDEXT_HASH_DEPRECATION_WARNINGS=1 /D_WINDLL /D_DISABLE_EXTENDED_ALIGNED_STORAGE 。。。 。。。 /DUE_BUILD_DEBUG=1 /DWITH_EDITOR=1 /DWITH_ENGINE=1 /DWITH_UNREAL_DEVELOPER_TOOLS=0 /DWITH_PLUGIN_SUPPORT=0 /DUE_BUILD_MINIMAL=0 /DIS_MONOLITHIC=0 /DIS_PROGRAM=0 /DPLATFORM_WINDOWS=1 /DOVERRIDE_PLATFORM_HEADER_NAME=Windows /source-charset:utf-8 /execution-charset:utf-8 /I . /I D:\svn\ThirdParty /I ... ... /I D:\svn\TPSProject\Private /EP "D:\svn\TPSProject\Private\TargetCode.cpp"
x64 Native Tools Command Prompt for VS2019
cd /d %EngineDir%\Engine\Source cl.exe @"G:\TargetCode.response" > "G:\TargetCode.i.cpp"
注:也可以通过在项目的Target.cs文件里面,将bPreprocessOnly设置为true,来生成出来预处理后的文件
#include头文件
包括外部模块的头文件时,只用写Public、Classes文件夹之后的相对目录。
包含内部模块的头文件时,除了写Public、Classes文件夹之后的相对目录,还可以只用写Private文件夹之后的相对目录。
具体逻辑详见:UnrealEngine\Engine\Source\Programs\UnrealBuildTool\Configuration\UEBuildModuleCPP.cs的AddDefaultIncludePaths函数
private void AddDefaultIncludePaths() { // Add the module's parent directory to the public include paths, so other modules may include headers from it explicitly. foreach (DirectoryReference ModuleDir in ModuleDirectories) { PublicIncludePaths.Add(ModuleDir.ParentDirectory); // Add the base directory to the legacy include paths. LegacyPublicIncludePaths.Add(ModuleDir); // Add the 'classes' directory, if it exists DirectoryReference ClassesDirectory = DirectoryReference.Combine(ModuleDir, "Classes"); if (DirectoryLookupCache.DirectoryExists(ClassesDirectory)) { PublicIncludePaths.Add(ClassesDirectory); } // Add all the public directories DirectoryReference PublicDirectory = DirectoryReference.Combine(ModuleDir, "Public"); if (DirectoryLookupCache.DirectoryExists(PublicDirectory)) { PublicIncludePaths.Add(PublicDirectory); ReadOnlyHashSet<string> ExcludeNames = UEBuildPlatform.GetBuildPlatform(Rules.Target.Platform).GetExcludedFolderNames(); EnumerateLegacyIncludePaths(DirectoryItem.GetItemByDirectoryReference(PublicDirectory), ExcludeNames, LegacyPublicIncludePaths); } // Add the base private directory for this module DirectoryReference PrivateDirectory = DirectoryReference.Combine(ModuleDir, "Private"); if (DirectoryLookupCache.DirectoryExists(PrivateDirectory)) { PrivateIncludePaths.Add(PrivateDirectory); } } }
如:UnrealEngine\Engine\Source\Runtime\Engine\Public\SceneManagement.h 写成
#include "SceneManagement.h"
如:UnrealEngine\Engine\Source\Runtime\Engine\Classes\GameFramework\Actor.h 写成
#include "GameFramework/Actor.h"
如果只想用GEngine,只需要#include "Engine/Engine.h"就行,不要用#include "Engine.h"(#include "Engine.h"里面加了一大堆其他头文件,非常容易与windows sdk发生冲突,导致一些奇怪的编译错误)
UnrealEngine\Engine\Source\Runtime\Engine\Classes\Engine\Engine.h // #include "Engine.h" UnrealEngine\Engine\Source\Runtime\Engine\Public\Engine.h // #include "Engine/Engine.h"
跨平台目录说明
注1:Lumin是Magic Leap公司基于Linux和Android开发的穿戴式设备操作系统,目前已用在自家产品Magic Leap One AR头盔中
注2:HoloLens是Microsoft公司基于win10开发的混合现实的穿戴式设备操作系统,目前已用在自家产品HoloLens AR头盔中
注3:GenericPlatform提供公共基类,Windows、Linux、Unix、Mac、Apple、HoloLens、Lumin、Android、IOS从GenericPlatform上派生来实现各平台的功能
注4:通过HAL来对外提供统一的接口。其他模块仅需要include HAL目录下的头文件即可