¿Cómo podría agregar dir a $ PATH en Makefile?

87

Quiero escribir un Makefile que ejecute pruebas. Las pruebas están en un directorio './tests' y los archivos ejecutables que se van a probar están en el directorio './bin'.

Cuando ejecuto las pruebas, no ven los archivos exec, ya que el directorio ./bin no está en $ PATH.

Cuando hago algo como esto:

EXPORT PATH=bin:$PATH
make test

Todo funciona. Sin embargo, necesito cambiar $ PATH en el Makefile.

Contenido simple de Makefile:

test all:
    PATH=bin:${PATH}
    @echo $(PATH)
    x

Imprime la ruta correctamente, sin embargo, no encuentra el archivo x.

Cuando hago esto manualmente:

$ export PATH=bin:$PATH
$ x

entonces todo está bien.

¿Cómo puedo cambiar $ PATH en el Makefile?

Szymon Lipiński
fuente
¿No puedes simplemente llamar a las pruebas desde el directorio ejecutable como ../test/test_to_run? Lo siento si he entendido mal la pregunta.
Chris
Quiero que este archivo sea visible para las pruebas normalmente. No quiero jugar con los directorios, ya que la refactorización sería una pesadilla.
Szymon Lipiński
La única forma en que puede acercarse a esto es hacer que el archivo MAKE escriba un script de shell que contenga la variable decls y luego tenga la fuente de shell padre con ese script .. Sin embargo, esto probablemente no sea práctico.
Michael Smith
Creo que unix.stackexchange.com/questions/11530/… es una pregunta muy diferente (estúpida), a diferencia de la tuya.
imz - Ivan Zakharyaschev

Respuestas:

106

¿Probó la exportdirectiva de Make en sí (asumiendo que usa GNU Make)?

export PATH := bin:$(PATH)

test all:
    x

Además, hay un error en tu ejemplo:

test all:
    PATH=bin:${PATH}
    @echo $(PATH)
    x

Primero, el valor que se echoedita es una expansión de la PATHvariable realizada por Make, no el shell. Si imprime el valor esperado, entonces, supongo, ha establecido la PATHvariable en algún lugar antes en su Makefile, o en un shell que invocó Make. Para evitar tal comportamiento, debe escapar de los dólares:

test all:
    PATH=bin:$$PATH
    @echo $$PATH
    x

En segundo lugar, en cualquier caso, esto no funcionará porque Make ejecuta cada línea de la receta en un shell separado . Esto se puede cambiar escribiendo la receta en una sola línea:

test all:
    export PATH=bin:$$PATH; echo $$PATH; x
Eldar Abusalimov
fuente
7
$(PATH)se establecerá en el valor del PATHshell que invoca a make. Según el manual , "Cada variable de entorno que make ve cuando se inicia se transforma en una variable de make con el mismo nombre y valor".
Emil Sit
La directiva de exportación funcionó para mí (¡gracias!), Pero solo después de instalar GNU Make 4.3. En la versión 3.81 (el valor por defecto en MacOS Catalina), la versión actualizada PATHse refleja correctamente en variables ( echo $(PATH)) y dentro de entornos de comandos ( env, which python, bash -c python), pero no parece que se utilizará cuando se localiza el ejecutable para el comando: el comando pythontodavía corre el Python ejecutable en el original PATH.
doctaphred
27

Por diseño, el makeanalizador ejecuta líneas en invocaciones de shell separadas, es por eso que al cambiar la variable (por ejemplo PATH) en una línea, es posible que el cambio no se aplique a las siguientes líneas (consulte esta publicación ).

Una forma de solucionar este problema es convertir varios comandos en una sola línea (separados por ;), o utilizar un objetivo especial One Shell ( .ONESHELL, a partir de GNU Make 3.82).

Alternativamente, puede proporcionar una PATHvariable en el momento en que se invoca el shell. Por ejemplo:

PATH  := $(PATH):$(PWD)/bin:/my/other/path
SHELL := env PATH=$(PATH) /bin/bash
Kenorb
fuente
2
¡Me gusta el enfoque!
Alan Franzoni
2
¡Esto es lo mejor, porque funciona incluso con $(shell)invocaciones! : D Ejemplo: pastebin.com/Pii8pmkD
PsychoX
En dev.azure obtengo: env: 'env': No existe tal archivo o directorio; Trabaja localmente; /
Kamil Dziedzic
No funciona en Debian 10 con make 4.2: make: env PATH = <path> / bin / sh: Command not found. Usar trabajos de exportación. Asegúrese de usar $ (HOME) y no ~ para una ruta en el directorio de inicio.
MKesper
25

Los cambios de ruta parecen ser persistentes si primero configuras la variable SHELL en tu archivo MAKE:

SHELL := /bin/bash
PATH := bin:$(PATH)

test all:
    x

No sé si este es el comportamiento deseado o no.

subespecificado
fuente
Esto solucionó el problema que estaba teniendo (estoy ejecutando zsh). ¡Gracias!
Jezen Thomas
Sí, esto de hecho hace lo que quería el OP ... pero ¿es una característica o un error? Incluso después de leer la sección SHELL del manual de make, no estoy seguro.
pje
5
Esto tampoco funciona para mí. whichy envahora elige el nuevo PATH, pero la ejecución directa de un binario todavía no se encuentra en el PATH modificado, solo en el original.
Konrad Rudolph
3

Lo que suelo hacer es proporcionar la ruta al ejecutable explícitamente:

EXE=./bin/
...
test all:
    $(EXE)x

También utilizo esta técnica para ejecutar binarios no nativos en un emulador como QEMU si estoy compilando de forma cruzada:

EXE = qemu-mips ./bin/

Si make está usando el shell sh, esto debería funcionar:

test all:
    PATH=bin:$PATH x
Richard Pennington
fuente
Sí, genial, sin embargo, tengo mis pruebas escritas en perl y necesito llamar al exe desde el script de perl, no directamente desde el archivo make. Tengo que repensar todas las pruebas de estas cosas :)
Szymon Lipiński
Te tengo. ¿Qué tal configurar PATH en la línea de comandos? Vea la edición de arriba.
Richard Pennington
-2

Para establecer la PATHvariable, solo dentro del Makefile, use algo como:

PATH := $(PATH):/my/dir

test:
@echo my new PATH = $(PATH)
karnhick
fuente
No funciona como yo quiero. Actualicé la pregunta con ejemplos de lo que quiero lograr.
Szymon Lipiński