Управление многословием
Я использую make файл для компиляции программы из многих файлов .c
, и в любое время make
вызывается только компилирует те файлы, которые были изменены после последнего запуска (ничего особенного до сих пор).
Чтобы избежать загромождения моего экрана, я добавляю @
в начале каждого вызова $(CC)
, и перед этим я печатаю настроенное сообщение echo
. Например:
%.o: %.c $(h1) $(h3) %.h
@echo -e "\tCompiling <" $<
@$(CC) $(CFLAGS) -c $< -o $(libDir)[email protected]$(MATHOPTS)
Мой вопрос: как я могу управлять многословием make
более "динамическим способом", чтобы иметь возможность:
- Нормальное поведение: для каждого выполненного правила файла напечатано только настроенное сообщение.
- Подробное поведение: напечатайте команду, фактически выполняемую каждым правилом makefile (как будто
@
вообще не использовался).
Ответы
Ответ 1
Я бы сделал так, как делает 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)[email protected]$(MATHOPTS)
Если вам нужно выполнить другие команды в своих правилах, мне нравится следующий фрагмент. Запишите $(AT)
вместо @
и он будет молчать, когда V=0
, но будет напечатан, когда V=1
.
AT_0 := @
AT_1 :=
AT = $(AT_$(V))
Ответ 2
Другое решение (которое мне нравится, потому что оно гибкое)
ifeq ("$(BUILD_VERBOSE)","1")
Q :=
vecho = @echo
else
Q := @
vecho = @true
endif
%.o: %.c
$(vecho) "-> Compiling [email protected]"
$(Q)$(CC) $(CFLAGS) -c $< -o [email protected]
Вы можете пропустить материал vecho, но иногда это пригодится.
Ответ 3
Я бы создал функцию, которая принимает команду для выполнения и решает, следует ли ее эхо.
# '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)[email protected]$(MATHOPTS), \
Compiling $<)
Тогда результатом простого вызова make
будет что-то вроде:
Compiling foo.c
В то время как make V=1
даст:
gcc -Wall -c foo.c -o foo.o ...
Ответ 4
Вместо того, чтобы компилировать "@gcc", вы можете опустить это "@" и передать вместо этого команду "-s" в свою команду make. (Оставьте "@echo" так, как есть.) Тогда "make -s" будет вашей короткой командой make, а "make" будет многословной.
Флаг '-s или' --silent для предотвращения всех эхо-сигналов, как будто все рецепты начинаются с '@.
На страницах GNU Make manual
(Другой ответ лучше отвечает на ваш вопрос, но этот подход заслуживает упоминания.)
Ответ 5
Так как я не могу прокомментировать предложение AT = $(AT_$(V))
, обратите внимание, что Automake предоставляет стандартный макрос, который выполняет те же действия, что и AT
, который называется AM_V_at
.
Вы также обнаружите, что у него есть другая очень полезная переменная AM_V_GEN
, которая разрешает либо ничего, либо @echo " GEN " [email protected];
, в зависимости от многословия.
Это позволяет вам закодировать что-то вроде этого:
grldr.mbr: mbrstart
$(AM_V_GEN)
$(AM_V_at)-rm -f grldr.mbr
$(AM_V_at)cat mbrstart > grldr.mbr
Выход из него будет либо (с расширением verbosity):
GEN grldr.mbr
или (многословие включено):
rm -f grldr.mbr
cat mbrstart > grldr.mbr
Довольно удобно, и это устраняет необходимость определять собственные макросы.