259

我在应用程序特定目录中有几个 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为了将二进制文件放在它们各自的类型文件夹中?

4

12 回答 12

351

外壳函数。

您可以使用shell功能:current_dir = $(shell pwd). 或shell结合notdir,如果您不需要绝对路径: current_dir = $(notdir $(shell pwd))

更新。

给定的解决方案仅在您make从 Makefile 的当前目录运行时才有效。
正如@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))))
于 2013-08-08T22:11:50.167 回答
166

取自这里

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

希望这可以帮助

于 2014-04-27T14:37:03.793 回答
61

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

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

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

于 2014-03-06T03:06:38.253 回答
35
THIS_DIR := $(dir $(abspath $(firstword $(MAKEFILE_LIST))))
于 2015-03-16T07:45:12.003 回答
10

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

/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/])用于去除尾部斜杠。

于 2018-04-09T19:27:07.040 回答
7

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

事实证明lastword,直到 3.81 才添加abspathrealpath:(

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 ../任何地方;制作

都给我whereverfor和forcurrent_dir的绝对路径。wherevermkfile_dir

于 2016-01-06T23:01:54.030 回答
2

Makefile这是使用 shell 语法获取文件的绝对路径的单行代码:

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

这是基于@0xff 答案的不带外壳的版本:

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

通过打印来测试它,例如:

cwd:
        @echo $(CWD)
于 2016-02-29T11:59:12.750 回答
0

据我所知,这是这里唯一适用于空格的答案:

space:= 
space+=

CURRENT_PATH := $(subst $(lastword $(notdir $(MAKEFILE_LIST))),,$(subst $(space),\$(space),$(shell realpath '$(strip $(MAKEFILE_LIST))')))

它的工作原理是通过替换 which 允许 Make 正确解析它来转义空格字符' ''\ '然后MAKEFILE_LIST通过进行另一个替换来删除 makefile 的文件名,这样你就剩下了 makefile 所在的目录。不完全是最紧凑的世界上的事情,但它确实有效。

你最终会得到这样的东西,其中所有的空间都被转义:

$(info CURRENT_PATH = $(CURRENT_PATH))

CURRENT_PATH = /mnt/c/Users/foobar/gDrive/P\ roje\ cts/we\ b/sitecompiler/
于 2020-04-25T17:09:34.110 回答
0

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

解决方案是:$(CURDIR)

你可以这样使用它:

CUR_DIR = $(CURDIR)

## Start :
start:
    cd $(CUR_DIR)/path_to_folder
于 2019-07-18T15:09:42.977 回答
0

示例供您参考,如下:

文件夹结构可能如下:

在此处输入图像描述

其中有两个 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中使用。

于 2016-01-07T15:57:53.790 回答
-2

更新 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 和其他目录中执行,它可以显示正确。

于 2017-02-17T12:03:00.717 回答
-2

Makefile 中的一行就足够了:

DIR := $(notdir $(CURDIR))

于 2020-01-09T18:07:26.280 回答