Как получить текущий каталог в вашем Makefile?
у меня есть несколько Makefiles в конкретных каталогах приложений, таких как это:
/project1/apps/app_typeA/Makefile
/project1/apps/app_typeB/Makefile
/project1/apps/app_typeC/Makefile
каждый Makefile включает a .inc файл в этом пути на один уровень выше:
/project1/apps/app_rules.inc
внутри app_rules.inc я устанавливаю место назначения, где я хочу, чтобы двоичные файлы были размещены при сборке. Я хочу, чтобы все двоичные файлы были в их соответствующих app_type путь:
/project1/bin/app_typeA/
я пробовал использовать $(CURDIR), например:
OUTPUT_PATH = /project1/bin/$(CURDIR)
но вместо этого я получил двоичные файлы похоронен во всем имени пути, как это:(обратите внимание на избыточность)
/project1/bin/projects/users/bob/project1/apps/app_typeA
что я могу сделать, чтобы получить "текущий каталог" выполнения, так что я могу знать только app_typeX для того, чтобы поместить двоичные файлы в соответствующие папки типов?
11 ответов:
функция оболочки.
можно использовать
shellфункция:current_dir = $(shell pwd). Илиshellв сочетании сnotdir, если вам не нужен абсолютный путь:current_dir = $(notdir $(shell pwd)).обновление.
данное решение работает только тогда, когда вы используете
makeиз текущего каталога Makefile.
Как отметил @Flimm:обратите внимание, что это возвращает текущий рабочий каталог, а не родительский каталог файл Makefile.
например, если вы запуститеcd /; make -f /home/username/project/Makefileнаcurrent_dirпеременная/, а не/home/username/project/.код ниже будет работать для любого для Makefiles вызывается из любого каталога:
mkfile_path := $(abspath $(lastword $(MAKEFILE_LIST))) current_dir := $(notdir $(patsubst %/,%,$(dir $(mkfile_path))))
до здесь;
ROOT_DIR:=$(shell dirname $(realpath $(lastword $(MAKEFILE_LIST))))показывает, как;
$ cd /home/user/ $ make -f test/Makefile /home/user/test $ cd test; make Makefile /home/user/testнадеюсь, что это помогает
Если вы используете GNU make, $(CURDIR) на самом деле является встроенной переменной. Это и есть
место, где находится Makefileтекущий рабочий каталог, в котором, вероятно, находится Makefile, но не всегда.OUTPUT_PATH = /project1/bin/$(notdir $(CURDIR))см. приложение краткий справочник в http://www.gnu.org/software/make/manual/make.html
Я пробовал многие из этих ответов, но на моей системе AIX с gnu make 3.80 мне нужно было сделать некоторые вещи старой школы.
получается, что
lastword,abspathиrealpathне были добавлены до 3.81. : (mkfile_path := $(word $(words $(MAKEFILE_LIST)),$(MAKEFILE_LIST)) mkfile_dir:=$(shell cd $(shell dirname $(mkfile_path)); pwd) current_dir:=$(notdir $(mkfile_dir))как говорили другие, не самый элегантный, поскольку он дважды вызывает оболочку, и у него все еще есть проблемы с пространствами.
но поскольку у меня нет пробелов в моих путях, это работает для меня независимо от того, как я начал
make:
- make-f ../wherever / makefile
- make-C ../ где бы то ни было
- make-C ~ / wherever
- cd ../ где бы то ни было; сделать
все Дайте мне
whereverнаcurrent_dirи абсолютный путь кwhereverнаmkfile_dir.
собирая примеры, приведенные здесь, это дает полный путь к файлу makefile:
# Get the location of this makefile. ROOT_DIR := $(dir $(abspath $(lastword $(MAKEFILE_LIST))))
мне нравится выбранный ответ, но я думаю, что было бы более полезно на самом деле показать его работу, чем объяснить его.
/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выход:
+ 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Примечание: функции
$(patsubst %/,%,[path/goes/here/])используется для удаления задней косой черты.
пример для вашей справки, как показано ниже:
структура папок может быть так:
где есть два Makefiles, каждый, как показано ниже;
sample/Makefile test/Makefileтеперь давайте посмотрим содержимое Makefiles.
sample / Makefile
export ROOT_DIR=${PWD} all: echo ${ROOT_DIR} $(MAKE) -C testtest / Makefile
all: echo ${ROOT_DIR} echo "make test ends here !"теперь выполните sample / Makefile, as;
cd sample makeвыход:
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'объяснение заключается в том, что родительский/домашний каталог может храниться в флаге среды и может быть экспортирован, чтобы его можно было использовать во всех подкаталогах makefiles.
вот один-лайнер, чтобы получить абсолютный путь к вашей
Makefileфайл с использованием синтаксиса оболочки:SHELL := /bin/bash CWD := $(shell cd -P -- '$(shell dirname -- "")' && pwd -P)а вот версия без оболочки на основе @0xff ответ:
CWD=$(abspath $(patsubst %/,%,$(dir $(abspath $(lastword $(MAKEFILE_LIST))))))проверьте его, напечатав его, например:
cwd: @echo $(CWD)
если переменная make содержит относительный путь ROOT_DIR
ROOT_DIR := ../../../них, чтобы получить абсолютный путь просто использовать ниже метод.
ROOT_DIR := $(abspath $(ROOT_DIR))его работа отлично в GNUMake...
обновление 2018/03/05 finnaly я использую это:
shellPath=`echo $PWD/``echo ${0%/*}` # process absolute path shellPath1=`echo $PWD/` shellPath2=`echo ${0%/*}` if [ ${shellPath2:0:1} == '/' ] ; then shellPath=${shellPath2} fi
Он может быть выполнен правильно в относительном пути или абсолютном пути. Выполняется правильно, вызывается crontab. Выполняется корректно в другой оболочке.
показать пример, a.sh путь печати собственной личности.
[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 /]#
старый: Я использую это:
MAKEFILE_PATH := $(PWD)/$({0%/*})Он может показать правильно, если выполняется в другой оболочке и другой каталог.

Comments