web-dev-qa-db-fra.com

Comment forcer make à toujours reconstruire un fichier

J'ai un fichier version.c dans mon projet qui contient la révision actuelle du projet et quelques autres éléments passés en tant que définition (option du compilateur -D) à partir de makefile.

Je sais que pour forcer make à compiler version.c toujours quelle que soit la date de modification, je peux touch version.c.

Existe-t-il un seul fichier Makefile pour y parvenir? Si j'écris .PHONY : version.o, le fichier objet ne sera pas construit du tout.

EDIT: Voici mon makefile:

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 $<
17
devemouse

La façon classique de le faire est:

version.o:   .FORCE

.FORCE:

(et vous pourriez ajouter .PHONY: .FORCE). Le fichier '.FORCE' est supposé ne pas exister, donc il est toujours 'créé', donc version.o est toujours obsolète, donc version.o est toujours compilé.

Je ne suis pas sûr que la transformation de version.o dans un fichier bidon soit correcte; c'est en fait un fichier réel, pas un fichier factice.

41
Jonathan Leffler

Si vous voulez faire cela en utilisant le mécanisme FORCE, la solution correcte ressemble à ceci:

version.o: FORCE

.PHONY: FORCE
FORCE:

En déclarant explicitement que FORCE est bidon, nous nous assurons que tout fonctionnera correctement même si .SECONDARY: est utilisé (.SECONDARY: fera en sorte que FORCE soit considéré comme un fichier intermédiaire et évitera de reconstruire les fichiers intermédiaires, à moins que les conditions préalables ne soient plus récentes que la cible ultime, et FORCE n'a pas de prérequis, donc .PHONY: FORCE est nécessaire).

L'autre solution (en utilisant $(Shell touch version.c)) a aussi un problème: cela peut amener votre éditeur à penser que la version.c a été mise à jour et à demander un rechargement du fichier, ce qui pourrait s'avérer destructif si vous avez modifié le tampon du fichier. mais je ne l'ai pas encore sauvegardé. Si cela ne vous dérange pas, cela peut être encore simplifié en observant que la commande touch est silencieuse, de sorte que l'affectation à la variable hack dummy n'est pas nécessaire:

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

Le "truc" .PHONY mentionné dans les commentaires sur la question ne fonctionne généralement pas. Cela peut sembler être le cas, car il forcera une nouvelle liaison iff si version.o existe déjà, mais le fichier objet réel ne sera pas reconstruit si la règle de fichier .o est une règle implicite (ce qui est généralement le cas). Le problème est que make ne fait pas la recherche de règle implicite pour des cibles explicitement fausses. Ce fichier de marque montre l'échec:

fooprog: test.o
        cp $< $@

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

.PHONY: test.o # WRONG

clean:
        rm test.o fooprog

Si une règle de modèle statique est utilisée à la place d'une règle implicite, l'astuce de .PHONY: version.o fonctionnera. En général, utiliser des règles de modèle statiques au lieu de règles implicites supprime la plupart des comportements Make les plus confus. Mais la plupart des fichiers utilisent des règles implicites.

4
Britton Kerin

Pas une façon de makefile, mais plus facile que de toucher:

make -B

«-B» «--ally-make»

Considérez toutes les cibles périmées. GNU commence à considérer les cibles et leurs conditions préalables à l'aide des algorithmes normaux; Cependant, toutes les cibles ainsi considérées sont toujours refaites, quel que soit le statut de leurs conditions préalables. Pour éviter une récursion infinie, si MAKE_RESTARTS (voir Autres variables spéciales) est défini sur un nombre supérieur à 0, cette option est désactivée lorsque vous envisagez de refaire des makefiles (voir Comment les makefiles sont refaits).

3
Rafael J

La version rapide de hack quand vous en avez juste besoin et que vous ne voulez pas jouer à Make games:

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

Fondamentalement, il suffit de faire Make run touch pour vous.

0
Brad