Project

General

Profile

(Cross) Compiling DCMTK for Android

DCMTK works on many Operating Systems like Windows, Mac OS and Linux. Since mobile devices become more and more important, it makes sense to also support platforms like Android or iOS. This tutorial explains how to cross-compile DCMTK for Android, using a CMake Android toolchain built into DCMTK in connection with Google's official Android SDK and NDK. The build is supported and tested under Linux and Windows, other host platforms may work, too.

Prerequisites

Depending on your host operating system different external software packages will be required during the compilation process. Independent of the host operating system used, the following software packages are required:
  • The Android NDK, as it includes the required toolchains and runtime libraries for cross compiling.
  • The Android SDK, as it includes the Android device emulator which is used for configuration- and unit tests.
  • The CMake build system which is employed by DCMTK to configure the compilation process for Android and for providing the unit test framework.

If your operating system comes with a package manager (e.g. apt on Debian) take a look whether it provides related packages. This will most likely ease the rest of the configuration process. Additionally, if you want to use extended functionality in DCMTK based on third party libraries, these libraries are required as cross compiled binaries for Android as well.

Linux

Most Linuxes provide all additional requirements by default. Therefore, and since Android and the Android NDK are based on a Linux-based structure, it is probably the recommended host platform in order to cross-compile DCMTK for Android. Therefore it is recommended over Windows.

Microsoft Windows

The following additional packages are required for the Windows operating system:
  • MSYS is required for starting the Android device emulator as a detached asynchroneous process from CMake. It is also more comfortable for compiling and running the unit tests compared to the native Windows command prompt (cmd.exe). Make sure to add the MSYS ''bin'' directory to the PATH environment variable, otherwise CMake won't be able to detect the required executables automatically.

The Windows Version of the Android SDK is somewhat incomplete, for example the Android device emulator can not be shut down remotely by CMake (see this bug). In addition, the configuration and build steps will run much slower under Windows.

Other host operating systems

Other host operating systems are currently not supported. Unix like systems (e.g. MacOS X) may also work, but are not explicitly supported at the moment.

Setting up the Build Configuration

After installing all required software and cross compiling the individually required third party libraries, you will have to configure the Android SDK and create an emulator configuration for later use. Afterwards you may setup the project build configuration via CMake that will be used during the compilation step.

Configuring the Android device emulator

Make sure to setup the Android SDK as required for being able to run the emulator with an appropriate configuration. See for example this tutorial about the Android SDK for that purpose. Make sure to install the required system images for the API version you are going to use. When that is done create a matching Android Virtual Device (AVD) configuration, for example utilizing the AVD Manager. The configuration may look like shown in figure 1.
Setting up the build configuration via CMake
This section describes how the build configuration can be setup with CMake's graphical user interface. This is recommended when doing it for the first time, since it allows to neetly gain an overview about the available configuration parameters and provides an interactive interface which easily guides you around the possible errors in a step-by-step fashion. After you have become confortable with the relevant parameters (i.e. CMake variables) you may use CMake's commandline interface instead of the GUI, but this will not be described in this tutorial as it should be self explanatory once you understood the configuration process.
The first step is to point CMake to the source code and build directories and afterwards hit the configure button. Select Unix Makefiles on a Unix-like host operating system and MSYS Makefiles under Microsoft Windows. Choose Specify toolchain for cross-compiling and hit the Next button (see figure 2). You will then have to point CMake to a fitting Android toolchain configuration script. DCMTK provides the file android.toolchain.cmake in the CMake subdirectory for that purpose, but you may also use a different one if preferred. The toolchain file provided within DCMTK is based on a file provided by the independent OpenCV project but has been adapted slightly to fit DCMTK's special requirements. You will therefore most likely run into problems when using a different file, which you will have to fix on your own in that case.
Figure 2: Choosing the CMake generator and toolchain file Figure 1: Setting up the Android Virtual Device (AVD) configuration
After selecting the generator and toolchain file, CMake will try to detect your Android NDK and SDK. This will most likely be successfull if they were installed to an appropriate location (for example employing your operating systems package manager) and typically fail if not. If the Android SDK could not be detected, you will have to create the CMake variable ANDROID_NDK to point CMake at your NDK's location (see figure 3). The Android SDK location may be set utilizing the variable ANDROID_SDK_ROOT, which will automatically be added to the CMake cache when it is first required. You may alternatively setup the following variables manually:
  • ANDROID_ANDROID_PROGRAM - location of the android program within your SDK. Called android.bat under Windows.
  • ANDROID_ADB_PROGRAM - location of the adb program within your SDK. Called adb.exe under Windows.
  • ANDROID_EMULATOR_PROGRAM - location of the emulator program within your SDK. Called emulator.exe under Windows.

Hit Configure again after changing any of these variables, to have CMake reevaluate the changes.

Setting target device specific parameters

After the NDK's and SDK's location are known within CMake, CMake will detect all available toolchains and all present Android Virtual Device (AVD) configurations. Afterwards the configuration process will be halted, emitting an error message (see figure TODO). This does not mean that something went wrong: Emiting an error is simply the only known way to abort the CMake configuration process in the middle in order to adjust target device specific settings to your preferences before continuing the process, which has to be done before dependant configure tests are executed. The toolchain file will set all of its CMake variables to default values, which should work for many users. However, you should ensure these values match your intended purpose. Here is a list of the most important variables that should be inspected:
ANDROID_ABI - the application binary interface to use, the range of possible values depends on the installed NDK.
ANDROID_NATIVE_API_LEVEL - the application program interface version to use, please note that DCMTK requires some functions that aren't present in every API version.
ANDROID_TOOLCHAIN_NAME - the compiler toolchain to use. The NDK provides different toolchains, for example different versions of GCC and Clang.
Figure 3: Adding the Variable ''ANDROID_NDK'' to the CMake cache ANDROID_STL - the C++ standard library implementation to use. The NDK provides different STL implementations, for example the GNU STL and the multiplatform STLport.

We recommend using a shared library to decrease the individual binary's sizes, for example gnustl_shared.

Please have a look at the comments inside the Android toolchain file for more information about available CMake variables and their effects.

Independendet of the toolchain file, some more target device specific variables exist within DCMTK's configuration. These are:
  • ANDROID_EMULATOR_AVD - the Android Virtual Device configuration to use when running the emulator. Recent versions of CMake will provide a drop down list limited to all available AVDs to ease the selection. Select the AVD you prepared for this purpose.
  • ANDROID_TEMPORARY_FILES_LOCATION - the location on the target device that is used for storing temporary files. Defaults to "/cache" and needs to be changed if you don't have write access to that location on your target device.
  • ANDROID_STL_SHARED_OBJECT - this should point to the the C++ standard library implementation shared object on the host system (part of the NDK), which needs to be copied to the target device, as the created binaries depend on it. CMake will search for a file named like specified within ANDROID_STL and most likely figure it out itself. If not, please select the file manually (only required when using the shared C++ standard library, otherwise ANDROID_STL_SHARED_OBJECT-NOTFOUND is fine, too).

Other configuration parameters of DCMTK

Several additional parameters exist to control DCMTK's configuration. Have a look at this page for more information about the available options. One variable might be particularly important when targeting a mobile device with limited storage capacity:
  • BUILD_SHARED_LIBS - when enabled, this variable tells CMake to create shared objects instead of static libraries for each of the libraries DCMTK consists of. This has a similar effect like using the shared version of the C++ standard library (see above), i.e. helps reducing the individual binary's file sizes.

Generating the build configuration

After you configured all of DCMTK's settings as desired, you may finally run the configure process by hitting the ''Configure'' button again. This will start the Android device emulator with the configured AVD and run several configuration tests. On Windows, this will show the emulator's main window which allows you to keep track of the running emulator instances. This is a workaround for the bug mentioned above that doesn't allow CMake to shutdown the emulator automatically. Don't close the emulator windows until CMake tells you to do so.
When CMake is done running compiler-only configure tests, it will wait until the emulator becomes accessible and then transmit some files to the device (to the location specified as ANDROID_TEMPORARY_FILES_LOCATION). It will then run some configuration tests directly on the emulated device and download the results to the local configuration.
Hit ''Generate'' when everything is done, this will create the build scripts and configuration files in the configured format (Unix or MSYS Makefiles).

Building DCMTK

Building the DCMTK is done employing the build scripts generated during the previous step. Start the appropriate command shell (most likely a terminal emulator under Linux and MSYS under Windows) and navigate to your build directory. Then type ''make'': This will initiate the build process and create the libraries and modules DCMTK consists of with the configured settings from the previous steps. You may use ''make -jX'' where X is the number of build processes to run simultaneously, to decrease the build duration. You may also build individual components only, for example ''make dcmdata'' to only build DCMDATA and the libraries it depends on. Run ''make help'' to print a list of available build targets.
Please note that running simultaneous build processes is broken on some versions of the MSYS shell. If the build process seems to get stuck in the middle often, try using a different version of MSYS or run in single process mode only.

Running the unit tests

After building the DCMTK was successfull, you may run the included unit tests to verify DCMTK works as expected at the configured settings (e.g. ANDROID_NATIVE_API_LEVEL, ...). You can achieve that by running ''make test'' or ''ctest''. This will upload the unit tests and all dependant libraries (including anything specified as "ANDROID_STL_SHARED_OBJECT") to the emulated device. Afterwards all the testcase will be run and the results will be downloaded from the device and analyzed.
Again, on Windows you will have to shutdown the emulator manually when a message indicates it isn't required any longer.

You may run ''ctest -R <testcase-name>'' to run individual testcases only, for example ''ctest -R ofstd_thread'' to test if the threading implementation works as expected.

Installing DCMTK

You may install the created binaries and include files by running ''make install''. The install location will be the path specified as CMAKE_INSTALL_PREFIX, which defaults to the appropriate location inside your Android NDK. On the one hand this is convenient since it will allow your projects to use the DCMTK as if it was part of the NDK. But on the other hand running ''make install'' may require a priviliged user account (for write access to the install directory). Another drawback is that you end up with a "dirty" NDK directory when proceeding this way. In the end it is up to you to decide the install location and if you want to run the install step at all, or maybe just use the binaries from the build directory directly.