Comment obtenir le répertoire relatif actuel de votre Makefile?

J’ai plusieurs Makefiles dans des répertoires spécifiques à l’application, comme ceci:

/project1/apps/app_typeA/Makefile /project1/apps/app_typeB/Makefile /project1/apps/app_typeC/Makefile 

Chaque Makefile inclut un fichier .inc dans ce chemin d’un niveau supérieur:

 /project1/apps/app_rules.inc 

Inside app_rules.inc Je suis en train de définir la destination de l’endroit où je veux placer les binarys lors de leur construction. Je veux que tous les fichiers binarys se app_type dans leur chemin d’access app_type :

 /project1/bin/app_typeA/ 

J’ai essayé d’utiliser $(CURDIR) , comme ceci:

 OUTPUT_PATH = /project1/bin/$(CURDIR) 

mais à la place, les binarys sont enterrés dans le nom de chemin complet comme ceci: (remarquez la redondance)

 /project1/bin/projects/users/bob/project1/apps/app_typeA 

Que puis-je faire pour obtenir le “répertoire courant” d’exécution afin de pouvoir connaître uniquement le type app_typeX afin de placer les binarys dans leur dossier de types respectif?

La fonction shell

Vous pouvez utiliser la fonction shell : current_dir = $(shell pwd) . Ou shell en combinaison avec notdir , si vous n’avez pas besoin de chemin absolu: current_dir = $(notdir $(shell pwd)) .

Mettre à jour.

La solution donnée ne fonctionne que lorsque vous exécutez make depuis le répertoire actuel du Makefile.
Comme l’a noté @Flimm:

Notez que cela retourne le répertoire de travail en cours, pas le répertoire parent du Makefile.
Par exemple, si vous exécutez cd /; make -f /home/username/project/Makefile cd /; make -f /home/username/project/Makefile , la variable current_dir sera / , pas /home/username/project/ .

Le code ci-dessous fonctionnera pour tous les Makefiles appelés depuis n’importe quel répertoire:

 mkfile_path := $(abspath $(lastword $(MAKEFILE_LIST))) current_dir := $(notdir $(patsubst %/,%,$(dir $(mkfile_path)))) 

Comme pris d’ ici ;

 ROOT_DIR:=$(shell dirname $(realpath $(lastword $(MAKEFILE_LIST)))) 

Se présente comme;

 $ cd /home/user/ $ make -f test/Makefile /home/user/test $ cd test; make Makefile /home/user/test 

J’espère que cela t’aides

Si vous utilisez GNU make, $ (CURDIR) est en fait une variable intégrée. C’est l’ emplacement où le Makefile réside dans le répertoire de travail actuel, qui est probablement l’endroit où se trouve le Makefile, mais pas toujours .

 OUTPUT_PATH = /project1/bin/$(notdir $(CURDIR)) 

Voir Annexe A: http://www.gnu.org/software/make/manual/make.html

 THIS_DIR := $(dir $(abspath $(lastword $(MAKEFILE_LIST)))) 

J’ai essayé beaucoup de ces réponses, mais sur mon système AIX avec gnu, je devais faire 3.80 pour faire certaines choses de la vieille école.

Il s’avère que le dernier lastword abspath et realpath été ajouté qu’à 3.81. 🙁

 mkfile_path := $(word $(words $(MAKEFILE_LIST)),$(MAKEFILE_LIST)) mkfile_dir:=$(shell cd $(shell dirname $(mkfile_path)); pwd) current_dir:=$(notdir $(mkfile_dir)) 

Comme d’autres l’ont dit, ce n’est pas le plus élégant car il invoque un shell à deux resockets, et il comporte toujours des problèmes d’espace.

Mais comme je n’ai aucun espace sur mes chemins, cela fonctionne pour moi, peu importe comment j’ai commencé:

  • make -f ../wherever/makefile
  • faire du C .. / partout
  • make -C ~ / partout
  • cd ../ partout; faire

Tout me donne wherever ce wherever pour current_dir et le chemin absolu vers mkfile_dir .

En rassemblant les exemples donnés ici, cela donne le chemin complet du fichier makefile:

 # Get the location of this makefile. ROOT_DIR := $(dir $(abspath $(lastword $(MAKEFILE_LIST)))) 

J’aime la réponse choisie, mais je pense qu’il serait plus utile de la montrer que de l’expliquer.

/tmp/makefile_path_test.sh

 #!/bin/bash -eu # Create a testing dir temp_dir=/tmp/makefile_path_test proj_dir=$temp_dir/dir1/dir2/dir3 mkdir -p $proj_dir # Create the Makefile in $proj_dir # (Because of this, $proj_dir is what $(path) should evaluate to.) cat > $proj_dir/Makefile < <'EOF' path := $(patsubst %/,%,$(dir $(abspath $(lastword $(MAKEFILE_LIST))))) cwd := $(shell pwd) all: @echo "MAKEFILE_LIST: $(MAKEFILE_LIST)" @echo " path: $(path)" @echo " cwd: $(cwd)" @echo "" EOF # See/debug each command set -x # Test using the Makefile in the current directory cd $proj_dir make # Test passing a Makefile cd $temp_dir make -f $proj_dir/Makefile # Cleanup rm -rf $temp_dir 

Sortie:

 + cd /tmp/makefile_path_test/dir1/dir2/dir3 + make MAKEFILE_LIST: Makefile path: /private/tmp/makefile_path_test/dir1/dir2/dir3 cwd: /tmp/makefile_path_test/dir1/dir2/dir3 + cd /tmp/makefile_path_test + make -f /tmp/makefile_path_test/dir1/dir2/dir3/Makefile MAKEFILE_LIST: /tmp/makefile_path_test/dir1/dir2/dir3/Makefile path: /tmp/makefile_path_test/dir1/dir2/dir3 cwd: /tmp/makefile_path_test + rm -rf /tmp/makefile_path_test 

REMARQUE: La fonction $(patsubst %/,%,[path/goes/here/]) est utilisée pour supprimer la barre oblique finale.

Exemple pour votre référence, comme ci-dessous:

La structure du dossier peut être comme suit:

entrer la description de l'image ici

Où il y a deux Makefiles, chacun comme ci-dessous;

 sample/Makefile test/Makefile 

Voyons maintenant le contenu des Makefiles.

sample / Makefile

 export ROOT_DIR=${PWD} all: echo ${ROOT_DIR} $(MAKE) -C test 

test / Makefile

 all: echo ${ROOT_DIR} echo "make test ends here !" 

Maintenant, exécutez l’exemple / Makefile, comme;

 cd sample make 

SORTIE:

 echo /home/symphony/sample /home/symphony/sample make -C test make[1]: Entering directory `/home/symphony/sample/test' echo /home/symphony/sample /home/symphony/sample echo "make test ends here !" make test ends here ! make[1]: Leaving directory `/home/symphony/sample/test' 

Explication, serait que le répertoire parent / home peut être stocké dans l’indicateur d’environnement, et peut être exporté, de sorte qu’il puisse être utilisé dans tous les fichiers makefile du sous-répertoire.

Voici une ligne pour obtenir un chemin absolu vers votre fichier Makefile en utilisant la syntaxe shell:

 SHELL := /bin/bash CWD := $(shell cd -P -- '$(shell dirname -- "$0")' && pwd -P) 

Et voici la version sans shell basée sur @ 0xff réponse :

 CWD=$(abspath $(patsubst %/,%,$(dir $(abspath $(lastword $(MAKEFILE_LIST)))))) 

Testez-le en l’imprimant, comme:

 cwd: @echo $(CWD) 

Si la variable make contient le chemin relatif est ROOT_DIR

 ROOT_DIR := ../../../ 

Eux pour obtenir le chemin absolu, utilisez simplement la méthode ci-dessous.

 ROOT_DIR := $(abspath $(ROOT_DIR)) 

Son travail bien dans GNUMake …

mise à jour 2018/03/05 finnaly J’utilise ceci:


 shellPath=`echo $PWD/``echo ${0%/*}` # process absolute path shellPath1=`echo $PWD/` shellPath2=`echo ${0%/*}` if [ ${shellPath2:0:1} == '/' ] ; then shellPath=${shellPath2} fi 

Il peut être exécuté correctement en chemin relatif ou en chemin absolu. Exécuté correct invoqué par crontab. Exécuté correct dans un autre shell.

exemple, a.sh print self path.

 [root@izbp1a7wyzv7b5hitowq2yz /]# more /root/test/a.sh shellPath=`echo $PWD/``echo ${0%/*}` # process absolute path shellPath1=`echo $PWD/` shellPath2=`echo ${0%/*}` if [ ${shellPath2:0:1} == '/' ] ; then shellPath=${shellPath2} fi echo $shellPath [root@izbp1a7wyzv7b5hitowq2yz /]# more /root/b.sh shellPath=`echo $PWD/``echo ${0%/*}` # process absolute path shellPath1=`echo $PWD/` shellPath2=`echo ${0%/*}` if [ ${shellPath2:0:1} == '/' ] ; then shellPath=${shellPath2} fi $shellPath/test/a.sh [root@izbp1a7wyzv7b5hitowq2yz /]# ~/b.sh /root/test [root@izbp1a7wyzv7b5hitowq2yz /]# /root/b.sh /root/test [root@izbp1a7wyzv7b5hitowq2yz /]# cd ~ [root@izbp1a7wyzv7b5hitowq2yz ~]# ./b.sh /root/./test [root@izbp1a7wyzv7b5hitowq2yz ~]# test/a.sh /root/test [root@izbp1a7wyzv7b5hitowq2yz ~]# cd test [root@izbp1a7wyzv7b5hitowq2yz test]# ./a.sh /root/test/. [root@izbp1a7wyzv7b5hitowq2yz test]# cd / [root@izbp1a7wyzv7b5hitowq2yz /]# /root/test/a.sh /root/test [root@izbp1a7wyzv7b5hitowq2yz /]# 

old: J’utilise ceci:

 MAKEFILE_PATH := $(PWD)/$({0%/*}) 

Il peut être correct s’il est exécuté dans un autre shell ou dans un autre répertoire.