Tenez compte de ce qui suit ( MCVE d'un) Makefile
:
echo >test.dat cp test.dat test.bin
Si vous exécutez make
dans un répertoire propre, cela échoue:
echo >test.dat make: *** No rule to make target 'test.bin', needed by 'my_target'. Stop.
Exécutez-le à nouveau et il réussit:
my_target: prepare test.bin prepare: echo >test.dat %.bin: %.dat cp $? $@
Ce qui semble arriver, c'est que la règle pour créer * .bin
à partir de * .dat
reconnaît seulement qu'elle sait faire test.bin
si test.dat
existe avant que quoi que ce soit ne soit exécuté , même si d'après la sortie il a déjà créé test.dat code> avant d'essayer de créer
test.bin
.
Cela ne me convient pas car je dois d'abord préparer quelques fichiers (les importer d'une autre partie antérieure du build).
Y a-t-il une solution? Peut-être un moyen de permettre aux règles d'être (ré) évaluées à la lumière des fichiers qui sont maintenant présents?
3 Réponses :
Cela se produit pour les cibles génériques, comme % .bin
. Ils sont évalués au premier passage. Vous pouvez ajouter une cible explicite de test.bin . Vous pouvez également suivre les conseils de tkausl et avoir test.dat dépendent de préparer (une cible bidon). Dans ce cas, vous n'avez plus besoin de la double dépendance:
my_target: test.bin
Merci pour la réponse. J'ai peut-être trop simplifié le problème. En réalité, le produit de construction final dépend de nombreux fichiers qui doivent être copiés, puis traités en quelques étapes, puis finalement liés. Le problème que j'avais se résume à cette chose de cible générique, qui se produit à un stade au milieu de tout cela, mais je ne sais pas comment généraliser votre réponse au vrai problème. J'en jouerai un autre demain et modifierai ma question si je peux représenter le problème d'une manière sensée. Merci!
Il y a un certain nombre de problèmes avec votre makefile. Cependant, sur la base de vos commentaires, je suis enclin à supposer que le MCVE ici est juste un peu trop "M" et qu'il a été tellement réduit qu'il a un certain nombre de problèmes de base. Je ne vais donc pas en discuter, à moins que vous ne le souhaitiez.
Le problème ici est que vous créez des fichiers importants sans indiquer que c'est ce que vous faites. Make garde en interne un cache du contenu des répertoires avec lesquels il travaille, pour des raisons de performances, et ce cache n'est mis à jour que lorsque make invoque une règle qu'il comprend la modifiera.
Ici, votre cible est prepare
mais la recette crée en fait un fichier complètement différent, test.dat
. Donc, make ne modifie pas son cache interne du contenu du répertoire et quand il vérifie le cache pour voir si le fichier test.dat
existe, il ne le fait pas.
Vous devez vous assurer que votre makefile est écrit de manière à ne pas tromper make: si une recette crée un fichier foo
alors le nom de la cible doit être foo
, pas bar
.
Merci - cette réponse a mis en évidence le problème: vous créez des fichiers importants sans indiquer de faire que c'est ce que vous faites . La solution était de créer une règle dont le but était de créer les fichiers requis, plutôt que de le faire comme effet secondaire d'une autre règle. Merci de votre aide!
vous devez écrire
%.dat: prepare @:
ou (lorsque vous voulez rester avec des caractères génériques)
test.dat: prepare
Habituellement, vous voudrez peut-être créer et utiliser des fichiers .stamp
au lieu d'une cible prepare
.
Créez une cible
test.dat
qui crée le fichier et laissezpréparer
en dépendre.