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
解决方案
核心问题分析
- 源文件未正确添加:原代码中
target_sources(dilithium PUBLIC ${dilithium_SOURCE_DIR})仅指定目录,CMake不会自动递归收集C源文件,导致库中无函数实现的二进制代码。 - 编译宏定义传递错误:
set_target_properties无法传递编译宏(DILITHIUM_MODE、DILITHIUM_USE_AES),这些宏需作为编译定义传递才能生成对应模式的函数符号。 - C/C++链接兼容性问题:Dilithium是C语言库,C++代码直接调用会因名字修饰导致符号不匹配。
- 函数名错误:测试代码中调用的
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
相关产品推荐
相关产品推荐

