需要链接的库将根据所使用的 Boost.Asio 功能和其他 Boost 头文件来确定。一般来说,可以通过对未定义引用的命名空间进行一些猜测来确定要链接到哪个库,并检查 Boost 库中的符号(如果不起作用)。
在下面的所有示例中,我使用的是 gcc 4.8.1。确切的错误消息并不重要,因为编译器之间的错误消息内容应该非常相似。
采用包含 Boost.Asio 的基本程序:
#include <boost/asio.hpp>
int main() {}
编译时:
$ g++ example.cpp -isystem /usr/local/boost_1_55_0
...
example.cpp:(.text+0x31): undefined reference to
`boost::system::generic_category()'
...
/tmp/cc9ow7fd.o: In function `boost::asio::error::get_system_category()':
example.cpp:(.text._ZN5boost4asio5error19get_system_categoryEv[
_ZN5boost4asio5error19get_system_categoryEv]+0x5): undefined reference
to `boost::system::system_category()'
请注意,未定义的引用是包含在boost::system
命名空间。如果要查看已安装的 Boost 库的列表,libboost_system.so
可能会被认为是一个很好的链接候选者。如果没有明显的候选者,那么可以使用类似的工具nm http://linux.die.net/man/1/nm or readelf http://linux.die.net/man/1/readelf检查候选库并寻找符号:
$ nm --defined-only --print-file-name --demangle \
> /usr/local/lib/libboost_*.so | grep boost::system::generic_category
...
/usr/local/lib/libboost_system.so:
00000000000015c0 T boost::system::generic_category()
...
在这种情况下,boost::system::generic_category()
符号在文本部分定义libboost_system.so
。因此,基本程序需要链接到boost_system
:
g++ example.cpp -isystem /usr/local/boost_1_55_0 -L/usr/local/lib/ -lboost_system
这是一个稍微复杂一点的示例。该程序异步等待由附加线程执行的协程中的单调计时器。
#include <boost/asio.hpp>
#include <boost/asio/spawn.hpp>
#include <boost/asio/steady_timer.hpp>
#include <boost/thread/thread.hpp>
boost::asio::io_service io_service;
void handler(boost::asio::yield_context yield)
{
boost::asio::steady_timer timer(io_service);
timer.expires_from_now(boost::chrono::seconds(3));
timer.async_wait(yield);
}
int main()
{
boost::asio::spawn(io_service, &handler);
boost::thread thread(boost::bind(
&boost::asio::io_service::run, &io_service));
thread.join();
}
虽然可以使用与以前相同的方法,但链接器错误会导致 40 多行模板符号损坏,这可能非常令人畏惧。作为一种替代方法,可以编译该示例,但不能使用-c
选项。然后,可以检查生成的目标文件中是否有未定义的符号:
$ g++ example.cpp -isystem /usr/local/boost_1_55_0 -c
$ nm --demangle --undefined example.o | grep boost
U boost::coroutines::stack_traits::default_size()
U boost::coroutines::stack_traits::is_unbounded()
U boost::coroutines::stack_traits::maximum_size()
U boost::coroutines::stack_traits::minimum_size()
U boost::coroutines::detail::coroutine_context::jump(
boost::coroutines::detail::coroutine_context&, long, bool)
U boost::coroutines::detail::coroutine_context::coroutine_context(
void (*)(long), boost::coroutines::stack_context const&)
U boost::coroutines::detail::coroutine_context::coroutine_context()
U boost::chrono::steady_clock::now()
U boost::detail::thread_data_base::~thread_data_base()
U boost::system::system_category()
U boost::system::generic_category()
U boost::thread::join_noexcept()
U boost::thread::native_handle()
U boost::thread::start_thread_noexcept()
U boost::thread::detach()
U typeinfo for boost::detail::thread_data_base
U vtable for boost::detail::thread_data_base
此输出比链接器错误更易于管理。再次,符号命名空间(boost::coroutine
, boost::chrono
, boost::thread
, and boost::system
)提供了关于哪个库可以定义该符号的良好提示。上述程序可以通过以下方式编译和链接:
g++ example.cpp -isystem /usr/local/boost_1_55_0 -L/usr/local/lib/ -lboost_coroutine -lboost_chrono -lboost_thread -lboost_system
另外,请注意链接顺序很重要 https://stackoverflow.com/q/45135/1053968.