www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.bugs - [Issue 18423] New: rdmd incorrectly assumes that the D compiler

https://issues.dlang.org/show_bug.cgi?id=18423

          Issue ID: 18423
           Summary: rdmd incorrectly assumes that the D compiler outputs
                    dependency info to stdout
           Product: D
           Version: D2
          Hardware: x86_64
                OS: Linux
            Status: NEW
          Severity: major
          Priority: P1
         Component: tools
          Assignee: nobody puremagic.com
          Reporter: joseph.wakeling webdrake.net

When `rdmd` invokes the D compiler to generate dependencies information, it
makes a hardcoded assumption that this information gets written by the compiler
to `stdout`.  However, this assumption is not valid for all D compilers.  In
particular, compiler frontend messages are written out to a configurable
`stdmsg`: https://github.com/dlang/dmd/commit/dc8421f

... and this configurability is used by GDC to output such messages to `stderr`
(reflecting GCC policy that `stdout` is reserved for `-pipe` output; see:
https://github.com/dlang/tools/pull/297#issuecomment-363342259).

This means not only that `rdmd` will not work with more recent GDC releases,
but that `rdmd`'s assumptions about `stdout` are not valid in general (given
the configurable `stdmsg` in the DMD frontend).

The gory details
~~~~~~~~~~~~~~~~

The `getDependencies` function inside `rdmd.d` invokes the D compiler via the
`run` command, passing in options (the `depsGetter` variable) and the name of a
file to which to write the compiler output (`depsFilename`):

```
immutable depsExitCode = run(depsGetter, depsFilename);
```

Internally, `run` takes this and uses `spawnProcess` to invoke the D compiler:

```
private int run(string[] args, string output = null, bool replace = false)
{
    ...

    File outputFile;
    if (output.ptr)
        outputFile = File(output, "wb");
    else
        outputFile = stdout;
    auto process = spawnProcess(args, stdin, outputFile);
    return process.wait();
}
```

In other words, `run` opens a file whose name is given by `depsFilename`, and
uses it to replace `stdout` for the spawned process.  The contents of this file
are then read using the nested `readDepsFile()` function defined internally
inside `getDependencies`.

In consequence, if the information parsed by `readDepsFile` is not written to
`stdout` by the D compiler, it will not get written into `outputFile`, and
therefore not be available to parse.

--
Feb 11 2018