C++ differ between Linking with .o and with .a file: different behavior, why?

90 views Asked by At

I expected that:

linking with .o file, and linking with .a file archived from the .o file, should have no difference.

But the fact is not. I have got 2 source files, each declaring 1class+1 static object+1 function, and a main.cpp that called one of the functions

$cat First.cpp
#include<stdio.h>
struct First{
  First(){printf("First\n");}
};
void f1(){printf("f1\n");}//Not called in main
static First f_obj;

$cat Second.cpp
#include<stdio.h>
struct Second{
  Second(){printf("Second\n");}
};
void f2(){printf("f2\n");}//Not called in main
static Second s_obj;

$cat main.cpp
void f2();
int main()
{
    f2();
    return 0;
}

$g++ -c First.cpp  -fPIC
$g++ -c Second.cpp -fPIC
$ar -rvs libmystatic.a  First.o Second.o
$g++ main.cpp -o MylinkSta -lmystatic -L.
$g++ main.cpp -o MyDirect First.o Second.o

$./MylinkSta
Second
f2

$./MyDirect
Second
First
f2

So you can see

(1) The running result of MylinkSta doesn't construct 'First' object, but MyDirect does.

(2) While the 'Second' object is always constructed.

I really don't see any difference between linking with 2 '.o' files, and linking with '.a' file that's archived from these 2 '.o' files.

Why they behave differently? I experimented with gcc/clang on rhel/ubuntu, all show the same result. I wonder if there's any C++ ABI standard that says when a static/global object created should be really invoked, by any linking option?

How does this difference come from?

1

There are 1 answers

1
yugr On BEST ANSWER

This is due to semantics of static libs. Linker will only include files from static library if it contains symbol that is referenced by some object file which precedes it in command line (e.g. main.cpp references f2 from Second so it's included). You can override this behavior with surrounding you library with

-Wl,--whole-archive -lmystatic -Wl,--no-whole-archive

but this isn't standard.