如何获得您的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,以便将二进制文件放在各自的类型文件夹中?

409860 次浏览

壳层函数。

你可以使用shell函数: 或者shellnotdir的组合,如果你不需要绝对路径: current_dir = $(notdir $(shell pwd)) . < / p >

更新。

给出的解决方案仅当你从Makefile的当前目录运行make时有效 正如@Flimm所指出的:

注意,这将返回当前工作目录,而不是Makefile的父目录。例如,如果你运行cd /; make -f /home/username/project/Makefilecurrent_dir变量将是/,而不是/home/username/project/

下面的代码将适用于从任何目录调用的makefile:

mkfile_path := $(abspath $(lastword $(MAKEFILE_LIST)))
current_dir := $(notdir $(patsubst %/,%,$(dir $(mkfile_path))))

如果您正在使用GNU make, $(CURDIR)实际上是一个内置变量。它是Makefile所在的位置 当前工作目录,这可能是Makefile所在的目录,但并不总是这样

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

参见http://www.gnu.org/software/make/manual/make.html中的附录A快速参考

取自在这里;

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

希望这能有所帮助

THIS_DIR := $(dir $(abspath $(firstword $(MAKEFILE_LIST))))

我尝试了许多这些答案,但是在我的AIX系统上,我需要使用gnu make 3.80做一些老派的事情。

lastwordabspathrealpath直到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 ../where /makefile ./
  • make -C ../任意位置
  • make -C ~/where
  • cd . . /的地方;使

都给我current_dirwherevermkfile_dirwherever的绝对路径。

举例如下,供参考:

文件夹结构可能是这样的:

enter image description here

其中有两个makefile,分别如下所示;

sample/Makefile
test/Makefile

现在,让我们看看Makefiles的内容。

样品/ Makefile

export ROOT_DIR=${PWD}


all:
echo ${ROOT_DIR}
$(MAKE) -C test

测试/ Makefile

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'

解释一下,父/home目录可以存储在environment-flag中,并且可以导出,这样就可以在所有子目录的makefile中使用。

下面是使用shell语法获取Makefile文件的绝对路径的一行程序:

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

下面是基于@0xff回答的不带shell的版本:

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

通过打印来测试,比如:

cwd:
@echo $(CWD)
< p >更新2018/03/05 最后我使用这个:


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 /]#

< p >老: 我使用这个:

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

如果在其他shell和其他目录下执行,可以显示正确。

我喜欢选定的答案,但我认为实际展示它比解释它更有帮助。

/ 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/])用于去掉后面的斜杠。

这里找到的解决方案:https://sourceforge.net/p/ipt-netflow/bugs-requests-patches/53/

__abc0: $(curdir)

你可以这样使用它:

CUR_DIR = $(CURDIR)


## Start :
start:
cd $(CUR_DIR)/path_to_folder

Makefile中的一行就足够了:

DIR := $(notdir $(CURDIR))

据我所知,这是唯一的答案,正确的空格:

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/

简单、正确、现代的方式:

对于GNU make >= 3.81,它是在2006年引入的

ROOT_DIR := $(dir $(realpath $(lastword $(MAKEFILE_LIST))))
  1. MAKEFILE_LIST在包含文件进入和退出作用域时发生变化。最后一项是当前文件。

  2. lastword提取最后一项(制作文件名称,相对于pwd)

  3. realpathmake内置的,并解析为文件系统根的规范路径

  4. dir删除文件名,只留下目录。

使用{}代替()

cur_dir=${shell pwd}
parent_dir=${shell dirname ${shell pwd}}}