From 0a81ea1f12cbaf60ec60b8e4a27c5ea476a655de Mon Sep 17 00:00:00 2001 From: Marc Chevrier Date: Mon, 31 Jan 2022 16:43:41 +0100 Subject: Genex-LINK_GROUP: Add possibility to group libraries at link step Fixes: #23121 --- Help/manual/cmake-generator-expressions.7.rst | 151 ++++++- Help/manual/cmake-variables.7.rst | 4 + Help/release/dev/Genex-LINK_GROUP.rst | 8 + .../CMAKE_LANG_LINK_GROUP_USING_FEATURE.rst | 20 + ...AKE_LANG_LINK_GROUP_USING_FEATURE_SUPPORTED.rst | 13 + .../CMAKE_LANG_LINK_LIBRARY_USING_FEATURE.rst | 3 +- Help/variable/CMAKE_LINK_GROUP_USING_FEATURE.rst | 25 ++ Help/variable/CMAKE_LINK_GROUP_USING_FEATURE.txt | 54 +++ .../CMAKE_LINK_GROUP_USING_FEATURE_SUPPORTED.rst | 14 + Help/variable/CMAKE_LINK_LIBRARY_USING_FEATURE.rst | 3 +- Source/Checks/cm_cxx_filesystem.cxx | 2 + Source/cmComputeLinkDepends.cxx | 433 +++++++++++++++++---- Source/cmComputeLinkDepends.h | 16 +- Source/cmComputeLinkInformation.cxx | 284 ++++++++++---- Source/cmComputeLinkInformation.h | 37 +- Source/cmGeneratorExpressionNode.cxx | 85 ++++ Source/cmGeneratorTarget.cxx | 6 +- Source/cmMakefile.cxx | 18 +- Source/cmTarget.cxx | 17 +- Tests/RunCMake/CMakeLists.txt | 13 + Tests/RunCMake/GenEx-LINK_GROUP/CMakeLists.txt | 3 + Tests/RunCMake/GenEx-LINK_GROUP/RunCMakeTest.cmake | 35 ++ .../GenEx-LINK_GROUP/add_custom_command-result.txt | 1 + .../GenEx-LINK_GROUP/add_custom_command-stderr.txt | 9 + .../GenEx-LINK_GROUP/add_custom_command.cmake | 4 + .../GenEx-LINK_GROUP/add_custom_target-result.txt | 1 + .../GenEx-LINK_GROUP/add_custom_target-stderr.txt | 9 + .../GenEx-LINK_GROUP/add_custom_target.cmake | 3 + .../GenEx-LINK_GROUP/add_link_options-result.txt | 1 + .../GenEx-LINK_GROUP/add_link_options-stderr.txt | 9 + .../GenEx-LINK_GROUP/add_link_options.cmake | 5 + .../GenEx-LINK_GROUP/bad-feature1-result.txt | 1 + .../GenEx-LINK_GROUP/bad-feature1-stderr.txt | 5 + Tests/RunCMake/GenEx-LINK_GROUP/bad-feature1.cmake | 6 + .../GenEx-LINK_GROUP/bad-feature2-result.txt | 1 + .../GenEx-LINK_GROUP/bad-feature2-stderr.txt | 5 + Tests/RunCMake/GenEx-LINK_GROUP/bad-feature2.cmake | 8 + .../GenEx-LINK_GROUP/bad-feature3-result.txt | 1 + .../GenEx-LINK_GROUP/bad-feature3-stderr.txt | 6 + Tests/RunCMake/GenEx-LINK_GROUP/bad-feature3.cmake | 9 + .../GenEx-LINK_GROUP/bad-feature4-result.txt | 1 + .../GenEx-LINK_GROUP/bad-feature4-stderr.txt | 6 + Tests/RunCMake/GenEx-LINK_GROUP/bad-feature4.cmake | 9 + .../GenEx-LINK_GROUP/bad-feature5-result.txt | 1 + .../GenEx-LINK_GROUP/bad-feature5-stderr.txt | 6 + Tests/RunCMake/GenEx-LINK_GROUP/bad-feature5.cmake | 9 + .../circular-dependencies1-result.txt | 1 + .../circular-dependencies1-stderr.txt | 11 + .../GenEx-LINK_GROUP/circular-dependencies1.cmake | 17 + .../circular-dependencies2-result.txt | 1 + .../circular-dependencies2-stderr.txt | 11 + .../GenEx-LINK_GROUP/circular-dependencies2.cmake | 18 + .../GenEx-LINK_GROUP/compatible-features1.cmake | 18 + .../GenEx-LINK_GROUP/compatible-features2.cmake | 13 + .../GenEx-LINK_GROUP/compatible-features3.cmake | 13 + .../GenEx-LINK_GROUP/empty-arguments-result.txt | 1 + .../GenEx-LINK_GROUP/empty-arguments-stderr.txt | 8 + .../GenEx-LINK_GROUP/empty-arguments.cmake | 4 + Tests/RunCMake/GenEx-LINK_GROUP/empty.c | 0 .../feature-not-supported-result.txt | 1 + .../feature-not-supported-stderr.txt | 5 + .../GenEx-LINK_GROUP/feature-not-supported.cmake | 9 + .../forbidden-arguments-result.txt | 1 + .../forbidden-arguments-stderr.txt | 16 + .../GenEx-LINK_GROUP/forbidden-arguments.cmake | 6 + .../incompatible-features1-result.txt | 1 + .../incompatible-features1-stderr.txt | 6 + .../GenEx-LINK_GROUP/incompatible-features1.cmake | 15 + .../incompatible-library-features1-result.txt | 1 + .../incompatible-library-features1-stderr.txt | 6 + .../incompatible-library-features1.cmake | 17 + .../incompatible-library-features2-result.txt | 1 + .../incompatible-library-features2-stderr.txt | 6 + .../incompatible-library-features2.cmake | 17 + .../GenEx-LINK_GROUP/invalid-feature-result.txt | 1 + .../GenEx-LINK_GROUP/invalid-feature-stderr.txt | 8 + .../GenEx-LINK_GROUP/invalid-feature.cmake | 6 + .../GenEx-LINK_GROUP/library-ignored-stderr.txt | 13 + .../GenEx-LINK_GROUP/library-ignored.cmake | 15 + .../GenEx-LINK_GROUP/link_directories-result.txt | 1 + .../GenEx-LINK_GROUP/link_directories-stderr.txt | 9 + .../GenEx-LINK_GROUP/link_directories.cmake | 5 + .../nested-incompatible-features1-result.txt | 1 + .../nested-incompatible-features1-stderr.txt | 8 + .../nested-incompatible-features1.cmake | 11 + .../nested-incompatible-features2-result.txt | 1 + .../nested-incompatible-features2-stderr.txt | 8 + .../nested-incompatible-features2.cmake | 14 + .../nested-incompatible-genex-result.txt | 1 + .../nested-incompatible-genex-stderr.txt | 18 + .../nested-incompatible-genex.cmake | 6 + .../GenEx-LINK_GROUP/no-arguments-result.txt | 1 + .../GenEx-LINK_GROUP/no-arguments-stderr.txt | 8 + Tests/RunCMake/GenEx-LINK_GROUP/no-arguments.cmake | 4 + .../GenEx-LINK_GROUP/only-targets-result.txt | 1 + .../GenEx-LINK_GROUP/only-targets-stderr.txt | 13 + Tests/RunCMake/GenEx-LINK_GROUP/only-targets.cmake | 16 + .../override-library-features1.cmake | 4 + .../override-library-features2.cmake | 4 + .../target_link_directories-result.txt | 1 + .../target_link_directories-stderr.txt | 9 + .../GenEx-LINK_GROUP/target_link_directories.cmake | 4 + .../target_link_options-result.txt | 1 + .../target_link_options-stderr.txt | 9 + .../GenEx-LINK_GROUP/target_link_options.cmake | 4 + .../RunCMake/GenEx-LINK_LIBRARY/RunCMakeTest.cmake | 1 + .../GenEx-LINK_LIBRARY/invalid-feature-result.txt | 1 + .../GenEx-LINK_LIBRARY/invalid-feature-stderr.txt | 8 + .../GenEx-LINK_LIBRARY/invalid-feature.cmake | 6 + .../CMakeLists.txt | 3 + .../LINK_GROUP-group-and-single-check.cmake | 4 + .../LINK_GROUP-group-and-single-result.txt | 1 + .../LINK_GROUP-multiple-groups-check.cmake | 4 + .../LINK_GROUP-multiple-groups-result.txt | 1 + .../LINK_GROUP-simple1-check.cmake | 4 + .../LINK_GROUP-simple1-result.txt | 1 + .../LINK_GROUP-simple2-check.cmake | 4 + .../LINK_GROUP-simple2-result.txt | 1 + .../LINK_GROUP-with-LINK_LIBRARY-check.cmake | 4 + .../LINK_GROUP-with-LINK_LIBRARY-result.txt | 1 + ...NK_GROUP-with-LINK_LIBRARY_OVERRIDE-check.cmake | 4 + ...INK_GROUP-with-LINK_LIBRARY_OVERRIDE-result.txt | 1 + .../LINK_GROUP.cmake | 52 +++ .../RunCMakeTest.cmake | 63 +++ .../target_link_libraries-LINK_GROUP/base.c | 9 + .../cross_refs.cmake | 22 ++ .../target_link_libraries-LINK_GROUP/func1.c | 7 + .../target_link_libraries-LINK_GROUP/func2.c | 7 + .../target_link_libraries-LINK_GROUP/func3.c | 6 + .../imported-target-result.txt | 1 + .../imported-target-stdout.txt | 16 + .../imported-target.cmake | 22 ++ .../target_link_libraries-LINK_GROUP/lib.c | 15 + .../target_link_libraries-LINK_GROUP/main.c | 7 + 134 files changed, 1881 insertions(+), 184 deletions(-) create mode 100644 Help/release/dev/Genex-LINK_GROUP.rst create mode 100644 Help/variable/CMAKE_LANG_LINK_GROUP_USING_FEATURE.rst create mode 100644 Help/variable/CMAKE_LANG_LINK_GROUP_USING_FEATURE_SUPPORTED.rst create mode 100644 Help/variable/CMAKE_LINK_GROUP_USING_FEATURE.rst create mode 100644 Help/variable/CMAKE_LINK_GROUP_USING_FEATURE.txt create mode 100644 Help/variable/CMAKE_LINK_GROUP_USING_FEATURE_SUPPORTED.rst create mode 100644 Tests/RunCMake/GenEx-LINK_GROUP/CMakeLists.txt create mode 100644 Tests/RunCMake/GenEx-LINK_GROUP/RunCMakeTest.cmake create mode 100644 Tests/RunCMake/GenEx-LINK_GROUP/add_custom_command-result.txt create mode 100644 Tests/RunCMake/GenEx-LINK_GROUP/add_custom_command-stderr.txt create mode 100644 Tests/RunCMake/GenEx-LINK_GROUP/add_custom_command.cmake create mode 100644 Tests/RunCMake/GenEx-LINK_GROUP/add_custom_target-result.txt create mode 100644 Tests/RunCMake/GenEx-LINK_GROUP/add_custom_target-stderr.txt create mode 100644 Tests/RunCMake/GenEx-LINK_GROUP/add_custom_target.cmake create mode 100644 Tests/RunCMake/GenEx-LINK_GROUP/add_link_options-result.txt create mode 100644 Tests/RunCMake/GenEx-LINK_GROUP/add_link_options-stderr.txt create mode 100644 Tests/RunCMake/GenEx-LINK_GROUP/add_link_options.cmake create mode 100644 Tests/RunCMake/GenEx-LINK_GROUP/bad-feature1-result.txt create mode 100644 Tests/RunCMake/GenEx-LINK_GROUP/bad-feature1-stderr.txt create mode 100644 Tests/RunCMake/GenEx-LINK_GROUP/bad-feature1.cmake create mode 100644 Tests/RunCMake/GenEx-LINK_GROUP/bad-feature2-result.txt create mode 100644 Tests/RunCMake/GenEx-LINK_GROUP/bad-feature2-stderr.txt create mode 100644 Tests/RunCMake/GenEx-LINK_GROUP/bad-feature2.cmake create mode 100644 Tests/RunCMake/GenEx-LINK_GROUP/bad-feature3-result.txt create mode 100644 Tests/RunCMake/GenEx-LINK_GROUP/bad-feature3-stderr.txt create mode 100644 Tests/RunCMake/GenEx-LINK_GROUP/bad-feature3.cmake create mode 100644 Tests/RunCMake/GenEx-LINK_GROUP/bad-feature4-result.txt create mode 100644 Tests/RunCMake/GenEx-LINK_GROUP/bad-feature4-stderr.txt create mode 100644 Tests/RunCMake/GenEx-LINK_GROUP/bad-feature4.cmake create mode 100644 Tests/RunCMake/GenEx-LINK_GROUP/bad-feature5-result.txt create mode 100644 Tests/RunCMake/GenEx-LINK_GROUP/bad-feature5-stderr.txt create mode 100644 Tests/RunCMake/GenEx-LINK_GROUP/bad-feature5.cmake create mode 100644 Tests/RunCMake/GenEx-LINK_GROUP/circular-dependencies1-result.txt create mode 100644 Tests/RunCMake/GenEx-LINK_GROUP/circular-dependencies1-stderr.txt create mode 100644 Tests/RunCMake/GenEx-LINK_GROUP/circular-dependencies1.cmake create mode 100644 Tests/RunCMake/GenEx-LINK_GROUP/circular-dependencies2-result.txt create mode 100644 Tests/RunCMake/GenEx-LINK_GROUP/circular-dependencies2-stderr.txt create mode 100644 Tests/RunCMake/GenEx-LINK_GROUP/circular-dependencies2.cmake create mode 100644 Tests/RunCMake/GenEx-LINK_GROUP/compatible-features1.cmake create mode 100644 Tests/RunCMake/GenEx-LINK_GROUP/compatible-features2.cmake create mode 100644 Tests/RunCMake/GenEx-LINK_GROUP/compatible-features3.cmake create mode 100644 Tests/RunCMake/GenEx-LINK_GROUP/empty-arguments-result.txt create mode 100644 Tests/RunCMake/GenEx-LINK_GROUP/empty-arguments-stderr.txt create mode 100644 Tests/RunCMake/GenEx-LINK_GROUP/empty-arguments.cmake create mode 100644 Tests/RunCMake/GenEx-LINK_GROUP/empty.c create mode 100644 Tests/RunCMake/GenEx-LINK_GROUP/feature-not-supported-result.txt create mode 100644 Tests/RunCMake/GenEx-LINK_GROUP/feature-not-supported-stderr.txt create mode 100644 Tests/RunCMake/GenEx-LINK_GROUP/feature-not-supported.cmake create mode 100644 Tests/RunCMake/GenEx-LINK_GROUP/forbidden-arguments-result.txt create mode 100644 Tests/RunCMake/GenEx-LINK_GROUP/forbidden-arguments-stderr.txt create mode 100644 Tests/RunCMake/GenEx-LINK_GROUP/forbidden-arguments.cmake create mode 100644 Tests/RunCMake/GenEx-LINK_GROUP/incompatible-features1-result.txt create mode 100644 Tests/RunCMake/GenEx-LINK_GROUP/incompatible-features1-stderr.txt create mode 100644 Tests/RunCMake/GenEx-LINK_GROUP/incompatible-features1.cmake create mode 100644 Tests/RunCMake/GenEx-LINK_GROUP/incompatible-library-features1-result.txt create mode 100644 Tests/RunCMake/GenEx-LINK_GROUP/incompatible-library-features1-stderr.txt create mode 100644 Tests/RunCMake/GenEx-LINK_GROUP/incompatible-library-features1.cmake create mode 100644 Tests/RunCMake/GenEx-LINK_GROUP/incompatible-library-features2-result.txt create mode 100644 Tests/RunCMake/GenEx-LINK_GROUP/incompatible-library-features2-stderr.txt create mode 100644 Tests/RunCMake/GenEx-LINK_GROUP/incompatible-library-features2.cmake create mode 100644 Tests/RunCMake/GenEx-LINK_GROUP/invalid-feature-result.txt create mode 100644 Tests/RunCMake/GenEx-LINK_GROUP/invalid-feature-stderr.txt create mode 100644 Tests/RunCMake/GenEx-LINK_GROUP/invalid-feature.cmake create mode 100644 Tests/RunCMake/GenEx-LINK_GROUP/library-ignored-stderr.txt create mode 100644 Tests/RunCMake/GenEx-LINK_GROUP/library-ignored.cmake create mode 100644 Tests/RunCMake/GenEx-LINK_GROUP/link_directories-result.txt create mode 100644 Tests/RunCMake/GenEx-LINK_GROUP/link_directories-stderr.txt create mode 100644 Tests/RunCMake/GenEx-LINK_GROUP/link_directories.cmake create mode 100644 Tests/RunCMake/GenEx-LINK_GROUP/nested-incompatible-features1-result.txt create mode 100644 Tests/RunCMake/GenEx-LINK_GROUP/nested-incompatible-features1-stderr.txt create mode 100644 Tests/RunCMake/GenEx-LINK_GROUP/nested-incompatible-features1.cmake create mode 100644 Tests/RunCMake/GenEx-LINK_GROUP/nested-incompatible-features2-result.txt create mode 100644 Tests/RunCMake/GenEx-LINK_GROUP/nested-incompatible-features2-stderr.txt create mode 100644 Tests/RunCMake/GenEx-LINK_GROUP/nested-incompatible-features2.cmake create mode 100644 Tests/RunCMake/GenEx-LINK_GROUP/nested-incompatible-genex-result.txt create mode 100644 Tests/RunCMake/GenEx-LINK_GROUP/nested-incompatible-genex-stderr.txt create mode 100644 Tests/RunCMake/GenEx-LINK_GROUP/nested-incompatible-genex.cmake create mode 100644 Tests/RunCMake/GenEx-LINK_GROUP/no-arguments-result.txt create mode 100644 Tests/RunCMake/GenEx-LINK_GROUP/no-arguments-stderr.txt create mode 100644 Tests/RunCMake/GenEx-LINK_GROUP/no-arguments.cmake create mode 100644 Tests/RunCMake/GenEx-LINK_GROUP/only-targets-result.txt create mode 100644 Tests/RunCMake/GenEx-LINK_GROUP/only-targets-stderr.txt create mode 100644 Tests/RunCMake/GenEx-LINK_GROUP/only-targets.cmake create mode 100644 Tests/RunCMake/GenEx-LINK_GROUP/override-library-features1.cmake create mode 100644 Tests/RunCMake/GenEx-LINK_GROUP/override-library-features2.cmake create mode 100644 Tests/RunCMake/GenEx-LINK_GROUP/target_link_directories-result.txt create mode 100644 Tests/RunCMake/GenEx-LINK_GROUP/target_link_directories-stderr.txt create mode 100644 Tests/RunCMake/GenEx-LINK_GROUP/target_link_directories.cmake create mode 100644 Tests/RunCMake/GenEx-LINK_GROUP/target_link_options-result.txt create mode 100644 Tests/RunCMake/GenEx-LINK_GROUP/target_link_options-stderr.txt create mode 100644 Tests/RunCMake/GenEx-LINK_GROUP/target_link_options.cmake create mode 100644 Tests/RunCMake/GenEx-LINK_LIBRARY/invalid-feature-result.txt create mode 100644 Tests/RunCMake/GenEx-LINK_LIBRARY/invalid-feature-stderr.txt create mode 100644 Tests/RunCMake/GenEx-LINK_LIBRARY/invalid-feature.cmake create mode 100644 Tests/RunCMake/target_link_libraries-LINK_GROUP/CMakeLists.txt create mode 100644 Tests/RunCMake/target_link_libraries-LINK_GROUP/LINK_GROUP-group-and-single-check.cmake create mode 100644 Tests/RunCMake/target_link_libraries-LINK_GROUP/LINK_GROUP-group-and-single-result.txt create mode 100644 Tests/RunCMake/target_link_libraries-LINK_GROUP/LINK_GROUP-multiple-groups-check.cmake create mode 100644 Tests/RunCMake/target_link_libraries-LINK_GROUP/LINK_GROUP-multiple-groups-result.txt create mode 100644 Tests/RunCMake/target_link_libraries-LINK_GROUP/LINK_GROUP-simple1-check.cmake create mode 100644 Tests/RunCMake/target_link_libraries-LINK_GROUP/LINK_GROUP-simple1-result.txt create mode 100644 Tests/RunCMake/target_link_libraries-LINK_GROUP/LINK_GROUP-simple2-check.cmake create mode 100644 Tests/RunCMake/target_link_libraries-LINK_GROUP/LINK_GROUP-simple2-result.txt create mode 100644 Tests/RunCMake/target_link_libraries-LINK_GROUP/LINK_GROUP-with-LINK_LIBRARY-check.cmake create mode 100644 Tests/RunCMake/target_link_libraries-LINK_GROUP/LINK_GROUP-with-LINK_LIBRARY-result.txt create mode 100644 Tests/RunCMake/target_link_libraries-LINK_GROUP/LINK_GROUP-with-LINK_LIBRARY_OVERRIDE-check.cmake create mode 100644 Tests/RunCMake/target_link_libraries-LINK_GROUP/LINK_GROUP-with-LINK_LIBRARY_OVERRIDE-result.txt create mode 100644 Tests/RunCMake/target_link_libraries-LINK_GROUP/LINK_GROUP.cmake create mode 100644 Tests/RunCMake/target_link_libraries-LINK_GROUP/RunCMakeTest.cmake create mode 100644 Tests/RunCMake/target_link_libraries-LINK_GROUP/base.c create mode 100644 Tests/RunCMake/target_link_libraries-LINK_GROUP/cross_refs.cmake create mode 100644 Tests/RunCMake/target_link_libraries-LINK_GROUP/func1.c create mode 100644 Tests/RunCMake/target_link_libraries-LINK_GROUP/func2.c create mode 100644 Tests/RunCMake/target_link_libraries-LINK_GROUP/func3.c create mode 100644 Tests/RunCMake/target_link_libraries-LINK_GROUP/imported-target-result.txt create mode 100644 Tests/RunCMake/target_link_libraries-LINK_GROUP/imported-target-stdout.txt create mode 100644 Tests/RunCMake/target_link_libraries-LINK_GROUP/imported-target.cmake create mode 100644 Tests/RunCMake/target_link_libraries-LINK_GROUP/lib.c create mode 100644 Tests/RunCMake/target_link_libraries-LINK_GROUP/main.c diff --git a/Help/manual/cmake-generator-expressions.7.rst b/Help/manual/cmake-generator-expressions.7.rst index 0e9060d..403c06e 100644 --- a/Help/manual/cmake-generator-expressions.7.rst +++ b/Help/manual/cmake-generator-expressions.7.rst @@ -1183,13 +1183,160 @@ Output-Related Expressions .. note:: This expression does not guarantee that the list of specified libraries - will be kept grouped. So, constructs like ``start-group`` and - ``end-group``, as supported by ``GNU ld``, cannot be used. + will be kept grouped. So, to manage constructs like ``start-group`` and + ``end-group``, as supported by ``GNU ld``, the :genex:`LINK_GROUP` + generator expression can be used. ``CMake`` pre-defines some features of general interest: .. include:: ../variable/LINK_LIBRARY_PREDEFINED_FEATURES.txt +.. genex:: $ + + .. versionadded:: 3.24 + + Manage the grouping of libraries during the link step. + This expression may be used to specify how to kept groups of libraries during + the link of a target. + For example: + + .. code-block:: cmake + + add_library(lib1 STATIC ...) + add_library(lib2 ...) + target_link_libraries(lib2 PRIVATE "$") + + This specify to use the ``lib1`` target and ``external`` library with the + group feature ``cross_refs`` for linking target ``lib2``. The feature must + have be defined by :variable:`CMAKE__LINK_GROUP_USING_` + variable or, if :variable:`CMAKE__LINK_GROUP_USING__SUPPORTED` + is false, by :variable:`CMAKE_LINK_GROUP_USING_` variable. + + .. note:: + + The evaluation of this generator expression will use, for the following + variables, the values defined at the level of the creation of the target: + + * :variable:`CMAKE__LINK_GROUP_USING__SUPPORTED` + * :variable:`CMAKE__LINK_GROUP_USING_` + * :variable:`CMAKE_LINK_GROUP_USING__SUPPORTED` + * :variable:`CMAKE_LINK_GROUP_USING_` + + This expression can only be used to specify link libraries (i.e. part of + :command:`link_libraries` or :command:`target_link_libraries` commands and + :prop_tgt:`LINK_LIBRARIES` or :prop_tgt:`INTERFACE_LINK_LIBRARIES` target + properties). + + .. note:: + + If this expression appears in the :prop_tgt:`INTERFACE_LINK_LIBRARIES` + property of a target, it will be included in the imported target generated + by :command:`install(EXPORT)` command. It is the responsibility of the + environment consuming this import to define the link feature used by this + expression. + + The ``library-list`` argument can hold CMake targets or external libraries. + Any ``CMake`` target of type :ref:`OBJECT ` or + :ref:`INTERFACE ` will be ignored by this expression and + will be handled in the standard way. + + .. note:: + + This 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. + + Each target or external library involved in the link step can be part of + different groups as far as these groups use the same feature, so mixing + different group features for the same target or library is forbidden. The + different groups will be part of the link step. + + .. code-block:: cmake + + add_library(lib1 ...) + add_library(lib2 ...) + + add_library(lib3 ...) + target_link_libraries(lib3 PUBLIC "$") + + add_library(lib4 ...) + target_link_libraries(lib4 PRIVATE "$") + # lib4 will be linked with the groups {lib1,lib2} and {lib1,lib3} + + add_library(lib5 ...) + target_link_libraries(lib5 PRIVATE "$") + # an error will be raised here because lib1 is part of two groups with + # different features + + When a target or an external library is involved in the link step as part of + a group and also as standalone, any occurrence of the standalone link item + will be replaced by the group or groups it belong to. + + .. code-block:: cmake + + add_library(lib1 ...) + add_library(lib2 ...) + + add_library(lib3 ...) + target_link_libraries(lib3 PUBLIC lib1) + + add_library(lib4 ...) + target_link_libraries(lib4 PRIVATE lib3 "$") + # lib4 will only be linked with lib3 and the group {lib1,lib2} + + This example will be "re-written" by ``CMake`` in the following form: + + .. code-block:: cmake + + add_library(lib1 ...) + add_library(lib2 ...) + + add_library(lib3 ...) + target_link_libraries(lib3 PUBLIC "$") + + add_library(lib4 ...) + target_link_libraries(lib4 PRIVATE lib3 "$") + # lib4 will only be linked with lib3 and the group {lib1,lib2} + + Be aware that the precedence of the group over the standalone link item can + result in some circular dependency between groups, which will raise an + error because circular dependencies are not allowed for groups. + + .. code-block:: cmake + + add_library(lib1A ...) + add_library(lib1B ...) + + add_library(lib2A ...) + add_library(lib2B ...) + + target_link_libraries(lib1A PUBLIC lib2A) + target_link_libraries(lib2B PUBLIC lib1B) + + add_library(lib ...) + target_link_libraries(lib3 PRIVATE "$" + "$") + + This example will be "re-written" by ``CMake`` in the following form: + + .. code-block:: cmake + + add_library(lib1A ...) + add_library(lib1B ...) + + add_library(lib2A ...) + add_library(lib2B ...) + + target_link_libraries(lib1A PUBLIC "$") + target_link_libraries(lib2B PUBLIC "$") + + add_library(lib ...) + target_link_libraries(lib3 PRIVATE "$" + "$") + + So, we have a circular dependency between groups ``{lib1A,lib1B}`` and + ``{lib2A,lib2B}``. + .. genex:: $ Content of ``...`` when the property is exported using :command:`install(EXPORT)`, diff --git a/Help/manual/cmake-variables.7.rst b/Help/manual/cmake-variables.7.rst index b38f56c..ffebfff 100644 --- a/Help/manual/cmake-variables.7.rst +++ b/Help/manual/cmake-variables.7.rst @@ -440,6 +440,8 @@ Variables that Control the Build /variable/CMAKE_LANG_LINK_LIBRARY_USING_FEATURE /variable/CMAKE_LANG_LINK_LIBRARY_USING_FEATURE_SUPPORTED /variable/CMAKE_LANG_LINKER_LAUNCHER + /variable/CMAKE_LANG_LINK_GROUP_USING_FEATURE + /variable/CMAKE_LANG_LINK_GROUP_USING_FEATURE_SUPPORTED /variable/CMAKE_LANG_LINK_LIBRARY_FILE_FLAG /variable/CMAKE_LANG_LINK_LIBRARY_FLAG /variable/CMAKE_LANG_LINK_WHAT_YOU_USE_FLAG @@ -449,6 +451,8 @@ Variables that Control the Build /variable/CMAKE_LIBRARY_PATH_FLAG /variable/CMAKE_LINK_DEF_FILE_FLAG /variable/CMAKE_LINK_DEPENDS_NO_SHARED + /variable/CMAKE_LINK_GROUP_USING_FEATURE + /variable/CMAKE_LINK_GROUP_USING_FEATURE_SUPPORTED /variable/CMAKE_LINK_INTERFACE_LIBRARIES /variable/CMAKE_LINK_LIBRARY_FILE_FLAG /variable/CMAKE_LINK_LIBRARY_FLAG diff --git a/Help/release/dev/Genex-LINK_GROUP.rst b/Help/release/dev/Genex-LINK_GROUP.rst new file mode 100644 index 0000000..aa9e318 --- /dev/null +++ b/Help/release/dev/Genex-LINK_GROUP.rst @@ -0,0 +1,8 @@ +Genex-LINK_GROUP +---------------- + +* The :genex:`LINK_GROUP` generator expression was added to manage the grouping + of libraries during the link step. The variables + :variable:`CMAKE__LINK_GROUP_USING_` and + :variable:`CMAKE_LINK_GROUP_USING_` are used to define features + usable by the :genex:`LINK_GROUP` generator expression. diff --git a/Help/variable/CMAKE_LANG_LINK_GROUP_USING_FEATURE.rst b/Help/variable/CMAKE_LANG_LINK_GROUP_USING_FEATURE.rst new file mode 100644 index 0000000..b68c94a --- /dev/null +++ b/Help/variable/CMAKE_LANG_LINK_GROUP_USING_FEATURE.rst @@ -0,0 +1,20 @@ +CMAKE__LINK_GROUP_USING_ +--------------------------------------- + +.. versionadded:: 3.24 + +This variable defines, for the specified ```` and the linker language +````, the expression expected by the linker when libraries are specified +using :genex:`LINK_GROUP` generator expression. + +.. note:: + + * Feature names can contain Latin letters, digits and undercores. + * Feature names defined in all uppercase are reserved to CMake. + +See also the associated variable +:variable:`CMAKE__LINK_GROUP_USING__SUPPORTED` and +:variable:`CMAKE_LINK_GROUP_USING_` variable for the definition of +features independent from the link language. + +.. include:: CMAKE_LINK_GROUP_USING_FEATURE.txt diff --git a/Help/variable/CMAKE_LANG_LINK_GROUP_USING_FEATURE_SUPPORTED.rst b/Help/variable/CMAKE_LANG_LINK_GROUP_USING_FEATURE_SUPPORTED.rst new file mode 100644 index 0000000..533eee7 --- /dev/null +++ b/Help/variable/CMAKE_LANG_LINK_GROUP_USING_FEATURE_SUPPORTED.rst @@ -0,0 +1,13 @@ +CMAKE__LINK_GROUP_USING__SUPPORTED +------------------------------------------------- + +.. versionadded:: 3.24 + +Set to ``TRUE`` if the ````, as defined by variable +:variable:`CMAKE__LINK_GROUP_USING_`, is supported for the +linker language ````. + +.. note:: + + This variable is evaluated before the more generic variable + :variable:`CMAKE_LINK_GROUP_USING__SUPPORTED`. diff --git a/Help/variable/CMAKE_LANG_LINK_LIBRARY_USING_FEATURE.rst b/Help/variable/CMAKE_LANG_LINK_LIBRARY_USING_FEATURE.rst index 45b8aa8..a9fa9a7 100644 --- a/Help/variable/CMAKE_LANG_LINK_LIBRARY_USING_FEATURE.rst +++ b/Help/variable/CMAKE_LANG_LINK_LIBRARY_USING_FEATURE.rst @@ -9,7 +9,8 @@ using :genex:`LINK_LIBRARY` generator expression. .. note:: - Feature names defined in all uppercase are reserved to CMake. + * Feature names can contain Latin letters, digits and undercores. + * Feature names defined in all uppercase are reserved to CMake. See also the associated variable :variable:`CMAKE__LINK_LIBRARY_USING__SUPPORTED` and diff --git a/Help/variable/CMAKE_LINK_GROUP_USING_FEATURE.rst b/Help/variable/CMAKE_LINK_GROUP_USING_FEATURE.rst new file mode 100644 index 0000000..8aade01 --- /dev/null +++ b/Help/variable/CMAKE_LINK_GROUP_USING_FEATURE.rst @@ -0,0 +1,25 @@ +CMAKE_LINK_GROUP_USING_ +-------------------------------- + +.. versionadded:: 3.24 + +This variable defines, for the specified ````, the expression expected +by the linker when libraries are specified using :genex:`LINK_GROUP` generator +expression. + +.. note:: + + * Feature names can contain Latin letters, digits and undercores. + * Feature names defined in all uppercase are reserved to CMake. + +See also the associated variable +:variable:`CMAKE_LINK_GROUP_USING__SUPPORTED` and +:variable:`CMAKE__LINK_GROUP_USING_` variable for the definition +of features dependent from the link language. + +This variable will be used by :genex:`LINK_GROUP` generator expression if, +for the linker language, the variable +:variable:`CMAKE__LINK_GROUP_USING__SUPPORTED` is false or not +set. + +.. include:: CMAKE_LINK_GROUP_USING_FEATURE.txt diff --git a/Help/variable/CMAKE_LINK_GROUP_USING_FEATURE.txt b/Help/variable/CMAKE_LINK_GROUP_USING_FEATURE.txt new file mode 100644 index 0000000..ecd9cb5 --- /dev/null +++ b/Help/variable/CMAKE_LINK_GROUP_USING_FEATURE.txt @@ -0,0 +1,54 @@ + +It must contain two elements. + +:: + + + +```` and ```` will be used to encapsulate the list of +libraries. + +For the elements of this variable, the ``LINKER:`` prefix can be used: + + .. include:: ../command/LINK_OPTIONS_LINKER.txt + :start-line: 3 + +Examples +^^^^^^^^ + +Solving cross-references between two static libraries +""""""""""""""""""""""""""""""""""""""""""""""""""""" + +A common need is the capability to search repeatedly in a group of static +libraries until no new undefined references are created. This capability is +offered by different environments but with a specific syntax: + +.. code-block:: cmake + + set(CMAKE_C_LINK_GROUP_USING_cross_refs_SUPPORTED TRUE) + if(CMAKE_C_COMPILER_ID STREQUAL "GNU" + AND CMAKE_SYSTEM_NAME STREQUAL "Linux") + set(CMAKE_C_LINK_GROUP_USING_cross_refs "LINKER:--start-group" + "LINKER:--end-group") + elseif(CMAKE_C_COMPILER_ID STREQUAL "SunPro" + AND CMAKE_SYSTEM_NAME STREQUAL "SunOS") + set(CMAKE_C_LINK_GROUP_USING_cross_refs "LINKER:-z,rescan-start" + "LINKER:-z,rescan-end") + else() + # feature not yet supported for the other environments + set(CMAKE_C_LINK_GROUP_USING_cross_refs_SUPPORTED FALSE) + endif() + + add_library(lib1 STATIC ...) + + add_library(lib3 SHARED ...) + if(CMAKE_C_LINK_GROUP_USING_cross_refs_SUPPORTED) + target_link_libraries(lib3 PRIVATE "$") + else() + target_link_libraries(lib3 PRIVATE lib1 external) + endif() + +CMake will generate the following link expressions: + +* ``GNU``: ``-Wl,--start-group /path/to/lib1.a -lexternal -Wl,--end-group`` +* ``SunPro``: ``-Wl,-z,rescan-start /path/to/lib1.a -lexternal -Wl,-z,rescan-end`` diff --git a/Help/variable/CMAKE_LINK_GROUP_USING_FEATURE_SUPPORTED.rst b/Help/variable/CMAKE_LINK_GROUP_USING_FEATURE_SUPPORTED.rst new file mode 100644 index 0000000..249ccbc --- /dev/null +++ b/Help/variable/CMAKE_LINK_GROUP_USING_FEATURE_SUPPORTED.rst @@ -0,0 +1,14 @@ +CMAKE_LINK_GROUP_USING__SUPPORTED +------------------------------------------ + +.. versionadded:: 3.24 + +Set to ``TRUE`` if the ````, as defined by variable +:variable:`CMAKE_LINK_GROUP_USING_`, is supported regardless the +linker language. + +.. note:: + + This variable is evaluated if, and only if, the variable + :variable:`CMAKE__LINK_GROUP_USING__SUPPORTED` evaluates to + ``FALSE``. diff --git a/Help/variable/CMAKE_LINK_LIBRARY_USING_FEATURE.rst b/Help/variable/CMAKE_LINK_LIBRARY_USING_FEATURE.rst index eae60c5..7aace32 100644 --- a/Help/variable/CMAKE_LINK_LIBRARY_USING_FEATURE.rst +++ b/Help/variable/CMAKE_LINK_LIBRARY_USING_FEATURE.rst @@ -9,7 +9,8 @@ using :genex:`LINK_LIBRARY` generator expression. .. note:: - Feature names defined in all uppercase are reserved to CMake. + * Feature names can contain Latin letters, digits and undercores. + * Feature names defined in all uppercase are reserved to CMake. See also the associated variable :variable:`CMAKE_LINK_LIBRARY_USING__SUPPORTED` and diff --git a/Source/Checks/cm_cxx_filesystem.cxx b/Source/Checks/cm_cxx_filesystem.cxx index ae8acc5..b7d5be5 100644 --- a/Source/Checks/cm_cxx_filesystem.cxx +++ b/Source/Checks/cm_cxx_filesystem.cxx @@ -3,6 +3,8 @@ int main() { + return 1; + std::filesystem::path p0(L"/a/b/c"); std::filesystem::path p1("/a/b/c"); diff --git a/Source/cmComputeLinkDepends.cxx b/Source/cmComputeLinkDepends.cxx index 7c8de9e..a4dc01b 100644 --- a/Source/cmComputeLinkDepends.cxx +++ b/Source/cmComputeLinkDepends.cxx @@ -180,6 +180,7 @@ items that we know the linker will re-use automatically (shared libs). */ namespace { +// LINK_LIBRARY helpers const auto LL_BEGIN = "GetDefinition(featureSupported).IsOn(); } + +// LINK_GROUP helpers +const auto LG_BEGIN = "GetDefinition(featureSupported).IsOn()) { + return true; + } + + featureSupported = + cmStrCat("CMAKE_LINK_GROUP_USING_", feature, "_SUPPORTED"); + return makefile->GetDefinition(featureSupported).IsOn(); +} } const std::string cmComputeLinkDepends::LinkEntry::DEFAULT = "DEFAULT"; @@ -311,6 +337,11 @@ cmComputeLinkDepends::Compute() // Infer dependencies of targets for which they were not known. this->InferDependencies(); + // finalize groups dependencies + // All dependencies which are raw items must be replaced by the group + // it belongs to, if any. + this->UpdateGroupDependencies(); + // Cleanup the constraint graph. this->CleanConstraintGraph(); @@ -325,6 +356,19 @@ cmComputeLinkDepends::Compute() this->DisplayConstraintGraph(); } + // Compute the DAG of strongly connected components. The algorithm + // used by cmComputeComponentGraph should identify the components in + // the same order in which the items were originally discovered in + // the BFS. This should preserve the original order when no + // constraints disallow it. + this->CCG = + cm::make_unique(this->EntryConstraintGraph); + this->CCG->Compute(); + + if (!this->CheckCircularDependencies()) { + return this->FinalLinkEntries; + } + // Compute the final ordering. this->OrderLinkEntries(); @@ -350,6 +394,29 @@ cmComputeLinkDepends::Compute() // Reverse the resulting order since we iterated in reverse. std::reverse(this->FinalLinkEntries.begin(), this->FinalLinkEntries.end()); + // Expand group items + if (!this->GroupItems.empty()) { + for (const auto& group : this->GroupItems) { + const LinkEntry& groupEntry = this->EntryList[group.first]; + auto it = this->FinalLinkEntries.begin(); + while (true) { + it = std::find_if(it, this->FinalLinkEntries.end(), + [&groupEntry](const LinkEntry& entry) -> bool { + return groupEntry.Item == entry.Item; + }); + if (it == this->FinalLinkEntries.end()) { + break; + } + it->Item.Value = ""; + for (auto i = group.second.rbegin(); i != group.second.rend(); ++i) { + it = this->FinalLinkEntries.insert(it, this->EntryList[*i]); + } + it = this->FinalLinkEntries.insert(it, groupEntry); + it->Item.Value = ""; + } + } + } + // Display the final set. if (this->DebugMode) { this->DisplayFinalEntries(); @@ -379,7 +446,8 @@ cmComputeLinkDepends::AllocateLinkEntry(cmLinkItem const& item) return lei; } -std::pair cmComputeLinkDepends::AddLinkEntry(cmLinkItem const& item) +std::pair cmComputeLinkDepends::AddLinkEntry(cmLinkItem const& item, + int groupIndex) { // Allocate a spot for the item entry. auto lei = this->AllocateLinkEntry(item); @@ -399,23 +467,28 @@ std::pair cmComputeLinkDepends::AddLinkEntry(cmLinkItem const& item) entry.Item.Value[1] != 'l' && entry.Item.Value.substr(0, 10) != "-framework") { entry.Kind = LinkEntry::Flag; + } else if (cmHasPrefix(entry.Item.Value, LG_BEGIN) && + cmHasSuffix(entry.Item.Value, '>')) { + entry.Kind = LinkEntry::Group; } - // If the item has dependencies queue it to follow them. - if (entry.Target) { - // Target dependencies are always known. Follow them. - BFSEntry qe = { index, nullptr }; - this->BFSQueue.push(qe); - } else { - // Look for an old-style _LIB_DEPENDS variable. - std::string var = cmStrCat(entry.Item.Value, "_LIB_DEPENDS"); - if (cmValue val = this->Makefile->GetDefinition(var)) { - // The item dependencies are known. Follow them. - BFSEntry qe = { index, val->c_str() }; + if (entry.Kind != LinkEntry::Group) { + // If the item has dependencies queue it to follow them. + if (entry.Target) { + // Target dependencies are always known. Follow them. + BFSEntry qe = { index, groupIndex, nullptr }; this->BFSQueue.push(qe); - } else if (entry.Kind != LinkEntry::Flag) { - // The item dependencies are not known. We need to infer them. - this->InferredDependSets[index].Initialized = true; + } else { + // Look for an old-style _LIB_DEPENDS variable. + std::string var = cmStrCat(entry.Item.Value, "_LIB_DEPENDS"); + if (cmValue val = this->Makefile->GetDefinition(var)) { + // The item dependencies are known. Follow them. + BFSEntry qe = { index, groupIndex, val->c_str() }; + this->BFSQueue.push(qe); + } else if (entry.Kind != LinkEntry::Flag) { + // The item dependencies are not known. We need to infer them. + this->InferredDependSets[index].Initialized = true; + } } } @@ -445,8 +518,8 @@ void cmComputeLinkDepends::AddLinkObject(cmLinkItem const& item) void cmComputeLinkDepends::FollowLinkEntry(BFSEntry qe) { // Get this entry representation. - int depender_index = qe.Index; - LinkEntry const& entry = this->EntryList[depender_index]; + int depender_index = qe.GroupIndex == -1 ? qe.Index : qe.GroupIndex; + LinkEntry const& entry = this->EntryList[qe.Index]; // Follow the item's dependencies. if (entry.Target) { @@ -628,6 +701,10 @@ void cmComputeLinkDepends::AddLinkEntries(int depender_index, std::map dependSets; std::string feature = LinkEntry::DEFAULT; + bool inGroup = false; + std::pair groupIndex{ -1, false }; + std::vector groupItems; + // Loop over the libraries linked directly by the depender. for (T const& l : libs) { // Skip entries that will resolve to the target getting linked or @@ -636,6 +713,7 @@ void cmComputeLinkDepends::AddLinkEntries(int depender_index, if (item.AsStr() == this->Target->GetName() || item.AsStr().empty()) { continue; } + if (cmHasPrefix(item.AsStr(), LL_BEGIN) && cmHasSuffix(item.AsStr(), '>')) { feature = ExtractFeature(item.AsStr()); @@ -666,12 +744,82 @@ void cmComputeLinkDepends::AddLinkEntries(int depender_index, continue; } + if (cmHasPrefix(item.AsStr(), LG_BEGIN) && + cmHasSuffix(item.AsStr(), '>')) { + groupIndex = this->AddLinkEntry(item); + if (groupIndex.second) { + LinkEntry& entry = this->EntryList[groupIndex.first]; + entry.Feature = ExtractGroupFeature(item.AsStr()); + } + inGroup = true; + if (depender_index >= 0) { + this->EntryConstraintGraph[depender_index].emplace_back( + groupIndex.first, false, false, cmListFileBacktrace()); + } else { + // This is a direct dependency of the target being linked. + this->OriginalEntries.push_back(groupIndex.first); + } + continue; + } + + int dependee_index; + + if (cmHasPrefix(item.AsStr(), LG_END) && cmHasSuffix(item.AsStr(), '>')) { + dependee_index = groupIndex.first; + if (groupIndex.second) { + this->GroupItems.emplace(groupIndex.first, groupItems); + } + inGroup = false; + groupIndex = std::make_pair(-1, false); + groupItems.clear(); + continue; + } + + if (depender_index >= 0 && inGroup) { + const auto& depender = this->EntryList[depender_index]; + const auto& groupFeature = this->EntryList[groupIndex.first].Feature; + if (depender.Target != nullptr && depender.Target->IsImported() && + !IsGroupFeatureSupported(this->Makefile, this->LinkLanguage, + groupFeature)) { + this->CMakeInstance->IssueMessage( + MessageType::AUTHOR_ERROR, + cmStrCat("The 'IMPORTED' target '", depender.Target->GetName(), + "' uses the generator-expression '$' with " + "the feature '", + groupFeature, + "', which is undefined or unsupported.\nDid you miss to " + "define it by setting variables \"CMAKE_", + this->LinkLanguage, "_LINK_GROUP_USING_", groupFeature, + "\" and \"CMAKE_", this->LinkLanguage, "_LINK_GROUP_USING_", + groupFeature, "_SUPPORTED\"?"), + this->Target->GetBacktrace()); + } + } + // Add a link entry for this item. - auto ale = this->AddLinkEntry(item); - int dependee_index = ale.first; + auto ale = this->AddLinkEntry(item, groupIndex.first); + dependee_index = ale.first; LinkEntry& entry = this->EntryList[dependee_index]; auto const& itemFeature = this->GetCurrentFeature(entry.Item.Value, feature); + if (inGroup && ale.second && entry.Target != nullptr && + (entry.Target->GetType() == cmStateEnums::TargetType::OBJECT_LIBRARY || + entry.Target->GetType() == + cmStateEnums::TargetType::INTERFACE_LIBRARY)) { + const auto& groupFeature = this->EntryList[groupIndex.first].Feature; + this->CMakeInstance->IssueMessage( + MessageType::AUTHOR_WARNING, + cmStrCat( + "The feature '", groupFeature, + "', specified as part of a generator-expression " + "'$", + LG_BEGIN, groupFeature, ">', will not be applied to the ", + (entry.Target->GetType() == cmStateEnums::TargetType::OBJECT_LIBRARY + ? "OBJECT" + : "INTERFACE"), + " library '", entry.Item.Value, "'."), + this->Target->GetBacktrace()); + } if (itemFeature != LinkEntry::DEFAULT) { if (ale.second) { // current item not yet defined @@ -702,50 +850,97 @@ void cmComputeLinkDepends::AddLinkEntries(int depender_index, (entry.Target->GetType() != cmStateEnums::TargetType::OBJECT_LIBRARY && entry.Target->GetType() != cmStateEnums::TargetType::INTERFACE_LIBRARY); - if (supportedItem && entry.Feature != itemFeature) { - // incompatibles features occurred - this->CMakeInstance->IssueMessage( - MessageType::FATAL_ERROR, - cmStrCat("Impossible to link target '", this->Target->GetName(), - "' because the link item '", entry.Item.Value, - "', specified ", - (itemFeature == LinkEntry::DEFAULT - ? "without any feature or 'DEFAULT' feature" - : cmStrCat("with the feature '", itemFeature, '\'')), - ", has already occurred ", - (entry.Feature == LinkEntry::DEFAULT - ? "without any feature or 'DEFAULT' feature" - : cmStrCat("with the feature '", entry.Feature, '\'')), - ", which is not allowed."), - this->Target->GetBacktrace()); + if (supportedItem) { + if (inGroup) { + const auto& currentFeature = this->EntryList[groupIndex.first].Feature; + for (const auto& g : this->GroupItems) { + const auto& groupFeature = this->EntryList[g.first].Feature; + if (groupFeature == currentFeature) { + continue; + } + if (std::find(g.second.cbegin(), g.second.cend(), dependee_index) != + g.second.cend()) { + this->CMakeInstance->IssueMessage( + MessageType::FATAL_ERROR, + cmStrCat("Impossible to link target '", this->Target->GetName(), + "' because the link item '", entry.Item.Value, + "', specified with the group feature '", currentFeature, + '\'', ", has already occurred with the feature '", + groupFeature, '\'', ", which is not allowed."), + this->Target->GetBacktrace()); + continue; + } + } + } + if (entry.Feature != itemFeature) { + // incompatibles features occurred + this->CMakeInstance->IssueMessage( + MessageType::FATAL_ERROR, + cmStrCat("Impossible to link target '", this->Target->GetName(), + "' because the link item '", entry.Item.Value, + "', specified ", + (itemFeature == LinkEntry::DEFAULT + ? "without any feature or 'DEFAULT' feature" + : cmStrCat("with the feature '", itemFeature, '\'')), + ", has already occurred ", + (entry.Feature == LinkEntry::DEFAULT + ? "without any feature or 'DEFAULT' feature" + : cmStrCat("with the feature '", entry.Feature, '\'')), + ", which is not allowed."), + this->Target->GetBacktrace()); + } } - // The dependee must come after the depender. - if (depender_index >= 0) { - this->EntryConstraintGraph[depender_index].emplace_back( - dependee_index, false, false, cmListFileBacktrace()); + if (inGroup) { + // store item index for dependencies handling + groupItems.push_back(dependee_index); } else { - // This is a direct dependency of the target being linked. - this->OriginalEntries.push_back(dependee_index); - } - - // Update the inferred dependencies for earlier items. - for (auto& dependSet : dependSets) { - // Add this item to the inferred dependencies of other items. - // Target items are never inferred dependees because unknown - // items are outside libraries that should not be depending on - // targets. - if (!this->EntryList[dependee_index].Target && - this->EntryList[dependee_index].Kind != LinkEntry::Flag && - dependee_index != dependSet.first) { - dependSet.second.insert(dependee_index); + std::vector indexes; + bool entryHandled = false; + // search any occurrence of the library in already defined groups + for (const auto& group : this->GroupItems) { + for (auto index : group.second) { + if (entry.Item.Value == this->EntryList[index].Item.Value) { + indexes.push_back(group.first); + entryHandled = true; + break; + } + } } - } + if (!entryHandled) { + indexes.push_back(dependee_index); + } + + for (auto index : indexes) { + // The dependee must come after the depender. + if (depender_index >= 0) { + this->EntryConstraintGraph[depender_index].emplace_back( + index, false, false, cmListFileBacktrace()); + } else { + // This is a direct dependency of the target being linked. + this->OriginalEntries.push_back(index); + } + + // Update the inferred dependencies for earlier items. + for (auto& dependSet : dependSets) { + // Add this item to the inferred dependencies of other items. + // Target items are never inferred dependees because unknown + // items are outside libraries that should not be depending on + // targets. + if (!this->EntryList[index].Target && + this->EntryList[index].Kind != LinkEntry::Flag && + this->EntryList[index].Kind != LinkEntry::Group && + dependee_index != dependSet.first) { + dependSet.second.insert(index); + } + } - // If this item needs to have dependencies inferred, do so. - if (this->InferredDependSets[dependee_index].Initialized) { - // Make sure an entry exists to hold the set for the item. - dependSets[dependee_index]; + // If this item needs to have dependencies inferred, do so. + if (this->InferredDependSets[index].Initialized) { + // Make sure an entry exists to hold the set for the item. + dependSets[index]; + } + } } } @@ -808,6 +1003,36 @@ void cmComputeLinkDepends::InferDependencies() } } +void cmComputeLinkDepends::UpdateGroupDependencies() +{ + if (this->GroupItems.empty()) { + return; + } + + // Walks through all entries of the constraint graph to replace dependencies + // over raw items by the group it belongs to, if any. + for (auto& edgeList : this->EntryConstraintGraph) { + for (auto& edge : edgeList) { + int index = edge; + if (this->EntryList[index].Kind == LinkEntry::Group || + this->EntryList[index].Kind == LinkEntry::Flag || + this->EntryList[index].Kind == LinkEntry::Object) { + continue; + } + // search the item in the defined groups + for (const auto& groupItems : this->GroupItems) { + auto pos = std::find(groupItems.second.cbegin(), + groupItems.second.cend(), index); + if (pos != groupItems.second.cend()) { + // replace lib dependency by the group it belongs to + edge = cmGraphEdge{ groupItems.first, false, false, + cmListFileBacktrace() }; + } + } + } + } +} + void cmComputeLinkDepends::CleanConstraintGraph() { for (cmGraphEdgeList& edgeList : this->EntryConstraintGraph) { @@ -821,6 +1046,76 @@ void cmComputeLinkDepends::CleanConstraintGraph() } } +bool cmComputeLinkDepends::CheckCircularDependencies() const +{ + std::vector const& components = this->CCG->GetComponents(); + int nc = static_cast(components.size()); + for (int c = 0; c < nc; ++c) { + // Get the current component. + NodeList const& nl = components[c]; + + // Skip trivial components. + if (nl.size() < 2) { + continue; + } + + // no group must be evolved + bool cycleDetected = false; + for (int ni : nl) { + if (this->EntryList[ni].Kind == LinkEntry::Group) { + cycleDetected = true; + break; + } + } + if (!cycleDetected) { + continue; + } + + // Construct the error message. + auto formatItem = [](LinkEntry const& entry) -> std::string { + if (entry.Kind == LinkEntry::Group) { + auto items = + entry.Item.Value.substr(entry.Item.Value.find(':', 12) + 1); + items.pop_back(); + std::replace(items.begin(), items.end(), '|', ','); + return cmStrCat("group \"", ExtractGroupFeature(entry.Item.Value), + ":{", items, "}\""); + } + return cmStrCat('"', entry.Item.Value, '"'); + }; + + std::ostringstream e; + e << "The inter-target dependency graph, for the target \"" + << this->Target->GetName() + << "\", contains the following strongly connected component " + "(cycle):\n"; + std::vector const& cmap = this->CCG->GetComponentMap(); + for (int i : nl) { + // Get the depender. + LinkEntry const& depender = this->EntryList[i]; + + // Describe the depender. + e << " " << formatItem(depender) << "\n"; + + // List its dependencies that are inside the component. + EdgeList const& el = this->EntryConstraintGraph[i]; + for (cmGraphEdge const& ni : el) { + int j = ni; + if (cmap[j] == c) { + LinkEntry const& dependee = this->EntryList[j]; + e << " depends on " << formatItem(dependee) << "\n"; + } + } + } + this->CMakeInstance->IssueMessage(MessageType::FATAL_ERROR, e.str(), + this->Target->GetBacktrace()); + + return false; + } + + return true; +} + void cmComputeLinkDepends::DisplayConstraintGraph() { // Display the graph nodes and their edges. @@ -835,15 +1130,6 @@ void cmComputeLinkDepends::DisplayConstraintGraph() void cmComputeLinkDepends::OrderLinkEntries() { - // Compute the DAG of strongly connected components. The algorithm - // used by cmComputeComponentGraph should identify the components in - // the same order in which the items were originally discovered in - // the BFS. This should preserve the original order when no - // constraints disallow it. - this->CCG = - cm::make_unique(this->EntryConstraintGraph); - this->CCG->Compute(); - // The component graph is guaranteed to be acyclic. Start a DFS // from every entry to compute a topological order for the // components. @@ -1033,11 +1319,18 @@ int cmComputeLinkDepends::ComputeComponentCount(NodeList const& nl) void cmComputeLinkDepends::DisplayFinalEntries() { fprintf(stderr, "target [%s] links to:\n", this->Target->GetName().c_str()); + char space[] = " "; + int count = 2; for (LinkEntry const& lei : this->FinalLinkEntries) { - if (lei.Target) { - fprintf(stderr, " target [%s]", lei.Target->GetName().c_str()); + if (lei.Kind == LinkEntry::Group) { + fprintf(stderr, " %s group", + lei.Item.Value == "" ? "start" : "end"); + count = lei.Item.Value == "" ? 4 : 2; + } else if (lei.Target) { + fprintf(stderr, "%*starget [%s]", count, space, + lei.Target->GetName().c_str()); } else { - fprintf(stderr, " item [%s]", lei.Item.Value.c_str()); + fprintf(stderr, "%*sitem [%s]", count, space, lei.Item.Value.c_str()); } if (lei.Feature != LinkEntry::DEFAULT) { fprintf(stderr, ", feature [%s]", lei.Feature.c_str()); diff --git a/Source/cmComputeLinkDepends.h b/Source/cmComputeLinkDepends.h index 3c83f5a..8cc916a 100644 --- a/Source/cmComputeLinkDepends.h +++ b/Source/cmComputeLinkDepends.h @@ -54,7 +54,10 @@ public: Library, Object, SharedDep, - Flag + Flag, + // The following member is for the management of items specified + // through genex $ + Group }; BT Item; @@ -90,7 +93,8 @@ private: std::pair::iterator, bool> AllocateLinkEntry( cmLinkItem const& item); - std::pair AddLinkEntry(cmLinkItem const& item); + std::pair AddLinkEntry(cmLinkItem const& item, + int groupIndex = -1); void AddLinkObject(cmLinkItem const& item); void AddVarLinkEntries(int depender_index, const char* value); void AddDirectLinkEntries(); @@ -103,10 +107,14 @@ private: std::vector EntryList; std::map LinkEntryIndex; + // map storing, for each group, the list of items + std::map> GroupItems; + // BFS of initial dependencies. struct BFSEntry { int Index; + int GroupIndex; const char* LibDepends; }; std::queue BFSQueue; @@ -139,12 +147,16 @@ private: std::vector InferredDependSets; void InferDependencies(); + // To finalize dependencies over groups in place of raw items + void UpdateGroupDependencies(); + // Ordering constraint graph adjacency list. using NodeList = cmGraphNodeList; using EdgeList = cmGraphEdgeList; using Graph = cmGraphAdjacencyList; Graph EntryConstraintGraph; void CleanConstraintGraph(); + bool CheckCircularDependencies() const; void DisplayConstraintGraph(); // Ordering algorithm. diff --git a/Source/cmComputeLinkInformation.cxx b/Source/cmComputeLinkInformation.cxx index fe4491d..67214f1 100644 --- a/Source/cmComputeLinkInformation.cxx +++ b/Source/cmComputeLinkInformation.cxx @@ -350,21 +350,23 @@ cmComputeLinkInformation::cmComputeLinkInformation( if (!this->GetLibLinkFileFlag().empty()) { this->LibraryFeatureDescriptors.emplace( "__CMAKE_LINK_LIBRARY", - FeatureDescriptor{ "__CMAKE_LINK_LIBRARY", - cmStrCat(this->GetLibLinkFileFlag(), "") }); + LibraryFeatureDescriptor{ + "__CMAKE_LINK_LIBRARY", + cmStrCat(this->GetLibLinkFileFlag(), "") }); } if (!this->GetObjLinkFileFlag().empty()) { this->LibraryFeatureDescriptors.emplace( "__CMAKE_LINK_OBJECT", - FeatureDescriptor{ "__CMAKE_LINK_OBJECT", - cmStrCat(this->GetObjLinkFileFlag(), "") }); + LibraryFeatureDescriptor{ + "__CMAKE_LINK_OBJECT", + cmStrCat(this->GetObjLinkFileFlag(), "") }); } if (!this->LoaderFlag->empty()) { // Define a Feature descriptor for the link of an executable with exports this->LibraryFeatureDescriptors.emplace( "__CMAKE_LINK_EXECUTABLE", - FeatureDescriptor{ "__CMAKE_LINK_EXECUTABLE", - cmStrCat(this->LoaderFlag, "") }); + LibraryFeatureDescriptor{ "__CMAKE_LINK_EXECUTABLE", + cmStrCat(this->LoaderFlag, "") }); } // Check the platform policy for missing soname case. @@ -544,6 +546,19 @@ bool cmComputeLinkInformation::Compute() // Add the link line items. for (cmComputeLinkDepends::LinkEntry const& linkEntry : linkEntries) { + if (linkEntry.Kind == cmComputeLinkDepends::LinkEntry::Group) { + const auto& groupFeature = this->GetGroupFeature(linkEntry.Feature); + if (groupFeature.Supported) { + this->Items.emplace_back( + BT{ linkEntry.Item.Value == "" + ? groupFeature.Prefix + : groupFeature.Suffix, + linkEntry.Item.Backtrace }, + ItemIsPath::No); + } + continue; + } + if (currentFeature != nullptr && linkEntry.Feature != currentFeature->Name) { // emit feature suffix, if any @@ -664,6 +679,117 @@ bool IsValidFeatureFormat(const std::string& format) format.find("") != std::string::npos || format.find("") != std::string::npos; } + +class FeaturePlaceHolderExpander : public cmPlaceholderExpander +{ +public: + FeaturePlaceHolderExpander(const std::string* library, + const std::string* libItem = nullptr, + const std::string* linkItem = nullptr) + : Library(library) + , LibItem(libItem) + , LinkItem(linkItem) + { + } + +private: + std::string ExpandVariable(std::string const& variable) override + { + if (this->Library != nullptr && variable == "LIBRARY") { + return *this->Library; + } + if (this->LibItem != nullptr && variable == "LIB_ITEM") { + return *this->LibItem; + } + if (this->LinkItem != nullptr && variable == "LINK_ITEM") { + return *this->LinkItem; + } + + return variable; + } + + const std::string* Library = nullptr; + const std::string* LibItem = nullptr; + const std::string* LinkItem = nullptr; +}; +} + +cmComputeLinkInformation::FeatureDescriptor::FeatureDescriptor( + std::string name, std::string itemFormat) + : Name(std::move(name)) + , Supported(true) + , ItemPathFormat(std::move(itemFormat)) + , ItemNameFormat(this->ItemPathFormat) +{ +} +cmComputeLinkInformation::FeatureDescriptor::FeatureDescriptor( + std::string name, std::string itemPathFormat, std::string itemNameFormat) + : Name(std::move(name)) + , Supported(true) + , ItemPathFormat(std::move(itemPathFormat)) + , ItemNameFormat(std::move(itemNameFormat)) +{ +} +cmComputeLinkInformation::FeatureDescriptor::FeatureDescriptor( + std::string name, std::string prefix, std::string itemPathFormat, + std::string itemNameFormat, std::string suffix) + : Name(std::move(name)) + , Supported(true) + , Prefix(std::move(prefix)) + , Suffix(std::move(suffix)) + , ItemPathFormat(std::move(itemPathFormat)) + , ItemNameFormat(std::move(itemNameFormat)) +{ +} +cmComputeLinkInformation::FeatureDescriptor::FeatureDescriptor( + std::string name, std::string prefix, std::string suffix, bool) + : Name(std::move(name)) + , Supported(true) + , Prefix(std::move(prefix)) + , Suffix(std::move(suffix)) +{ +} + +std::string cmComputeLinkInformation::FeatureDescriptor::GetDecoratedItem( + std::string const& library, ItemIsPath isPath) const +{ + auto format = + isPath == ItemIsPath::Yes ? this->ItemPathFormat : this->ItemNameFormat; + + // replace , and patterns with library path + FeaturePlaceHolderExpander expander(&library, &library, &library); + return expander.ExpandVariables(format); +} +std::string cmComputeLinkInformation::FeatureDescriptor::GetDecoratedItem( + std::string const& library, std::string const& libItem, + std::string const& linkItem, ItemIsPath isPath) const +{ + auto format = + isPath == ItemIsPath::Yes ? this->ItemPathFormat : this->ItemNameFormat; + + // replace , and patterns + FeaturePlaceHolderExpander expander(&library, &libItem, &linkItem); + return expander.ExpandVariables(format); +} + +cmComputeLinkInformation::LibraryFeatureDescriptor::LibraryFeatureDescriptor( + std::string name, std::string itemFormat) + : FeatureDescriptor(std::move(name), std::move(itemFormat)) +{ +} +cmComputeLinkInformation::LibraryFeatureDescriptor::LibraryFeatureDescriptor( + std::string name, std::string itemPathFormat, std::string itemNameFormat) + : FeatureDescriptor(std::move(name), std::move(itemPathFormat), + std::move(itemNameFormat)) +{ +} +cmComputeLinkInformation::LibraryFeatureDescriptor::LibraryFeatureDescriptor( + std::string name, std::string prefix, std::string itemPathFormat, + std::string itemNameFormat, std::string suffix) + : FeatureDescriptor(std::move(name), std::move(prefix), + std::move(itemPathFormat), std::move(itemNameFormat), + std::move(suffix)) +{ } bool cmComputeLinkInformation::AddLibraryFeature(std::string const& feature) @@ -792,12 +918,13 @@ bool cmComputeLinkInformation::AddLibraryFeature(std::string const& feature) if (items.size() == 2) { this->LibraryFeatureDescriptors.emplace( - feature, FeatureDescriptor{ feature, items[0].Value, items[1].Value }); + feature, + LibraryFeatureDescriptor{ feature, items[0].Value, items[1].Value }); } else { this->LibraryFeatureDescriptors.emplace( feature, - FeatureDescriptor{ feature, items[0].Value, items[1].Value, - items[2].Value, items[3].Value }); + LibraryFeatureDescriptor{ feature, items[0].Value, items[1].Value, + items[2].Value, items[3].Value }); } return true; @@ -819,89 +946,80 @@ cmComputeLinkInformation::FindLibraryFeature(std::string const& feature) const return &it->second; } -namespace { -class FeaturePlaceHolderExpander : public cmPlaceholderExpander +cmComputeLinkInformation::GroupFeatureDescriptor::GroupFeatureDescriptor( + std::string name, std::string prefix, std::string suffix) + : FeatureDescriptor(std::move(name), std::move(prefix), std::move(suffix), + true) { -public: - FeaturePlaceHolderExpander(const std::string* library, - const std::string* libItem = nullptr, - const std::string* linkItem = nullptr) - : Library(library) - , LibItem(libItem) - , LinkItem(linkItem) - { - } +} -private: - std::string ExpandVariable(std::string const& variable) override - { - if (this->Library != nullptr && variable == "LIBRARY") { - return *this->Library; - } - if (this->LibItem != nullptr && variable == "LIB_ITEM") { - return *this->LibItem; - } - if (this->LinkItem != nullptr && variable == "LINK_ITEM") { - return *this->LinkItem; - } +cmComputeLinkInformation::FeatureDescriptor const& +cmComputeLinkInformation::GetGroupFeature(std::string const& feature) +{ + auto it = this->GroupFeatureDescriptors.find(feature); + if (it != this->GroupFeatureDescriptors.end()) { + return it->second; + } - return variable; + auto featureName = + cmStrCat("CMAKE_", this->LinkLanguage, "_LINK_GROUP_USING_", feature); + cmValue featureSupported = + this->Makefile->GetDefinition(cmStrCat(featureName, "_SUPPORTED")); + if (!featureSupported.IsOn()) { + featureName = cmStrCat("CMAKE_LINK_GROUP_USING_", feature); + featureSupported = + this->Makefile->GetDefinition(cmStrCat(featureName, "_SUPPORTED")); + } + if (!featureSupported.IsOn()) { + this->CMakeInstance->IssueMessage( + MessageType::FATAL_ERROR, + cmStrCat("Feature '", feature, + "', specified through generator-expression '$' to " + "link target '", + this->Target->GetName(), "', is not supported for the '", + this->LinkLanguage, "' link language."), + this->Target->GetBacktrace()); + return this->GroupFeatureDescriptors.emplace(feature, FeatureDescriptor{}) + .first->second; } - const std::string* Library = nullptr; - const std::string* LibItem = nullptr; - const std::string* LinkItem = nullptr; -}; -} + cmValue langFeature = this->Makefile->GetDefinition(featureName); + if (!langFeature) { + this->CMakeInstance->IssueMessage( + MessageType::FATAL_ERROR, + cmStrCat("Feature '", feature, + "', specified through generator-expression '$' to " + "link target '", + this->Target->GetName(), "', is not defined for the '", + this->LinkLanguage, "' link language."), + this->Target->GetBacktrace()); + return this->GroupFeatureDescriptors.emplace(feature, FeatureDescriptor{}) + .first->second; + } -cmComputeLinkInformation::FeatureDescriptor::FeatureDescriptor( - std::string name, std::string itemFormat) - : Name(std::move(name)) - , Supported(true) - , ItemPathFormat(std::move(itemFormat)) - , ItemNameFormat(this->ItemPathFormat) -{ -} -cmComputeLinkInformation::FeatureDescriptor::FeatureDescriptor( - std::string name, std::string itemPathFormat, std::string itemNameFormat) - : Name(std::move(name)) - , Supported(true) - , ItemPathFormat(std::move(itemPathFormat)) - , ItemNameFormat(std::move(itemNameFormat)) -{ -} -cmComputeLinkInformation::FeatureDescriptor::FeatureDescriptor( - std::string name, std::string prefix, std::string itemPathFormat, - std::string itemNameFormat, std::string suffix) - : Name(std::move(name)) - , Supported(true) - , Prefix(std::move(prefix)) - , Suffix(std::move(suffix)) - , ItemPathFormat(std::move(itemPathFormat)) - , ItemNameFormat(std::move(itemNameFormat)) -{ -} + auto items = + cmExpandListWithBacktrace(langFeature, this->Target->GetBacktrace(), true); -std::string cmComputeLinkInformation::FeatureDescriptor::GetDecoratedItem( - std::string const& library, ItemIsPath isPath) const -{ - auto format = - isPath == ItemIsPath::Yes ? this->ItemPathFormat : this->ItemNameFormat; + // replace LINKER: pattern + this->Target->ResolveLinkerWrapper(items, this->LinkLanguage, true); - // replace , and patterns with library path - FeaturePlaceHolderExpander expander(&library, &library, &library); - return expander.ExpandVariables(format); -} -std::string cmComputeLinkInformation::FeatureDescriptor::GetDecoratedItem( - std::string const& library, std::string const& libItem, - std::string const& linkItem, ItemIsPath isPath) const -{ - auto format = - isPath == ItemIsPath::Yes ? this->ItemPathFormat : this->ItemNameFormat; + if (items.size() == 2) { + return this->GroupFeatureDescriptors + .emplace( + feature, + GroupFeatureDescriptor{ feature, items[0].Value, items[1].Value }) + .first->second; + } - // replace , and patterns - FeaturePlaceHolderExpander expander(&library, &libItem, &linkItem); - return expander.ExpandVariables(format); + this->CMakeInstance->IssueMessage( + MessageType::FATAL_ERROR, + cmStrCat("Feature '", feature, "', specified by variable '", featureName, + "', is malformed (wrong number of elements) and cannot be used " + "to link target '", + this->Target->GetName(), "'."), + this->Target->GetBacktrace()); + return this->GroupFeatureDescriptors.emplace(feature, FeatureDescriptor{}) + .first->second; } void cmComputeLinkInformation::AddImplicitLinkInfo() diff --git a/Source/cmComputeLinkInformation.h b/Source/cmComputeLinkInformation.h index 4b7fb1a..a4ada1f 100644 --- a/Source/cmComputeLinkInformation.h +++ b/Source/cmComputeLinkInformation.h @@ -255,12 +255,6 @@ private: { public: FeatureDescriptor() = default; - FeatureDescriptor(std::string name, std::string itemFormat); - FeatureDescriptor(std::string name, std::string itemPathFormat, - std::string itemNameFormat); - FeatureDescriptor(std::string name, std::string prefix, - std::string itemPathFormat, std::string itemNameFormat, - std::string suffix); const std::string Name; const bool Supported = false; @@ -273,13 +267,44 @@ private: std::string const& defaultValue, ItemIsPath isPath) const; + protected: + FeatureDescriptor(std::string name, std::string itemFormat); + FeatureDescriptor(std::string name, std::string itemPathFormat, + std::string itemNameFormat); + FeatureDescriptor(std::string name, std::string prefix, + std::string itemPathFormat, std::string itemNameFormat, + std::string suffix); + + FeatureDescriptor(std::string name, std::string prefix, std::string suffix, + bool isGroup); + private: std::string ItemPathFormat; std::string ItemNameFormat; }; + + class LibraryFeatureDescriptor : public FeatureDescriptor + { + public: + LibraryFeatureDescriptor(std::string name, std::string itemFormat); + LibraryFeatureDescriptor(std::string name, std::string itemPathFormat, + std::string itemNameFormat); + LibraryFeatureDescriptor(std::string name, std::string prefix, + std::string itemPathFormat, + std::string itemNameFormat, std::string suffix); + }; std::map LibraryFeatureDescriptors; bool AddLibraryFeature(std::string const& feature); FeatureDescriptor const& GetLibraryFeature(std::string const& feature) const; FeatureDescriptor const* FindLibraryFeature( std::string const& feature) const; + + class GroupFeatureDescriptor : public FeatureDescriptor + { + public: + GroupFeatureDescriptor(std::string name, std::string prefix, + std::string suffix); + }; + std::map GroupFeatureDescriptors; + FeatureDescriptor const& GetGroupFeature(std::string const& feature); }; diff --git a/Source/cmGeneratorExpressionNode.cxx b/Source/cmGeneratorExpressionNode.cxx index b63b90b..db043ec 100644 --- a/Source/cmGeneratorExpressionNode.cxx +++ b/Source/cmGeneratorExpressionNode.cxx @@ -1231,7 +1231,15 @@ static const struct LinkLibraryNode : public cmGeneratorExpressionNode return std::string(); } + static cmsys::RegularExpression featureNameValidator("^[A-Za-z0-9_]+$"); auto const& feature = list.front(); + if (!featureNameValidator.find(feature)) { + reportError(context, content->GetOriginalExpression(), + cmStrCat("The feature name '", feature, + "' contains invalid characters.")); + return std::string(); + } + const auto LL_BEGIN = cmStrCat("'); const auto LL_END = cmStrCat("'); @@ -1252,6 +1260,17 @@ static const struct LinkLibraryNode : public cmGeneratorExpressionNode "$ with different features cannot be nested."); return std::string(); } + // $ must not appear as part of $ + it = std::find_if(list.cbegin() + 1, list.cend(), + [](const std::string& item) -> bool { + return cmHasPrefix(item, "GetOriginalExpression(), + "$ cannot be nested inside a " + "$ expression."); + return std::string(); + } list.front() = LL_BEGIN; list.push_back(LL_END); @@ -1260,6 +1279,71 @@ static const struct LinkLibraryNode : public cmGeneratorExpressionNode } } linkLibraryNode; +static const struct LinkGroupNode : public cmGeneratorExpressionNode +{ + LinkGroupNode() {} // NOLINT(modernize-use-equals-default) + + int NumExpectedParameters() const override { return OneOrMoreParameters; } + + std::string Evaluate( + const std::vector& parameters, + cmGeneratorExpressionContext* context, + const GeneratorExpressionContent* content, + cmGeneratorExpressionDAGChecker* dagChecker) const override + { + if (!context->HeadTarget || !dagChecker || + !dagChecker->EvaluatingLinkLibraries()) { + reportError(context, content->GetOriginalExpression(), + "$ may only be used with binary targets " + "to specify group of link libraries."); + return std::string(); + } + + std::vector list; + cmExpandLists(parameters.begin(), parameters.end(), list); + if (list.empty()) { + reportError( + context, content->GetOriginalExpression(), + "$ expects a feature name as first argument."); + return std::string(); + } + // $ cannot be nested + if (std::find_if(list.cbegin(), list.cend(), + [](const std::string& item) -> bool { + return cmHasPrefix(item, "GetOriginalExpression(), + "$ cannot be nested."); + return std::string(); + } + if (list.size() == 1) { + // no libraries specified, ignore this genex + return std::string(); + } + + static cmsys::RegularExpression featureNameValidator("^[A-Za-z0-9_]+$"); + auto const& feature = list.front(); + if (!featureNameValidator.find(feature)) { + reportError(context, content->GetOriginalExpression(), + cmStrCat("The feature name '", feature, + "' contains invalid characters.")); + return std::string(); + } + + const auto LG_BEGIN = cmStrCat( + "(list.cbegin() + 1, list.cend()), + "|"_s), + '>'); + const auto LG_END = cmStrCat("'); + + list.front() = LG_BEGIN; + list.push_back(LG_END); + + return cmJoin(list, ";"_s); + } +} linkGroupNode; + static const struct HostLinkNode : public cmGeneratorExpressionNode { HostLinkNode() {} // NOLINT(modernize-use-equals-default) @@ -2731,6 +2815,7 @@ const cmGeneratorExpressionNode* cmGeneratorExpressionNode::GetNode( { "LINK_LANG_AND_ID", &linkLanguageAndIdNode }, { "LINK_LANGUAGE", &linkLanguageNode }, { "LINK_LIBRARY", &linkLibraryNode }, + { "LINK_GROUP", &linkGroupNode }, { "HOST_LINK", &hostLinkNode }, { "DEVICE_LINK", &deviceLinkNode }, { "SHELL_PATH", &shellPathNode } diff --git a/Source/cmGeneratorTarget.cxx b/Source/cmGeneratorTarget.cxx index a246c12..e893b44 100644 --- a/Source/cmGeneratorTarget.cxx +++ b/Source/cmGeneratorTarget.cxx @@ -6341,7 +6341,8 @@ cm::string_view missingTargetPossibleReasons = bool cmGeneratorTarget::VerifyLinkItemColons(LinkItemRole role, cmLinkItem const& item) const { - if (item.Target || item.AsStr().find("::") == std::string::npos) { + if (item.Target || cmHasPrefix(item.AsStr(), "GetProperty(prop)) { // Look for internal pattern - static cmsys::RegularExpression linkLibrary( - "(^|;)(]*>)(;|$)"); - if (!linkLibrary.find(value)) { + static cmsys::RegularExpression linkPattern( + "(^|;)(]*>)(;|$)"); + if (!linkPattern.find(value)) { return; } // Report an error. this->IssueMessage( MessageType::FATAL_ERROR, - cmStrCat( - "Property ", prop, " contains the invalid item \"", - linkLibrary.match(2), "\". The ", prop, - " property may contain the generator-expression " - "\"$\" " - "which may be used to specify how the libraries are linked.")); + cmStrCat("Property ", prop, " contains the invalid item \"", + linkPattern.match(2), "\". The ", prop, + " property may contain the generator-expression \"$\" which may be used to specify how the libraries are " + "linked.")); } } } diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx index 92a0ac4..4ca1b9b 100644 --- a/Source/cmTarget.cxx +++ b/Source/cmTarget.cxx @@ -1788,20 +1788,21 @@ void CheckLinkLibraryPattern(const std::string& property, const std::string& value, cmMakefile* context) { // Look for and internal tags - static cmsys::RegularExpression linkLibrary( - "(^|;)(]*>)(;|$)"); - if (!linkLibrary.find(value)) { + static cmsys::RegularExpression linkPattern( + "(^|;)(]*>)(;|$)"); + if (!linkPattern.find(value)) { return; } // Report an error. context->IssueMessage( MessageType::FATAL_ERROR, - cmStrCat("Property ", property, " contains the invalid item \"", - linkLibrary.match(2), "\". The ", property, - " property may contain the generator-expression " - "\"$\" " - "which may be used to specify how the libraries are linked.")); + cmStrCat( + "Property ", property, " contains the invalid item \"", + linkPattern.match(2), "\". The ", property, + " property may contain the generator-expression \"$\" which may be used to specify how the libraries are linked.")); } void CheckLINK_INTERFACE_LIBRARIES(const std::string& prop, diff --git a/Tests/RunCMake/CMakeLists.txt b/Tests/RunCMake/CMakeLists.txt index eda857b..82bc8c3 100644 --- a/Tests/RunCMake/CMakeLists.txt +++ b/Tests/RunCMake/CMakeLists.txt @@ -314,6 +314,7 @@ add_RunCMake_test(GenEx-LINK_LANG_AND_ID) add_RunCMake_test(GenEx-HOST_LINK) add_RunCMake_test(GenEx-DEVICE_LINK) add_RunCMake_test(GenEx-LINK_LIBRARY) +add_RunCMake_test(GenEx-LINK_GROUP) add_RunCMake_test(GenEx-TARGET_FILE -DLINKER_SUPPORTS_PDB=${LINKER_SUPPORTS_PDB}) add_RunCMake_test(GenEx-GENEX_EVAL) add_RunCMake_test(GenEx-TARGET_RUNTIME_DLLS) @@ -670,6 +671,18 @@ add_RunCMake_test(target_link_libraries-LINK_LIBRARY -DCMAKE_SYSTEM_NAME=${CMAKE -DCMAKE_IMPORT_LIBRARY_PREFIX=${CMAKE_IMPORT_LIBRARY_PREFIX} -DCMAKE_IMPORT_LIBRARY_SUFFIX=${CMAKE_IMPORT_LIBRARY_SUFFIX} -DCMAKE_LINK_LIBRARY_FLAG=${CMAKE_LINK_LIBRARY_FLAG}) +add_RunCMake_test(target_link_libraries-LINK_GROUP -DCMAKE_SYSTEM_NAME=${CMAKE_SYSTEM_NAME} + -DMINGW=${MINGW} + -DMSYS=${MSYS} + -DCYGWIN=${CYGWIN} + -DCMAKE_C_COMPILER_ID=${CMAKE_C_COMPILER_ID} + -DCMAKE_C_COMPILER_VERSION=${CMAKE_C_COMPILER_VERSION} + -DMSVC_VERSION=${MSVC_VERSION} + -DCMAKE_SHARED_LIBRARY_PREFIX=${CMAKE_SHARED_LIBRARY_PREFIX} + -DCMAKE_SHARED_LIBRARY_SUFFIX=${CMAKE_SHARED_LIBRARY_SUFFIX} + -DCMAKE_IMPORT_LIBRARY_PREFIX=${CMAKE_IMPORT_LIBRARY_PREFIX} + -DCMAKE_IMPORT_LIBRARY_SUFFIX=${CMAKE_IMPORT_LIBRARY_SUFFIX} + -DCMAKE_LINK_LIBRARY_FLAG=${CMAKE_LINK_LIBRARY_FLAG}) add_RunCMake_test(add_link_options -DCMAKE_C_COMPILER_ID=${CMAKE_C_COMPILER_ID}) add_RunCMake_test(target_link_options -DCMAKE_C_COMPILER_ID=${CMAKE_C_COMPILER_ID} -DCMake_TEST_CUDA=${CMake_TEST_CUDA}) diff --git a/Tests/RunCMake/GenEx-LINK_GROUP/CMakeLists.txt b/Tests/RunCMake/GenEx-LINK_GROUP/CMakeLists.txt new file mode 100644 index 0000000..612169c --- /dev/null +++ b/Tests/RunCMake/GenEx-LINK_GROUP/CMakeLists.txt @@ -0,0 +1,3 @@ +cmake_minimum_required(VERSION 3.18...3.22) +project(${RunCMake_TEST} NONE) +include(${RunCMake_TEST}.cmake) diff --git a/Tests/RunCMake/GenEx-LINK_GROUP/RunCMakeTest.cmake b/Tests/RunCMake/GenEx-LINK_GROUP/RunCMakeTest.cmake new file mode 100644 index 0000000..98eef35 --- /dev/null +++ b/Tests/RunCMake/GenEx-LINK_GROUP/RunCMakeTest.cmake @@ -0,0 +1,35 @@ +include(RunCMake) + +run_cmake(add_custom_target) +run_cmake(add_custom_command) +run_cmake(add_link_options) +run_cmake(link_directories) +run_cmake(target_link_options) +run_cmake(target_link_directories) +run_cmake(no-arguments) +run_cmake(empty-arguments) +run_cmake(forbidden-arguments) +run_cmake(nested-incompatible-genex) +run_cmake(invalid-feature) +run_cmake(bad-feature1) +run_cmake(bad-feature2) +run_cmake(bad-feature3) +run_cmake(bad-feature4) +run_cmake(bad-feature5) +run_cmake(feature-not-supported) +run_cmake(library-ignored) +run_cmake(compatible-features1) +run_cmake(compatible-features2) +run_cmake(compatible-features3) +run_cmake(incompatible-features1) +run_cmake(nested-incompatible-features1) +run_cmake(nested-incompatible-features2) +run_cmake(circular-dependencies1) +run_cmake(circular-dependencies2) +run_cmake(only-targets) + +# usage of LINK_LIBRARY with LINK_GROUP +run_cmake(incompatible-library-features1) +run_cmake(incompatible-library-features2) +run_cmake(override-library-features1) +run_cmake(override-library-features2) diff --git a/Tests/RunCMake/GenEx-LINK_GROUP/add_custom_command-result.txt b/Tests/RunCMake/GenEx-LINK_GROUP/add_custom_command-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/GenEx-LINK_GROUP/add_custom_command-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/GenEx-LINK_GROUP/add_custom_command-stderr.txt b/Tests/RunCMake/GenEx-LINK_GROUP/add_custom_command-stderr.txt new file mode 100644 index 0000000..a80a11b --- /dev/null +++ b/Tests/RunCMake/GenEx-LINK_GROUP/add_custom_command-stderr.txt @@ -0,0 +1,9 @@ +CMake Error at add_custom_command.cmake:[0-9]+ \(add_custom_command\): + Error evaluating generator expression: + + \$ + + \$ may only be used with binary targets to specify group of + link libraries. +Call Stack \(most recent call first\): + CMakeLists.txt:[0-9]+ \(include\) diff --git a/Tests/RunCMake/GenEx-LINK_GROUP/add_custom_command.cmake b/Tests/RunCMake/GenEx-LINK_GROUP/add_custom_command.cmake new file mode 100644 index 0000000..1efe276 --- /dev/null +++ b/Tests/RunCMake/GenEx-LINK_GROUP/add_custom_command.cmake @@ -0,0 +1,4 @@ +add_custom_target(drive) +add_custom_command(TARGET drive PRE_BUILD + COMMAND ${CMAKE_COMMAND} -E echo "$" +) diff --git a/Tests/RunCMake/GenEx-LINK_GROUP/add_custom_target-result.txt b/Tests/RunCMake/GenEx-LINK_GROUP/add_custom_target-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/GenEx-LINK_GROUP/add_custom_target-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/GenEx-LINK_GROUP/add_custom_target-stderr.txt b/Tests/RunCMake/GenEx-LINK_GROUP/add_custom_target-stderr.txt new file mode 100644 index 0000000..deb246a --- /dev/null +++ b/Tests/RunCMake/GenEx-LINK_GROUP/add_custom_target-stderr.txt @@ -0,0 +1,9 @@ +CMake Error at add_custom_target.cmake:[0-9]+ \(add_custom_target\): + Error evaluating generator expression: + + \$ + + \$ may only be used with binary targets to specify group of + link libraries. +Call Stack \(most recent call first\): + CMakeLists.txt:[0-9]+ \(include\) diff --git a/Tests/RunCMake/GenEx-LINK_GROUP/add_custom_target.cmake b/Tests/RunCMake/GenEx-LINK_GROUP/add_custom_target.cmake new file mode 100644 index 0000000..cbb5ff0 --- /dev/null +++ b/Tests/RunCMake/GenEx-LINK_GROUP/add_custom_target.cmake @@ -0,0 +1,3 @@ +add_custom_target(drive + COMMAND ${CMAKE_COMMAND} -E echo "$" +) diff --git a/Tests/RunCMake/GenEx-LINK_GROUP/add_link_options-result.txt b/Tests/RunCMake/GenEx-LINK_GROUP/add_link_options-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/GenEx-LINK_GROUP/add_link_options-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/GenEx-LINK_GROUP/add_link_options-stderr.txt b/Tests/RunCMake/GenEx-LINK_GROUP/add_link_options-stderr.txt new file mode 100644 index 0000000..17c348c --- /dev/null +++ b/Tests/RunCMake/GenEx-LINK_GROUP/add_link_options-stderr.txt @@ -0,0 +1,9 @@ +CMake Error at add_link_options.cmake:[0-9]+ \(add_link_options\): + Error evaluating generator expression: + + \$ + + \$ may only be used with binary targets to specify group of + link libraries. +Call Stack \(most recent call first\): + CMakeLists.txt:[0-9]+ \(include\) diff --git a/Tests/RunCMake/GenEx-LINK_GROUP/add_link_options.cmake b/Tests/RunCMake/GenEx-LINK_GROUP/add_link_options.cmake new file mode 100644 index 0000000..2e31b34 --- /dev/null +++ b/Tests/RunCMake/GenEx-LINK_GROUP/add_link_options.cmake @@ -0,0 +1,5 @@ +enable_language(C) + +add_link_options("$") + +add_library(empty SHARED empty.c) diff --git a/Tests/RunCMake/GenEx-LINK_GROUP/bad-feature1-result.txt b/Tests/RunCMake/GenEx-LINK_GROUP/bad-feature1-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/GenEx-LINK_GROUP/bad-feature1-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/GenEx-LINK_GROUP/bad-feature1-stderr.txt b/Tests/RunCMake/GenEx-LINK_GROUP/bad-feature1-stderr.txt new file mode 100644 index 0000000..8c95452 --- /dev/null +++ b/Tests/RunCMake/GenEx-LINK_GROUP/bad-feature1-stderr.txt @@ -0,0 +1,5 @@ +CMake Error at bad-feature1.cmake:[0-9]+ \(add_library\): + Feature 'bad_feat', specified through generator-expression '\$' + to link target 'lib', is not supported for the 'C' link language. +Call Stack \(most recent call first\): + CMakeLists.txt:[0-9]+ \(include\) diff --git a/Tests/RunCMake/GenEx-LINK_GROUP/bad-feature1.cmake b/Tests/RunCMake/GenEx-LINK_GROUP/bad-feature1.cmake new file mode 100644 index 0000000..0161221 --- /dev/null +++ b/Tests/RunCMake/GenEx-LINK_GROUP/bad-feature1.cmake @@ -0,0 +1,6 @@ +enable_language(C) + +add_library(dep SHARED empty.c) + +add_library(lib SHARED empty.c) +target_link_libraries(lib PRIVATE "$") diff --git a/Tests/RunCMake/GenEx-LINK_GROUP/bad-feature2-result.txt b/Tests/RunCMake/GenEx-LINK_GROUP/bad-feature2-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/GenEx-LINK_GROUP/bad-feature2-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/GenEx-LINK_GROUP/bad-feature2-stderr.txt b/Tests/RunCMake/GenEx-LINK_GROUP/bad-feature2-stderr.txt new file mode 100644 index 0000000..3f057c4 --- /dev/null +++ b/Tests/RunCMake/GenEx-LINK_GROUP/bad-feature2-stderr.txt @@ -0,0 +1,5 @@ +CMake Error at bad-feature2.cmake:[0-9]+ \(add_library\): + Feature 'feat', specified through generator-expression '\$' to + link target 'lib', is not defined for the 'C' link language. +Call Stack \(most recent call first\): + CMakeLists.txt:[0-9]+ \(include\) diff --git a/Tests/RunCMake/GenEx-LINK_GROUP/bad-feature2.cmake b/Tests/RunCMake/GenEx-LINK_GROUP/bad-feature2.cmake new file mode 100644 index 0000000..7e56194 --- /dev/null +++ b/Tests/RunCMake/GenEx-LINK_GROUP/bad-feature2.cmake @@ -0,0 +1,8 @@ +enable_language(C) + +set(CMAKE_C_LINK_GROUP_USING_feat_SUPPORTED TRUE) + +add_library(dep SHARED empty.c) + +add_library(lib SHARED empty.c) +target_link_libraries(lib PRIVATE "$") diff --git a/Tests/RunCMake/GenEx-LINK_GROUP/bad-feature3-result.txt b/Tests/RunCMake/GenEx-LINK_GROUP/bad-feature3-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/GenEx-LINK_GROUP/bad-feature3-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/GenEx-LINK_GROUP/bad-feature3-stderr.txt b/Tests/RunCMake/GenEx-LINK_GROUP/bad-feature3-stderr.txt new file mode 100644 index 0000000..43e2700 --- /dev/null +++ b/Tests/RunCMake/GenEx-LINK_GROUP/bad-feature3-stderr.txt @@ -0,0 +1,6 @@ +CMake Error at bad-feature3.cmake:[0-9]+ \(add_library\): + Feature 'feat', specified by variable 'CMAKE_C_LINK_GROUP_USING_feat', is + malformed \(wrong number of elements\) and cannot be used to link target + 'lib'. +Call Stack \(most recent call first\): + CMakeLists.txt:[0-9]+ \(include\) diff --git a/Tests/RunCMake/GenEx-LINK_GROUP/bad-feature3.cmake b/Tests/RunCMake/GenEx-LINK_GROUP/bad-feature3.cmake new file mode 100644 index 0000000..58b422a --- /dev/null +++ b/Tests/RunCMake/GenEx-LINK_GROUP/bad-feature3.cmake @@ -0,0 +1,9 @@ +enable_language(C) + +set(CMAKE_C_LINK_GROUP_USING_feat_SUPPORTED TRUE) +set(CMAKE_C_LINK_GROUP_USING_feat "") + +add_library(dep SHARED empty.c) + +add_library(lib SHARED empty.c) +target_link_libraries(lib PRIVATE "$") diff --git a/Tests/RunCMake/GenEx-LINK_GROUP/bad-feature4-result.txt b/Tests/RunCMake/GenEx-LINK_GROUP/bad-feature4-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/GenEx-LINK_GROUP/bad-feature4-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/GenEx-LINK_GROUP/bad-feature4-stderr.txt b/Tests/RunCMake/GenEx-LINK_GROUP/bad-feature4-stderr.txt new file mode 100644 index 0000000..0a2ba60 --- /dev/null +++ b/Tests/RunCMake/GenEx-LINK_GROUP/bad-feature4-stderr.txt @@ -0,0 +1,6 @@ +CMake Error at bad-feature4.cmake:[0-9]+ \(add_library\): + Feature 'feat', specified by variable 'CMAKE_C_LINK_GROUP_USING_feat', is + malformed \(wrong number of elements\) and cannot be used to link target + 'lib'. +Call Stack \(most recent call first\): + CMakeLists.txt:[0-9]+ \(include\) diff --git a/Tests/RunCMake/GenEx-LINK_GROUP/bad-feature4.cmake b/Tests/RunCMake/GenEx-LINK_GROUP/bad-feature4.cmake new file mode 100644 index 0000000..dcb8236 --- /dev/null +++ b/Tests/RunCMake/GenEx-LINK_GROUP/bad-feature4.cmake @@ -0,0 +1,9 @@ +enable_language(C) + +set(CMAKE_C_LINK_GROUP_USING_feat_SUPPORTED TRUE) +set(CMAKE_C_LINK_GROUP_USING_feat "-opt") + +add_library(dep SHARED empty.c) + +add_library(lib SHARED empty.c) +target_link_libraries(lib PRIVATE "$") diff --git a/Tests/RunCMake/GenEx-LINK_GROUP/bad-feature5-result.txt b/Tests/RunCMake/GenEx-LINK_GROUP/bad-feature5-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/GenEx-LINK_GROUP/bad-feature5-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/GenEx-LINK_GROUP/bad-feature5-stderr.txt b/Tests/RunCMake/GenEx-LINK_GROUP/bad-feature5-stderr.txt new file mode 100644 index 0000000..4b1f01d --- /dev/null +++ b/Tests/RunCMake/GenEx-LINK_GROUP/bad-feature5-stderr.txt @@ -0,0 +1,6 @@ +CMake Error at bad-feature5.cmake:[0-9]+ \(add_library\): + Feature 'feat', specified by variable 'CMAKE_C_LINK_GROUP_USING_feat', is + malformed \(wrong number of elements\) and cannot be used to link target + 'lib'. +Call Stack \(most recent call first\): + CMakeLists.txt:[0-9]+ \(include\) diff --git a/Tests/RunCMake/GenEx-LINK_GROUP/bad-feature5.cmake b/Tests/RunCMake/GenEx-LINK_GROUP/bad-feature5.cmake new file mode 100644 index 0000000..cb10996 --- /dev/null +++ b/Tests/RunCMake/GenEx-LINK_GROUP/bad-feature5.cmake @@ -0,0 +1,9 @@ +enable_language(C) + +set(CMAKE_C_LINK_GROUP_USING_feat_SUPPORTED TRUE) +set(CMAKE_C_LINK_GROUP_USING_feat "-start" "" "-stop") + +add_library(dep SHARED empty.c) + +add_library(lib SHARED empty.c) +target_link_libraries(lib PRIVATE "$") diff --git a/Tests/RunCMake/GenEx-LINK_GROUP/circular-dependencies1-result.txt b/Tests/RunCMake/GenEx-LINK_GROUP/circular-dependencies1-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/GenEx-LINK_GROUP/circular-dependencies1-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/GenEx-LINK_GROUP/circular-dependencies1-stderr.txt b/Tests/RunCMake/GenEx-LINK_GROUP/circular-dependencies1-stderr.txt new file mode 100644 index 0000000..94008e1 --- /dev/null +++ b/Tests/RunCMake/GenEx-LINK_GROUP/circular-dependencies1-stderr.txt @@ -0,0 +1,11 @@ +CMake Error at circular-dependencies1.cmake:[0-9]+ \(add_library\): + The inter-target dependency graph, for the target "lib1", contains the + following strongly connected component \(cycle\): + + group "feat:{dep1.1,dep1.2}" + depends on group "feat:{dep2.1,dep2.2}" + group "feat:{dep2.1,dep2.2}" + depends on group "feat:{dep1.1,dep1.2}" + +Call Stack \(most recent call first\): + CMakeLists.txt:[0-9]+ \(include\) diff --git a/Tests/RunCMake/GenEx-LINK_GROUP/circular-dependencies1.cmake b/Tests/RunCMake/GenEx-LINK_GROUP/circular-dependencies1.cmake new file mode 100644 index 0000000..a1d7575 --- /dev/null +++ b/Tests/RunCMake/GenEx-LINK_GROUP/circular-dependencies1.cmake @@ -0,0 +1,17 @@ +enable_language(C) + +set(CMAKE_C_LINK_GROUP_USING_feat_SUPPORTED TRUE) +set(CMAKE_C_LINK_GROUP_USING_feat "--start" "--stop") + +add_library(dep1.1 SHARED empty.c) +add_library(dep1.2 SHARED empty.c) + +add_library(dep2.1 SHARED empty.c) +add_library(dep2.2 SHARED empty.c) + +target_link_libraries(dep1.1 PUBLIC dep2.1) +target_link_libraries(dep2.2 PUBLIC dep1.2) + +add_library(lib1 SHARED empty.c) +target_link_libraries(lib1 PRIVATE "$" + "$") diff --git a/Tests/RunCMake/GenEx-LINK_GROUP/circular-dependencies2-result.txt b/Tests/RunCMake/GenEx-LINK_GROUP/circular-dependencies2-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/GenEx-LINK_GROUP/circular-dependencies2-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/GenEx-LINK_GROUP/circular-dependencies2-stderr.txt b/Tests/RunCMake/GenEx-LINK_GROUP/circular-dependencies2-stderr.txt new file mode 100644 index 0000000..365e98f --- /dev/null +++ b/Tests/RunCMake/GenEx-LINK_GROUP/circular-dependencies2-stderr.txt @@ -0,0 +1,11 @@ +CMake Error at circular-dependencies2.cmake:[0-9]+ \(add_library\): + The inter-target dependency graph, for the target "lib2", contains the + following strongly connected component \(cycle\): + + group "feat:{base3,base4}" + depends on group "feat:{base1,base2}" + group "feat:{base1,base2}" + depends on group "feat:{base3,base4}" + +Call Stack \(most recent call first\): + CMakeLists.txt:[0-9]+ \(include\) diff --git a/Tests/RunCMake/GenEx-LINK_GROUP/circular-dependencies2.cmake b/Tests/RunCMake/GenEx-LINK_GROUP/circular-dependencies2.cmake new file mode 100644 index 0000000..99fda4d --- /dev/null +++ b/Tests/RunCMake/GenEx-LINK_GROUP/circular-dependencies2.cmake @@ -0,0 +1,18 @@ +enable_language(C) + +set(CMAKE_C_LINK_GROUP_USING_feat_SUPPORTED TRUE) +set(CMAKE_C_LINK_GROUP_USING_feat "--start" "--stop") + +add_library(base1 SHARED empty.c) +add_library(base2 SHARED empty.c) +add_library(base3 SHARED empty.c) +add_library(base4 SHARED empty.c) + +target_link_libraries(base1 PUBLIC base3) +target_link_libraries(base4 PUBLIC base2) + +add_library(lib1 SHARED empty.c) +target_link_libraries(lib1 PUBLIC "$") + +add_library(lib2 SHARED empty.c) +target_link_libraries(lib2 PRIVATE "$" lib1) diff --git a/Tests/RunCMake/GenEx-LINK_GROUP/compatible-features1.cmake b/Tests/RunCMake/GenEx-LINK_GROUP/compatible-features1.cmake new file mode 100644 index 0000000..9d10f95 --- /dev/null +++ b/Tests/RunCMake/GenEx-LINK_GROUP/compatible-features1.cmake @@ -0,0 +1,18 @@ +enable_language(C) + +set(CMAKE_C_LINK_GROUP_USING_feat1_SUPPORTED TRUE) +set(CMAKE_C_LINK_GROUP_USING_feat1 "--start" "--stop") + +set(CMAKE_C_LINK_GROUP_USING_feat2_SUPPORTED TRUE) +set(CMAKE_C_LINK_GROUP_USING_feat2 "--start" "--stop") + +add_library(dep1 SHARED empty.c) + +add_library(dep2 SHARED empty.c) +target_link_libraries(dep2 PRIVATE "$") + +add_library(dep3 SHARED empty.c) +target_link_libraries(dep3 PUBLIC dep2) + +add_library(lib1 SHARED empty.c) +target_link_libraries(lib1 PRIVATE $) diff --git a/Tests/RunCMake/GenEx-LINK_GROUP/compatible-features2.cmake b/Tests/RunCMake/GenEx-LINK_GROUP/compatible-features2.cmake new file mode 100644 index 0000000..1fe2880 --- /dev/null +++ b/Tests/RunCMake/GenEx-LINK_GROUP/compatible-features2.cmake @@ -0,0 +1,13 @@ +enable_language(C) + +set(CMAKE_C_LINK_GROUP_USING_feat_SUPPORTED TRUE) +set(CMAKE_C_LINK_GROUP_USING_feat "--start" "--stop") + +add_library(dep1 SHARED empty.c) +add_library(dep2 SHARED empty.c) + +add_library(lib1 SHARED empty.c) +target_link_libraries(lib1 PUBLIC "$") + +add_library(lib2 SHARED empty.c) +target_link_libraries(lib2 PRIVATE "$") diff --git a/Tests/RunCMake/GenEx-LINK_GROUP/compatible-features3.cmake b/Tests/RunCMake/GenEx-LINK_GROUP/compatible-features3.cmake new file mode 100644 index 0000000..ac486ce --- /dev/null +++ b/Tests/RunCMake/GenEx-LINK_GROUP/compatible-features3.cmake @@ -0,0 +1,13 @@ +enable_language(C) + +set(CMAKE_C_LINK_GROUP_USING_feat_SUPPORTED TRUE) +set(CMAKE_C_LINK_GROUP_USING_feat "--start" "--stop") + +add_library(dep1 SHARED empty.c) +add_library(dep2 SHARED empty.c) +target_link_libraries(dep2 PUBLIC dep1) +add_library(dep3 SHARED empty.c) +target_link_libraries(dep3 PUBLIC dep1) + +add_library(lib1 SHARED empty.c) +target_link_libraries(lib1 PUBLIC "$" dep3) diff --git a/Tests/RunCMake/GenEx-LINK_GROUP/empty-arguments-result.txt b/Tests/RunCMake/GenEx-LINK_GROUP/empty-arguments-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/GenEx-LINK_GROUP/empty-arguments-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/GenEx-LINK_GROUP/empty-arguments-stderr.txt b/Tests/RunCMake/GenEx-LINK_GROUP/empty-arguments-stderr.txt new file mode 100644 index 0000000..27101cb --- /dev/null +++ b/Tests/RunCMake/GenEx-LINK_GROUP/empty-arguments-stderr.txt @@ -0,0 +1,8 @@ +CMake Error at empty-arguments.cmake:[0-9]+ \(target_link_libraries\): + Error evaluating generator expression: + + \$ + + \$ expects a feature name as first argument. +Call Stack \(most recent call first\): + CMakeLists.txt:[0-9]+ \(include\) diff --git a/Tests/RunCMake/GenEx-LINK_GROUP/empty-arguments.cmake b/Tests/RunCMake/GenEx-LINK_GROUP/empty-arguments.cmake new file mode 100644 index 0000000..6093935 --- /dev/null +++ b/Tests/RunCMake/GenEx-LINK_GROUP/empty-arguments.cmake @@ -0,0 +1,4 @@ +enable_language(C) + +add_library(lib SHARED empty.c) +target_link_libraries(lib PRIVATE "$") diff --git a/Tests/RunCMake/GenEx-LINK_GROUP/empty.c b/Tests/RunCMake/GenEx-LINK_GROUP/empty.c new file mode 100644 index 0000000..e69de29 diff --git a/Tests/RunCMake/GenEx-LINK_GROUP/feature-not-supported-result.txt b/Tests/RunCMake/GenEx-LINK_GROUP/feature-not-supported-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/GenEx-LINK_GROUP/feature-not-supported-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/GenEx-LINK_GROUP/feature-not-supported-stderr.txt b/Tests/RunCMake/GenEx-LINK_GROUP/feature-not-supported-stderr.txt new file mode 100644 index 0000000..3507f4d --- /dev/null +++ b/Tests/RunCMake/GenEx-LINK_GROUP/feature-not-supported-stderr.txt @@ -0,0 +1,5 @@ +CMake Error at feature-not-supported.cmake:[0-9]+ \(add_library\): + Feature 'feat', specified through generator-expression '\$' to + link target 'lib', is not supported for the 'C' link language. +Call Stack \(most recent call first\): + CMakeLists.txt:[0-9]+ \(include\) diff --git a/Tests/RunCMake/GenEx-LINK_GROUP/feature-not-supported.cmake b/Tests/RunCMake/GenEx-LINK_GROUP/feature-not-supported.cmake new file mode 100644 index 0000000..c4739bb --- /dev/null +++ b/Tests/RunCMake/GenEx-LINK_GROUP/feature-not-supported.cmake @@ -0,0 +1,9 @@ +enable_language(C) + +set(CMAKE_C_LINK_GROUP_USING_feat_SUPPORTED FALSE) +set(CMAKE_C_LINK_GROUP_USING_feat "--start" "--end") + +add_library(dep SHARED empty.c) + +add_library(lib SHARED empty.c) +target_link_libraries(lib PRIVATE "$") diff --git a/Tests/RunCMake/GenEx-LINK_GROUP/forbidden-arguments-result.txt b/Tests/RunCMake/GenEx-LINK_GROUP/forbidden-arguments-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/GenEx-LINK_GROUP/forbidden-arguments-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/GenEx-LINK_GROUP/forbidden-arguments-stderr.txt b/Tests/RunCMake/GenEx-LINK_GROUP/forbidden-arguments-stderr.txt new file mode 100644 index 0000000..bae6505 --- /dev/null +++ b/Tests/RunCMake/GenEx-LINK_GROUP/forbidden-arguments-stderr.txt @@ -0,0 +1,16 @@ +CMake Error at forbidden-arguments.cmake:[0-9]+ \(link_libraries\): + Property LINK_LIBRARIES contains the invalid item "". The + LINK_LIBRARIES property may contain the generator-expression + "\$" which may be used to specify how the libraries are + linked. +Call Stack \(most recent call first\): + CMakeLists.txt:[0-9]+ \(include\) + + +CMake Error at forbidden-arguments.cmake:[0-9]+ \(target_link_libraries\): + Property LINK_LIBRARIES contains the invalid item "". The + LINK_LIBRARIES property may contain the generator-expression + "\$" which may be used to specify how the libraries are + linked. +Call Stack \(most recent call first\): + CMakeLists.txt:[0-9]+ \(include\) diff --git a/Tests/RunCMake/GenEx-LINK_GROUP/forbidden-arguments.cmake b/Tests/RunCMake/GenEx-LINK_GROUP/forbidden-arguments.cmake new file mode 100644 index 0000000..dcbf8dd --- /dev/null +++ b/Tests/RunCMake/GenEx-LINK_GROUP/forbidden-arguments.cmake @@ -0,0 +1,6 @@ +enable_language(C) + +link_libraries( foo ) + +add_library(lib SHARED empty.c) +target_link_libraries(lib PRIVATE foo ) diff --git a/Tests/RunCMake/GenEx-LINK_GROUP/incompatible-features1-result.txt b/Tests/RunCMake/GenEx-LINK_GROUP/incompatible-features1-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/GenEx-LINK_GROUP/incompatible-features1-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/GenEx-LINK_GROUP/incompatible-features1-stderr.txt b/Tests/RunCMake/GenEx-LINK_GROUP/incompatible-features1-stderr.txt new file mode 100644 index 0000000..932245d --- /dev/null +++ b/Tests/RunCMake/GenEx-LINK_GROUP/incompatible-features1-stderr.txt @@ -0,0 +1,6 @@ +CMake Error at incompatible-features1.cmake:[0-9]+ \(add_library\): + Impossible to link target 'lib1' because the link item 'dep2', specified + with the group feature 'feat1', has already occurred with the feature + 'feat2', which is not allowed. +Call Stack \(most recent call first\): + CMakeLists.txt:[0-9]+ \(include\) diff --git a/Tests/RunCMake/GenEx-LINK_GROUP/incompatible-features1.cmake b/Tests/RunCMake/GenEx-LINK_GROUP/incompatible-features1.cmake new file mode 100644 index 0000000..efac0f8 --- /dev/null +++ b/Tests/RunCMake/GenEx-LINK_GROUP/incompatible-features1.cmake @@ -0,0 +1,15 @@ +enable_language(C) + +set(CMAKE_C_LINK_GROUP_USING_feat1_SUPPORTED TRUE) +set(CMAKE_C_LINK_GROUP_USING_feat1 "--start" "--stop") + +set(CMAKE_C_LINK_GROUP_USING_feat2_SUPPORTED TRUE) +set(CMAKE_C_LINK_GROUP_USING_feat2 "--start" "--stop") + +add_library(dep1 SHARED empty.c) +add_library(dep2 SHARED empty.c) +add_library(dep3 SHARED empty.c) +target_link_libraries(dep3 PUBLIC "$") + +add_library(lib1 SHARED empty.c) +target_link_libraries(lib1 PRIVATE "$") diff --git a/Tests/RunCMake/GenEx-LINK_GROUP/incompatible-library-features1-result.txt b/Tests/RunCMake/GenEx-LINK_GROUP/incompatible-library-features1-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/GenEx-LINK_GROUP/incompatible-library-features1-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/GenEx-LINK_GROUP/incompatible-library-features1-stderr.txt b/Tests/RunCMake/GenEx-LINK_GROUP/incompatible-library-features1-stderr.txt new file mode 100644 index 0000000..e3a4250 --- /dev/null +++ b/Tests/RunCMake/GenEx-LINK_GROUP/incompatible-library-features1-stderr.txt @@ -0,0 +1,6 @@ +CMake Error at incompatible-library-features1.cmake:[0-9]+ \(add_library\): + Impossible to link target 'lib1' because the link item 'dep1', specified + with the feature 'feat1', has already occurred without any feature or + 'DEFAULT' feature, which is not allowed. +Call Stack \(most recent call first\): + CMakeLists.txt:[0-9]+ \(include\) diff --git a/Tests/RunCMake/GenEx-LINK_GROUP/incompatible-library-features1.cmake b/Tests/RunCMake/GenEx-LINK_GROUP/incompatible-library-features1.cmake new file mode 100644 index 0000000..203f071 --- /dev/null +++ b/Tests/RunCMake/GenEx-LINK_GROUP/incompatible-library-features1.cmake @@ -0,0 +1,17 @@ +enable_language(C) + +set(CMAKE_C_LINK_GROUP_USING_feat1_SUPPORTED TRUE) +set(CMAKE_C_LINK_GROUP_USING_feat1 "--start" "--stop") + +set(CMAKE_C_LINK_LIBRARY_USING_feat1_SUPPORTED TRUE) +set(CMAKE_C_LINK_LIBRARY_USING_feat1 "--libflag1") + +set(CMAKE_C_LINK_LIBRARY_USING_feat2_SUPPORTED TRUE) +set(CMAKE_C_LINK_LIBRARY_USING_feat2 "--libflag2") + +add_library(dep1 SHARED empty.c) +add_library(dep2 SHARED empty.c) +target_link_libraries(dep2 PUBLIC "$") + +add_library(lib1 SHARED empty.c) +target_link_libraries(lib1 PRIVATE "$,dep1>") diff --git a/Tests/RunCMake/GenEx-LINK_GROUP/incompatible-library-features2-result.txt b/Tests/RunCMake/GenEx-LINK_GROUP/incompatible-library-features2-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/GenEx-LINK_GROUP/incompatible-library-features2-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/GenEx-LINK_GROUP/incompatible-library-features2-stderr.txt b/Tests/RunCMake/GenEx-LINK_GROUP/incompatible-library-features2-stderr.txt new file mode 100644 index 0000000..889cba0 --- /dev/null +++ b/Tests/RunCMake/GenEx-LINK_GROUP/incompatible-library-features2-stderr.txt @@ -0,0 +1,6 @@ +CMake Error at incompatible-library-features2.cmake:[0-9]+ \(add_library\): + Impossible to link target 'lib1' because the link item 'dep1', specified + with the feature 'feat1', has already occurred with the feature 'feat2', + which is not allowed. +Call Stack \(most recent call first\): + CMakeLists.txt:[0-9]+ \(include\) diff --git a/Tests/RunCMake/GenEx-LINK_GROUP/incompatible-library-features2.cmake b/Tests/RunCMake/GenEx-LINK_GROUP/incompatible-library-features2.cmake new file mode 100644 index 0000000..6490819 --- /dev/null +++ b/Tests/RunCMake/GenEx-LINK_GROUP/incompatible-library-features2.cmake @@ -0,0 +1,17 @@ +enable_language(C) + +set(CMAKE_C_LINK_GROUP_USING_feat1_SUPPORTED TRUE) +set(CMAKE_C_LINK_GROUP_USING_feat1 "--start" "--stop") + +set(CMAKE_C_LINK_LIBRARY_USING_feat1_SUPPORTED TRUE) +set(CMAKE_C_LINK_LIBRARY_USING_feat1 "--libflag1") + +set(CMAKE_C_LINK_LIBRARY_USING_feat2_SUPPORTED TRUE) +set(CMAKE_C_LINK_LIBRARY_USING_feat2 "--libflag2") + +add_library(dep1 SHARED empty.c) +add_library(dep2 SHARED empty.c) +target_link_libraries(dep2 PUBLIC "$") + +add_library(lib1 SHARED empty.c) +target_link_libraries(lib1 PRIVATE "$>") diff --git a/Tests/RunCMake/GenEx-LINK_GROUP/invalid-feature-result.txt b/Tests/RunCMake/GenEx-LINK_GROUP/invalid-feature-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/GenEx-LINK_GROUP/invalid-feature-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/GenEx-LINK_GROUP/invalid-feature-stderr.txt b/Tests/RunCMake/GenEx-LINK_GROUP/invalid-feature-stderr.txt new file mode 100644 index 0000000..793b393 --- /dev/null +++ b/Tests/RunCMake/GenEx-LINK_GROUP/invalid-feature-stderr.txt @@ -0,0 +1,8 @@ +CMake Error at invalid-feature.cmake:[0-9]+ \(target_link_libraries\): + Error evaluating generator expression: + + \$ + + The feature name 'feat:invalid' contains invalid characters. +Call Stack \(most recent call first\): + CMakeLists.txt:[0-9]+ \(include\) diff --git a/Tests/RunCMake/GenEx-LINK_GROUP/invalid-feature.cmake b/Tests/RunCMake/GenEx-LINK_GROUP/invalid-feature.cmake new file mode 100644 index 0000000..34a319c --- /dev/null +++ b/Tests/RunCMake/GenEx-LINK_GROUP/invalid-feature.cmake @@ -0,0 +1,6 @@ +enable_language(C) + +add_library(dep SHARED empty.c) + +add_library(lib SHARED empty.c) +target_link_libraries(lib PRIVATE "$") diff --git a/Tests/RunCMake/GenEx-LINK_GROUP/library-ignored-stderr.txt b/Tests/RunCMake/GenEx-LINK_GROUP/library-ignored-stderr.txt new file mode 100644 index 0000000..b29c4ec --- /dev/null +++ b/Tests/RunCMake/GenEx-LINK_GROUP/library-ignored-stderr.txt @@ -0,0 +1,13 @@ +CMake Warning \(dev\) at library-ignored.cmake:[0-9]+ \(add_library\): + The feature 'feat', specified as part of a generator-expression + '\$', will not be applied to the INTERFACE library 'front'. +Call Stack \(most recent call first\): + CMakeLists.txt:[0-9]+ \(include\) +This warning is for project developers. Use -Wno-dev to suppress it. + +CMake Warning \(dev\) at library-ignored.cmake:[0-9]+ \(add_library\): + The feature 'feat', specified as part of a generator-expression + '\$', will not be applied to the OBJECT library 'dep'. +Call Stack \(most recent call first\): + CMakeLists.txt:[0-9]+ \(include\) +This warning is for project developers. Use -Wno-dev to suppress it. diff --git a/Tests/RunCMake/GenEx-LINK_GROUP/library-ignored.cmake b/Tests/RunCMake/GenEx-LINK_GROUP/library-ignored.cmake new file mode 100644 index 0000000..b3f19a7 --- /dev/null +++ b/Tests/RunCMake/GenEx-LINK_GROUP/library-ignored.cmake @@ -0,0 +1,15 @@ +enable_language(C) + +set(CMAKE_C_LINK_GROUP_USING_feat_SUPPORTED TRUE) +set(CMAKE_C_LINK_GROUP_USING_feat "--start" "--end") + +add_library(dep OBJECT empty.c) + +add_library(lib SHARED empty.c) + +add_library(front INTERFACE) +target_link_libraries(front INTERFACE lib) + + +add_library(lib2 SHARED empty.c) +target_link_libraries(lib2 PRIVATE "$") diff --git a/Tests/RunCMake/GenEx-LINK_GROUP/link_directories-result.txt b/Tests/RunCMake/GenEx-LINK_GROUP/link_directories-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/GenEx-LINK_GROUP/link_directories-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/GenEx-LINK_GROUP/link_directories-stderr.txt b/Tests/RunCMake/GenEx-LINK_GROUP/link_directories-stderr.txt new file mode 100644 index 0000000..51194a4 --- /dev/null +++ b/Tests/RunCMake/GenEx-LINK_GROUP/link_directories-stderr.txt @@ -0,0 +1,9 @@ +CMake Error at link_directories.cmake:[0-9]+ \(link_directories\): + Error evaluating generator expression: + + \$ + + \$ may only be used with binary targets to specify group of + link libraries. +Call Stack \(most recent call first\): + CMakeLists.txt:[0-9]+ \(include\) diff --git a/Tests/RunCMake/GenEx-LINK_GROUP/link_directories.cmake b/Tests/RunCMake/GenEx-LINK_GROUP/link_directories.cmake new file mode 100644 index 0000000..e356e91 --- /dev/null +++ b/Tests/RunCMake/GenEx-LINK_GROUP/link_directories.cmake @@ -0,0 +1,5 @@ +enable_language(C) + +link_directories("$") + +add_library(empty SHARED empty.c) diff --git a/Tests/RunCMake/GenEx-LINK_GROUP/nested-incompatible-features1-result.txt b/Tests/RunCMake/GenEx-LINK_GROUP/nested-incompatible-features1-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/GenEx-LINK_GROUP/nested-incompatible-features1-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/GenEx-LINK_GROUP/nested-incompatible-features1-stderr.txt b/Tests/RunCMake/GenEx-LINK_GROUP/nested-incompatible-features1-stderr.txt new file mode 100644 index 0000000..78631ab --- /dev/null +++ b/Tests/RunCMake/GenEx-LINK_GROUP/nested-incompatible-features1-stderr.txt @@ -0,0 +1,8 @@ +CMake Error at nested-incompatible-features1.cmake:[0-9]+ \(target_link_libraries\): + Error evaluating generator expression: + + \$> + + \$ cannot be nested. +Call Stack \(most recent call first\): + CMakeLists.txt:3 \(include\) diff --git a/Tests/RunCMake/GenEx-LINK_GROUP/nested-incompatible-features1.cmake b/Tests/RunCMake/GenEx-LINK_GROUP/nested-incompatible-features1.cmake new file mode 100644 index 0000000..50e0c64 --- /dev/null +++ b/Tests/RunCMake/GenEx-LINK_GROUP/nested-incompatible-features1.cmake @@ -0,0 +1,11 @@ +enable_language(C) + +set(CMAKE_C_LINK_GROUP_USING_feat_SUPPORTED TRUE) +set(CMAKE_C_LINK_GROUP_USING_feat "--start" "--end") + +add_library(dep1 SHARED empty.c) + +add_library(dep2 SHARED empty.c) + +add_library(lib SHARED empty.c) +target_link_libraries(lib PRIVATE "$>") diff --git a/Tests/RunCMake/GenEx-LINK_GROUP/nested-incompatible-features2-result.txt b/Tests/RunCMake/GenEx-LINK_GROUP/nested-incompatible-features2-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/GenEx-LINK_GROUP/nested-incompatible-features2-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/GenEx-LINK_GROUP/nested-incompatible-features2-stderr.txt b/Tests/RunCMake/GenEx-LINK_GROUP/nested-incompatible-features2-stderr.txt new file mode 100644 index 0000000..1a27c37 --- /dev/null +++ b/Tests/RunCMake/GenEx-LINK_GROUP/nested-incompatible-features2-stderr.txt @@ -0,0 +1,8 @@ +CMake Error at nested-incompatible-features2.cmake:[0-9]+ \(target_link_libraries\): + Error evaluating generator expression: + + \$> + + \$ cannot be nested. +Call Stack \(most recent call first\): + CMakeLists.txt:[0-9]+ \(include\) diff --git a/Tests/RunCMake/GenEx-LINK_GROUP/nested-incompatible-features2.cmake b/Tests/RunCMake/GenEx-LINK_GROUP/nested-incompatible-features2.cmake new file mode 100644 index 0000000..c6ea14c --- /dev/null +++ b/Tests/RunCMake/GenEx-LINK_GROUP/nested-incompatible-features2.cmake @@ -0,0 +1,14 @@ +enable_language(C) + +set(CMAKE_C_LINK_GROUP_USING_feat1_SUPPORTED TRUE) +set(CMAKE_C_LINK_GROUP_USING_feat1 "--start" "--end") + +set(CMAKE_C_LINK_GROUP_USING_feat2_SUPPORTED TRUE) +set(CMAKE_C_LINK_GROUP_USING_feat2 "--start" "--end") + +add_library(dep1 SHARED empty.c) + +add_library(dep2 SHARED empty.c) + +add_library(lib SHARED empty.c) +target_link_libraries(lib PRIVATE "$>") diff --git a/Tests/RunCMake/GenEx-LINK_GROUP/nested-incompatible-genex-result.txt b/Tests/RunCMake/GenEx-LINK_GROUP/nested-incompatible-genex-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/GenEx-LINK_GROUP/nested-incompatible-genex-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/GenEx-LINK_GROUP/nested-incompatible-genex-stderr.txt b/Tests/RunCMake/GenEx-LINK_GROUP/nested-incompatible-genex-stderr.txt new file mode 100644 index 0000000..87eeb4d --- /dev/null +++ b/Tests/RunCMake/GenEx-LINK_GROUP/nested-incompatible-genex-stderr.txt @@ -0,0 +1,18 @@ +CMake Error at nested-incompatible-genex.cmake:[0-9]+ \(add_library\): + Error evaluating generator expression: + + \$> + + \$ cannot be nested inside a \$ expression. +Call Stack \(most recent call first\): + CMakeLists.txt:[0-9]+ \(include\) + + +CMake Error at nested-incompatible-genex.cmake:[0-9]+ \(target_link_libraries\): + Error evaluating generator expression: + + \$> + + \$ cannot be nested inside a \$ expression. +Call Stack \(most recent call first\): + CMakeLists.txt:[0-9]+ \(include\) diff --git a/Tests/RunCMake/GenEx-LINK_GROUP/nested-incompatible-genex.cmake b/Tests/RunCMake/GenEx-LINK_GROUP/nested-incompatible-genex.cmake new file mode 100644 index 0000000..e3f2ade --- /dev/null +++ b/Tests/RunCMake/GenEx-LINK_GROUP/nested-incompatible-genex.cmake @@ -0,0 +1,6 @@ +enable_language(C) + +link_libraries("$>") + +add_library(lib SHARED empty.c) +target_link_libraries(lib PRIVATE "$>") diff --git a/Tests/RunCMake/GenEx-LINK_GROUP/no-arguments-result.txt b/Tests/RunCMake/GenEx-LINK_GROUP/no-arguments-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/GenEx-LINK_GROUP/no-arguments-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/GenEx-LINK_GROUP/no-arguments-stderr.txt b/Tests/RunCMake/GenEx-LINK_GROUP/no-arguments-stderr.txt new file mode 100644 index 0000000..63c2648 --- /dev/null +++ b/Tests/RunCMake/GenEx-LINK_GROUP/no-arguments-stderr.txt @@ -0,0 +1,8 @@ +CMake Error at no-arguments.cmake:[0-9]+ \(target_link_libraries\): + Error evaluating generator expression: + + \$ + + \$ expression requires at least one parameter. +Call Stack \(most recent call first\): + CMakeLists.txt:[0-9]+ \(include\) diff --git a/Tests/RunCMake/GenEx-LINK_GROUP/no-arguments.cmake b/Tests/RunCMake/GenEx-LINK_GROUP/no-arguments.cmake new file mode 100644 index 0000000..ffc1381 --- /dev/null +++ b/Tests/RunCMake/GenEx-LINK_GROUP/no-arguments.cmake @@ -0,0 +1,4 @@ +enable_language(C) + +add_library(lib SHARED empty.c) +target_link_libraries(lib PRIVATE "$") diff --git a/Tests/RunCMake/GenEx-LINK_GROUP/only-targets-result.txt b/Tests/RunCMake/GenEx-LINK_GROUP/only-targets-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/GenEx-LINK_GROUP/only-targets-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/GenEx-LINK_GROUP/only-targets-stderr.txt b/Tests/RunCMake/GenEx-LINK_GROUP/only-targets-stderr.txt new file mode 100644 index 0000000..6b770f0 --- /dev/null +++ b/Tests/RunCMake/GenEx-LINK_GROUP/only-targets-stderr.txt @@ -0,0 +1,13 @@ +CMake Error at only-targets.cmake:[0-9]+ \(target_link_libraries\): + Target "lib2" has LINK_LIBRARIES_ONLY_TARGETS enabled, but it links to: + + external + + which is not a target. Possible reasons include: + + \* There is a typo in the target name. + \* A find_package call is missing for an IMPORTED target. + \* An ALIAS target is missing. + +Call Stack \(most recent call first\): + CMakeLists.txt:[0-9]+ \(include\) diff --git a/Tests/RunCMake/GenEx-LINK_GROUP/only-targets.cmake b/Tests/RunCMake/GenEx-LINK_GROUP/only-targets.cmake new file mode 100644 index 0000000..8501f1d --- /dev/null +++ b/Tests/RunCMake/GenEx-LINK_GROUP/only-targets.cmake @@ -0,0 +1,16 @@ +enable_language(C) + +set(CMAKE_C_LINK_GROUP_USING_feat_SUPPORTED TRUE) +set(CMAKE_C_LINK_GROUP_USING_feat "--start" "--end") + +set(CMAKE_LINK_LIBRARIES_ONLY_TARGETS 1) + +add_library(dep1 SHARED empty.c) + +add_library(lib1 SHARED empty.c) +# accepted +target_link_libraries(lib1 PRIVATE "$") + +add_library(lib2 SHARED empty.c) +# invalid +target_link_libraries(lib2 PRIVATE "$") diff --git a/Tests/RunCMake/GenEx-LINK_GROUP/override-library-features1.cmake b/Tests/RunCMake/GenEx-LINK_GROUP/override-library-features1.cmake new file mode 100644 index 0000000..127e73f --- /dev/null +++ b/Tests/RunCMake/GenEx-LINK_GROUP/override-library-features1.cmake @@ -0,0 +1,4 @@ + +include(incompatible-library-features1.cmake) + +set_property(TARGET lib1 PROPERTY LINK_LIBRARY_OVERRIDE "feat1,dep1") diff --git a/Tests/RunCMake/GenEx-LINK_GROUP/override-library-features2.cmake b/Tests/RunCMake/GenEx-LINK_GROUP/override-library-features2.cmake new file mode 100644 index 0000000..9ad0bfe --- /dev/null +++ b/Tests/RunCMake/GenEx-LINK_GROUP/override-library-features2.cmake @@ -0,0 +1,4 @@ + +include(incompatible-library-features2.cmake) + +set_property(TARGET lib1 PROPERTY LINK_LIBRARY_OVERRIDE_dep1 "feat1") diff --git a/Tests/RunCMake/GenEx-LINK_GROUP/target_link_directories-result.txt b/Tests/RunCMake/GenEx-LINK_GROUP/target_link_directories-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/GenEx-LINK_GROUP/target_link_directories-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/GenEx-LINK_GROUP/target_link_directories-stderr.txt b/Tests/RunCMake/GenEx-LINK_GROUP/target_link_directories-stderr.txt new file mode 100644 index 0000000..042dd0b --- /dev/null +++ b/Tests/RunCMake/GenEx-LINK_GROUP/target_link_directories-stderr.txt @@ -0,0 +1,9 @@ +CMake Error at target_link_directories.cmake:[0-9]+ \(target_link_directories\): + Error evaluating generator expression: + + \$ + + \$ may only be used with binary targets to specify group of + link libraries. +Call Stack \(most recent call first\): + CMakeLists.txt:[0-9]+ \(include\) diff --git a/Tests/RunCMake/GenEx-LINK_GROUP/target_link_directories.cmake b/Tests/RunCMake/GenEx-LINK_GROUP/target_link_directories.cmake new file mode 100644 index 0000000..47a5f9c --- /dev/null +++ b/Tests/RunCMake/GenEx-LINK_GROUP/target_link_directories.cmake @@ -0,0 +1,4 @@ +enable_language(C) + +add_library(empty SHARED empty.c) +target_link_directories(empty PRIVATE "$") diff --git a/Tests/RunCMake/GenEx-LINK_GROUP/target_link_options-result.txt b/Tests/RunCMake/GenEx-LINK_GROUP/target_link_options-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/GenEx-LINK_GROUP/target_link_options-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/GenEx-LINK_GROUP/target_link_options-stderr.txt b/Tests/RunCMake/GenEx-LINK_GROUP/target_link_options-stderr.txt new file mode 100644 index 0000000..7030b9c --- /dev/null +++ b/Tests/RunCMake/GenEx-LINK_GROUP/target_link_options-stderr.txt @@ -0,0 +1,9 @@ +CMake Error at target_link_options.cmake:[0-9]+ \(target_link_options\): + Error evaluating generator expression: + + \$ + + \$ may only be used with binary targets to specify group of + link libraries. +Call Stack \(most recent call first\): + CMakeLists.txt:[0-9]+ \(include\) diff --git a/Tests/RunCMake/GenEx-LINK_GROUP/target_link_options.cmake b/Tests/RunCMake/GenEx-LINK_GROUP/target_link_options.cmake new file mode 100644 index 0000000..d7dd876 --- /dev/null +++ b/Tests/RunCMake/GenEx-LINK_GROUP/target_link_options.cmake @@ -0,0 +1,4 @@ +enable_language(C) + +add_library(empty SHARED empty.c) +target_link_options(empty PRIVATE $) diff --git a/Tests/RunCMake/GenEx-LINK_LIBRARY/RunCMakeTest.cmake b/Tests/RunCMake/GenEx-LINK_LIBRARY/RunCMakeTest.cmake index d5438b8..9c266fe 100644 --- a/Tests/RunCMake/GenEx-LINK_LIBRARY/RunCMakeTest.cmake +++ b/Tests/RunCMake/GenEx-LINK_LIBRARY/RunCMakeTest.cmake @@ -9,6 +9,7 @@ run_cmake(target_link_directories) run_cmake(no-arguments) run_cmake(empty-arguments) run_cmake(forbidden-arguments) +run_cmake(invalid-feature) run_cmake(bad-feature1) run_cmake(bad-feature2) run_cmake(bad-feature3) diff --git a/Tests/RunCMake/GenEx-LINK_LIBRARY/invalid-feature-result.txt b/Tests/RunCMake/GenEx-LINK_LIBRARY/invalid-feature-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/GenEx-LINK_LIBRARY/invalid-feature-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/GenEx-LINK_LIBRARY/invalid-feature-stderr.txt b/Tests/RunCMake/GenEx-LINK_LIBRARY/invalid-feature-stderr.txt new file mode 100644 index 0000000..fb5cdab --- /dev/null +++ b/Tests/RunCMake/GenEx-LINK_LIBRARY/invalid-feature-stderr.txt @@ -0,0 +1,8 @@ +CMake Error at invalid-feature.cmake:[0-9]+ \(target_link_libraries\): + Error evaluating generator expression: + + \$ + + The feature name 'feat:invalid' contains invalid characters. +Call Stack \(most recent call first\): + CMakeLists.txt:[0-9]+ \(include\) diff --git a/Tests/RunCMake/GenEx-LINK_LIBRARY/invalid-feature.cmake b/Tests/RunCMake/GenEx-LINK_LIBRARY/invalid-feature.cmake new file mode 100644 index 0000000..c49e4cd --- /dev/null +++ b/Tests/RunCMake/GenEx-LINK_LIBRARY/invalid-feature.cmake @@ -0,0 +1,6 @@ +enable_language(C) + +add_library(dep SHARED empty.c) + +add_library(lib SHARED empty.c) +target_link_libraries(lib PRIVATE "$") diff --git a/Tests/RunCMake/target_link_libraries-LINK_GROUP/CMakeLists.txt b/Tests/RunCMake/target_link_libraries-LINK_GROUP/CMakeLists.txt new file mode 100644 index 0000000..915fc41 --- /dev/null +++ b/Tests/RunCMake/target_link_libraries-LINK_GROUP/CMakeLists.txt @@ -0,0 +1,3 @@ +cmake_minimum_required(VERSION 3.1...3.22) +project(${RunCMake_TEST} NONE) +include(${RunCMake_TEST}.cmake NO_POLICY_SCOPE) diff --git a/Tests/RunCMake/target_link_libraries-LINK_GROUP/LINK_GROUP-group-and-single-check.cmake b/Tests/RunCMake/target_link_libraries-LINK_GROUP/LINK_GROUP-group-and-single-check.cmake new file mode 100644 index 0000000..3b8f3ba --- /dev/null +++ b/Tests/RunCMake/target_link_libraries-LINK_GROUP/LINK_GROUP-group-and-single-check.cmake @@ -0,0 +1,4 @@ + +if (NOT actual_stdout MATCHES "(/|-)-START_GROUP\"? +.*${LINK_SHARED_LIBRARY_PREFIX}base1${LINK_SHARED_LIBRARY_SUFFIX} +.*${LINK_SHARED_LIBRARY_PREFIX}base3${LINK_SHARED_LIBRARY_SUFFIX} +\"?(/|-)-END_GROUP\"? +.*${LINK_SHARED_LIBRARY_PREFIX}base5${LINK_SHARED_LIBRARY_SUFFIX} +\"?(/|-)-START_GROUP\"? +.*${LINK_SHARED_LIBRARY_PREFIX}base1${LINK_SHARED_LIBRARY_SUFFIX} +.*${LINK_SHARED_LIBRARY_PREFIX}base3${LINK_SHARED_LIBRARY_SUFFIX} +\"?(/|-)-END_GROUP") + set (RunCMake_TEST_FAILED "Not found expected '--START_GROUP --END_GROUP --START_GROUP --END_GROUP'.") +endif() diff --git a/Tests/RunCMake/target_link_libraries-LINK_GROUP/LINK_GROUP-group-and-single-result.txt b/Tests/RunCMake/target_link_libraries-LINK_GROUP/LINK_GROUP-group-and-single-result.txt new file mode 100644 index 0000000..8d98f9d --- /dev/null +++ b/Tests/RunCMake/target_link_libraries-LINK_GROUP/LINK_GROUP-group-and-single-result.txt @@ -0,0 +1 @@ +.* diff --git a/Tests/RunCMake/target_link_libraries-LINK_GROUP/LINK_GROUP-multiple-groups-check.cmake b/Tests/RunCMake/target_link_libraries-LINK_GROUP/LINK_GROUP-multiple-groups-check.cmake new file mode 100644 index 0000000..97732a5 --- /dev/null +++ b/Tests/RunCMake/target_link_libraries-LINK_GROUP/LINK_GROUP-multiple-groups-check.cmake @@ -0,0 +1,4 @@ + +if (NOT actual_stdout MATCHES "(/|-)-START_GROUP\"? +.*${LINK_SHARED_LIBRARY_PREFIX}base2${LINK_SHARED_LIBRARY_SUFFIX} +.*${LINK_SHARED_LIBRARY_PREFIX}base4${LINK_SHARED_LIBRARY_SUFFIX} +\"?(/|-)-END_GROUP\"? +\"?(/|-)-START_GROUP\"? +.*${LINK_SHARED_LIBRARY_PREFIX}base1${LINK_SHARED_LIBRARY_SUFFIX} +.*${LINK_SHARED_LIBRARY_PREFIX}base2${LINK_SHARED_LIBRARY_SUFFIX} +\"?(/|-)-END_GROUP") + set (RunCMake_TEST_FAILED "Not found expected '--START_GROUP --END_GROUP --START_GROUP --END_GROUP'.") +endif() diff --git a/Tests/RunCMake/target_link_libraries-LINK_GROUP/LINK_GROUP-multiple-groups-result.txt b/Tests/RunCMake/target_link_libraries-LINK_GROUP/LINK_GROUP-multiple-groups-result.txt new file mode 100644 index 0000000..8d98f9d --- /dev/null +++ b/Tests/RunCMake/target_link_libraries-LINK_GROUP/LINK_GROUP-multiple-groups-result.txt @@ -0,0 +1 @@ +.* diff --git a/Tests/RunCMake/target_link_libraries-LINK_GROUP/LINK_GROUP-simple1-check.cmake b/Tests/RunCMake/target_link_libraries-LINK_GROUP/LINK_GROUP-simple1-check.cmake new file mode 100644 index 0000000..3e53d26 --- /dev/null +++ b/Tests/RunCMake/target_link_libraries-LINK_GROUP/LINK_GROUP-simple1-check.cmake @@ -0,0 +1,4 @@ + +if (NOT actual_stdout MATCHES "(/|-)-START_GROUP\"? +.*${LINK_SHARED_LIBRARY_PREFIX}base1${LINK_SHARED_LIBRARY_SUFFIX} +.*${LINK_SHARED_LIBRARY_PREFIX}base2${LINK_SHARED_LIBRARY_SUFFIX} +\"?(/|-)-END_GROUP") + set (RunCMake_TEST_FAILED "Not found expected '--START_GROUP --END_GROUP'.") +endif() diff --git a/Tests/RunCMake/target_link_libraries-LINK_GROUP/LINK_GROUP-simple1-result.txt b/Tests/RunCMake/target_link_libraries-LINK_GROUP/LINK_GROUP-simple1-result.txt new file mode 100644 index 0000000..8d98f9d --- /dev/null +++ b/Tests/RunCMake/target_link_libraries-LINK_GROUP/LINK_GROUP-simple1-result.txt @@ -0,0 +1 @@ +.* diff --git a/Tests/RunCMake/target_link_libraries-LINK_GROUP/LINK_GROUP-simple2-check.cmake b/Tests/RunCMake/target_link_libraries-LINK_GROUP/LINK_GROUP-simple2-check.cmake new file mode 100644 index 0000000..475a0e2 --- /dev/null +++ b/Tests/RunCMake/target_link_libraries-LINK_GROUP/LINK_GROUP-simple2-check.cmake @@ -0,0 +1,4 @@ + +if (NOT actual_stdout MATCHES "(/|-)-START_GROUP\"? +.*${LINK_SHARED_LIBRARY_PREFIX}base2${LINK_SHARED_LIBRARY_SUFFIX} +.*${LINK_SHARED_LIBRARY_PREFIX}base3${LINK_SHARED_LIBRARY_SUFFIX} +\"?(/|-)-END_GROUP\"? +.*${LINK_SHARED_LIBRARY_PREFIX}base1${LINK_SHARED_LIBRARY_SUFFIX}") + set (RunCMake_TEST_FAILED "Not found expected '--START_GROUP --END_GROUP '.") +endif() diff --git a/Tests/RunCMake/target_link_libraries-LINK_GROUP/LINK_GROUP-simple2-result.txt b/Tests/RunCMake/target_link_libraries-LINK_GROUP/LINK_GROUP-simple2-result.txt new file mode 100644 index 0000000..8d98f9d --- /dev/null +++ b/Tests/RunCMake/target_link_libraries-LINK_GROUP/LINK_GROUP-simple2-result.txt @@ -0,0 +1 @@ +.* diff --git a/Tests/RunCMake/target_link_libraries-LINK_GROUP/LINK_GROUP-with-LINK_LIBRARY-check.cmake b/Tests/RunCMake/target_link_libraries-LINK_GROUP/LINK_GROUP-with-LINK_LIBRARY-check.cmake new file mode 100644 index 0000000..2b2460e --- /dev/null +++ b/Tests/RunCMake/target_link_libraries-LINK_GROUP/LINK_GROUP-with-LINK_LIBRARY-check.cmake @@ -0,0 +1,4 @@ + +if (NOT actual_stdout MATCHES "(/|-)-START_GROUP\"? +\"?(/|-)-LIBFLAG.*${LINK_SHARED_LIBRARY_PREFIX}base1${LINK_SHARED_LIBRARY_SUFFIX}\"? +.*${LINK_SHARED_LIBRARY_PREFIX}base2${LINK_SHARED_LIBRARY_SUFFIX} +\"?(/|-)-END_GROUP") + set (RunCMake_TEST_FAILED "Not found expected '--START_GROUP --LIBFLAG --END_GROUP'.") +endif() diff --git a/Tests/RunCMake/target_link_libraries-LINK_GROUP/LINK_GROUP-with-LINK_LIBRARY-result.txt b/Tests/RunCMake/target_link_libraries-LINK_GROUP/LINK_GROUP-with-LINK_LIBRARY-result.txt new file mode 100644 index 0000000..8d98f9d --- /dev/null +++ b/Tests/RunCMake/target_link_libraries-LINK_GROUP/LINK_GROUP-with-LINK_LIBRARY-result.txt @@ -0,0 +1 @@ +.* diff --git a/Tests/RunCMake/target_link_libraries-LINK_GROUP/LINK_GROUP-with-LINK_LIBRARY_OVERRIDE-check.cmake b/Tests/RunCMake/target_link_libraries-LINK_GROUP/LINK_GROUP-with-LINK_LIBRARY_OVERRIDE-check.cmake new file mode 100644 index 0000000..5ef830c --- /dev/null +++ b/Tests/RunCMake/target_link_libraries-LINK_GROUP/LINK_GROUP-with-LINK_LIBRARY_OVERRIDE-check.cmake @@ -0,0 +1,4 @@ + +if (NOT actual_stdout MATCHES "(/|-)-START_GROUP\"? +\"?(/|-)-LIBFLAG.*${LINK_SHARED_LIBRARY_PREFIX}base1${LINK_SHARED_LIBRARY_SUFFIX}\"? +\"?(/|-)-LIBFLAG.*${LINK_SHARED_LIBRARY_PREFIX}base3${LINK_SHARED_LIBRARY_SUFFIX}\"? +.*${LINK_SHARED_LIBRARY_PREFIX}base2${LINK_SHARED_LIBRARY_SUFFIX} +\"?(/|-)-END_GROUP") + set (RunCMake_TEST_FAILED "Not found expected '--START_GROUP --LIBFLAG --LIBFLAG --END_GROUP'.") +endif() diff --git a/Tests/RunCMake/target_link_libraries-LINK_GROUP/LINK_GROUP-with-LINK_LIBRARY_OVERRIDE-result.txt b/Tests/RunCMake/target_link_libraries-LINK_GROUP/LINK_GROUP-with-LINK_LIBRARY_OVERRIDE-result.txt new file mode 100644 index 0000000..8d98f9d --- /dev/null +++ b/Tests/RunCMake/target_link_libraries-LINK_GROUP/LINK_GROUP-with-LINK_LIBRARY_OVERRIDE-result.txt @@ -0,0 +1 @@ +.* diff --git a/Tests/RunCMake/target_link_libraries-LINK_GROUP/LINK_GROUP.cmake b/Tests/RunCMake/target_link_libraries-LINK_GROUP/LINK_GROUP.cmake new file mode 100644 index 0000000..d08db16 --- /dev/null +++ b/Tests/RunCMake/target_link_libraries-LINK_GROUP/LINK_GROUP.cmake @@ -0,0 +1,52 @@ +enable_language(C) + +# ensure command line is always displayed and do not use any response file +set(CMAKE_VERBOSE_MAKEFILE TRUE) +set(CMAKE_C_USE_RESPONSE_FILE_FOR_LIBRARIES FALSE) + +if (CMAKE_GENERATOR MATCHES "Borland|NMake") + string(REPLACE "${CMAKE_START_TEMP_FILE}" "" CMAKE_C_CREATE_SHARED_LIBRARY "${CMAKE_C_CREATE_SHARED_LIBRARY}") + string(REPLACE "${CMAKE_END_TEMP_FILE}" "" CMAKE_C_CREATE_SHARED_LIBRARY "${CMAKE_C_CREATE_SHARED_LIBRARY}") +endif() + + +add_library(base1 SHARED base.c) +add_library(base2 SHARED base.c) + + +set(CMAKE_C_LINK_GROUP_USING_feat1 "--START_GROUP" "--END_GROUP") +set(CMAKE_C_LINK_GROUP_USING_feat1_SUPPORTED TRUE) + +set(CMAKE_C_LINK_LIBRARY_USING_feat1 "--LIBFLAG") +set(CMAKE_C_LINK_LIBRARY_USING_feat1_SUPPORTED TRUE) + + +add_library(LinkGroup_simple1 SHARED lib.c) +target_link_libraries(LinkGroup_simple1 PRIVATE "$") + + +add_library(base3 SHARED base.c) +target_link_libraries(base3 PUBLIC base1) +add_library(LinkGroup_simple2 SHARED lib.c) +target_link_libraries(LinkGroup_simple2 PRIVATE "$") + + +add_library(base4 SHARED base.c) +target_link_libraries(base4 INTERFACE "$") +add_library(LinkGroup_multiple-groups SHARED lib.c) +target_link_libraries(LinkGroup_multiple-groups PRIVATE "$") + + +add_library(base5 SHARED base.c) +target_link_libraries(base5 PUBLIC base1) +add_library(LinkGroup_group-and-single SHARED lib.c) +target_link_libraries(LinkGroup_group-and-single PRIVATE "$" base5) + + +add_library(LinkGroup_with-LINK_LIBRARY SHARED lib.c) +target_link_libraries(LinkGroup_with-LINK_LIBRARY PRIVATE "$,base2>") + + +add_library(LinkGroup_with-LINK_LIBRARY_OVERRIDE SHARED lib.c) +target_link_libraries(LinkGroup_with-LINK_LIBRARY_OVERRIDE PRIVATE "$,base2>") +set_property(TARGET LinkGroup_with-LINK_LIBRARY_OVERRIDE PROPERTY LINK_LIBRARY_OVERRIDE_base1 feat1) diff --git a/Tests/RunCMake/target_link_libraries-LINK_GROUP/RunCMakeTest.cmake b/Tests/RunCMake/target_link_libraries-LINK_GROUP/RunCMakeTest.cmake new file mode 100644 index 0000000..eedc5b9 --- /dev/null +++ b/Tests/RunCMake/target_link_libraries-LINK_GROUP/RunCMakeTest.cmake @@ -0,0 +1,63 @@ + +include(RunCMake) + +cmake_policy(SET CMP0054 NEW) + +macro(run_cmake_target test subtest target) + set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/${test}-build) + set(RunCMake_TEST_NO_CLEAN 1) + run_cmake_command(${test}-${subtest} ${CMAKE_COMMAND} --build . --target ${target} --config Release --verbose ${ARGN}) + + unset(RunCMake_TEST_BINARY_DIR) + unset(RunCMake_TEST_NO_CLEAN) +endmacro() + + +# Some environments are excluded because they are not able to honor verbose mode +if ((RunCMake_GENERATOR MATCHES "Makefiles|Ninja|Xcode" + OR (RunCMake_GENERATOR MATCHES "Visual Studio" AND MSVC_VERSION GREATER_EQUAL "1600")) + AND NOT CMAKE_C_COMPILER_ID STREQUAL "Intel") + + set(RunCMake_TEST_OUTPUT_MERGE TRUE) + if (NOT RunCMake_GENERATOR_IS_MULTI_CONFIG) + set(RunCMake_TEST_OPTIONS -DCMAKE_BUILD_TYPE=Release) + endif() + + if (CMAKE_SYSTEM_NAME STREQUAL "Windows" + OR CMAKE_SYSTEM_NAME STREQUAL "CYGWIN" + OR CMAKE_SYSTEM_NAME STREQUAL "MSYS") + set(LINK_SHARED_LIBRARY_PREFIX ${CMAKE_IMPORT_LIBRARY_PREFIX}) + set(LINK_SHARED_LIBRARY_SUFFIX ${CMAKE_IMPORT_LIBRARY_SUFFIX}) + else() + set(LINK_SHARED_LIBRARY_PREFIX ${CMAKE_SHARED_LIBRARY_PREFIX}) + set(LINK_SHARED_LIBRARY_SUFFIX ${CMAKE_SHARED_LIBRARY_SUFFIX}) + endif() + if (MINGW OR MSYS OR CYGWIN) + set(LINK_EXTERN_LIBRARY_SUFFIX "") + else() + set(LINK_EXTERN_LIBRARY_SUFFIX "${CMAKE_IMPORT_LIBRARY_SUFFIX}") + endif() + + run_cmake(LINK_GROUP) + + run_cmake_target(LINK_GROUP simple1 LinkGroup_simple1) + run_cmake_target(LINK_GROUP simple2 LinkGroup_simple2) + run_cmake_target(LINK_GROUP multiple-groups LinkGroup_multiple-groups) + run_cmake_target(LINK_GROUP group-and-single LinkGroup_group-and-single) + run_cmake_target(LINK_GROUP with-LINK_LIBRARY LinkGroup_with-LINK_LIBRARY) + run_cmake_target(LINK_GROUP with-LINK_LIBRARY_OVERRIDE LinkGroup_with-LINK_LIBRARY_OVERRIDE) + + run_cmake(imported-target) + + # tests using features as described in the documentation + if((CMAKE_C_COMPILER_ID STREQUAL "GNU" AND CMAKE_SYSTEM_NAME STREQUAL "Linux") + OR (CMAKE_C_COMPILER_ID STREQUAL "SunPro" AND CMAKE_C_COMPILER_VERSION VERSION_GREATER "5.9" + AND CMAKE_SYSTEM_NAME STREQUAL "SunOS")) + run_cmake(cross_refs) + run_cmake_target(cross_refs link main) + endif() + + unset(RunCMake_TEST_OPTIONS) + unset(RunCMake_TEST_OUTPUT_MERGE) + +endif() diff --git a/Tests/RunCMake/target_link_libraries-LINK_GROUP/base.c b/Tests/RunCMake/target_link_libraries-LINK_GROUP/base.c new file mode 100644 index 0000000..a5075d4 --- /dev/null +++ b/Tests/RunCMake/target_link_libraries-LINK_GROUP/base.c @@ -0,0 +1,9 @@ + +#if !defined(STATIC_BASE) +# if defined(_WIN32) +__declspec(dllexport) +# endif +#endif + void base() +{ +} diff --git a/Tests/RunCMake/target_link_libraries-LINK_GROUP/cross_refs.cmake b/Tests/RunCMake/target_link_libraries-LINK_GROUP/cross_refs.cmake new file mode 100644 index 0000000..4a2a08c --- /dev/null +++ b/Tests/RunCMake/target_link_libraries-LINK_GROUP/cross_refs.cmake @@ -0,0 +1,22 @@ + +enable_language(C) + + set(CMAKE_C_LINK_GROUP_USING_cross_refs_SUPPORTED TRUE) +if(CMAKE_C_COMPILER_ID STREQUAL "GNU" + AND CMAKE_SYSTEM_NAME STREQUAL "Linux") +set(CMAKE_C_LINK_GROUP_USING_cross_refs "LINKER:--start-group" + "LINKER:--end-group") +elseif(CMAKE_C_COMPILER_ID STREQUAL "SunPro" + AND CMAKE_SYSTEM_NAME STREQUAL "SunOS") + set(CMAKE_C_LINK_GROUP_USING_cross_refs "LINKER:-z,rescan-start" + "LINKER:-z,rescan-end") +else() + # feature not yet supported for the other environments + set(CMAKE_C_LINK_GROUP_USING_cross_refs_SUPPORTED FALSE) +endif() + +add_library(func1 STATIC func1.c func3.c) +add_library(func2 STATIC func2.c) + +add_executable(main main.c) +target_link_libraries(main PRIVATE "$") diff --git a/Tests/RunCMake/target_link_libraries-LINK_GROUP/func1.c b/Tests/RunCMake/target_link_libraries-LINK_GROUP/func1.c new file mode 100644 index 0000000..3399e00 --- /dev/null +++ b/Tests/RunCMake/target_link_libraries-LINK_GROUP/func1.c @@ -0,0 +1,7 @@ + +extern void func2(); + +void func1() +{ + func2(); +} diff --git a/Tests/RunCMake/target_link_libraries-LINK_GROUP/func2.c b/Tests/RunCMake/target_link_libraries-LINK_GROUP/func2.c new file mode 100644 index 0000000..0f9aa64 --- /dev/null +++ b/Tests/RunCMake/target_link_libraries-LINK_GROUP/func2.c @@ -0,0 +1,7 @@ + +extern void func3(); + +void func2() +{ + func3(); +} diff --git a/Tests/RunCMake/target_link_libraries-LINK_GROUP/func3.c b/Tests/RunCMake/target_link_libraries-LINK_GROUP/func3.c new file mode 100644 index 0000000..0b7df64 --- /dev/null +++ b/Tests/RunCMake/target_link_libraries-LINK_GROUP/func3.c @@ -0,0 +1,6 @@ + +extern void func3(); + +void func3() +{ +} diff --git a/Tests/RunCMake/target_link_libraries-LINK_GROUP/imported-target-result.txt b/Tests/RunCMake/target_link_libraries-LINK_GROUP/imported-target-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/target_link_libraries-LINK_GROUP/imported-target-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/target_link_libraries-LINK_GROUP/imported-target-stdout.txt b/Tests/RunCMake/target_link_libraries-LINK_GROUP/imported-target-stdout.txt new file mode 100644 index 0000000..16b93d1 --- /dev/null +++ b/Tests/RunCMake/target_link_libraries-LINK_GROUP/imported-target-stdout.txt @@ -0,0 +1,16 @@ +CMake Warning \(dev\) at imported-target.cmake:[0-9]+ \(add_library\): + The 'IMPORTED' target 'NS::lib2' uses the generator-expression + '\$' with the feature 'feat', which is undefined or unsupported. + + Did you miss to define it by setting variables + "CMAKE_C_LINK_GROUP_USING_feat" and + "CMAKE_C_LINK_GROUP_USING_feat_SUPPORTED"\? +Call Stack \(most recent call first\): + CMakeLists.txt:[0-9]+ \(include\) +This warning is for project developers. Use -Wno-dev to suppress it. + +CMake Error at imported-target.cmake:[0-9]+ \(add_library\): + Feature 'feat', specified through generator-expression '\$' to + link target 'lib', is not supported for the 'C' link language. +Call Stack \(most recent call first\): + CMakeLists.txt:[0-9]+ \(include\) diff --git a/Tests/RunCMake/target_link_libraries-LINK_GROUP/imported-target.cmake b/Tests/RunCMake/target_link_libraries-LINK_GROUP/imported-target.cmake new file mode 100644 index 0000000..bd83f97 --- /dev/null +++ b/Tests/RunCMake/target_link_libraries-LINK_GROUP/imported-target.cmake @@ -0,0 +1,22 @@ + +enable_language(C) + +# Create imported target NS::lib +add_library(NS::lib STATIC IMPORTED) +set_target_properties(NS::lib PROPERTIES + IMPORTED_LOCATION "/path/to/lib" + IMPORTED_IMPLIB "/path/to/import.lib" +) + +# Create imported target NS::lib2 +add_library(NS::lib2 SHARED IMPORTED) + +set_target_properties(NS::lib2 PROPERTIES + IMPORTED_LOCATION "/path/to/lib" + IMPORTED_IMPLIB "/path/to/import.lib" + INTERFACE_LINK_LIBRARIES "$" +) + + +add_library(lib SHARED lib.c) +target_link_libraries(lib PRIVATE NS::lib2) diff --git a/Tests/RunCMake/target_link_libraries-LINK_GROUP/lib.c b/Tests/RunCMake/target_link_libraries-LINK_GROUP/lib.c new file mode 100644 index 0000000..35ab367 --- /dev/null +++ b/Tests/RunCMake/target_link_libraries-LINK_GROUP/lib.c @@ -0,0 +1,15 @@ + +#if !defined(STATIC_BASE) +# if defined(_WIN32) +__declspec(dllimport) +# endif +#endif + void base(); + +#if defined(_WIN32) +__declspec(dllexport) +#endif + void lib() +{ + base(); +} diff --git a/Tests/RunCMake/target_link_libraries-LINK_GROUP/main.c b/Tests/RunCMake/target_link_libraries-LINK_GROUP/main.c new file mode 100644 index 0000000..403583d --- /dev/null +++ b/Tests/RunCMake/target_link_libraries-LINK_GROUP/main.c @@ -0,0 +1,7 @@ + +extern void func1(); + +int main() +{ + func1(); +} -- cgit v0.12