Problems Linking on Linux

Aug 4, 2014 at 2:39 PM
I am trying to port our Casablanca based application to Linux (Ubuntu 14.04) and am having a problem with a bunch of symbols not being found by the linker. I am hoping someone else has had a similar problem porting their cpprest application(s) to Linux and will recognize the problem and point me towards a solution.

Thanks in advance for your help!

Short Version

I am linking against locally built boost and cpprest libraries. They are built against ICU libraries installed as part of the libicu-dev. Everything compiles fine but the linker doesn't find the symbols in the icu library - even though nm sees them just fine.

All the Gory Details

In the link part of my build I am getting a pile of undefined references to ucnv_* functions (ucnv_open_52, ucnv_close_52, etc.). The g++ link command has –licuuc. The linker isn’t complaining about not finding the library but it doesn’t seem to find the symbols in it.

In case it helps the g++ command looks something like this (cleaned up to hopefully improve readability):
/usr/bin/g++ {application .o files} -o {application name} -rdynamic -licuuc -lssl -lcrypto {locally built boost .a files} -lpthread –pthread
However, I get a pile of errors associated with boost locale. For example:
/libraries/boost_1_55_0/stage/lib/libboost_locale.a(codepage.o): In function `boost::locale::conv::impl::uconv_to_utf<wchar_t>::open(char const*, boost::locale::conv::method_type)':
codepage.cpp:(.text._ZN5boost6locale4conv4impl12uconv_to_utfIwE4openEPKcNS1_11method_typeE[_ZN5boost6locale4conv4impl12uconv_to_utfIwE4openEPKcNS1_11method_typeE]+0xac): undefined reference to `ucnv_open_52'
codepage.cpp:(.text._ZN5boost6locale4conv4impl12uconv_to_utfIwE4openEPKcNS1_11method_typeE[_ZN5boost6locale4conv4impl12uconv_to_utfIwE4openEPKcNS1_11method_typeE]+0xc4): undefined reference to `ucnv_close_52'
{many more}
This is on an ubuntu 14.04 machine using the default packages.
$ dpkg --get-selections | grep icu
icu-devtools                                    install
libicu-dev:amd64                                install
libicu52:amd64                                  install
Looking at ldconfig –v shows that libicuuc is being loaded from /usr/lib/x86_64-linux-gnu (didn’t include dump as it was pretty long)

However, dumping the symbols for those files and grep’ing for a symbol g++ could not find shows it is in both the .so and .a variants…
$ nm -DC  /usr/lib/x86_64-linux-gnu/libicuuc.so | grep ucnv_open_52
000000000005f3f0 T ucnv_open_52

$ nm -gC  /usr/lib/x86_64-linux-gnu/libicuuc.a | grep ucnv_open_52
0000000000000d10 T ucnv_open_52
                 U ucnv_open_52
                 U ucnv_open_52
                 U ucnv_open_52
                 U ucnv_open_52
                 U ucnv_open_52
                 U ucnv_open_52
So what did I miss? Why cannot g++ find the symbols for the ICU library?

Thanks again for your help.
Coordinator
Aug 4, 2014 at 4:51 PM
Hi mabgfounder,

Thanks for all the detail in your post! It sounds like your issue is your linking order. You said that your g++ line looks like:
/usr/bin/g++ {application .o files} -o {application name} -rdynamic -licuuc -lssl -lcrypto {locally built boost .a files} -lpthread –pthread
However, because of the way the GNU linker works, you will need to link dependencies AFTER the libraries that depend on them. So try changing your linking line to look like:
/usr/bin/g++ {application .o files} -o {application name} {locally built boost .a files} -rdynamic -licuuc -lssl -lcrypto -lpthread –pthread
For more details on this, you can look at my answer to this previous discussion: https://casablanca.codeplex.com/discussions/542485

I'm 99% sure this is your issue, but if this doesn't fix things, could you please post the full link line?

Sincerely,
roschuma
Aug 4, 2014 at 7:09 PM
Thanks roschuma! That was my problem exactly.

I had a little trouble getting cmake to play along - for the benefit of anyone finding this thread later my fix was simply to add icuuc to the list of target_link_libraries for ${Casablanca_LIBRARY} itself. (in Release/src/CMakeLists.txt). Otherwise CMake kept placing cpprest and boost after the target_link_libraries for my application. After I did this it was easy enough to simply use add_directory to pull in the cpprest dependencies.

Thanks again roschuma for your help!