我在应用程序特定目录中有几个 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
以便将二进制文件放入它们各自的类型文件夹中?
外壳函数。
您可以使用 shell
函数:current_dir = $(shell pwd)
。或 shell
与 notdir
组合,如果您不需要绝对路径:current_dir = $(notdir $(shell pwd))
。
更新。
仅当您从 Makefile 的当前目录运行 make
时,给定的解决方案才有效。
正如@Flimm 所说:
请注意,这将返回当前工作目录,而不是 Makefile 的父目录。例如,如果您运行 cd /; make -f /home/username/project/Makefile,current_dir 变量将是 /,而不是 /home/username/project/。
下面的代码适用于从任何目录调用的 Makefile:
mkfile_path := $(abspath $(lastword $(MAKEFILE_LIST)))
current_dir := $(notdir $(patsubst %/,%,$(dir $(mkfile_path))))
取自here;
ROOT_DIR:=$(shell dirname $(realpath $(firstword $(MAKEFILE_LIST))))
显示为;
$ cd /home/user/
$ make -f test/Makefile
/home/user/test
$ cd test; make Makefile
/home/user/test
希望这可以帮助
dir
而不是 shell dirname
尽管它获取带有尾随 /
字符的路径名。
DIR:=$(strip $(shell dirname $(realpath $(lastword $(MAKEFILE_LIST)))))
dirname
的参数周围 - 以防路径中有空格。
如果您使用 GNU make,$(CURDIR) 实际上是一个内置变量。它是 Makefile 驻留在当前工作目录的位置,这可能是 Makefile 所在的位置,但并非总是如此。
OUTPUT_PATH = /project1/bin/$(notdir $(CURDIR))
请参阅 http://www.gnu.org/software/make/manual/make.html 中的附录 A 快速参考
/
。我尝试与 gmake
v3.81 绑定。但是如果 make
被称为 make -f xxx/Makefile
,你是对的。
CURDIR
对我有用,而 PWD
没有。我做了 mkdir -p a/s/d
,然后在每个文件夹中都有一个在 +$(MAKE) <subdir>
之前打印 PWD
和 CURDIR
的生成文件。
THIS_DIR := $(dir $(abspath $(firstword $(MAKEFILE_LIST))))
$(dir)
保留了最后一个路径分隔符。在解决该问题之前添加 $(realpath)
。
我喜欢选择的答案,但我认为实际展示它的工作比解释它更有帮助。
/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/])
用于去除尾部斜杠。
我尝试了许多这样的答案,但是在我的 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))
正如其他人所说,它不是最优雅的,因为它两次调用 shell,并且仍然存在空格问题。
但由于我的路径中没有任何空格,因此无论我如何开始 make
,它都适用于我:
make -f ../无论在哪里/makefile
make -C ../无论在哪里
make -C ~/无论在哪里
cd ../任何地方;制作
全部给我 wherever
为 current_dir
和到 wherever
的绝对路径为 mkfile_dir
。
这是使用 shell 语法获取 Makefile
文件的绝对路径的单行代码:
SHELL := /bin/bash
CWD := $(shell cd -P -- '$(shell dirname -- "$0")' && pwd -P)
这是基于 @0xff answer 的不带外壳的版本:
CWD := $(abspath $(patsubst %/,%,$(dir $(abspath $(lastword $(MAKEFILE_LIST))))))
通过打印来测试它,例如:
cwd:
@echo $(CWD)
示例供您参考,如下:
文件夹结构可能如下:
https://i.stack.imgur.com/1vdmj.png
其中有两个 Makefile,每个如下;
sample/Makefile
test/Makefile
现在,让我们看看 Makefile 的内容。
样本/Makefile
export ROOT_DIR=${PWD}
all:
echo ${ROOT_DIR}
$(MAKE) -C test
测试/生成文件
all:
echo ${ROOT_DIR}
echo "make test ends here !"
现在,执行示例/Makefile,如下所示;
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'
解释是,父/主目录可以存储在环境标志中,并且可以导出,以便可以在所有子目录makefile中使用。
在此处找到解决方案:https://sourceforge.net/p/ipt-netflow/bugs-requests-patches/53/
解决方案是:$(CURDIR)
你可以这样使用它:
CUR_DIR = $(CURDIR)
## Start :
start:
cd $(CUR_DIR)/path_to_folder
$(CURDIR)
已尝试失败。
make
的位置)。这确实是 OP 真正想要的,但问题标题是虚假的,所以问题本身是不一致的。因此,这是对不正确问题的正确答案。 ;)
据我所知,这是这里唯一适用于空格的答案:
space:=
space+=
CURRENT_PATH := $(subst $(lastword $(notdir $(MAKEFILE_LIST))),,$(subst $(space),\$(space),$(shell realpath '$(strip $(MAKEFILE_LIST))')))
它本质上是通过将 ' '
替换为 '\ '
来转义空格字符来工作的,这允许 Make 正确解析它,然后它通过执行另一个替换来删除 MAKEFILE_LIST
中的 makefile 的文件名,这样你就剩下那个目录了makefile 在里面。这不是世界上最紧凑的东西,但它确实有效。
你最终会得到这样的东西,其中所有的空间都被转义:
$(info CURRENT_PATH = $(CURRENT_PATH))
CURRENT_PATH = /mnt/c/Users/foobar/gDrive/P\ roje\ cts/we\ b/sitecompiler/
更新 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 调用执行正确。在其他 shell 中执行正确。
显示示例,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%/*})
如果在其他 shell 和其他目录中执行,它可以显示正确。
Makefile 中的一行就足够了:
DIR := $(notdir $(CURDIR))
"Sub Directory/Makefile"
处的 makefile 的$(lastword "$(MAKEFILE_LIST)")
将为您提供"Directory/Makefile"
。我认为没有办法解决这个问题,因为带有两个 makefile 的$(MAKEFILE_LIST)
给了你一个字符串"Makefile One Makefile Two
,它不能处理空格current_dir
对我不起作用。$(PWD)
可以,而且要简单得多。"solution only works when you are running make from the Makefile's current directory"
是表示“没有真正工作”的温和方式。我会将最新的文章放在答案的顶部。