A customer recently asked the casual but loaded question: Was it easy to port Pointwise to the Mac?
Wow, where to begin? Practically speaking, porting a large and complex piece of software from one platform to another is always challenging, often very tedious, and sometimes quite difficult. In our case we were fortunate to have made some good choices early in the design of the product that made porting to the various platforms we support (Windows, Linux, and Mac) generally straightforward. I’ll give you a brief summary of some of the critical choices we made, and in particular some of the challenges we faced when porting to Mac OS X specifically.
Design: Choose Wisely
Build on a Solid Foundation
The development of Pointwise began almost 8 years ago. One of the most important design decisions made in those early days was the choice of programming language and third-party support libraries. Our legacy meshing product, Gridgen, has a long and laborious development history, having been written originally in Fortran on the SGI IRIX platform and gradually converted to C and running on several flavors of UNIX, Windows and OS X. The initial designers of Pointwise chose C++ due to its maturity, deep support on all targeted platforms, and the vast number of tools already available for it. C++ also allowed our development team to completely rethink the workflow of the meshing process in modern, object-oriented terms. It also opened up new frontiers (i.e., challenges) for the more, um, “seasoned” members of our staff – who says you can’t teach an old dog new tricks?
Once the language and OO design philosophy was settled upon, we embarked on a key mission to evaluate and choose a library of tools that would satisfy the requirements of performance as well as provide a set of rich graphical user interface (GUI) controls. This was probably the most important decision when viewed from the standpoint of providing a consistent, flexible, state-of-the-art user experience that would be easily portable to all platforms. For us, the choice was clear: Qt (now available in open source under the LGPL) met nearly all of our requirements. Qt is straightforward to build and deploy on many platforms, and offers a rich set of controls, containers and programming constructs that would have been difficult for us to build on our own. The only problem was deciding whether to refer to it as “Q-T” or “cute” – we chose the former.
Avoid Tight Coupling Whenever Possible
Qt hides almost all of the platform details so our developers can focus on meshing functionality instead of on, say, how to interact with a filesystem. But “decoupling” goes beyond the operating system. You may already know that 100% of the meshing and geometric capabilities of Pointwise are available through a Tcl/Tk scripting layer that we call Glyph. (Gridgen also provides a Tcl/Tk scripting layer, but not 100% of its capabilities are exposed. That has a lot to do with the fact that scripting was added to Gridgen late it its life while it was designed into Pointwise from the start.) Also in Gridgen, Tcl/Tk was tightly integrated with the main body of code, which made it difficult for some of our customers to extend the scripting language in ways they desired. Pointwise implements the Glyph 2 language using standard Tcl packaging conventions. This makes it easy for a customer to, say, incorporate a relational database package or a set of their own tools and create their own meshing application.
A huge, beneficial side effect of adopting this approach early on was that it let us add a plugin interface for exporting grids to CFD solvers. Now, customers, distributors and other third-parties can implement functionality in Pointwise without our help and without even sharing the source code with us. But I digress.
Code It Right the First Time
Much of the task of porting software from one platform to another is simply the tedium of compiling a source file and fixing any errors or warnings that arise. For example, some compilers treat templates differently, while others adhere more strictly than others to language standards. (Microsoft’s Visual C++ compiler tends to be more forgiving than GNU when processing C++ template classes.) We discovered that, in almost all cases, this pain is greatly minimized by simply making sure that all developers on the team code in a consistent manner:
- write well-constructed classes,
- make proper use of containers and other tools, and
- stick to the project coding style guidelines.
Yes, I said it, a consistent coding style is invaluable when porting source code – doesn’t matter what it is, just so everyone stays on the same page. A significant part of this is enforced through continuous peer code reviews, both formal and informal.
Test Everything: Early, Often and Automatically
From the outset, we’ve relied on our Glyph scripting interface to exercise the core code. We run over 250 suites of automated test scripts every night, and on every platform we support. The scope of these tests spans from simple commands, like setting a color on an entity, to heavy workflows like anisotropic tetrahedral extrusion (T-Rex) on full geometries. When a new feature is added, supporting tests are written. When something breaks, a test is added to help ensure the fix lives forever. Our automated build and test system lets us know as soon as something fails, and it’s usually easy to see what changes were made since the last time a test worked. It also keeps track of how long a test took to run and presents that information graphically. A reliable automated test system is a must when building systems that support multiple platforms.
Tip: Use Common Development Tools
Apple’s primary development environment, Xcode, is tailored for OS X and iOS development. For those of us who don’t work exclusively (or even primarily) on a Mac, it’s not the friendliest tool to simply jump into and start using. Using Xcode would also mean that we would have to maintain another completely separate build configuration. Fortunately, since the base compiler suite and debugging kernel on Mac OS X is GNU (the same core tools that we use on linux), this meant we could simply extend our makefiles for compilation, and use the GNU debugger (gdb) when necessary. The downside is that debugging with gdb is not really any better than learning to use Xcode.
As luck would have it, Qt Software came to the rescue, albeit somewhat late, in the form of Qt Creator. Creator is a full-featured IDE that can integrate with a variety of compiler/debugger suites. On Linux and Mac, it integrates very well with the GNU tools, and it provides a consistent user interface for building and debugging code. Since we were already using GNU tools, it was a snap to use Creator, and now it is invaluable when porting code and debugging Mac-only or Linux-only problems.
Mac OS X: Thrown for a Loop
One drawback of using a scripting language (Tcl) that also has graphical capabilities (Tk), we discovered, was that of competing event loops. All modern graphical interfaces are built on object-oriented, event-driven models. The operating system (that thing that all software runs on, that passes user input to a program and processes output on a screen or other device) drives all event processing in a prescribed manner, but it differs widely from platform to platform. For the most part, Qt hides all of the platform-specific drudgery of event processing. But, we don’t support just one GUI system, we support two: Qt and Tk. (This is because you can run a Tcl/Tk application on top of the Pointwise main user interface.)
It turns out that on some platforms there are certain Tk events that get “eaten” by the Qt event loop. Which platforms? Well, we encountered instances of this problem on all our platforms, but most notably on – you guessed it – Mac OS X. In fact, this problem was perplexing enough that it forced us to delay the release of Tk scripting support until 2010. Apparently this problem is almost unique to us (yippee!), since only one third-party vendor offered any kind of solution, and not a very good one at that. So how did we solve this? Ultimately, after a lot of head-scratching and late nights the solution was some well-placed code hacks to both Qt and the version of Tk that we ship with Pointwise. Don’t worry though, Qt has since incorporated our small fixes, and the Tk changes did not impact any scripting capabilities.
One of the more challenging aspects of hacking Qt for Mac OS X involved the Cocoa API. There are two programming APIs on the Mac:
- Carbon (which is a 32-bit-only C language API that has been dropped as of OS X 10.6 “Snow Leopard”) and
- Cocoa (which is an Objective C language API and is not supported on PowerPC Macs as of OS X 10.7 “Lion”).
It turns out that we didn’t really have to address the event-eating problem with Carbon since we dragged it out long enough, when both Cocoa and Qt’s implementation on it were mature. Still, Cocoa was a bit daunting since Objective C doesn’t look a lot like C++, but is often interspersed with C++ and can be difficult to debug, particularly for us ”seasoned” developers accustomed to Windows and Linux debugging tools.
Fruits of Our Labor
So, to answer that customer’s question, 99% of the task of porting Pointwise to the Mac was straightforward due to the choices we made early in the design. The other 1% was borne out of our particular system requirements — not easy to overcome, but not insurmountable, and certainly well worth the effort for our Apple-loving customers.
Just please don’t ask us to port Pointwise to the iPad.
See the Results
Interested in a CFD mesh generator for Mac OS X? Request a free trial of Pointwise today.