Jestem wielkim fanem podmodułów Git . Lubię być w stanie śledzić zależność wraz z jej wersją, abyś mógł przywrócić poprzednią wersję swojego projektu i mieć odpowiednią wersję zależności, aby zbudować bezpiecznie i czysto. Co więcej, łatwiej jest wydać nasze biblioteki jako projekty open source, ponieważ historia bibliotek jest odrębna od historii aplikacji, które od nich zależą (i które nie będą otwarte).
Konfiguruję przepływ pracy dla wielu projektów w pracy i zastanawiałem się, jak by to było, gdybyśmy przyjęli to podejście trochę ekstremalnie zamiast jednego projektu monolitycznego. Szybko zdałem sobie sprawę, że istnieje potencjalna puszka robaków, które naprawdę wykorzystują podmoduły.
Przypuśćmy parę wniosków: studio
a player
, i bibliotek zależnych core
, graph
oraz network
, gdzie zależności są w następujący sposób:
core
jest samodzielnygraph
zależy odcore
(podmoduł w./libs/core
)network
zależy odcore
(podmoduł w./libs/core
)studio
zależy odgraph
inetwork
(podmoduły./libs/graph
i./libs/network
)player
zależy odgraph
inetwork
(podmoduły./libs/graph
i./libs/network
)
Załóżmy, że korzystamy z CMake i że każdy z tych projektów ma testy jednostkowe i wszystkie prace. Każdy projekt (w tym studio
i player
) musi mieć możliwość samodzielnej kompilacji w celu wykonywania pomiarów kodu, testowania jednostkowego itp.
Chodzi o to, że rekurencyjne git submodule fetch
, a następnie masz następującą strukturę katalogów:
studio/
studio/libs/ (sub-module depth: 1)
studio/libs/graph/
studio/libs/graph/libs/ (sub-module depth: 2)
studio/libs/graph/libs/core/
studio/libs/network/
studio/libs/network/libs/ (sub-module depth: 2)
studio/libs/network/libs/core/
Zauważ, że core
klonowany jest dwukrotnie w studio
projekcie. Oprócz marnowania miejsca na dysku mam problem z kompilacją systemu, ponieważ buduję core
dwa razy i potencjalnie otrzymuję dwie różne wersje core
.
Pytanie
Jak zorganizować podmoduły, aby uzyskać zależną od wersji zależność i samodzielną kompilację bez uzyskiwania wielu kopii wspólnych zagnieżdżonych podmodułów?
Możliwe rozwiązanie
Jeśli zależność od biblioteki jest w pewnym sensie sugestią (tj. Jest „znana z pracy z wersją X” lub „tylko oficjalnie obsługiwana jest wersja X”), a potencjalnie zależne aplikacje lub biblioteki są odpowiedzialne za tworzenie z dowolną wersją, którą lubią, to Mogę sobie wyobrazić następujący scenariusz:
- Poproś system kompilacji
graph
inetwork
powiedz, gdzie mają znaleźćcore
(np. Za pomocą kompilatora zawierają ścieżkę). Zdefiniuj dwa cele kompilacji, „autonomiczny” i „zależność”, gdzie „samodzielny” jest oparty na „zależności” i dodaje ścieżkę dołączania, aby wskazywać na lokalnycore
podmoduł. - Wprowadź dodatkową zależność:
studio
włączonecore
. Następniestudio
budujecore
, ustawia zawierać ścieżkę do własnej kopiicore
podmodułem, a następnie budujegraph
inetwork
w trybie „zależność”.
Wynikowa struktura folderów wygląda następująco:
studio/
studio/libs/ (sub-module depth: 1)
studio/libs/core/
studio/libs/graph/
studio/libs/graph/libs/ (empty folder, sub-modules not fetched)
studio/libs/network/
studio/libs/network/libs/ (empty folder, sub-modules not fetched)
Wymaga to jednak pewnej magii systemu kompilacji (jestem pewien, że można to zrobić za pomocą CMake) i trochę ręcznej pracy przy aktualizacjach wersji (aktualizacja graph
może również wymagać aktualizacji core
i network
uzyskania kompatybilnej wersji core
we wszystkich projektach) .
Masz jakieś przemyślenia na ten temat?
źródło
Odpowiedzi:
Jestem bardzo spóźniony na tę imprezę, ale twoje pytanie wciąż nie wydaje się pełnej odpowiedzi i jest to dość znaczący hit Google.
Mam dokładnie taki sam problem z C ++ / CMake / Git / Submodules i mam podobny problem z MATLAB / Git / Submodules, co powoduje dodatkową dziwność, ponieważ MATLAB nie jest skompilowany. Ostatnio natknąłem się na ten film , który wydaje się proponować „rozwiązanie”. Nie podoba mi się to rozwiązanie, ponieważ zasadniczo oznacza wyrzucanie submodułów, ale eliminuje problem. Jest tak, jak zaleca @errordeveloper. Każdy projekt nie ma podmodułów. Aby zbudować projekt, utwórz superprojekt, aby go zbudować, i dołącz go jako element równorzędny do jego zależności.
Twój projekt do opracowania
graph
może wyglądać następująco:a następnie twoim projektem dla studia może być:
Super-projekty to tylko podstawa
CMakeLists.txt
i kilka podmodułów. Ale żaden z projektów nie ma samych podmodułów.Jedyne koszty, jakie widzę w tym podejściu, to rozpowszechnianie błahych „superprojektów”, które są po prostu poświęcone budowaniu twoich prawdziwych projektów. A jeśli ktoś przejmie jeden z twoich projektów, nie można łatwo stwierdzić bez znalezienia super-projektu, jakie są jego zależności. Może to na przykład sprawić, że będzie on bardzo brzydki na Github.
źródło
Przypuszczam, że kiedy integrujesz oba moduły
graph
inetwork
podmodułystudio
, zawsze musisz mieć tę samą wersjęcore
w danym momencie w historiistudio
. Chciałbym podlinkowaćstudio/libs/core
podmoduł dostudio/libs/{graph,network}/libs
.Aktualizacja:
Stworzyłem wiele repozytoriów z podanymi przez ciebie zależnościami:
v1
iv2
są dwiema różnymi wersjamicore
.graph
obsługuje wersję 2, podczas gdynetwork
wymaga trochę pracy i utknął w wersji 1. Wstudio
, lokalne wersjecore
obu punktów dov1
, aby mieć działający program. Teraz, oprócz perspektywy kompilacji, wszystko działa dobrze z submodułami.Teraz mogę usunąć następujący katalog:
I zamień go na symboliczny link:
Lokalnie zatwierdzam tę zmianę i tracę możliwość posiadania dwóch oddzielnych wersji
core
wewnątrzstudio
, ale buduję tylkocore
raz. Kiedy będę gotowy na uaktualnieniev2
, mogę:... w studio / libs / network.
źródło
graph/libs/core
zewnątrz, nie używasz submodułu. Jeśli łączysz zstudio/libs/core
jedną z bibliotek własnych podmodułu, to którą wybierasz,graph
czynetwork
? Co ponadto dzieje się, gdy ma trzy lub więcej warstw głębokości? Wreszcie, co jeślicore
może być szereg zmian. To oczywiste, że nie chcesz się połączyć do obu wersjicore
, żegraph
inetwork
używasz.core
byłby submodułem pobranym z oryginalnejcore
biblioteki, zaktualizowanym do wersji kompatybilnej z obydwomagraph
inetwork
(musisz zdecydować, która z nich jest dobra). Dowiązania symboliczne zostałyby dodane w lokalnychgraph
inetwork
podmodułach (nieruchome).graph
inetwork
które wskazywałyby poza własne repozytorium (np. Gdzie indziej wstudio
projekcie). Skąd wiedzą, kiedy użyć własnego podmodułu, a kiedy użyć dowiązania symbolicznego? Być może powinieneś dodać przykład, aby zademonstrować swój tok myślenia.Spłaszczyłbym go, aby głębokość podmodułu wynosiła tylko jeden, i mieć repozytorium, które pomieściłoby wszystkie moduły jako podmoduły i nic poza README i skryptami kompilacji. Dla każdego pakietu istniałby osobny skrypt kompilacji łączący jego zależności. W przeciwnym razie możesz mieć osobne repozytorium dla pakietu.
źródło
Nie użyłbym submodułów.
To kuszące, tak jak kiedyś w przypadku svn-externals. Czy możesz być jednak pewien, że wszystkie projekty, które łączysz, są nadal w tym samym miejscu w ciągu roku? A co za pięć?
Dlatego po prostu kopiuję wszystkie wymagane zależności do mojego projektu. Oznacza to, że dopóki moje repozytorium jest ważne, mogę sprawdzić dokładny stan.
Zasadniczo mam następującą strukturę folderów:
Chociaż nie jest to bardzo miłe z punktu widzenia miejsca na dysku, cenię sobie gwarancję, że mogę sprawdzić każdy zarejestrowany stan, o ile repo jest dostępne znacznie wyżej.
Ponadto istnieje wiele problemów z submodułami opisanymi tutaj
źródło
W obliczu dokładnie tego samego problemu. Jednym z rozwiązań mogłoby być jakieś repo
libs
, które trzymaćcore
,network
,graph
jak submodules i zaledwie CMakeLists że powie każdy z bibliotekami, gdzie znaleźć jego zależności. Każda aplikacja będzie miała terazlibs
podmoduł i będzie używać tylko niezbędnych bibliotek.Testowanie każdej biblioteki można skonfigurować na 2 sposoby:
źródło
graph
nie musisz wiedzieć onetwork
- nie przekazujnetwork
rzeczy związanych zgraph
podkatalogiem