1
votes

Here's the project I'm developing: https://github.com/bigdatadev/riemannpp

I'm a relative beginner to autotools, and I'm having difficulty getting my shared object riemannpp to link against another library called riemann-client (link in the README.md).

I find the compile / link flags for riemann-client using PKG_CHECK_MODULES in configure.ac (ln. 38). I then use the flags in Makefile.am when I build the .so using LIBADD (ln. 29).

If you try to compile the sources (make), libriemannpp.so will build, but seems that I am doing something very wrong when I try to link the client and unit tests. I add the reference to libriemannpp.so by referencing libriemannpp.la (Makefile.am ln. 41).

The error I'm getting is undefined references to functions from the riemann-client library which riemannpp.so depends. nm shows that riemannpp.so has undefined references, but ldd shows no dependency on riemann-client, which nm shows does exports the missing symbols. I have tried fiddling with the Makefile.am to get the riemannpp library to link properly, but I'm giving in and am hoping an expert will be able to help me out.

If anyone can help me understand what I'm doing wrong and how to fix it I would be very grateful.

I'm using Ubuntu 14.04 with default system packages for gcc, autoconf, automake and libtool.


EDIT: Some more information

ldd output on libriemannpp.so:

  • linux-vdso.so.1 => (0x00007fff36b29000)
  • libstdc++.so.6 => /usr/lib/x86_64-linux-gnu/libstdc++.so.6 (0x00007f9b13f54000)
  • libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f9b13b8e000)
  • libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007f9b13977000)
  • libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007f9b13671000)
  • /lib64/ld-linux-x86-64.so.2 (0x00007f9b14488000)

nm output on libriemannpp.so:

  • U _Z17riemann_event_newv
  • U _Z17riemann_event_setP6_Eventz
  • U _Z17riemann_query_newPKc
  • U _Z18riemann_client_newv
  • U _Z18riemann_event_freeP6_Event
  • U _Z18riemann_query_freeP6_Query
  • ... etc ...

nm output on libriemann-client.so:

  • 0000000000002c70 T riemann_event_attribute_add
  • 0000000000002cd0 T riemann_event_create
  • 0000000000002610 T riemann_event_free
  • 00000000000025f0 T riemann_event_new
  • ... etc ...

So it seems that the symbols are correctly defined in libriemann-client.so. At least I'm not going completely insane...

The offending build output:

/bin/bash ./libtool  --tag=CXX   --mode=link g++  -g -O2 -std=c++11   -o src/client/riemannpp src/client/riemannpp.o ./src/riemannpp/libriemannpp.la -L/usr/local/lib -lriemann-client    
libtool: link: g++ -g -O2 -std=c++11 -o src/client/.libs/riemannpp src/client/riemannpp.o  ./src/riemannpp/.libs/libriemannpp.so -L/usr/local/lib /usr/local/lib/libriemann-client.so
./src/riemannpp/.libs/libriemannpp.so: undefined reference to `riemann_client_send_message(_riemann_client_t*, _Msg*)'
./src/riemannpp/.libs/libriemannpp.so: undefined reference to `riemann_query_set_string(_Query*, char const*)'
./src/riemannpp/.libs/libriemannpp.so: undefined reference to `riemann_client_send_message_oneshot(_riemann_client_t*, _Msg*)'
./src/riemannpp/.libs/libriemannpp.so: undefined reference to `riemann_client_disconnect(_riemann_client_t*)'
./src/riemannpp/.libs/libriemannpp.so: undefined reference to `riemann_attribute_set(_Attribute*, char const*, char const*)'
./src/riemannpp/.libs/libriemannpp.so: undefined reference to `riemann_client_new()'
./src/riemannpp/.libs/libriemannpp.so: undefined reference to `riemann_attribute_free(_Attribute*)'
./src/riemannpp/.libs/libriemannpp.so: undefined reference to `riemann_event_new()'
./src/riemannpp/.libs/libriemannpp.so: undefined reference to `riemann_client_free(_riemann_client_t*)'
./src/riemannpp/.libs/libriemannpp.so: undefined reference to `riemann_query_new(char const*)'
./src/riemannpp/.libs/libriemannpp.so: undefined reference to `riemann_attribute_create(char const*, char const*)'
./src/riemannpp/.libs/libriemannpp.so: undefined reference to `riemann_message_set_query(_Msg*, _Query*)'
./src/riemannpp/.libs/libriemannpp.so: undefined reference to `riemann_event_set(_Event*, ...)'
./src/riemannpp/.libs/libriemannpp.so: undefined reference to `riemann_query_free(_Query*)'
./src/riemannpp/.libs/libriemannpp.so: undefined reference to `riemann_event_attribute_add(_Event*, _Attribute*)'
./src/riemannpp/.libs/libriemannpp.so: undefined reference to `riemann_attribute_set_value(_Attribute*, char const*)'
./src/riemannpp/.libs/libriemannpp.so: undefined reference to `riemann_attribute_new()'
./src/riemannpp/.libs/libriemannpp.so: undefined reference to `riemann_message_new()'
./src/riemannpp/.libs/libriemannpp.so: undefined reference to `riemann_client_connect(_riemann_client_t*, riemann_client_type_t, char const*, int)'
./src/riemannpp/.libs/libriemannpp.so: undefined reference to `riemann_event_tag_add(_Event*, char const*)'
./src/riemannpp/.libs/libriemannpp.so: undefined reference to `riemann_message_free(_Msg*)'
./src/riemannpp/.libs/libriemannpp.so: undefined reference to `riemann_attribute_set_key(_Attribute*, char const*)'
./src/riemannpp/.libs/libriemannpp.so: undefined reference to `riemann_message_set_events_n(_Msg*, unsigned long, _Event**)'
./src/riemannpp/.libs/libriemannpp.so: undefined reference to `riemann_client_create(riemann_client_type_t, char const*, int)'
./src/riemannpp/.libs/libriemannpp.so: undefined reference to `riemann_event_free(_Event*)'

Steps to try it out:

$ git clone [email protected]:algernon/riemann-c-client.git
$ cd riemann-c-client
$ sudo apt-get install protobuf-c-compiler # ubuntu
$ ./configure && make && sudo make install
$ cd ..
$ git clone [email protected]:bigdatadev/riemannpp.git
$ cd riemannpp
$ ./autogen.sh
$ ./configure && make

Note that you will have unresolved symbol references in libriemannpp.so when compiling the client program, despite libriemannpp having references to the riemann-c-client (obtained via pkg-config riemann-client --cflags --libs).


EDIT: I get the same problem even if I run ./configure --disable-shared, which seems to rule out any possibility of a bug in the shared object I'm building. I'm clearly missing how to add the dependency information to the library, but Google isn't giving any answers away.

It seems very unlikely that this is a bug in the riemann-client library, as that builds and passes its unit tests flawlessly.

1

1 Answers

1
votes

riemann-client fails to use

#ifdef __cplusplus
extern "C" {
#endif
   ...
#ifdef __cplusplus
}
#endif

in its header files, therefore your riemanpp code parts think it is calling C++ code when in fact it is C. And you cannot just use

#ifdef __cplusplus
extern "C" {
#endif
#include <riemann/event.h>
...

as that could possibly subject C++ headers to be wrongly wrapped into C calling conventions. (Meaning the fix must occur in riemann-client)