Ajouter un répertoire à PATH via Makefile

9

J'ai du mal à exporter le CHEMIN que j'ai modifié à l'intérieur du Makefile dans le terminal actuel. J'essaie d'ajouter au PATH, le dossier bin à l'intérieur du répertoire Makefile.

Voici la bande pertinente du makefile:

PATH := $(shell pwd)/bin:$(PATH)

install:
    mkdir -p ./bin 
    export PATH
    echo $(PATH)

L'écho l'imprime correctement mais si je refais l'écho dans le terminal, le CHEMIN reste le même.

tshepang
la source

Réponses:

16

Vous ne pouvez tout simplement pas faire cela. Il n'y a aucun moyen¹ le processus de création peut changer l'environnement de son parent (ou son répertoire actuel, auquel vous pourriez penser ensuite).

En fait, encore moins se passe que vous ne le pensez.

  • Toutes les makeimplémentations ne reflètent pas l'affectation à la PATHvariable make dans l'environnement; GNU make (présent sur Linux et d'autres systèmes) le fait, mais BSD make ne le fait pas.
  • Chaque ligne de commande sous une cible s'exécute dans un sous-shell distinct. (Sauf dans certains BSD plus anciens, les implémentations sont faites.)export PATH ligne s'exécute donc sur un shell qui se termine immédiatement après. Non pas que cette ligne ferait quoi que ce soit en premier lieu - si elle PATHest définie à ce stade, c'est parce qu'elle est déjà dans l'environnement du shell.

Make est pour construire des choses automatiquement. Si vous souhaitez définir des variables pour votre environnement interactif, ce n'est pas l'outil que vous devriez regarder. Au lieu de cela, écrivez un extrait de shell et sourcez- le dans le shell actuel:

. ./define-my-variables.sh

Dans votre makefile, sourcez le script dans chaque sous-shell . Vous pouvez utiliser une barre oblique inverse pour exécuter une commande longue; rappelez-vous que

  • La séquence backslash-newline est supprimée par make, donc le shell ne verra pas de nouvelle ligne là-bas.
  • N'oubliez pas de préfixer chaque ligne par un onglet.
  • Le comportement d'erreur de Make consiste à abandonner si une commande échoue. Le shell ne fera pas cela par défaut, et l'échec de toute commande, mais la dernière passera inaperçue par défaut, vous devez donc exécuter set -e.
install:
    set -e; \
    . ./define-my-variables.sh; \
    mkdir -p bin; \
    …

¹ Remarque obligatoire: aucun sens. Même invoquer à distance chdirvia ptraceun débogueur ne fonctionnera pas comme avec la plupart des shells car ils n'aiment pas que leur répertoire actuel soit changé sous leurs pieds.

Gilles 'SO- arrête d'être méchant'
la source
Euh, je pense que "vous ne pouvez tout simplement pas faire cela" est incorrect. Voir la réponse @Yeo: unix.stackexchange.com/a/291973/176350
XML
La réponse de @XML Yeo fait quelque chose de différent qui n'est pas ce que la question demande.
Gilles 'SO- arrête d'être méchant'
7

Tu ne peux pas. Il n'est pas possible pour un sous-processus (comme make) de modifier l'environnement de son processus parent.

Vous pourriez faire quelque chose comme

$ eval `make pathupdate`

Où la pathupdatecible ressemble:

pathupdate:
    @echo PATH=\"$(PATH)\"
cjm
la source
6

Votre réponse se trouve ici: https://stackoverflow.com/a/8942216/367461

Fondamentalement, vous devez faire ceci:

export PATH := $(shell pwd)/bin:$(PATH)

test:
    mkdir -p ./bin
    @echo $(PATH)

J'ai testé cela sur Fedora 23 avec GNU Make 4.0, et cela fonctionne bien pour moi.

Dan Jones
la source
1
C'est la bonne réponse pour GNU Make. Pour BSD Make, vous pouvez utiliser .SHELL: name=sh path=/path/to/wrapper-scriptpuis créer un script wrapper commeexport FOO=bar; exec bash "$@"
rjh
2

Je suis sur le point de poser cette même question parce que je n'ai pas pu faire fonctionner l'autre exemple de réponse.

Cependant, j'ai réussi à obtenir la solution de travail pour moi en utilisant la evalcommande. Je ne sais pas trop pourquoi cela n'a pas été publié plus tôt.

do_something: 
    $(eval export PATH=$(shell pwd)/bin:$(PATH))
    @echo $(PATH)

Remarque: les PATHmodifications sont temporaires dans la marque elle-même. Après la sortie de la marque, le CHEMIN est réinitialisé à la valeur précédente.

Yeo
la source
Cela n'a pas été posté plus tôt car ce n'est pas ce que la question pose: la question demande comment obtenir le PATH modifié après la sortie de make. En outre, cela pourrait être fait de manière beaucoup plus simple: mettez-vous export PATH=…en do_something:ligne, vous n'avez pas besoin eval.
Gilles 'SO- arrête d'être méchant'
1

Vous pouvez faire en sorte que Make s'appelle récursivement avec un environnement modifié, en tant que tel:

dummy: build_all

all: 
    PATH=/new/directory:$(PATH) $(MAKE) build_all

build_all:
    your make rules 

Si vous souhaitez utiliser un extrait de shell:

dummy: build_all

all:
    . ./define-my-variables.sh ; $(MAKE) build_all

build_all:
   your make rules
Sam B.
la source