Investigate MSVC's /experimental:deterministic flag's effect, maybe use it in MSVC crosstool. (Maybe put it behind a Bazel experimental flag.)
Motivation: to make C++ builds deterministic. For example, MSVC doesn't support overriding non-deterministic macros like __DATE__, maybe this flag solves that problem.
Windows 10
bazel info release?release 0.29.1
/cc @meteorcloudy @hlopko
We have no experience so far.
From https://developercommunity.visualstudio.com/idea/426033/support-for-cls-experimentaldeterministic-becoming.html, looks like this is not yet documented anywhere and is still under development?
I found https://developercommunity.visualstudio.com/content/problem/502528/changing-pdb-source-file-paths-with-experimentalde.html which says:
"""PDBs are not deterministic and aren't the intended target of this feature, so there may still be a great many full paths still embedded in the PDBs after doing this. These switches are intended for object file and executable determinism, not PDBs."""
Since executables embed a ref to the PDB in /debug build, it looks like deterministic builds with debug information remain impossible with MSVC.
(Plug: They _are_ possible with clang-cl and lld-link, see http://blog.llvm.org/2019/11/deterministic-builds-with-clang-and-lld.html for how.)
Some other maybe interesting links:
I've been playing around with some trial and error and found that:
d1nodatetime: undefs __DATE__, __TIME__, __TIMESTAMP__. user may redefine them.Brepro (should be supplied to all of cl, lib, and link): implies d1nodatetime and sets initial value of those #defines equal to 1. Additionally modifies some data stored in object files to make them binary-identical between builds.experimental:deterministic implies Brepro and issues a warning if problematic code is found (usage of __TIME__, etc.)Using Brepro, INCREMENTAL:NO, and Z7, I'm able to get outputs to be binary-identical between builds on the same computer, with some exceptions: If a .manifest and/or resource file (.rc) is processed during compilation/linking, it creates a temporary file during processing, and for whatever reason, this temporary path is included in the resulting pdb (obviously the temporary has been deleted by the time the build is done, so...pointless). This can be "solved" by just omitting the .rc or using a side-by-side .manifest instead of embedding it. However, pdbs with these different temporary paths inside are completely interchangeable - the difference does not prevent a debugger loading it for example.
d1trimfile:<path[=ENV_VAR]> (seen in above links) sounds like it was originally intended to trim the __FILE__ definition, which it does seem to do in my testing (handy if you use FC, I guess). As discussed in above links, they seem to have made it apply to paths stored in .obj files referencing a pdb as well, which occurs on non-Z7 builds, i.e. Zi builds. Unfortunately my quick test still shows full pdb path being in the eventual exe file.
However...why is this a problem? The differences in the pdb can be seen to be inconsequential and the exe will be identical apart from the pdb path, which is accounted for by existing tools (like debuggers and symsrv, which dont use a path to index the pdb).
Maybe make a request to msvc team to have d1trimfile also apply to the pdb path stored in exe? Since they recently made a related change perhaps it just needs to be asked for.
(You can make the pdb path in the exe relative with /pdbaltpath:%_PDB%.)
@nico what exactly is `%_PDB%? Where it comes from? I wonder how to I change Bazel MSVC toolchain to use it?
Most helpful comment
Some other maybe interesting links:
I've been playing around with some trial and error and found that:
d1nodatetime: undefs__DATE__,__TIME__,__TIMESTAMP__. user may redefine them.Brepro(should be supplied to all of cl, lib, and link): impliesd1nodatetimeand sets initial value of those#definesequal to 1. Additionally modifies some data stored in object files to make them binary-identical between builds.experimental:deterministicimpliesBreproand issues a warning if problematic code is found (usage of__TIME__, etc.)Using
Brepro,INCREMENTAL:NO, andZ7, I'm able to get outputs to be binary-identical between builds on the same computer, with some exceptions: If a .manifest and/or resource file (.rc) is processed during compilation/linking, it creates a temporary file during processing, and for whatever reason, this temporary path is included in the resulting pdb (obviously the temporary has been deleted by the time the build is done, so...pointless). This can be "solved" by just omitting the .rc or using a side-by-side .manifest instead of embedding it. However, pdbs with these different temporary paths inside are completely interchangeable - the difference does not prevent a debugger loading it for example.d1trimfile:<path[=ENV_VAR]>(seen in above links) sounds like it was originally intended to trim the__FILE__definition, which it does seem to do in my testing (handy if you useFC, I guess). As discussed in above links, they seem to have made it apply to paths stored in .obj files referencing a pdb as well, which occurs on non-Z7builds, i.e.Zibuilds. Unfortunately my quick test still shows full pdb path being in the eventual exe file.However...why is this a problem? The differences in the pdb can be seen to be inconsequential and the exe will be identical apart from the pdb path, which is accounted for by existing tools (like debuggers and
symsrv, which dont use a path to index the pdb).Maybe make a request to msvc team to have
d1trimfilealso apply to the pdb path stored in exe? Since they recently made a related change perhaps it just needs to be asked for.