The Behavior When a Gnu Make Phony Target Happens to Be The Same as a Directory Name

the behavior when a gnu make phony target happens to be the same as a directory name

Special targets are case-sensitive. To make libs etc actually be phony targets, you need to spell .PHONY thus:

.PHONY: all headers libs exes

As it is, you have an ordinary rule with a somewhat unusually-named target!

What is the purpose of .PHONY in a Makefile?

By default, Makefile targets are "file targets" - they are used to build files from other files. Make assumes its target is a file, and this makes writing Makefiles relatively easy:

foo: bar
create_one_from_the_other foo bar

However, sometimes you want your Makefile to run commands that do not represent physical files in the file system. Good examples for this are the common targets "clean" and "all". Chances are this isn't the case, but you may potentially have a file named clean in your main directory. In such a case Make will be confused because by default the clean target would be associated with this file and Make will only run it when the file doesn't appear to be up-to-date with regards to its dependencies.

These special targets are called phony and you can explicitly tell Make they're not associated with files, e.g.:

.PHONY: clean
clean:
rm -rf *.o

Now make clean will run as expected even if you do have a file named clean.

In terms of Make, a phony target is simply a target that is always out-of-date, so whenever you ask make <phony_target>, it will run, independent from the state of the file system. Some common make targets that are often phony are: all, install, clean, distclean, TAGS, info, check.

In a makefile, is a directory name a phony target or real target?

Edit: This only applies to GNU make - a fair assumption given the "linux" tag.

Your target is a real target, not a PHONY one. The problem is that the output directory gets updated when you put targets in it so that it is always newer than your target. This means your target will always get built because it is out of date with respect to its dependencies.

What you need is an order-only prerequisite. These prerequisites allow you to specify that it needs to be built if it does not exist, but not to pay attention to the timestamp. That is, a target will not be out of date with respect to order-only prerequisites.

You specify it like this:

$(EXEC_WITH_PATH): $(DPEND) $(OBJS) | ${OBJ_DIR}
...

Anything after the vertical bar is an order-only prerequisite.

You can now make your OBJ_DIR target simpler:

${OBJ_DIR} :
mkdir -p ${OBJ_DIR}

Note: I've used the ${OBJ_DIR} syntax instead of $(OBJ_DIR) because that is what you used. Order-only prerequisites do not depend on that syntax.

Why make all works as expected without adding all to .PHONY target?

How do you know that the all rule is "still executing"? That rule has no recipe, so there's no way it can be "executed".

If what you mean is that even though the all file exists in the local directory, make is still building the targets test1 and test2, that's how make works (this doesn't have anything to do with phony vs. non-phony targets). When make decides whether or not build a particular target first it tries to build all the prerequisites of that target, and all the prerequisites of those targets, etc. Only after all that is complete, can make know whether or not to build the first target (all in this case).

Makefile: rule with the same name as subdirectory ignored

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.

Why does following makefile rebuilt target build everytime

This is pretty much the same as the question you've linked. You never create a file called mkBuildDir, so it's always out-of-date, so build is always out of date.

Your mkBuildDir target isn't doing anything useful (though I presume this is a cut-down makefile). If instead you did

# it'd be better to list the TARFILES explicitly, though this will probably work
TARFILES=`ls *.tar.gz`

all: build untar

build: $(TARFILES)
test -d build || mkdir build
chmod 700 build
for prefix in $(TARFILES); do \
tar xvf $$prefix --directory=build; \
done

clean:
rm -Rf build

that would probably accomplish what you're looking for.

Having too many phony targets in a Makefile is usually a makefile 'code smell'. They are rarely the best/idiomatic way of doing things.

Why are .PHONY implicit pattern rules not triggered?

You're right, it would make more sense to define the subdir rules as PHONY. But Make does not consider implicit rules for PHONY targets, so you'll have to rewrite that rule. I suggest the following:

SUBDIR_TARGETS = all.subdir clean.subdir
.PHONY: all clean $(SUBDIR_TARGETS)

$(SUBDIR_TARGETS): %.subdir:
$(MAKE) -C src $*
$(MAKE) -C dict $*

all: all.subdir
clean: clean.subdir


Related Topics



Leave a reply



Submit