bernd feinman
bernd feinman

Reputation: 346

How to conditionally build a target in Release mode in CMake?

I want to build a target only in Release mode.

I tried the following:

if (CMAKE_BUILD_TYPE EQUAL "RELEASE")

but it doesn't work, because when I build with the following command

cmake --build . --config Release

it apparently doesn't set CMAKE_BUILD_TYPE.

What's the correct way to detect Release vs Debug build with modern CMake?

(I can't find a way to use generator expressions for conditionally define a target).

Upvotes: 3

Views: 1296

Answers (1)

Alex Reinking
Alex Reinking

Reputation: 20016

I want to build a target only in Release mode. [...] (I can't find a way to use generator expressions for conditionally define a target).

Although you cannot conditionally define a target based on the active configuration, you can avoid building it in certain configurations.

Suppose, for sake of motivation, that you have a library containing some release-only feature, such as extended logging or telemetry. We'll call this target MyProject_Telemetry. Now, let's rename this to MyProject_TelemetryImpl and update its ALIAS target (which I assume already exists) for safer linking:

add_library(MyProject_TelemetryImpl)
add_library(MyProject::TelemetryImpl ALIAS MyProject_TelemetryImpl)

# ... define the target here ...

Now we'll create a wrapper INTERFACE library that conditionally links to it:

add_library(MyProject::Telemetry INTERFACE)
target_link_libraries(
    MyProject::Telemetry
    INTERFACE
    "$<$<NOT:$<CONFIG:Debug>>:MyProject::TelemetryImpl>"
)

Anything that used to link to MyProject::Telemetry will now link to this interface instead. This interface is empty except for its dependency on the real library, but that dependency only exists in release modes (i.e. Release, MinSizeRel, and RelWithDebInfo).

Now, if a user builds the whole project (via make, ninja, the ALL target in VS, etc.), it will still build TelemetryImpl. To fix this, we just need to set one more property:

set_property(TARGET MyProject_TelemetryImpl PROPERTY EXCLUDE_FROM_ALL YES)

Now the real library will build only when another target depends on it. As we established, this is only true in Release mode.

Upvotes: 3

Related Questions