How to figure out current Makefile location in gmake at runtime - makefile

I would like to tell (g)make to include some common initializations from a separate file knowing the relative location of the included file with respect to the main Makefile.
However in the manuals I cannot find any built-in variable that would, for example, give you the name of the current Makefile.
For example if I want to include the content of a file in the same directory as the current make file, instead of hard-wiring the location of the include:
# MAIN Makefile : ./scripts/make/TaskA.mk
include ./scripts/make/Common.inc
...
I would like to write something like the following assuming that _MAKEFILE_ contains the TaskA.mk location:
# MAIN Makefile : ./scripts/make/TaskA.mk
MAKEFILE_DIR=$(dirname $(_MAKE_FILE_))
include $(MAKEFILE_DIR)/Common.inc

Doesn't the manual give a recipe based on MAKEFILE_LIST?
Basically
this_makefile := $(lastword $(MAKEFILE_LIST))
before any include directives should do the trick.

Look at GNU make - Other Special Variables. MAKEFILE_LIST includes all Makefiles read. So, if you take the first one and extract the directory, you're done.
MAKEFILE_DIR=$(dir $(firstword $(MAKEFILE_LIST)))
include $(MAKEFILE_DIR)Common.inc

Related

Include a third makefile with a path relative to second, when second isn't in directory of first

I have a Makefile with only project-level definitions: which source files to use, what binary or library to make, etc..
It includes ../../Make.Arch for architecture-specific definitions (such as compiler command).
In turn, Make.Arch is meant to include ../etc/Makefile.Standard for all the boilerplate of actually allowing the make system to work .
But include requires a path relative to where the makefile is actually being run (or maybe where the first Makefile is), not relative to the second... What to do?
Make interprets relative paths from the working directory, the directory in which Make is being run. You haven't specified how you're running Make, so I'll assume your running it in the directory with Makefile.
If you are allowed to modify the makefiles, you can change the paths.
You could change Make.Arch from this:
include ../etc/Makefile.Standard
to this:
include ../../../etc/Makefile.Standard
but that would require that any makefile that uses Make.Arch be two directories down from it. That's clearly not a good idea. But we can use a variable:
include $(ARCH_DIR)/../etc/Makefile.Standard
which is provided by Makefile (or any other makefile that uses Make.Arch):
ARCH_DIR := ../..
include $(ARCH_DIR)/Make.Arch
If you are not allowed to modify the makefiles, then you must cheat. One way is to create a symbolic link to Makefile.Standard.
mkdir ../etc
ln -s ../../../etc/Makefile.Standard ../etc
Now Makefile will work. (It ought to be possible to make a link to etc/, but for some reason I can't get that to work right now.)

gnu make, include path for `include` directives

Apart from the standard directories used by make to locate files loaded by include directives, is there any way to specify additional include paths within the makefile itself? I'm aware of the -I command-line GNU make option but I would like to know if there's any make variable to specify the same.
I suggested using the .INCLUDE_DIRS variable, but as pointed out in the comment below, that variable is read-only.
The only other way I can think of is to have a top-level file invoke the real makefile, and have the top level one update MAKEFLAGS:
# Top level -- Call it GNUmakefile?
INCLUDE_DIRS := first second third
MAKEFLAGS += $(foreach dir,$(INCLUDE_DIRS),--include-dir=$(dir))
.DEFAULT all:;$(MAKE) -f Makefile $(MAKECMDGOALS)
Then the real Makefile is invoked with the three directories in .INCLUDE_DIRS.

gnu make put include path into make file

My include file references many other make files using something like:
include Enablers/MSRP/Android.mk
the problem is that the make file that references all other makefiles is deep in sub-folders, or, in other words the correct path would be something like:
include ../../../../../Enablers/MSRP/Android.mk
In order for me to build my makefile I have to add ../../../../.. to make search path:
ndk-build -I../../../../.. -j8 other params...
(ndk-build is a wrapper for gnu make on android buildsystem, it's equivalent to make build-local.mk other params)
So, what can i do to to avoid adding the ../../../../.. to make search path? I could go the makefile and update all makefile include statements, but I'm looking for the way to add that extra include path at the top of my makefile. Something like:
makeincludepaht += include Enablers/MSRP/Android.mk
include Enablers/MSRP/Android.mk
...
Append the new include path to the standard search path:
.INCLUDE_DIRS += ../../..
Look at the end of the Special Variables section for the .INCLUDE_DIRS special variable.
I'm not familiar with ndk-build, but I have similar setup. I just set a variable in make that contains this path and then use that variable in all my includes.
makefile:
INCLUDE_TOP=../../../../..
include $(INCLUDE_TOP)/someDir/includes.mk
You can also then use INCLUDE_TOP inside includes.mk for all your paths. It is usually better to make it default to some value by conditionally setting in there.
includes.mk:
# will only set if not already set
INCLUDE_TOP ?= ./
HEADERS=$(INCLUDE_TOP)/headers

Make include in makefiles be relative to the file's location

Directly related to this question. How can I make the include directive in makefiles behave relatively to the location of the current script?
Assume that the current path is arbitrary and you have no control over it. Only the makefile location is known. Your makefile is not the root one - it's included. That's exactly how it is in Android NDK.
Is there a builtin variable with the current makefile's name? Can I strip filename away from it, leaving just the path? Using make 3.81 on Cygwin.
You can get the name of the makefile being currently processed from MAKEFILE_LIST builtin variable.
Given that the current makefile is the last one that has been included (in other words you didn't use another include directive since the beginning of the current script), the path to the script itself would be:
SELF_DIR := $(dir $(lastword $(MAKEFILE_LIST)))
Now you are able to include a script in the same directory as such (note an absence of slash, it has already been added by $(dir ...)):
include $(SELF_DIR)another.mk
Note: In GNU Make 3.80 there was no lastword builtin function. In that case you may implement it as follows replacing $(lastword ...) with $(call lastword,...):
lastword = $(if $(firstword $1),$(word $(words $1),$1))
Is there a builtin variable with the current makefile's name?
Yes, there is, use ${CURDIR}. This is the directory where top-level Makefile is located, so you don't need to strip anything from it.
http://www.gnu.org/software/make/manual/make.html#Recursion
I find that relative paths work (GNUMake 3.81), but if they don't for you, try this:
include $(abspath ../whatever)

Depend on the make file itself

In the event that a Makefile itself is changed, a safe bet would be to consider all targets out of date.
Is there a clever way to add this dependency? Are there any alternatives?
Make sure the object files depend on the makefile:
$(OBJFILES) : Makefile
Where Makefile is the name of the make file.
A safe bet, but a terrible idea. Example: you're using automake and update Makefile.am to add a single source file. The correct response is to compile just the new file and link it in. In your scheme everything would be rebuilt.
Moreover, adding the dependency isn't going to do anything unless you touch the file, something like:
$(SRCS): Makefile
touch $#
This will then trip up editors that use the mtime to detect concurrent modification (emacs is one example).
If you're doing something major, just run make clean all after doing the change.
Since GNU make version 4.3 it is now possible with the use of those two special variable:
.EXTRA_PREREQS
To add new prerequisite to every target
MAKEFILE_LIST
To get the path of the make file
To have every target depend on the current make file:
Put near the top of the file (before any include since it would affect the MAKEFILE_LIST) the following line:
.EXTRA_PREREQS:= $(abspath $(lastword $(MAKEFILE_LIST)))
To have every target depend on the current make file and also the make files which were included
Put the following line at the end of your file:
.EXTRA_PREREQS+=$(foreach mk, ${MAKEFILE_LIST},$(abspath ${mk}))

Resources