Necesito para ejecutar algunos hacen de las reglas de forma condicional, sólo si el Python instalado es mayor que la de una versión determinada (digamos 2.5).

Pensé que podría hacer algo como ejecutar:

python -c 'import sys; print int(sys.version_info >= (2,5))'

y, a continuación, utilizando la salida (‘1’ si bien ‘0’ en caso contrario) en un ifeq hacer declaración.

En un simple shell bash script es sólo:

MY_VAR=`python -c 'import sys; print int(sys.version_info >= (2,5))'`

pero que no funciona en un archivo Makefile.

Alguna sugerencia? Yo podría utilizar cualquier otro sensata solución para lograr esto.

  • Extraño comillas alrededor de los comandos de trabajo para la ejecución de otras secuencias de comandos para mí en un archivo Makefile. Podría ser algo más.
InformationsquelleAutor fortran | 2010-01-07

6 Comentarios

  1. 296

    El uso de la marca shell builtin como en MY_VAR=$(shell echo whatever)

    [email protected]:~$make
    MY_VAR IS whatever

    [email protected]:~$ cat Makefile 
    MY_VAR := $(shell echo whatever)
    
    all:
        @echo MY_VAR IS $(MY_VAR)
    • shell no es un estándar de Hacer integrados de comando. Este es un GNU Make builtin.
    • stackoverflow.com/a/2373111/12916 añade una nota importante acerca de escape $.
    • Este ejemplo simple funciona. También funciona con comandos de shell de la tubería. Pero es esencial que usted debe usar $$ para representar $ en el shell de comandos
    • Mientras que la pregunta es medianamente viejo, es mejor hacer MI_VAR := $(shell …), de lo contrario cada vez MI_VAR es evaluado, se va a ejecutar $(shell …) de nuevo.
    • Había un espacio entre la cáscara y la apertura de paréntesis y sólo después de quitar el espacio en mi makefile de texto de salida
    • Reemplazar shell echo whatever con python -c 'import sys; print int(sys.version_info >= (2,5))'. Usted obtener «error de sintaxis cerca de testigo inesperado». No puedo entender cómo alguien pensaba que esto respondió a la pregunta. Puede alguien por favor explique lo que me falta?
    • Añadir una respuesta que se ocupa de la inexplicable errores que he hecho referencia anteriormente.
    • Si utiliza $(MY_VAR) de nuevo en otro de los comandos dentro de ese objetivo de que se ejecute echo whatever de nuevo o utilizar la salida del último comando? Porque la necesito para que sólo se ejecute una vez.
    • Funciona desde dentro de una receta.
    • señaló que sólo funciona si la última línea se inicia con una líder en la pestaña (no espacios). Si copia y pega, dependiendo de su editor el comportamiento de usted puede obtener espacios. E. g. pegar en el Eclipse Makefile editor producido un líder en la ficha.
    • Gracias por mencionar la re-ejecución si = se utiliza en lugar de :=. Esto me tenía desconcertado ahora como estoy con un no-determinista de comandos (mktemp).
    • Que make(1) sí; las fichas son necesarios en lugar de espacios (en objetivos por lo menos).
    • Cierto, pero entonces, si usted la sigue por un += se va a añadir a la variable, así como una nota de interés (muy útil para, por ejemplo, CFLAGS porque puede, dependiendo de directorio de construcción, por ejemplo, diferentes marcadores de compilación).
    • sí, sé que es hacer que se requiere formato de entrada; mi comentario era sobre el comportamiento de los editores de texto.
    • = es el adecuado si sólo vas a usar esa variable en un objetivo, si usted utiliza := entonces no importa qué objetivo de ejecutar la variable se evalúa siempre

  2. 24

    Envolver la asignación en un eval está trabajando para mí.

    # dependency on .PHONY prevents Make from 
    # thinking there's `nothing to be done`
    set_opts: .PHONY
      $(eval DOCKER_OPTS = -v $(shell mktemp -d -p /scratch):/output)
    • «Nota: El @verdadera aquí impide Hacer pensar que no hay nada que hacer.» Um, que es lo que .PHONY always make these targets es para.
    • Gracias! Esto me ayuda a bypass «raro bash» en el fichero makefile
  3. 13

    Estoy escribiendo una respuesta a aumentar la visibilidad de la sintaxis real que resuelve el problema. Por desgracia, lo que alguien podría ver como algo trivial, pueden convertirse en una importante dolor de cabeza para alguien que busca una respuesta simple a una pregunta razonable.

    Poner lo siguiente en el archivo «Makefile».

    MY_VAR := $(shell python -c 'import sys; print int(sys.version_info >= (2,5))')
    
    all:
        @echo MY_VAR IS $(MY_VAR)

    El comportamiento que le gustaría ver es el siguiente (suponiendo que tiene los últimos python instalado).

    make
    MY_VAR IS 1

    Si copia y pega el texto en el archivo Makefile, va a conseguir esto? Probablemente no. Probablemente obtendrá un error parecido a lo que se informó aquí:

    makefile:4: *** falta de separador. Parada

    Por qué: Porque, aunque yo personalmente utiliza un auténtico ficha de Desbordamiento de Pila (tratando de ser útil) se convierte en mi ficha en un número de espacios. Usted, frustrado ciudadanos de la internet, ahora copia este, pensando que ahora tiene el mismo texto que he utilizado. El comando make, ahora lee los espacios y encuentra que el «todos» los comandos de formato es incorrecto. Así, copia el texto de arriba, pegar y, a continuación, convertir el espacio en blanco antes de «@echo» a una ficha, y en este ejemplo se debe, al fin, esperemos que funcione para usted.

    • Depende de lo que el editor va a pegar en. He copiado y pegado en un Eclipse Makefile editor, y tiene un líder en la ficha (según sea necesario).
    • Oh, yo no creo eso. Átomo de aquí.
  4. 13

    Aquí es un poco más complicado con la tubería y la asignación de variable en el interior de la receta:

    getpodname:
        # Getting pod name
        @eval $$(minikube docker-env) ;\
        $(eval PODNAME=$(shell sh -c "kubectl get pods | grep profile-posts-api | grep Running" | awk '{print $$1}'))
        echo $(PODNAME)
    • En caso de que alguna vez llega a la mano estoy usando un poco de enfoque similar para obtener PODNAME por el nombre de la implementación: $(eval PODNAME=$(shell sh -c "kubectl get pod -l app=sqlproxy -o jsonpath='{.items[0].metadata.name}'"))
  5. 4

    Con GNU Make, puede utilizar shell y eval para almacenar, ejecutar y asignar la salida de comando arbitrario de la línea de invocaciones. La diferencia entre el ejemplo de abajo y los que utilizan := es el := asignación sucede una vez (cuando se encuentra) y para todos. De forma recursiva ampliado conjunto de variables con = son un poco más «perezoso»; las referencias a otras variables se mantienen hasta que la variable en sí se hace referencia, y el posterior recursiva de expansión se lleva a cabo cada vez que la variable se hace referencia, lo que es deseable para hacer «de conformidad, que se puede llamar, fragmentos». Ver el manual sobre la configuración de las variables de para obtener más información.

    # Generate a random number.
    # This is not run initially.
    GENERATE_ID = $(shell od -vAn -N2 -tu2 < /dev/urandom)
    
    # Generate a random number, and assign it to MY_ID
    # This is not run initially.
    SET_ID = $(eval MY_ID=$(GENERATE_ID))
    
    # You can use .PHONY to tell make that we aren't building a target output file
    .PHONY: mytarget
    mytarget:
    # This is empty when we begin
        @echo $(MY_ID)
    # This recursively expands SET_ID, which calls the shell command and sets MY_ID
        $(SET_ID)
    # This will now be a random number
        @echo $(MY_ID)
    # Recursively expand SET_ID again, which calls the shell command (again) and sets MY_ID (again)
        $(SET_ID)
    # This will now be a different random number
        @echo $(MY_ID)
  6. 4

    Cuidado con recetas como esta

    target:
        MY_ID=$(GENERATE_ID);
        echo $MY_ID;

    Hace dos cosas mal. La primera línea de la receta se ejecuta por separado, en un shell de instancia a partir de la segunda línea. La variable se pierde en el tiempo. Segunda cosa mal es que el $ no se escapó.

    target:
        MY_ID=$(GENERATE_ID); \
        echo $$MY_ID;

    Ambos problemas se han solucionado y la variable es utilizable. La barra diagonal inversa combina ambas líneas a ejecutar en una sola cáscara, por lo tanto el valor de la variable y la lectura de la variable epílogos, funciona.

    Me doy cuenta de que el post original dice cómo obtener los resultados de un comando de la shell en una variable, y esta respuesta se muestra cómo obtener en una variable de shell. Pero otros lectores puedan beneficiarse.

    Una mejoría final, si el consumidor espera una «variable de entorno» se establece, entonces usted tiene que exportar.

    my_shell_script
        echo $MY_ID

    tendría esto en el archivo makefile

    target:
        export MY_ID=$(GENERATE_ID); \
        ./my_shell_script;

    La esperanza de que ayude a alguien. En general, se debe evitar realizar cualquier trabajo real fuera de las recetas, porque si alguien usa el archivo makefile con ‘–dry-run’ opción de VER sólo lo que va a hacer, no tiene efectos colaterales indeseables. Cada $(shell) llamada se evalúan en tiempo de compilación y el verdadero trabajo accidentalmente podrían hacer. Mejor dejar el trabajo real, como la generación de identificadores, en el interior de las recetas cuando sea posible.

    • Su respuesta es exactamente lo que estoy buscando. Gracias, hombre

Dejar respuesta

Please enter your comment!
Please enter your name here