J'utilise des Makefiles.
J'ai une cible appelée run
qui exécute la cible de génération. Simplifié, il ressemble à ceci:
prog: ....
...
run: prog
./prog
Existe-t-il un moyen de transmettre des arguments? Pour que
make run asdf --> ./prog asdf
make run the dog kicked the cat --> ./prog the dog kicked the cat
Merci!
Réponses:
Je ne sais pas comment faire exactement ce que vous voulez, mais une solution de contournement pourrait être:
Alors:
la source
$(foo)' or
$ {foo} 'est une référence valide pour la variable `foo '." et donne des exemples où seul $ () est utilisé. Et bien.Cette question a presque trois ans, mais de toute façon ...
Si vous utilisez GNU make, c'est facile à faire. Le seul problème est que
make
les arguments sans option de la ligne de commande seront interprétés comme des cibles. La solution est de les transformer en cibles de ne rien faire, alorsmake
ne vous plaignez pas:L'exécution de ceci donne:
la source
prog foo bar --baz
make
ne pas interpréter--baz
comme une option de ligne de commande:make -- prog foo bar --baz
. Le--
signifie "tout ce qui suit est un argument, pas une option".RUN_ARGS
utiliser?else
branche à laifeq
etRUN_ARGS
y mettre ?$(eval $(RUN_ARGS):dummy;@:)
, sans aucune cible fictive définie.pour la marque standard, vous pouvez passer des arguments en définissant des macros comme celle-ci
puis utilisez-les comme ça
Références pour faire NMake de Microsoft
la source
Vous pouvez passer la variable au Makefile comme ci-dessous:
Usage:
ou:
Vous pouvez également utiliser la solution fournie par Beta :
Usage:
la source
TL; DR n'essayez pas de faire cela
créez plutôt un script:
et faites ceci:
réponse à la question posée:
vous pouvez utiliser une variable dans la recette
puis passez une affectation de variable comme argument pour faire
cela s'exécutera
./prog arg
.mais méfiez-vous des pièges. je développerai les pièges de cette méthode et d'autres méthodes plus bas.
réponse à l'intention supposée derrière la question:
l'hypothèse: vous voulez exécuter
prog
avec quelques arguments mais le faire reconstruire avant de l'exécuter si nécessaire.la réponse: créer un script qui reconstruit si nécessaire puis exécute prog avec args
ce script rend l'intention très claire. il utilise make pour faire ce pour quoi il est bon: construire. il utilise un script shell pour faire ce qu'il est bon: le traitement par lots.
De plus, vous pouvez faire tout ce dont vous pourriez avoir besoin avec toute la flexibilité et l'expressivité d'un script shell sans toutes les mises en garde d'un makefile.
la syntaxe d'appel est désormais pratiquement identique:
comparer aux:
contrairement à
Contexte:
make n'est pas conçu pour transmettre des arguments à une cible. tous les arguments de la ligne de commande sont interprétés soit comme un objectif (alias cible), comme une option, soit comme une affectation de variable.
donc si vous lancez ceci:
make interprétera
run
etfoo
comme objectifs (cibles) à mettre à jour en fonction de leurs recettes.--wat
en option pour faire. etvar=arg
comme une affectation variable.pour plus de détails, voir: https://www.gnu.org/software/make/manual/html_node/Goals.html#Goals
pour la terminologie, voir: https://www.gnu.org/software/make/manual/html_node/Rule-Introduction.html#Rule-Introduction
sur la méthode d'affectation des variables et pourquoi je la déconseille
et la variable dans la recette
c'est le moyen le plus "correct" et le plus simple de passer des arguments à une recette. mais bien qu'il puisse être utilisé pour exécuter un programme avec des arguments, il n'est certainement pas conçu pour être utilisé de cette façon. voir https://www.gnu.org/software/make/manual/html_node/Overriding.html#Overriding
à mon avis, cela a un gros inconvénient: ce que vous voulez faire, c'est exécuter
prog
avec argumentarg
. mais au lieu d'écrire:tu écris:
cela devient encore plus gênant lorsque vous essayez de passer plusieurs arguments ou des arguments contenant des espaces:
comparer aux:
pour mémoire, voici à quoi je
prog
ressemble:notez également que vous ne devez pas mettre
$(var)
de guillemets dans le makefile:car alors,
prog
il n'y aura toujours qu'un seul argument:c'est pourquoi je déconseille cette route.
pour être complet, voici quelques autres méthodes pour "passer des arguments pour exécuter".
méthode 1:
super courte explication: filtrer l'objectif actuel de la liste des objectifs. create catch all target (
%
) qui ne fait rien pour ignorer silencieusement les autres objectifs.méthode 2:
super courte explication: si la cible est
run
alors supprimez le premier objectif et créez des cibles de ne rien faire pour les objectifs restants en utilisanteval
.les deux vous permettront d'écrire quelque chose comme ça
pour une explication plus approfondie, étudiez le manuel de make: https://www.gnu.org/software/make/manual/html_node/index.html
problèmes de méthode 1:
les arguments qui commencent par un tiret seront interprétés par make et ne seront pas transmis comme objectif.
solution de contournement
les arguments avec un signe égal seront interprétés par make et ne seront pas passés
pas de solution
les arguments avec des espaces sont maladroits
pas de solution
si un argument se trouve être
run
(égal à la cible), il sera également suppriméfonctionnera
./prog foo bar
au lieu de./prog foo bar run
solution possible avec la méthode 2
si un argument est une cible légitime, il sera également exécuté.
s'exécutera
./prog foo bar clean
mais aussi la recette de la cibleclean
(en supposant qu'elle existe).solution possible avec la méthode 2
lorsque vous saisissez mal une cible légitime, elle est ignorée en silence à cause de la capture de toutes les cibles.
va simplement ignorer silencieusement
celan
.solution de contournement consiste à tout rendre verbeux. vous voyez donc ce qui se passe. mais cela crée beaucoup de bruit pour la sortie légitime.
problèmes de méthode 2:
si un argument a le même nom qu'une cible existante, make affichera un avertissement indiquant qu'il est écrasé.
aucune solution de contournement que je connaisse
les arguments avec un signe égal seront toujours interprétés par make et ne seront pas passés
pas de solution
les arguments avec des espaces sont toujours maladroits
pas de solution
des arguments avec des sauts d'espace
eval
essayant de créer des cibles de ne rien faire.solution: créez la cible globale catch all sans rien faire comme ci-dessus. avec le problème ci-dessus, il ignorera à nouveau silencieusement les cibles légitimes mal tapées.
il utilise
eval
pour modifier le makefile lors de l'exécution. combien pire pouvez-vous aller en termes de lisibilité et de débogage et le principe du moindre étonnement .solution de contournement: ne faites pas ça !! 1 au lieu d'écrire un script shell qui exécute make puis s'exécute
prog
.j'ai seulement testé en utilisant gnu make. d'autres marques peuvent avoir un comportement différent.
TL; DR n'essayez pas de faire cela
créez plutôt un script:
et faites ceci:
la source
Voici une autre solution qui pourrait vous aider dans certains de ces cas d'utilisation:
En d'autres termes, choisissez un préfixe (
test-
dans ce cas), puis passez le nom cible directement au programme / runner. Je suppose que cela est surtout utile s'il y a un script de coureur impliqué qui peut déballer le nom cible en quelque chose d'utile pour le programme sous-jacent.la source
$*
pour passer uniquement la partie de la cible qui correspond au%
.Non. En regardant la syntaxe de la page de manuel de GNU make
vous pouvez spécifier plusieurs cibles, d'où «non» (au moins non de la manière exacte que vous avez spécifiée).
la source
Vous pouvez extraire explicitement chaque nième argument de la ligne de commande. Pour ce faire, vous pouvez utiliser la variable MAKECMDGOALS, elle contient la liste des arguments de ligne de commande donnés à «make», qu'elle interprète comme une liste de cibles. Si vous voulez extraire le nième argument, vous pouvez utiliser cette variable combinée avec la fonction "word", par exemple, si vous voulez le deuxième argument, vous pouvez le stocker dans une variable comme suit:
la source
make: *** No rule to make target 'arg'. Stop.
anon ,
run: ./prog
semble un peu étrange, car la partie droite devrait être une cible, doncrun: prog
semble mieux.Je suggérerais simplement:
et je voudrais ajouter que des arguments peuvent être transmis:
make arg1="asdf" run
arg1="asdf" make run
la source
Voici mon exemple. Notez que j'écris sous Windows 7, en utilisant mingw32-make.exe fourni avec Dev-Cpp. (J'ai c: \ Windows \ System32 \ make.bat, donc la commande est toujours appelée "make".)
Utilisation pour un nettoyage régulier:
Utilisation pour nettoyer et créer une sauvegarde dans mydir /:
la source
Pas trop fier de cela, mais je ne voulais pas passer dans les variables d'environnement alors j'ai inversé la façon d'exécuter une commande standard:
cela affichera la commande que vous souhaitez exécuter, alors évaluez-la simplement dans un sous-shell:
la source
J'ai trouvé un moyen d'obtenir les arguments avec un signe égal (=)! La réponse est surtout un ajout à la réponse de @lesmana (car c'est la plus complète et expliquée ici), mais ce serait trop gros pour l'écrire en commentaire. Encore une fois, je répète son message: TL; DR n'essayez pas de faire ça!
J'avais besoin d'un moyen de traiter mon argument
--xyz-enabled=false
(car la valeur par défaut est vraie), que nous savons tous maintenant que ce n'est pas une cible de fabrication et donc ne fait pas partie de$(MAKECMDGOALS)
.En examinant toutes les variables de make en faisant écho à la,
$(.VARIABLES)
j'ai obtenu ces sorties intéressantes:Cela nous permet d'aller de deux façons: soit en commençant par une
--
(si cela s'applique à votre cas), soit en examinant la variable spécifique à GNU make (probablement pas destinée à être utilisée)-*-command-variables-*-
. ** Voir le pied de page pour des options supplémentaires ** Dans mon cas, cette variable contenait:Avec cette variable nous pouvons la combiner avec la solution déjà existante avec
$(MAKECMDGOALS)
et donc en définissant:et l'utiliser avec (mélanger explicitement l'ordre des arguments):
revenu:
Comme vous pouvez le voir, nous perdons l'ordre total des arguments. La partie avec les arguments "affectation" semble avoir été inversée, l'ordre des arguments "cible" est conservé. J'ai placé les "affectations" -args au début, j'espère que votre programme ne se soucie pas de l'emplacement de l'argument.
Mise à jour: les variables suivantes sont également prometteuses:
la source
Une autre astuce que j'utilise est le
-n
drapeau, qui indiquemake
de faire un run à sec. Par exemple,la source