¿Cómo pasar un argumento a Makefile desde la línea de comando?


109

¿Cómo pasar un argumento a Makefile desde la línea de comando?

Entiendo que puedo hacer

$ make action VAR="value"
$ value

con Makefile

VAR = "default"
action:
    @echo $(VAR)

¿Cómo obtengo el siguiente comportamiento?

$ make action value
value

?

Qué tal si

$make action value1 value2
value1 value2


3
Posible duplicado de Pasar argumentos para "ejecutar"
lesmana

Respuestas:


212

Probablemente no deberías hacer esto; estás rompiendo el patrón básico de cómo funciona Make. Pero aqui esta:

action:
        @echo action $(filter-out $@,$(MAKECMDGOALS))

%:      # thanks to chakrit
    @:    # thanks to William Pursell

EDITAR:
Para explicar el primer comando,

$(MAKECMDGOALS) es la lista de "objetivos" detallada en la línea de comando, por ejemplo, "acción valor1 valor2".

$@es una variable automática para el nombre del destino de la regla, en este caso "acción".

filter-outes una función que elimina algunos elementos de una lista. Entonces $(filter-out bar, foo bar baz)regresa foo baz(puede ser más sutil, pero no necesitamos sutileza aquí).

Ponlos juntos y $(filter-out $@,$(MAKECMDGOALS))devuelve la lista de objetivos especificados en la línea de comando que no sean "acción", que podría ser "valor1 valor2".


1
$(shell echo $(MAKECMDGOALS) | sed 's!^.* $@ !!')para omitir todos los objetivos antes y simplemente considerar los siguientes como argumentos:make target1 target2 action value1 value2
Evgeniy Generalov

1
Perdona mi ignorancia. He intentado buscar en Google %:y @:no puedo encontrar información sobre lo que hacen esas "directivas" (o como se llamen). ¿Podría explicar por favor?
Jon

15
@Jon: El manual está aquí . La parte que consta de %:y @:es una regla . El nombre del objetivo %significa que es una regla que coincide con cualquier cosa ; es decir, si Make no puede encontrar otra forma de construir lo que le dice que construya, ejecutará esa regla. El @:es una receta ; los :medios no hacen nada y los @medios lo hacen en silencio.
Beta

Gracias. Había estado leyendo ese manual y no consideré al principio, que %:era en realidad % :, un nombre de destino de tipo comodín. Sin @:embargo , no veo nada en esa página del manual con respecto a ... sí sugiere que una regla de "no hacer nada" simplemente tendría un ;después de la especificación de destino, por lo que, ¿no sería más preciso escribir % : ;como el "comodín hacer -¿Nada "regla?
Jon

1
filter-outno funciona cuando la acción es una dependencia del objetivo especificado en la línea de comando, porque $@se establecerá en el nombre de la dependencia, no en el argumento original llamado en la línea de comando. En cambio, lo asigno MAKECMDGOALSa una matriz de shell y luego elimino el primer elemento:@ args=($(MAKECMDGOALS)); args=("$${args[@]:1}")
Gingi

18

Aquí hay una solución de trabajo genérica basada en @ Beta

Estoy usando GNU Make 4.1 SHELL=/bin/bashencima de mi Makefile, ¡así que YMMV!

Esto nos permite aceptar argumentos adicionales (al no hacer nada cuando obtenemos un trabajo que no coincide, en lugar de arrojar un error).

%:
    @:

Y esta es una macro que obtiene los argumentos para nosotros:

args = `arg="$(filter-out $@,$(MAKECMDGOALS))" && echo $${arg:-${1}}`

Aquí hay un trabajo que podría llamar a este:

test:
    @echo $(call args,defaultstring)

El resultado sería:

$ make test
defaultstring
$ make test hi
hi

¡Nota! Puede que sea mejor utilizar un "archivo de tareas", que es un patrón bash que funciona de manera similar, solo que sin los matices de Maketools. Ver https://github.com/adriancooney/Taskfile


¡¡Funcionó!! Para otras personas que lo prueben, asegúrese de que haya tabantes @echo, no space.
Abdullah Al Maruf - Tuhin

11

Enfoque mucho más sencillo. Considere una tarea:

provision:
        ansible-playbook -vvvv \
        -i .vagrant/provisioners/ansible/inventory/vagrant_ansible_inventory \
        --private-key=.vagrant/machines/default/virtualbox/private_key \
        --start-at-task="$(AT)" \
        -u vagrant playbook.yml

Ahora, cuando quiero llamarlo, simplemente ejecuto algo como:

AT="build assets" make provision

o solo:

make provisionen este caso ATes una cadena vacía


-2

no intentes hacer esto

$ make action value1 value2

en su lugar, cree un script:

#! /bin/sh
# rebuild if necessary
make
# do action with arguments
action "$@"

y haz esto:

$ ./buildthenaction.sh value1 value2

para obtener más explicaciones de por qué hacer esto y las advertencias de la piratería de archivos Makefile, lea mi respuesta a otra pregunta muy similar pero aparentemente no duplicada: Pasar argumentos para "hacer correr"

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.