Coming from other build systems to CMake one will quickly learn that CMake can build only one configuration at a time. In practice you need to set up multiple build directories and configure/build with CMake for each and every one.
Autotools can do static and shared builds of libraries. For CMake
most of the project would do a static build, then a shared build
by setting the CMake variable BUILD_SHARED_LIBS
to ON
.
QMake can do debug and release builds at the same time, and as we can read at Qt for Android better than ever before, it can configure multiple Android architecture configurations at the same time.
What can we do to get the same level of convenience with CMake?
Shared and static
CMake needs to have unique target names, so if we would have to build a shared and static build we would need to have different target names.
Since we need to build the same library twice, but with only
one cmake --build
invocation, it would mean that CMake needs
to call itself.
That’s it what I’m going to do. Build the same source directory in two different build directories. The add_subdirectory CMake command allows a second parameter for a build directory.
Here is what’s needed to have a library build itself shared and static:
Debug and release
If we apply the same idea to a debug and release build, we have:
This will work with command line generators like Ninja or Makefiles, but it won’t work with multi-config generators like Visual Studio.
Debug and release for Visual Studio
In order to get Visual Studio to produce a debug and release mode,
we need to be able to invoke CMake with separate --config <CONFIG>
values for Debug and Release.
Even if we fiddle with CMAKE_CONFIGURATION_TYPES the above method is not enough. msbuild will fail to build.
We need to get independent CMake runs on the same source code. Luckily CMake provides us with ExternalProject module.
ExternalProject
is meant for software downloaded from the internet, but
it also works fine with existing source code
The code looks like this:
I needed to restrict the CMAKE_CONFIGURATION_TYPES
only for the needed configuration,
and to have a custom BUILD_COMMAND
, INSTALL_COMMAND
, and to install the library.
At the end in the build directory I’ve got a lib
directory containing the two libraries.
If you have multiple libraries depending on each other, you will have to have proper CMake packages for the libraries, and set the appropriate CMAKE_PREFIX_PATH values.
Android multi architecture
In order to test the same setup for Android, I am assuming you have the Android NDK somewhere in your system.
I configured and build the project from a Windows command prompt window like this:
The CMake code which builds for armeabi-v7a
, arm64-v8a
, x86
, x86_64
is below:
I only needed to pass the ANDROID_ABI
, and CMAKE_TOOLCHAIN_FILE
variables.
Conclusion
With the technique presented here CMake can easily do multiple configuration builds in one go!