Discussion:
[1003.1(2013)/Issue7+TC1 0000857]: Make rules which do not create the target file or do unexpected things with its timestamp
Austin Group Bug Tracker
2014-07-08 10:14:47 UTC
Permalink
The following issue has been SUBMITTED.
======================================================================
http://austingroupbugs.net/view.php?id=857
======================================================================
Reported By: jammule
Assigned To:
======================================================================
Project: 1003.1(2013)/Issue7+TC1
Issue ID: 857
Category: Shell and Utilities
Type: Omission
Severity: Comment
Priority: normal
Status: New
Name: Jarmo Jaakkola
Organization:
User Reference:
Section: make
Page Number: 2937
Line Number: 97105-97113
Interp Status: ---
Final Accepted Text:
======================================================================
Date Submitted: 2014-07-08 10:14 UTC
Last Modified: 2014-07-08 10:14 UTC
======================================================================
Summary: Make rules which do not create the target file or do
unexpected things with its timestamp
Description:
<p>I haven't been able to find clear answers from the standard to some
behavior that seems to be taken for granted with make. These are all
somewhat related, so I'll list them here instead of making a separate issue
from each of them.</p>

<p><b>Case 1: </b>It is customary to use the following idiom to force a
target's related commands to always run:</p>

<pre>
foo: FORCE
commands...

FORCE:
</pre>

<p>(This is what some implementations offer the ".PHONY: foo" special
target as an extension for.)</p>

<p>My reading of the standard does not come clear why, or if at all, this
should work (assuming FORCE does not exist). This is the current
formulation on page 2937, lines 97105-97113:</p>

<blockquote><p>The make utility attempts to perform the actions required to
ensure that the specified targets are up-to-date. A target is considered
out-of-date if it is older than any of its prerequisites or if it does not
exist. The make utility shall treat all prerequisites as targets themselves
and recursively ensure that they are up-to-date, processing them in the
order in which they appear in the rule. The make utility shall use the
modification times of files to determine whether the corresponding targets
are out-of-date.</p>

<p>After make has ensured that all of the prerequisites of a target are
up-to-date and if the target is out-of-date, the commands associated with
the target entry shall be executed. If there are no commands listed for the
target, the target shall be treated as up-to-date.</p></blockquote>

<p>When "make foo" is issued this is what I think should happen:</p>

<ol>
<li>The rule for target foo is looked up and found. To determine if foo is
out-of-date,first each of its dependencies becomes a target to update
itself.</li>
<li>The rule for FORCE is looked up and found. It has no dependencies, but
it does not exist, so it is out-of-date.</li>
<li>There are no commands listed for the target, so the target comes
up-to-date.</li>
<li>All of foo's prerequisites are now up-to-date, foo's out-of-dateness
can be determined.</li>
<li>The ONLY way for a target to be out-of-date is for any of its
prerequisites to be newer than itself (based on timestamp) or the target
not to exist. FORCE does not exist, so there is no timestamp to compare
and now one of the inputs to the decision is unspecified. What should
happen?</li>
</ol>

<p>Based on tests with NetBSD and GNU make the convention is to regard, for
the current run, the target as having a timestamp that is newer than any
target it is a prerequisite for (i.e. force them out-of-date). The
requirement of a target entry with no commands being considered up-to-date
hints at this also.</p>

<p>Also, I think that in the sentence "If there are no commands listed for
the target, [...]" the word "target" should be replaced with "target
entry". As it now stands the sentence could be taken to mean "In the case
there are no commands in the applicable rule <em>or there is no applicable
rule at all</em>, the target shall be treated as up-to-date." This is
because "target" is sometimes used for a single rule entry, sometimes for
the collection of all matching rule entries and and sometimes for the
target name.</p>

<p><b>Case 2: </b>Extension of the previous one:</p>

<pre>
foo: bar
commands...

bar:
commands_that_do_not_create_bar...
</pre>

<p>What now? Nowhere is there a requirement that the executed commands
actually create the target. Nor should there be, because of the convention
of meta-targets "all", "clean", etc. Based on my tests, this works exactly
the same as the previous case.</p>

<p>Of course, in both cases, if foo's commands actually try to use bar, it
will fail and that is an error on the application's side.</p>

<p><b>Case 3: </b>Assuming bar exists and is older than foo:</p>

<pre>
foo: bar
commands...

bar:
commands_that_do_not_update_bar's_modification_time
</pre>

<p>Or even better, assuming bar is newer than foo:</p>

<pre>
foo: bar
commands...

bar:
make_bar's_modification_time_older_than_foo's...
</pre>

<p>It is not necessarily immediately obvious that the timestamps of a
target and its prerequisites are to be checked after the prerequisites have
been brought up-to-date. First it is said: "A target is considered
out-of-date if it is older than any of its prerequisites or if it does not
exist." Later: "After make has ensured that all of the prerequisites of a
target are up-to-date and if the target is out-of-date, [...]" These do
not in my opinion forbid a naive implementation that would check the
out-of-dateness of a target before its prerequisites are updated.</p>

<p><b>Case 4: </b>It is not specified that it should be an error if there
is no rule for target and there is no corresponding file. Neither is it
specified that a target, for which no rule but a corresponding file exists,
is effectively equivalent to</p>

<pre>
target:
</pre>
Desired Action:
<p>If the observed implementation functionality is supposed to be standards
compliant, the text on page 2937, lines 97105-97113 should be changed.
Here is a suggestion, with the changes in <b>bold</b>:</p>

<blockquote><p>The make utility attempts to perform the actions required to
ensure that the specified targets are up-to-date. A target is considered
out-of-date when <b>all of its prerequisites are up-to-date and it is older
than any of them,</b> or if it does not exist. The make utility shall treat
all prerequisites as targets themselves and recursively ensure that they
are up-to-date, processing them in the order in which they appear in the
rule. The make utility shall use the modification times of files to
determine whether the corresponding targets are out-of-date.</p>

<p>After make has ensured that all of the prerequisites of a target are
up-to-date and if the target is out-of-date, the commands associated with
the target entry shall be executed. If there are no commands listed for the
target <b>entry</b>, the target shall be treated as up-to-date. <b>If a
file corresponding to the target does not exist after the target has been
successfully brought up-to-date, the target shall be treated as being newer
than any target it is a prerequisite for.</b></p>

<p><b>When no rule matches a target for which a corresponding file exists,
the target shall be treated as up-to-date. It is an error if there is no
rule for a target that does not have a corresponding
file.</b></p></blockquote>
======================================================================

Issue History
Date Modified Username Field Change
======================================================================
2014-07-08 10:14 jammule New Issue
2014-07-08 10:14 jammule Name => Jarmo Jaakkola
2014-07-08 10:14 jammule Section => make
2014-07-08 10:14 jammule Page Number => 2937
2014-07-08 10:14 jammule Line Number => 97105-97113
======================================================================
Loading...