2009-03-01 8 views
20

¿Hay alguna manera de obligar a Visual Studio a vincular todos los símbolos de un archivo lib a la DLL como ATM? Está optimizando las funciones "no utilizadas" que necesita el programa utilizando el dll en tiempo de ejecución.forzar visual studio para vincular todos los símbolos en un archivo lib

Intenté usar/OPT: NOREF y/OPT: NOICF pero parece que no funcionan.

La razón por la que los necesito es porque son de clase global que se registran a sí mismos con un controlador y no están vinculados en el dll.

+0

¿Puede enumerar la línea de comando completa que está utilizando para compilar y vincular? –

Respuesta

19

No sé si hay una manera más elegante en Visual Studio, pero la solución multiplataforma que utilizamos tiene dos macros que fuerzan al archivo de objeto problamatic a vincularse.

Uno se coloca en el archivo fuente de funciones que se excluyen, el otro se coloca en una función que el enlazador sabe que se llamará.

Algo así como;

#define FORCE_LINK_THIS(x) int force_link_##x = 0; 

#define FORCE_LINK_THAT(x) { extern int force_link_##x; force_link_##x = 1; } 

No es exactamente elegante, pero no hemos encontrado una mejor solución que funcione en todas las plataformas.

+0

Muy lindo. ¿Por qué no es '__declspec (dllexport)' suficientemente bueno? –

+1

'__declspec (dllexport)' y '__declspec (dllimport)' no son suficientes porque declaran (al compilador) que el código está en una DLL. Esto hace innecesarias las funciones thunk y .DEF. Solo una optimización menor: '#define FORCE_LINK_THAT (x) void force_link_function _ ## x (void) {extern int force_link _ ## x; force_link _ ## x = 1; } ' permite que la macro se coloque en la parte superior de un archivo del que sabe que se vinculará. No hay ninguna diferencia de que la función ficticia nunca se llame. –

+1

También parece funcionar con una función con un cuerpo vacío. Simplemente llámalo a algún lugar en el archivo ejecutable o dll al que estés vinculando la librería. – BigSandwich

0

¿Cómo va a llamar la DLL a las funciones de su lib en tiempo de ejecución? Eso suena un poco difícil de creer.

Ahora si los usuarios de la DLL van a llamar a las funciones de su biblioteca, su pregunta tiene sentido. Los compiladores de Windows (a diferencia de los compiladores de Unix) solo exportan funciones de una DLL si se solicita explícitamente. La forma más común de hacer esto es declarar la función "dllexport", pero también puede nombrar las funciones en un archivo .DEF para pasarlo al enlazador. Tenga en cuenta que debe enumerar el nombre anulado de C++ en el archivo .DEF.

+0

porque son clases globales que se registran a sí mismas con un controlador y no están vinculadas en el dll. – Lodle

+0

Sería útil poner eso en la pregunta, entonces. Es una buena pregunta, con esa adición, pero diferente de lo que preguntaste ahora. – MSalters

1

Tuve el mismo problema con un sistema de complementos donde las fábricas de varias DLL usaban una fábrica principal común, todo lo que se registraba al iniciar al cargar bibliotecas, sin tener que compilar la lista de complementos a utilizar. Esto funcionaba muy bien en Linux pero tenía dos problemas en Windows:

  1. las fábricas no eran comunes entre las DLL. Este no es tu problema pero está relacionado. Tengo una solución aquí: Ensuring to use common fatories. Mira la respuesta de James con la función set_the_global.
  2. no se configuraron al inicio si no se utilizó ningún símbolo de la DLL en el principal. Creo que es tu problema La única solución que encontré fue usar archivos de configuración (uno por subproyecto) que enumera los nombres de los complementos (DLL) disponibles y forzar su vinculación utilizando, en mi caso, QLibrary. Usando cmake, se genera una versión predeterminada de un archivo de configuración para cada subproyecto en tiempo de compilación usando la siguiente macro, llamado en lugar de add_library en cada dir plugin:

    file(WRITE ${CMAKE_BINARY_DIR}/${CMAKE_PROJECT_NAME}-plugins "") 
    macro (DECLARE_AMOSE_PLUGIN _plugin) 
        file (APPEND ${CMAKE_BINARY_DIR}/${CMAKE_PROJECT_NAME}-plugins "${_plugin}\n") 
        add_library(${_plugin} SHARED ${${_plugin}_LIB_SRCS}) 
    endmacro (DECLARE_AMOSE_PLUGIN) 
    
0

he usado un pragma, parece trabaje, pero no se ahogue si no incluye la línea.

#include "library1.h" 
#include <QApplication> 
#pragma comment(lib, "C:\\Qt\\5.5\\msvc2013_64\\lib\\Qt5Guid.lib") 
PHI_STATUS PHI_EXP_CONV PHI_ShowGUI(size_t reserved) 
{ 
    QApplication app(none, nullptr); 
    ... 
} 

También puede vincularlos a través del campo Additional Dependencies en la pestaña Librarian.

3

En realidad, hay una solución medio oficial, y here it is.

TL; DR:

'Usar entradas de dependencia biblioteca'.

En VS lingo 'library dependency inputs' es un nombre para los archivos obj que constituyen una biblioteca. En realidad se puede controlar este comportamiento en dos ámbitos:

  1. por refernce: por el 'utilizar entradas de dependencia de la biblioteca' combinado en las propiedades de referencia. Esta es la solución que usé personalmente, y la mencionada in the post. Use Library Dependency Inputs

  2. por todo el ejecutable: en el proyecto exe propiedades/C++/enlazador/general/Use entradas de dependencia biblioteca -> Sí

La motivación histórica para estos ajustes arcanos es enabling incremental linking in places it wasn't available before, pero tiene el efecto secundario útil de vincular directamente con los archivos obj que están empaquetados en una lib, por lo que también construye objetos globales sin referencia.

0

Probado en MSVC2k17 ...

__pragma(comment(linker,"/export:REGISTERfunc")); 
void REGISTERfunc() { printf("I'm linked!\n"); } 

funciona de forma totalmente. ¡Esto incluso puede estar dentro de un archivo .lib estáticamente enlazado y continuará hasta el ejecutable de salida y más allá!

EDITAR: ¡Incluso puedes ponerlo en una macro para obtener puntos increíbles!

EDITAR: Otra nota: Debe habilitar la generación de código de tiempo de enlace./LTCG ... algo

Cuestiones relacionadas