views:

19

answers:

1

Consider, if you will, the following situation:

$ pwd
/tmp/submake_example
$ head $(find -type f)
==> ./subdir/Makefile <==
subtarget:
        echo "executing subtarget from directory $$(pwd)"

==> ./Makefile <==
include subdir/Makefile
$ make subtarget
echo "executing subtarget from directory $(pwd)"
executing subtarget from directory /tmp/submake_example

Is there a way that I can have the command for the target subtarget executed from within the directory subdir? I'd like to be able to access the targets of included makefiles from the command line in the main directory.

A: 

After some digging and experimentation, I've discovered a couple of things.

The approach recommended by this reference, which refers to the paper Recursive Make Considered Harmful, is pretty complicated, and involves manually maintaining a directory stack throughout the makefile inclusion heirarchy.

I also discovered, independently of any reference, that the last element of the variable $(MAKEFILE_LIST) will, at least for some basic test cases, contain the name of the makefile that's currently being included. This means that it's possible to store its directory in a simply expanded, target-specific variable with code like

foo: dir := $(dir $(lastword $(MAKEFILE_LIST)))

That's it. Then you can just use $(dir) within that rule like any other variable; it retains the value that it assumed during makefile inclusion. cd to it, put it in command paths, whatever.

You have to be careful to put the assignment to dir before any include directives in that makefile.

This won't work if there's a space in the directory name, but I gather that pretty much nothing in make works if there are spaces in file or directory names.

It's also notable that this approach uses features only found in GNU make. Sounds like a killer app to me, though I remain a bit perplexed as to why they don't just provide the directory name in a builtin variable or function.

Anyway this seems to work, at least at first glance. I'm still pretty much just floating this one without any real backup, so comments on the practicality of this approach, and alternative suggestions, are very welcome.

intuited