CFLAGS, CCFLAGS, CXXFLAGS - что именно эти переменные контролируют?
Я использую GNU make для компиляции моего кода на С++, и я хотел бы понять, как сделать мои компиляции настраиваемыми.
Я читал в разных местах, что CFLAGS
, CCFLAGS
и CXXFLAGS
используются для этой цели. Итак, как я должен их использовать? Если у меня есть дополнительные аргументы командной строки для компилятора, я должен добавить их в CFLAGS
или добавить их? Существует ли обычная практика?
Почему три разные переменные? Я предполагаю, что компилятор C должен получить CFLAGS
и CCFLAGS
, тогда как компилятор С++ должен получить CFLAGS
и CXXFLAGS
- я правильно понял?
Предполагается ли, что пользователь должен установить эти переменные вообще? Устанавливаете ли какие-либо автоматические инструменты (automake
, autoconf
и т.д.)? Система linux, которую я должен использовать, не определяет ни одну из этих переменных - это типичный?
В настоящее время мой Makefile выглядит так, и я чувствую, что это немного грязно:
ifdef code_coverage
GCOV_FLAG := -fprofile-arcs -ftest-coverage
else
GCOV_FLAG :=
endif
WFLAGS := -Wall
INC_FLAGS := -Istuff -Imore_stuff -Ietc
CCFLAGSINT := -O3 $(WFLAGS) $(INC_FLAGS) $(CCFLAGS)
... (somewhere in the makefile, the command-line for compilation looks like this)
$(CC) $(CCFLAGSINT) -c $< -o [email protected]
... (somewhere in the makefile, the command-line for linking looks like this)
$(CC) $(GCOV_FLAG) $(CCFLAGSINT) $(OBJLIST) $(LDFLAGS) -o [email protected]
Я уверен, что здесь нет ошибок; Makefile работает очень хорошо. Но есть ли что-либо, что противоречит соглашениям (например, CCFLAGSINT
- вместо того, чтобы просто перезаписать CCFLAGS
? Или CXXFLAGS
? FUD!)
Извините за столько вопросов; вы, очевидно, не ответите им, но я надеюсь, что ответы помогут мне понять общую идею этих настроек.
Ответы
Ответ 1
Как вы заметили, это Makefile {макросы или переменные}, а не опции компилятора. Они реализуют ряд соглашений. (Макросы - это старое имя для них, которое до сих пор используется некоторыми. GNU make doc называет их переменными.)
Единственная причина, по которой имена имеют значение, это правила make по умолчанию, видимые через make -p
, которые используют некоторые из них.
Если вы пишете все свои собственные правила, вы можете выбрать все свои собственные имена макросов.
В ванильном гну делают, нет такой вещи, как CCFLAGS. Есть CFLAGS
, CPPFLAGS
и CXXFLAGS
. CFLAGS
для компилятора C, CXXFLAGS
для C++ и CPPFLAGS
для обоих.
Почему CPPFLAGS
в обоих? Традиционно он является домом флагов препроцессора (-D
, -U
), и оба c и C++ используют их. Предположение о том, что все хотят одинаковую среду для c и C++, возможно, сомнительно, но традиционно.
PS Как отметил Джеймс Мур, некоторые проекты используют CPPFLAGS для флагов компилятору C++, а не для флагов препроцессора C. Android NDK, для одного огромного примера.
Ответ 2
Согласно GNU make
руководство:
CFLAGS: дополнительные флаги для компилятора C.
CXXFLAGS: дополнительные флаги для компилятора C++.
CPPFLAGS: дополнительные флаги для препроцессора C и программ, которые его используют (компиляторы C и Fortran).
источник: https://www.gnu.org/software/make/manual/make.html#index-cFLAGS
примечание: PP обозначает PreProcessor (а не Plus Plus), т.е.
CPP: программа для запуска препроцессора C с результатами на стандартный вывод; по умолчанию '$ (CC) -E.
Эти переменные используются неявными правилами make
Компиляция C программ
no сделан автоматически из nc с рецептом формы
'$ (CC) $ (CPPFLAGS) $ (CFLAGS) -c.
Компиляция C++ программ
no производится автоматически из n.cc, n.cpp или nC с рецептом вида
'$ (CXX) $ (CPPFLAGS) $ (CXXFLAGS) -c.
Мы рекомендуем вам использовать суффикс '.cc для исходных файлов C++ вместо'.C.
источник: https://www.gnu.org/software/make/manual/make.html#Catalogue-of-Rules
Ответ 3
И просто для того, чтобы Mizux сказал как минимальный пример:
main_c.c
#include <stdio.h>
int main(void) {
puts("hello");
}
main_cpp.cpp
#include <iostream>
int main(void) {
std::cout << "hello" << std::endl;
}
Тогда без какого-либо Makefile
:
make CFLAGS='-g -O3' CXXFLAGS='-ggdb3 -O0' CPPFLAGS='-DX=1 -DY=2' main_c main_cpp
работает:
cc -g -O3 -DX=1 -DY=2 main_c.c -o main_c
g++ -ggdb3 -O0 -DX=1 -DY=2 main_cpp.cpp -o main_cpp
Итак, мы понимаем, что:
-
make
были неявные правила для создания main_c
и main_cpp
из main_c.c
и main_cpp.cpp
- CFLAGS и CPPFLAGS использовались как часть неявного правила для компиляции
.c
- CXXFLAGS и CPPFLAGS использовались как часть неявного правила для компиляции
.cpp