252 votes

Comment forcer un makefile à reconstruire une cible ?

J'ai un makefile qui construit et appelle ensuite un autre makefile. Comme ce makefile appelle d'autres makefiles qui font le travail, il ne change pas vraiment. Il continue donc à penser que le projet est construit et à jour.

dnetdev11 ~ # make
make: `release' is up to date.

Comment puis-je forcer le makefile à reconstruire la cible ?

clean = $(MAKE) -f ~/xxx/xxx_compile.workspace.mak clean

build = svn up ~/xxx                                                       \
        $(clean)                                                                \
        ~/cbp2mak/cbp2mak -C ~/xxx ~/xxx/xxx_compile.workspace        \
        $(MAKE) -f ~/xxx/xxx_compile.workspace.mak $(1)                    \

release:
        $(build )

debug:
        $(build DEBUG=1)

clean:
        $(clean)

install:
        cp ~/xxx/source/xxx_utility/release/xxx_util /usr/local/bin
        cp ~/xxx/source/xxx_utility/release/xxxcore.so /usr/local/lib

Note : Les noms ont été supprimés pour protéger les innocents

Version finale corrigée :

clean = $(MAKE) -f xxx_compile.workspace.mak clean;

build = svn up;                                         \
        $(clean)                                        \
        ./cbp2mak/cbp2mak -C . xxx_compile.workspace;   \
        $(MAKE) -f xxx_compile.workspace.mak    $(1);   \

.PHONY: release debug clean install

release:
        $(call build,)

debug:
        $(call build,DEBUG=1)

clean:
        $(clean)

install:
        cp ./source/xxx_utillity/release/xxx_util /usr/bin
        cp ./dlls/Release/xxxcore.so /usr/lib

0 votes

Lodle, comme il s'agit d'une question fréquemment posée, voudriez-vous modifier la question pour la rendre plus moderne ? .PHONY n'était pas votre seul problème, et vous n'êtes pas vraiment censé éditer la solution dans la question, ou du moins plus maintenant).

869voto

sykora Points 30290

El -B à faire, dont la forme longue est --always-make , dit make pour ne pas tenir compte des timestamps et faire les cibles spécifiées. Cela peut aller à l'encontre de l'objectif de make, mais c'est peut-être ce dont vous avez besoin.

9 votes

@MarkKCowan Je suis tout à fait d'accord ! Cette option est exactement ce que je recherchais, et non une solution de contournement comme le suggère Dave.

9 votes

L'inconvénient de cette approche est qu'elle construit trop de choses. En particulier avec autotools, je l'ai vu réexécuter configure J'aimerais qu'une solution basée sur LD_PRELOAD puisse être construite !

0 votes

Oui, et il peut même réécrire des fichiers que vous ne vouliez pas ! comme les bibliothèques système globales qui apparaissent dans les dépendances et sont reconstruites et écrasées...

40voto

Dave Points 5879

Vous pouvez déclarer une ou plusieurs de vos cibles comme étant faux .

Une cible fictive n'est pas vraiment le nom d'un fichier ; il s'agit plutôt du nom d'une recette à exécuter lorsque vous faites un choix explicite. nom d'une recette à exécuter lorsque vous faites une demande explicite. demande explicite. Il existe deux raisons d'utiliser une cible fictive : pour éviter un conflit avec un fichier du même nom, et pour améliorer les performances.

...

Une cible fictive ne doit pas être une condition préalable à un fichier cible réel. il l'est, sa recette sera exécutée chaque fois que make mettra à jour ce fichier ce fichier. Tant qu'une cible fictive n'est jamais un prérequis d'une cible réelle, la recette de la cible fictive ne sera exécutée que lorsque la cible fictive sera mise à jour. cible réelle, la recette de la cible fictive ne sera exécutée que si la cible fictive est un fichier spinoff. est un objectif spécifié

95 votes

Cette réponse, bien qu'elle soit "acceptée" et fortement "upvoted", est vraiment à côté de la plaque. D'abord, il est dit "déclarer les cibles comme étant fausses" mais ensuite il est dit "la cible fausse n'est pas vraiment le nom d'un fichier". Eh bien, si votre cible est un fichier, c'est une contradiction dans la réponse. Deuxièmement, il est dit que "la cible fictive ne devrait pas être une condition préalable à une cible réelle" - et si c'était le cas ? La question initiale ne précisait pas si elle l'était ou non. La réponse correcte est, no de déclarer votre pour qu'elles soient fausses, mais plutôt, déclarer une cible fausse supplémentaire, et ensuite, faire dépendre les cibles que vous voulez reconstruire, de celle-ci.

6 votes

@MarkGaleck. Lorsque la réponse indique que "Une cible fictive est une cible qui n'est pas réellement le nom d'un fichier", elle cite directement le manuel make de gcc. C'est parfaitement correct.

0 votes

"Cible" est un terme de marque qui désigne le texte situé à gauche des deux points. : et pas seulement le résultat final que vous voulez créer (par exemple, votre fichier binaire). Dans la question, release , debug , clean y install sont les cibles de Make, et non xxx_util o xxxcore.so ou quoi que ce soit d'autre.

25voto

Jonathan Leffler Points 299946

Une astuce qui était autrefois documentée dans un manuel Sun pour make est d'utiliser une cible (inexistante) '.FORCE'. Vous pouvez le faire en créant un fichier, force.mk, qui contient :

.FORCE:
$(FORCE_DEPS): .FORCE

Ensuite, en supposant que votre makefile existant s'appelle makefile tu pourrais courir :

make FORCE_DEPS=release -f force.mk -f makefile release

Depuis .FORCE n'existe pas, tout ce qui en dépend sera périmé et reconstruit.

Tout ceci fonctionnera avec n'importe quelle version de make sous Linux, vous disposez de GNU Make et pouvez donc utiliser la cible .PHONY comme indiqué.

Il convient également de se demander pourquoi make considère que le communiqué est à jour. Cela peut être dû au fait que vous avez un touch release parmi les commandes exécutées ; cela pourrait être dû au fait qu'il existe un fichier ou un répertoire appelé 'release' qui n'a pas de dépendances et qui est donc à jour. Et puis il y a la raison réelle...

21voto

easel Points 2466

Quelqu'un d'autre a suggéré .PHONY, ce qui est tout à fait correct. .PHONY doit être utilisé pour toute règle pour laquelle une comparaison de date entre l'entrée et la sortie est invalide. Puisque vous n'avez pas de cibles de la forme output: input vous devriez utiliser .PHONY pour TOUTES ces personnes !

Tout ceci étant dit, vous devriez probablement définir quelques variables en haut de votre makefile pour les différents noms de fichiers, et définir de vraies règles de make qui ont à la fois des sections d'entrée et de sortie afin de pouvoir utiliser les avantages de make, à savoir que vous ne compilerez réellement que les choses qui sont nécessaires à copmile !

Edit : ajout d'un exemple. Non testé, mais c'est comme ça que vous faites .PHONY

.PHONY: clean    
clean:
    $(clean)

1 votes

Si vous pouviez me montrer un exemple, ce serait bien. Pour l'instant, j'essaie juste de faire fonctionner ce satané truc :P

2 votes

L'emplacement de la .PHONY La cible n'a pas d'importance. Elle peut être n'importe où dans le Makefile .

7voto

poundifdef Points 6005

Si je me souviens bien, 'make' utilise des timestamps (temps de modification des fichiers) pour déterminer si une cible est à jour ou non. Une façon courante de forcer une reconstruction est de mettre à jour cet horodatage, en utilisant la commande 'touch'. Vous pourriez essayer d'invoquer 'touch' dans votre makefile pour mettre à jour l'horodatage d'une des cibles (peut-être un de ces sous-makefiles), ce qui pourrait forcer Make à exécuter cette commande.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X