麻烦运行 LLVM例子

Trouble running LLVM examples

我为此苦苦挣扎的时间比我愿意承认的要长,非常感谢您的帮助。

我正在尝试做一个涉及构建链接器和调度程序的项目,我想如果我可以使用一些已经构建到 LLVM 中的功能,那会很棒。我正在使用 LLVM 10。为了开始,我做了一些阅读并尝试构建 this example. Because I plan on embedding LLVM into another project, used this 作为 'how to build' 示例的参考(见下文)。我认为依赖项只是示例 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}\n${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: 我在其他一些示例上尝试了相同的过程,看看会发生什么。在 Fibonacci 上一切正常,然后在 运行 时间出现段错误。在 ModuleMaker 上,我在对 main 的未定义引用上构建失败...我真的搞砸了这里的东西我只是不知道是什么。

编辑 2: 感谢您的回复。我目前正在尝试使用 建议正确构建所有内容。简单地使用 CMakeLists.txt 并使用 Ninja 进行构建是行不通的 :((我更新了上面的构建过程输出)。我遇到了与以前类似的错误。由于 Alex 提到他需要使用不同版本的 llvm 头文件,我想我只是从源代码构建一个更新版本 - 但 LLVM 再一次击败了我。在我尝试的每个发布版本上,README 炸弹中的源代码构建过程(我 运行ning Ubuntu 20.04 lts)。我开始认为我最好的选择是挑选文件并自己破解一些东西,因为这太让人头疼了。

编辑 3: 我成功了:)

解决方案


一切运行,当我更新到最新版本的 LLVM 时构建良好。我 运行 在 Ubuntu 20.04 lts 上遇到了很多构建问题,这些问题是缺少依赖项的产物。 This kind soul 发布了他需要安装的所有 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)

注意以下几点:

  1. LLVM 不提供自己的导入目标(不好)
  2. 因此我们创建自己的导入目标来包装它,test::LLVM
  3. 我们将 MCMCJIT 组件添加到组件列表中。
  4. 我们将 package-provided 变量和计算的库列表分配给导入目标的相关属性。
  5. 我们总是调用带有可见性说明符的target_link_libraries(它们是PRIVATEINTERFACEPUBLIC。省略就是上面的none.)
  6. 我们在 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,因为旧版本在某些系统上有段错误。但是,该错误与构建过程无关。