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