CFLAGS กับ CPPFLAGS


104

ฉันเข้าใจว่า CFLAGS (หรือ CXXFLAGS สำหรับ C ++) มีไว้สำหรับคอมไพเลอร์ในขณะที่ CPPFLAGS ถูกใช้โดยตัวประมวลผลล่วงหน้า

แต่ฉันยังไม่เข้าใจความแตกต่าง

ฉันจำเป็นต้องระบุพา ธ รวมสำหรับไฟล์ส่วนหัวที่มาพร้อมกับ #include - เนื่องจาก #include เป็นคำสั่งของตัวประมวลผลก่อนตัวประมวลผลล่วงหน้า (CPPFLAGS) เป็นสิ่งเดียวที่ฉันสนใจหรือไม่

ฉันต้องให้เส้นทางการรวมเพิ่มเติมแก่คอมไพเลอร์ภายใต้สถานการณ์ใด

โดยทั่วไปหากตัวประมวลผลก่อนค้นหาและรวมไฟล์ส่วนหัวที่จำเป็นเหตุใดจึงจำเป็นต้องแจ้งเกี่ยวกับไดเร็กทอรีรวมพิเศษ CFLAGS ใช้อะไรได้บ้าง?

(ในกรณีของฉันฉันพบว่าทั้งสองอย่างนี้อนุญาตให้ฉันรวบรวมโปรแกรมของฉันได้ซึ่งทำให้เกิดความสับสน ... ฉันสามารถใช้ CFLAGS หรือ CPPFLAGS เพื่อบรรลุเป้าหมายของฉัน (ในบริบทอัตโนมัติอย่างน้อยที่สุด) อะไรให้อะไร)


2
สำเนาที่เป็นไปได้ของstackoverflow.com/questions/495598/…
Michael Mrozek

คำตอบ:


154

กฎการสร้างโดยปริยายสำหรับการรวบรวมโปรแกรม C คือ

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

โดยที่$()ไวยากรณ์จะขยายตัวแปร เนื่องจากทั้งสองอย่างCPPFLAGSและCFLAGSใช้ในการเรียกคอมไพเลอร์ซึ่งคุณใช้กำหนดเส้นทางรวมเป็นเรื่องของรสนิยมส่วนตัว ตัวอย่างเช่นถ้าfoo.cเป็นไฟล์ในไดเร็กทอรีปัจจุบัน

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

ทั้งคู่จะเรียกคอมไพเลอร์ของคุณในลักษณะเดียวกันคือ

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

ความแตกต่างระหว่างทั้งสองเข้ามามีบทบาทเมื่อคุณมีหลายภาษาซึ่งต้องใช้เส้นทางรวมเดียวกันเช่นถ้าคุณbar.cppลองแล้ว

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

จากนั้นการรวบรวมจะเป็น

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

เนื่องจากกฎโดยนัยของ C ++ ยังใช้CPPFLAGSตัวแปร

ความแตกต่างนี้จะช่วยให้คุณคำแนะนำที่ดีที่จะใช้ - ถ้าคุณต้องการธงที่จะใช้สำหรับทุกภาษาใส่ไว้ในCPPFLAGSถ้ามันสำหรับภาษาที่เฉพาะเจาะจงใส่ไว้ในCFLAGS, CXXFLAGSฯลฯ ตัวอย่างของประเภทหลังรวมถึงการปฏิบัติตามมาตรฐานหรือธงเตือน - คุณไม่ต้องการส่ง-std=c99ต่อไปยังคอมไพเลอร์ C ++ ของคุณ!

จากนั้นคุณอาจลงเอยด้วยสิ่งนี้ใน makefile ของคุณ

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

1
โปรดทราบว่าคุณไม่สามารถเรียกใช้แบบสแตนด์อโลนcppโดยใช้CPPFLAGSและคาดหวังผลลัพธ์ที่สมเหตุสมผลใด ๆ เนื่องจาก-std=c99มีผลต่อสัญลักษณ์ที่กำหนด (โดยเฉพาะแทนมาโครการทดสอบคุณลักษณะ) $(CC) $(CPPFLAGS) $(CFLAGS) -Eแต่คุณต้อง
Jed

10

CPPFLAGSแมโครเป็นหนึ่งที่จะใช้เพื่อระบุ#includeไดเรกทอรี

ทั้งสองอย่างCPPFLAGSและCFLAGSทำงานในกรณีของคุณเนื่องจากmakeกฎ (1) รวมทั้งการประมวลผลล่วงหน้าและการคอมไพล์ไว้ในคำสั่งเดียว (ดังนั้นจึงใช้มาโครทั้งสองในคำสั่ง)

คุณไม่จำเป็นต้องระบุเป็นรวมไดเรกทอรีถ้าคุณใช้แบบฟอร์ม. #include "..."คุณไม่จำเป็นต้องระบุไดเร็กทอรีรวมคอมไพเลอร์มาตรฐาน คุณจำเป็นต้องระบุไดเร็กทอรีรวมอื่น ๆ ทั้งหมด


สิ่งนี้สมเหตุสมผลกว่า แต่ฉันก็ยังไม่เห็นว่า CFLAGS ทำอะไร ถ้าตามที่คุณบอกเป็นนัยว่าการคอมไพล์ในโปรเจ็กต์ที่ซับซ้อนกว่านั้นเสร็จสิ้นในขั้นตอนแยกต่างหากจากการประมวลผลก่อนการประมวลผลล่วงหน้าจะประสบความสำเร็จ แต่การคอมไพล์ล้มเหลวหาก CFLAGS ไม่เพิ่มพา ธ เดียวกับที่ CPPFLAGS เพิ่มสำหรับพรีโปรเซสเซอร์? ฉันเดาว่าฉันไม่เข้าใจว่าคอมไพเลอร์ทำอะไรกับเส้นทางรวมหากตัวประมวลผลล่วงหน้าประมวลผลคำสั่ง #include แล้ว?
EBM

4
@EB หากคุณกำลังรวบรวมไฟล์ที่ประมวลผลล่วงหน้าแสดงว่าไม่จำเป็นต้องรวมพา ธ - ส่วนหัวที่ต้องการได้ถูกเพิ่มไปยังซอร์สที่ประมวลผลล่วงหน้าแล้ว (ดูผลลัพธ์เมื่อคุณเรียกใช้gcc -Eไฟล์ - ไม่มี #includes) คอมไพเลอร์สมัยใหม่ส่วนใหญ่รวมขั้นตอนก่อนการประมวลผลและการรวบรวมดังนั้นคุณไม่ต้องกังวลเกี่ยวกับเรื่องนี้
Scott Wales


0

หากต้องการเพิ่มให้กับผู้ที่กล่าวถึงกฎโดยนัยคุณควรดูสิ่งที่ make ได้กำหนดไว้โดยปริยายและสำหรับ env ของคุณโดยใช้:

make -p

ตัวอย่างเช่น:

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

ซึ่งขยายออกไป

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

นอกจากนี้ยังจะพิมพ์# environmentข้อมูล ที่นี่คุณจะพบเส้นทางรวมของ GCC ท่ามกลางข้อมูลที่เป็นประโยชน์อื่น ๆ

C_INCLUDE_PATH=/usr/include

เมื่อพูดถึงการค้นหาเส้นทางมีมากมายแสงเป็นหนึ่ง ... หรือบางอย่างที่มีผลต่อสิ่งนั้น

  1. C_INCLUDE_PATHเป็นทั้งระบบตั้งไว้ในเชลล์ของ*.rcคุณ
  2. $(CPPFLAGS) มีไว้สำหรับพรีโปรเซสเซอร์รวมพา ธ
  3. หากคุณต้องการเพิ่มเส้นทางการค้นหาทั่วไปสำหรับ make ให้ใช้:
VPATH = my_dir_to_search

... หรือเฉพาะเจาะจงมากขึ้น

vpath %.c src
vpath %.h include

ทำให้ใช้ VPATH เป็นเส้นทางการค้นหาทั่วไปดังนั้นโปรดใช้ด้วยความระมัดระวัง หากไฟล์มีอยู่มากกว่าหนึ่งตำแหน่งที่แสดงอยู่ใน VPATH make จะเกิดขึ้นครั้งแรกในรายการ

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.