Reputation: 75
I've been struggling with this for longer than I care to admit and would really appreciate some help.
I'm trying to do a project which involves building a linker and scheduler, and thought if I could use some of the functionality that's already been build into LLVM that would be great. I'm using LLVM 10. To get started I did some reading and tried to build this example. Because I plan on embedding LLVM into another project, used this as a reference for 'how to build' the example (see below). I figured the dependencies are just the components from the example CMakeLists.txt.
If I'm not mistaken, I'm getting a linker error and that the component list is the problem, but I'm struggling to resolve it. The way it seems LLVM does linking is by mapping a component name to an library file, but since I don't know which missing library might be causing it I'm stuck. Also, I don't know what llvm_libs is, but adding it to the component list seemed to resolve some of the linker errors I was getting originally. Also also, changing the order of the component list will give me different amounts of errors, which absolutely confounds me.
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})
Then from a subdir I run
$ 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
If anyone knows what my problem is, has any advice on running these LLVM examples, or knows of any resources that might better my understanding of wtf is happening I will be eternally grateful :). Thanks in advance for any help!
Edit 1: I tried the same procedure on some other examples to see what would happen. On Fibonacci everything build fine then seg faulted on runtime. On ModuleMaker I build fails on undefined reference to main... I'm really bungling something up here I just don't know what.
Edit 2: Thank you for the responses. I'm currently attempting to get everything to build correctly using Alexs advice. Simply using the CMakeLists.txt and building using Ninja did not work :( (I updated the build process outputs above). I was getting similar errors as before. Since Alex mentioned that he needed to use a different version of llvm header files, I figured I'd just build an updated version from source - but LLVM bested me once again. The build from source procedure in the README bombs on every release version I try (I'm running Ubuntu 20.04 lts). I'm starting to think my best bet is to just cherry-pick files and hack something together myself because this is getting to be too much of a headache.
Edit 3: I got it working :)
Everything ran and built fine when I updated to the newest version of LLVM. I ran into a lot of build problems on Ubuntu 20.04 lts that were a product of missing dependencies. This kind soul posted all the deps he needed to install in order to build llvm without errors.
Upvotes: 2
Views: 822
Reputation: 19816
So the following build worked for me and should hopefully be a model for you re: how to use 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)
Notice the following:
test::LLVM
.MC
and MCJIT
components to the list of components.target_link_libraries
with a visibility specifier (they are PRIVATE
, INTERFACE
, and PUBLIC
. Omitting it is none of the above.)find_package
call and omit the unnecessary CONFIG
argument. Every major version of LLVM breaks the API in significant ways.At the terminal, I now see:
$ 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
Note: I had to use the sources for HowToUseJIT from a more recent LLVM release (the one from 13.0.0) because the old one has a segfault on some systems. However, that bug is unrelated to the build process.
Upvotes: 2