Helios
Helios

Reputation: 487

Makefile: rule with the same name as subdirectory ignored

This is my makefile:

all: first second

second:
    @echo "==Building second=="

first:
    @echo "==Building first=="

If there is a directory named second, the rule with the same name will be completely ignored by the makefile. If there isn't, everything goes normally.

Note that this happens whether or not the second folder as a Makefile in it.

I ran on this issue while organizing my project: I thought about creating a general Makefile which then invokes the Makefiles in each directories.. so to me it appears natural that the rule has the same name as the folder.

The solution is trivial: change the rule name inside the Makefile...but this behavior seems rather odd: do you have any idea/insight on this, and another possible solution?

I am using GNU Make 3.81, inside Bash 4.2.25, under Ubuntu 12.04.2 LTS.

Upvotes: 7

Views: 3850

Answers (3)

MadScientist
MadScientist

Reputation: 100866

If you're just looking for the reason the rule is not run, it's simple: make tries to build targets. Targets are represented (by default) by the existence of artifacts in the filesystem. It doesn't matter to make whether the artifact is a file or a directory (or, theoretically, anything else).

In order for make to consider a file out-of-date and in need of updating (and thus, for make to run the recipe associated with the target), at least one of two things must be true: either the target (i.e., file or directory) cannot exist or, if it does exist, its last modified time must be older than at least one of its prerequisites.

In your situation you have second, which exists, so the first requirement for rebuilding is not met, and which has no prerequisites, so the second requirement is not met... and so the target is not considered to be out of date and the recipe is not invoked.

As bobbogo suggests, you can tell make that the target should always be rebuilt, regardless of anything else, by declaring the target to be .PHONY. Make will understand that the target does not represent an artifact in the filesystem and is, instead, just a fake target in the makefile used to organize the build.

Upvotes: 11

Daniel
Daniel

Reputation: 500

If I understand your problem statement right, you are not invoking echo, but rather $(MAKE) -Csecond. High time to read Miller's Recursive Make Considered Harmful! While these are not exactly inherent problems of traditional makes, it would be hard and clumsy to do it better with them.

For this reason makepp was created. You can have the about same makefiles, but you don't need to specify recursion. If your target directories have makefiles, they usually get loaded into the same process automatically. Or if your targets get produced to another directory, you must tell makepp which makefiles to load. Either way one process has the overview of all (automatically detected!) dependencies.

There is much more to makepp. Besides doing almost all that GNU make can, there are lots more useful things, and you can even extend your makefiles with some Perl programming.

Upvotes: 0

bobbogo
bobbogo

Reputation: 15483

It seems that you want the second rule to always run, whether or not the file (or directory) "second" already exists. You can make second this sort of symbolic target by declaring it as a pre-requisite of .PHONY.

.PHONY: all
all: first second

.PHONY: second
second:
    @echo "==Building second=="
...

Upvotes: 3

Related Questions