Joe
Joe

Reputation: 7798

Linking an archive to an archive

With GCC on Linux, is it possible to link a .a into another .a and then only link the resultant .a to my application? Or must my application know of the dependence between one archive and another and link them both?

My understanding is that I must know of the dependencies and link all archives at the end, not in an intermediary step, which seems a little ugly.

This is slightly different than How to merge two "ar" static libraries into one as I'm after a clear description that this is only possible by working around the problem and that linking the two archives together in the naive way is incorrect and will not work, along with the reason as to why.

Upvotes: 2

Views: 2194

Answers (2)

SHG
SHG

Reputation: 2616

Yes, your application has to know the dependencies between your different static libraries.

  • Let's say you have two static libraries a and b.
  • a has a function void print_a(), and b has a function void print_b() that is calling to print_a(). So, b depends on a.
  • Their binaries will look like liba.a and libb.a.

Let's say that library b has a reference to a function defined in library a - void print_b(void). When compiling library b only its symbols are defined in the binary's code section while the others are still undefined:

host$ nm libb.a | grep print
                 U _print_a          <--- Undefined
0000000000000000 T _print_b          <--- Defined, in code section
0000000000000068 S _print_b.eh
                 U _printf

Therefore, when compiling the application that wants to use both of the libraries, linking only to libb.a won't be enough. You'll have to link your application to both libraries. Each library will provide its own symbols addresses in the code section and then your application will be able to link to both.

Something like:

gcc -o main main.c libb.a liba.a

BTW: When compiling library b that uses a, you can but it's not necessary to link to a. The result will be just the same.


Why is this the behavior

When compiling + linking the application that uses static libraries, the symbols in the application source files have to be defined somewhere (with the exception of dynamic linking, but this is done only with dynamic libraries/shared objects. Here we deal with static ones).

Now, remember that a static library is just an archive of objects. When it's created there's no linking phase. Just:

  1. Compiling source code (*.c) to objects (*.o)
  2. Archiving them together in a libXXXX.a file.

It means that if this library (library b in my example) uses some function (void print_a(void)) that is defined in another library (a), this symbol won't be resolved (not as a compilation error, but as the normal behavior). It will be set as Undefined symbol (as we see in the output of nm command) after the library creation, and it will wait to be linked later to its definition. And it's OK because a static library is not executable.

Now returning to application - the linking phase of the application needs to find all the definitions of all the symbols. If you just gave it libb.a as an argument, it wouldn't be able to find the definition to print_a(), because it's not there, it's still undefined. It exists only in liba.a.

Therefore, you must provide both of the libraries.

Upvotes: 1

Meet Taraviya
Meet Taraviya

Reputation: 889

Let libx.a and liby.a be the modules you want to combine. You can try:-

mkdir tmp                 # create temporary directory for extracting 
cd tmp
ar x ../libx.a            # extract libx.a
cp ../liby.a ../libxy.a
ar -q ../libxy.a *        # add extracted files to libxy.a
cd ..
rm -rf tmp

libxy.a thus created contains .o files from both .a files

Upvotes: 1

Related Questions