Hello,
I was recently playing with define_property and ran into a situation where I received the error:
CMake Error (define_property): Debug
define_property Variable name “COMPANY_CACHE_VAR” does not end
with property name “CMP_CACHE_VAR”
Looking at the define_property documentation I found there is a requirement that the variable name must end with the property name. That makes sense to enforce CMake conventions. However, I have a concern about naming conflicts as well as possible confusion for those who are less familiar with the difference between variables and properties. For that reason I’m suggesting a feature to allow a separate project-defined prefix in the property name:
# Defines the property CMP_CACHE_VAR
define_property(TARGET PROPERTY CMP_CACHE_VAR
INITIALIZE_FROM_VARIABLE COMPANY_CACHE_VAR PREFIX CMP)
Alternatively, no new keyword is added and, if name validation fails in a call to define_property, CMake would strip up through the first ‘_’ and try validation again. However, this approach would require updating the documentation to indicate that the remaining identifier after the prefix still requires at least one underscore. I personally can’t think of a situation where this approach would break existing scripts.
I believe the prefix would be useful to solve both of the outlined issues. Dropping CMP_ to satisfy the naming requirement works, but I believe there is a realistic chance of a naming conflict with a future CMake property. An example of this is COMPILE_WARNING_AS_ERROR property added in CMake 3.24. Personally, I had COMPANY_WARNINGS_AS_ERRORS in my projects, which following CMake’s conventions, would become WARNINGS_AS_ERRORS. While it wasn’t a conflict in the end, it was a near miss. A prefix would avoid this issue entirely.
The second option is to name the variable COMPANY_CMP_CACHE_VAR, but that artificially extends the variable name and adds a redundant prefix. Avoiding this was part of the rationale for changing the original define_property requirements in Issue #23348.
The third, and generally accepted, option is to use the same name for both the property and the variable. I think this may lead to confusion and mistakes for new users who are less familiar with the differences between properties and variables. I presume this is the reason CMake chose to use different names in the first place. Consider the following example where the cache variable is shadowed and the new target ends up with the wrong default:
set(COMPANY_CACHE_VAR on CACHE BOOL "")
define_property(TARGET PROPERTY COMPANY_CACHE_VAR
INITIALIZE_FROM_VARIABLE COMPANY_CACHE_VAR)
add_library(mylib INTERFACE)
set_target_properties(mylib PROPERTIES COMPANY_CACHE_VAR OFF)
# Later in the script, COMPANY_CACHE_VAR now shadows the cache with the wrong value
get_property(COMPANY_CACHE_VAR TARGET mylib PROPERTY COMPANY_CACHE_VAR)
# Yet somewhere else in the script, add a new target
add_executable(mainexe IMPORTED)
get_property(_wrong_default TARGET mainexe PROPERTY COMPANY_CACHE_VAR)
# Outputs "EXE Property is OFF", which may be surprising and difficult to debug
message("EXE Property is ${_wrong_default}")
I think the above is realistic as there is a natural inclination to name the variable after the property. Allowing a prefix solves the issues as the offending line would output to the variable CMP_CACHE_VAR instead and no shadowing would have occurred:
# Different variable, so we don't accidentally shadow COMPANY_CACHE_VAR
get_property(CMP_CACHE_VAR TARGET mylib PROPERTY CMP_CACHE_VAR)
A prefix for property names would resolve what I believe to be a real issue with risking naming conflicts with future CMake properties and could reduce confusion that sharing variable and property names may introduce. Keeping the name check while allowing a different prefix I believe also keeps the spirit of tying property names to their associated cache variables.
Thank you for taking the time.
-Josh