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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.11 16:25:20