<chapter id="porting"> <title>Porting Wine to new Platforms</title> <para> This document provides a few tips on porting Wine to your favorite (UNIX-based) operating system. </para> <sect1 id="wine-porting"> <title>Porting Wine to new Platforms</title> <sect2> <title>Why <symbol>#ifdef MyOS</symbol> is probably a mistake.</title> <para> Operating systems change. Maybe yours doesn't have the <filename>foo.h</filename> header, but maybe a future version will have it. If you want to <symbol>#include <foo.h></symbol>, it doesn't matter what operating system you are using; it only matters whether <filename>foo.h</filename> is there. </para> <para> Furthermore, operating systems change names or "fork" into several ones. An <symbol>#ifdef MyOs</symbol> will break over time. </para> <para> If you use the feature of <command>autoconf</command> -- the Gnu auto-configuration utility -- wisely, you will help future porters automatically because your changes will test for <emphasis>features</emphasis>, not names of operating systems. A feature can be many things: </para> <itemizedlist> <listitem> <para> existence of a header file </para> </listitem> <listitem> <para> existence of a library function </para> </listitem> <listitem> <para> existence of libraries </para> </listitem> <listitem> <para> bugs in header files, library functions, the compiler, ... </para> </listitem> </itemizedlist> <para> You will need Gnu Autoconf, which you can get from your friendly Gnu mirror. This program takes Wine's <filename>configure.ac</filename> file and produces a <filename>configure</filename> shell script that users use to configure Wine to their system. </para> <para> There <emphasis>are</emphasis> exceptions to the "avoid <symbol>#ifdef MyOS</symbol>" rule. Wine, for example, needs the internals of the signal stack -- that cannot easily be described in terms of features. Moreover, you can not use <filename>autoconf</filename>'s <symbol>HAVE_*</symbol> symbols in Wine's headers, as these may be used by Winelib users who may not be using a <filename>configure</filename> script. </para> <para> Let's now turn to specific porting problems and how to solve them. </para> </sect2> <sect2> <title>MyOS doesn't have the <filename>foo.h</filename> header!</title> <para> This first step is to make <command>autoconf</command> check for this header. In <filename>configure.in</filename> you add a segment like this in the section that checks for header files (search for "header files"): </para> <programlisting> AC_CHECK_HEADER(foo.h, AC_DEFINE(HAVE_FOO_H)) </programlisting> <para> If your operating system supports a header file with the same contents but a different name, say <filename>bar.h</filename>, add a check for that also. </para> <para> Now you can change </para> <programlisting> #include <foo.h> </programlisting> <para> to </para> <programlisting> #ifdef HAVE_FOO_H #include <foo.h> #elif defined (HAVE_BAR_H) #include <bar.h> #endif </programlisting> <para> If your system doesn't have a corresponding header file even though it has the library functions being used, you might have to add an <symbol>#else</symbol> section to the conditional. Avoid this if you can. </para> <para> You will also need to add <symbol>#undef HAVE_FOO_H</symbol> (etc.) to <filename>include/config.h.in</filename> </para> <para> Finish up with <command>make configure</command> and <command>./configure</command>. </para> </sect2> <sect2> <title>MyOS doesn't have the <function>bar</function> function!</title> <para> A typical example of this is the <function>memmove</function> function. To solve this problem you would add <function>memmove</function> to the list of functions that <command>autoconf</command> checks for. In <filename>configure.in</filename> you search for <function>AC_CHECK_FUNCS</function> and add <function>memmove</function>. (You will notice that someone already did this for this particular function.) </para> <para> Secondly, you will also need to add <symbol>#undef HAVE_BAR</symbol> to <filename>include/config.h.in</filename> </para> <para> The next step depends on the nature of the missing function. </para> <variablelist> <varlistentry> <term>Case 1:</term> <listitem> <para> It's easy to write a complete implementation of the function. (<function>memmove</function> belongs to this case.) </para> <para> You add your implementation in <filename>misc/port.c</filename> surrounded by <symbol>#ifndef HAVE_MEMMOVE</symbol> and <symbol>#endif</symbol>. </para> <para> You might have to add a prototype for your function. If so, <filename>include/miscemu.h</filename> might be the place. Don't forget to protect that definition by <symbol>#ifndef HAVE_MEMMOVE</symbol> and <symbol>#endif</symbol> also! </para> </listitem> </varlistentry> <varlistentry> <term>Case 2:</term> <listitem> <para> A general implementation is hard, but Wine is only using a special case. </para> <para> An example is the various <function>wait</function> calls used in <function>SIGNAL_child</function> from <filename>loader/signal.c</filename>. Here we have a multi-branch case on features: </para> <programlisting> #ifdef HAVE_THIS ... #elif defined (HAVE_THAT) ... #elif defined (HAVE_SOMETHING_ELSE) ... #endif </programlisting> <para> Note that this is very different from testing on operating systems. If a new version of your operating systems comes out and adds a new function, this code will magically start using it. </para> </listitem> </varlistentry> </variablelist> <para> Finish up with <command>make configure</command> and <command>./configure</command>. </para> </sect2> </sect1> </chapter> <!-- Keep this comment at the end of the file Local variables: mode: sgml sgml-parent-document:("wine-devel.sgml" "set" "book" "part" "chapter" "") End: -->