views:

540

answers:

1

Hi! Until some time ago, I thought a .a static library was just a collection of .o object files, just archiving them and not making them handled differently. But linking with a .o object and linking with a .a static library containing this .o object are apparently not the same. And I don't understand why...

Let's consider the following source code files:

// main.cpp
#include <iostream>
int main(int argc, char* argv[]) {
    std::cout << "main" << std::endl;
}


// object.hpp
#include <iostream>
struct Object
{
    Object() { std::cout << "Object constructor called" << std::endl; }
    ~Object() { std::cout << "Object destructor called" << std::endl; }
};


// object.cpp
#include "object.hpp"
static Object gObject;

Let's compile and link and run this code:

g++ -Wall object.cpp main.cpp -o main1
./main1
> Object constructor called
> main
> Object destructor called

The constructor an the destructor of the global gObject object is called.

Now let's create a static library from our code and use (link) it in another program:

g++ -Wall -c object.cpp main.cpp
ar rcs lib.a object.o
g++ -Wall -o main2 main.o lib.a
./main2
> main
  • gObject's constructor and destructor are not called... why?
  • How to have them automatically called?

Thanks.

+10  A: 

.a static libraries contain several .o but they are not linked in unless you reference them from the main app.
.o files standalone link always.

So .o files in the linker always go inside, referenced or not, but from .a files only referenced .o object files are linked.

As a note, static global objects are not required to be initialized till you actually reference anything in the compilation unit, most compilers will initialize all of them before main, but the only requirement is that they get initialized before any function of the compilation unit gets executed.

Arkaitz Jimenez
Thanks. It seems that linking with all .o files contained in a .a can be forced by using the linker option -Wl,--whole-archive (or -Wl,-all_load on MacOSX)...
moala
See also -force_load for MacOSX
moala
@Arkaitz Jimenez: Will be there any problem, if both `1.o` and `2.o` from `some.a` have two global variables with the same name? Can they be linked into one executable (consider cases: the global is referred / not referred from executable)?
dma_k
It seems I found the answer to my question: these two symbols have to go into one symbol table for the executable, which creates a collision. When object files form separate libraries, the symbol tables are separated.
dma_k