TL; DR no intentes hacer esto
$ make run arg
en su lugar crea script:
#! /bin/sh
# rebuild prog if necessary
make prog
# run prog with some arguments
./prog "$@"
y haz esto:
$ ./buildandrunprog.sh arg
Responda a la pregunta planteada:
puedes usar una variable en la receta
run: prog
./prog $(var)
luego pasa una asignación variable como argumento para hacer
$ make run var=arg
Esto se ejecutará ./prog arg
.
pero cuidado con las trampas. Voy a elaborar sobre las trampas de este método y otros métodos más adelante.
Responda a la intención asumida detrás de la pregunta:
la suposición: desea ejecutar prog
con algunos argumentos pero debe reconstruir antes de ejecutar si es necesario.
la respuesta: cree un script que se reconstruya si es necesario y luego ejecute prog con args
#! /bin/sh
# rebuild prog if necessary
make prog
# run prog with some arguments
./prog "$@"
Este guión deja muy clara la intención. utiliza make para hacer lo que es bueno: construir. utiliza un script de shell para hacer lo que es bueno: procesamiento por lotes.
Además, puede hacer cualquier otra cosa que necesite con la total flexibilidad y expresividad de un script de shell sin todas las advertencias de un archivo MAKE.
También la sintaxis de llamada ahora es prácticamente idéntica:
$ ./buildandrunprog.sh foo "bar baz"
comparar con:
$ ./prog foo "bar baz"
contraste con
$ make run var="foo bar\ baz"
antecedentes:
make no está diseñado para pasar argumentos a un objetivo. Todos los argumentos en la línea de comando se interpretan como un objetivo (también conocido como objetivo), como una opción o como una asignación variable.
así que si ejecutas esto:
$ make run foo --wat var=arg
make interpretará run
y foo
como objetivos (objetivos) actualizar según sus recetas. --wat
como una opción para hacer. y var=arg
como una asignación variable.
Para obtener más detalles, consulte: https://www.gnu.org/software/make/manual/html_node/Goals.html#Goals
para ver la terminología, consulte: https://www.gnu.org/software/make/manual/html_node/Rule-Introduction.html#Rule-Introduction
sobre el método de asignación de variables y por qué lo recomiendo
$ make run var=arg
y la variable en la receta
run: prog
./prog $(var)
Esta es la forma más "correcta" y directa de pasar argumentos a una receta. pero aunque puede usarse para ejecutar un programa con argumentos, ciertamente no está diseñado para usarse de esa manera. ver https://www.gnu.org/software/make/manual/html_node/Overriding.html#Overriding
En mi opinión, esto tiene una gran desventaja: lo que quieres hacer es correr prog
con argumentos arg
. pero en lugar de escribir:
$ ./prog arg
estas escribiendo:
$ make run var=arg
esto se vuelve aún más incómodo cuando se intenta pasar múltiples argumentos o argumentos que contienen espacios:
$ make run var="foo bar\ baz"
./prog foo bar\ baz
argcount: 2
arg: foo
arg: bar baz
comparar con:
$ ./prog foo "bar baz"
argcount: 2
arg: foo
arg: bar baz
para que conste, así es prog
como se ve mi :
#! /bin/sh
echo "argcount: $#"
for arg in "$@"; do
echo "arg: $arg"
done
También tenga en cuenta que no debe poner $(var)
comillas en el archivo MAKE:
run: prog
./prog "$(var)"
porque entonces prog
siempre obtendremos un solo argumento:
$ make run var="foo bar\ baz"
./prog "foo bar\ baz"
argcount: 1
arg: foo bar\ baz
Todo esto es por lo que recomiendo contra esta ruta.
para completar aquí hay algunos otros métodos para "pasar argumentos para hacer correr".
Método 1:
run: prog
./prog $(filter-out $@, $(MAKECMDGOALS))
%:
@true
explicación súper corta: filtrar el objetivo actual de la lista de objetivos. create catch all target ( %
) que no hace nada para ignorar silenciosamente los otros objetivos.
método 2:
ifeq (run, $(firstword $(MAKECMDGOALS)))
runargs := $(wordlist 2, $(words $(MAKECMDGOALS)), $(MAKECMDGOALS))
$(eval $(runargs):;@true)
endif
run:
./prog $(runargs)
explicación súper corta: si el objetivo es run
eliminar el primer objetivo y crear objetivos de no hacer nada para los objetivos restantes usando eval
.
ambos te permitirán escribir algo como esto
$ make run arg1 arg2
Para una explicación más profunda, estudie el manual de make: https://www.gnu.org/software/make/manual/html_node/index.html
problemas del método 1:
Los argumentos que comienzan con un guión serán interpretados por make y no se pasarán como un objetivo.
$ make run --foo --bar
solución alterna
$ make run -- --foo --bar
los argumentos con un signo igual se interpretarán por make y no se pasarán
$ make run foo=bar
sin solución
argumentos con espacios es incómodo
$ make run foo "bar\ baz"
sin solución
si resulta que un argumento es run
(igual al objetivo), también se eliminará
$ make run foo bar run
correrá en ./prog foo bar
lugar de./prog foo bar run
posible solución alternativa con el método 2
Si un argumento es un objetivo legítimo, también se ejecutará.
$ make run foo bar clean
correrá ./prog foo bar clean
pero también la receta para el objetivo clean
(suponiendo que exista).
posible solución alternativa con el método 2
cuando escribes mal un objetivo legítimo, se ignorará en silencio debido a la captura de todos los objetivos.
$ make celan
simplemente ignorará en silencio celan
.
La solución es hacer que todo sea detallado. para que veas lo que pasa. pero eso crea mucho ruido para la salida legítima.
problemas del método 2:
si un argumento tiene el mismo nombre que un objetivo existente, make imprimirá una advertencia de que se está sobrescribiendo.
no hay solución que yo sepa
los argumentos con un signo igual seguirán siendo interpretados por make y no se pasarán
sin solución
argumentos con espacios sigue siendo incómodo
sin solución
Los argumentos con saltos de espacio que eval
intentan crear no hacen nada.
solución alternativa: cree el objetivo global de capturar todo sin hacer nada como se indicó anteriormente. con el problema anterior, que nuevamente ignorará silenciosamente los objetivos legítimos mal escritos.
Se utiliza eval
para modificar el archivo MAKE en tiempo de ejecución. cuánto peor puede ir en términos de legibilidad y debugabilidad y el Principio de menor asombro .
solución alternativa: ¡no hagas esto! 1 en su lugar, escribe un script de shell que ejecute make y luego se ejecute prog
.
Solo he probado usando gnu make. otras marcas pueden tener un comportamiento diferente.
TL; DR no intentes hacer esto
$ make run arg
en su lugar crea script:
#! /bin/sh
# rebuild prog if necessary
make prog
# run prog with some arguments
./prog "$@"
y haz esto:
$ ./buildandrunprog.sh arg