2009-03-01 12 views
20

Czy jest jakiś sposób zmuszenia wizualnego studio do połączenia wszystkich symboli z pliku lib do biblioteki dll, ponieważ jest to optymalizacja "nieużywanych" funkcji, które są potrzebne programowi za pomocą dll w czasie wykonywania.Wymuś wizualne studio, aby połączyć wszystkie symbole w pliku biblioteki.

Próbowałem użyć/OPT: NOREF i/OPT: NOICF, ale nie wydają się działać.

Powodem, dla którego ich potrzebuję, jest fakt, że są to klasy globalne, które rejestrują się w kontrolerze i nie są połączone w bibliotece dll.

+0

Czy możesz wyświetlić pełną linię komend, której używasz do kompilowania i łączenia? –

Odpowiedz

19

Nie wiem, czy w Visual Studio istnieje bardziej elegancki sposób, ale w przypadku rozwiązania wieloplatformowego używamy dwóch makr, które wymuszają powiązanie pliku obiektu problamatycznego.

Jedną umieszcza się w pliku źródłowym funkcji, które są wykluczane, a druga umieszczana jest w funkcji wywoływanej przez linker.

Coś jak;

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

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

Nie jest to dokładnie elegancki, ale nie znaleźliśmy lepszego rozwiązania, które działa na różnych platformach.

+0

Bardzo urocze. Dlaczego "__declspec (dllexport)" nie jest wystarczająco dobre? –

+1

'__declspec (dllexport)' i '__declspec (dllimport)' nie są wystarczające, ponieważ deklarują (do kompilatora), że kod znajduje się w DLL. Dzięki temu funkcje thunk i pliki .DEF są niepotrzebne. Tylko drobna optymalizacja: '#define FORCE_LINK_THAT (x) void force_link_function _ ## x (void) {extern int force_link _ ## x; force_link _ ## x = 1; } ' pozwala na umieszczenie makra na górze pliku, z którego wiadomo, że będzie on połączony. Nie ma żadnej różnicy, że funkcja dummy nigdy nie jest wywoływana. –

+1

Wydaje się również działać z funkcją o pustym ciele. Po prostu wywołaj go gdzieś w pliku wykonywalnym lub bibliotece DLL, do której łączysz bibliotekę. – BigSandwich

0

W jaki sposób biblioteka DLL będzie wywoływać funkcje z biblioteki w środowisku wykonawczym? To brzmi trochę trudno w to uwierzyć.

Teraz, jeśli użytkownicy użytkowników DLL zadzwonią do twoich funkcji bibliotecznych, twoje pytanie ma sens. Kompilatory systemu Windows (w przeciwieństwie do kompilatorów Uniksa) eksportują tylko funkcje z biblioteki DLL, jeśli jest to wyraźnie wymagane. Najczęstszym sposobem wykonania tej czynności jest zadeklarowanie funkcji "dllexport", ale można również nazwać funkcje w pliku .DEF, przekazując ją do łącznika. Zauważ, że musisz podać nazwę zmienioną w C++ w pliku .DEF.

+0

, ponieważ są to klasy globalne, które rejestrują się za pomocą kontrolera i nie są połączone w bibliotece dll. – Lodle

+0

Byłoby to przydatne, aby umieścić to w pytaniu. To dobre pytanie, z tym dodatkiem, ale różni się od tego, o co teraz prosiłeś. – MSalters

1

Miałem ten sam problem z systemem wtyczek, w którym fabryki w różnych bibliotekach DLL używały wspólnej głównej fabryki, wszystkiego rejestrując się przy starcie podczas ładowania bibliotek, bez konieczności kompilowania listy wtyczek do użycia. To działało bardzo dobrze pod Linuksem, ale miało dwa problemy pod Windows:

  1. Fabryki nie były częste między bibliotekami DLL. To nie jest twój problem, ale jest powiązany. Mam rozwiązanie tutaj: Ensuring to use common fatories. Spójrz na odpowiedź Jamesa z funkcją set_the_global.
  2. Nie zostały one skonfigurowane podczas uruchamiania, jeśli w głównym pliku nie użyto symbolu biblioteki DLL. Myślę, że to twój problem. Jedyne rozwiązanie, jakie znalazłem, to użycie plików konfiguracyjnych (jeden podprojekt) z listą dostępnych wtyczek (DLL) i wymuszenie ich łączenia za pomocą, w moim przypadku, QLibrary. Korzystanie cmake, domyślną wersję pliku konfiguracyjnego dla każdego podprojektu jest generowane w czasie kompilacji za pomocą następujące makro o nazwie zamiast add_library w każdym katalogu wtyczek:

    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

użyłem pragmy wydaje działa, ale nie dusi się, jeśli nie dodasz linii.

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

Można również połączyć je za pomocą pola Additional Dependencies w zakładce Librarian.

3

Istnieje półoficjalne rozwiązanie tego problemu i here it is.

TL; DR:

'Użyj wejścia z zależnościami biblioteki'.

W języku VS "iniekcje zależności bibliotek" to nazwa plików obj, które stanowią bibliotekę. rzeczywiście można kontrolować to zachowanie w dwóch zakresach:

  1. Per refernce: przez "użyć biblioteki wejść Zależność combo we właściwościach odniesienia. To jest rozwiązanie, którego użyłem osobiście i wspomniałem o in the post. Use Library Dependency Inputs

  2. Per całego pliku wykonywalnego: w projekcie exe Właściwości/C++/Linker/Ogólne/używać wejścia z zależnościami biblioteki -> Tak

historyczna motywacja dla tych magicznych ustawień jest enabling incremental linking in places it wasn't available before, ale ma użyteczny efekt uboczny łączenia bezpośrednio z plikami obj, które są pakowane w bibliotekę, tworząc w ten sposób również obiekty globalne bez odwołań.

0

Testowane MSVC2k17 ...

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

Totally działa. Może to być nawet w statycznie połączonym pliku .lib i przenosi się do pliku wykonywalnego wyjścia i poza nim!

EDYCJA: Możesz nawet umieścić go w makrze, aby uzyskać bonusowe punkty!

EDYCJA: Kolejna uwaga: Musisz włączyć generowanie kodu czasu łączącego./LTCG ... coś

Powiązane problemy