143 lines
		
	
	
		
			5.2 KiB
		
	
	
	
		
			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) &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>
 |