1
0
Fork 0
mirror of https://github.com/ganelson/inform.git synced 2024-07-17 06:24:24 +03:00
inform7/docs/supervisor-module/3-ib.html
Graham Nelson 1268a0f40e Colonised
2020-04-14 17:56:54 +01:00

390 lines
43 KiB
HTML

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>Incremental Building</title>
<meta name="viewport" content="width=device-width initial-scale=1">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<meta http-equiv="Content-Language" content="en-gb">
<link href="../inweb.css" rel="stylesheet" rev="stylesheet" type="text/css">
</head>
<body>
<nav role="navigation">
<h1><a href="../index.html">
<img src="../docs-src/Figures/Inform.png" height=72">
</a></h1>
<ul><li><a href="../compiler.html">compiler tools</a></li>
<li><a href="../other.html">other tools</a></li>
<li><a href="../extensions.html">extensions and kits</a></li>
<li><a href="../units.html">unit test tools</a></li>
</ul><h2>Compiler Webs</h2><ul>
<li><a href="../inbuild/index.html">inbuild</a></li>
<li><a href="../inform7/index.html">inform7</a></li>
<li><a href="../inter/index.html">inter</a></li>
</ul><h2>Inbuild Modules</h2><ul>
<li><a href="index.html"><span class="selectedlink">supervisor</span></a></li>
</ul><h2>Inform7 Modules</h2><ul>
<li><a href="../core-module/index.html">core</a></li>
<li><a href="../inflections-module/index.html">inflections</a></li>
<li><a href="../linguistics-module/index.html">linguistics</a></li>
<li><a href="../kinds-module/index.html">kinds</a></li>
<li><a href="../if-module/index.html">if</a></li>
<li><a href="../multimedia-module/index.html">multimedia</a></li>
<li><a href="../problems-module/index.html">problems</a></li>
<li><a href="../index-module/index.html">index</a></li>
</ul><h2>Inter Modules</h2><ul>
<li><a href="../bytecode-module/index.html">bytecode</a></li>
<li><a href="../building-module/index.html">building</a></li>
<li><a href="../codegen-module/index.html">codegen</a></li>
</ul><h2>Shared Modules</h2><ul>
<li><a href="../arch-module/index.html">arch</a></li>
<li><a href="../syntax-module/index.html">syntax</a></li>
<li><a href="../words-module/index.html">words</a></li>
<li><a href="../html-module/index.html">html</a></li>
<li><a href="../../../inweb/docs/foundation-module/index.html">foundation</a></li>
</ul>
</nav>
<main role="main">
<!--Weave of 'Incremental Building' generated by 7-->
<ul class="crumbs"><li><a href="../index.html">Home</a></li><li><a href="../compiler.html">Inbuild Modules</a></li><li><a href="index.html">supervisor</a></li><li><a href="index.html#3">Chapter 3: Incremental Builds</a></li><li><b>Incremental Building</b></li></ul><p class="purpose">Deciding what is the least possible amount which needs to be built, in what order, to arrive at a working version of a copy.</p>
<ul class="toc"><li><a href="#SP1">&#167;1. Timestamps</a></li><li><a href="#SP5">&#167;5. Build process</a></li></ul><hr class="tocbar">
<p class="inwebparagraph"><a id="SP1"></a><b>&#167;1. Timestamps. </b>We want to assign a timestamp to every vertex in the graph, whose meaning is
that what it represents has been up-to-date since that time.
</p>
<p class="inwebparagraph">For a file vertex, we take that from the file system's timestamp. For a
copy vertex, we do the same for a copy which is a single file (such as an
extension), but for a copy which is a directory containing a composite of
resources, there's no good way to know. (Perhaps we could scan the files
in it recursively, but then we have to worry about hidden files, symlinks,
and all of that.) Instead, we use the build graph itself to decide; for
example, the timestamp for a kit is the most recent timestamp of any of its
binary Inter files, because those are its build-dependencies.
</p>
<pre class="display">
<span class="identifier">time_t</span><span class="plain"> </span><span class="functiontext">IncrementalBuild::timestamp<button class="popup" onclick="togglePopup('usagePopup133')">...<span class="popuptext" id="usagePopup133">Usage of <b>IncrementalBuild::timestamp</b>:<br><a href="#SP3">&#167;3</a>, <a href="#SP4">&#167;4</a>, <a href="#SP7_1_3_1">&#167;7.1.3.1</a></span></button></span><span class="plain">(</span><span class="reserved">build_vertex</span><span class="plain"> *</span><span class="identifier">V</span><span class="plain">) {</span>
<span class="reserved">switch</span><span class="plain"> (</span><span class="identifier">V</span><span class="plain">-&gt;</span><span class="identifier">type</span><span class="plain">) {</span>
<span class="reserved">case</span><span class="plain"> </span><span class="identifier">FILE_VERTEX:</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">Filenames::timestamp</span><span class="plain">(</span><span class="identifier">V</span><span class="plain">-&gt;</span><span class="element">as_file</span><span class="plain">);</span>
<span class="reserved">case</span><span class="plain"> </span><span class="identifier">COPY_VERTEX:</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">V</span><span class="plain">-&gt;</span><span class="element">as_copy</span><span class="plain">-&gt;</span><span class="element">location_if_file</span><span class="plain">)</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">Filenames::timestamp</span><span class="plain">(</span><span class="identifier">V</span><span class="plain">-&gt;</span><span class="element">as_copy</span><span class="plain">-&gt;</span><span class="element">location_if_file</span><span class="plain">);</span>
<span class="reserved">return</span><span class="plain"> </span><span class="functiontext"><a href="#SP3">IncrementalBuild::time_of_latest_build_dependency</a></span><span class="plain">(</span><span class="identifier">V</span><span class="plain">);</span>
<span class="identifier">default:</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">Platform::never_time</span><span class="plain">();</span>
<span class="plain">}</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="inwebparagraph"><a id="SP2"></a><b>&#167;2. </b>The following compares two times: it returns 1 if <code class="display"><span class="extract">t1</span></code> is later, -1 if
<code class="display"><span class="extract">t2</span></code> is later, and 0 if they are identical.
</p>
<p class="inwebparagraph">Note that we never apply the C standard library function <code class="display"><span class="extract">difftime</span></code> in
the case of the never-time, which we consider to be before all other times.
(On most platforms it will be the C epoch of 1970, and <code class="display"><span class="extract">difftime</span></code> alone
would be fine, but we're being careful.)
</p>
<pre class="display">
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">IncrementalBuild::timecmp<button class="popup" onclick="togglePopup('usagePopup134')">...<span class="popuptext" id="usagePopup134">Usage of <b>IncrementalBuild::timecmp</b>:<br><a href="#SP3">&#167;3</a>, <a href="#SP4">&#167;4</a>, <a href="#SP7_1_3_1">&#167;7.1.3.1</a></span></button></span><span class="plain">(</span><span class="identifier">time_t</span><span class="plain"> </span><span class="identifier">t1</span><span class="plain">, </span><span class="identifier">time_t</span><span class="plain"> </span><span class="identifier">t2</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">t1</span><span class="plain"> == </span><span class="identifier">Platform::never_time</span><span class="plain">()) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">t2</span><span class="plain"> == </span><span class="identifier">Platform::never_time</span><span class="plain">()) </span><span class="reserved">return</span><span class="plain"> </span><span class="constant">0</span><span class="plain">;</span>
<span class="reserved">return</span><span class="plain"> -1;</span>
<span class="plain">}</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">t2</span><span class="plain"> == </span><span class="identifier">Platform::never_time</span><span class="plain">()) {</span>
<span class="reserved">return</span><span class="plain"> </span><span class="constant">1</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">t1</span><span class="plain"> == </span><span class="identifier">t2</span><span class="plain">) </span><span class="reserved">return</span><span class="plain"> </span><span class="constant">0</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">difftime</span><span class="plain">(</span><span class="identifier">t1</span><span class="plain">, </span><span class="identifier">t2</span><span class="plain">) &gt; </span><span class="constant">0</span><span class="plain">) </span><span class="reserved">return</span><span class="plain"> </span><span class="constant">1</span><span class="plain">;</span>
<span class="reserved">return</span><span class="plain"> -1;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="inwebparagraph"><a id="SP3"></a><b>&#167;3. </b>We then take the latest timestamp of any build dependency:
</p>
<pre class="display">
<span class="identifier">time_t</span><span class="plain"> </span><span class="functiontext">IncrementalBuild::time_of_latest_build_dependency<button class="popup" onclick="togglePopup('usagePopup135')">...<span class="popuptext" id="usagePopup135">Usage of <b>IncrementalBuild::time_of_latest_build_dependency</b>:<br><a href="#SP1">&#167;1</a>, <a href="#SP7_1_3_1">&#167;7.1.3.1</a></span></button></span><span class="plain">(</span><span class="reserved">build_vertex</span><span class="plain"> *</span><span class="identifier">V</span><span class="plain">) {</span>
<span class="identifier">time_t</span><span class="plain"> </span><span class="identifier">latest</span><span class="plain"> = </span><span class="identifier">Platform::never_time</span><span class="plain">();</span>
<span class="reserved">build_vertex</span><span class="plain"> *</span><span class="identifier">W</span><span class="plain">;</span>
<span class="identifier">LOOP_OVER_LINKED_LIST</span><span class="plain">(</span><span class="identifier">W</span><span class="plain">, </span><span class="reserved">build_vertex</span><span class="plain">, </span><span class="identifier">V</span><span class="plain">-&gt;</span><span class="element">build_edges</span><span class="plain">) {</span>
<span class="identifier">time_t</span><span class="plain"> </span><span class="identifier">t</span><span class="plain"> = </span><span class="functiontext"><a href="#SP1">IncrementalBuild::timestamp</a></span><span class="plain">(</span><span class="identifier">W</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext"><a href="#SP2">IncrementalBuild::timecmp</a></span><span class="plain">(</span><span class="identifier">t</span><span class="plain">, </span><span class="identifier">latest</span><span class="plain">) &gt; </span><span class="constant">0</span><span class="plain">) </span><span class="identifier">latest</span><span class="plain"> = </span><span class="identifier">t</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">latest</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="inwebparagraph"><a id="SP4"></a><b>&#167;4. </b>And of any use dependency:
</p>
<pre class="display">
<span class="identifier">time_t</span><span class="plain"> </span><span class="functiontext">IncrementalBuild::time_of_latest_use_dependency<button class="popup" onclick="togglePopup('usagePopup136')">...<span class="popuptext" id="usagePopup136">Usage of <b>IncrementalBuild::time_of_latest_use_dependency</b>:<br><a href="#SP7_1_3_1">&#167;7.1.3.1</a></span></button></span><span class="plain">(</span><span class="reserved">build_vertex</span><span class="plain"> *</span><span class="identifier">V</span><span class="plain">) {</span>
<span class="identifier">time_t</span><span class="plain"> </span><span class="identifier">latest</span><span class="plain"> = </span><span class="identifier">Platform::never_time</span><span class="plain">();</span>
<span class="reserved">build_vertex</span><span class="plain"> *</span><span class="identifier">W</span><span class="plain">;</span>
<span class="identifier">LOOP_OVER_LINKED_LIST</span><span class="plain">(</span><span class="identifier">W</span><span class="plain">, </span><span class="reserved">build_vertex</span><span class="plain">, </span><span class="identifier">V</span><span class="plain">-&gt;</span><span class="element">use_edges</span><span class="plain">) {</span>
<span class="identifier">time_t</span><span class="plain"> </span><span class="identifier">t</span><span class="plain"> = </span><span class="functiontext"><a href="#SP1">IncrementalBuild::timestamp</a></span><span class="plain">(</span><span class="identifier">W</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext"><a href="#SP2">IncrementalBuild::timecmp</a></span><span class="plain">(</span><span class="identifier">t</span><span class="plain">, </span><span class="identifier">latest</span><span class="plain">) &gt; </span><span class="constant">0</span><span class="plain">) </span><span class="identifier">latest</span><span class="plain"> = </span><span class="identifier">t</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">latest</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="inwebparagraph"><a id="SP5"></a><b>&#167;5. Build process. </b>This is a recursive process, beginning at the node representing what we want
to build. As we recurse, we pass a bitmap of the following:
</p>
<pre class="definitions">
<span class="definitionkeyword">define</span> <span class="constant">BUILD_DEPENDENCIES_MATTER_GB</span><span class="plain"> </span><span class="constant">1</span><span class="plain"> </span><span class="comment"> We will need all your build dependencies too</span>
<span class="definitionkeyword">define</span> <span class="constant">USE_DEPENDENCIES_MATTER_GB</span><span class="plain"> </span><span class="constant">2</span><span class="plain"> </span><span class="comment"> We will need all your use dependencies too</span>
<span class="definitionkeyword">define</span> <span class="constant">IGNORE_TIMESTAMPS_GB</span><span class="plain"> </span><span class="constant">4</span><span class="plain"> </span><span class="comment"> Don't be incremental: trust nothing, rebuild everything</span>
</pre>
<pre class="display">
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">IncrementalBuild::build<button class="popup" onclick="togglePopup('usagePopup137')">...<span class="popuptext" id="usagePopup137">Usage of <b>IncrementalBuild::build</b>:<br>Copies - <a href="2-cps.html#SP10">&#167;10</a></span></button></span><span class="plain">(</span><span class="identifier">OUTPUT_STREAM</span><span class="plain">, </span><span class="reserved">build_vertex</span><span class="plain"> *</span><span class="identifier">V</span><span class="plain">, </span><span class="reserved">build_methodology</span><span class="plain"> *</span><span class="identifier">meth</span><span class="plain">) {</span>
<span class="reserved">return</span><span class="plain"> </span><span class="functiontext"><a href="#SP7">IncrementalBuild::begin_recursion</a></span><span class="plain">(</span><span class="identifier">OUT</span><span class="plain">,</span>
<span class="constant">BUILD_DEPENDENCIES_MATTER_GB</span><span class="plain">, </span><span class="identifier">V</span><span class="plain">, </span><span class="identifier">meth</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">IncrementalBuild::rebuild<button class="popup" onclick="togglePopup('usagePopup138')">...<span class="popuptext" id="usagePopup138">Usage of <b>IncrementalBuild::rebuild</b>:<br>Copies - <a href="2-cps.html#SP10">&#167;10</a></span></button></span><span class="plain">(</span><span class="identifier">OUTPUT_STREAM</span><span class="plain">, </span><span class="reserved">build_vertex</span><span class="plain"> *</span><span class="identifier">V</span><span class="plain">, </span><span class="reserved">build_methodology</span><span class="plain"> *</span><span class="identifier">meth</span><span class="plain">) {</span>
<span class="reserved">return</span><span class="plain"> </span><span class="functiontext"><a href="#SP7">IncrementalBuild::begin_recursion</a></span><span class="plain">(</span><span class="identifier">OUT</span><span class="plain">,</span>
<span class="constant">BUILD_DEPENDENCIES_MATTER_GB</span><span class="plain"> + </span><span class="constant">IGNORE_TIMESTAMPS_GB</span><span class="plain">, </span><span class="identifier">V</span><span class="plain">, </span><span class="identifier">meth</span><span class="plain">);</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="inwebparagraph"><a id="SP6"></a><b>&#167;6. </b>This is called when Inbuild's <code class="display"><span class="extract">-trace</span></code> switch is set at the command line.
</p>
<pre class="display">
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">trace_ibg</span><span class="plain"> = </span><span class="identifier">FALSE</span><span class="plain">;</span>
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">IncrementalBuild::enable_trace<button class="popup" onclick="togglePopup('usagePopup139')">...<span class="popuptext" id="usagePopup139">Usage of <b>IncrementalBuild::enable_trace</b>:<br>none</span></button></span><span class="plain">(</span><span class="reserved">void</span><span class="plain">) {</span>
<span class="identifier">trace_ibg</span><span class="plain"> = </span><span class="identifier">TRUE</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="inwebparagraph"><a id="SP7"></a><b>&#167;7. </b>We want to be very sure that this recursion does not lock up, or perform
unnecessary work by performing the same node twice. To do this we apply the
<code class="display"><span class="extract">built</span></code> flag to a node when it has been built; but to make this is not left
over from last time around, we only regard it when the <code class="display"><span class="extract">last_built_in_generation</span></code> count
for the node is set to the current "generation", a unique number incremented
for each time we recurse.
</p>
<pre class="display">
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">no_build_generations</span><span class="plain"> = </span><span class="constant">0</span><span class="plain">;</span>
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">IncrementalBuild::begin_recursion<button class="popup" onclick="togglePopup('usagePopup140')">...<span class="popuptext" id="usagePopup140">Usage of <b>IncrementalBuild::begin_recursion</b>:<br><a href="#SP5">&#167;5</a></span></button></span><span class="plain">(</span><span class="identifier">OUTPUT_STREAM</span><span class="plain">, </span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">gb</span><span class="plain">, </span><span class="reserved">build_vertex</span><span class="plain"> *</span><span class="identifier">V</span><span class="plain">,</span>
<span class="reserved">build_methodology</span><span class="plain"> *</span><span class="identifier">BM</span><span class="plain">) {</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">changes</span><span class="plain"> = </span><span class="constant">0</span><span class="plain">;</span>
<span class="identifier">text_stream</span><span class="plain"> *</span><span class="identifier">T</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">trace_ibg</span><span class="plain">) </span><span class="identifier">T</span><span class="plain"> = </span><span class="identifier">STDOUT</span><span class="plain">;</span>
<span class="identifier">no_build_generations</span><span class="plain">++;</span>
<span class="identifier">WRITE_TO</span><span class="plain">(</span><span class="identifier">T</span><span class="plain">, </span><span class="string">"Incremental build %d:\n"</span><span class="plain">, </span><span class="identifier">no_build_generations</span><span class="plain">);</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">rv</span><span class="plain"> = </span><span class="functiontext"><a href="#SP7">IncrementalBuild::recurse</a></span><span class="plain">(</span><span class="identifier">OUT</span><span class="plain">, </span><span class="identifier">T</span><span class="plain">, </span><span class="identifier">gb</span><span class="plain">, </span><span class="identifier">V</span><span class="plain">, </span><span class="identifier">BM</span><span class="plain">, &amp;</span><span class="identifier">changes</span><span class="plain">, </span><span class="identifier">no_build_generations</span><span class="plain">);</span>
<span class="identifier">WRITE_TO</span><span class="plain">(</span><span class="identifier">T</span><span class="plain">, </span><span class="string">"%d change(s)\n"</span><span class="plain">, </span><span class="identifier">changes</span><span class="plain">);</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">rv</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">IncrementalBuild::recurse<button class="popup" onclick="togglePopup('usagePopup141')">...<span class="popuptext" id="usagePopup141">Usage of <b>IncrementalBuild::recurse</b>:<br><a href="#SP7_1_1">&#167;7.1.1</a>, <a href="#SP7_1_2">&#167;7.1.2</a></span></button></span><span class="plain">(</span><span class="identifier">OUTPUT_STREAM</span><span class="plain">, </span><span class="identifier">text_stream</span><span class="plain"> *</span><span class="identifier">T</span><span class="plain">, </span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">gb</span><span class="plain">, </span><span class="reserved">build_vertex</span><span class="plain"> *</span><span class="identifier">V</span><span class="plain">,</span>
<span class="reserved">build_methodology</span><span class="plain"> *</span><span class="identifier">BM</span><span class="plain">, </span><span class="reserved">int</span><span class="plain"> *</span><span class="identifier">changes</span><span class="plain">, </span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">generation</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">T</span><span class="plain">) {</span>
<span class="identifier">WRITE_TO</span><span class="plain">(</span><span class="identifier">T</span><span class="plain">, </span><span class="string">"Visit %c%c%c: "</span><span class="plain">,</span>
<span class="plain">(</span><span class="identifier">gb</span><span class="plain"> &amp; </span><span class="constant">BUILD_DEPENDENCIES_MATTER_GB</span><span class="plain">)?</span><span class="character">'b'</span><span class="plain">:</span><span class="character">'.'</span><span class="plain">,</span>
<span class="plain">(</span><span class="identifier">gb</span><span class="plain"> &amp; </span><span class="constant">USE_DEPENDENCIES_MATTER_GB</span><span class="plain">)?</span><span class="character">'u'</span><span class="plain">:</span><span class="character">'.'</span><span class="plain">,</span>
<span class="plain">(</span><span class="identifier">gb</span><span class="plain"> &amp; </span><span class="constant">IGNORE_TIMESTAMPS_GB</span><span class="plain">)?</span><span class="character">'i'</span><span class="plain">:</span><span class="character">'.'</span><span class="plain">);</span>
<span class="functiontext"><a href="3-bg.html#SP6">Graphs::describe</a></span><span class="plain">(</span><span class="identifier">T</span><span class="plain">, </span><span class="identifier">V</span><span class="plain">, </span><span class="identifier">FALSE</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">V</span><span class="plain">-&gt;</span><span class="element">last_built_in_generation</span><span class="plain"> == </span><span class="identifier">generation</span><span class="plain">) </span><span class="reserved">return</span><span class="plain"> </span><span class="identifier">V</span><span class="plain">-&gt;</span><span class="element">build_result</span><span class="plain">;</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">rv</span><span class="plain"> = </span><span class="identifier">TRUE</span><span class="plain">;</span>
&lt;<span class="cwebmacro">Build this node if necessary, setting rv to its success or failure</span> <span class="cwebmacronumber">7.1</span>&gt;<span class="plain">;</span>
<span class="identifier">V</span><span class="plain">-&gt;</span><span class="element">build_result</span><span class="plain"> = </span><span class="identifier">rv</span><span class="plain">;</span>
<span class="identifier">V</span><span class="plain">-&gt;</span><span class="element">last_built_in_generation</span><span class="plain"> = </span><span class="identifier">generation</span><span class="plain">;</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">rv</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="inwebparagraph"><a id="SP7_1"></a><b>&#167;7.1. </b>In everything which follows, <code class="display"><span class="extract">rv</span></code> (prosaically, this stands only for "return
value") remains <code class="display"><span class="extract">TRUE</span></code> until the first active step fails, at which point no
other active steps are ever taken, nor are any recursions made. In effect,
the first failure halts the process.
</p>
<p class="inwebparagraph">We are recursing depth-first, that is, we build the things needed to build
<code class="display"><span class="extract">V</span></code> before we build <code class="display"><span class="extract">V</span></code> itself.
</p>
<p class="inwebparagraph">A point of difference between this algorithm and <code class="display"><span class="extract">make</span></code> is that we do not
halt with an error if a node has no way to be built. This is because the
graphs are here are built by Inbuild itself, not by a possibly erroneous
makefile whose author has forgotten something and whose intentions are not
clear. Here, if a node has no build script attached, it must be because it
needs no action taken.
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Build this node if necessary, setting rv to its success or failure</span> <span class="cwebmacronumber">7.1</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">T</span><span class="plain">) </span><span class="identifier">STREAM_INDENT</span><span class="plain">(</span><span class="identifier">T</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">gb</span><span class="plain"> &amp; </span><span class="constant">BUILD_DEPENDENCIES_MATTER_GB</span><span class="plain">) </span>&lt;<span class="cwebmacro">Build the build dependencies of the node</span> <span class="cwebmacronumber">7.1.1</span>&gt;<span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">gb</span><span class="plain"> &amp; </span><span class="constant">USE_DEPENDENCIES_MATTER_GB</span><span class="plain">) </span>&lt;<span class="cwebmacro">Build the use dependencies of the node</span> <span class="cwebmacronumber">7.1.2</span>&gt;<span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">T</span><span class="plain">) </span><span class="identifier">STREAM_OUTDENT</span><span class="plain">(</span><span class="identifier">T</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">rv</span><span class="plain">) &amp;&amp; (</span><span class="functiontext"><a href="3-bg.html#SP5">Graphs::can_be_built</a></span><span class="plain">(</span><span class="identifier">V</span><span class="plain">))) </span>&lt;<span class="cwebmacro">Build the node itself, if necessary</span> <span class="cwebmacronumber">7.1.3</span>&gt;<span class="plain">;</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP7">&#167;7</a>.</p>
<p class="inwebparagraph"><a id="SP7_1_1"></a><b>&#167;7.1.1. </b>Suppose V needs W (for whatever reason), and that W can only be used with X.
It follows that we will have to build X as well as W, since the process of
building V is itself a use of W, and therefore of X. So we always enable the
<code class="display"><span class="extract">USE_DEPENDENCIES_MATTER_GB</span></code> bit when recursing through an edge.
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Build the build dependencies of the node</span> <span class="cwebmacronumber">7.1.1</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">build_vertex</span><span class="plain"> *</span><span class="identifier">W</span><span class="plain">;</span>
<span class="identifier">LOOP_OVER_LINKED_LIST</span><span class="plain">(</span><span class="identifier">W</span><span class="plain">, </span><span class="reserved">build_vertex</span><span class="plain">, </span><span class="identifier">V</span><span class="plain">-&gt;</span><span class="element">build_edges</span><span class="plain">)</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">rv</span><span class="plain">)</span>
<span class="identifier">rv</span><span class="plain"> = </span><span class="functiontext"><a href="#SP7">IncrementalBuild::recurse</a></span><span class="plain">(</span><span class="identifier">OUT</span><span class="plain">, </span><span class="identifier">T</span><span class="plain">,</span>
<span class="identifier">gb</span><span class="plain"> | </span><span class="constant">USE_DEPENDENCIES_MATTER_GB</span><span class="plain">, </span><span class="identifier">W</span><span class="plain">, </span><span class="identifier">BM</span><span class="plain">, </span><span class="identifier">changes</span><span class="plain">, </span><span class="identifier">generation</span><span class="plain">);</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP7_1">&#167;7.1</a>.</p>
<p class="inwebparagraph"><a id="SP7_1_2"></a><b>&#167;7.1.2. </b><code class="display">
&lt;<span class="cwebmacrodefn">Build the use dependencies of the node</span> <span class="cwebmacronumber">7.1.2</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">build_vertex</span><span class="plain"> *</span><span class="identifier">W</span><span class="plain">;</span>
<span class="identifier">LOOP_OVER_LINKED_LIST</span><span class="plain">(</span><span class="identifier">W</span><span class="plain">, </span><span class="reserved">build_vertex</span><span class="plain">, </span><span class="identifier">V</span><span class="plain">-&gt;</span><span class="element">use_edges</span><span class="plain">)</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">rv</span><span class="plain">)</span>
<span class="identifier">rv</span><span class="plain"> = </span><span class="functiontext"><a href="#SP7">IncrementalBuild::recurse</a></span><span class="plain">(</span><span class="identifier">OUT</span><span class="plain">, </span><span class="identifier">T</span><span class="plain">,</span>
<span class="identifier">gb</span><span class="plain"> | </span><span class="constant">USE_DEPENDENCIES_MATTER_GB</span><span class="plain">, </span><span class="identifier">W</span><span class="plain">, </span><span class="identifier">BM</span><span class="plain">, </span><span class="identifier">changes</span><span class="plain">, </span><span class="identifier">generation</span><span class="plain">);</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP7_1">&#167;7.1</a>.</p>
<p class="inwebparagraph"><a id="SP7_1_3"></a><b>&#167;7.1.3. </b>Now for the node <code class="display"><span class="extract">V</span></code> itself.
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Build the node itself, if necessary</span> <span class="cwebmacronumber">7.1.3</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">needs_building</span><span class="plain"> = </span><span class="identifier">FALSE</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">gb</span><span class="plain"> &amp; </span><span class="constant">IGNORE_TIMESTAMPS_GB</span><span class="plain">) || (</span><span class="identifier">V</span><span class="plain">-&gt;</span><span class="element">always_build_this</span><span class="plain">)) </span><span class="identifier">needs_building</span><span class="plain"> = </span><span class="identifier">TRUE</span><span class="plain">;</span>
<span class="reserved">else</span><span class="plain"> </span>&lt;<span class="cwebmacro">Decide based on timestamps</span> <span class="cwebmacronumber">7.1.3.1</span>&gt;<span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">needs_building</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">T</span><span class="plain">) { </span><span class="identifier">WRITE_TO</span><span class="plain">(</span><span class="identifier">T</span><span class="plain">, </span><span class="string">"Build: "</span><span class="plain">); </span><span class="functiontext"><a href="3-bg.html#SP6">Graphs::describe</a></span><span class="plain">(</span><span class="identifier">T</span><span class="plain">, </span><span class="identifier">V</span><span class="plain">, </span><span class="identifier">FALSE</span><span class="plain">); }</span>
<span class="plain">(*</span><span class="identifier">changes</span><span class="plain">)++;</span>
<span class="identifier">rv</span><span class="plain"> = </span><span class="functiontext"><a href="3-bs.html#SP2">BuildScripts::execute</a></span><span class="plain">(</span><span class="identifier">V</span><span class="plain">, </span><span class="identifier">V</span><span class="plain">-&gt;</span><span class="identifier">script</span><span class="plain">, </span><span class="identifier">BM</span><span class="plain">);</span>
<span class="plain">} </span><span class="reserved">else</span><span class="plain"> {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">T</span><span class="plain">) { </span><span class="identifier">WRITE_TO</span><span class="plain">(</span><span class="identifier">T</span><span class="plain">, </span><span class="string">"No build\n"</span><span class="plain">); }</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP7_1">&#167;7.1</a>.</p>
<p class="inwebparagraph"><a id="SP7_1_3_1"></a><b>&#167;7.1.3.1. </b>This is where the incremental promise is finally kept. If the timestamp of
<code class="display"><span class="extract">V</span></code> is definitely before later than that of everything it depends on, then
it would be redundant to recreate it.
</p>
<p class="inwebparagraph">Note that equal timestamps force rebuilding. File timestamping is quite coarse
on some systems, so equal timeatamps might only mean that the two files were
created during the same second.
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Decide based on timestamps</span> <span class="cwebmacronumber">7.1.3.1</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="identifier">time_t</span><span class="plain"> </span><span class="identifier">last_up_to_date_at</span><span class="plain"> = </span><span class="functiontext"><a href="#SP1">IncrementalBuild::timestamp</a></span><span class="plain">(</span><span class="identifier">V</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">last_up_to_date_at</span><span class="plain"> == </span><span class="identifier">Platform::never_time</span><span class="plain">())</span>
<span class="identifier">needs_building</span><span class="plain"> = </span><span class="identifier">TRUE</span><span class="plain">;</span>
<span class="reserved">else</span><span class="plain"> {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">T</span><span class="plain">) { </span><span class="identifier">WRITE_TO</span><span class="plain">(</span><span class="identifier">T</span><span class="plain">, </span><span class="string">"Last built at: %08x\n"</span><span class="plain">, </span><span class="identifier">last_up_to_date_at</span><span class="plain">); }</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">gb</span><span class="plain"> &amp; </span><span class="constant">BUILD_DEPENDENCIES_MATTER_GB</span><span class="plain">) {</span>
<span class="identifier">time_t</span><span class="plain"> </span><span class="identifier">t</span><span class="plain"> = </span><span class="functiontext"><a href="#SP3">IncrementalBuild::time_of_latest_build_dependency</a></span><span class="plain">(</span><span class="identifier">V</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">T</span><span class="plain">) { </span><span class="identifier">WRITE_TO</span><span class="plain">(</span><span class="identifier">T</span><span class="plain">, </span><span class="string">"Most recent build dependency: %08x\n"</span><span class="plain">, </span><span class="identifier">t</span><span class="plain">); }</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext"><a href="#SP2">IncrementalBuild::timecmp</a></span><span class="plain">(</span><span class="identifier">t</span><span class="plain">, </span><span class="identifier">last_up_to_date_at</span><span class="plain">) &gt;= </span><span class="constant">0</span><span class="plain">)</span>
<span class="identifier">needs_building</span><span class="plain"> = </span><span class="identifier">TRUE</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">gb</span><span class="plain"> &amp; </span><span class="constant">USE_DEPENDENCIES_MATTER_GB</span><span class="plain">) {</span>
<span class="identifier">time_t</span><span class="plain"> </span><span class="identifier">t</span><span class="plain"> = </span><span class="functiontext"><a href="#SP4">IncrementalBuild::time_of_latest_use_dependency</a></span><span class="plain">(</span><span class="identifier">V</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">T</span><span class="plain">) { </span><span class="identifier">WRITE_TO</span><span class="plain">(</span><span class="identifier">T</span><span class="plain">, </span><span class="string">"Most recent use dependency: %08x\n"</span><span class="plain">, </span><span class="identifier">t</span><span class="plain">); }</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext"><a href="#SP2">IncrementalBuild::timecmp</a></span><span class="plain">(</span><span class="identifier">t</span><span class="plain">, </span><span class="identifier">last_up_to_date_at</span><span class="plain">) &gt;= </span><span class="constant">0</span><span class="plain">)</span>
<span class="identifier">needs_building</span><span class="plain"> = </span><span class="identifier">TRUE</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP7_1_3">&#167;7.1.3</a>.</p>
<hr class="tocbar">
<ul class="toc"><li><a href="3-bm.html">Back to 'Build Methodology'</a></li><li><a href="3-bs.html">Continue with 'Build Scripts'</a></li></ul><hr class="tocbar">
<!--End of weave-->
<script>
function togglePopup(material_id) {
var popup = document.getElementById(material_id);
popup.classList.toggle("show");
}
</script>
<link href="Popups.css" rel="stylesheet" rev="stylesheet" type="text/css">
</main>
</body>
</html>