Этот отрывок из make
руководства объясняет, почему ваш makefile
не работает так, как вы предполагали:
GNU make выполняет свою работу в два разаотдельные фазы.На первом этапе он считывает все make-файлы, включая make-файлы и т. Д. И усваивает все переменные и их значения, неявные и явные правила, а также строит граф зависимостей для всех целей и их предварительных условий.На втором этапе make использует эти внутренние структуры, чтобы определить, какие цели необходимо восстановить, и вызвать необходимые для этого правила.
Поскольку вы выполняете команду (touch
, в вашемпример) внутри правила make
выполнит его на втором этапе.Но к тому времени граф зависимостей и устаревшие цели уже были определены;это произошло на первом этапе.
Имея это в виду, вы можете понять, почему это работает каждый раз.Ваша желаемая команда действительно выполняется каждый раз, но main.o
будет считаться устаревшей только в том случае, если файл version.h
был уже новее, чем main.o
на первом этапе, то есть перед любым изправила были выполнены.Таким образом, main.o
будет считаться устаревшим, только если он старше version.h
в тот момент, когда вы вызываете команду make
.Это тот случай, если main.o
не был перекомпилирован в последний раз, когда вы вызывали make
.
Хитрость, которую вы могли бы использовать для выполнения вашей команды во времени, каждый раз, заключалась бы в добавлении фиктивной переменной где-нибудь вначало и заставить его выполнить желаемую команду во время его оценки.Принимая touch
снова в качестве примера команды, вы будете делать что-то вроде этого в первой строке:
DUMMY := $(shell touch version.h)
Поскольку это непосредственное назначение, команда будет выполнена на первом этапе.Если эта команда обновит version.h
, то все цели, зависящие от version.h
, будут считаться устаревшими и перестроенными.Это включает main.o
.
. При таком подходе вам больше не нужен механизм .PHONY: update-version
и связанные с ним правила и рецепты.
Обновление
Перечитывая, я понимаю, что вы написали: "Всегда запускайте некоторые команды , когда основной целевой файл требует определенный файл".Что ты имеешь в виду?Далее вы написали: «Когда я запускаю make, обновление заголовка версии выполняется каждый раз (как я хочу)» - это то, что делает makefile
, полученный из этого ответа.Вы можете уточнить?А что вы подразумеваете под "основной целью"?