CFLAGS so với CPPFLAGS


103

Tôi hiểu rằng CFLAGS (hoặc CXXFLAGS cho C ++) dành cho trình biên dịch, trong khi CPPFLAGS được sử dụng bởi trình tiền xử lý.

Nhưng tôi vẫn không hiểu sự khác biệt.

Tôi cần chỉ định đường dẫn bao gồm cho tệp tiêu đề được bao gồm với #include - bởi vì #include là chỉ thị tiền xử lý, bộ tiền xử lý (CPPFLAGS) có phải là điều duy nhất tôi quan tâm không?

Trong những trường hợp nào tôi cần cung cấp cho trình biên dịch thêm một đường dẫn bao gồm?

Nói chung, nếu bộ tiền xử lý tìm thấy và bao gồm các tệp tiêu đề cần thiết, tại sao nó cần được thông báo về các thư mục bao gồm bổ sung? CFLAGS có công dụng gì?

(Trong trường hợp của tôi, tôi thực sự thấy rằng CẢ HAI trong số này cho phép tôi biên dịch chương trình của mình, điều này làm tăng thêm sự nhầm lẫn ... Tôi có thể sử dụng CFLAGS HOẶC CPPFLAGS để hoàn thành mục tiêu của mình (ít nhất là trong ngữ cảnh autoconf. Điều gì mang lại?)


2
bản sao có thể có của stackoverflow.com/questions/495598/…
Michael Mrozek

Câu trả lời:


153

Quy tắc thực hiện ngầm để biên dịch một chương trình C là

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

nơi $()cú pháp mở rộng các biến. Vì cả hai CPPFLAGSCFLAGSđều được sử dụng trong lệnh gọi trình biên dịch, mà bạn sử dụng để xác định đường dẫn bao gồm là vấn đề của sở thích cá nhân. Ví dụ nếu foo.clà một tệp trong thư mục hiện tại

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

cả hai sẽ gọi trình biên dịch của bạn theo cùng một cách, cụ thể là

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

Sự khác biệt giữa hai ngôn ngữ này xuất hiện khi bạn có nhiều ngôn ngữ cần cùng một đường dẫn bao gồm, ví dụ: nếu bạn có bar.cppthì hãy thử

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

sau đó tổng hợp sẽ là

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

vì quy tắc ngầm định của C ++ cũng sử dụng CPPFLAGSbiến.

Sự khác biệt này cung cấp cho bạn hướng dẫn tốt để sử dụng - nếu bạn muốn cờ được sử dụng cho tất cả các ngôn ngữ đặt nó vào CPPFLAGS, nếu nó cho một ngôn ngữ cụ thể thì hãy đưa nó vào CFLAGS, CXXFLAGSv.v. Ví dụ về loại sau bao gồm cờ tuân thủ tiêu chuẩn hoặc cảnh báo - bạn sẽ không muốn chuyển -std=c99đến trình biên dịch C ++ của mình!

Sau đó, bạn có thể kết thúc với một cái gì đó như thế này trong tệp trang điểm của bạn

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

1
Lưu ý rằng bạn không thể chạy độc lập cppbằng cách sử dụng CPPFLAGSvà mong đợi bất kỳ kết quả hợp lý nào vì -std=c99ảnh hưởng đến ký hiệu nào được xác định (đặc biệt là thay cho macro kiểm tra tính năng). Thay vào đó, bạn cần $(CC) $(CPPFLAGS) $(CFLAGS) -E.
Jed

10

Các CPPFLAGSvĩ mô là một trong những sử dụng để chỉ định #includethư mục.

Cả hai CPPFLAGSvà đều CFLAGShoạt động trong trường hợp của bạn vì makequy tắc (1) kết hợp cả tiền xử lý và biên dịch trong một lệnh (vì vậy cả hai macro đều được sử dụng trong lệnh).

Bạn không cần chỉ định .là thư mục bao gồm nếu bạn sử dụng biểu mẫu #include "...". Bạn cũng không cần chỉ định thư mục bao gồm trình biên dịch tiêu chuẩn. Bạn cần chỉ định tất cả các thư mục bao gồm khác.


Điều này có ý nghĩa hơn, nhưng tôi vẫn không thấy CFLAGS làm được gì. Nếu, như bạn có vẻ ngụ ý, việc biên dịch trong các dự án phức tạp hơn được thực hiện theo một bước riêng biệt với tiền xử lý, liệu tiền xử lý có thành công nhưng quá trình biên dịch không thành công nếu CFLAGS không thêm các đường dẫn giống như CPPFLAGS đã thêm cho bộ tiền xử lý? Tôi đoán tôi không hiểu trình biên dịch làm gì với các đường dẫn bao gồm nếu trình xử lý trước đã xử lý các lệnh #include?
EBM

4
@EB Nếu bạn đang biên dịch các tệp được xử lý trước thì đường dẫn bao gồm là không cần thiết - các tiêu đề bắt buộc đã được thêm vào nguồn được xử lý trước (Hãy xem kết quả đầu ra khi bạn chạy gcc -Etrên tệp - không có #includes). Hầu hết các trình biên dịch hiện đại đều kết hợp các bước tiền xử lý và biên dịch, vì vậy bạn không phải lo lắng về điều này.
Scott Wales


0

Để thêm vào những người đã đề cập đến các quy tắc ngầm, tốt nhất nên xem những gì make đã xác định ngầm và cho env của bạn bằng cách sử dụng:

make -p

Ví dụ:

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

mở rộng

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

Điều này cũng sẽ in # environmentdữ liệu. Tại đây, bạn sẽ tìm thấy đường dẫn bao gồm của GCC trong số các thông tin hữu ích khác.

C_INCLUDE_PATH=/usr/include

Trong thực tế, khi nói đến tìm kiếm, các con đường có rất nhiều, ánh sáng là một ... hoặc một cái gì đó để tạo ra hiệu ứng đó.

  1. C_INCLUDE_PATHtrên toàn hệ thống, hãy đặt nó trong trình bao của bạn *.rc.
  2. $(CPPFLAGS) là cho đường dẫn bao gồm bộ tiền xử lý.
  3. Nếu bạn cần thêm một đường dẫn tìm kiếm chung để thực hiện, hãy sử dụng:
VPATH = my_dir_to_search

... hoặc thậm chí cụ thể hơn

vpath %.c src
vpath %.h include

hãy sử dụng VPATH làm đường dẫn tìm kiếm chung, vì vậy hãy sử dụng một cách thận trọng. Nếu một tệp tồn tại ở nhiều vị trí được liệt kê trong VPATH, make sẽ chiếm vị trí xuất hiện đầu tiên trong danh sách.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.