Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there an intelligent way to know the name of the library to link to at compile time? (Linux/Kubuntu)

Please bear with me. I really want to know as I am curious about the answer:

Is there an intelligent way to know the name of the library to link to at compile time?

Allow me to give you an example that illustrates perfectly the reason for my question.

I am a C++ newbie. I am learning about compiling, linking and libraries like boost. I just discovered boost/filesystem and wanted to try it. Having had troubles compiling, I used the following minimalist code:


// file boost_example.cpp
 #include "boost/filesystem.hpp"
#include <iostream>

int main() { std::cout<<"Hello"; return 0; }

I tried to compile it, but being a newbie, I made a newbie mistake: I forgot to link to the proper library!

     g++ boost_example.cpp -o run

To be precise, I experienced the problem explained in this chapter of this fine book.
I knew I had boost installed (I was told to install it to compile another project). I tried to copy from the Makefile of that other project, but the following didn't work:
     g++ boost_example.cpp -o run -lbooster
     g++ boost_example.cpp -o run -lboost
Trying to make an educated guess from the #include line in the code, I tried the following to no avail:
     g++ boost_example.cpp -o run -lboost_filesystem
By that time, I had started to search the web frantically. I hate search engines because most of the time, you don't find what you're looking. I found the following but they didn't help but to waste my time:
Boost library link problem under kubuntu
C++/Boost linker errors

Since I am a RTFM kind of guy, I had actually checked the official documentation for the library I wanted to use: http://www.boost.org/doc/libs/1_43_0/libs/filesystem/doc/index.htm but I didn't find any compile information.

At some stage, I got inspired to check what I had actually installed on my system:

$ locate boost_file
/usr/lib/libboost_filesystem-mt.a
/usr/lib/libboost_filesystem-mt.so
/usr/lib/libboost_filesystem-mt.so.1.38.0
Thus, I found the proper name of the library to link. The following worked:
     g++ boost_example.cpp -o run -lboost_filesystem-mt

Now, beside using (possibly) intelligent guess work and searching the web, is there a more intelligent way to find the name of the library to link to? I would never have guessed the library name boost_filesystem-mt given the header "boost/filesystem.hpp".

What's worse: boost_filesystem-mt is not mentioned anywhere on the official site! (I'm guessing it's distro/packaging dependent).

Again, I always make a point of RTFM before asking a question, and I found this chapter of the aforementioned book, so I checked what I could find on my system at /usr/lib/:

$ ls /usr/lib/boost
/usr/lib/libboost_date_time-mt.a           /usr/lib/libboost_prg_exec_monitor-mt.so.1.38.0
/usr/lib/libboost_date_time-mt.so          /usr/lib/libboost_program_options-mt.a
/usr/lib/libboost_date_time-mt.so.1.38.0   /usr/lib/libboost_program_options-mt.so
/usr/lib/libbooster.a                      /usr/lib/libboost_program_options-mt.so.1.38.0
/usr/lib/libbooster.so                     /usr/lib/libboost_python-mt.a
/usr/lib/libbooster.so.0                   /usr/lib/libboost_python-mt-py25.a
/usr/lib/libbooster.so.0.0.0               /usr/lib/libboost_python-mt-py25.so
/usr/lib/libboost_filesystem-mt.a          /usr/lib/libboost_python-mt-py25.so.1.38.0
/usr/lib/libboost_filesystem-mt.so         /usr/lib/libboost_python-mt-py26.a
/usr/lib/libboost_filesystem-mt.so.1.38.0  /usr/lib/libboost_python-mt-py26.so
/usr/lib/libboost_graph-mt.a               /usr/lib/libboost_python-mt-py26.so.1.38.0
/usr/lib/libboost_graph-mt.so              /usr/lib/libboost_python-mt.so
/usr/lib/libboost_graph-mt.so.1.38.0       /usr/lib/libboost_regex-mt.a
/usr/lib/libboost_iostreams-mt.a           /usr/lib/libboost_regex-mt.so
/usr/lib/libboost_iostreams-mt.so          /usr/lib/libboost_regex-mt.so.1.38.0
/usr/lib/libboost_iostreams-mt.so.1.38.0   /usr/lib/libboost_serialization-mt.a
/usr/lib/libboost_math_c99f-mt.a           /usr/lib/libboost_serialization-mt.so
/usr/lib/libboost_math_c99f-mt.so          /usr/lib/libboost_serialization-mt.so.1.38.0
/usr/lib/libboost_math_c99f-mt.so.1.38.0   /usr/lib/libboost_signals-mt.a
/usr/lib/libboost_math_c99l-mt.a           /usr/lib/libboost_signals-mt.so
/usr/lib/libboost_math_c99l-mt.so          /usr/lib/libboost_signals-mt.so.1.38.0
/usr/lib/libboost_math_c99l-mt.so.1.38.0   /usr/lib/libboost_system-mt.a
/usr/lib/libboost_math_c99-mt.a            /usr/lib/libboost_system-mt.so
/usr/lib/libboost_math_c99-mt.so           /usr/lib/libboost_system-mt.so.1.38.0
/usr/lib/libboost_math_c99-mt.so.1.38.0    /usr/lib/libboost_thread-mt.a
/usr/lib/libboost_math_tr1f-mt.a           /usr/lib/libboost_thread-mt.so
/usr/lib/libboost_math_tr1f-mt.so          /usr/lib/libboost_thread-mt.so.1.38.0
/usr/lib/libboost_math_tr1f-mt.so.1.38.0   /usr/lib/libboost_unit_test_framework-mt.a
/usr/lib/libboost_math_tr1l-mt.a           /usr/lib/libboost_unit_test_framework-mt.so
/usr/lib/libboost_math_tr1l-mt.so          /usr/lib/libboost_unit_test_framework-mt.so.1.38.0
/usr/lib/libboost_math_tr1l-mt.so.1.38.0   /usr/lib/libboost_wave-mt.a
/usr/lib/libboost_math_tr1-mt.a            /usr/lib/libboost_wave-mt.so
/usr/lib/libboost_math_tr1-mt.so           /usr/lib/libboost_wave-mt.so.1.38.0
/usr/lib/libboost_math_tr1-mt.so.1.38.0    /usr/lib/libboost_wserialization-mt.a
/usr/lib/libboost_prg_exec_monitor-mt.a    /usr/lib/libboost_wserialization-mt.so
/usr/lib/libboost_prg_exec_monitor-mt.so   /usr/lib/libboost_wserialization-mt.so.1.38.0

And now I am scratching my head very hard, because I really don't know how to correlate the above to the list of boost libraries.

I apologize for this long-winded example, but it perfectly illustrate my problem:

Beside guesswork, searching the web, asking other people, trial and error, etc... is there a more intelligent way to find the name of the library one should link to? Aren't those kind of things supposed to be documented somewhere?

I'm certainly interested in knowing the answer as far as boost is concerned, but my question is more generic and is applicable to any library.

Incidentally, I have a very similar question regarding the name of linux packages (be they .deb or .rpm). If I am told that to compile such or such software I need, say, PRCE or FooBar, how do I know precisely the name of the package to install? I know how to user apt-cache (for Kubuntu debs) but some package naming are not intuitive and I often end up installing packages I don't really need...

like image 987
augustin Avatar asked Aug 12 '10 11:08

augustin


People also ask

What is Dynamic Linking in Linux?

Dynamic linking is the most common method, especially on Linux systems. Dynamic linking keeps libraries modular, so just one library can be shared between any number of applications. Modularity also allows a shared library to be updated independently of the applications that rely upon it.

Where are shared libraries located in Linux?

The Filesystem Hierarchy Standard describes the filesystem conventions of a Linux system. In this standard, folders /lib, /usr/lib and /usr/local/lib are the default folders to store shared libraries.

How are shared libraries loaded in Linux?

Shared libraries are the most common way to manage dependencies on Linux systems. These shared resources are loaded into memory before the application starts, and when several processes require the same library, it will be loaded only once on the system. This feature saves on memory usage by the application.


2 Answers

There is a brute-force method I sometimes use, but you do have to know what directories to look in for the library you need (/lib, /usr/lib and /usr/local/lib are the usual suspects). I've created a shell script I call "gnm," (short for "grep nm," the two utilities it uses) with the below contents. If you create such a text file, remember to make it executable (chmod +x gnm).

#!/bin/sh
if [ $# -lt 2 ] ; then
  echo Usage: $0 pattern file[s]
  exit
fi
pattern=$1
shift
while [ $# -gt 0 ] ; do
  nm $1 | grep $pattern > /dev/null
  if [ $? -eq 0 ] ; then
    echo $1
  fi
  shift
done

When I'm searching for a library that defines a particular symbol, I issue a command something like:

gnm symbol /usr/lib/*.a 

For example, the source you mentioned gives me the following link errors:

boost_example.cpp:(.text+0x38): undefined reference to `boost::system::get_system_category()'
boost_example.cpp:(.text+0x44): undefined reference to `boost::system::get_generic_category()'
boost_example.cpp:(.text+0x50): undefined reference to `boost::system::get_generic_category()'
boost_example.cpp:(.text+0x5c): undefined reference to `boost::system::get_generic_category()'
boost_example.cpp:(.text+0x68): undefined reference to `boost::system::get_system_category()'

so I use the command:

gnm get_system_category /usr/lib/*.a

which reports:

/usr/lib/libboost_filesystem.a
/usr/lib/libboost_system.a

Trying the first of these results in the same errors, but the second one works:

g++ boost_example.cpp -lboost_system -o run

I don't know why I needed the system library where you needed filesystem; maybe different versions of Boost.

like image 78
Dave Taflin Avatar answered Oct 13 '22 22:10

Dave Taflin


I just found the most intelligent and most official way (on my system) to figure out the link flag. What follows is only valid for boost on a Debian or Debian derivative distribution (like Kubuntu in my case). The other replies might be more generic for any library on any system.

Depending on the boost version installed, you may have the following file on your Debian-like distribution:
/usr/share/doc/libboost1.38-doc/README.Debian
part of which reads:

--------

The following table shows which components use a library (shared or
static) and the corresponding "-l" flag.  Note that only the
multithreaded version of the libraries is shipped.

  Component              Link Flag                    Library Type
  ---------              ---------                    ------------
  Boost.Date_Time        -lboost_date_time-mt           static  shared
  Boost.Filesystem       -lboost_filesystem-mt          static  shared
  Boost.Graph            -lboost_graph-mt               static  shared
  Boost.IOStreams        -lboost_iostreams-mt           static  shared
  Boost.Math             -lboost_math_c99-mt            static  shared
                         -lboost_math_c99f-mt           static  shared
                         -lboost_math_c99l-mt           static  shared
  Boost.MPI              -lboost_mpi-mt                 static  shared
  Boost.Program_options  -lboost_program_options-mt     static  shared
  Boost.Python           -lboost_python-mt-py24         static  shared
                         -lboost_python-mt-py25         static  shared
  Boost.Regex            -lboost_regex-mt               static  shared
  Boost.Serialization    -lboost_serialization-mt       static  shared
                         -lboost_wserialization-mt      static  shared
  Boost.Signals          -lboost_signals-mt             static  shared
  Boost.System           -lboost_system-mt              static  shared
  Boost.Test             -lboost_prg_exec_monitor-mt    static  shared
                         -lboost_unit_test_framework-mt static  shared
  Boost.Thread           -lboost_thread-mt              static  shared
  Boost.Wave             -lboost_wave-mt                static  shared


One only had to find the proper place for the documentation!

like image 29
augustin Avatar answered Oct 13 '22 20:10

augustin