CFLAGS vs CPPFLAGS

103

Saya memahami bahwa CFLAGS (atau CXXFLAGS untuk C ++) adalah untuk compiler, sedangkan CPPFLAGS digunakan oleh preprocessor.

Tapi saya masih belum mengerti bedanya.

Saya perlu menentukan jalur penyertaan untuk file header yang disertakan dengan #include - karena #include adalah arahan preprocessor, apakah preprocessor (CPPFLAGS) adalah satu-satunya hal yang saya pedulikan?

Dalam keadaan apa saya perlu memberi kompiler jalur penyertaan tambahan?

Secara umum, jika preprocessor menemukan dan menyertakan file header yang diperlukan, mengapa perlu diberi tahu tentang tambahan direktori include? Apa gunanya CFLAGS?

(Dalam kasus saya, saya benar-benar menemukan bahwa KEDUA ini memungkinkan saya untuk mengkompilasi program saya, yang menambah kebingungan ... Saya dapat menggunakan CFLAGS ATAU CPPFLAGS untuk mencapai tujuan saya (setidaknya dalam konteks autoconf). Apa yang memberi?)

EBM
sumber
2
kemungkinan duplikat stackoverflow.com/questions/495598/…
Michael Mrozek

Jawaban:

153

Aturan implisit make untuk kompilasi program C adalah

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

dimana $()sintaks memperluas variabel. Karena keduanya CPPFLAGSdan CFLAGSdigunakan dalam panggilan kompilator, yang Anda gunakan untuk mendefinisikan jalur penyertaan adalah masalah selera pribadi. Misalnya jika foo.cadalah file di direktori saat ini

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

akan memanggil kompilator Anda dengan cara yang persis sama, yaitu

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

Perbedaan antara keduanya mulai berlaku ketika Anda memiliki beberapa bahasa yang membutuhkan jalur penyertaan yang sama, misalnya jika Anda telah bar.cppmencobanya

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

maka kompilasi akan dilakukan

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

karena aturan implisit C ++ juga menggunakan CPPFLAGSvariabel.

Perbedaan ini memberi Anda panduan yang baik untuk digunakan - jika Anda ingin flag digunakan untuk semua bahasa, masukkan ke dalam CPPFLAGS, jika itu untuk bahasa tertentu CFLAGS, CXXFLAGSdsb. Contoh tipe yang terakhir termasuk kepatuhan standar atau flag peringatan - Anda tidak ingin meneruskan -std=c99ke kompiler C ++ Anda!

Anda mungkin akan mendapatkan sesuatu seperti ini di makefile Anda

CPPFLAGS=-I/usr/include
CFLAGS=-std=c99
CXXFLAGS=-Weffc++
Scott Wales
sumber
1
Perhatikan bahwa Anda tidak dapat menjalankan berdiri sendiri cppmenggunakan CPPFLAGSdan mengharapkan hasil yang wajar karena -std=c99memengaruhi simbol mana yang ditentukan (terutama sebagai pengganti makro uji fitur). Sebaliknya, Anda membutuhkannya $(CC) $(CPPFLAGS) $(CFLAGS) -E.
Jed
10

The CPPFLAGSmakro adalah satu untuk menggunakan untuk menentukan #includedirektori.

Keduanya CPPFLAGSdan CFLAGSberfungsi dalam kasus Anda karena aturan make(1) menggabungkan preprocessing dan kompilasi dalam satu perintah (jadi kedua makro digunakan dalam perintah).

Anda tidak perlu menentukan . sebagai direktori penyertaan jika Anda menggunakan formulir #include "...". Anda juga tidak perlu menentukan direktori penyertaan kompilator standar. Anda perlu menentukan semua direktori penyertaan lainnya.

Steve Emmerson
sumber
Ini lebih masuk akal, tapi saya masih belum melihat apa yang dilakukan CFLAGS. Jika, seperti yang Anda maksudkan, kompilasi dalam proyek yang lebih kompleks dilakukan dalam langkah terpisah dari preprocessing, apakah preprocessing akan berhasil tetapi kompilasi gagal jika CFLAGS tidak menambahkan jalur yang sama dengan yang ditambahkan CPPFLAGS untuk preprocessor? Saya rasa saya tidak mengerti apa yang dilakukan kompilator dengan jalur include jika preprocessor sudah memproses arahan #include?
EBM
4
@EB Jika Anda sedang mengompilasi file praproses maka tidak perlu menyertakan jalur - header yang diperlukan telah ditambahkan ke sumber yang diproses sebelumnya (Lihat outputnya saat Anda menjalankan gcc -Efile - tidak ada #includes). Kebanyakan kompiler modern menggabungkan langkah-langkah pra-pemrosesan dan kompilasi, jadi Anda tidak perlu khawatir tentang ini.
Scott Wales
0

Untuk menambahkan kepada mereka yang telah menyebutkan aturan implisit, yang terbaik adalah melihat apa yang telah didefinisikan secara implisit dan untuk env Anda menggunakan:

make -p

Misalnya:

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

yang mengembang

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

Ini juga akan mencetak # environmentdata. Di sini, Anda akan menemukan jalur penyertaan GCC di antara info berguna lainnya.

C_INCLUDE_PATH=/usr/include

Dalam membuat, ketika datang ke pencarian, jalannya banyak, cahayanya satu ... atau sesuatu untuk efek itu.

  1. C_INCLUDE_PATH untuk seluruh sistem, setel di shell Anda *.rc .
  2. $(CPPFLAGS) adalah untuk preprocessor jalur include.
  3. Jika Anda perlu menambahkan jalur pencarian umum untuk make, gunakan:
VPATH = my_dir_to_search

... atau bahkan lebih spesifik

vpath %.c src
vpath %.h include

buat menggunakan VPATH sebagai jalur pencarian umum jadi gunakan dengan hati-hati. Jika file ada di lebih dari satu lokasi yang terdaftar di VPATH, make akan mengambil kejadian pertama dalam daftar.

67hz
sumber