C++ Compiler Review - Part 1
Written by Gordon Zeglinski
- 1 Introduction
- 2 Visual Age C++ for OS/2 version 3.0
- 3 WATCOM C/C++ 10a
- 4 Wrapping Things Up
This issue kicks off our look at the various C/C++ compilers for OS/2. We will look at VisualAge C++, Watcom C/C++ 10a, Metaware High C/C++ 3.32 and hopefully Borland C++ 2.0. We start by giving an overview of the development environment and the features of each compiler. After we look at what each compiler has to offer, we will compare the executables generated by each compiler (size and speed) as well as the compile times for each compiler. These tests will consist of compiling various OS/2 utilities (like unzip, zip, POVRay, sysbench, etc.), a C++ test program, a Standardized Template Library (STL) example, and the source code to AdeptXBBS.
In this issue, we will look at Watcom C/C++ version 10 and IBM's Visual Age C++ (C-Set++ 3.0).
Before we start, I'll state my own compiler background. For the last 2 years, I have been using C-Set++ 2.x to develop OS/2 code. I've become very familiar with this environment, and invariably I will use it as the base to which I formulate qualitative statements. A review of C-Set++ 2.1 appeared in volume 1, issue 5 of EDM/2.
All the compilers will be run on a 486 DX2/66 MHz PC clone with 20M of RAM running Warp Fullpack.
Visual Age C++ for OS/2 version 3.0
A full install of Visual Age C++ (VAC++) requires about 180M of disk space. It generates only 32-bit OS/2 programs. This package is the successor to C-Set++ version 2.1. Thus, comparing it to C-Set++ 2.1 is natural.
VAC++ has many new features over C-Set++ 2.1. Officially they include:
- Performance improvements in the compiler and linker
- Direct to SOM (DTS) support in the compiler
- New Class Browser
- Live Parsing Editor
- The Visual Builder - an object oriented graphical program code generator
- "Open Class Library" - allows C++ applications to be portable to multiple platforms (Unix, Power PC, Windows 32-bit, etc.) when VisualAge becomes available for these platforms
- Database access classes
- Multimedia classes
- Workframe 3.0
Installation over C-Set++ 2.1 was somewhat of a pain. The old copy of C-Set++ must be completely deleted and all references to it have to be removed from CONFIG.SYS. The install uses the standard CID used by many new IBM products. Other than manually having to clean up the old install, it's a fairly simple installation. The Warp toolkit, workframe, compiler and related tools are all installed at the same time. Once you setup the install, it will successfully complete unattended. Considering it takes about 30 minutes to install off a double speed CD drive, it's great being able to leave the machine alone and go do something useful. One problem with the Warp toolkit is that it messes up the environment variables need by the SOM Developer's Toolkit (if you have this toolkit installed). Some manual tweaking will be necessary to get the SOM toolkit working properly again.
As in C-Set++ 2.1, the compiler needs a fair bit of RAM and is primarily disk bound on this system. The compiler is about 1.3 times slower compiling a large C based project than C-Set++ 2.1. Also the compiler seems to be more RAM hungry as well. However, the compiler is noticeably faster during the linking of C++ code that uses templates. In addition to the DTS support, the C runtime library now has new functions that improve heap maintenance. In addition to multiple heaps, heap checking functions are now supported. POSIX locale's and support functions have been added as well.
I've run into several optimizer bugs while testing the compiler. Fortunately, these bugs have been fixed in the compiler CSD that was recently released. This CSD seems to reduce the compiler's memory consumption slightly as well. I still have one outstanding bug report with technical support: calling PrfOpenProfile() causing an access violation exception. Migrating existing applications to VAC++ may require a bit of work. If you are packaging your own copy of the C runtime library, you will need to redo the DEF file that controls which functions you are exporting. As well, the names of several libraries have changed. If you are explicitly linking to any of these libraries, you will have to change their names in your makefiles.
The Workframe/2 product has always been a flexible and easily extended programming environment. Version 3.0 is completely different than version 2.1. It combines some some of the concepts of both Workframe 1.0 and 2.1 into a new easy to understand package. However, if you had used version 2.1, you will be scratching your head for a while as you relearn how to do things. (It will be a long while, too.)
Something weird is going on with the Workframe, too; everyone I've talked to outside of IBM has significant performance problems. For instance, pop-up menus take seconds to appear, and anything involving filling in the project's filenames takes almost half a minute to finish. During this time, the CPU usage goes way up and the system becomes sluggish. One person inside IBM, who is extremely knowledgeable about the inner's of the Workframe, has reported performance levels that are FAR better than what I've seen.
In addition to the performance problem, MAKEMAKE doesn't always generate makefiles that work. I tried to migrate my WF version 2.1 projects to version 3.0, but the process took too long and was awkward. It was faster creating new 3.0 projects from scratch.
So, let's start by forgetting all we know about WF 2.1 and throwing away all our previous projects. How hard is it to get a project working? Unlike version 2.1, version 3.0 comes properly configured. To start a new project, you drag out and drop a copy of the project template. Then, you open its settings to configure the working directory, target, and the various build parameters. There are several great new features that should significantly reduce the amount of time it takes to configure a new project or toggle a project from "development mode" to "distribution mode". In version 2.1 one had to have multiple projects one for each mode. This made it extremely awkward to toggle a project's mode. "Build Smarts" in version 3.0 makes this easy.
Overall, version 3.0 is more stable and easy to start using than version 2.1. However, the performance problems and the faulty MAKEMAKE result in version 3.0 being less useful than version 2.1.
IPMD version 2.x (the debugger in C-Set++ 2.x) had been the OS/2 debugger to beat. It has many features to aid in debugging PM and multi-threaded programs effectively. Version 3.0 adds to this feature list but removes the "hierarchy browser". (I always wondered why they put a C++ hierarchy browser in the debugger in the first place. It merely duplicates some of the functionality in the browser.) A quick summary of the new features include:
- child process debugging - allows processes started by the debugged program to be debugged.
- exception filtering - allows the debugger to be configured to ignore certain exceptions
- SOM support - allows SOM classes to be monitored in the monitor windows.
- Check heap when stopping - the debugger checks the heap when the program stops executing (ie. at a breakpoint or after a step command)
- improved call stack now displays more information about the stack usage
The heap check function is particularly useful when searching for memory corruption. The strange thing, though, is that there isn't a way to check the heap at any time. The heap can only be automatically checked when the debugged program has been stopped by the debugger. The PM Message Spy and Window Analysis functions are still present and have been redesigned to improve functionality.
Overall, the debugger's feature set has been greatly improved. However, it has numerous bugs which make it less useful than the previous version. Following is a brief list of problems I've encountered while moving 3 medium-to-large programs to VAC++:
- in asynchronous debug mode, the debugger "looses control" of the PM program. It's as if the debugger can't terminate the debugged program. Trying to "restart" the application results in the application being run until the user terminates the application. Once terminated, the debugger "restarts" the application.
- in syncronous mode, trying to step into (pressing "I") a function will result in the debugger hanging.
- after an access violation exception occurs in an OS/2 DLL, doing anything other than continuing to execute the program can result in the debugger soft hanging the system.
- in syncronous mode, doing a lot of stepping over (pressing "O") can result in hanging the debugger.
- occasionally, when hitting a break point in thread 10 or 11 of the program, the debugger crashes with an access violation in one of its DLLs.
Note: all of these bugs are reproducible in all 3 of the ported applications while debugging multithreaded C or C++ PM code.
Because stepping into or over functions is a fundamental feature of a debugger and the severity of the other bugs I found, I have to say that the debugger is presently useless for PM programs. I don't have any large text mode programs to test the debugger on so it may very well work fine for these types of applications.
The browser now has support for SOM classes and has a new interface. When running at 1280x1024, it would crash if I tried to open a graphical view. Reducing the resolution to 800x600 (used for the screen shots) allowed the graphical view to work. A nice feature is that the file menu has options to load in the browser information for classes in the Open Class library; this makes the browser a good way to see how third party libraries are designed.
The profiler in version 2.1 was an excellent tool for gathering information on how your program runs. To profile the program it has to be compiled with profiling hooks inserted into the generated code by the compiler. The hooks are used to inform the profiler when a function is called. The result is that a highly accurate map of program execution can be generated, which can then be viewed in a multitude of ways to show time-based or calling-chain information.
The major improvements to version 3.0 are support to trace up to 64 threads, trace runtime-loaded DLLs, and the ability to start and stop tracing any time during an applications execution. The only problem with version 3.0 is that it crashes on startup.
The visual builder is written in Smalltalk and it needs a lot of memory. Most people I talk to say to run the builder well, you need 32M of RAM. I gave it a try on this system the HD was trashing a fair bit and the builder was sluggish, but it looked nice. Its design is very object-oriented and fairly easy to pick up. If it only would use less memory...
Open Class Library
The Open Class Library is designed to allow one's C++ code to be easily moved from one platform to another. There is a price to pay for portability, though. The library is quite large and needs a fair bit of memory at runtime. For small projects, it may be better to simply write the code to the raw API. The class supports various objects to manipulate the user-interface, collection classes, and I/O streams. The most notable improvements to the user interface support is the inclusion of toolbar support, 2-D graphics, animated buttons and flyover help. Flyover help is textual information that appears by the mouse when the mouse is positioned over a button or toolbar element.
Note: a CSD for this component is available.
As usual, the amount of paper documents is kept to a minimum. All documentation is on-line in either INF or BOO format. The INF documents have been refined over C-Set++ 2.1 in that they are now easier to use and search. For the paper junky, Postscript files are included.
Within days of getting VAC++, a CSD for the compiler and Open Class library were available. The compiler CSD lists the optimization bug I found while compiling unzip as fixed, but it did not fix the problem I have while calling PrfOpenProfile(). As a whole, this package has many excellent features, many of which should make code development much easier and faster. Unfortunately, it presently has too many bugs to act as a replacement for large projects developed under C-Set++ 2.1.
Given the C-Set++ team's track record with providing fixes for C-Set++ 2.1, though, I think that once we get a round of CSDs for all the components, this will be the compiler package for OS/2. It's likely that by the time a new project grows to the stage where the bugs I have found are important, there will be CSDs out to fix them.
WATCOM C/C++ 10a
Watcom C/C++ 10a requires about 180M of disk space for a full installation. This includes support for:
- 16-bit development for the following platforms:
- OS/2 1.x
- Windows 3.x applications
- 32-bit development for the following platforms:
- 32-bit OS/2 2.x
- extended DOS
- Windows NT
- Win 3.x using a proprietary windows extender
- Novell NLMs
- AutoCAD ADS applications
[Editor's note - I believe it also supports QNX development.]
The package includes a multi-platform GUI and text mode debugger, a class browser, a profiler, a GUI and text mode editor, a windows resource editor, OS/2 2.1 toolkit, SOM 2.0 developers toolkit, and Microsoft's foundation classes for Windows. (Yes, the Windows development tools are richer than the tools for OS/2 PM development.) There are no message "spy" utilities, window hierarchy utilities, etc. for PM development. IBM's Developers Connection CD's include basic applications that allow the developer to spy on messages, etc. Having PM-related debugging features integrated into the debugger is advantageous when developing PM apps, though. Also, the OS/2 version of the text editor isn't PM based. The biggest letdown with the package is that there are more Windows utilities than OS/2 ones. The main components of the package, however, have native OS/2 support.
A complaint that I have is that the installation program needs to be polished. While it is capable of copying the most of files to the HD, it only partially configures the system. It doesn't set the INCLUDE or LIB paths at all, configure the DOS AUTOEXEC.BAT, or setup the Windows environments (when installing Windows cross platform support). Also, when running Warp you have to edit the CONFIG.SYS after installing Watcom but before rebooting. You must move the ...\WATCOM\BINP\DLL;...\WATCOM\SOM\LIB to the end of your LIBPATH otherwise the WPS will hang when you reboot due to a SOM version difference.
The compiler is lean and mean. Compile speed has been greatly improved over that of Watcom C/C++ 9.5. In fact this compiler is now considerably faster than C-Set++ 2.1. As with version 9.5, the compiler is easy on your HD because it is primarily CPU bound. Thus, a faster CPU will have a dramatic effect on compilation time.
The part I like the most about the compiler is its cross-platform capabilities. The 32-bit OS/2 compiler can generate code for any 32-bit target platform. Similarly, the 16-bit compiler can generate code for any 16-bit target platform. In fact, I used the 16-bit OS/2 compiler to create a Windows 3.x 16-bit applications. (If you have to write Windows programs you might as well use an OS/2 native development environment!) Another bonus is that the package ships with an assembler. Combining the 16-bit C/C++ compiler with the assembler, you have a great OS/2 device driver development environment. (It beats MSC 6.0 + MASM any day, in my opinion.)
The IDE is somewhat similar to the Borland C++ IDE - it's easy to use and fairly intuitive. Several targets can be grouped into a single project. However, the configuring the IDE is not straightforward. I couldn't find any menus or documentation on how to add support for different tools into the IDE. By default, the IDE expects all C and C++ files to use the suffixes .C and .CPP respectively. This is annoying if you want to distinguish between the "type" of C code. An interesting feature, though, is that you can assign specific compiler switches to individual files. Typically, IDE's only allow you to configure a set of switches for a given file type. All .C files must then use the same switches. This is not the case for the Watcom IDE.
My biggest complaints about the IDE are that it can crash when you least want it to (usually right after making a lot of changes to the project), it uses EPM as its editor, and it needs a bit more polish. Once it's polished up a bit and configuration is made easier it should be great.
The debugger has both a PM and text mode version. The PM version, though, is essentially the text mode debugger in PM version. It lacks any PM-specific features and is rather plain. A useful feature is that it can execute macros when a breakpoint is encountered. Its biggest feature is that the OS/2 native debugger can be used to "remote" debug DOS and Windows programs. This "remote" debugging can be performed on a networked machine or on the local machine. Unfortunately this feature doesn't work completely under Warp.
Also, debugging multi-threaded programs under Warp needs a special command line switch (see http://www.watcom.on.ca for info). These problems are supposed to be fixed in version 10.5, though. The debug information can be stored in SYM files, giving you the advantage of not having to rebuild the executable to make a distributable form of your code.
The browser lets you view inheritance information and the relationship between functions in a source file. The biggest problem with the browser is that it includes all the structures and classes. This can make it quite hard to find the class you are interested in, if you include or . While you can selectively remove objects from the inheritance view, there is no way to remove or include all objects using criteria such as where they are defined, how they are defined, etc. The result is that one often has to remove all the objects from the inheritance view and then add back those that one is interested in. An editor can be launched from the browser to modify the source code. (Note: the IDE crashed while launching the editor, but I have not been able to reproduce this.)
The profiler displays the data gathered by the sampler. Unfortunately the sampler didn't work properly under Warp. While trying to sample a multi-threaded PM application, the sampler would report an internal error when the sampled program terminated.
The basic package includes compiler and tools on CD along with a getting started book. The documentation package is extra. It includes the following:
- Watcom Graphical Tools User's Guide
- Watcom Tools User Guide
- Watcom C++ Class Library Reference
- Watcom C/C++ User's Guide
- Watcom C Library Reference
- Watcom Linker User's Guide
- Watcom Programmer's Guide
- Watcom Debugger User's Guide
- Watcom C Language Reference *
- The C++ Programming Language, second Edition by Bjarne Stroustrup (see note below).
- Bjarne Stroustrup's book is not found in the online OS/2 documentation, of course.
- The book The C++ Programming Language is an excellent reference and is not specific to the Watcom compiler. The rest of the books are rather hard to follow, though. It's sometimes hard to find the information that deals with the particular host and target environment you are using. I suppose this is the price one pays when the package supports so many target environments.
The Watcom package allows one to make applications 16 and 32-bit applications for OS/2, DOS and Windows (NT, et al.) all from an OS/2-based environment. The compiler generates very tight, fast code and does this relatively fast. The incompatibilities it has with Warp should be taken care of in version 10.5. In particular, this package - when combined with OS/2 - makes an excellent DOS and Windows development environment. Its biggest weakness is the lack of any PM specific functions in its debugger, and its Warp incompatibilities.
Wrapping Things Up
In this issue, we looked at Watcom C/C++ 10a and Visual Age C++ version 3.0. Watcom C/C++ 10.0 was written before the release of Warp. While its debugger and profiler have problems running under Warp, a new version of Watcom C/C++ has just been released which I am told is Warp-friendly. Watcom C/C++ makes a good multi-platform compiler although it would be even better if it included some multi-platform GUI objects.
Visual Age C++ comes with a class library designed for cross platform usage and a nice visual builder that utilizes this class library. The biggest problem with Visual Age C++ is that currently it is has too many bugs in its tools to be useful for handling large applications where a debugger and profiler may be needed.
In the next issue we will look at the Metaware High C/C++ compiler and possibly Borland C/C++ for OS/2. We will also see how well each compiler generates various C and C++ code, and test their C++ features.