CFLAGS vs CPPFLAGS

104

Rozumiem, że CFLAGS (lub CXXFLAGS dla C ++) są dla kompilatora, podczas gdy CPPFLAGS jest używany przez preprocesor.

Ale nadal nie rozumiem różnicy.

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

W jakich okolicznościach muszę udostępnić kompilatorowi dodatkową ścieżkę dołączania?

Ogólnie, jeśli preprocesor znajduje i dołącza potrzebne pliki nagłówkowe, dlaczego kiedykolwiek trzeba mu informować o dodatkowych katalogach dołączania? Jakie w ogóle zastosowanie ma CFLAGS?

(W moim przypadku stwierdziłem, że OBIE z nich pozwalają mi skompilować program, co pogłębia zamieszanie ... Mogę użyć CFLAGS LUB CPPFLAGS, aby osiągnąć mój cel (przynajmniej w kontekście autoconf). Co daje?)

EBM
źródło
2
możliwy duplikat stackoverflow.com/questions/495598/…
Michael Mrozek

Odpowiedzi:

156

Niejawna reguła make do kompilowania programu w C to

%.o:%.c
    $(CC) $(CPPFLAGS) $(CFLAGS) -c -o $@ $<

gdzie $()składnia rozszerza zmienne. Ponieważ oba CPPFLAGSi CFLAGSsą używane w wywołaniu kompilatora, którego używasz do definiowania ścieżek dołączania, jest kwestią osobistego gustu. Na przykład, jeśli foo.cjest to plik w bieżącym katalogu

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

oba będą wywoływać Twój kompilator dokładnie w ten sam sposób, mianowicie

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

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

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

wtedy będą kompilacje

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

ponieważ niejawna reguła C ++ również używa tej CPPFLAGSzmiennej.

Różnica ta daje instrukcji dobre dla którego można używać - jeśli chcesz flagi do wykorzystania dla wszystkich języków umieścić go CPPFLAGS, jeśli jest to dla języka określonego umieścić go w CFLAGS, CXXFLAGSitd. Przykłady tego ostatniego typu zawierają standardowe zgodności lub flagi ostrzegawcze - nie chciałbyś przejść -std=c99do swojego kompilatora C ++!

Możesz wtedy otrzymać coś takiego w swoim pliku makefile

CPPFLAGS=-I/usr/include
CFLAGS=-std=c99
CXXFLAGS=-Weffc++
Scott Wales
źródło
1
Należy pamiętać, że nie można uruchomić samodzielny cppużyciu CPPFLAGSi oczekiwać żadnego rozsądnego rezultatu, ponieważ -std=c99wpływa na której są zdefiniowane symbole (zwłaszcza zamiast makr testowych funkcja). Zamiast tego potrzebujesz $(CC) $(CPPFLAGS) $(CFLAGS) -E.
Jed,
10

To CPPFLAGSmakro służy do określania #includekatalogów.

Oba CPPFLAGSi CFLAGSdziałają w twoim przypadku, ponieważ makereguła (1) łączy przetwarzanie wstępne i kompilację w jednym poleceniu (więc oba makra są używane w poleceniu).

.Jeśli używasz formularza, nie musisz określać jako katalogu dołączonego #include "...". Nie musisz też określać katalogu dołączania standardowego kompilatora. Musisz określić wszystkie inne katalogi nagłówkowe.

Steve Emmerson
źródło
To ma więcej sensu, ale nadal nie rozumiem, co robi CFLAGS. Jeśli, jak wydaje się sugerować, kompilacja w bardziej złożonych projektach jest wykonywana w innym kroku niż przetwarzanie wstępne, czy przetwarzanie wstępne powiedzie się, ale kompilacja zakończy się niepowodzeniem, jeśli CFLAGS nie doda tych samych ścieżek, które CPPFLAGS dodał dla preprocesora? Chyba nie rozumiem, co kompilator robi ze ścieżkami dołączania, jeśli preprocesor przetworzył już dyrektywy #include?
EBM
4
@EB Jeśli kompilujesz wstępnie przetworzone pliki, dołącz ścieżki są niepotrzebne - wymagane nagłówki zostały już dodane do wstępnie przetworzonego źródła (spójrz na wynik po uruchomieniu gcc -Ena pliku - nie ma #includes). Większość nowoczesnych kompilatorów łączy etapy przetwarzania wstępnego i kompilacji, więc nie musisz się tym martwić.
Scott Wales,
0

Aby dodać do tych, którzy wspomnieli o niejawnych regułach, najlepiej sprawdzić, co marka zdefiniowała niejawnie i dla twojego środowiska, używając:

make -p

Na przykład:

%.o: %.c
    $(COMPILE.c) $(OUTPUT_OPTION) $<

który się rozszerza

COMPILE.c = $(CXX) $(CXXFLAGS) $(CPPFLAGS) $(TARGET_ARCH) -c

Spowoduje to również wydrukowanie # environmentdanych. Tutaj znajdziesz ścieżkę dołączania GCC, wśród innych przydatnych informacji.

C_INCLUDE_PATH=/usr/include

W rezultacie, jeśli chodzi o wyszukiwanie, ścieżek jest wiele, światło jest jedno ... lub coś w tym rodzaju.

  1. C_INCLUDE_PATHjest ogólnosystemowy, ustaw go w powłoce *.rc.
  2. $(CPPFLAGS) jest dla ścieżki dołączania preprocesora.
  3. Jeśli chcesz dodać ogólną ścieżkę wyszukiwania marki, użyj:
VPATH = my_dir_to_search

... a nawet bardziej szczegółowe

vpath %.c src
vpath %.h include

make używa VPATH jako ogólnej ścieżki wyszukiwania, więc używaj jej ostrożnie. Jeśli plik istnieje w więcej niż jednej lokalizacji wymienionej w VPATH, make zajmie się pierwszym wystąpieniem na liście.

67 Hz
źródło