Supporting a Windows port from a Unix/Linux point of view

I am the lead developer for XPLC, working mainly in a Linux (or at least, Unix) environment. One of the goals of XPLC is portability, and while we haven't ported to a great number of environments yet, we maintain a Windows port to keep us honest, figuring that things are different enough in Windows, but I have been facing a number of problems that I am sure others have encountered before.

The problem is that of the build system. On Unix, we use Autoconf to generate files included by makefiles, which has worked for us on Linux, FreeBSD, Solaris and a number of other environments.

On Windows, Visual Studio version 5, 6 and 7 all have incompatible "project" files. If you are not extra careful, machine-dependent paths and configuration items might slip in, and even if you are careful, it looks like the wizards might sometimes play us a good prank. Even then, I only have access to version 7, and while there are some version 6 project files, they are badly out of date and I have no way of updating or checking them.

I thought about making only "nmake" makefiles, so that I would have at least a remote chance of being able to maintain across compiler versions, but the Windows developers that are using XPLC don't want me to remove the ever-out-of-date project files, because they want to be able to "quickly open the project and hit the compile button" (even though in reality, they have to fix and update the project file almost every time they would like to recompile).

I suppose that in a closed source environment, a company would give the same version of Visual Studio to all their developers, but what do open source projects do?

I also had problems with old Win32 APIs changing signature between version 6 and 7, for example _findfirst changed from returning a "long" to returning a "intptr_t".

What should I conform to? How do I keep the Windows users happy? Do I have to buy every versions? How do I keep this under control? Where's my head? Am I just stupid?

Personally I wouldn't port to Windows. In my (admittedly naive) world Windows in pay-land, and why should I make stuff for free for Windows users? How many Windows-only developers port their stuff to Linux? Pretty much none, so why should I do the reverse...

But it doesn't necessarily have to be an issue: nobody's holding a gun to your head, forcing you to use build systems where each new version breaks the old versions (I hope).

To maintain any sense of sanity, i'd strongly suggest abandoning your Visual Studia project files entirely and immediately. It seems asinine to keep them, given the compatibility issues, and the fact that they
don't make a good build system.

Visual Studio is one of many IDEs, and at that a compiler specific
IDE that could be used for software development on windows.

It is bad to use visual studio files, not only because of the compatibilities between versions, but because of the lack of
interoperability between compilers of different vendors.

Using nmake would be a better idea than using project files; however,
it would be even nicer to not depend on commercial development
software:

It is possible to use GNU Autoconf on windows, take a look at
how Mozilla win32 is built. They basically use some of the Win32 GNU utilities available from the cygwin utilities package.

There is also a port of the GCC compiler for win32, called Mingw32, which is for Open Source projects, in my opinion, a better choice than commercial compilers,
since:

They're cheaper, the tools needed to compile it are obtainable by most of your users

They don't need proprietary project file formats

It's reminiscent of unix in that more things are similar
than with VC++, for instance

Ok, obviously, you don't want to alienate your windows developers, but does it make sense to require one particular proprietary compiler just because your present windows users happen to have it available?

If the only problem is that luser-developers wish to compile the project at the
push of a button, perhaps you can supply a simple batch file (named e.g.
build.bat) in your source tree which hands over to nmake.

Okay, I don't maintain it myself, but Igor Zlatkovic who
keeps the libxml2/libxslt port running after much debate, trial
and errors (like using Visual Studio project files) finally
ended up with a CLI configuration tool written in JavaScript.
then the build is done with nmake (or GNU make if configured)

If you're serious about competing with monopolists and bringing freedom to users, having a Win32 port is an excellent idea. Sure, the underlying OS is proprietary, but there's a lot of end users who'd like to use some non-sucky software, and who might eventually be interested in trying a Linux desktop--especially if all their favorite open source apps are available in both places. ;-)

If you like to use Visual Studio as a Windows IDE, then just pick your favorite version, and gently suggest that your contributors send you patches for any other IDE they want to use. (In particular, if you're a library author, there's great value in supporting all the popular IDEs with native project files.)

On a related note: If you're a C++ GUI developer, and want a good shot at portability, try wxWindows.

In Abiword we use make (with help from CygWin32 but using VC++ compiler) to provide a build system for Windows. For UNIX we use that same make or an automake/conf version. For MacOS X, only the auto* version is maintained. That means that we already maintain two build system for legacy reasons, but anyone can sync the makefiles when adding a new platform independent source file.

As for projects, we have a MSVC6 project in a SEPARATE module that we (non Windows guys), but the Windows maintainer, don't care about. The same way, I created a ProjectBuilder (Apple's MacOS X dev tools) for conveniance and store them in a different module.

So, the bottom line: stick to make (not nmake) and require CygWin32 (or MingWin32). If they really want to use MSVC, let them store projects files in a separate module.

Dropping the Windows port is not possible, as we aim to have more and more ports to less and less Unixy platforms, Windows provides a good "alien" environment that is close at hand.

The Mozilla build environment isn't so good of an example, because of what is involved (the list of requirements and the instructions for setting up a build are very long!), but the principle of using CygWin to make it work isn't too bad.

I'll combine the ideas from emk and hub: I've just moved what project files we had in a VisualC++ subdir, and I won't update them, though I'll accept patches.

Using JavaScript in the Windows Scripting Host isn't a bad idea at all, I don't think I'll do this right now, but as I try to make the Unixy build system work in Windows, I might use a Windows-specific "configure.js" like DV linked to.

Warning: I see absolutely no value in autoconf/automake.
I've done many large cross-platform products and never
found an environment that couldn't be easily accomodated
by exclusive use of the native GNU toolchain elements,
including a few judicious gmake macros, but disincluding
autoconf/automake which are an unmaintainable morass of m4.
You, on the other hand, have already embraced autoconf,
so my experience may not be relevant to your tastes.

I don't know of any good reson to support VS.NET unless you
want CLR targets. Why bother? The platform is immature
and may never be of real interest. I wouldn't spend
disproportionate resources to support something that can
be done in other ways, better.

Portability in my mind means the ability to compile and use
the code on the set of supported platforms, not the ability
to build the thing using a cheese grater. It should *run*
on a cheese grater, not build there. In fact, I like to use
cross-compilers or Java so that I can just use one build
environment (typically Linux or FreeBSD) for all supported
target platforms.

But then again, perhaps you have unstated requirements that
imply VC++. You can do that with gmake too, but if you must
use a .dsp, you could write a custom tool to generate one
from your autoconf macros and Makefile.in, if autoconf was
worth crap, which it isn't. Since it isn't, writing XSLT
code to converse a platform-neutral XML build description
into a .dsp or a gmake file as required would be a great
contribution to the evisceration of that vile insect, ant.

Back when I developed a medium-size app on MacOS7/Win32/NextStep
I just maintained separate build files for the three
environments, but mingw32 and OSX have made that unnecessary
my current project uses gmake throughout, except for the part
that will only run on Win32 (just .cab signing), which is
accomplished by firing off a .cmd script via ssh to a w2k
VMWare image.

My Win32-based partner in crime is currently installing mingw32 and is figuring it out at the moment (he is appaled that an "hello world" program is 200k stripped, something is making things statically linked I guess), so we'll definitely support that path. I plan on setting up a cross-compiling mingw32 on my workstation too.

I found that autoconf is rather manageable, and can be introduced piece-meal into a build system, but I have to agree with you on automake. I think it is a good idea, but a rather poor implementation. So many times I had a working source package that I downloaded from the Internet, then the automake-generated makefile would notice that I had automake and would then proceed to break the working package! But this is the same idea as having a platform-neutral build description turned into gmake and/or .dsp files.

And all that automake really helped with, portability-wise, is the ability to use non-GNU make. I said screw that, GNU make is required. I took the opportunity to write wickedly fast and precise non-recursive makefiles (maybe I'm masochistic, but I like hacking funny languages like make).

But even on platforms where gcc is available, subtle differences in header files and what libraries are needed make autoconf quite handy.

New Advogato Features

New HTML Parser: The long-awaited libxml2 based HTML parser
code is live. It needs further work but already handles most
markup better than the original parser.