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

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.

Related

Search order in LD_LIBRARY_PATH

A shared object library required by my program is present in two paths under LD_LIBRARY_PATH, but only one of the two should be loaded by my program because of version compatibility issue. For example, if LD_LIBRARY_PATH is path1:path2 and the shared library libxxx.so is in both path1 and path2, will path1/libxxx.so be loaded or path2/libxxx.so be loaded when I run the program?
Also I would appreciate it if anyone has a better solution than reordering the paths in LD_LIBRARY_PATH. After searching on the internet I saw some solution using rpath but didn't quite understand how that works.
The directories get searched in the order they appear in LD_LIBRARY_PATH.
Keep in mind that the loader also looks elsewhere, not just LD_LIBRARY_PATH, which may or may not be a factor.
Since you asked for a "better solution", here are two:
Get this broken shared library built correctly
There is a well-established mechanism and convention for versioning shared libraries so that different versions of the same shared library get loaded. A program that needs a particular version of a shared library will load the one that it needs.
In fact, it's a safe bet that you already have a bunch of different versions of multiple shared libraries installed, due to applications in your Linux distribution that need different versions of the same shared library.
This is nothing more complicated than not using the same name for incompatible versions of the same shared library. There is a well-defined convention for naming actual shared library filenames, that work together with the linker in order to make this happen (the -soname link option, see your linker documentation for more information).
Don't use LD_LIBRARY_PATH
It is possible to link an executable and embed in the executable itself a pathname to search, first and foremost, for any shared libraries, either before or after LD_LIBRARY_PATH.
Remove all directories from LD_LIBRARY_PATH.
Use the -rpath, with/without --enable-new-dtags or --disable-new-dtags option when linking your executable. The correct set of options depends on your specific details, and specific versions of your linker. See your linker documentation for more information. You mentioned you tried to find information on this in Google, but all that Google will do is, perhaps, refer you to the same documentation that you already have: the manual pages for the linker. That's the best source for complete information on using this or any other linker option.
The best solution depends on your specific circumstances; whether you're building the executable, and/or shared libraries, how easy/hard it is to change whatever you're building; or whether you're not building anything at all, just black boxes that need to be executed.

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

Why explicit parameters for static and dynamic linking

I have mostly worked in Windows, and recently I started working in Linux. I have a doubt. I have used Visual Studio as IDE in Windows and used Makefile in Linux.
There are two types of libraries in Windows (VC++), static library (.lib) and DLL. It is quite obvious (isn't it?) if I link with lib file I am using static linking else dynamic linking.
Now when I use g++ compiler, why I need to explicitly mention -Bstatic/-static or Bdynamic/-dynamic flags. Because if file is .a file then I must be using static -linking and if file is .so I am using dynamic linking.
There are times when you want to "force" the compiler to do what it normally wouldn't. In particularly -static is useful when you are building against a library that may not be installed [or not have the same version installed] on another machine where you want your code to run.
the -Bdynamic is useful if you want to have ONE library linked statically, but not EVERY library that your code uses.
e.g. gcc -o myprog myprog.o -Wl,-Bstatic -lspecial -Wl,-Bdynamic
will link myprog using static linking for libspecial (which may be something that isn't widely distributed, for example something you have built yourself)
For general, local development, you don't need either.
In the GNU toolchain, and other Unix compilers, you generally don't specify the full path to a library; you give the linker a flag such as
-lfoo
and let it figure out whether it should link with libfoo.a, libfoo.so, and where these files are located. When only a static library is available, it will link with that.
So, you don't really need to specify -Bstatic except in a few specific cases. Dynamic linking is the default and if you don't want a custom library to be linked dynamically, then just don't build a .so out of it.
Besides, you can explicitly link with a static library by giving the full filename to the linker
gcc -o some_binary main.o libfoo.a
to get a dynamically linked binary with libfoo statically linked in.
I think you've got it backwards. Whether I'm linking with
a dynamic library or with a static one, under Windows, I need
a .lib file; they just aren't generated in the same manner,
and don't contain the same thing. Under Unix, when I link with
a shared object, I link directly against the .so file, and not
against some additional file generated at the same time.
The options -Bstatic and -Bdynamic only come into play when
both a .so and a .a are present, in the same directory; they
tell the linker which one to choose for libraries specified
using the -l option. In Windows, this situation cannot occur;
since you need a .lib for the .dll, you cannot have a .lib
to be statically linked in the same directory.
Because if file is .a file then I must be using static -linking and if file is .so I am using dynamic linking.
These filename "extensions" are only human conventions — there is no reason that they have to be .a and .so respectively. Quite rightly does GCC not force us into that convention.

Can I bind shared libraries with "gcc -llibnamehere", in addition to static ones?

Two projects:
The loader, a standalone executable (only loads modules)
any module, a shared library (librainbowdash.so) (there can be many modules)
Now, the module is linked with -lpthreads, but I get some weird errors which make me think pthreads is bound as a shared object only, and when the loader loads a module pthreads are not being loaded. (debugging with GDB is impossible, that kind of errors).
I thought the -l switch only allows static libraries? Does it? Doesn't it?
-l specifies library names. It is up to the linker to resolve the library names into static libraries or shared objects to be linked against as appropriate. And it is the loader's job to load any shared libraries used.
If you look in the ld and gcc manpages, it is possible to define 'option groups', I might be a bit rusty, but it should go something like
gcc -o yourprog -Wl,-Bstatic yourprog.c -lstatic_lib -Wl,-Bdynamic -ldynamic_lib
The exact incantation is probably wrong.
From experience, passing the full path of the static library has proven to be much less of a headache than figuring out the exact form of the above mentioned incantation.
That being said, I doubt you would gain much benefit by statically linking pthreads.
I think you might also use
gcc -pthread ...
as well.
Using a simple -static will make the output and all its dependencies static. This is probably not what you want.
It might be that your shared library points to lpthread in a wrong location. Using ldd tool e.g., ldd libfoo.so is often a very effective way to find such linking problems.

Linux C++ linker /usr/bin/ld

I wrote a small application on Redhat Linux 6 using g++ 4.4.6. After compilation, I received an error
/usr/bin/ld: cannot find -lcrypto
I did a search for the crypto library and find them here,
[root#STL-DUNKEL01 bin]# find / -name libcrypto*
/usr/lib64/libcrypto.so.0.9.8e
/usr/lib64/libcrypto.so.10
/usr/lib64/libcrypto.so.6
/usr/lib64/libcrypto.so.1.0.0
My question is whether the compilation error is caused by /usr/bin/ld not having /usr/lib64/ in the search path? If yes, how can I add it?
Thanks.
No, you have likely incorrectly diagnosed the cause.
You need a libcrypto.so to link against. This is usually a symlink to one of the actual libraries, whose soname (libcrypto.so.??) will be embedded into the binary. Only that library is needed at runtime, but the symlink is necessary to compile.
See Diego E. Pettenò: Linkers and names for more details.
You have to add -L/usr/lib64 when calling gcc or ld.
Note, you can specify LD_LIBRARY_PATH as well/instead, but it is considered harmful to do so. (The link mentions Solaris specifically, but the issues apply to other OSs as well.)
Quote:
LD_LIBRARY_PATH is used in preference to any run time or default system linker path. If (God forbid) you had it set to something like /dcs/spod/baduser/lib, if there was a hacked version of libc in that directory (for example) your account could be compromised. It is for this reason that set-uid programs completely ignore LD_LIBRARY_PATH.
When code is compiled and depends on this to work, it can cause confusion where different versions of a library are installed in different directories, for example there is a libtiff in /usr/openwin/lib and /usr/local/lib. In this case, the former library is an older one used by some programs that come with Solaris.
Sometimes when using precompiled binaries they may have been built with 3rd party libraries in specific locations; ideally code should either ship with the libraries and install into a certain location or link the code as a pre-installation step. Solaris 7 introduces $ORIGIN which allows for a relative library location to be specified at run time (see the Solaris Linker and Libraries Guide). The alternative is to set LD_LIBRARY_PATH on a per-program basis, either as a wrapper program to the real program or a shell alias. Note however, that LD_LIBRARY_PATH may be inherited by programs called by the wrapped one ...
Add the directory to /etc/ld.so.conf
then run "sudo ldconfig" to make the changes take effect.
You can provide the directories to search for the libraries in as a parameter to gcc like so -L<directory_to_search_in>. And note that there can be multiple parameters to -L. Also, are you trying to build a 32-bit application or a 64-bit one?