<div dir="ltr">Hi,<div><br></div><div>I have a code generator that transforms html (and html-related files like css) to cpp.</div><div><br></div><div>The source files are located in some nested directory tree, and the generator is in its top level (named pbuilder).</div><div><br></div><div>The code generator produces its artifacts in the source directory. I can't control it (it's a closed binary executable).</div><div><br></div><div>I'd like to compare timestamps of the input and output file, and generate iff the input is newer.</div><div><br></div><div>This is what I have so far:</div><div><br></div><div>
<pre style="margin-top:0px;margin-bottom:0px"><span style="color:#808000">import</span><span style="color:#c0c0c0"> </span>qbs<span style="color:#c0c0c0"> </span>1.0</pre>
<pre style="margin-top:0px;margin-bottom:0px"><span style="color:#808000">import</span><span style="color:#c0c0c0"> </span>qbs.FileInfo</pre>
<pre style="margin-top:0px;margin-bottom:0px"><br></pre>
<pre style="margin-top:0px;margin-bottom:0px"><span style="color:#800080">Product</span><span style="color:#c0c0c0"> </span>{</pre>
<pre style="margin-top:0px;margin-bottom:0px"><span style="color:#c0c0c0">    </span><span style="color:#800000">type</span>:<span style="color:#c0c0c0"> </span><span style="color:#008000">"html-cpp"</span></pre>
<pre style="margin-top:0px;margin-bottom:0px"><br></pre>
<pre style="margin-top:0px;margin-bottom:0px"><span style="color:#c0c0c0">    </span><span style="color:#800080">Group</span><span style="color:#c0c0c0"> </span>{</pre>
<pre style="margin-top:0px;margin-bottom:0px"><span style="color:#c0c0c0">        </span><span style="color:#800000">name</span>:<span style="color:#c0c0c0"> </span><span style="color:#008000">"Input</span><span style="color:#c0c0c0"> </span><span style="color:#008000">Files"</span></pre>
<pre style="margin-top:0px;margin-bottom:0px"><span style="color:#c0c0c0">        </span><span style="color:#800000">files</span>:<span style="color:#c0c0c0"> </span><span style="color:#008000">"**/*.htm*"</span></pre>
<pre style="margin-top:0px;margin-bottom:0px"><span style="color:#c0c0c0">        </span><span style="color:#800000">fileTags</span>:<span style="color:#c0c0c0"> </span>[<span style="color:#008000">"html"</span>]</pre>
<pre style="margin-top:0px;margin-bottom:0px"><span style="color:#c0c0c0">    </span>}</pre>
<pre style="margin-top:0px;margin-bottom:0px"><br></pre>
<pre style="margin-top:0px;margin-bottom:0px"><span style="color:#c0c0c0">    </span><span style="color:#800080">Rule</span><span style="color:#c0c0c0"> </span>{</pre>
<pre style="margin-top:0px;margin-bottom:0px"><span style="color:#c0c0c0">        </span><span style="color:#800000">inputs</span>:<span style="color:#c0c0c0"> </span>[<span style="color:#008000">"html"</span>]</pre>
<pre style="margin-top:0px;margin-bottom:0px"><span style="color:#c0c0c0">        </span><span style="color:#800080">Artifact</span><span style="color:#c0c0c0"> </span>{</pre>
<pre style="margin-top:0px;margin-bottom:0px"><span style="color:#c0c0c0">            </span><span style="color:#800000">fileTags</span>:<span style="color:#c0c0c0"> </span>[<span style="color:#008000">"html-cpp"</span>]</pre>
<pre style="margin-top:0px;margin-bottom:0px"><span style="color:#c0c0c0">            </span><span style="color:#800000">filePath</span>:<span style="color:#c0c0c0"> </span>FileInfo.path(input.filePath)<span style="color:#c0c0c0"> </span>+<span style="color:#c0c0c0"> </span><span style="color:#008000">'/'</span><span style="color:#c0c0c0"> </span>+<span style="color:#c0c0c0"> </span>FileInfo.baseName(input.filePath)<span style="color:#c0c0c0"> </span>+<span style="color:#c0c0c0"> </span><span style="color:#008000">".cpp"</span></pre>
<pre style="margin-top:0px;margin-bottom:0px"><span style="color:#c0c0c0">        </span>}</pre>
<pre style="margin-top:0px;margin-bottom:0px"><span style="color:#c0c0c0">        </span><span style="color:#800000">prepare</span>:<span style="color:#c0c0c0"> </span>{</pre>
<pre style="margin-top:0px;margin-bottom:0px"><span style="color:#c0c0c0">            </span><span style="color:#808000">var</span><span style="color:#c0c0c0"> </span><span style="font-style:italic;color:#2985c7">pbuilderPath</span><span style="color:#c0c0c0"> </span>=<span style="color:#c0c0c0"> </span>project.path<span style="color:#c0c0c0"> </span>+<span style="color:#c0c0c0"> </span><span style="color:#008000">"/pbuilder"</span>;</pre>
<pre style="margin-top:0px;margin-bottom:0px"><span style="color:#c0c0c0">            </span><span style="color:#808000">var</span><span style="color:#c0c0c0"> </span><span style="font-style:italic;color:#2985c7">cmd</span><span style="color:#c0c0c0"> </span>=<span style="color:#c0c0c0"> </span><span style="color:#808000">new</span><span style="color:#c0c0c0"> </span>Command(<span style="font-style:italic;color:#2985c7">pbuilderPath</span>,<span style="color:#c0c0c0"> </span>input.filePath);</pre>
<pre style="margin-top:0px;margin-bottom:0px"><span style="color:#c0c0c0">            </span><span style="font-style:italic;color:#2985c7">cmd</span>.description<span style="color:#c0c0c0"> </span>=<span style="color:#c0c0c0"> </span><span style="color:#008000">'pbuilding</span><span style="color:#c0c0c0"> </span><span style="color:#008000">'</span><span style="color:#c0c0c0"> </span>+<span style="color:#c0c0c0"> </span>input.fileName;</pre>
<pre style="margin-top:0px;margin-bottom:0px"><span style="color:#c0c0c0">            </span><span style="font-style:italic;color:#2985c7">cmd</span>.highlight<span style="color:#c0c0c0"> </span>=<span style="color:#c0c0c0"> </span><span style="color:#008000">'compiler'</span>;</pre>
<pre style="margin-top:0px;margin-bottom:0px"><span style="color:#c0c0c0">            </span><span style="color:#808000">return</span><span style="color:#c0c0c0"> </span><span style="font-style:italic;color:#2985c7">cmd</span>;</pre>
<pre style="margin-top:0px;margin-bottom:0px"><span style="color:#c0c0c0">        </span>}</pre>
<pre style="margin-top:0px;margin-bottom:0px"><span style="color:#c0c0c0">    </span>}</pre>
<pre style="margin-top:0px;margin-bottom:0px">}</pre>
<pre style="margin-top:0px;margin-bottom:0px"><br></pre><pre style="margin-top:0px;margin-bottom:0px"><font face="arial, helvetica, sans-serif">When I execute it for the first time, it generates all the files. Later, as long as I don't modify the qbs file or delete the build graph, only source files that were modified are regenerated, which is good.</font></pre><pre style="margin-top:0px;margin-bottom:0px"><font face="arial, helvetica, sans-serif"><br></font></pre><pre style="margin-top:0px;margin-bottom:0px"><font face="arial, helvetica, sans-serif">The problems I'm facing are:</font></pre><pre style="margin-top:0px;margin-bottom:0px"><ul><li><span style="font-family:arial,helvetica,sans-serif">If I delete the output file it is not regenerated (unless I delete the build graph, which regenerates all the files)</span><br></li><li><span style="font-family:arial,helvetica,sans-serif">If the source file is modified, but the target file has a newer date (e.g. pbuilder was invoked from the shell), it is still regenerated.</span></li><li><span style="font-family:arial,helvetica,sans-serif">On the first run, I'd like to avoid regenerating up-to-date targets. I can live with that though.</span></li><li><span style="font-family:arial,helvetica,sans-serif">In my example, I simplified the generator's output. The generator actually produces 2 files: input.c and input_v.cpp. After it finishes, I need to rename input.c -> input.cpp (overwriting the existing one), and delete input_v.cpp.</span></li></ul><div><font face="arial, helvetica, sans-serif">I'm currently using a rather ugly Makefile for this, which works quite well, but is hard to maintain.</font></div><div><font face="arial, helvetica, sans-serif"><br></font></div><div><font face="arial, helvetica, sans-serif">How can this be done correctly?</font></div><div><font face="arial, helvetica, sans-serif"><br></font></div><div><font face="arial, helvetica, sans-serif">- Orgad</font></div></pre></div></div>