Kitware Source Feature Article: April 2010

Kitware on Apple OS X: It Just Works, in MacPorts

Getting Kitware tools up and running on a Darwin-OSX system is not as easy as loading binaries from the Kitware severs. This is because there are binaries for CMake on OSX, but none for VTK and ITK. If you’ve rolled your own Kitware toolkits on Linux, you would think building from the source is the next step. At least this is what I did. After downloading the release bundles for CMake, VTK and ITK, configuring, compiling and installing CMake and then configuring, compiling and installing VTK and ITK, I found myself wondering.... Did I get shared libs? Where are the .so files? I went back to ccmake to check the configuration and build again. The configuration specified shared libs, but I got a bunch of .dylib files. What are they and how do I look into them? (So Google and ohhhh! We use otool, not ldd, on OSX.)

I also wanted a lot of other options, including wrapping for Python, connectivity to databases, and threading. So, I started to collect several more downloads, including binaries for Python, MySQL, and PostgreSQL. I had no idea where these binaries were installed. I was wondering - what are frameworks? Did I really ask for that? Do I really want to link against a framework? What were those config options again?

After hopping on the email list to ask for help from the gurus I ended up, several days later, with several documents on how to configure a dozen packages, lots of mysterious build and run-time dependencies, tons of email threads on several lists, and I lost a couple of handfuls of hair!

Building these tools on Darwin-OSX is not so easy. I thought to myself, there has to be a better way! I soon realized that ports exist to provide access to some of the Kitware tools. However, I also realized that they do not provide all the options that I want. And then I found MacPorts. After learning a few things about how to use and develop ports, it was clear that MacPorts provides (a) a way to effectively document the build and install process, (b) automatic resolution and installation of build and library dependencies, (c) an easy path to replicate installations across systems (including binary packages), and (d) easy maintenance of the installation and upgrade process.

MacPorts
I have provided several references at the end of this article to help other users begin working with MacPorts [1], [2], [3]. MacPorts have a few easy build and installation options for Kitware tools on OSX. What could be easier than these installation commands?

$ sudo port install cmake
$ sudo port install InsightToolkit
$ sudo port install vtk-devel

The port system has automatic detection of CMake as a build dependency, so this works too:

$ sudo port install InsightToolkit vtk-devel

If CMake is not already installed, this command will run the installation. (The build for ITK includes a build for CableSwig, so it’s not a separate build dependency.) To see what is installed for VTK and ITK, use

$ port contents vtk-devel
$ port contents InsightToolkit

Even upgrades are easy to manage. Whenever a port is updated, it can be detected with

$ sudo port selfupdate
$ port outdated

To proceed with an upgrade, try

$ sudo port upgrade outdated

To uninstall the old ports during the upgrade, use

$ sudo port upgrade –u outdated

To rebuild ports that depend on the upgraded ports, try

$ sudo port upgrade –uR outdated

Once you start adding in additional contingencies, like MySQL and Qt things can get tricky; often the solution is to simply enable a variant. For example, try a few of the following commands

$ port variants InsightToolkit
$ sudo port install InsightToolkit +examples
$ port variants vtk-devel
$ sudo port install vtk-devel +mpi +mysql

Issues with MacPorts
It may take hours to build and install Kitware libraries. Nevertheless, it saves all the headache of fetching release bundles, manual configuration, and fixing tricky link dependencies and bugs. By default, MacPorts builds from source, so it is not as efficient as some binary systems, like Yum/rpm and Debian. (If you prefer a Debian system on OSX, check out "fink".) There are options to enable creation of binary archives from your builds, which can be shipped to other systems in your domain. A significant advantage of MacPorts is the dependency resolution architecture that facilitates careful library linking to other open-source ports that can coexist with the Darwin-OSX system. The dependency resolution architecture provides library links that can be isolated from Apple system upgrades and it can facilitate integrated updates of all packages within MacPorts.

As with almost any package management system, there are some issues with complex software integration. For instance, consider the problem of integrating VTK with Qt. Just run a search for this online and you will find numerous discussions of many troubles trying to explore all the version compatibility and build contingencies to get these and other libraries to cooperate. Sure, you may choose to go it alone and get something working for your system (probably under /usr/local), but you might first consider learning MacPorts and becoming yet another contributor to solving the same problem for thousands of developers.

Some of the greatest trouble in building for OSX lies within choices for the display engine (cocoa, carbon, x11). Some of the libraries use one or another by default for various reasons. If you need to change a default display, first look at the variants for the port and, if that’s not your solution, hacking the port to provide the right variant may be the solution for you and thousands of others too.

Bugs! The best way to contact a port maintainer about any installation problem is to create a ticket at http://trac.macports.org/. Also, you might get some help from macports-users@lists.macosforge.org. If you discover functional bugs after the installation, that's likely an upstream issue in the source of the toolkit.

MacPorts for VTK
At the time this article was written there were several ports available for VTK (5.4.2 is in 'vtk-devel'). To find all the VTK ports, try a search like this:

$ port search vtk

Then, check out the description and the variants with

$ port info vtk-devel
$ port variants vtk-devel

There are variants available for documentation, wrapping, database connectivity, MPI, and so on. Almost all of the configuration options available in CMake have a variant in the port.

MacPorts for ITK
The MacPorts for ITK are available at several recent release versions. To find all the current versions available, use

$ port search InsightToolkit

To get the port description and variants, try

$ port info InsightToolkit
$ port variants InsightToolkit

The default variants are indicated with a [+] and variant contingencies may be indicated with '*requires' and '*conflicts'. At the time this article was written, the defaults included documentation, shared libs, and wrapping for Java, Python, and Tcl.

For a new installation of ITK, at the latest release available, try

$ sudo port selfupdate
$ sudo port install InsightToolkit

It's recommended that you run the installation overnight. For detailed progress on the build and install, use

$ sudo port -d install InsightToolkit

The -d option is used for 'debug' information, but also serves as a useful progress meter. When it's complete, you can see everything installed with

$ port contents InsightToolkit

ITK Upgrades
To upgrade to a new release of ITK use the following command

$ sudo port selfupdate
$ sudo port upgrade InsightToolkit

The following command can be used to remove a previous installation when performing the upgrade

$ sudo port upgrade –u InsightToolkit

The latest version can coexist with prior versions, such as ITK 3.14. The ports are designed to install into version-specific paths and to rename binaries with version-specific names. The latest release of the port should have symlinks from generic paths and binaries to the latest version specific installation.

To keep an older version after an upgrade, it may be necessary to install a prior version-specific port (e.g., "InsightToolkit314"). That process could look like this:

$ sudo port selfupdate
$ sudo port upgrade -u InsightToolkit
$ sudo port install InsightToolkit314

Wrapping for ITK
Some port hacks were required to get all the library link settings right for the Tcl and Python libraries in WrapITK/lib/ (by changing the library paths using install_name_tool). Further hacks were required for the itkwish shell script in ${prefix}/bin/itkwish and the binary in WrapITK/bin/itkwish. At the time of testing, itkwish worked and 'import itk' worked for Python 2.5. Java wrapping is also available, but it was not tested for the purposes of this article.

CMake issues
To build against a VTK or ITK library, your CMakeLists.txt may have to set the VTK_DIR or the ITK_DIR to be certain about linking

SET (ITK_DIR /opt/local/lib/InsightToolkit-3.16)
SET (VTK_DIR /opt/local/lib/vtk-5.4)

The ITK port currently adds a version-specific CMake module, based on modifications to FindITK.cmake (found in ${prefix}/share/cmake-*/Modules/). So, it may be possible to use the following for ITK:

FIND_PACKAGE(ITK-3.16 REQUIRED)

Most, if not all, of the default CMake modules will not look for libraries in the MacPorts ${prefix}, which is /opt/local by default [4].

Portfiles
For the curious, the details of the port are all in the 'Portfile' that contains pseudo-Tcl code for the build and install process. If you want to edit and install your own custom Portfile, follow the instructions on "local repositories" in the http://guide.macports.org.

The most current Portfile is in the svn sever, which can be browsed at http://svn.macosforge.org - navigate to the trunk/dports/ area of interest. For the ports currently in sync on your system, view their properties and content using

$ port file InsightToolkit
$ port cat InsightToolkit

Development with MacPorts: InsightToolkit
For a MacPorts package, most of the library dependencies are configured for other open-source packages provided by MacPorts (some utilities or libraries may be provided by Apple). To see dependencies of a port, try

$ port deps InsightToolkit

To take advantage of this when developing ITK, first learn how to create a "local repository" [5]. Once you have a local repository, copy the current Portfile for ITK so that you can modify it (find it using 'port file InsightToolkit').

The port installation process actually comprises several phases [5]. A developer can stop the installation after the build phase (see 'man port' for all the developer targets). At that point, there is a complete source tree and a separate build tree (with no tweaks to the Portfile, you get a release version of ITK, see 'port info InsightToolkit'). To try this

$ sudo port build InsightToolkit
$ macportPath="/opt/local/var/macports"
$ buildPath=${macportPath}/build/*InsightToolkit/
$ ls $buildPath

Then you might try to develop directly in the MacPorts build tree. If you're tempted to copy the InsightToolkit tree somewhere else to develop with it, there are some rpath issues to contend with. One problem with moving the build tree somewhere else is that the OSX convention is to use rpath, so the build tree has a lot of specific links within the build tree (many of these are reset during the "destroot" phase and there are a ton of hacks in the InsightToolkit port to get the rpath right after the "destroot" phase).

Use the following commands if you need to check or correct any CMake configuration settings, or if you need to read and edit your Portfile

$ sudo port configure InsightToolkit + <VARIANTS>
$ cd $buildPath # see above
$ sudo cmake -LAH ../InsightTookit-<version>

If you develop directly in the MacPorts build tree, use gmake directly in the build path or rebuild with 'port build InsightToolkit' (this should be an incremental build, unless the Portfile is changed). If you use the port build command, it is likely to say the build is complete; to override that you could use the -f flag or you can edit the 'state' file (work/.macports.InsightToolkit.state in the build path) to remove the line that indicates the build is done. The port command can sometimes clean out a build tree, but that can be disabled with a -k option to keep the working build tree. For instance, if you run all the phases of a full installation, without a -k option, the MacPorts install process will 'clean' away the entire source and build trees (that's the default set in ${prefix}/etc/macports/macports.config).

If you need a current CVS source tree, tweak the Portfile in your local repository. Just modify the version definition and the fetch phase, which can be configured to use CVS retrieval [5]. The Portfile assumes there is a release version and the version string is used throughout the Portfile to provide version specific installations (you may need to set a pseudo-version string). Note that version, epoch, and revision strings are used by port to identify the most current release for installation.

Acknowledgements
This work involved help from generous developers in the open source community, including folks dwelling @cmake.org, @itk.org, @vtk.org (Bill Lorensen, Luis Ibáñez , David Cole, Gaëtan Lehmann, Sean McBride, Michael Jackson, et al.) and the folks @macports.org (Bryan Blackburn, Jeremy Huddleston, Jeremy Lavergne, Rainer Müller, Toby Peterson, Joshua Root, Frank Schmia, Ryan Schmidt, et al.). This work was supported by NIH grant # UL1 DE019608.

Online Resources

  • For updates and additional details, see the ITK_MacPorts_Package_Maintainers page at http://www.itk.org/Wiki/.
  • There is a general reference for OS-X developers at http://developer.apple.com/mac/library/navigation/index.html
  • For topics on programming with Mach object files, see:
    http://developer.apple.com/Mac/library/documentation/DeveloperTools/Conceptual/MachOTopics/

References
[1]  http://www.macports.org
[2]  http://trac.macports.org/wiki/InstallingMacPorts
[3]  http://trac.macports.org/wiki/FAQ
[4]  See http://trac.macports.org/wiki/FAQ for more info.
[5]  Learn how to create a local repository, read more about the port installation process, and the advanced fetch phase at http://guide.macports.org

Darren Weber  Darren Weber is staff scientist at the Buck Institute for Age Research (Novato, CA) where he works on microscopy image processing. Formerly, he was a postdoctoral fellow at UCSF, working in human brain imaging to investigate attention systems. He holds a PhD in cognitive neuroscience from The Flinders University of South Australia. He enjoys quality time with his daughter, mountain biking in the Marin open-space, and the Zen path to enlightenment. Contact him at psdlw.users.sf.net or dweber.consulting@gmail.com.