Site logo

A sad and confusing tale of Linux emulation on Windows 01/31/23

Make is a build automation tool that automatically builds executable programs and libraries from source code by reading files called Makefiles which specify how to derive the target program.

Now you might be asking yourselves: "Huh? A build tool? Why should we care we do web applications!" True, it was true in the 1980s when it was created and even today, but bear with me. make handles automation of tedious tasks using nothing but an executable and what's called a Makefile to define said tasks in a pretty straightforward manner.

When you think about script automation you're probably thinking about npm scripts or composer scripts which requires having NodeJS + NPM / PHP + Composer installed with your tasks defined in a package.json file or a composer.json file. Using the package manager of your chosen language as an automation toolkit is incredibly handy and could be more than enough, but what about a project involving multiple languages and the help of tools from multiple eco-systems? When you throw into the mix docker commands for building images for your project and aws commands to automate your AWS infrastructure, things really start becoming too big for a single package manager to handle.

Now this is where make shines - it was built to be the glue of different executables and parameters to create a single automation utility. In the MSYS2 environment there are two make executables:

  1. The "native" (i.e: MSVCRT dependent) port of make for windows is lacking in some functionality due to the lack of POSIX on Win32. This refers to the regular make executable usually located in the /usr/bin folder.
  2. There also exists a version of make in the MSYS distribution that is dependent on the MSYS runtime (i.e: the mingw32-make). This port operates more as make was intended to operate and gives less headaches during execution. Based on this, the MinGW developers decided it would be best to rename the native version to mingw32-make, so that both the "native" (i.e: MSVCRT dependent) version and the MSYS version (i.e: mingw32-make) could be present at the same time without file name collision.

Cygwin is an attempt to create a complete UNIX/POSIX environment on Windows and to do this it uses various DLLs. MinGW is a C/C++ compiler suite which allows you to create Windows executables without dependency on such DLLs. Cygwin adds a Linux API layer to emulate Linux functionality. This also includes POSIX standards. MinGW on the other hand aims at providing a native GCC compiler for Windows platform.

MSYS is a project started by the MinGW team as a fork of Cygwin that never kept up with Cygwin.

MsysGit is a fork of a slightly older version of MSYS with some custom patches, old versions of bash, perl and a native port of git.

MSYS2 is a recent fork of Cygwin which tracks the latest Cygwin closely so that it doesn't end up out of date.

MSYS2 Shell, MinGW32 Shell & MinGW64 Shell

To best describe it, here are two quotes from a comment on sourceforge by Matthieu Vachon:

All three shells have the same capabilities, but because of the different orders of folders in their PATH variables, tools that will be picked are different from shell to shell. So, if you want to compile something, use the appropriate shell for what you want to do (MSYS2 program, Windows native 32 bits or Windows native 64 bits). For msys2_shell, PATH is roughly only /usr/local/bin:/usr/bin:/bin. This means that when running gcc, you will get /usr/bin/gcc. For mingw32_shell, PATH is roughly mingw32/bin:/usr/local/bin:/usr/bin:/bin. This means that now, running gcc you will get instead /mingw32/bin/gcc. For mingw64_shell, PATH is roughly /mingw64/bin:/usr/local/bin:/usr/bin:/bin and as you have guessed, running gcc you will get instead /mingw64/bin/gcc.