| <?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) &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, &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> |