Pasar argumentos para "hacer ejecutar"

Resuelto anon asked hace 14 años • 17 respuestas

Yo uso archivos Make.

Tengo un objetivo llamado runque ejecuta el objetivo de compilación. Simplificado, se parece a lo siguiente:

prog: ....
  ...

run: prog
  ./prog

¿Hay alguna forma de pasar argumentos? De modo que

make run asdf --> ./prog asdf
make run the dog kicked the cat --> ./prog the dog kicked the cat
anon avatar Feb 07 '10 03:02 anon
Aceptado

No conozco una manera de hacer exactamente lo que quieres, pero una solución alternativa podría ser:

run: ./prog
    ./prog $(ARGS)

Entonces:

make ARGS="asdf" run
# or
make run ARGS="asdf"
Jakob Borg avatar Feb 06 '2010 20:02 Jakob Borg

Esta pregunta tiene casi tres años, pero de todos modos...

Si estás usando GNU make, esto es fácil de hacer. El único problema es que makeinterpretará los argumentos que no sean opciones en la línea de comando como objetivos. La solución es convertirlos en objetivos que no hacen nada, así que makeno te quejes:

# If the first argument is "run"...
ifeq (run,$(firstword $(MAKECMDGOALS)))
  # use the rest as arguments for "run"
  RUN_ARGS := $(wordlist 2,$(words $(MAKECMDGOALS)),$(MAKECMDGOALS))
  # ...and turn them into do-nothing targets
  $(eval $(RUN_ARGS):;@:)
endif

prog: # ...
    # ...

.PHONY: run
run : prog
    @echo prog $(RUN_ARGS)

Ejecutar esto da:

$ make run foo bar baz
prog foo bar baz
Idelic avatar Dec 27 '2012 21:12 Idelic

TL;DR no intentes hacer esto

$ make run arg

en su lugar cree un script build_and_run_prog.sh:

#! /bin/sh
# rebuild prog if necessary
make prog
# run prog with some arguments
./prog "$@"

y haz esto:

$ ./build_and_run_prog.sh arg

Siga leyendo para obtener una explicación de por qué esta es la opción más razonable y por qué es mejor evitar las otras alternativas.


Respuesta a la pregunta formulada : cómo pasar argumentos a un objetivo de creación

puedes usar una variable en la receta

run: prog
    ./prog $(var)

luego pase una asignación de variable como argumento para hacer

$ make run var=arg

esto se ejecutará ./prog arg.

esta es la forma más correcta y sencilla de "pasar argumentos a una receta". consulte el manual de gnu make sobre variables anuladas

pero si bien puede usarse para ejecutar un programa con argumentos, ciertamente no está diseñado para usarse de esa manera.

Permítanme explicar algunos problemas.

lo que quieres hacer es ejecutar progcon argumento arg. pero en lugar de escribir:

$ ./prog arg

necesitas escribir:

$ 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.

en lugar de escribir

$ ./prog foo "bar baz"

necesitas escribir

$ make run var="foo bar\ baz"

o

$ make run var="foo \"bar baz\""

Espero que veas cómo esto se volverá bastante incómodo para cualquier cosa que no sean los argumentos más simples.

También tenga en cuenta que no debe poner $(var)comillas en el archivo MAKE:

run: prog
    ./prog "$(var)"

porque entonces progsiempre obtendrá un solo argumento.


Responda a la supuesta intención detrás de su pregunta : desea ejecutar progcon algunos argumentos pero reconstruirlo antes de ejecutarlo si es necesario.

Cree un script que se reconstruya si es necesario y luego ejecute prog con args

build_and_run_prog.sh:

#! /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 aquello para lo que sirve: construir/compilar. Utiliza un script de shell para hacer aquello para lo que sirve: 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.

Además, la sintaxis de llamada ahora es prácticamente idéntica:

$ ./build_and_run_prog.sh foo "bar baz"

en comparación con:

$ ./prog foo "bar baz"

contraste con

$ make run var="foo bar\ baz"

Explicación básica de cómo make maneja los argumentos :

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 de variable.

entonces si ejecutas esto:

$ make run foo --wat var=arg

make interpretará runy foocomo objetivos (objetivos) actualizará según sus recetas. --watcomo opción para hacer. Y var=argcomo asignación variable para make.

Espero que puedas ver que el único método que tienes para pasar información desde la línea de comando para usarla dentro de una receta (sin hacks) es mediante la asignación de variables.

para más detalles consulte el manual de gnu sobre cómo ejecutar make


Para completar, estos son algunos de los trucos para "pasar argumentos para ejecutar".

Método 1 :

run: prog
    ./prog $(filter-out $@, $(MAKECMDGOALS))

%:
    @true

Explicación súper breve: filtre el objetivo actual de la lista de objetivos. luego pase la lista de objetivos como argumentos a prog. También cree un objetivo general ( %) que no haga nada para ignorar silenciosamente todos los demás "objetivos".

esto te permitirá escribir algo como esto

$ make run arg1 arg2

problemas del método 1 :

  • Los argumentos que comienzan con un guión se interpretarán como marca y no como objetivo.

      $ make run --foo --bar
    

    solución alterna

      $ make run -- --foo --bar
    
  • Los argumentos con signo igual serán interpretados como make y no aprobados.

      $ make run foo=bar
    

    no hay solución

  • Las discusiones con espacios son incómodas.

      $ make run foo "bar\ baz"
    

    no hay solución

  • Si un argumento resulta ser run(igual al objetivo), también se eliminará.

      $ make run foo bar run
    

    se ejecutará ./prog foo baren lugar de./prog foo bar run

    solución alternativa posible con el método 2

  • Si un argumento es un objetivo legítimo, también se ejecutará.

      $ make run foo bar clean
    

    se ejecutará ./prog foo bar clean, sino también la receta para el objetivo clean(suponiendo que exista).

    solución alternativa posible con el método 2

  • Cuando escribe mal un objetivo legítimo, se ignorará silenciosamente debido al objetivo de captura total.

      $ make celan
    

    simplemente lo ignorará en silencio celan.

    La solución alternativa es hacer que todo sea detallado. pues ya ves lo que pasa. pero eso crea mucho ruido para la producción legítima.

Método 2 :

ifeq (run, $(firstword $(MAKECMDGOALS)))
  runargs := $(wordlist 2, $(words $(MAKECMDGOALS)), $(MAKECMDGOALS))
  $(eval $(runargs):;@true)
endif

run:
    ./prog $(runargs)

Explicación súper breve: si el objetivo es run, procese la lista de objetivos y guárdela en la variable. También cree objetivos de no hacer nada para los "objetivos" restantes usando eval. más tarde, cuando se ejecute, progpase la variable preparada como argumentos.

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 aprobados.

    no hay solución

  • Las discusiones con espacios siguen siendo incómodas

    no hay solución

  • Argumentos con pausas espaciales evalque intentan crear objetivos de no hacer nada.

    Solución alternativa: cree el objetivo global de captura total sin hacer nada como se indicó anteriormente. con el problema anterior de que nuevamente ignorará silenciosamente los objetivos legítimos mal escritos.

  • se utiliza evalpara modificar el archivo MAKE en tiempo de ejecución. ¿Cuánto peor se puede llegar en términos de legibilidad y depuración y el Principio de mínimo asombro ?

    solución alternativa: ¡no lo hagas!

Solo he probado usando gnu make. otras marcas pueden tener un comportamiento diferente.


ñu hacer manual

https://www.gnu.org/software/make/manual/html_node/index.html

Lesmana avatar Jul 10 '2017 02:07 Lesmana

para la marca estándar, puede pasar argumentos definiendo macros como esta

make run arg1=asdf

entonces úsalos así

run: ./prog $(arg1)
   etc

Referencias para hacer NMake de Microsoft

John Knoeller avatar Feb 06 '2010 20:02 John Knoeller