Write Cross-Platform Software
Posted 7 Jan 2002 at 00:04 UTC by goingware
Would you like to write more portable code? Do you wonder how the
developers of AbiWord,
Mozilla and the GIMP got their programs to run on
both Linux and Windows, and even other operating systems? Would you like
to develop and run your application on Linux but infect
Windows and Mac OS users with the love of Free Software? Would you like
your Linux software to run on PowerPC, ARM, S/390, Alpha and Sparc and
not just x86?
I have written my first
column of a planned
series at a new cross-platform resource on the web:
ByteSwap.net
The site is in its infancy, but I have great things planned for it.
Besides future columns, I will have a database of links to pages and software to
inform and enable cross-platform development.
I don't have the database software for this yet, but the hosting service
(Hostway) provides MySQL. If you know some software that will work well
for a dmoz or Yahoo-like index, let me know.
I invite others to write articles to publish on the site. Write me at
editor@byteswap.net to discuss
it.
I have been involved with porting and cross-platform development for
some time. Among the ports I did was moving Spellswell from Working Software from the Mac OS to
the BeOS. Also I helped ZooLib author Andy Green
prepare the framework for open source release under the MIT License by
writing a large application in it, and leading a beta test where other
developers used it to write their own applications. And now that I have
finally learned DocBook I am
writing the programmer's manual for ZooLib - it hasn't been that well
accepted yet, I think in large part because there is no documentation.
Interesting article. On the subject of frameworks, wxWindows
(wxwindows.org) is celebrating its
10th birthday early this year and definitely does not represent "least
common denominator" as far as platform features go. It offers widgets
which look native to the platform upon which it runs, and most
importantly, is available under a very attractive license.
Codingstyle.com will be running an
interview with many key developers of the wxWindows project, it should
be up on January 9th.
Why is it that cross-platform is often considered "runs on Linux and
Windows", when a much simpler start to cross-platformability would be to
get it running properly on other free operating systems, such as the
*BSDs?
Define ported.
Has either Mozilla or Gimp been ported to Windows, when neither follows the standards and practices of that OS's interfaces? For
that matter, has Mozilla or Gimp even been correctly ported to a Unix desktop? Mozilla's UI is equally custom on any OS, and Gimp
isn't a correct GNOME app.
To favor getting something compiling and running on many OSes is to tradeoff usability on all of those OSes. At most one
environment's users will get something standard. Everyone else gets something weird and different. If you're Mozilla, you choose to
make *everyone* put up with something different.
By that standard of ported, do I want to write portable apps? No way. I prefer to improve usability by adhering to standards.
Although most people don't do it, it is possible to write an application
framework that adheres to platform UI standards on multiple platforms.
For example, ZooLib places
its menu bar at the top of the screen on Mac OS, like native Mac
applications do, and at the top of the window for other OSes. On the
Mac, it uses the Appearance Manager to render its widgets, and has
renderers for each of the platforms it supports to give it a native look.
To some extent, keeping to platform UI standards may require some
customization for each platform. This is certainly possible, and
straightforward if it is managed well, but yes I understand many people
don't do it.
Perhaps a problem is chauvinism on the part of the developers. I recall
reading somewhere (it may have been here) that Gimp users on windows
complained that all the tool palettes didn't follow the document window
when the document moved into the foreground or background. The Gimp
developers responded that the windows users should get a new window
manager. But custom window managers are not available for Windows, or
at least not easily so.
One can certainly trumpet the superiority of one's favorite OS but I
feel the developer's duty is to serve the needs of his users. Maybe you
don't want to provide an MDI interface, but there are other
alternatives, such as activating all the tool palettes when the document
is activated, and hiding them when it is deactivated.
Yes of course standards compliance is good.
But let's consider two things:
- usefulness is as key measure of software
- standards are made to be changed
The Gimp is the application that convinced me that
GNU/Linux could suceed on the desktop. It fills an
essential market need - the need for a good/useful (GNU)
bitmap graphics program. Sure it behaves a little
strangely for a Windows app, but then so do lots of
native Windows apps. On the other hand I personally
prefer to have it work the same way independently
of the operating system it runs on.
For a long time, Microsoft promoted MDI as a UI standard,
but not any more. Similarly, emacs and vi are the standard
text editors for *NIX - but as growing numbers of Windows
users move to Linux - Windows style key bindings are
beginning to emerge as standards for Linux text editors.
Congratulations for starting this series of articles. I believe that
this is an excellent idea. Very unfortunately, many C/C++ developers
are not aware of the importance of writing portable code, I would like
to emphasize a few more points:
It's not about the GUI !!:
Operating systems today are extremely similar when you
look under the hood. Yet, there are very few good, simple
and efficient libraries to perform most low-level tasks
we've learned to live with daily. I'm thinking about
multi-threading, networking, DLL loading, database access,
abstract data types, and a lot of other similar features..
I'd like to point out a few remarkable achievements like
the Apache Portable Runtime
for C programmers, or the Boost
project for C++. The
Netscape Portable Runtime also comes to mind. Note that all
of these are fairly recent compared to the C and C++ languages
themselves and work reliably on a large number of platforms.
Unfortunately, many developers think that portability is only
useful when you want to code a GUI application that must run on
mostly Windows and Unix. Hence, the massive list of 'portable
frameworks' dedicated to managing "pretty windows", and which
invariably finish by providing their own threading, data types,
string management, etc.. ( WxWindows, Qt, ZooLib and a lot of
other GUI libraries come to mind..)
Of course, these "bonus features" are generally not compatible
from one framework to another one, and you end up being locked
by the set of features they want to provide and support on
multiple platforms. I think we should really separate the
GUI framework from the "runtime" when speaking about portability..
The importance of build tools !!
Aside from the program source code themselves, portability is
also inherently limited by the build tools we use to assemble our
code and data into programs on various platforms.
Things like Makefiles are supposed to be simple to write, but
that's only true when you use one compiler on one
platform. Otherwise things get extremely messy very quickly.
Of course, programs like Autoconf and Automake were born out of
the need to build portable programs on various flavors
of Unix. However, they're still pretty difficult to use on other
platforms, including Windows, except if you want to limit yourself
to gcc (and this is hardly a good idea when you want to write truly
portable code). They also do not deal very well with things like
multiple builds of the same sources (i.e. release, debug, optimised)
which are simply a requirement for any serious software
project.
Generally, the only way to deal with these limitations is to use
some additional magic (Perl scripts anyone ?) _above_ AutoConf,
AutoMake and Make.. And we all know how easy and reliable these
can be to write :-).
I thus encourage and serious developer to try alternative build
tools as soon as possible. There are a few well-crafted programs
like Jam
or Ant
that deserve to kick Make's ass in many useful projects..
All of them allow you to produce "build control" file that do not
embbed compiler directives directly, and are thus portable among
platforms and compilers. And now for some shameless plug:
I myself use Jam
and this allows me to compile my code with the following compilers:
Visual C++, Borland C++, Intel C++, Watcom C++, LCC-Win32,
Mingw GCC and Cygwin GCC on Windows. Nearly any C or C++
compiler on Unix. EMX/GCC, Visual Age C++ and Watcom on OS/2
All of this is done from a single set of "Jamfiles" so there is
no need to update compiler or platform specific control files each
time I switch toolsets.. I did not test them myself, but the source
code has been also compiled on VMS and BeOS systems since Jam is
availabel for them too, and all of this was without modifying a line
of my package.. Jam has still a few limitations, however
the Boost project is working
very hard to improve it so expect very good things about it in the
near future :-)
The importance of choice
From the ability to build and run your code on multiple platforms
with multiple compilers come the ability to choose the best tool for
the task you need. For example, on Windows, I heavily use the free
Borland C++
compiler suite during development since it provides impressive
compilation speeds and a really, really nice
Turbo
Debugger that beat GDB and its front ends in nearly all aspects
IMHO.
Of course, important milestones are compiled through GCC and Visual
C++.. This is a good opportunity to find subtle bugs because you'll
never find two compilers on this planet which will generate the same
set of warnings or errors in the case of buggy code. Also, GDB is the
only debugger that will allow you to spot really subtle bugs when
they happen.. I also often switch to Linux to be able to use "dmalloc"
and "Electric Fence", which are not available on Windows otherwise.
This freedom of choice is a great way to help you reduce your bug
count drastically. That doesn't mean they'll be a thing of the past
though, but your debugging time will be focused on really important
topic, not "=" versus "==" typographic mistakes ;-)
freetype, thank you
for your enthusiasm. I am very gratified by the response I have
received so far.
Certainly cross-platform is not just about GUI, although that is what is
usually thought about the most. A good example of a cross-platform
library that has nothing to do with the user interface is the Adaptive Communication
Environment, "An OO Network Programming Toolkit in C++".
I agree wholeheartedly that it would be a big improvement if the
different frameworks shared common libraries. After he released ZooLib
as open source, Andy Green contemplated working on a "cross-platform
framework toolkit", that would provide common functions that any
cross-platform framework would need. He approached at least one other
framework author about this, but I think because both were very busy it
didn't go anywhere.
There are some reasons each toolkit re-invents its own runtime. A big
reason, for the C++ toolkits, is the inadequacy of the C++ standard
library on some target platforms. Templates and exceptions have not
been in the language for so many years, and the standard hasn't been set
for that long at all, and it is a very complex standard that is
difficult for compiler implementers to adhere to.
A difficulty with cross-platform work is that, while I say you don't
need least common denominator behaviour in the finished product, you do
have to suffer from least common denominator support for the language
and libraries in the different development systems you use.
Evidence of this problem is the Mozilla C++ Portability
Guide, which says, among other things, not to use C++ exceptions or
templates. Doing this comes at a great cost of what you can do in C++,
and the result is workarounds that involve writing one's own low-level
libraries. I understand AbiWord
also takes this approach. The benefit is that you are portable to more
systems, especially to older systems that are not maintained well
anymore.
One doesn't have to take that approach. An entirely different
attitude is to require that the target platform have compliant compilers
and libraries available, and then to make use of standard language
features as you wish. It comes at the cost of limiting the platforms
you can run on, but it potentially speeds development. It certainly
makes the framework sourcebase smaller because you depend on libraries
others have written.
A framework that takes this approach is
Whisper,
which runs on Mac OS and Windows. The author says "Like Raven Whisper
is a modern framework that takes advantage of templates, multiple
inheritance, STL, and exceptions."
I think that common runtime libraries for frameworks will come, but I
don't think we're there yet. For example, ZooLib has its own thread
classes, and the implementation provides an "almost preemptive" thread
library for the classic Mac OS, which doesn't have preemptive threads.
It runs a scheduler whenever you try to acquire a mutex. Boost provides a thread library, but
there is no support for classic Mac OS yet, so for now it is not
possible to use Boost threads in ZooLib.
I don't know much about the netscape runtime, but I guess they are able
to make threads work on the Mac because Mozilla works on classic Mac OS.