Skip to content

Building with CMake

Jean-Michaël Celerier edited this page Mar 26, 2015 · 19 revisions

Motivation

Make a reliable cross-platform build-system for Jamoma. The minimal CMake version required is 3.0.

CMake basics

Reference

Setup :

git clone https://github.com/Jamoma/Jamoma
# ...[clone Core & Implementations/Max, switch everything to dev]...
mkdir build
cd build

Release build on OS X with full package :

cmake -DCMAKE_BUILD_TYPE=Release "-DCMAKE_OSX_ARCHITECTURES=x86_64;i386" -DBUILD_JAMOMAMAX:Bool=True ../Jamoma 
make package -j4

Release build on Windows with full package :

cmake -DCMAKE_BUILD_TYPE=Release -DBUILD_JAMOMAMAX:Bool=True -G "Visual Studio 12 2013" ../Jamoma msbuild PACKAGE.vcxproj /p:Configuration=Release /m

Build tree

CMake is not a build system per se, but more a meta-build system, in the sense that CMake's work is to generate platform-specific build scripts, in the format chosen by the user. One can for instance generate:

  • Makefiles / Ninja (a faster(about 10% for Jamoma) make replacement by google)
  • XCode projects
  • Visual Studio solutions
  • Code::blocks, Eclipse and project files for other common IDEs

The basic syntax is :

cmake [options] ..path to a folder containing a CMakeLists.txt.. 

For Jamoma, there is a CMakeLists.txt in the umbrella repository, and another in JamomaCore. When built from umbrella, both JamomaCore and JamomaMax will be built, with the goal to extend to other implementations of Jamoma.

CMake will then generate a build tree in the folder it is called from. It is good practice to make an out-of-source build (and for Jamoma it is critical since the Max package and some test files will be copied from the source folder to the build tree).

For instance :

git clone https://github.com/Jamoma/Jamoma
... setup the branches, etc ...
mkdir build
cd build
cmake ../Jamoma

Will generate a build tree in the build folder. The rest of this document will assume that the folder hierarchy is as follows :

base folder \
 build
 Jamoma \
    Core, etc...

Targets

CMake operate with targets. When there is a CMake command to add a library, a test, or an executable, CMake will generate targets. They will map to project files for the IDE generators, or simple make targets. For instance, there are specific targets for all the core libraries (Foundation, Modular, Graph, etc...) and all the extensions. There are also some useful targets either automatically generated by CMake in every case or added for the Jamoma project. For instance :

- `ExperimentalTest` to batch-run unit tests
- `code_coverage` to run code coverage on the unit tests (added by me).
- `ALL_BUILD` behaves like `make all`
- `CLEAN` behaves like `make clean`
- `INSTALL` behaves like `make install`
- `PACKAGE` creates a platform-specific package/installer (DMG on OS X, NSIS installer on Windows, Debian / RPM package on Linux...) with the things that are to be installed by `INSTALL`.

Build operations and variables

Common switches

Debug / Release

cmake -DCMAKE_BUILD_TYPE=Debug [...]
cmake -DCMAKE_BUILD_TYPE=Release [...]

JamomaMax

cmake -DBUILD_JAMOMAMAX:Bool=True [...]

Code coverage

This requires gcov, lcov, and a Debug build.

cmake -DCMAKE_BUILD_TYPE=Debug -DCODE_COVERAGE=True [...]

Generators and platform-specific variables

Generators are chosen with the -G command line switch. cmake --help will print all the available generators for the platform.

OS X

Calling CMake without generators generates Makefiles by default. To generate XCode projects :

cmake -G "XCode" ../Jamoma/

A Jamoma.xcodeproj file is then generated in the current folder, that can be opened with XCode (however there are still problems with '~' and '=' in the name of externals, I have to check them out).

It is possible to build from the command line :

xcodebuild -target [The target, like ALL_BUILD or Foundation]

To generate XCode projects targeted for iOS : (still experimental, I only quickly tested this with the simulator and not everything builds. Also, it will only build JamomaCore.)

# iOS
cmake -G "Xcode" -DCMAKE_TOOLCHAIN_FILE=../Jamoma/Core/Shared/CMake/toolchains/iOS.cmake ../Jamoma/Core 
# Simulator
cmake -G "Xcode" -DIOS_PLATFORM=SIMULATOR -DCMAKE_TOOLCHAIN_FILE=../Jamoma/Core/Shared/CMake/toolchains/iOS.cmake ../Jamoma/Core 

To generate universal binaries (by default CMake only generates x64) :

cmake "-DCMAKE_OSX_ARCHITECTURES=x86_64;i386" ../Jamoma

To build tests statically linked : (this has to be reviewed, I haven't checked it since about two months)

cmake -DSTATIC_TESTING ../Jamoma

Windows

By default, CMake will look for an installed version of Visual Studio and generate solutions & projects for this version. To specify a version :

cmake -DCMAKE_BUILD_TYPE=[Debug or Release] -G "Visual Studio 12 2013" ../Jamoma/
cmake -DCMAKE_BUILD_TYPE=[Debug or Release] -G "Visual Studio 12 2013 (x64)" ../Jamoma/ # DOES NOT WORK YET

Jamoma has been tested with VS2013 but might work with VS2012.

This will generate a Jamoma.sln in the current folder.

To build :

msbuild [ALL_BUILD/PACKAGE/...].vcxproj /p:Configuration=[Debug or Release, according to the configuration that was used for CMake] /m

Or open the created VS solution.

Linux

cmake ../Jamoma
make -j[number of processors]

Android

This requires the (heavy) Android SDK / NDK, and the Android toolchain file : https://github.com/taka-no-me/android-cmake/tree/experimental. But after that it's as straightforward as it is for Linux.

Writing CMakeLists.txt for Jamoma subprojects

-> For a library (a simple one): https://github.com/jamoma/JamomaCore/blob/dev/Graph/library/CMakeLists.txt

-> For an extension : (showcases use of external libraries) https://github.com/jamoma/JamomaCore/blob/dev/DSP/extensions/AudioEngine/CMakeLists.txt

-> For a Max external : https://github.com/jamoma/JamomaMax/blob/dev/source/j.cue/CMakeLists.txt

Using Jamoma from external projects using CMake.

A CMake configuration file for the Jamoma project is generated. This allows other apps that would like to use Jamoma to do things as straightforward as :

project (aProject)
find_package(Jamoma 0.6 REQUIRED) #Jamoma has to be installed somewhere.

add_executable(anExecutable "main.cpp")
target_link_libraries(anExecutable WIN32 MACOSX_BUNDLE Jamoma::Foundation Jamoma::Modular)

It is also possible to generate OS X .app bundles with the Jamoma libs & extensions correctly copied

# Make a copy at build time in the CMake-generated .app
copy_in_bundle_jamoma(anExecutable ${CMAKE_BINARY_DIR}/anExecutable.app "Foundation;Modular" "MIDI;Minuit;OSC;SystemLib")
# When installing, set the correct RPATHs in the executable, plug-ins and libraries.
fixup_bundle_jamoma(${CMAKE_INSTALL_PREFIX}/anExecutable.app anExecutable "Foundation;Modular")

This is in two steps because, basically, when building an app that involves both Qt and Jamoma, the official CMake Qt scripts will override the RPATHs in ways incompatible with Jamoma, hence we have to re-overwrite them afterwards.

Known problems & TODO

  • Run the Ruby tests from CMake.
  • Maybe run the Max/MSP integrations tests too ?
  • Check that the iOS build works correctly.
  • Document the CMake code, and do a full check-up.
  • Windows x64 build.
  • Use the FOLDER command to make nice folders in IDEs.
  • Optimize the way things are linked together (for now some extensions may link with unneeded libraries, especially in JamomaMax world).
  • Document the extensions that don't build on some platforms because of missing libraries (e.g. no portaudio at all on Android).