Как получить текущий относительный каталог вашего Makefile?
У меня есть несколько Makefile в конкретных каталогах приложения, например:
/project1/apps/app_typeA/Makefile
/project1/apps/app_typeB/Makefile
/project1/apps/app_typeC/Makefile
Каждый файл Makefile содержит файл .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
, чтобы поместить двоичные файлы в их папку типов типов?
Ответы
Ответ 1
Функция оболочки.
Вы можете использовать функцию shell
: current_dir = $(shell pwd)
. Или shell
в сочетании с notdir
, если вам не нужен абсолютный путь: current_dir = $(notdir $(shell pwd))
.
Обновить.
Данное решение работает только при запуске make
из текущего каталога Makefile.
Как заметил @Flimm:
Обратите внимание, что это возвращает текущий рабочий каталог, а не родительский каталог Makefile.
Например, если вы запускаете cd/; make -f/home/username/project/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))))
Ответ 2
Как взято из здесь;
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
Надеюсь, что это поможет
Ответ 3
Если вы используете GNU make, $ (CURDIR) на самом деле является встроенной переменной. Это место, где Makefile находится в текущем рабочем каталоге, где, вероятно, находится Makefile, но не всегда.
OUTPUT_PATH = /project1/bin/$(notdir $(CURDIR))
См. Приложение A Краткий справочник в http://www.gnu.org/software/make/manual/make.html.
Ответ 4
THIS_DIR := $(dir $(abspath $(lastword $(MAKEFILE_LIST))))
Ответ 5
Я пробовал многие из этих ответов, но в моей системе 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../wherever
- make -C ~/wherever
- cd../wherever; сделать
Все дают мне wherever
для current_dir
и абсолютный путь к wherever
для mkfile_dir
.
Ответ 6
Мне нравится выбранный ответ, но я думаю, что было бы более полезно продемонстрировать его работу, чем объяснить его.
/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/])
используется для удаления конечной косой черты.
Ответ 7
Объединяя приведенные здесь примеры, это дает полный путь к make файлу:
# Get the location of this makefile.
ROOT_DIR := $(dir $(abspath $(lastword $(MAKEFILE_LIST))))
Ответ 8
Пример для вашей ссылки, как показано ниже:
Структура папок может быть такой:
![введите описание изображения здесь]()
Где есть два Makefiles, каждый из которых ниже:
sample/Makefile
test/Makefile
Теперь давайте посмотрим содержимое Make файлов.
Пример/Makefile
export ROOT_DIR=${PWD}
all:
echo ${ROOT_DIR}
$(MAKE) -C test
Тест/Makefile
all:
echo ${ROOT_DIR}
echo "make test ends here !"
Теперь выполните образец /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'
Объяснение: родительский/домашний каталог может быть сохранен в флагом среды и может быть экспортирован, чтобы его можно было использовать во всех make файлах подкаталогов.
Ответ 9
Вот одна строка для получения абсолютного пути к вашему файлу Makefile
с использованием синтаксиса оболочки:
SHELL := /bin/bash
CWD := $(shell cd -P -- '$(shell dirname -- "$0")' && pwd -P)
А вот версия без оболочки, основанная на ответе @0xff:
CWD := $(abspath $(patsubst %/,%,$(dir $(abspath $(lastword $(MAKEFILE_LIST))))))
Проверьте это, распечатав, например:
cwd:
@echo $(CWD)
Ответ 10
Сделайте себе огромную пользу и ожидайте, что каждый файл make будет запускаться из директории, в которой он находится. Не нужно заботиться о каких-либо путях в любой команде.
Ответ 11
Решение найдено здесь: https://sourceforge.net/p/ipt-netflow/bugs-requests-patches/53/
Решение: $ (CURDIR)
Вы можете использовать это так:
CUR_DIR = $(CURDIR)
## Start :
start:
rm -rf $(CUR_DIR)/data/db && docker-compose up
Ответ 12
обновление 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.
[[email protected] /]# 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
[[email protected] /]# 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
[[email protected] /]# ~/b.sh
/root/test
[[email protected] /]# /root/b.sh
/root/test
[[email protected] /]# cd ~
[[email protected] ~]# ./b.sh
/root/./test
[[email protected] ~]# test/a.sh
/root/test
[[email protected] ~]# cd test
[[email protected] test]# ./a.sh
/root/test/.
[[email protected] test]# cd /
[[email protected] /]# /root/test/a.sh
/root/test
[[email protected] /]#
старый:
Я использую это:
MAKEFILE_PATH := $(PWD)/$({0%/*})
Он может отображаться корректно, если выполняется в другой оболочке и в другом каталоге.
Ответ 13
Если переменная make содержит относительный путь ROOT_DIR
ROOT_DIR := ../../../
Чтобы получить абсолютный путь, используйте метод ниже.
ROOT_DIR := $(abspath $(ROOT_DIR))
Его работа прекрасна в GNUMake...