2010-05-02 15 views
79

Rozumiem, że CFLAGS (lub CXXFLAGS dla C++) są dla kompilatora, natomiast CPPFLAGS jest używane przez preprocesor.CFLAGS kontra CPPFLAGS

Ale nadal nie rozumiem różnicy.

Potrzebuję podać ścieżkę dołączania do pliku nagłówkowego, który jest dołączony do #include - ponieważ #include jest dyrektywą preprocesora, czy preprocesor (CPPFLAGS) jest jedyną rzeczą, na której mi zależy?

W jakich okolicznościach należy podać kompilatorowi dodatkową ścieżkę dołączania?

Ogólnie, jeśli preprocesor znajduje i zawiera potrzebne pliki nagłówka, dlaczego trzeba go kiedykolwiek poinformować o dodatkowych katalogach? Jaki jest pożytek z CFLAGS?

(w moim przypadku okazało się, że faktycznie OBA z nich pozwala mi skompilować mój program, który dodaje do zamieszania ... mogę użyć CFLAGS LUB CPPFLAGS aby osiągnąć swój cel (w autoconf przynajmniej kontekst). Co daje?)

+1

możliwe duplikat http://stackoverflow.com/questions/495598/difference-between-cppflags-and-cxxflags-in-gnu -make –

Odpowiedz

120

make niejawny reguła kompilacji programu C jest

%.o:%.c 
    $(CC) $(CPPFLAGS) $(CFLAGS) -c -o [email protected] $< 

gdzie składnia $() rozszerza zmienne. Ponieważ w wywołaniu kompilatora używane są zarówno CPPFLAGS, jak i CFLAGS, których używasz do definiowania ścieżek zawierających, jest to kwestia osobistego gustu. Na przykład, jeśli foo.c plik jest w katalogu bieżącym

make foo.o CPPFLAGS="-I/usr/include" 
make foo.o CFLAGS="-I/usr/include" 

będzie zarówno zadzwonić kompilator dokładnie w ten sam sposób, a mianowicie

gcc -I/usr/include -c -o foo.o foo.c 

Różnica między nimi wchodzi w grę, gdy masz wiele języków które muszą zawierać te same ścieżki, na przykład, jeśli masz bar.cpp następnie spróbuj

make bar.o CPPFLAGS="-I/usr/include" 
make bar.o CFLAGS="-I/usr/include" 

następnie kompilacje będzie

g++ -I/usr/include -c -o bar.o bar.cpp 
g++ -c -o bar.o bar.cpp 

jako, że domniemana reguła C++ również używa zmiennej CPPFLAGS.

Różnica ta daje dobry przewodnik dla którego można używać - jeśli chcesz flagi do wykorzystania dla wszystkich języków umieścić go w CPPFLAGS, jeśli to dla określonego języka umieścić go w CFLAGS, CXXFLAGS itd Przykładami tych ostatnich typ zawiera flagi zgodności standardowej lub ostrzegawczej - nie chcesz przekazać -std=c99 do kompilatora C++!

Można wtedy skończyć z czymś takim w swoim makefile

CPPFLAGS=-I/usr/include 
CFLAGS=-std=c99 
CXXFLAGS=-Weffc++ 
+0

Należy zauważyć, że nie można uruchomić autonomicznego 'cpp' przy użyciu' CPPFLAGS' i spodziewać się jakiegokolwiek rozsądnego wyniku, ponieważ '-std = c99' wpływa na to, które symbole są zdefiniowane (zwłaszcza w miejsce makr testów właściwości). Zamiast tego potrzebujesz '$ (CC) $ (CPPFLAGS) $ (CFLAGS) -E'. – Jed

2

Masz na myśli implicit make rules.

+0

Podczas gdy ten link może odpowiedzieć na pytanie, lepiej umieścić tutaj istotne części odpowiedzi i podać link do odniesienia. Odpowiedzi dotyczące linków mogą stać się nieprawidłowe, jeśli strona z linkami się zmieni. - [Z recenzji] (/ recenzja/niskiej jakości-posts/18639008) – Ctznkane525

9

Makro CPPFLAGS służy do określania katalogów #include.

Zarówno CPPFLAGS i CFLAGS praca w swojej sprawie, ponieważ make (1) zasada łączy zarówno wyprzedzającym i zestawiania w jednym poleceniu (tak oba makra są używane w poleceniu).

Nie musisz podawać . jako katalogu włączeń, jeśli używasz formularza #include "...". Nie musisz także określać standardowego katalogu dołączania kompilatora. Musisz podać wszystkie pozostałe katalogi-include.

+0

Ma to więcej sensu, ale nadal nie widzę, co robi CFLAGS. Jeśli, jak wydajesz się sugerować, kompilacja w bardziej złożonych projektach jest wykonywana w oddzielnym kroku od wstępnego przetwarzania, czy wstępne przetwarzanie zakończy się pomyślnie, ale kompilacja się nie powiedzie, jeśli CFLAGS nie doda tych samych ścieżek, które dodano CPPFLAGS do preprocesora? Chyba nie rozumiem, co robi kompilator ze ścieżkami włączeń, jeśli preprocesor już przetworzył dyrektywy #include? – EBM

+3

@EB Jeśli kompilujesz wstępnie przetworzone pliki, to wtedy ścieżki są niepotrzebne - wymagane nagłówki zostały już dodane do wstępnie przetworzonego źródła (spójrz na dane wyjściowe po uruchomieniu 'gcc -E' na pliku - nie ma żadnego # obejmuje). Większość współczesnych kompilatorów łączy etapy przetwarzania wstępnego i kompilacji, więc nie musisz się tym martwić. –