Jak uzyskać bieżący katalog względny pliku Makefile?
Mam kilka plików Makefile w katalogach specyficznych dla aplikacji, takich jak:
/project1/apps/app_typeA/Makefile
/project1/apps/app_typeB/Makefile
/project1/apps/app_typeC/Makefile
Każdy plik Makefile zawieraplik inc w tej ścieżce o jeden poziom wyżej:
/project1/apps/app_rules.inc
Wewnątrz app_rules.inc ustawiam miejsce docelowe, w którym chcę, aby pliki binarne były umieszczane po zbudowaniu. Chcę, aby wszystkie binaria były w odpowiedniej ścieżce app_type
:
/project1/bin/app_typeA/
Próbowałem użyć $(CURDIR)
, tak:
OUTPUT_PATH = /project1/bin/$(CURDIR)
Ale zamiast tego mam binaria Zakopane w całej nazwie ścieżki w ten sposób: (zwróć uwagę na redundancję)
/project1/bin/projects/users/bob/project1/apps/app_typeA
Co mogę zrobić, aby uzyskać "bieżący katalog" wykonania tak, że mogę wiedzieć tylko app_typeX
aby umieścić pliki binarne w folderze odpowiednich typów?
11 answers
Funkcja powłoki.
Możesz użyć shell
Funkcja: current_dir = $(shell pwd)
.
Lub shell
w połączeniu z notdir
, jeśli nie potrzebujesz ścieżki bezwzględnej:
current_dir = $(notdir $(shell pwd))
.
Update.
Podane rozwiązanie działa tylko wtedy, gdy uruchamiasz make
z bieżącego katalogu pliku Makefile.
Jak zauważył @Flimm:
Zwróci to bieżący katalog roboczy, a nie Katalog nadrzędny pliku Makefile.
na przykład, jeśli uruchomiszcd /; make -f /home/username/project/Makefile
,current_dir
zmienną będzie/
, a nie/home/username/project/
.
Poniższy kod będzie działał dla dowolnych plików for Makefile wywoływanych z dowolnego katalogu:
mkfile_path := $(abspath $(lastword $(MAKEFILE_LIST)))
current_dir := $(notdir $(patsubst %/,%,$(dir $(mkfile_path))))
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-08-11 18:24:25
Jak z TUTAJ ;
ROOT_DIR:=$(shell dirname $(realpath $(lastword $(MAKEFILE_LIST))))
Pojawia się jako;
$ cd /home/user/
$ make -f test/Makefile
/home/user/test
$ cd test; make Makefile
/home/user/test
Hope this helps
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:18:22
Jeśli używasz GNU make, $(CURDIR) jest w rzeczywistości zmienną wbudowaną. Jest to miejsce, w którym znajduje się plik Makefile bieżący katalog roboczy, który prawdopodobnie znajduje się tam, gdzie znajduje się plik Makefile, ale nie zawsze .
OUTPUT_PATH = /project1/bin/$(notdir $(CURDIR))
Patrz Dodatek A Krótki odnośnik w http://www.gnu.org/software/make/manual/make.html
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-03-06 01:07:13
THIS_DIR := $(dir $(abspath $(lastword $(MAKEFILE_LIST))))
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-03-16 07:45:12
Próbowałem wielu z tych odpowiedzi, ale w moim systemie AIX z gnu make 3.80 musiałem zrobić kilka rzeczy po staremu.
Okazuje się, że lastword
, abspath
i realpath
zostały dodane dopiero w 3.81. :(
mkfile_path := $(word $(words $(MAKEFILE_LIST)),$(MAKEFILE_LIST))
mkfile_dir:=$(shell cd $(shell dirname $(mkfile_path)); pwd)
current_dir:=$(notdir $(mkfile_dir))
Jak mówili inni, nie najbardziej elegancki, ponieważ przywołuje powłokę dwa razy, i nadal ma problemy ze spacjami.
Ale ponieważ nie mam żadnych spacji na ścieżkach, działa to dla mnie niezależnie od tego, jak zacząłem make
:
- make-f ../ wherever / makefile
- make-C ../ wherever
- make-C ~ / wherever
- Cd../ wherever; make
Wszystkie daj mi wherever
dla current_dir
i absolutną ścieżkę do wherever
dla mkfile_dir
.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-01-06 23:01:54
Zestawiając przykłady podane tutaj, daje to pełną ścieżkę do pliku makefile:
# Get the location of this makefile.
ROOT_DIR := $(dir $(abspath $(lastword $(MAKEFILE_LIST))))
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-02-07 21:18:53
Podoba mi się wybrana odpowiedź, ale myślę, że bardziej pomocne byłoby pokazać, że działa, niż wyjaśnić.
/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
Wyjście:
+ 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
Uwaga: Funkcja $(patsubst %/,%,[path/goes/here/])
służy do usuwania końcowego ukośnika.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-04-09 19:27:07
Przykład w celach informacyjnych, jak poniżej:
Struktura folderów może wyglądać następująco:
Gdzie są dwa pliki Makefile, każdy jak poniżej;
sample/Makefile
test/Makefile
Teraz zobaczmy zawartość plików Makefile.
Sample / Makefile
export ROOT_DIR=${PWD}
all:
echo ${ROOT_DIR}
$(MAKE) -C test
Test/Makefile
all:
echo ${ROOT_DIR}
echo "make test ends here !"
Teraz wykonaj sample / Makefile, jako;
cd sample
make
Wyjście:
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'
Wyjaśnienie, byłoby takie, że rodzic / Dom katalog może być przechowywany w environment-flag i może być eksportowany, tak że może być używany we wszystkich podkatalogach makefiles.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-01-18 14:53:21
Tutaj jest jedna linijka, aby uzyskać absolutną ścieżkę do pliku Makefile
używając składni powłoki:
SHELL := /bin/bash
CWD := $(shell cd -P -- '$(shell dirname -- "$0")' && pwd -P)
A oto wersja bez powłoki oparta na @ 0xFF odpowiedź :
CWD=$(abspath $(patsubst %/,%,$(dir $(abspath $(lastword $(MAKEFILE_LIST))))))
Przetestuj go drukując, jak:
cwd:
@echo $(CWD)
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:10:42
Jeśli zmienna make zawiera ścieżkę względną ROOT_DIR
ROOT_DIR := ../../../
Aby uzyskać ścieżkę bezwzględną, użyj poniższej metody.
ROOT_DIR := $(abspath $(ROOT_DIR))
Działa dobrze w GNUMake...Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-02-20 05:09:50
Aktualizacja 2018/03/05 finnaly używam tego:
shellPath=`echo $PWD/``echo ${0%/*}`
# process absolute path
shellPath1=`echo $PWD/`
shellPath2=`echo ${0%/*}`
if [ ${shellPath2:0:1} == '/' ] ; then
shellPath=${shellPath2}
fi
Może być wykonany poprawnie w ścieżce względnej lub bezwzględnej. Wykonane poprawnie wywołane przez crontab. Wykonywane poprawnie w innej powłoce.
Pokaż przykład, a.sh wydrukuj ścieżkę własną.
[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 /]#
Stary: Używam tego:
MAKEFILE_PATH := $(PWD)/$({0%/*})
Może pokazać poprawność, jeśli zostanie wykonana w innej powłoce i innym katalogu.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-03-05 09:55:36