makefile выполнить другую цель

123

У меня есть make-файл, структурированный примерно так:

all : 
    compile executable

clean :
    rm -f *.o $(EXEC)

Я понял, что последовательно выполняю «make clean», а затем «clear» в моем терминале перед запуском «make all». Мне нравится иметь чистый терминал, прежде чем я попытаюсь отсеять неприятные ошибки компиляции C ++. Итак, я попытался добавить третью цель:

fresh :
    rm -f *.o $(EXEC)
    clear
    make all

Это работает, однако это запускает второй экземпляр make (я считаю). Есть ли правильный способ получить ту же функциональность без запуска второго экземпляра make?

sas4740
источник

Ответы:

172

На самом деле вы правы: он запускает другой экземпляр make. Возможное решение:

.PHONY : clearscr fresh clean all

all :
    compile executable

clean :
    rm -f *.o $(EXEC)

fresh : clean clearscr all

clearscr:
    clear

Вызывая, make freshвы сначала получаете cleanцель, затем clearscreenвыполняемую clearи, наконец, allвыполняющую работу.

ИЗМЕНИТЬ 4 августа

Что происходит в случае параллельной сборки с -jопцией make ? Есть способ навести порядок. Из руководства make, раздел 4.2:

Однако иногда возникает ситуация, когда вы хотите наложить определенный порядок на правила, которые должны быть вызваны, без принудительного обновления цели, если выполняется одно из этих правил. В этом случае вы хотите определить предпосылки только для заказа. Предварительные условия только для заказа можно указать, поместив вертикальную черту (|) в список предварительных требований: любые предварительные требования слева от вертикальной черты являются нормальными; любые предварительные условия справа относятся только к порядку: цели: нормальные-предварительные условия | заказ-только-предпосылки

Нормальный раздел предварительных условий, конечно, может быть пустым. Кроме того, вы все равно можете объявить несколько строк предварительных условий для одной и той же цели: они добавляются соответствующим образом. Обратите внимание, что если вы объявляете один и тот же файл как обычное предварительное условие, так и предварительное условие только для заказа, нормальное предварительное условие имеет приоритет (поскольку они являются строгим надмножеством поведения предварительного условия только для заказа).

Следовательно, make-файл становится

.PHONY : clearscr fresh clean all

all :
    compile executable

clean :
    rm -f *.o $(EXEC)

fresh : | clean clearscr all

clearscr:
    clear

ИЗМЕНИТЬ 5 декабря

Запуск более одного экземпляра make-файла не представляет большого труда, поскольку каждая команда внутри задачи в любом случае будет подчиненной оболочкой . Но вы можете использовать многоразовые методы, используя функцию вызова .

log_success = (echo "\x1B[32m>> $1\x1B[39m")
log_error = (>&2 echo "\x1B[31m>> $1\x1B[39m" && exit 1)

install:
  @[ "$(AWS_PROFILE)" ] || $(call log_error, "AWS_PROFILE not set!")
  command1  # this line will be a subshell
  command2  # this line will be another subshell
  @command3  # Use `@` to hide the command line
  $(call log_error, "It works, yey!")

uninstall:
  @[ "$(AWS_PROFILE)" ] || $(call log_error, "AWS_PROFILE not set!")
  ....
  $(call log_error, "Nuked!")
Dacav
источник
6
@ sas4740: в основном все последующее .PHONY : рассматривается как некое ключевое слово, которое всегда выполняется, в то время как нефальшивые цели предназначены для файлов.
Dacav
условны ли «предварительные условия только для заказа»? для цели t2 я хочу сначала сделать t0, чем только если t0 успешно выполнить t1, и только если оба успеха выполнят некоторую задачу в t3
fantastory
1
@fantastory, нет, я думаю, они независимы. t2будет зависеть от t0, t1и t3. Если вам это нужно, вы должны поставить t3как требуется t2, t1как требуется t3и t0как требуется t1. Это означает 3 разных правила. Однако вам следует это проверить. Я не уверен на 100%.
Dacav
3
«
Предварительные
2
Я не понимаю, где гарантия того, что «чистый» лучше, чем «все»? То, что вы их сразу ставите из | не заставляет их выполняться по порядку. Зависимость только от заказа означает, что цель не обязательно обновляется после такой операции. Это не имеет ничего общего с порядком зависимых элементов ... или?
CygnusX1
6

Если вы удалили make allстроку из своей «новой» цели:

fresh :
    rm -f *.o $(EXEC)
    clear

Вы можете просто запустить команду make fresh all, которая будет выполняться как make fresh; make all.

Некоторые могут рассматривать это как второй экземпляр make, но это определенно не подэкземпляр make (make внутри make), к чему, похоже, привела ваша попытка.

codenaugh
источник