You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Conan集成LLVM-13时链接Support库遇未定义引用错误求助

问题背景

我正在使用LLVM conan包构建编译器,此前一切正常,但调用llvm::sys::getDefaultTargetTriple和llvm::TargetRegistry::lookupTarget时出现未定义引用错误。这两个函数来自LLVM Support库,且llvm::sys::getDefaultTargetTriple是自动生成的(本地能找到对应的.inc源文件)。构建日志显示Conan已指示CMake链接LLVM Support库(含-lLLVMSupport参数)。

当前环境是LLVM-13.0.0和gcc-12.0.1,之前GCC5搭配LLVM3/4时出现过类似问题,已修改Conan profile的C++ ABI设置但暂未生效,可能会尝试重新构建LLVM。

急需解决以下问题:

  1. 如何手动获取当前操作系统对应的目标三元组字符串?LLVM文档显示它基于宏,用gcc -dumpmachine是否可行?
  2. 手动生成“target”的可行性如何?
  3. 核心问题:如何修复链接错误,成功链接llvm::sys::getDefaultTargetTriple和llvm::TargetRegistry::lookupTarget?
完整构建日志
root@3129d254c74c:~/workdir/compilerbuild# ninja warp_compiler
[2/2] Linking CXX executable bin/warp_compiler
FAILED: bin/warp_compiler 
: && /usr/bin/c++   CMakeFiles/warp_compiler.dir/Compiler/Compile.cpp.o CMakeFiles/warp_compiler.dir/Compiler/FunctionParser.cpp.o CMakeFiles/warp_compiler.dir/Compiler/Main.cpp.o -o bin/warp_compiler -L/root/.conan/data/cpputest/4.0/_/_/package/7f06ab4d29b1f14af224d13dc05f362c6832ed41/lib   -L/root/.conan/data/llvm-core/13.0.0/_/_/package/6efbb14f313e71b5e1dbf77c1c011f47614b7c7c/lib   -L/root/.conan/data/libxml2/2.9.10/_/_/package/c4a7cacf01760cbd7354b11a55bf653f7df2bf5d/lib   -L/root/.conan/data/zlib/1.2.12/_/_/package/2a19826344ff00be1c04403f2f8e7008ed3a7cc6/lib   -L/root/.conan/data/libiconv/1.17/_/_/package/2a19826344ff00be1c04403f2f8e7008ed3a7cc6/lib -Wl,-rpath,/root/.conan/data/cpputest/4.0/_/_/package/7f06ab4d29b1f14af224d13dc05f362c6832ed41/lib:/root/.conan/data/llvm-core/13.0.0/_/_/package/6efbb14f313e71b5e1dbf77c1c011f47614b7c7c/lib:/root/.conan/data/libxml2/2.9.10/_/_/package/c4a7cacf01760cbd7354b11a55bf653f7df2bf5d/lib:/root/.conan/data/zlib/1.2.12/_/_/package/2a19826344ff00be1c04403f2f8e7008ed3a7cc6/lib:/root/.conan/data/libiconv/1.17/_/_/package/2a19826344ff00be1c04403f2f8e7008ed3a7cc6/lib  lib/liblibwarp.a  -lCppUTestExt  -lCppUTest  -lLLVMTableGenGlobalISel  -lLLVMTableGen  -lLLVMFileCheck  -lLLVMAArch64AsmParser  -lLLVMAArch64CodeGen  -lLLVMAArch64Disassembler  -lLLVMAArch64Desc  -lLLVMAArch64Info  -lLLVMAArch64Utils  -lLLVMAMDGPUAsmParser  -lLLVMAMDGPUCodeGen  -lLLVMMIRParser  -lLLVMAMDGPUDisassembler  -lLLVMAMDGPUDesc  -lLLVMAMDGPUInfo  -lLLVMAMDGPUUtils  -lLLVMARMAsmParser  -lLLVMARMCodeGen  -lLLVMARMDisassembler  -lLLVMARMDesc  -lLLVMARMInfo  -lLLVMARMUtils  -lLLVMAVRAsmParser  -lLLVMAVRCodeGen  -lLLVMAVRDesc  -lLLVMAVRDisassembler  -lLLVMAVRInfo  -lLLVMBPFAsmParser  -lLLVMBPFCodeGen  -lLLVMBPFDesc  -lLLVMBPFDisassembler  -lLLVMBPFInfo  -lLLVMCoverage  -lLLVMDWARFLinker  -lLLVMDWP  -lLLVMDebugInfoGSYM  -lLLVMDlltoolDriver  -lLLVMFrontendOpenACC  -lLLVMFuzzMutate  -lLLVMHexagonCodeGen  -lLLVMHexagonAsmParser  -lLLVMHexagonDisassembler  -lLLVMHexagonDesc  -lLLVMHexagonInfo  -lLLVMInterfaceStub  -lLLVMInterpreter  -lLLVMLTO  -lLLVMExtensions  -lLLVMLanaiCodeGen  -lLLVMLanaiAsmParser  -lLLVMLanaiDisassembler  -lLLVMLanaiDesc  -lLLVMLanaiInfo  -lLLVMLibDriver  -lLLVMOption  -lLLVMLineEditor  -lLLVMMCA  -lLLVMMCJIT  -lLLVMMSP430AsmParser  -lLLVMMSP430CodeGen  -lLLVMMSP430Desc  -lLLVMMSP430Disassembler  -lLLVMMSP430Info  -lLLVMMipsAsmParser  -lLLVMMipsCodeGen  -lLLVMMipsDesc  -lLLVMMipsDisassembler  -lLLVMMipsInfo  -lLLVMNVPTXCodeGen  -lLLVMNVPTXDesc  -lLLVMNVPTXInfo  -lLLVMObjectYAML  -lLLVMOrcJIT  -lLLVMPasses  -lLLVMCoroutines  -lLLVMipo  -lLLVMFrontendOpenMP  -lLLVMIRReader  -lLLVMAsmParser  -lLLVMInstrumentation  -lLLVMLinker  -lLLVMVectorize  -lLLVMObjCARCOpts  -lLLVMExecutionEngine  -lLLVMRuntimeDyld  -lLLVMJITLink  -lLLVMOrcTargetProcess  -lLLVMOrcShared  -lLLVMPowerPCAsmParser  -lLLVMPowerPCCodeGen  -lLLVMPowerPCDesc  -lLLVMPowerPCDisassembler  -lLLVMPowerPCInfo  -lLLVMRISCVAsmParser  -lLLVMRISCVCodeGen  -lLLVMRISCVDisassembler  -lLLVMRISCVDesc  -lLLVMRISCVInfo  -lLLVMSparcAsmParser  -lLLVMSparcCodeGen  -lLLVMSparcDesc  -lLLVMSparcDisassembler  -lLLVMSparcInfo  -lLLVMSymbolize  -lLLVMDebugInfoPDB  -lLLVMSystemZAsmParser  -lLLVMSystemZCodeGen  -lLLVMSystemZDisassembler  -lLLVMSystemZDesc  -lLLVMSystemZInfo  -lLLVMWebAssemblyAsmParser  -lLLVMWebAssemblyCodeGen  -lLLVMWebAssemblyDisassembler  -lLLVMWebAssemblyDesc  -lLLVMWebAssemblyInfo  -lLLVMWebAssemblyUtils  -lLLVMWindowsManifest  -lLLVMX86AsmParser  -lLLVMX86CodeGen  -lLLVMCFGuard  -lLLVMGlobalISel  -lLLVMX86Desc  -lLLVMX86Disassembler  -lLLVMX86Info  -lLLVMXCoreCodeGen  -lLLVMAsmPrinter  -lLLVMDebugInfoDWARF  -lLLVMDebugInfoMSF  -lLLVMSelectionDAG  -lLLVMCodeGen  -lLLVMBitWriter  -lLLVMScalarOpts  -lLLVMAggressiveInstCombine  -lLLVMInstCombine  -lLLVMTransformUtils  -lLLVMTarget  -lLLVMAnalysis  -lLLVMProfileData  -lLLVMXCoreDesc  -lLLVMXCoreDisassembler  -lLLVMMCDisassembler  -lLLVMXCoreInfo  -lLLVMXRay  -lLLVMObject  -lLLVMMCParser  -lLLVMMC  -lLLVMDebugInfoCodeView  -lLLVMBitReader  -lLLVMCore  -lLLVMRemarks  -lLLVMBitstreamReader  -lLLVMTextAPI  -lLLVMBinaryFormat  -lLLVMSupport  -lLLVMDemangle  -lxml2  -lz  -liconv  -lcharset  -ldl  -lrt  -lm  -lpthread && :
/usr/bin/ld: CMakeFiles/warp_compiler.dir/Compiler/Compile.cpp.o: in function `Warp::SyntaxTranslation::LLVM::initialize_target(llvm::Module&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, llvm::TargetOptions, llvm::Optional<llvm::Reloc::Model>)':
Compile.cpp:(.text+0x1534): undefined reference to `llvm::TargetRegistry::lookupTarget(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >&)'
/usr/bin/ld: CMakeFiles/warp_compiler.dir/Compiler/Main.cpp.o: in function `main':
Main.cpp:(.text+0xf46): undefined reference to `llvm::sys::getDefaultTargetTriple[abi:cxx11]()'
collect2: error: ld returned 1 exit status
ninja: build stopped: subcommand failed.
问题解答

1. 手动获取目标三元组字符串

gcc -dumpmachine完全可行,输出结果与LLVM目标三元组格式一致。也可以在代码中直接使用__TARGET_TRIPLE__宏获取编译时的目标三元组;如果需要运行时获取,调用gcc -dumpmachine并捕获输出是最简单的临时方案。

2. 手动生成Target的可行性

完全可行,但需要编写大量样板代码:

  • 手动填充TargetRegistry::Target结构体的所有字段,包括目标名称、三元组、代码生成器、汇编器等指针。
  • 调用TargetRegistry::RegisterTarget完成目标注册,逻辑与LLVM内置目标的注册流程一致。
  • 缺点是需要维护与LLVM版本匹配的代码,无法复用LLVM内置目标实现,仅适合临时应急,不推荐长期使用。

3. 修复链接错误的核心方案

方案1:调整库链接顺序

LLVM库依赖关系严格,链接顺序错误会导致未定义引用。从你的链接命令看,-lLLVMSupport放在最后,而llvm::TargetRegistry依赖LLVMTarget库,LLVMTarget又依赖LLVMSupport。将依赖链靠前的库放在链接命令的后面,比如把-lLLVMSupport移到-lLLVMTarget之前,或者直接使用llvm-config --libs输出的官方推荐链接顺序。

方案2:确保C++ ABI兼容性

修改Conan profile后需彻底生效:

  • 确认profile中设置compiler.cppstd与LLVM构建时的C标准一致(比如C17),且compiler.libcxx=libstdc++11(gcc-12默认使用该ABI,但需确认LLVM包是用此ABI编译的)。
  • 清空Conan缓存和本地构建目录,重新执行conan install和构建命令,确保新的profile设置被应用。

方案3:确认LLVM包的目标注册代码

部分LLVM包可能未编译所需目标或未启用初始化代码:

  • 检查Conan的LLVM包配置,确认启用了你需要的目标架构(如X86、ARM等)。
  • 在代码中手动初始化目标注册,比如添加extern "C" void LLVMInitializeX86TargetInfo();并调用该函数(对应你的目标架构),确保目标被注册到TargetRegistry中。

方案4:使用llvm-config生成链接参数

放弃Conan自动生成的链接参数,改用llvm-config --libs core support target获取正确的链接库列表和顺序,替换到CMake的链接命令中,这是最可靠的方案之一。


内容的提问来源于stack exchange,提问作者cgbsu

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.06 19:01:52