libc/winsup/doc/gcc.xml

143 lines
5.2 KiB
XML

<?xml version="1.0" encoding='UTF-8'?>
<!DOCTYPE sect1 PUBLIC "-//OASIS//DTD DocBook V4.5//EN"
"http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd">
<sect1 id="gcc"><title>Using GCC with Cygwin</title>
<sect2 id="gcc-default"><title>Standard Usage</title>
<para>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:</para>
<example id="gcc-hello-world">
<title>Building Hello World with GCC</title>
<screen>
<prompt>bash$</prompt> <userinput>gcc hello.c -o hello.exe</userinput>
<prompt>bash$</prompt> <userinput>hello.exe</userinput>
Hello, World
<prompt>bash$</prompt>
</screen>
</example>
</sect2>
<sect2 id="gcc-64"><title>Building applications for 64 bit Cygwin</title>
<para>The 64 bit Cygwin toolchain uses the
<ulink url="http://en.wikipedia.org/wiki/X86_calling_convention#Microsoft_x64_calling_convention">Microsoft x64 calling convention</ulink>
by default, so you can create applications using the Win32 API just as with
the 32 bit Cygwin toolchain.</para>
<para>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
<ulink url="http://en.wikipedia.org/wiki/64-bit_computing#64-bit_data_models">64-bit computing</ulink>.</para>
<para>While the Mingw and Microsoft compilers use the <literal>LLP64</literal>
data model, Cygwin compilers use the <literal>LP64</literal> data model, just
like Linux. This affects the size of the type <literal>long</literal>. In the
<literal>LLP64</literal> model preferred by Microsoft,
<function>sizeof(long)</function> is 4. This applies for the related Win32
types like <literal>LONG</literal>, <literal>ULONG</literal>,
<literal>DWORD</literal>, etc., too.</para>
<para>In the <literal>LP64</literal> model used by Cygwin, <function>sizeof(long)</function> is 8,
just like the size of pointers or the types <literal>size_t/ssize_t</literal>.
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.</para>
<para>Here's an example. The Win32 function <function>ReadFile</function>
returns the number of read bytes via a pointer to a DWORD variable:</para>
<screen>
BOOL WINAPI ReadFile (HANDLE, PVOID, DWORD, PDWORD, LPOVERLAPPED);
</screen>
<para>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 <function>my_read</function> function using ReadFile:</para>
<example id="gcc-64-ex1">
<title>64bit-programming, Using ReadFile, 1st try</title>
<screen>
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) &amp;bytes_read, NULL))
return bytes_read;
set_errno_from_get_last_error ();
return -1;
}
</screen>
</example>
<para>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
<function>sizeof(ssize_t)</function> is 8, <function>ReadFile</function>
will write the number of read bytes into the lower 4 bytes of the variable
<literal>bytes_read</literal>, while the upper 4 bytes will contain an
undefined value. <function>my_read</function> will very likely return the
wrong number of read bytes to the caller.</para>
<para>Here's the fixed version of <function>my_read</function>:</para>
<example id="gcc-64-ex2">
<title>64bit-programming, Using ReadFile, 2nd try</title>
<screen>
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, &amp;bytes_read, NULL))
return (ssize_t) bytes_read;
set_errno_from_get_last_error ();
return -1;
}
</screen>
</example>
</sect2>
<sect2 id="gcc-gui"><title>GUI Mode Applications</title>
<para>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.</para>
<para>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.</para>
<para>The build process is similar to any other build process. The only
difference is that you use <command>gcc -mwindows</command> to link your
program into a GUI application instead of a command-line application.
Here's an example Makefile:</para>
<screen>
<![CDATA[
myapp.exe : myapp.o myapp.res
gcc -mwindows myapp.o myapp.res -o $@
myapp.res : myapp.rc resource.h
windres $< -O coff -o $@
]]>
</screen>
<para>Note the use of <filename>windres</filename> to compile the
Windows resources into a COFF-format <filename>.res</filename> file.
That will include all the bitmaps, icons, and other resources you
need, into one handy object file. For more information on
<filename>windres</filename>, consult the Binutils manual. </para>
</sect2>
</sect1>