Unreal插件 pragma optimize编译错误问题的排查与解决
Unreal各种编译模式与宏的对应关系UE文档: https://docs.unrealengine.com/en-US/Programming/Development/BuildConfigurations
对应关系,仔细看下面这个函数就一目了然:
EBuildConfigurations::Type FApp::GetBuildConfiguration(){#if UE_BUILD_DEBUG return EBuildConfigurations::Debug;#elif UE_BUILD_DEVELOPMENT return bIsDebugGame ? EBuildConfigurations::DebugGame : EBuildConfigurations::Development;#elif UE_BUILD_SHIPPING return EBuildConfigurations::Shipping;#elif UE_BUILD_TEST return EBuildConfigurations::Test;#else return EBuildConfigurations::Unknown;#endif}
特别注意的是, Development模式和DebugGame模式对应的宏都是: UE_BUILD_DEVELOPMENT
每种编译模式都可以和Editor模式组合,区分Editor模式的宏是: WITH_EDITOR
例如,判断当前是否Development模式的唯一正确方法:
#include "Misc/App.h"FApp::GetBuildConfiguration() == EBuildConfigurations::Developmentpragma optimize编译错误问题背景
需要发布一版最新插件,因为要部署给用户用,编译模式必须是: Development Editor
然而发布的过程中,使用Debug模式可以编译出来,但是切换为Development Editor模式却有编译错误:
xxxxx.cpp: error C4426: optimization flags changed after including header, may be due to #pragma optimize()
听取同事的建议,将#pragma optimize("", on)切换为#pragma optimize("", off),也还是不能跳过这个编译错误
我把项目里的所有#pragma optimize都注释掉,也还是一样的错误。
排查过程
因为迫切需要发布最新插件,所以我下定决心排查下到底是什么问题。
我就开始排除大法,
首先,根据错误提示,问题肯定出在xxxxx.cpp里我先怀疑是xxxxx.cpp里include不该include的头文件,所以先把所有include都干掉;结果还是有这个错误继续缩小范围,xxxxx.cpp里所有的函数实现都注释掉,所有函数体直接return,结果还是有这个错误最后一看,这个文件里除了空函数,就剩下了如下的宏:
BEGIN_SLATE_FUNCTION_BUILD_OPTIMIZATION
然后我就开始跟这个宏定义BEGIN_SLATE_FUNCTION_BUILD_OPTIMIZATION,代码摘抄如下:
// SlateOptMacros.h#define BEGIN_SLATE_FUNCTION_BUILD_OPTIMIZATION BEGIN_FUNCTION_BUILD_OPTIMIZATION#define END_SLATE_FUNCTION_BUILD_OPTIMIZATION END_FUNCTION_BUILD_OPTIMIZATION//Platform.h#define BEGIN_FUNCTION_BUILD_OPTIMIZATION PRAGMA_DISABLE_OPTIMIZATION//CoreMiscDefines.h#define PRAGMA_DISABLE_OPTIMIZATION PRAGMA_DISABLE_OPTIMIZATION_ACTUAL#if UE_BUILD_DEBUG #define PRAGMA_ENABLE_OPTIMIZATIONPRAGMA_DISABLE_OPTIMIZATION_ACTUAL#else #define PRAGMA_ENABLE_OPTIMIZATIONPRAGMA_ENABLE_OPTIMIZATION_ACTUAL#endif//WindowsPlatform.h#if !defined(__clang__) #define PRAGMA_DISABLE_OPTIMIZATION_ACTUAL __pragma(optimize("",off)) #define PRAGMA_ENABLE_OPTIMIZATION_ACTUAL__pragma(optimize("",on))#elif defined(_MSC_VER) // Clang only supports __pragma with -fms-extensions #define PRAGMA_DISABLE_OPTIMIZATION_ACTUAL __pragma(clang optimize off) #define PRAGMA_ENABLE_OPTIMIZATION_ACTUAL__pragma(clang optimize on)#endif
阅读代码,发现BEGIN_SLATE_FUNCTION_BUILD_OPTIMIZATION, 其实就相当于执行了一次#pragma optimize
当前编译用的是Development Editor模式,所以执行的是#pragma optimize("", on)
临时方案
由于背景中编译错误的意思就是: 在文件中xxxxx.cpp改变了#pragma optimize的值导致
BEGIN_SLATE_FUNCTION_BUILD_OPTIMIZATION会把#pragma optimize打开,所以我就在xxxxx.cpp的结尾加了行是#pragma optimize("", off),结果就可以编译通过了。
我接着仔细分析这个宏,因为BEGIN_SLATE_FUNCTION_BUILD_OPTIMIZATION具体执行的on或off,取决于当前的编译模式。
因此,当编译模式改为Debug模式后,我加的这行又会造成编译错误;所以这不是最终方案
最终方案
在整个工程中搜索BEGIN_SLATE_FUNCTION_BUILD_OPTIMIZATION,看其他地方是怎么用BEGIN_SLATE_FUNCTION_BUILD_OPTIMIZATION的。
发现其他地方,只要写了BEGIN_SLATE_FUNCTION_BUILD_OPTIMIZATION,都会有END_SLATE_FUNCTION_BUILD_OPTIMIZATION
于是我把#pragma optimize("", off)替换为END_SLATE_FUNCTION_BUILD_OPTIMIZATION,也是可以编译通过了。
跟了一下END_SLATE_FUNCTION_BUILD_OPTIMIZATION,发现他的逻辑和BEGIN_SLATE_FUNCTION_BUILD_OPTIMIZATION是完全对称的
把插件中的其他#pragma optimize语句全部干掉,结果也是ok的
经验与反思
主要3条经验
解决C++编译问题,束手无策的时候可以试试排除大法
不要在工程里手写任何类似#pragma optimize的语句,因为这样写的话,切换UE的编译模式一定会有编译错误
一个文件里,加了BEGIN_SLATE_FUNCTION_BUILD_OPTIMIZATION,千万别忘了加END_SLATE_FUNCTION_BUILD_OPTIMIZATION
Q: 之前同事的建议,将xxxxx.cpp的#pragma optimize("", on)切换为#pragma optimize("", off),也还是不能跳过这个编译错误的原因是什么?
A: 因为xxxxx.cpp里的#pragma optimize写在的文件的头部, 改完之后,先执行的为#pragma optimize("", off), 后执行的BEGIN_SLATE_FUNCTION_BUILD_OPTIMIZATION,所以等于没改。
页:
[1]