当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
##### 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 手册

 

方案2 升级引擎

经测试2022.3自带NDK版本为23.1.7779620
使用最新版(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宏定义为1
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处理部分平台的默认解决方案,可靠性高,复杂度低
修改后部分堆栈信息可能会不准确,但暂未出现该情况,也未发现其他影响
// 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
https://forum.unity.com/threads/xcode-can-not-build-unitywebrequest-o.1096375/#post-9744418

方案4 修改构建参数

PlayerSettings.SetIl2CppCodeGeneration(android/ios, UnityEditor.Build.Il2CppCodeGeneration.OptimizeSize)
PlayerSettings面板上也可以设置
OptimizeSize一定程度上缩小了整体代码体量,有可能可以避免该问题

参考文献
https://blog.csdn.net/weixin_42565127/article/details/129419285