How to get current relative directory of your Make

2019-01-16 01:36发布

I have a several Makefiles in app specific directories like this:

/project1/apps/app_typeA/Makefile
/project1/apps/app_typeB/Makefile
/project1/apps/app_typeC/Makefile

Each Makefile includes a .inc file in this path one level up:

/project1/apps/app_rules.inc

Inside app_rules.inc I'm setting the destination of where I want the binaries to be placed when built. I want all binaries to be in their respective app_type path:

/project1/bin/app_typeA/

I tried using $(CURDIR), like this:

OUTPUT_PATH = /project1/bin/$(CURDIR)

but instead I got the binaries buried in the entire path name like this: (notice the redundancy)

/project1/bin/projects/users/bob/project1/apps/app_typeA

What can I do to get the "current directory" of execution so that I can know just the app_typeX in order to put the binaries in their respective types folder?

10条回答
我欲成王,谁敢阻挡
2楼-- · 2019-01-16 01:48

The shell function.

You can use shell function: current_dir = $(shell pwd). Or shell in combination with notdir, if you need not absolute path: current_dir = $(notdir $(shell pwd)).

Update.

Given solution only works when you are running make from the Makefile's current directory.
As @Flimm noted:

Note that this returns the current working directory, not the parent directory of the Makefile.
For example, if you run cd /; make -f /home/username/project/Makefile, the current_dir variable will be /, not /home/username/project/.

Code below will work for any for Makefiles invoked from any directory:

mkfile_path := $(abspath $(lastword $(MAKEFILE_LIST)))
current_dir := $(notdir $(patsubst %/,%,$(dir $(mkfile_path))))
查看更多
一纸荒年 Trace。
3楼-- · 2019-01-16 01:53

If you are using GNU make, $(CURDIR) is actually a built-in variable. It is the location where the Makefile resides the current working directory, which is probably where the Makefile is, but not always.

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

See Appendix A Quick Reference in http://www.gnu.org/software/make/manual/make.html

查看更多
姐就是有狂的资本
4楼-- · 2019-01-16 01:53

Example for your reference, as below:

The folder structure might be as:

enter image description here

Where there are two Makefiles, each as below;

sample/Makefile
test/Makefile

Now, let us see the content of the Makefiles.

sample/Makefile

export ROOT_DIR=${PWD}

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

test/Makefile

all:
    echo ${ROOT_DIR}
    echo "make test ends here !"

Now, execute the sample/Makefile, as;

cd sample
make

OUTPUT:

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'

Explanation, would be that the parent/home directory can be stored in the environment-flag, and can be exported, so that it can be used in all the sub-directory makefiles.

查看更多
混吃等死
5楼-- · 2019-01-16 01:55

Here is one-liner to get absolute path to your Makefile file using shell syntax:

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

And here is version without shell based on @0xff answer:

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

Test it by printing it, like:

cwd:
        @echo $(CWD)
查看更多
淡お忘
6楼-- · 2019-01-16 02:03
THIS_DIR := $(dir $(abspath $(lastword $(MAKEFILE_LIST))))
查看更多
成全新的幸福
7楼-- · 2019-01-16 02:06

I like the chosen answer, but I think it would be more helpful to actually show it working than explain it.

/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

Output:

+ 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

NOTE: The function $(patsubst %/,%,[path/goes/here/]) is used to strip the trailing slash.

查看更多
登录 后发表回答