Conan 2.0加载的库无法链接C++可执行文件,符号未定义
问题:链接OpenSSL库时出现未定义符号错误
项目环境
- 1个cpp文件
- Conan 2.0包管理器
- CMake构建工具
conanfile.txt
[tool_requires] cmake/3.27.1 [requires] nlohmann_json/3.11.2 libcurl/8.2.1 openssl/3.1.2 [generators] CMakeDeps CMakeToolchain
CMakeLists.txt
cmake_minimum_required(VERSION 3.27.1) project(Testing VERSION 1.0 DESCRIPTION "Testing Application" LANGUAGES CXX) set(CMAKE_VERBOSE_MAKEFILE ON) set(CMAKE_SWIG_FLAGS "-Wall") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++17") set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -v") find_package(CURL REQUIRED) message(${CURL_INCLUDE_DIRS}) message(${CURL_LIBRARIES}) find_package(OpenSSL REQUIRED) find_package(nlohmann_json REQUIRED) include_directories(${CURL_INCLUDE_DIRS}) include_directories(${OpenSSL_INCLUDE_DIR}) include_directories(${nlohmann_json_INCLUDE_DIR}) add_executable(e_test encrypt_test.cpp ) target_link_libraries(e_test CURL::libcurl ${OpenSSL_LIBRARIES} nlohmann_json::nlohmann_json )
加密测试cpp文件(encrypt_test.cpp)
#include <openssl/evp.h> #include <openssl/pem.h> #include <openssl/rsa.h> #include <openssl/err.h> #include <iostream> #include <string> int main() { // Initialize the OpenSSL library OpenSSL_add_all_algorithms(); ERR_load_crypto_strings(); // Load the recipient's public key EVP_PKEY* publicKey = nullptr; FILE* publicKeyFile = fopen("../public_key.pem", "rb"); // Load the recipient's public key if (publicKeyFile) { publicKey = PEM_read_PUBKEY(publicKeyFile, nullptr, nullptr, nullptr); fclose(publicKeyFile); } else { std::cerr << "Error loading public key." << std::endl; return 1; } // Message to encrypt std::string message = "Hello, OpenSSL!"; // Buffer for encrypted message unsigned char* encryptedMessage = nullptr; size_t encryptedMessageLength = 0; // Create an EVP context EVP_PKEY_CTX* ctx = EVP_PKEY_CTX_new(publicKey, nullptr); // Initialize the encryption operation if (EVP_PKEY_encrypt_init(ctx) == 1 && EVP_PKEY_encrypt(ctx, nullptr, &encryptedMessageLength, reinterpret_cast<const unsigned char*>(message.c_str()), message.length()) == 1) { std::cout<<"I am here\n"; encryptedMessage = new unsigned char[encryptedMessageLength]; if (EVP_PKEY_encrypt(ctx, encryptedMessage, &encryptedMessageLength, reinterpret_cast<const unsigned char*>(message.c_str()), message.length()) != 1) { std::cerr << "Encryption error." << std::endl; return 1; } } // Print or process the encrypted message as needed std::cout << "Encrypted message length: " << encryptedMessageLength <<"\n" ; std::cout << "Encrypted message: " << std::string(reinterpret_cast<const char*>(encryptedMessage), encryptedMessageLength) << std::endl; // Clean up delete[] encryptedMessage; EVP_PKEY_CTX_free(ctx); EVP_PKEY_free(publicKey); ERR_free_strings(); return 0; }
构建错误信息
Undefined symbols for architecture x86_64: "_EVP_PKEY_CTX_free", referenced from: _main in encrypt_test.cpp.o "_EVP_PKEY_CTX_new", referenced from: _main in encrypt_test.cpp.o "_EVP_PKEY_encrypt", referenced from: _main in encrypt_test.cpp.o "_EVP_PKEY_encrypt_init", referenced from: _main in encrypt_test.cpp.o "_EVP_PKEY_free", referenced from: _main in encrypt_test.cpp.o "_OPENSSL_init_crypto", referenced from: _main in encrypt_test.cpp.o "_PEM_read_PUBKEY", referenced from: _main in encrypt_test.cpp.o ld: symbol(s) not found for architecture x86_64 clang: error: linker command failed with exit code 1 (use -v to see invocation) ninja: build stopped: subcommand failed.
构建脚本
#!/bin/bash conan profile detect conan install . --output-folder=build --build=missing cd build sh conanrun.sh cmake -G "Ninja" -DCMAKE_TOOLCHAIN_FILE=conan_toolchain.cmake -DCMAKE_BUILD_TYPE=Debug .. && cmake --build . --config Debug sh deactivate_conanrun.sh
注:移除conanrun.sh和停用脚本无影响。项目未引入Conan时,通过命令行构建可正常运行;已确认CMake能找到Conan安装的库文件和头文件,但链接时仍报错。
解决方案
问题出在CMake链接OpenSSL的方式上,${OpenSSL_LIBRARIES}未正确关联Conan提供的OpenSSL加密库组件,改用Conan生成的目标链接方式即可解决:
修改CMakeLists.txt
将target_link_libraries行中的${OpenSSL_LIBRARIES}替换为OpenSSL::Crypto:
target_link_libraries(e_test CURL::libcurl OpenSSL::Crypto nlohmann_json::nlohmann_json )
同时建议移除手动设置的include_directories,因为Conan生成的目标已自动配置好包含路径:
# 移除以下三行 # include_directories(${CURL_INCLUDE_DIRS}) # include_directories(${OpenSSL_INCLUDE_DIR}) # include_directories(${nlohmann_json_INCLUDE_DIR})
原因说明
- Conan 2.0通过CMakeDeps生成的OpenSSL配置,提供了
OpenSSL::Crypto(对应libcrypto库)和OpenSSL::SSL(对应libssl库)两个明确的目标。 - 你的代码使用了OpenSSL加密模块API(EVP、PEM等),这些属于libcrypto,必须链接
OpenSSL::Crypto才能正确关联符号。 - 手动使用
${OpenSSL_LIBRARIES}可能无法识别Conan安装的库路径或缺少必要的链接参数,而目标链接方式会让CMake自动处理所有依赖路径和选项。
内容的提问来源于stack exchange,提问作者Aditya Mukherjee
相关产品推荐
相关产品推荐

