2009-08-05 3 views
25

Potrzebuję pomocy w pisaniu kodu między platformami; nie aplikacja, ale biblioteka.Dynamiczne biblioteki C++ Cross Platform; Linux i Windows

Tworzę bibliotekę zarówno statyczną jak i dynamiczną z większością prac rozwojowych wykonywanych w Linuksie, mam bibliotekę statyczną i współdzieloną wygenerowaną w Linuksie, ale teraz chciałem wygenerować wersję Windows statycznej i dynamicznej biblioteki w formie z .lib i .dll przy użyciu tego samego kodu źródłowego.

Czy to możliwe? Trochę się martwię, ponieważ zauważyłem wygenerowanie plików Windows .dll wymaganych przy użyciu _dllspec lub czegoś podobnego w kodzie źródłowym.

Jeśli nie, to ktoś może doradzić mi najlepsze i najszybsze rozwiązanie, aby mój kod został skompilowany w systemie Windows. Nie muszę robić kompilacji pod Linuksem, cieszę się, że mogę to zrobić bezpośrednio pod Windows. Używam również dwóch zewnętrznych bibliotek, które są boost i Xerces XML, które zainstalowałem zarówno w moim systemie Windows i systemie Linux, więc mam nadzieję, że nie powinny być problemem.

To, czego naprawdę chcę, to mieć jedną kopię kodu źródłowego, którą można skompilować pod Linuksem i Windows, aby wygenerować biblioteki specyficzne dla każdej platformy. Nie obchodzi mnie, że muszę edytować kod na korzyść systemu Windows lub Linux, o ile mogę mieć jedną kopię kodu źródłowego.

+0

Kompilacja krzyżowa zazwyczaj odnosi się do oprogramowania budowlanego na jednej platformie, która ma działać na innej. Ponieważ mówisz, że chcesz kodu źródłowego, który może być skompilowany zarówno na Linuksie, jak i na Windowsie, twoje pytanie dotyczy raczej pisania przenośnej, wieloplatformowej bazy kodu źródłowego niż kompilacji skrośnej. –

+0

GIYF Właściwie, w tym przypadku, libtool jest twoim przyjacielem ... –

+0

Podczas czekania na odpowiedzi, sprawdź CMake: http://www.cmake.org/ – Pete

Odpowiedz

18

Zasadniczo istnieją dwie kwestie trzeba być związane z:

  1. wymóg, że w systemie Windows, DLL wyraźnie eksportuje symbole, które powinny być widoczne dla świata zewnętrznego (przez __declspec(dllexport) i
  2. Będąc w stanie utrzymać system budowlanej (idealnie, nie trzeba utrzymać oddzielny makefile i Microsoft Visual C++ projektu/roztwór)

w pierwszym, trzeba będzie dowiedzieć się o __declspec(dllexport). na Tylko projekty Windows, zazwyczaj jest to realizowane w sposób opisany w mojej odpowiedzi na this question. Możesz rozszerzyć ten krok dalej, upewniając się, że twój symbol eksportu (taki jak MY_PROJECT_API) jest zdefiniowany, ale rozwija się do niczego podczas budowania dla Linuksa. W ten sposób możesz dodać symbole eksportu do kodu w zależności od potrzeb systemu Windows bez wpływu na kompilację systemu Linux.

Po drugie, można zbadać pewien rodzaj wieloplatformowego systemu kompilacji.

Jeśli nie masz nic przeciwko zestawowi narzędzi GNU, możesz chcieć zbadać libtool (być może w połączeniu z automake i autoconf). Narzędzia są obsługiwane natywnie w systemie Linux i obsługiwane w systemie Windows za pośrednictwem Cygwin lub MinGW/MSYS. MinGW daje także opcję kompilacji krzyżowej, czyli budowania natywnych binariów Windows podczas pracy z Linuksem. Dwa zasoby, które uznałem za przydatne w nawigacji Autotools (w tym libtool) to "Autobook" (w szczególności sekcja na temat DLLs and Libtool) i Alexandre Duret-Lutz's PowerPoint slides.

Jak wspomnieli inni, opcja CMake jest również opcją, ale nie mogę samodzielnie o tym mówić.

+0

dziękuję, zrobiłem kilka wyszukiwania google i domyślam się, że przeszukałem złe rzeczy, libtool brzmi interesująco i być może cmake jak ktoś wspomniany powyżej. Jestem trochę nowy w Linuksie, więc te narzędzia nie szybko dzwonią: p –

9

Możesz całkiem łatwo zrobić to za pomocą # ifdef. W systemie Windows _WIN32 powinny być określone przez kompilator (nawet do 64 bit), a więc kod jak

#ifdef _WIN32 
# define EXPORTIT __declspec(dllexport) 
#else 
# define EXPORTIT 
#endif 

EXPORTIT int somefunction(); 

powinno działać OK dla Ciebie.

+0

hmm tak myślałem o tym, zobaczę, jak to pójdzie, może użyć tego jako mojego ostatniego ratunku, jeśli nie mam szczęścia z powyższe narzędzia –

+0

@iQ: Nadal będziesz musiał to robić, nawet przy użyciu powyższych narzędzi. Nie zajmują się eksportowaniem, po prostu ukrywają niektóre różnice między procesem kompilacji na różnych platformach. –

+0

tak, zgaduję, że masz rację, będę musiał użyć makr. Obecnie próbuję spojrzeć na blockblocks, które moim zdaniem może automatycznie zdefiniować plik .def, chociaż nie wiem, jak dobrze lub źle. Będę musiał trochę poeksperymentować. –

7

Może to lepiej, jeśli dodać extern "C" !!!,

/* plik CMakeLists.txt */

SET (LIB_TYPE SHARED) 

ADD_LIBRARY(MyLibrary ${LIB_TYPE} MyLibrary.h) 

/* plik MyLibrary.h */

#if defined(_WIN32) || defined(__WIN32__) 

    #if defined(MyLibrary_EXPORTS) // add by CMake 

    #define MYLIB_EXPORT extern "C" __declspec(dllexport) 
    #else 

    #define MYLIB_EXPORT extern "C" __declspec(dllimport) 

    #endif /* MyLibrary_EXPORTS */ 

#elif defined(linux) || defined(__linux) 

#define MYLIB_EXPORT 

#endif 


MYLIB_EXPORT inline int Function(int a) 

{ 
    return a ; 
} 
+1

Z miłości do Boga, proszę, użyj ładniejszego formatu! – tstenner

+0

@tstenner chcesz powiedzieć, że nie tylko absolutnie UWIELBIAM, kiedy ludzie tworzą swój własny styl formatowania w locie podczas pisania swojego kodu? :) –

+0

@tstenner zgodził się .. ten "format" to też .. jak mogę powiedzieć .. –