CFLAGS проти CPPFLAGS


104

Я розумію, що CFLAGS (або CXXFLAGS для C ++) призначений для компілятора, тоді як CPPFLAGS використовується препроцесором.

Але я все ще не розумію різниці.

Мені потрібно вказати шлях включення для файлу заголовка, який входить до #include - оскільки #include є директивою препроцесора, чи є єдиним, що мене хвилює для препроцесора (CPPFLAGS)?

За яких обставин мені потрібно надати компілятору додатковий шлях включення?

Взагалі, якщо препроцесор знаходить і включає необхідні файли заголовків, чому йому взагалі потрібно розповідати про додаткові каталоги, що включають? Що взагалі використовують CFLAGS?

(У моєму випадку я дійсно виявив, що БОЛЬСЯ з них дозволяють мені скласти свою програму, що додає плутанини ... Я можу використовувати CFLAGS OR CPPFLAGS для досягнення своєї мети (принаймні в контексті autoconf). Що дає?)


Відповіді:


154

Неявне правило make для компілювання програми на 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.
Джед

10

CPPFLAGSМакрос є один використовувати для вказівки #includeкаталогів.

Обидва CPPFLAGSі CFLAGSпрацюють у вашому випадку, оскільки makeправило (1) поєднує в одній команді як попередню обробку, так і компіляцію (тому обидва макроси використовуються в команді).

Вам не потрібно вказувати .як каталог включення, якщо ви використовуєте форму #include "...". Вам також не потрібно вказувати стандартний каталог, що включає компілятор. Вам потрібно вказати всі інші каталоги включення.


Це має більше сенсу, але я все ще не бачу, що робить CFLAGS. Якщо, як вам здається, випливає, що компіляція в більш складних проектах проводиться в окремому кроці від попередньої обробки, чи буде попередня обробка успішною, але компіляція не вдасться, якщо CFLAGS не додасть ті самі шляхи, які CPPFLAGS додав для препроцесора? Я думаю, я не розумію, що робить компілятор, включаючи шляхи, якщо препроцесор вже обробив директиви #include?
EBM

4
@EB Якщо ви компілюєте попередньо оброблені файли, то включити шляхи непотрібні - потрібні заголовки вже додані до попередньо обробленого джерела (Подивіться на вихід, коли ви запускаєте gcc -Eфайл - немає #includes). Більшість сучасних компіляторів поєднують етапи попередньої обробки та компіляції, тому вам не доведеться турбуватися про це.
Скотт Уельс


0

Щоб додати до тих, хто згадував неявні правила, найкраще побачити, що марк визначав неявно та для вашої 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 вперше виникне у списку.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.