Управление многословием марки

Я использую make-файл для компиляции программы, состоящей из многих .c файлы и в любое время make вызывается только те файлы, которые были изменены после последнего запуска (пока ничего особенного).

Чтобы не загромождать мой экран, я добавляю @ в начале каждого $(CC) позвоните, и перед этим я распечатаю echo сообщение. Например:

%.o: %.c $(h1) $(h3) %.h
    @echo -e "\tCompiling <" $< 
    @$(CC) $(CFLAGS) -c $< -o $(libDir)$@$(MATHOPTS)

Мой вопрос: как я могу контролировать многословие make более "динамично", чтобы иметь возможность:

  1. Нормальное поведение: для каждого выполненного правила make-файла печатается только настроенное сообщение.
  2. Подробное поведение: вывести команду, фактически выполняемую каждым правилом 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

Довольно удобно, и это избавляет от необходимости определять свои собственные макросы.

Другие вопросы по тегам