ALIAS: Add support for set_property and set_target_properties commands

Currently, getting properties from an ALIAS target retrieves the property
from the target which the alias references while setting properties results
in an error. This relaxes set_property and set_target_properties to
accept ALIAS targets and act on the referenced target, mirroring the get
behavior.

An error is raised when setting ALIAS_GLOBAL or ALIASED_TARGET on an ALIAS
target.

Closes: #19445
This commit is contained in:
Arha Gatram
2026-06-24 10:35:20 -07:00
parent c5fcc275c8
commit a121419908
19 changed files with 83 additions and 28 deletions

View File

@@ -112,11 +112,16 @@ Alias Executables
``ALIAS`` targets can be used as targets to read properties ``ALIAS`` targets can be used as targets to read properties
from, executables for custom commands and custom targets. They can also be from, executables for custom commands and custom targets. They can also be
tested for existence with the regular :command:`if(TARGET)` subcommand. tested for existence with the regular :command:`if(TARGET)` subcommand.
The ``<name>`` may not be used to modify properties of ``<target>``, that
is, it may not be used as the operand of :command:`set_property`,
:command:`set_target_properties`, :command:`target_link_libraries` etc.
An ``ALIAS`` target may not be installed or exported. An ``ALIAS`` target may not be installed or exported.
.. versionchanged:: 4.5
The ``<name>`` may be used as the operand of :command:`set_property` and
:command:`set_target_properties` to modify properties of ``<target>``. It
may not be used with the commands :command:`target_link_libraries`,
:command:`target_compile_definitions` etc. CMake 4.4 and earlier did not
allow the ``<name>`` to modify properties of ``<target>`` with
:command:`set_property` and :command:`set_target_properties`.
See Also See Also
^^^^^^^^ ^^^^^^^^

View File

@@ -317,12 +317,17 @@ Alias Libraries
``ALIAS`` targets can be used as linkable targets and as targets to ``ALIAS`` targets can be used as linkable targets and as targets to
read properties from. They can also be tested for existence with the read properties from. They can also be tested for existence with the
regular :command:`if(TARGET)` subcommand. The ``<name>`` may not be used regular :command:`if(TARGET)` subcommand. An ``ALIAS`` target may not be
to modify properties of ``<target>``, that is, it may not be used as the
operand of :command:`set_property`, :command:`set_target_properties`,
:command:`target_link_libraries` etc. An ``ALIAS`` target may not be
installed or exported. installed or exported.
.. versionchanged:: 4.5
The ``<name>`` may be used as the operand of :command:`set_property` and
:command:`set_target_properties` to modify properties of ``<target>``. It
may not be used with the commands :command:`target_link_libraries`,
:command:`target_compile_definitions` etc. CMake 4.4 and earlier did not
allow the ``<name>`` to modify properties of ``<target>`` with
:command:`set_property` and :command:`set_target_properties`.
See Also See Also
^^^^^^^^ ^^^^^^^^

View File

@@ -40,7 +40,9 @@ It must be one of the following:
Scope may name zero or more existing targets. Scope may name zero or more existing targets.
See also the :command:`set_target_properties` command. See also the :command:`set_target_properties` command.
:ref:`Alias Targets` do not support setting target properties. .. versionchanged:: 4.5
If ``<target>`` is an :ref:`Alias Target <Alias Targets>`, properties are
set on the target which the alias references.
``FILE_SET`` ``FILE_SET``
.. versionadded:: 4.3 .. versionadded:: 4.3

View File

@@ -15,7 +15,9 @@ set next. You can use any prop value pair you want and extract it
later with the :command:`get_property` or :command:`get_target_property` later with the :command:`get_property` or :command:`get_target_property`
command. command.
:ref:`Alias Targets` do not support setting target properties. .. versionchanged:: 4.5
If ``<targets>`` contains :ref:`Alias Targets`, properties are set on the
corresponding target referenced by each alias.
See Also See Also
^^^^^^^^ ^^^^^^^^

View File

@@ -1429,9 +1429,16 @@ target, which may be an :prop_tgt:`IMPORTED` target from a package, or an
target_link_libraries(exe1 Upstream::lib1) target_link_libraries(exe1 Upstream::lib1)
``ALIAS`` targets are not mutable, installable or exportable. They are ``ALIAS`` targets are not mutable, installable or exportable. They are
entirely local to the buildsystem description. A name can be tested for entirely local to the buildsystem description.
whether it is an ``ALIAS`` name by reading the :prop_tgt:`ALIASED_TARGET`
property from it: .. versionchanged:: 4.5
``ALIAS`` targets may be used as the operand for :command:`set_property` and
similar commands used to modify properties of targets. The commands operate
on the target which the alias references. CMake 4.4 and earlier did not
allow modifying targets via an ``ALIAS``.
A name can be tested for whether it is an ``ALIAS`` name by reading the
:prop_tgt:`ALIASED_TARGET` property from it:
.. code-block:: cmake .. code-block:: cmake

View File

@@ -0,0 +1,6 @@
alias-transparency
------------------
* The :command:`set_property` and :command:`set_target_properties` commands
now accept :ref:`Alias Targets`. Properties are set on the target which
the alias references.

View File

@@ -709,11 +709,14 @@ bool HandleTargetMode(cmExecutionStatus& status,
bool appendMode, bool remove) bool appendMode, bool remove)
{ {
for (std::string const& name : names) { for (std::string const& name : names) {
if (status.GetMakefile().IsAlias(name)) { // Better error message for alias properties set on an alias target.
status.SetError("can not be used on an ALIAS target."); if (propertyName == "ALIASED_TARGET" || propertyName == "ALIAS_GLOBAL") {
return false; if (status.GetMakefile().IsAlias(name)) {
status.SetError(cmStrCat("can not set property ", propertyName,
" on an ALIAS target: ", name));
return false;
}
} }
if (cmTarget* target = status.GetMakefile().FindTargetToUse(name)) { if (cmTarget* target = status.GetMakefile().FindTargetToUse(name)) {
if (target->IsSymbolic()) { if (target->IsSymbolic()) {
status.SetError("can not be used on a SYMBOLIC target."); status.SetError("can not be used on a SYMBOLIC target.");

View File

@@ -35,10 +35,6 @@ bool cmSetTargetPropertiesCommand(std::vector<std::string> const& args,
// loop over all the targets // loop over all the targets
for (std::string const& tname : cmStringRange{ args.begin(), propsIter }) { for (std::string const& tname : cmStringRange{ args.begin(), propsIter }) {
if (mf.IsAlias(tname)) {
status.SetError("can not be used on an ALIAS target.");
return false;
}
if (cmTarget* target = mf.FindTargetToUse(tname)) { if (cmTarget* target = mf.FindTargetToUse(tname)) {
if (target->IsSymbolic()) { if (target->IsSymbolic()) {
status.SetError("can not be used on a SYMBOLIC target."); status.SetError("can not be used on a SYMBOLIC target.");
@@ -46,6 +42,14 @@ bool cmSetTargetPropertiesCommand(std::vector<std::string> const& args,
} }
// loop through all the props and set them // loop through all the props and set them
for (auto k = propsIter + 1; k != args.end(); k += 2) { for (auto k = propsIter + 1; k != args.end(); k += 2) {
// Better error message for alias properties set on an alias target.
if (*k == "ALIASED_TARGET" || *k == "ALIAS_GLOBAL") {
if (mf.IsAlias(tname)) {
status.SetError(cmStrCat("can not set property ", *k,
" on an ALIAS target: ", tname));
return false;
}
}
target->SetProperty(*k, *(k + 1)); target->SetProperty(*k, *(k + 1));
target->CheckProperty(*k, &mf); target->CheckProperty(*k, &mf);
} }

View File

@@ -12,8 +12,10 @@ run_cmake(imported-global-target)
run_cmake(imported-target) run_cmake(imported-target)
run_cmake(alias-target) run_cmake(alias-target)
run_cmake(set_property) run_cmake(set_property)
run_cmake(set_property-ALIAS_GLOBAL)
run_cmake(get_property) run_cmake(get_property)
run_cmake(set_target_properties) run_cmake(set_target_properties)
run_cmake(set_target_properties-ALIAS_GLOBAL)
run_cmake(target_link_libraries) run_cmake(target_link_libraries)
run_cmake(target_include_directories) run_cmake(target_include_directories)
run_cmake(export) run_cmake(export)

View File

@@ -0,0 +1,2 @@
CMake Error at set_property-ALIAS_GLOBAL\.cmake:[0-9]+ \(set_property\):
set_property can not set property ALIAS_GLOBAL on an ALIAS target: alias

View File

@@ -0,0 +1,6 @@
enable_language(CXX)
add_library(foo empty.cpp)
add_library(alias ALIAS foo)
set_property(TARGET alias PROPERTY ALIAS_GLOBAL something)

View File

@@ -1,4 +0,0 @@
CMake Error at set_property\.cmake:8 \(set_property\):
set_property can not be used on an ALIAS target\.
Call Stack \(most recent call first\):
CMakeLists\.txt:3 \(include\)

View File

@@ -6,3 +6,8 @@ add_library(foo empty.cpp)
add_library(alias ALIAS foo) add_library(alias ALIAS foo)
set_property(TARGET alias PROPERTY ANYTHING 1) set_property(TARGET alias PROPERTY ANYTHING 1)
get_target_property(val foo ANYTHING)
if(NOT val STREQUAL "1")
message(SEND_ERROR "set_property(): Target property 'ANYTHING' set on ALIAS 'alias' has wrong value on aliased target 'foo': '${val}' instead of '1'.")
endif()

View File

@@ -0,0 +1,3 @@
CMake Error at set_target_properties-ALIAS_GLOBAL\.cmake:[0-9]+ \(set_target_properties\):
set_target_properties can not set property ALIAS_GLOBAL on an ALIAS target:
alias

View File

@@ -0,0 +1,6 @@
enable_language(CXX)
add_library(foo empty.cpp)
add_library(alias ALIAS foo)
set_target_properties(alias PROPERTIES ALIAS_GLOBAL something)

View File

@@ -1,4 +0,0 @@
CMake Error at set_target_properties\.cmake:8 \(set_target_properties\):
set_target_properties can not be used on an ALIAS target\.
Call Stack \(most recent call first\):
CMakeLists\.txt:3 \(include\)

View File

@@ -6,3 +6,8 @@ add_library(foo empty.cpp)
add_library(alias ALIAS foo) add_library(alias ALIAS foo)
set_target_properties(alias PROPERTIES ANYTHING 1) set_target_properties(alias PROPERTIES ANYTHING 1)
get_target_property(val foo ANYTHING)
if(NOT val STREQUAL "1")
message(SEND_ERROR "set_target_properties(): Target property 'ANYTHING' set on ALIAS 'alias' has wrong value on aliased target 'foo': '${val}' instead of '1'.")
endif()