基于LLVM的C++编译器出现大量undefined reference链接错误求助
LLVM开发C++编译器时的undefined reference链接错误解决
问题现象
在Windows 10系统下使用CLion开发基于LLVM的C++编译器,已实现数字、字符串的基础功能,但编译阶段出现大量undefined reference链接错误,涉及LLVM核心类的方法调用。
错误示例
undefined reference to `llvm::BasicBlock::BasicBlock(llvm::LLVMContext&, llvm::Twine const&, llvm::Function*, llvm::BasicBlock*)' undefined reference to `llvm::ConstantInt::get(llvm::IntegerType*, unsigned long long, bool)' undefined reference to `llvm::Type::getInt32Ty(llvm::LLVMContext&)' undefined reference to `llvm::Type::getInt64Ty(llvm::LLVMContext&)' undefined reference to `llvm::Function::Create(llvm::FunctionType*, llvm::GlobalValue::LinkageTypes, llvm::Twine const&, llvm::Module&)' undefined reference to `llvm::outs()'
代码生成器实现
#ifndef COMPILER_CODEGENERATION_H #define COMPILER_CODEGENERATION_H #include "llvm/IR/Module.h" #include "llvm/IR/IRBuilder.h" #include "llvm/IR/LLVMContext.h" #include "llvm/IR/Verifier.h" #include "llvm/IR/Function.h" #include "ASTNode.h" namespace COMPILER { class CodeGenerator { std::shared_ptr<llvm::Module> _module; std::shared_ptr<llvm::LLVMContext> _context; std::shared_ptr<llvm::IRBuilder<>> _irBuilder; llvm::BasicBlock * createBlock(const std::string &blockName, llvm::Function *targetFunc) { return llvm::BasicBlock::Create(*_context,blockName, targetFunc); } llvm::Function * createFunctionPrototype(const std::string &funcName, llvm::FunctionType *funcType) { auto proto = llvm::Function::Create(funcType, llvm::Function::ExternalLinkage, funcName, *_module); llvm::verifyFunction(*proto); return proto; } void createFunction(const std::string &funcName, llvm::FunctionType *funcType) { auto proto = createFunctionPrototype(funcName, funcType); auto block = createBlock("entry", proto); _irBuilder->SetInsertPoint(block); } public: CodeGenerator( const std::shared_ptr<llvm::Module> &module, const std::shared_ptr<llvm::LLVMContext> &context, const std::shared_ptr<llvm::IRBuilder<>> &builder ) { _module = module; _context = context; _irBuilder = builder; } // LLVM Value can represent anything. Eg. instructions, strings, numbers ... void Compile(const std::vector<std::unique_ptr<Compiler::IExpression>> &statementList) { createFunction("main", llvm::FunctionType::get(_irBuilder->getInt32Ty(), false)); for(auto &expressionStatement: statementList) { expressionStatement->codegen(_module, _context, _irBuilder); } } }; llvm::Value * Compiler::NumberExpressionNode::codegen( const std::shared_ptr<llvm::Module> &module, const std::shared_ptr<llvm::LLVMContext> &context, const std::shared_ptr<llvm::IRBuilder<>> &builder){ return builder->getInt64(_num); } } #endif
LLVM编译安装命令
cd <path_where_the_files_will_be_installed> git clone --config core.autocrlf=false --depth 1 https://github.com/llvm/llvm-project.git cd llvm-project cd llvm mkdir build cd build cmake .. cmake --build . --config Debug --target INSTALL -j <number_of_cores>
当前CMakeLists.txt
cmake_minimum_required(VERSION 3.24) project(Compiler) set(CMAKE_CXX_STANDARD 17) find_package(LLVM REQUIRED CONFIG PATHS Dependencies/llvm/llvm-project/llvm/build NO_DEFAULT_PATH) include_directories(${LLVM_INCLUDE_DIRS}) add_definitions(${LLVM_DEFINITIONS}) add_executable(Compiler main.cpp compiler/src/Tokenization.h compiler/src/ASTNode.h compiler/src/Parser.h compiler/src/CodeGeneration.h compiler/src/Compiler.h) llvm_map_components_to_libnames(llvm_libs support core irreader) target_link_libraries(Compiler ${llvm_libs})
解决方案
1. 修复命名空间不匹配问题
代码中Compiler::NumberExpressionNode::codegen的实现被包裹在COMPILER命名空间内,导致符号定义与声明不匹配。需将该方法的实现移至Compiler命名空间下,或统一命名空间为COMPILER:
// 修改后正确的实现方式 namespace Compiler { llvm::Value * NumberExpressionNode::codegen( const std::shared_ptr<llvm::Module> &module, const std::shared_ptr<llvm::LLVMContext> &context, const std::shared_ptr<llvm::IRBuilder<>> &builder){ return builder->getInt64(_num); } }
2. 调整LLVM路径匹配安装目录
cmake --build . --target INSTALL会将LLVM安装到build/install目录(默认),原find_package路径指向build目录,无法正确找到LLVM的配置文件。修改CMakeLists.txt中的路径:
find_package(LLVM REQUIRED CONFIG PATHS Dependencies/llvm/llvm-project/llvm/build/install/lib/cmake/LLVM NO_DEFAULT_PATH)
3. 确保编译配置一致
LLVM以Debug模式编译安装,项目也需使用Debug模式构建(CLion中可在右上角构建配置中切换),Debug与Release模式的符号不兼容,会导致链接错误。
4. 补充LLVM组件依赖
当前仅链接了support、core、irreader,需补充ir组件(包含IR构建相关的核心实现):
llvm_map_components_to_libnames(llvm_libs core support irreader ir)
5. 验证LLVM配置正确性
在CMakeLists.txt中添加打印语句,确认LLVM路径和组件是否正确识别:
message(STATUS "LLVM_INCLUDE_DIRS: ${LLVM_INCLUDE_DIRS}") message(STATUS "LLVM_LIBRARIES: ${LLVM_LIBRARIES}") message(STATUS "llvm_libs: ${llvm_libs}")
内容的提问来源于stack exchange,提问作者Viliam Holly
相关产品推荐
相关产品推荐

