Conditionally execute statements depending on build type in CMake

28 views Asked by At

In a CMake project I download and build several open source projects using the ExternalProject module. I have followed a variant described in the "Superbuild Structure" chapter of Craig Scott's excellent Professional CMake book, using a common install area for all dependencies. I try to follow the same pattern for each third-party library, and will take Zlib as example here.

It works fine as long as I'm using Release build of the external projects, but if I want to build them with the same build type as the main project, I run into problems, which is that the resulting library filenames depend on the build type. I want to set a variable to the file name, but can't find a recommended way of doing that. I understand that using if(CMAKE_BUILD_TYPE STREQUAL "Debug") would only work in single configuration generators, but that it on the other hand is not possible to use generator expressions in if statements e.g. if($<CONFIG:Debug>).

Here's a working solution, but it would fail for multiple configuration generators:

cmake_minimum_required(VERSION 3.26)
project(test VERSION 1.0 LANGUAGES C CXX)
include(ExternalProject)
set(buildStageInstallDir C:/temp)

# The following if statement works only in single configuration generators:
if (CMAKE_BUILD_TYPE STREQUAL "Debug")
    set(importLibrary lib/zlibd.lib)
    set(dynamicLibrary bin/zlibd.dll)
else()
    set(importLibrary lib/zlib.lib)
    set(dynamicLibrary bin/zlib.dll)
endif()
ExternalProject_Add(
    zlib
    INSTALL_DIR ${buildStageInstallDir}
    URL https://www.zlib.net/zlib-1.3.1.tar.gz
    CMAKE_ARGS -DCMAKE_INSTALL_PREFIX:PATH=<INSTALL_DIR>
        -DCMAKE_BUILD_TYPE:STRING=$<CONFIG> # Build Zlib with the same build type as the main project
    INSTALL_BYPRODUCTS <INSTALL_DIR>/${importLibrary} # needed by Ninja generator!
)
add_library(zlib::zlib SHARED IMPORTED)
set_target_properties(zlib::zlib PROPERTIES
    IMPORTED_LOCATION ${buildStageInstallDir}/${dynamicLibrary}
    IMPORTED_IMPLIB ${buildStageInstallDir}/${importLibrary}
)
add_dependencies(zlib::zlib zlib)

Replacing the if statement with generator expressions in set does not work:

set(importLibrary $<IF:$<CONFIG:Debug>,lib/zlibd.lib,lib/zlib.lib>)
set(dynamicLibrary $<IF:$<CONFIG:Debug>,bin/zlibd.dll,bin/zlib.dll>)

That results in Ninja error: FindFirstFileExA(C:/temp/$<IF:$<CONFIG:Debug>,lib/zlibd.lib,lib): The filename, directory name, or volume label syntax is incorrect. when I try to use the zlib::zlib library, and I do understand that it is not possible to use generator expressions in that way.

I have searched various documentation and Professional CMake, but haven't found the answer: what is the recommended way of conditionally executing statements depending on build type?

0

There are 0 answers