tutorial script español descarga course clean c++ g++ cmake ar

c++ - script - vincular una fábrica de autorregistro y abstracta



cmake windows tutorial (1)

He estado trabajando y probando una fábrica abstracta de autorregistro basada en la que se describe aquí:

https://stackoverflow.com/a/582456

En todos mis casos de prueba, funciona como un encanto, y proporciona las funciones y la reutilización que quería.

Vincularme en esta fábrica en mi proyecto usando cmake ha sido bastante complicado (aunque parece ser más un problema).

Tengo el base.hpp idéntico, derivadob.hpp / cpp, y un deriveda.hpp / cpp equivalente al ejemplo vinculado. En general, simplemente instanciamos la fábrica y llamamos a createInstance () dos veces, una vez cada una con "DerivedA" y "DerivedB".

El ejecutable creado por la línea:

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

funciona como se esperaba Mover mis clases derivadas a una biblioteca (usando cmake, pero también he probado esto con ar solo) y luego falla el enlace:

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

solo llama a la primera instanciación estática (de derivedA.cpp) y nunca a la segunda instanciación estática, es decir,

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

Tenga en cuenta que al intercambiar los dos en la línea ar solo se llama a la instanciación estática derivada b.cpp, y no a la instanciación de deriveda.cpp.

¿Me falta algo con ar o bibliotecas estáticas que de alguna manera no funcionan bien con variables estáticas en C ++?


Contrariamente a la intuición, incluir un archivo en un comando de enlace no es lo mismo que incluir todos los archivos de objetos que están en el archivo. Solo se incluyen aquellos archivos objeto dentro del archivo necesarios para resolver los símbolos indefinidos. Esto es bueno si se tiene en cuenta que una vez que no existía una vinculación dinámica y de otro modo la totalidad de las bibliotecas (creo que la biblioteca C) se duplicaría en cada ejecutable. Esto es lo que la página de manual ld (1) (GNU ld en linux) tiene que decir:

El vinculador buscará un archivo solo una vez, en la ubicación donde se especifica en la línea de comando. Si el archivo define un símbolo que no estaba definido en algún objeto que apareció antes del archivo en la línea de comando, el vinculador incluirá los archivos correspondientes del archivo. Sin embargo, un símbolo indefinido en un objeto que aparece más adelante en la línea de comando no hará que el vinculador busque nuevamente en el archivo.

Lamentablemente, no hay una forma estándar de incluir a cada miembro de un archivo en el archivo ejecutable vinculado. En Linux puedes usar g++ -Wl,-whole-archive y en Mac OS X puedes usar g++ -all_load .

Entonces con GNU binutils ld, el comando de enlace debe ser

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

el -Wl,-no-whole-archive asegura que cualquier archivo que aparezca más tarde en el comando de enlace final generado por g ++ se vinculará de la manera normal.