Automake and standard shared libraries - shared-libraries

How can I force automake to create a standard shared library, instead of a libtoolized one? Normally, I'd create the abc.so which is referenced with a full path and loaded into the main program. Is there a way to force AM to do the same? If I list it as _LIBRARY, automake complains: 'abc.so' is not a standard library name; did you mean 'libabc.a'
Just to clarify: Yes, I only need .so support - no statics. And yes, I want a custom file name.

libtool is the way to go. If you want a custom name, add the -module option to _LDFLAGS, for example:
plugindir= /some/where
plugin_LTLIBRARIES= abc.la
abc_la_LDFLAGS= -module

Automake does not know how to build a shared library because there is no portable way to do so. If you want a shared library with Automake, you have to use Automake+Libtool. Note that you can easily configure libtool not to build any static library (with LT_INIT([disable-static]) in your configure.ac) by default.

A libtoolized library is a wrapper around one or more standard libraries.
You can find these libraries in ".libs" after running "make", or in "$prefix/lib" after running "make install".
On a Linux machine, you should find eventually a file called "libabc.so".

IIRC, there is nothing special about libraries created with the help of libtool, unless you link against libltdl. If you do not want to use libtool, you have the power to choose and do not care too much about portability, then you are free to use automake without libtool. I would recommend to use the power of libtool instead.
Actually, I do not even know what _LIBRARY is good for, did not found it in the the manual/Linking section.

Related

stack statically link external library on mac

I would really like to create a single binary for my application however it depends on libzmq and I am building on OSX, has anyone managed to get an external library linking correctly on a mac?
I did something similar with lua. My aproach is to pass full path to the static library to ghc. In cabal file:
if os(darwin)
ghc-options: /usr/local/lib/liblua5.1.a
According to documentation ghc will pass it to linker:
Files with other suffixes (or without suffixes) are passed straight to
the linker.
However it doesn't work if the library is used in other package which you depend on. So if you are using e.g. zeromq4-haskell package, then you need to modify it locally.

Explanation sought: libtool, automake, shared libraries (and Fortran)

The problem I had is solved. I'm posting this to solicit an explanation as to why the solution actually works. I've gotten great feedback here before.
I have a legacy code base that used a very simplistic build system, and my project is to migrate that to Autotools for customization and, particularly, building shared libraries. The main library is written in C, but must also be linkable from Fortran (for legacy purposes), and is distributed with some test codes in F77. The authors organized the source code into modules...
src_module1/
src_module2/
...
testc/
testf77/
Their built the library lib/libmain.a by compiling code in the src_*/ directories and archiving the objects with ranlib.
My first approach was to build a shared library from each src_*/ separately and "link" all of these into one shared library. Using Autotools, the src_module1/Makefile.am would contain
noinst_LTLIBRARIES = libmodule1.la
libmodule1_la_SOURCES = ...
and so on for the other modules, and finally the lib/Makefile.am would need only:
lib_LTLIBRARIES = libmain.la
libmain_la_SOURCES =
libmain_la_LIBADD = $(top_srcdir)/src_module1/libmodule1.la ...
This seemed to work perfectly. However, when the code in testc/ was compiled and linked against libmain.la, a "symbols not found" error was issued.
Thinking that this was an issue with libtool or shared libraries, I tried building static only, basically changing all .la to .a and all _LTLIBRARIES to _LIBRARIES. Same problem. This time, however, noticing the error "ranlib: warning for library: libmain.a the table of contents is empty (no object file members in the library define global symbols)" when trying to link libmain.a itself.
The solution that I found seems like a hack. I did not build Makefiles for any of the src_*/ directories, but instead used only for the lib/ directory and its Makefile.am had the lines:
lib_LTLIBRARIES = libmain.la
libmain_la_SOURCES = [all sources from all ../src_modules/ ]
This worked. The compiled programs in testc/ linked against libmain.la without issue. One of the "modules" is a set of Fortran bindings that wrap other C functions in the library. Even the Fortran codes in testf77/ linked against libmain.la properly.
Could someone carefully explain what happens when libtool builds a shared library? Or even when building a static library? Why is it that several static libraries can't be linked together to make one static library? Why are symbols only available when libtool/ranlib builds the library "from sources"? And what about installing a shared/static library, i.e. moving it to the /usr/local/lib --- what happens there? The Wikipedia article on static and shared libraries isn't really detailed enough for me.
I do appreciate all efforts to make sense of my longwinded question.
What you first tried ought to work. I am using this kind of setup all the time (in a C++ context). It's also documented, and part of the Automake test suite (although maybe not with Fortran).
A libtool library that is not installable, i.e., one declared with noinst_LTLIBRARIES, is called a libtool convenience library. That noinst_ makes a big difference in what is built. Even if Libtool is configured to build shared libraries, a libtool convenience library is not actually a shared library: it is just a set of object files (compiled as PIC so that they can be latter be used in a shared library) stored in an archive. You can use a libtool convenience library anywhere using this set of objects would make sense, e.g., to build a shared library.
When multiple libtool convenience libraries are LIBADDed to an installable libtool library (such as your libmain.la), Libtool has to unpack the archives containing the objects of each convenience library and link them into the final library.
There is a trap that is worth noting here: when building a shared library out of
convenience libraries, if the _SOURCES variable is empty Automake does not know which linker to use and default to the C linker. If you want to trick Automake into using the linking rule for some specific language, you can declare a nodist_EXTRA_..._SOURCES source file that do not have to exist. (See the Libtool Convenience Libraries section of the Automake manual for an example.)
Maybe that was your problem? If you have some Fortran files in the sources of some of your modules (your description suggests these are only C files), the Fortran linker will be used to build libmain.la only if a Fortran file appears in the source files declared for that libtool library. And the C linker will be used when libmain_la_SOURCES is empty.
Otherwise, I have no idea why it didn't work.
There is an small error in your example:
libmain_la_LIBADD = $(top_srcdir)/src_module1/libmodule1.la
should be
libmain_la_LIBADD = $(top_builddir)/src_module1/libmodule1.la
because the library is not created in the source directory. However I assume this is just a typo, and you won't see the difference unless you do a VPATH build or run make distcheck.
Your second try, using _LIBRARIES without Libtool is not expected to work.
_LIBRARIES can only be used to declare static archives, and in this case _LIBADD may only contain object files, not other static archives. Unpacking an archive to reuse its objects into another archive can be tricky to do portably. Automake's answer to this problem has always been: install Libtool and use _LTLIBRARIES (Libtool can be configured to build only static libraries).

making gcc prefer static libs to shared objects when linking?

When linking against libraries using the -l option (say -lfoo), gcc will prefer a shared object to a static library if both are found (will prefer libfoo.so to libfoo.a). Is there a way to make gcc prefer the static library, if both are found?
The issue I'm trying to solve is the following: I'm creating a plugin for an application (the flight simulator called X-Plane), with the following constraints:
the plugin is to be in the form of a 32 bit shared object, even when running on a 64 bit system
the running environment does not provide a convenient way to load shared objects which are not in the 'normal' locations, say /usr/lib or /usr/lib32:
one cannot expect the user to set LD_PRELOAD or LD_LIBRARY_PATH to find shared objects shipped with my plugin
the X-Plane running environment would not add my plugins directory to ``LD_LIBRARY_PATH, before dynamically loading the plugin shared object, which would allow me to ship all my required shared objects alongside my plugin shared object
one cannot expect 64 bit users to install 32 bit shared objects that are non-trivial (say, are not included in the ia32-libs package on ubuntu)
to solve the above constraints, a possible solution is to link the generated shared object against static, 32 bit versions of all non-trivial libraries used. but, when installing such libraries, usually both static and dynamic versions are installed, and thus gcc will always link against the shared object instead of the static library.
of course, moving / removing / deleting the shared objects in question, and just leaving the static libraries in say /usr/lib32, is a work-around, but it is not a nice one
note:
yes, I did read up on how to link shared objects & libraries, and I'm not trying to creatae a 'totally statically linked shared object'
yes, I tried -Wl,-static -lfoo -Wl,-Bdynamic, but didn't bring the expected results
yes, I tried -l:libfoo.a as well, but this didn't bring the expected results either
You can specify the full path to the static libs without the -l flag to link with those.
gcc ... source.c ... /usr/lib32/libmysuperlib.a ...
Just add the .a file to the link line without -l as if it were a .o file.
It's dated, but may work: http://www.network-theory.co.uk/docs/gccintro/gccintro_25.html
(almost end of the page)
"As noted earlier, it is also possible to link directly with individual library files by specifying the full path to the library on the command line."

Using library with different names within autoconf

I am trying to build an application with OpenSync 0.4 (0.3.9 indeed) dependency.
In the project's configure.ac the opensync library is written as libopensync1. However, this doesn't build on my Gentoo system. Changing libopensync1 to libopensync does fix the issue for me.
I searched with Google and found that libopensync1 is used in some distributions, while libopensync in others. So how to resolve this issue in configure.ac?
Thanks.
The macro AC_SEARCH_LIBS does what you need. (There is much heated debate about whether or not pkg-config should ever be used. If you choose to rely on it, ptomato gives a reasonable approach.) Simply add this to your configure.ac:
AC_SEARCH_LIBS([osync_mapping_new],[opensync1 opensync],[],
[AC_MSG_ERROR([can't find opensync])])
This will first look for a library named opensync1; if
it doesn't find that, it will look for opensync.
The primary drawback of using pkg-config is that most projects that
rely on it do not actually check if the data provided by the .pc
file is reliable, so configure may succeed but a subsequent build
will fail. It is always possible for a user to set PKG_CONFIG=true
when running configure and completely eliminate all of the data
provided by any associated .pc files, setting LIBS, CFLAGS, etc by
hand the 'old-fashioned' way.
The primary drawback of not using pkg-config is that the user
has to set LIBS, CFLAGS, etc. the old-fashioned way. In practice,
this is pretty trivial, and all pkg-config has done is move the
data from a single CONFIG_SITE file to separately maintained
.pc files for each package.
If you do use PKG_MODULE_CHECK, follow it up with a call to
AC_CHECK_LIB or AC_SEARCH_LIBS to validate the data in whatever
.pc file was located by PKG_CHECK_MODULES
I'm assuming that the place at which this occurs inside your configure.ac is inside a PKG_CHECK_MODULES call.
Looking at the libopensync sources, it seems that libopensync1 is the newer name, and libopensync is the old name. So, we'll use pkg-config macros to look for the newer name unless it doesn't exist.
Put this in your configure.ac:
# Check if libopensync1 is known to pkg-config, and if not, look for libopensync instead
PKG_CHECK_EXISTS([libopensync1], [OPENSYNC=libopensync1], [OPENSYNC=libopensync])
Then later in your PKG_CHECK_MODULES call, replace libopensync1 with $OPENSYNC.

Linking with a different .so file in linux

I'm trying to compile a piece of software which has the standard build process e.g.
configure
make
make install
The software requires a library e.g. libreq.so which is installed in /usr/local/lib. However, my problem is I'd like to build the software and link it with a different version of the same library (i have the source for the library as well) that I've installed in /home/user/mylibs.
My question is, how do I compile and link the software against the library in /home/user/mylibs rather than the one in /usr/local/lib
I tried setting "LD_LIBRARY_PATH" to include /home/user/mylibs but that didn't work.
Thanks!
When you have an autoconf configure script, use:
CPPFLAGS=-I/home/user/include LDFLAGS=-L/home/user/mylibs ./configure ...
This adds the nominated directory to the list of directories searched for headers (usually necessary when you're using a library), and adds the other nominated directory to the list searched for actual libraries.
I use this all the time - on my work machine, /usr/local is 'maintained' by MIS and contains obsolete code 99.9% of the time (and is NFS-mounted, read-only), so I struggle to avoid using it at all and maintain my own, more nearly current, versions of the software under /usr/gnu. It works for me.
Try using LD_PRELOAD set to your actual file.
LD_LIBRARY_PATH is for finding the dynamic link libraries at runtime. At compiling you should add -L parameters to gcc/g++ to specify in which directory the *.so files are. You also need to add the library name with -l<NAME> (where the library is libNAME.so).
Important! For linking you not only need the libNAME.so file but a libNAME.a is needed too.
When you run the application, don't forget to add the dir to the LD_LIBRARY_PATH.
When you added the /home/user/mylibs to the LD_LIBRARY_PATH did you add it to the front or end of the existing paths? The tokens are searched in-order so you will want yours to appear first in the list.
Also, many standard build environments that use configure will allow you to specify an exact library for each required piece. You will have to run ./configure --help but you should see something like --using-BLAH-lib=/path/to/your/library or similar.

Resources