You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.20 02:35:32