当il2cpp生成的C++文件过多时,部分版本(2022.3)的unity会遇到链接失败的问题(ios/android均存在,在部分打包机上几乎稳定重现)
项目il2cpp目录下的cpp代码量约1000左右,大小接近2G
打包失败具体表现为Library/Bee/artifacts/Android/xxx/libil2cpp.so文件生成失败
log如下
Link_Android_arm32 Library/Bee/artifacts/Android/xxx/libil2cpp.so
经测试2022.3自带NDK版本为23.1.7779620
使用最新版(r26d
对于安卓,可单独替换新版NDK
或仅替换NDK内llvm目录(Program Files/Unity/Hub/Editor/2022.3.21f1/Editor/Data/PlaybackEngines/AndroidPlayer/NDK/toolchains/llvm)
IOS相关库结构有所不同,可能需要根据具体报错位置从新版引擎中更新Bee.Toolchain.LLVM.dll或相关报错位置的库文件
Unity\Hub\Editor\2022.3.21f1\Editor\Data\PlaybackEngines\iOSSupport\il2cpp\libil2cpp\os\c-api\il2cpp-config-platforms.h
Unity\Hub\Editor\2022.3.21f1\Editor\Data\il2cpp\libil2cpp\os\c-api\il2cpp-config-platforms.h
该方案也是unity处理部分平台的默认解决方案,可靠性高,复杂度低
修改后部分堆栈信息可能会不准确,但暂未出现该情况,也未发现其他影响
##### CommandLine
"C:/xxx/Unity/Hub/Editor/2022.3.21f1/Editor/Data/PlaybackEngines/AndroidPlayer/NDK/toolchains/llvm/prebuilt/windows-x86_64/bin/clang++" @"Library\Bee\artifacts\rsp\xxx.rsp"
##### ExitCode
1
##### Output
ld.lld: error: E:/xxx/Library/Bee/artifacts/Android/il2cppOutput/cpp\xxx.cpp:29199:(il2cpp+0x2456C): relocation R_ARM_CALL out of range: -33554440 is not in [-33554432, 33554431]
clang++: error: linker command failed with exit code 1 (use -v to see invocation)
*** Tundra build failed (115.65 seconds - 0:01:55), 827 items updated, 5499 evaluated
方案1 删减或剔除代码
可以手动删减冗余的代码和库以缩小整体的代码体量
可搭配Unity自带的代码裁剪功能
注意裁剪时需要配置link.xml保留不希望被裁剪的部分
PlayerSettings.SetManagedStrippingLevel
相关文档如下
托管代码剥离 - Unity 手册
The Unity linker - Unity 手册
可搭配Unity自带的代码裁剪功能
注意裁剪时需要配置link.xml保留不希望被裁剪的部分
PlayerSettings.SetManagedStrippingLevel
相关文档如下
托管代码剥离 - Unity 手册
The Unity linker - Unity 手册
方案2 升级引擎
使用最新版(r26d
26.3.11579264
)NDK后安卓构建时不再复现该问题对于安卓,可单独替换新版NDK
或仅替换NDK内llvm目录(Program Files/Unity/Hub/Editor/2022.3.21f1/Editor/Data/PlaybackEngines/AndroidPlayer/NDK/toolchains/llvm)
IOS相关库结构有所不同,可能需要根据具体报错位置从新版引擎中更新Bee.Toolchain.LLVM.dll或相关报错位置的库文件
方案3 修改引擎
修改引擎代码il2cpp-config-platforms.h中IL2CPP_LARGE_EXECUTABLE_ARM_WORKAROUND宏定义为1Unity\Hub\Editor\2022.3.21f1\Editor\Data\PlaybackEngines\iOSSupport\il2cpp\libil2cpp\os\c-api\il2cpp-config-platforms.h
Unity\Hub\Editor\2022.3.21f1\Editor\Data\il2cpp\libil2cpp\os\c-api\il2cpp-config-platforms.h
该方案也是unity处理部分平台的默认解决方案,可靠性高,复杂度低
修改后部分堆栈信息可能会不准确,但暂未出现该情况,也未发现其他影响
// Large executables on ARM64 and ARMv7 can cause linker errors. // Specifically, the arm instruction set limits the range a branch can // take (e.g. 128MB on ARM64). Normally, the linker will insert branch // islands to bridge gaps larger than the maximum branch range. However, // branch islands only work within a section, not across sections. So if // IL2CPP puts managed code into a specific section of the binary, branch // isalnds won't work. That means that proejcts with a large executable // size may fail to link. // // Set the define IL2CPP_LARGE_EXECUTABLE_ARM_WORKAROUND to a value of 1 // work around this issue. // // The cost of this define is in correctness of managed stack traces. // With this define enabled, managed stack traces maybe not be correct // in some cases, because the stack trace generation code must use // fuzzy heuristics to detemine if a given instrion pointer is in a // managed method. #if IL2CPP_TARGET_EMBEDDED_LINUX && IL2CPP_TARGET_ARMV7 // currently on EmbeddedLinux stack unwinding doesn't work properly when using custom code sections on ARMv7 // as a result processing exceptions from managed code and resolving managed stack traces doesn't work #ifndef IL2CPP_LARGE_EXECUTABLE_ARM_WORKAROUND #define IL2CPP_LARGE_EXECUTABLE_ARM_WORKAROUND 1 #endif #endif #if IL2CPP_TARGET_ARM64 || IL2CPP_TARGET_ARMV7 #ifndef IL2CPP_LARGE_EXECUTABLE_ARM_WORKAROUND #define IL2CPP_LARGE_EXECUTABLE_ARM_WORKAROUND 0 #endif #endif
方案4 修改构建参数
PlayerSettings.SetIl2CppCodeGeneration(android/ios, UnityEditor.Build.Il2CppCodeGeneration.OptimizeSize)PlayerSettings面板上也可以设置
OptimizeSize一定程度上缩小了整体代码体量,有可能可以避免该问题
参考文献
https://blog.csdn.net/weixin_42565127/article/details/129419285
QQ:393422044
Email:fkrfkrfkr@163.com