Link two static libraries in one application
posted on 2009-08-28
Introduction
This is a technical post about compiling a C/C++ application using gcc. This post requires understanding of C programming and building it.
I’m about to discribe a problem that made me lose several hours searching for the problem, while the solution was quite simple.
Situation
I was working on an application that uses two static libraries, or so called archives. My application uses functions from one library, while that library uses functions from another library. This situation sound complex, but I’ll explain using an example.
Example
The application helloWorld.app
uses two archives libArchive1.a
and
libArchive2.a
.
libArchive1.a
This first archive is build from:
libArchive1/libArchive1.h
#include <string> std::string GetHello();
libArchive1/libArchive1.c
#include "libArchive1.h" std::string GetHello() { return std::string("Hello "); }
You can compile these files to an archive using these 2 commands:
g++ -c libArchive1/libArchive1.c -o libArchive1/libArchive1.o ar rcs libArchive1/libArchive1.a libArchive1/libArchive1.o
libArchive2.a
Similar library to libArchive1.a
with use of the GetHello()
function:
libArchive2/libArchive2.h
#include "libArchive1.h" std::string GetHelloWorld();
libArchive2/libArchive2.c
#include "libArchive2.h" std::string GetHelloWorld() { return GetHello() + std::string("World!\n"); }
Compile by:
g++ -c libArchive2/libArchive2.c -IlibArchive1 -o libArchive2/libArchive2.o ar rcs libArchive2/libArchive2.a libArchive2/libArchive2.o
This will require to provide the parameter -I
so the compiler knows
where to get the file libArchive1.h
.
helloWorld.app
Small application printing “Hello World!” to stdout using the
GetHelloWorld()
function.
printHelloWorld.c
#include <iostream> // for cout #include "libArchive2.h" int main(int argc, char* argv[]) { std::cout << GetHelloWorld(); return 0; }
Now here is where the problem did arise, compiling the application. This is what I did:
g++ helloWorldApp/printHelloWorld.c -IlibArchive1 -IlibArchive2 -LlibArchive1 -LlibArchive2 -lArchive1 -lArchive2 -o helloWorld.app
The arguments -lArchive1
and -lArchive2
will tell the compiler to
link in libArchive1
and libArchive1
. But I got the following
error: undefined reference to GetHello()
After a long search (the application I was working on was a lot more
complex, so many things could have been wrong), I found the order of
importing libraries with the -l
argument matter. So after switching
the order of -lArchive1
-lArchive2
, the application got compiled
and did print the text “Hello World!” when running it.
Conclusion
The order of importing libraries matter. As far as I know it is a compiler bug and seems to be solved in newer versions (on Mac OSX 10.5 it works, on OpenSUSE 11 the error occurs). Anyhow, if you have problem with this place the least depended library last in the argument list:
g++ appHelloWorld/printHelloWorld.c -IlibArchive1 -IlibArchive2 -LlibArchive1 -LlibArchive2 -lArchive2 -lArchive1 -o helloWorldApp
This will sound really technical for a lot of people, but it took me too long solving it to not share it with you. I hope someone will benefit from it.
You can download the source code of this example here.
Further Reading
- The C Book - Linkage
- Linker order - GCC on stackoverflow.com