https://gcc.gnu.org/bugzilla/show_bug.cgi?id=110710
--- Comment #8 from peter0x44 at disroot dot org --- The way make works is it prefers using an sh.exe if it finds it on the PATH. https://git.savannah.gnu.org/cgit/make.git/tree/src/variable.c#n1637 (see variable.c of GNU make) Otherwise, cmd.exe is used. This is probably why many people don't notice, as most "mingw" environments do have this. But "mingw" does not imply "has an sh.exe shell". You can totally add gcc to your cmd.exe PATH and use it fine, and you can also write Makefiles with GNU Make that expect to use cmd.exe to execute their build rules. If GCC's generated temporary Makefiles expect to run under a "posix sh" always, I believe they should have on the first line: SHELL = /bin/sh For a workaround, I would recommend busybox-w32. It's what w64devkit uses. You can just put it on your PATH and see if it solves that issue. It's what w64devkit uses, and I have used `-flto=auto` with it successfully before. As for actually reviewing this issue in the generated Makefiles, there are a few approaches that can be used. One of them it to utilize a "polyglot test" to tell which shell the build rules are being executed under. Something like: SHELLTYPE := posix ifeq ($(shell echo "test", "test")) SHELLTYPE := cmd endif This works because cmd.exe's echo command writes quotes. under cmd.exe echo "test" will write: "test" and under a posix: test (without quotes) Then, the Makefile can later do something like: ifeq (posix, $(SHELLTYPE)) gcc whatever.c 2>/dev/null else gcc whatever.c 2>NUL endif Now, this is an enormous HACK, but it worked okay in some cases, for me. I implemented it in a different Makefile generating project here: https://github.com/premake/premake-core/pull/2039 But is probably a terrible idea for GCC, since I believe ifeq is a GNU Make extension. So is $(shell), afaik. I'm only presenting this option for completeness. I think the better solution for this case would be for --host=*-w64-mingw32, write out Makefiles with: SHELL = cmd and then proceed to use all the cmd.exe shell equivalents, like 2>NUL, move instead of mv, etc. I've spent quite a bit of time before thinking and exploring this particular "problem space", so it's just my analysis here. Unfortunately, I think there are no "nice" ways to solve this problem.