Step 1: run all tests, mark all the flaky ones.
Step 2: run all tests under sanitizers, mark all the ones that fail.
Step 3: fix all the sanitizer failures.
Step 4: (the other stuff you wrote)
Step 1: run all tests, mark all the flaky ones.
Step 2: run all tests under sanitizers, mark all the ones that fail.
Step 3: fix all the sanitizer failures.
Step 4: (the other stuff you wrote)
Step -1: Get it under source control and backed up.
Step -2: Find out if the source code corresponds to the executable. Which of the 7 variants of the source code (if any).
Step -3: Do dark rituals over a weekend with cdparanioa to scrape the source code from the bunch of scratched cd's found in someone's bottom drawer. Bonus point if said person died last week, and other eldritch horrors lurk in that bottom drawer. Build a VM clone of the one machine still capable of compiling it.
Yes, I have scars, why do you ask?
Maybe VM clones of various users too, and recordings of their work flows?
I think about that a lot now that I'm older and spend a fair bit of time in MRI machines...
The first time I looked at it, I saw that the make file set the warning level to 0 and redirected the output to NUL. Removing that, I ran nmake and prayed. About 45 minutes later it finished building, evidently successfully. It turned out that having the warnings actually print added 10 minutes to the build.
It was averaging more than one error per line of code at /w3. And it was around 40k lines of code. Not large by the standards of today but huge back then for MSDOS. Peeking, it used K&R c and included no header files. So step 1 for me was to hook up some scaffolding using various tools from mks to make sure as I edited things that the error count didn’t increase.
The biggest thing I learned from this project was to not combine other coding with the warning removal or other cleanup. Makes it much easier to spot when you introduce bugs.
Answer: Our office was in the WTC and was destroyed on 9/11. Luckily everyone got out alive, but then we discovered we had no off-site backups of the source code. In order to continue development, we had to retrieve the released binaries from our customers and decompile them to get back source code.
I don't know what the practice was at that time, but some years later, people weren't allowed to have the source on their laptops, they had to SSH/RDP/etc in to a hosted development system to work on it, which might explain how losing the office resulted in losing the source code even with people doing WFH
/s
Step -4: Get the version of windows and the compiler it was last known to compile with.
Been there. Done that.
Then you discover -frandom-seed - and go ballistic when you read "but it should be a different seed for each sourcefile"
Then you figure out your linker likes emitting a timestamp in object files. Then you discover /Brepro (if you're lucky enough to use lld-link.
Then you used to discover that Win7's app compat db expected a "real" timestamp, and a hash just won't do. (Thank God, that's dead now). This is usually the part where you start questioning your life choices.
Then somebody comes to your desk and asks if you can also make partial rebuilds deterministic.
On the upside, step 1 is usually quick, there will be no tests.
But yes, if the goal is "slap it all in a container", that's probably good and at least somewhat reproducible. We aren't Python here! ;)
That's okay, it's probably just some bank in a random country that requires some software package to be installed, presumably in the interest of security, which injects a dll into every process on the machine and unsurprisingly has a bug which causes your process to crash at random in only that part of the world.
You don't even have to get that far. Shell extensions (for file open or save dialogs) and printer drivers also introduce arbitrary DLLs to your processes. And some of them are compiled in an old version of IIRC Delphi or Turbo Pascal, which on the DLL startup code unconditionally changes the floating point control word to something which causes unexpected behavior in some framework you're using.
(We ended up wrapping all calls to file open or save or print dialogs with code to save and restore the floating point control word, just in case they had loaded one of these annoying DLLs.)
But that sort of report isn't a deep mystery, it's just a specific class of bug. Given the description, you've got a pretty good idea of what you're looking for.
For a long-ago example: I worked on a project that had an optimizer that used time-bounded simulated annealing to optimize. No two builds ever the same. It was "great".
Though in the last 6 years I've seen at least one case where truly deterministic builds mattered:
A performance bug only happens when a malloc() during init was not aligned to 32 bytes, glibc on x86_64 only guaranteed 16 bytes, but depending on what alloc / dealloc happened before it may just land on 32 bytes boundary.
The alloc / dealloc sequence before that point was pretty deterministic, however there were a few strings containing __FILE__. And gitlab runner checked-out codes to a path with random number (or an index? I don't remember) without -ffile-prefix-map or $PWD trick so its length varies.
This is a good guy. Knows what they need, knows you are smart enough to potentially finally slay the dragon, will fight the bureaucracy on your behalf. Asking a hard ask is rarely beneficial for the asker on the failure side. Don't burn yourself out for it though and don't be afraid to ask hard favors from the asker.
> The string can either be a number (decimal, octal or hex) or an arbitrary string (in which case it’s converted to a number by computing CRC32). > The string should be different for every file you compile.
So basically just pass in the project relative path to the file into random-seed and you'll be fine. It's a shame the guidance doesn't explain why the string should be different because that feels like it could be advice that's not rooted in any technical reality.
__time__ isn't actually that bad as it's an anti-pattern and much better for the build system to inject the build time explicitly as an input macro (if your software needs it for UX purposes).
__FILE__ is the more annoying one but can be solved through fmacro-prefix-map.
And it wouldn't be C++ if a large chunk of the bad decisions wasn't rooted in the preprocessor.
I have absolutely inherited codebases where one of the early steps was to make a commit excising every single comment in the code, because so many of them were old, lies, or old lies, that it wasn't worth the risk of a junior developer accidentally thinking they could be relied upon.
(and of course they remained available in history to be potentially buffed up and resurrected, but still, argh)
Sometimes the test still passes, and that is a good sign that something is very wrong!