Where does the linker get library names? - c++

I'm kind of new to developing, and I am wondering how the linker is getting the library names?
for example, in the linker additions lines, when i wanted to add support for libxml2, the command was -lxml2. yet when i wanted to add the lib for xmlsec, it was -lxmlsec1. when i wanted to add openssl, i needed both a -lcrypto and a -lssl.
can someone explain to me where these library names come from? it doesn't seem very intuitive. if i want to include a library, how am i supposed to find what -l command to use?
this is on a ubuntu system developing a C++ program.

The 'regular' linker is dumbest program I know of :) When it comes for libraries, it follows a very simple set of rules. First, for every -l rule it adds lib in front and .a in the end to form a static library name. It also forms a dynamic library name by adding .so instead of .a. For every -I rule it adds specified path to it's library search paths.
So when it sees a -l rule, and looks into all library paths which were set by -L rules (in the order those appeared in the command line) and sees if it can find dynamic or static library at this location (if it can see both, it picks one depending on -B rule).
This was a generic introduction. Now, to your particular question, in order to check which library you should include, you should read documentation. I always tells you which -l rules you'd need.

Related

Locating "undefined" references in a C/C++ Project

I am building a C++ project on my Ubuntu 64bit system using a provided Makefile, and this project also provides an API library for developers.
The compilation was successful, no errors at all, but when I try to include in my files the API libraries provided in the "api" folder, then g++ complains about undefined references.
It is not a problem about dependencies (I already built the project succesfully), in fact the missing references are about classes and functions provided by the project, but they are in some specific (sub-)folders (I don't know which ones!), I guess in some .so files, and g++ is not finding them, probably because it does not know they are in those specific subfolders.
It is not the first time this happens when trying to use APIs from any project, then I think I am missing something or I am doing something wrong in general when trying to use the libraries provided in a project.
In particular, the main problem is that I don't know how to tell the compiler where some classes or data structures are declared, and moreover I don't know how to locate them in order to know where they are.
Usually, a workaround I use to avoid this problem is to run make install (as root or using sudo) so that libraries and APIs are installed in standard folders (like /usr/include or /usr/lib) and if I do this thend I can include the API libraries using #include <library>, but in this last case it didn't work either, because perhaps some required files containing the not found classes/structures are not properly installed in the right folders in the system.
Another workaround I used sometimes is to try to put all the project files in the same folder instead of using the project folder structure, but clearly this is not good! :-)
But I noticed that several other people managed to use the APIs, then apparently they know some way of finding the files containing the "undefined" references and including them in the compilation.
Then my general question is: given a "classic" C++ project based on "Makefile" files and with usual folder names like src, lib, build, bin, etc., if I want to write C++ files using the libraries provided by the project, but the compiler complains about undefined references, how can I find the files (.so or .o or .cpp) containing such references? Is there any tool to find them? And how can I tell the compiler where they are? Should I use some command-line option for g++ or should I use the #include macro in some smart way?
PS I also tried to use the pkc-config linux tool to get right options to use for compilation and they were available, but the compiler still complains about the undefined references.
Some more degails about the project i tried:
For interested people a link to the project is below:
https://github.com/dreal/dreal3
And instructions on how to build it:
http://dreal.github.io/download/
Look into the -rpath linker option - specifically with the "$ORIGIN" argument. That lets you find libraries relative to your executable location so you don't have to install them to the standard locations but just need to put them somewhere known, relative to the executable. That should help you with one piece of the puzzle.
Note: -Wl, can be used to pass arguments to the linker via g++.
As for pointing the compiler/linker at a library so it can resolve undefined references by using that library, use the -l (that's lowercase L) option to specify the library name and -L to specify directories to search for libraries.
As for looking into a library (.so) file to see what symbols are in there, you have a few tools at your disposal: objdump, nm, readelf and objcopy.

Locating which methods in C/C++ libraries to link against on *NIX

In the past, what has worked for me when I'm very lazy (for both Linux and Windows) was to just boldly use "grep -r" in each possible lib paths (i.e. /lib, /lib64, /usr/lib, etc) which I know the libs resides at, to see if I can guess which libs are the probable candidates to link against and make sure to add the "-L" paths and "-l" lib files.
For most of MSDN documented libraries, usually, Microsoft is nice enough to indicate which DLL's to link against, but for Linux it's a little more work (i.e. I need to possibly use search engine on multiple sites). For example, let's take ntohl(), which MSDN kindly shows static .lib and dynamic .dll files I can link against (it would be nice to know the paths, but that I can 'find' later). If I 'man 3 ntohl' for example, the best it can tell me is that I need to #include arpa/inet.h, but I'd still have to find out (for me, grep) which lib to link against (perhaps ntohl() is not a good example since it's usually part of libc.so, but please bear with me, the point is, I had to grep to find out it's on libc.so).
Q: What are the right (practiced) ways to locate methods of C/C++ libraries that will accurately tell me which binary files has the implementations for the method I want to link against?
NOTE: Please disregard the versions (i.e. libc-2.19.so vs libc-xx.so) and arch/target (i386-linux-gnu vs x86_64-linux-gnu), which is not as important as locating the correct lib files which has the actual implementations for linking.
Typically, unless otherwise specified, all functions come from the default C or C++ library that the compiler will link with by default.
Otherwise, the expectation is that the manual page for the library function will explicitly indicate that a non-default library must be linked with. For example, the manual page for pthread_create(3) tells you that linking with -lpthread is required.
Of course, one has to be dependent on third party libraries providing adequate documentation, either by supplying traditional manual pages, with linking instructions of this manner, or via some other documentation. Quite often, the library's website will have documentation that explains how to use the library.
Linux is not controlled by a monolithic entity that imposes uniform documentation requirements.
Many packages use pkg-config or their own version like mysql_config.
You can add the flags to the compiler using those tools:
g++ $(pkg-config somelib --cflags) -o prog prog.cpp $(pkg-config somelib --libs)
Otherwise I use the package manager to tell be what libraries are contained in a given package and where they get installed to.
To discover what libraries are available through pkg-config use:
pkg-config --list-all
Use man pkg-config for more information.

How to prefer one library location vs. another one with Clang?

I have a system-wide libc++.so in /usr/lib64. I want to link my binary against another libc++.so which is located somewhere else, say, in $HOME/.local/lib. Also, I want to be able to find all other libraries the same way as before, assuming that $HOME/.local/lib contains only libc++.so.
I'm trying to do this like: clang++ -L$HOME/.local/lib -lc++, but the compiler still links against /usr/lib64/libc++.so.
How to force the compiler (or linker) to link against a specific library location?
-L adds the directory to the search path used by the linker. This has no effect on the search paths used at runtime. At runtime, the search paths, in order, are:
The environment variable LD_LIBRARY_PATH
rpath specified in the executable
System library path
While you can achieve what you want by specifying the environment variable LD_LIBRARY_PATH=$HOME/.local/lib, it is a bad solution since it modifies the search paths of all executables. Specifying the rpath is a much cleaner solution since it only affects the behaviour of your executable. You can do this through the linker option of your toolchain, which is likely -rpath. So the command would be clang++ -rpath $HOME/.local/lib -lc++.

What is the difference between LDADD and LIBADD?

I'm trying to setup an automake project that uses a mix of libtool libraries and exectuables, and I'm having a hard time grokking the automake documentation, esp. as relates to telling the compiler to link against.
So can someone explain the differences between LDADD and LIBADD?
Things like:
when is one used over the other,
which one takes -lname_of_library style values vs. direct filenames,
etc.
Whenever I try to read the relevant documentation, it seems like it assumes that I know things that I don't.
Use the LIBADD primary for libraries, and LDADD for executables. If you were building a libtool library libfoo.la, that depended on another library libbar.la, you would use:
libfoo_la_LIBADD = libbar.la
If you had other non-libtool libraries, you would also add these with -L and -l options:
libfoo_la_LIBADD = libbar.la -L/opt/local/lib -lpng
Typically, you would use the configure script to find these extra libraries, and use AC_SUBST to pass them with:
libfoo_la_LIBADD = libbar.la $(EXTRA_FOO_LIBS)
For a program, just use LDADD :
myprog_LDADD = libfoo.la # links libfoo, libbar, and libpng to myprog.
Sometimes the boundaries are a bit vague. $(EXTRA_FOO_LIBS) could have been added to myprog_LDADD. Adding dependencies to a libtool (.la) library, and using libtool do all the platform-specific linker magic, is usually the best approach. It keeps all the linker metadata in the one place.
As mentioned in one of the books, LDADD is ADDitional linker(LD) items - i.e. items that are added when performing linking. This would be, for example, when producing programs. LDADD can specify:
libtool files e.g. lib/libfudge.la
libraries e.g. -lm, or
full paths to libraries e.g. /lib/libmagicalwonderland.a
link flags & libraries e.g. -L/opt/lib -lmagical
They are in order of preference - Using the last two is just asking for trouble as they're pointing at things that may or may not be present.
LIBADD is to specify ADDitional LIBraries to use. This is used when building a library to specify that additional libraries are needed in order to build or make use of the library. You'll see it specified as something like libfred_la_LIBADD =. It can be used to specify libtool libraries, or system libraries and will place these libraries into the resulting libtool .la for the library so when it comes to linking against the library you get all the appropriate libraries brought along.
You should only specify libraries to link, so, for example, my library libfred.la depends on some math routines i.e. it depends on libm. When I'm specifying the additional libraries for the library, I state:
libfred_la_LIBADD = -lm
This dependency is encoded when I build the library, and gets passed on to consumers of the library as well.
The rule of thumb is:
LIBADD for things that are being added to a library
LDADD for things that are being added to a program

Issues with linking library C++

My problem is I am not able to include a library into my current project. [The way to include a library in netbeans into a project is to link it via linker to the project]. However, in my current project(which is written by another programmer who left the organization) the option of linker is not appearing. I have attached a screenshot. I am faced with the issue that the option of linking the library via linker to my current project is not appearing in IDE. Can someone please please help me out. I'll be highly thankful to you for the same.
Please guide me as to how should I link the library to my project. I have really spent a lot of days doing it but I did not succeed.
Assuming you are only interesting in libspatialindex:
Make sure you have the appropriate files installed: try a locate libspatialindex and see where it is installed. You could have a *.a, *.so or similar extension. Note the path.
Go into your project root directory, i.e: /home/keira/netbeans/projects/myproject
Try: gcc -i main.cpp -L/usr/lib/ -lspatialindex -o myfile
Replace the -L/usr/lib with the actual location where you know the library is at.
The cxx link flag is usually the name of the library with an -l prefix. If for example the name found in the system is libspatialindex.so then its a good bet to try with -lspatialindex.
There is a way to find the actual flags on Debian & Ubuntu systems but I cannot atm remember it. Alternatively you can always look on google or read the library documentation.
When you usually see linker errors with undefined functions, etc, it means you're not linking, provided you have included the headers and they are found.
Now for Netbeans, I assume there is the option of passing extra arguments to the compiler. In this case, all you need is the -lspatialindex flag, provided Netbeans knows where to find the library and the headers. That is how it works in KDevelop and other IDE's I have used.
Alternatively if you want more control and more automation, you may want use a tool like cmake.