mantler
mantler

Reputation: 889

Link a static lib into a shared lib?

Background:

I want to link a few static libs into a shared lib. The reason is that I want my application to use the specific lib versions that I have tested it with. I do not want to ship the static versions as shared libraries with my application. I have created this sample lib and application to simplify as much as possible. I would like to continue to link the shared lib to the application during linking.

Question:

Why do I get the error messages listed below? What am I doing wrong? Perhaps this is not the usual way of doing things on linux, but is it possible to do so? Is this boost specific?

---- library

//example.cpp
#include <boost/thread.hpp>
void doit()
{
    boost::thread t1;
}

#build script
g++ -Wall -fPIC -I/usr/include -c example.cpp -o example.o
g++ -shared /usr/lib/libboost_thread.a /usr/lib/libboost_system.a 
    example.o -o libexample.so
#build OK. 

---- sample application

//main.cpp
#include <iostream>
void doit();
int main()
{
    std::cout << "main\n";
    doit();
    return 0;
};

#build script.
g++ -Wall -c main.cpp -o main.o
g++ libexample.so main.o -o main

#error message.
libexample.so: undefined reference to `boost::thread::thread()'
libexample.so: undefined reference to `boost::thread::~thread()'
collect2: ld returned 1 exit status

All source code is located in the same directory. Boost is installed in /usr/lib and /usr/include. Boost, version 1.40, was installed using apt-get on a ubuntu 10.04 machine.

Thank you!

Upvotes: 6

Views: 5414

Answers (1)

Unknown
Unknown

Reputation: 5772

I think the easiest way for you is to use the --whole-archive linker switch (there are more SO questions on this topic, see one here how to link static library into dynamic library in gcc ).

The downside of that is that your shared library will export all symbols from the Boost static libraries and you might have weird issues if you'll use your .so in an application that also uses Boost (but a different version or compiled with different switches).

So you need to use a version script to hide what's exported from the library (see How to hide the exported symbols name within a shared library , also google for linker version scripts), leaving only doit() visible. In your case, such a version script could look like:

{
global:
    doit*;
local:
    *;
}      

You also need to make sure that the static libraries you're linking with are compiled with -fPIC (which is unlikely, if you didn't tweak their build flags), other wise you'll have a performance penalty on i386 and might not link at all on amd64.

Upvotes: 2

Related Questions