Clang交叉编译链接失败最常撞见的是undefined reference to xxx,本质是链接器在目标平台ABI层面拒绝拼合对象,如x86_64 libc.a链接arm64目标、或UE5插件符号未设default visibility导致动态加载器不可见。

Clang交叉编译链接失败的典型报错长什么样
最常撞见的是 undefined reference to `xxx`(符号未定义)、ld: error: unable to find library -lxxx、ld: error: architecture mismatch,或者更隐蔽的 ld: warning: direct access in function xxx to global weak symbol yyy means the weak symbol cannot be overridden at runtime。这些不是“找不到库”的简单提示,而是链接器在目标平台 ABI 层面已经拒绝拼合对象——比如你用了 x86_64 的 libc.a 去链接 arm64 目标,或 UE5 插件导出符号时没加 __attribute__((visibility("default"))),导致 Linux 动态加载器根本看不到它。
检查链接器是否真在用目标平台工具链
Clang 本身不带链接器,它默认调用系统 ld;但交叉编译必须用目标平台专用链接器(如 aarch64-linux-gnu-ld 或 lld)。UBT(UnrealBuildTool)在 LinuxTargetPlatform 下实际会尝试调用 clang++ -target aarch64-linux-gnu --ld-path=/path/to/lld,但如果 LLVM_INSTALL_DIR 指向的是 Windows 主机上的普通 LLVM(不含 lld 或 llvm-ar),就会 fallback 到宿主机 ld,结果必挂。
- 运行
clang++ --target=aarch64-linux-gnu -fuse-ld=lld --version,确认返回中包含lld字样且无报错 - 检查
UE_BUILD_ROOT/Engine/Source/Programs/UnrealBuildTool/Configuration/LinuxToolChain.cs中LinkerPath是否指向了真实存在的lld或交叉ld - 在 BuildGraph 日志里搜索
Using linker:,看它最终选的是哪个二进制;若显示/usr/bin/ld或C:\Windows\System32\ld.exe,说明工具链路径配置失效
动态库路径和符号可见性怎么同步控制
Linux 上链接成功 ≠ 运行成功。很多“链接通过但启动即 segfault”的问题,根源是运行时找不到 libUE5Runtime.so 或其中某个弱符号被隐藏。UE5 默认把大部分模块设为 Hidden 可见性,而 LinuxTargetPlatform 要求插件接口必须显式导出。
- 确保所有需跨模块调用的函数声明前加
UENUM_API/UE5CORE_API宏(它们本质是__attribute__((visibility("default")))) - 在
.Build.cs中对含原生代码的模块启用bEnableUndefinedSymbolReporting = true,强制链接器报出所有未解析符号 - 打包后用
readelf -d YourGame-Linux-Shipping | grep NEEDED检查依赖项是否全为libc.so.6、libpthread.so.0等标准名;若出现libUE5Editor.so就说明误打了 Editor-only 模块
为什么 -L 和 -rpath 不能只靠环境变量生效
UBT 不读取 LD_LIBRARY_PATH,也不自动把 -L 路径转成运行时 RPATH。你手动加的 -L/path/to/sysroot/lib 只影响链接阶段查找,运行时仍会去 /lib、/usr/lib 找——除非你显式注入 -Wl,-rpath,/path/to/sysroot/lib。
- 在
LinuxToolChain.cs的GetAdditionalLinkerArguments方法里硬编码添加-Wl,-rpath,$ORIGIN/../lib(推荐相对路径,避免绝对路径绑定死) - 验证是否写入:用
readelf -d YourGame | grep rpath,输出应含Library rpath: [$ORIGIN/../lib] - 若用 Steam Deck 或国产发行版,还需补上
-Wl,-rpath,/usr/lib/aarch64-linux-gnu(Debian/Ubuntu 系统库路径)
真正卡住人的从来不是“怎么让链接器跑起来”,而是“怎么让它用对的链接器、找对的库、导出对的符号、并在运行时按预期路径加载”。这四步里任何一环断掉,都会表现为“链接失败”——但错误日志往往只告诉你最后一环崩了,前面三环得自己逆推。


















