Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Get makefile directory

Tags:

makefile

I am distributing my cpp files along with a makefile. Now the makefile is located in the same directory as the cpp file.

What is the variable (if any) in makefile that allows me to retrieve the current directory where the makefile is located? In this way I can use that variable to specify my cpp path for compilation.

My makefile is as follows:

all:
    g++ ($makeFileDir)/main.cpp ($makeFileDir)/hello.cpp ($makeFileDir)/factorial.cpp -o ($makeFileDir)/hello.exe

Edit: I am running my makefiles on Windows

like image 597
Graviton Avatar asked Jan 05 '10 08:01

Graviton


People also ask

How do I get the current directory in makefile?

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

What is DIR in makefile?

The directory-part of the file name is everything up through (and including) the last slash in it. If the file name contains no slash, the directory part is the string ' ./ '. For example, $(dir src/foo.c hacks)

Can a make target be a directory?

Yes, a Makefile can have a directory as target. Your problem could be that the cd doesn't do what you want: it does cd and the git clone is carried out in the original directory (the one you cd ed from, not the one you cd ed to). This is because for every command in the Makefile an extra shell is created.

How do I use mkdir in makefile?

Solution 1: build the directory when the Makefile is parsed A quick call to $(shell) can achieve that. Before any targets are created or commands run the Makefile is read and parsed. If you put $(shell mkdir -p $(OUT)) somewhere in the Makefile then GNU Make will run the mkdir every time the Makefile is loaded.


2 Answers

Here is a cross-platform way to get the directory of the Makefile, which should be fully shell-agnostic.

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

Note that this will give you the directory of the Makefile being currently interpreted. You might have bad (or good!) surprises if you include a Malefile using this statement from another.

That should be enough if you use a recent implementation of make for windows, i.e. Chocolatey's.

Issues with older make for Windows

Depending on the version of make you're using on Windows, there can be inconsistencies in the handling of backslashes. You might need one of the following variant. That's the case for GnuWin's make 3.81 binary for example.

  • Make the path separator consistent. The statement below uses forward slashes only, just swap \ and / to get the opposite behavior. From my experience (with GnuWin's make), you might have to use forward slashes to use such a variable for make include statements or to use it in VPATH. But you would of course need backslashes in the DOS shell, and therefore in recipes... You might need two versions of the variable, but at least the substitution makes sure that the path separator is consistent!
makeFileDir := $(subst \,/,$(dir $(abspath $(lastword $(MAKEFILE_LIST)))))
  • The abspath function of GnuWin make 3.81 is broken and doesn't handle paths with drive letters in it. Here is a workaround to handle Windows absolute paths (with drive letter) as well. You can then use it to get the directory of the Makefile (here with the path separator substitution as well). I won't explain the details, but the workaround simply returns the argument if that's already a Windows absolute path, i.e. if there is : in the root of the path, and uses the builtin abspath otherwise.
define fixabspath
$(if $(findstring :,$(firstword $(subst /, ,$(subst \,/,$(1))))),$\$
$(1),$\
$(abspath $(1)))

makeFileDir := $(subst \,/,$(dir $(call fixabspath,$(lastword $(MAKEFILE_LIST)))))

Remarks

  • There might be sources I'm omitting here and I'm sorry for that. It's been a long time ago.
  • In the fixabspath definition, $\ are just here to split the line for readability.
  • The MAKEFILE_LIST variable contains a list of the Makefiles being interpreted, the last one being the current one. See the corresponding manual page.
  • If I remember correctly, this also works with macOS' native make.
like image 199
jmon12 Avatar answered Sep 19 '22 00:09

jmon12


I remember I had the exact same problem. It's not possible, as far as I remember. The best bet you can have is to pass it as a variable. That is both cross platform and guaranteed to work, as you know the makefile dir at invoke time (otherwise you can't invoke it).

In alternative, you can do a very dirty trick, meaning you try to combine your current path (you can obtain with $(CURDIR) in gnu make) with the path of the invocation of the makefile (which can be tricky, and depends on your make)

like image 34
Stefano Borini Avatar answered Sep 19 '22 00:09

Stefano Borini