Dans mon fichier GNUake, je voudrais avoir une règle qui utilise un répertoire temporaire. Par exemple:
out.tar: TMP := $(Shell mktemp -d)
echo hi $(TMP)/hi.txt
tar -C $(TMP) cf $@ .
rm -rf $(TMP)
Comme indiqué, la règle ci-dessus crée le répertoire temporaire au moment où elle est analysée. Cela signifie que, même si je ne décroche pas toujours.tar, de nombreux répertoires temporaires sont créés. Je voudrais éviter que mon/tmp soit jonché de répertoires temporaires inutilisés.
Existe-t-il un moyen de ne définir la variable que lorsque la règle est déclenchée, et non à chaque fois qu'elle est définie?
Mon idée principale est de vider mktemp et tar dans un script Shell, mais cela semble quelque peu inesthétique.
Dans votre exemple, la variable TMP
est définie (et le répertoire temporaire créé) chaque fois que les règles pour out.tar
sont évaluées. Afin de créer le répertoire uniquement lorsque out.tar
est effectivement déclenché, vous devez déplacer la création du répertoire dans les étapes suivantes:
out.tar :
$(eval TMP := $(Shell mktemp -d))
@echo hi $(TMP)/hi.txt
tar -C $(TMP) cf $@ .
rm -rf $(TMP)
La fonction eval évalue une chaîne comme si elle avait été saisie manuellement dans le fichier makefile. Dans ce cas, la variable TMP
est définie sur le résultat de l'appel de fonction Shell
.
edit (en réponse aux commentaires):
Pour créer une variable unique, vous pouvez procéder comme suit:
out.tar :
$(eval $@_TMP := $(Shell mktemp -d))
@echo hi $($@_TMP)/hi.txt
tar -C $($@_TMP) cf $@ .
rm -rf $($@_TMP)
Cela préfixerait le nom de la cible (out.tar, dans ce cas) à la variable, produisant une variable portant le nom out.tar_TMP
. Espérons que cela suffira à prévenir les conflits.
Un moyen relativement simple de procéder consiste à écrire la séquence entière sous forme de script Shell.
out.tar:
set -e ;\
TMP=$$(mktemp -d) ;\
echo hi $$TMP/hi.txt ;\
tar -C $$TMP cf $@ . ;\
rm -rf $$TMP ;\
J'ai regroupé quelques conseils connexes ici: https://stackoverflow.com/a/29085684/86967
Une autre possibilité consiste à utiliser des lignes distinctes pour configurer les variables Make quand une règle est déclenchée.
Par exemple, voici un fichier makefile avec deux règles. Si une règle se déclenche, elle crée un répertoire temporaire et définit TMP sur le nom du répertoire temporaire.
PHONY = ruleA ruleB display
all: ruleA
ruleA: TMP = $(Shell mktemp -d testruleA_XXXX)
ruleA: display
ruleB: TMP = $(Shell mktemp -d testruleB_XXXX)
ruleB: display
display:
echo ${TMP}
L'exécution du code produit le résultat attendu:
$ ls
Makefile
$ make ruleB
echo testruleB_Y4Ow
testruleB_Y4Ow
$ ls
Makefile testruleB_Y4Ow