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

j'ai plusieurs Makefiles dans des répertoires spécifiques d'applications comme celui-ci:

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

chaque Makefile comprend: a.fichier inc dans ce chemin un niveau supérieur:

/project1/apps/app_rules.inc

dans app_rules.inc je mets la destination de l'endroit où je veux que les binaires soient placés une fois construits. Je veux que tous les binaires soient dans leur chemin respectif app_type :

/project1/bin/app_typeA/

j'ai essayé d'utiliser $(CURDIR) , comme ceci:

OUTPUT_PATH = /project1/bin/$(CURDIR)

mais à la place j'ai eu les binaires enterrés dans le nom de chemin entier comme ceci: (noter la redondance)

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

Que puis-je faire pour obtenir le" répertoire courant "de l'exécution de sorte que je puisse connaître juste le app_typeX afin de mettre les binaires dans leur dossier de types respectifs?

140
demandé sur kenorb 2013-08-09 02:02:21

11 réponses

la fonction shell.

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

mise à Jour.

la solution donnée ne fonctionne que lorsque vous exécutez make à partir du répertoire courant du Makefile.

Comme @Flimm a noté:

notez que ceci renvoie le répertoire de travail courant, pas le répertoire parent du Makefile.

par exemple, si vous lancez cd /; make -f /home/username/project/Makefile , la variable current_dir sera / , pas /home/username/project/ .

code ci-dessous fonctionne pour tous les Makefiles invoqués à partir de n'importe quel répertoire:

mkfile_path := $(abspath $(lastword $(MAKEFILE_LIST)))
current_dir := $(notdir $(patsubst %/,%,$(dir $(mkfile_path))))
184
répondu Nikolai Popov 2014-08-11 18:24:25

tel que repris de ici ;

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

apparaît comme;

$ cd /home/user/

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

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

Espérons que cette aide

96
répondu sleepycal 2017-05-23 12:18:22

si vous utilisez GNU make, $(CURDIR) est en fait une variable intégrée. C'est l'emplacement où le Makefile réside le répertoire de travail courant, qui est probablement où le Makefile est, mais pas toujours .

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

voir Annexe A Référence rapide dans http://www.gnu.org/software/make/manual/make.html

34
répondu Tzunghsing David Wong 2017-03-06 01:07:13
THIS_DIR := $(dir $(abspath $(lastword $(MAKEFILE_LIST))))
19
répondu momo 2015-03-16 07:45:12

j'ai essayé beaucoup de ces réponses, mais sur mon système AIX avec gnu make 3.80 j'avais besoin de faire des choses à l'ancienne.

S'avère que lastword , abspath et realpath n'ont pas été ajoutés avant le 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, pas le plus élégant car il invoque une coquille deux fois, et il a encore les problèmes d'espaces.

mais comme je n'ai pas d'espace dans mes chemins, cela fonctionne pour moi indépendamment de comment j'ai commencé make :

  • make-F../endroit/ou / makefile
  • make-C..et où
  • make-C ~/, là où
  • cd ../où; faire

Tous me donner wherever pour current_dir et le chemin d'accès absolu à wherever pour mkfile_dir .

3
répondu Jesse Chisholm 2016-01-06 23:01:54

en regroupant les exemples donnés ici, cela donne le chemin complet vers le makefile:

# Get the location of this makefile.
ROOT_DIR := $(dir $(abspath $(lastword $(MAKEFILE_LIST))))
3
répondu Jon 2017-02-07 21:18:53

j'aime la réponse choisie, mais je pense qu'il serait plus utile de montrer ce travail 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

NOTE: la fonction $(patsubst %/,%,[path/goes/here/]) est utilisée pour enlever la barre oblique.

2
répondu Bruno Bronosky 2018-04-09 19:27:07

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

la structure du dossier peut être:

enter image description here

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

sample/Makefile
test/Makefile

voyons maintenant le contenu des Makefiles.

échantillon/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 le fichier sample/ 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 parent répertoire/home peuvent être stockés dans l'environnement-drapeau, et peuvent être exportés, de sorte qu'il peut être utilisé dans tous les sous-répertoire makefiles.

0
répondu parasrish 2016-01-18 14:53:21

voici un-liner pour obtenir le chemin absolu vers votre fichier Makefile en utilisant la syntaxe shell:

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

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

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

tester en l'imprimant, comme:

cwd:
        @echo $(CWD)
0
répondu kenorb 2017-05-23 12:10:42

si la variable make contient le chemin relatif est ROOT_DIR

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

eux pour obtenir le chemin absolu il suffit d'utiliser la méthode ci-dessous.

ROOT_DIR := $(abspath $(ROOT_DIR))

son travail est excellent à GNUMake...

0
répondu Jerry 2018-02-20 05:09:50

mise à jour 2018/03/05 enfin 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 dans le chemin relatif ou le chemin absolu. Exécution correcte invoquée par crontab. Exécuté correctement dans un autre shell.

show example, 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 /]# 

Vieux: J'utilise ceci:

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

il peut indiquer correct si exécuté dans un autre shell et un autre répertoire.

-1
répondu zhukunqian 2018-03-05 09:55:36