Using GCC with Cygwin
Standard Usage
Use gcc to compile, just like under UNIX. Refer to the GCC User's Guide
for information on standard usage and options. Here's a simple example:
Building Hello World with GCC
bash$ gcc hello.c -o hello.exe
bash$ hello.exe
Hello, World
bash$
Building applications for 64 bit Cygwin
The 64 bit Cygwin toolchain uses the
Microsoft x64 calling convention
by default, so you can create applications using the Win32 API just as with
the 32 bit Cygwin toolchain.
There's just one important difference. The 64 bit Cygwin compilers use
a different data model than the Mingw and Microsoft compilers. For reference,
see the Wikipedia entry on
64-bit computing.
While the Mingw and Microsoft compilers use the LLP64
data model, Cygwin compilers use the LP64 data model, just
like Linux. This affects the size of the type long. In the
LLP64 model preferred by Microsoft,
sizeof(long) is 4. This applies for the related Win32
types like LONG, ULONG,
DWORD, etc., too.
In the LP64 model used by Cygwin, sizeof(long) is 8,
just like the size of pointers or the types size_t/ssize_t.
This simplifies porting Linux applications to 64 bit Cygwin, but it requires
due diligence when calling Windows functions taking LONG, ULONG, DWORD, or any
other equivalent type. This is especially important in conjunction with
pointers.
Here's an example. The Win32 function ReadFile
returns the number of read bytes via a pointer to a DWORD variable:
BOOL WINAPI ReadFile (HANDLE, PVOID, DWORD, PDWORD, LPOVERLAPPED);
Note that the forth parameter is a pointer to a DWORD, thus it's a
pointer to a 4 byte type, on 32 as well as on 64 bit Windows. Now we write
our own my_read function using ReadFile:
64bit-programming, Using ReadFile, 1st try
ssize_t
my_read (int fd, void *buffer, size_t bytes_to_read)
{
HANDLE fh = _get_osfhandle (fd);
ssize_t bytes_read;
if (ReadFile (fh, buffer, bytes_to_read, (PDWORD) &bytes_read, NULL))
return bytes_read;
set_errno_from_get_last_error ();
return -1;
}
While this example code works fine on 32 bit Windows, it has in fact
a bad bug. The assumption that the size of ssize_t is the same as the size
of DWORD is wrong for 64 bit. In fact, since
sizeof(ssize_t) is 8, ReadFile
will write the number of read bytes into the lower 4 bytes of the variable
bytes_read, while the upper 4 bytes will contain an
undefined value. my_read will very likely return the
wrong number of read bytes to the caller.
Here's the fixed version of my_read:
64bit-programming, Using ReadFile, 2nd try
ssize_t
my_read (int fd, void *buffer, size_t bytes_to_read)
{
HANDLE fh = _get_osfhandle (fd);
DWORD bytes_read;
if (ReadFile (fh, buffer, bytes_to_read, &bytes_read, NULL))
return (ssize_t) bytes_read;
set_errno_from_get_last_error ();
return -1;
}
GUI Mode Applications
Cygwin comes with an X server, so usually you should compile your
GUI applications as X applications to allow better interoperability with
other Cygwin GUI applications.
Other than that, Cygwin allows you to build programs with full access
to the standard Windows API, including the GUI functions as defined in
any Microsoft or off-the-shelf publication.
The build process is similar to any other build process. The only
difference is that you use gcc -mwindows to link your
program into a GUI application instead of a command-line application.
Here's an example Makefile:
Note the use of windres to compile the
Windows resources into a COFF-format .res file.
That will include all the bitmaps, icons, and other resources you
need, into one handy object file. For more information on
windres, consult the Binutils manual.