| <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: | |
| --> |