summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Help/command/target_sources.rst4
-rw-r--r--Help/guide/tutorial/A Basic Starting Point.rst26
-rw-r--r--Help/manual/cmake-generator-expressions.7.rst1922
-rw-r--r--Help/prop_tgt/LINK_LIBRARIES_ONLY_TARGETS.rst2
-rw-r--r--Help/release/dev/finddoxygen-better-version-checking.rst11
-rw-r--r--Modules/FindDoxygen.cmake46
-rw-r--r--Modules/FindPython/Support.cmake10
-rw-r--r--Modules/Platform/AIX-GNU.cmake4
-rw-r--r--Modules/Platform/AIX-XL.cmake4
-rwxr-xr-xModules/Platform/AIX/ExportImportList46
-rw-r--r--Source/CMakeVersion.cmake2
-rw-r--r--Source/cmGlobalGenerator.cxx4
-rw-r--r--Source/cmGlobalVisualStudio10Generator.cxx8
-rw-r--r--Source/cmGlobalVisualStudio10Generator.h2
-rw-r--r--Source/cmGlobalVisualStudio71Generator.cxx2
-rw-r--r--Source/cmGlobalVisualStudioGenerator.cxx6
-rw-r--r--Source/cmGlobalVisualStudioGenerator.h3
-rw-r--r--Source/cmNinjaTargetGenerator.cxx8
-rw-r--r--Source/cmVisualStudio10TargetGenerator.cxx2
-rw-r--r--Templates/MSBuild/FlagTables/v10_CSharp.json7
-rw-r--r--Templates/MSBuild/FlagTables/v11_CSharp.json7
-rw-r--r--Templates/MSBuild/FlagTables/v12_CSharp.json7
-rw-r--r--Templates/MSBuild/FlagTables/v140_CSharp.json7
-rw-r--r--Templates/MSBuild/FlagTables/v141_CSharp.json7
-rw-r--r--Templates/MSBuild/FlagTables/v142_CSharp.json7
-rw-r--r--Templates/MSBuild/FlagTables/v143_CSharp.json7
-rw-r--r--Tests/RunCMake/NinjaMultiConfig/CompileCommands-check.cmake28
-rw-r--r--Tests/RunCMake/NinjaMultiConfig/CompileCommands.cmake3
-rw-r--r--Tests/RunCMake/NinjaMultiConfig/RunCMakeTest.cmake5
-rw-r--r--Tests/RunCMake/VS10Project/InterfaceLibSources-check.cmake9
-rw-r--r--Tests/RunCMake/export/RunCMakeTest.cmake1
-rw-r--r--Tests/RunCMake/export/TryCompileExport.cmake9
-rw-r--r--Tests/RunCMake/include_external_msproject/Program.cs9
-rw-r--r--Tests/RunCMake/include_external_msproject/RunCMakeTest.cmake11
-rw-r--r--Tests/RunCMake/include_external_msproject/VSCSharpOnlyProject.cmake9
-rw-r--r--Tests/RunCMake/include_external_msproject/consoleapp.csproj14
-rwxr-xr-xUtilities/Release/macos/sign-notarize.bash43
37 files changed, 1329 insertions, 973 deletions
diff --git a/Help/command/target_sources.rst b/Help/command/target_sources.rst
index 4699a08..a079307 100644
--- a/Help/command/target_sources.rst
+++ b/Help/command/target_sources.rst
@@ -52,10 +52,10 @@ expressions to ensure the sources are correctly assigned to the target.
.. code-block:: cmake
# WRONG: starts with generator expression, but relative path used
- target_sources(MyTarget "$<$<CONFIG:Debug>:dbgsrc.cpp>")
+ target_sources(MyTarget PRIVATE "$<$<CONFIG:Debug>:dbgsrc.cpp>")
# CORRECT: absolute path used inside the generator expression
- target_sources(MyTarget "$<$<CONFIG:Debug>:${CMAKE_CURRENT_SOURCE_DIR}/dbgsrc.cpp>")
+ target_sources(MyTarget PRIVATE "$<$<CONFIG:Debug>:${CMAKE_CURRENT_SOURCE_DIR}/dbgsrc.cpp>")
See the :manual:`cmake-buildsystem(7)` manual for more on defining
buildsystem properties.
diff --git a/Help/guide/tutorial/A Basic Starting Point.rst b/Help/guide/tutorial/A Basic Starting Point.rst
index cf1ec01..d57cc35 100644
--- a/Help/guide/tutorial/A Basic Starting Point.rst
+++ b/Help/guide/tutorial/A Basic Starting Point.rst
@@ -19,8 +19,19 @@ required. This will be the starting point for our tutorial. Create a
add_executable(Tutorial tutorial.cxx)
-Note that this example uses lower case commands in the ``CMakeLists.txt`` file.
-Upper, lower, and mixed case commands are supported by CMake. The source
+Any project's top most ``CMakeLists.txt`` must start by specifying
+a minimum CMake version using :command:`cmake_minimum_required`. This ensures
+that the later CMake functions are run with a compatible version of CMake.
+
+To start a project, we use :command:`project` to set the project name. This
+call is required with every project and should be called soon after
+:command:`cmake_minimum_required`.
+
+Lastly, we use :command:`add_executable` to specify we want an executable
+named Tutorial generated using ``tutorial.cxx`` as the source.
+
+Note that this example uses lower case commands in the ``CMakeLists.txt``
+file. Upper, lower, and mixed case commands are supported by CMake. The source
code for ``tutorial.cxx`` is provided in the ``Step1`` directory and can be
used to compute the square root of a number.
@@ -79,7 +90,7 @@ to set the project name and version number.
:language: cmake
:end-before: # specify the C++ standard
-Then, configure a header file to pass the version number to the source
+Then use :command:`configure_file` to pass the version number to the source
code:
.. literalinclude:: Step2/CMakeLists.txt
@@ -91,7 +102,8 @@ code:
Since the configured file will be written into the binary tree, we
must add that directory to the list of paths to search for include
-files. Add the following lines to the end of the ``CMakeLists.txt`` file:
+files. Use :command:`target_include_directories` to add the following lines to
+the end of the ``CMakeLists.txt`` file:
.. literalinclude:: Step2/CMakeLists.txt
:caption: CMakeLists.txt
@@ -107,9 +119,9 @@ directory with the following contents:
:name: TutorialConfig.h.in
:language: c++
-When CMake configures this header file the values for
+When CMake configures this header file, the values for
``@Tutorial_VERSION_MAJOR@`` and ``@Tutorial_VERSION_MINOR@`` will be
-replaced.
+replaced with the corresponding version numbers from the project.
Next modify ``tutorial.cxx`` to include the configured header file,
``TutorialConfig.h``.
@@ -141,7 +153,7 @@ Next let's add some C++11 features to our project by replacing ``atof`` with
We will need to explicitly state in the CMake code that it should use the
correct flags. The easiest way to enable support for a specific C++ standard
in CMake is by using the :variable:`CMAKE_CXX_STANDARD` variable. For this
-tutorial, set the :variable:`CMAKE_CXX_STANDARD` variable in the
+tutorial, :command:`set` the :variable:`CMAKE_CXX_STANDARD` variable in the
``CMakeLists.txt`` file to ``11`` and :variable:`CMAKE_CXX_STANDARD_REQUIRED`
to ``True``. Make sure to add the ``CMAKE_CXX_STANDARD`` declarations above the
call to ``add_executable``.
diff --git a/Help/manual/cmake-generator-expressions.7.rst b/Help/manual/cmake-generator-expressions.7.rst
index 25e581a..9949772 100644
--- a/Help/manual/cmake-generator-expressions.7.rst
+++ b/Help/manual/cmake-generator-expressions.7.rst
@@ -11,40 +11,189 @@ Introduction
============
Generator expressions are evaluated during build system generation to produce
-information specific to each build configuration.
+information specific to each build configuration. They have the form
+``$<...>``. For example:
+
+.. code-block:: cmake
+
+ target_include_directories(tgt PRIVATE /opt/include/$<CXX_COMPILER_ID>)
+
+This would expand to ``/opt/include/GNU``, ``/opt/include/Clang``, etc.
+depending on the C++ compiler used.
Generator expressions are allowed in the context of many target properties,
such as :prop_tgt:`LINK_LIBRARIES`, :prop_tgt:`INCLUDE_DIRECTORIES`,
:prop_tgt:`COMPILE_DEFINITIONS` and others. They may also be used when using
commands to populate those properties, such as :command:`target_link_libraries`,
:command:`target_include_directories`, :command:`target_compile_definitions`
-and others.
+and others. They enable conditional linking, conditional definitions used when
+compiling, conditional include directories, and more. The conditions may be
+based on the build configuration, target properties, platform information,
+or any other queryable information.
-They enable conditional linking, conditional definitions used when compiling,
-conditional include directories, and more. The conditions may be based on
-the build configuration, target properties, platform information or any other
-queryable information.
+Generator expressions can be nested:
-Generator expressions have the form ``$<...>``. To avoid confusion, this page
-deviates from most of the CMake documentation in that it omits angular brackets
-``<...>`` around placeholders like ``condition``, ``string``, ``target``,
-among others.
+.. code-block:: cmake
-Generator expressions can be nested, as shown in most of the examples below.
+ target_compile_definitions(tgt PRIVATE
+ $<$<VERSION_LESS:$<CXX_COMPILER_VERSION>,4.2.0>:OLD_COMPILER>
+ )
-.. _`Boolean Generator Expressions`:
+The above would expand to ``OLD_COMPILER`` if the
+:variable:`CMAKE_CXX_COMPILER_VERSION <CMAKE_<LANG>_COMPILER_VERSION>` is less
+than 4.2.0.
-Boolean Generator Expressions
-=============================
+Whitespace And Quoting
+======================
-Boolean expressions evaluate to either ``0`` or ``1``.
-They are typically used to construct the condition in a :ref:`conditional
-generator expression<Conditional Generator Expressions>`.
+Generator expressions are typically parsed after command arguments.
+If a generator expression contains spaces, new lines, semicolons or
+other characters that may be interpreted as command argument separators,
+the whole expression should be surrounded by quotes when passed to a
+command. Failure to do so may result in the expression being split and
+it may no longer be recognized as a generator expression.
-Available boolean expressions are:
+When using :command:`add_custom_command` or :command:`add_custom_target`,
+use the ``VERBATIM`` and ``COMMAND_EXPAND_LISTS`` options to obtain robust
+argument splitting and quoting.
-Logical Operators
------------------
+.. code-block:: cmake
+
+ # WRONG: Embedded space will be treated as an argument separator.
+ # This ends up not being seen as a generator expression at all.
+ add_custom_target(run_some_tool
+ COMMAND some_tool -I$<JOIN:$<TARGET_PROPERTY:tgt,INCLUDE_DIRECTORIES>, -I>
+ VERBATIM
+ )
+
+.. code-block:: cmake
+
+ # Better, but still not robust. Quotes prevent the space from splitting the
+ # expression. However, the tool will receive the expanded value as a single
+ # argument.
+ add_custom_target(run_some_tool
+ COMMAND some_tool "-I$<JOIN:$<TARGET_PROPERTY:tgt,INCLUDE_DIRECTORIES>, -I>"
+ VERBATIM
+ )
+
+.. code-block:: cmake
+
+ # Nearly correct. Using a semicolon to separate arguments and adding the
+ # COMMAND_EXPAND_LISTS option means that paths with spaces will be handled
+ # correctly. Quoting the whole expression ensures it is seen as a generator
+ # expression. But if the target property is empty, we will get a bare -I
+ # with nothing after it.
+ add_custom_target(run_some_tool
+ COMMAND some_tool "-I$<JOIN:$<TARGET_PROPERTY:tgt,INCLUDE_DIRECTORIES>,;-I>"
+ COMMAND_EXPAND_LISTS
+ VERBATIM
+ )
+
+Using variables to build up a more complex generator expression is also a
+good way to reduce errors and improve readability. The above example can be
+improved further like so:
+
+.. code-block:: cmake
+
+ # The $<BOOL:...> check prevents adding anything if the property is empty,
+ # assuming the property value cannot be one of CMake's false constants.
+ set(prop "$<TARGET_PROPERTY:tgt,INCLUDE_DIRECTORIES>")
+ add_custom_target(run_some_tool
+ COMMAND some_tool "$<$<BOOL:${prop}>:-I$<JOIN:${prop},;-I>>"
+ COMMAND_EXPAND_LISTS
+ VERBATIM
+ )
+
+A common mistake is to try to split a generator expression across multiple
+lines with indenting:
+
+.. code-block:: cmake
+
+ # WRONG: New lines and spaces all treated as argument separators, so the
+ # generator expression is split and not recognized correctly.
+ target_compile_definitions(tgt PRIVATE
+ $<$<AND:
+ $<CXX_COMPILER_ID:GNU>,
+ $<VERSION_GREATER_EQUAL:$<CXX_COMPILER_VERSION>,5>
+ >:HAVE_5_OR_LATER>
+ )
+
+Again, use helper variables with well-chosen names to build up a readable
+expression instead:
+
+.. code-block:: cmake
+
+ set(is_gnu "$<CXX_COMPILER_ID:GNU>")
+ set(v5_or_later "$<VERSION_GREATER_EQUAL:$<CXX_COMPILER_VERSION>,5>")
+ set(meet_requirements "$<AND:${is_gnu},${v5_or_later}>")
+ target_compile_definitions(tgt PRIVATE
+ "$<${meet_requirements}:HAVE_5_OR_LATER>"
+ )
+
+Debugging
+=========
+
+Since generator expressions are evaluated during generation of the buildsystem,
+and not during processing of ``CMakeLists.txt`` files, it is not possible to
+inspect their result with the :command:`message()` command. One possible way
+to generate debug messages is to add a custom target:
+
+.. code-block:: cmake
+
+ add_custom_target(genexdebug COMMAND ${CMAKE_COMMAND} -E echo "$<...>")
+
+After running ``cmake``, you can then build the ``genexdebug`` target to print
+the result of the ``$<...>`` expression (i.e. run the command
+``cmake --build ... --target genexdebug``).
+
+Another way is to write debug messages to a file with :command:`file(GENERATE)`:
+
+.. code-block:: cmake
+
+ file(GENERATE OUTPUT filename CONTENT "$<...>")
+
+Generator Expression Reference
+==============================
+
+.. note::
+
+ This reference deviates from most of the CMake documentation in that it
+ omits angular brackets ``<...>`` around placeholders like ``condition``,
+ ``string``, ``target``, etc. This is to prevent an opportunity for those
+ placeholders to be misinterpreted as generator expressions.
+
+.. _`Conditional Generator Expressions`:
+
+Conditional Expressions
+-----------------------
+
+A fundamental category of generator expressions relates to conditional logic.
+Two forms of conditional generator expressions are supported:
+
+.. genex:: $<condition:true_string>
+
+ Evaluates to ``true_string`` if ``condition`` is ``1``, or an empty string
+ if ``condition`` evaluates to ``0``. Any other value for ``condition``
+ results in an error.
+
+.. genex:: $<IF:condition,true_string,false_string>
+
+ .. versionadded:: 3.8
+
+ Evaluates to ``true_string`` if ``condition`` is ``1``, or ``false_string``
+ if ``condition`` is ``0``. Any other value for ``condition`` results in an
+ error.
+
+Typically, the ``condition`` is itself a generator expression. For instance,
+the following expression expands to ``DEBUG_MODE`` when the ``Debug``
+configuration is used, and the empty string for all other configurations:
+
+.. code-block:: cmake
+
+ $<$<CONFIG:Debug>:DEBUG_MODE>
+
+Boolean-like ``condition`` values other than ``1`` or ``0`` can be handled
+by wrapping them with the ``$<BOOL:...>`` generator expression:
.. genex:: $<BOOL:string>
@@ -58,49 +207,71 @@ Logical Operators
Otherwise evaluates to ``1``.
+The ``$<BOOL:...>`` generator expression is often used when a ``condition``
+is provided by a CMake variable:
+
+.. code-block:: cmake
+
+ $<$<BOOL:${HAVE_SOME_FEATURE}>:-DENABLE_SOME_FEATURE>
+
+
+.. _`Boolean Generator Expressions`:
+
+Logical Operators
+-----------------
+
+The common boolean logic operators are supported:
+
.. genex:: $<AND:conditions>
- where ``conditions`` is a comma-separated list of boolean expressions.
- Evaluates to ``1`` if all conditions are ``1``.
- Otherwise evaluates to ``0``.
+ where ``conditions`` is a comma-separated list of boolean expressions,
+ all of which must evaluate to either ``1`` or ``0``. The whole expression
+ evaluates to ``1`` if all conditions are ``1``. If any condition is ``0``,
+ the whole expression evaluates to ``0``.
.. genex:: $<OR:conditions>
where ``conditions`` is a comma-separated list of boolean expressions.
- Evaluates to ``1`` if at least one of the conditions is ``1``.
- Otherwise evaluates to ``0``.
+ all of which must evaluate to either ``1`` or ``0``. The whole expression
+ evaluates to ``1`` if at least one of the ``conditions`` is ``1``. If all
+ ``conditions`` evaluate to ``0``, the whole expression evaluates to ``0``.
.. genex:: $<NOT:condition>
+ ``condition`` must be ``0`` or ``1``. The result of the expression is
``0`` if ``condition`` is ``1``, else ``1``.
+.. _`Comparison Expressions`:
+
+Primary Comparison Expressions
+------------------------------
+
+CMake supports a variety of generator expressions that compare things.
+This section covers the primary and most widely used comparison types.
+Other more specific comparison types are documented in their own separate
+sections further below.
+
String Comparisons
-------------------
+^^^^^^^^^^^^^^^^^^
.. genex:: $<STREQUAL:string1,string2>
``1`` if ``string1`` and ``string2`` are equal, else ``0``.
The comparison is case-sensitive. For a case-insensitive comparison,
combine with a :ref:`string transforming generator expression
- <String Transforming Generator Expressions>`,
+ <String Transforming Generator Expressions>`. For example, the following
+ evaluates to ``1`` if ``${foo}`` is any of ``BAR``, ``Bar``, ``bar``, etc.
.. code-block:: cmake
- $<STREQUAL:$<UPPER_CASE:${foo}>,"BAR"> # "1" if ${foo} is any of "BAR", "Bar", "bar", ...
+ $<STREQUAL:$<UPPER_CASE:${foo}>,BAR>
.. genex:: $<EQUAL:value1,value2>
``1`` if ``value1`` and ``value2`` are numerically equal, else ``0``.
-.. genex:: $<IN_LIST:string,list>
-
- .. versionadded:: 3.12
-
- ``1`` if ``string`` is member of the semicolon-separated ``list``, else ``0``.
- Uses case-sensitive comparisons.
-
Version Comparisons
--------------------
+^^^^^^^^^^^^^^^^^^^
.. genex:: $<VERSION_LESS:v1,v2>
@@ -126,9 +297,70 @@ Version Comparisons
``1`` if ``v1`` is a version greater than or equal to ``v2``, else ``0``.
-Path Comparisons
+.. _`String Transforming Generator Expressions`:
+
+String Transformations
+----------------------
+
+.. genex:: $<LOWER_CASE:string>
+
+ Content of ``string`` converted to lower case.
+
+.. genex:: $<UPPER_CASE:string>
+
+ Content of ``string`` converted to upper case.
+
+.. genex:: $<MAKE_C_IDENTIFIER:...>
+
+ Content of ``...`` converted to a C identifier. The conversion follows the
+ same behavior as :command:`string(MAKE_C_IDENTIFIER)`.
+
+List Expressions
----------------
+.. genex:: $<IN_LIST:string,list>
+
+ .. versionadded:: 3.12
+
+ ``1`` if ``string`` is an item in the semicolon-separated ``list``, else ``0``.
+ It uses case-sensitive comparisons.
+
+.. genex:: $<JOIN:list,string>
+
+ Joins the list with the content of ``string`` inserted between each item.
+
+.. genex:: $<REMOVE_DUPLICATES:list>
+
+ .. versionadded:: 3.15
+
+ Removes duplicated items in the given ``list``. The relative order of items
+ is preserved, but if duplicates are encountered, only the first instance is
+ preserved.
+
+.. genex:: $<FILTER:list,INCLUDE|EXCLUDE,regex>
+
+ .. versionadded:: 3.15
+
+ Includes or removes items from ``list`` that match the regular expression
+ ``regex``.
+
+Path Expressions
+----------------
+
+Most of the expressions in this section are closely associated with the
+:command:`cmake_path` command, providing the same capabilities, but in
+the form of a generator expression.
+
+For all generator expressions in this section, paths are expected to be in
+cmake-style format. The :ref:`$\<PATH:CMAKE_PATH\> <GenEx PATH-CMAKE_PATH>`
+generator expression can be used to convert a native path to a cmake-style
+one.
+
+.. _GenEx Path Comparisons:
+
+Path Comparisons
+^^^^^^^^^^^^^^^^
+
.. genex:: $<PATH_EQUAL:path1,path2>
.. versionadded:: 3.24
@@ -142,18 +374,11 @@ Path Comparisons
.. _GenEx Path Queries:
Path Queries
-------------
+^^^^^^^^^^^^
-The ``$<PATH>`` generator expression offers the same capabilities as the
-:command:`cmake_path` command, for the :ref:`Query <Path Query>` options.
-
-For all ``$<PATH>`` generator expressions, paths are expected in cmake-style
-format. The :ref:`$\<PATH:CMAKE_PATH\> <GenEx PATH-CMAKE_PATH>` generator
-expression can be used to convert a native path to a cmake-style one.
-
-The ``$<PATH>`` generator expression can also be used for path
-:ref:`Decomposition <GenEx Path Decomposition>` and
-:ref:`Transformations <GenEx Path Transformations>`.
+These expressions provide the generation-time capabilities equivalent to the
+:ref:`Query <Path Query>` options of the :command:`cmake_path` command.
+All paths are expected to be in cmake-style format.
.. genex:: $<PATH:HAS_*,path>
@@ -199,211 +424,421 @@ The ``$<PATH>`` generator expression can also be used for path
.. versionadded:: 3.24
- Returns ``1`` if ``path`` is the prefix of ``input``,``0`` otherwise.
+ Returns ``1`` if ``path`` is the prefix of ``input``, ``0`` otherwise.
When the ``NORMALIZE`` option is specified, ``path`` and ``input`` are
:ref:`normalized <Normalization>` before the check.
-Variable Queries
-----------------
+.. _GenEx Path Decomposition:
-.. genex:: $<TARGET_EXISTS:target>
+Path Decomposition
+^^^^^^^^^^^^^^^^^^
- .. versionadded:: 3.12
+These expressions provide the generation-time capabilities equivalent to the
+:ref:`Decomposition <Path Decomposition>` options of the :command:`cmake_path`
+command. All paths are expected to be in cmake-style format.
- ``1`` if ``target`` exists, else ``0``.
+.. genex:: $<PATH:GET_*,...>
-.. genex:: $<CONFIG:cfgs>
+ .. versionadded:: 3.24
- ``1`` if config is any one of the entries in comma-separated list
- ``cfgs``, else ``0``. This is a case-insensitive comparison. The mapping in
- :prop_tgt:`MAP_IMPORTED_CONFIG_<CONFIG>` is also considered by this
- expression when it is evaluated on a property on an :prop_tgt:`IMPORTED`
- target.
+ The following operations retrieve a different component or group of
+ components from a path. See :ref:`Path Structure And Terminology` for the
+ meaning of each path component.
-.. genex:: $<PLATFORM_ID:platform_ids>
+ ::
- where ``platform_ids`` is a comma-separated list.
- ``1`` if the CMake's platform id matches any one of the entries in
- ``platform_ids``, otherwise ``0``.
- See also the :variable:`CMAKE_SYSTEM_NAME` variable.
+ $<PATH:GET_ROOT_NAME,path>
+ $<PATH:GET_ROOT_DIRECTORY,path>
+ $<PATH:GET_ROOT_PATH,path>
+ $<PATH:GET_FILENAME,path>
+ $<PATH:GET_EXTENSION[,LAST_ONLY],path>
+ $<PATH:GET_STEM[,LAST_ONLY],path>
+ $<PATH:GET_RELATIVE_PART,path>
+ $<PATH:GET_PARENT_PATH,path>
-.. genex:: $<C_COMPILER_ID:compiler_ids>
+ If a requested component is not present in the path, an empty string is
+ returned.
- where ``compiler_ids`` is a comma-separated list.
- ``1`` if the CMake's compiler id of the C compiler matches any one
- of the entries in ``compiler_ids``, otherwise ``0``.
- See also the :variable:`CMAKE_<LANG>_COMPILER_ID` variable.
+.. _GenEx Path Transformations:
-.. genex:: $<CXX_COMPILER_ID:compiler_ids>
+Path Transformations
+^^^^^^^^^^^^^^^^^^^^
- where ``compiler_ids`` is a comma-separated list.
- ``1`` if the CMake's compiler id of the CXX compiler matches any one
- of the entries in ``compiler_ids``, otherwise ``0``.
- See also the :variable:`CMAKE_<LANG>_COMPILER_ID` variable.
+These expressions provide the generation-time capabilities equivalent to the
+:ref:`Modification <Path Modification>` and :ref:`Generation <Path Generation>`
+options of the :command:`cmake_path` command. All paths are expected to be
+in cmake-style format.
-.. genex:: $<CUDA_COMPILER_ID:compiler_ids>
+.. _GenEx PATH-CMAKE_PATH:
- .. versionadded:: 3.15
+.. genex:: $<PATH:CMAKE_PATH[,NORMALIZE],path>
- where ``compiler_ids`` is a comma-separated list.
- ``1`` if the CMake's compiler id of the CUDA compiler matches any one
- of the entries in ``compiler_ids``, otherwise ``0``.
- See also the :variable:`CMAKE_<LANG>_COMPILER_ID` variable.
+ .. versionadded:: 3.24
-.. genex:: $<OBJC_COMPILER_ID:compiler_ids>
+ Returns ``path``. If ``path`` is a native path, it is converted into a
+ cmake-style path with forward-slashes (``/``). On Windows, the long filename
+ marker is taken into account.
- .. versionadded:: 3.16
+ When the ``NORMALIZE`` option is specified, the path is :ref:`normalized
+ <Normalization>` after the conversion.
- where ``compiler_ids`` is a comma-separated list.
- ``1`` if the CMake's compiler id of the Objective-C compiler matches any one
- of the entries in ``compiler_ids``, otherwise ``0``.
- See also the :variable:`CMAKE_<LANG>_COMPILER_ID` variable.
+.. genex:: $<PATH:APPEND,path,input,...>
-.. genex:: $<OBJCXX_COMPILER_ID:compiler_ids>
+ .. versionadded:: 3.24
- .. versionadded:: 3.16
+ Returns all the ``input`` arguments appended to ``path`` using ``/`` as the
+ ``directory-separator``. Depending on the ``input``, the value of ``path``
+ may be discarded.
- where ``compiler_ids`` is a comma-separated list.
- ``1`` if the CMake's compiler id of the Objective-C++ compiler matches any one
- of the entries in ``compiler_ids``, otherwise ``0``.
- See also the :variable:`CMAKE_<LANG>_COMPILER_ID` variable.
+ See :ref:`cmake_path(APPEND) <APPEND>` for more details.
-.. genex:: $<Fortran_COMPILER_ID:compiler_ids>
+.. genex:: $<PATH:REMOVE_FILENAME,path>
- where ``compiler_ids`` is a comma-separated list.
- ``1`` if the CMake's compiler id of the Fortran compiler matches any one
- of the entries in ``compiler_ids``, otherwise ``0``.
- See also the :variable:`CMAKE_<LANG>_COMPILER_ID` variable.
+ .. versionadded:: 3.24
-.. genex:: $<HIP_COMPILER_ID:compiler_ids>
+ Returns ``path`` with filename component (as returned by
+ ``$<PATH:GET_FILENAME>``) removed. After removal, any trailing
+ ``directory-separator`` is left alone, if present.
- .. versionadded:: 3.21
+ See :ref:`cmake_path(REMOVE_FILENAME) <REMOVE_FILENAME>` for more details.
- where ``compiler_ids`` is a comma-separated list.
- ``1`` if the CMake's compiler id of the HIP compiler matches any one
- of the entries in ``compiler_ids``, otherwise ``0``.
- See also the :variable:`CMAKE_<LANG>_COMPILER_ID` variable.
+.. genex:: $<PATH:REPLACE_FILENAME,path,input>
-.. genex:: $<ISPC_COMPILER_ID:compiler_ids>
+ .. versionadded:: 3.24
- .. versionadded:: 3.19
+ Returns ``path`` with the filename component replaced by ``input``. If
+ ``path`` has no filename component (i.e. ``$<PATH:HAS_FILENAME>`` returns
+ ``0``), ``path`` is unchanged.
- where ``compiler_ids`` is a comma-separated list.
- ``1`` if the CMake's compiler id of the ISPC compiler matches any one
- of the entries in ``compiler_ids``, otherwise ``0``.
- See also the :variable:`CMAKE_<LANG>_COMPILER_ID` variable.
+ See :ref:`cmake_path(REPLACE_FILENAME) <REPLACE_FILENAME>` for more details.
+
+.. genex:: $<PATH:REMOVE_EXTENSION[,LAST_ONLY],path>
+
+ .. versionadded:: 3.24
+
+ Returns ``path`` with the :ref:`extension <EXTENSION_DEF>` removed, if any.
+
+ See :ref:`cmake_path(REMOVE_EXTENSION) <REMOVE_EXTENSION>` for more details.
+
+.. genex:: $<PATH:REPLACE_EXTENSION[,LAST_ONLY],path>
+
+ .. versionadded:: 3.24
+
+ Returns ``path`` with the :ref:`extension <EXTENSION_DEF>` replaced by
+ ``input``, if any.
+
+ See :ref:`cmake_path(REPLACE_EXTENSION) <REPLACE_EXTENSION>` for more details.
+
+.. genex:: $<PATH:NORMAL_PATH,path>
+
+ .. versionadded:: 3.24
+
+ Returns ``path`` normalized according to the steps described in
+ :ref:`Normalization`.
+
+.. genex:: $<PATH:RELATIVE_PATH,path,base_directory>
+
+ .. versionadded:: 3.24
+
+ Returns ``path``, modified to make it relative to the ``base_directory``
+ argument.
+
+ See :ref:`cmake_path(RELATIVE_PATH) <cmake_path-RELATIVE_PATH>` for more
+ details.
+
+.. genex:: $<PATH:ABSOLUTE_PATH[,NORMALIZE],path,base_directory>
+
+ .. versionadded:: 3.24
+
+ Returns ``path`` as absolute. If ``path`` is a relative path
+ (``$<PATH:IS_RELATIVE>`` returns ``1``), it is evaluated relative to the
+ given base directory specified by ``base_directory`` argument.
+
+ When the ``NORMALIZE`` option is specified, the path is
+ :ref:`normalized <Normalization>` after the path computation.
+
+ See :ref:`cmake_path(ABSOLUTE_PATH) <ABSOLUTE_PATH>` for more details.
+
+Shell Paths
+^^^^^^^^^^^
+
+.. genex:: $<SHELL_PATH:...>
+
+ .. versionadded:: 3.4
+
+ Content of ``...`` converted to shell path style. For example, slashes are
+ converted to backslashes in Windows shells and drive letters are converted
+ to posix paths in MSYS shells. The ``...`` must be an absolute path.
+
+ .. versionadded:: 3.14
+ The ``...`` may be a :ref:`semicolon-separated list <CMake Language Lists>`
+ of paths, in which case each path is converted individually and a result
+ list is generated using the shell path separator (``:`` on POSIX and
+ ``;`` on Windows). Be sure to enclose the argument containing this genex
+ in double quotes in CMake source code so that ``;`` does not split arguments.
+
+Configuration Expressions
+-------------------------
+
+.. genex:: $<CONFIG>
+
+ Configuration name. Use this instead of the deprecated :genex:`CONFIGURATION`
+ generator expression.
+
+.. genex:: $<CONFIG:cfgs>
+
+ ``1`` if config is any one of the entries in comma-separated list
+ ``cfgs``, else ``0``. This is a case-insensitive comparison. The mapping in
+ :prop_tgt:`MAP_IMPORTED_CONFIG_<CONFIG>` is also considered by this
+ expression when it is evaluated on a property of an :prop_tgt:`IMPORTED`
+ target.
+
+.. genex:: $<OUTPUT_CONFIG:...>
+
+ .. versionadded:: 3.20
+
+ Only valid in :command:`add_custom_command` and :command:`add_custom_target`
+ as the outer-most generator expression in an argument.
+ With the :generator:`Ninja Multi-Config` generator, generator expressions
+ in ``...`` are evaluated using the custom command's "output config".
+ With other generators, the content of ``...`` is evaluated normally.
+
+.. genex:: $<COMMAND_CONFIG:...>
+
+ .. versionadded:: 3.20
+
+ Only valid in :command:`add_custom_command` and :command:`add_custom_target`
+ as the outer-most generator expression in an argument.
+ With the :generator:`Ninja Multi-Config` generator, generator expressions
+ in ``...`` are evaluated using the custom command's "command config".
+ With other generators, the content of ``...`` is evaluated normally.
+
+Toolchain And Language Expressions
+----------------------------------
+
+Platform
+^^^^^^^^
+
+.. genex:: $<PLATFORM_ID>
+
+ The current system's CMake platform id.
+ See also the :variable:`CMAKE_SYSTEM_NAME` variable.
+
+.. genex:: $<PLATFORM_ID:platform_ids>
+
+ where ``platform_ids`` is a comma-separated list.
+ ``1`` if CMake's platform id matches any one of the entries in
+ ``platform_ids``, otherwise ``0``.
+ See also the :variable:`CMAKE_SYSTEM_NAME` variable.
+
+Compiler Version
+^^^^^^^^^^^^^^^^
+
+See also the :variable:`CMAKE_<LANG>_COMPILER_VERSION` variable, which is
+closely related to the expressions in this sub-section.
+
+.. genex:: $<C_COMPILER_VERSION>
+
+ The version of the C compiler used.
.. genex:: $<C_COMPILER_VERSION:version>
``1`` if the version of the C compiler matches ``version``, otherwise ``0``.
- See also the :variable:`CMAKE_<LANG>_COMPILER_VERSION` variable.
+
+.. genex:: $<CXX_COMPILER_VERSION>
+
+ The version of the CXX compiler used.
.. genex:: $<CXX_COMPILER_VERSION:version>
``1`` if the version of the CXX compiler matches ``version``, otherwise ``0``.
- See also the :variable:`CMAKE_<LANG>_COMPILER_VERSION` variable.
+
+.. genex:: $<CUDA_COMPILER_VERSION>
+
+ .. versionadded:: 3.15
+
+ The version of the CUDA compiler used.
.. genex:: $<CUDA_COMPILER_VERSION:version>
.. versionadded:: 3.15
``1`` if the version of the CXX compiler matches ``version``, otherwise ``0``.
- See also the :variable:`CMAKE_<LANG>_COMPILER_VERSION` variable.
+
+.. genex:: $<OBJC_COMPILER_VERSION>
+
+ .. versionadded:: 3.16
+
+ The version of the OBJC compiler used.
.. genex:: $<OBJC_COMPILER_VERSION:version>
.. versionadded:: 3.16
``1`` if the version of the OBJC compiler matches ``version``, otherwise ``0``.
- See also the :variable:`CMAKE_<LANG>_COMPILER_VERSION` variable.
+
+.. genex:: $<OBJCXX_COMPILER_VERSION>
+
+ .. versionadded:: 3.16
+
+ The version of the OBJCXX compiler used.
.. genex:: $<OBJCXX_COMPILER_VERSION:version>
.. versionadded:: 3.16
``1`` if the version of the OBJCXX compiler matches ``version``, otherwise ``0``.
- See also the :variable:`CMAKE_<LANG>_COMPILER_VERSION` variable.
+
+.. genex:: $<Fortran_COMPILER_VERSION>
+
+ The version of the Fortran compiler used.
.. genex:: $<Fortran_COMPILER_VERSION:version>
``1`` if the version of the Fortran compiler matches ``version``, otherwise ``0``.
- See also the :variable:`CMAKE_<LANG>_COMPILER_VERSION` variable.
+
+.. genex:: $<HIP_COMPILER_VERSION>
+
+ .. versionadded:: 3.21
+
+ The version of the HIP compiler used.
.. genex:: $<HIP_COMPILER_VERSION:version>
.. versionadded:: 3.21
``1`` if the version of the HIP compiler matches ``version``, otherwise ``0``.
- See also the :variable:`CMAKE_<LANG>_COMPILER_VERSION` variable.
+
+.. genex:: $<ISPC_COMPILER_VERSION>
+
+ .. versionadded:: 3.19
+
+ The version of the ISPC compiler used.
.. genex:: $<ISPC_COMPILER_VERSION:version>
.. versionadded:: 3.19
``1`` if the version of the ISPC compiler matches ``version``, otherwise ``0``.
- See also the :variable:`CMAKE_<LANG>_COMPILER_VERSION` variable.
-.. genex:: $<TARGET_POLICY:policy>
+Compiler Language And ID
+^^^^^^^^^^^^^^^^^^^^^^^^
- ``1`` if the ``policy`` was NEW when the 'head' target was created,
- else ``0``. If the ``policy`` was not set, the warning message for the policy
- will be emitted. This generator expression only works for a subset of
- policies.
+See also the :variable:`CMAKE_<LANG>_COMPILER_ID` variable, which is closely
+related to most of the expressions in this sub-section.
-.. genex:: $<COMPILE_FEATURES:features>
+.. genex:: $<C_COMPILER_ID>
- .. versionadded:: 3.1
+ CMake's compiler id of the C compiler used.
- where ``features`` is a comma-spearated list.
- Evaluates to ``1`` if all of the ``features`` are available for the 'head'
- target, and ``0`` otherwise. If this expression is used while evaluating
- the link implementation of a target and if any dependency transitively
- increases the required :prop_tgt:`C_STANDARD` or :prop_tgt:`CXX_STANDARD`
- for the 'head' target, an error is reported. See the
- :manual:`cmake-compile-features(7)` manual for information on
- compile features and a list of supported compilers.
+.. genex:: $<C_COMPILER_ID:compiler_ids>
-.. _`Boolean COMPILE_LANGUAGE Generator Expression`:
+ where ``compiler_ids`` is a comma-separated list.
+ ``1`` if CMake's compiler id of the C compiler matches any one
+ of the entries in ``compiler_ids``, otherwise ``0``.
-.. genex:: $<COMPILE_LANG_AND_ID:language,compiler_ids>
+.. genex:: $<CXX_COMPILER_ID>
+
+ CMake's compiler id of the CXX compiler used.
+
+.. genex:: $<CXX_COMPILER_ID:compiler_ids>
+
+ where ``compiler_ids`` is a comma-separated list.
+ ``1`` if CMake's compiler id of the CXX compiler matches any one
+ of the entries in ``compiler_ids``, otherwise ``0``.
+
+.. genex:: $<CUDA_COMPILER_ID>
.. versionadded:: 3.15
- ``1`` when the language used for compilation unit matches ``language`` and
- the CMake's compiler id of the language compiler matches any one of the
- entries in ``compiler_ids``, otherwise ``0``. This expression is a short form
- for the combination of ``$<COMPILE_LANGUAGE:language>`` and
- ``$<LANG_COMPILER_ID:compiler_ids>``. This expression may be used to specify
- compile options, compile definitions, and include directories for source files of a
- particular language and compiler combination in a target. For example:
+ CMake's compiler id of the CUDA compiler used.
- .. code-block:: cmake
+.. genex:: $<CUDA_COMPILER_ID:compiler_ids>
- add_executable(myapp main.cpp foo.c bar.cpp zot.cu)
- target_compile_definitions(myapp
- PRIVATE $<$<COMPILE_LANG_AND_ID:CXX,AppleClang,Clang>:COMPILING_CXX_WITH_CLANG>
- $<$<COMPILE_LANG_AND_ID:CXX,Intel>:COMPILING_CXX_WITH_INTEL>
- $<$<COMPILE_LANG_AND_ID:C,Clang>:COMPILING_C_WITH_CLANG>
- )
+ .. versionadded:: 3.15
- This specifies the use of different compile definitions based on both
- the compiler id and compilation language. This example will have a
- ``COMPILING_CXX_WITH_CLANG`` compile definition when Clang is the CXX
- compiler, and ``COMPILING_CXX_WITH_INTEL`` when Intel is the CXX compiler.
- Likewise when the C compiler is Clang it will only see the ``COMPILING_C_WITH_CLANG``
- definition.
+ where ``compiler_ids`` is a comma-separated list.
+ ``1`` if CMake's compiler id of the CUDA compiler matches any one
+ of the entries in ``compiler_ids``, otherwise ``0``.
- Without the ``COMPILE_LANG_AND_ID`` generator expression the same logic
- would be expressed as:
+.. genex:: $<OBJC_COMPILER_ID>
- .. code-block:: cmake
+ .. versionadded:: 3.16
- target_compile_definitions(myapp
- PRIVATE $<$<AND:$<COMPILE_LANGUAGE:CXX>,$<CXX_COMPILER_ID:AppleClang,Clang>>:COMPILING_CXX_WITH_CLANG>
- $<$<AND:$<COMPILE_LANGUAGE:CXX>,$<CXX_COMPILER_ID:Intel>>:COMPILING_CXX_WITH_INTEL>
- $<$<AND:$<COMPILE_LANGUAGE:C>,$<C_COMPILER_ID:Clang>>:COMPILING_C_WITH_CLANG>
- )
+ CMake's compiler id of the OBJC compiler used.
+
+.. genex:: $<OBJC_COMPILER_ID:compiler_ids>
+
+ .. versionadded:: 3.16
+
+ where ``compiler_ids`` is a comma-separated list.
+ ``1`` if CMake's compiler id of the Objective-C compiler matches any one
+ of the entries in ``compiler_ids``, otherwise ``0``.
+
+.. genex:: $<OBJCXX_COMPILER_ID>
+
+ .. versionadded:: 3.16
+
+ CMake's compiler id of the OBJCXX compiler used.
+
+.. genex:: $<OBJCXX_COMPILER_ID:compiler_ids>
+
+ .. versionadded:: 3.16
+
+ where ``compiler_ids`` is a comma-separated list.
+ ``1`` if CMake's compiler id of the Objective-C++ compiler matches any one
+ of the entries in ``compiler_ids``, otherwise ``0``.
+
+.. genex:: $<Fortran_COMPILER_ID>
+
+ CMake's compiler id of the Fortran compiler used.
+
+.. genex:: $<Fortran_COMPILER_ID:compiler_ids>
+
+ where ``compiler_ids`` is a comma-separated list.
+ ``1`` if CMake's compiler id of the Fortran compiler matches any one
+ of the entries in ``compiler_ids``, otherwise ``0``.
+
+.. genex:: $<HIP_COMPILER_ID>
+
+ .. versionadded:: 3.21
+
+ CMake's compiler id of the HIP compiler used.
+
+.. genex:: $<HIP_COMPILER_ID:compiler_ids>
+
+ .. versionadded:: 3.21
+
+ where ``compiler_ids`` is a comma-separated list.
+ ``1`` if CMake's compiler id of the HIP compiler matches any one
+ of the entries in ``compiler_ids``, otherwise ``0``.
+
+.. genex:: $<ISPC_COMPILER_ID>
+
+ .. versionadded:: 3.19
+
+ CMake's compiler id of the ISPC compiler used.
+
+.. genex:: $<ISPC_COMPILER_ID:compiler_ids>
+
+ .. versionadded:: 3.19
+
+ where ``compiler_ids`` is a comma-separated list.
+ ``1`` if CMake's compiler id of the ISPC compiler matches any one
+ of the entries in ``compiler_ids``, otherwise ``0``.
+
+.. genex:: $<COMPILE_LANGUAGE>
+
+ .. versionadded:: 3.3
+
+ The compile language of source files when evaluating compile options.
+ See :ref:`the related boolean expression
+ <Boolean COMPILE_LANGUAGE Generator Expression>`
+ ``$<COMPILE_LANGUAGE:language>``
+ for notes about the portability of this generator expression.
+
+.. _`Boolean COMPILE_LANGUAGE Generator Expression`:
.. genex:: $<COMPILE_LANGUAGE:languages>
@@ -411,8 +846,8 @@ Variable Queries
``1`` when the language used for compilation unit matches any of the entries
in ``languages``, otherwise ``0``. This expression may be used to specify
- compile options, compile definitions, and include directories for source files of a
- particular language in a target. For example:
+ compile options, compile definitions, and include directories for source
+ files of a particular language in a target. For example:
.. code-block:: cmake
@@ -451,49 +886,82 @@ Variable Queries
add_executable(myapp main.cpp)
target_link_libraries(myapp myapp_c myapp_cxx)
-.. _`Boolean LINK_LANGUAGE Generator Expression`:
-
-.. genex:: $<LINK_LANG_AND_ID:language,compiler_ids>
+.. genex:: $<COMPILE_LANG_AND_ID:language,compiler_ids>
- .. versionadded:: 3.18
+ .. versionadded:: 3.15
- ``1`` when the language used for link step matches ``language`` and the
- CMake's compiler id of the language linker matches any one of the entries
- in ``compiler_ids``, otherwise ``0``. This expression is a short form for the
- combination of ``$<LINK_LANGUAGE:language>`` and
+ ``1`` when the language used for compilation unit matches ``language`` and
+ CMake's compiler id of the ``language`` compiler matches any one of the
+ entries in ``compiler_ids``, otherwise ``0``. This expression is a short form
+ for the combination of ``$<COMPILE_LANGUAGE:language>`` and
``$<LANG_COMPILER_ID:compiler_ids>``. This expression may be used to specify
- link libraries, link options, link directories and link dependencies of a
- particular language and linker combination in a target. For example:
+ compile options, compile definitions, and include directories for source
+ files of a particular language and compiler combination in a target.
+ For example:
.. code-block:: cmake
- add_library(libC_Clang ...)
- add_library(libCXX_Clang ...)
- add_library(libC_Intel ...)
- add_library(libCXX_Intel ...)
+ add_executable(myapp main.cpp foo.c bar.cpp zot.cu)
+ target_compile_definitions(myapp
+ PRIVATE $<$<COMPILE_LANG_AND_ID:CXX,AppleClang,Clang>:COMPILING_CXX_WITH_CLANG>
+ $<$<COMPILE_LANG_AND_ID:CXX,Intel>:COMPILING_CXX_WITH_INTEL>
+ $<$<COMPILE_LANG_AND_ID:C,Clang>:COMPILING_C_WITH_CLANG>
+ )
- add_executable(myapp main.c)
- if (CXX_CONFIG)
- target_sources(myapp PRIVATE file.cxx)
- endif()
- target_link_libraries(myapp
- PRIVATE $<$<LINK_LANG_AND_ID:CXX,Clang,AppleClang>:libCXX_Clang>
- $<$<LINK_LANG_AND_ID:C,Clang,AppleClang>:libC_Clang>
- $<$<LINK_LANG_AND_ID:CXX,Intel>:libCXX_Intel>
- $<$<LINK_LANG_AND_ID:C,Intel>:libC_Intel>)
+ This specifies the use of different compile definitions based on both
+ the compiler id and compilation language. This example will have a
+ ``COMPILING_CXX_WITH_CLANG`` compile definition when Clang is the CXX
+ compiler, and ``COMPILING_CXX_WITH_INTEL`` when Intel is the CXX compiler.
+ Likewise, when the C compiler is Clang, it will only see the
+ ``COMPILING_C_WITH_CLANG`` definition.
- This specifies the use of different link libraries based on both the
- compiler id and link language. This example will have target ``libCXX_Clang``
- as link dependency when ``Clang`` or ``AppleClang`` is the ``CXX``
- linker, and ``libCXX_Intel`` when ``Intel`` is the ``CXX`` linker.
- Likewise when the ``C`` linker is ``Clang`` or ``AppleClang``, target
- ``libC_Clang`` will be added as link dependency and ``libC_Intel`` when
- ``Intel`` is the ``C`` linker.
+ Without the ``COMPILE_LANG_AND_ID`` generator expression, the same logic
+ would be expressed as:
- See :ref:`the note related to
- <Constraints LINK_LANGUAGE Generator Expression>`
- ``$<LINK_LANGUAGE:language>`` for constraints about the usage of this
- generator expression.
+ .. code-block:: cmake
+
+ target_compile_definitions(myapp
+ PRIVATE $<$<AND:$<COMPILE_LANGUAGE:CXX>,$<CXX_COMPILER_ID:AppleClang,Clang>>:COMPILING_CXX_WITH_CLANG>
+ $<$<AND:$<COMPILE_LANGUAGE:CXX>,$<CXX_COMPILER_ID:Intel>>:COMPILING_CXX_WITH_INTEL>
+ $<$<AND:$<COMPILE_LANGUAGE:C>,$<C_COMPILER_ID:Clang>>:COMPILING_C_WITH_CLANG>
+ )
+
+Compile Features
+^^^^^^^^^^^^^^^^
+
+.. genex:: $<COMPILE_FEATURES:features>
+
+ .. versionadded:: 3.1
+
+ where ``features`` is a comma-separated list.
+ Evaluates to ``1`` if all of the ``features`` are available for the 'head'
+ target, and ``0`` otherwise. If this expression is used while evaluating
+ the link implementation of a target and if any dependency transitively
+ increases the required :prop_tgt:`C_STANDARD` or :prop_tgt:`CXX_STANDARD`
+ for the 'head' target, an error is reported. See the
+ :manual:`cmake-compile-features(7)` manual for information on
+ compile features and a list of supported compilers.
+
+Linker Language And ID
+^^^^^^^^^^^^^^^^^^^^^^
+
+.. genex:: $<LINK_LANGUAGE>
+
+ .. versionadded:: 3.18
+
+ The link language of the target when evaluating link options.
+ See :ref:`the related boolean expression
+ <Boolean LINK_LANGUAGE Generator Expression>` ``$<LINK_LANGUAGE:languages>``
+ for notes about the portability of this generator expression.
+
+ .. note::
+
+ This generator expression is not supported by the link libraries
+ properties to avoid side-effects due to the double evaluation of
+ these properties.
+
+
+.. _`Boolean LINK_LANGUAGE Generator Expression`:
.. genex:: $<LINK_LANGUAGE:languages>
@@ -509,7 +977,7 @@ Variable Queries
add_library(api_C ...)
add_library(api_CXX ...)
add_library(api INTERFACE)
- target_link_options(api INTERFACE $<$<LINK_LANGUAGE:C>:-opt_c>
+ target_link_options(api INTERFACE $<$<LINK_LANGUAGE:C>:-opt_c>
$<$<LINK_LANGUAGE:CXX>:-opt_cxx>)
target_link_libraries(api INTERFACE $<$<LINK_LANGUAGE:C>:api_C>
$<$<LINK_LANGUAGE:CXX>:api_CXX>)
@@ -560,485 +1028,391 @@ Variable Queries
evaluation will give ``C`` as link language, so the second pass will
correctly add target ``libother`` as link dependency.
-String-Valued Generator Expressions
-===================================
-
-These expressions expand to some string.
-For example,
-
-.. code-block:: cmake
-
- include_directories(/usr/include/$<CXX_COMPILER_ID>/)
-
-expands to ``/usr/include/GNU/`` or ``/usr/include/Clang/`` etc, depending on
-the compiler identifier.
-
-String-valued expressions may also be combined with other expressions.
-Here an example for a string-valued expression within a boolean expressions
-within a conditional expression:
-
-.. code-block:: cmake
-
- $<$<VERSION_LESS:$<CXX_COMPILER_VERSION>,4.2.0>:OLD_COMPILER>
-
-expands to ``OLD_COMPILER`` if the
-:variable:`CMAKE_CXX_COMPILER_VERSION <CMAKE_<LANG>_COMPILER_VERSION>` is less
-than 4.2.0.
-
-And here two nested string-valued expressions:
-
-.. code-block:: cmake
-
- -I$<JOIN:$<TARGET_PROPERTY:INCLUDE_DIRECTORIES>, -I>
-
-generates a string of the entries in the :prop_tgt:`INCLUDE_DIRECTORIES` target
-property with each entry preceded by ``-I``.
-
-Expanding on the previous example, if one first wants to check if the
-``INCLUDE_DIRECTORIES`` property is non-empty, then it is advisable to
-introduce a helper variable to keep the code readable:
-
-.. code-block:: cmake
-
- set(prop "$<TARGET_PROPERTY:INCLUDE_DIRECTORIES>") # helper variable
- $<$<BOOL:${prop}>:-I$<JOIN:${prop}, -I>>
-
-The following string-valued generator expressions are available:
-
-Escaped Characters
-------------------
-
-String literals to escape the special meaning a character would otherwise have:
-
-.. genex:: $<ANGLE-R>
-
- A literal ``>``. Used for example to compare strings that contain a ``>``.
-
-.. genex:: $<COMMA>
-
- A literal ``,``. Used for example to compare strings which contain a ``,``.
-
-.. genex:: $<SEMICOLON>
-
- A literal ``;``. Used to prevent list expansion on an argument with ``;``.
-
-.. _`Conditional Generator Expressions`:
-
-Conditional Expressions
------------------------
-
-Conditional generator expressions depend on a boolean condition
-that must be ``0`` or ``1``.
-
-.. genex:: $<condition:true_string>
-
- Evaluates to ``true_string`` if ``condition`` is ``1``.
- Otherwise evaluates to the empty string.
-
-.. genex:: $<IF:condition,true_string,false_string>
-
- .. versionadded:: 3.8
-
- Evaluates to ``true_string`` if ``condition`` is ``1``.
- Otherwise evaluates to ``false_string``.
-
-Typically, the ``condition`` is a :ref:`boolean generator expression
-<Boolean Generator Expressions>`. For instance,
-
-.. code-block:: cmake
-
- $<$<CONFIG:Debug>:DEBUG_MODE>
-
-expands to ``DEBUG_MODE`` when the ``Debug`` configuration is used, and
-otherwise expands to the empty string.
-
-.. _`String Transforming Generator Expressions`:
-
-String Transformations
-----------------------
-
-.. genex:: $<JOIN:list,string>
-
- Joins the list with the content of ``string``.
-
-.. genex:: $<REMOVE_DUPLICATES:list>
-
- .. versionadded:: 3.15
-
- Removes duplicated items in the given ``list``. The relative order of items
- is preserved, but if duplicates are encountered, only the first instance is
- preserved.
-
-.. genex:: $<FILTER:list,INCLUDE|EXCLUDE,regex>
-
- .. versionadded:: 3.15
-
- Includes or removes items from ``list`` that match the regular expression ``regex``.
-
-.. genex:: $<LOWER_CASE:string>
-
- Content of ``string`` converted to lower case.
-
-.. genex:: $<UPPER_CASE:string>
-
- Content of ``string`` converted to upper case.
-
-.. genex:: $<GENEX_EVAL:expr>
-
- .. versionadded:: 3.12
-
- Content of ``expr`` evaluated as a generator expression in the current
- context. This enables consumption of generator expressions whose
- evaluation results itself in generator expressions.
-
-.. genex:: $<TARGET_GENEX_EVAL:tgt,expr>
-
- .. versionadded:: 3.12
-
- Content of ``expr`` evaluated as a generator expression in the context of
- ``tgt`` target. This enables consumption of custom target properties that
- themselves contain generator expressions.
-
- Having the capability to evaluate generator expressions is very useful when
- you want to manage custom properties supporting generator expressions.
- For example:
-
- .. code-block:: cmake
-
- add_library(foo ...)
-
- set_property(TARGET foo PROPERTY
- CUSTOM_KEYS $<$<CONFIG:DEBUG>:FOO_EXTRA_THINGS>
- )
-
- add_custom_target(printFooKeys
- COMMAND ${CMAKE_COMMAND} -E echo $<TARGET_PROPERTY:foo,CUSTOM_KEYS>
- )
+.. genex:: $<LINK_LANG_AND_ID:language,compiler_ids>
- This naive implementation of the ``printFooKeys`` custom command is wrong
- because ``CUSTOM_KEYS`` target property is not evaluated and the content
- is passed as is (i.e. ``$<$<CONFIG:DEBUG>:FOO_EXTRA_THINGS>``).
+ .. versionadded:: 3.18
- To have the expected result (i.e. ``FOO_EXTRA_THINGS`` if config is
- ``Debug``), it is required to evaluate the output of
- ``$<TARGET_PROPERTY:foo,CUSTOM_KEYS>``:
+ ``1`` when the language used for link step matches ``language`` and the
+ CMake's compiler id of the language linker matches any one of the entries
+ in ``compiler_ids``, otherwise ``0``. This expression is a short form for the
+ combination of ``$<LINK_LANGUAGE:language>`` and
+ ``$<LANG_COMPILER_ID:compiler_ids>``. This expression may be used to specify
+ link libraries, link options, link directories and link dependencies of a
+ particular language and linker combination in a target. For example:
.. code-block:: cmake
- add_custom_target(printFooKeys
- COMMAND ${CMAKE_COMMAND} -E
- echo $<TARGET_GENEX_EVAL:foo,$<TARGET_PROPERTY:foo,CUSTOM_KEYS>>
- )
-
-.. _GenEx Path Decomposition:
-
-Path Decomposition
-------------------
-
-The ``$<PATH>`` generator expression offers the same capabilities as the
-:command:`cmake_path` command, for the
-:ref:`Decomposition <Path Decomposition>` options.
-
-For all ``$<PATH>`` generator expressions, paths are expected in cmake-style
-format. The :ref:`$\<PATH:CMAKE_PATH\> <GenEx PATH-CMAKE_PATH>` generator
-expression can be used to convert a native path to a cmake-style one.
-
-The ``$<PATH>`` generator expression can also be used for path
-:ref:`Queries <GenEx Path Queries>` and
-:ref:`Transformations <GenEx Path Transformations>`.
-
-.. genex:: $<PATH:GET_*,...>
-
- .. versionadded:: 3.24
-
- The following operations retrieve a different component or group of
- components from a path. See :ref:`Path Structure And Terminology` for the
- meaning of each path component.
-
- ::
-
- $<PATH:GET_ROOT_NAME,path>
- $<PATH:GET_ROOT_DIRECTORY,path>
- $<PATH:GET_ROOT_PATH,path>
- $<PATH:GET_FILENAME,path>
- $<PATH:GET_EXTENSION[,LAST_ONLY],path>
- $<PATH:GET_STEM[,LAST_ONLY],path>
- $<PATH:GET_RELATIVE_PART,path>
- $<PATH:GET_PARENT_PATH,path>
-
- If a requested component is not present in the path, an empty string is
- returned.
-
-.. _GenEx Path Transformations:
-
-Path Transformations
---------------------
+ add_library(libC_Clang ...)
+ add_library(libCXX_Clang ...)
+ add_library(libC_Intel ...)
+ add_library(libCXX_Intel ...)
-The ``$<PATH>`` generator expression offers the same capabilities as the
-:command:`cmake_path` command, for the
-:ref:`Modification <Path Modification>` and
-:ref:`Generation <Path Generation>` options.
+ add_executable(myapp main.c)
+ if (CXX_CONFIG)
+ target_sources(myapp PRIVATE file.cxx)
+ endif()
+ target_link_libraries(myapp
+ PRIVATE $<$<LINK_LANG_AND_ID:CXX,Clang,AppleClang>:libCXX_Clang>
+ $<$<LINK_LANG_AND_ID:C,Clang,AppleClang>:libC_Clang>
+ $<$<LINK_LANG_AND_ID:CXX,Intel>:libCXX_Intel>
+ $<$<LINK_LANG_AND_ID:C,Intel>:libC_Intel>)
-For all ``$<PATH>`` generator expressions, paths are expected in cmake-style
-format. The :ref:`$\<PATH:CMAKE_PATH\> <GenEx PATH-CMAKE_PATH>` generator
-expression can be used to convert a native path to a cmake-style one.
+ This specifies the use of different link libraries based on both the
+ compiler id and link language. This example will have target ``libCXX_Clang``
+ as link dependency when ``Clang`` or ``AppleClang`` is the ``CXX``
+ linker, and ``libCXX_Intel`` when ``Intel`` is the ``CXX`` linker.
+ Likewise when the ``C`` linker is ``Clang`` or ``AppleClang``, target
+ ``libC_Clang`` will be added as link dependency and ``libC_Intel`` when
+ ``Intel`` is the ``C`` linker.
-The ``$<PATH>`` generator expression can also be used for path
-:ref:`Queries <GenEx Path Queries>` and
-:ref:`Decomposition <GenEx Path Decomposition>`.
+ See :ref:`the note related to
+ <Constraints LINK_LANGUAGE Generator Expression>`
+ ``$<LINK_LANGUAGE:language>`` for constraints about the usage of this
+ generator expression.
-.. _GenEx PATH-CMAKE_PATH:
+Link Features
+^^^^^^^^^^^^^
-.. genex:: $<PATH:CMAKE_PATH[,NORMALIZE],path>
+.. genex:: $<LINK_LIBRARY:feature,library-list>
.. versionadded:: 3.24
- Returns ``path``. If ``path`` is a native path, it is converted into a
- cmake-style path with forward-slashes (``/``). On Windows, the long filename
- marker is taken into account.
-
- When the ``NORMALIZE`` option is specified, the path is :ref:`normalized
- <Normalization>` after the conversion.
+ Specify a set of libraries to link to a target, along with a ``feature``
+ which provides details about *how* they should be linked. For example:
-.. genex:: $<PATH:APPEND,path,input,...>
+ .. code-block:: cmake
- .. versionadded:: 3.24
+ add_library(lib1 STATIC ...)
+ add_library(lib2 ...)
+ target_link_libraries(lib2 PRIVATE "$<LINK_LIBRARY:WHOLE_ARCHIVE,lib1>")
- Returns all the ``input`` arguments appended to ``path`` using ``/`` as the
- ``directory-separator``. Depending on the ``input``, the value of ``path``
- may be discarded.
+ This specifies that ``lib2`` should link to ``lib1`` and use the
+ ``WHOLE_ARCHIVE`` feature when doing so.
- See :ref:`cmake_path(APPEND) <APPEND>` for more details.
+ Feature names are case-sensitive and may only contain letters, numbers and
+ underscores. Feature names defined in all uppercase are reserved for CMake's
+ own built-in features. The pre-defined built-in library features are:
-.. genex:: $<PATH:REMOVE_FILENAME,path>
+ .. include:: ../variable/LINK_LIBRARY_PREDEFINED_FEATURES.txt
- .. versionadded:: 3.24
+ Built-in and custom library features are defined in terms of the following
+ variables:
- Returns ``path`` with filename component (as returned by
- ``$<PATH:GET_FILENAME>``) removed. After removal, any trailing
- ``directory-separator`` is left alone, if present.
+ * :variable:`CMAKE_<LANG>_LINK_LIBRARY_USING_<FEATURE>_SUPPORTED`
+ * :variable:`CMAKE_<LANG>_LINK_LIBRARY_USING_<FEATURE>`
+ * :variable:`CMAKE_LINK_LIBRARY_USING_<FEATURE>_SUPPORTED`
+ * :variable:`CMAKE_LINK_LIBRARY_USING_<FEATURE>`
- See :ref:`cmake_path(REMOVE_FILENAME) <REMOVE_FILENAME>` for more details.
+ The value used for each of these variables is the value as set at the end of
+ the directory scope in which the target was created. The usage is as follows:
-.. genex:: $<PATH:REPLACE_FILENAME,path,input>
+ 1. If the language-specific
+ :variable:`CMAKE_<LANG>_LINK_LIBRARY_USING_<FEATURE>_SUPPORTED` variable
+ is true, the ``feature`` must be defined by the corresponding
+ :variable:`CMAKE_<LANG>_LINK_LIBRARY_USING_<FEATURE>` variable.
+ 2. If no language-specific ``feature`` is supported, then the
+ :variable:`CMAKE_LINK_LIBRARY_USING_<FEATURE>_SUPPORTED` variable must be
+ true and the ``feature`` must be defined by the corresponding
+ :variable:`CMAKE_LINK_LIBRARY_USING_<FEATURE>` variable.
- .. versionadded:: 3.24
+ The following limitations should be noted:
- Returns ``path`` with the filename component replaced by ``input``. If
- ``path`` has no filename component (i.e. ``$<PATH:HAS_FILENAME>`` returns
- ``0``), ``path`` is unchanged.
+ * The ``library-list`` can specify CMake targets or libraries.
+ Any CMake target of type :ref:`OBJECT <Object Libraries>`
+ or :ref:`INTERFACE <Interface Libraries>` will ignore the feature aspect
+ of the expression and instead be linked in the standard way.
- See :ref:`cmake_path(REPLACE_FILENAME) <REPLACE_FILENAME>` for more details.
+ * The ``$<LINK_LIBRARY:...>`` generator expression can only be used to
+ specify link libraries. In practice, this means it can appear in the
+ :prop_tgt:`LINK_LIBRARIES`, :prop_tgt:`INTERFACE_LINK_LIBRARIES`, and
+ :prop_tgt:`INTERFACE_LINK_LIBRARIES_DIRECT` target properties, and be
+ specified in :command:`target_link_libraries` and :command:`link_libraries`
+ commands.
-.. genex:: $<PATH:REMOVE_EXTENSION[,LAST_ONLY],path>
+ * If a ``$<LINK_LIBRARY:...>`` generator expression appears in the
+ :prop_tgt:`INTERFACE_LINK_LIBRARIES` property of a target, it will be
+ included in the imported target generated by a :command:`install(EXPORT)`
+ command. It is the responsibility of the environment consuming this
+ import to define the link feature used by this expression.
- .. versionadded:: 3.24
+ * Each target or library involved in the link step must have at most only
+ one kind of library feature. The absence of a feature is also incompatible
+ with all other features. For example:
- Returns ``path`` with the :ref:`extension <EXTENSION_DEF>` removed, if any.
+ .. code-block:: cmake
- See :ref:`cmake_path(REMOVE_EXTENSION) <REMOVE_EXTENSION>` for more details.
+ add_library(lib1 ...)
+ add_library(lib2 ...)
+ add_library(lib3 ...)
-.. genex:: $<PATH:REPLACE_EXTENSION[,LAST_ONLY],path>
+ # lib1 will be associated with feature1
+ target_link_libraries(lib2 PUBLIC "$<LINK_LIBRARY:feature1,lib1>")
- .. versionadded:: 3.24
+ # lib1 is being linked with no feature here. This conflicts with the
+ # use of feature1 in the line above and would result in an error.
+ target_link_libraries(lib3 PRIVATE lib1 lib2)
- Returns ``path`` with the :ref:`extension <EXTENSION_DEF>` replaced by
- ``input``, if any.
+ Where it isn't possible to use the same feature throughout a build for a
+ given target or library, the :prop_tgt:`LINK_LIBRARY_OVERRIDE` and
+ :prop_tgt:`LINK_LIBRARY_OVERRIDE_<LIBRARY>` target properties can be
+ used to resolve such incompatibilities.
- See :ref:`cmake_path(REPLACE_EXTENSION) <REPLACE_EXTENSION>` for more details.
+ * The ``$<LINK_LIBRARY:...>`` generator expression does not guarantee
+ that the list of specified targets and libraries will be kept grouped
+ together. To manage constructs like ``--start-group`` and ``--end-group``,
+ as supported by the GNU ``ld`` linker, use the :genex:`LINK_GROUP`
+ generator expression instead.
-.. genex:: $<PATH:NORMAL_PATH,path>
+.. genex:: $<LINK_GROUP:feature,library-list>
.. versionadded:: 3.24
- Returns ``path`` normalized according to the steps described in
- :ref:`Normalization`.
-
-.. genex:: $<PATH:RELATIVE_PATH,path,base_directory>
+ Specify a group of libraries to link to a target, along with a ``feature``
+ which defines how that group should be linked. For example:
- .. versionadded:: 3.24
+ .. code-block:: cmake
- Returns ``path``, modified to make it relative to the ``base_directory``
- argument.
+ add_library(lib1 STATIC ...)
+ add_library(lib2 ...)
+ target_link_libraries(lib2 PRIVATE "$<LINK_GROUP:RESCAN,lib1,external>")
- See :ref:`cmake_path(RELATIVE_PATH) <cmake_path-RELATIVE_PATH>` for more
- details.
+ This specifies that ``lib2`` should link to ``lib1`` and ``external``, and
+ that both of those two libraries should be included on the linker command
+ line according to the definition of the ``RESCAN`` feature.
-.. genex:: $<PATH:ABSOLUTE_PATH[,NORMALIZE],path,base_directory>
+ Feature names are case-sensitive and may only contain letters, numbers and
+ underscores. Feature names defined in all uppercase are reserved for CMake's
+ own built-in features. Currently, there is only one pre-defined built-in
+ group feature:
- .. versionadded:: 3.24
+ .. include:: ../variable/LINK_GROUP_PREDEFINED_FEATURES.txt
- Returns ``path`` as absolute. If ``path`` is a relative path
- (``$<PATH:IS_RELATIVE>`` returns ``1``), it is evaluated relative to the
- given base directory specified by ``base_directory`` argument.
+ Built-in and custom group features are defined in terms of the following
+ variables:
- When the ``NORMALIZE`` option is specified, the path is
- :ref:`normalized <Normalization>` after the path computation.
+ * :variable:`CMAKE_<LANG>_LINK_GROUP_USING_<FEATURE>_SUPPORTED`
+ * :variable:`CMAKE_<LANG>_LINK_GROUP_USING_<FEATURE>`
+ * :variable:`CMAKE_LINK_GROUP_USING_<FEATURE>_SUPPORTED`
+ * :variable:`CMAKE_LINK_GROUP_USING_<FEATURE>`
- See :ref:`cmake_path(ABSOLUTE_PATH) <ABSOLUTE_PATH>` for more details.
+ The value used for each of these variables is the value as set at the end of
+ the directory scope in which the target was created. The usage is as follows:
-Variable Queries
-----------------
+ 1. If the language-specific
+ :variable:`CMAKE_<LANG>_LINK_GROUP_USING_<FEATURE>_SUPPORTED` variable
+ is true, the ``feature`` must be defined by the corresponding
+ :variable:`CMAKE_<LANG>_LINK_GROUP_USING_<FEATURE>` variable.
+ 2. If no language-specific ``feature`` is supported, then the
+ :variable:`CMAKE_LINK_GROUP_USING_<FEATURE>_SUPPORTED` variable must be
+ true and the ``feature`` must be defined by the corresponding
+ :variable:`CMAKE_LINK_GROUP_USING_<FEATURE>` variable.
-.. genex:: $<CONFIG>
+ The ``LINK_GROUP`` generator expression is compatible with the
+ :genex:`LINK_LIBRARY` generator expression. The libraries involved in a
+ group can be specified using the :genex:`LINK_LIBRARY` generator expression.
- Configuration name.
+ Each target or external library involved in the link step is allowed to be
+ part of multiple groups, but only if all the groups involved specify the
+ same ``feature``. Such groups will not be merged on the linker command line,
+ the individual groups will still be preserved. Mixing different group
+ features for the same target or library is forbidden.
-.. genex:: $<CONFIGURATION>
+ .. code-block:: cmake
- Configuration name. Deprecated since CMake 3.0. Use ``CONFIG`` instead.
+ add_library(lib1 ...)
+ add_library(lib2 ...)
+ add_library(lib3 ...)
+ add_library(lib4 ...)
+ add_library(lib5 ...)
-.. genex:: $<PLATFORM_ID>
+ target_link_libraries(lib3 PUBLIC "$<LINK_GROUP:feature1,lib1,lib2>")
+ target_link_libraries(lib4 PRIVATE "$<LINK_GROUP:feature1,lib1,lib3>")
+ # lib4 will be linked with the groups {lib1,lib2} and {lib1,lib3}.
+ # Both groups specify the same feature, so this is fine.
- The current system's CMake platform id.
- See also the :variable:`CMAKE_SYSTEM_NAME` variable.
+ target_link_libraries(lib5 PRIVATE "$<LINK_GROUP:feature2,lib1,lib3>")
+ # An error will be raised here because both lib1 and lib3 are part of two
+ # groups with different features.
-.. genex:: $<C_COMPILER_ID>
+ When a target or an external library is involved in the link step as part of
+ a group and also as not part of any group, any occurrence of the non-group
+ link item will be replaced by the groups it belongs to.
- The CMake's compiler id of the C compiler used.
- See also the :variable:`CMAKE_<LANG>_COMPILER_ID` variable.
+ .. code-block:: cmake
-.. genex:: $<CXX_COMPILER_ID>
+ add_library(lib1 ...)
+ add_library(lib2 ...)
+ add_library(lib3 ...)
+ add_library(lib4 ...)
- The CMake's compiler id of the CXX compiler used.
- See also the :variable:`CMAKE_<LANG>_COMPILER_ID` variable.
+ target_link_libraries(lib3 PUBLIC lib1)
-.. genex:: $<CUDA_COMPILER_ID>
+ target_link_libraries(lib4 PRIVATE lib3 "$<LINK_GROUP:feature1,lib1,lib2>")
+ # lib4 will only be linked with lib3 and the group {lib1,lib2}
- The CMake's compiler id of the CUDA compiler used.
- See also the :variable:`CMAKE_<LANG>_COMPILER_ID` variable.
+ Because ``lib1`` is part of the group defined for ``lib4``, that group then
+ gets applied back to the use of ``lib1`` for ``lib3``. The end result will
+ be as though the linking relationship for ``lib3`` had been specified as:
-.. genex:: $<OBJC_COMPILER_ID>
+ .. code-block:: cmake
- .. versionadded:: 3.16
+ target_link_libraries(lib3 PUBLIC "$<LINK_GROUP:feature1,lib1,lib2>")
- The CMake's compiler id of the OBJC compiler used.
- See also the :variable:`CMAKE_<LANG>_COMPILER_ID` variable.
+ Be aware that the precedence of the group over the non-group link item can
+ result in circular dependencies between groups. If this occurs, a fatal
+ error is raised because circular dependencies are not allowed for groups.
-.. genex:: $<OBJCXX_COMPILER_ID>
+ .. code-block:: cmake
- .. versionadded:: 3.16
+ add_library(lib1A ...)
+ add_library(lib1B ...)
+ add_library(lib2A ...)
+ add_library(lib2B ...)
+ add_library(lib3 ...)
- The CMake's compiler id of the OBJCXX compiler used.
- See also the :variable:`CMAKE_<LANG>_COMPILER_ID` variable.
+ # Non-group linking relationships, these are non-circular so far
+ target_link_libraries(lib1A PUBLIC lib2A)
+ target_link_libraries(lib2B PUBLIC lib1B)
-.. genex:: $<Fortran_COMPILER_ID>
+ # The addition of these groups creates circular dependencies
+ target_link_libraries(lib3 PRIVATE
+ "$<LINK_GROUP:feat,lib1A,lib1B>"
+ "$<LINK_GROUP:feat,lib2A,lib2B>"
+ )
- The CMake's compiler id of the Fortran compiler used.
- See also the :variable:`CMAKE_<LANG>_COMPILER_ID` variable.
+ Because of the groups defined for ``lib3``, the linking relationships for
+ ``lib1A`` and ``lib2B`` effectively get expanded to the equivalent of:
-.. genex:: $<HIP_COMPILER_ID>
+ .. code-block:: cmake
- .. versionadded:: 3.21
+ target_link_libraries(lib1A PUBLIC "$<LINK_GROUP:feat,lib2A,lib2B>")
+ target_link_libraries(lib2B PUBLIC "$<LINK_GROUP:feat,lib1A,lib1B>")
- The CMake's compiler id of the HIP compiler used.
- See also the :variable:`CMAKE_<LANG>_COMPILER_ID` variable.
+ This creates a circular dependency between groups:
+ ``lib1A --> lib2B --> lib1A``.
-.. genex:: $<ISPC_COMPILER_ID>
+ The following limitations should also be noted:
- .. versionadded:: 3.19
+ * The ``library-list`` can specify CMake targets or libraries.
+ Any CMake target of type :ref:`OBJECT <Object Libraries>`
+ or :ref:`INTERFACE <Interface Libraries>` will ignore the feature aspect
+ of the expression and instead be linked in the standard way.
- The CMake's compiler id of the ISPC compiler used.
- See also the :variable:`CMAKE_<LANG>_COMPILER_ID` variable.
+ * The ``$<LINK_GROUP:...>`` generator expression can only be used to
+ specify link libraries. In practice, this means it can appear in the
+ :prop_tgt:`LINK_LIBRARIES`, :prop_tgt:`INTERFACE_LINK_LIBRARIES`,and
+ :prop_tgt:`INTERFACE_LINK_LIBRARIES_DIRECT` target properties, and be
+ specified in :command:`target_link_libraries` and :command:`link_libraries`
+ commands.
-.. genex:: $<C_COMPILER_VERSION>
+ * If a ``$<LINK_GROUP:...>`` generator expression appears in the
+ :prop_tgt:`INTERFACE_LINK_LIBRARIES` property of a target, it will be
+ included in the imported target generated by a :command:`install(EXPORT)`
+ command. It is the responsibility of the environment consuming this
+ import to define the link feature used by this expression.
- The version of the C compiler used.
- See also the :variable:`CMAKE_<LANG>_COMPILER_VERSION` variable.
+Link Context
+^^^^^^^^^^^^
-.. genex:: $<CXX_COMPILER_VERSION>
+.. genex:: $<LINK_ONLY:...>
- The version of the CXX compiler used.
- See also the :variable:`CMAKE_<LANG>_COMPILER_VERSION` variable.
+ .. versionadded:: 3.1
-.. genex:: $<CUDA_COMPILER_VERSION>
+ Content of ``...``, except while collecting :ref:`Target Usage Requirements`,
+ in which case it is the empty string. This is intended for use in an
+ :prop_tgt:`INTERFACE_LINK_LIBRARIES` target property, typically populated
+ via the :command:`target_link_libraries` command, to specify private link
+ dependencies without other usage requirements.
- The version of the CUDA compiler used.
- See also the :variable:`CMAKE_<LANG>_COMPILER_VERSION` variable.
+ .. versionadded:: 3.24
+ ``LINK_ONLY`` may also be used in a :prop_tgt:`LINK_LIBRARIES` target
+ property. See policy :policy:`CMP0131`.
-.. genex:: $<OBJC_COMPILER_VERSION>
+.. genex:: $<DEVICE_LINK:list>
- .. versionadded:: 3.16
+ .. versionadded:: 3.18
- The version of the OBJC compiler used.
- See also the :variable:`CMAKE_<LANG>_COMPILER_VERSION` variable.
+ Returns the list if it is the device link step, an empty list otherwise.
+ The device link step is controlled by :prop_tgt:`CUDA_SEPARABLE_COMPILATION`
+ and :prop_tgt:`CUDA_RESOLVE_DEVICE_SYMBOLS` properties and
+ policy :policy:`CMP0105`. This expression can only be used to specify link
+ options.
-.. genex:: $<OBJCXX_COMPILER_VERSION>
+.. genex:: $<HOST_LINK:list>
- .. versionadded:: 3.16
+ .. versionadded:: 3.18
- The version of the OBJCXX compiler used.
- See also the :variable:`CMAKE_<LANG>_COMPILER_VERSION` variable.
+ Returns the list if it is the normal link step, an empty list otherwise.
+ This expression is mainly useful when a device link step is also involved
+ (see :genex:`$<DEVICE_LINK:list>` generator expression). This expression can
+ only be used to specify link options.
-.. genex:: $<Fortran_COMPILER_VERSION>
- The version of the Fortran compiler used.
- See also the :variable:`CMAKE_<LANG>_COMPILER_VERSION` variable.
+.. _`Target-Dependent Queries`:
-.. genex:: $<HIP_COMPILER_VERSION>
+Target-Dependent Expressions
+----------------------------
- .. versionadded:: 3.21
+These queries refer to a target ``tgt``. Unless otherwise stated, this can
+be any runtime artifact, namely:
- The version of the HIP compiler used.
- See also the :variable:`CMAKE_<LANG>_COMPILER_VERSION` variable.
+* An executable target created by :command:`add_executable`.
+* A shared library target (``.so``, ``.dll`` but not their ``.lib`` import
+ library) created by :command:`add_library`.
+* A static library target created by :command:`add_library`.
-.. genex:: $<ISPC_COMPILER_VERSION>
+In the following, the phrase "the ``tgt`` filename" means the name of the
+``tgt`` binary file. This has to be distinguished from the phrase
+"the target name", which is just the string ``tgt``.
- .. versionadded:: 3.19
+.. genex:: $<TARGET_EXISTS:tgt>
- The version of the ISPC compiler used.
- See also the :variable:`CMAKE_<LANG>_COMPILER_VERSION` variable.
+ .. versionadded:: 3.12
-.. genex:: $<COMPILE_LANGUAGE>
+ ``1`` if ``tgt`` exists as a CMake target, else ``0``.
- .. versionadded:: 3.3
+.. genex:: $<TARGET_NAME_IF_EXISTS:tgt>
- The compile language of source files when evaluating compile options.
- See :ref:`the related boolean expression
- <Boolean COMPILE_LANGUAGE Generator Expression>`
- ``$<COMPILE_LANGUAGE:language>``
- for notes about the portability of this generator expression.
+ .. versionadded:: 3.12
-.. genex:: $<LINK_LANGUAGE>
+ The target name ``tgt`` if the target exists, an empty string otherwise.
- .. versionadded:: 3.18
+ Note that ``tgt`` is not added as a dependency of the target this
+ expression is evaluated on.
- The link language of target when evaluating link options.
- See :ref:`the related boolean expression
- <Boolean LINK_LANGUAGE Generator Expression>` ``$<LINK_LANGUAGE:language>``
- for notes about the portability of this generator expression.
+.. genex:: $<TARGET_NAME:...>
- .. note::
+ Marks ``...`` as being the name of a target. This is required if exporting
+ targets to multiple dependent export sets. The ``...`` must be a literal
+ name of a target, it may not contain generator expressions.
- This generator expression is not supported by the link libraries
- properties to avoid side-effects due to the double evaluation of
- these properties.
+.. genex:: $<TARGET_PROPERTY:tgt,prop>
-.. _`Target-Dependent Queries`:
+ Value of the property ``prop`` on the target ``tgt``.
-Target-Dependent Queries
-------------------------
+ Note that ``tgt`` is not added as a dependency of the target this
+ expression is evaluated on.
-These queries refer to a target ``tgt``. This can be any runtime artifact,
-namely:
+.. genex:: $<TARGET_PROPERTY:prop>
-* an executable target created by :command:`add_executable`
-* a shared library target (``.so``, ``.dll`` but not their ``.lib`` import library)
- created by :command:`add_library`
-* a static library target created by :command:`add_library`
+ Value of the property ``prop`` on the target for which the expression
+ is being evaluated. Note that for generator expressions in
+ :ref:`Target Usage Requirements` this is the consuming target rather
+ than the target specifying the requirement.
-In the following, "the ``tgt`` filename" means the name of the ``tgt``
-binary file. This has to be distinguished from "the target name",
-which is just the string ``tgt``.
+.. genex:: $<TARGET_OBJECTS:tgt>
-.. genex:: $<TARGET_NAME_IF_EXISTS:tgt>
+ .. versionadded:: 3.1
- .. versionadded:: 3.12
+ List of objects resulting from building ``tgt``. This would typically be
+ used on :ref:`object library <Object Libraries>` targets.
- The target name ``tgt`` if the target exists, an empty string otherwise.
+.. genex:: $<TARGET_POLICY:policy>
- Note that ``tgt`` is not added as a dependency of the target this
- expression is evaluated on.
+ ``1`` if the ``policy`` was ``NEW`` when the 'head' target was created,
+ else ``0``. If the ``policy`` was not set, the warning message for the policy
+ will be emitted. This generator expression only works for a subset of
+ policies.
.. genex:: $<TARGET_FILE:tgt>
@@ -1273,20 +1647,6 @@ which is just the string ``tgt``.
Note that ``tgt`` is not added as a dependency of the target this
expression is evaluated on (see policy :policy:`CMP0112`).
-.. genex:: $<TARGET_PROPERTY:tgt,prop>
-
- Value of the property ``prop`` on the target ``tgt``.
-
- Note that ``tgt`` is not added as a dependency of the target this
- expression is evaluated on.
-
-.. genex:: $<TARGET_PROPERTY:prop>
-
- Value of the property ``prop`` on the target for which the expression
- is being evaluated. Note that for generator expressions in
- :ref:`Target Usage Requirements` this is the consuming target rather
- than the target specifying the requirement.
-
.. genex:: $<TARGET_RUNTIME_DLLS:tgt>
.. versionadded:: 3.21
@@ -1294,8 +1654,8 @@ which is just the string ``tgt``.
List of DLLs that the target depends on at runtime. This is determined by
the locations of all the ``SHARED`` targets in the target's transitive
dependencies. Using this generator expression on targets other than
- executables, ``SHARED`` libraries, and ``MODULE`` libraries is an error. On
- non-DLL platforms, it evaluates to an empty string.
+ executables, ``SHARED`` libraries, and ``MODULE`` libraries is an error.
+ **On non-DLL platforms, this expression always evaluates to an empty string**.
This generator expression can be used to copy all of the DLLs that a target
depends on into its output directory in a ``POST_BUILD`` custom command. For
@@ -1310,7 +1670,7 @@ which is just the string ``tgt``.
add_custom_command(TARGET exe POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy $<TARGET_RUNTIME_DLLS:exe> $<TARGET_FILE_DIR:exe>
COMMAND_EXPAND_LISTS
- )
+ )
.. note::
@@ -1321,368 +1681,100 @@ which is just the string ``tgt``.
section for details. Many :ref:`Find Modules` produce imported targets
with the ``UNKNOWN`` type and therefore will be ignored.
-.. genex:: $<INSTALL_PREFIX>
-
- Content of the install prefix when the target is exported via
- :command:`install(EXPORT)`, or when evaluated in the
- :prop_tgt:`INSTALL_NAME_DIR` property or the ``INSTALL_NAME_DIR`` argument of
- :command:`install(RUNTIME_DEPENDENCY_SET)`, and empty otherwise.
-
-Output-Related Expressions
---------------------------
-
-.. genex:: $<TARGET_NAME:...>
-
- Marks ``...`` as being the name of a target. This is required if exporting
- targets to multiple dependent export sets. The ``...`` must be a literal
- name of a target- it may not contain generator expressions.
-
-.. genex:: $<LINK_ONLY:...>
-
- .. versionadded:: 3.1
-
- Content of ``...``, except while collecting :ref:`Target Usage Requirements`,
- in which case it is the empty string. This is intended for use in an
- :prop_tgt:`INTERFACE_LINK_LIBRARIES` target property, typically populated
- via the :command:`target_link_libraries` command, to specify private link
- dependencies without other usage requirements.
-
- .. versionadded:: 3.24
- ``LINK_ONLY`` may also be used in a :prop_tgt:`LINK_LIBRARIES` target
- property. See policy :policy:`CMP0131`.
-
-.. genex:: $<DEVICE_LINK:list>
-
- .. versionadded:: 3.18
-
- Returns the list if it is the device link step, an empty list otherwise.
- The device link step is controlled by :prop_tgt:`CUDA_SEPARABLE_COMPILATION`
- and :prop_tgt:`CUDA_RESOLVE_DEVICE_SYMBOLS` properties and
- policy :policy:`CMP0105`. This expression can only be used to specify link
- options.
-
-.. genex:: $<HOST_LINK:list>
-
- .. versionadded:: 3.18
-
- Returns the list if it is the normal link step, an empty list otherwise.
- This expression is mainly useful when a device link step is also involved
- (see :genex:`$<DEVICE_LINK:list>` generator expression). This expression can
- only be used to specify link options.
-
-.. genex:: $<LINK_LIBRARY:feature,library-list>
-
- .. versionadded:: 3.24
-
- Specify a set of libraries to link to a target, along with a ``feature``
- which provides details about *how* they should be linked. For example:
-
- .. code-block:: cmake
-
- add_library(lib1 STATIC ...)
- add_library(lib2 ...)
- target_link_libraries(lib2 PRIVATE "$<LINK_LIBRARY:WHOLE_ARCHIVE,lib1>")
-
- This specifies that ``lib2`` should link to ``lib1`` and use the
- ``WHOLE_ARCHIVE`` feature when doing so.
- Feature names are case-sensitive and may only contain letters, numbers and
- underscores. Feature names defined in all uppercase are reserved for CMake's
- own built-in features. The pre-defined built-in library features are:
-
- .. include:: ../variable/LINK_LIBRARY_PREDEFINED_FEATURES.txt
-
- Built-in and custom library features are defined in terms of the following
- variables:
-
- * :variable:`CMAKE_<LANG>_LINK_LIBRARY_USING_<FEATURE>_SUPPORTED`
- * :variable:`CMAKE_<LANG>_LINK_LIBRARY_USING_<FEATURE>`
- * :variable:`CMAKE_LINK_LIBRARY_USING_<FEATURE>_SUPPORTED`
- * :variable:`CMAKE_LINK_LIBRARY_USING_<FEATURE>`
-
- The value used for each of these variables is the value as set at the end of
- the directory scope in which the target was created. The usage is as follows:
-
- 1. If the language-specific
- :variable:`CMAKE_<LANG>_LINK_LIBRARY_USING_<FEATURE>_SUPPORTED` variable
- is true, the ``feature`` must be defined by the corresponding
- :variable:`CMAKE_<LANG>_LINK_LIBRARY_USING_<FEATURE>` variable.
- 2. If no language-specific ``feature`` is supported, then the
- :variable:`CMAKE_LINK_LIBRARY_USING_<FEATURE>_SUPPORTED` variable must be
- true and the ``feature`` must be defined by the corresponding
- :variable:`CMAKE_LINK_LIBRARY_USING_<FEATURE>` variable.
+Export And Install Expressions
+------------------------------
- The following limitations should be noted:
-
- * The ``library-list`` can specify CMake targets or libraries.
- Any CMake target of type :ref:`OBJECT <Object Libraries>`
- or :ref:`INTERFACE <Interface Libraries>` will ignore the feature aspect
- of the expression and instead be linked in the standard way.
-
- * The ``$<LINK_LIBRARY:...>`` generator expression can only be used to
- specify link libraries. In practice, this means it can appear in the
- :prop_tgt:`LINK_LIBRARIES`, :prop_tgt:`INTERFACE_LINK_LIBRARIES`, and
- :prop_tgt:`INTERFACE_LINK_LIBRARIES_DIRECT` target properties, and be
- specified in :command:`target_link_libraries` and :command:`link_libraries`
- commands.
-
- * If a ``$<LINK_LIBRARY:...>`` generator expression appears in the
- :prop_tgt:`INTERFACE_LINK_LIBRARIES` property of a target, it will be
- included in the imported target generated by a :command:`install(EXPORT)`
- command. It is the responsibility of the environment consuming this
- import to define the link feature used by this expression.
-
- * Each target or library involved in the link step must have at most only
- one kind of library feature. The absence of a feature is also incompatible
- with all other features. For example:
-
- .. code-block:: cmake
-
- add_library(lib1 ...)
- add_library(lib2 ...)
- add_library(lib3 ...)
-
- # lib1 will be associated with feature1
- target_link_libraries(lib2 PUBLIC "$<LINK_LIBRARY:feature1,lib1>")
-
- # lib1 is being linked with no feature here. This conflicts with the
- # use of feature1 in the line above and would result in an error.
- target_link_libraries(lib3 PRIVATE lib1 lib2)
-
- Where it isn't possible to use the same feature throughout a build for a
- given target or library, the :prop_tgt:`LINK_LIBRARY_OVERRIDE` and
- :prop_tgt:`LINK_LIBRARY_OVERRIDE_<LIBRARY>` target properties can be
- used to resolve such incompatibilities.
-
- * The ``$<LINK_LIBRARY:...>`` generator expression does not guarantee
- that the list of specified targets and libraries will be kept grouped
- together. To manage constructs like ``--start-group`` and ``--end-group``,
- as supported by the GNU ``ld`` linker, use the :genex:`LINK_GROUP`
- generator expression instead.
-
-.. genex:: $<LINK_GROUP:feature,library-list>
-
- .. versionadded:: 3.24
-
- Specify a group of libraries to link to a target, along with a ``feature``
- which defines how that group should be linked. For example:
-
- .. code-block:: cmake
-
- add_library(lib1 STATIC ...)
- add_library(lib2 ...)
- target_link_libraries(lib2 PRIVATE "$<LINK_GROUP:RESCAN,lib1,external>")
+.. genex:: $<INSTALL_INTERFACE:...>
- This specifies that ``lib2`` should link to ``lib1`` and ``external``, and
- that both of those two libraries should be included on the linker command
- line according to the definition of the ``RESCAN`` feature.
+ Content of ``...`` when the property is exported using
+ :command:`install(EXPORT)`, and empty otherwise.
- Feature names are case-sensitive and may only contain letters, numbers and
- underscores. Feature names defined in all uppercase are reserved for CMake's
- own built-in features. Currently, there is only one pre-defined built-in
- group feature:
+.. genex:: $<BUILD_INTERFACE:...>
- .. include:: ../variable/LINK_GROUP_PREDEFINED_FEATURES.txt
+ Content of ``...`` when the property is exported using :command:`export`, or
+ when the target is used by another target in the same buildsystem. Expands to
+ the empty string otherwise.
- Built-in and custom group features are defined in terms of the following
- variables:
+.. genex:: $<INSTALL_PREFIX>
- * :variable:`CMAKE_<LANG>_LINK_GROUP_USING_<FEATURE>_SUPPORTED`
- * :variable:`CMAKE_<LANG>_LINK_GROUP_USING_<FEATURE>`
- * :variable:`CMAKE_LINK_GROUP_USING_<FEATURE>_SUPPORTED`
- * :variable:`CMAKE_LINK_GROUP_USING_<FEATURE>`
+ Content of the install prefix when the target is exported via
+ :command:`install(EXPORT)`, or when evaluated in the
+ :prop_tgt:`INSTALL_NAME_DIR` property or the ``INSTALL_NAME_DIR`` argument of
+ :command:`install(RUNTIME_DEPENDENCY_SET)`, and empty otherwise.
- The value used for each of these variables is the value as set at the end of
- the directory scope in which the target was created. The usage is as follows:
+Multi-level Expression Evaluation
+---------------------------------
- 1. If the language-specific
- :variable:`CMAKE_<LANG>_LINK_GROUP_USING_<FEATURE>_SUPPORTED` variable
- is true, the ``feature`` must be defined by the corresponding
- :variable:`CMAKE_<LANG>_LINK_GROUP_USING_<FEATURE>` variable.
- 2. If no language-specific ``feature`` is supported, then the
- :variable:`CMAKE_LINK_GROUP_USING_<FEATURE>_SUPPORTED` variable must be
- true and the ``feature`` must be defined by the corresponding
- :variable:`CMAKE_LINK_GROUP_USING_<FEATURE>` variable.
-
- The ``LINK_GROUP`` generator expression is compatible with the
- :genex:`LINK_LIBRARY` generator expression. The libraries involved in a
- group can be specified using the :genex:`LINK_LIBRARY` generator expression.
+.. genex:: $<GENEX_EVAL:expr>
- Each target or external library involved in the link step is allowed to be
- part of multiple groups, but only if all the groups involved specify the
- same ``feature``. Such groups will not be merged on the linker command line,
- the individual groups will still be preserved. Mixing different group
- features for the same target or library is forbidden.
+ .. versionadded:: 3.12
- .. code-block:: cmake
+ Content of ``expr`` evaluated as a generator expression in the current
+ context. This enables consumption of generator expressions whose
+ evaluation results itself in generator expressions.
- add_library(lib1 ...)
- add_library(lib2 ...)
- add_library(lib3 ...)
- add_library(lib4 ...)
- add_library(lib5 ...)
+.. genex:: $<TARGET_GENEX_EVAL:tgt,expr>
- target_link_libraries(lib3 PUBLIC "$<LINK_GROUP:feature1,lib1,lib2>")
- target_link_libraries(lib4 PRIVATE "$<LINK_GROUP:feature1,lib1,lib3>")
- # lib4 will be linked with the groups {lib1,lib2} and {lib1,lib3}.
- # Both groups specify the same feature, so this is fine.
+ .. versionadded:: 3.12
- target_link_libraries(lib5 PRIVATE "$<LINK_GROUP:feature2,lib1,lib3>")
- # An error will be raised here because both lib1 and lib3 are part of two
- # groups with different features.
+ Content of ``expr`` evaluated as a generator expression in the context of
+ ``tgt`` target. This enables consumption of custom target properties that
+ themselves contain generator expressions.
- When a target or an external library is involved in the link step as part of
- a group and also as not part of any group, any occurrence of the non-group
- link item will be replaced by the groups it belongs to.
+ Having the capability to evaluate generator expressions is very useful when
+ you want to manage custom properties supporting generator expressions.
+ For example:
.. code-block:: cmake
- add_library(lib1 ...)
- add_library(lib2 ...)
- add_library(lib3 ...)
- add_library(lib4 ...)
-
- target_link_libraries(lib3 PUBLIC lib1)
-
- target_link_libraries(lib4 PRIVATE lib3 "$<LINK_GROUP:feature1,lib1,lib2>")
- # lib4 will only be linked with lib3 and the group {lib1,lib2}
+ add_library(foo ...)
- Because ``lib1`` is part of the group defined for ``lib4``, that group then
- gets applied back to the use of ``lib1`` for ``lib3``. The end result will
- be as though the linking relationship for ``lib3`` had been specified as:
+ set_property(TARGET foo PROPERTY
+ CUSTOM_KEYS $<$<CONFIG:DEBUG>:FOO_EXTRA_THINGS>
+ )
- .. code-block:: cmake
+ add_custom_target(printFooKeys
+ COMMAND ${CMAKE_COMMAND} -E echo $<TARGET_PROPERTY:foo,CUSTOM_KEYS>
+ )
- target_link_libraries(lib3 PUBLIC "$<LINK_GROUP:feature1,lib1,lib2>")
+ This naive implementation of the ``printFooKeys`` custom command is wrong
+ because ``CUSTOM_KEYS`` target property is not evaluated and the content
+ is passed as is (i.e. ``$<$<CONFIG:DEBUG>:FOO_EXTRA_THINGS>``).
- Be aware that the precedence of the group over the non-group link item can
- result in circular dependencies between groups. If this occurs, a fatal
- error is raised because circular dependencies are not allowed for groups.
+ To have the expected result (i.e. ``FOO_EXTRA_THINGS`` if config is
+ ``Debug``), it is required to evaluate the output of
+ ``$<TARGET_PROPERTY:foo,CUSTOM_KEYS>``:
.. code-block:: cmake
- add_library(lib1A ...)
- add_library(lib1B ...)
- add_library(lib2A ...)
- add_library(lib2B ...)
- add_library(lib3 ...)
-
- # Non-group linking relationships, these are non-circular so far
- target_link_libraries(lib1A PUBLIC lib2A)
- target_link_libraries(lib2B PUBLIC lib1B)
-
- # The addition of these groups creates circular dependencies
- target_link_libraries(lib3 PRIVATE
- "$<LINK_GROUP:feat,lib1A,lib1B>"
- "$<LINK_GROUP:feat,lib2A,lib2B>"
+ add_custom_target(printFooKeys
+ COMMAND ${CMAKE_COMMAND} -E
+ echo $<TARGET_GENEX_EVAL:foo,$<TARGET_PROPERTY:foo,CUSTOM_KEYS>>
)
- Because of the groups defined for ``lib3``, the linking relationships for
- ``lib1A`` and ``lib2B`` effectively get expanded to the equivalent of:
-
- .. code-block:: cmake
-
- target_link_libraries(lib1A PUBLIC "$<LINK_GROUP:feat,lib2A,lib2B>")
- target_link_libraries(lib2B PUBLIC "$<LINK_GROUP:feat,lib1A,lib1B>")
-
- This creates a circular dependency between groups:
- ``lib1A --> lib2B --> lib1A``.
-
- The following limitations should also be noted:
-
- * The ``library-list`` can specify CMake targets or libraries.
- Any CMake target of type :ref:`OBJECT <Object Libraries>`
- or :ref:`INTERFACE <Interface Libraries>` will ignore the feature aspect
- of the expression and instead be linked in the standard way.
-
- * The ``$<LINK_GROUP:...>`` generator expression can only be used to
- specify link libraries. In practice, this means it can appear in the
- :prop_tgt:`LINK_LIBRARIES`, :prop_tgt:`INTERFACE_LINK_LIBRARIES`,and
- :prop_tgt:`INTERFACE_LINK_LIBRARIES_DIRECT` target properties, and be
- specified in :command:`target_link_libraries` and :command:`link_libraries`
- commands.
-
- * If a ``$<LINK_GROUP:...>`` generator expression appears in the
- :prop_tgt:`INTERFACE_LINK_LIBRARIES` property of a target, it will be
- included in the imported target generated by a :command:`install(EXPORT)`
- command. It is the responsibility of the environment consuming this
- import to define the link feature used by this expression.
-
-.. genex:: $<INSTALL_INTERFACE:...>
-
- Content of ``...`` when the property is exported using :command:`install(EXPORT)`,
- and empty otherwise.
-
-.. genex:: $<BUILD_INTERFACE:...>
-
- Content of ``...`` when the property is exported using :command:`export`, or
- when the target is used by another target in the same buildsystem. Expands to
- the empty string otherwise.
-
-.. genex:: $<MAKE_C_IDENTIFIER:...>
-
- Content of ``...`` converted to a C identifier. The conversion follows the
- same behavior as :command:`string(MAKE_C_IDENTIFIER)`.
-
-.. genex:: $<TARGET_OBJECTS:objLib>
-
- .. versionadded:: 3.1
-
- List of objects resulting from build of ``objLib``.
-
-.. genex:: $<SHELL_PATH:...>
-
- .. versionadded:: 3.4
-
- Content of ``...`` converted to shell path style. For example, slashes are
- converted to backslashes in Windows shells and drive letters are converted
- to posix paths in MSYS shells. The ``...`` must be an absolute path.
-
- .. versionadded:: 3.14
- The ``...`` may be a :ref:`semicolon-separated list <CMake Language Lists>`
- of paths, in which case each path is converted individually and a result
- list is generated using the shell path separator (``:`` on POSIX and
- ``;`` on Windows). Be sure to enclose the argument containing this genex
- in double quotes in CMake source code so that ``;`` does not split arguments.
-
-.. genex:: $<OUTPUT_CONFIG:...>
-
- .. versionadded:: 3.20
-
- Only valid in :command:`add_custom_command` and :command:`add_custom_target`
- as the outer-most generator expression in an argument.
- With the :generator:`Ninja Multi-Config` generator, generator expressions
- in ``...`` are evaluated using the custom command's "output config".
- With other generators, the content of ``...`` is evaluated normally.
-
-.. genex:: $<COMMAND_CONFIG:...>
-
- .. versionadded:: 3.20
+Escaped Characters
+------------------
- Only valid in :command:`add_custom_command` and :command:`add_custom_target`
- as the outer-most generator expression in an argument.
- With the :generator:`Ninja Multi-Config` generator, generator expressions
- in ``...`` are evaluated using the custom command's "command config".
- With other generators, the content of ``...`` is evaluated normally.
+These expressions evaluate to specific string literals. Use them in place of
+the actual string literal where you need to prevent them from having their
+special meaning.
-Debugging
-=========
+.. genex:: $<ANGLE-R>
-Since generator expressions are evaluated during generation of the buildsystem,
-and not during processing of ``CMakeLists.txt`` files, it is not possible to
-inspect their result with the :command:`message()` command.
+ A literal ``>``. Used for example to compare strings that contain a ``>``.
-One possible way to generate debug messages is to add a custom target,
+.. genex:: $<COMMA>
-.. code-block:: cmake
+ A literal ``,``. Used for example to compare strings which contain a ``,``.
- add_custom_target(genexdebug COMMAND ${CMAKE_COMMAND} -E echo "$<...>")
+.. genex:: $<SEMICOLON>
-The shell command ``make genexdebug`` (invoked after execution of ``cmake``)
-would then print the result of ``$<...>``.
+ A literal ``;``. Used to prevent list expansion on an argument with ``;``.
-Another way is to write debug messages to a file:
+Deprecated Expressions
+----------------------
-.. code-block:: cmake
+.. genex:: $<CONFIGURATION>
- file(GENERATE OUTPUT filename CONTENT "$<...>")
+ Configuration name. Deprecated since CMake 3.0. Use :genex:`CONFIG` instead.
diff --git a/Help/prop_tgt/LINK_LIBRARIES_ONLY_TARGETS.rst b/Help/prop_tgt/LINK_LIBRARIES_ONLY_TARGETS.rst
index a9af74d..0749c6f 100644
--- a/Help/prop_tgt/LINK_LIBRARIES_ONLY_TARGETS.rst
+++ b/Help/prop_tgt/LINK_LIBRARIES_ONLY_TARGETS.rst
@@ -8,6 +8,8 @@ Enforce that link items that can be target names are actually existing targets.
Set this property to a true value to enable additional checks on the contents
of the :prop_tgt:`LINK_LIBRARIES` and :prop_tgt:`INTERFACE_LINK_LIBRARIES`
target properties, typically populated by :command:`target_link_libraries`.
+Checks are also applied to libraries added to a target through the
+:prop_tgt:`INTERFACE_LINK_LIBRARIES_DIRECT` properties of its dependencies.
CMake will verify that link items that might be target names actually name
existing targets. An item is considered a possible target name if:
diff --git a/Help/release/dev/finddoxygen-better-version-checking.rst b/Help/release/dev/finddoxygen-better-version-checking.rst
new file mode 100644
index 0000000..3c2215d
--- /dev/null
+++ b/Help/release/dev/finddoxygen-better-version-checking.rst
@@ -0,0 +1,11 @@
+finddoxygen-better-version-checking
+-----------------------------------
+
+* The :module:`FindDoxygen` module now evaluates as many candidate
+ Doxygen installs as are necessary to satisfy version constraints,
+ with the package considered to be not found if none are available.
+
+* The :module:`FindDoxygen` module now handles version ranges.
+
+* The :module:`FindDoxygen` module now ignores non-semantic portions
+ of the output from Doxygen's `--version` option.
diff --git a/Modules/FindDoxygen.cmake b/Modules/FindDoxygen.cmake
index 4a16e31..23b7107 100644
--- a/Modules/FindDoxygen.cmake
+++ b/Modules/FindDoxygen.cmake
@@ -432,9 +432,44 @@ endif()
# or use something like homebrew.
# ============== End OSX stuff ================
+include(${CMAKE_CURRENT_LIST_DIR}/FindPackageHandleStandardArgs.cmake)
+
#
# Find Doxygen...
#
+function(_Doxygen_get_version doxy_version result_var doxy_path)
+ execute_process(
+ COMMAND "${doxy_path}" --version
+ OUTPUT_VARIABLE full_doxygen_version
+ OUTPUT_STRIP_TRAILING_WHITESPACE
+ RESULT_VARIABLE version_result
+ )
+
+ # Ignore any commit hashes, etc.
+ string(REGEX MATCH [[^[0-9]+\.[0-9]+\.[0-9]+]] sem_doxygen_version "${full_doxygen_version}")
+
+ set(${result_var} ${version_result} PARENT_SCOPE)
+ set(${doxy_version} ${sem_doxygen_version} PARENT_SCOPE)
+endfunction()
+
+function(_Doxygen_version_validator version_match doxy_path)
+ if(NOT DEFINED Doxygen_FIND_VERSION)
+ set(${is_valid_version} TRUE PARENT_SCOPE)
+ else()
+ _Doxygen_get_version(candidate_version version_result "${doxy_path}")
+
+ if(version_result)
+ message(DEBUG "Unable to determine candidate doxygen version at ${doxy_path}: ${version_result}")
+ endif()
+
+ find_package_check_version("${candidate_version}" valid_doxy_version
+ HANDLE_VERSION_RANGE
+ )
+
+ set(${version_match} "${valid_doxy_version}" PARENT_SCOPE)
+ endif()
+endfunction()
+
macro(_Doxygen_find_doxygen)
find_program(
DOXYGEN_EXECUTABLE
@@ -446,16 +481,13 @@ macro(_Doxygen_find_doxygen)
/Applications/Utilities/Doxygen.app/Contents/Resources
/Applications/Utilities/Doxygen.app/Contents/MacOS
DOC "Doxygen documentation generation tool (http://www.doxygen.org)"
+ VALIDATOR _Doxygen_version_validator
)
mark_as_advanced(DOXYGEN_EXECUTABLE)
if(DOXYGEN_EXECUTABLE)
- execute_process(
- COMMAND "${DOXYGEN_EXECUTABLE}" --version
- OUTPUT_VARIABLE DOXYGEN_VERSION
- OUTPUT_STRIP_TRAILING_WHITESPACE
- RESULT_VARIABLE _Doxygen_version_result
- )
+ _Doxygen_get_version(DOXYGEN_VERSION _Doxygen_version_result "${DOXYGEN_EXECUTABLE}")
+
if(_Doxygen_version_result)
message(WARNING "Unable to determine doxygen version: ${_Doxygen_version_result}")
endif()
@@ -642,11 +674,11 @@ endforeach()
unset(_comp)
# Verify find results
-include(${CMAKE_CURRENT_LIST_DIR}/FindPackageHandleStandardArgs.cmake)
find_package_handle_standard_args(
Doxygen
REQUIRED_VARS DOXYGEN_EXECUTABLE
VERSION_VAR DOXYGEN_VERSION
+ HANDLE_VERSION_RANGE
HANDLE_COMPONENTS
)
diff --git a/Modules/FindPython/Support.cmake b/Modules/FindPython/Support.cmake
index 53519ba..7a127e4 100644
--- a/Modules/FindPython/Support.cmake
+++ b/Modules/FindPython/Support.cmake
@@ -2871,7 +2871,15 @@ if (("Development.Module" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS
if ("INCLUDE_DIR" IN_LIST _${_PYTHON_PREFIX}_FIND_DEVELOPMENT_ARTIFACTS)
while (NOT _${_PYTHON_PREFIX}_INCLUDE_DIR)
- if ("LIBRARY" IN_LIST _${_PYTHON_PREFIX}_FIND_DEVELOPMENT_ARTIFACTS
+ set (_${_PYTHON_PREFIX}_LIBRARY_REQUIRED TRUE)
+ foreach (_${_PYTHON_PREFIX}_COMPONENT IN ITEMS Module Embed)
+ string (TOUPPER "${_${_PYTHON_PREFIX}_COMPONENT}" _${_PYTHON_PREFIX}_ID)
+ if ("Development.${_${_PYTHON_PREFIX}_COMPONENT}" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS
+ AND NOT "LIBRARY" IN_LIST _${_PYTHON_PREFIX}_FIND_DEVELOPMENT_${_${_PYTHON_PREFIX}_ID}_ARTIFACTS)
+ set (_${_PYTHON_PREFIX}_LIBRARY_REQUIRED FALSE)
+ endif()
+ endforeach()
+ if (_${_PYTHON_PREFIX}_LIBRARY_REQUIRED
AND NOT _${_PYTHON_PREFIX}_LIBRARY_RELEASE)
# Don't search for include dir if no library was founded
break()
diff --git a/Modules/Platform/AIX-GNU.cmake b/Modules/Platform/AIX-GNU.cmake
index 5a532c7..a9aa8e0 100644
--- a/Modules/Platform/AIX-GNU.cmake
+++ b/Modules/Platform/AIX-GNU.cmake
@@ -23,11 +23,11 @@ macro(__aix_compiler_gnu lang)
# Construct the export list ourselves to pass only the object files so
# that we export only the symbols actually provided by the sources.
set(CMAKE_${lang}_CREATE_SHARED_LIBRARY
- "\"${CMAKE_ROOT}/Modules/Platform/AIX/ExportImportList\" -o <OBJECT_DIR>/exports.exp <AIX_EXPORTS> <OBJECTS>"
+ "\"${CMAKE_ROOT}/Modules/Platform/AIX/ExportImportList\" -o <OBJECT_DIR>/exports.exp -c <CMAKE_${lang}_COMPILER> <AIX_EXPORTS> <OBJECTS>"
"<CMAKE_${lang}_COMPILER> <CMAKE_SHARED_LIBRARY_${lang}_FLAGS> -Wl,-bE:<OBJECT_DIR>/exports.exp <LANGUAGE_COMPILE_FLAGS> <LINK_FLAGS> <CMAKE_SHARED_LIBRARY_CREATE_${lang}_FLAGS> <SONAME_FLAG><TARGET_SONAME> -o <TARGET> <OBJECTS> <LINK_LIBRARIES>"
)
set(CMAKE_${lang}_LINK_EXECUTABLE_WITH_EXPORTS
- "\"${CMAKE_ROOT}/Modules/Platform/AIX/ExportImportList\" -o <TARGET_IMPLIB> -l . <AIX_EXPORTS> <OBJECTS>"
+ "\"${CMAKE_ROOT}/Modules/Platform/AIX/ExportImportList\" -o <TARGET_IMPLIB> -c <CMAKE_${lang}_COMPILER> -l . <AIX_EXPORTS> <OBJECTS>"
"<CMAKE_${lang}_COMPILER> <FLAGS> <CMAKE_${lang}_LINK_FLAGS> -Wl,-bE:<TARGET_IMPLIB> <LINK_FLAGS> <OBJECTS> -o <TARGET> <LINK_LIBRARIES>")
endmacro()
diff --git a/Modules/Platform/AIX-XL.cmake b/Modules/Platform/AIX-XL.cmake
index 2a8c159..902cbb3 100644
--- a/Modules/Platform/AIX-XL.cmake
+++ b/Modules/Platform/AIX-XL.cmake
@@ -29,12 +29,12 @@ macro(__aix_compiler_xl lang)
# Construct the export list ourselves to pass only the object files so
# that we export only the symbols actually provided by the sources.
set(CMAKE_${lang}_CREATE_SHARED_LIBRARY
- "\"${CMAKE_ROOT}/Modules/Platform/AIX/ExportImportList\" -o <OBJECT_DIR>/exports.exp <AIX_EXPORTS>${_OBJECTS}"
+ "\"${CMAKE_ROOT}/Modules/Platform/AIX/ExportImportList\" -o <OBJECT_DIR>/exports.exp -c <CMAKE_${lang}_COMPILER> <AIX_EXPORTS>${_OBJECTS}"
"<CMAKE_${lang}_COMPILER> <CMAKE_SHARED_LIBRARY_${lang}_FLAGS> -Wl,-bE:<OBJECT_DIR>/exports.exp <LANGUAGE_COMPILE_FLAGS> <LINK_FLAGS> <CMAKE_SHARED_LIBRARY_CREATE_${lang}_FLAGS> <SONAME_FLAG><TARGET_SONAME> -o <TARGET> <OBJECTS> <LINK_LIBRARIES>"
)
set(CMAKE_${lang}_LINK_EXECUTABLE_WITH_EXPORTS
- "\"${CMAKE_ROOT}/Modules/Platform/AIX/ExportImportList\" -o <TARGET_IMPLIB> -l . <AIX_EXPORTS> <OBJECTS>"
+ "\"${CMAKE_ROOT}/Modules/Platform/AIX/ExportImportList\" -o <TARGET_IMPLIB> -c <CMAKE_${lang}_COMPILER> -l . <AIX_EXPORTS> <OBJECTS>"
"<CMAKE_${lang}_COMPILER> <FLAGS> <CMAKE_${lang}_LINK_FLAGS> -Wl,-bE:<TARGET_IMPLIB> <LINK_FLAGS> <OBJECTS> -o <TARGET> <LINK_LIBRARIES>")
unset(_OBJECTS)
diff --git a/Modules/Platform/AIX/ExportImportList b/Modules/Platform/AIX/ExportImportList
index 891bce7..5e16fcb 100755
--- a/Modules/Platform/AIX/ExportImportList
+++ b/Modules/Platform/AIX/ExportImportList
@@ -5,7 +5,7 @@
# This script is internal to CMake and meant only to be
# invoked by CMake-generated build systems on AIX.
-usage='usage: ExportImportList -o <out-file> [-l <lib>] [-n] [--] <objects>...'
+usage='usage: ExportImportList -o <out-file> -c <compiler> [-l <lib>] [-n] [--] <objects>...'
die() {
echo "$@" 1>&2; exit 1
@@ -15,11 +15,13 @@ die() {
out=''
lib=''
no_objects=''
+compiler=''
while test "$#" != 0; do
case "$1" in
-l) shift; lib="$1" ;;
-o) shift; out="$1" ;;
-n) no_objects='1' ;;
+ -c) shift; compiler="$1" ;;
--) shift; break ;;
-*) die "$usage" ;;
*) break ;;
@@ -27,27 +29,47 @@ while test "$#" != 0; do
shift
done
test -n "$out" || die "$usage"
+# We need the compiler executable to resolve where the ibm-llvm-nm executable is
+test -n "$compiler" || die "$usage"
# Build a temporary file that atomically replaces the output later.
out_tmp="$out.tmp$$"
trap 'rm -f "$out_tmp"' EXIT INT TERM
> "$out_tmp"
+# If IPA was enabled and a compiler from the IBMClang family is used, then
+# the object files contain LLVM bitcode[0] rather than XCOFF objects and so
+# need to be handled differently.
+#
+# [0]: https://www.ibm.com/docs/en/openxl-c-and-cpp-aix/17.1.0?topic=compatibility-link-time-optimization-lto
+NM="$(dirname "$compiler")/../libexec/ibm-llvm-nm"
+
+function IsBitcode {
+ # N4 = first 4 bytes, -tx = output in hexadecimal, -An = don't display offset
+ # cut: trim off the preceding whitespace where the offset would be
+ # 4243code is the hexadecimal magic number for LLVM bitcode
+ [ "$(od -N4 -tx -An $1 | cut -d ' ' -f 2)" == "4243c0de" ];
+}
+
# Collect symbols exported from all object files.
if test -z "$no_objects"; then
for f in "$@"; do
- dump -tov -X 32_64 "$f" |
- awk '
- BEGIN {
- V["EXPORTED"]=" export"
- V["PROTECTED"]=" protected"
- }
- /^\[[0-9]+\]\tm +[^ ]+ +\.(text|data|bss) +[^ ]+ +(extern|weak) +(EXPORTED|PROTECTED| ) / {
- if (!match($NF,/^(\.|__sinit|__sterm|__[0-9]+__)/)) {
- print $NF V[$(NF-1)]
+ if IsBitcode "$f"; then
+ "$NM" "$f" --defined-only --extern-only --just-symbol-name 2>/dev/null
+ else
+ dump -tov -X 32_64 "$f" |
+ awk '
+ BEGIN {
+ V["EXPORTED"]=" export"
+ V["PROTECTED"]=" protected"
+ }
+ /^\[[0-9]+\]\tm +[^ ]+ +\.(text|data|bss) +[^ ]+ +(extern|weak) +(EXPORTED|PROTECTED| ) / {
+ if (!match($NF,/^(\.|__sinit|__sterm|__[0-9]+__)/)) {
+ print $NF V[$(NF-1)]
+ }
}
- }
- '
+ '
+ fi
done >> "$out_tmp"
fi
diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake
index 23ca43b..82e1f62 100644
--- a/Source/CMakeVersion.cmake
+++ b/Source/CMakeVersion.cmake
@@ -1,7 +1,7 @@
# CMake version number components.
set(CMake_VERSION_MAJOR 3)
set(CMake_VERSION_MINOR 24)
-set(CMake_VERSION_PATCH 20220708)
+set(CMake_VERSION_PATCH 20220720)
#set(CMake_VERSION_RC 0)
set(CMake_VERSION_IS_DIRTY 0)
diff --git a/Source/cmGlobalGenerator.cxx b/Source/cmGlobalGenerator.cxx
index 4cb541a..5113a46 100644
--- a/Source/cmGlobalGenerator.cxx
+++ b/Source/cmGlobalGenerator.cxx
@@ -1399,7 +1399,9 @@ void cmGlobalGenerator::CreateGenerationObjects(TargetTypes targetTypes)
this->CheckTargetProperties();
}
this->CreateGeneratorTargets(targetTypes);
- this->ComputeBuildFileGenerators();
+ if (targetTypes == TargetTypes::AllTargets) {
+ this->ComputeBuildFileGenerators();
+ }
}
void cmGlobalGenerator::CreateImportedGenerationObjects(
diff --git a/Source/cmGlobalVisualStudio10Generator.cxx b/Source/cmGlobalVisualStudio10Generator.cxx
index 155efde..dec0858 100644
--- a/Source/cmGlobalVisualStudio10Generator.cxx
+++ b/Source/cmGlobalVisualStudio10Generator.cxx
@@ -1294,6 +1294,14 @@ bool cmGlobalVisualStudio10Generator::IsInSolution(
gt->GetName() == CMAKE_CHECK_BUILD_SYSTEM_TARGET);
}
+bool cmGlobalVisualStudio10Generator::IsDepInSolution(
+ const std::string& targetName) const
+{
+ return !targetName.empty() &&
+ !(this->Version >= cmGlobalVisualStudioGenerator::VSVersion::VS16 &&
+ targetName == CMAKE_CHECK_BUILD_SYSTEM_TARGET);
+}
+
bool cmGlobalVisualStudio10Generator::Find64BitTools(cmMakefile* mf)
{
if (this->DefaultPlatformToolset == "v100") {
diff --git a/Source/cmGlobalVisualStudio10Generator.h b/Source/cmGlobalVisualStudio10Generator.h
index 2203f71..12fd7a8 100644
--- a/Source/cmGlobalVisualStudio10Generator.h
+++ b/Source/cmGlobalVisualStudio10Generator.h
@@ -120,6 +120,8 @@ public:
bool IsInSolution(const cmGeneratorTarget* gt) const override;
+ bool IsDepInSolution(const std::string& targetName) const override;
+
/** Return true if building for WindowsCE */
bool TargetsWindowsCE() const override { return this->SystemIsWindowsCE; }
diff --git a/Source/cmGlobalVisualStudio71Generator.cxx b/Source/cmGlobalVisualStudio71Generator.cxx
index ce943a2..758ce83 100644
--- a/Source/cmGlobalVisualStudio71Generator.cxx
+++ b/Source/cmGlobalVisualStudio71Generator.cxx
@@ -180,7 +180,7 @@ void cmGlobalVisualStudio71Generator::WriteExternalProject(
fout << "\tProjectSection(ProjectDependencies) = postProject\n";
for (BT<std::pair<std::string, bool>> const& it : depends) {
std::string const& dep = it.Value.first;
- if (!dep.empty()) {
+ if (this->IsDepInSolution(dep)) {
fout << "\t\t{" << this->GetGUID(dep) << "} = {" << this->GetGUID(dep)
<< "}\n";
}
diff --git a/Source/cmGlobalVisualStudioGenerator.cxx b/Source/cmGlobalVisualStudioGenerator.cxx
index cddaaa4..c6af20a 100644
--- a/Source/cmGlobalVisualStudioGenerator.cxx
+++ b/Source/cmGlobalVisualStudioGenerator.cxx
@@ -843,6 +843,12 @@ bool cmGlobalVisualStudioGenerator::IsInSolution(
return gt->IsInBuildSystem();
}
+bool cmGlobalVisualStudioGenerator::IsDepInSolution(
+ const std::string& targetName) const
+{
+ return !targetName.empty();
+}
+
bool cmGlobalVisualStudioGenerator::TargetCompare::operator()(
cmGeneratorTarget const* l, cmGeneratorTarget const* r) const
{
diff --git a/Source/cmGlobalVisualStudioGenerator.h b/Source/cmGlobalVisualStudioGenerator.h
index 4f5f100..f45b4d4 100644
--- a/Source/cmGlobalVisualStudioGenerator.h
+++ b/Source/cmGlobalVisualStudioGenerator.h
@@ -101,6 +101,9 @@ public:
// return true if target should be included in solution.
virtual bool IsInSolution(const cmGeneratorTarget* gt) const;
+ // return true if project dependency should be included in solution.
+ virtual bool IsDepInSolution(const std::string& targetName) const;
+
/** Get the top-level registry key for this VS version. */
std::string GetRegistryBase();
diff --git a/Source/cmNinjaTargetGenerator.cxx b/Source/cmNinjaTargetGenerator.cxx
index 86ae45d..a4080d8 100644
--- a/Source/cmNinjaTargetGenerator.cxx
+++ b/Source/cmNinjaTargetGenerator.cxx
@@ -1343,9 +1343,11 @@ void cmNinjaTargetGenerator::WriteObjectBuildStatement(
}
}
- this->ExportObjectCompileCommand(
- language, sourceFilePath, objectDir, objectFileName, objectFileDir,
- vars["FLAGS"], vars["DEFINES"], vars["INCLUDES"], config);
+ if (firstForConfig) {
+ this->ExportObjectCompileCommand(
+ language, sourceFilePath, objectDir, objectFileName, objectFileDir,
+ vars["FLAGS"], vars["DEFINES"], vars["INCLUDES"], config);
+ }
objBuild.Outputs.push_back(objectFileName);
if (firstForConfig) {
diff --git a/Source/cmVisualStudio10TargetGenerator.cxx b/Source/cmVisualStudio10TargetGenerator.cxx
index a7460e8..2356869 100644
--- a/Source/cmVisualStudio10TargetGenerator.cxx
+++ b/Source/cmVisualStudio10TargetGenerator.cxx
@@ -2930,7 +2930,7 @@ void cmVisualStudio10TargetGenerator::WritePathAndIncrementalLinkOptions(
Elem& e0)
{
cmStateEnums::TargetType ttype = this->GeneratorTarget->GetType();
- if (ttype > cmStateEnums::GLOBAL_TARGET) {
+ if (ttype > cmStateEnums::INTERFACE_LIBRARY) {
return;
}
if (this->ProjectType == VsProjectType::csproj) {
diff --git a/Templates/MSBuild/FlagTables/v10_CSharp.json b/Templates/MSBuild/FlagTables/v10_CSharp.json
index 9f21d9a..5341841 100644
--- a/Templates/MSBuild/FlagTables/v10_CSharp.json
+++ b/Templates/MSBuild/FlagTables/v10_CSharp.json
@@ -201,6 +201,13 @@
"flags": []
},
{
+ "name": "DebugType",
+ "switch": "debug:embedded",
+ "comment": "",
+ "value": "embedded",
+ "flags": []
+ },
+ {
"name": "Optimize",
"switch": "optimize",
"comment": "",
diff --git a/Templates/MSBuild/FlagTables/v11_CSharp.json b/Templates/MSBuild/FlagTables/v11_CSharp.json
index 9f21d9a..5341841 100644
--- a/Templates/MSBuild/FlagTables/v11_CSharp.json
+++ b/Templates/MSBuild/FlagTables/v11_CSharp.json
@@ -201,6 +201,13 @@
"flags": []
},
{
+ "name": "DebugType",
+ "switch": "debug:embedded",
+ "comment": "",
+ "value": "embedded",
+ "flags": []
+ },
+ {
"name": "Optimize",
"switch": "optimize",
"comment": "",
diff --git a/Templates/MSBuild/FlagTables/v12_CSharp.json b/Templates/MSBuild/FlagTables/v12_CSharp.json
index 9f21d9a..5341841 100644
--- a/Templates/MSBuild/FlagTables/v12_CSharp.json
+++ b/Templates/MSBuild/FlagTables/v12_CSharp.json
@@ -201,6 +201,13 @@
"flags": []
},
{
+ "name": "DebugType",
+ "switch": "debug:embedded",
+ "comment": "",
+ "value": "embedded",
+ "flags": []
+ },
+ {
"name": "Optimize",
"switch": "optimize",
"comment": "",
diff --git a/Templates/MSBuild/FlagTables/v140_CSharp.json b/Templates/MSBuild/FlagTables/v140_CSharp.json
index 9f21d9a..5341841 100644
--- a/Templates/MSBuild/FlagTables/v140_CSharp.json
+++ b/Templates/MSBuild/FlagTables/v140_CSharp.json
@@ -201,6 +201,13 @@
"flags": []
},
{
+ "name": "DebugType",
+ "switch": "debug:embedded",
+ "comment": "",
+ "value": "embedded",
+ "flags": []
+ },
+ {
"name": "Optimize",
"switch": "optimize",
"comment": "",
diff --git a/Templates/MSBuild/FlagTables/v141_CSharp.json b/Templates/MSBuild/FlagTables/v141_CSharp.json
index 9f21d9a..5341841 100644
--- a/Templates/MSBuild/FlagTables/v141_CSharp.json
+++ b/Templates/MSBuild/FlagTables/v141_CSharp.json
@@ -201,6 +201,13 @@
"flags": []
},
{
+ "name": "DebugType",
+ "switch": "debug:embedded",
+ "comment": "",
+ "value": "embedded",
+ "flags": []
+ },
+ {
"name": "Optimize",
"switch": "optimize",
"comment": "",
diff --git a/Templates/MSBuild/FlagTables/v142_CSharp.json b/Templates/MSBuild/FlagTables/v142_CSharp.json
index ae1bd47..9ea8f4b 100644
--- a/Templates/MSBuild/FlagTables/v142_CSharp.json
+++ b/Templates/MSBuild/FlagTables/v142_CSharp.json
@@ -208,6 +208,13 @@
"flags": []
},
{
+ "name": "DebugType",
+ "switch": "debug:embedded",
+ "comment": "",
+ "value": "embedded",
+ "flags": []
+ },
+ {
"name": "Optimize",
"switch": "optimize",
"comment": "",
diff --git a/Templates/MSBuild/FlagTables/v143_CSharp.json b/Templates/MSBuild/FlagTables/v143_CSharp.json
index ae1bd47..9ea8f4b 100644
--- a/Templates/MSBuild/FlagTables/v143_CSharp.json
+++ b/Templates/MSBuild/FlagTables/v143_CSharp.json
@@ -208,6 +208,13 @@
"flags": []
},
{
+ "name": "DebugType",
+ "switch": "debug:embedded",
+ "comment": "",
+ "value": "embedded",
+ "flags": []
+ },
+ {
"name": "Optimize",
"switch": "optimize",
"comment": "",
diff --git a/Tests/RunCMake/NinjaMultiConfig/CompileCommands-check.cmake b/Tests/RunCMake/NinjaMultiConfig/CompileCommands-check.cmake
new file mode 100644
index 0000000..a1ae6ac
--- /dev/null
+++ b/Tests/RunCMake/NinjaMultiConfig/CompileCommands-check.cmake
@@ -0,0 +1,28 @@
+set(expected_compile_commands
+[==[^\[
+{
+ "directory": "[^
+]*(/Tests/RunCMake/NinjaMultiConfig/CompileCommands-build|\\\\Tests\\\\RunCMake\\\\NinjaMultiConfig\\\\CompileCommands-build)",
+ "command": "[^
+]*Debug[^
+]*",
+ "file": "[^
+]*(/Tests/RunCMake/NinjaMultiConfig/main\.c|\\\\Tests\\\\RunCMake\\\\NinjaMultiConfig\\\\main\.c)"
+},
+{
+ "directory": "[^
+]*(/Tests/RunCMake/NinjaMultiConfig/CompileCommands-build|\\\\Tests\\\\RunCMake\\\\NinjaMultiConfig\\\\CompileCommands-build)",
+ "command": "[^
+]*Release[^
+]*",
+ "file": "[^
+]*(/Tests/RunCMake/NinjaMultiConfig/main\.c|\\\\Tests\\\\RunCMake\\\\NinjaMultiConfig\\\\main\.c)"
+}
+]$]==])
+
+file(READ "${RunCMake_TEST_BINARY_DIR}/compile_commands.json" actual_compile_commands)
+if(NOT actual_compile_commands MATCHES "${expected_compile_commands}")
+ string(REPLACE "\n" "\n " expected_compile_commands_formatted "${expected_compile_commands}")
+ string(REPLACE "\n" "\n " actual_compile_commands_formatted "${actual_compile_commands}")
+ string(APPEND RunCMake_TEST_FAILED "Expected compile_commands.json to match:\n ${expected_compile_commands_formatted}\nActual compile_commands.json:\n ${actual_compile_commands_formatted}\n")
+endif()
diff --git a/Tests/RunCMake/NinjaMultiConfig/CompileCommands.cmake b/Tests/RunCMake/NinjaMultiConfig/CompileCommands.cmake
new file mode 100644
index 0000000..fc44d5a
--- /dev/null
+++ b/Tests/RunCMake/NinjaMultiConfig/CompileCommands.cmake
@@ -0,0 +1,3 @@
+enable_language(C)
+
+add_executable(exe main.c)
diff --git a/Tests/RunCMake/NinjaMultiConfig/RunCMakeTest.cmake b/Tests/RunCMake/NinjaMultiConfig/RunCMakeTest.cmake
index 738bc6c..c040e8f 100644
--- a/Tests/RunCMake/NinjaMultiConfig/RunCMakeTest.cmake
+++ b/Tests/RunCMake/NinjaMultiConfig/RunCMakeTest.cmake
@@ -453,6 +453,11 @@ run_cmake_command(NoUnusedVariables ${CMAKE_COMMAND} ${CMAKE_CURRENT_LIST_DIR}
"-DCMAKE_DEFAULT_BUILD_TYPE=Debug"
"-DCMAKE_DEFAULT_CONFIGS=all"
)
+unset(RunCMake_TEST_BINARY_DIR)
+
+set(RunCMake_TEST_OPTIONS "-DCMAKE_CONFIGURATION_TYPES=Debug\\;Release;-DCMAKE_CROSS_CONFIGS=all;-DCMAKE_EXPORT_COMPILE_COMMANDS=ON")
+run_cmake(CompileCommands)
+unset(RunCMake_TEST_OPTIONS)
# CudaSimple uses separable compilation, which is currently only supported on NVCC.
if(CMake_TEST_CUDA)
diff --git a/Tests/RunCMake/VS10Project/InterfaceLibSources-check.cmake b/Tests/RunCMake/VS10Project/InterfaceLibSources-check.cmake
index bcdc101..1701a36 100644
--- a/Tests/RunCMake/VS10Project/InterfaceLibSources-check.cmake
+++ b/Tests/RunCMake/VS10Project/InterfaceLibSources-check.cmake
@@ -5,6 +5,7 @@ if(NOT EXISTS "${vcProjectFile}")
endif()
set(found_iface_h 0)
+set(found_int_dir 0)
file(STRINGS "${vcProjectFile}" lines)
foreach(line IN LISTS lines)
if(line MATCHES "<([A-Za-z0-9_]+) +Include=.*iface\\.h")
@@ -19,7 +20,15 @@ foreach(line IN LISTS lines)
endif()
set(found_iface_h 1)
endif()
+ if(line MATCHES "^ *<IntDir [^<>]+>[^<>]+</IntDir>")
+ set(found_int_dir 1)
+ endif()
endforeach()
if(NOT found_iface_h)
set(RunCMake_TEST_FAILED "iface.h not referenced in\n ${vcProjectFile}")
+ return()
+endif()
+if(NOT found_int_dir)
+ set(RunCMake_TEST_FAILED "No references to IntDir in\n ${vcProjectFile}")
+ return()
endif()
diff --git a/Tests/RunCMake/export/RunCMakeTest.cmake b/Tests/RunCMake/export/RunCMakeTest.cmake
index 0e6020f..ee00b27 100644
--- a/Tests/RunCMake/export/RunCMakeTest.cmake
+++ b/Tests/RunCMake/export/RunCMakeTest.cmake
@@ -18,3 +18,4 @@ run_cmake(DependOnDoubleExport)
run_cmake(UnknownExport)
run_cmake(NamelinkOnlyExport)
run_cmake(SeparateNamelinkExport)
+run_cmake(TryCompileExport)
diff --git a/Tests/RunCMake/export/TryCompileExport.cmake b/Tests/RunCMake/export/TryCompileExport.cmake
new file mode 100644
index 0000000..5ad7c6e
--- /dev/null
+++ b/Tests/RunCMake/export/TryCompileExport.cmake
@@ -0,0 +1,9 @@
+enable_language(CXX)
+
+add_library(interface INTERFACE)
+install(TARGETS interface EXPORT export)
+export(EXPORT export)
+
+add_library(imported IMPORTED INTERFACE)
+
+try_compile(tc "${CMAKE_CURRENT_BINARY_DIR}/tc" "${CMAKE_CURRENT_SOURCE_DIR}/empty.cpp" LINK_LIBRARIES imported)
diff --git a/Tests/RunCMake/include_external_msproject/Program.cs b/Tests/RunCMake/include_external_msproject/Program.cs
new file mode 100644
index 0000000..5ed58c8
--- /dev/null
+++ b/Tests/RunCMake/include_external_msproject/Program.cs
@@ -0,0 +1,9 @@
+namespace ConsoleApp
+{
+ internal class Program
+ {
+ static void Main(string[] args)
+ {
+ }
+ }
+}
diff --git a/Tests/RunCMake/include_external_msproject/RunCMakeTest.cmake b/Tests/RunCMake/include_external_msproject/RunCMakeTest.cmake
index cb0eb18..4fbf147 100644
--- a/Tests/RunCMake/include_external_msproject/RunCMakeTest.cmake
+++ b/Tests/RunCMake/include_external_msproject/RunCMakeTest.cmake
@@ -10,3 +10,14 @@ if(RunCMake_GENERATOR MATCHES "Visual Studio ([^9]|9[0-9])")
run_cmake(SkipGetTargetFrameworkProperties)
run_cmake(VSCSharpReference)
endif()
+
+if(RunCMake_GENERATOR MATCHES "^Visual Studio (1[6-9]|[2-9][0-9])")
+ function(run_VSCSharpOnlyProject)
+ set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/VSCSharpOnlyProject-build)
+ run_cmake(VSCSharpOnlyProject)
+ set(RunCMake_TEST_NO_CLEAN 1)
+ set(build_flags /restore)
+ run_cmake_command(VSCSharpOnlyProject-build ${CMAKE_COMMAND} --build . -- ${build_flags})
+ endfunction()
+ run_VSCSharpOnlyProject()
+endif()
diff --git a/Tests/RunCMake/include_external_msproject/VSCSharpOnlyProject.cmake b/Tests/RunCMake/include_external_msproject/VSCSharpOnlyProject.cmake
new file mode 100644
index 0000000..e7e0b99
--- /dev/null
+++ b/Tests/RunCMake/include_external_msproject/VSCSharpOnlyProject.cmake
@@ -0,0 +1,9 @@
+project(VSCSharpOnlyProject)
+
+file(COPY
+ ${CMAKE_CURRENT_SOURCE_DIR}/Program.cs
+ ${CMAKE_CURRENT_SOURCE_DIR}/consoleapp.csproj
+ DESTINATION ${CMAKE_CURRENT_BINARY_DIR})
+
+include_external_msproject(
+ test "${CMAKE_CURRENT_BINARY_DIR}/consoleapp.csproj")
diff --git a/Tests/RunCMake/include_external_msproject/consoleapp.csproj b/Tests/RunCMake/include_external_msproject/consoleapp.csproj
new file mode 100644
index 0000000..2894848
--- /dev/null
+++ b/Tests/RunCMake/include_external_msproject/consoleapp.csproj
@@ -0,0 +1,14 @@
+<Project Sdk="Microsoft.NET.Sdk">
+ <PropertyGroup>
+ <OutputType>Exe</OutputType>
+ <TargetFramework>net472</TargetFramework>
+ <RootNamespace>ConsoleApp</RootNamespace>
+ <AssemblyName>ConsoleApp</AssemblyName>
+ <PlatformTarget>x64</PlatformTarget>
+ <EnableDefaultItems>false</EnableDefaultItems>
+ </PropertyGroup>
+
+ <ItemGroup>
+ <Compile Include="Program.cs" />
+ </ItemGroup>
+</Project>
diff --git a/Utilities/Release/macos/sign-notarize.bash b/Utilities/Release/macos/sign-notarize.bash
index fe27afe..55ed591 100755
--- a/Utilities/Release/macos/sign-notarize.bash
+++ b/Utilities/Release/macos/sign-notarize.bash
@@ -1,6 +1,6 @@
#!/usr/bin/env bash
set -e
-readonly usage='usage: sign-notarize.bash -i <id> -d <dev-acct> -k <key-item> [-p <provider>] [--] <package>.dmg
+readonly usage='usage: sign-notarize.bash -i <id> -k <keychain-profile> [--] <package>.dmg
Sign and notarize the "CMake.app" bundle inside the given "<package>.dmg" disk image.
Also produce a "<package>.tar.gz" tarball containing the same "CMake.app".
@@ -8,9 +8,22 @@ Also produce a "<package>.tar.gz" tarball containing the same "CMake.app".
Options:
-i <id> Signing Identity
- -d <dev-acct> Developer account name
- -k <key-item> Keychain item containing account credentials
- -p <provider> Provider short name
+ -k <keychain-profile> Keychain profile containing stored credentials
+
+Create the keychain profile ahead of time using
+
+ xcrun notarytool store-credentials <keychain-profile> \
+ --apple-id <dev-acct> --team-id <team-id> [--password <app-specific-password>]
+
+where:
+
+ <dev-acct> is an Apple ID of a developer account
+ <team-id> is from https://developer.apple.com/account/#!/membership
+ <app-specific-password> is generated via https://support.apple.com/en-us/HT204397
+ If --password is omitted, notarytool will prompt for it.
+
+This creates a keychain item called "com.apple.gke.notary.tool" with an
+account name "com.apple.gke.notary.tool.saved-creds.<keychain-profile>".
'
cleanup() {
@@ -29,15 +42,11 @@ die() {
}
id=''
-dev_acct=''
-key_item=''
-provider=''
+keychain_profile=''
while test "$#" != 0; do
case "$1" in
-i) shift; id="$1" ;;
- -d) shift; dev_acct="$1" ;;
- -k) shift; key_item="$1" ;;
- -p) shift; provider="$1" ;;
+ -k) shift; keychain_profile="$1" ;;
--) shift ; break ;;
-*) die "$usage" ;;
*) break ;;
@@ -51,18 +60,14 @@ esac
test "$#" = 0 || die "$usage"
# Verify arguments.
-if test -z "$id" -o -z "$dev_acct" -o -z "$key_item"; then
+if test -z "$id" -o -z "$keychain_profile"; then
die "$usage"
fi
-if test -n "$provider"; then
- provider="--provider $provider"
-fi
# Verify environment.
-if ! xcnotary="$(type -p xcnotary)"; then
- die "'xcnotary' not found in PATH"
+if ! xcrun --find notarytool 2>/dev/null; then
+ die "'xcrun notarytool' not found"
fi
-readonly xcnotary
readonly tmpdir="$(mktemp -d)"
@@ -95,7 +100,9 @@ codesign --verify --timestamp --options=runtime --verbose --deep \
"$vol_path/CMake.app/Contents/bin/cpack" \
"$vol_path/CMake.app"
-xcnotary notarize "$vol_path/CMake.app" -d "$dev_acct" -k "$key_item" $provider
+ditto -c -k --keepParent "$vol_path/CMake.app" "$tmpdir/CMake.app.zip"
+xcrun notarytool submit "$tmpdir/CMake.app.zip" --keychain-profile "$keychain_profile" --wait
+xcrun stapler staple "$vol_path/CMake.app"
# Create a tarball of the volume next to the original disk image.
readonly tar_gz="${dmg/%.dmg/.tar.gz}"