it-swarm.dev

¿Cómo escribo el comando 'cd' en un makefile?

Por ejemplo, tengo algo como esto en mi makefile:

all:
     cd some_directory

Pero cuando escribí make solo vi 'cd some_directory', como en el comando echo.

289
Davit Siradeghyan

En realidad, está ejecutando el comando, cambiando el directorio a some_directory, sin embargo, esto se realiza en un subproceso Shell y no afecta ni a la marca ni al Shell desde el que se está trabajando.

Si desea realizar más tareas dentro de some_directory, debe agregar un punto y coma y agregar los otros comandos también. Tenga en cuenta que no puede usar las nuevas líneas tal como se interpretan por make como el final de la regla, por lo que cualquier nueva línea que use para la claridad debe escaparse con una barra invertida.

Por ejemplo:

all:
        cd some_dir; echo "I'm in some_dir"; \
          gcc -Wall -o myTest myTest.c

Tenga en cuenta también que el punto y coma es necesario entre todos los comandos, aunque agregue una barra invertida y una nueva línea. Esto se debe al hecho de que el Shell analiza toda la cadena como una sola línea. Como se señaló en los comentarios, debe usar '&&' para unir comandos, lo que significa que solo se ejecutan si el comando anterior fue exitoso.

all:
        cd some_dir && echo "I'm in some_dir" && \
          gcc -Wall -o myTest myTest.c

Esto es especialmente importante cuando se realiza un trabajo destructivo, como la limpieza, ya que de lo contrario destruirá las cosas equivocadas, si la cd falla por cualquier motivo.

Sin embargo, un uso común es llamar a make en el subdirectorio, que es posible que desee examinar. Hay una opción de línea de comando para esto, así que no tienes que llamar cd, así que tu regla se vería así.

all:
        $(MAKE) -C some_dir all

que cambiará a some_dir y ejecutará Makefile allí con el objetivo "todos". Como práctica recomendada, use $(MAKE) en lugar de llamar a make directamente, ya que se encargará de llamar a la instancia de make correcta (si, por ejemplo, usa una versión de make especial para su entorno de compilación), y proporcione un comportamiento ligeramente diferente cuando se ejecuta utilizando ciertos modificadores, como -t.

Para el registro, haga siempre echos el comando que ejecuta (a menos que se suprima explícitamente), incluso si no tiene salida, que es lo que está viendo.

517
falstro

A partir de GNU make 3.82 , puede usar .ONESHELL target especial para ejecutar todas las líneas de receta en una única instanciación del Shell (énfasis en negrita):

  • Nuevo objetivo especial: .ONESHELL indica a make que invoque una instancia única del Shell y le proporcione la receta completa , independientemente de la cantidad de líneas que contenga. [...]
.ONESHELL:
all:
    cd ~/some_dir
    pwd # Prints ~/some_dir if cd succeeded
68
Chnossos

Aquí hay un lindo truco para lidiar con directorios y hacer. En lugar de utilizar cadenas multilínea, o "cd;" en cada comando, define una función chdir simple como tal:

CHDIR_Shell := $(Shell)
define chdir
   $(eval _D=$(firstword $(1) $(@D)))
   $(info $(MAKE): cd $(_D)) $(eval Shell = cd $(_D); $(CHDIR_Shell))
endef

Entonces todo lo que tienes que hacer es llamarlo en tu regla como tal:

all:
          $(call chdir,some_dir)
          echo "I'm now always in some_dir"
          gcc -Wall -o myTest myTest.c

Incluso puedes hacer lo siguiente:

some_dir/myTest:
          $(call chdir)
          echo "I'm now always in some_dir"
          gcc -Wall -o myTest myTest.c
20
JoeS

¿Qué quieres que haga una vez que llegue allí? Cada comando se ejecuta en una subshell, por lo que la subshell cambia de directorio, pero el resultado final es que el siguiente comando aún se encuentra en el directorio actual.

Con GNU make, puedes hacer algo como:

BIN=/bin
foo:
    $(Shell cd $(BIN); ls)
7
Nadir SOUALEM

Para cambiar dir

foo: 
    $(MAKE) -C mydir

multi:
    $(MAKE) -C / -C my-custom-dir   ## Equivalent to /my-custom-dir
0
jackotonye