[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: The bugs in make v3.82
From: |
Paul Smith |
Subject: |
Re: The bugs in make v3.82 |
Date: |
Tue, 28 Sep 2010 17:41:39 -0400 |
On Tue, 2010-09-28 at 18:42 +0400, Alexander Kornilov wrote:
> Could you, please, review my new example (bug_0001_fixed.zip
> attached)?
>
> But some issue still present on Windows platform:
>
> Preconditions: 'Obj' directory present as dependency of target (see
> example from attachment).
>
> Obj/%.d: %.cpp makefile Obj
>
> 1. Execute make. File Obj/test1.d Obj/test2.d Obj/test3.d was
> generated;
> 2. Delete file Obj/test2.d;
> 3. Execute make again.
>
> Expected result:
> Only Obj/test2.d generated.
>
> Actual result (Windows platform):
> File Obj/test1.d Obj/test2.d Obj/test3.d generated again on Windows
> platform.
Please keep it on the mailing list so everyone can see.
First you can reduce these lines:
objList := $(srcList:%.cpp=%.o)
objList := $(addprefix $(objDir)/,$(objList))
to just:
objList := $(srcList:%.cpp=$(objDir)/%.o)
Ditto for depList.
You still have a bug in your makefile, which is also very common. I'll
bet it fails the same way on Linux as well, not just Windows.
Here's the rule that's causing your problems:
$(objDir)/%.d: %.cpp $(objDir) makefile
This lists the directory "Obj" as a prerequisite of all the .d files.
Directories are treated no differently than any other file by make; the
time last modified of the directory is checked against the target.
The problem is that the time last modified on a directory is updated
when (and only when) the directory itself changes: that is, a new file
is added, or a file is removed, or a file is renamed. That means that
every time you add/remove/rename a file in the Obj directory, the
directory timestamp is updated and any .d file that has already been
created will be considered out of date, and rebuilt.
Using a directory as a normal prerequisite is almost never what you
want.
You have two choices. I prefer the simple one which is to just force
the directory to be created whenever the makefile is invoked; something
like:
__dummy := $(shell mkdir -p $(objDir))
The advantage here is this is executed as the makefile is read in, every
time, so you don't have to list this as a prerequisite of any target to
make sure it's created.
The other choice is to use an order-only prerequisite (see the manual).
This would be something like:
$(objDir)/%.d: %.cpp makefile | $(objDir)
The downside is you have to remember to do that for any rule that writes
to $(objDir). The advantage is that the directory is not created unless
it's actually needed.