How to get current relative directory of your Makefile?
Solution 1
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 runcd /; make -f /home/username/project/Makefile
, thecurrent_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))))
Solution 2
As taken from here;
ROOT_DIR:=$(shell dirname $(realpath $(firstword $(MAKEFILE_LIST))))
Shows up as;
$ cd /home/user/
$ make -f test/Makefile
/home/user/test
$ cd test; make Makefile
/home/user/test
Hope this helps
Solution 3
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
Solution 4
THIS_DIR := $(dir $(abspath $(firstword $(MAKEFILE_LIST))))
Solution 5
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.
Related videos on Youtube
Comments
-
boltup_im_coding about 4 years
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? -
boltup_im_coding almost 11 yearsThat does not work. It is the same problem. pwd prints the full path name, I just want the name of the actual current folder I'm in.
-
Nikolai Popov almost 11 years@unexpected62 What about
notdir
? -
boltup_im_coding almost 11 yearsThanks. I am a make noob. So what's going on here exactly? notdir is removing everything through the last slash in the output of pwd? I saw gnu.org/software/make/manual/html_node/File-Name-Functions.html
-
Nikolai Popov almost 11 yearsYep,
notdir
does just that. -
Tom Gruner over 10 yearsIt needs to have the value expanded immediately so the := operator should be used. As in mkfile_path := and current_dir = (otherwise the right side values could be evaluated later when the MAKEFILE_LIST has changed after other Makefiles were included
-
simpleuser about 10 yearsNote that a similar issue occurs is you use -C to specify the directory in which to make. The $PWD will be the directory you ran gmake from.
-
Simon Peverett about 10 yearsFrom the GNU Make manual (page 51): " when GNU make starts (after it has processed any -C options) it sets the variable CURDIR to the pathname of the current working directory." Not the location of where the Makefile is located - although, they might be the same.
-
knocte about 10 yearssad thing is that this doesn't work for AutoMake (Makefile.am files) :(
-
Subfuzion over 9 yearsDownvoted because the answer is not technically correct, as noted by Simon Peverett in the previous comment.
-
Serge Roussak over 9 yearsIMHO it would better to use internal make-function
dir
instead ofshell dirname
though it gets pathname with trailing/
character. -
sleepycal over 9 years@SergeRoussak Could you perhaps write a seperate answer explaining why? I don't know enough about make to give an informed opinion.
-
Serge Roussak over 9 yearsbecause of reduction of dependancies on external tools. Ie what if there will alias of dirname command at some system?..
-
mrosales over 9 yearsI know this is an old question but I just ran into and thought this could be useful. This also will not work when there is a space in the relative path of the makefile. Specifically,
$(lastword "$(MAKEFILE_LIST)")
of a makefile at path"Sub Directory/Makefile"
will give you"Directory/Makefile"
. I dont think there is any way around this since$(MAKEFILE_LIST)
with two makefiles gives you a single string"Makefile One Makefile Two
, which cannot handle spaces -
Craig Ringer over 9 years... unless you have spaces in any paths.
-
TrueY about 9 years@SimonPeverett: The expression in brackets means the the "current working directory AFTER -C opts applied". Namely $(CURDIR) gives the exactly the same results for "make -C xxx" and "cd xxx; make". Also it removes the trailing
/
. I tried tied withgmake
v3.81. But You are right ifmake
is called asmake -f xxx/Makefile
. -
Thorsten Lorenz about 9 yearsThis almost worked for me, but DIR had a leading whitespace, so a minor change made work perfectly:
DIR:=$(strip $(shell dirname $(realpath $(lastword $(MAKEFILE_LIST)))))
-
sleepycal about 9 yearsThanks @ThorstenLorenz, I've edited the answer to reflect this
-
robal over 8 years... unless you have included some other makefile in previous line
-
fbence over 8 years@mrosales I am having this same problem. You could get it from shell with
${PWD##*/}
, but$(shell ${PWD##*/} )
complains, that*** unterminated call to function
shell': missing)'.
-
Brent Bradburn over 8 yearsTo reference the current makefile, the use of
$MAKEFILE_LIST
must precede anyinclude
operations (docs). -
Brent Bradburn over 8 yearsShould use quotes -- at least around the argument to
dirname
-- in case there are spaces in the path. -
Jesse Chisholm over 8 yearsSee my variant answer for gnu make version 3.80, which doesn't have lastword, realpath or abspath.
-
Zsigmond Lőrinczy over 8 yearsI, for one, have compiled gnu-make-3.82 on aix (5-6-7) without problems.
-
Jesse Chisholm over 8 yearsYes, by 3.81 the needed functions for the earlier solutions were implemented. My answer is for older systems with 3.80 or earlier. Sadly, at work I am not allowed to add or upgrade tools to the AIX system. :(
-
Jesse Chisholm over 8 yearsThis gets the current working directory, not the makefile's home directory.
-
parasrish over 8 yearsThese are the lines in the Makefile. Now, as the Makefile command executes, this will get the path at which the Makefile is. I understand "makefile home directory" is refering to the same, i.e. the directory-path in which Makefile is executing.
-
parasrish over 8 years@Jesse Chisholm please revisit. I have explained with usage.
-
ntc2 almost 8 yearsThe
:=
(vs plain=
) is important if you have anyinclude
statements, since otherwise the included makefiles will come after the current makefile. -
Keith M over 7 years"It can show correct if executed if other shell and other directory" doesn't make sense in English. Can you try explaining again?
-
zhukunqian over 7 yearssorry for my poor english
-
Keith M over 7 yearsThanks for the edit, I see you meant IN now. Can you explain what this does before I try it? I'm not sure how to use it. Like what do you mean by "other shell"
-
Mark K Cowan over 7 years
CURDIR
works for me wherePWD
did not. I didmkdir -p a/s/d
then in each folder had a makefile which printedPWD
andCURDIR
before+$(MAKE) <subdir>
. -
fbence over 6 yearsthese don't seem to work if there is a space in the path
-
Bruno Bronosky about 6 yearsI have created an answer that demonstrates this. stackoverflow.com/a/49740268/117471
-
sherrellbc about 6 years@robal Yep. That is what I just encountered. This works great if you only have two Makefiles (the main one plus an included one).
-
CMCDragonkai about 6 yearsThe updated methods doesn't work if there are spaces in the path to the Makefile. It's the
dir
that fails if there are spaces. That should be mentioned in the answer along with any possible workarounds. -
CaTx almost 6 yearsThat
current_dir
doesn't work for me.$(PWD)
does and it's much simpler. -
villapx over 5 years@mrosales @fbence GNU make, in general, doesn't really handle paths that have spaces in them. Something as simple as
SRCS
variable with all your source file names in it no longer works if a single file has a space in its name. -
EMon over 5 yearsCritical Importance! The second example above needs the := assignment operator or else some very weird and angry things can happen with complex makefiles (trust me)
-
Johan Boulé about 5 yearsFirst one is a repeated error and doesn't work for out-of-tree-builds.
-
Johan Boulé about 5 yearsThis answer has so many wrong things it can't possibly be fixed. I suggest a simple removal.
-
Johan Boulé about 5 yearsA repeated error: it doesn't work for out-of-tree-builds. Also, your gnome terminal provides a simple way to copy text: just select it. The rumor has Imgur is brankrupt.
-
kkm about 5 years@SergeRoussak:
dirname
(and its cousinbasename
) are POSIX. I agree, "what if your system does not havedirname
?" is a valid question, but so is "what if your system does not havemake
?" :-) Also, AFAIK,$(realpath )
is a relatively recent, and GNU-make specific. So here is more dependency on tools for ya. But your$(dir )
suggestion is a good one! -
Sean almost 5 yearsWelcome to Stack Overflow. Can you add more detail to your answer? The question states that
$(CURDIR)
was already tried unsuccessfully. -
Sz. almost 5 yearsWARNING, quick-googlers: This is not the directory, where the makefile is, but the current working directory (where
make
was launched in). It is, indeed, what OP really wanted, but the question title is bogus, so the question itself is inconsistent. So, this is a correct answer to an incorrect question. ;) -
Stéphane Gourichon almost 5 years
current_dir
is not what I expected.mkfile_dir := $(dir $(mkfile_path))
is what I expected: full path to the makefile directory. -
Richard Kiefer over 4 yearsNote that you need to enforce immediate variable expansion using the
:=
operator. Otherwise, you get funky behavior. -
Victor Sergienko over 4 years
"solution only works when you are running make from the Makefile's current directory"
is a mild way to say "not really working". I would put the latest piece at the top of the answer. -
UpAndAdam over 4 yearsThis is flat out wrong and a redundant wrong answer
-
UpAndAdam over 4 years@CMCDragonkai except that answer is abysmally wrong... any answer of PWD is wrong. And if you are going to be that incorrect use the built in CURDIR instead.
-
carbolymer over 4 yearsdoes not work - if you're including other files from
Makefile
- this will return the path of the last included file! -
Guss almost 4 yearsThis works well for me (haven't tested spaces in dirs, but I don't expect to encounter this). The main issue I had with this code is that
$(dir)
retains the last path separator. Adding$(realpath)
before it solves that problem. -
Mike Maxwell over 3 years@carbolmyer: I use included makefiles extensively. I think that by using $(firstword...) instead of $(lastword...), this can be made to work, assuming the makefile you want is the first one you read. But I won't claim that this works in every situation. In particular, it would not work to find the directory for an intermediate 'include'd makefile. So the statement in my case is
current_dir=$(dir $(abspath $(firstword $(MAKEFILE_LIST))))
It is a little surprising that make doesn't have a built-in variable for the full path of the current makefile. -
devatherock over 3 yearsChanging
mkfile_path
tomkfile_path := $(lastword $(abspath $(MAKEFILE_LIST)))
works for me when the directory path contains spaces -
user503582 over 2 yearsThis should be the correct answer. No need to reinvent the wheel. Make does it for you ootb.