问题描述
我在这件事上挣扎的时间比我愿意承认的要长,我真的很感激你的帮助。
我正在尝试做一个涉及构建链接器和调度器的项目,我想如果我可以使用LLVM中已经构建的一些功能,那就太好了。我使用的是LLVM10。为了开始,我阅读了一些内容,并尝试构建this示例。因为我计划将LLVM嵌入到另一个项目中,使用this作为"如何构建"该示例的参考(见下文)。我认为依赖项只是示例CMakeLists.txt中的组件。
如果我没有弄错的话,我收到了一个链接器错误,组件列表是问题所在,但我正在努力解决它。LLVM似乎是通过将组件名称映射到库文件来实现链接的,但由于我不知道哪个缺少的库可能会导致它,所以我陷入了困境。此外,我不知道llvm_libs是什么,但将其添加到组件列表似乎解决了我最初收到的一些链接器错误。此外,更改组件列表的顺序会给我带来不同程度的错误,这绝对会让我感到困惑。
CMakeLists.txt
cmake_minimum_required(VERSION 3.13.4)
project(HowToUseJIT)
find_package(LLVM REQUIRED CONFIG)
message(STATUS "Found LLVM ${LLVM_PACKAGE_VERSION}")
message(STATUS "Using LLVMConfig.cmake in: ${LLVM_DIR}")
# Set your project compile flags.
# E.g. if using the C++ header files
# you will need to enable C++11 support
# for your compiler.
message(STATUS "INCLUDE ${LLVM_INCLUDE_DIRS}")
include_directories(${LLVM_INCLUDE_DIRS})
message(STATUS "DEFINITIONS ${LLVM_DEFINITIONS}
${LLVM_DEFINITIONS_LIST}")
separate_arguments(LLVM_DEFINITIONS_LIST NATIVE_COMMAND ${LLVM_DEFINITIONS})
add_definitions(${LLVM_DEFINITIONS_LIST})
# Now build our tools
add_executable(HowToUseJIT HowToUseJIT.cpp)
# Find the libraries that correspond to the LLVM components
# that we wish to use
llvm_map_components_to_libnames(llvm_libs support core interpreter nativecodegen executionengine)
# Link against LLVM libraries
message(STATUS "LIBS ${llvm_libs}")
target_link_libraries(HowToUseJIT ${llvm_libs})
然后从子目录运行
$ cmake ../
-- The C compiler identification is GNU 9.3.0
-- The CXX compiler identification is GNU 9.3.0
-- Check for working C compiler: /usr/bin/cc
-- Check for working C compiler: /usr/bin/cc -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Detecting C compile features
-- Detecting C compile features - done
-- Check for working CXX compiler: /usr/bin/c++
-- Check for working CXX compiler: /usr/bin/c++ -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Configuring done
-- Generating done
-- Build files have been written to: /home/jeremy_arsenault/Documents/random/llvm_examples/HowToUseJIT/build
$ cmake --build .
[ 50%] Building CXX object CMakeFiles/HowToUseJIT.dir/HowToUseJIT.cpp.o
[100%] Linking CXX executable HowToUseJIT
/usr/bin/ld: CMakeFiles/HowToUseJIT.dir/HowToUseJIT.cpp.o: in function `main':
HowToUseJIT.cpp:(.text+0x4b7): undefined reference to `llvm::EngineBuilder::EngineBuilder(std::unique_ptr<llvm::Module, std::default_delete<llvm::Module> >)'
/usr/bin/ld: HowToUseJIT.cpp:(.text+0x4dc): undefined reference to `llvm::EngineBuilder::~EngineBuilder()'
/usr/bin/ld: HowToUseJIT.cpp:(.text+0x693): undefined reference to `llvm::EngineBuilder::~EngineBuilder()'
/usr/bin/ld: CMakeFiles/HowToUseJIT.dir/HowToUseJIT.cpp.o: in function `llvm::EngineBuilder::create()':
HowToUseJIT.cpp:(.text._ZN4llvm13EngineBuilder6createEv[_ZN4llvm13EngineBuilder6createEv]+0x18): undefined reference to `llvm::EngineBuilder::selectTarget()'
/usr/bin/ld: HowToUseJIT.cpp:(.text._ZN4llvm13EngineBuilder6createEv[_ZN4llvm13EngineBuilder6createEv]+0x2a): undefined reference to `llvm::EngineBuilder::create(llvm::TargetMachine*)'
/usr/bin/ld: CMakeFiles/HowToUseJIT.dir/HowToUseJIT.cpp.o: in function `llvm::IRBuilderDefaultInserter::IRBuilderDefaultInserter()':
HowToUseJIT.cpp:(.text._ZN4llvm24IRBuilderDefaultInserterC2Ev[_ZN4llvm24IRBuilderDefaultInserterC5Ev]+0xf): undefined reference to `vtable for llvm::IRBuilderDefaultInserter'
/usr/bin/ld: CMakeFiles/HowToUseJIT.dir/HowToUseJIT.cpp.o: in function `llvm::InitializeNativeTarget()':
HowToUseJIT.cpp:(.text._ZN4llvm22InitializeNativeTargetEv[_ZN4llvm22InitializeNativeTargetEv]+0x9): undefined reference to `LLVMInitializeX86TargetInfo'
/usr/bin/ld: HowToUseJIT.cpp:(.text._ZN4llvm22InitializeNativeTargetEv[_ZN4llvm22InitializeNativeTargetEv]+0xe): undefined reference to `LLVMInitializeX86Target'
/usr/bin/ld: HowToUseJIT.cpp:(.text._ZN4llvm22InitializeNativeTargetEv[_ZN4llvm22InitializeNativeTargetEv]+0x13): undefined reference to `LLVMInitializeX86TargetMC'
/usr/bin/ld: CMakeFiles/HowToUseJIT.dir/HowToUseJIT.cpp.o: in function `llvm::IRBuilder<llvm::ConstantFolder, llvm::IRBuilderDefaultInserter>::~IRBuilder()':
HowToUseJIT.cpp:(.text._ZN4llvm9IRBuilderINS_14ConstantFolderENS_24IRBuilderDefaultInserterEED2Ev[_ZN4llvm9IRBuilderINS_14ConstantFolderENS_24IRBuilderDefaultInserterEED5Ev]+0x1c): undefined reference to `llvm::IRBuilderDefaultInserter::~IRBuilderDefaultInserter()'
/usr/bin/ld: CMakeFiles/HowToUseJIT.dir/HowToUseJIT.cpp.o: in function `llvm::IRBuilderFolder::IRBuilderFolder()':
HowToUseJIT.cpp:(.text._ZN4llvm15IRBuilderFolderC2Ev[_ZN4llvm15IRBuilderFolderC5Ev]+0xf): undefined reference to `vtable for llvm::IRBuilderFolder'
/usr/bin/ld: CMakeFiles/HowToUseJIT.dir/HowToUseJIT.cpp.o: in function `llvm::ConstantFolder::ConstantFolder()':
HowToUseJIT.cpp:(.text._ZN4llvm14ConstantFolderC2Ev[_ZN4llvm14ConstantFolderC5Ev]+0x1f): undefined reference to `vtable for llvm::ConstantFolder'
/usr/bin/ld: CMakeFiles/HowToUseJIT.dir/HowToUseJIT.cpp.o: in function `llvm::IRBuilder<llvm::ConstantFolder, llvm::IRBuilderDefaultInserter>::IRBuilder(llvm::BasicBlock*, llvm::MDNode*, llvm::ArrayRef<llvm::OperandBundleDefT<llvm::Value*> >)':
HowToUseJIT.cpp:(.text._ZN4llvm9IRBuilderINS_14ConstantFolderENS_24IRBuilderDefaultInserterEEC2EPNS_10BasicBlockEPNS_6MDNodeENS_8ArrayRefINS_17OperandBundleDefTIPNS_5ValueEEEEE[_ZN4llvm9IRBuilderINS_14ConstantFolderENS_24IRBuilderDefaultInserterEEC5EPNS_10BasicBlockEPNS_6MDNodeENS_8ArrayRefINS_17OperandBundleDefTIPNS_5ValueEEEEE]+0xbb): undefined reference to `llvm::IRBuilderDefaultInserter::~IRBuilderDefaultInserter()'
/usr/bin/ld: CMakeFiles/HowToUseJIT.dir/HowToUseJIT.cpp.o: in function `llvm::ConstantFolder::~ConstantFolder()':
HowToUseJIT.cpp:(.text._ZN4llvm14ConstantFolderD2Ev[_ZN4llvm14ConstantFolderD5Ev]+0x13): undefined reference to `vtable for llvm::ConstantFolder'
/usr/bin/ld: HowToUseJIT.cpp:(.text._ZN4llvm14ConstantFolderD2Ev[_ZN4llvm14ConstantFolderD5Ev]+0x26): undefined reference to `llvm::IRBuilderFolder::~IRBuilderFolder()'
collect2: error: ld returned 1 exit status
make[2]: *** [CMakeFiles/HowToUseJIT.dir/build.make:91: HowToUseJIT] Error 1
make[1]: *** [CMakeFiles/Makefile2:77: CMakeFiles/HowToUseJIT.dir/all] Error 2
make: *** [Makefile:84: all] Error 2
如果有人知道我的问题是什么,对运行这些LLVM示例有任何建议,或者知道任何资源可以更好地理解wtf正在发生的事情,我将永远感激:)。提前感谢您的帮助!
编辑1:我在其他一些示例中尝试了相同的过程,看看会发生什么情况。在斐波纳奇上,一切都构建得很好,但seg在运行时出错。在我构建的ModuleMaker上,由于未定义对Main的引用而失败...我真的搞砸了,我只是不知道是什么。
编辑2:感谢您的回复。我目前正在尝试使用Alexs建议来正确构建所有内容。简单地使用CMakeLists.txt和使用忍者构建不起作用:((我更新了上面的构建过程输出)。我收到了与以前类似的错误。因为Alex提到他需要使用不同版本的llvm头文件,我以为我只需要从源代码构建一个更新版本--但LLVM又一次击败了我。自述文件中的从源代码构建过程会在我尝试的每个发布版本上爆炸(我正在运行Ubuntu 20.04LTS)。我开始认为,我最好的办法就是自己挑选文件,然后自己拼凑一些东西,因为这太令人头疼了。
编辑3:我使其正常工作:)
解决方案
当我更新到最新版本的LLVM时,一切都运行和构建得很好。我在Ubuntu20.04LTS上遇到了很多构建问题,这些问题都是由于缺少依赖项造成的。This好心人发布了他需要安装的所有dep,以便无错误地构建llvm。
推荐答案
所以以下版本对我有效,希望能成为您的模型:如何使用CMake...
cmake_minimum_required(VERSION 3.22)
project(test)
# Find LLVM and the components we require.
find_package(LLVM 10 REQUIRED)
llvm_map_components_to_libnames(
LLVM_LIBRARIES
Core
ExecutionEngine
Interpreter
MC
MCJIT
Support
nativecodegen
)
# Create a wrapper for the LLVM components we need in this
# project. This will allow us to link it to multiple targets
# without duplicating a lot of code. It's too bad that LLVM
# doesn't provide anything like this.
add_library(test::LLVM INTERFACE IMPORTED)
target_include_directories(test::LLVM INTERFACE ${LLVM_INCLUDE_DIRS})
target_compile_definitions(test::LLVM INTERFACE ${LLVM_DEFINITIONS})
target_link_libraries(test::LLVM INTERFACE ${LLVM_LIBRARIES})
# Create our actual executable and link LLVM to it.
add_executable(HowToUseJIT HowToUseJIT.cpp)
target_link_libraries(HowToUseJIT PRIVATE test::LLVM)
注意以下事项:
- LLVM不提供其自己的导入目标(错误)
- 因此,我们创建自己的导入目标来包装它,
test::LLVM
。 - 我们将
MC
和MCJIT
组件添加到组件列表。 - 我们将包提供的变量和库的计算列表分配给导入目标的相关属性。
- 我们总是使用可见性说明符调用
target_link_libraries
(它们是PRIVATE
、INTERFACE
和PUBLIC
。省略它以上都不是。) - 我们在
find_package
调用中声明了所需的LLVM的版本号,并省略了不必要的CONFIG
参数。LLVM的每个主要版本都在很大程度上打破了API。
在航站楼,我现在看到:
$ cmake -G Ninja -S . -B build -DCMAKE_BUILD_TYPE=Release
-- The C compiler identification is GNU 9.3.0
-- The CXX compiler identification is GNU 9.3.0
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working C compiler: /usr/bin/cc - skipped
-- Detecting C compile features
-- Detecting C compile features - done
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Check for working CXX compiler: /usr/bin/c++ - skipped
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Configuring done
-- Generating done
-- Build files have been written to: /path/to/build
$ cmake --build build/ --verbose
[1/2] /usr/bin/c++ -D_GNU_SOURCE -D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS -isystem /usr/lib/llvm-10/include -O3 -DNDEBUG -MD -MT CMakeFiles/HowToUseJIT.dir/HowToUseJIT.cpp.o -MF CMakeFiles/HowToUseJIT.dir/HowToUseJIT.cpp.o.d -o CMakeFiles/HowToUseJIT.dir/HowToUseJIT.cpp.o -c /path/to/HowToUseJIT.cpp
[2/2] : && /usr/bin/c++ -O3 -DNDEBUG CMakeFiles/HowToUseJIT.dir/HowToUseJIT.cpp.o -o HowToUseJIT /usr/lib/llvm-10/lib/libLLVMInterpreter.a /usr/lib/x86_64-linux-gnu/libffi.so /usr/lib/llvm-10/lib/libLLVMMCJIT.a /usr/lib/llvm-10/lib/libLLVMExecutionEngine.a /usr/lib/llvm-10/lib/libLLVMRuntimeDyld.a /usr/lib/llvm-10/lib/libLLVMX86CodeGen.a /usr/lib/llvm-10/lib/libLLVMAsmPrinter.a /usr/lib/llvm-10/lib/libLLVMDebugInfoDWARF.a /usr/lib/llvm-10/lib/libLLVMCFGuard.a /usr/lib/llvm-10/lib/libLLVMGlobalISel.a /usr/lib/llvm-10/lib/libLLVMSelectionDAG.a /usr/lib/llvm-10/lib/libLLVMCodeGen.a /usr/lib/llvm-10/lib/libLLVMTarget.a /usr/lib/llvm-10/lib/libLLVMBitWriter.a /usr/lib/llvm-10/lib/libLLVMScalarOpts.a /usr/lib/llvm-10/lib/libLLVMAggressiveInstCombine.a /usr/lib/llvm-10/lib/libLLVMInstCombine.a /usr/lib/llvm-10/lib/libLLVMTransformUtils.a /usr/lib/llvm-10/lib/libLLVMAnalysis.a /usr/lib/llvm-10/lib/libLLVMProfileData.a /usr/lib/llvm-10/lib/libLLVMX86Desc.a /usr/lib/llvm-10/lib/libLLVMObject.a /usr/lib/llvm-10/lib/libLLVMBitReader.a /usr/lib/llvm-10/lib/libLLVMCore.a /usr/lib/llvm-10/lib/libLLVMRemarks.a /usr/lib/llvm-10/lib/libLLVMBitstreamReader.a /usr/lib/llvm-10/lib/libLLVMMCParser.a /usr/lib/llvm-10/lib/libLLVMTextAPI.a /usr/lib/llvm-10/lib/libLLVMX86Utils.a /usr/lib/llvm-10/lib/libLLVMMCDisassembler.a /usr/lib/llvm-10/lib/libLLVMMC.a /usr/lib/llvm-10/lib/libLLVMBinaryFormat.a /usr/lib/llvm-10/lib/libLLVMDebugInfoCodeView.a /usr/lib/llvm-10/lib/libLLVMDebugInfoMSF.a /usr/lib/llvm-10/lib/libLLVMX86Info.a /usr/lib/llvm-10/lib/libLLVMSupport.a -lz -lrt -ldl -ltinfo -lpthread -lm /usr/lib/llvm-10/lib/libLLVMDemangle.a && :
$ ./build/HowToUseJIT
We just constructed this LLVM module:
; ModuleID = 'test'
source_filename = "test"
target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
define i32 @add1(i32 %AnArg) {
EntryBlock:
%0 = add i32 1, %AnArg
ret i32 %0
}
define i32 @foo() {
EntryBlock:
%0 = tail call i32 @add1(i32 10)
ret i32 %0
}
Running foo: Result: 11
注意:我必须使用更新的LLVM版本(13.0.0版本)中的sources for HowToUseJIT,因为旧版本在某些系统上有段错误。但是,该错误与构建过程无关。
这篇关于运行LLVM示例时出现问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!