How to link to the libabc.a instead of libabc.so? - build

In the book Autotools: A Practioner's Guide to GNU Autoconf, Automake, and Libtool, chapter 6 (building libraries with libtool), an example of linking library is given.
In the example, a library libjupiter.so is linked to another library libjupcommon.a. The first attempt fails because libjupiter.so needs PIC, but libjupcommon.a is not. The author adds libjupcommon_a_CFLAGS = -fPIC to fix it. It gets much better, but the warning of 'Linking the shared library libjupiter.la against the static library ../common/libjupcommon.a is not portable!' appears.
Therefore the author modifies the Makefile.am's again, using libtool to build libjupcommon.la. The libjupiter links to the libjupcommon.la.
Like this:
noinst_LTLIBRARIES = libjupcommon.la
libjupcommon_la_SOURCES = jupcommon.h print.c
and
...
libjupiter_la_LIBADD = ../common/libjupcommon.la
This time everything's OK.
Now, my problem:
I have a library needs another library, just like libjupiter needs libjupcommon. The difference is my libjupcommon is from another project and installed into the system. It is not a noinst_LTLIBRARIES. Both .so and .a version exist. When I try to link the libjupcommon.la like the example shows, the .so is chosen, but I don't want a dynamic linking relationship. I want to link to the .a, like the example in the book.
Linking to .a explicitly (by using _LIBADD=the .a file) gives a usable library, but the warning of '... not portable' is given.
What's the proper way to achieve linking to the .a in this case?
PS: Download the example from the book's official site. In autotools/book/jupiter-libtool-ch6/common, modify the Makefile.am's noinst_LTLIBRARIES to lib_LTLIBRARIES should be a close mimic to my problem.

There's a couple things you could try. You could try running configure with the --disable-shared option to turn off compilation of shared libs (and add the static lib to libfoo_LIBADD again). You could try adding -static to libfoo_LDFLAGS to get libtool to build it statically (again with the static lib added to libfoo_LIBADD).
EDIT: Since both static and shared libs are needed the above won't work.
Try adding:
AC_CHECK_LIB([abc],[some_function_in_libabc])
to configure.ac.

You can force static linking to one library (while keeping all other links shared) using this construct:
-Wl,-Bstatic -Wl,-whole-archive -Xlinker -l$1 -Wl,-no-whole-archive -Wl,-Bdynamic
Replace $1 above with your library name.
Explanation: Most of the above monstrosity is to get around the fact that libtool will re-arrange the command line arguments, ever so helpfully. Using -Xlinker will force libtool to ignore the -l$1 and not re-arrange it. The -Wl,-Bstatic tells the linker to link all following libraries as static. -Wl,-Bdynamic switches back to dynamic linking for further libraries.

Related

g++ unable to link static version of shared objects

I want to hide as much information as I can from ldd, so I'm learning how to statically link in libraries instead of dynamically linking them. I've read from another stackoverflow post that the correct syntax is
g++ -ldynamiclib -o exe files.cpp staticlib.a
Thus, my current compilation code looks like this:
STATIC_LIB=""
STATIC_LIB="$STATIC_LIB ${PATH}/libcrypto.a"
STATIC_LIB="$STATIC_LIB ${PATH}/libdl-2.5.so" // I couldn't find the .a version for this, so I tried doing it this way, and have also tried doing just -ldl
STATIC_LIB="$STATIC_LIB ${PATH}/libstdc++.a"
STATIC_LIB="$STATIC_LIB ${PATH}/libgcc.a"
STATIC_LIB="$STATIC_LIB ${PATH}/libc.a"
g++ -g -I${INCLUDE_PATH} -o executable file1.cpp file2.cpp $STATIC_LIB
I've confirmed with ldd that this way works for libcrypto, as it is an external library that I brought in. However, this does not work at all for everything else, and I can still see them being listed when I use ldd. Does anyone knows the correct way of doing this?
P.S. I've also tried several other alternatives such as including -static, or using -Wl,-Bstatic, and I couldn't get either of those to work. Not sure if it's my syntax or if it's just not possible.
Those libraries libstdc++, libgcc and libc are special in that they're very fundamental to the running of any program compiled with gcc. Special gcc options exist if you want to link them statically, namely -static-libstdc++ and -static-libgcc.
Note that you should really know what you're doing if you choose these options. It can create portability problems for your program, many of which express themselves in unintuitive ways.

How dynamic linking works, its usage and how and why you would make a dylib

I have read several posts on stack overflow and read about dynamic linking online. And this is what I have taken away from all those readings -
Dynamic linking is an optimization technique that was employed to take full advantage of the virtual memory of the system. One process can share its pages with other processes. For example the libc++ needs to be linked with all C++ programs but instead of copying over the executable to every process, it can be linked dynamically with many processes via shared virtual pages.
However this leads me to the following questions
When a C++ program is compiled. It needs to have references to the C++ library functions and code (say for example the code of the thread library). How does the compiler make the executable have these references? Does this not result in a circular dependency between the compiler and the operating system? Since the compiler has to make a reference to the dynamic library in the executable.
How and when would you use a dynamic library? How do you make one? What is the specific compiling command that is used to produce such a file from a standard *.cpp file?
Usually when I install a library, there is a lib/ directory with *.a files and *.dylib (on mac-OSX) files. How do I know which ones to link to statically as I would with a regular *.o file and which ones are supposed to be dynamically linked with? I am assuming the *.dylib files are dynamic libraries. Which compiler flag would one use to link to these?
What are the -L and -l flags for? What does it mean to specify for example a -lusb flag on the command line?
If you feel like this question is asking too many things at once, please let me know. I would be completely ok with splitting this question up into multiple ones. I just ask them together because I feel like the answer to one question leads to another.
When a C++ program is compiled. It needs to have references to the C++
library functions and code (say for example the code for the library).
Assume we have a hypothetical shared library called libdyno.so. You'll eventually be able to peek inside it using using objdump or nm.
objdump --syms libdyno.so
You can do this today on your system with any shared library. objdump on a MAC is called gobjdump and comes with brew in the binutils package. Try this on a mac...
gobjdump --syms /usr/lib/libz.dylib
You can now see that the symbols are contained in the shared object. When you link with the shared object you typically use something like
g++ -Wall -g -pedantic -ldyno DynoLib_main.cpp -o dyno_main
Note the -ldyno in that command. This is telling the compiler (really the linker ld) to look for a shared object file called libdyno.so wherever it normally looks for them. Once it finds that object it can then find the symbols it needs. There's no circular dependency because you the developer asked for the dynamic library to be loaded by specifying the -l flag.
How and when would you use a dynamic library? How do you make one? As in what
is the specific compiling command that is used to produce such a file from a
standard .cpp file
Create a file called DynoLib.cpp
#include "DynoLib.h"
DynamicLib::DynamicLib() {}
int DynamicLib::square(int a) {
return a * a;
}
Create a file called DynoLib.h
#ifndef DYNOLIB_H
#define DYNOLIB_H
class DynamicLib {
public:
DynamicLib();
int square(int a);
};
#endif
Compile them to be a shared library as follows. This is linux specific...
g++ -Wall -g -pedantic -shared -std=c++11 DynoLib.cpp -o libdyno.so
You can now inspect this object using the command I gave earlier ie
objdump --syms libdyno.so
Now create a file called DynoLib_main.cpp that will be linked with libdyno.so and use the function we just defined in it.
#include "DynoLib.h"
#include <iostream>
using namespace std;
int main(void) {
DynamicLib *lib = new DynamicLib();
std::cout << "Square " << lib->square(1729) << std::endl;
return 1;
}
Compile it as follows
g++ -Wall -g -pedantic -L. -ldyno DynoLib_main.cpp -o dyno_main
./dyno_main
Square 2989441
You can also have a look at the main binary using nm. In the following I'm seeing if there is anything with the string square in it ie is the symbol I need from libdyno.so in any way referenced in my binary.
nm dyno_runner |grep square
U _ZN10DynamicLib6squareEi
The answer is yes. The uppercase U means undefined but this is the symbol name for our square method in the DynamicLib Class that we created earlier. The odd looking name is due to name mangling which is it's own topic.
How do I know which ones to link to statically as I would with a regular
.o file and which ones are supposed to be dynamically linked with?
You don't need to know. You specify what you want to link with and let the compiler (and linker etc) do the work. Note the -l flag names the library and the -L tells it where to look. There's a decent write up on how the compiler finds thing here
gcc Linkage option -L: Alternative ways how to specify the path to the dynamic library
Or have a look at man ld.
What are the -L and -l flags for? What does it mean to specify
for example a -lusb flag on the command line?
See the above link. This is from man ld..
-L searchdir
Add path searchdir to the list of paths that ld will search for
archive libraries and ld control scripts. You may use this option any
number of times. The directories are searched in the order in which
they are specified on the command line. Directories specified on the
command line are searched before the default directories. All -L
options apply to all -l options, regardless of the order in which the
options appear. -L options do not affect how ld searches for a linker
script unless -T option is specified.`
If you managed to get here it pays dividends to learn about the linker ie ld. It plays an important job and is the source of a ton of confusion because most people start out dealing with a compiler and think that compiler == linker and this is not true.
The main difference is that you include static linked libraries with your app. They are linked when you build your app. Dynamic libraries are linked at run time, so you do not need to include them with your app. These days dynamic libraries are used to reduce the size of apps by having many dynamic libraries on everyone's computer.
Dynamic libraries also allow users to update libraries without re-building the client apps. If a bug is found in a library that you use in your app and it is statically linked, you will have to rebuild your app and re-issue it to all your users. If a bug is found in a dynamically linked library, all your users just need to update their libraries and your app does not need an update.

How to use automake to link two libs, one dynamically and the other statically?

Suppose I want to link the foo application with the bar and baz libs. Both support pkg-config and provide .pc files. The bar lib I want to link dynamically and the baz library I want to link statically. How can I achieve this with automake?
My current setup links both of them dinamycally and looks like this:
foo_SOURCES = main.c
foo_LDADD = #BAR_LIBS# #BAZ_LIBS#
foo_CFLAGS = #BAR_CFLAGS# #BAZ_CFLAGS#
There is no (justifiable) reason to not use shared libraries when they are available. automake provides no specific support here; there's is the -Wl,-Bstatic ${FOO_LIBS} -Wl,-Bdynamic hack, but it is what it is - a hack, and there is no guarantee it will work at all times.

"lib" Prefix on Libraries

From http://www.adp-gmbh.ch/cpp/gcc/create_lib.html:
Note: the library must start with the three letters lib and have the suffix .a.
Is this an operating system convention, or a gcc/ar quirk? Xcode seems to be able to create libraries without the prefix. What's it doing differently?
You can name a library whatever you want, but if you want gcc's -l flag to find the right one, you need to name it the way that link describes. For example:
gcc -o myapp myapp.c -lm
Will compile myapp.c, link the resulting object with libm.a, and output an executable called myapp. These days, there might be a more complicated search path involving dynamic library names, etc., but you should get the basic idea from this example.
From the gcc man page:
-l library ...
... surrounds library with lib and .a and searches several directories.

linking problem on linux (can't find the name of the appropriate library)

I trying to use a library (http://code.google.com/p/qxmpp/) but I can't find the name of the library to link it to. I want to understand how can you find out the name of the library to use in the linking parameters.
Looks like that is a source archive only -- no binaries included. Have you built the library from it? Where did the build process put it? /usr/lib or /usr/local/lib would be usual suspects, but read the build and install documentation in the package.
Given that the name of the library is libqxmpp.a and (as you mention in a comment) that it's in the usual lib directory (/usr/lib), you can easily deduce the proper options:
gcc and other compilers have an -l switch that finds the library based on the name you give it. By default, it will look in the paths given to GCC at build time (usually /lib and /usr/lib) and any others given to /etc/ld.so.conf. If you add the switch -lX, it will prepend lib to the name and by default append .so and look for any file that looks like libX.so in any of the lib directories it knows about.
Working backwards, we can deduce that invoking gcc with -lqxmpp will look for a file named libqxmpp.so (actually, it looks for a few other names, too.) How do we get it to look for a .a file? Those archives (man ar) are static libraries, so pass the -static switch just before the library:
gcc -o progname your.o program.o files.o -static -lqxmpp
(If you need to link to other libraries, you may need to add -Wl,-dynamic for them if you don't want them statically linked or if static libs aren't available.)
Alternatively, you can do this if you know the full path:
gcc -o progname your.o program.o files.o /usr/lib/libqxmpp.a
... And it works just the same.