Welcome to mirror list, hosted at ThFree Co, Russian Federation.

cygwin.com/git/newlib-cygwin.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'winsup/doc/faq-programming.xml')
-rw-r--r--winsup/doc/faq-programming.xml333
1 files changed, 292 insertions, 41 deletions
diff --git a/winsup/doc/faq-programming.xml b/winsup/doc/faq-programming.xml
index bfc27fac7..c01a127e6 100644
--- a/winsup/doc/faq-programming.xml
+++ b/winsup/doc/faq-programming.xml
@@ -1,5 +1,11 @@
+<?xml version="1.0" encoding='UTF-8'?>
+<!DOCTYPE article PUBLIC "-//OASIS//DTD DocBook V4.5//EN"
+ "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd">
<!-- faq-programming.xml -->
+<qandadiv id="faq.programming">
+<title>Programming Questions</title>
+
<qandaentry id="faq.programming.packages">
<question><para>How do I contribute a package?</para></question>
<answer>
@@ -48,6 +54,287 @@ package. Or compile with the <literal>-s</literal> option to gcc.
</para>
</answer></qandaentry>
+<qandaentry id="faq.programming.64bitporting">
+<question><para>What do I have to look out for when porting applications to 64 bit Cygwin?</para></question>
+<answer>
+
+<para>The Cygwin x86_64 toolchain is using the
+<ulink url="http://en.wikipedia.org/wiki/LLP64#64-bit_data_models">LP64</ulink>
+data model. That means, in contrast to Windows, which uses an
+<ulink url="http://en.wikipedia.org/wiki/LLP64#64-bit_data_models">LLP64</ulink>
+data model, sizeof(long) != sizeof(int), just as on Linux.</para>
+
+<para>For comparison:</para>
+
+<screen>
+ Cygwin Windows Cygwin
+ Linux x86_64 Linux
+ Windows x86_64
+ i686
+
+sizeof(int) 4 4 4
+sizeof(long) 4 4 8
+sizeof(size_t) 4 8 8
+sizeof(void*) 4 8 8
+</screen>
+
+<para>This difference can result in interesting problems, especially when
+using Win32 functions, especially when using pointers to Windows
+datatypes like LONG, ULONG, DWORD. Given that Windows is LLP64, all of
+the aforementioned types are 4 byte in size, on 32 as well as on 64 bit
+Windows, while `long' on 64 bit Cygwin is 8 bytes.</para>
+
+<para>Take the example ReadFile:</para>
+
+<screen>
+ ReadFile (HANDLE, LPVOID, DWORD, LPDWORD, LPOVERLAPPED);
+</screen>
+
+<para>In the 32 bit Cygwin and Mingw environments, as well as in the 64 bit
+Mingw environment, it is no problem to substitute DWORD with unsigned
+long:</para>
+
+<screen>
+ unsigned long number_of_bytes_read;
+ [...]
+ ReadFile (fhdl, buf, buflen, &amp;number_of_bytes_read, NULL);
+</screen>
+
+<para>However, in 64 bit Cygwin, using LP64, number_of_bytes_read is 8 bytes
+in size. But since ReadFile expects a pointer to a 4 byte type, the function
+will only change the lower 4 bytes of number_of_bytes_read on return, while
+the content of the upper 4 bytes stays undefined.</para>
+
+<para>Here are a few <emphasis>donts</emphasis> which should help porting
+applications from the known ILP32 data model of 32 bit Cygwin, to the LP64
+data model of 64 bit Cygwin. Note that these are not Cygwin-only problems.
+Many Linux applications suffered the same somewhat liberal handling of
+datatypes when the AMD64 CPU was new.</para>
+
+<itemizedlist mark="bullet">
+
+<listitem><para>
+<emphasis>Don't</emphasis> mix up int and long in printf/scanf. This:
+
+<screen>
+ int i; long l;
+ printf ("%d %ld\n", l, i);
+</screen>
+
+may not print what you think it should. Enable the gcc options -Wformat or
+-Wall, which warn about type mismatches in printf/scanf functions.
+
+<note>Using -Wall (optionally with -Werror to drive the point home) makes a
+lot of sense in general, not only when porting code to a new platform.</note>
+</para></listitem>
+
+<listitem><para>
+<emphasis>Don't</emphasis> mix int and long pointers.
+
+<screen>
+ long *long_ptr = (long *) &amp;my_int; /* Uh oh! */
+ *long_ptr = 42;
+</screen>
+
+The assignment will write 8 bytes to the address of my_int. Since my_int
+is only 4 bytes, <emphasis>something else</emphasis> gets randomly overwritten.
+Finding this kind of bug is very hard, because you will often see a problem
+which has no immediate connection to the actual bug.
+</para></listitem>
+
+<listitem><para>
+<emphasis>Don't</emphasis> mix int and pointers at all! This will
+<emphasis>not</emphasis> work as expected anymore:
+
+<screen>
+ void *ptr;
+ printf ("Pointer value is %x\n", ptr);
+</screen>
+
+%x denotes an int argument. The value printed by printf is a 4 byte value,
+so on x86_64 the printed pointer value is missing its upper 4 bytes; the output
+is very likely wrong. Use %p instead, which portable across architectures:
+
+<screen>
+ void *ptr;
+ printf ("Pointer value is %p\n", ptr);
+</screen>
+</para></listitem>
+
+<listitem><para>
+Along the same lines <emphasis>don't</emphasis> use the type int in
+pointer arithmetic. Don't cast pointers to int, don't cast pointer
+differences to int, and don't store pointer differences in an int type.
+Use the types <literal>intptr_t</literal>, <literal>uintptr_t</literal>
+and <literal>ptrdiff_t</literal> instead, they are designed for performing
+architecture-independent pointer arithmetic.
+</para></listitem>
+
+<listitem><para>
+<emphasis>Don't</emphasis> make blind assumptions about the size of a POSIX
+type. For instance, <literal>time_t</literal> is 8 bytes on 64 bit Cygwin,
+while it is (still, at the time of writing this) 4 bytes on 32 bit Cygwin,
+since time_t is based on the type long.
+</para></listitem>
+
+<listitem><para>
+<emphasis>Don't</emphasis> use functions returning pointers without declaration.
+For instance
+
+<screen>
+ printf ("Error message is: %s\n", strerror (errno));
+</screen>
+
+This code will <emphasis>crash</emphasis>, unless you included
+<filename>string.h</filename>. The implicit rule in C is that an undeclared
+function is of type int. But int is 4 byte and pointers are 8 byte, so the
+string pointer given to printf is missing the upper 4 bytes.
+</para></listitem>
+
+<listitem><para>
+<emphasis>Don't</emphasis> use C base types together with Win32 functions.
+Keep in mind that DWORD, LONG, ULONG are <emphasis>not</emphasis> the same
+as long and unsigned long. Try to use only Win32 datatypes in conjunction
+with Win32 API function calls to avoid type problems. See the above
+ReadFile example. Windows functions in printf calls should be treated
+carefully as well. This code is common for 32 bit code, but probably prints
+the wrong value on 64 bit:
+
+<screen>
+ printf ("Error message is: %lu\n", GetLastError ());
+</screen>
+
+Using gcc's -Wformat option would warn about this. Casting to the requested
+base type helps in this case:
+
+<screen>
+ printf ("Error message is: %lu\n", (unsigned long) GetLastError ());
+</screen>
+</para></listitem>
+
+<listitem><para>
+<emphasis>Don't</emphasis> mix Windows datatypes with POSIX type-specific
+MIN/MAX values.
+
+<screen>
+ unsigned long l_max = ULONG_MAX; /* That's right. */
+ ULONG w32_biggest = ULONG_MAX; /* Hey, wait! What? */
+ ULONG w32_biggest = UINT_MAX; /* Ok, but borderline. */
+</screen>
+
+Again, keep in mind that ULONG (or DWORD) is <emphasis>not</emphasis> unsigned
+long but rather unsigned int on 64 bit.
+</para></listitem>
+
+</itemizedlist>
+
+</answer></qandaentry>
+
+<qandaentry id="faq.programming.64bitporting-fail">
+<question><para>My project doesn't build at all on 64 bit Cygwin. What's up?</para></question>
+<answer>
+
+<para>Typically reasons for that are:</para>
+
+<itemizedlist mark="bullet">
+
+<listitem><para><literal>__CYGWIN32__</literal> is not defined in the
+64 bit toolchain. This may hit a few projects which are around since before
+Y2K. Check your project for occurences of <literal>__CYGWIN32__</literal>
+and change them to <literal>__CYGWIN__</literal>, which is defined in the
+Cygwin toolchain since 1998, to get the same Cygwin-specific code changes done.
+</para></listitem>
+
+<listitem><para>The project maintainers took it for granted that Cygwin is
+running only on i686 CPUs and the code is making this assumption blindly.
+You have to check the code for such assumptions and fix them.
+</para></listitem>
+
+<listitem><para>The project is using autotools, the
+<filename>config.sub</filename> and <filename>config.guess</filename> files
+are hopelessly outdated and don't recognize
+<literal>x86_64-{pc,unknown}-cygwin</literal> as valid target. Update the
+project configury (cygport will do this by default) and try again.
+</para></listitem>
+
+<listitem><para>The project uses Windows functions on Cygwin and it's suffering
+from the problems described in the preceeding FAQ entry.
+</para></listitem>
+
+</itemizedlist>
+
+<para>In all of this cases, please make sure to fix that upstream, or send
+your patches to the upstream maintainers, so the problems get fixed for the
+future.</para>
+
+</answer></qandaentry>
+
+<qandaentry id="faq.programming.64bitporting-cygwin64">
+<question><para>Why is __CYGWIN64__ not defined for 64 bit?</para></question>
+<answer>
+
+<para>There is no <literal>__CYGWIN64__</literal> because we would like to
+have a unified way to handle Cygwin code in portable projects. Using
+<literal>__CYGWIN32__</literal> and <literal>__CYGWIN64__</literal> only
+complicates the code for no good reason. Along the same lines you won't
+find predefined macros <literal>__linux32__</literal> and
+<literal>__linux64__</literal> on Linux.</para>
+
+<para>If you really have to differ between 32 and 64 bit in some way, you have
+three choices.</para>
+
+<itemizedlist mark="bullet">
+
+<listitem><para>If your code depends on the CPU architecture, use the
+predefined compiler definition for the architecture, like this:</para>
+
+<screen>
+#ifdef __CYGWIN__
+# ifdef __x86_64__ /* Alternatively __x86_64, __amd64__, __amd64 */
+ /* Code specific for AMD64 CPU */
+# elif __X86__
+ /* Code specific for ix86 CPUs */
+# else
+# error Unsupported Architecture
+# endif
+#endif
+</screen></listitem>
+
+<listitem><para>If your code depends on differences in the data model, you
+should consider to use the <literal>__LP64__</literal> definition
+instead:</para>
+
+<screen>
+#ifdef __CYGWIN__
+# ifdef __LP64__ /* Alternatively _LP64 */
+ /* Code specific for 64 bit CPUs */
+# else
+ /* Code specific for 32 bit CPUs */
+# endif
+#endif
+</screen></listitem>
+
+<listitem><para>If your code uses Windows functions, and some of the
+functionality is 64 bit Windows-specific, use <literal>_WIN64</literal>,
+which is defined on 64 bit Cygwin, as soon as you include
+<filename>windows.h</filename>. This should only be used in the most
+desperate of occasions, though, and <emphasis>only</emphasis> if it's
+really about a difference in Windows API functionality!</para>
+
+<screen>
+#ifdef __CYGWIN__
+# ifdef _WIN64
+ /* Code specific for 64 bit Windows */
+# else
+ /* Code specific for 32 bit Windows */
+# endif
+#endif
+</screen></listitem>
+
+</itemizedlist>
+
+</answer></qandaentry>
+
<qandaentry id="faq.programming.glibc">
<question><para>Where is glibc?</para></question>
<answer>
@@ -62,7 +349,7 @@ would be difficult.
<question><para>Where is Objective C?</para></question>
<answer>
-<para>Support for compiling Objective C is available in the <literal>gcc4-objc</literal>
+<para>Support for compiling Objective C is available in the <literal>gcc{4}-objc</literal>
package; resulting binaries will depend on the <literal>libobjc2</literal>
package at runtime.
</para>
@@ -72,10 +359,8 @@ package at runtime.
<question><para>Why does my make fail on Cygwin with an execvp error? </para></question>
<answer>
-<para>First of all, if you are using <literal>make -j[N]</literal>, then stop. It doesn't
-work well. Also beware of using non-portable shell features in your
-Makefiles (see tips at <ulink
-url="http://cygwin.com/faq/faq.using.html#faq.using.shell-scripts" />).
+<para>Beware of using non-portable shell features in your Makefiles (see tips
+at <ulink url="http://cygwin.com/faq/faq.html#faq.using.shell-scripts" />).
</para>
<para>Errors of <literal>make: execvp: /bin/sh: Illegal Argument</literal> or
<literal>make: execvp: /bin/sh: Argument list too long</literal> are often
@@ -461,7 +746,7 @@ recommend trying the latest snapshot from
<ulink url="http://cygwin.com/snapshots/" /> or building the DLL from CVS.
</para>
<para>To build a debugging version of the Cygwin DLL, you will need to follow
-the instructions at <ulink url="http://cygwin.com/faq/faq-nochunks.html#faq.programming.building-cygwin" />.
+the instructions at <ulink url="http://cygwin.com/faq/faq.html#faq.programming.building-cygwin" />.
You can also contact the mailing list for pointers (a simple test case that
demonstrates the bug is always welcome).
</para>
@@ -681,15 +966,6 @@ This is right <literal>gcc hello.cc -lstdc++</literal>.
use <literal>struct stat</literal>. It's 64 bit aware.</para>
</answer></qandaentry>
-<qandaentry id="faq.programming.undeclared-functions">
-<question><para>I use a function I know is in the API, but I still get a link error.</para></question>
-<answer>
-
-<para>The function probably isn't declared in the header files, or
-the UNICODE stuff for it isn't filled in.
-</para>
-</answer></qandaentry>
-
<qandaentry id="faq.programming.libc">
<question><para>Can you make DLLs that are linked against libc ?</para></question>
<answer>
@@ -758,17 +1034,6 @@ data types, line numbers, local variables etc.
</para>
</answer></qandaentry>
-<qandaentry id="faq.programming.x86-assembly">
-<question><para>Where can I find info on x86 assembly?</para></question>
-<answer>
-
-<para>CPU reference manuals for Intel's current chips are available in
-downloadable PDF form on Intel's web site:
-</para>
-<para><ulink url="http://developer.intel.com/">http://developer.intel.com/</ulink>
-</para>
-</answer></qandaentry>
-
<qandaentry id="faq.programming.make-scripts">
<question><para>Shell scripts aren't running properly from my makefiles?</para></question>
<answer>
@@ -849,18 +1114,4 @@ linker flag.</para></listitem>
</orderedlist></listitem></orderedlist>
</answer></qandaentry>
-<qandaentry id="faq.programming.djgpp">
-<question><para>Why not use DJGPP ?</para></question>
-<answer>
-
-<para>DJGPP is a similar idea, but for DOS instead of Win32. DJGPP uses a
-"DOS extender" to provide a more reasonable operating interface for its
-applications. The Cygwin toolset doesn't have to do this since all of
-the applications are native WIN32. Applications compiled with the
-Cygwin tools can access the Win32 API functions, so you can write
-programs which use the Windows GUI.
-</para>
-<para>You can get more info on DJGPP by following
-<ulink url="http://www.delorie.com/">http://www.delorie.com/</ulink>.
-</para></answer></qandaentry>
-
+</qandadiv>