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

CMake引入Dilithium库后函数未定义链接错误求助

问题:CMake引入Dilithium库后可访问宏定义但无法调用函数

作为CMake新手,引入Dilithium库后,能正常使用头文件中的#define变量,但调用库中函数时出现链接错误,相关代码与错误信息如下:

CMakeLists.txt内容

cmake_minimum_required(VERSION 3.10)
project(react-native-dilithium VERSION 1.0.0)

include(FetchContent)

FetchContent_Declare(dilithium                              
  GIT_REPOSITORY https://github.com/pq-crystals/dilithium.git
  GIT_TAG        master        
)

FetchContent_MakeAvailable(dilithium)

add_library(dilithium SHARED)
target_sources(dilithium PUBLIC ${dilithium_SOURCE_DIR})
set_target_properties(dilithium PROPERTIES LINKER_LANGUAGE CXX PROPERTIES DILITHIUM_MODE 5 PROPERTIES DILITHIUM_USE_AES TRUE)

add_executable(cpp_test main.cpp)

target_include_directories(cpp_test PUBLIC 
  ${dilithium_BINARY_DIR}
  ${dilithium_SOURCE_DIR}/ref
)


target_link_libraries(cpp_test PUBLIC dilithium)

测试代码

#include <iostream>
#include <api.h>

using namespace std;

int main(int argc, char* argv[]) {
    // Message to sign
    const char* message = "This is a message to be signed.";
    size_t message_len = strlen(message);

    // Private key (replace with your actual key)
    unsigned char private_key[pqcrystals_dilithium5aes_ref_SECRETKEYBYTES];

    // Signature buffer (allocate enough space based on parameter set)
    unsigned char signature[pqcrystals_dilithium5aes_ref_BYTES];
    size_t signature_len = sizeof(signature);

    // Call the signing function
    int result = pqcrystals_dilithium5aes_ref_signature(
        signature, &signature_len,
        (const unsigned char*)message, message_len,
        private_key
    );

    return 0;
}

错误信息

ld: Undefined symbols:
  pqcrystals_dilithium5aes_ref_signature(unsigned char*, unsigned long*, unsigned char const*, unsigned long, unsigned char const*), referenced from:
      _main in main.cpp.o
clang: error: linker command failed with exit code 1 (use -v to see invocation)
make[2]: *** [cpp_test] Error 1
make[1]: *** [CMakeFiles/cpp_test.dir/all] Error 2
make: *** [all] Error 2

解决方案

核心问题分析

  1. 源文件未正确添加:原代码中target_sources(dilithium PUBLIC ${dilithium_SOURCE_DIR})仅指定目录,CMake不会自动递归收集C源文件,导致库中无函数实现的二进制代码。
  2. 编译宏定义传递错误:set_target_properties无法传递编译宏(DILITHIUM_MODE、DILITHIUM_USE_AES),这些宏需作为编译定义传递才能生成对应模式的函数符号。
  3. C/C++链接兼容性问题:Dilithium是C语言库,C++代码直接调用会因名字修饰导致符号不匹配。
  4. 函数名错误:测试代码中调用的pqcrystals_dilithium5aes_ref_signature并非库中实际函数,正确函数名为pqcrystals_dilithium5aes_ref_sign。

修正后的CMakeLists.txt

cmake_minimum_required(VERSION 3.10)
project(react-native-dilithium VERSION 1.0.0)

include(FetchContent)

FetchContent_Declare(dilithium                              
  GIT_REPOSITORY https://github.com/pq-crystals/dilithium.git
  GIT_TAG        master        
)

FetchContent_GetProperties(dilithium)
if(NOT dilithium_POPULATED)
  FetchContent_Populate(dilithium)
  
  # 收集ref目录下所有C源文件
  file(GLOB DILITHIUM_SRC_FILES "${dilithium_SOURCE_DIR}/ref/*.c")
  
  add_library(dilithium SHARED ${DILITHIUM_SRC_FILES})
  
  # 传递编译宏定义,启用Dilithium 5模式和AES优化
  target_compile_definitions(dilithium PUBLIC DILITHIUM_MODE=5 DILITHIUM_USE_AES)
  
  # 设置库的头文件搜索路径
  target_include_directories(dilithium PUBLIC 
    ${dilithium_SOURCE_DIR}
    ${dilithium_SOURCE_DIR}/ref
  )
endif()

add_executable(cpp_test main.cpp)

# 让测试程序能找到Dilithium头文件
target_include_directories(cpp_test PUBLIC 
  ${dilithium_SOURCE_DIR}/ref
)

# 链接Dilithium库
target_link_libraries(cpp_test PUBLIC dilithium)

修正后的测试代码

#include <iostream>
// 用extern "C"包裹C头文件,避免C++名字修饰
extern "C" {
#include <api.h>
}

using namespace std;

int main(int argc, char* argv[]) {
    const char* message = "This is a message to be signed.";
    size_t message_len = strlen(message);

    unsigned char private_key[pqcrystals_dilithium5aes_ref_SECRETKEYBYTES];
    unsigned char public_key[pqcrystals_dilithium5aes_ref_PUBLICKEYBYTES];
    unsigned char signature[pqcrystals_dilithium5aes_ref_BYTES];
    size_t signature_len = sizeof(signature);

    // 先生成密钥对(必须步骤,否则私钥未初始化)
    pqcrystals_dilithium5aes_ref_keypair(public_key, private_key);

    // 调用正确的签名函数
    int result = pqcrystals_dilithium5aes_ref_sign(
        signature, &signature_len,
        (const unsigned char*)message, message_len,
        private_key
    );

    cout << "签名结果:" << (result == 0 ? "成功" : "失败") << endl;
    return 0;
}

关键修正点说明

  • 手动收集Dilithium的C源文件,确保函数实现被编译进库;
  • 使用target_compile_definitions传递编译宏,生成对应模式的函数符号;
  • 用extern "C"包裹C头文件,解决C/C++名字修饰不兼容问题;
  • 修正函数名为库中实际存在的pqcrystals_dilithium5aes_ref_sign,并补充密钥生成的必要步骤。

内容的提问来源于stack exchange,提问作者Roman

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.30 13:15:03