Управление многословием марки
Я использую make-файл для компиляции программы, состоящей из многих .c
файлы и в любое время make
вызывается только те файлы, которые были изменены после последнего запуска (пока ничего особенного).
Чтобы не загромождать мой экран, я добавляю @
в начале каждого $(CC)
позвоните, и перед этим я распечатаю echo
сообщение. Например:
%.o: %.c $(h1) $(h3) %.h
@echo -e "\tCompiling <" $<
@$(CC) $(CFLAGS) -c $< -o $(libDir)$@$(MATHOPTS)
Мой вопрос: как я могу контролировать многословие make
более "динамично", чтобы иметь возможность:
- Нормальное поведение: для каждого выполненного правила make-файла печатается только настроенное сообщение.
- Подробное поведение: вывести команду, фактически выполняемую каждым правилом make-файла (как если бы
@
не использовался вообще).
5 ответов
Я бы сделал это так, как работает automake:
V = 0
ACTUAL_CC := $(CC)
CC_0 = @echo "Compiling $<..."; $(ACTUAL_CC)
CC_1 = $(ACTUAL_CC)
CC = $(CC_$(V))
%.o: %.c $(h1) $(h3) %.h
$(CC) $(CFLAGS) -c $< -o $(libDir)$@$(MATHOPTS)
Если вам нужно выполнить другие команды в ваших правилах, мне нравится следующий фрагмент. Написать $(AT)
вместо @
и будет тихо, когда V=0
но печатается когда V=1
,
AT_0 := @
AT_1 :=
AT = $(AT_$(V))
Другое решение (которое мне нравится, потому что оно гибкое)
ifeq ("$(BUILD_VERBOSE)","1")
Q :=
vecho = @echo
else
Q := @
vecho = @true
endif
%.o: %.c
$(vecho) "-> Compiling $@"
$(Q)$(CC) $(CFLAGS) -c $< -o $@
Вы можете пропустить вещи Vecho, но иногда они могут пригодиться.
Вместо использования "@gcc" для компиляции вы можете опустить этот "@" и вместо этого передать опцию "-s" в команду make. (Оставьте "@echo" как есть.) Тогда "make -s" будет вашей краткой командой make, а "make" будет многословным.
Флаг '-s' или '--silent', чтобы сделать, предотвращает все эхо, как если бы все рецепты начинались с '@'.
Из GNU Make справочные страницы
(Другие ответы лучше ответят на ваш вопрос, но этот подход заслуживает упоминания.)
Я хотел бы создать функцию, которая принимает команду для выполнения и решает, следует ли ее повторить.
# 'cmd' takes two arguments:
# 1. The actual command to execute.
# 2. Optional message to print instead of echoing the command
# if executing without 'V' flag.
ifdef V
cmd = $1
else
cmd = @$(if $(value 2),echo -e "$2";)$1
endif
%.o: %.c $(h1) $(h3) %.h
$(call cmd, \
$(CC) $(CFLAGS) -c $< -o $(libDir)$@$(MATHOPTS), \
Compiling $<)
Тогда результат добра make
вызов будет что-то вроде:
Compiling foo.c
В то время как make V=1
дам:
gcc -Wall -c foo.c -o foo.o ...
Поскольку я не могу комментировать AT = $(AT_$(V))
предложение, обратите внимание, что Automake предоставляет стандартный макрос, который делает то же самое, что и AT
, который называется AM_V_at
,
Вы также найдете, что у него есть еще один очень полезный AM_V_GEN
переменная, которая разрешает либо ничего, либо @echo " GEN " $@;
в зависимости от многословия.
Это позволяет вам кодировать что-то вроде этого:
grldr.mbr: mbrstart
$(AM_V_GEN)
$(AM_V_at)-rm -f grldr.mbr
$(AM_V_at)cat mbrstart > grldr.mbr
Вывод которого будет либо (многословие отключено):
GEN grldr.mbr
или (многословие включено):
rm -f grldr.mbr
cat mbrstart > grldr.mbr
Довольно удобно, и это избавляет от необходимости определять свои собственные макросы.