CFLAGS, CCFLAGS, CXXFLAGS - что именно контролируют эти переменные? - PullRequest
62 голосов
/ 04 апреля 2011

Я использую GNU make для компиляции своего кода C ++, и я хотел бы понять, как сделать мои компиляции настраиваемыми.

Я читал в разных местах, что CFLAGS, CCFLAGS и CXXFLAGSиспользуются для этой цели.Так как я должен их использовать?Если у меня есть дополнительные аргументы командной строки для компилятора, я должен добавить их к CFLAGS или добавить их?Существует ли распространенная практика?

Почему три разные переменные?Я полагаю, что компилятор C должен получить CFLAGS и CCFLAGS, а компилятор C ++ должен получить 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 $@

... (somewhere in the makefile, the command-line for linking looks like this)
    $(CC) $(GCOV_FLAG) $(CCFLAGSINT) $(OBJLIST) $(LDFLAGS) -o $@

Я почти уверен, что здесь нет ошибок;Makefile работает очень хорошо.Но есть ли что-то, что противоречит соглашениям (например, CCFLAGSINT - нужно ли просто перезаписать CCFLAGS вместо этого? Или CXXFLAGS? FUD!)

Извините за столько вопросов;Вы, очевидно, не будете отвечать на них все, но я надеюсь, что ответы помогут мне понять общую идею этих настроек.

Ответы [ 3 ]

75 голосов
/ 04 апреля 2011

Как вы заметили, это Makefile {макросы или переменные}, а не опции компилятора.Они реализуют ряд соглашений.(Макросы - это старое имя для них, которое до сих пор используется некоторыми. GNU make doc называет их переменными.)

Единственная причина, по которой имена имеют значение, это правила make по умолчанию, видимые через make -p, которые используют некоторыеиз них.

Если вы напишите все свои собственные правила, вы сможете выбрать все свои собственные имена макросов.

В ванильном гну make нет такой вещи, как CCFLAGS.Есть CFLAGS, CPPFLAGS и CXXFLAGS.CFLAGS для компилятора C, CXXFLAGS для C ++ и CPPFLAGS для обоих.

Почему CPPFLAGS в обоих?Традиционно, это место флагов препроцессора (-D, -U), и c и c ++ используют их.Теперь предположение, что каждый хочет одного и того же определяющего окружения для c и c ++, возможно, сомнительно, но традиционно.


PS Как отметил Джеймс Мур ,некоторые проекты используют CPPFLAGS для флагов компилятору C ++, а не для флагов препроцессора C.Android NDK, для одного огромного примера.

8 голосов
/ 05 сентября 2018

Согласно инструкции 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
н.о. производится автоматически из н.с с рецептом вида
‘$ (CC) $ (CPPFLAGS) $ (CFLAGS) -c’.

Компиляция программ на C ++
n.o производится автоматически из n.cc, n.cpp или n.C с рецептом вида
‘$ (CXX) $ (CPPFLAGS) $ (CXXFLAGS) -c’.
Мы рекомендуем вам использовать суффикс «.cc» для исходных файлов C ++ вместо «.C».

Источник: https://www.gnu.org/software/make/manual/make.html#Catalogue-of-Rules

0 голосов

И просто сделать то, что 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 имели неявные правила дляmake main_c и main_cpp из main_c.c и main_cpp.cpp
  • CFLAGS и CPPFLAGS использовались как часть неявного правила для .c компиляции
  • CXXFLAGS и CPPFLAGS использовались какчасть неявного правила для .cpp компиляции

Эти переменные используются только в неявных правилах make автоматически: если компиляция использовала наши собственные явные правила, то нам пришлось бы явно использовать эти переменные, как в:

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

main_cpp: main_c.c
    $(CXX) $(CXXFLAGS) $(CPPFLAGS) -o $@ $<

для достижения аналогичного влияния на неявные правила.

Мы могли бы также назвать эти переменные так, как нам хочется: но поскольку Make уже обрабатывает их магически в неявных правилах, они делаютвыбор хорошего имени.

Протестировано в Ubuntu 16.04, GNU Make 4.1.

...