Building a Shared Library but linking against a Static One - makefile

I have an Autogen Makefile.am that I'm trying to use to build a test program for a shared library. To build my test binary, I want to continue building the shared library as target but I want the test program to be linked statically. I've spent the last few hours trying to craft my Makefile.am to get it to do this.
I've tried explicitly changing the LDADD line to use the .a version of the library and get a file not found error even though I can see this library is getting built.
I try to add the .libs directory to my link path via LDFLAGS and still it can't find it.
I tried moving my library sources to my test SOURCES list and this won't work because executable object files are built differently than those for static libraries.
I even tried replicating a lib_LIBRARIES entry for the .a version (so there's both a lib_LTLIBRARIES and a lib_LIBRARIES) and replicate all the LDFLAGS, SOURCES, dir and HEADERS for the shared version as part of the static version (replacing la with a of the form _a_SOURCES = _la_SOURCES. Still that doesn't work because now it can't figure out what to build.
My configure.ac file is using the default LT_INIT which should give me both static and dynamic libraries and as I said it is apprently building both even if the libtool can't see the .a file.
Please, anyone know how to do this?

As #Brett Hale mentions in his comment, you should tell Makefile.am that you want the program to be statically linked.
To achieve this you must append -static to your LDFLAGS.
Changing the LDFLAGS for a specific binary is achieved by changing binary_LDFLAGS (where binary is the name of the binary you want to build).
so something like this should do the trick:
binary_LDFLAGS = $(AM_LDFLAGS) -static

Related

Adding PCL (Point Cloud Library) to existing project with Makefiles

I have a problem with PCL: specifically I want to use it in the existing project with existing Makefiles. However, PCL is using CMake and I couldn't find how to add it to Makefile directly. Does anyone know how to do that?
First try to compile the one of the example provided in PCL website using CMake.
http://pointclouds.org/documentation/tutorials/pcl_visualizer.php
After compiling the above example, you will find various new files and a folder created by CMake in your directory.
Go to CMakeFiles/pcl_visualizer_demo.dir/ .
Open file named link.txt, which contains the terminal command which has various pcl(point cloud libraries) linked dynamically to the file.
command should look similar to the command shown below
/usr/bin/c++ -O3 -Wno-deprecated -s CMakeFiles/pcl_visualizer_demo.dir -o pcl_visualizer_demo -rdynamic -lpcl_common -Wl,-Bstatic -lflann_cpp_s -Wl,-Bdynamic -lpcl_kdtree -lpcl_octree -lpcl_search -lqhull -lpcl_surface -lpcl_sample_consensus -lpcl_io -lpcl_filters -lpcl_features -lpcl_keypoints -lpcl_registration -lpcl_segmentation -lpcl_recognition -lpcl_visualization -lpcl_people -lpcl_outofcore -lpcl_tracking /usr/lib/libvtkGenericFiltering.so.5.8.0 /usr/lib/libvtkGeovis.so.5.8.0 /usr/lib/libvtkCharts.so.5.8.0 /usr/lib/libvtkViews.so.5.8.0 /usr/lib/libvtkInfovis.so.5.8.0 /usr/lib/libvtkWidgets.so.5.8.0
You can include these libraries in your Makefile directly.
If you use different functions or pcl headers files, then first try compiling it using CMake and get the libraries linked and add it to your Makefile of previous project.
I tried this method for my project which worked perfectly fine. I tried pkg-config to link the libraries, which didn't work in my case. I was not able to find any other method that easily links all the required libraries.

Libtool link shared lib against a static lib given by an explicit path (no -l option)

I want to pull all symbols from a static library (libyaml-cpp) into a shared one that I'm building (libLHAPDF), to avoid an explicit dependency for users of the latter. (It's not my favourite way to do things, but the difficulty of installing the prerequisite was a regular negative feedback about the package.) So I try to build the relevant bit of my shared library with an automake rule like this:
libLHAPDFInfo_la_LDFLAGS = $(AM_LDFLAGS) \
$(srcdir)/yamlcpp/yaml-cpp/libyaml-cpp.a
I specifically want something like this rather than
libLHAPDFInfo_la_LDFLAGS = -L$(srcdir)/yamlcpp/yaml-cpp -lyaml-cpp \
$(AM_LDFLAGS)
because there could be a shared lib version of libyaml-cpp installed elsewhere on the system, and I don't want to use it. (The odd flag ordering in that latter case is an attempt to make sure that -lyaml-cpp finds the one built in the srcdir... and yes it really is srcdir and not builddir in this case!)
However, the first version gives a warning that I'd rather not have:
*** Warning: Linking the shared library libLHAPDFInfo.la against the
*** static library ./yamlcpp/yaml-cpp/libyaml-cpp.a is not portable!
and more importantly it doesn't actually work: if I run nm on the generated library I see undefined symbols:
$ nm src/.libs/libLHAPDFInfo.a | grep YAML
U _ZN11LHAPDF_YAML4NodeC1Ev
U _ZN11LHAPDF_YAML4NodeD1Ev
...
(Details: libLHAPDFInfo.a is a noinst_LTLIBRARIES entry used as an intermediate to building the final shared lib. So this doesn't even work when linking one static lib against another. And to avoid symbol clashes, the bundled version is slightly hacked to rename the YAML namespace to LHAPDF_YAML: that doesn't change anything, but I thought I'd mention it just in case those symbol names seem strange to you.)
If I use the second form of the link flags (the -lyaml-cpp way), I get all the LHAPDF_YAML symbols in libLHAPDFInfo.a and thereafter into the shared library. And there is no longer any warning about non-portability of the static library linking (which was built with -fPIC, so it is valid to do this). But if a shared libyaml-cpp is also found on the system, it gets used regardless of the -L/-l flag ordering -- which I don't want.
Any suggestions of how I can make sure that the version of the library at a particular path will be used, while getting the symbols correctly copied across and avoiding libtool warnings?
EDIT: Having said that I could get symbols copied from libyaml-cpp.a into libLHAPDFInfo.a via the -lyaml-cpp flag, after more iterations I could no longer get this approach to show the expected symbols via nm. Looking at the ar/ranlib commands executed by libtool when making libLHAPDFInfo.a, the -l arguments seem to get completely dropped. So I don't know how it ever worked... as far as I can tell it's just not a mode that libtool supports, not that that is documented. In the end I renamed libyaml-cpp to liblhapdf-yaml-cpp.a as part of the build (since no lib with that name should be found accidentally), and linked that into the final shared libLHAPDF.so rather than the static convenience lib. Not as neat as I'd have liked -- I was hoping to isolate all the yaml-cpp dependency handling into the build of one convenience lib, and relying on file copies to disambiguate library lookup is unsatisfying -- but it works.

g++ library search failure

I have a directory structure as below:
/
|
+--- /lib
| libsomething.a
| libsomething.so
|
+----/obj
anObjFile.o
When I run the following command from within the obj directory:
g++ -L../lib -lsomething anObjFile.o
I get undefined reference errors. Apparently gcc is failing to locate libsomething.a.
But now if I delete libsomething.so and then rerun the command, linking succeeds.
As per gcc documentation -lsomething should expand to libsomething.a. Then why is presence of libsomething.so causing the library search to fail? Also, how can I resolve this problem?
I'm on Linux Mint 12 with gcc version 4.6.1.
The .so file is a dynamic library, meaning it is used each time you run your program. In that case you need to tell your OS (Mint in this case) where that dynamic library is located so your prgramm can find it at run time.
The .a file is a static library, meaning functions needed from it will be copied into your prgramm while linking. So your prgramm can run without the library file.
If nothing else is said gcc will assume you want to use the dynamic lib. If it can find a .so file it will use it instead of a .a file. If you want to tell gcc to make your programm static (use the .a file) you can add -static to your gcc call.
However the reason why the linking fails when the dynamic library is used is not clear. How did you install/build the library?

Linux GNU Build: Build Dynamic Library from a Set of Static Libraries

I have a make system I just completed, and my goal is to have one Monalithic .so file at the end. So far I have compiled all the seperate parts into .a files. I did this just to compact the number of .o files I would have to work with.
My idea so far is to just unpack the .a files at the end and then rebuild all of them into the large .so file. Is this sincable or is there another (better) way to do this?
See the --whole-archive option in the man page for the ld command to combine static libs into a dynamic lib.

using agg (antigrain) library and getting gsl shell working

My main aim is to get the GSL Shell working on my OSX 10.7 system. So far I have the correct version of lua with the correct patches running. I also have a working version of GSL which compiles and runs example programs. I can build agg perfectly and also run their example programs by running make in the macosx_sdl folder.
My first question is how on earth do I create my own project with agg? I know that you are supposed to simply add the files to your project file and go, but this does not seem to want to compile for me. Is it simply a case of adding the include directory and the libagg.a?
Finally, how do I build gsl shell? Currently it complains about the agg-plot folder a lot, so where do I put the agg files to make this build, then when i've done it where do I place the agg files so that the lua scripts can get to them?!
Hope someone can help!
In general to use the AGG library you need to make sure that the compiler is able to find the headers files and, during the linking, the libraries, either in form of a static or dynamic libraries.
To make the headers files and the libraries available you need to take into account the system that is used to build the software. If a traditional makefile sistem is used you need to add some flags to make sure that the headers file can be found. This can be achieved by adding into the makefile something like:
CFLAGS += -I/path/to/agg/headers
and for the linker:
LIBS += -L/path/to/agg/library -lagg -lm
In the specific case of GSL Shell 1.1 the file "make-packages" is used in the Makefile to configure the required packages. You can add here the flags required to locate the AGG library:
AGG_INCLUDES = -I/usr/include/agg2
AGG_LIBS = -lagg -lX11 -lpthread -lsupc++
you should just modify the path provided with the "-I" option and, in AGG_LIBS, add an option "-L/path/to/agg/library" to specify the path where the AGG libraries are located.
Please note also that the agg libraries depends on other libraries. For example on linux it needs at least the X11 library. The libraries supc++ may be needed if the linking is made by invoking gcc instead of g++ because if gcc is used the C++ runtime libraries are not included.

Resources