ALIAS: Add support for target_* commands

Now that set_property and set_target_properties support ALIAS targets,
we need to extend support to all the target_* type commands that modify
target properties.

Relaxes target_compile_definitions, target_compile_features,
target_compile_options, target_include_directories,
target_link_directories, target_link_libraries, target_link_options,
target_precompile_headers, and target_sources to now accept ALIAS
targets. These commands set properties on the target which the alias
references.
This commit is contained in:
Arha Gatram
2026-06-15 15:32:01 -07:00
committed by Brad King
parent 3b327695aa
commit 79e421b053
31 changed files with 173 additions and 59 deletions

View File

@@ -115,12 +115,10 @@ tested for existence with the regular :command:`if(TARGET)` subcommand.
An ``ALIAS`` target may not be installed or exported. An ``ALIAS`` target may not be installed or exported.
.. versionchanged:: 4.5 .. versionchanged:: 4.5
The ``<name>`` may be used as the operand of :command:`set_property` and The ``<name>`` may be used as the operand of :command:`set_property`,
:command:`set_target_properties` to modify properties of ``<target>``. It :command:`set_target_properties`, :command:`target_link_libraries`, etc. to
may not be used with the commands :command:`target_link_libraries`, modify properties of ``<target>``. CMake 4.4 and earlier did not allow the
:command:`target_compile_definitions` etc. CMake 4.4 and earlier did not ``<name>`` to modify properties of ``<target>``.
allow the ``<name>`` to modify properties of ``<target>`` with
:command:`set_property` and :command:`set_target_properties`.
See Also See Also
^^^^^^^^ ^^^^^^^^

View File

@@ -321,12 +321,10 @@ regular :command:`if(TARGET)` subcommand. An ``ALIAS`` target may not be
installed or exported. installed or exported.
.. versionchanged:: 4.5 .. versionchanged:: 4.5
The ``<name>`` may be used as the operand of :command:`set_property` and The ``<name>`` may be used as the operand of :command:`set_property`,
:command:`set_target_properties` to modify properties of ``<target>``. It :command:`set_target_properties`, :command:`target_link_libraries`, etc. to
may not be used with the commands :command:`target_link_libraries`, modify properties of ``<target>``. CMake 4.4 and earlier did not allow the
:command:`target_compile_definitions` etc. CMake 4.4 and earlier did not ``<name>`` to modify properties of ``<target>``.
allow the ``<name>`` to modify properties of ``<target>`` with
:command:`set_property` and :command:`set_target_properties`.
See Also See Also
^^^^^^^^ ^^^^^^^^

View File

@@ -11,8 +11,11 @@ Add compile definitions to a target.
Specifies compile definitions to use when compiling a given ``<target>``. The Specifies compile definitions to use when compiling a given ``<target>``. The
named ``<target>`` must have been created by a command such as named ``<target>`` must have been created by a command such as
:command:`add_executable` or :command:`add_library` and must not be an :command:`add_executable` or :command:`add_library`.
:ref:`ALIAS target <Alias Targets>`.
.. versionchanged:: 4.5
If ``<target>`` is an :ref:`Alias Target <Alias Targets>`, the command
operates on the target which the alias references.
The ``INTERFACE``, ``PUBLIC`` and ``PRIVATE`` keywords are required to The ``INTERFACE``, ``PUBLIC`` and ``PRIVATE`` keywords are required to
specify the :ref:`scope <Target Command Scope>` of the following arguments. specify the :ref:`scope <Target Command Scope>` of the following arguments.

View File

@@ -29,8 +29,11 @@ Repeated calls for the same ``<target>`` append items.
Allow setting ``INTERFACE`` items on :ref:`IMPORTED targets <Imported Targets>`. Allow setting ``INTERFACE`` items on :ref:`IMPORTED targets <Imported Targets>`.
The named ``<target>`` must have been created by a command such as The named ``<target>`` must have been created by a command such as
:command:`add_executable` or :command:`add_library` and must not be an :command:`add_executable` or :command:`add_library`.
:ref:`ALIAS target <Alias Targets>`.
.. versionchanged:: 4.5
If ``<target>`` is an :ref:`Alias Target <Alias Targets>`, the command
operates on the target which the alias references.
.. |command_name| replace:: ``target_compile_features`` .. |command_name| replace:: ``target_compile_features``
.. |more_see_also| replace:: See the :manual:`cmake-compile-features(7)` .. |more_see_also| replace:: See the :manual:`cmake-compile-features(7)`

View File

@@ -13,7 +13,11 @@ Adds options to the :prop_tgt:`COMPILE_OPTIONS` or
:prop_tgt:`INTERFACE_COMPILE_OPTIONS` target properties. These options :prop_tgt:`INTERFACE_COMPILE_OPTIONS` target properties. These options
are used when compiling the given ``<target>``, which must have been are used when compiling the given ``<target>``, which must have been
created by a command such as :command:`add_executable` or created by a command such as :command:`add_executable` or
:command:`add_library` and must not be an :ref:`ALIAS target <Alias Targets>`. :command:`add_library`.
.. versionchanged:: 4.5
If ``<target>`` is an :ref:`Alias Target <Alias Targets>`, the command
operates on the target which the alias references.
.. note:: .. note::

View File

@@ -11,8 +11,11 @@ Add include directories to a target.
Specifies include directories to use when compiling a given target. Specifies include directories to use when compiling a given target.
The named ``<target>`` must have been created by a command such The named ``<target>`` must have been created by a command such
as :command:`add_executable` or :command:`add_library` and must not be an as :command:`add_executable` or :command:`add_library`.
:ref:`ALIAS target <Alias Targets>`.
.. versionchanged:: 4.5
If ``<target>`` is an :ref:`Alias Target <Alias Targets>`, the command
operates on the target which the alias references.
By using ``AFTER`` or ``BEFORE`` explicitly, you can select between appending By using ``AFTER`` or ``BEFORE`` explicitly, you can select between appending
and prepending, independent of the default. and prepending, independent of the default.

View File

@@ -17,8 +17,11 @@ with the latter being interpreted as relative to the current source
directory. These items will be added to the link command. directory. These items will be added to the link command.
The named ``<target>`` must have been created by a command such as The named ``<target>`` must have been created by a command such as
:command:`add_executable` or :command:`add_library` and must not be an :command:`add_executable` or :command:`add_library`.
:ref:`ALIAS target <Alias Targets>`.
.. versionchanged:: 4.5
If ``<target>`` is an :ref:`Alias Target <Alias Targets>`, the command
operates on the target which the alias references.
The ``INTERFACE``, ``PUBLIC`` and ``PRIVATE`` keywords are required to The ``INTERFACE``, ``PUBLIC`` and ``PRIVATE`` keywords are required to
specify the :ref:`scope <Target Command Scope>` of the items that follow specify the :ref:`scope <Target Command Scope>` of the items that follow

View File

@@ -21,16 +21,19 @@ All of them have the general form
target_link_libraries(<target> ... <item>... ...) target_link_libraries(<target> ... <item>... ...)
The named ``<target>`` must have been created by a command such as The named ``<target>`` must have been created by a command such as
:command:`add_executable` or :command:`add_library` and must not be an :command:`add_executable` or :command:`add_library`. If policy
:ref:`ALIAS target <Alias Targets>`. If policy :policy:`CMP0079` is not :policy:`CMP0079` is not set to ``NEW``, then the target must have been
set to ``NEW`` then the target must have been created in the current created in the current directory. Repeated calls for the same ``<target>``
directory. Repeated calls for the same ``<target>`` append items in append items in the order called.
the order called.
.. versionadded:: 3.13 .. versionadded:: 3.13
The ``<target>`` doesn't have to be defined in the same directory as the The ``<target>`` doesn't have to be defined in the same directory as the
``target_link_libraries`` call. ``target_link_libraries`` call.
.. versionchanged:: 4.5
If ``<target>`` is an :ref:`Alias Target <Alias Targets>`, the command
operates on the target which the alias references.
Each ``<item>`` may be: Each ``<item>`` may be:
* **A library target name**: The generated link line will have the * **A library target name**: The generated link line will have the

View File

@@ -13,8 +13,11 @@ library target.
[{INTERFACE|PUBLIC|PRIVATE} <item>...]...) [{INTERFACE|PUBLIC|PRIVATE} <item>...]...)
The named ``<target>`` must have been created by a command such as The named ``<target>`` must have been created by a command such as
:command:`add_executable` or :command:`add_library` and must not be an :command:`add_executable` or :command:`add_library`.
:ref:`ALIAS target <Alias Targets>`.
.. versionchanged:: 4.5
If ``<target>`` is an :ref:`Alias Target <Alias Targets>`, the command
operates on the target which the alias references.
This command can be used to add any link options, but alternative commands This command can be used to add any link options, but alternative commands
exist to add libraries (:command:`target_link_libraries` or exist to add libraries (:command:`target_link_libraries` or

View File

@@ -21,8 +21,11 @@ Main Form
The command adds header files to the :prop_tgt:`PRECOMPILE_HEADERS` and/or The command adds header files to the :prop_tgt:`PRECOMPILE_HEADERS` and/or
:prop_tgt:`INTERFACE_PRECOMPILE_HEADERS` target properties of ``<target>``. :prop_tgt:`INTERFACE_PRECOMPILE_HEADERS` target properties of ``<target>``.
The named ``<target>`` must have been created by a command such as The named ``<target>`` must have been created by a command such as
:command:`add_executable` or :command:`add_library` and must not be an :command:`add_executable` or :command:`add_library`.
:ref:`ALIAS target <Alias Targets>`.
.. versionchanged:: 4.5
If ``<target>`` is an :ref:`Alias Target <Alias Targets>`, the command
operates on the target which the alias references.
The ``INTERFACE``, ``PUBLIC`` and ``PRIVATE`` keywords are required to The ``INTERFACE``, ``PUBLIC`` and ``PRIVATE`` keywords are required to
specify the :ref:`scope <Target Command Scope>` of the following arguments. specify the :ref:`scope <Target Command Scope>` of the following arguments.

View File

@@ -14,13 +14,16 @@ Add sources to a target.
Specifies sources to use when building a target and/or its dependents. Specifies sources to use when building a target and/or its dependents.
The named ``<target>`` must have been created by a command such as The named ``<target>`` must have been created by a command such as
:command:`add_executable` or :command:`add_library` or :command:`add_executable` or :command:`add_library` or
:command:`add_custom_target` and must not be an :command:`add_custom_target`. The ``<items>`` may use
:ref:`ALIAS target <Alias Targets>`. The ``<items>`` may use
:manual:`generator expressions <cmake-generator-expressions(7)>`. :manual:`generator expressions <cmake-generator-expressions(7)>`.
.. versionadded:: 3.20 .. versionadded:: 3.20
``<target>`` can be a custom target. ``<target>`` can be a custom target.
.. versionchanged:: 4.5
If ``<target>`` is an :ref:`Alias Target <Alias Targets>`, the command
operates on the target which the alias references.
The ``INTERFACE``, ``PUBLIC`` and ``PRIVATE`` keywords are required to The ``INTERFACE``, ``PUBLIC`` and ``PRIVATE`` keywords are required to
specify the :ref:`scope <Target Command Scope>` of the source file paths specify the :ref:`scope <Target Command Scope>` of the source file paths
(``<items>``) that follow them. ``PRIVATE`` and ``PUBLIC`` items will (``<items>``) that follow them. ``PRIVATE`` and ``PUBLIC`` items will

View File

@@ -5,4 +5,11 @@ alias-transparency
now accept :ref:`Alias Targets`. Properties are set on the target which now accept :ref:`Alias Targets`. Properties are set on the target which
the alias references. the alias references.
* The :command:`target_compile_definitions`, :command:`target_compile_features`,
:command:`target_compile_options`, :command:`target_include_directories`,
:command:`target_link_directories`, :command:`target_link_libraries`,
:command:`target_link_options`, :command:`target_precompile_headers`,
and :command:`target_sources` commands now accept :ref:`Alias Targets`.
The commands operate on the target which the alias references.
* The :prop_tgt:`ALIASED_TARGET` target property is now read-only. * The :prop_tgt:`ALIASED_TARGET` target property is now read-only.

View File

@@ -78,12 +78,6 @@ bool cmTargetLinkLibrariesCommand(std::vector<std::string> const& args,
cmMakefile& mf = status.GetMakefile(); cmMakefile& mf = status.GetMakefile();
// Alias targets cannot be on the LHS of this command.
if (mf.IsAlias(args[0])) {
status.SetError("can not be used on an ALIAS target.");
return false;
}
// Lookup the target for which libraries are specified. // Lookup the target for which libraries are specified.
cmTarget* target = mf.GetGlobalGenerator()->FindTarget(args[0]); cmTarget* target = mf.GetGlobalGenerator()->FindTarget(args[0]);
if (!target) { if (!target) {

View File

@@ -29,10 +29,6 @@ bool cmTargetPropCommandBase::HandleArguments(
return false; return false;
} }
if (this->Makefile->IsAlias(args[0])) {
this->SetError("can not be used on an ALIAS target.");
return false;
}
// Lookup the target for which property-values are specified. // Lookup the target for which property-values are specified.
this->Target = this->Makefile->GetGlobalGenerator()->FindTarget(args[0]); this->Target = this->Makefile->GetGlobalGenerator()->FindTarget(args[0]);
if (!this->Target) { if (!this->Target) {

View File

@@ -17,7 +17,14 @@ run_cmake(get_property)
run_cmake(set_target_properties) run_cmake(set_target_properties)
run_cmake(set_target_properties-ALIAS_GLOBAL) run_cmake(set_target_properties-ALIAS_GLOBAL)
run_cmake(target_link_libraries) run_cmake(target_link_libraries)
run_cmake(target_compile_definitions)
run_cmake(target_compile_features)
run_cmake(target_compile_options)
run_cmake(target_include_directories) run_cmake(target_include_directories)
run_cmake(target_link_directories)
run_cmake(target_link_options)
run_cmake(target_precompile_headers)
run_cmake(target_sources)
run_cmake(export) run_cmake(export)
run_cmake(install-export) run_cmake(install-export)
run_cmake(name-conflict) run_cmake(name-conflict)

View File

@@ -0,0 +1,12 @@
enable_language(CXX)
add_library(foo empty.cpp)
add_library(alias ALIAS foo)
target_compile_definitions(alias PRIVATE MY_DEFINE)
get_target_property(val foo COMPILE_DEFINITIONS)
if(NOT "MY_DEFINE" STREQUAL "${val}")
message(SEND_ERROR "target_compile_definitions(): Target property 'COMPILE_DEFINITIONS' set on ALIAS 'alias' has wrong value on aliased target 'foo': '${val}' instead of 'MY_DEFINE'.")
endif()

View File

@@ -0,0 +1,14 @@
enable_language(CXX)
add_library(foo empty.cpp)
add_library(alias ALIAS foo)
if("cxx_std_11" IN_LIST CMAKE_CXX_COMPILE_FEATURES)
target_compile_features(alias PRIVATE cxx_std_11)
get_target_property(val foo COMPILE_FEATURES)
if(NOT "cxx_std_11" IN_LIST val)
message(SEND_ERROR "target_compile_features(): Target property 'COMPILE_FEATURES' set on ALIAS 'alias' has wrong value on aliased target 'foo': '${val}' instead of 'cxx_std_11'.")
endif()
endif()

View File

@@ -0,0 +1,12 @@
enable_language(CXX)
add_library(foo empty.cpp)
add_library(alias ALIAS foo)
target_compile_options(alias PRIVATE -Wall)
get_target_property(val foo COMPILE_OPTIONS)
if(NOT "-Wall" STREQUAL "${val}")
message(SEND_ERROR "target_compile_options(): Target property 'COMPILE_OPTIONS' set on ALIAS 'alias' has wrong value on aliased target 'foo': '${val}' instead of '-Wall'.")
endif()

View File

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

View File

@@ -6,3 +6,7 @@ add_library(foo empty.cpp)
add_library(alias ALIAS foo) add_library(alias ALIAS foo)
target_include_directories(alias PRIVATE $<BUILD_INTERFACE:${CMAKE_CURRENT_BINARY_DIR}>) target_include_directories(alias PRIVATE $<BUILD_INTERFACE:${CMAKE_CURRENT_BINARY_DIR}>)
get_target_property(val foo INCLUDE_DIRECTORIES)
if(NOT "$<BUILD_INTERFACE:${CMAKE_CURRENT_BINARY_DIR}>" STREQUAL "${val}")
message(SEND_ERROR "target_include_directories(): Target property 'INCLUDE_DIRECTORIES' set on ALIAS 'alias' has wrong value on aliased target 'foo': '${val}' instead of '$<BUILD_INTERFACE:${CMAKE_CURRENT_BINARY_DIR}>'.")
endif()

View File

@@ -0,0 +1,12 @@
enable_language(CXX)
add_library(foo empty.cpp)
add_library(alias ALIAS foo)
target_link_directories(alias PRIVATE /usr/local/lib)
get_target_property(val foo LINK_DIRECTORIES)
if(NOT "/usr/local/lib" STREQUAL "${val}")
message(SEND_ERROR "target_link_directories(): Target property 'LINK_DIRECTORIES' set on ALIAS 'alias' has wrong value on aliased target 'foo': '${val}' instead of '/usr/local/lib'.")
endif()

View File

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

View File

@@ -6,4 +6,8 @@ add_library(bar empty.cpp)
add_library(alias ALIAS foo) add_library(alias ALIAS foo)
target_link_libraries(alias bar) target_link_libraries(alias PRIVATE bar)
get_target_property(val foo LINK_LIBRARIES)
if(NOT "bar" IN_LIST val)
message(SEND_ERROR "target_link_libraries(): Target property 'LINK_LIBRARIES' is missing value added to ALIAS 'alias' on aliased target 'foo': 'bar' not in '${val}'.")
endif()

View File

@@ -0,0 +1,12 @@
enable_language(CXX)
add_library(foo empty.cpp)
add_library(alias ALIAS foo)
target_link_options(alias PRIVATE LINKER:--test)
get_target_property(val foo LINK_OPTIONS)
if(NOT "LINKER:--test" STREQUAL "${val}")
message(SEND_ERROR "target_link_options(): Target property 'LINK_OPTIONS' set on ALIAS 'alias' has wrong value on aliased target 'foo': '${val}' instead of 'LINKER:--test'.")
endif()

View File

@@ -0,0 +1,12 @@
enable_language(CXX)
add_library(foo empty.cpp)
add_library(alias ALIAS foo)
target_precompile_headers(alias PRIVATE <vector>)
get_target_property(val foo PRECOMPILE_HEADERS)
if(NOT "<vector>" IN_LIST val)
message(SEND_ERROR "target_precompile_headers(): Target property 'PRECOMPILE_HEADERS' is missing value added to ALIAS 'alias' on aliased target 'foo': '<vector>' not in '${val}'.")
endif()

View File

@@ -0,0 +1,12 @@
enable_language(CXX)
add_library(foo)
add_library(alias ALIAS foo)
target_sources(alias PRIVATE empty.cpp)
get_target_property(val foo SOURCES)
if(NOT "empty.cpp" IN_LIST val)
message(SEND_ERROR "target_sources(): Target property 'SOURCES' is missing value added to ALIAS 'alias' on aliased target 'foo': 'empty.cpp' not in '${val}'.")
endif()

View File

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

View File

@@ -2,4 +2,11 @@ enable_language(CXX)
add_executable(main empty.cpp) add_executable(main empty.cpp)
add_executable(Alias::Main ALIAS main) add_executable(Alias::Main ALIAS main)
target_compile_features(Alias::Main PRIVATE cxx_delegating_constructors)
if("cxx_delegating_constructors" IN_LIST CMAKE_CXX_COMPILE_FEATURES)
target_compile_features(Alias::Main PRIVATE cxx_delegating_constructors)
get_target_property(val main COMPILE_FEATURES)
if(NOT "cxx_delegating_constructors" IN_LIST val)
message(SEND_ERROR "target_compile_features(): Target property 'COMPILE_FEATURES' is missing value added to ALIAS 'Alias::Main' on aliased target 'main': 'cxx_delegating_constructors' not in '${val}'.")
endif()
endif()