Search code examples
c#roslyn

<Deterministic>true</Deterministic> and file build order


I managed to observe a change in program behavior based on the order of files passed to the compiler. Never mind how; that's what it is. The file name order matters.

By default, projects do wildcard expansion of files (which is unstable), but there exists the option <Deterministic>true</Deterministic>; what order are files passed to the compiler when <Deterministic>true</Deterministic> is set?

Searching for documentation turned up nothing.

If you tell me no such order exists I will most definitely file a bug against Roslyn; if I can observe a functional change by re-ordering files than it's definitely not deterministic.

Simplest possible reproduction:

/* a file */
partial class Class1 {
    public static int x = 3;
}
/* another file */
partial class Class1 {
    public static int y = x;
}
/* Program.cs */
Console.WriteLine(Class1.y);

Reproduction is easiest on a FAT filesystem. The file names are unimportant; the order you create them is important.


Solution

  • The compiler's behavior indeed depends on the ordering of files. There's some other cases too around partial classes/members, which can have XML doc comments on both which get merged, and the order of the merging depends on the file ordering.

    The compiler, as in "the csc.exe process", will ensure that the order it gets the source files passed in via the command line are handed around and processed in the correct order internally. It is absolutely deterministic, given a specific ordering of files -- it's just that the file ordering is effectively an input to the determinism. If you had a case where the same compiler invocation with the same ordering of files gave a different non-deterministic output, we'd absolutely want that bug.

    However, the end-to-end tooling makes this murky: as you observed the globbing MSBuild does might depend on your file system, or operating system, etc. And frankly, if your file ordering matters, then you might just want to not use globbing because that's just asking for trouble at some point!

    We absolutely have bugs in the IDE where when we create the "internal" compiler for IntelliSense, we might not get the file ordering correct to match the ordering the actual build will use. We haven't prioritized these bugs since they're very hard to hit. Frankly, in the 15 years I've worked on this you might be the winner for the first customer to notice!