Linking self registration, abstract factory

I worked and tested self-registration, an abstract factory based on the one described here:

stack overflow

In all my test cases, it works like a charm and provides the features and reuse that I wanted.

Binding in this factory in my project using cmake was quite complicated (although it seems to be more of an ar problem).

I have identical base.hpp, b.pp / cpp derivatives and equivalent .hpp / cpp derivatives to the linked example. Basically, I just create an instance of the factory and call createInstance () twice, each time with "DerivedA" and "DerivedB".

The executable file created by the line:

g++ -o testFactory main.cpp derivedb.o deriveda.o 

works as expected. Moving my derived classes to the library (using cmake, but I also tested this with ar), and then communication failed:

 ar cr libbase.a deriveda.o derivedb.o g++ -o testFactory libbase.a main.cpp 

calls only the first static instantiation (from a derivative of A.cpp) and never the second static instantiation, i.e.

 // deriveda.cpp (if listed first in the "ar" line, this gets called) DerivedRegister<DerivedA> DerivedA::reg("DerivedA"); // derivedb.cpp (if listed second in the "ar" line, this does not get called) DerivedRegister<DerivedB> DerivedB::reg("DerivedB"); 

Note that replacing two in the string ar causes only a static instantiation of the derived bb.cpp, not an instance of the derived .cpp.

Am I missing something with ar or static libraries that somehow don't play with static variables in C ++?

+7
source share
1 answer

Unlike intuition, including the archive in the communication team, it does not coincide with the fact that it includes all the files of objects that are in the archive. Only those object files in the archive are included that are necessary for resolving undefined characters. This is good if you think that when there was no dynamic linking, and otherwise all libraries (I think the C library) will be duplicated in each executable file. Here is what the ld (1) manpage (GNU ld on linux) should say:

Linkers will search the archive only once, in the place where it is specified on the command line. If the archive defines the undefined character in some object that appeared before the archive on the command line, the linker will contain files from the archive. However, the undefined character in an object that appears later on the command line will not force the linker to search the archive again.

Unfortunately, there is no standard way to include each archive member in a linked executable file. On linux, you can use g++ -Wl,-whole-archive , and on Mac OS X you can use g++ -all_load .

So, with GNU binutils ld, the link command should be

 g++ -o testFactory -Wl,-whole-archive libbase.a -Wl,-no-whole-archive main.cpp 

-Wl,-no-whole-archive guarantees that any archive that appears later in the final channel command generated by g ++ will be linked in the usual way.

+10
source

All Articles