如何获取Makefile的当前相对目录?

时间:2013-08-08 22:02:21

标签: makefile gnu-make working-directory

我在app特定目录中有几个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 以便将二进制文件放入各自的类型文件夹中?

14 个答案:

答案 0 :(得分:220)

shell函数。

您可以使用shell功能:current_dir = $(shell pwd)。 或者shellnotdir结合使用,如果您不需要绝对路径: 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))))

答案 1 :(得分:114)

取自here;

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

希望这有帮助

答案 2 :(得分:36)

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

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

请参阅http://www.gnu.org/software/make/manual/make.html

中的附录A快速参考

答案 3 :(得分:25)

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

答案 4 :(得分:5)

我尝试了很多这些答案,但在我的AIX系统上使用gnu make 3.80我需要做一些旧学校的事情。

事实证明,直到3.81才添加lastwordabspathrealpath。 :(

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 ../ wherever / makefile
  • make -C ../ where wherever
  • make -C~ / wherever
  • cd ../wherever;使

所有人wherevercurrent_dir提供wherevermkfile_dir提供String emailAddress = "someone@somewhere.com"; hostServices.showDocument("mailto:" + emailAddress + "?Subject=This is my subject" + "&body=Please see the details at this link: " + "http://myserver.com:8080/application/page.html?param1=SOMETHING&param2=12345"; 的绝对路径。

答案 5 :(得分:5)

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

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

答案 6 :(得分:0)

供您参考的示例,如下所示:

文件夹结构可能如下:

enter image description here

哪里有两个Makefile,每个都如下;

sample/Makefile
test/Makefile

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

  

样品/生成文件

export ROOT_DIR=${PWD}

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

测试/生成文件

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'

说明,父/ home目录可以存储在environment-flag中,并且可以导出,以便可以在所有子目录makefile中使用。

答案 7 :(得分:0)

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

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

这是基于@0xff answer的没有shell的版本:

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

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

cwd:
        @echo $(CWD)

答案 8 :(得分:0)

帮自己一个忙,希望每个make文件都可以从包含目录中运行。无需关心任何命令中的任何路径。

答案 9 :(得分:0)

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

解决方案是:$(CURDIR)

您可以这样使用它:

CUR_DIR = $(CURDIR)

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

答案 10 :(得分:0)

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

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/

答案 11 :(得分:-1)

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

答案 12 :(得分:-1)

如果make变量包含相对路径 ROOT_DIR

override func viewDidLoad() {
    super.viewDidLoad()    

    let mainQueue = OperationQueue.main
    NotificationCenter.default.addObserver(forName: NSNotification.Name.UIApplicationUserDidTakeScreenshot, 
                object: nil, 
                queue: mainQueue) { notification in
        print("SCREENSHOT TAKEN")
    }
}

获取绝对路径只需使用以下方法。

ROOT_DIR := ../../../

它在GNUMake中的工作正常......

答案 13 :(得分:-3)

Makefile中的一行应该足够了:

DIR := $(notdir $(CURDIR))