<div dir="ltr">It would also be nice to have something like &quot;rebuild_hash&quot;: &quot;opaque string&quot;, such that if the hash is the same as a prior run, downstream nodes don&#39;t need to be rebuilt. This would allow compilers to stuff information in the BMI that shouldn&#39;t propagate rebuilds, such as comments that may show up in warnings, but can&#39;t effect the compiled output. It may even be worth having that as a per-output hash, to support cases using split-dwarf (or other platform equivalents) when the debug info changes in a way that would require re-running dwp, but not relinking downstream libraries or binaries.</div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Mon, Mar 4, 2019 at 5:57 PM Ben Boeckel via Modules &lt;<a href="mailto:modules@lists.isocpp.org">modules@lists.isocpp.org</a>&gt; wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">Hi,<br>
<br>
For CMake support for C++ modules, I&#39;ve patched GCC so it outputs<br>
dependency information in a JSON format. Before going too far down this<br>
road, I&#39;d like to get feedback on the format. This is for the purposes<br>
of being able to implement D1483R1[1] without requiring build tools to<br>
implement a C++ parser and instead have the compiler do the &quot;scan&quot; step<br>
described there.<br>
<br>
    {                               //<br>
    &quot;outputs&quot;: [                    // Files to be output for this<br>
    &quot;source.o&quot;                      // compilation[2].<br>
    ],                              //<br>
    &quot;provides&quot;: [                   // BMI files provided by this<br>
    &quot;I.gcm&quot;                         // compilation.<br>
    ],                              //<br>
    &quot;logical-provides&quot;: {           // Mapping of module names provided<br>
    &quot;I&quot;: &quot;I.gcm&quot;                    // to provided BMI files.<br>
    },                              //<br>
    &quot;requires&quot;: [                   // Modules names required by this<br>
    &quot;M&quot;                             // compilation.<br>
    ],                              //<br>
    &quot;depends&quot;: [                    // Preprocessor dependency files<br>
    &quot;../path/to/source.cpp&quot;,        // which affect this scan (so it can<br>
    &quot;/usr/include/stdc-predef.h&quot;    // be rerun if necessary).<br>
    ],                              //<br>
    &quot;version&quot;: 0,                   // The file format version.<br>
    &quot;revision&quot;: 1                   // The file format revision.<br>
    }                               //<br>
<br>
This example output is for a file with the contents:<br>
<br>
    export module I;<br>
    import M;<br>
<br>
    export int i() {<br>
        return m();<br>
    }<br>
<br>
My existing patch to GCC is currently missing `revision` and uses<br>
`version` == 1 (but my CMake patches also don&#39;t check the field right<br>
now). I&#39;d like to get a Clang patch written up in the next few weeks.<br>
<br>
Points to note:<br>
<br>
  - All top-level types are as-is and the key names are never localized:<br>
    * `outputs`: array<br>
    * `provides`: array<br>
    * `logical-provides`: object<br>
    * `requires`: array<br>
    * `depends`: array<br>
    * `version`: int<br>
    * `revision`: int<br>
  - Values are strings if the name or path is valid UTF-8. The keys of<br>
    `logical-provides` must be strings, therefore `requires` must also<br>
    be only strings since these are used as lookup keys to find the<br>
    on-disk file representing the listed `provide` (shouldn&#39;t be an<br>
    issue since these are module names).<br>
  - In the case of invalid UTF-8, an object is used with the following<br>
    layout (all data here is literal and not localized):<br>
<br>
    {                               //<br>
    &quot;format&quot;: &quot;...&quot;,                // The format of the data.<br>
    &quot;data&quot;: [...]                   // Array of integers interpreted as<br>
    }                               // the appropriate integer size.<br>
<br>
  - Relative paths are relative to the working directory of the<br>
    compiler. Build tools may need to rewrite paths for the build tool<br>
    to actually understand them.[3]<br>
  - `version` is bumped if there is any semantic data added (e.g., more<br>
    information which is required to get a correct build), types change,<br>
    etc.<br>
  - `revision` is bumped if additionally helpful, but not semantically<br>
    important, field is added to the format.<br>
<br>
Defined formats (I&#39;m fine with bikeshedding these names once the overall<br>
format has been hammered out):<br>
<br>
  - &quot;raw8&quot;: interpret `data` as an array of uint8_t bytes to be passed<br>
    to platform-specific filesystem APIs as an 8-bit encoding<br>
  - &quot;raw16&quot;: interpret `data` as an array of uint16_t bytes to be passed<br>
    to platform-specific filesystem APIs as a 16-bit encoding<br>
  - &quot;raw32&quot;: interpret `data` as an array of uint32_t bytes to be passed<br>
    to platform-specific filesystem APIs as a 32-bit encoding<br>
<br>
This basically means &quot;check if it is UTF-8, if it is, escape `\` and `&quot;`<br>
and output that, otherwise indicate the byte size of the data and write<br>
it as an integer array&quot;.<br>
<br>
In the future, we can add additional formats as a revision bump.<br>
<br>
So,<br>
<br>
  - Is anything missing from this format?<br>
  - Is there any issue with getting this information from compilers?<br>
  - Are any of the constraints too onerous on compilers?<br>
  - Are there any constraints which should be added to make it even<br>
    easier for build tools to parse/interpret this format?<br>
  - For non-UTF-8 data, do we want to default to `raw8` format without<br>
    one specified? Or should it always be required?<br>
  - Are non-UTF-8 module names valid? Does anyone know what SG16 is<br>
    saying about Unicode identifiers (which I presume would affect<br>
    module names as well)?<br>
<br>
Thanks,<br>
<br>
--Ben<br>
<br>
[1]<a href="https://mathstuf.fedorapeople.org/fortran-modules/fortran-modules.html" rel="noreferrer" target="_blank">https://mathstuf.fedorapeople.org/fortran-modules/fortran-modules.html</a><br>
[2]Note that some flags to GCC can cause it to output multiple files for<br>
a compilation step (such as -fsplit-dwarf). It is my hope that such<br>
flags can be wired up to this facility in the future as I don&#39;t think it<br>
is done right now.<br>
[3]Additionally, CMake takes the `.gcm` files and places it elsewhere in<br>
the tree via GCC&#39;s module map files. Object files are also placed via<br>
`-o` which is otherwise occupied during the scan step at the moment, so<br>
their paths may also need to be reinterpreted at the build tool level.<br>
_______________________________________________<br>
Modules mailing list<br>
<a href="mailto:Modules@lists.isocpp.org" target="_blank">Modules@lists.isocpp.org</a><br>
Subscription: <a href="http://lists.isocpp.org/mailman/listinfo.cgi/modules" rel="noreferrer" target="_blank">http://lists.isocpp.org/mailman/listinfo.cgi/modules</a><br>
Link to this post: <a href="http://lists.isocpp.org/modules/2019/03/0123.php" rel="noreferrer" target="_blank">http://lists.isocpp.org/modules/2019/03/0123.php</a><br>
</blockquote></div>