2008-09-18 24 views
21

Używam gcc do generowania pliku zależności, ale moje reguły kompilacji umieszczają dane wyjściowe w podkatalogu. Czy jest jakiś sposób, aby powiedzieć gcc, aby umieścić mój prefiks podkatalogu w pliku zależności, który generuje dla mnie?Generowanie zależności gcc dla innego katalogu wyjściowego

gcc $(INCLUDES) -E -MM $(CFLAGS) $(SRC) >>$(DEP) 

Odpowiedz

18

Odpowiedź jest w GCC manual: użyć flagi -MT.

-MT target

zmienić cel reguły emitowanego przez pokolenia zależności. Domyślnie CPP przyjmuje nazwę głównego pliku wejściowego, usuwa wszelkie składniki katalogu i dowolny przyrostek pliku, taki jak .c i dołącza zwykły sufiks obiektu. Rezultatem jest cel.

Opcja -MT ustawi cel na dokładnie taki, jaki określisz. Jeśli chcesz mieć wiele celów, możesz je określić jako pojedynczy argument dla -MT lub użyć wielu opcji -MT.

Na przykład -MT '$(objpfx)foo.o' może dać

$(objpfx)foo.o: foo.c 
+0

'-MT' nie jest dostępny dla mojego gcc 2.9.5, gość powinien być dostępny 3.xx powyżej – checksum

+2

@checksum: ... nie było [2.9.5] (http://gcc.gnu.org /gcc-2.95/) został wydany> 14 lat temu? –

+0

Tak, znalazłem to podczas utrzymywania starszego kodu z nieaktualną platformą kompilacji. : | Nadal korzysta z wersji 2.9.1.57 (było to wywołanie egcs zamiast gcc), a dobrą cechą jest to, że ma minimalną zależność tylko z 4 plikami i mniej niż 700k. :) Złe jest to, że nie ma wsparcia '-MT'. :( – checksum

0

Jeśli istnieje argument na to w gcc, nie wiem, co to jest. Kończymy wyprowadzanie zależności przez sed, aby przepisać wszystkie wystąpienia .o jako $ {OBJDIR} /. O

0

Ok, tylko po to, aby upewnić się, że mam właściwe pytanie: Zakładam, że masz test. c, który obejmuje test.h, a chcesz wygenerować subdir/test.d (podczas nie generujący podkat/test.o) gdzie podkat/test.d zawiera

subdir/test.o: test.c test.h 

zamiast

test.o: test.c test.h 

to właśnie dostajesz teraz. Czy to prawda?

Nie mogłem wymyślić łatwego sposobu wykonania dokładnie tego, o co prosisz. Jednak patrząc na http://www.gnu.org/software/gcc/news/dependencies.html, jeśli chcesz utworzyć plik .d podczas generowania pliku .o, można użyć

gcc $ (zawiera) -MMD $ (CFLAGS) $ (SRC) -o $ (sUBDIR)/$ (OBJ)

(Zważywszy SRC = test.c, sUBDIR = podkat i OBJ = test.o) To stworzy zarówno podkat/test.o i podkat/test.d, gdzie subdir/test.d zawiera pożądane wyjście jak wyżej. Nadzieja, która pomaga.

0
  1. [GNU] make denerwuje się, jeśli nie umieścisz wyjścia w bieżącym katalogu. To, co naprawdę powinieneś zrobić, to uruchomić make z katalogu build i użyć zmiennej VPATH make, aby zlokalizować kod źródłowy. Jeśli okłamiesz kompilator, wcześniej czy później zemści się.

  2. Jeśli nalegasz na generowanie obiektów i zależności w jakimś innym katalogu, musisz użyć argumentu -o w odpowiedzi od Emile'a.

36

Jestem zakładając używasz GNU make i GCC. Najpierw dodaj zmienną do przechowywania listy plików zależności. Zakładając, że masz już jeden, który zawiera wszystkie nasze źródła:

SRCS = \ 
     main.c \ 
     foo.c \ 
     stuff/bar.c 

DEPS = $(SRCS:.c=.d) 

następnie dołączyć wygenerowanych zależności w makefile:

include $(DEPS) 

następnie dodać tę regułę Wzór:

# automatically generate dependency rules 

%.d : %.c 
     $(CC) $(CCFLAGS) -MF"[email protected]" -MG -MM -MP -MT"[email protected]" -MT"$(<:.c=.o)" "$<" 

# -MF write the generated dependency rule to a file 
# -MG assume missing headers will be generated and don't stop with an error 
# -MM generate dependency rule for prerequisite, skipping system headers 
# -MP add phony target for each header to prevent errors when header is missing 
# -MT add a target to the generated dependency 

„$ @ "jest celem (rzecz po lewej stronie:)," $ < "jest warunkiem wstępnym (rzecz po prawej stronie:). Wyrażenie "$ (<: .c = .o)" zastępuje rozszerzenie .c z .o.

W tym przypadku należy wygenerować regułę z dwoma celami, dodając dwukrotnie parametr -MT; dzięki temu zarówno plik .o, jak i plik .d zależą od pliku źródłowego i jego nagłówków; w ten sposób plik zależności zostanie automatycznie zregenerowany po każdej zmianie odpowiednich plików .c lub .h.

Opcje -MG i -MP zapobiegają maniakom, jeśli brakuje pliku nagłówkowego.

+3

Dla mnie, na gcc 4.1.2, gmake 3.8.1, jeśli plik nagłówkowy nie istnieje, przepis "$ (CC) $ (CCFLAGS) -MF" $ @ "-MG -MM -MP -MT" $ @ "-MT" $ (<:. c = .o) "" nieskończone pętle $ // "// Usunięcie opcji -MP zatrzymuje nieskończoną pętlę –

9

może podoba Ci się ta wersja krótsza odpowiedzi Ks McCaughey za:

SRCS = \ 
    main.c \ 
    foo.c \ 
    stuff/bar.c 

DEPS = $(SRCS:.c=.d)

Dodaj -include $(DEPS) UWAGA - prefiks, który wycisza błędy jeśli .d plików jeszcze nie istnieją.

Nie ma potrzeby stosowania osobnej reguły wzorca do generowania plików zależności. Po prostu dodaj -MD lub -MMD do normalnej linii kompilacji, a pliki .d zostaną wygenerowane w tym samym czasie, gdy zostaną skompilowane pliki źródłowe. Na przykład:

%.o: %.c 
    gcc $(INCLUDE) -MMD -c $< -o [email protected] 

# -MD can be used to generate a dependency output file as a side-effect of the compilation process. 
+2

Przy okazji pamiętaj, aby unikać umieszczania" włączania " "nad twoim pierwszym celem.Logiczne jest umieszczenie go na dole pliku Makefile, ponieważ zawsze było to tradycyjne miejsce do umieszczania zależności, kiedy trzeba je było ręcznie wykonać! –

3

Detailing na odpowiedź DGentry za to działa dobrze dla mnie:

.depend: $(SOURCES) 
    $(CC) $(CFLAGS) -MM $(SOURCES) | sed 's|[a-zA-Z0-9_-]*\.o|$(OBJDIR)/&|' > ./.depend 

Działa to również w przypadku, gdy istnieje tylko jeden plik depency że zawiera zasady zależnościami dla wszystkich plików źródłowych .