在开发 Android 的时候,有需求需要同时支持 arm64 和 armv7,需要在 Build.cs 中同时把 armv7 和 arm64 的链接库都添加到 PublicAdditionalLibraries
中:
1 | PublicAdditionalLibraries.AddRange(new string[] |
但是,在 UE 的 ModuleRules 里没有能判断当前编译的架构的方法(ModuleRules 的构造在编译时只会执行一次),导致编译 arm64 的时候找到了 armv7 的链接库,导致链接错误:
1 | 14>ld.lld: error: D:/Client/Plugins/WWise/ThirdParty/Android_armeabi-v7a/Profile/lib\libAkSoundEngine.a(AkAudioLib.o) is incompatible with aarch64linux |
所以,需要找到一种方法,能够在使用 PublicAdditionalLibraries
同时添加了 arm64 和 armv7 链接库的情况下让编译器能够自动地匹配到应该去什么路径来执行链接。
翻了一下 UBT 的代码,发现 UE 中对在 Android 上对链接库的路径做了模式匹配:
1 | static private Dictionary<string, string[]> AllArchNames = new Dictionary<string, string[]> { |
最关键的就是这这一行:
1 | if (Regex.IsMatch(Dir, "/" + ArchName + "$") || Regex.IsMatch(Dir, "/" + ArchName + "/") || Regex.IsMatch(Dir, "/" + ArchName + "_API[0-9]+_NDK[0-9]+", RegexOptions.IgnoreCase)) |
根据上面正则的规则,可以把链接库的路径改为:
1 | XXXX/armeabi-v7a/ |
只要我们为 Android 添加的链接库路径匹配这个规则,使用 UE 编译时就会自动使用对应架构的链接库(.a 和.so 都是可以使用这个规则的)。
UE 这也太坑了,这个要求文档没写,完全是一个潜规则。