https://gcc.gnu.org/bugzilla/show_bug.cgi?id=106624
--- Comment #8 from Sergei Trofimovich <slyfox at gcc dot gnu.org> --- I think I understand now why it's such a mysterious failure. gcc uses putenv() incorrectly! I think the real bug was introduced in: commit 1270ccda70ca09f7d4 "Factor out jobserver_active_p.". It's gist is the change from `xputenv (concat ("MAKEFLAGS=", dup, NULL));` to `xputenv (jinfo.skipped_makeflags.c_str ());`. The difference here is what happens with memory allocated to be put into putenv(). putenv() is an odd API as it does not copy data, it just interns the pointer: // $ cat a.c #include <stdio.h> #include <stdlib.h> #include <string.h> char arr[1000] = "FOO=1234"; int main() { putenv(arr); printf("getenv(FOO)='%s'\n", getenv("FOO")); sprintf(arr + strlen("FOO="), "!!!!"); printf("getenv(FOO)='%s'\n", getenv("FOO")); } Thus `xputenv (jinfo.skipped_makeflags.c_str ());` gets clobbered with garbage as soon as string is freed and reallocated. I think commit 53e3b2bf16a486c "lto: support --jobserver-style=fifo for recent GNU make" only happens to tickle string reallocation as it does things with more std::strings. As a hack it looks like the following is enough to build a gcc for me: --- a/gcc/gcc.cc +++ b/gcc/gcc.cc @@ -9182,7 +9182,7 @@ driver::detect_jobserver () const { jobserver_info jinfo; if (!jinfo.is_active && !jinfo.skipped_makeflags.empty ()) - xputenv (jinfo.skipped_makeflags.c_str ()); + xputenv (xstrdup(jinfo.skipped_makeflags.c_str ())); } /* Determine what the exit code of the driver should be. */ Not sure what should be used instead for proper memory management.