Understanding CMake's OUTPUT_NAME_CONFIG for Target Properties: Targets and Configurations


What is OUTPUT_NAME_CONFIG?

OUTPUT_NAME_CONFIG is a target property in CMake that allows you to specify the base name (without extension) for the output file generated by a target during the build process. However, it's unique in that it lets you define this name on a per-configuration basis.

How Does It Work?

In CMake, a configuration (e.g., Debug, Release) determines various build settings like compiler optimization levels, debugging symbols, and more. By using OUTPUT_NAME_CONFIG, you can have different output file names for different configurations.

Setting OUTPUT_NAME_CONFIG

set_target_properties(target_name PROPERTIES OUTPUT_NAME_CONFIG:<CONFIG_NAME> value)
  • value: The desired base name for the output file in that configuration.
  • <CONFIG_NAME>: The specific configuration for which you want to define the output name. You can replace this with macros like CMAKE_BUILD_TYPE to set the name based on the current configuration.
  • target_name: The name of the target you're setting the property for.

Example

set_target_properties(myProgram PROPERTIES
  OUTPUT_NAME_CONFIG RELEASE myProgram
  OUTPUT_NAME_CONFIG DEBUG myProgram_debug
)

With this configuration, when you build in Release mode, the output file will be named myProgram.exe(or the appropriate extension for your platform). When you build inDebugmode, the output file will be namedmyProgram_debug.exe`.

  • This property can be particularly useful when dealing with multiple configurations or output files with different purposes (e.g., a debug version with extra information).
  • It's a per-target property, meaning you can define different output names for different targets in the same project.
  • OUTPUT_NAME_CONFIG provides flexibility in naming output files based on build configurations.


Example 1: Multiple Configurations with Different Extensions

This example shows how to set different output file extensions based on the build configuration:

add_executable(myProgram main.cpp)

set_target_properties(myProgram PROPERTIES
  OUTPUT_NAME_CONFIG DEBUG myProgram_debug  # Output with .debug extension
  OUTPUT_NAME_CONFIG RELEASE myProgram        # Output without extension (platform-specific)
)

In this case, the output file will be named myProgram_debug.exe (or the appropriate extension) in Debug mode and myProgram.exe (or the platform-specific extension) in Release mode.

Example 2: Shared Library with Versioning

This example defines a version suffix for the shared library name in a specific configuration:

add_library(myLibrary SHARED library.cpp)

set_target_properties(myLibrary PROPERTIES
  OUTPUT_NAME_CONFIG RELEASE myLibrary        # Release version without suffix
  OUTPUT_NAME_CONFIG RELWITHDEBINFO myLibrary_v1  # Debug version with version suffix
)

Here, the shared library will be named myLibrary.so (or the platform-specific extension) in Release mode and myLibrary_v1.so in RELWITHDEBINFO mode (which typically includes debugging symbols).

Example 3: Using CMake Macros

This example utilizes CMake macros to dynamically set the output name based on configuration:

macro(set_config_output_name target_name base_name)
  set_target_properties(${target_name} PROPERTIES
    OUTPUT_NAME_CONFIG $<CONFIG:DEBUG>  ${base_name}_debug
    OUTPUT_NAME_CONFIG $<CONFIG:RELEASE> ${base_name}
  )
endmacro(set_config_output_name)

add_executable(myProgram main.cpp)
set_config_output_name(myProgram myProgram)

This approach defines a reusable macro set_config_output_name that takes the target name and base name as arguments. It then uses conditional logic based on the CONFIG macro to set the output name with or without a suffix depending on the configuration.



Using the CONFIG Suffix

CMake automatically appends a configuration suffix to the target name by default. This suffix typically follows the format:

  • Other configuration-specific suffixes depending on your build environment
  • No suffix for Release configuration
  • -Debug for Debug configuration

You can leverage this behavior without explicitly setting OUTPUT_NAME_CONFIG. For instance, if your target is named myProgram, the output files might be:

  • myProgram-Debug.exe (or platform-specific extension) in Debug mode
  • myProgram.exe (or platform-specific extension) in Release mode

Customizing Target Names

if(CMAKE_BUILD_TYPE MATCHES "Debug")
  add_executable(myProgram_debug main.cpp)
else()
  add_executable(myProgram main.cpp)
endif()

This approach creates separate targets (myProgram and myProgram_debug) for different configurations, resulting in distinct output file names.

Post-Build Events

For more complex scenarios, you might consider using CMake's post-build events. These events allow you to execute custom commands after a target is built. You can utilize these commands to rename the output file based on the configuration or perform other actions.

add_executable(myProgram main.cpp)

add_custom_command(
  TARGET myProgram
  POST_BUILD
  COMMAND ${CMAKE_COMMAND} -E COPY $<TARGET_FILE:myProgram> myProgram_${CMAKE_BUILD_TYPE}
)

This example copies the output file of myProgram and renames it with the current build type (Debug or Release) appended as a suffix.

  • For more intricate renaming logic or additional post-build actions, post-build events offer greater flexibility.
  • If you prefer leveraging CMake's automatic configuration suffixes or require separate targets for different configurations, using the CONFIG suffix or customizing target names might be suitable.
  • If you need simple configuration-based naming (e.g., adding a _debug suffix), OUTPUT_NAME_CONFIG can be a concise solution.