[Boost-users] Getting ASIO application to link (undefined reference to `boost::system::generic_category())

318 views
Skip to first unread message

Ulf Samuelsson

unread,
Sep 17, 2013, 10:58:55 AM9/17/13
to boost...@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;
}
_______________________________________________
Boost-users mailing list
Boost...@lists.boost.org
http://lists.boost.org/mailman/listinfo.cgi/boost-users

Ulf Samuelsson

unread,
Sep 17, 2013, 1:20:54 PM9/17/13
to boost...@lists.boost.org
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

Slava

unread,
Sep 18, 2013, 2:32:11 AM9/18/13
to boost...@lists.boost.org
On Tue, 17 Sep 2013 19:20:54 +0200, Ulf Samuelsson <boost...@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

Ulf Samuelsson

unread,
Sep 18, 2013, 2:40:27 AM9/18/13
to boost...@lists.boost.org
On 2013-09-18 08:32, Slava wrote:
> On Tue, 17 Sep 2013 19:20:54 +0200, Ulf Samuelsson
> <boost...@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

Bjorn Reese

unread,
Sep 18, 2013, 6:47:12 AM9/18/13
to boost...@lists.boost.org
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/

Ulf Samuelsson

unread,
Sep 18, 2013, 11:20:44 AM9/18/13
to boost...@lists.boost.org
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

Lars Viklund

unread,
Sep 18, 2013, 11:20:06 AM9/18/13
to boost...@lists.boost.org
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 | z...@acc.umu.se

Gavin Lambert

unread,
Sep 19, 2013, 10:10:04 PM9/19/13
to boost...@lists.boost.org
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.
Reply all
Reply to author
Forward
0 new messages