Powiedzmy, że mam plik makefile z regułą
%.o: %.c
gcc -Wall -Iinclude ...
Chcę, aby * .o było odbudowywane po każdej zmianie pliku nagłówkowego. Zamiast opracowywać listę zależności, za każdym razem, gdy /include
zmieni się dowolny plik nagłówkowy , wszystkie obiekty w katalogu muszą zostać odbudowane.
Nie mogę wymyślić fajnego sposobu na zmianę reguły, aby to uwzględnić, jestem otwarty na sugestie. Dodatkowe punkty, jeśli lista nagłówków nie musi być zakodowana na stałe
dependencies
makefile
header-files
Mikrofon
źródło
źródło
Odpowiedzi:
Jeśli używasz kompilatora GNU, kompilator może utworzyć dla Ciebie listę zależności. Fragment pliku Makefile:
lub
gdzie
SRCS
jest zmienną wskazującą na całą listę plików źródłowych.Jest też narzędzie
makedepend
, ale nigdy nie podobało mi się tak bardzogcc -MM
źródło
depend
uruchomić tylko wtedy, gdy zmieniły się pliki źródłowe? Wydaje się, że działa za każdym razem, niezależnie ...build/file.o
?Większość odpowiedzi jest zaskakująco skomplikowana lub błędna. Jednak proste i solidne przykłady zostały opublikowane w innym miejscu [przegląd kodowy ]. Prawdą jest, że opcje oferowane przez preprocesor gnu są nieco zagmatwane. Jednak usunięcie wszystkich katalogów z celu kompilacji
-MM
jest udokumentowane i nie jest błędem [ gpp ]:-MMD
Prawdopodobnie chcesz skorzystać z (nieco nowszej) opcji. Dla kompletności przykład pliku makefile, który obsługuje wiele katalogów src i buduje katalogi z komentarzami. Prosta wersja bez katalogów kompilacji znajduje się w [ codereview ].Ta metoda działa, ponieważ jeśli istnieje wiele linii zależności dla jednego celu, zależności są po prostu łączone, np .:
jest równa:
jak wspomniano w: Makefile wiele linii zależności dla jednego celu?
źródło
CPP
należy przeczytaćCPPS
a.cpp
,b.cpp
) w./src/
, czy to podstawienie nie spowodowałoby$(OBJ)=./build/src/a.o ./build/src/b.o
?Jak napisałem tutaj, gcc może tworzyć zależności i kompilować w tym samym czasie:
Parametr „-MF” określa plik, w którym mają być przechowywane zależności.
Myślnik na początku „-include” mówi Make, aby kontynuował, gdy plik .d nie istnieje (np. Przy pierwszej kompilacji).
Zauważ, że wydaje się, że w gcc jest błąd dotyczący opcji -o. Jeśli ustawisz nazwę pliku obiektu na obj / _file__c.o, to wygenerowany plik .d nadal będzie zawierał plik .o, a nie obj / _file__c.o.
źródło
man gcc
mówi-MM
implikuje-E
, co „zatrzymuje się po wstępnym przetworzeniu”. Zamiast-MMD
tego potrzebujesz : stackoverflow.com/a/30142139/895245A może coś takiego:
Możesz również użyć symboli wieloznacznych bezpośrednio, ale zwykle okazuje się, że potrzebuję ich w więcej niż jednym miejscu.
Zauważ, że działa to dobrze tylko w małych projektach, ponieważ zakłada, że każdy plik obiektowy zależy od każdego pliku nagłówkowego.
źródło
make clean all
każdym razem.gcc
Linia nie jest wykonywany w ogóle, ale wbudowany reguły (%o: %.c
reguła) jest wykonywany zamiast.Powyższe rozwiązanie Martina działa świetnie, ale nie obsługuje plików .o, które znajdują się w podkatalogach. Godric zwraca uwagę, że flaga -MT rozwiązuje ten problem, ale jednocześnie zapobiega poprawnemu zapisaniu pliku .o. Następujące osoby zadbają o oba te problemy:
źródło
To wykona zadanie dobrze, a nawet obsłuży określone podkatalogi:
przetestowałem to z gcc 4.8.3
źródło
Oto dwuwierszówka:
Działa to z domyślną recepturą na make, o ile masz listę wszystkich plików obiektów w
OBJS
.źródło
Wolę to rozwiązanie, zamiast zaakceptowanej odpowiedzi Michaela Williamsona, wychwytuje zmiany w źródłach + plikach wbudowanych, następnie źródłach + nagłówkach, a na końcu tylko źródłach. Zaletą jest to, że cała biblioteka nie jest ponownie kompilowana, jeśli wprowadzono tylko kilka zmian. Nie jest to wielka uwaga w przypadku projektu z kilkoma plikami, jeśli jednak masz 10 lub 100 źródeł, zauważysz różnicę.
źródło
U mnie działa:
źródło
Nieco zmodyfikowana wersja Sophie odpowiedź , która pozwala wysyłać * .d pliki do innego folderu (będę tylko wkleić interesującą część, która generuje pliki z zależnościami):
Zwróć uwagę, że parametr
służy do zapewnienia, że cele (tj. nazwy plików obiektów) w wygenerowanych plikach * .d zawierają pełną ścieżkę do plików * .o, a nie tylko nazwę pliku.
Nie wiem, dlaczego ten parametr NIE jest potrzebny, gdy używam -MMD w połączeniu z -c (jak w wersji Sophie ). W tej kombinacji wydaje się, że zapisuje pełną ścieżkę plików * .o do plików * .d. Bez tej kombinacji -MMD zapisuje również tylko czyste nazwy plików bez żadnych składników katalogów do plików * .d. Może ktoś wie, dlaczego -MMD zapisuje pełną ścieżkę w połączeniu z -c. Nie znalazłem żadnej wskazówki na stronie podręcznika g ++.
źródło