boost::asio::ssl::context::context(boost::asic::ssl::context
boost::asio::ssl::context::context(boost::asio::ssl::context_base::method) undefined Symbols
我正在运行OSX Yosemite 10.10.5,带有clang-700.0.72和brew安装的boost 1.56。
我将boost::asio用于非ssl和tls套接字。在我的项目中,有问题的行是而不是,但似乎源于boost 1.56本身。
我使用cmake,我使用openssl进行链接,使用find_package(OpenSSL REQUIRED)
,我确实有openssl 1.0.2g
。
该项目使用C++11,违规行似乎是:
Undefined symbols for architecture x86_64:
"_SSLv2_client_method", referenced from:
boost::asio::ssl::context::context(boost::asio::ssl::context_base::method) in asio_tls.cpp.o
"_SSLv2_method", referenced from:
boost::asio::ssl::context::context(boost::asio::ssl::context_base::method) in asio_tls.cpp.o
"_SSLv2_server_method", referenced from:
boost::asio::ssl::context::context(boost::asio::ssl::context_base::method) in asio_tls.cpp.o
ld: symbol(s) not found for architecture x86_64
我根本不使用SSLv2,事实上,代码只关注于使用TLS v2:
class asio_socket_https
{
public:
asio_socket_https(const std::string token)
: ctx_(boost::asio::ssl::context::tlsv12_client), token_(token)
{}
稍后,在初始化套接字和上下文时,我会这样做:
ctx_.set_options(boost::asio::ssl::context::default_workarounds
|boost::asio::ssl::context::no_sslv2
|boost::asio::ssl::context::no_sslv3
|boost::asio::ssl::context::no_tlsv1
|boost::asio::ssl::context::single_dh_use);
我没有编译错误,该应用程序是根据libssl/libcrypto链接的,我还没有在Linux下测试过它(只有OSX)。
我看到了一个SO问题,主题相同,但这里没有答案。
实际链路标志:
/usr/bin/g++ -std=c++11 -Wall -g -Wl,-search_paths_first -Wl,-headerpad_max_install_names CMakeFiles/asio_tls.dir/examples/asio_tls.cpp.o -o asio_tls librapp.0.2.dylib /usr/local/lib/libboost_system-mt.dylib /usr/local/lib/libboost_thread-mt.dylib /usr/local/lib/libboost_random-mt.dylib /usr/local/lib/libboost_unit_test_framework-mt.dylib /usr/local/lib/libboost_program_options-mt.dylib /usr/local/Cellar/openssl/1.0.2g/lib/libssl.dylib /usr/local/Cellar/openssl/1.0.2g/lib/libcrypto.dylib
编辑
我今天在Ubuntu 14.04下测试了同样的代码,在检测openssl 1.0.1f时,它构建得很好(没有任何问题)。这似乎是一个OSX特有的问题。
@rhashimoto似乎是对的,而链接器在/usr/local/Cellar/openssl/
中使用的是Cellar版本的openssl,使用的头在/usr/local/openssl
下,我认为这与brew管理的不同。
解决方案
问题是在我的CMakeLists.txt
中,我认为find_package(OpenSSL REQUIRED)
就足够了,不幸的是,这破坏了与导入的库头链接的库版本。
默认库是OSX的openssl,而我使用${OPENSSL_LIBRARIES}
显式链接。
只需添加以下内容就解决了问题(现在它使用从brew安装的openssl):
find_package(OpenSSL REQUIRED)
if (OPENSSL_FOUND)
include_directories(${OPENSSL_INCLUDE_DIR})
endif()
然后进行target_link_libraries(... ${OPENSSL_LIBRARIES})
Boost Asio在boost/asio/ssl/impl/context.ipp
中使用SSLv2_client_method()
和SSLv2_server_method()
,条件是不存在预处理器符号OPENSSL_NO_SSL2
:
#if defined(OPENSSL_NO_SSL2)
case context::sslv2:
case context::sslv2_client:
case context::sslv2_server:
boost::asio::detail::throw_error(
boost::asio::error::invalid_argument, "context");
break;
#else // defined(OPENSSL_NO_SSL2)
case context::sslv2:
handle_ = ::SSL_CTX_new(::SSLv2_method());
break;
case context::sslv2_client:
handle_ = ::SSL_CTX_new(::SSLv2_client_method());
break;
case context::sslv2_server:
handle_ = ::SSL_CTX_new(::SSLv2_server_method());
break;
#endif // defined(OPENSSL_NO_SSL2)
如果OPENSSL_NO_SSL2
不包括对SSLv2的支持,那么它应该在OpenSSL库头中定义,但显然您的构建没有接受它。
对这种行为的一个常见解释是,您使用一个仍然支持SSLv2的OpenSSL库中的头进行编译,并使用另一个不支持SSLv2OpenSSL库的二进制文件进行链接。在编译器选项中插入-H
标志可能会有所帮助,它会在处理标头时记录标头路径,因为您可以验证正在使用哪些标头。
- 理解boost::asio-async_read在无需读取内容时的行为
- boost::进程间消息队列引发错误
- 如何运行位于boost/libs/python/example/tutorial目录中的hello.cpp和Jamfil
- cmake如何在fedora工作站中找到boost静态库包
- CMake项目Boost库错误:Boost/config/compiler/gcc.hpp:165:10:致命错误:cs
- Boost Graph Library,修复节点大小
- 什么是"#include <boost/functional/hash.hpp> "?
- 基于boost的程序的静态链接——zlib问题
- C++:如何在CLion IDE中安装Boost
- C++Boost Asio Pool线程,带有lambda函数和传递引用变量
- 如何在boost beast http请求中设置http头
- Boost Spirit,获取迭代器内部语义动作
- boost::asio::steady_timer()与sleep()我应该使用哪一个
- boost::context::basic_segmented_stack 不是按需增长
- Boost 1.57 Boost.Context fcontext_t资源管理
- boost::asio::ssl::context::context(boost::asic::ssl::context
- 如何修改boost::asio::ssl::context的方法
- Boost::Context在iOS上工作吗?
- boost::asio::ssl::context::add_verify_path
- 什么是boost::asio::ssl::context::load_verify_file以及如何使用它