2012-04-09 15 views
7

pracuję z i testowanie własnej rejestracji streszczenie fabryki w oparciu o opisany tutaj:łączenie własnej rejestracji streszczenie fabryka

https://stackoverflow.com/a/582456

We wszystkich moich testów, to działa jak urok i zapewnia funkcje i ponowne użycie, które chciałem.

Łączenie w tej fabryce w moim projekcie przy użyciu cmake jest dość trudne (choć wydaje się być bardziej problemem ar).

I mają identyczną base.hpp, derivedb.hpp/CPP, i równoważne deriveda.hpp/CPP przykładzie połączone. W zasadzie po prostu tworzę instancję fabryki i wywołuję createInstance() dwa razy, raz każdy z "DerivedA" i "DerivedB".

wykonywalnego stworzony przez linię:

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

działa zgodnie z oczekiwaniami. Przenoszenie moich klas pochodnych do biblioteki (za pomocą CMake, ale ja testowałem to z ar sam również), a następnie łączenie zawiedzie:

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

tylko wywołuje pierwszej instancji statycznego (od derivedA.cpp) i nigdy drugi instancji statyczny, tj

// 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"); 

Zauważ, że zamiana dwa w linii ar wywołuje tylko derivedb.cpp statycznego instancji, a nie instancji deriveda.cpp.

jestem brakuje czegoś z bibliotek ar lub statycznych, że jakoś nie grają ładny z zmiennych statycznych w C++?

Odpowiedz

10

Wbrew intuicji, w tym archiwum w poleceniu łącza nie jest taka sama jak w tym wszystkie pliki obiektów, które są w archiwum. Uwzględniane są tylko te pliki obiektów w archiwum, które są niezbędne do rozpoznania niezdefiniowanych symboli. Jest to dobra rzecz, jeśli weźmiemy pod uwagę, że gdy nie było już dynamicznego łączenia, w przeciwnym razie cała biblioteka (myślenie o bibliotece C) byłaby duplikowana w każdym pliku wykonywalnym. Oto co ma do powiedzenia strona podręcznika ld (1) (GNU ld na Linux):

Łącznik przeszuka archiwum tylko raz, w miejscu, w którym jest podana w wierszu poleceń. Jeśli archiwum definiuje niezdefiniowany symbol w obiekcie, który pojawił się przed archiwum w linii poleceń, linker będzie zawierał odpowiednie pliki z archiwum. Jednak niezdefiniowany symbol w obiekcie pojawiającym się później w wierszu poleceń nie spowoduje, że linker ponownie przeszuka archiwum.

Niestety nie ma standardowego sposobu na dołączenie każdego członka archiwum do połączonego pliku wykonywalnego. Na Linuksie możesz użyć g++ -Wl,-whole-archive, a na Mac OS X możesz użyć g++ -all_load.

Więc z binutils GNU ld, komenda link powinien być

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

-Wl,-no-whole-archive zapewnia, że ​​wszelkie pojawiające się później w archiwum końcowego polecenia linków generowanych przez g ++ zostaną połączone w normalny sposób.

+0

Dzięki dużo, to umieścić mnie na właściwą drogę. W celu późniejszego wykorzystania, pomogło to również (dzięki ulepszonemu wyszukiwaniu-foo w całym archiwum!) http://stackoverflow.com/a/842770/1322752 –