GNU Makefile règle de générer un peu de cibles à partir d'un seul fichier source
Je suis tenter de faire le suivant. Il y a un programme, appeler foo-bin
, qui tient en un seul fichier d'entrée et génère deux fichiers de sortie. Un muet Makefile règle serait:
file-a.out file-b.out: input.in
foo-bin input.in file-a.out file-b.out
Toutefois, cela ne veut pas dire make
en aucune façon que les deux objectifs seront générés simultanément. C'est très bien lors de l'exécution de make
en série, mais sera susceptible de causer des problèmes si l'on essaie make -j16
ou quelque chose d'aussi fou.
La question est de savoir si il existe un moyen pour écrire un Makefile règle pour ce cas? Clairement, il serait de générer un DAG, mais de toute façon le GNU make manuel ne précise pas comment cette affaire pourrait être manipulés.
L'exécution du même code deux fois et en ne générant qu'un résultat est hors de question, car le calcul prend du temps (pense: les heures). La sortie d'un seul fichier doit également être assez difficile, car il est fréquemment utilisé comme entrée pour GNUPLOT qui ne sait pas comment gérer qu'une fraction d'un fichier de données.
- Automake a de la documentation à ce sujet: gnu.org/software/automake/manual/html_node/...
Vous devez vous connecter pour publier un commentaire.
Je voudrais résoudre comme suit :
Dans ce cas parallèle faire sera "sérialiser" la création de a et b, mais depuis la création de b ne fait rien, il ne prend pas de temps.
file-b.out
a été créé comme indiqué, puis mystérieusement effacé,make
sera impossible de recréer ce parce quefile-a.out
sera toujours présente. Toutes les pensées?file-a.out
alors la solution ci-dessus fonctionne bien. Ceci suggère un hack: si un seul de a ou b, puis les dépendances doivent être ordonnés de manière à ce que la fichier manquant apparaît comme la production deinput.in
. Quelques$(widcard...)
s,$(filter...)
s,$(filter-out...)
s etc., devrait faire l'affaire. Ugh.foo-bin
sera bien évidemment créer l'un des fichiers (à l'aide de la microseconde résolution), vous devez donc vous assurer d'avoir le bon dépendance de la commande lorsque les deux fichiers existent.touch file-a.out
comme une seconde commande après l'foo-bin
invocation.touch file-b.out
comme une seconde commande dans la première règle et de dupliquer les commandes dans la deuxième règle. Si le fichier est manquant ou âgés de plus deinput.in
, la commande sera exécutée une seule fois et se régénère à la fois les fichiers avecfile-b.out
plus récente quefile-a.out
.L'astuce consiste à utiliser un modèle de règle avec des objectifs multiples. Dans ce cas, supposons que les deux objectifs sont créés par une seule invocation de la commande.
Cette différence d'interprétation entre le modèle de règles et les règles normales n'est pas exactement du sens, mais il est utile pour les cas comme cela, et il est documenté dans le manuel.
Cette astuce peut être utilisée pour n'importe quel nombre de fichiers de sortie, aussi longtemps que leurs noms ont en commun certaines sous-chaîne pour la
%
de match. (Dans ce cas, la sous-chaîne commune est ".")make
va exécuter la même commande deux fois simultanément.foo%in bar%src: input.in
🙂.
. Intelligent.$(subst .,%,$(varA) $(varB)): input.in
(testé avec GNU make 4.1).N
processus pour la même cible avecmake -jN
.N'ont pas de toute façon intuitive pour le faire, mais il y a deux décent solutions de contournement.
Tout d'abord, si les cibles concernées ont une racine commune, vous pouvez utiliser un préfixe de la règle (avec GNU make). C'est, si vous voulez fixer la règle suivante:
Vous pouvez l'écrire de cette façon:
(À l'aide du modèle de la règle de la variable $*, qui signifie " correspondant à la partie du modèle)
Si vous voulez être portable à la non-GNU Make implémentations ou si vos fichiers ne peuvent pas être nommés pour correspondre à un modèle de règle, il est une autre façon:
Cela dit de faire une entrée.dans.intermédiaires ne sont pas exister avant de faire est d'exécuter, de sorte que son absence (ou son timestamp) ne cause pas de foo-bin pour être exécuté par erreur. Et si l'un des fichiers-un.ou fichier-b.ou les deux sont out-of-date (par rapport à l'entrée.dans l'), foo-bin sera exécuté qu'une fois. Vous pouvez utiliser .SECONDAIRE au lieu de .INTERMÉDIAIRE, qui ordonnera de ne PAS supprimer un hypothétique de saisie nom de fichier.dans.intermédiaire. Cette méthode est également sûr pour les parallèles de faire des builds.
Le point-virgule sur la première ligne est important. Il crée un vide recette pour que la règle, de sorte que Faire sait que l'on va vraiment être la mise à jour de fichier-un.et fichier-b.(grâce @siulkiulki et d'autres qui l'a signalé)
-j1
construit). Aussi, si le makefile est interrompu et qu'il laisse lainput.in.intermediate
fichier autour de ça devient vraiment confus.file-a.out file-b.out: input.in.intermediate
àfile-a.out file-b.out: input.in.intermediate ;
Voir stackoverflow.com/questions/37873522/... pour plus de détails.Ceci est basé sur @deemer deuxième réponse qui ne repose pas sur le patron de règles, et il résout un problème que je vivais avec imbriqué utilise de la solution de contournement.
J'aurais ajouté présente comme un commentaire de @deemer réponse, mais je ne peux pas parce que je viens de créer ce compte et n'ont pas de réputation.
Explication: Le vide recette est nécessaire afin de permettre de faire de faire de la bonne tenue de la comptabilité de marque
file-a.out
etfile-b.out
comme ayant été reconstruite. Si vous avez encore un autre objectif intermédiaire qui dépendfile-a.out
, puis Faire sera de choisir de ne pas générer de l'extérieur intermédiaires, affirmant:C'est comment je le fais. D'abord j'ai toujours séparé de pré-requesits de recettes. Alors dans ce cas une nouvelle cible pour faire la recette.
La première fois:
1. Nous essayons de créer un fichier-un.hors, mais factice-a-et-b.out doit être fait en premier afin de faire fonctionner le mannequin-a-et-b.de recettes.
2. Nous essayons de créer un fichier-b.hors, le mannequin-a-et-b.jusqu'à ce jour.
La deuxième et les suivantes du temps:
1. Nous essayons de créer un fichier-un.out: faire regarde les conditions préalables, les normales conditions préalables sont à jour, secondaire conditions requises sont manquantes sont donc ignorées.
2. Nous essayons de créer un fichier-b.out: faire regarde les conditions préalables, les normales conditions préalables sont à jour, secondaire conditions requises sont manquantes sont donc ignorées.
file-b.out
faire n'a aucun moyen de le re-créer.Comme une extension de @deemer réponse, j'ai généralisé dans une fonction.
Ventilation:
Bande tout avant/après les espaces du premier argument
Créer une variable cible à une valeur unique, à utiliser comme cible intermédiaire. Pour ce cas, la valeur sera .l'inter.fichier-un.out_file-b.out.
Créer un vide recette pour les sorties avec l'unique objectif depedency.
Déclarer la cible unique comme intermédiaire.
Terminer avec une référence à l'unique cible de sorte que cette fonction peut être utilisée directement dans une recette.
Notez également l'utilisation de eval ici, c'est parce eval étend à rien donc, la pleine expansion de la fonction est l'unique cible.
Faut donner crédit à Atomique Règles de GNU Make qui cette fonction est inspirée de l'.