Software Engineering with Wine - 2010

Contents

Introduction

Popular open source projects like Firefox and Chromium tend to be cross-platform, i.e. they compile and run properly on several operating systems, usually Windows, Mac OS X, and Linux.

This sounds great, but keeping the software building on all three operating systems can be a challenge. Developers working on one operating system can make changes that work great for them, but break the build on other operating systems or compilers.

Automated build-and-test servers help to some extent, but they can get bogged down. It's better if developers can at least compile the app for two operating systems on their own machine before submitting their changes.

However, Linux and Mac developers don't like having to buy a copy of Windows to run it in a virtual machine on their computers. This is where Wine comes in. Wine is a clean-room, open source, and free reimplementation of the Win32 API on top of the Unix API; it can run the Visual C++ commandline compiler on Linux or Mac OS X without a copy of Windows. This makes the build tools for Firefox happy... except for one thing: wine's implementation of cmd.exe doesn't support all the features used by Firefox's build scripts.

In particular, the batch files start-msvc8.bat and guess-msvc.bat don't work yet in Wine.

Likewise, Wine user Dima Ryazanov is trying to build his project in Wine using SCons, and is running into three cmd bugs.

Worse, Wine doesn't (or didn't until very recently) have a test suite for cmd.exe, so we don't really know what works and what doesn't.

Your mission, should you choose to accept it, is to improve Wine so it makes the above developers build scripts run properly without breaking anything.

There are many bugs and missing features in wine's cmd, but here's the short list of problems known to cause trouble for the firefox build batch files:

And here are the bugs known to cause trouble for Dima's SCons build: The team should divide up to attack these problems.

Step 1: write a conformance test for your feature

Wine uses "Test-Driven Development" to make developing easier (fewer worries about breaking code elsewhere in the tree) and to avoid regressions.

The author of wine's cmd had his own little test suite, but never submitted it, and has since lost it (oops!). So I submitted one (see the original patch, or the improved version part 1, part 2, part 3, part 4). After applying the patch, you'll need to run autoconf to regenerate the configure script before building wine.

The test suite consists of a set of batch files and their expected output. The test pass on Wine and on all versions of Windows I've tested with so far except windows NT (whoops; fix here).

To use the test suite on Linux, apply that patch (if it hasn't already been accepted into the tree), configure and build wine, then do 'make test' in the programs/cmd/tests directory.

To run it on a Windows system, do 'make crosstest' in programs/cmd/tests, then copy the resulting cmd_crosstest.exe to the windows system and run it there like this: 'cmd_crosstest batch'.

To run it on WineTestBot (our server farm running many versions of Windows), first get a WineTestBot account, then upload cmd_crosstest.exe to WineTestBot; give 'batch' as the argument, and select debug level 2 if you want to see all the output rather than just the first bad line.

Your new test should look something like the one added by this patch, e.g. it should include tests for any already-fixed bugs related to the feature, and should exercize every part of the feature that already works on wine (or that you plan to implement).

Once you have the existing cmd tests passing on Linux and Windows, add a very simple test to your local copy of programs/cmd/tests for the bug you're trying to fix, and make sure it passes on all versions of Windows (and fails on Wine).

Step 2: understand the existing code

Wine's cmd is a bit baroque, but there are several tools to help figure out what's going on.

First, there's nothing like reading the source. Curl up with a mug of coffee and read through wcmd.h and wcmdmain.c, then step through how it works on a one-line batch file contining just the line

ECHO hi
The call chain goes something like this: wmain() calls WCMD_ReadAndParseLine() and WCMD_process_commands(), which calls WCMD_execute(), which calls WCMD_echo().

Second, notice the WINE_TRACE calls in the source. To see their output, run your test like this:

WINEDEBUG=+cmd ~/wine-git/wine cmd /c foo.cmd > log 2>&1
You may want to add your own trace statements around the area you're going to be modifying.

Third, you may find it helpful to run it in a debugger; you can do this with

~/wine-git/wine winedbg cmd /c test_foo.cmd
winedbg starts running the app, but stops before main; give the command 'cont' to see it run. (I tend to only use the debugger when my code is crashing.)

Step 3: implement your new feature, submit patch, improve until accepted

Once you understand how cmd is mishandling your test case internally, you're in position to do something about it. Try to find the simplest change that will get your test case to pass.

You may find that other bugs in Wine's cmd affect your test case, but not the original program. For instance, wine's cmd outputs different whitespace when echoing commands, so you may need to use @ or ECHO OFF to work around that.

Once you have a fix, and your test is passing everywhere, generate a patch using diff or git, and send it to the team mailing list for review. After addressing any issues pointed out by the mentors on the team mailing list, send it to the wine-patches mailing list, following the workflow described in the Wine Wiki page SubmittingPatches.

"Release early, release often" is an important rule of thumb in open source projects. The sooner you get your code out into the real world, the sooner other people can test it and find bugs for you. And code that sits on your hard drive might never see the light of day. Last year's CS130 team implemented dxdiag, but neglected to start the process of sending patches to winehq soon enough. As a result, their code now sits forlorn, waiting for someone to clean it up, break it into small patches, and work to get it committed into the Wine project. So try hard to get patches submitted early in the term rather than waiting for the last few weeks.

Schedule

Here's a possible schedule for the course:

Week 1: choose task, set up development system, read the existing code, write test

Pick one of the problems listed above. If those are all taken, pick some other easy/fun feature, e.g.

Get a Linux system set up for Wine development. We can schedule an install party if needed.

Write a conformance test that shows the feature working in Windows but not in Wine. Once it passes on your Windows machine (and fails as expected on Linux), and passes on WineTestBot (including the Dutch bot), send it to the project mailing list for review.

Also, read through the cmd sources as described above, and make sure you understand how cmd works in the area around your chosen feature.

Week 2: fix the bug/implement the feature you wrote a test for in week 1

Submit your code to wine-patches after it passes review on the team mailing list. (Some features, like set /a, are too big to implement in one week, but you can do at least a trivial implementation for starters.)

Also resubmit your test, with improvements, if it hasn't been accepted yet.

Week 3: keep improving and resubmitting until accepted

If your feature was too big to do in one week, keep working on it. Be sure to ask the mentors on the team mailing list for help if you need it!

Also, it's likely that the wine maintainer found some issues with your patch, and hasn't committed it yet. Use this week to figure out what he wants and give it to him. (Remember, the maintainer is always right.)

Midterm Review

Show progress running the Firefox build scripts and Dima's SCons scripts.

At this point, at least half of the team should have submitted patches to wine-devel, and at least one student should have patches accepted into the Wine tree. If more than one student has code in by now, I'll buy a round of root beers for the team...

Weeks 4, 5, 6

If the first feature you picked was easy, and your fix and test were accepted, go ahead and do another one from the lists above. The review process should go easier the second time around.

Otherwise, keep improving and resubmitting your fix until it is accepted.

You might also run the two Firefox build batch files (after installing Visual C++ Express 2005 with winetricks, so they can detect a C compiler) to see if any other problems are lurking.

Weeks 7, 8

Unless you picked a monster feature (like SET /A or FOR /F), do one more easy cmd feature, or write and submit tests for a couple of already-implemented features (we can always use more regression tests).

Or perhaps get a game like Conway's game of life in batch running in wine's cmd. Some changes to the batch file may be required, since it was written for ms-dos. It might also turn up some wine bugs.

Final Review

Show progress running the Firefox build scripts.

Demo a batch game running on wine, maybe?


Project organization

During this project, let's try to stay in close touch.

The main repository is of course the git repository at winehq.org. However, because that one is very challenging to commit to, I'm setting up a git repository at http://github.com/dankegel/wcmd-uplift we can use until our code is ready to submit to winehq.

The mailing list ucla-cs130-wine is set up for students currently enrolled in the class. Please use this to ask questions about the project or run ideas past the coordinator or other students.

I've also set up a chat room for this project using IRC; it's at irc://irc.freenode.net/#ucla-cs130-wine

My favorite way to access IRC is with the Chatzilla plugin to Firefox (Tools / Addons / Get Addons, search for IRC). Then you can just click on the above link, and/or add it to your bookmarks.

Sometimes I use IRCII (sudo apt-get install ircii; irc -c '#ucla-cs130-wine' $USER irc.freenode.net) That's handy when I need to use irc without X (e.g., if my ISP is blocking IRC but not ssh, I can use irc at a remote computer via ssh).

Also, in person weekly meetings might be a good idea. If anyone wants those, let's set them up.


Useful links

cmd reference pages: OldNewThing posts about cmd (sometimes the replies are as interesting as the post): Other:

Generic Wine Development Documentation

www.winehq.org has a fair amount of documentation. You should at least have a look at the following:

Setting Up a Wine Development System

  1. Install a fairly recent mainstream linux distribution, e.g. Ubuntu 9.10. (Students with Windows already installed may wish to try the Wubi installer, which installs Ubuntu as if it were a Windows application.)
  2. Install the packages needed to build wine, using the commands
    wget http://winezeug.googlecode.com/svn/trunk/install-wine-deps.sh
    sudo sh install-wine-deps.sh
    
    (see RecommendedPackages).
  3. Get the Wine source tree as described at wiki.winehq.org/GitWine:
    git clone git://source.winehq.org/git/wine.git wine-git
    
    This creates a Wine source tree in a new directory named wine-git.
  4. Build Wine by doing "./configure; make" as usual in the Wine source tree.
  5. Try running some of the programs that come with Wine, e.g.
    cd ~/wine-git
    ./wine programs/cmd/cmd.exe.so
    

Running Wine's Test Suite

Once you have built Wine, it's time to run the conformance test suite. See the instructions at www.winehq.org/docs/winedev-guide/testing-wine. For example, if you're building inside the source tree:
cd ~/wine-git
make -k test  > log 2>&1
(The -k makes it continue past failing tests; the "2>&1 log" redirects both stdout and stderr to a file named "log".) This should take about five minutes. If a test hangs, you may need to kill the process or wineserver from another window.)

To see a list of failures, just look for lines with "Test failed" in them, e.g.

grep "Test failed" log | more
You can get a count of failures with wc:
grep "Test failed" log | wc
You shouldn't see more than ten or so errors in 32 bit Wine (assuming your have an nvidia graphics card).

How To Submit Changes To Wine

See http://wiki.winehq.org/SubmittingPatches.

Once you have made a change to Wine or its test suite that you're happy with, create a patch (see here and here for how), and make sure the patch applies cleanly to a fresh checkout of the Wine sources, and still builds and runs properly. If you used git to retrieve the sources, you should be able to use 'git diff > my.patch' to create a patch.

Once your patch works, add a changelog entry at the top, giving your name and the license (LGPL), and saying very briefly what it does. Then have a friend review the patch for errors, and clean up anything they found confusing or wrong.

If you're a student working in a structured project, send it to your project leader for review, and clean up any issues they find.

Finally, post it to the wine-patches mailing list, and watch for replies on the wine-devel mailing list.

If the patch isn't accepted right away, don't worry, just address any feedback you're given, and resubmit it once a week or so. Ask on wine-devel if you're unsure what's happening. Continue resubmitting until it makes it in. (Sometimes the Wine maintainer's mailbox overflows, so don't expect approval to be quick or easy.)