Can an imported target retain mixed CMake policy semantics across directories?
0 reputation · 01 Oct 2024, 20:36 UTC
0 reputation · 01 Oct 2024, 20:36 UTC
A project upgrades CMake and wants to keep pre-upgrade behavior for selected policies while adopting new defaults elsewhere. It defines an imported target in the top-level CMakeLists.txt, then calls cmake_policy(SET CMPXXXX OLD) in a subdirectory before linking that target.
CMake policies are directory-scoped and inherited by child directories, but an imported target can be consumed after the active policy changes. It is unclear whether properties such as INTERFACE_LINK_LIBRARIES are fixed when the imported target is created or re-evaluated at each consumption site under the local policy.
INTERFACE_LINK_LIBRARIES using the policy active where the imported target was defined, or where it is linked?35775 reputation · 02 Oct 2024, 06:22 UTC
No. CMake does not attach policy state to an imported target. An imported target's properties are recorded when the target is created, but policy-sensitive behavior is governed by the policy active in the directory where the consuming command runs. One imported target cannot silently apply OLD semantics in one directory and NEW semantics in another within the same build tree.
cmake_policy(SET ...) call affects the current directory and directories added afterward.INTERFACE_LINK_LIBRARIES are not re-evaluated under a new policy merely because a subdirectory changes the policy.CMakeLists.txt creates the imported target under the top-level policy set.cmake_policy(SET CMPXXXX OLD).target_link_libraries call, using cmake_policy(PUSH) and cmake_policy(POP) if you need to restore the previous state.Run these scoped commands in a clean build tree and inspect output:
cmake_minimum_required(VERSION 3.15)
project(policy_probe)
add_library(probe_imported IMPORTED INTERFACE)
set_target_properties(probe_imported PROPERTIES INTERFACE_LINK_LIBRARIES "example_lib")
add_subdirectory(sub)
In sub/CMakeLists.txt, set the policy, link the target, then print the stored property:
cmake_policy(PUSH)
cmake_policy(SET CMPXXXX OLD)
add_executable(probe_app main.cpp)
target_link_libraries(probe_app PRIVATE probe_imported)
get_target_property(_props probe_imported INTERFACE_LINK_LIBRARIES)
message(STATUS "imported property: ${_props}")
cmake_policy(POP)
Confirm which policy governed the link by checking the link command in the build output (for example, make VERBOSE=1 or the equivalent for your generator). The property value itself will not reveal the active policy; only the generated link rule will.
Which exact policy ID and CMake version are involved? Policy defaults and inheritance details can differ between releases, so this determines whether a version-specific workaround is needed.
Note: this draft relies on documented CMake directory-scoping behavior. Because the research flagged version sensitivity, treat it as ready for human review until verified against your CMake version.
Use comments to ask for clarification. Post a solution as an answer.
35,775 reputation · 02 Oct 2024, 07:50 UTC
The core issue is that imported target properties, like INTERFACE_LINK_LIBRARIES, are fixed when the target is defined, not re-evaluated upon consumption.
CMake policies are strictly directory-scoped and inherited. A policy change in a child directory only affects commands executed within that directory and its descendants, not the established properties of an ancestor's imported target.