Как заставить make всегда пересобирать файл - PullRequest
18 голосов
/ 04 октября 2011

У меня есть файл version.c в моем проекте, который содержит текущую ревизию проекта и некоторые другие вещи, которые передаются как определение (опция -D компилятора) из makefile.

Я знаю, что для принудительной установкиmake для компиляции version.c всегда, независимо от даты модификации, я могу touch version.c.

Есть ли способ сделать это только для make-файла?Если я напишу .PHONY : version.o, объектный файл вообще не будет собран.

РЕДАКТИРОВАТЬ: Вот мой make-файл:

export CC = gcc


export MODULES = $(sort \
     sys \
     cim \
     version \
)

export FILES = $(sort \
             main.c \
             cim.c \
             version.c \
)

VPATH = $(MODULES)

OBJS = $(FILES:.c=.o)

INCLUDES = $(addprefix -I,$(MODULES))

all:$(OBJS)
    $(CC) $(INCLUDES) $(OBJS) -o main.exe


clean:
    rm -rf *.o *.exe

cim.o: cim.c
main.o: main.c cim.o
version.o: version.c

.PHONY: version.o

.c.o :
    $(CC) $(CFLAGS) $(INCLUDES) -c $<

Ответы [ 4 ]

44 голосов
/ 04 октября 2011

Классический способ сделать это:

version.o:   .FORCE

.FORCE:

(и вы можете добавить .PHONY: .FORCE).Предполагается, что файл .FORCE не существует, поэтому он всегда «создается», поэтому version.o всегда устарел, поэтому version.o всегда компилируется.убедитесь, что version.o в фальшивый файл правильно;на самом деле это настоящий файл, а не фальшивый.

10 голосов
/ 09 марта 2018

Не способ создания файла, но проще, чем сенсорный:

make -B

‘- B’ ‘--always-make’

Считать все цели устаревшими. GNU осуществляет рассмотрение целей и их предпосылок с использованием обычных алгоритмов; тем не мение, все рассматриваемые цели всегда переделываются независимо от статуса их предпосылок. Чтобы избежать бесконечной рекурсии, если MAKE_RESTARTS (см. Другие специальные переменные) имеет значение больше 0 опция отключена при рассмотрении вопроса о том, чтобы переделать make-файлы (см. Как восстанавливаются файлы Makefile).

5 голосов
/ 03 января 2017

Если вы хотите сделать это с помощью механизма FORCE, правильное решение будет выглядеть следующим образом:

version.o: FORCE

.PHONY: FORCE
FORCE:

Явно объявив FORCE фальшивым, мы убедимся, что все будет работать правильно, даже если .SECONDARY:используется (.SECONDARY: приведет к тому, что FORCE будет считаться промежуточным файлом, и make не будет перестраивать промежуточные файлы, если они не имеют предварительных условий, более новых, чем конечная цель, и FORCE не имеет никаких предварительных условий, поэтому .PHONY: FORCE необходимо).

Другое решение (использующее $(shell touch version.c)) также имеет проблему: это может заставить ваш редактор думать, что version.c обновлен, и запросить перезагрузку файла, что можетв конечном итоге будет разрушительным, если вы редактировали буфер файла, но еще не сохранили его.Если вы не возражаете против этого, это можно сделать еще проще, заметив, что команда touch молчит, поэтому присвоение фиктивной переменной hack не требуется:

$(shell touch version.c)  # This is enough, but will likely confuse your editor

.PHONY "трюк", упомянутый в комментариях к вопросу, как правило, не работает.Это может выглядеть так, потому что это приведет к повторной ссылке, если version.o уже существует, но фактический объектный файл не будет перестроен, если правило файла .o является неявным правилом (которым оно обычно является).Проблема в том, что make не выполняет неявный поиск правил для явно поддельных целей.Этот make-файл показывает ошибку:

fooprog: test.o
        cp $< $@

%.o: %.c
        cp $< $@

.PHONY: test.o # WRONG

clean:
        rm test.o fooprog

Если вместо неявного правила используется правило статического шаблона, трюк .PHONY: version.o будет работать.В целом, использование статических шаблонных правил вместо неявных правил избавляет от наиболее запутанного поведения Make.Но большинство файлов make используют неявные правила.

0 голосов
/ 09 июля 2016

Версия для быстрого взлома, когда вам просто нужно, чтобы она работала, и вы не хотите играть. Сделать игры:

# Hack to get main.c rebuilt
hack := $(shell touch main.c)

По сути, просто заставьте Пробежку touch для вас.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...