2013-10-27 7 views
6

Jestem w trakcie reorganizacji fizycznego (na dysku) układu large cross-platform C++ project z wieloma zależnościami stron trzecich, zbudowanymi przy użyciu CMake.Fizyczny układ na dysku dużego, wieloplatformowego projektu C++ z wieloma niezależnymi zależnościami

Ponieważ musimy obsługiwać system Windows, platformę, na której nie ma dobrze rozwiniętego menedżera pakietów, od dawna postanowiliśmy włączyć biblioteki stron trzecich, z których korzystamy w drzewie źródłowym. Jednak na innych platformach, które obsługujemy, takich jak Linux i Mac OS X, wiele z tych bibliotek stron trzecich jest dostępnych jako pakiety lub są już obecne w systemie i są łatwo dostępne przez CMake.

Obecny układ projekt jest następująca:

root/ 
    src/ 
     3rd-party-lib1/  (build system modified to output to build/) 
     3rd-party-lib2/  (build system modified to output to build/) 
     project-module1/  (our own code) 
     project-module2/  (our own code) 
    build/     (CMake is invoked from here) 
     3rd-party-lib1-bin/ 
     3rd-party-lib2-bin/ 

Biblioteki osób trzecich zostały manipulowane tak zbudowany, że kiedy oni wyjściowe ich binarne do root/build/<lib>/.

Problemy z tym układzie są wielorakie:

  • Biblioteki osób trzecich nie są w 100% oryginalne. To sprawia, że ​​ich aktualizacja jest nieco trudniejsza, niż jest to wymagane.
  • Katalog zawiera mieszaninę naszego własnego kodu i kodu zewnętrznego, co jest mylące.
  • Katalog src/ jest bardzo duży. Ponieważ src/ zawiera biblioteki stron trzecich, jest bardzo duży w porównaniu do rzeczywistej ilości oryginalnego kodu źródłowego, dzięki czemu tworzenie własnego kodu jest nieco bardziej skomplikowane niż wymagane (nie możemy po prostu zarchiwizować całego katalogu src/).
  • Repozytorium projektu (Git) jest bardzo duże, ze względu na dołączenie bibliotek stron trzecich (które mogą zawierać wiele plików innych niż źródłowe, takich jak dokumentacja, dane testowe itp.), I zwiększa się czas je aktualizujemy. Niestety nie ma tu drogi powrotnej, chyba że zdecydujemy się na ponowne uruchomienie ze świeżym repozytorium (niestety tracąc całą historię commitów).
  • Wiele z dołączonych bibliotek zewnętrznych (np. Zlib, libpng) nie jest w ogóle potrzebnych dla użytkowników budujących projekt w systemie Linux lub Mac OS X, chociaż znacznie upraszczają one działania użytkowników systemu Windows.

Alternatywny układ byłby następujący:

root/ 
    3rdparty/ 
     3rd-party-lib1/  (100% original, contains built artifacts) 
     3rd-party-lib2/  (100% original, contains built artifacts) 
    src/ 
     project-module1/  (our own code) 
     project-module2/  (our own code) 
    build/     (CMake is invoked from here) 

Nasze pliki CWprowadä musiałby być zmodyfikowany, aby szukać plików nagłówkowych i bibliotek stron trzecich we właściwym miejscu dla każdej biblioteki.

Jakie są najlepsze praktyki dotyczące obsługi bibliotek stron trzecich w natywnych projektach wieloplatformowych? Który układ doprowadziłby do najbardziej zaskakującego doświadczenia programistycznego dla naszych programistów na ich platformach? Konkretne przykłady udanych układów z istniejących projektów są również mile widziane.

+1

Może menedżer pakietów dla systemu Windows rozwiąże problem. Próbowałem samemu go zbudować: http://vertexwahn.de/bluego.html - teraz tylko boost i Qt są obsługiwane. W moich własnych projektach stosuję podejście hybrydowe - zakłada się, że instaluje je Boost, Qt, OptiX, Cuda, Windows SDK - inne biblioteki takie jak gtest, OpenEXR, zlib, freetype, glews itp. Są dostarczane z kodem źródłowym. – Vertexwahn

+0

Dzięki za wejście. Oczekujemy również, że użytkownicy mają już Qt i Boost dostępne na swoich komputerach. Moje obawy dotyczą tak naprawdę innych mniejszych i mniej znanych bibliotek, takich jak ILMBase, OpenEXR, Alembic, zlib, libpng, itp. –

+0

Właśnie odkryłem NuGet dla C++: http://blogs.msdn.com/b/vcblog/archive/2013 /04/26/nuget-for-c.aspx. Niektóre biblioteki są już obsługiwane: http://www.nuget.org/profiles/coapp/ Ale nie mam z tym żadnego praktycznego doświadczenia. – Vertexwahn

Odpowiedz

7

Moje doświadczenie sugeruje następujące jak najlepsze praktyki:

  • Kiedy biblioteka osób trzecich open-source służy zupełnie jak jest popełnić lokalną kopię pobranego skompresowanego archiwum wewnątrz głównego git repo , aby uniknąć problemów z łącznością sieciową przed zapobieganiem kompilacjom oprogramowania.

  • Gdy zewnętrzna biblioteka stron trzecich jest prawie używana tak, jak jest, ale musi zostać zmodyfikowana (ta jest powszechna podczas kompilacji krzyżowej: wiele pakietów wymaga drobnych korekt do ich kroków konfiguracji), przechowuj skompresowane archiwum tarball i plik łatki "unified diff" w głównym repozytorium git i zastosuj poprawkę w kroku PATCH_COMMAND ExternalProject_Add.

  • Gdy zewnętrzna biblioteka open source jest (ma być) mocno modyfikowana lub rozbudowywana przez organizację, użyj osobnego repozytorium git do przechowywania wskaźników do repozytorium wyższego poziomu (najłatwiejszy, gdy używa również git, ale wcześniejszego svn można również zarządzać). Zatwierdź zmiany w organizacji w odrębnym oddziale oddziału używanym do odzwierciedlania poprzedniej wersji. Jeśli chcesz, możesz wprowadzić zależność między głównym repozytorium git a tym, ponieważ DOWNLOAD_COMMAND może pobierać bezpośrednio z arbitralnego repozytorium git, nie jest to technicznie konieczne.

  • Rozsądnie jest traktować małe, rzadsze pliki binarne firm trzecich do pojedynczej platformy docelowej, archiwizując je również w ramach głównego repozytorium git. Jednak pliki binarne innych firm, które są dostępne dla różnych platform, są duże lub często ewoluowane powinny być przechowywane w ich własnym repozytorium git i pobierane za pośrednictwem DOWNLOAD_COMMAND, jak wyżej.

+0

+1, ale IMHO nie ma potrzeby udostępniania tarballa/plików binarnych do głównego repozytorium git. Dlaczego po prostu nie tworzysz migawki wersji i nie pobierzesz jej z niestandardowej lokalizacji za pomocą 'ExternalProject_Add'? –

+0

W zależności od okoliczności może to być rozsądna alternatywa - lub nawet użycie ExternalProject_Add_Step może być wystarczające. Istnieje jednak poważne ryzyko, że wiedza na temat sposobu tworzenia tego migawki zostanie z czasem utracona. Aby się przed tym obronić, ważne jest, aby proces tworzenia migawki był rejestrowany w konsekwentnie powtarzalnej formie. Ale, o ile proces ten nie jest naprawdę czasochłonny, nie ma znaczenia w oddzielaniu algorytmu, który wytwarza go z algorytmu generującego główną kompilację. – newbrific

+0

Dzięki @newbrific za doskonałą odpowiedź! Pozostawię to pytanie nieco dłużej, aby nie zniechęcać innych współtwórców do dzielenia się swoimi pomysłami i doświadczeniem. –

Powiązane problemy