How to get current relative directory of your Makefile?

Nikolai Popov

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)).


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 Makefiles invoked from any directory:

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

As taken from here;

ROOT_DIR:=$(shell dirname $(realpath $(lastword $(MAKEFILE_LIST))))

Shows up as;

$ cd /home/user/

$ make -f test/Makefile 

$ cd test; make Makefile 

Hope this helps

Tzunghsing David Wong

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

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

I tried many of these answers, but on my AIX system with gnu make 3.80 I needed to do some things old school.

Turns out that lastword, abspath and realpath were not added until 3.81. :(

mkfile_path := $(word $(words $(MAKEFILE_LIST)),$(MAKEFILE_LIST))
mkfile_dir:=$(shell cd $(shell dirname $(mkfile_path)); pwd)
current_dir:=$(notdir $(mkfile_dir))

As others have said, not the most elegant as it invokes a shell twice, and it still has the spaces issues.

But as I don't have any spaces in my paths, it works for me regardless of how I started make:

  • make -f ../wherever/makefile
  • make -C ../wherever
  • make -C ~/wherever
  • cd ../wherever; make

All give me wherever for current_dir and the absolute path to wherever for mkfile_dir.

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


#!/bin/bash -eu

# Create a testing dir
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)

    @echo "         path: $(path)"
    @echo "          cwd: $(cwd)"
    @echo ""

# See/debug each command
set -x

# Test using the Makefile in the current directory
cd $proj_dir

# 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
         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.

Solution found here :

The solution is : $(CURDIR)

You can use it like that :


## Start :
    cd $(CUR_DIR)/path_to_folder

Example for your reference, as below:

The folder structure might be as:

enter image description here

Where there are two Makefiles, each as below;


Now, let us see the content of the Makefiles.


export ROOT_DIR=${PWD}

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


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

Now, execute the sample/Makefile, as;

cd sample


echo /home/symphony/sample
make -C test
make[1]: Entering directory `/home/symphony/sample/test'
echo /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.

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:

        @echo $(CWD)

Do yourself a huge favor and expect each make file to be run from the containing directory. No need to care about any paths whatsoever in any command.

update 2018/03/05 finnaly I use this:

shellPath=`echo $PWD/``echo ${0%/*}`

# process absolute path
shellPath1=`echo $PWD/`
shellPath2=`echo ${0%/*}`
if [ ${shellPath2:0:1} == '/' ] ; then

It can be executed correct in relative path or absolute path. Executed correct invoked by crontab. Executed correct in other shell.

show example, print self path.

[[email protected] /]# more /root/test/
shellPath=`echo $PWD/``echo ${0%/*}`

# process absolute path
shellPath1=`echo $PWD/`
shellPath2=`echo ${0%/*}`
if [ ${shellPath2:0:1} == '/' ] ; then

echo $shellPath
[[email protected] /]# more /root/
shellPath=`echo $PWD/``echo ${0%/*}`

# process absolute path
shellPath1=`echo $PWD/`
shellPath2=`echo ${0%/*}`
if [ ${shellPath2:0:1} == '/' ] ; then

[[email protected] /]# ~/
[[email protected] /]# /root/
[[email protected] /]# cd ~
[[email protected] ~]# ./
[[email protected] ~]# test/
[[email protected] ~]# cd test
[[email protected] test]# ./
[[email protected] test]# cd /
[[email protected] /]# /root/test/
[[email protected] /]# 

old: I use this:

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

It can show correct if executed in other shell and other directory.