Search code examples
compilationclangllvmclang++

How to link different object file with LLVM library?


I am following the LLVM tutorial : Kaleidoscope: Code generation to LLVM IR, which will use LLVM libraries like LLVMContext, Module and so on. Different from the tutorial, I am trying to write the lexer, parser and code generator in different source file and link them into one executable file. Here is my compile command on the Ubuntu 20.04:

clang++ -g -O3 -I /home/therlf/LLVM/include -I ./ -I /home/therlf/LLVM_Temp/llvm/include `llvm-config --cxxflags --ldflags --system-libs --libs all` ast/CallExprAST.o ast/NumberExprAST.o ast/PrototypeAST.o ast/FunctionAST.o ast/BinaryExprAST.o ast/VariableExprAST.o lexer/lexer.o logger/logger.o parser/parser.o main.cpp -o main

But I only get lots of "undefined error". Here are some of them:

/usr/bin/ld: /tmp/main-2b71c8.o:(.data+0x0): undefined reference to `llvm::DisableABIBreakingChecks

/home/therlf/MyProject/tmp/ast/CallExprAST.cpp:6: undefined reference to `llvm::Module::getFunction(llvm::StringRef) const'

/home/therlf/LLVM/include/llvm/IR/InstrTypes.h:1112: undefined reference to `llvm::Instruction::Instruction(llvm::Type*, unsigned int, llvm::Use*, unsigned int, llvm::Instruction*)'

/usr/bin/ld: /home/therlf/LLVM/include/llvm/IR/InstrTypes.h:977: undefined reference to `llvm::VectorType::get(llvm::Type*, llvm::ElementCount)'

At first I thought it's including path's error. But when I compiled and ran the source file in the tutorial successfully, which is just a whole source file with everything packed into file, I knew the including path is nothing wrong.

I have searched for this question, and some blogs say that you should link them with lld and use the -fuse-ld=lld in the compile command. But I don't have lld, and the clang++ doesn't know the argument -fuse-ld, which will report an error. The blog says that you should have lld as long as you have installed LLVM. In fact here are what I got: LLVM tools

And I know the llvm-link is used to link IR file, not the object file compiled from cpp source file.

Here is my LLVM version:

10.0.0svn

And here is my Makefile:

SOURCES = $(shell find ast kaleidoscope lexer logger parser  -name '*.cpp')
HEADERS = $(shell find ast kaleidoscope lexer logger parser -name '*.h')
OBJ = ${SOURCES:.cpp=.o}

CC = clang++
# -stdlib=libc++ -std=c++11
CFLAGS = -g -O3 -I /home/therlf/LLVM/include -I ./ -I /home/therlf/LLVM_Temp/llvm/include
LLVMFLAGS = `llvm-config --cxxflags --ldflags --system-libs --libs all`

.PHONY: main

main: main.cpp ${OBJ}
    ${CC} ${CFLAGS} ${LLVMFLAGS} ${OBJ} $< -o $@

clean:
    rm -r ${OBJ}

%.o: %.cpp ${HEADERS}
    ${CC} ${CFLAGS} ${LLVMFLAGS} -c $< -o $@

In fact, I follow the project structure from the repository : ghaiklor/llvm-kaleidoscope and the Makefile is nearly identical.

Sincerely thank you for your answers!


Solution

  • I have sloved this problem by exchanging my linker ld with linker lld. You should install lld first by this command in ubuntu if you can't find it in the LLVM/tools directory like I did.

    sudo apt-get update
    sudo apt-get -y install lld
    

    And then you can add -fuse-ld=lld to your compile command

    or you can

    cd /usr/bin
    ln -s /path/to/ld.lld /usr/bin/ld
    

    This should work if everything goes well.

    But I still can't figure out the reason behand this situation :-(