web-dev-qa-db-fra.com

Comment écrire la commande 'cd' dans un fichier makefile?

Par exemple, j'ai quelque chose comme ça dans mon makefile:

all:
     cd some_directory

Mais lorsque j'ai tapé make, je n'ai vu que 'cd some_directory', comme dans la commande echo.

306
Davit Siradeghyan

En réalité, il exécute la commande en modifiant le répertoire en some_directory, mais cette opération est effectuée dans un shell de sous-processus et ne concerne ni la marque ni le shell à partir duquel vous travaillez.

Si vous souhaitez effectuer plus de tâches dans some_directory, vous devez ajouter un point-virgule et ajouter les autres commandes. Notez que vous ne pouvez pas utiliser les nouvelles lignes car elles sont interprétées par make comme la fin de la règle. Par conséquent, toute nouvelle ligne utilisée pour plus de clarté doit être précédée d'une barre oblique inversée.

Par exemple:

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

Notez également que le point-virgule est nécessaire entre chaque commande, même si vous ajoutez une barre oblique inverse et une nouvelle ligne. Cela est dû au fait que toute la chaîne est analysée comme une seule ligne par le shell. Comme indiqué dans les commentaires, vous devez utiliser '&&' pour associer des commandes, ce qui signifie qu'elles ne sont exécutées que si la commande précédente a abouti.

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

Ceci est particulièrement important lorsque vous effectuez un travail destructeur, tel que le nettoyage, sinon vous détruirez le mauvais matériel si le cd échouait pour une raison quelconque.

Une utilisation courante est d'appeler make dans le sous-répertoire, ce que vous voudrez peut-être examiner. Il y a une option de ligne de commande pour cela, donc vous n'avez pas à appeler vous-même cd, votre règle ressemblerait à ceci

all:
        $(MAKE) -C some_dir all

qui va changer en some_dir et exécuter la Makefile avec la cible "tout". Il est recommandé d’utiliser $(MAKE) au lieu d’appeler directement make, car il s’appuiera sur l’appel de la bonne instance make (si vous utilisez par exemple une version spéciale pour votre environnement de construction). , ainsi qu'un comportement légèrement différent lors de l'utilisation de certains commutateurs, tels que -t.

Pour mémoire, make toujours renvoie la commande à exécuter (sauf si explicitement supprimée), même si elle n’a aucune sortie, ce que vous voyez.

541
falstro

À partir de GNU make 3.82 , vous pouvez utiliser le .ONESHELL cible spéciale pour exécuter toutes les lignes de recettes dans une seule instanciation de Shell (gras, en gras). :

  • Nouvelle cible spéciale: _.ONESHELL_ indique make d’appeler une seule instance du shell et de lui fournir la recette complète , quel que soit le nombre de lignes qu'il contient. [...]
_.ONESHELL:
all:
    cd ~/some_dir
    pwd # Prints ~/some_dir if cd succeeded
_
75
Chnossos

Voici une astuce mignonne pour gérer les répertoires et les créer. Au lieu d'utiliser des chaînes multilignes, ou "cd;" sur chaque commande, définissez une fonction chdir simple comme suit:

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

Alors tout ce que vous avez à faire est d’appeler cela dans votre règle de la manière suivante:

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

Vous pouvez même faire ce qui suit:

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

Que voulez-vous que cela fasse une fois qu'il y est arrivé? Chaque commande étant exécutée dans un sous-shell, le sous-shell change de répertoire, mais le résultat final est que la commande suivante est toujours dans le répertoire en cours.

Avec GNU make, vous pouvez faire quelque chose comme:

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

Pour changer de direction

foo: 
    $(MAKE) -C mydir

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