Getting ASIO application to link (undefined reference to `boost::system::generic_category())

Hi, Trying to get an ASIO example (udp_echo_client) to build on an Ubuntu 12.04 machine. It looks like both 1.46 and 1.48 can be installed. (I have installed 1.48). The libboost*.so all are linked vs 1.48, and the /usr/include/boost/version.hpp contains #define BOOST_LIB_VERSION "1_48" so I think that there should not be a version mismatch, I can build some really simple examples but, as soon as I add "asio" with the statement below, the build fails. using boost::asio::ip::udp; Fiirst problem is that `boost::system::generic_category()' is missing. When I grep the libboost libraries, they are only found in "libboost_[file]system[-mt].so" but these files are included in the link. Searching on Internet, also tells me to link with those libraries, which is not a help. Tried with "-mt" version as well. Added #include <boost/system/error_code.hpp> #include <boost/system/linux_error.hpp> without any change. What is going on? Running out of ideas... Thanks for any advice. /Ulf Samuelsson ---------------------------------------------------------- g++ -I/usr/include -Iinclude -L/usr/lib -lboost_filesystem -lboost_system -lpthread -std=c++0x -o udp_echo_client udp_echo_client.cpp /tmp/ccu20iRA.o: In function `__static_initialization_and_destruction_0(int, int)': udp_echo_client.cpp:(.text+0x58d): undefined reference to `boost::system::generic_category()' udp_echo_client.cpp:(.text+0x597): undefined reference to `boost::system::generic_category()' udp_echo_client.cpp:(.text+0x5a1): undefined reference to `boost::system::system_category()' /tmp/ccu20iRA.o: In function `boost::system::error_code::error_code()': udp_echo_client.cpp:(.text._ZN5boost6system10error_codeC2Ev[_ZN5boost6system10error_codeC5Ev]+0x10): undefined reference to `boost::system::system_category()' /tmp/ccu20iRA.o: In function `boost::asio::error::get_system_category()': udp_echo_client.cpp:(.text._ZN5boost4asio5error19get_system_categoryEv[boost::asio::error::get_system_category()]+0x7): undefined reference to `boost::system::system_category()' /tmp/ccu20iRA.o: In function `boost::asio::detail::posix_tss_ptr_create(unsigned int&)': udp_echo_client.cpp:(.text._ZN5boost4asio6detail20posix_tss_ptr_createERj[boost::asio::detail::posix_tss_ptr_create(unsigned int&)]+0x15): undefined reference to `pthread_key_create' /tmp/ccu20iRA.o: In function `boost::asio::detail::posix_thread::~posix_thread()': udp_echo_client.cpp:(.text._ZN5boost4asio6detail12posix_threadD2Ev[_ZN5boost4asio6detail12posix_threadD5Ev]+0x1d): undefined reference to `pthread_detach' /tmp/ccu20iRA.o: In function `boost::asio::detail::posix_thread::join()': udp_echo_client.cpp:(.text._ZN5boost4asio6detail12posix_thread4joinEv[boost::asio::detail::posix_thread::join()]+0x25): undefined reference to `pthread_join' /tmp/ccu20iRA.o: In function `boost::asio::detail::posix_thread::start_thread(boost::asio::detail::posix_thread::func_base*)': udp_echo_client.cpp:(.text._ZN5boost4asio6detail12posix_thread12start_threadEPNS2_9func_baseE[boost::asio::detail::posix_thread::start_thread(boost::asio::detail::posix_thread::func_base*)]+0x24): undefined reference to `pthread_create' /tmp/ccu20iRA.o: In function `boost::asio::detail::posix_tss_ptr<boost::asio::detail::call_stack<boost::asio::detail::task_io_service, boost::asio::detail::task_io_service::thread_info>::context>::~posix_tss_ptr()': udp_echo_client.cpp:(.text._ZN5boost4asio6detail13posix_tss_ptrINS1_10call_stackINS1_15task_io_serviceENS4_11thread_infoEE7contextEED2Ev[_ZN5boost4asio6detail13posix_tss_ptrINS1_10call_stackINS1_15task_io_serviceENS4_11thread_infoEE7contextEED5Ev]+0xf): undefined reference to `pthread_key_delete' /tmp/ccu20iRA.o: In function `boost::asio::detail::posix_tss_ptr<boost::asio::detail::call_stack<boost::asio::detail::task_io_service, boost::asio::detail::task_io_service::thread_info>::context>::operator boost::asio::detail::call_stack<boost::asio::detail::task_io_service, boost::asio::detail::task_io_service::thread_info>::context*() const': udp_echo_client.cpp:(.text._ZNK5boost4asio6detail13posix_tss_ptrINS1_10call_stackINS1_15task_io_serviceENS4_11thread_infoEE7contextEEcvPS7_Ev[boost::asio::detail::posix_tss_ptr<boost::asio::detail::call_stack<boost::asio::detail::task_io_service, boost::asio::detail::task_io_service::thread_info>::context>::operator boost::asio::detail::call_stack<boost::asio::detail::task_io_service, boost::asio::detail::task_io_service::thread_info>::context*() const]+0xf): undefined reference to `pthread_getspecific' /tmp/ccu20iRA.o: In function `boost::asio::detail::posix_tss_ptr<boost::asio::detail::call_stack<boost::asio::detail::strand_service::strand_impl, unsigned char>::context>::~posix_tss_ptr()': udp_echo_client.cpp:(.text._ZN5boost4asio6detail13posix_tss_ptrINS1_10call_stackINS1_14strand_service11strand_implEhE7contextEED2Ev[_ZN5boost4asio6detail13posix_tss_ptrINS1_10call_stackINS1_14strand_service11strand_implEhE7contextEED5Ev]+0xf): undefined reference to `pthread_key_delete' /tmp/ccu20iRA.o: In function `boost::asio::detail::posix_tss_ptr<boost::asio::detail::call_stack<boost::asio::detail::task_io_service, boost::asio::detail::task_io_service::thread_info>::context>::operator=(boost::asio::detail::call_stack<boost::asio::detail::task_io_service, boost::asio::detail::task_io_service::thread_info>::context*)': udp_echo_client.cpp:(.text._ZN5boost4asio6detail13posix_tss_ptrINS1_10call_stackINS1_15task_io_serviceENS4_11thread_infoEE7contextEEaSEPS7_[boost::asio::detail::posix_tss_ptr<boost::asio::detail::call_stack<boost::asio::detail::task_io_service, boost::asio::detail::task_io_service::thread_info>::context>::operator=(boost::asio::detail::call_stack<boost::asio::detail::task_io_service, boost::asio::detail::task_io_service::thread_info>::context*)]+0x16): undefined reference to `pthread_setspecific' collect2: ld returnerade avslutningsstatus 1 make: *** [udp_echo_client] Fel 1 -------------------------------------------------------------- Makefile: ------------------------------------------------------ # Using 1.48.0 in Ubuntu 12.04 BOOST=/usr INCLUDES += -I$(BOOST)/include -Iinclude LIBS +=-L$(BOOST)/lib -lboost_filesystem -lboost_system -lpthread CFLAGS=$(INCLUDES) $(LIBS) -std=c++0x all: udp_echo_client udp_echo_client: udp_echo_client.cpp g++ $(CFLAGS) -o $@ udp_echo_client.cpp clean: rm -f udp_echo_client rm -f *~ -------------------------------------------------------- Code from example: -------------------------------------------------------- // // blocking_udp_echo_client.cpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // // Copyright (c) 2003-2013 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // #include <cstdlib> #include <cstring> #include <iostream> #include <boost/asio.hpp> using boost::asio::ip::udp; enum { max_length = 1024 }; int main(int argc, char* argv[]) { try { if (argc != 3) { std::cerr << "Usage: blocking_udp_echo_client <host> <port>\n"; return 1; } boost::asio::io_service io_service; udp::socket s(io_service, udp::endpoint(udp::v4(), 0)); udp::resolver resolver(io_service); udp::endpoint endpoint = *resolver.resolve({udp::v4(), argv[1], argv[2]}); std::cout << "Enter message: "; char request[max_length]; std::cin.getline(request, max_length); size_t request_length = std::strlen(request); s.send_to(boost::asio::buffer(request, request_length), endpoint); char reply[max_length]; udp::endpoint sender_endpoint; size_t reply_length = s.receive_from( boost::asio::buffer(reply, max_length), sender_endpoint); std::cout << "Reply is: "; std::cout.write(reply, reply_length); std::cout << "\n"; } catch (std::exception& e) { std::cerr << "Exception: " << e.what() << "\n"; } return 0; }

Solved! The Libraries need to be at the end during the link phase. $ g++ -c -I/usr/include -Iinclude -std=c++0x -o udp_echo_client.o udp_echo_client.cpp $ g++ -o udp_echo_client udp_echo_client.o -L/usr/lib -lboost_filesystem -lboost_system -lpthread works BR Ulf -------- Original Message -------- Subject: Getting ASIO application to link (undefined reference to `boost::system::generic_category()) Date: Tue, 17 Sep 2013 16:58:55 +0200 From: Ulf Samuelsson <boost-user@emagii.com> To: boost-users@lists.boost.org Hi, Trying to get an ASIO example (udp_echo_client) to build on an Ubuntu 12.04 machine. It looks like both 1.46 and 1.48 can be installed. (I have installed 1.48). The libboost*.so all are linked vs 1.48, and the /usr/include/boost/version.hpp contains #define BOOST_LIB_VERSION "1_48" so I think that there should not be a version mismatch, I can build some really simple examples but, as soon as I add "asio" with the statement below, the build fails. using boost::asio::ip::udp; Fiirst problem is that `boost::system::generic_category()' is missing. When I grep the libboost libraries, they are only found in "libboost_[file]system[-mt].so" but these files are included in the link. Searching on Internet, also tells me to link with those libraries, which is not a help. Tried with "-mt" version as well. Added #include <boost/system/error_code.hpp> #include <boost/system/linux_error.hpp> without any change. What is going on? Running out of ideas... Thanks for any advice. /Ulf Samuelsson ---------------------------------------------------------- g++ -I/usr/include -Iinclude -L/usr/lib -lboost_filesystem -lboost_system -lpthread -std=c++0x -o udp_echo_client udp_echo_client.cpp /tmp/ccu20iRA.o: In function `__static_initialization_and_destruction_0(int, int)': udp_echo_client.cpp:(.text+0x58d): undefined reference to `boost::system::generic_category()' udp_echo_client.cpp:(.text+0x597): undefined reference to `boost::system::generic_category()' udp_echo_client.cpp:(.text+0x5a1): undefined reference to `boost::system::system_category()' /tmp/ccu20iRA.o: In function `boost::system::error_code::error_code()': udp_echo_client.cpp:(.text._ZN5boost6system10error_codeC2Ev[_ZN5boost6system10error_codeC5Ev]+0x10): undefined reference to `boost::system::system_category()' /tmp/ccu20iRA.o: In function `boost::asio::error::get_system_category()': udp_echo_client.cpp:(.text._ZN5boost4asio5error19get_system_categoryEv[boost::asio::error::get_system_category()]+0x7): undefined reference to `boost::system::system_category()' /tmp/ccu20iRA.o: In function `boost::asio::detail::posix_tss_ptr_create(unsigned int&)': udp_echo_client.cpp:(.text._ZN5boost4asio6detail20posix_tss_ptr_createERj[boost::asio::detail::posix_tss_ptr_create(unsigned int&)]+0x15): undefined reference to `pthread_key_create' /tmp/ccu20iRA.o: In function `boost::asio::detail::posix_thread::~posix_thread()': udp_echo_client.cpp:(.text._ZN5boost4asio6detail12posix_threadD2Ev[_ZN5boost4asio6detail12posix_threadD5Ev]+0x1d): undefined reference to `pthread_detach' /tmp/ccu20iRA.o: In function `boost::asio::detail::posix_thread::join()': udp_echo_client.cpp:(.text._ZN5boost4asio6detail12posix_thread4joinEv[boost::asio::detail::posix_thread::join()]+0x25): undefined reference to `pthread_join' /tmp/ccu20iRA.o: In function `boost::asio::detail::posix_thread::start_thread(boost::asio::detail::posix_thread::func_base*)': udp_echo_client.cpp:(.text._ZN5boost4asio6detail12posix_thread12start_threadEPNS2_9func_baseE[boost::asio::detail::posix_thread::start_thread(boost::asio::detail::posix_thread::func_base*)]+0x24): undefined reference to `pthread_create' /tmp/ccu20iRA.o: In function `boost::asio::detail::posix_tss_ptr<boost::asio::detail::call_stack<boost::asio::detail::task_io_service, boost::asio::detail::task_io_service::thread_info>::context>::~posix_tss_ptr()': udp_echo_client.cpp:(.text._ZN5boost4asio6detail13posix_tss_ptrINS1_10call_stackINS1_15task_io_serviceENS4_11thread_infoEE7contextEED2Ev[_ZN5boost4asio6detail13posix_tss_ptrINS1_10call_stackINS1_15task_io_serviceENS4_11thread_infoEE7contextEED5Ev]+0xf): undefined reference to `pthread_key_delete' /tmp/ccu20iRA.o: In function `boost::asio::detail::posix_tss_ptr<boost::asio::detail::call_stack<boost::asio::detail::task_io_service, boost::asio::detail::task_io_service::thread_info>::context>::operator boost::asio::detail::call_stack<boost::asio::detail::task_io_service, boost::asio::detail::task_io_service::thread_info>::context*() const': udp_echo_client.cpp:(.text._ZNK5boost4asio6detail13posix_tss_ptrINS1_10call_stackINS1_15task_io_serviceENS4_11thread_infoEE7contextEEcvPS7_Ev[boost::asio::detail::posix_tss_ptr<boost::asio::detail::call_stack<boost::asio::detail::task_io_service, boost::asio::detail::task_io_service::thread_info>::context>::operator boost::asio::detail::call_stack<boost::asio::detail::task_io_service, boost::asio::detail::task_io_service::thread_info>::context*() const]+0xf): undefined reference to `pthread_getspecific' /tmp/ccu20iRA.o: In function `boost::asio::detail::posix_tss_ptr<boost::asio::detail::call_stack<boost::asio::detail::strand_service::strand_impl, unsigned char>::context>::~posix_tss_ptr()': udp_echo_client.cpp:(.text._ZN5boost4asio6detail13posix_tss_ptrINS1_10call_stackINS1_14strand_service11strand_implEhE7contextEED2Ev[_ZN5boost4asio6detail13posix_tss_ptrINS1_10call_stackINS1_14strand_service11strand_implEhE7contextEED5Ev]+0xf): undefined reference to `pthread_key_delete' /tmp/ccu20iRA.o: In function `boost::asio::detail::posix_tss_ptr<boost::asio::detail::call_stack<boost::asio::detail::task_io_service, boost::asio::detail::task_io_service::thread_info>::context>::operator=(boost::asio::detail::call_stack<boost::asio::detail::task_io_service, boost::asio::detail::task_io_service::thread_info>::context*)': udp_echo_client.cpp:(.text._ZN5boost4asio6detail13posix_tss_ptrINS1_10call_stackINS1_15task_io_serviceENS4_11thread_infoEE7contextEEaSEPS7_[boost::asio::detail::posix_tss_ptr<boost::asio::detail::call_stack<boost::asio::detail::task_io_service, boost::asio::detail::task_io_service::thread_info>::context>::operator=(boost::asio::detail::call_stack<boost::asio::detail::task_io_service, boost::asio::detail::task_io_service::thread_info>::context*)]+0x16): undefined reference to `pthread_setspecific' collect2: ld returnerade avslutningsstatus 1 make: *** [udp_echo_client] Fel 1 -------------------------------------------------------------- Makefile: ------------------------------------------------------ # Using 1.48.0 in Ubuntu 12.04 BOOST=/usr INCLUDES += -I$(BOOST)/include -Iinclude LIBS +=-L$(BOOST)/lib -lboost_filesystem -lboost_system -lpthread CFLAGS=$(INCLUDES) $(LIBS) -std=c++0x all: udp_echo_client udp_echo_client: udp_echo_client.cpp g++ $(CFLAGS) -o $@ udp_echo_client.cpp clean: rm -f udp_echo_client rm -f *~ -------------------------------------------------------- Code from example: -------------------------------------------------------- // // blocking_udp_echo_client.cpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // // Copyright (c) 2003-2013 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // #include <cstdlib> #include <cstring> #include <iostream> #include <boost/asio.hpp> using boost::asio::ip::udp; enum { max_length = 1024 }; int main(int argc, char* argv[]) { try { if (argc != 3) { std::cerr << "Usage: blocking_udp_echo_client <host> <port>\n"; return 1; } boost::asio::io_service io_service; udp::socket s(io_service, udp::endpoint(udp::v4(), 0)); udp::resolver resolver(io_service); udp::endpoint endpoint = *resolver.resolve({udp::v4(), argv[1], argv[2]}); std::cout << "Enter message: "; char request[max_length]; std::cin.getline(request, max_length); size_t request_length = std::strlen(request); s.send_to(boost::asio::buffer(request, request_length), endpoint); char reply[max_length]; udp::endpoint sender_endpoint; size_t reply_length = s.receive_from( boost::asio::buffer(reply, max_length), sender_endpoint); std::cout << "Reply is: "; std::cout.write(reply, reply_length); std::cout << "\n"; } catch (std::exception& e) { std::cerr << "Exception: " << e.what() << "\n"; } return 0; }

On Tue, 17 Sep 2013 19:20:54 +0200, Ulf Samuelsson <boost-user@emagii.com> wrote:
Solved! The Libraries need to be at the end during the link phase.
$ g++ -c -I/usr/include -Iinclude -std=c++0x -o udp_echo_client.o udp_echo_client.cpp $ g++ -o udp_echo_client udp_echo_client.o -L/usr/lib -lboost_filesystem -lboost_system -lpthread
works
BR Ulf
... what means that the linker uses static libraries (.a). Use -t linker flag (-Wl,-t to gcc) to debug which libraries linker finds and which it takes. // The *.so are in -dev packages in some distributions. Maybe you need boost*dev package(s) installed in ubuntu? Regards, Slava

On 2013-09-18 08:32, Slava wrote:
On Tue, 17 Sep 2013 19:20:54 +0200, Ulf Samuelsson <boost-user@emagii.com> wrote:
Solved! The Libraries need to be at the end during the link phase.
$ g++ -c -I/usr/include -Iinclude -std=c++0x -o udp_echo_client.o udp_echo_client.cpp $ g++ -o udp_echo_client udp_echo_client.o -L/usr/lib -lboost_filesystem -lboost_system -lpthread
works
BR Ulf
... what means that the linker uses static libraries (.a). Use -t linker flag (-Wl,-t to gcc) to debug which libraries linker finds and which it takes. // The *.so are in -dev packages in some distributions. Maybe you need boost*dev package(s) installed in ubuntu?
No, the solution is simple. The -l<library> must be AFTER the reference to the object files. FAIL: g++ -lboost_system myfile.o OK: g++ myfile.o -lboost_system Maybe there is a good reason for this. BR Ulf
Regards, Slava
_______________________________________________ Boost-users mailing list Boost-users@lists.boost.org http://lists.boost.org/mailman/listinfo.cgi/boost-users

On 09/18/2013 08:40 AM, Ulf Samuelsson wrote:
No, the solution is simple. The -l<library> must be AFTER the reference to the object files.
FAIL: g++ -lboost_system myfile.o OK: g++ myfile.o -lboost_system
Maybe there is a good reason for this.
Many linkers are single-pass linkers because that gives better linking speed. See "The linking process" section of: http://eli.thegreenplace.net/2013/07/09/library-order-in-static-linking/

On Wed, Sep 18, 2013 at 12:47:12PM +0200, Bjorn Reese wrote:
On 09/18/2013 08:40 AM, Ulf Samuelsson wrote:
No, the solution is simple. The -l<library> must be AFTER the reference to the object files.
FAIL: g++ -lboost_system myfile.o OK: g++ myfile.o -lboost_system
Maybe there is a good reason for this.
Many linkers are single-pass linkers because that gives better linking speed. See "The linking process" section of:
http://eli.thegreenplace.net/2013/07/09/library-order-in-static-linking/
As touched on in the article linked, the ability to override functions by sneaking in a library providing the function before the usual provider is considered a feature by some. If you want arbitrary ordering on the linker command line, some linkers offer --start-group and --end-group directives that spin the libraries bounded by the directives enough times to satisfy as many symbols as possible. Otherwise, the short form of the linker command line order advice is: Stuff that needs stuff needs to be before stuff that provides stuff. -- Lars Viklund | zao@acc.umu.se

On 2013-09-18 12:47, Bjorn Reese wrote:
On 09/18/2013 08:40 AM, Ulf Samuelsson wrote:
No, the solution is simple. The -l<library> must be AFTER the reference to the object files.
FAIL: g++ -lboost_system myfile.o OK: g++ myfile.o -lboost_system
Maybe there is a good reason for this.
Many linkers are single-pass linkers because that gives better linking speed. See "The linking process" section of:
http://eli.thegreenplace.net/2013/07/09/library-order-in-static-linking/
That still does not mean that you cannot parse a command line before starting the actual link process. Maybe in obscure cases you want tighter control when a library can be used, but it should IMHO be the exception. BR Ulf
_______________________________________________ Boost-users mailing list Boost-users@lists.boost.org http://lists.boost.org/mailman/listinfo.cgi/boost-users

On 9/19/2013 3:20 AM, Quoth Ulf Samuelsson:
That still does not mean that you cannot parse a command line before starting the actual link process.
It's not about the command line parsing, it's about the order that the objects and libraries themselves are parsed in. The order in which objects are linked can be critically important for certain designs (eg. if you do want a symbol in your application to override one provided by a library, or if you're building a multi-object data structure in a special shared data section). And so that order has been defined as the order that they're listed on the command line, which just makes sense. Sure, it can be a little surprising when you're not used to it, but it's not hard to get it "right" thereafter. And while it's possible to tell the linker to loop through multiple times until it's found everything, this is generally a bad idea as it hides circular dependencies, which are usually a sign of a bad design. And it's slower than just listing things in the correct order to begin with.
participants (5)
-
Bjorn Reese
-
Gavin Lambert
-
Lars Viklund
-
Slava
-
Ulf Samuelsson