Difference between revisions of "Wine Developer's Guide/Coding Practice"

From WineHQ Wiki
Jump to: navigation, search
(Why ifdef MyOS is probably a mistake.: fix markup)
(Alexandre's Bottom Line: git patches only apply with -p1)
 
(One intermediate revision by one other user not shown)
Line 51: Line 51:
 
=== Alexandre's Bottom Line ===
 
=== Alexandre's Bottom Line ===
  
“The basic rules are: no attachments, no MIME crap, no line wrapping, a single patch per mail. Basically if I can't do <code>cat raw_mail | patch -p0</code> it's in the wrong format.”
+
“The basic rules are: no attachments, no MIME crap, no line wrapping, a single patch per mail. Basically if I can't do <code>cat raw_mail | patch -p1</code> it's in the wrong format.”
  
 
== Quality Assurance ==
 
== Quality Assurance ==
Line 148: Line 148:
  
 
When adding a new language, also make sure the parameters defined in <tt>dlls/kernel32/nls/*.nls</tt> fit your local habits and language.
 
When adding a new language, also make sure the parameters defined in <tt>dlls/kernel32/nls/*.nls</tt> fit your local habits and language.
 +
 +
[[Category:Documentation]][[Category:Development]]

Latest revision as of 00:22, 22 November 2016

This chapter describes the relevant coding practices in Wine, that you should be aware of before doing any serious development in Wine.

1 Patch Format

Patches are submitted via email to the Wine patches mailing list, wine-patches@winehq.org. Your patch should include:

  • A meaningful subject (very short description of patch)
  • A long (paragraph) description of what was wrong and what is now better (recommended).
  • A change log entry (short description of what was changed).
  • The patch in “Git” format

To generate a patch using Git, first commit it to your local tree.

If you are adding a file, use git add. Commit the change using git commit. The commit message will be sent with your patch, and recorded in the commit log.

After committing the patch, you can extract it using git format-patch and send it to wine-patches using git imap-send or simply attaching it to your mail manually.

2 Some notes about style

There are a few conventions about coding style that have been adopted over the years of development. The rational for these “rules” is explained for each one.

  • No HTML mail, since patches should be in-lined and HTML turns the patch into garbage. Also it is considered bad etiquette as it uglifies the message, and is not viewable by many of the subscribers.

  • Only one change set per patch. Patches should address only one bug/problem at a time. If a lot of changes need to be made then it is preferred to break it into a series of patches. This makes it easier to find regressions.

  • Tabs are not forbidden but discouraged. A tab is defined as 8 characters and the usual amount of indentation is 4 characters.

  • C++ style comments are forbidden since some compilers choke on them.

  • Commenting out a block of code is usually done by using if (0). For example:

    /* note about reason for commenting block */
    if (0) {
    code
    code /* comments */
    code
    }
    

    The reason for using this method is that it does not require that you edit comments that may be inside the block of code and it makes sure the code gets maintained.

  • Patches should be in-lined (if you can configure your email client to not wrap lines), or attached as plain text attachments so they can be read inline. This may mean some more work for you. However it allows others to review your patch easily and decreases the chances of it being overlooked or forgotten.

  • Code is usually limited to 100 columns. It generally makes code easier to read.

  • If the patch fixes a bug in Bugzilla please provide a link to the bug in the comments of the patch. Also, mark the bug as “resolved fixed” after your patch gets committed.

2.1 Inline attachments with Outlook Express

Outlook Express is notorious for mangling attachments. Giving the patch a .txt extension and attaching will solve the problem for most mailers including Outlook. Also, there is a way to enable Outlook Express to send .diff attachments.

You need the following two things to make it work.

  1. Make sure that .diff files have “\r\n” line endings, because if OE detects that there are none it switches to quoted-printable format attachments.
  2. Using regedit add key Content Type with value text/plain to the .diff extension under HKEY_CLASSES_ROOT (same as for .txt extension). This tells OE to use Content-Type: text/plain instead of application/octet-stream.

Item #1 is important. After you hit the Send button, go to Outbox and using Properties verify the message source to make sure that the mail has the correct format. You might want to send several test emails to yourself too.

2.2 Alexandre's Bottom Line

“The basic rules are: no attachments, no MIME crap, no line wrapping, a single patch per mail. Basically if I can't do cat raw_mail | patch -p1 it's in the wrong format.”

3 Quality Assurance

(Or, “How do I get Alexandre to apply my patch quickly so I can build on it and it will not go stale?”)

Make sure your patch applies to the current Git HEAD revisions. If a bunch of patches are committed that may affect whether your patch will apply cleanly then verify that your patch does apply! git fetch; git rebase origin is your friend!

Patches must not break building Wine or cause test failures. Adding dead code should also be avoided.

Save yourself some embarrassment and run your patched code against more than just your current test example. Experience will tell you how much effort to apply here. If there are any conformance tests for the code you're working on, run them and make sure they still pass after your patch is applied. Running tests can be done by running make test. You may need to run make testclean to undo the results of a previous test run. See the “testing” guide for more details on Wine conformance tests.

4 Porting Wine to new Platforms

This document provides a few tips on porting Wine to your favorite (UNIX-based) operating system.

4.1 Why 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 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 HAVE_* symbols in Wine 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.

4.2 MyOS doesn't have the foo.h header!

This first step is to make autoconf check for this header. In configure.ac 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 autoconf and ./configure.

4.3 MyOS doesn't have the 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.ac 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.

Case 1:

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!

Case 2:

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 autoconf and ./configure.

5 Adding New Languages

This section documents the procedure for adding a new language to the list of languages that Wine can display system menus and forms in. Adding new translations is not hard as it requires no programming knowledge or special skills.

First add the language ID (most often like xx, e.g. fr for French, or xx_YY for country-specific variations, e.g. pt_BR for Brazilian Portuguese ; look in tools/wmc/po.c for a list) in the LINGUAS section of configure.ac, and in po/LINGUAS.

Language dependent resources reside in .po files in the po/ directory. Simply create the language-specific .po file using the wine.pot template:

cp po/wine.pot po/xx.po

and start translating (note the file must use UTF-8 encoding).

When adding a new language, also make sure the parameters defined in dlls/kernel32/nls/*.nls fit your local habits and language.