Moving Beyond LOCATION: Reliable Techniques for Determining Build Target Paths in CMake


CMP0026: Disallow Use of the LOCATION Target Property

This policy controls how you access the location (file path) of build targets within CMake projects. It was introduced in CMake version 3.0 to promote a more modern and reliable approach for determining target locations.

Understanding the LOCATION Property

In CMake versions 2.8.12 and earlier, the LOCATION target property (and its configuration-specific variants) could be used to retrieve the final location of a build target after the build process. However, this approach had limitations:

  • Deprecated Syntax
    This property was considered outdated and discouraged by CMake developers.
  • Unreliable During Configuration
    The property might not reflect the actual location until after the build was complete, making it unsuitable for configuration-time operations.
  • Inconsistency
    The LOCATION property's behavior could vary depending on the build system generator (e.g., Makefiles, Ninja).

The New Approach

CMP0026 addresses these issues by disallowing the use of the LOCATION property. Instead, CMake recommends the following preferred methods to determine the location of build targets:

  • Direct Target Name
    Use the target name directly with commands like add_custom_command or configure_file. For example:

    add_custom_command(
        OUTPUT ${TARGET_NAME}.processed
        COMMAND process ${TARGET_NAME}
    )
    

Setting and Handling the Policy

  • Enabling/Disabling (Not Recommended)
    While you can use cmake_policy or cmake_minimum_required to explicitly set this policy to OLD (allowing LOCATION), it's generally discouraged due to potential issues and its deprecated nature.
  • CMake Version Check
    If you're using CMake 3.0 or later, CMP0026 is enabled by default, and you'll likely encounter warnings if you attempt to use the LOCATION property.

Benefits of Using Alternative Methods

By adopting the recommended approaches, you gain the following advantages:

  • Modern CMake Practices
    Aligning your code with current CMake best practices.
  • Enhanced Reliability
    You can access target locations during configuration, leading to more robust CMakeLists.txt files.
  • Improved Portability
    Generator expressions work seamlessly across different build system generators.

In Summary



Using Direct Target Name

This example shows a custom command that processes the output of a target named MY_TARGET:

add_executable(MY_TARGET source1.cpp source2.cpp)

add_custom_command(
    OUTPUT ${MY_TARGET}.processed  # Use target name directly
    COMMAND process ${MY_TARGET}  # Pass target name to the command
)

Employing Generator Expressions

This example demonstrates configuring a file based on the location of the target MY_TARGET:

add_executable(MY_TARGET source1.cpp source2.cpp)

configure_file(my_config.txt.in OUTPUT $<TARGET_FILE:MY_TARGET>.config)
  • $<TARGET_FILE:MY_TARGET>: This generator expression dynamically retrieves the final location of the MY_TARGET executable based on the build system generator (e.g., Makefile, Ninja).

Handling Potential CMP0026 Warnings (Not Recommended)

If you're working with an older project that still uses the LOCATION property and you encounter CMP0026 warnings, you could temporarily disable the policy (not recommended for long-term use):

cmake_policy(SET CMP0026 OLD)  # Disabling (discouraged)

# Code using LOCATION (may cause issues)

cmake_policy(SET CMP0026 NEW)  # Re-enabling (recommended)


Direct Target Name

  • Example:

    add_executable(MY_TARGET source1.cpp source2.cpp)
    
    add_custom_command(
        OUTPUT ${MY_TARGET}.processed
        COMMAND process ${MY_TARGET}  # Pass target name directly
    )
    
  • Use the target name directly with commands like add_custom_command, configure_file, or any other command that needs to interact with the target's location.

Generator Expressions

  • add_executable(MY_TARGET source1.cpp source2.cpp)
    
    configure_file(my_config.txt.in OUTPUT $<TARGET_FILE:MY_TARGET>.config)
    
  • Leverage generator expressions like <TARGET_FILE> to obtain the location dynamically based on the build system generator. This ensures compatibility across different build systems (e.g., Makefiles, Ninja).

Remember that these are the recommended methods in modern CMake practices. Using the LOCATION property (which CMP0026 discourages) can lead to:

  • Deprecated Syntax
    This property is considered outdated by CMake developers.
  • Unreliable During Configuration
    The location might not be available until after the build, making it unsuitable for configuration-time operations.
  • Inconsistency
    The behavior might vary depending on the build system generator.

By adopting these alternatives, you gain:

  • Modern CMake Practices
    Aligning your code with current CMake best practices.
  • Enhanced Reliability
    You can access target locations during configuration, leading to more robust CMakeLists.txt files.
  • Improved Portability
    Generator expressions work seamlessly across different build system generators.