将C++应用从OSX移植到Ubuntu时CMake链接OpenSSL失败
以下是可能导致你遇到SSL_ctrl等未定义符号错误的CMake配置问题:
未使用CMake内置的OpenSSL检测模块
很多开发者习惯手动指定OpenSSL的头文件和库路径,这种方式在跨平台时极易出错。Ubuntu系统中OpenSSL的安装路径与OSX(比如brew安装的位置)差异很大,硬编码路径会导致链接到不存在的库。正确的做法是依赖CMake官方提供的FindOpenSSL.cmake:find_package(OpenSSL REQUIRED) target_link_libraries(bybit_feed PRIVATE OpenSSL::SSL OpenSSL::Crypto)避免手动写
include_directories、link_directories再直接链接ssl和crypto库。库链接顺序不符合Ubuntu链接器要求
Ubuntu使用的GNU链接器(ld)对库的链接顺序有严格要求:依赖其他库的目标/库要放在被依赖库的前面。如果你的bybit_feed依赖了某个第三方库,而该库又依赖OpenSSL,错误的顺序会导致未定义符号。比如错误写法:target_link_libraries(bybit_feed ssl crypto third_party_lib)正确顺序应该是:
target_link_libraries(bybit_feed third_party_lib OpenSSL::SSL OpenSSL::Crypto)跨平台适配逻辑存在漏洞
你的CMake配置是双平台适配,但可能没有针对Ubuntu做正确的条件分支处理。比如直接复用了OSX下的OpenSSL路径配置,而这些路径在Ubuntu系统中并不存在:# 错误示例:无平台区分的硬编码路径 include_directories(/usr/local/opt/openssl/include) link_directories(/usr/local/opt/openssl/lib)应该添加平台判断,让Ubuntu分支使用自动检测逻辑:
if(APPLE) include_directories(/usr/local/opt/openssl/include) link_directories(/usr/local/opt/openssl/lib) elseif(UNIX) find_package(OpenSSL REQUIRED) endif()手动指定库文件时未匹配编译模式
如果你是手动指定OpenSSL的库文件路径,可能在Debug编译模式下链接了Release版本的库,或者反之。Ubuntu系统默认的OpenSSL库不区分Debug/Release,但如果是自行编译的OpenSSL,必须确保CMake链接的库与当前编译模式一致。使用find_package可以自动规避这个问题。
内容的提问来源于stack exchange,提问作者Thomas Murphy

