2009-03-01 10 views
20

C'è un modo per forzare Visual Studio a collegare tutti i simboli da un file lib alla DLL poiché atm sta ottimizzando le funzioni "inutilizzate" che sono necessarie al programma usando il dll in fase di esecuzione.force visual studio per collegare tutti i simboli in un file lib

Ho provato a utilizzare/OPT: NOREF e/OPT: NOICF ma non sembrano funzionare.

La ragione per cui ho bisogno è che sono di classe globale che li registra con un controller e non sono collegati nella DLL.

+0

Puoi elencare la riga di comando completa che stai utilizzando per compilare e collegare? –

risposta

19

Non so se c'è un modo più elegante in Visual Studio, ma la soluzione multipiattaforma la usiamo per avere due macro che costringono il file oggetto problamatic a essere collegato.

Uno è inserito nel file sorgente delle funzioni che vengono escluse, l'altro è inserito in una funzione che verrà chiamata dal linker.

Qualcosa come;

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

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

Non è esattamente elegante, ma non abbiamo trovato una soluzione migliore che funzioni su tutte le piattaforme.

+0

Molto carino. Perché '__declspec (dllexport) non è abbastanza buono? –

+1

'__declspec (dllexport)' e '__declspec (dllimport)' non sono sufficienti perché dichiarano (al compilatore) che il codice si trova in una DLL. Ciò rende superflue le funzioni thunk e i file .DEF. Solo un'ottimizzazione minore: '#define FORCE_LINK_THAT (x) void force_link_function _ ## x (void) {extern int force_link _ ## x; force_link _ ## x = 1; } ' consente di posizionare la macro nella parte superiore di un file dal quale si sa che sarà collegata. Non fa differenza che la funzione dummy non venga mai chiamata. –

+1

Sembra funzionare anche con una funzione con un corpo vuoto. Chiamalo in qualche posto nell'eseguibile o nella DLL che stai collegando alla libreria. – BigSandwich

0

In che modo la DLL chiamerà le funzioni dalla libreria lib in fase di esecuzione? Sembra un po 'difficile da credere.

Ora se gli utenti della DLL della DLL chiamano le funzioni della libreria, la tua domanda ha senso. I compilatori di Windows (diversamente dai compilatori Unix) esportano solo le funzioni da una DLL se richiesto esplicitamente. Il modo più comune per farlo è dichiarare la funzione "dllexport", ma è anche possibile assegnare un nome alle funzioni in un file .DEF come passarlo al linker. Si noti che è necessario elencare il nome in codice C++ nel file .DEF.

+0

perché sono di classe globale che si regge con un controller e non sono collegati nella DLL. – Lodle

+0

Sarebbe utile metterlo nella domanda, allora. È una bella domanda, con quell'aggiunta, ma diversa da ciò che hai chiesto ora. – MSalters

1

Ho avuto lo stesso problema con un sistema di plug-in in cui le fabbriche di varie DLL utilizzavano una fabbrica comune comune, tutto registrato all'avvio durante il caricamento delle librerie, senza dover compilare l'elenco di plug-in da utilizzare. Funzionava molto bene sotto Linux ma aveva due problemi sotto Windows:

  1. le factory non erano comuni tra DLL. Questo non è un tuo problema ma è correlato. Ho una soluzione qui: Ensuring to use common fatories. Guarda la risposta di James con la funzione set_the_global.
  2. non sono stati impostati all'avvio se nessun simbolo della DLL è stato utilizzato nel principale. Penso che sia il tuo problema. L'unica soluzione che ho trovato era usare i file di configurazione (uno per sottoprogetto) elencando i nomi dei plugin (DLL) disponibili e forzare il loro collegamento usando, nel mio caso, QLibrary. Utilizzando CMake, una versione di default di un file di configurazione per ogni sottoprogetto viene generato al momento della compilazione usando la seguente macro, chiamato al posto di add_library in ogni 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

ho usato un pragma, sembra lavoro, ma non soffocare se non si include la linea.

#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); 
    ... 
} 

È inoltre possibile collegare tramite il campo Additional Dependencies nella scheda Librarian.

3

Esiste in realtà una soluzione semi-ufficiale e here it is.

TL; DR:

'Utilizzare gli ingressi di dipendenza biblioteca'.

In VS lingo 'input di dipendenza della libreria' è un nome per i file obj che costituiscono una libreria. Si può effettivamente controllare questo comportamento in due ambiti:

  1. Per refernce: dal 'utilizzare gli ingressi di dipendenza della biblioteca' combo nelle proprietà di riferimento. Questa è la soluzione che ho utilizzato personalmente e quella citata in the post. Use Library Dependency Inputs

  2. Per l'intero eseguibile: nel progetto exe proprietà/C++/Linker/General/Usare ingressi dipendenza biblioteca -> Sì

La motivazione storica per queste impostazioni arcani è enabling incremental linking in places it wasn't available before, ma ha l'effetto collaterale utile del collegamento diretto con i file obj che sono impacchettati in una lib, costruendo in tal modo anche oggetti globali non referenziati.

0

Testato in MSVC2k17 ...

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

funziona completamente. Questo può anche essere all'interno di un .lib collegato staticamente e continuerà fino all'eseguibile in uscita e oltre!

MODIFICA: puoi anche inserirlo in una macro per ottenere punti bonus fantastici!

MODIFICA: Un'altra nota: è necessario attivare la generazione del codice di tempo di collegamento./LTCG ... qualcosa

Problemi correlati