From the point of view of porting a C program, a good way to understand this is to take an example:
#include <sys/stat.h>
#include <stdlib.h>
int main(void)
{
struct stat stbuf;
stat("c:foo.txt", &stbuf);
system("command");
printf("Hello, World\n");
return 0;
}
If we change stat
to _stat
, we can compile this program with Microsoft Visual C. We can also compile this program with MinGW, and with Cygwin.
Under Microsoft Visual C, the program will be linked to a MSVC redistributable run-time library: mxvcrtnn.dll
, where nn
is some version suffix. To ship this program we will have to include that DLL. That DLL provides _stat
, system
and printf
. (We also have the option of statically linking the run-time.)
Under MinGW, the program will be linked to msvcrt.dll
, which is an internal, undocumented, unversioned library that is part of Windows, and off-limits to application use. That library is essentially a fork of the redistributable run-time library from MS Visual C for use by Windows itself.
Under both of these, the program will have similar behaviors:
stat
function will return very limited information—no useful permissions or inode number, for instance.c:file.txt
is resolved according to the current working directory associated with drive c:
. system
uses cmd.exe /c
for running the external command.We can also compile the program under Cygwin. Similarly to the redistributable run-time used by MS Visual C, the Cygwin program will be linked to Cygwin's run-time libraries: cygwin1.dll
(Cygwin proper) and cyggcc_s-1.dll
(GCC run-time support). Since Cygwin is now under the LGPL, we can package with our program, even if it isn't GPL-compatible free software, and ship the program.
Under Cygwin, the library functions will behave differently:
stat
function has rich functionality, returning meaningful values in most of the fields.c:file.txt
is not understood at all as containing a drive letter reference, since c:
isn't followed by a slash. The colon is considered part of the name and somehow mangled into it. There is no concept of a relative path against a volume or drive in Cygwin, no "currently logged drive" concept, and no per-drive current working directory.system
function tries to use the /bin/sh -c
interpreter. Cygwin will resolve the /
path according to the location of your executable, and expect a sh.exe
program to be co-located with your executable.Both Cygwin and MinGW allow you to use Win32 functions. If you want to call MessageBox
or CreateProcess
, you can do that. You can also easily build a program which doesn't require a console window, using gcc -mwindows
, under MinGW and Cygwin.
Cygwin is not strictly POSIX. In addition to providing access to the Windows API, it also provides its own implementations of some Microsoft C functions (stuff found in msvcrt.dll
or the re-distributable msvcrtnn.dll
run-times). An example of this are the spawn*
family of functions like spawnvp
. These are a good idea to use instead of fork
and exec
on Cygwin since they map better to the Windows process creation model which has no concept of fork
.
Thus:
Cygwin programs are no less "native" than MS Visual C programs on grounds of requiring the accompaniment of libraries. Programming language implementations on Windows are expected to provide their own run-time, even C language implementations. There is no "libc" on Windows for public use.
The fact that MinGW requires no third-party DLL is actually a disadvantage; it is depending on an undocumented, Windows-internal fork of the Visual C run-time. MinGW does this because the GPL system library exception applies to msvcrt.dll
, which means that GPL-ed programs can be compiled and redistributed with MinGW.
Due to its much broader and deeper support for POSIX compared to msvcrt.dll
, Cygwin is by far the superior environment for porting POSIX programs. Since it is now under the LGPL, it allows applications with all sorts of licenses, open or closed source, to be redistributed. Cygwin even contains VT100 emulation and termios
, which work with the Microsoft console! A POSIX application that sets up raw mode with tcsetattr
and uses VT100 codes to control the cursor will work right in the cmd.exe
window. As far as the end-user is concerned, it's a native console app making Win32 calls to control the console.
However:
/bin/sh
and other issues. These differences are what render Cygwin programs "non-native". If a program takes a path as an argument, or input from a dialog box, Windows users expect that path to work the same way as it does in other Windows programs. If it doesn't work that way, that's a problem.Plug: Shortly after the LGPL announcement, I started the Cygnal (Cygwin Native Application Library) project to provide a fork of the Cygwin DLL which aims to fix these issues. Programs can be developed under Cygwin, and then deployed with the Cygnal version of cygwin1.dll
without recompiling. As this library improves, it will gradually eliminate the need for MinGW.
When Cygnal solves the path handling problem, it will be possible to develop a single executable which works with Windows paths when shipped as a Windows application with Cygnal, and seamlessly works with Cygwin paths when installed in your /usr/bin
under Cygwin. Under Cygwin, the executable will transparently work with a path like /cygdrive/c/Users/bob
. In the native deployment where it is linking against the Cygnal version of cygwin1.dll
, that path will make no sense, whereas it will understand c:foo.txt
.