diff options
873 files changed, 15724 insertions, 5002 deletions
diff --git a/.clang-format b/.clang-format index 0c7d6b0..a7f049a 100644 --- a/.clang-format +++ b/.clang-format @@ -22,7 +22,7 @@ IncludeBlocks: Regroup IncludeCategories: - Regex: '^[<"]cmConfigure\.h' Priority: -1 - - Regex: '^(<|")cm/' + - Regex: '^(<|")cm(ext)?/' Priority: 2 - Regex: '^(<|")windows\.h' Priority: 3 diff --git a/Auxiliary/vim/syntax/cmake.vim b/Auxiliary/vim/syntax/cmake.vim index 5de117b..31ec1d0 100644 --- a/Auxiliary/vim/syntax/cmake.vim +++ b/Auxiliary/vim/syntax/cmake.vim @@ -101,6 +101,7 @@ syn keyword cmakeProperty contained \ CLEAN_NO_CUSTOM \ CMAKE_CONFIGURE_DEPENDS \ CMAKE_CXX_KNOWN_FEATURES + \ CMAKE_CUDA_KNOWN_FEATURES \ CMAKE_C_KNOWN_FEATURES \ CMAKE_ROLE \ COMMON_LANGUAGE_RUNTIME @@ -725,6 +726,7 @@ syn keyword cmakeVariable contained \ CMAKE_CUDA_COMPILER_AR \ CMAKE_CUDA_COMPILER_ARCHITECTURE_ID \ CMAKE_CUDA_COMPILER_EXTERNAL_TOOLCHAIN + \ CMAKE_CUDA_COMPILE_FEATURES \ CMAKE_CUDA_COMPILER_ID \ CMAKE_CUDA_COMPILER_LAUNCHER \ CMAKE_CUDA_COMPILER_LOADED diff --git a/CTestCustom.cmake.in b/CTestCustom.cmake.in index d3ab9d3..fb8e099 100644 --- a/CTestCustom.cmake.in +++ b/CTestCustom.cmake.in @@ -72,6 +72,7 @@ list(APPEND CTEST_CUSTOM_WARNING_EXCEPTION "cm(StringCommand|CTestTestHandler)\\.cxx.*warning.*rand.*isn.*t random" # we do not do crypto "cm(StringCommand|CTestTestHandler)\\.cxx.*warning.*srand.*seed choices are.*poor" # we do not do crypto "IPA warning: function.*multiply defined in" + "LICENSE WARNING" # PGI license expiry. Not useful in nightly testing. # Ignore compiler summary warning, assuming prior text has matched some # other warning expression: diff --git a/Copyright.txt b/Copyright.txt index f236214..19f3deb 100644 --- a/Copyright.txt +++ b/Copyright.txt @@ -1,5 +1,5 @@ CMake - Cross Platform Makefile Generator -Copyright 2000-2019 Kitware, Inc. and Contributors +Copyright 2000-2020 Kitware, Inc. and Contributors All rights reserved. Redistribution and use in source and binary forms, with or without diff --git a/Help/command/ctest_test.rst b/Help/command/ctest_test.rst index 7a3393b..5c67b2c 100644 --- a/Help/command/ctest_test.rst +++ b/Help/command/ctest_test.rst @@ -23,6 +23,7 @@ Perform the :ref:`CTest Test Step` as a :ref:`Dashboard Client`. [STOP_TIME <time-of-day>] [RETURN_VALUE <result-var>] [CAPTURE_CMAKE_ERROR <result-var>] + [REPEAT <mode>:<n>] [QUIET] ) @@ -95,6 +96,25 @@ The options are: and then the ``--test-load`` command-line argument to :manual:`ctest(1)`. See also the ``TestLoad`` setting in the :ref:`CTest Test Step`. +``REPEAT <mode>:<n>`` + Run tests repeatedly based on the given ``<mode>`` up to ``<n>`` times. + The modes are: + + ``UNTIL_FAIL`` + Require each test to run ``<n>`` times without failing in order to pass. + This is useful in finding sporadic failures in test cases. + + ``UNTIL_PASS`` + Allow each test to run up to ``<n>`` times in order to pass. + Repeats tests if they fail for any reason. + This is useful in tolerating sporadic failures in test cases. + + ``AFTER_TIMEOUT`` + Allow each test to run up to ``<n>`` times in order to pass. + Repeats tests only if they timeout. + This is useful in tolerating sporadic timeouts in test cases + on busy machines. + ``SCHEDULE_RANDOM <ON|OFF>`` Launch tests in a random order. This may be useful for detecting implicit test dependencies. diff --git a/Help/command/foreach.rst b/Help/command/foreach.rst index ae2afb2..a01a104 100644 --- a/Help/command/foreach.rst +++ b/Help/command/foreach.rst @@ -47,7 +47,7 @@ of undocumented behavior that may change in future releases. .. code-block:: cmake - foreach(loop_var IN [LISTS [<lists>]] [ITEMS [<items>]]) + foreach(<loop_var> IN [LISTS [<lists>]] [ITEMS [<items>]]) In this variant, ``<lists>`` is a whitespace or semicolon separated list of list-valued variables. The ``foreach`` @@ -82,3 +82,46 @@ yields -- X=6 -- X=7 -- X=8 + + +.. code-block:: cmake + + foreach(<loop_var>... IN ZIP_LISTS <lists>) + +In this variant, ``<lists>`` is a whitespace or semicolon +separated list of list-valued variables. The ``foreach`` +command iterates over each list simultaneously setting the +iteration variables as follows: + +- if the only ``loop_var`` given, then it sets a series of + ``loop_var_N`` variables to the current item from the + corresponding list; +- if multiple variable names passed, their count should match + the lists variables count; +- if any of the lists are shorter, the corresponding iteration + variable is not defined for the current iteration. + +.. code-block:: cmake + + list(APPEND English one two three four) + list(APPEND Bahasa satu dua tiga) + + foreach(num IN ZIP_LISTS English Bahasa) + message(STATUS "num_0=${num_0}, num_1=${num_1}") + endforeach() + + foreach(en ba IN ZIP_LISTS English Bahasa) + message(STATUS "en=${en}, ba=${ba}") + endforeach() + +yields +:: + + -- num_0=one, num_1=satu + -- num_0=two, num_1=dua + -- num_0=three, num_1=tiga + -- num_0=four, num_1= + -- en=one, ba=satu + -- en=two, ba=dua + -- en=three, ba=tiga + -- en=four, ba= diff --git a/Help/command/macro.rst b/Help/command/macro.rst index 05e5d79..3f6f2f9 100644 --- a/Help/command/macro.rst +++ b/Help/command/macro.rst @@ -91,6 +91,12 @@ just terminate execution of the macro; rather, control is returned from the scope of the macro call. To avoid confusion, it is recommended to avoid :command:`return()` in macros altogether. +Unlike a function, the :variable:`CMAKE_CURRENT_FUNCTION`, +:variable:`CMAKE_CURRENT_FUNCTION_LIST_DIR`, +:variable:`CMAKE_CURRENT_FUNCTION_LIST_FILE`, +:variable:`CMAKE_CURRENT_FUNCTION_LIST_LINE` variables are not +set for macro. + .. _`Argument Caveats`: Argument Caveats diff --git a/Help/command/message.rst b/Help/command/message.rst index c614286..6bc0e4c 100644 --- a/Help/command/message.rst +++ b/Help/command/message.rst @@ -1,13 +1,33 @@ message ------- -Display a message to the user. +Log a message. + +Synopsis +^^^^^^^^ + +.. parsed-literal:: + + `General messages`_ + message([<mode>] "message text" ...) + + `Reporting checks`_ + message(<checkState> "message text" ...) + + +General messages +^^^^^^^^^^^^^^^^ .. code-block:: cmake - message([<mode>] "message to display" ...) + message([<mode>] "message text" ...) + +Record the specified message text in the log. If more than one message +string is given, they are concatenated into a single message with no +separator between the strings. -The optional ``<mode>`` keyword determines the type of message: +The optional ``<mode>`` keyword determines the type of message, which +influences the way the message is handled: ``FATAL_ERROR`` CMake Error, stop processing and generation. @@ -59,12 +79,104 @@ The :manual:`curses interface <ccmake(1)>` shows ``STATUS`` to ``TRACE`` messages one at a time on a status line and other messages in an interactive pop-up box. The ``--log-level`` command-line option to each of these tools can be used to control which messages will be shown. +To make a log level persist between CMake runs, the +:variable:`CMAKE_MESSAGE_LOG_LEVEL` variable can be set instead. +Note that the command line option takes precedence over the cache variable. -Messages of log levels ``NOTICE`` and below will also have each line preceded +Messages of log levels ``NOTICE`` and below will have each line preceded by the content of the :variable:`CMAKE_MESSAGE_INDENT` variable (converted to a single string by concatenating its list items). For ``STATUS`` to ``TRACE`` messages, this indenting content will be inserted after the hyphens. +Messages of log levels ``NOTICE`` and below can also have each line preceded +with context of the form ``[some.context.example]``. The content between the +square brackets is obtained by converting the :variable:`CMAKE_MESSAGE_CONTEXT` +list variable to a dot-separated string. The message context will always +appear before any indenting content but after any automatically added leading +hyphens. By default, message context is not shown, it has to be explicitly +enabled by giving the :manual:`cmake <cmake(1)>` ``--log-context`` +command-line option or by setting the :variable:`CMAKE_MESSAGE_CONTEXT_SHOW` +variable to true. See the :variable:`CMAKE_MESSAGE_CONTEXT` documentation for +usage examples. + CMake Warning and Error message text displays using a simple markup language. Non-indented text is formatted in line-wrapped paragraphs delimited by newlines. Indented text is considered pre-formatted. + + +Reporting checks +^^^^^^^^^^^^^^^^ + +A common pattern in CMake output is a message indicating the start of some +sort of check, followed by another message reporting the result of that check. +For example: + +.. code-block:: cmake + + message(STATUS "Looking for someheader.h") + #... do the checks, set checkSuccess with the result + if(checkSuccess) + message(STATUS "Looking for someheader.h - found") + else() + message(STATUS "Looking for someheader.h - not found") + endif() + +This can be more robustly and conveniently expressed using the ``CHECK_...`` +keyword form of the ``message()`` command: + +.. code-block:: cmake + + message(<checkState> "message" ...) + +where ``<checkState>`` must be one of the following: + + ``CHECK_START`` + Record a concise message about the check about to be performed. + + ``CHECK_PASS`` + Record a successful result for a check. + + ``CHECK_FAIL`` + Record an unsuccessful result for a check. + +When recording a check result, the command repeats the message from the most +recently started check for which no result has yet been reported, then some +separator characters and then the message text provided after the +``CHECK_PASS`` or ``CHECK_FAIL`` keyword. Check messages are always reported +at ``STATUS`` log level. + +Checks may be nested and every ``CHECK_START`` should have exactly one +matching ``CHECK_PASS`` or ``CHECK_FAIL``. +The :variable:`CMAKE_MESSAGE_INDENT` variable can also be used to add +indenting to nested checks if desired. For example: + +.. code-block:: cmake + + message(CHECK_START "Finding my things") + list(APPEND CMAKE_MESSAGE_INDENT " ") + unset(missingComponents) + + message(CHECK_START "Finding partA") + # ... do check, assume we find A + message(CHECK_PASS "found") + + message(CHECK_START "Finding partB") + # ... do check, assume we don't find B + list(APPEND missingComponents B) + message(CHECK_FAIL "not found") + + list(POP_BACK CMAKE_MESSAGE_INDENT) + if(missingComponents) + message(CHECK_FAIL "missing components: ${missingComponents}") + else() + message(CHECK_PASS "all components found") + endif() + +Output from the above would appear something like the following:: + + -- Finding my things + -- Finding partA + -- Finding partA - found + -- Finding partB + -- Finding partB - not found + -- Finding my things - missing components: B diff --git a/Help/command/project.rst b/Help/command/project.rst index 3951456..b6093d3 100644 --- a/Help/command/project.rst +++ b/Help/command/project.rst @@ -102,9 +102,12 @@ options are intended for use as default values in package metadata and documenta Code Injection ^^^^^^^^^^^^^^ -If the :variable:`CMAKE_PROJECT_INCLUDE_BEFORE` variable is set, the file -pointed to by that variable will be included as the first step of the +If the :variable:`CMAKE_PROJECT_INCLUDE_BEFORE` or +:variable:`CMAKE_PROJECT_<PROJECT-NAME>_INCLUDE_BEFORE` variables are set, +the files they point to will be included as the first step of the ``project()`` command. +If both are set, then :variable:`CMAKE_PROJECT_INCLUDE_BEFORE` will be +included before :variable:`CMAKE_PROJECT_<PROJECT-NAME>_INCLUDE_BEFORE`. If the :variable:`CMAKE_PROJECT_INCLUDE` or :variable:`CMAKE_PROJECT_<PROJECT-NAME>_INCLUDE` variables are set, the files diff --git a/Help/command/target_compile_features.rst b/Help/command/target_compile_features.rst index 9271cd5..c5401e6 100644 --- a/Help/command/target_compile_features.rst +++ b/Help/command/target_compile_features.rst @@ -8,9 +8,9 @@ Add expected compiler features to a target. target_compile_features(<target> <PRIVATE|PUBLIC|INTERFACE> <feature> [...]) Specifies compiler features required when compiling a given target. If the -feature is not listed in the :variable:`CMAKE_C_COMPILE_FEATURES` variable -or :variable:`CMAKE_CXX_COMPILE_FEATURES` variable, -then an error will be reported by CMake. If the use of the feature requires +feature is not listed in the :variable:`CMAKE_C_COMPILE_FEATURES`, +:variable:`CMAKE_CUDA_COMPILE_FEATURES`, or :variable:`CMAKE_CXX_COMPILE_FEATURES` +variables, then an error will be reported by CMake. If the use of the feature requires an additional compiler flag, such as ``-std=gnu++11``, the flag will be added automatically. diff --git a/Help/cpack_gen/nsis.rst b/Help/cpack_gen/nsis.rst index cd2aea6..dc65249 100644 --- a/Help/cpack_gen/nsis.rst +++ b/Help/cpack_gen/nsis.rst @@ -128,3 +128,24 @@ on Windows Nullsoft Scriptable Install System. set(CPACK_NSIS_MENU_LINKS "doc/cmake-@CMake_VERSION_MAJOR@.@CMake_VERSION_MINOR@/cmake.html" "CMake Help" "https://cmake.org" "CMake Web Site") + +.. variable:: CPACK_NSIS_UNINSTALL_NAME + + Specify the name of the program to uninstall the version. + Default is ``Uninstall``. + +.. variable:: CPACK_NSIS_WELCOME_TITLE + + The title to display on the top of the page for the welcome page. + +.. variable:: CPACK_NSIS_WELCOME_TITLE_3LINES + + Display the title in the welcome page on 3 lines instead of 2. + +.. variable:: CPACK_NSIS_FINISH_TITLE + + The title to display on the top of the page for the finish page. + +.. variable:: CPACK_NSIS_FINISH_TITLE_3LINES + + Display the title in the finish page on 3 lines instead of 2. diff --git a/Help/cpack_gen/packagemaker.rst b/Help/cpack_gen/packagemaker.rst index e9464b7..81acb9d 100644 --- a/Help/cpack_gen/packagemaker.rst +++ b/Help/cpack_gen/packagemaker.rst @@ -15,9 +15,60 @@ macOS using PackageMaker: compatible with. Different versions of macOS support different features. For example, CPack can only build component-based installers for macOS 10.4 or newer, and can only build installers that download - component son-the-fly for macOS 10.5 or newer. If left blank, this value + components on-the-fly for macOS 10.5 or newer. If left blank, this value will be set to the minimum version of macOS that supports the requested features. Set this variable to some value (e.g., 10.4) only if you want to guarantee that your installer will work on that version of macOS, and don't mind missing extra features available in the installer shipping with later versions of macOS. + +.. variable:: CPACK_PACKAGEMAKER_BACKGROUND + + Adds a background to Distribtion XML if specified. The value contains the + path to image in ``Resources`` directory. + +.. variable:: CPACK_PACKAGEMAKER_BACKGROUND_ALIGNMENT + + Adds an ``alignment`` attribute to the background in Distribution XML. + Refer to Apple documentation for valid values. + +.. variable:: CPACK_PACKAGEMAKER_BACKGROUND_SCALING + + Adds a ``scaling`` attribute to the background in Distribution XML. + Refer to Apple documentation for valid values. + +.. variable:: CPACK_PACKAGEMAKER_BACKGROUND_MIME_TYPE + + Adds a ``mime-type`` attribute to the background in Distribution XML. + The option contains MIME type of an image. + +.. variable:: CPACK_PACKAGEMAKER_BACKGROUND_UTI + + Adds an ``uti`` attribute to the background in Distribution XML. + The option contains UTI type of an image. + +.. variable:: CPACK_PACKAGEMAKER_BACKGROUND_DARKAQUA + + Adds a background for the Dark Aqua theme to Distribution XML if + specified. The value contains the path to image in ``Resources`` + directory. + +.. variable:: CPACK_PACKAGEMAKER_BACKGROUND_DARKAQUA_ALIGNMENT + + Does the same as :variable:`CPACK_PACKAGEMAKER_BACKGROUND_ALIGNMENT` option, + but for the dark theme. + +.. variable:: CPACK_PACKAGEMAKER_BACKGROUND_DARKAQUA_SCALING + + Does the same as :variable:`CPACK_PACKAGEMAKER_BACKGROUND_SCALING` option, + but for the dark theme. + +.. variable:: CPACK_PACKAGEMAKER_BACKGROUND_DARKAQUA_MIME_TYPE + + Does the same as :variable:`CPACK_PACKAGEMAKER_BACKGROUND_MIME_TYPE` option, + but for the dark theme. + +.. variable:: CPACK_PACKAGEMAKER_BACKGROUND_DARKAQUA_UTI + + Does the same as :variable:`CPACK_PACKAGEMAKER_BACKGROUND_UTI` option, + but for the dark theme. diff --git a/Help/cpack_gen/productbuild.rst b/Help/cpack_gen/productbuild.rst index d22fcd4..82b79ae 100644 --- a/Help/cpack_gen/productbuild.rst +++ b/Help/cpack_gen/productbuild.rst @@ -58,7 +58,6 @@ macOS using ProductBuild: component name. No ``postinstall`` script is added if this variable is not defined for a given component. - .. variable:: CPACK_PRODUCTBUILD_RESOURCES_DIR If specified the productbuild generator copies files from this directory @@ -66,3 +65,54 @@ macOS using ProductBuild: before the :variable:`CPACK_RESOURCE_FILE_WELCOME`, :variable:`CPACK_RESOURCE_FILE_README`, and :variable:`CPACK_RESOURCE_FILE_LICENSE` files are copied. + +.. variable:: CPACK_PRODUCTBUILD_BACKGROUND + + Adds a background to Distribtion XML if specified. The value contains the + path to image in ``Resources`` directory. + +.. variable:: CPACK_PRODUCTBUILD_BACKGROUND_ALIGNMENT + + Adds an ``alignment`` attribute to the background in Distribution XML. + Refer to Apple documentation for valid values. + +.. variable:: CPACK_PRODUCTBUILD_BACKGROUND_SCALING + + Adds a ``scaling`` attribute to the background in Distribution XML. + Refer to Apple documentation for valid values. + +.. variable:: CPACK_PRODUCTBUILD_BACKGROUND_MIME_TYPE + + Adds a ``mime-type`` attribute to the background in Distribution XML. + The option contains MIME type of an image. + +.. variable:: CPACK_PRODUCTBUILD_BACKGROUND_UTI + + Adds an ``uti`` attribute to the background in Distribution XML. + The option contains UTI type of an image. + +.. variable:: CPACK_PRODUCTBUILD_BACKGROUND_DARKAQUA + + Adds a background for the Dark Aqua theme to Distribution XML if + specified. The value contains the path to image in ``Resources`` + directory. + +.. variable:: CPACK_PRODUCTBUILD_BACKGROUND_DARKAQUA_ALIGNMENT + + Does the same as :variable:`CPACK_PRODUCTBUILD_BACKGROUND_ALIGNMENT` option, + but for the dark theme. + +.. variable:: CPACK_PRODUCTBUILD_BACKGROUND_DARKAQUA_SCALING + + Does the same as :variable:`CPACK_PRODUCTBUILD_BACKGROUND_SCALING` option, + but for the dark theme. + +.. variable:: CPACK_PRODUCTBUILD_BACKGROUND_DARKAQUA_MIME_TYPE + + Does the same as :variable:`CPACK_PRODUCTBUILD_BACKGROUND_MIME_TYPE` option, + but for the dark theme. + +.. variable:: CPACK_PRODUCTBUILD_BACKGROUND_DARKAQUA_UTI + + Does the same as :variable:`CPACK_PRODUCTBUILD_BACKGROUND_UTI` option, + but for the dark theme. diff --git a/Help/dev/maint.rst b/Help/dev/maint.rst index 44e2273..a1c1a6f 100644 --- a/Help/dev/maint.rst +++ b/Help/dev/maint.rst @@ -14,6 +14,11 @@ Review a Merge Request The `CMake Review Process`_ requires a maintainer to issue the ``Do: merge`` command to integrate a merge request. Please check at least the following: +* If the MR source branch (or part of it) should be backported + to the ``release`` branch (and is already based on a commit + contained in the ``release`` branch), add a ``Backport: release`` or + ``Backport: release:<commit-ish>`` trailing line to the MR description. + * If the MR source branch is not named well for the change it makes (e.g. it is just ``master`` or the patch changed during review), add a ``Topic-rename: <topic>`` trailing line to the MR description @@ -38,9 +43,10 @@ command to integrate a merge request. Please check at least the following: of various nightly builders.) * Ensure that the MR targets the ``master`` branch. A MR intended for - the ``release`` branch should be based on ``release`` but still merged - to ``master`` first (via ``Do: merge``). A maintainer may then merge - the MR topic to ``release`` manually. + the ``release`` branch should be based on ``release`` but still target + ``master``. Use the above-mentioned ``Backport: release`` line to tell + ``Do: merge`` to merge to both. If a MR is merged without the backport + line, a maintainer may still merge the MR topic to ``release`` manually. Maintain Current Release ======================== @@ -51,6 +57,12 @@ using a local branch named ``release-$ver``, where ``$ver`` is the version number of the current release in the form ``$major.$minor``. It is always merged into ``master`` before publishing. +To merge an open MR to the ``release`` branch, edit its description to +use the ``Backport: release`` line mentioned above and then ``Do: merge`` +normally. To update the ``release`` branch manually (e.g. to merge a +``$topic`` branch that was merged without the backport line), use the +following procedure. + Before merging a ``$topic`` branch into ``release``, verify that the ``$topic`` branch has already been merged to ``master`` via the usual ``Do: merge`` process. Then, to merge the ``$topic`` branch into diff --git a/Help/dev/review.rst b/Help/dev/review.rst index cbde6fe..8ec41d2 100644 --- a/Help/dev/review.rst +++ b/Help/dev/review.rst @@ -53,6 +53,10 @@ in GitLab to track the state of a MR: to a period of inactivity. See the `Expire`_ step. Use this label after closing a MR for this reason. +* ``workflow:external-discussion`` indicates that the MR has been closed + pending discussion elsewhere. See the `External Discussion`_ step. + Use this label after closing a MR for this reason. + The workflow status labels are intended to be mutually exclusive, so please remove any existing workflow label when adding one. @@ -429,6 +433,21 @@ Additionally, ``Do: merge`` extracts configuration from trailing lines in the MR description (the following have no effect if used in a MR comment instead): +* ``Backport: release[:<commit-ish>]``: merge the topic branch into + the ``release`` branch to backport the change. This is allowed + only if the topic branch is based on a commit in ``release`` already. + If only part of the topic branch should be backported, specify it as + ``:<commit-ish>``. The ``<commit-ish>`` may use `git rev-parse`_ + syntax to reference commits relative to the topic ``HEAD``. + See additional `backport instructions`_ for details. + For example: + + ``Backport: release`` + Merge the topic branch head into both ``release`` and ``master``. + ``Backport: release:HEAD~1^2`` + Merge the topic branch head's parent's second parent commit into + the ``release`` branch. Merge the topic branch head to ``master``. + * ``Topic-rename: <topic>``: substitute ``<topic>`` for the name of the MR topic branch in the constructed merge commit message. It is also used in merge commits constructed by ``Do: stage``. @@ -436,6 +455,8 @@ comment instead): rename set in the MR description. .. _`CMake GitLab Project Masters`: https://gitlab.kitware.com/cmake/cmake/settings/members +.. _`backport instructions`: https://gitlab.kitware.com/utils/git-workflow/wikis/Backport-topics +.. _`git rev-parse`: https://git-scm.com/docs/git-rev-parse Close ----- diff --git a/Help/envvar/CMAKE_EXPORT_COMPILE_COMMANDS.rst b/Help/envvar/CMAKE_EXPORT_COMPILE_COMMANDS.rst new file mode 100644 index 0000000..e9e0810 --- /dev/null +++ b/Help/envvar/CMAKE_EXPORT_COMPILE_COMMANDS.rst @@ -0,0 +1,9 @@ +CMAKE_EXPORT_COMPILE_COMMANDS +----------------------------- + +.. include:: ENV_VAR.txt + +The default value for :variable:`CMAKE_EXPORT_COMPILE_COMMANDS` when there +is no explicit configuration given on the first run while creating a new +build tree. On later runs in an existing build tree the value persists in +the cache as :variable:`CMAKE_EXPORT_COMPILE_COMMANDS`. diff --git a/Help/envvar/CMAKE_LANG_COMPILER_LAUNCHER.rst b/Help/envvar/CMAKE_LANG_COMPILER_LAUNCHER.rst new file mode 100644 index 0000000..4f91e9a --- /dev/null +++ b/Help/envvar/CMAKE_LANG_COMPILER_LAUNCHER.rst @@ -0,0 +1,10 @@ +CMAKE_<LANG>_COMPILER_LAUNCHER +------------------------------ + +.. include:: ENV_VAR.txt + +Default compiler launcher to use for the specified language. Will only be used +by CMake to initialize the variable on the first configuration. Afterwards, it +is available through the cache setting of the variable of the same name. For +any configuration run (including the first), the environment variable will be +ignored if the :variable:`CMAKE_<LANG>_COMPILER_LAUNCHER` variable is defined. diff --git a/Help/generator/Ninja Multi-Config.rst b/Help/generator/Ninja Multi-Config.rst new file mode 100644 index 0000000..71cc392 --- /dev/null +++ b/Help/generator/Ninja Multi-Config.rst @@ -0,0 +1,74 @@ +Ninja Multi-Config +------------------ + +Generates multiple ``build-<Config>.ninja`` files. + +This generator is very much like the :generator:`Ninja` generator, but with +some key differences. Only these differences will be discussed in this +document. + +Unlike the :generator:`Ninja` generator, ``Ninja Multi-Config`` generates +multiple configurations at once with :variable:`CMAKE_CONFIGURATION_TYPES` +instead of only one configuration with :variable:`CMAKE_BUILD_TYPE`. One +``build-<Config>.ninja`` file will be generated for each of these +configurations (with ``<Config>`` being the configuration name.) No +``build.ninja`` file is generated, unless +:variable:`CMAKE_NINJA_MULTI_DEFAULT_BUILD_TYPE` is specified. You must specify +the desired ``build-<Config>.ninja`` file with ``ninja -f``. Running +``cmake --build . --config <Config> --target <target>`` will run Ninja with +``build-<Config>.ninja`` as the ``-f`` file and ``<target>`` as the build +target. + +Executables and libraries of any configuration can be built regardless of which +``build-<Config>.ninja`` file is used, simply by specifying +``<target>:<Config>`` as the Ninja target. You can also specify +``<target>:all`` to build a target in all configurations. Each +``build-<Config>.ninja`` file will additionally have ``<target>`` targets which +are aliases for ``<target>:<Config>``. However, custom commands and custom +targets will always use the configuration specified in +``build-<Config>.ninja``. This is due to the fact that it is impossible in +Ninja for the same file to be output with different commands in the same build +graph. + +Consider the following example: + +.. code-block:: cmake + + cmake_minimum_required(VERSION 3.16) + project(MultiConfigNinja C) + + add_executable(generator generator.c) + add_custom_command(OUTPUT generated.c COMMAND generator generated.c) + add_library(generated ${CMAKE_BINARY_DIR}/generated.c) + +Now assume you configure the project with ``Ninja Multi-Config`` and run one of +the following commands: + +.. code-block:: shell + + ninja -f build-Debug.ninja generated + # OR + cmake --build . --config Debug --target generated + +This would build the ``Debug`` configuration of ``generator``, which would be +used to generate ``generated.c``, which would be used to build the ``Debug`` +configuration of ``generated``. + +But if you run the following instead: + +.. code-block:: shell + + ninja -f build-Release.ninja generated:Debug + # OR + cmake --build . --config Release --target generated:Debug + +This would build the ``Release`` configuration of ``generator``, which would be +used to generate ``generated.c``, which would be used to build the ``Debug`` +configuration of ``generated``. This is useful for running a release-optimized +version of a generator utility while still building the debug version of the +targets built with the generated code. + +As a convenience, ``Ninja Multi-Config`` offers a +:variable:`CMAKE_NINJA_MULTI_DEFAULT_BUILD_TYPE` setting. If this variable is +specified, a ``build.ninja`` file will be generated which points to the +specified ``build-<Config>.ninja`` file. diff --git a/Help/generator/Ninja.rst b/Help/generator/Ninja.rst index c75d2c4..275055d 100644 --- a/Help/generator/Ninja.rst +++ b/Help/generator/Ninja.rst @@ -1,7 +1,7 @@ Ninja ----- -Generates build.ninja files. +Generates ``build.ninja`` files. A ``build.ninja`` file is generated into the build tree. Use the ninja program to build the project through the ``all`` target and install the @@ -38,3 +38,9 @@ features have not been integrated into upstream Ninja. Kitware maintains a branch of Ninja with the required features on `github.com/Kitware/ninja`_. .. _`github.com/Kitware/ninja`: https://github.com/Kitware/ninja/tree/features-for-fortran#readme + +See Also +^^^^^^^^ + +The :generator:`Ninja Multi-Config` generator is similar to the ``Ninja`` +generator, but generates multiple configurations at once. diff --git a/Help/manual/cmake-compile-features.7.rst b/Help/manual/cmake-compile-features.7.rst index a14e322..05dc038 100644 --- a/Help/manual/cmake-compile-features.7.rst +++ b/Help/manual/cmake-compile-features.7.rst @@ -19,11 +19,11 @@ While features are typically specified in programming language standards, CMake provides a primary user interface based on granular handling of the features, not the language standard that introduced the feature. -The :prop_gbl:`CMAKE_C_KNOWN_FEATURES` and -:prop_gbl:`CMAKE_CXX_KNOWN_FEATURES` global properties contain all the +The :prop_gbl:`CMAKE_C_KNOWN_FEATURES`, :prop_gbl:`CMAKE_CUDA_KNOWN_FEATURES`, +and :prop_gbl:`CMAKE_CXX_KNOWN_FEATURES` global properties contain all the features known to CMake, regardless of compiler support for the feature. -The :variable:`CMAKE_C_COMPILE_FEATURES` and -:variable:`CMAKE_CXX_COMPILE_FEATURES` variables contain all features +The :variable:`CMAKE_C_COMPILE_FEATURES`, :variable:`CMAKE_CUDA_COMPILE_FEATURES` +, and :variable:`CMAKE_CXX_COMPILE_FEATURES` variables contain all features CMake knows are known to the compiler, regardless of language standard or compile flags needed to use them. @@ -368,8 +368,9 @@ versions specified for each: * all compilers and versions listed above with only meta-features for C++. * ``TI``: Texas Instruments compiler. -CMake is currently aware of the :prop_tgt:`CUDA standards <CUDA_STANDARD>` -from the following :variable:`compiler ids <CMAKE_<LANG>_COMPILER_ID>` as of the +CMake is currently aware of the :prop_tgt:`CUDA standards <CUDA_STANDARD>` and +their associated meta-features (e.g. ``cuda_std_11``) available from the +following :variable:`compiler ids <CMAKE_<LANG>_COMPILER_ID>` as of the versions specified for each: * ``NVIDIA``: NVIDIA nvcc compiler 7.5+. diff --git a/Help/manual/cmake-env-variables.7.rst b/Help/manual/cmake-env-variables.7.rst index 96ceb94..adfc39e 100644 --- a/Help/manual/cmake-env-variables.7.rst +++ b/Help/manual/cmake-env-variables.7.rst @@ -23,10 +23,12 @@ Environment Variables that Control the Build /envvar/CMAKE_BUILD_PARALLEL_LEVEL /envvar/CMAKE_CONFIG_TYPE + /envvar/CMAKE_EXPORT_COMPILE_COMMANDS /envvar/CMAKE_GENERATOR /envvar/CMAKE_GENERATOR_INSTANCE /envvar/CMAKE_GENERATOR_PLATFORM /envvar/CMAKE_GENERATOR_TOOLSET + /envvar/CMAKE_LANG_COMPILER_LAUNCHER /envvar/CMAKE_MSVCIDE_RUN_PATH /envvar/CMAKE_NO_VERBOSE /envvar/CMAKE_OSX_ARCHITECTURES diff --git a/Help/manual/cmake-file-api.7.rst b/Help/manual/cmake-file-api.7.rst index 04b6ed2..12eecd9 100644 --- a/Help/manual/cmake-file-api.7.rst +++ b/Help/manual/cmake-file-api.7.rst @@ -199,6 +199,7 @@ The reply index file contains a JSON object: "root": "/prefix/share/cmake-3.14" }, "generator": { + "multiConfig": false, "name": "Unix Makefiles" } }, @@ -267,6 +268,9 @@ The members are: A JSON object describing the CMake generator used for the build. It has members: + ``multiConfig`` + A boolean specifying whether the generator supports multiple output + configurations. ``name`` A string specifying the name of the generator. ``platform`` diff --git a/Help/manual/cmake-generator-expressions.7.rst b/Help/manual/cmake-generator-expressions.7.rst index 75f4bd4..691481b 100644 --- a/Help/manual/cmake-generator-expressions.7.rst +++ b/Help/manual/cmake-generator-expressions.7.rst @@ -596,7 +596,8 @@ Target-Dependent Queries requirement. ``$<INSTALL_PREFIX>`` Content of the install prefix when the target is exported via - :command:`install(EXPORT)` and empty otherwise. + :command:`install(EXPORT)`, or when evaluated in + :prop_tgt:`INSTALL_NAME_DIR`, and empty otherwise. Output-Related Expressions -------------------------- diff --git a/Help/manual/cmake-generators.7.rst b/Help/manual/cmake-generators.7.rst index 41f7652..6f88c0a 100644 --- a/Help/manual/cmake-generators.7.rst +++ b/Help/manual/cmake-generators.7.rst @@ -52,13 +52,14 @@ Makefile Generators /generator/Unix Makefiles /generator/Watcom WMake -Ninja Generator -^^^^^^^^^^^^^^^ +Ninja Generators +^^^^^^^^^^^^^^^^ .. toctree:: :maxdepth: 1 /generator/Ninja + /generator/Ninja Multi-Config .. _`IDE Build Tool Generators`: diff --git a/Help/manual/cmake-modules.7.rst b/Help/manual/cmake-modules.7.rst index c60dc40..be64112 100644 --- a/Help/manual/cmake-modules.7.rst +++ b/Help/manual/cmake-modules.7.rst @@ -122,6 +122,7 @@ They are normally called through the :command:`find_package` command. /module/FindCABLE /module/FindCoin3D /module/FindCups + /module/FindCUDAToolkit /module/FindCURL /module/FindCurses /module/FindCVS diff --git a/Help/manual/cmake-policies.7.rst b/Help/manual/cmake-policies.7.rst index 44ea1a8..2118031 100644 --- a/Help/manual/cmake-policies.7.rst +++ b/Help/manual/cmake-policies.7.rst @@ -51,6 +51,15 @@ The :variable:`CMAKE_MINIMUM_REQUIRED_VERSION` variable may also be used to determine whether to report an error on use of deprecated macros or functions. +Policies Introduced by CMake 3.17 +================================= + +.. toctree:: + :maxdepth: 1 + + CMP0099: Link properties are transitive over private dependency on static libraries. </policy/CMP0099> + CMP0098: FindFLEX runs flex in CMAKE_CURRENT_BINARY_DIR when executing. </policy/CMP0098> + Policies Introduced by CMake 3.16 ================================= diff --git a/Help/manual/cmake-properties.7.rst b/Help/manual/cmake-properties.7.rst index e704371..b9db12d 100644 --- a/Help/manual/cmake-properties.7.rst +++ b/Help/manual/cmake-properties.7.rst @@ -22,6 +22,7 @@ Properties of Global Scope /prop_gbl/AUTOMOC_TARGETS_FOLDER /prop_gbl/AUTORCC_SOURCE_GROUP /prop_gbl/CMAKE_C_KNOWN_FEATURES + /prop_gbl/CMAKE_CUDA_KNOWN_FEATURES /prop_gbl/CMAKE_CXX_KNOWN_FEATURES /prop_gbl/CMAKE_ROLE /prop_gbl/DEBUG_CONFIGURATIONS @@ -348,6 +349,7 @@ Properties on Targets /prop_tgt/VS_DOTNET_REFERENCES /prop_tgt/VS_DOTNET_REFERENCES_COPY_LOCAL /prop_tgt/VS_DOTNET_TARGET_FRAMEWORK_VERSION + /prop_tgt/VS_DOTNET_DOCUMENTATION_FILE /prop_tgt/VS_DPI_AWARE /prop_tgt/VS_GLOBAL_KEYWORD /prop_tgt/VS_GLOBAL_PROJECT_TYPES @@ -380,6 +382,7 @@ Properties on Targets /prop_tgt/XCODE_SCHEME_ADDRESS_SANITIZER /prop_tgt/XCODE_SCHEME_ADDRESS_SANITIZER_USE_AFTER_RETURN /prop_tgt/XCODE_SCHEME_ARGUMENTS + /prop_tgt/XCODE_SCHEME_WORKING_DIRECTORY /prop_tgt/XCODE_SCHEME_DEBUG_AS_ROOT /prop_tgt/XCODE_SCHEME_DEBUG_DOCUMENT_VERSIONING /prop_tgt/XCODE_SCHEME_DISABLE_MAIN_THREAD_CHECKER diff --git a/Help/manual/cmake-variables.7.rst b/Help/manual/cmake-variables.7.rst index 53b7f8d..d0eaa31 100644 --- a/Help/manual/cmake-variables.7.rst +++ b/Help/manual/cmake-variables.7.rst @@ -37,10 +37,15 @@ Variables that Provide Information /variable/CMAKE_CROSSCOMPILING_EMULATOR /variable/CMAKE_CTEST_COMMAND /variable/CMAKE_CURRENT_BINARY_DIR + /variable/CMAKE_CURRENT_FUNCTION + /variable/CMAKE_CURRENT_FUNCTION_LIST_DIR + /variable/CMAKE_CURRENT_FUNCTION_LIST_FILE + /variable/CMAKE_CURRENT_FUNCTION_LIST_LINE /variable/CMAKE_CURRENT_LIST_DIR /variable/CMAKE_CURRENT_LIST_FILE /variable/CMAKE_CURRENT_LIST_LINE /variable/CMAKE_CURRENT_SOURCE_DIR + /variable/CMAKE_DEBUG_TARGET_PROPERTIES /variable/CMAKE_DIRECTORY_LABELS /variable/CMAKE_DL_LIBS /variable/CMAKE_DOTNET_TARGET_FRAMEWORK_VERSION @@ -70,7 +75,6 @@ Variables that Provide Information /variable/CMAKE_MAKE_PROGRAM /variable/CMAKE_MATCH_COUNT /variable/CMAKE_MATCH_n - /variable/CMAKE_MESSAGE_INDENT /variable/CMAKE_MINIMUM_REQUIRED_VERSION /variable/CMAKE_MINOR_VERSION /variable/CMAKE_NETRC @@ -155,7 +159,6 @@ Variables that Change Behavior /variable/CMAKE_CODELITE_USE_TARGETS /variable/CMAKE_COLOR_MAKEFILE /variable/CMAKE_CONFIGURATION_TYPES - /variable/CMAKE_DEBUG_TARGET_PROPERTIES /variable/CMAKE_DEPENDS_IN_PROJECT_ONLY /variable/CMAKE_DISABLE_FIND_PACKAGE_PackageName /variable/CMAKE_ECLIPSE_GENERATE_LINKED_RESOURCES @@ -206,7 +209,12 @@ Variables that Change Behavior /variable/CMAKE_LINK_DIRECTORIES_BEFORE /variable/CMAKE_MFC_FLAG /variable/CMAKE_MAXIMUM_RECURSION_DEPTH + /variable/CMAKE_MESSAGE_CONTEXT + /variable/CMAKE_MESSAGE_CONTEXT_SHOW + /variable/CMAKE_MESSAGE_INDENT + /variable/CMAKE_MESSAGE_LOG_LEVEL /variable/CMAKE_MODULE_PATH + /variable/CMAKE_NINJA_MULTI_DEFAULT_BUILD_TYPE /variable/CMAKE_POLICY_DEFAULT_CMPNNNN /variable/CMAKE_POLICY_WARNING_CMPNNNN /variable/CMAKE_PREFIX_PATH @@ -214,6 +222,7 @@ Variables that Change Behavior /variable/CMAKE_PROJECT_INCLUDE /variable/CMAKE_PROJECT_INCLUDE_BEFORE /variable/CMAKE_PROJECT_PROJECT-NAME_INCLUDE + /variable/CMAKE_PROJECT_PROJECT-NAME_INCLUDE_BEFORE /variable/CMAKE_SKIP_INSTALL_ALL_DEPENDENCY /variable/CMAKE_STAGING_PREFIX /variable/CMAKE_SUBLIME_TEXT_2_ENV_SETTINGS @@ -235,10 +244,12 @@ Variables that Change Behavior /variable/CMAKE_XCODE_GENERATE_TOP_LEVEL_PROJECT_ONLY /variable/CMAKE_XCODE_SCHEME_ADDRESS_SANITIZER /variable/CMAKE_XCODE_SCHEME_ADDRESS_SANITIZER_USE_AFTER_RETURN + /variable/CMAKE_XCODE_SCHEME_WORKING_DIRECTORY /variable/CMAKE_XCODE_SCHEME_DEBUG_DOCUMENT_VERSIONING /variable/CMAKE_XCODE_SCHEME_DISABLE_MAIN_THREAD_CHECKER /variable/CMAKE_XCODE_SCHEME_DYNAMIC_LIBRARY_LOADS /variable/CMAKE_XCODE_SCHEME_DYNAMIC_LINKER_API_USAGE + /variable/CMAKE_XCODE_SCHEME_ENVIRONMENT /variable/CMAKE_XCODE_SCHEME_GUARD_MALLOC /variable/CMAKE_XCODE_SCHEME_MAIN_THREAD_CHECKER_STOP /variable/CMAKE_XCODE_SCHEME_MALLOC_GUARD_EDGES @@ -466,6 +477,7 @@ Variables for Languages /variable/CMAKE_COMPILER_IS_GNUCC /variable/CMAKE_COMPILER_IS_GNUCXX /variable/CMAKE_COMPILER_IS_GNUG77 + /variable/CMAKE_CUDA_COMPILE_FEATURES /variable/CMAKE_CUDA_HOST_COMPILER /variable/CMAKE_CUDA_EXTENSIONS /variable/CMAKE_CUDA_STANDARD diff --git a/Help/manual/cmake.1.rst b/Help/manual/cmake.1.rst index 4ab55a0..6f33866 100644 --- a/Help/manual/cmake.1.rst +++ b/Help/manual/cmake.1.rst @@ -206,9 +206,24 @@ Options The :command:`message` command will only output messages of the specified log level or higher. The default log level is ``STATUS``. + To make a log level persist between CMake runs, set + :variable:`CMAKE_MESSAGE_LOG_LEVEL` as a cache variable instead. + If both the command line option and the variable are given, the command line + option takes precedence. + For backward compatibility reasons, ``--loglevel`` is also accepted as a synonym for this option. +``--log-context`` + Enable the :command:`message` command outputting context attached to each + message. + + This option turns on showing context for the current CMake run only. + To make showing the context persistent for all subsequent CMake runs, set + :variable:`CMAKE_MESSAGE_CONTEXT_SHOW` as a cache variable instead. + When this command line option is given, :variable:`CMAKE_MESSAGE_CONTEXT_SHOW` + is ignored. + ``--debug-trycompile`` Do not delete the :command:`try_compile` build tree. Only useful on one :command:`try_compile` at a time. @@ -539,22 +554,38 @@ Available commands are: 7a0b54896fe5e70cca6dd643ad6f672614b189bf26f8153061c4d219474b05dad08c4e729af9f4b009f1a1a280cb625454bf587c690f4617c27e3aebdf3b7a2d file2.txt ``remove [-f] <file>...`` - Remove the file(s). If any of the listed files already do not - exist, the command returns a non-zero exit code, but no message - is logged. The ``-f`` option changes the behavior to return a + .. deprecated:: 3.17 + + Remove the file(s). The planned behaviour was that if any of the + listed files already do not exist, the command returns a non-zero exit code, + but no message is logged. The ``-f`` option changes the behavior to return a zero exit code (i.e. success) in such situations instead. ``remove`` does not follow symlinks. That means it remove only symlinks and not files it point to. + The implementation was buggy and always returned 0. It cannot be fixed without + breaking backwards compatibility. Use ``rm`` instead. + ``remove_directory <dir>...`` - Remove ``<dir>`` directories and their contents. If a directory does + .. deprecated:: 3.17 + + Remove ``<dir>`` directories and their contents. If a directory does not exist it will be silently ignored. If ``<dir>`` is a symlink to a directory, just the symlink will be removed. + Use ``rm`` instead. ``rename <oldname> <newname>`` Rename a file or directory (on one volume). If file with the ``<newname>`` name already exists, then it will be silently replaced. +``rm [-rRf] <file> <dir>...`` + Remove the files ``<file>`` or directories ``dir``. + Use ``-r`` or ``-R`` to remove directories and their contents recursively. + If any of the listed files/directories do not exist, the command returns a + non-zero exit code, but no message is logged. The ``-f`` option changes + the behavior to return a zero exit code (i.e. success) in such + situations instead. + ``server`` Launch :manual:`cmake-server(7)` mode. diff --git a/Help/manual/ctest.1.rst b/Help/manual/ctest.1.rst index e29ebca..25cb639 100644 --- a/Help/manual/ctest.1.rst +++ b/Help/manual/ctest.1.rst @@ -261,10 +261,27 @@ Options fail, subsequent calls to CTest with the ``--rerun-failed`` option will run the set of tests that most recently failed (if any). -``--repeat-until-fail <n>`` - Require each test to run ``<n>`` times without failing in order to pass. +``--repeat <mode>:<n>`` + Run tests repeatedly based on the given ``<mode>`` up to ``<n>`` times. + The modes are: + + ``until-fail`` + Require each test to run ``<n>`` times without failing in order to pass. + This is useful in finding sporadic failures in test cases. + + ``until-pass`` + Allow each test to run up to ``<n>`` times in order to pass. + Repeats tests if they fail for any reason. + This is useful in tolerating sporadic failures in test cases. - This is useful in finding sporadic failures in test cases. + ``after-timeout`` + Allow each test to run up to ``<n>`` times in order to pass. + Repeats tests only if they timeout. + This is useful in tolerating sporadic timeouts in test cases + on busy machines. + +``--repeat-until-fail <n>`` + Equivalent to ``--repeat until-fail:<n>``. ``--max-width <width>`` Set the max width for a test name to output. @@ -1096,6 +1113,20 @@ Additional configuration settings include: * `CTest Script`_ variable: none * :module:`CTest` module variable: ``VALGRIND_COMMAND_OPTIONS`` +``DrMemoryCommand`` + Specify a ``MemoryCheckCommand`` that is known to be a command-line + compatible with DrMemory. + + * `CTest Script`_ variable: none + * :module:`CTest` module variable: ``DRMEMORY_COMMAND`` + +``DrMemoryCommandOptions`` + Specify command-line options to the ``DrMemoryCommand`` tool. + They will be placed prior to the test command line. + + * `CTest Script`_ variable: none + * :module:`CTest` module variable: ``DRMEMORY_COMMAND_OPTIONS`` + .. _`CTest Submit Step`: CTest Submit Step diff --git a/Help/module/FindCUDAToolkit.rst b/Help/module/FindCUDAToolkit.rst new file mode 100644 index 0000000..5f01d68 --- /dev/null +++ b/Help/module/FindCUDAToolkit.rst @@ -0,0 +1 @@ +.. cmake-module:: ../../Modules/FindCUDAToolkit.cmake diff --git a/Help/policy/CMP0098.rst b/Help/policy/CMP0098.rst new file mode 100644 index 0000000..6d1443b --- /dev/null +++ b/Help/policy/CMP0098.rst @@ -0,0 +1,30 @@ +CMP0098 +------- + +:module:`FindFLEX` runs ``flex`` in directory +:variable:`CMAKE_CURRENT_BINARY_DIR` when executing. + +The module provides a ``FLEX_TARGET`` macro which generates FLEX output. +In CMake 3.16 and below the macro would generate a custom command that runs +``flex`` in the current source directory. CMake 3.17 and later prefer to +run it in the build directory and use :variable:`CMAKE_CURRENT_BINARY_DIR` +as the ``WORKING_DIRECTORY`` of its :command:`add_custom_command` invocation. +This ensures that any implicitly generated file is written relative to the +build tree rather than the source tree, unless the generated file is +provided as absolute path. + +This policy provides compatibility for projects that have not been updated +to expect the new behavior. + +The ``OLD`` behavior for this policy is for ``FLEX_TARGET`` to use +the current source directory for the ``WORKING_DIRECTORY`` and where +to generate implicit files. The ``NEW`` behavior of this policy is to +use the current binary directory for the ``WORKING_DIRECTORY`` relative to +which implicit files are generated unless provided as absolute path. + +This policy was introduced in CMake version 3.17. Use the +:command:`cmake_policy` command to set it to ``OLD`` or ``NEW`` explicitly. +Unlike many policies, CMake version |release| does *not* warn +when this policy is not set and simply uses ``OLD`` behavior. + +.. include:: DEPRECATED.txt diff --git a/Help/policy/CMP0099.rst b/Help/policy/CMP0099.rst new file mode 100644 index 0000000..c897e7b --- /dev/null +++ b/Help/policy/CMP0099.rst @@ -0,0 +1,24 @@ +CMP0099 +------- + +Target link properties :prop_tgt:`INTERFACE_LINK_OPTIONS`, +:prop_tgt:`INTERFACE_LINK_DIRECTORIES` and :prop_tgt:`INTERFACE_LINK_DEPENDS` +are now transitive over private dependencies of static libraries. + +In CMake 3.16 and below the interface link properties attached to libraries +are not propagated for private dependencies of static libraries. +Only the libraries themselves are propagated to link the dependent binary. +CMake 3.17 and later prefer to propagate all interface link properties. +This policy provides compatibility for projects that have not been updated +to expect the new behavior. + +The ``OLD`` behavior for this policy is to not propagate interface link +properties. The ``NEW`` behavior of this policy is to propagate interface link +properties. + +This policy was introduced in CMake version 3.17. Use the +:command:`cmake_policy` command to set it to ``OLD`` or ``NEW`` explicitly. +Unlike many policies, CMake version |release| does *not* warn +when this policy is not set and simply uses ``OLD`` behavior. + +.. include:: DEPRECATED.txt diff --git a/Help/prop_gbl/CMAKE_CUDA_KNOWN_FEATURES.rst b/Help/prop_gbl/CMAKE_CUDA_KNOWN_FEATURES.rst new file mode 100644 index 0000000..44e37fe --- /dev/null +++ b/Help/prop_gbl/CMAKE_CUDA_KNOWN_FEATURES.rst @@ -0,0 +1,30 @@ +CMAKE_CUDA_KNOWN_FEATURES +------------------------- + +List of CUDA features known to this version of CMake. + +The features listed in this global property may be known to be available to the +CUDA compiler. If the feature is available with the C++ compiler, it will +be listed in the :variable:`CMAKE_CUDA_COMPILE_FEATURES` variable. + +The features listed here may be used with the :command:`target_compile_features` +command. See the :manual:`cmake-compile-features(7)` manual for information on +compile features and a list of supported compilers. + + +The features known to this version of CMake are: + +``cuda_std_03`` + Compiler mode is at least CUDA/C++ 03. + +``cuda_std_11`` + Compiler mode is at least CUDA/C++ 11. + +``cuda_std_14`` + Compiler mode is at least CUDA/C++ 14. + +``cuda_std_17`` + Compiler mode is at least CUDA/C++ 17. + +``cuda_std_20`` + Compiler mode is at least CUDA/C++ 20. diff --git a/Help/prop_tgt/COMPILE_FEATURES.rst b/Help/prop_tgt/COMPILE_FEATURES.rst index 195215e..46aec4f 100644 --- a/Help/prop_tgt/COMPILE_FEATURES.rst +++ b/Help/prop_tgt/COMPILE_FEATURES.rst @@ -4,7 +4,8 @@ COMPILE_FEATURES Compiler features enabled for this target. The list of features in this property are a subset of the features listed -in the :variable:`CMAKE_CXX_COMPILE_FEATURES` variable. +in the :variable:`CMAKE_C_COMPILE_FEATURES`, :variable:`CMAKE_CUDA_COMPILE_FEATURES`, and +:variable:`CMAKE_CXX_COMPILE_FEATURES` variables. Contents of ``COMPILE_FEATURES`` may use "generator expressions" with the syntax ``$<...>``. See the :manual:`cmake-generator-expressions(7)` manual for diff --git a/Help/prop_tgt/INSTALL_NAME_DIR.rst b/Help/prop_tgt/INSTALL_NAME_DIR.rst index 2216072..747615a 100644 --- a/Help/prop_tgt/INSTALL_NAME_DIR.rst +++ b/Help/prop_tgt/INSTALL_NAME_DIR.rst @@ -10,3 +10,7 @@ installed targets. This property is initialized by the value of the variable :variable:`CMAKE_INSTALL_NAME_DIR` if it is set when a target is created. + +This property supports :manual:`generator expressions <cmake-generator-expressions(7)>`. +In particular, the ``$<INSTALL_PREFIX>`` generator expression can be used to set the +directory relative to the install-time prefix. diff --git a/Help/prop_tgt/INSTALL_RPATH_USE_LINK_PATH.rst b/Help/prop_tgt/INSTALL_RPATH_USE_LINK_PATH.rst index d8be954..d16a7a1 100644 --- a/Help/prop_tgt/INSTALL_RPATH_USE_LINK_PATH.rst +++ b/Help/prop_tgt/INSTALL_RPATH_USE_LINK_PATH.rst @@ -3,8 +3,12 @@ INSTALL_RPATH_USE_LINK_PATH Add paths to linker search and installed rpath. -``INSTALL_RPATH_USE_LINK_PATH`` is a boolean that if set to ``True`` will -append directories in the linker search path and outside the project -to the :prop_tgt:`INSTALL_RPATH`. This property is initialized by the value of -the variable ``CMAKE_INSTALL_RPATH_USE_LINK_PATH`` if it is set when a -target is created. +``INSTALL_RPATH_USE_LINK_PATH`` is a boolean that if set to ``True`` +will append to the runtime search path (rpath) of installed binaries +any directories outside the project that are in the linker search path or +contain linked library files. The directories are appended after the +value of the :prop_tgt:`INSTALL_RPATH` target property. + +This property is initialized by the value of the variable +:variable:`CMAKE_INSTALL_RPATH_USE_LINK_PATH` if it is set when a target is +created. diff --git a/Help/prop_tgt/VS_DOTNET_DOCUMENTATION_FILE.rst b/Help/prop_tgt/VS_DOTNET_DOCUMENTATION_FILE.rst new file mode 100644 index 0000000..1bc361c --- /dev/null +++ b/Help/prop_tgt/VS_DOTNET_DOCUMENTATION_FILE.rst @@ -0,0 +1,6 @@ +VS_DOTNET_DOCUMENTATION_FILE +---------------------------- + +Visual Studio managed project .NET documentation output + +Sets the target XML documentation file output. diff --git a/Help/prop_tgt/XCODE_SCHEME_WORKING_DIRECTORY.rst b/Help/prop_tgt/XCODE_SCHEME_WORKING_DIRECTORY.rst new file mode 100644 index 0000000..7ffa74b --- /dev/null +++ b/Help/prop_tgt/XCODE_SCHEME_WORKING_DIRECTORY.rst @@ -0,0 +1,13 @@ +XCODE_SCHEME_WORKING_DIRECTORY +------------------------------ + +Specify the ``Working Directory`` a of the `Run` and `Profile` +action in the generated Xcode scheme. In case the value contains +generator expressions those are evaluated. + +This property is initialized by the value of the variable +:variable:`CMAKE_XCODE_SCHEME_WORKING_DIRECTORY` if it is set +when a target is created. + +Please refer to the :prop_tgt:`XCODE_GENERATE_SCHEME` target property +documentation to see all Xcode schema related properties. diff --git a/Help/release/dev/0-sample-topic.rst b/Help/release/dev/0-sample-topic.rst new file mode 100644 index 0000000..e4cc01e --- /dev/null +++ b/Help/release/dev/0-sample-topic.rst @@ -0,0 +1,7 @@ +0-sample-topic +-------------- + +* This is a sample release note for the change in a topic. + Developers should add similar notes for each topic branch + making a noteworthy change. Each document should be named + and titled to match the topic name to avoid merge conflicts. diff --git a/Help/release/dev/CMAKE_CURRENT_FUNCTION.rst b/Help/release/dev/CMAKE_CURRENT_FUNCTION.rst new file mode 100644 index 0000000..a15e63d --- /dev/null +++ b/Help/release/dev/CMAKE_CURRENT_FUNCTION.rst @@ -0,0 +1,9 @@ +CMAKE_CURRENT_FUNCTION +---------------------- + +* Define the following variables inside a function: + + - :variable:`CMAKE_CURRENT_FUNCTION` + - :variable:`CMAKE_CURRENT_FUNCTION_LIST_DIR` + - :variable:`CMAKE_CURRENT_FUNCTION_LIST_FILE` + - :variable:`CMAKE_CURRENT_FUNCTION_LIST_LINE` diff --git a/Help/release/dev/ExternalProject-git-no-recurse.rst b/Help/release/dev/ExternalProject-git-no-recurse.rst new file mode 100644 index 0000000..b9e09d3 --- /dev/null +++ b/Help/release/dev/ExternalProject-git-no-recurse.rst @@ -0,0 +1,7 @@ +ExternalProject-git-no-recurse +------------------------------ + +* The :module:`ExternalProject` module :command:`ExternalProject_Add` + command gained a ``GIT_SUBMODULES_RECURSE`` option to specify whether + Git submodules should be updated recursively. The default is on to + preserve existing behavior. diff --git a/Help/release/dev/FindCUDAToolkit-module.rst b/Help/release/dev/FindCUDAToolkit-module.rst new file mode 100644 index 0000000..53a69c6 --- /dev/null +++ b/Help/release/dev/FindCUDAToolkit-module.rst @@ -0,0 +1,4 @@ +FindCUDAToolkit-module +---------------------- + +* The :module:`FindCUDAToolkit` module was added to find the CUDA Toolkit without enabling CUDA as a language. diff --git a/Help/release/dev/FindCURL-cmake-package.rst b/Help/release/dev/FindCURL-cmake-package.rst new file mode 100644 index 0000000..67c5bbc --- /dev/null +++ b/Help/release/dev/FindCURL-cmake-package.rst @@ -0,0 +1,7 @@ +FindCURL-cmake-package +---------------------- + +* The :module:`FindCURL` module learned to find CURL using + the ``CURLConfig.cmake`` package configuration file generated by + CURL's cmake buildsystem. It also gained a new ``CURL_NO_CURL_CMAKE`` + option to disable this behavior. diff --git a/Help/release/dev/FindFLEX-work-dir.rst b/Help/release/dev/FindFLEX-work-dir.rst new file mode 100644 index 0000000..3569185 --- /dev/null +++ b/Help/release/dev/FindFLEX-work-dir.rst @@ -0,0 +1,6 @@ +FindFLEX-work-dir +----------------- + +* The :module:`FindFLEX` module's ``FLEX_TARGET`` command now runs ``flex`` + with :variable:`CMAKE_CURRENT_BINARY_DIR` as the working directory. + See policy :policy:`CMP0098`. diff --git a/Help/release/dev/FindLibArchive-target.rst b/Help/release/dev/FindLibArchive-target.rst new file mode 100644 index 0000000..8998dae --- /dev/null +++ b/Help/release/dev/FindLibArchive-target.rst @@ -0,0 +1,5 @@ +FindLibArchive-target +--------------------- + +* The :module:`FindLibArchive` module now returns an ``IMPORTED`` target + for libarchive. diff --git a/Help/release/dev/Link-properties-transitive.rst b/Help/release/dev/Link-properties-transitive.rst new file mode 100644 index 0000000..535b40c --- /dev/null +++ b/Help/release/dev/Link-properties-transitive.rst @@ -0,0 +1,8 @@ +Link-properties-transitive +-------------------------- + +* Target link properties :prop_tgt:`INTERFACE_LINK_OPTIONS`, + :prop_tgt:`INTERFACE_LINK_DIRECTORIES` and + :prop_tgt:`INTERFACE_LINK_DEPENDS` are now transitive over private + dependency on static libraries. + See policy :policy:`CMP0099`. diff --git a/Help/release/dev/ccmake-colored-values.rst b/Help/release/dev/ccmake-colored-values.rst new file mode 100644 index 0000000..b00885d --- /dev/null +++ b/Help/release/dev/ccmake-colored-values.rst @@ -0,0 +1,5 @@ +ccmake-colored-values +--------------------- + +* :manual:`ccmake(1)` now displays cache values using colors + based on the entry type if the terminal supports color. diff --git a/Help/release/dev/ccmake_progress_bar_and_log_display.rst b/Help/release/dev/ccmake_progress_bar_and_log_display.rst new file mode 100644 index 0000000..5c67c7d --- /dev/null +++ b/Help/release/dev/ccmake_progress_bar_and_log_display.rst @@ -0,0 +1,6 @@ +ccmake_progress_bar_and_log_display +----------------------------------- + +* :manual:`ccmake(1)` now displays messages and a progress bar during + configure and generate. It will keep the output displayed if any + errors or warnings occurred. diff --git a/Help/release/dev/command_rm.rst b/Help/release/dev/command_rm.rst new file mode 100644 index 0000000..a58362e --- /dev/null +++ b/Help/release/dev/command_rm.rst @@ -0,0 +1,12 @@ +Command-Line +-------------------- + +* :manual:`cmake(1)` gained a ``rm`` command line + option that can be used to remove directories (with ``-r`` or ``-R`` flag) + and files. + If the ``-f`` flag is not specified, attempting to remove a file that + doesn't exist returns an non-zero error code. + This command deprecates ``remove`` and ``remove_directory``. + The ``remove`` implementation was buggy and always returned 0 when ``force`` + flag was not present and a file didn't exist. It cannot be fixed without + breaking backwards compatibility so we introduced ``rm``. diff --git a/Help/release/dev/compiler-launcher-env.rst b/Help/release/dev/compiler-launcher-env.rst new file mode 100644 index 0000000..58519d9 --- /dev/null +++ b/Help/release/dev/compiler-launcher-env.rst @@ -0,0 +1,5 @@ +compiler-launcher-env +--------------------- + +* The :envvar:`CMAKE_<LANG>_COMPILER_LAUNCHER` environment variable may now be + used to initialize the :variable:`CMAKE_<LANG>_COMPILER_LAUNCHER` variable. diff --git a/Help/release/dev/cpack-nsis-uninstaller-name.rst b/Help/release/dev/cpack-nsis-uninstaller-name.rst new file mode 100644 index 0000000..b7ceb4c --- /dev/null +++ b/Help/release/dev/cpack-nsis-uninstaller-name.rst @@ -0,0 +1,6 @@ +cpack-nsis-uninstaller-name +--------------------------- + +* The :cpack_gen:`CPack NSIS Generator` now supports + :variable:`CPACK_NSIS_UNINSTALL_NAME`. + This can be used to specify the name of the Uninstall program. diff --git a/Help/release/dev/cpack-nsis-welcome-finish-page-title.rst b/Help/release/dev/cpack-nsis-welcome-finish-page-title.rst new file mode 100644 index 0000000..8091d31 --- /dev/null +++ b/Help/release/dev/cpack-nsis-welcome-finish-page-title.rst @@ -0,0 +1,10 @@ +cpack-nsis-welcome-finish-page-title +------------------------------------ + +* The :cpack_gen:`CPack NSIS Generator` now supports + :variable:`CPACK_NSIS_WELCOME_TITLE` and :variable:`CPACK_NSIS_WELCOME_TITLE_3LINES`. + These can be used to specify the welcome page title and display it in 3 lines. + +* The :cpack_gen:`CPack NSIS Generator` now supports + :variable:`CPACK_NSIS_FINISH_TITLE` and :variable:`CPACK_NSIS_FINISH_TITLE_3LINES`. + These can be used to specify the finish page title and display it in 3 lines. diff --git a/Help/release/dev/cpack-pkg-background.rst b/Help/release/dev/cpack-pkg-background.rst new file mode 100644 index 0000000..796f5d6 --- /dev/null +++ b/Help/release/dev/cpack-pkg-background.rst @@ -0,0 +1,8 @@ +cpack-pkg-background +-------------------- + +* The :cpack_gen:`CPack productbuild Generator` and + :cpack_gen:`CPack PackageMaker Generator` gained options + :variable:`CPACK_PRODUCTBUILD_BACKGROUND` and + :variable:`CPACK_PACKAGEMAKER_BACKGROUND`, respectively, + to specify a background image for the macOS installer. diff --git a/Help/release/dev/ctest-configuration-type.rst b/Help/release/dev/ctest-configuration-type.rst new file mode 100644 index 0000000..89e36c4 --- /dev/null +++ b/Help/release/dev/ctest-configuration-type.rst @@ -0,0 +1,5 @@ +ctest-configuration-type +------------------------ + +* The :variable:`CTEST_CONFIGURATION_TYPE` variable is now set from the command + line when :manual:`ctest(1)` is invoked with ``-C <cfg>``. diff --git a/Help/release/dev/ctest-drmemory-support.rst b/Help/release/dev/ctest-drmemory-support.rst new file mode 100644 index 0000000..b329995 --- /dev/null +++ b/Help/release/dev/ctest-drmemory-support.rst @@ -0,0 +1,5 @@ +ctest-drmemory-support +---------------------- + +* The :manual:`ctest(1)` gained support for Dr. Memory to run + memcheck runs. diff --git a/Help/release/dev/ctest-repeat.rst b/Help/release/dev/ctest-repeat.rst new file mode 100644 index 0000000..b1ff59b --- /dev/null +++ b/Help/release/dev/ctest-repeat.rst @@ -0,0 +1,10 @@ +ctest-repeat +------------ + +* The :manual:`ctest(1)` tool gained a ``--repeat <mode>:<n>`` option + to specify conditions in which to repeat tests. This generalizes + the existing ``--repeat-until-fail <n>`` option to add modes for + ``until-pass`` and ``after-timeout``. + +* The :command:`ctest_test` command gained a ``REPEAT <mode>:<n>`` option + to specify conditions in which to repeat tests. diff --git a/Help/release/dev/cuda-gains-meta-features.rst b/Help/release/dev/cuda-gains-meta-features.rst new file mode 100644 index 0000000..e5e1022 --- /dev/null +++ b/Help/release/dev/cuda-gains-meta-features.rst @@ -0,0 +1,7 @@ +cuda-gains-meta-features +------------------------ + +* The :manual:`Compile Features <cmake-compile-features(7)>` functionality + now offers meta-features for the CUDA language standard levels + (e.g. ``cuda_std_03``, ``cuda_std_14``). See + :prop_gbl:`CMAKE_CUDA_KNOWN_FEATURES`. diff --git a/Help/release/dev/deprecate-policy-old.rst b/Help/release/dev/deprecate-policy-old.rst new file mode 100644 index 0000000..401f4b2 --- /dev/null +++ b/Help/release/dev/deprecate-policy-old.rst @@ -0,0 +1,8 @@ +deprecate-policy-old +-------------------- + +* An explicit deprecation diagnostic was added for policy ``CMP0068`` + and policy ``CMP0069`` (``CMP0067`` and below were already deprecated). + The :manual:`cmake-policies(7)` manual explains that the OLD behaviors + of all policies are deprecated and that projects should port to the + NEW behaviors. diff --git a/Help/release/dev/export-compile-commands-environment-variable.rst b/Help/release/dev/export-compile-commands-environment-variable.rst new file mode 100644 index 0000000..da9d66b --- /dev/null +++ b/Help/release/dev/export-compile-commands-environment-variable.rst @@ -0,0 +1,6 @@ +export-compile-commands-environment-variable +-------------------------------------------- + +* The :variable:`CMAKE_EXPORT_COMPILE_COMMANDS` variable now takes its + initial value from the :envvar:`CMAKE_EXPORT_COMPILE_COMMANDS` environment + variable if no explicit configuration is given. diff --git a/Help/release/dev/feature-CMAKE_MESSAGE_CONTEXT.rst b/Help/release/dev/feature-CMAKE_MESSAGE_CONTEXT.rst new file mode 100644 index 0000000..a6a5c71 --- /dev/null +++ b/Help/release/dev/feature-CMAKE_MESSAGE_CONTEXT.rst @@ -0,0 +1,11 @@ +feature-CMAKE_MESSAGE_CONTEXT +----------------------------- + +* The :variable:`CMAKE_MESSAGE_LOG_LEVEL` variable can now be used + to persist a log level between CMake runs, unlike the ``--log-level`` + command line option which only applies to that particular run. + +* The :command:`message` command learned to output context provided in + the :variable:`CMAKE_MESSAGE_CONTEXT` variable for log levels + ``NOTICE`` and below. Enable this output with the new ``--log-context`` + command-line option or :variable:`CMAKE_MESSAGE_CONTEXT_SHOW` variable. diff --git a/Help/release/dev/fileapi-multi-config.rst b/Help/release/dev/fileapi-multi-config.rst new file mode 100644 index 0000000..e0e2e16 --- /dev/null +++ b/Help/release/dev/fileapi-multi-config.rst @@ -0,0 +1,6 @@ +fileapi-multi-config +-------------------- + +* The :manual:`file API <cmake-file-api(7)>` index file now emits a + ``multiConfig`` flag specifying whether or not the generator supports + multiple output configurations. diff --git a/Help/release/dev/foreach-ZIP_LISTS.rst b/Help/release/dev/foreach-ZIP_LISTS.rst new file mode 100644 index 0000000..d45d9b9 --- /dev/null +++ b/Help/release/dev/foreach-ZIP_LISTS.rst @@ -0,0 +1,5 @@ +foreach-ZIP_LISTS +----------------- + +* The :command:`foreach` learned a new option ``ZIP_LISTS`` to iterate + over multiple lists simultaneously. diff --git a/Help/release/dev/install-name-dir-genex.rst b/Help/release/dev/install-name-dir-genex.rst new file mode 100644 index 0000000..0cb41f0 --- /dev/null +++ b/Help/release/dev/install-name-dir-genex.rst @@ -0,0 +1,7 @@ +install-name-dir-genex +---------------------- + +* The :prop_tgt:`INSTALL_NAME_DIR` target property now supports + :manual:`generator expressions <cmake-generator-expressions(7)>`. + In particular, the ``$<INSTALL_PREFIX>`` generator expression can + be used to set the directory relative to the install-time prefix. diff --git a/Help/release/dev/load_cache-script-mode.rst b/Help/release/dev/load_cache-script-mode.rst new file mode 100644 index 0000000..d84b08a --- /dev/null +++ b/Help/release/dev/load_cache-script-mode.rst @@ -0,0 +1,5 @@ +load_cache-script-mode +---------------------- + +* The :command:`load_cache(READ_WITH_PREFIX)` command mode is now allowed + when using ``cmake -P`` to :ref:`Run a Script <Script Processing Mode>`. diff --git a/Help/release/dev/mingw_no_sh.rst b/Help/release/dev/mingw_no_sh.rst new file mode 100644 index 0000000..7008865 --- /dev/null +++ b/Help/release/dev/mingw_no_sh.rst @@ -0,0 +1,5 @@ +mingw-no-sh +----------- + +* The :generator:`MinGW Makefiles` generator no longer issues an error if + ``sh.exe`` is present in the environment's ``PATH``. diff --git a/Help/release/dev/multi-configuration-ninja.rst b/Help/release/dev/multi-configuration-ninja.rst new file mode 100644 index 0000000..d9f72cb --- /dev/null +++ b/Help/release/dev/multi-configuration-ninja.rst @@ -0,0 +1,6 @@ +multi-configuration-ninja +------------------------- + +* :manual:`cmake(1)` gained a :generator:`Ninja Multi-Config` generator, + which is similar to the :generator:`Ninja` generator but can be used to build + multiple configurations at once. diff --git a/Help/release/dev/new-message-types.rst b/Help/release/dev/new-message-types.rst new file mode 100644 index 0000000..8f164b9 --- /dev/null +++ b/Help/release/dev/new-message-types.rst @@ -0,0 +1,5 @@ +new-message-types +----------------- + +* The :command:`message` command gained new keywords ``CHECK_START``, + ``CHECK_PASS`` and ``CHECK_FAIL``. diff --git a/Help/release/dev/ninja-tool.rst b/Help/release/dev/ninja-tool.rst new file mode 100644 index 0000000..aa0292e --- /dev/null +++ b/Help/release/dev/ninja-tool.rst @@ -0,0 +1,7 @@ +ninja-tool +---------- + +* The :generator:`Ninja` generator now prefers the first ninja build + tool to appear in the ``PATH`` no matter whether it is called + ``ninja-build``, ``ninja``, or ``samu``. Previously the first + of those names to appear anywhere in the ``PATH`` would be preferred. diff --git a/Help/release/dev/sdcc-new-librarian.rst b/Help/release/dev/sdcc-new-librarian.rst new file mode 100644 index 0000000..93961ce --- /dev/null +++ b/Help/release/dev/sdcc-new-librarian.rst @@ -0,0 +1,6 @@ +sdcc-new-librarian +------------------ + +* Since sdcc 3.2.0, sdcclib has been deprecated in favor of sdar as librarian. + Since sdcc 3.8.6, it has been removed from the distribution. + Use sdar if found, else use sdcclib to keep older compatibility. diff --git a/Help/release/dev/vs-per-config-sources.rst b/Help/release/dev/vs-per-config-sources.rst new file mode 100644 index 0000000..bf7572b --- /dev/null +++ b/Help/release/dev/vs-per-config-sources.rst @@ -0,0 +1,5 @@ +vs-per-config-sources +--------------------- + +* :ref:`Visual Studio Generators` learned to support per-config sources. + Previously only :ref:`Command-Line Build Tool Generators` supported them. diff --git a/Help/release/dev/vs-vctargetspath.rst b/Help/release/dev/vs-vctargetspath.rst new file mode 100644 index 0000000..d40af34 --- /dev/null +++ b/Help/release/dev/vs-vctargetspath.rst @@ -0,0 +1,10 @@ +vs-vctargetspath +---------------- + +* With :ref:`Visual Studio Generators` for VS 2010 and above, + the :variable:`CMAKE_GENERATOR_TOOLSET` setting gained an option + to specify the ``VCTargetsPath`` value for project files. + +* The :variable:`CMAKE_VS_GLOBALS` variable value now applies during + compiler identification and in targets created by the + :command:`add_custom_target` command. diff --git a/Help/release/dev/vs_dotnet_documentation_file.rst b/Help/release/dev/vs_dotnet_documentation_file.rst new file mode 100644 index 0000000..fdffb1c --- /dev/null +++ b/Help/release/dev/vs_dotnet_documentation_file.rst @@ -0,0 +1,6 @@ +vs_dotnet_documentation_file +---------------------------- + +* The :prop_tgt:`VS_DOTNET_DOCUMENTATION_FILE` target property was added + to tell :ref:`Visual Studio Generators` to generate a ``DocumentationFile`` + reference in ``.csproj`` files. diff --git a/Help/release/dev/xcode-scheme-env.rst b/Help/release/dev/xcode-scheme-env.rst new file mode 100644 index 0000000..238cb61 --- /dev/null +++ b/Help/release/dev/xcode-scheme-env.rst @@ -0,0 +1,5 @@ +xcode-scheme-env +---------------- + +* The :variable:`CMAKE_XCODE_SCHEME_ENVIRONMENT` variable was added + to initialize the :prop_tgt:`XCODE_SCHEME_ENVIRONMENT` target property. diff --git a/Help/release/dev/xcode-scheme-workdir.rst b/Help/release/dev/xcode-scheme-workdir.rst new file mode 100644 index 0000000..8eb5ed8 --- /dev/null +++ b/Help/release/dev/xcode-scheme-workdir.rst @@ -0,0 +1,7 @@ +xcode-scheme-workdir +-------------------- + +* The Xcode generator learnt to set the value of the + ``Custom Working Directory`` schema + option with the :prop_tgt:`XCODE_SCHEME_WORKING_DIRECTORY` + target property. diff --git a/Help/release/dev/xlf-ninja.rst b/Help/release/dev/xlf-ninja.rst new file mode 100644 index 0000000..916e713 --- /dev/null +++ b/Help/release/dev/xlf-ninja.rst @@ -0,0 +1,5 @@ +xlf-ninja +--------- + +* The IBM XL Fortran compiler is now supported by the :generator:`Ninja` + generator. diff --git a/Help/release/index.rst b/Help/release/index.rst index 0cc3f97..a4585a5 100644 --- a/Help/release/index.rst +++ b/Help/release/index.rst @@ -7,6 +7,8 @@ CMake Release Notes This file should include the adjacent "dev.txt" file in development versions but not in release versions. +.. include:: dev.txt + Releases ======== diff --git a/Help/variable/CMAKE_CUDA_COMPILE_FEATURES.rst b/Help/variable/CMAKE_CUDA_COMPILE_FEATURES.rst new file mode 100644 index 0000000..2cd2650 --- /dev/null +++ b/Help/variable/CMAKE_CUDA_COMPILE_FEATURES.rst @@ -0,0 +1,11 @@ +CMAKE_CUDA_COMPILE_FEATURES +--------------------------- + +List of features known to the CUDA compiler + +These features are known to be available for use with the CUDA compiler. This +list is a subset of the features listed in the +:prop_gbl:`CMAKE_CUDA_KNOWN_FEATURES` global property. + +See the :manual:`cmake-compile-features(7)` manual for information on +compile features and a list of supported compilers. diff --git a/Help/variable/CMAKE_CURRENT_FUNCTION.rst b/Help/variable/CMAKE_CURRENT_FUNCTION.rst new file mode 100644 index 0000000..aa2936c --- /dev/null +++ b/Help/variable/CMAKE_CURRENT_FUNCTION.rst @@ -0,0 +1,6 @@ +CMAKE_CURRENT_FUNCTION +---------------------- + +When executing code inside a :command:`function`, this variable +contains the name of the current function. It can be used for +diagnostic or debug messages. diff --git a/Help/variable/CMAKE_CURRENT_FUNCTION_LIST_DIR.rst b/Help/variable/CMAKE_CURRENT_FUNCTION_LIST_DIR.rst new file mode 100644 index 0000000..0119381 --- /dev/null +++ b/Help/variable/CMAKE_CURRENT_FUNCTION_LIST_DIR.rst @@ -0,0 +1,33 @@ +CMAKE_CURRENT_FUNCTION_LIST_DIR +------------------------------- + +When executing code inside a :command:`function`, this variable +contains the full directory of the listfile defining the current function. + +It is quite common practice in CMake that modules use some additional files +(e.g., templates to render). And the code typically did the following: + +.. code-block:: cmake + :caption: Bad + + set(_THIS_MODULE_BASE_DIR "${CMAKE_CURRENT_LIST_DIR}") + + function(foo) + configure_file( + "${_THIS_MODULE_BASE_DIR}/some.template.in" + some.output + ) + endfunction() + +Using this variable inside a function eliminates the neccessity of the +additional one with "global" scope: + +.. code-block:: cmake + :caption: Good + + function(foo) + configure_file( + "${CMAKE_CURRENT_FUNCTION_LIST_DIR}/some.template.in" + some.output + ) + endfunction() diff --git a/Help/variable/CMAKE_CURRENT_FUNCTION_LIST_FILE.rst b/Help/variable/CMAKE_CURRENT_FUNCTION_LIST_FILE.rst new file mode 100644 index 0000000..d2c846a --- /dev/null +++ b/Help/variable/CMAKE_CURRENT_FUNCTION_LIST_FILE.rst @@ -0,0 +1,5 @@ +CMAKE_CURRENT_FUNCTION_LIST_FILE +-------------------------------- + +When executing code inside a :command:`function`, this variable +contains the full path to the listfile declaring a current function. diff --git a/Help/variable/CMAKE_CURRENT_FUNCTION_LIST_LINE.rst b/Help/variable/CMAKE_CURRENT_FUNCTION_LIST_LINE.rst new file mode 100644 index 0000000..5a7cd13 --- /dev/null +++ b/Help/variable/CMAKE_CURRENT_FUNCTION_LIST_LINE.rst @@ -0,0 +1,5 @@ +CMAKE_CURRENT_FUNCTION_LIST_LINE +-------------------------------- + +When executing code inside a :command:`function`, this variable +contains the line number in the listfile where a current function has defined. diff --git a/Help/variable/CMAKE_EXPORT_COMPILE_COMMANDS.rst b/Help/variable/CMAKE_EXPORT_COMPILE_COMMANDS.rst index 4548abc..6d2450b 100644 --- a/Help/variable/CMAKE_EXPORT_COMPILE_COMMANDS.rst +++ b/Help/variable/CMAKE_EXPORT_COMPILE_COMMANDS.rst @@ -25,6 +25,9 @@ form. The format of the JSON file looks like: } ] +This is initialized by the :envvar:`CMAKE_EXPORT_COMPILE_COMMANDS` environment +variable. + .. note:: This option is implemented only by :ref:`Makefile Generators` and the :generator:`Ninja`. It is ignored on other generators. diff --git a/Help/variable/CMAKE_GENERATOR_TOOLSET.rst b/Help/variable/CMAKE_GENERATOR_TOOLSET.rst index 222824f..53ad2f3 100644 --- a/Help/variable/CMAKE_GENERATOR_TOOLSET.rst +++ b/Help/variable/CMAKE_GENERATOR_TOOLSET.rst @@ -58,3 +58,8 @@ Supported pairs are: Specify the toolset version to use. Supported by VS 2017 and above with the specified toolset installed. See the :variable:`CMAKE_VS_PLATFORM_TOOLSET_VERSION` variable. + +``VCTargetsPath=<path>`` + Specify an alternative ``VCTargetsPath`` value for Visual Studio + project files. This allows use of VS platform extension configuration + files (``.props`` and ``.targets``) that are not installed with VS. diff --git a/Help/variable/CMAKE_HOST_SYSTEM_PROCESSOR.rst b/Help/variable/CMAKE_HOST_SYSTEM_PROCESSOR.rst index ba8a850..5f08728 100644 --- a/Help/variable/CMAKE_HOST_SYSTEM_PROCESSOR.rst +++ b/Help/variable/CMAKE_HOST_SYSTEM_PROCESSOR.rst @@ -3,6 +3,13 @@ CMAKE_HOST_SYSTEM_PROCESSOR The name of the CPU CMake is running on. -On systems that support ``uname``, this variable is set to the output of -``uname -p``. On Windows it is set to the value of the environment variable -``PROCESSOR_ARCHITECTURE``. +On Windows, this variable is set to the value of the environment variable +``PROCESSOR_ARCHITECTURE``. On systems that support ``uname``, this variable is +set to the output of: + +- ``uname -m`` on GNU, Linux, Cygwin, Darwin, Android, or +- ``arch`` on OpenBSD, or +- on other systems, + + * ``uname -p`` if its exit code is nonzero, or + * ``uname -m`` otherwise. diff --git a/Help/variable/CMAKE_INSTALL_RPATH_USE_LINK_PATH.rst b/Help/variable/CMAKE_INSTALL_RPATH_USE_LINK_PATH.rst index 78148d5..a99c108 100644 --- a/Help/variable/CMAKE_INSTALL_RPATH_USE_LINK_PATH.rst +++ b/Help/variable/CMAKE_INSTALL_RPATH_USE_LINK_PATH.rst @@ -3,7 +3,11 @@ CMAKE_INSTALL_RPATH_USE_LINK_PATH Add paths to linker search and installed rpath. -``CMAKE_INSTALL_RPATH_USE_LINK_PATH`` is a boolean that if set to ``true`` -will append directories in the linker search path and outside the -project to the :prop_tgt:`INSTALL_RPATH`. This is used to initialize the -target property :prop_tgt:`INSTALL_RPATH_USE_LINK_PATH` for all targets. +``CMAKE_INSTALL_RPATH_USE_LINK_PATH`` is a boolean that if set to ``True`` +will append to the runtime search path (rpath) of installed binaries +any directories outside the project that are in the linker search path or +contain linked library files. The directories are appended after the +value of the :prop_tgt:`INSTALL_RPATH` target property. + +This varibale is used to initialize the target property +:prop_tgt:`INSTALL_RPATH_USE_LINK_PATH` for all targets. diff --git a/Help/variable/CMAKE_LANG_COMPILER_LAUNCHER.rst b/Help/variable/CMAKE_LANG_COMPILER_LAUNCHER.rst index e6c8bb5..e5dda60 100644 --- a/Help/variable/CMAKE_LANG_COMPILER_LAUNCHER.rst +++ b/Help/variable/CMAKE_LANG_COMPILER_LAUNCHER.rst @@ -5,3 +5,6 @@ Default value for :prop_tgt:`<LANG>_COMPILER_LAUNCHER` target property. This variable is used to initialize the property on each target as it is created. This is done only when ``<LANG>`` is ``C``, ``CXX``, ``Fortran``, or ``CUDA``. + +This variable is initialized to the :envvar:`CMAKE_<LANG>_COMPILER_LAUNCHER` +environment variable if it is set. diff --git a/Help/variable/CMAKE_MESSAGE_CONTEXT.rst b/Help/variable/CMAKE_MESSAGE_CONTEXT.rst new file mode 100644 index 0000000..6b4ca40 --- /dev/null +++ b/Help/variable/CMAKE_MESSAGE_CONTEXT.rst @@ -0,0 +1,62 @@ +CMAKE_MESSAGE_CONTEXT +--------------------- + +When enabled by the :manual:`cmake <cmake(1)>` ``--log-context`` command line +option or the :variable:`CMAKE_MESSAGE_CONTEXT_SHOW` variable, the +:command:`message` command converts the ``CMAKE_MESSAGE_CONTEXT`` list into a +dot-separated string surrounded by square brackets and prepends it to each line +for messages of log levels ``NOTICE`` and below. + +For logging contexts to work effectively, projects should generally +``APPEND`` and ``POP_BACK`` an item to the current value of +``CMAKE_MESSAGE_CONTEXT`` rather than replace it. +Projects should not assume the message context at the top of the source tree +is empty, as there are scenarios where the context might have already been set +(e.g. hierarchical projects). + +.. warning:: + + Valid context names are restricted to anything that could be used + as a CMake variable name. All names that begin with an underscore + or the string ``cmake_`` are also reserved for use by CMake and + should not be used by projects. + +Example: + +.. code-block:: cmake + + function(bar) + list(APPEND CMAKE_MESSAGE_CONTEXT "bar") + message(VERBOSE "bar VERBOSE message") + endfunction() + + function(baz) + list(APPEND CMAKE_MESSAGE_CONTEXT "baz") + message(DEBUG "baz DEBUG message") + endfunction() + + function(foo) + list(APPEND CMAKE_MESSAGE_CONTEXT "foo") + bar() + message(TRACE "foo TRACE message") + baz() + endfunction() + + list(APPEND CMAKE_MESSAGE_CONTEXT "top") + + message(VERBOSE "Before `foo`") + foo() + message(VERBOSE "After `foo`") + + list(POP_BACK CMAKE_MESSAGE_CONTEXT) + + +Which results in the following output: + +.. code-block:: none + + -- [top] Before `foo` + -- [top.foo.bar] bar VERBOSE message + -- [top.foo] foo TRACE message + -- [top.foo.baz] baz DEBUG message + -- [top] After `foo` diff --git a/Help/variable/CMAKE_MESSAGE_CONTEXT_SHOW.rst b/Help/variable/CMAKE_MESSAGE_CONTEXT_SHOW.rst new file mode 100644 index 0000000..7ec218e --- /dev/null +++ b/Help/variable/CMAKE_MESSAGE_CONTEXT_SHOW.rst @@ -0,0 +1,15 @@ +CMAKE_MESSAGE_CONTEXT_SHOW +-------------------------- + +Setting this variable to true enables showing a context with each line +logged by the :command:`message` command (see :variable:`CMAKE_MESSAGE_CONTEXT` +for how the context itself is specified). + +This variable is an alternative to providing the ``--log-context`` option +on the :manual:`cmake <cmake(1)>` command line. Whereas the command line +option will apply only to that one CMake run, setting +``CMAKE_MESSAGE_CONTEXT_SHOW`` to true as a cache variable will ensure that +subsequent CMake runs will continue to show the message context. + +Projects should not set ``CMAKE_MESSAGE_CONTEXT_SHOW``. It is intended for +users so that they may control whether or not to include context with messages. diff --git a/Help/variable/CMAKE_MESSAGE_LOG_LEVEL.rst b/Help/variable/CMAKE_MESSAGE_LOG_LEVEL.rst new file mode 100644 index 0000000..1d4cfe6 --- /dev/null +++ b/Help/variable/CMAKE_MESSAGE_LOG_LEVEL.rst @@ -0,0 +1,15 @@ +CMAKE_MESSAGE_LOG_LEVEL +----------------------- + +When set, this variable specifies the logging level used by the +:command:`message` command. Valid values are the same as those for the +``--log-level`` command line option of the :manual:`cmake(1)` program. +If this variable is set and the ``--log-level`` command line option is +given, the command line option takes precedence. + +The main advantage to using this variable is to make a log level persist +between CMake runs. Setting it as a cache variable will ensure that +subsequent CMake runs will continue to use the chosen log level. + +Projects should not set this variable, it is intended for users so that +they may control the log level according to their own needs. diff --git a/Help/variable/CMAKE_NINJA_MULTI_DEFAULT_BUILD_TYPE.rst b/Help/variable/CMAKE_NINJA_MULTI_DEFAULT_BUILD_TYPE.rst new file mode 100644 index 0000000..2b950e1 --- /dev/null +++ b/Help/variable/CMAKE_NINJA_MULTI_DEFAULT_BUILD_TYPE.rst @@ -0,0 +1,7 @@ +CMAKE_NINJA_MULTI_DEFAULT_BUILD_TYPE +------------------------------------ + +Specifies a configuration type to use as the default in ``build.ninja`` for the +:generator:`Ninja Multi-Config` generator. + +If this variable is not specified, no ``build.ninja`` file is generated. diff --git a/Help/variable/CMAKE_PROJECT_INCLUDE.rst b/Help/variable/CMAKE_PROJECT_INCLUDE.rst index 965c94e..5835264 100644 --- a/Help/variable/CMAKE_PROJECT_INCLUDE.rst +++ b/Help/variable/CMAKE_PROJECT_INCLUDE.rst @@ -5,5 +5,6 @@ A CMake language file or module to be included as the last step of all :command:`project` command calls. This is intended for injecting custom code into project builds without modifying their source. -See also the :variable:`CMAKE_PROJECT_<PROJECT-NAME>_INCLUDE` and +See also the :variable:`CMAKE_PROJECT_<PROJECT-NAME>_INCLUDE`, +:variable:`CMAKE_PROJECT_<PROJECT-NAME>_INCLUDE_BEFORE` and :variable:`CMAKE_PROJECT_INCLUDE_BEFORE` variables. diff --git a/Help/variable/CMAKE_PROJECT_INCLUDE_BEFORE.rst b/Help/variable/CMAKE_PROJECT_INCLUDE_BEFORE.rst index 70b15e6..280c14a 100644 --- a/Help/variable/CMAKE_PROJECT_INCLUDE_BEFORE.rst +++ b/Help/variable/CMAKE_PROJECT_INCLUDE_BEFORE.rst @@ -5,5 +5,6 @@ A CMake language file or module to be included as the first step of all :command:`project` command calls. This is intended for injecting custom code into project builds without modifying their source. -See also the :variable:`CMAKE_PROJECT_<PROJECT-NAME>_INCLUDE` and +See also the :variable:`CMAKE_PROJECT_<PROJECT-NAME>_INCLUDE`, +:variable:`CMAKE_PROJECT_<PROJECT-NAME>_INCLUDE_BEFORE` and :variable:`CMAKE_PROJECT_INCLUDE` variables. diff --git a/Help/variable/CMAKE_PROJECT_PROJECT-NAME_INCLUDE.rst b/Help/variable/CMAKE_PROJECT_PROJECT-NAME_INCLUDE.rst index 3485c38..74247f1 100644 --- a/Help/variable/CMAKE_PROJECT_PROJECT-NAME_INCLUDE.rst +++ b/Help/variable/CMAKE_PROJECT_PROJECT-NAME_INCLUDE.rst @@ -6,5 +6,6 @@ A CMake language file or module to be included as the last step of any name. This is intended for injecting custom code into project builds without modifying their source. -See also the :variable:`CMAKE_PROJECT_INCLUDE` and +See also the :variable:`CMAKE_PROJECT_<PROJECT-NAME>_INCLUDE_BEFORE`, +:variable:`CMAKE_PROJECT_INCLUDE` and :variable:`CMAKE_PROJECT_INCLUDE_BEFORE` variables. diff --git a/Help/variable/CMAKE_PROJECT_PROJECT-NAME_INCLUDE_BEFORE.rst b/Help/variable/CMAKE_PROJECT_PROJECT-NAME_INCLUDE_BEFORE.rst new file mode 100644 index 0000000..db1432d --- /dev/null +++ b/Help/variable/CMAKE_PROJECT_PROJECT-NAME_INCLUDE_BEFORE.rst @@ -0,0 +1,11 @@ +CMAKE_PROJECT_<PROJECT-NAME>_INCLUDE_BEFORE +------------------------------------------- + +A CMake language file or module to be included as the first step of any +:command:`project` command calls that specify ``<PROJECT-NAME>`` as the project +name. This is intended for injecting custom code into project builds without +modifying their source. + +See also the :variable:`CMAKE_PROJECT_<PROJECT-NAME>_INCLUDE`, +:variable:`CMAKE_PROJECT_INCLUDE` and +:variable:`CMAKE_PROJECT_INCLUDE_BEFORE` variables. diff --git a/Help/variable/CMAKE_VS_WINRT_BY_DEFAULT.rst b/Help/variable/CMAKE_VS_WINRT_BY_DEFAULT.rst index 2ba8fe2..2eea424 100644 --- a/Help/variable/CMAKE_VS_WINRT_BY_DEFAULT.rst +++ b/Help/variable/CMAKE_VS_WINRT_BY_DEFAULT.rst @@ -1,8 +1,18 @@ CMAKE_VS_WINRT_BY_DEFAULT ------------------------- -Tell :ref:`Visual Studio Generators` for VS 2010 and above that the -target platform compiles as WinRT by default (compiles with ``/ZW``). +Inform :ref:`Visual Studio Generators` for VS 2010 and above that the +target platform enables WinRT compilation by default and it needs to +be explicitly disabled if ``/ZW`` or :prop_tgt:`VS_WINRT_COMPONENT` is +omitted (as opposed to enabling it when either of those options is +present) + +This makes cmake configuration consistent in terms of WinRT among +platforms - if you did not enable the WinRT compilation explicitly, it +will be disabled (by either not enabling it or explicitly disabling it) + +Note: WinRT compilation is always explicitly disabled for C language +source files, even if it is expliclty enabled for a project This variable is meant to be set by a :variable:`toolchain file <CMAKE_TOOLCHAIN_FILE>` for such platforms. diff --git a/Help/variable/CMAKE_XCODE_SCHEME_ENVIRONMENT.rst b/Help/variable/CMAKE_XCODE_SCHEME_ENVIRONMENT.rst new file mode 100644 index 0000000..4832659 --- /dev/null +++ b/Help/variable/CMAKE_XCODE_SCHEME_ENVIRONMENT.rst @@ -0,0 +1,15 @@ +CMAKE_XCODE_SCHEME_ENVIRONMENT +------------------------------ + +Specify environment variables that should be added to the Arguments +section of the generated Xcode scheme. + +If set to a list of environment variables and values of the form +``MYVAR=value`` those environment variables will be added to the +scheme. + +This variable initializes the :prop_tgt:`XCODE_SCHEME_ENVIRONMENT` +property on all targets. + +Please refer to the :prop_tgt:`XCODE_GENERATE_SCHEME` target property +documentation to see all Xcode schema related properties. diff --git a/Help/variable/CMAKE_XCODE_SCHEME_WORKING_DIRECTORY.rst b/Help/variable/CMAKE_XCODE_SCHEME_WORKING_DIRECTORY.rst new file mode 100644 index 0000000..cc690f7 --- /dev/null +++ b/Help/variable/CMAKE_XCODE_SCHEME_WORKING_DIRECTORY.rst @@ -0,0 +1,12 @@ +CMAKE_XCODE_SCHEME_WORKING_DIRECTORY +------------------------------------ + +Specify the ``Working Directory`` a of the `Run` and `Profile` +action in the generated Xcode scheme. + +This variable initializes the +:prop_tgt:`XCODE_SCHEME_WORKING_DIRECTORY` +property on all targets. + +Please refer to the :prop_tgt:`XCODE_GENERATE_SCHEME` target property +documentation to see all Xcode schema related properties. diff --git a/Help/variable/CTEST_CONFIGURATION_TYPE.rst b/Help/variable/CTEST_CONFIGURATION_TYPE.rst index c905480..9e277fa 100644 --- a/Help/variable/CTEST_CONFIGURATION_TYPE.rst +++ b/Help/variable/CTEST_CONFIGURATION_TYPE.rst @@ -3,3 +3,6 @@ CTEST_CONFIGURATION_TYPE Specify the CTest ``DefaultCTestConfigurationType`` setting in a :manual:`ctest(1)` dashboard client script. + +If the configuration type is set via ``-C <cfg>`` from the command line +then this variable is populated accordingly. diff --git a/Help/variable/CTEST_MEMORYCHECK_TYPE.rst b/Help/variable/CTEST_MEMORYCHECK_TYPE.rst index b8b4c30..4e7d5c0 100644 --- a/Help/variable/CTEST_MEMORYCHECK_TYPE.rst +++ b/Help/variable/CTEST_MEMORYCHECK_TYPE.rst @@ -3,6 +3,6 @@ CTEST_MEMORYCHECK_TYPE Specify the CTest ``MemoryCheckType`` setting in a :manual:`ctest(1)` dashboard client script. -Valid values are ``Valgrind``, ``Purify``, ``BoundsChecker``, and +Valid values are ``Valgrind``, ``Purify``, ``BoundsChecker``, ``DrMemory`` and ``ThreadSanitizer``, ``AddressSanitizer``, ``LeakSanitizer``, ``MemorySanitizer``, and ``UndefinedBehaviorSanitizer``. diff --git a/Modules/AndroidTestUtilities.cmake b/Modules/AndroidTestUtilities.cmake index e333cdb..95e2ef7 100644 --- a/Modules/AndroidTestUtilities.cmake +++ b/Modules/AndroidTestUtilities.cmake @@ -76,8 +76,6 @@ Module Functions include(${CMAKE_CURRENT_LIST_DIR}/ExternalData.cmake) -set(_AndroidTestUtilities_SELF_DIR "${CMAKE_CURRENT_LIST_DIR}") - # The parameters to this function should be set to the list of directories, # files, and libraries that need to be installed prior to testing. function(android_add_test_data test_name) @@ -159,6 +157,6 @@ function(android_add_test_data test_name) "-Darg_files=${processed_FILES}" "-Darg_libs=${AST_LIBS}" "-Darg_src_dir=${CMAKE_CURRENT_SOURCE_DIR}" - -P ${_AndroidTestUtilities_SELF_DIR}/AndroidTestUtilities/PushToAndroidDevice.cmake) + -P ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/AndroidTestUtilities/PushToAndroidDevice.cmake) endif() endfunction() diff --git a/Modules/CMakeAddFortranSubdirectory.cmake b/Modules/CMakeAddFortranSubdirectory.cmake index 2613569..c02aa2c 100644 --- a/Modules/CMakeAddFortranSubdirectory.cmake +++ b/Modules/CMakeAddFortranSubdirectory.cmake @@ -43,7 +43,6 @@ future version that supports installation of the external project binaries during ``make install``. #]=======================================================================] -set(_MS_MINGW_SOURCE_DIR ${CMAKE_CURRENT_LIST_DIR}) include(CheckLanguage) include(ExternalProject) @@ -87,11 +86,11 @@ function(_setup_mingw_config_and_build source_dir build_dir) file(TO_NATIVE_PATH "${MINGW_PATH}" MINGW_PATH) string(REPLACE "\\" "\\\\" MINGW_PATH "${MINGW_PATH}") configure_file( - ${_MS_MINGW_SOURCE_DIR}/CMakeAddFortranSubdirectory/config_mingw.cmake.in + ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/CMakeAddFortranSubdirectory/config_mingw.cmake.in ${build_dir}/config_mingw.cmake @ONLY) configure_file( - ${_MS_MINGW_SOURCE_DIR}/CMakeAddFortranSubdirectory/build_mingw.cmake.in + ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/CMakeAddFortranSubdirectory/build_mingw.cmake.in ${build_dir}/build_mingw.cmake @ONLY) endfunction() @@ -155,7 +154,7 @@ function(cmake_add_fortran_subdirectory subdir) # make the external project always run make with each build externalproject_add_step(${project_name}_build forcebuild COMMAND ${CMAKE_COMMAND} - -E remove + -E rm -f ${CMAKE_CURRENT_BUILD_DIR}/${project_name}-prefix/src/${project_name}-stamp/${project_name}-build DEPENDEES configure DEPENDERS build diff --git a/Modules/CMakeCInformation.cmake b/Modules/CMakeCInformation.cmake index df43559..1e08bb7 100644 --- a/Modules/CMakeCInformation.cmake +++ b/Modules/CMakeCInformation.cmake @@ -110,6 +110,11 @@ if(CMAKE_C_STANDARD_LIBRARIES_INIT) mark_as_advanced(CMAKE_C_STANDARD_LIBRARIES) endif() +if(NOT CMAKE_C_COMPILER_LAUNCHER AND DEFINED ENV{CMAKE_C_COMPILER_LAUNCHER}) + set(CMAKE_C_COMPILER_LAUNCHER "$ENV{CMAKE_C_COMPILER_LAUNCHER}" + CACHE STRING "Compiler launcher for C.") +endif() + include(CMakeCommonLanguageInclude) # now define the following rule variables diff --git a/Modules/CMakeCUDACompiler.cmake.in b/Modules/CMakeCUDACompiler.cmake.in index 711129a..4a615a3 100644 --- a/Modules/CMakeCUDACompiler.cmake.in +++ b/Modules/CMakeCUDACompiler.cmake.in @@ -4,7 +4,16 @@ set(CMAKE_CUDA_HOST_LINK_LAUNCHER "@CMAKE_CUDA_HOST_LINK_LAUNCHER@") set(CMAKE_CUDA_COMPILER_ID "@CMAKE_CUDA_COMPILER_ID@") set(CMAKE_CUDA_COMPILER_VERSION "@CMAKE_CUDA_COMPILER_VERSION@") set(CMAKE_CUDA_STANDARD_COMPUTED_DEFAULT "@CMAKE_CUDA_STANDARD_COMPUTED_DEFAULT@") +set(CMAKE_CUDA_COMPILE_FEATURES "@CMAKE_CUDA_COMPILE_FEATURES@") +set(CMAKE_CUDA03_COMPILE_FEATURES "@CMAKE_CUDA03_COMPILE_FEATURES@") +set(CMAKE_CUDA11_COMPILE_FEATURES "@CMAKE_CUDA11_COMPILE_FEATURES@") +set(CMAKE_CUDA14_COMPILE_FEATURES "@CMAKE_CUDA14_COMPILE_FEATURES@") +set(CMAKE_CUDA17_COMPILE_FEATURES "@CMAKE_CUDA17_COMPILE_FEATURES@") +set(CMAKE_CUDA20_COMPILE_FEATURES "@CMAKE_CUDA20_COMPILE_FEATURES@") + +set(CMAKE_CUDA_PLATFORM_ID "@CMAKE_CUDA_PLATFORM_ID@") set(CMAKE_CUDA_SIMULATE_ID "@CMAKE_CUDA_SIMULATE_ID@") +set(CMAKE_CUDA_COMPILER_FRONTEND_VARIANT "@CMAKE_CUDA_COMPILER_FRONTEND_VARIANT@") set(CMAKE_CUDA_SIMULATE_VERSION "@CMAKE_CUDA_SIMULATE_VERSION@") @SET_MSVC_CUDA_ARCHITECTURE_ID@ @@ -17,6 +26,22 @@ set(CMAKE_CUDA_SOURCE_FILE_EXTENSIONS cu) set(CMAKE_CUDA_LINKER_PREFERENCE 15) set(CMAKE_CUDA_LINKER_PREFERENCE_PROPAGATES 1) +set(CMAKE_CUDA_SIZEOF_DATA_PTR "@CMAKE_CUDA_SIZEOF_DATA_PTR@") +set(CMAKE_CUDA_COMPILER_ABI "@CMAKE_CUDA_COMPILER_ABI@") +set(CMAKE_CUDA_LIBRARY_ARCHITECTURE "@CMAKE_CUDA_LIBRARY_ARCHITECTURE@") + +if(CMAKE_CUDA_SIZEOF_DATA_PTR) + set(CMAKE_SIZEOF_VOID_P "${CMAKE_CUDA_SIZEOF_DATA_PTR}") +endif() + +if(CMAKE_CUDA_COMPILER_ABI) + set(CMAKE_INTERNAL_PLATFORM_ABI "${CMAKE_CUDA_COMPILER_ABI}") +endif() + +if(CMAKE_CUDA_LIBRARY_ARCHITECTURE) + set(CMAKE_LIBRARY_ARCHITECTURE "@CMAKE_CUDA_LIBRARY_ARCHITECTURE@") +endif() + set(CMAKE_CUDA_TOOLKIT_INCLUDE_DIRECTORIES "@CMAKE_CUDA_TOOLKIT_INCLUDE_DIRECTORIES@") set(CMAKE_CUDA_HOST_IMPLICIT_LINK_LIBRARIES "@CMAKE_CUDA_HOST_IMPLICIT_LINK_LIBRARIES@") diff --git a/Modules/CMakeCUDACompilerId.cu.in b/Modules/CMakeCUDACompilerId.cu.in index 6eda924..2055de2 100644 --- a/Modules/CMakeCUDACompilerId.cu.in +++ b/Modules/CMakeCUDACompilerId.cu.in @@ -26,7 +26,7 @@ const char* info_language_dialect_default = "INFO" ":" "dialect_default[" #elif __cplusplus >= 201103L "11" #else - "98" + "03" #endif "]"; diff --git a/Modules/CMakeCUDAInformation.cmake b/Modules/CMakeCUDAInformation.cmake index b0d80d1..974f5fa 100644 --- a/Modules/CMakeCUDAInformation.cmake +++ b/Modules/CMakeCUDAInformation.cmake @@ -82,6 +82,11 @@ if(CMAKE_CUDA_STANDARD_LIBRARIES_INIT) mark_as_advanced(CMAKE_CUDA_STANDARD_LIBRARIES) endif() +if(NOT CMAKE_CUDA_COMPILER_LAUNCHER AND DEFINED ENV{CMAKE_CUDA_COMPILER_LAUNCHER}) + set(CMAKE_CUDA_COMPILER_LAUNCHER "$ENV{CMAKE_CUDA_COMPILER_LAUNCHER}" + CACHE STRING "Compiler launcher for CUDA.") +endif() + include(CMakeCommonLanguageInclude) # now define the following rules: @@ -93,9 +98,7 @@ include(CMakeCommonLanguageInclude) # CMAKE_CUDA_LINK_EXECUTABLE if(CMAKE_CUDA_HOST_COMPILER) - set(CMAKE_CUDA_HOST_FLAGS "-ccbin=<CMAKE_CUDA_HOST_COMPILER>") -else() - set(CMAKE_CUDA_HOST_FLAGS "") + string(APPEND _CMAKE_CUDA_EXTRA_FLAGS " -ccbin=<CMAKE_CUDA_HOST_COMPILER>") endif() set(__IMPLICT_LINKS ) @@ -135,26 +138,26 @@ endif() #Specify how to compile when ptx has been requested if(NOT CMAKE_CUDA_COMPILE_PTX_COMPILATION) set(CMAKE_CUDA_COMPILE_PTX_COMPILATION - "<CMAKE_CUDA_COMPILER> ${CMAKE_CUDA_HOST_FLAGS} <DEFINES> <INCLUDES> <FLAGS> -x cu -ptx <SOURCE> -o <OBJECT>") + "<CMAKE_CUDA_COMPILER> ${_CMAKE_CUDA_EXTRA_FLAGS} <DEFINES> <INCLUDES> <FLAGS> -x cu -ptx <SOURCE> -o <OBJECT>") endif() #Specify how to compile when separable compilation has been requested if(NOT CMAKE_CUDA_COMPILE_SEPARABLE_COMPILATION) set(CMAKE_CUDA_COMPILE_SEPARABLE_COMPILATION - "<CMAKE_CUDA_COMPILER> ${CMAKE_CUDA_HOST_FLAGS} <DEFINES> <INCLUDES> <FLAGS> -x cu -dc <SOURCE> -o <OBJECT>") + "<CMAKE_CUDA_COMPILER> ${_CMAKE_CUDA_EXTRA_FLAGS} <DEFINES> <INCLUDES> <FLAGS> -x cu -dc <SOURCE> -o <OBJECT>") endif() #Specify how to compile when whole compilation has been requested if(NOT CMAKE_CUDA_COMPILE_WHOLE_COMPILATION) set(CMAKE_CUDA_COMPILE_WHOLE_COMPILATION - "<CMAKE_CUDA_COMPILER> ${CMAKE_CUDA_HOST_FLAGS} <DEFINES> <INCLUDES> <FLAGS> -x cu -c <SOURCE> -o <OBJECT>") + "<CMAKE_CUDA_COMPILER> ${_CMAKE_CUDA_EXTRA_FLAGS} <DEFINES> <INCLUDES> <FLAGS> -x cu -c <SOURCE> -o <OBJECT>") endif() -if(CMAKE_GENERATOR STREQUAL "Ninja") +if(CMAKE_GENERATOR STREQUAL "Ninja" AND NOT CMAKE_DEPFILE_FLAGS_CUDA ) set(CMAKE_CUDA_COMPILE_DEPENDENCY_DETECTION - "<CMAKE_CUDA_COMPILER> ${CMAKE_CUDA_HOST_FLAGS} <DEFINES> <INCLUDES> <FLAGS> -x cu -M <SOURCE> -MT <OBJECT> -o $DEP_FILE") + "<CMAKE_CUDA_COMPILER> ${_CMAKE_CUDA_EXTRA_FLAGS} <DEFINES> <INCLUDES> <FLAGS> -x cu -M <SOURCE> -MT <OBJECT> -o $DEP_FILE") #The Ninja generator uses the make file dependency files to determine what - #files need to be recompiled. Unfortunately, nvcc doesn't support building + #files need to be recompiled. Unfortunately, nvcc < 10.2 doesn't support building #a source file and generating the dependencies of said file in a single #invocation. Instead we have to state that you need to chain two commands. # @@ -171,13 +174,6 @@ if(NOT CMAKE_CUDA_LINK_EXECUTABLE) "<CMAKE_CUDA_HOST_LINK_LAUNCHER> <LINK_FLAGS> <OBJECTS> -o <TARGET> <LINK_LIBRARIES>${__IMPLICT_LINKS}") endif() -if( CMAKE_CUDA_COMPILER_ID STREQUAL "NVIDIA" AND - CMAKE_CUDA_COMPILER_VERSION VERSION_GREATER_EQUAL "8.0.0") - set(_CMAKE_CUDA_EXTRA_DEVICE_LINK_FLAGS "-Wno-deprecated-gpu-targets") -else() - set(_CMAKE_CUDA_EXTRA_DEVICE_LINK_FLAGS "") -endif() - # Add implicit host link directories that contain device libraries # to the device link line. set(__IMPLICT_DLINK_DIRS ${CMAKE_CUDA_IMPLICIT_LINK_DIRECTORIES}) @@ -192,14 +188,15 @@ foreach(dir ${__IMPLICT_DLINK_DIRS}) endforeach() unset(__IMPLICT_DLINK_DIRS) + #These are used when linking relocatable (dc) cuda code if(NOT CMAKE_CUDA_DEVICE_LINK_LIBRARY) set(CMAKE_CUDA_DEVICE_LINK_LIBRARY - "<CMAKE_CUDA_COMPILER> ${CMAKE_CUDA_HOST_FLAGS} <LANGUAGE_COMPILE_FLAGS> ${CMAKE_CUDA_COMPILE_OPTIONS_PIC} ${_CMAKE_CUDA_EXTRA_DEVICE_LINK_FLAGS} -shared -dlink <OBJECTS> -o <TARGET> <LINK_LIBRARIES>${__IMPLICT_DLINK_FLAGS}") + "<CMAKE_CUDA_COMPILER> ${_CMAKE_CUDA_EXTRA_FLAGS} <LANGUAGE_COMPILE_FLAGS> ${CMAKE_CUDA_COMPILE_OPTIONS_PIC} ${_CMAKE_CUDA_EXTRA_DEVICE_LINK_FLAGS} -shared -dlink <OBJECTS> -o <TARGET> <LINK_LIBRARIES>${__IMPLICT_DLINK_FLAGS}") endif() if(NOT CMAKE_CUDA_DEVICE_LINK_EXECUTABLE) set(CMAKE_CUDA_DEVICE_LINK_EXECUTABLE - "<CMAKE_CUDA_COMPILER> ${CMAKE_CUDA_HOST_FLAGS} <FLAGS> ${CMAKE_CUDA_COMPILE_OPTIONS_PIC} ${_CMAKE_CUDA_EXTRA_DEVICE_LINK_FLAGS} -shared -dlink <OBJECTS> -o <TARGET> <LINK_LIBRARIES>${__IMPLICT_DLINK_FLAGS}") + "<CMAKE_CUDA_COMPILER> ${_CMAKE_CUDA_EXTRA_FLAGS} <FLAGS> ${CMAKE_CUDA_COMPILE_OPTIONS_PIC} ${_CMAKE_CUDA_EXTRA_DEVICE_LINK_FLAGS} -shared -dlink <OBJECTS> -o <TARGET> <LINK_LIBRARIES>${__IMPLICT_DLINK_FLAGS}") endif() unset(_CMAKE_CUDA_EXTRA_DEVICE_LINK_FLAGS) diff --git a/Modules/CMakeCXXInformation.cmake b/Modules/CMakeCXXInformation.cmake index a896b99..da7440a 100644 --- a/Modules/CMakeCXXInformation.cmake +++ b/Modules/CMakeCXXInformation.cmake @@ -207,6 +207,11 @@ if(CMAKE_CXX_STANDARD_LIBRARIES_INIT) mark_as_advanced(CMAKE_CXX_STANDARD_LIBRARIES) endif() +if(NOT CMAKE_CXX_COMPILER_LAUNCHER AND DEFINED ENV{CMAKE_CXX_COMPILER_LAUNCHER}) + set(CMAKE_CXX_COMPILER_LAUNCHER "$ENV{CMAKE_CXX_COMPILER_LAUNCHER}" + CACHE STRING "Compiler launcher for CXX.") +endif() + include(CMakeCommonLanguageInclude) # now define the following rules: diff --git a/Modules/CMakeDetermineCompileFeatures.cmake b/Modules/CMakeDetermineCompileFeatures.cmake index 01a81a1..b50e5f1 100644 --- a/Modules/CMakeDetermineCompileFeatures.cmake +++ b/Modules/CMakeDetermineCompileFeatures.cmake @@ -5,7 +5,7 @@ function(cmake_determine_compile_features lang) if(lang STREQUAL C AND COMMAND cmake_record_c_compile_features) - message(STATUS "Detecting ${lang} compile features") + message(CHECK_START "Detecting ${lang} compile features") set(CMAKE_C90_COMPILE_FEATURES) set(CMAKE_C99_COMPILE_FEATURES) @@ -16,7 +16,7 @@ function(cmake_determine_compile_features lang) cmake_record_c_compile_features() if(NOT _result EQUAL 0) - message(STATUS "Detecting ${lang} compile features - failed") + message(CHECK_FAIL "failed") return() endif() @@ -40,10 +40,10 @@ function(cmake_determine_compile_features lang) set(CMAKE_C99_COMPILE_FEATURES ${CMAKE_C99_COMPILE_FEATURES} PARENT_SCOPE) set(CMAKE_C11_COMPILE_FEATURES ${CMAKE_C11_COMPILE_FEATURES} PARENT_SCOPE) - message(STATUS "Detecting ${lang} compile features - done") + message(CHECK_PASS "done") elseif(lang STREQUAL CXX AND COMMAND cmake_record_cxx_compile_features) - message(STATUS "Detecting ${lang} compile features") + message(CHECK_START "Detecting ${lang} compile features") set(CMAKE_CXX98_COMPILE_FEATURES) set(CMAKE_CXX11_COMPILE_FEATURES) @@ -56,7 +56,7 @@ function(cmake_determine_compile_features lang) cmake_record_cxx_compile_features() if(NOT _result EQUAL 0) - message(STATUS "Detecting ${lang} compile features - failed") + message(CHECK_FAIL "failed") return() endif() @@ -90,7 +90,58 @@ function(cmake_determine_compile_features lang) set(CMAKE_CXX17_COMPILE_FEATURES ${CMAKE_CXX17_COMPILE_FEATURES} PARENT_SCOPE) set(CMAKE_CXX20_COMPILE_FEATURES ${CMAKE_CXX20_COMPILE_FEATURES} PARENT_SCOPE) - message(STATUS "Detecting ${lang} compile features - done") + message(CHECK_PASS "done") + + elseif(lang STREQUAL CUDA AND COMMAND cmake_record_cuda_compile_features) + message(CHECK_START "Detecting ${lang} compile features") + + set(CMAKE_CUDA03_COMPILE_FEATURES) + set(CMAKE_CUDA11_COMPILE_FEATURES) + set(CMAKE_CUDA14_COMPILE_FEATURES) + set(CMAKE_CUDA17_COMPILE_FEATURES) + set(CMAKE_CUDA20_COMPILE_FEATURES) + + include("${CMAKE_ROOT}/Modules/Internal/FeatureTesting.cmake") + + cmake_record_cuda_compile_features() + + if(NOT _result EQUAL 0) + message(CHECK_FAIL "failed") + return() + endif() + + if (CMAKE_CUDA17_COMPILE_FEATURES AND CMAKE_CUDA20_COMPILE_FEATURES) + list(REMOVE_ITEM CMAKE_CUDA20_COMPILE_FEATURES ${CMAKE_CUDA17_COMPILE_FEATURES}) + endif() + if (CMAKE_CUDA14_COMPILE_FEATURES AND CMAKE_CUDA17_COMPILE_FEATURES) + list(REMOVE_ITEM CMAKE_CUDA17_COMPILE_FEATURES ${CMAKE_CUDA14_COMPILE_FEATURES}) + endif() + if (CMAKE_CUDA11_COMPILE_FEATURES AND CMAKE_CUDA14_COMPILE_FEATURES) + list(REMOVE_ITEM CMAKE_CUDA14_COMPILE_FEATURES ${CMAKE_CUDA11_COMPILE_FEATURES}) + endif() + if (CMAKE_CUDA03_COMPILE_FEATURES AND CMAKE_CUDA11_COMPILE_FEATURES) + list(REMOVE_ITEM CMAKE_CUDA11_COMPILE_FEATURES ${CMAKE_CUDA03_COMPILE_FEATURES}) + endif() + + if(NOT CMAKE_CUDA_COMPILE_FEATURES) + set(CMAKE_CUDA_COMPILE_FEATURES + ${CMAKE_CUDA03_COMPILE_FEATURES} + ${CMAKE_CUDA11_COMPILE_FEATURES} + ${CMAKE_CUDA14_COMPILE_FEATURES} + ${CMAKE_CUDA17_COMPILE_FEATURES} + ${CMAKE_CUDA20_COMPILE_FEATURES} + ) + endif() + + set(CMAKE_CUDA_COMPILE_FEATURES ${CMAKE_CUDA_COMPILE_FEATURES} PARENT_SCOPE) + set(CMAKE_CUDA03_COMPILE_FEATURES ${CMAKE_CUDA03_COMPILE_FEATURES} PARENT_SCOPE) + set(CMAKE_CUDA11_COMPILE_FEATURES ${CMAKE_CUDA11_COMPILE_FEATURES} PARENT_SCOPE) + set(CMAKE_CUDA14_COMPILE_FEATURES ${CMAKE_CUDA14_COMPILE_FEATURES} PARENT_SCOPE) + set(CMAKE_CUDA17_COMPILE_FEATURES ${CMAKE_CUDA17_COMPILE_FEATURES} PARENT_SCOPE) + set(CMAKE_CUDA20_COMPILE_FEATURES ${CMAKE_CUDA20_COMPILE_FEATURES} PARENT_SCOPE) + + message(CHECK_PASS "done") + endif() endfunction() diff --git a/Modules/CMakeDetermineCompilerABI.cmake b/Modules/CMakeDetermineCompilerABI.cmake index 06f3ba2..c5611b5 100644 --- a/Modules/CMakeDetermineCompilerABI.cmake +++ b/Modules/CMakeDetermineCompilerABI.cmake @@ -12,7 +12,7 @@ include(CMakeTestCompilerCommon) function(CMAKE_DETERMINE_COMPILER_ABI lang src) if(NOT DEFINED CMAKE_${lang}_ABI_COMPILED) - message(STATUS "Detecting ${lang} compiler ABI info") + message(CHECK_START "Detecting ${lang} compiler ABI info") # Compile the ABI identification source. set(BIN "${CMAKE_PLATFORM_INFO_DIR}/CMakeDetermineCompilerABI_${lang}.bin") @@ -66,7 +66,7 @@ function(CMAKE_DETERMINE_COMPILER_ABI lang src) # Load the resulting information strings. if(CMAKE_${lang}_ABI_COMPILED AND NOT _copy_error) - message(STATUS "Detecting ${lang} compiler ABI info - done") + message(CHECK_PASS "done") file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log "Detecting ${lang} compiler ABI info compiled with the following output:\n${OUTPUT}\n\n") file(STRINGS "${BIN}" ABI_STRINGS LIMIT_COUNT 2 REGEX "INFO:[A-Za-z0-9_]+\\[[^]]*\\]") @@ -124,8 +124,7 @@ function(CMAKE_DETERMINE_COMPILER_ABI lang src) # a try-compile if("${lang}" MATCHES "Fortran" AND "${CMAKE_GENERATOR}" MATCHES "Visual Studio") - set(_desc "Determine Intel Fortran Compiler Implicit Link Path") - message(STATUS "${_desc}") + message(CHECK_START "Determine Intel Fortran Compiler Implicit Link Path") # Build a sample project which reports symbols. try_compile(IFORT_LIB_PATH_COMPILED ${CMAKE_BINARY_DIR}/CMakeFiles/IntelVSImplicitPath @@ -138,8 +137,7 @@ function(CMAKE_DETERMINE_COMPILER_ABI lang src) "${CMAKE_BINARY_DIR}/CMakeFiles/IntelVSImplicitPath/output.txt" "${_output}") include(${CMAKE_BINARY_DIR}/CMakeFiles/IntelVSImplicitPath/output.cmake OPTIONAL) - set(_desc "Determine Intel Fortran Compiler Implicit Link Path -- done") - message(STATUS "${_desc}") + message(CHECK_PASS "done") endif() # Implicit link libraries cannot be used explicitly for multiple @@ -166,7 +164,7 @@ function(CMAKE_DETERMINE_COMPILER_ABI lang src) endif() else() - message(STATUS "Detecting ${lang} compiler ABI info - failed") + message(CHECK_FAIL "failed") file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log "Detecting ${lang} compiler ABI info failed to compile with the following output:\n${OUTPUT}\n${_copy_error}\n\n") endif() diff --git a/Modules/CMakeDetermineCompilerId.cmake b/Modules/CMakeDetermineCompilerId.cmake index 7b571c3..52d8976 100644 --- a/Modules/CMakeDetermineCompilerId.cmake +++ b/Modules/CMakeDetermineCompilerId.cmake @@ -182,6 +182,10 @@ function(CMAKE_DETERMINE_COMPILER_ID lang flagvar src) message(STATUS "The ${lang} compiler identification is unknown") endif() + if(lang STREQUAL "Fortran" AND CMAKE_${lang}_COMPILER_ID STREQUAL "XL") + set(CMAKE_${lang}_XL_CPP "${CMAKE_${lang}_COMPILER_ID_CPP}" PARENT_SCOPE) + endif() + set(CMAKE_${lang}_COMPILER_ID "${CMAKE_${lang}_COMPILER_ID}" PARENT_SCOPE) set(CMAKE_${lang}_PLATFORM_ID "${CMAKE_${lang}_PLATFORM_ID}" PARENT_SCOPE) set(CMAKE_${lang}_COMPILER_ARCHITECTURE_ID "${CMAKE_${lang}_COMPILER_ARCHITECTURE_ID}" PARENT_SCOPE) @@ -242,7 +246,7 @@ Id flags: ${testflags} ${CMAKE_${lang}_COMPILER_ID_FLAGS_ALWAYS} set(id_platform ${CMAKE_VS_PLATFORM_NAME}) set(id_lang "${lang}") set(id_PostBuildEvent_Command "") - if(CMAKE_VS_PLATFORM_TOOLSET MATCHES "^[Ll][Ll][Vv][Mm](_v[0-9]+(_xp)?)?$") + if(CMAKE_VS_PLATFORM_TOOLSET MATCHES "^([Ll][Ll][Vv][Mm](_v[0-9]+(_xp)?)?|[Cc][Ll][Aa][Nn][Gg][Cc][Ll])$") set(id_cl_var "ClangClExecutable") elseif(CMAKE_VS_PLATFORM_TOOLSET MATCHES "v[0-9]+_clang_.*") set(id_cl clang.exe) @@ -318,6 +322,15 @@ Id flags: ${testflags} ${CMAKE_${lang}_COMPILER_ID_FLAGS_ALWAYS} if(CMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION) set(id_WindowsTargetPlatformVersion "<WindowsTargetPlatformVersion>${CMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION}</WindowsTargetPlatformVersion>") endif() + if(CMAKE_VS_PLATFORM_TOOLSET_VCTARGETS_CUSTOM_DIR) + set(id_ToolsetVCTargetsDir "<VCTargetsPath>${CMAKE_VS_PLATFORM_TOOLSET_VCTARGETS_CUSTOM_DIR}</VCTargetsPath>") + endif() + set(id_CustomGlobals "") + foreach(pair IN LISTS CMAKE_VS_GLOBALS) + if("${pair}" MATCHES "([^=]+)=(.*)$") + string(APPEND id_CustomGlobals "<${CMAKE_MATCH_1}>${CMAKE_MATCH_2}</${CMAKE_MATCH_1}>\n ") + endif() + endforeach() if(id_platform STREQUAL ARM64) set(id_WindowsSDKDesktopARMSupport "<WindowsSDKDesktopARM64Support>true</WindowsSDKDesktopARM64Support>") elseif(id_platform STREQUAL ARM) @@ -534,6 +547,12 @@ Id flags: ${testflags} ${CMAKE_${lang}_COMPILER_ID_FLAGS_ALWAYS} ERROR_VARIABLE CMAKE_${lang}_COMPILER_ID_OUTPUT RESULT_VARIABLE CMAKE_${lang}_COMPILER_ID_RESULT ) + if("${CMAKE_${lang}_COMPILER_ID_OUTPUT}" MATCHES "exec: [^\n]*\\((/[^,\n]*/cpp),CMakeFortranCompilerId.F") + set(_cpp "${CMAKE_MATCH_1}") + if(EXISTS "${_cpp}") + set(CMAKE_${lang}_COMPILER_ID_CPP "${_cpp}" PARENT_SCOPE) + endif() + endif() endif() # Check the result of compilation. diff --git a/Modules/CMakeDetermineFortranCompiler.cmake b/Modules/CMakeDetermineFortranCompiler.cmake index 5ddd64f..e850541 100644 --- a/Modules/CMakeDetermineFortranCompiler.cmake +++ b/Modules/CMakeDetermineFortranCompiler.cmake @@ -271,6 +271,11 @@ include(CMakeFindBinUtils) include(Compiler/${CMAKE_Fortran_COMPILER_ID}-FindBinUtils OPTIONAL) unset(_CMAKE_PROCESSING_LANGUAGE) +if(CMAKE_Fortran_XL_CPP) + set(_SET_CMAKE_Fortran_XL_CPP + "set(CMAKE_Fortran_XL_CPP \"${CMAKE_Fortran_XL_CPP}\")") +endif() + if(CMAKE_Fortran_COMPILER_ARCHITECTURE_ID) set(_SET_CMAKE_Fortran_COMPILER_ARCHITECTURE_ID "set(CMAKE_Fortran_COMPILER_ARCHITECTURE_ID ${CMAKE_Fortran_COMPILER_ARCHITECTURE_ID})") diff --git a/Modules/CMakeDetermineSystem.cmake b/Modules/CMakeDetermineSystem.cmake index dc208c6..f3ec4da 100644 --- a/Modules/CMakeDetermineSystem.cmake +++ b/Modules/CMakeDetermineSystem.cmake @@ -43,7 +43,7 @@ if(CMAKE_HOST_UNIX) else() exec_program(${CMAKE_UNAME} ARGS -r OUTPUT_VARIABLE CMAKE_HOST_SYSTEM_VERSION) endif() - if(CMAKE_HOST_SYSTEM_NAME MATCHES "Linux|CYGWIN.*|Darwin|^GNU$") + if(CMAKE_HOST_SYSTEM_NAME MATCHES "Linux|CYGWIN.*|Darwin|^GNU$|Android") exec_program(${CMAKE_UNAME} ARGS -m OUTPUT_VARIABLE CMAKE_HOST_SYSTEM_PROCESSOR RETURN_VALUE val) if(CMAKE_HOST_SYSTEM_NAME STREQUAL "Darwin" AND diff --git a/Modules/CMakeFortranCompiler.cmake.in b/Modules/CMakeFortranCompiler.cmake.in index ae7b73a..34f44aa 100644 --- a/Modules/CMakeFortranCompiler.cmake.in +++ b/Modules/CMakeFortranCompiler.cmake.in @@ -6,6 +6,7 @@ set(CMAKE_Fortran_COMPILER_WRAPPER "@CMAKE_Fortran_COMPILER_WRAPPER@") set(CMAKE_Fortran_PLATFORM_ID "@CMAKE_Fortran_PLATFORM_ID@") set(CMAKE_Fortran_SIMULATE_ID "@CMAKE_Fortran_SIMULATE_ID@") set(CMAKE_Fortran_SIMULATE_VERSION "@CMAKE_Fortran_SIMULATE_VERSION@") +@_SET_CMAKE_Fortran_XL_CPP@ @_SET_CMAKE_Fortran_COMPILER_ARCHITECTURE_ID@ @SET_MSVC_Fortran_ARCHITECTURE_ID@ set(CMAKE_AR "@CMAKE_AR@") diff --git a/Modules/CMakeFortranInformation.cmake b/Modules/CMakeFortranInformation.cmake index ffa6a24..e80716b 100644 --- a/Modules/CMakeFortranInformation.cmake +++ b/Modules/CMakeFortranInformation.cmake @@ -163,6 +163,11 @@ set(CMAKE_Fortran_FLAGS_INIT "$ENV{FFLAGS} ${CMAKE_Fortran_FLAGS_INIT}") cmake_initialize_per_config_variable(CMAKE_Fortran_FLAGS "Flags used by the Fortran compiler") +if(NOT CMAKE_Fortran_COMPILER_LAUNCHER AND DEFINED ENV{CMAKE_Fortran_COMPILER_LAUNCHER}) + set(CMAKE_Fortran_COMPILER_LAUNCHER "$ENV{CMAKE_Fortran_COMPILER_LAUNCHER}" + CACHE STRING "Compiler launcher for Fortran.") +endif() + include(CMakeCommonLanguageInclude) # now define the following rule variables diff --git a/Modules/CMakeGenericSystem.cmake b/Modules/CMakeGenericSystem.cmake index 77d8cfd..7efe5c4 100644 --- a/Modules/CMakeGenericSystem.cmake +++ b/Modules/CMakeGenericSystem.cmake @@ -51,16 +51,16 @@ if(CMAKE_GENERATOR MATCHES "Make") set_property(GLOBAL PROPERTY TARGET_MESSAGES ${CMAKE_TARGET_MESSAGES}) endif() if(CMAKE_GENERATOR MATCHES "Unix Makefiles") - set(CMAKE_EXPORT_COMPILE_COMMANDS OFF CACHE BOOL - "Enable/Disable output of compile commands during generation." + set(CMAKE_EXPORT_COMPILE_COMMANDS "$ENV{CMAKE_EXPORT_COMPILE_COMMANDS}" + CACHE BOOL "Enable/Disable output of compile commands during generation." ) mark_as_advanced(CMAKE_EXPORT_COMPILE_COMMANDS) endif() endif() if(CMAKE_GENERATOR MATCHES "Ninja") - set(CMAKE_EXPORT_COMPILE_COMMANDS OFF CACHE BOOL - "Enable/Disable output of compile commands during generation." + set(CMAKE_EXPORT_COMPILE_COMMANDS "$ENV{CMAKE_EXPORT_COMPILE_COMMANDS}" + CACHE BOOL "Enable/Disable output of compile commands during generation." ) mark_as_advanced(CMAKE_EXPORT_COMPILE_COMMANDS) endif() diff --git a/Modules/CMakeGraphVizOptions.cmake b/Modules/CMakeGraphVizOptions.cmake index 1911e73..be4a3be 100644 --- a/Modules/CMakeGraphVizOptions.cmake +++ b/Modules/CMakeGraphVizOptions.cmake @@ -5,119 +5,145 @@ CMakeGraphVizOptions -------------------- -The builtin graphviz support of CMake. +The builtin Graphviz support of CMake. -Variables specific to the graphviz support -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Generating Graphviz files +^^^^^^^^^^^^^^^^^^^^^^^^^ -CMake -can generate `graphviz <http://www.graphviz.org/>`_ files, showing the dependencies between the -targets in a project and also external libraries which are linked -against. When CMake is run with the ``--graphviz=foo.dot`` option, it will -produce: +CMake can generate `Graphviz <https://www.graphviz.org/>`_ files showing the +dependencies between the targets in a project, as well as external libraries +which are linked against. -* a ``foo.dot`` file showing all dependencies in the project -* a ``foo.dot.<target>`` file for each target, file showing on which other targets the respective target depends -* a ``foo.dot.<target>.dependers`` file, showing which other targets depend on the respective target +When running CMake with the ``--graphviz=foo.dot`` option, it produces: -The different dependency types ``PUBLIC``, ``PRIVATE`` and ``INTERFACE`` -are represented as solid, dashed and dotted edges. +* a ``foo.dot`` file, showing all dependencies in the project +* a ``foo.dot.<target>`` file for each target, showing on which other targets + it depends +* a ``foo.dot.<target>.dependers`` file for each target, showing which other + targets depend on it -This can result in huge graphs. Using the file -``CMakeGraphVizOptions.cmake`` the look and content of the generated -graphs can be influenced. This file is searched first in -:variable:`CMAKE_BINARY_DIR` and then in :variable:`CMAKE_SOURCE_DIR`. If found, it is -read and the variables set in it are used to adjust options for the -generated graphviz files. +Those .dot files can be converted to images using the *dot* command from the +Graphviz package: -.. variable:: GRAPHVIZ_GRAPH_TYPE +.. code-block:: shell - The graph type. + dot -Tpng -o foo.png foo.dot - * Mandatory : NO - * Default : "digraph" +The different dependency types ``PUBLIC``, ``INTERFACE`` and ``PRIVATE`` +are represented as solid, dashed and dotted edges. - Valid graph types are: +Variables specific to the Graphviz support +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - * "graph" : Nodes are joined with lines - * "digraph" : Nodes are joined with arrows showing direction - * "strict graph" : Like "graph" but max one line between each node - * "strict digraph" : Like "graph" but max one line between each node in each direction +The resulting graphs can be huge. The look and content of the generated graphs +can be controlled using the file ``CMakeGraphVizOptions.cmake``. This file is +first searched in :variable:`CMAKE_BINARY_DIR`, and then in +:variable:`CMAKE_SOURCE_DIR`. If found, the variables set in it are used to +adjust options for the generated Graphviz files. .. variable:: GRAPHVIZ_GRAPH_NAME The graph name. - * Mandatory : NO - * Default : "GG" + * Mandatory: NO + * Default: value of :variable:`CMAKE_PROJECT_NAME` .. variable:: GRAPHVIZ_GRAPH_HEADER - The header written at the top of the graphviz file. + The header written at the top of the Graphviz files. - * Mandatory : NO - * Default : "node [n fontsize = "12"];" + * Mandatory: NO + * Default: "node [ fontsize = "12" ];" .. variable:: GRAPHVIZ_NODE_PREFIX - The prefix for each node in the graphviz file. + The prefix for each node in the Graphviz files. - * Mandatory : NO - * Default : "node" + * Mandatory: NO + * Default: "node" .. variable:: GRAPHVIZ_EXECUTABLES - Set this to FALSE to exclude executables from the generated graphs. + Set to FALSE to exclude executables from the generated graphs. - * Mandatory : NO - * Default : TRUE + * Mandatory: NO + * Default: TRUE .. variable:: GRAPHVIZ_STATIC_LIBS - Set this to FALSE to exclude static libraries from the generated graphs. + Set to FALSE to exclude static libraries from the generated graphs. - * Mandatory : NO - * Default : TRUE + * Mandatory: NO + * Default: TRUE .. variable:: GRAPHVIZ_SHARED_LIBS - Set this to FALSE to exclude shared libraries from the generated graphs. + Set to FALSE to exclude shared libraries from the generated graphs. - * Mandatory : NO - * Default : TRUE + * Mandatory: NO + * Default: TRUE .. variable:: GRAPHVIZ_MODULE_LIBS - Set this to FALSE to exclude module libraries from the generated graphs. + Set to FALSE to exclude module libraries from the generated graphs. + + * Mandatory: NO + * Default: TRUE + +.. variable:: GRAPHVIZ_INTERFACE_LIBS + + Set to FALSE to exclude interface libraries from the generated graphs. + + * Mandatory: NO + * Default: TRUE - * Mandatory : NO - * Default : TRUE +.. variable:: GRAPHVIZ_OBJECT_LIBS + + Set to FALSE to exclude object libraries from the generated graphs. + + * Mandatory: NO + * Default: TRUE + +.. variable:: GRAPHVIZ_UNKNOWN_LIBS + + Set to FALSE to exclude unknown libraries from the generated graphs. + + * Mandatory: NO + * Default: TRUE .. variable:: GRAPHVIZ_EXTERNAL_LIBS - Set this to FALSE to exclude external libraries from the generated graphs. + Set to FALSE to exclude external libraries from the generated graphs. + + * Mandatory: NO + * Default: TRUE + +.. variable:: GRAPHVIZ_CUSTOM_TARGETS + + Set to TRUE to include custom targets in the generated graphs. - * Mandatory : NO - * Default : TRUE + * Mandatory: NO + * Default: FALSE .. variable:: GRAPHVIZ_IGNORE_TARGETS - A list of regular expressions for ignoring targets. + A list of regular expressions for names of targets to exclude from the + generated graphs. - * Mandatory : NO - * Default : empty + * Mandatory: NO + * Default: empty .. variable:: GRAPHVIZ_GENERATE_PER_TARGET - Set this to FALSE to exclude per target graphs ``foo.dot.<target>``. + Set to FALSE to not generate per-target graphs ``foo.dot.<target>``. - * Mandatory : NO - * Default : TRUE + * Mandatory: NO + * Default: TRUE .. variable:: GRAPHVIZ_GENERATE_DEPENDERS - Set this to FALSE to exclude depender graphs ``foo.dot.<target>.dependers``. + Set to FALSE to not generate depender graphs ``foo.dot.<target>.dependers``. - * Mandatory : NO - * Default : TRUE + * Mandatory: NO + * Default: TRUE #]=======================================================================] diff --git a/Modules/CMakeMinGWFindMake.cmake b/Modules/CMakeMinGWFindMake.cmake index 523f00c..f026e9a 100644 --- a/Modules/CMakeMinGWFindMake.cmake +++ b/Modules/CMakeMinGWFindMake.cmake @@ -7,10 +7,5 @@ find_program(CMAKE_MAKE_PROGRAM mingw32-make.exe PATHS c:/MinGW/bin /MinGW/bin "[HKEY_CURRENT_USER\\Software\\CodeBlocks;Path]/MinGW/bin" ) -find_program(CMAKE_SH sh.exe ) -if(CMAKE_SH) - message(FATAL_ERROR "sh.exe was found in your PATH, here:\n${CMAKE_SH}\nFor MinGW make to work correctly sh.exe must NOT be in your path.\nRun cmake from a shell that does not have sh.exe in your PATH.\nIf you want to use a UNIX shell, then use MSYS Makefiles.\n") - set(CMAKE_MAKE_PROGRAM NOTFOUND) -endif() -mark_as_advanced(CMAKE_MAKE_PROGRAM CMAKE_SH) +mark_as_advanced(CMAKE_MAKE_PROGRAM) diff --git a/Modules/CMakeNinjaFindMake.cmake b/Modules/CMakeNinjaFindMake.cmake index 702af13..32f78da 100644 --- a/Modules/CMakeNinjaFindMake.cmake +++ b/Modules/CMakeNinjaFindMake.cmake @@ -4,5 +4,6 @@ find_program(CMAKE_MAKE_PROGRAM NAMES ninja-build ninja samu + NAMES_PER_DIR DOC "Program used to build from build.ninja files.") mark_as_advanced(CMAKE_MAKE_PROGRAM) diff --git a/Modules/CMakeTestCCompiler.cmake b/Modules/CMakeTestCCompiler.cmake index 7bf6fde..eadea89 100644 --- a/Modules/CMakeTestCCompiler.cmake +++ b/Modules/CMakeTestCCompiler.cmake @@ -27,7 +27,7 @@ unset(CMAKE_C_COMPILER_WORKS CACHE) # is set and cmake stops processing commands and will not generate # any makefiles or projects. if(NOT CMAKE_C_COMPILER_WORKS) - PrintTestCompilerStatus("C" "") + PrintTestCompilerStatus("C") __TestCompiler_setTryCompileTargetType() file(WRITE ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/testCCompiler.c "#ifdef __cplusplus\n" @@ -52,7 +52,7 @@ if(NOT CMAKE_C_COMPILER_WORKS) endif() if(NOT CMAKE_C_COMPILER_WORKS) - PrintTestCompilerStatus("C" " -- broken") + PrintTestCompilerResult(CHECK_FAIL "broken") file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log "Determining if the C compiler works failed with " "the following output:\n${__CMAKE_C_COMPILER_OUTPUT}\n\n") @@ -63,7 +63,7 @@ if(NOT CMAKE_C_COMPILER_WORKS) "CMake will not be able to correctly generate this project.") else() if(C_TEST_WAS_RUN) - PrintTestCompilerStatus("C" " -- works") + PrintTestCompilerResult(CHECK_PASS "works") file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log "Determining if the C compiler works passed with " "the following output:\n${__CMAKE_C_COMPILER_OUTPUT}\n\n") diff --git a/Modules/CMakeTestCSharpCompiler.cmake b/Modules/CMakeTestCSharpCompiler.cmake index 6715c30..1119a45 100644 --- a/Modules/CMakeTestCSharpCompiler.cmake +++ b/Modules/CMakeTestCSharpCompiler.cmake @@ -20,7 +20,9 @@ set(test_compile_file "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/test # is set and cmake stops processing commands and will not generate # any makefiles or projects. if(NOT CMAKE_CSharp_COMPILER_WORKS) - PrintTestCompilerStatus("C#" "${CMAKE_CSharp_COMPILER}") + # Don't call PrintTestCompilerStatus() because the "C#" we want to pass + # as the LANG doesn't match with the variable name "CMAKE_CSharp_COMPILER" + message(CHECK_START "Check for working C# compiler: ${CMAKE_CSharp_COMPILER}") file(WRITE "${test_compile_file}" "namespace Test {" " public class CSharp {" @@ -38,7 +40,7 @@ if(NOT CMAKE_CSharp_COMPILER_WORKS) endif() if(NOT CMAKE_CSharp_COMPILER_WORKS) - PrintTestCompilerStatus("C#" "${CMAKE_CSharp_COMPILER} -- broken") + PrintTestCompilerResult(CHECK_FAIL "broken") file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log "Determining if the C# compiler works failed with " "the following output:\n${__CMAKE_CSharp_COMPILER_OUTPUT}\n\n") @@ -49,7 +51,7 @@ if(NOT CMAKE_CSharp_COMPILER_WORKS) "CMake will not be able to correctly generate this project.") else() if(CSharp_TEST_WAS_RUN) - PrintTestCompilerStatus("C#" "${CMAKE_CSharp_COMPILER} -- works") + PrintTestCompilerResult(CHECK_PASS "works") file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log "Determining if the C# compiler works passed with " "the following output:\n${__CMAKE_CSharp_COMPILER_OUTPUT}\n\n") diff --git a/Modules/CMakeTestCUDACompiler.cmake b/Modules/CMakeTestCUDACompiler.cmake index f0454da..a0f6bc9 100644 --- a/Modules/CMakeTestCUDACompiler.cmake +++ b/Modules/CMakeTestCUDACompiler.cmake @@ -20,7 +20,7 @@ unset(CMAKE_CUDA_COMPILER_WORKS CACHE) # is set and cmake stops processing commands and will not generate # any makefiles or projects. if(NOT CMAKE_CUDA_COMPILER_WORKS) - PrintTestCompilerStatus("CUDA" "") + PrintTestCompilerStatus("CUDA") file(WRITE ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/main.cu "#ifndef __CUDACC__\n" "# error \"The CMAKE_CUDA_COMPILER is set to an invalid CUDA compiler\"\n" @@ -38,7 +38,7 @@ if(NOT CMAKE_CUDA_COMPILER_WORKS) endif() if(NOT CMAKE_CUDA_COMPILER_WORKS) - PrintTestCompilerStatus("CUDA" " -- broken") + PrintTestCompilerResult(CHECK_FAIL "broken") file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log "Determining if the CUDA compiler works failed with " "the following output:\n${__CMAKE_CUDA_COMPILER_OUTPUT}\n\n") @@ -49,7 +49,7 @@ if(NOT CMAKE_CUDA_COMPILER_WORKS) "CMake will not be able to correctly generate this project.") else() if(CUDA_TEST_WAS_RUN) - PrintTestCompilerStatus("CUDA" " -- works") + PrintTestCompilerResult(CHECK_PASS "works") file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log "Determining if the CUDA compiler works passed with " "the following output:\n${__CMAKE_CUDA_COMPILER_OUTPUT}\n\n") @@ -58,6 +58,9 @@ else() # Try to identify the ABI and configure it into CMakeCUDACompiler.cmake include(${CMAKE_ROOT}/Modules/CMakeDetermineCompilerABI.cmake) CMAKE_DETERMINE_COMPILER_ABI(CUDA ${CMAKE_ROOT}/Modules/CMakeCUDACompilerABI.cu) + # Try to identify the compiler features + include(${CMAKE_ROOT}/Modules/CMakeDetermineCompileFeatures.cmake) + CMAKE_DETERMINE_COMPILE_FEATURES(CUDA) if("x${CMAKE_CUDA_SIMULATE_ID}" STREQUAL "xMSVC") set(CMAKE_CUDA_IMPLICIT_LINK_LIBRARIES "${CMAKE_CUDA_HOST_IMPLICIT_LINK_LIBRARIES}") diff --git a/Modules/CMakeTestCXXCompiler.cmake b/Modules/CMakeTestCXXCompiler.cmake index 7e595b7..bd42153 100644 --- a/Modules/CMakeTestCXXCompiler.cmake +++ b/Modules/CMakeTestCXXCompiler.cmake @@ -27,7 +27,7 @@ unset(CMAKE_CXX_COMPILER_WORKS CACHE) # is set and cmake stops processing commands and will not generate # any makefiles or projects. if(NOT CMAKE_CXX_COMPILER_WORKS) - PrintTestCompilerStatus("CXX" "") + PrintTestCompilerStatus("CXX") __TestCompiler_setTryCompileTargetType() file(WRITE ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/testCXXCompiler.cxx "#ifndef __cplusplus\n" @@ -45,7 +45,7 @@ if(NOT CMAKE_CXX_COMPILER_WORKS) endif() if(NOT CMAKE_CXX_COMPILER_WORKS) - PrintTestCompilerStatus("CXX" " -- broken") + PrintTestCompilerResult(CHECK_FAIL "broken") file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log "Determining if the CXX compiler works failed with " "the following output:\n${__CMAKE_CXX_COMPILER_OUTPUT}\n\n") @@ -56,7 +56,7 @@ if(NOT CMAKE_CXX_COMPILER_WORKS) "CMake will not be able to correctly generate this project.") else() if(CXX_TEST_WAS_RUN) - PrintTestCompilerStatus("CXX" " -- works") + PrintTestCompilerResult(CHECK_PASS "works") file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log "Determining if the CXX compiler works passed with " "the following output:\n${__CMAKE_CXX_COMPILER_OUTPUT}\n\n") diff --git a/Modules/CMakeTestCompilerCommon.cmake b/Modules/CMakeTestCompilerCommon.cmake index 6ee5175..da7c007 100644 --- a/Modules/CMakeTestCompilerCommon.cmake +++ b/Modules/CMakeTestCompilerCommon.cmake @@ -2,8 +2,15 @@ # file Copyright.txt or https://cmake.org/licensing for details. -function(PrintTestCompilerStatus LANG MSG) - message(STATUS "Check for working ${LANG} compiler: ${CMAKE_${LANG}_COMPILER}${MSG}") +function(PrintTestCompilerStatus LANG) + # ARGN shouldn't be needed now, but it is there to preserve backward + # compatibility in case this function is called from project code or + # custom toolchains (they shouldn't, but we can easily support it) + message(CHECK_START "Check for working ${LANG} compiler: ${CMAKE_${LANG}_COMPILER}${ARGN}") +endfunction() + +function(PrintTestCompilerResult TYPE MSG) + message(${TYPE} "${MSG}") endfunction() # if required set the target type if not already explicitly set diff --git a/Modules/CMakeTestFortranCompiler.cmake b/Modules/CMakeTestFortranCompiler.cmake index e9860e9..7461f9c 100644 --- a/Modules/CMakeTestFortranCompiler.cmake +++ b/Modules/CMakeTestFortranCompiler.cmake @@ -21,7 +21,7 @@ unset(CMAKE_Fortran_COMPILER_WORKS CACHE) # is set and cmake stops processing commands and will not generate # any makefiles or projects. if(NOT CMAKE_Fortran_COMPILER_WORKS) - PrintTestCompilerStatus("Fortran" "") + PrintTestCompilerStatus("Fortran") file(WRITE ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/testFortranCompiler.f " PROGRAM TESTFortran PRINT *, 'Hello' @@ -37,7 +37,7 @@ if(NOT CMAKE_Fortran_COMPILER_WORKS) endif() if(NOT CMAKE_Fortran_COMPILER_WORKS) - PrintTestCompilerStatus("Fortran" " -- broken") + PrintTestCompilerResult(CHECK_FAIL "broken") file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log "Determining if the Fortran compiler works failed with " "the following output:\n${OUTPUT}\n\n") @@ -48,7 +48,7 @@ if(NOT CMAKE_Fortran_COMPILER_WORKS) "CMake will not be able to correctly generate this project.") else() if(FORTRAN_TEST_WAS_RUN) - PrintTestCompilerStatus("Fortran" " -- works") + PrintTestCompilerResult(CHECK_PASS "works") file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log "Determining if the Fortran compiler works passed with " "the following output:\n${OUTPUT}\n\n") @@ -60,7 +60,7 @@ else() # Test for Fortran 90 support by using an f90-specific construct. if(NOT DEFINED CMAKE_Fortran_COMPILER_SUPPORTS_F90) - message(STATUS "Checking whether ${CMAKE_Fortran_COMPILER} supports Fortran 90") + message(CHECK_START "Checking whether ${CMAKE_Fortran_COMPILER} supports Fortran 90") file(WRITE ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/testFortranCompilerF90.f90 " PROGRAM TESTFortran90 integer stop ; stop = 1 ; do while ( stop .eq. 0 ) ; end do @@ -70,13 +70,13 @@ else() ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/testFortranCompilerF90.f90 OUTPUT_VARIABLE OUTPUT) if(CMAKE_Fortran_COMPILER_SUPPORTS_F90) - message(STATUS "Checking whether ${CMAKE_Fortran_COMPILER} supports Fortran 90 -- yes") + message(CHECK_PASS "yes") file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log "Determining if the Fortran compiler supports Fortran 90 passed with " "the following output:\n${OUTPUT}\n\n") set(CMAKE_Fortran_COMPILER_SUPPORTS_F90 1) else() - message(STATUS "Checking whether ${CMAKE_Fortran_COMPILER} supports Fortran 90 -- no") + message(CHECK_FAIL "no") file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log "Determining if the Fortran compiler supports Fortran 90 failed with " "the following output:\n${OUTPUT}\n\n") diff --git a/Modules/CMakeTestOBJCCompiler.cmake b/Modules/CMakeTestOBJCCompiler.cmake index 0030683..bcc6fae 100644 --- a/Modules/CMakeTestOBJCCompiler.cmake +++ b/Modules/CMakeTestOBJCCompiler.cmake @@ -27,7 +27,7 @@ unset(CMAKE_OBJC_COMPILER_WORKS CACHE) # is set and cmake stops processing commands and will not generate # any makefiles or projects. if(NOT CMAKE_OBJC_COMPILER_WORKS) - PrintTestCompilerStatus("OBJC" "") + PrintTestCompilerStatus("OBJC") __TestCompiler_setTryCompileTargetType() file(WRITE ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/testOBJCCompiler.m "#ifdef __cplusplus\n" @@ -49,7 +49,7 @@ if(NOT CMAKE_OBJC_COMPILER_WORKS) endif() if(NOT CMAKE_OBJC_COMPILER_WORKS) - PrintTestCompilerStatus("OBJC" " -- broken") + PrintTestCompilerResult(CHECK_FAIL "broken") file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log "Determining if the Objective-C compiler works failed with " "the following output:\n${__CMAKE_OBJC_COMPILER_OUTPUT}\n\n") @@ -60,7 +60,7 @@ if(NOT CMAKE_OBJC_COMPILER_WORKS) "CMake will not be able to correctly generate this project.") else() if(OBJC_TEST_WAS_RUN) - PrintTestCompilerStatus("OBJC" " -- works") + PrintTestCompilerResult(CHECK_PASS "works") file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log "Determining if the Objective-C compiler works passed with " "the following output:\n${__CMAKE_OBJC_COMPILER_OUTPUT}\n\n") diff --git a/Modules/CMakeTestOBJCXXCompiler.cmake b/Modules/CMakeTestOBJCXXCompiler.cmake index bcce2f1..83227d5 100644 --- a/Modules/CMakeTestOBJCXXCompiler.cmake +++ b/Modules/CMakeTestOBJCXXCompiler.cmake @@ -27,7 +27,7 @@ unset(CMAKE_OBJCXX_COMPILER_WORKS CACHE) # is set and cmake stops processing commands and will not generate # any makefiles or projects. if(NOT CMAKE_OBJCXX_COMPILER_WORKS) - PrintTestCompilerStatus("OBJCXX" "") + PrintTestCompilerStatus("OBJCXX") __TestCompiler_setTryCompileTargetType() file(WRITE ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/testOBJCXXCompiler.mm "#ifndef __cplusplus\n" @@ -48,7 +48,7 @@ if(NOT CMAKE_OBJCXX_COMPILER_WORKS) endif() if(NOT CMAKE_OBJCXX_COMPILER_WORKS) - PrintTestCompilerStatus("OBJCXX" " -- broken") + PrintTestCompilerResult(CHECK_FAIL "broken") file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log "Determining if the Objective-C++ compiler works failed with " "the following output:\n${__CMAKE_OBJCXX_COMPILER_OUTPUT}\n\n") @@ -59,7 +59,7 @@ if(NOT CMAKE_OBJCXX_COMPILER_WORKS) "CMake will not be able to correctly generate this project.") else() if(OBJCXX_TEST_WAS_RUN) - PrintTestCompilerStatus("OBJCXX" " -- works") + PrintTestCompilerResult(CHECK_PASS "works") file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log "Determining if the Objective-C++ compiler works passed with " "the following output:\n${__CMAKE_OBJCXX_COMPILER_OUTPUT}\n\n") diff --git a/Modules/CMakeTestSwiftCompiler.cmake b/Modules/CMakeTestSwiftCompiler.cmake index 841aee6..3e4ff95 100644 --- a/Modules/CMakeTestSwiftCompiler.cmake +++ b/Modules/CMakeTestSwiftCompiler.cmake @@ -20,7 +20,7 @@ unset(CMAKE_Swift_COMPILER_WORKS CACHE) # is set and cmake stops processing commands and will not generate # any makefiles or projects. if(NOT CMAKE_Swift_COMPILER_WORKS) - PrintTestCompilerStatus("Swift" "") + PrintTestCompilerStatus("Swift") file(WRITE ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/main.swift "print(\"CMake\")\n") try_compile(CMAKE_Swift_COMPILER_WORKS ${CMAKE_BINARY_DIR} @@ -33,7 +33,7 @@ if(NOT CMAKE_Swift_COMPILER_WORKS) endif() if(NOT CMAKE_Swift_COMPILER_WORKS) - PrintTestCompilerStatus("Swift" " -- broken") + PrintTestCompilerResult(CHECK_FAIL "broken") file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log "Determining if the Swift compiler works failed with " "the following output:\n${__CMAKE_Swift_COMPILER_OUTPUT}\n\n") @@ -44,7 +44,7 @@ if(NOT CMAKE_Swift_COMPILER_WORKS) "CMake will not be able to correctly generate this project.") else() if(Swift_TEST_WAS_RUN) - PrintTestCompilerStatus("Swift" " -- works") + PrintTestCompilerResult(CHECK_PASS "works") file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log "Determining if the Swift compiler works passed with " "the following output:\n${__CMAKE_Swift_COMPILER_OUTPUT}\n\n") diff --git a/Modules/CPack.cmake b/Modules/CPack.cmake index 8a6a712..cbb5323 100644 --- a/Modules/CPack.cmake +++ b/Modules/CPack.cmake @@ -681,6 +681,8 @@ endif() # value of CPACK_NSIS_PACKAGE_NAME instead # of CPACK_PACKAGE_INSTALL_DIRECTORY _cpack_set_default(CPACK_NSIS_DISPLAY_NAME "${CPACK_PACKAGE_INSTALL_DIRECTORY}") +# Specify the name of the Uninstall file in NSIS +_cpack_set_default(CPACK_NSIS_UNINSTALL_NAME "Uninstall") if(CPACK_NSIS_DISPLAY_NAME_SET) _cpack_set_default(CPACK_NSIS_PACKAGE_NAME "${CPACK_NSIS_DISPLAY_NAME}") diff --git a/Modules/CTest.cmake b/Modules/CTest.cmake index 3a111ca..1a51bc8 100644 --- a/Modules/CTest.cmake +++ b/Modules/CTest.cmake @@ -174,7 +174,7 @@ if(BUILD_TESTING) "How many times to retry timed-out CTest submissions.") find_program(MEMORYCHECK_COMMAND - NAMES purify valgrind boundscheck + NAMES purify valgrind boundscheck drmemory PATHS "[HKEY_LOCAL_MACHINE\\SOFTWARE\\Rational Software\\Purify\\Setup;InstallFolder]" DOC "Path to the memory checking command, used for memory error detection." diff --git a/Modules/CheckCCompilerFlag.cmake b/Modules/CheckCCompilerFlag.cmake index a3e2da3..6d65313 100644 --- a/Modules/CheckCCompilerFlag.cmake +++ b/Modules/CheckCCompilerFlag.cmake @@ -36,28 +36,23 @@ include_guard(GLOBAL) include(CheckCSourceCompiles) include(CMakeCheckCompilerFlagCommonPatterns) -macro (CHECK_C_COMPILER_FLAG _FLAG _RESULT) - set(SAFE_CMAKE_REQUIRED_DEFINITIONS "${CMAKE_REQUIRED_DEFINITIONS}") - set(CMAKE_REQUIRED_DEFINITIONS "${_FLAG}") - - # Normalize locale during test compilation. - set(_CheckCCompilerFlag_LOCALE_VARS LC_ALL LC_MESSAGES LANG) - foreach(v ${_CheckCCompilerFlag_LOCALE_VARS}) - set(_CheckCCompilerFlag_SAVED_${v} "$ENV{${v}}") +function(check_c_compiler_flag _flag _var) + set(CMAKE_REQUIRED_DEFINITIONS "${_flag}") + + # Normalize locale during test compilation. + set(_locale_vars LC_ALL LC_MESSAGES LANG) + foreach(v IN LISTS _locale_vars) + set(_locale_vars_saved_${v} "$ENV{${v}}") set(ENV{${v}} C) endforeach() - CHECK_COMPILER_FLAG_COMMON_PATTERNS(_CheckCCompilerFlag_COMMON_PATTERNS) - CHECK_C_SOURCE_COMPILES("int main(void) { return 0; }" ${_RESULT} + check_compiler_flag_common_patterns(_common_patterns) + check_c_source_compiles("int main(void) { return 0; }" ${_var} # Some compilers do not fail with a bad flag FAIL_REGEX "command line option .* is valid for .* but not for C" # GNU - ${_CheckCCompilerFlag_COMMON_PATTERNS} + ${_common_patterns} ) - foreach(v ${_CheckCCompilerFlag_LOCALE_VARS}) - set(ENV{${v}} ${_CheckCCompilerFlag_SAVED_${v}}) - unset(_CheckCCompilerFlag_SAVED_${v}) + foreach(v IN LISTS _locale_vars) + set(ENV{${v}} ${_locale_vars_saved_${v}}) endforeach() - unset(_CheckCCompilerFlag_LOCALE_VARS) - unset(_CheckCCompilerFlag_COMMON_PATTERNS) - - set (CMAKE_REQUIRED_DEFINITIONS "${SAFE_CMAKE_REQUIRED_DEFINITIONS}") -endmacro () + set(${_var} "${${_var}}" PARENT_SCOPE) +endfunction() diff --git a/Modules/CheckCSourceCompiles.cmake b/Modules/CheckCSourceCompiles.cmake index 77ba0cc..67fc993 100644 --- a/Modules/CheckCSourceCompiles.cmake +++ b/Modules/CheckCSourceCompiles.cmake @@ -104,7 +104,7 @@ macro(CHECK_C_SOURCE_COMPILES SOURCE VAR) "${SOURCE}\n") if(NOT CMAKE_REQUIRED_QUIET) - message(STATUS "Performing Test ${VAR}") + message(CHECK_START "Performing Test ${VAR}") endif() try_compile(${VAR} ${CMAKE_BINARY_DIR} @@ -125,7 +125,7 @@ macro(CHECK_C_SOURCE_COMPILES SOURCE VAR) if(${VAR}) set(${VAR} 1 CACHE INTERNAL "Test ${VAR}") if(NOT CMAKE_REQUIRED_QUIET) - message(STATUS "Performing Test ${VAR} - Success") + message(CHECK_PASS "Success") endif() file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log "Performing C SOURCE FILE Test ${VAR} succeeded with the following output:\n" @@ -133,7 +133,7 @@ macro(CHECK_C_SOURCE_COMPILES SOURCE VAR) "Source file was:\n${SOURCE}\n") else() if(NOT CMAKE_REQUIRED_QUIET) - message(STATUS "Performing Test ${VAR} - Failed") + message(CHECK_FAIL "Failed") endif() set(${VAR} "" CACHE INTERNAL "Test ${VAR}") file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log diff --git a/Modules/CheckCSourceRuns.cmake b/Modules/CheckCSourceRuns.cmake index eba70f2..7d116db 100644 --- a/Modules/CheckCSourceRuns.cmake +++ b/Modules/CheckCSourceRuns.cmake @@ -92,7 +92,7 @@ macro(CHECK_C_SOURCE_RUNS SOURCE VAR) "${SOURCE}\n") if(NOT CMAKE_REQUIRED_QUIET) - message(STATUS "Performing Test ${VAR}") + message(CHECK_START "Performing Test ${VAR}") endif() try_run(${VAR}_EXITCODE ${VAR}_COMPILED ${CMAKE_BINARY_DIR} @@ -113,7 +113,7 @@ macro(CHECK_C_SOURCE_RUNS SOURCE VAR) if("${${VAR}_EXITCODE}" EQUAL 0) set(${VAR} 1 CACHE INTERNAL "Test ${VAR}") if(NOT CMAKE_REQUIRED_QUIET) - message(STATUS "Performing Test ${VAR} - Success") + message(CHECK_PASS "Success") endif() file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log "Performing C SOURCE FILE Test ${VAR} succeeded with the following compile output:\n" @@ -130,7 +130,7 @@ macro(CHECK_C_SOURCE_RUNS SOURCE VAR) endif() if(NOT CMAKE_REQUIRED_QUIET) - message(STATUS "Performing Test ${VAR} - Failed") + message(CHECK_FAIL "Failed") endif() file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log "Performing C SOURCE FILE Test ${VAR} failed with the following compile output:\n" diff --git a/Modules/CheckCXXCompilerFlag.cmake b/Modules/CheckCXXCompilerFlag.cmake index 5729843..5e07c25 100644 --- a/Modules/CheckCXXCompilerFlag.cmake +++ b/Modules/CheckCXXCompilerFlag.cmake @@ -36,28 +36,23 @@ include_guard(GLOBAL) include(CheckCXXSourceCompiles) include(CMakeCheckCompilerFlagCommonPatterns) -macro (CHECK_CXX_COMPILER_FLAG _FLAG _RESULT) - set(SAFE_CMAKE_REQUIRED_DEFINITIONS "${CMAKE_REQUIRED_DEFINITIONS}") - set(CMAKE_REQUIRED_DEFINITIONS "${_FLAG}") +function(check_cxx_compiler_flag _flag _var) + set(CMAKE_REQUIRED_DEFINITIONS "${_flag}") # Normalize locale during test compilation. - set(_CheckCXXCompilerFlag_LOCALE_VARS LC_ALL LC_MESSAGES LANG) - foreach(v ${_CheckCXXCompilerFlag_LOCALE_VARS}) - set(_CheckCXXCompilerFlag_SAVED_${v} "$ENV{${v}}") + set(_locale_vars LC_ALL LC_MESSAGES LANG) + foreach(v IN LISTS _locale_vars) + set(_locale_vars_saved_${v} "$ENV{${v}}") set(ENV{${v}} C) endforeach() - CHECK_COMPILER_FLAG_COMMON_PATTERNS(_CheckCXXCompilerFlag_COMMON_PATTERNS) - CHECK_CXX_SOURCE_COMPILES("int main() { return 0; }" ${_RESULT} + check_compiler_flag_common_patterns(_common_patterns) + check_cxx_source_compiles("int main() { return 0; }" ${_var} # Some compilers do not fail with a bad flag FAIL_REGEX "command line option .* is valid for .* but not for C\\\\+\\\\+" # GNU - ${_CheckCXXCompilerFlag_COMMON_PATTERNS} + ${_common_patterns} ) - foreach(v ${_CheckCXXCompilerFlag_LOCALE_VARS}) - set(ENV{${v}} ${_CheckCXXCompilerFlag_SAVED_${v}}) - unset(_CheckCXXCompilerFlag_SAVED_${v}) + foreach(v IN LISTS _locale_vars) + set(ENV{${v}} ${_locale_vars_saved_${v}}) endforeach() - unset(_CheckCXXCompilerFlag_LOCALE_VARS) - unset(_CheckCXXCompilerFlag_COMMON_PATTERNS) - - set (CMAKE_REQUIRED_DEFINITIONS "${SAFE_CMAKE_REQUIRED_DEFINITIONS}") -endmacro () + set(${_var} "${${_var}}" PARENT_SCOPE) +endfunction() diff --git a/Modules/CheckCXXSourceCompiles.cmake b/Modules/CheckCXXSourceCompiles.cmake index cc457a5..c693d32 100644 --- a/Modules/CheckCXXSourceCompiles.cmake +++ b/Modules/CheckCXXSourceCompiles.cmake @@ -105,7 +105,7 @@ macro(CHECK_CXX_SOURCE_COMPILES SOURCE VAR) "${SOURCE}\n") if(NOT CMAKE_REQUIRED_QUIET) - message(STATUS "Performing Test ${VAR}") + message(CHECK_START "Performing Test ${VAR}") endif() try_compile(${VAR} ${CMAKE_BINARY_DIR} @@ -126,7 +126,7 @@ macro(CHECK_CXX_SOURCE_COMPILES SOURCE VAR) if(${VAR}) set(${VAR} 1 CACHE INTERNAL "Test ${VAR}") if(NOT CMAKE_REQUIRED_QUIET) - message(STATUS "Performing Test ${VAR} - Success") + message(CHECK_PASS "Success") endif() file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log "Performing C++ SOURCE FILE Test ${VAR} succeeded with the following output:\n" @@ -134,7 +134,7 @@ macro(CHECK_CXX_SOURCE_COMPILES SOURCE VAR) "Source file was:\n${SOURCE}\n") else() if(NOT CMAKE_REQUIRED_QUIET) - message(STATUS "Performing Test ${VAR} - Failed") + message(CHECK_FAIL "Failed") endif() set(${VAR} "" CACHE INTERNAL "Test ${VAR}") file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log diff --git a/Modules/CheckCXXSourceRuns.cmake b/Modules/CheckCXXSourceRuns.cmake index 5e3f195..408e183 100644 --- a/Modules/CheckCXXSourceRuns.cmake +++ b/Modules/CheckCXXSourceRuns.cmake @@ -92,7 +92,7 @@ macro(CHECK_CXX_SOURCE_RUNS SOURCE VAR) "${SOURCE}\n") if(NOT CMAKE_REQUIRED_QUIET) - message(STATUS "Performing Test ${VAR}") + message(CHECK_START "Performing Test ${VAR}") endif() try_run(${VAR}_EXITCODE ${VAR}_COMPILED ${CMAKE_BINARY_DIR} @@ -114,7 +114,7 @@ macro(CHECK_CXX_SOURCE_RUNS SOURCE VAR) if("${${VAR}_EXITCODE}" EQUAL 0) set(${VAR} 1 CACHE INTERNAL "Test ${VAR}") if(NOT CMAKE_REQUIRED_QUIET) - message(STATUS "Performing Test ${VAR} - Success") + message(CHECK_PASS "Success") endif() file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log "Performing C++ SOURCE FILE Test ${VAR} succeeded with the following output:\n" @@ -131,7 +131,7 @@ macro(CHECK_CXX_SOURCE_RUNS SOURCE VAR) endif() if(NOT CMAKE_REQUIRED_QUIET) - message(STATUS "Performing Test ${VAR} - Failed") + message(CHECK_FAIL "Failed") endif() file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log "Performing C++ SOURCE FILE Test ${VAR} failed with the following output:\n" diff --git a/Modules/CheckFortranFunctionExists.cmake b/Modules/CheckFortranFunctionExists.cmake index 7ca205a..d06203f 100644 --- a/Modules/CheckFortranFunctionExists.cmake +++ b/Modules/CheckFortranFunctionExists.cmake @@ -38,7 +38,7 @@ include_guard(GLOBAL) macro(CHECK_FORTRAN_FUNCTION_EXISTS FUNCTION VARIABLE) if(NOT DEFINED ${VARIABLE}) - message(STATUS "Looking for Fortran ${FUNCTION}") + message(CHECK_START "Looking for Fortran ${FUNCTION}") if(CMAKE_REQUIRED_LINK_OPTIONS) set(CHECK_FUNCTION_EXISTS_ADD_LINK_OPTIONS LINK_OPTIONS ${CMAKE_REQUIRED_LINK_OPTIONS}) @@ -61,21 +61,20 @@ macro(CHECK_FORTRAN_FUNCTION_EXISTS FUNCTION VARIABLE) " ) try_compile(${VARIABLE} - ${CMAKE_BINARY_DIR} - ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/testFortranCompiler.f - ${CHECK_FUNCTION_EXISTS_ADD_LINK_OPTIONS} - ${CHECK_FUNCTION_EXISTS_ADD_LIBRARIES} - OUTPUT_VARIABLE OUTPUT + ${CMAKE_BINARY_DIR} + ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/testFortranCompiler.f + ${CHECK_FUNCTION_EXISTS_ADD_LINK_OPTIONS} + ${CHECK_FUNCTION_EXISTS_ADD_LIBRARIES} + OUTPUT_VARIABLE OUTPUT ) -# message(STATUS "${OUTPUT}") if(${VARIABLE}) set(${VARIABLE} 1 CACHE INTERNAL "Have Fortran function ${FUNCTION}") - message(STATUS "Looking for Fortran ${FUNCTION} - found") + message(CHECK_PASS "found") file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log "Determining if the Fortran ${FUNCTION} exists passed with the following output:\n" "${OUTPUT}\n\n") else() - message(STATUS "Looking for Fortran ${FUNCTION} - not found") + message(CHECK_FAIL "not found") set(${VARIABLE} "" CACHE INTERNAL "Have Fortran function ${FUNCTION}") file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log "Determining if the Fortran ${FUNCTION} exists failed with the following output:\n" diff --git a/Modules/CheckFortranSourceCompiles.cmake b/Modules/CheckFortranSourceCompiles.cmake index f94b254..f0fde8d 100644 --- a/Modules/CheckFortranSourceCompiles.cmake +++ b/Modules/CheckFortranSourceCompiles.cmake @@ -127,7 +127,7 @@ macro(CHECK_Fortran_SOURCE_COMPILES SOURCE VAR) "${SOURCE}\n") if(NOT CMAKE_REQUIRED_QUIET) - message(STATUS "Performing Test ${VAR}") + message(CHECK_START "Performing Test ${VAR}") endif() try_compile(${VAR} ${CMAKE_BINARY_DIR} @@ -148,7 +148,7 @@ macro(CHECK_Fortran_SOURCE_COMPILES SOURCE VAR) if(${VAR}) set(${VAR} 1 CACHE INTERNAL "Test ${VAR}") if(NOT CMAKE_REQUIRED_QUIET) - message(STATUS "Performing Test ${VAR} - Success") + message(CHECK_PASS "Success") endif() file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log "Performing Fortran SOURCE FILE Test ${VAR} succeeded with the following output:\n" @@ -156,7 +156,7 @@ macro(CHECK_Fortran_SOURCE_COMPILES SOURCE VAR) "Source file was:\n${SOURCE}\n") else() if(NOT CMAKE_REQUIRED_QUIET) - message(STATUS "Performing Test ${VAR} - Failed") + message(CHECK_FAIL "Failed") endif() set(${VAR} "" CACHE INTERNAL "Test ${VAR}") file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log diff --git a/Modules/CheckFortranSourceRuns.cmake b/Modules/CheckFortranSourceRuns.cmake index a80c13d..a3e5d5d 100644 --- a/Modules/CheckFortranSourceRuns.cmake +++ b/Modules/CheckFortranSourceRuns.cmake @@ -122,7 +122,7 @@ macro(CHECK_Fortran_SOURCE_RUNS SOURCE VAR) "${SOURCE}\n") if(NOT CMAKE_REQUIRED_QUIET) - message(STATUS "Performing Test ${VAR}") + message(CHECK_START "Performing Test ${VAR}") endif() try_run(${VAR}_EXITCODE ${VAR}_COMPILED ${CMAKE_BINARY_DIR} @@ -144,7 +144,7 @@ macro(CHECK_Fortran_SOURCE_RUNS SOURCE VAR) if("${${VAR}_EXITCODE}" EQUAL 0) set(${VAR} 1 CACHE INTERNAL "Test ${VAR}") if(NOT CMAKE_REQUIRED_QUIET) - message(STATUS "Performing Test ${VAR} - Success") + message(CHECK_PASS "Success") endif() file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log "Performing Fortran SOURCE FILE Test ${VAR} succeeded with the following output:\n" @@ -161,7 +161,7 @@ macro(CHECK_Fortran_SOURCE_RUNS SOURCE VAR) endif() if(NOT CMAKE_REQUIRED_QUIET) - message(STATUS "Performing Test ${VAR} - Failed") + message(CHECK_FAIL "Failed") endif() file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log "Performing Fortran SOURCE FILE Test ${VAR} failed with the following output:\n" diff --git a/Modules/CheckFunctionExists.cmake b/Modules/CheckFunctionExists.cmake index c39144f..136da89 100644 --- a/Modules/CheckFunctionExists.cmake +++ b/Modules/CheckFunctionExists.cmake @@ -57,7 +57,7 @@ macro(CHECK_FUNCTION_EXISTS FUNCTION VARIABLE) set(MACRO_CHECK_FUNCTION_DEFINITIONS "-DCHECK_FUNCTION_EXISTS=${FUNCTION} ${CMAKE_REQUIRED_FLAGS}") if(NOT CMAKE_REQUIRED_QUIET) - message(STATUS "Looking for ${FUNCTION}") + message(CHECK_START "Looking for ${FUNCTION}") endif() if(CMAKE_REQUIRED_LINK_OPTIONS) set(CHECK_FUNCTION_EXISTS_ADD_LINK_OPTIONS @@ -101,14 +101,14 @@ macro(CHECK_FUNCTION_EXISTS FUNCTION VARIABLE) if(${VARIABLE}) set(${VARIABLE} 1 CACHE INTERNAL "Have function ${FUNCTION}") if(NOT CMAKE_REQUIRED_QUIET) - message(STATUS "Looking for ${FUNCTION} - found") + message(CHECK_PASS "found") endif() file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log "Determining if the function ${FUNCTION} exists passed with the following output:\n" "${OUTPUT}\n\n") else() if(NOT CMAKE_REQUIRED_QUIET) - message(STATUS "Looking for ${FUNCTION} - not found") + message(CHECK_FAIL "not found") endif() set(${VARIABLE} "" CACHE INTERNAL "Have function ${FUNCTION}") file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log diff --git a/Modules/CheckIncludeFile.cmake b/Modules/CheckIncludeFile.cmake index d7b9481..3a10473 100644 --- a/Modules/CheckIncludeFile.cmake +++ b/Modules/CheckIncludeFile.cmake @@ -55,7 +55,7 @@ macro(CHECK_INCLUDE_FILE INCLUDE VARIABLE) configure_file(${CMAKE_ROOT}/Modules/CheckIncludeFile.c.in ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/CheckIncludeFile.c) if(NOT CMAKE_REQUIRED_QUIET) - message(STATUS "Looking for ${INCLUDE}") + message(CHECK_START "Looking for ${INCLUDE}") endif() if(${ARGC} EQUAL 3) set(CMAKE_C_FLAGS_SAVE ${CMAKE_C_FLAGS}) @@ -109,7 +109,7 @@ macro(CHECK_INCLUDE_FILE INCLUDE VARIABLE) if(${VARIABLE}) if(NOT CMAKE_REQUIRED_QUIET) - message(STATUS "Looking for ${INCLUDE} - found") + message(CHECK_PASS "found") endif() set(${VARIABLE} 1 CACHE INTERNAL "Have include ${INCLUDE}") file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log @@ -118,7 +118,7 @@ macro(CHECK_INCLUDE_FILE INCLUDE VARIABLE) "${OUTPUT}\n\n") else() if(NOT CMAKE_REQUIRED_QUIET) - message(STATUS "Looking for ${INCLUDE} - not found") + message(CHECK_FAIL "not found") endif() set(${VARIABLE} "" CACHE INTERNAL "Have include ${INCLUDE}") file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log diff --git a/Modules/CheckIncludeFileCXX.cmake b/Modules/CheckIncludeFileCXX.cmake index de5a83b..496550f 100644 --- a/Modules/CheckIncludeFileCXX.cmake +++ b/Modules/CheckIncludeFileCXX.cmake @@ -54,7 +54,7 @@ macro(CHECK_INCLUDE_FILE_CXX INCLUDE VARIABLE) configure_file(${CMAKE_ROOT}/Modules/CheckIncludeFile.cxx.in ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/CheckIncludeFile.cxx) if(NOT CMAKE_REQUIRED_QUIET) - message(STATUS "Looking for C++ include ${INCLUDE}") + message(CHECK_START "Looking for C++ include ${INCLUDE}") endif() if(${ARGC} EQUAL 3) set(CMAKE_CXX_FLAGS_SAVE ${CMAKE_CXX_FLAGS}) @@ -108,7 +108,7 @@ macro(CHECK_INCLUDE_FILE_CXX INCLUDE VARIABLE) if(${VARIABLE}) if(NOT CMAKE_REQUIRED_QUIET) - message(STATUS "Looking for C++ include ${INCLUDE} - found") + message(CHECK_PASS "found") endif() set(${VARIABLE} 1 CACHE INTERNAL "Have include ${INCLUDE}") file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log @@ -117,7 +117,7 @@ macro(CHECK_INCLUDE_FILE_CXX INCLUDE VARIABLE) "${OUTPUT}\n\n") else() if(NOT CMAKE_REQUIRED_QUIET) - message(STATUS "Looking for C++ include ${INCLUDE} - not found") + message(CHECK_FAIL "not found") endif() set(${VARIABLE} "" CACHE INTERNAL "Have include ${INCLUDE}") file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log diff --git a/Modules/CheckIncludeFiles.cmake b/Modules/CheckIncludeFiles.cmake index f52ab55..8e10cd6 100644 --- a/Modules/CheckIncludeFiles.cmake +++ b/Modules/CheckIncludeFiles.cmake @@ -131,7 +131,7 @@ macro(CHECK_INCLUDE_FILES INCLUDE VARIABLE) endif() if(NOT CMAKE_REQUIRED_QUIET) - message(STATUS "Looking for ${_description}") + message(CHECK_START "Looking for ${_description}") endif() try_compile(${VARIABLE} ${CMAKE_BINARY_DIR} @@ -147,7 +147,7 @@ macro(CHECK_INCLUDE_FILES INCLUDE VARIABLE) unset(_CIF_LINK_LIBRARIES) if(${VARIABLE}) if(NOT CMAKE_REQUIRED_QUIET) - message(STATUS "Looking for ${_description} - found") + message(CHECK_PASS "found") endif() set(${VARIABLE} 1 CACHE INTERNAL "Have include ${INCLUDE}") file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log @@ -156,7 +156,7 @@ macro(CHECK_INCLUDE_FILES INCLUDE VARIABLE) "${OUTPUT}\n\n") else() if(NOT CMAKE_REQUIRED_QUIET) - message(STATUS "Looking for ${_description} - not found") + message(CHECK_FAIL "not found") endif() set(${VARIABLE} "" CACHE INTERNAL "Have includes ${INCLUDE}") file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log diff --git a/Modules/CheckLanguage.cmake b/Modules/CheckLanguage.cmake index a1a3a7a..a337926 100644 --- a/Modules/CheckLanguage.cmake +++ b/Modules/CheckLanguage.cmake @@ -39,7 +39,7 @@ include_guard(GLOBAL) macro(check_language lang) if(NOT DEFINED CMAKE_${lang}_COMPILER) set(_desc "Looking for a ${lang} compiler") - message(STATUS ${_desc}) + message(CHECK_START "${_desc}") file(REMOVE_RECURSE ${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/Check${lang}) set(extra_compiler_variables) @@ -78,13 +78,15 @@ file(WRITE \"\${CMAKE_CURRENT_BINARY_DIR}/result.cmake\" file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log "${_desc} passed with the following output:\n" "${output}\n") + set(_CHECK_COMPILER_STATUS CHECK_PASS) else() set(CMAKE_${lang}_COMPILER NOTFOUND) + set(_CHECK_COMPILER_STATUS CHECK_FAIL) file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log "${_desc} failed with the following output:\n" "${output}\n") endif() - message(STATUS "${_desc} - ${CMAKE_${lang}_COMPILER}") + message(${_CHECK_COMPILER_STATUS} "${CMAKE_${lang}_COMPILER}") set(CMAKE_${lang}_COMPILER "${CMAKE_${lang}_COMPILER}" CACHE FILEPATH "${lang} compiler") mark_as_advanced(CMAKE_${lang}_COMPILER) diff --git a/Modules/CheckLibraryExists.cmake b/Modules/CheckLibraryExists.cmake index 6504df5..6470dfd 100644 --- a/Modules/CheckLibraryExists.cmake +++ b/Modules/CheckLibraryExists.cmake @@ -42,7 +42,7 @@ macro(CHECK_LIBRARY_EXISTS LIBRARY FUNCTION LOCATION VARIABLE) set(MACRO_CHECK_LIBRARY_EXISTS_DEFINITION "-DCHECK_FUNCTION_EXISTS=${FUNCTION} ${CMAKE_REQUIRED_FLAGS}") if(NOT CMAKE_REQUIRED_QUIET) - message(STATUS "Looking for ${FUNCTION} in ${LIBRARY}") + message(CHECK_START "Looking for ${FUNCTION} in ${LIBRARY}") endif() set(CHECK_LIBRARY_EXISTS_LINK_OPTIONS) if(CMAKE_REQUIRED_LINK_OPTIONS) @@ -78,7 +78,7 @@ macro(CHECK_LIBRARY_EXISTS LIBRARY FUNCTION LOCATION VARIABLE) if(${VARIABLE}) if(NOT CMAKE_REQUIRED_QUIET) - message(STATUS "Looking for ${FUNCTION} in ${LIBRARY} - found") + message(CHECK_PASS "found") endif() set(${VARIABLE} 1 CACHE INTERNAL "Have library ${LIBRARY}") file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log @@ -87,7 +87,7 @@ macro(CHECK_LIBRARY_EXISTS LIBRARY FUNCTION LOCATION VARIABLE) "${OUTPUT}\n\n") else() if(NOT CMAKE_REQUIRED_QUIET) - message(STATUS "Looking for ${FUNCTION} in ${LIBRARY} - not found") + message(CHECK_FAIL "not found") endif() set(${VARIABLE} "" CACHE INTERNAL "Have library ${LIBRARY}") file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log diff --git a/Modules/CheckOBJCSourceCompiles.cmake b/Modules/CheckOBJCSourceCompiles.cmake index a4676ad..601f1fa 100644 --- a/Modules/CheckOBJCSourceCompiles.cmake +++ b/Modules/CheckOBJCSourceCompiles.cmake @@ -104,7 +104,7 @@ macro(CHECK_OBJC_SOURCE_COMPILES SOURCE VAR) "${SOURCE}\n") if(NOT CMAKE_REQUIRED_QUIET) - message(STATUS "Performing Test ${VAR}") + message(CHECK_START "Performing Test ${VAR}") endif() try_compile(${VAR} ${CMAKE_BINARY_DIR} @@ -125,7 +125,7 @@ macro(CHECK_OBJC_SOURCE_COMPILES SOURCE VAR) if(${VAR}) set(${VAR} 1 CACHE INTERNAL "Test ${VAR}") if(NOT CMAKE_REQUIRED_QUIET) - message(STATUS "Performing Test ${VAR} - Success") + message(CHECK_PASS "Success") endif() file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log "Performing Objective-C SOURCE FILE Test ${VAR} succeeded with the following output:\n" @@ -133,7 +133,7 @@ macro(CHECK_OBJC_SOURCE_COMPILES SOURCE VAR) "Source file was:\n${SOURCE}\n") else() if(NOT CMAKE_REQUIRED_QUIET) - message(STATUS "Performing Test ${VAR} - Failed") + message(CHECK_FAIL "Failed") endif() set(${VAR} "" CACHE INTERNAL "Test ${VAR}") file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log diff --git a/Modules/CheckOBJCSourceRuns.cmake b/Modules/CheckOBJCSourceRuns.cmake index 00a1ebd..6684693 100644 --- a/Modules/CheckOBJCSourceRuns.cmake +++ b/Modules/CheckOBJCSourceRuns.cmake @@ -92,7 +92,7 @@ macro(CHECK_OBJC_SOURCE_RUNS SOURCE VAR) "${SOURCE}\n") if(NOT CMAKE_REQUIRED_QUIET) - message(STATUS "Performing Test ${VAR}") + message(CHECK_START "Performing Test ${VAR}") endif() try_run(${VAR}_EXITCODE ${VAR}_COMPILED ${CMAKE_BINARY_DIR} @@ -113,7 +113,7 @@ macro(CHECK_OBJC_SOURCE_RUNS SOURCE VAR) if("${${VAR}_EXITCODE}" EQUAL 0) set(${VAR} 1 CACHE INTERNAL "Test ${VAR}") if(NOT CMAKE_REQUIRED_QUIET) - message(STATUS "Performing Test ${VAR} - Success") + message(CHECK_PASS "Success") endif() file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log "Performing Objective-C SOURCE FILE Test ${VAR} succeeded with the following compile output:\n" @@ -130,7 +130,7 @@ macro(CHECK_OBJC_SOURCE_RUNS SOURCE VAR) endif() if(NOT CMAKE_REQUIRED_QUIET) - message(STATUS "Performing Test ${VAR} - Failed") + message(CHECK_FAIL "Failed") endif() file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log "Performing Objective-C SOURCE FILE Test ${VAR} failed with the following compile output:\n" diff --git a/Modules/CheckOBJCXXSourceCompiles.cmake b/Modules/CheckOBJCXXSourceCompiles.cmake index 4c0fdd0..2ee79f4 100644 --- a/Modules/CheckOBJCXXSourceCompiles.cmake +++ b/Modules/CheckOBJCXXSourceCompiles.cmake @@ -105,7 +105,7 @@ macro(CHECK_OBJCXX_SOURCE_COMPILES SOURCE VAR) "${SOURCE}\n") if(NOT CMAKE_REQUIRED_QUIET) - message(STATUS "Performing Test ${VAR}") + message(CHECK_START "Performing Test ${VAR}") endif() try_compile(${VAR} ${CMAKE_BINARY_DIR} @@ -126,7 +126,7 @@ macro(CHECK_OBJCXX_SOURCE_COMPILES SOURCE VAR) if(${VAR}) set(${VAR} 1 CACHE INTERNAL "Test ${VAR}") if(NOT CMAKE_REQUIRED_QUIET) - message(STATUS "Performing Test ${VAR} - Success") + message(CHECK_PASS "Success") endif() file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log "Performing Objective-C++ SOURCE FILE Test ${VAR} succeeded with the following output:\n" @@ -134,7 +134,7 @@ macro(CHECK_OBJCXX_SOURCE_COMPILES SOURCE VAR) "Source file was:\n${SOURCE}\n") else() if(NOT CMAKE_REQUIRED_QUIET) - message(STATUS "Performing Test ${VAR} - Failed") + message(CHECK_FAIL "Failed") endif() set(${VAR} "" CACHE INTERNAL "Test ${VAR}") file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log diff --git a/Modules/CheckOBJCXXSourceRuns.cmake b/Modules/CheckOBJCXXSourceRuns.cmake index a3d5923..7f7e04f 100644 --- a/Modules/CheckOBJCXXSourceRuns.cmake +++ b/Modules/CheckOBJCXXSourceRuns.cmake @@ -92,7 +92,7 @@ macro(CHECK_OBJCXX_SOURCE_RUNS SOURCE VAR) "${SOURCE}\n") if(NOT CMAKE_REQUIRED_QUIET) - message(STATUS "Performing Test ${VAR}") + message(CHECK_START "Performing Test ${VAR}") endif() try_run(${VAR}_EXITCODE ${VAR}_COMPILED ${CMAKE_BINARY_DIR} @@ -114,7 +114,7 @@ macro(CHECK_OBJCXX_SOURCE_RUNS SOURCE VAR) if("${${VAR}_EXITCODE}" EQUAL 0) set(${VAR} 1 CACHE INTERNAL "Test ${VAR}") if(NOT CMAKE_REQUIRED_QUIET) - message(STATUS "Performing Test ${VAR} - Success") + message(CHECK_PASS "Success") endif() file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log "Performing Objective-C++ SOURCE FILE Test ${VAR} succeeded with the following output:\n" @@ -131,7 +131,7 @@ macro(CHECK_OBJCXX_SOURCE_RUNS SOURCE VAR) endif() if(NOT CMAKE_REQUIRED_QUIET) - message(STATUS "Performing Test ${VAR} - Failed") + message(CHECK_FAIL "Failed") endif() file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log "Performing Objective-C++ SOURCE FILE Test ${VAR} failed with the following output:\n" diff --git a/Modules/CheckPrototypeDefinition.cmake b/Modules/CheckPrototypeDefinition.cmake index a7b020c..8b06403 100644 --- a/Modules/CheckPrototypeDefinition.cmake +++ b/Modules/CheckPrototypeDefinition.cmake @@ -54,6 +54,9 @@ include_guard(GLOBAL) function(check_prototype_definition _FUNCTION _PROTOTYPE _RETURN _HEADER _VARIABLE) if (NOT DEFINED ${_VARIABLE}) + if(NOT CMAKE_REQUIRED_QUIET) + message(CHECK_START "Checking prototype ${_FUNCTION} for ${_VARIABLE}") + endif() set(CHECK_PROTOTYPE_DEFINITION_CONTENT "/* */\n") set(CHECK_PROTOTYPE_DEFINITION_FLAGS ${CMAKE_REQUIRED_FLAGS}) @@ -103,14 +106,14 @@ function(check_prototype_definition _FUNCTION _PROTOTYPE _RETURN _HEADER _VARIAB if (${_VARIABLE}) set(${_VARIABLE} 1 CACHE INTERNAL "Have correct prototype for ${_FUNCTION}") if(NOT CMAKE_REQUIRED_QUIET) - message(STATUS "Checking prototype ${_FUNCTION} for ${_VARIABLE} - True") + message(CHECK_PASS "True") endif() file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log "Determining if the prototype ${_FUNCTION} exists for ${_VARIABLE} passed with the following output:\n" "${OUTPUT}\n\n") else () if(NOT CMAKE_REQUIRED_QUIET) - message(STATUS "Checking prototype ${_FUNCTION} for ${_VARIABLE} - False") + message(CHECK_FAIL "False") endif() set(${_VARIABLE} 0 CACHE INTERNAL "Have correct prototype for ${_FUNCTION}") file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log diff --git a/Modules/CheckSymbolExists.cmake b/Modules/CheckSymbolExists.cmake index 1053383..4f202c4 100644 --- a/Modules/CheckSymbolExists.cmake +++ b/Modules/CheckSymbolExists.cmake @@ -126,7 +126,7 @@ int main(int argc, char** argv) "${SOURCEFILE}" @ONLY) if(NOT CMAKE_REQUIRED_QUIET) - message(STATUS "Looking for ${SYMBOL}") + message(CHECK_START "Looking for ${SYMBOL}") endif() try_compile(${VARIABLE} ${CMAKE_BINARY_DIR} @@ -140,7 +140,7 @@ int main(int argc, char** argv) OUTPUT_VARIABLE OUTPUT) if(${VARIABLE}) if(NOT CMAKE_REQUIRED_QUIET) - message(STATUS "Looking for ${SYMBOL} - found") + message(CHECK_PASS "found") endif() set(${VARIABLE} 1 CACHE INTERNAL "Have symbol ${SYMBOL}") file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log @@ -150,7 +150,7 @@ int main(int argc, char** argv) "${CMAKE_CONFIGURABLE_FILE_CONTENT}\n") else() if(NOT CMAKE_REQUIRED_QUIET) - message(STATUS "Looking for ${SYMBOL} - not found") + message(CHECK_FAIL "not found") endif() set(${VARIABLE} "" CACHE INTERNAL "Have symbol ${SYMBOL}") file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log diff --git a/Modules/CheckTypeSize.cmake b/Modules/CheckTypeSize.cmake index 3727373..2b07b7c 100644 --- a/Modules/CheckTypeSize.cmake +++ b/Modules/CheckTypeSize.cmake @@ -86,7 +86,7 @@ cmake_policy(SET CMP0054 NEW) # Helper function. DO NOT CALL DIRECTLY. function(__check_type_size_impl type var map builtin language) if(NOT CMAKE_REQUIRED_QUIET) - message(STATUS "Check size of ${type}") + message(CHECK_START "Check size of ${type}") endif() # Include header files. @@ -173,7 +173,7 @@ function(__check_type_size_impl type var map builtin language) endif() if(NOT CMAKE_REQUIRED_QUIET) - message(STATUS "Check size of ${type} - done") + message(CHECK_PASS "done") endif() file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log "Determining size of ${type} passed with the following output:\n${output}\n\n") @@ -181,7 +181,7 @@ function(__check_type_size_impl type var map builtin language) else() # The check failed to compile. if(NOT CMAKE_REQUIRED_QUIET) - message(STATUS "Check size of ${type} - failed") + message(CHECK_FAIL "failed") endif() file(READ ${src} content) file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log diff --git a/Modules/CheckVariableExists.cmake b/Modules/CheckVariableExists.cmake index f4953a3..8a93535 100644 --- a/Modules/CheckVariableExists.cmake +++ b/Modules/CheckVariableExists.cmake @@ -42,7 +42,7 @@ macro(CHECK_VARIABLE_EXISTS VAR VARIABLE) set(MACRO_CHECK_VARIABLE_DEFINITIONS "-DCHECK_VARIABLE_EXISTS=${VAR} ${CMAKE_REQUIRED_FLAGS}") if(NOT CMAKE_REQUIRED_QUIET) - message(STATUS "Looking for ${VAR}") + message(CHECK_START "Looking for ${VAR}") endif() if(CMAKE_REQUIRED_LINK_OPTIONS) set(CHECK_VARIABLE_EXISTS_ADD_LINK_OPTIONS @@ -67,7 +67,7 @@ macro(CHECK_VARIABLE_EXISTS VAR VARIABLE) if(${VARIABLE}) set(${VARIABLE} 1 CACHE INTERNAL "Have variable ${VAR}") if(NOT CMAKE_REQUIRED_QUIET) - message(STATUS "Looking for ${VAR} - found") + message(CHECK_PASS "found") endif() file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log "Determining if the variable ${VAR} exists passed with the following output:\n" @@ -75,7 +75,7 @@ macro(CHECK_VARIABLE_EXISTS VAR VARIABLE) else() set(${VARIABLE} "" CACHE INTERNAL "Have variable ${VAR}") if(NOT CMAKE_REQUIRED_QUIET) - message(STATUS "Looking for ${VAR} - not found") + message(CHECK_FAIL "not found") endif() file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log "Determining if the variable ${VAR} exists failed with the following output:\n" diff --git a/Modules/Compiler/CMakeCommonCompilerMacros.cmake b/Modules/Compiler/CMakeCommonCompilerMacros.cmake index 96537f8..409b65a 100644 --- a/Modules/Compiler/CMakeCommonCompilerMacros.cmake +++ b/Modules/Compiler/CMakeCommonCompilerMacros.cmake @@ -134,3 +134,47 @@ macro(cmake_record_cxx_compile_features) unset(CMAKE_CXX98_STANDARD__HAS_FULL_SUPPORT) endif() endmacro() + +macro(cmake_record_cuda_compile_features) + set(_result 0) + if(_result EQUAL 0 AND DEFINED CMAKE_CUDA20_STANDARD_COMPILE_OPTION) + if(CMAKE_CUDA20_STANDARD__HAS_FULL_SUPPORT) + _has_compiler_features_cuda(20) + else() + _record_compiler_features_cuda(20) + endif() + unset(CMAKE_CUDA20_STANDARD__HAS_FULL_SUPPORT) + endif() + if(_result EQUAL 0 AND DEFINED CMAKE_CUDA17_STANDARD_COMPILE_OPTION) + if(CMAKE_CUDA17_STANDARD__HAS_FULL_SUPPORT) + _has_compiler_features_cuda(17) + else() + _record_compiler_features_cuda(17) + endif() + unset(CMAKE_CUDA17_STANDARD__HAS_FULL_SUPPORT) + endif() + if(_result EQUAL 0 AND DEFINED CMAKE_CUDA14_STANDARD_COMPILE_OPTION) + if(CMAKE_CUDA14_STANDARD__HAS_FULL_SUPPORT) + _has_compiler_features_cuda(14) + else() + _record_compiler_features_cuda(14) + endif() + unset(CMAKE_CUDA14_STANDARD__HAS_FULL_SUPPORT) + endif() + if(_result EQUAL 0 AND DEFINED CMAKE_CUDA11_STANDARD_COMPILE_OPTION) + if(CMAKE_CUDA11_STANDARD__HAS_FULL_SUPPORT) + _has_compiler_features_cuda(11) + else() + _record_compiler_features_cuda(11) + endif() + unset(CMAKE_CUDA11_STANDARD__HAS_FULL_SUPPORT) + endif() + if(_result EQUAL 0 AND DEFINED CMAKE_CUDA03_STANDARD_COMPILE_OPTION) + if(CMAKE_CUDA03_STANDARD__HAS_FULL_SUPPORT) + _has_compiler_features_cuda(03) + else() + _record_compiler_features_cuda(03) + endif() + unset(CMAKE_CUDA03_STANDARD__HAS_FULL_SUPPORT) + endif() +endmacro() diff --git a/Modules/Compiler/NAG-Fortran.cmake b/Modules/Compiler/NAG-Fortran.cmake index 9973feb..c54ab9d 100644 --- a/Modules/Compiler/NAG-Fortran.cmake +++ b/Modules/Compiler/NAG-Fortran.cmake @@ -1,6 +1,6 @@ # Help CMAKE_PARSE_IMPLICIT_LINK_INFO detect NAG Fortran object files. if(NOT CMAKE_Fortran_COMPILER_WORKS AND NOT CMAKE_Fortran_COMPILER_FORCED) - message(STATUS "Detecting NAG Fortran directory") + message(CHECK_START "Detecting NAG Fortran directory") # Run with -dryrun to see sample "link" line. execute_process( COMMAND ${CMAKE_Fortran_COMPILER} dummy.o -dryrun @@ -20,11 +20,11 @@ if(NOT CMAKE_Fortran_COMPILER_WORKS AND NOT CMAKE_Fortran_COMPILER_FORCED) " directory: ${_nag_dir}\n" " regex: ${CMAKE_Fortran_IMPLICIT_OBJECT_REGEX}\n" "from output:\n${_dryrun}\n\n") - message(STATUS "Detecting NAG Fortran directory - ${_nag_dir}") + message(CHECK_PASS "${_nag_dir}") else() file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log "Detecting NAG Fortran directory with -dryrun failed:\n${_dryrun}\n\n") - message(STATUS "Detecting NAG Fortran directory - failed") + message(CHECK_FAIL "failed") endif() endif() diff --git a/Modules/Compiler/NVIDIA-CUDA.cmake b/Modules/Compiler/NVIDIA-CUDA.cmake index b59deda..ad7f084 100644 --- a/Modules/Compiler/NVIDIA-CUDA.cmake +++ b/Modules/Compiler/NVIDIA-CUDA.cmake @@ -1,7 +1,32 @@ +include(Compiler/CMakeCommonCompilerMacros) + set(CMAKE_CUDA_COMPILER_HAS_DEVICE_LINK_PHASE True) set(CMAKE_CUDA_VERBOSE_FLAG "-v") set(CMAKE_CUDA_VERBOSE_COMPILE_FLAG "-Xcompiler=-v") +if (NOT CMAKE_CUDA_COMPILER_VERSION VERSION_LESS 10.2) + # The -forward-unknown-to-host-compiler flag was only + # added to nvcc in 10.2 so before that we had no good + # way to invoke the CUDA compiler and propagate unknown + # flags such as -pthread to the host compiler + set(_CMAKE_CUDA_EXTRA_FLAGS "-forward-unknown-to-host-compiler") +else() + set(_CMAKE_CUDA_EXTRA_FLAGS "") +endif() + +if(CMAKE_CUDA_COMPILER_VERSION VERSION_GREATER_EQUAL "8.0.0") + set(_CMAKE_CUDA_EXTRA_DEVICE_LINK_FLAGS "-Wno-deprecated-gpu-targets") +else() + set(_CMAKE_CUDA_EXTRA_DEVICE_LINK_FLAGS "") +endif() + +if (NOT CMAKE_CUDA_COMPILER_VERSION VERSION_LESS 10.2) + # The -MD flag was only added to nvcc in 10.2 so + # before that we had to invoke the compiler twice + # to get header dependency information + set(CMAKE_DEPFILE_FLAGS_CUDA "-MD -MT <OBJECT> -MF <DEPFILE>") +endif() + if(NOT "x${CMAKE_CUDA_SIMULATE_ID}" STREQUAL "xMSVC") set(CMAKE_CUDA_COMPILE_OPTIONS_PIE -Xcompiler=-fPIE) set(CMAKE_CUDA_COMPILE_OPTIONS_PIC -Xcompiler=-fPIC) @@ -19,17 +44,26 @@ set(CMAKE_SHARED_LIBRARY_CREATE_CUDA_FLAGS -shared) set(CMAKE_INCLUDE_SYSTEM_FLAG_CUDA -isystem=) if("x${CMAKE_CUDA_SIMULATE_ID}" STREQUAL "xMSVC") - set(CMAKE_CUDA_STANDARD_DEFAULT "") + set(CMAKE_CUDA03_STANDARD_COMPILE_OPTION "") + set(CMAKE_CUDA03_EXTENSION_COMPILE_OPTION "") + + set(CMAKE_CUDA11_STANDARD_COMPILE_OPTION "") + set(CMAKE_CUDA11_EXTENSION_COMPILE_OPTION "") + + if (NOT CMAKE_CUDA_COMPILER_VERSION VERSION_LESS 9.0) + set(CMAKE_CUDA14_STANDARD_COMPILE_OPTION "") + set(CMAKE_CUDA14_EXTENSION_COMPILE_OPTION "") + endif() else() - set(CMAKE_CUDA_STANDARD_DEFAULT 98) - set(CMAKE_CUDA98_STANDARD_COMPILE_OPTION "") - set(CMAKE_CUDA98_EXTENSION_COMPILE_OPTION "") + set(CMAKE_CUDA03_STANDARD_COMPILE_OPTION "") + set(CMAKE_CUDA03_EXTENSION_COMPILE_OPTION "") + set(CMAKE_CUDA11_STANDARD_COMPILE_OPTION "-std=c++11") set(CMAKE_CUDA11_EXTENSION_COMPILE_OPTION "-std=c++11") if (NOT CMAKE_CUDA_COMPILER_VERSION VERSION_LESS 9.0) - set(CMAKE_CUDA98_STANDARD_COMPILE_OPTION "-std=c++03") - set(CMAKE_CUDA98_EXTENSION_COMPILE_OPTION "-std=c++03") + set(CMAKE_CUDA03_STANDARD_COMPILE_OPTION "-std=c++03") + set(CMAKE_CUDA03_EXTENSION_COMPILE_OPTION "-std=c++03") set(CMAKE_CUDA14_STANDARD_COMPILE_OPTION "-std=c++14") set(CMAKE_CUDA14_EXTENSION_COMPILE_OPTION "-std=c++14") endif() @@ -46,3 +80,5 @@ if (CMAKE_CUDA_COMPILER_VERSION VERSION_GREATER_EQUAL "9.0") set(CMAKE_CUDA_RESPONSE_FILE_LINK_FLAG "--options-file ") set(CMAKE_CUDA_RESPONSE_FILE_FLAG "--options-file ") endif() + +__compiler_check_default_language_standard(CUDA 6.0 03) diff --git a/Modules/Compiler/XL-Fortran.cmake b/Modules/Compiler/XL-Fortran.cmake index c4fb097..1683dff 100644 --- a/Modules/Compiler/XL-Fortran.cmake +++ b/Modules/Compiler/XL-Fortran.cmake @@ -18,3 +18,7 @@ string(APPEND CMAKE_Fortran_FLAGS_INIT " -qthreaded -qhalt=e") # xlf: 1501-214 (W) command option E reserved for future use - ignored set(CMAKE_Fortran_CREATE_PREPROCESSED_SOURCE) set(CMAKE_Fortran_CREATE_ASSEMBLY_SOURCE) + +set(CMAKE_Fortran_PREPROCESS_SOURCE + "<CMAKE_Fortran_COMPILER> <DEFINES> <INCLUDES> <FLAGS> -qpreprocess -qnoobject -qsuppress=1517-020 -tF -B \"${CMAKE_CURRENT_LIST_DIR}/XL-Fortran/\" -WF,--cpp,\"${CMAKE_Fortran_XL_CPP}\",--out,<PREPROCESSED_SOURCE> <SOURCE>" + ) diff --git a/Modules/Compiler/XL-Fortran/cpp b/Modules/Compiler/XL-Fortran/cpp new file mode 100755 index 0000000..1fd62c2 --- /dev/null +++ b/Modules/Compiler/XL-Fortran/cpp @@ -0,0 +1,29 @@ +#!/usr/bin/env bash + +# Source file. +src="$(printf %q "$1")" +shift + +# Output file the compiler expects. +out="$(printf %q "$1")" +shift + +# Create the file the compiler expects. It will check syntax. +>"$out" + +cpp='cpp' +opts='' +while test "$#" != 0; do + case "$1" in + # Extract the option for the path to cpp. + --cpp) shift; cpp="$(printf %q "$1")" ;; + # Extract the option for our own output file. + --out) shift; out="$(printf %q "$1")" ;; + # Collect the rest of the command line. + *) opts="$opts $(printf %q "$1")" ;; + esac + shift +done + +# Execute the real preprocessor tool. +eval "exec $cpp $src $out $opts" diff --git a/Modules/CompilerId/VS-10.vcxproj.in b/Modules/CompilerId/VS-10.vcxproj.in index d742274..b48a332 100644 --- a/Modules/CompilerId/VS-10.vcxproj.in +++ b/Modules/CompilerId/VS-10.vcxproj.in @@ -15,6 +15,8 @@ @id_WindowsTargetPlatformVersion@ @id_WindowsSDKDesktopARMSupport@ @id_CudaToolkitCustomDir@ + @id_ToolsetVCTargetsDir@ + @id_CustomGlobals@ </PropertyGroup> @id_toolset_version_props@ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> diff --git a/Modules/DartConfiguration.tcl.in b/Modules/DartConfiguration.tcl.in index e4513b3..086ba07 100644 --- a/Modules/DartConfiguration.tcl.in +++ b/Modules/DartConfiguration.tcl.in @@ -69,6 +69,8 @@ CompilerVersion: @CMAKE_CXX_COMPILER_VERSION@ PurifyCommand: @PURIFYCOMMAND@ ValgrindCommand: @VALGRIND_COMMAND@ ValgrindCommandOptions: @VALGRIND_COMMAND_OPTIONS@ +DrMemoryCommand: @DRMEMORY_COMMAND@ +DrMemoryCommandOptions: @DRMEMORY_COMMAND_OPTIONS@ MemoryCheckType: @MEMORYCHECK_TYPE@ MemoryCheckSanitizerOptions: @MEMORYCHECK_SANITIZER_OPTIONS@ MemoryCheckCommand: @MEMORYCHECK_COMMAND@ diff --git a/Modules/DeployQt4.cmake b/Modules/DeployQt4.cmake index 4a18927..9aa4383 100644 --- a/Modules/DeployQt4.cmake +++ b/Modules/DeployQt4.cmake @@ -106,7 +106,6 @@ and plugin installation. See documentation of FIXUP_QT4_BUNDLE. # The functions defined in this file depend on the fixup_bundle function # (and others) found in BundleUtilities.cmake -set(DeployQt4_cmake_dir "${CMAKE_CURRENT_LIST_DIR}") set(DeployQt4_apple_plugins_dir "PlugIns") function(write_qt4_conf qt_conf_dir qt_conf_contents) @@ -392,7 +391,7 @@ function(install_qt4_executable executable) resolve_qt4_paths(libs "") install(CODE -"include(\"${DeployQt4_cmake_dir}/DeployQt4.cmake\") +"include(\"${CMAKE_CURRENT_FUNCTION_LIST_DIR}/DeployQt4.cmake\") set(BU_CHMOD_BUNDLE_ITEMS TRUE) FIXUP_QT4_EXECUTABLE(\"\$ENV{DESTDIR}\${CMAKE_INSTALL_PREFIX}/${executable}\" \"\" \"${libs}\" \"${dirs}\" \"${plugins_dir}\" \"${request_qt_conf}\")" ${component} diff --git a/Modules/ExternalProject.cmake b/Modules/ExternalProject.cmake index 66061a1..db3716a 100644 --- a/Modules/ExternalProject.cmake +++ b/Modules/ExternalProject.cmake @@ -265,6 +265,11 @@ External Project Definition is set to ``NEW`` if this value is set to an empty string then no submodules are initialized or updated. + ``GIT_SUBMODULES_RECURSE <bool>`` + Specify whether git submodules (if any) should update recursively by + passing the ``--recursive`` flag to ``git submodule update``. + If not specified, the default is on. + ``GIT_SHALLOW <bool>`` When this option is enabled, the ``git clone`` operation will be given the ``--depth 1`` option. This performs a shallow clone, which avoids @@ -1065,7 +1070,7 @@ define_property(DIRECTORY PROPERTY "EP_UPDATE_DISCONNECTED" INHERITED "ExternalProject module." ) -function(_ep_write_gitclone_script script_filename source_dir git_EXECUTABLE git_repository git_tag git_remote_name init_submodules git_submodules git_shallow git_progress git_config src_name work_dir gitclone_infofile gitclone_stampfile tls_verify) +function(_ep_write_gitclone_script script_filename source_dir git_EXECUTABLE git_repository git_tag git_remote_name init_submodules git_submodules_recurse git_submodules git_shallow git_progress git_config src_name work_dir gitclone_infofile gitclone_stampfile tls_verify) if(NOT GIT_VERSION_STRING VERSION_LESS 1.8.5) # Use `git checkout <tree-ish> --` to avoid ambiguity with a local path. set(git_checkout_explicit-- "--") @@ -1115,7 +1120,7 @@ if(NOT \"${gitclone_infofile}\" IS_NEWER_THAN \"${gitclone_stampfile}\") endif() execute_process( - COMMAND \${CMAKE_COMMAND} -E remove_directory \"${source_dir}\" + COMMAND \${CMAKE_COMMAND} -E rm -rf \"${source_dir}\" RESULT_VARIABLE error_code ) if(error_code) @@ -1153,7 +1158,7 @@ endif() set(init_submodules ${init_submodules}) if(init_submodules) execute_process( - COMMAND \"${git_EXECUTABLE}\" ${git_options} submodule update --recursive --init ${git_submodules} + COMMAND \"${git_EXECUTABLE}\" ${git_options} submodule update ${git_submodules_recurse} --init ${git_submodules} WORKING_DIRECTORY \"${work_dir}/${src_name}\" RESULT_VARIABLE error_code ) @@ -1191,7 +1196,7 @@ if(NOT \"${hgclone_infofile}\" IS_NEWER_THAN \"${hgclone_stampfile}\") endif() execute_process( - COMMAND \${CMAKE_COMMAND} -E remove_directory \"${source_dir}\" + COMMAND \${CMAKE_COMMAND} -E rm -rf \"${source_dir}\" RESULT_VARIABLE error_code ) if(error_code) @@ -1394,7 +1399,7 @@ if(error_code OR is_remote_ref OR NOT (\"\${tag_sha}\" STREQUAL \"\${head_sha}\" set(init_submodules ${init_submodules}) if(init_submodules) execute_process( - COMMAND \"${git_EXECUTABLE}\" submodule update --recursive --init ${git_submodules} + COMMAND \"${git_EXECUTABLE}\" submodule update ${git_submodules_recurse} --init ${git_submodules} WORKING_DIRECTORY \"${work_dir}/${src_name}\" RESULT_VARIABLE error_code ) @@ -1772,6 +1777,11 @@ function(_ep_write_initial_cache target_name script_filename script_initial_cach # Replace location tags. _ep_replace_location_tags(${target_name} script_initial_cache) _ep_replace_location_tags(${target_name} script_filename) + # Replace list separators. + get_property(sep TARGET ${target_name} PROPERTY _EP_LIST_SEPARATOR) + if(sep AND script_initial_cache) + string(REPLACE "${sep}" ";" script_initial_cache "${script_initial_cache}") + endif() # Write out the initial cache file to the location specified. file(GENERATE OUTPUT "${script_filename}" CONTENT "${script_initial_cache}") endfunction() @@ -2421,9 +2431,21 @@ function(_ep_add_download_command name) message(FATAL_ERROR "error: could not find git for clone of ${name}") endif() + get_property(git_submodules_recurse_set TARGET ${name} PROPERTY _EP_GIT_SUBMODULES_RECURSE SET) + if(NOT git_submodules_recurse_set) + set(git_submodules_recurse "--recursive") + else() + get_property(git_submodules_recurse_value TARGET ${name} PROPERTY _EP_GIT_SUBMODULES_RECURSE) + if(git_submodules_recurse_value) + set(git_submodules_recurse "--recursive") + else() + set(git_submodules_recurse "") + endif() + endif() + # The git submodule update '--recursive' flag requires git >= v1.6.5 # - if(GIT_VERSION_STRING VERSION_LESS 1.6.5) + if(git_submodules_recurse AND GIT_VERSION_STRING VERSION_LESS 1.6.5) message(FATAL_ERROR "error: git version 1.6.5 or later required for 'git submodule update --recursive': GIT_VERSION_STRING='${GIT_VERSION_STRING}'") endif() @@ -2477,7 +2499,7 @@ function(_ep_add_download_command name) # The script will delete the source directory and then call git clone. # _ep_write_gitclone_script(${tmp_dir}/${name}-gitclone.cmake ${source_dir} - ${GIT_EXECUTABLE} ${git_repository} ${git_tag} ${git_remote_name} ${git_init_submodules} "${git_submodules}" "${git_shallow}" "${git_progress}" "${git_config}" ${src_name} ${work_dir} + ${GIT_EXECUTABLE} ${git_repository} ${git_tag} ${git_remote_name} ${git_init_submodules} "${git_submodules_recurse}" "${git_submodules}" "${git_shallow}" "${git_progress}" "${git_config}" ${src_name} ${work_dir} ${stamp_dir}/${name}-gitinfo.txt ${stamp_dir}/${name}-gitclone-lastrun.txt "${tls_verify}" ) set(comment "Performing download step (git clone) for '${name}'") @@ -2563,7 +2585,7 @@ function(_ep_add_download_command name) if(IS_DIRECTORY "${url}") get_filename_component(abs_dir "${url}" ABSOLUTE) set(comment "Performing download step (DIR copy) for '${name}'") - set(cmd ${CMAKE_COMMAND} -E remove_directory ${source_dir} + set(cmd ${CMAKE_COMMAND} -E rm -rf ${source_dir} COMMAND ${CMAKE_COMMAND} -E copy_directory ${abs_dir} ${source_dir}) else() get_property(no_extract TARGET "${name}" PROPERTY _EP_DOWNLOAD_NO_EXTRACT SET) diff --git a/Modules/FetchContent.cmake b/Modules/FetchContent.cmake index 5716b01..f3e1b51 100644 --- a/Modules/FetchContent.cmake +++ b/Modules/FetchContent.cmake @@ -596,9 +596,6 @@ current working directory. #]=======================================================================] - -set(__FetchContent_privateDir "${CMAKE_CURRENT_LIST_DIR}/FetchContent") - #======================================================================= # Recording and retrieving content details for later population #======================================================================= @@ -888,7 +885,7 @@ function(__FetchContent_directPopulate contentName) # anything to be updated, so extra rebuilds of the project won't occur. # Make sure to pass through CMAKE_MAKE_PROGRAM in case the main project # has this set to something not findable on the PATH. - configure_file("${__FetchContent_privateDir}/CMakeLists.cmake.in" + configure_file("${CMAKE_CURRENT_FUNCTION_LIST_DIR}/FetchContent/CMakeLists.cmake.in" "${ARG_SUBBUILD_DIR}/CMakeLists.txt") execute_process( COMMAND ${CMAKE_COMMAND} ${generatorOpts} . diff --git a/Modules/FindBLAS.cmake b/Modules/FindBLAS.cmake index d3acafc..dc73f16 100644 --- a/Modules/FindBLAS.cmake +++ b/Modules/FindBLAS.cmake @@ -521,7 +521,7 @@ if (BLA_VENDOR STREQUAL "ATLAS" OR BLA_VENDOR STREQUAL "All") BLAS dgemm "" - "f77blas;atlas" + "blas;f77blas;atlas" "" ) endif() diff --git a/Modules/FindCUDA.cmake b/Modules/FindCUDA.cmake index b6859aa..0e2f551 100644 --- a/Modules/FindCUDA.cmake +++ b/Modules/FindCUDA.cmake @@ -5,17 +5,22 @@ FindCUDA .. deprecated:: 3.10 Superseded by first-class support for the CUDA language in CMake. + Superseded by the :module:`FindCUDAToolkit` for CUDA toolkit libraries. Replacement ^^^^^^^^^^^ -It is no longer necessary to use this module or call ``find_package(CUDA)``. -Instead, list ``CUDA`` among the languages named in the top-level -call to the :command:`project` command, or call the +It is no longer necessary to use this module or call ``find_package(CUDA)`` +for compiling CUDA code. Instead, list ``CUDA`` among the languages named +in the top-level call to the :command:`project` command, or call the :command:`enable_language` command with ``CUDA``. Then one can add CUDA (``.cu``) sources to programs directly in calls to :command:`add_library` and :command:`add_executable`. +To find and use the CUDA toolkit libraries the :module:`FindCUDAToolkit` +module has superseded this module. It works whether or not the ``CUDA`` +language is enabled. + Documentation of Deprecated Usage ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -676,7 +681,7 @@ endif() # Search for the cuda distribution. if(NOT CUDA_TOOLKIT_ROOT_DIR AND NOT CMAKE_CROSSCOMPILING) # Search in the CUDA_BIN_PATH first. - find_path(CUDA_TOOLKIT_ROOT_DIR + find_program(CUDA_TOOLKIT_ROOT_DIR_NVCC NAMES nvcc nvcc.exe PATHS ENV CUDA_TOOLKIT_ROOT @@ -688,19 +693,22 @@ if(NOT CUDA_TOOLKIT_ROOT_DIR AND NOT CMAKE_CROSSCOMPILING) ) # Now search default paths - find_path(CUDA_TOOLKIT_ROOT_DIR + find_program(CUDA_TOOLKIT_ROOT_DIR_NVCC NAMES nvcc nvcc.exe PATHS /opt/cuda/bin PATH_SUFFIXES cuda/bin DOC "Toolkit location." ) - if (CUDA_TOOLKIT_ROOT_DIR) + if (CUDA_TOOLKIT_ROOT_DIR_NVCC) + get_filename_component(CUDA_TOOLKIT_ROOT_DIR_NVCC_PAR "${CUDA_TOOLKIT_ROOT_DIR_NVCC}" DIRECTORY) + get_filename_component(CUDA_TOOLKIT_ROOT_DIR "${CUDA_TOOLKIT_ROOT_DIR_NVCC_PAR}" DIRECTORY CACHE) string(REGEX REPLACE "[/\\\\]?bin[64]*[/\\\\]?$" "" CUDA_TOOLKIT_ROOT_DIR ${CUDA_TOOLKIT_ROOT_DIR}) # We need to force this back into the cache. set(CUDA_TOOLKIT_ROOT_DIR ${CUDA_TOOLKIT_ROOT_DIR} CACHE PATH "Toolkit location." FORCE) set(CUDA_TOOLKIT_TARGET_DIR ${CUDA_TOOLKIT_ROOT_DIR}) endif() + unset(CUDA_TOOLKIT_ROOT_DIR_NVCC CACHE) if (NOT EXISTS ${CUDA_TOOLKIT_ROOT_DIR}) if(CUDA_FIND_REQUIRED) @@ -921,7 +929,7 @@ set(CUDA_LIBRARIES) if(CUDA_BUILD_EMULATION AND CUDA_CUDARTEMU_LIBRARY) list(APPEND CUDA_LIBRARIES ${CUDA_CUDARTEMU_LIBRARY}) elseif(CUDA_USE_STATIC_CUDA_RUNTIME AND CUDA_cudart_static_LIBRARY) - list(APPEND CUDA_LIBRARIES ${CUDA_cudart_static_LIBRARY} ${CMAKE_THREAD_LIBS_INIT} ${CMAKE_DL_LIBS}) + list(APPEND CUDA_LIBRARIES ${CUDA_cudart_static_LIBRARY} Threads::Threads ${CMAKE_DL_LIBS}) if (CUDA_rt_LIBRARY) list(APPEND CUDA_LIBRARIES ${CUDA_rt_LIBRARY}) endif() @@ -2003,7 +2011,7 @@ macro(CUDA_BUILD_CLEAN_TARGET) string(TOUPPER ${cuda_clean_target_name} cuda_clean_target_name) endif() add_custom_target(${cuda_clean_target_name} - COMMAND ${CMAKE_COMMAND} -E remove ${CUDA_ADDITIONAL_CLEAN_FILES}) + COMMAND ${CMAKE_COMMAND} -E rm -f ${CUDA_ADDITIONAL_CLEAN_FILES}) # Clear out the variable, so the next time we configure it will be empty. # This is useful so that the files won't persist in the list after targets diff --git a/Modules/FindCUDA/run_nvcc.cmake b/Modules/FindCUDA/run_nvcc.cmake index af15d55..ba35433 100644 --- a/Modules/FindCUDA/run_nvcc.cmake +++ b/Modules/FindCUDA/run_nvcc.cmake @@ -174,7 +174,7 @@ endmacro() # Delete the target file cuda_execute_process( "Removing ${generated_file}" - COMMAND "${CMAKE_COMMAND}" -E remove "${generated_file}" + COMMAND "${CMAKE_COMMAND}" -E rm -f "${generated_file}" ) # For CUDA 2.3 and below, -G -M doesn't work, so remove the -G flag @@ -241,7 +241,7 @@ endif() # Delete the temporary file cuda_execute_process( "Removing ${cmake_dependency_file}.tmp and ${NVCC_generated_dependency_file}" - COMMAND "${CMAKE_COMMAND}" -E remove "${cmake_dependency_file}.tmp" "${NVCC_generated_dependency_file}" + COMMAND "${CMAKE_COMMAND}" -E rm -f "${cmake_dependency_file}.tmp" "${NVCC_generated_dependency_file}" ) if(CUDA_result) @@ -267,7 +267,7 @@ if(CUDA_result) # Since nvcc can sometimes leave half done files make sure that we delete the output file. cuda_execute_process( "Removing ${generated_file}" - COMMAND "${CMAKE_COMMAND}" -E remove "${generated_file}" + COMMAND "${CMAKE_COMMAND}" -E rm -f "${generated_file}" ) message(FATAL_ERROR "Error generating file ${generated_file}") else() diff --git a/Modules/FindCUDAToolkit.cmake b/Modules/FindCUDAToolkit.cmake new file mode 100644 index 0000000..1837694 --- /dev/null +++ b/Modules/FindCUDAToolkit.cmake @@ -0,0 +1,785 @@ +# Distributed under the OSI-approved BSD 3-Clause License. See accompanying +# file Copyright.txt or https://cmake.org/licensing for details. + +#[=======================================================================[.rst: +FindCUDAToolkit +--------------- + +This script locates the NVIDIA CUDA toolkit and the associated libraries, but +does not require the ``CUDA`` language be enabled for a given project. This +module does not search for the NVIDIA CUDA Samples. + +Search Behavior +^^^^^^^^^^^^^^^ + +Finding the CUDA Toolkit requires finding the ``nvcc`` executable, which is +searched for in the following order: + +1. If the ``CUDA`` language has been enabled we will use the directory + containing the compiler as the first search location for ``nvcc``. + +2. If the ``CUDAToolkit_ROOT`` cmake configuration variable (e.g., + ``-DCUDAToolkit_ROOT=/some/path``) *or* environment variable is defined, it + will be searched. If both an environment variable **and** a + configuration variable are specified, the *configuration* variable takes + precedence. + + The directory specified here must be such that the executable ``nvcc`` can be + found underneath the directory specified by ``CUDAToolkit_ROOT``. If + ``CUDAToolkit_ROOT`` is specified, but no ``nvcc`` is found underneath, this + package is marked as **not** found. No subsequent search attempts are + performed. + +3. If the CUDA_PATH environment variable is defined, it will be searched. + +4. The user's path is searched for ``nvcc`` using :command:`find_program`. If + this is found, no subsequent search attempts are performed. Users are + responsible for ensuring that the first ``nvcc`` to show up in the path is + the desired path in the event that multiple CUDA Toolkits are installed. + +5. On Unix systems, if the symbolic link ``/usr/local/cuda`` exists, this is + used. No subsequent search attempts are performed. No default symbolic link + location exists for the Windows platform. + +6. The platform specific default install locations are searched. If exactly one + candidate is found, this is used. The default CUDA Toolkit install locations + searched are: + + +-------------+-------------------------------------------------------------+ + | Platform | Search Pattern | + +=============+=============================================================+ + | macOS | ``/Developer/NVIDIA/CUDA-X.Y`` | + +-------------+-------------------------------------------------------------+ + | Other Unix | ``/usr/local/cuda-X.Y`` | + +-------------+-------------------------------------------------------------+ + | Windows | ``C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\vX.Y`` | + +-------------+-------------------------------------------------------------+ + + Where ``X.Y`` would be a specific version of the CUDA Toolkit, such as + ``/usr/local/cuda-9.0`` or + ``C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v9.0`` + + .. note:: + + When multiple CUDA Toolkits are installed in the default location of a + system (e.g., both ``/usr/local/cuda-9.0`` and ``/usr/local/cuda-10.0`` + exist but the ``/usr/local/cuda`` symbolic link does **not** exist), this + package is marked as **not** found. + + There are too many factors involved in making an automatic decision in + the presence of multiple CUDA Toolkits being installed. In this + situation, users are encouraged to either (1) set ``CUDAToolkit_ROOT`` or + (2) ensure that the correct ``nvcc`` executable shows up in ``$PATH`` for + :command:`find_program` to find. + +Options +^^^^^^^ + +``VERSION`` + If specified, describes the version of the CUDA Toolkit to search for. + +``REQUIRED`` + If specified, configuration will error if a suitable CUDA Toolkit is not + found. + +``QUIET`` + If specified, the search for a suitable CUDA Toolkit will not produce any + messages. + +``EXACT`` + If specified, the CUDA Toolkit is considered found only if the exact + ``VERSION`` specified is recovered. + +Imported targets +^^^^^^^^^^^^^^^^ + +An :ref:`imported target <Imported targets>` named ``CUDA::toolkit`` is provided. + +This module defines :prop_tgt:`IMPORTED` targets for each +of the following libraries that are part of the CUDAToolkit: + +- :ref:`CUDA Runtime Library<cuda_toolkit_rt_lib>` +- :ref:`CUDA Driver Library<cuda_toolkit_driver_lib>` +- :ref:`cuBLAS<cuda_toolkit_cuBLAS>` +- :ref:`cuFFT<cuda_toolkit_cuFFT>` +- :ref:`cuRAND<cuda_toolkit_cuRAND>` +- :ref:`cuSOLVER<cuda_toolkit_cuSOLVER>` +- :ref:`cuSPARSE<cuda_toolkit_cuSPARSE>` +- :ref:`NPP<cuda_toolkit_NPP>` +- :ref:`nvBLAS<cuda_toolkit_nvBLAS>` +- :ref:`nvGRAPH<cuda_toolkit_nvGRAPH>` +- :ref:`nvJPEG<cuda_toolkit_nvJPEG>` +- :ref:`nvidia-ML<cuda_toolkit_nvML>` +- :ref:`nvRTC<cuda_toolkit_nvRTC>` +- :ref:`nvToolsExt<cuda_toolkit_nvToolsExt>` +- :ref:`OpenCL<cuda_toolkit_opencl>` +- :ref:`cuLIBOS<cuda_toolkit_cuLIBOS>` + +.. _`cuda_toolkit_rt_lib`: + +CUDA Runtime Library +"""""""""""""""""""" + +The CUDA Runtime library (cudart) are what most applications will typically +need to link against to make any calls such as `cudaMalloc`, and `cudaFree`. +They are an explicit dependency of almost every library. + +Targets Created: + +- ``CUDA::cudart`` +- ``CUDA::cudart_static`` + +.. _`cuda_toolkit_driver_lib`: + +CUDA Driver Library +"""""""""""""""""""" + +The CUDA Driver library (cuda) are used by applications that use calls +such as `cuMemAlloc`, and `cuMemFree`. This is generally used by advanced + + +Targets Created: + +- ``CUDA::cuda_driver`` +- ``CUDA::cuda_driver`` + +.. _`cuda_toolkit_cuBLAS`: + +cuBLAS +"""""" + +The `cuBLAS <https://docs.nvidia.com/cuda/cublas/index.html>`_ library. + +Targets Created: + +- ``CUDA::cublas`` +- ``CUDA::cublas_static`` + +.. _`cuda_toolkit_cuFFT`: + +cuFFT +""""" + +The `cuFFT <https://docs.nvidia.com/cuda/cufft/index.html>`_ library. + +Targets Created: + +- ``CUDA::cufft`` +- ``CUDA::cufftw`` +- ``CUDA::cufft_static`` +- ``CUDA::cufftw_static`` + +cuRAND +"""""" + +The `cuRAND <https://docs.nvidia.com/cuda/curand/index.html>`_ library. + +Targets Created: + +- ``CUDA::curand`` +- ``CUDA::curand_static`` + +.. _`cuda_toolkit_cuSOLVER`: + +cuSOLVER +"""""""" + +The `cuSOLVER <https://docs.nvidia.com/cuda/cusolver/index.html>`_ library. + +Targets Created: + +- ``CUDA::cusolver`` +- ``CUDA::cusolver_static`` + +.. _`cuda_toolkit_cuSPARSE`: + +cuSPARSE +"""""""" + +The `cuSPARSE <https://docs.nvidia.com/cuda/cusparse/index.html>`_ library. + +Targets Created: + +- ``CUDA::cusparse`` +- ``CUDA::cusparse_static`` + +.. _`cuda_toolkit_NPP`: + +NPP +""" + +The `NPP <https://docs.nvidia.com/cuda/npp/index.html>`_ libraries. + +Targets Created: + +- `nppc`: + + - ``CUDA::nppc`` + - ``CUDA::nppc_static`` + +- `nppial`: Arithmetic and logical operation functions in `nppi_arithmetic_and_logical_operations.h` + + - ``CUDA::nppial`` + - ``CUDA::nppial_static`` + +- `nppicc`: Color conversion and sampling functions in `nppi_color_conversion.h` + + - ``CUDA::nppicc`` + - ``CUDA::nppicc_static`` + +- `nppicom`: JPEG compression and decompression functions in `nppi_compression_functions.h` + + - ``CUDA::nppicom`` + - ``CUDA::nppicom_static`` + +- `nppidei`: Data exchange and initialization functions in `nppi_data_exchange_and_initialization.h` + + - ``CUDA::nppidei`` + - ``CUDA::nppidei_static`` + +- `nppif`: Filtering and computer vision functions in `nppi_filter_functions.h` + + - ``CUDA::nppif`` + - ``CUDA::nppif_static`` + +- `nppig`: Geometry transformation functions found in `nppi_geometry_transforms.h` + + - ``CUDA::nppig`` + - ``CUDA::nppig_static`` + +- `nppim`: Morphological operation functions found in `nppi_morphological_operations.h` + + - ``CUDA::nppim`` + - ``CUDA::nppim_static`` + +- `nppist`: Statistics and linear transform in `nppi_statistics_functions.h` and `nppi_linear_transforms.h` + + - ``CUDA::nppist`` + - ``CUDA::nppist_static`` + +- `nppisu`: Memory support functions in `nppi_support_functions.h` + + - ``CUDA::nppisu`` + - ``CUDA::nppisu_static`` + +- `nppitc`: Threshold and compare operation functions in `nppi_threshold_and_compare_operations.h` + + - ``CUDA::nppitc`` + - ``CUDA::nppitc_static`` + +- `npps`: + + - ``CUDA::npps`` + - ``CUDA::npps_static`` + +.. _`cuda_toolkit_nvBLAS`: + +nvBLAS +"""""" + +The `nvBLAS <https://docs.nvidia.com/cuda/nvblas/index.html>`_ libraries. +This is a shared library only. + +Targets Created: + +- ``CUDA::nvblas`` + +.. _`cuda_toolkit_nvGRAPH`: + +nvGRAPH +""""""" + +The `nvGRAPH <https://docs.nvidia.com/cuda/nvgraph/index.html>`_ library. + +Targets Created: + +- ``CUDA::nvgraph`` +- ``CUDA::nvgraph_static`` + + +.. _`cuda_toolkit_nvJPEG`: + +nvJPEG +"""""" + +The `nvJPEG <https://docs.nvidia.com/cuda/nvjpeg/index.html>`_ library. +Introduced in CUDA 10. + +Targets Created: + +- ``CUDA::nvjpeg`` +- ``CUDA::nvjpeg_static`` + +.. _`cuda_toolkit_nvRTC`: + +nvRTC +""""" + +The `nvRTC <https://docs.nvidia.com/cuda/nvrtc/index.html>`_ (Runtime Compilation) library. +This is a shared library only. + +Targets Created: + +- ``CUDA::nvrtc`` + +.. _`cuda_toolkit_nvml`: + +nvidia-ML +""""""""" + +The `NVIDIA Management Library <https://developer.nvidia.com/nvidia-management-library-nvml>`_. +This is a shared library only. + +Targets Created: + +- ``CUDA::nvml`` + +.. _`cuda_toolkit_opencl`: + +.. _`cuda_toolkit_nvToolsExt`: + +nvToolsExt +"""""""""" + +The `NVIDIA Tools Extension <https://docs.nvidia.com/gameworks/content/gameworkslibrary/nvtx/nvidia_tools_extension_library_nvtx.htm>`_. +This is a shared library only. + +Targets Created: + +- ``CUDA::nvToolsExt`` + +OpenCL +"""""" + +The `NVIDIA OpenCL Library <https://developer.nvidia.com/opencl>`_. +This is a shared library only. + +Targets Created: + +- ``CUDA::OpenCL`` + +.. _`cuda_toolkit_cuLIBOS`: + +cuLIBOS +""""""" + +The cuLIBOS library is a backend thread abstraction layer library which is +static only. The ``CUDA::cublas_static``, ``CUDA::cusparse_static``, +``CUDA::cufft_static``, ``CUDA::curand_static``, and (when implemented) NPP +libraries all automatically have this dependency linked. + +Target Created: + +- ``CUDA::culibos`` + +**Note**: direct usage of this target by consumers should not be necessary. + +.. _`cuda_toolkit_cuRAND`: + + + +Result variables +^^^^^^^^^^^^^^^^ + +``CUDAToolkit_FOUND`` + A boolean specifying whether or not the CUDA Toolkit was found. + +``CUDAToolkit_VERSION`` + The exact version of the CUDA Toolkit found (as reported by + ``nvcc --version``). + +``CUDAToolkit_VERSION_MAJOR`` + The major version of the CUDA Toolkit. + +``CUDAToolkit_VERSION_MAJOR`` + The minor version of the CUDA Toolkit. + +``CUDAToolkit_VERSION_PATCH`` + The patch version of the CUDA Toolkit. + +``CUDAToolkit_BIN_DIR`` + The path to the CUDA Toolkit library directory that contains the CUDA + executable ``nvcc``. + +``CUDAToolkit_INCLUDE_DIRS`` + The path to the CUDA Toolkit ``include`` folder containing the header files + required to compile a project linking against CUDA. + +``CUDAToolkit_LIBRARY_DIR`` + The path to the CUDA Toolkit library directory that contains the CUDA + Runtime library ``cudart``. + +``CUDAToolkit_NVCC_EXECUTABLE`` + The path to the NVIDIA CUDA compiler ``nvcc``. Note that this path may + **not** be the same as + :variable:`CMAKE_CUDA_COMPILER <CMAKE_<LANG>_COMPILER>`. ``nvcc`` must be + found to determine the CUDA Toolkit version as well as determining other + features of the Toolkit. This variable is set for the convenience of + modules that depend on this one. + + +#]=======================================================================] + +# NOTE: much of this was simply extracted from FindCUDA.cmake. + +# James Bigler, NVIDIA Corp (nvidia.com - jbigler) +# Abe Stephens, SCI Institute -- http://www.sci.utah.edu/~abe/FindCuda.html +# +# Copyright (c) 2008 - 2009 NVIDIA Corporation. All rights reserved. +# +# Copyright (c) 2007-2009 +# Scientific Computing and Imaging Institute, University of Utah +# +# This code is licensed under the MIT License. See the FindCUDA.cmake script +# for the text of the license. + +# The MIT License +# +# License for the specific language governing rights and limitations under +# Permission is hereby granted, free of charge, to any person obtaining a +# copy of this software and associated documentation files (the "Software"), +# to deal in the Software without restriction, including without limitation +# the rights to use, copy, modify, merge, publish, distribute, sublicense, +# and/or sell copies of the Software, and to permit persons to whom the +# Software is furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included +# in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +# DEALINGS IN THE SOFTWARE. +# +############################################################################### + +if(CMAKE_CUDA_COMPILER_LOADED AND NOT CUDAToolkit_BIN_DIR) + get_filename_component(cuda_dir "${CMAKE_CUDA_COMPILER}" DIRECTORY) + # use the already detected cuda compiler + set(CUDAToolkit_BIN_DIR "${cuda_dir}" CACHE PATH "") + unset(cuda_dir) +endif() + +# Try language- or user-provided path first. +if(CUDAToolkit_BIN_DIR) + find_program(CUDAToolkit_NVCC_EXECUTABLE + NAMES nvcc nvcc.exe + PATHS ${CUDAToolkit_BIN_DIR} + NO_DEFAULT_PATH + ) +endif() + +# Search using CUDAToolkit_ROOT +find_program(CUDAToolkit_NVCC_EXECUTABLE + NAMES nvcc nvcc.exe + PATHS ENV CUDA_PATH + PATH_SUFFIXES bin +) + +# If the user specified CUDAToolkit_ROOT but nvcc could not be found, this is an error. +if (NOT CUDAToolkit_NVCC_EXECUTABLE AND (DEFINED CUDAToolkit_ROOT OR DEFINED ENV{CUDAToolkit_ROOT})) + # Declare error messages now, print later depending on find_package args. + set(fail_base "Could not find nvcc executable in path specified by") + set(cuda_root_fail "${fail_base} CUDAToolkit_ROOT=${CUDAToolkit_ROOT}") + set(env_cuda_root_fail "${fail_base} environment variable CUDAToolkit_ROOT=$ENV{CUDAToolkit_ROOT}") + + if (CUDAToolkit_FIND_REQUIRED) + if (DEFINED CUDAToolkit_ROOT) + message(FATAL_ERROR ${cuda_root_fail}) + elseif (DEFINED ENV{CUDAToolkit_ROOT}) + message(FATAL_ERROR ${env_cuda_root_fail}) + endif() + else() + if (NOT CUDAToolkit_FIND_QUIETLY) + if (DEFINED CUDAToolkit_ROOT) + message(STATUS ${cuda_root_fail}) + elseif (DEFINED ENV{CUDAToolkit_ROOT}) + message(STATUS ${env_cuda_root_fail}) + endif() + endif() + set(CUDAToolkit_FOUND FALSE) + unset(fail_base) + unset(cuda_root_fail) + unset(env_cuda_root_fail) + return() + endif() +endif() + +# CUDAToolkit_ROOT cmake / env variable not specified, try platform defaults. +# +# - Linux: /usr/local/cuda-X.Y +# - macOS: /Developer/NVIDIA/CUDA-X.Y +# - Windows: C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\vX.Y +# +# We will also search the default symlink location /usr/local/cuda first since +# if CUDAToolkit_ROOT is not specified, it is assumed that the symlinked +# directory is the desired location. +if (NOT CUDAToolkit_NVCC_EXECUTABLE) + if (UNIX) + if (NOT APPLE) + set(platform_base "/usr/local/cuda-") + else() + set(platform_base "/Developer/NVIDIA/CUDA-") + endif() + else() + set(platform_base "C:\\Program Files\\NVIDIA GPU Computing Toolkit\\CUDA\\v") + endif() + + # Build out a descending list of possible cuda installations, e.g. + file(GLOB possible_paths "${platform_base}*") + # Iterate the glob results and create a descending list. + set(possible_versions) + foreach (p ${possible_paths}) + # Extract version number from end of string + string(REGEX MATCH "[0-9][0-9]?\\.[0-9]$" p_version ${p}) + if (IS_DIRECTORY ${p} AND p_version) + list(APPEND possible_versions ${p_version}) + endif() + endforeach() + + # Cannot use list(SORT) because that is alphabetical, we need numerical. + # NOTE: this is not an efficient sorting strategy. But even if a user had + # every possible version of CUDA installed, this wouldn't create any + # significant overhead. + set(versions) + foreach (v ${possible_versions}) + list(LENGTH versions num_versions) + # First version, nothing to compare with so just append. + if (num_versions EQUAL 0) + list(APPEND versions ${v}) + else() + # Loop through list. Insert at an index when comparison is + # VERSION_GREATER since we want a descending list. Duplicates will not + # happen since this came from a glob list of directories. + set(i 0) + set(early_terminate FALSE) + while (i LESS num_versions) + list(GET versions ${i} curr) + if (v VERSION_GREATER curr) + list(INSERT versions ${i} ${v}) + set(early_terminate TRUE) + break() + endif() + math(EXPR i "${i} + 1") + endwhile() + # If it did not get inserted, place it at the end. + if (NOT early_terminate) + list(APPEND versions ${v}) + endif() + endif() + endforeach() + + # With a descending list of versions, populate possible paths to search. + set(search_paths) + foreach (v ${versions}) + list(APPEND search_paths "${platform_base}${v}") + endforeach() + + # Force the global default /usr/local/cuda to the front on Unix. + if (UNIX) + list(INSERT search_paths 0 "/usr/local/cuda") + endif() + + # Now search for nvcc again using the platform default search paths. + find_program(CUDAToolkit_NVCC_EXECUTABLE + NAMES nvcc nvcc.exe + PATHS ${search_paths} + PATH_SUFFIXES bin + ) + + # We are done with these variables now, cleanup for caller. + unset(platform_base) + unset(possible_paths) + unset(possible_versions) + unset(versions) + unset(i) + unset(early_terminate) + unset(search_paths) + + if (NOT CUDAToolkit_NVCC_EXECUTABLE) + if (CUDAToolkit_FIND_REQUIRED) + message(FATAL_ERROR "Could not find nvcc, please set CUDAToolkit_ROOT.") + elseif(NOT CUDAToolkit_FIND_QUIETLY) + message(STATUS "Could not find nvcc, please set CUDAToolkit_ROOT.") + endif() + + set(CUDAToolkit_FOUND FALSE) + return() + endif() +endif() + +if(NOT CUDAToolkit_BIN_DIR AND CUDAToolkit_NVCC_EXECUTABLE) + get_filename_component(cuda_dir "${CUDAToolkit_NVCC_EXECUTABLE}" DIRECTORY) + set(CUDAToolkit_BIN_DIR "${cuda_dir}" CACHE PATH "" FORCE) + unset(cuda_dir) +endif() + +if(CUDAToolkit_NVCC_EXECUTABLE AND + CUDAToolkit_NVCC_EXECUTABLE STREQUAL CMAKE_CUDA_COMPILER) + # Need to set these based off the already computed CMAKE_CUDA_COMPILER_VERSION value + # This if statement will always match, but is used to provide variables for MATCH 1,2,3... + if(CMAKE_CUDA_COMPILER_VERSION MATCHES [=[([0-9]+)\.([0-9]+)\.([0-9]+)]=]) + set(CUDAToolkit_VERSION_MAJOR "${CMAKE_MATCH_1}") + set(CUDAToolkit_VERSION_MINOR "${CMAKE_MATCH_2}") + set(CUDAToolkit_VERSION_PATCH "${CMAKE_MATCH_3}") + set(CUDAToolkit_VERSION "${CMAKE_CUDA_COMPILER_VERSION}") + endif() +else() + # Compute the version by invoking nvcc + execute_process (COMMAND ${CUDAToolkit_NVCC_EXECUTABLE} "--version" OUTPUT_VARIABLE NVCC_OUT) + if(NVCC_OUT MATCHES [=[ V([0-9]+)\.([0-9]+)\.([0-9]+)]=]) + set(CUDAToolkit_VERSION_MAJOR "${CMAKE_MATCH_1}") + set(CUDAToolkit_VERSION_MINOR "${CMAKE_MATCH_2}") + set(CUDAToolkit_VERSION_PATCH "${CMAKE_MATCH_3}") + set(CUDAToolkit_VERSION "${CMAKE_MATCH_1}.${CMAKE_MATCH_2}.${CMAKE_MATCH_3}") + endif() + unset(NVCC_OUT) +endif() + + +get_filename_component(CUDAToolkit_ROOT_DIR ${CUDAToolkit_BIN_DIR} DIRECTORY ABSOLUTE) + +# Now that we have the real ROOT_DIR, find components inside it. +list(APPEND CMAKE_PREFIX_PATH ${CUDAToolkit_ROOT_DIR}) + +# Find the include/ directory +find_path(CUDAToolkit_INCLUDE_DIR + NAMES cuda_runtime.h +) + +# And find the CUDA Runtime Library libcudart +find_library(CUDA_CUDART + NAMES cudart + PATH_SUFFIXES lib64 lib/x64 +) +if (NOT CUDA_CUDART AND NOT CUDAToolkit_FIND_QUIETLY) + message(STATUS "Unable to find cudart library.") +endif() + +unset(CUDAToolkit_ROOT_DIR) +list(REMOVE_AT CMAKE_PREFIX_PATH -1) + +#----------------------------------------------------------------------------- +# Perform version comparison and validate all required variables are set. +include(${CMAKE_CURRENT_LIST_DIR}/FindPackageHandleStandardArgs.cmake) +find_package_handle_standard_args(CUDAToolkit + REQUIRED_VARS + CUDAToolkit_INCLUDE_DIR + CUDA_CUDART + CUDAToolkit_NVCC_EXECUTABLE + VERSION_VAR + CUDAToolkit_VERSION +) + +#----------------------------------------------------------------------------- +# Construct result variables +if(CUDAToolkit_FOUND) + set(CUDAToolkit_INCLUDE_DIRS ${CUDAToolkit_INCLUDE_DIR}) + get_filename_component(CUDAToolkit_LIBRARY_DIR ${CUDA_CUDART} DIRECTORY ABSOLUTE) +endif() + +#----------------------------------------------------------------------------- +# Construct import targets +if(CUDAToolkit_FOUND) + + function(find_and_add_cuda_import_lib lib_name) + + if(ARGC GREATER 1) + set(search_names ${ARGN}) + else() + set(search_names ${lib_name}) + endif() + + find_library(CUDA_${lib_name}_LIBRARY + NAMES ${search_names} + PATHS ${CUDAToolkit_LIBRARY_DIR} + ENV CUDA_PATH + PATH_SUFFIXES nvidia/current lib64 lib/x64 lib + ) + + if (NOT CUDA::${lib_name} AND CUDA_${lib_name}_LIBRARY) + add_library(CUDA::${lib_name} IMPORTED INTERFACE) + target_include_directories(CUDA::${lib_name} SYSTEM INTERFACE "${CUDAToolkit_INCLUDE_DIRS}") + target_link_libraries(CUDA::${lib_name} INTERFACE "${CUDA_${lib_name}_LIBRARY}") + endif() + endfunction() + + function(add_cuda_link_dependency lib_name) + foreach(dependency IN LISTS ${ARGN}) + target_link_libraries(CUDA::${lib_name} INTERFACE CUDA::${dependency}) + endforeach() + endfunction() + + add_library(CUDA::toolkit IMPORTED INTERFACE) + target_include_directories(CUDA::toolkit SYSTEM INTERFACE "${CUDAToolkit_INCLUDE_DIRS}") + target_link_directories(CUDA::toolkit INTERFACE "${CUDAToolkit_LIBRARY_DIR}") + + + find_and_add_cuda_import_lib(cuda_driver cuda) + + find_and_add_cuda_import_lib(cudart) + find_and_add_cuda_import_lib(cudart_static) + + foreach (cuda_lib cublas cufft cufftw curand cusolver cusparse nvgraph nvjpeg) + find_and_add_cuda_import_lib(${cuda_lib}) + add_cuda_link_dependency(${cuda_lib} cudart) + + find_and_add_cuda_import_lib(${cuda_lib}_static) + add_cuda_link_dependency(${cuda_lib}_static cudart_static) + endforeach() + + # cuSOLVER depends on cuBLAS, and cuSPARSE + add_cuda_link_dependency(cusolver cublas cusparse) + add_cuda_link_dependency(cusolver_static cublas_static cusparse) + + # nvGRAPH depends on cuRAND, and cuSOLVER. + add_cuda_link_dependency(nvgraph curand cusolver) + add_cuda_link_dependency(nvgraph_static curand_static cusolver_static) + + find_and_add_cuda_import_lib(nppc) + find_and_add_cuda_import_lib(nppc_static) + + add_cuda_link_dependency(nppc cudart) + add_cuda_link_dependency(nppc_static cudart_static culibos) + + # Process the majority of the NPP libraries. + foreach (cuda_lib nppial nppicc nppidei nppif nppig nppim nppist nppitc npps nppicom nppisu) + find_and_add_cuda_import_lib(${cuda_lib}) + find_and_add_cuda_import_lib(${cuda_lib}_static) + add_cuda_link_dependency(${cuda_lib} nppc) + add_cuda_link_dependency(${cuda_lib}_static nppc_static) + endforeach() + + find_and_add_cuda_import_lib(nvrtc) + add_cuda_link_dependency(nvrtc cuda_driver) + + find_and_add_cuda_import_lib(nvml nvidia-ml nvml) + + if(WIN32) + # nvtools can be installed outside the CUDA toolkit directory + # so prefer the NVTOOLSEXT_PATH windows only environment variable + # In addition on windows the most common name is nvToolsExt64_1 + find_library(CUDA_nvToolsExt_LIBRARY + NAMES nvToolsExt64_1 nvToolsExt64 nvToolsExt + PATHS ENV NVTOOLSEXT_PATH + ENV CUDA_PATH + PATH_SUFFIXES lib/x64 lib + ) + endif() + find_and_add_cuda_import_lib(nvToolsExt nvToolsExt nvToolsExt64) + + add_cuda_link_dependency(nvToolsExt cudart) + + find_and_add_cuda_import_lib(OpenCL) + + find_and_add_cuda_import_lib(culibos) + if(TARGET CUDA::culibos) + foreach (cuda_lib cublas cufft cusparse curand nvjpeg) + add_cuda_link_dependency(${cuda_lib}_static culibos) + endforeach() + endif() + +endif() diff --git a/Modules/FindCURL.cmake b/Modules/FindCURL.cmake index aeebc84..919babc 100644 --- a/Modules/FindCURL.cmake +++ b/Modules/FindCURL.cmake @@ -37,8 +37,35 @@ This module defines the following variables: ``CURL_VERSION_STRING`` The version of ``curl`` found. + +CURL CMake +^^^^^^^^^^ + +If CURL was built using the CMake buildsystem then it provides its own +``CURLConfig.cmake`` file for use with the :command:`find_package` command's +config mode. This module looks for this file and, if found, +returns its results with no further action. + +Set ``CURL_NO_CURL_CMAKE`` to ``ON`` to disable this search. + #]=======================================================================] +include(${CMAKE_CURRENT_LIST_DIR}/FindPackageHandleStandardArgs.cmake) + +if(NOT CURL_NO_CURL_CMAKE) + # do a find package call to specifically look for the CMake version + # of curl + find_package(CURL QUIET NO_MODULE) + mark_as_advanced(CURL_DIR) + + # if we found the CURL cmake package then we are done, and + # can print what we found and return. + if(CURL_FOUND) + find_package_handle_standard_args(CURL HANDLE_COMPONENTS CONFIG_MODE) + return() + endif() +endif() + find_package(PkgConfig QUIET) if(PKG_CONFIG_FOUND) pkg_check_modules(PC_CURL QUIET libcurl) @@ -139,7 +166,6 @@ if(CURL_FIND_COMPONENTS) endforeach() endif() -include(${CMAKE_CURRENT_LIST_DIR}/FindPackageHandleStandardArgs.cmake) find_package_handle_standard_args(CURL REQUIRED_VARS CURL_LIBRARY CURL_INCLUDE_DIR VERSION_VAR CURL_VERSION_STRING diff --git a/Modules/FindDCMTK.cmake b/Modules/FindDCMTK.cmake index d48de08..b2e00df 100644 --- a/Modules/FindDCMTK.cmake +++ b/Modules/FindDCMTK.cmake @@ -102,7 +102,7 @@ set(_SAVED_DCMTK_DIR ${DCMTK_DIR}) # Step1: Attempt to find a version of DCMTK providing a DCMTKConfig.cmake file. # if(NOT DCMTK_FIND_QUIETLY) - message(STATUS "Trying to find DCMTK expecting DCMTKConfig.cmake") + message(CHECK_START "Trying to find DCMTK expecting DCMTKConfig.cmake") endif() find_package(DCMTK QUIET NO_MODULE) if(DCMTK_FOUND @@ -110,12 +110,12 @@ if(DCMTK_FOUND AND NOT "x" STREQUAL "x${DCMTK_INCLUDE_DIRS}") if(NOT DCMTK_FIND_QUIETLY) - message(STATUS "Trying to find DCMTK expecting DCMTKConfig.cmake - ok") + message(CHECK_PASS "ok") endif() return() else() if(NOT DCMTK_FIND_QUIETLY) - message(STATUS "Trying to find DCMTK expecting DCMTKConfig.cmake - failed") + message(CHECK_FAIL "failed") endif() endif() diff --git a/Modules/FindFLEX.cmake b/Modules/FindFLEX.cmake index d22b7ec..90e5f86 100644 --- a/Modules/FindFLEX.cmake +++ b/Modules/FindFLEX.cmake @@ -142,8 +142,6 @@ if(FLEX_EXECUTABLE) #============================================================ # macro(FLEX_TARGET Name Input Output) - set(FLEX_TARGET_outputs "${Output}") - set(FLEX_EXECUTABLE_opts "") set(FLEX_TARGET_PARAM_OPTIONS) set(FLEX_TARGET_PARAM_ONE_VALUE_KEYWORDS @@ -165,31 +163,68 @@ if(FLEX_EXECUTABLE) if(NOT "${FLEX_TARGET_ARG_UNPARSED_ARGUMENTS}" STREQUAL "") message(SEND_ERROR ${FLEX_TARGET_usage}) else() + + cmake_policy(GET CMP0098 _flex_CMP0098 + PARENT_SCOPE # undocumented, do not use outside of CMake + ) + set(_flex_INPUT "${Input}") + if("x${_flex_CMP0098}x" STREQUAL "xNEWx") + set(_flex_WORKING_DIR "${CMAKE_CURRENT_BINARY_DIR}") + if(NOT IS_ABSOLUTE "${_flex_INPUT}") + set(_flex_INPUT "${CMAKE_CURRENT_SOURCE_DIR}/${_flex_INPUT}") + endif() + else() + set(_flex_WORKING_DIR "${CMAKE_CURRENT_SOURCE_DIR}") + endif() + unset(_flex_CMP0098) + + set(_flex_OUTPUT "${Output}") + if(NOT IS_ABSOLUTE ${_flex_OUTPUT}) + set(_flex_OUTPUT "${_flex_WORKING_DIR}/${_flex_OUTPUT}") + endif() + set(_flex_TARGET_OUTPUTS "${_flex_OUTPUT}") + + set(_flex_EXE_OPTS "") if(NOT "${FLEX_TARGET_ARG_COMPILE_FLAGS}" STREQUAL "") - set(FLEX_EXECUTABLE_opts "${FLEX_TARGET_ARG_COMPILE_FLAGS}") - separate_arguments(FLEX_EXECUTABLE_opts) + set(_flex_EXE_OPTS "${FLEX_TARGET_ARG_COMPILE_FLAGS}") + separate_arguments(_flex_EXE_OPTS) endif() + + set(_flex_OUTPUT_HEADER "") if(NOT "${FLEX_TARGET_ARG_DEFINES_FILE}" STREQUAL "") - list(APPEND FLEX_TARGET_outputs "${FLEX_TARGET_ARG_DEFINES_FILE}") - list(APPEND FLEX_EXECUTABLE_opts --header-file=${FLEX_TARGET_ARG_DEFINES_FILE}) + set(_flex_OUTPUT_HEADER "${FLEX_TARGET_ARG_DEFINES_FILE}") + if(IS_ABSOLUTE "${_flex_OUTPUT_HEADER}") + set(_flex_OUTPUT_HEADER_ABS "${_flex_OUTPUT_HEADER}") + else() + set(_flex_OUTPUT_HEADER_ABS "${_flex_WORKING_DIR}/${_flex_OUTPUT_HEADER}") + endif() + list(APPEND _flex_TARGET_OUTPUTS "${_flex_OUTPUT_HEADER_ABS}") + list(APPEND _flex_EXE_OPTS --header-file=${_flex_OUTPUT_HEADER_ABS}) endif() - add_custom_command(OUTPUT ${FLEX_TARGET_outputs} - COMMAND ${FLEX_EXECUTABLE} ${FLEX_EXECUTABLE_opts} -o${Output} ${Input} + get_filename_component(_flex_EXE_NAME_WE "${FLEX_EXECUTABLE}" NAME_WE) + add_custom_command(OUTPUT ${_flex_TARGET_OUTPUTS} + COMMAND ${FLEX_EXECUTABLE} ${_flex_EXE_OPTS} -o${_flex_OUTPUT} ${_flex_INPUT} VERBATIM - DEPENDS ${Input} - COMMENT "[FLEX][${Name}] Building scanner with flex ${FLEX_VERSION}" - WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}) + DEPENDS ${_flex_INPUT} + COMMENT "[FLEX][${Name}] Building scanner with ${_flex_EXE_NAME_WE} ${FLEX_VERSION}" + WORKING_DIRECTORY ${_flex_WORKING_DIR}) set(FLEX_${Name}_DEFINED TRUE) - set(FLEX_${Name}_OUTPUTS ${Output}) - set(FLEX_${Name}_INPUT ${Input}) - set(FLEX_${Name}_COMPILE_FLAGS ${FLEX_EXECUTABLE_opts}) - if("${FLEX_TARGET_ARG_DEFINES_FILE}" STREQUAL "") - set(FLEX_${Name}_OUTPUT_HEADER "") - else() - set(FLEX_${Name}_OUTPUT_HEADER ${FLEX_TARGET_ARG_DEFINES_FILE}) - endif() + set(FLEX_${Name}_OUTPUTS ${_flex_TARGET_OUTPUTS}) + set(FLEX_${Name}_INPUT ${_flex_INPUT}) + set(FLEX_${Name}_COMPILE_FLAGS ${_flex_EXE_OPTS}) + set(FLEX_${Name}_OUTPUT_HEADER ${_flex_OUTPUT_HEADER}) + + unset(_flex_EXE_NAME_WE) + unset(_flex_EXE_OPTS) + unset(_flex_INPUT) + unset(_flex_OUTPUT) + unset(_flex_OUTPUT_HEADER) + unset(_flex_OUTPUT_HEADER_ABS) + unset(_flex_TARGET_OUTPUTS) + unset(_flex_WORKING_DIR) + endif() endmacro() #============================================================ diff --git a/Modules/FindLibArchive.cmake b/Modules/FindLibArchive.cmake index ef27b7d..ce3c8b8 100644 --- a/Modules/FindLibArchive.cmake +++ b/Modules/FindLibArchive.cmake @@ -16,18 +16,26 @@ The module defines the following variables: LibArchive_INCLUDE_DIRS - include search path LibArchive_LIBRARIES - libraries to link LibArchive_VERSION - libarchive 3-component version number + +The module defines the following ``IMPORTED`` targets: + +:: + + LibArchive::LibArchive - target for linking against libarchive #]=======================================================================] find_path(LibArchive_INCLUDE_DIR NAMES archive.h PATHS "[HKEY_LOCAL_MACHINE\\SOFTWARE\\GnuWin32\\LibArchive;InstallPath]/include" + DOC "libarchive include directory" ) find_library(LibArchive_LIBRARY NAMES archive libarchive PATHS "[HKEY_LOCAL_MACHINE\\SOFTWARE\\GnuWin32\\LibArchive;InstallPath]/lib" + DOC "libarchive library" ) mark_as_advanced(LibArchive_INCLUDE_DIR LibArchive_LIBRARY) @@ -58,4 +66,11 @@ unset(LIBARCHIVE_FOUND) if(LibArchive_FOUND) set(LibArchive_INCLUDE_DIRS ${LibArchive_INCLUDE_DIR}) set(LibArchive_LIBRARIES ${LibArchive_LIBRARY}) + + if (NOT TARGET LibArchive::LibArchive) + add_library(LibArchive::LibArchive UNKNOWN IMPORTED) + set_target_properties(LibArchive::LibArchive PROPERTIES + IMPORTED_LOCATION "${LibArchive_LIBRARY}" + INTERFACE_INCLUDE_DIRECTORIES "${LibArchive_INCLUDE_DIR}") + endif () endif() diff --git a/Modules/FindMFC.cmake b/Modules/FindMFC.cmake index e366619..b8ca71b 100644 --- a/Modules/FindMFC.cmake +++ b/Modules/FindMFC.cmake @@ -31,7 +31,7 @@ if(MFC_ATTEMPT_TRY_COMPILE) set(CHECK_INCLUDE_FILE_VAR "afxwin.h") configure_file(${CMAKE_ROOT}/Modules/CheckIncludeFile.cxx.in ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/CheckIncludeFile.cxx) - message(STATUS "Looking for MFC") + message(CHECK_START "Looking for MFC") # Try both shared and static as the root project may have set the /MT flag try_compile(MFC_HAVE_MFC ${CMAKE_BINARY_DIR} @@ -51,13 +51,13 @@ if(MFC_ATTEMPT_TRY_COMPILE) OUTPUT_VARIABLE OUTPUT) endif() if(MFC_HAVE_MFC) - message(STATUS "Looking for MFC - found") + message(CHECK_PASS "found") set(MFC_HAVE_MFC 1 CACHE INTERNAL "Have MFC?") file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log "Determining if MFC exists passed with the following output:\n" "${OUTPUT}\n\n") else() - message(STATUS "Looking for MFC - not found") + message(CHECK_FAIL "not found") set(MFC_HAVE_MFC 0 CACHE INTERNAL "Have MFC?") file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log "Determining if MFC exists failed with the following output:\n" diff --git a/Modules/FindMPI.cmake b/Modules/FindMPI.cmake index 2779032..6b1da4b 100644 --- a/Modules/FindMPI.cmake +++ b/Modules/FindMPI.cmake @@ -1391,6 +1391,7 @@ foreach(LANG IN ITEMS C CXX Fortran) endif() else() set(_MPI_FIND_${LANG} FALSE) + string(APPEND _MPI_FAIL_REASON "MPI component '${LANG}' was requested, but language ${LANG} is not enabled. ") endif() if(_MPI_FIND_${LANG}) if( ${LANG} STREQUAL CXX AND NOT MPICXX IN_LIST MPI_FIND_COMPONENTS ) @@ -1688,6 +1689,7 @@ endif() find_package_handle_standard_args(MPI REQUIRED_VARS ${_MPI_REQ_VARS} VERSION_VAR ${_MPI_MIN_VERSION} + REASON_FAILURE_MESSAGE "${_MPI_FAIL_REASON}" HANDLE_COMPONENTS) #============================================================================= diff --git a/Modules/FindOpenSSL.cmake b/Modules/FindOpenSSL.cmake index 33ceab7..3688ae9 100644 --- a/Modules/FindOpenSSL.cmake +++ b/Modules/FindOpenSSL.cmake @@ -131,6 +131,7 @@ find_path(OPENSSL_INCLUDE_DIR ${_OPENSSL_ROOT_HINTS_AND_PATHS} HINTS ${_OPENSSL_INCLUDEDIR} + ${_OPENSSL_INCLUDE_DIRS} PATH_SUFFIXES include ) @@ -319,6 +320,7 @@ else() ${_OPENSSL_ROOT_HINTS_AND_PATHS} HINTS ${_OPENSSL_LIBDIR} + ${_OPENSSL_LIBRARY_DIRS} PATH_SUFFIXES lib ) @@ -330,6 +332,7 @@ else() ${_OPENSSL_ROOT_HINTS_AND_PATHS} HINTS ${_OPENSSL_LIBDIR} + ${_OPENSSL_LIBRARY_DIRS} PATH_SUFFIXES lib ) diff --git a/Modules/FindPNG.cmake b/Modules/FindPNG.cmake index bd400c7..f1fe89a 100644 --- a/Modules/FindPNG.cmake +++ b/Modules/FindPNG.cmake @@ -94,6 +94,10 @@ if(ZLIB_FOUND) set(PNG_INCLUDE_DIRS ${PNG_PNG_INCLUDE_DIR} ${ZLIB_INCLUDE_DIR} ) set(PNG_INCLUDE_DIR ${PNG_INCLUDE_DIRS} ) # for backward compatibility set(PNG_LIBRARIES ${PNG_LIBRARY} ${ZLIB_LIBRARY}) + if((CMAKE_SYSTEM_NAME STREQUAL "Linux") AND + ("${PNG_LIBRARY}" MATCHES "\\${CMAKE_STATIC_LIBRARY_SUFFIX}$")) + list(APPEND PNG_LIBRARIES m) + endif() if (CYGWIN) if(BUILD_SHARED_LIBS) @@ -110,6 +114,12 @@ if(ZLIB_FOUND) INTERFACE_COMPILE_DEFINITIONS "${_PNG_COMPILE_DEFINITIONS}" INTERFACE_INCLUDE_DIRECTORIES "${PNG_INCLUDE_DIRS}" INTERFACE_LINK_LIBRARIES ZLIB::ZLIB) + if((CMAKE_SYSTEM_NAME STREQUAL "Linux") AND + ("${PNG_LIBRARY}" MATCHES "\\${CMAKE_STATIC_LIBRARY_SUFFIX}$")) + set_property(TARGET PNG::PNG APPEND PROPERTY + INTERFACE_LINK_LIBRARIES m) + endif() + if(EXISTS "${PNG_LIBRARY}") set_target_properties(PNG::PNG PROPERTIES IMPORTED_LINK_INTERFACE_LANGUAGES "C" diff --git a/Modules/FindPkgConfig.cmake b/Modules/FindPkgConfig.cmake index 5162a44..f4b6ea1 100644 --- a/Modules/FindPkgConfig.cmake +++ b/Modules/FindPkgConfig.cmake @@ -337,7 +337,7 @@ macro(_pkg_set_path_internal) # remove empty values from the list list(REMOVE_ITEM _pkgconfig_path "") file(TO_NATIVE_PATH "${_pkgconfig_path}" _pkgconfig_path) - if(UNIX) + if(CMAKE_HOST_UNIX) string(REPLACE ";" ":" _pkgconfig_path "${_pkgconfig_path}") string(REPLACE "\\ " " " _pkgconfig_path "${_pkgconfig_path}") endif() diff --git a/Modules/FindProtobuf.cmake b/Modules/FindProtobuf.cmake index 2d45965..f35978d 100644 --- a/Modules/FindProtobuf.cmake +++ b/Modules/FindProtobuf.cmake @@ -482,22 +482,24 @@ if(Protobuf_INCLUDE_DIR) "${_PROTOBUF_COMMON_HEADER} reveals protobuf ${Protobuf_VERSION}") endif() - # Check Protobuf compiler version to be aligned with libraries version - execute_process(COMMAND ${Protobuf_PROTOC_EXECUTABLE} --version - OUTPUT_VARIABLE _PROTOBUF_PROTOC_EXECUTABLE_VERSION) + if(Protobuf_PROTOC_EXECUTABLE) + # Check Protobuf compiler version to be aligned with libraries version + execute_process(COMMAND ${Protobuf_PROTOC_EXECUTABLE} --version + OUTPUT_VARIABLE _PROTOBUF_PROTOC_EXECUTABLE_VERSION) - if("${_PROTOBUF_PROTOC_EXECUTABLE_VERSION}" MATCHES "libprotoc ([0-9.]+)") - set(_PROTOBUF_PROTOC_EXECUTABLE_VERSION "${CMAKE_MATCH_1}") - endif() + if("${_PROTOBUF_PROTOC_EXECUTABLE_VERSION}" MATCHES "libprotoc ([0-9.]+)") + set(_PROTOBUF_PROTOC_EXECUTABLE_VERSION "${CMAKE_MATCH_1}") + endif() - if(Protobuf_DEBUG) - message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] " - "${Protobuf_PROTOC_EXECUTABLE} reveals version ${_PROTOBUF_PROTOC_EXECUTABLE_VERSION}") - endif() + if(Protobuf_DEBUG) + message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] " + "${Protobuf_PROTOC_EXECUTABLE} reveals version ${_PROTOBUF_PROTOC_EXECUTABLE_VERSION}") + endif() - if(NOT "${_PROTOBUF_PROTOC_EXECUTABLE_VERSION}" VERSION_EQUAL "${Protobuf_VERSION}") + if(NOT "${_PROTOBUF_PROTOC_EXECUTABLE_VERSION}" VERSION_EQUAL "${Protobuf_VERSION}") message(WARNING "Protobuf compiler version ${_PROTOBUF_PROTOC_EXECUTABLE_VERSION}" - " doesn't match library version ${Protobuf_VERSION}") + " doesn't match library version ${Protobuf_VERSION}") + endif() endif() if(Protobuf_LIBRARY) diff --git a/Modules/FindPython/Support.cmake b/Modules/FindPython/Support.cmake index b67d563..0d6d2fc 100644 --- a/Modules/FindPython/Support.cmake +++ b/Modules/FindPython/Support.cmake @@ -409,6 +409,7 @@ function (_PYTHON_VALIDATE_INTERPRETER) if (_PVI_CHECK_EXISTS AND NOT EXISTS "${_${_PYTHON_PREFIX}_EXECUTABLE}") # interpreter does not exist anymore + set (_${_PYTHON_PREFIX}_Interpreter_REASON_FAILURE "Cannot find the interpreter \"${_${_PYTHON_PREFIX}_EXECUTABLE}\"") set_property (CACHE _${_PYTHON_PREFIX}_EXECUTABLE PROPERTY VALUE "_${_PYTHON_PREFIX}_EXECUTABLE-NOTFOUND") return() endif() @@ -427,6 +428,7 @@ function (_PYTHON_VALIDATE_INTERPRETER) endif() if (NOT abi IN_LIST _${_PYTHON_PREFIX}_ABIFLAGS) # incompatible ABI + set (_${_PYTHON_PREFIX}_Interpreter_REASON_FAILURE "Wrong ABI for the interpreter \"${_${_PYTHON_PREFIX}_EXECUTABLE}\"") set_property (CACHE _${_PYTHON_PREFIX}_EXECUTABLE PROPERTY VALUE "_${_PYTHON_PREFIX}_EXECUTABLE-NOTFOUND") return() endif() @@ -444,6 +446,11 @@ function (_PYTHON_VALIDATE_INTERPRETER) OUTPUT_STRIP_TRAILING_WHITESPACE) if (result OR (_PVI_EXACT AND NOT version VERSION_EQUAL expected_version) OR (version VERSION_LESS expected_version)) # interpreter not usable or has wrong major version + if (result) + set (_${_PYTHON_PREFIX}_Interpreter_REASON_FAILURE "Cannot use the interpreter \"${_${_PYTHON_PREFIX}_EXECUTABLE}\"") + else() + set (_${_PYTHON_PREFIX}_Interpreter_REASON_FAILURE "Wrong major version for the interpreter \"${_${_PYTHON_PREFIX}_EXECUTABLE}\"") + endif() set_property (CACHE _${_PYTHON_PREFIX}_EXECUTABLE PROPERTY VALUE "_${_PYTHON_PREFIX}_EXECUTABLE-NOTFOUND") return() endif() @@ -459,6 +466,11 @@ function (_PYTHON_VALIDATE_INTERPRETER) OUTPUT_STRIP_TRAILING_WHITESPACE) if (result OR NOT version EQUAL _${_PYTHON_PREFIX}_REQUIRED_VERSION_MAJOR) # interpreter not usable or has wrong major version + if (result) + set (_${_PYTHON_PREFIX}_Interpreter_REASON_FAILURE "Cannot use the interpreter \"${_${_PYTHON_PREFIX}_EXECUTABLE}\"") + else() + set (_${_PYTHON_PREFIX}_Interpreter_REASON_FAILURE "Wrong major version for the interpreter \"${_${_PYTHON_PREFIX}_EXECUTABLE}\"") + endif() set_property (CACHE _${_PYTHON_PREFIX}_EXECUTABLE PROPERTY VALUE "_${_PYTHON_PREFIX}_EXECUTABLE-NOTFOUND") return() endif() @@ -476,6 +488,11 @@ function (_PYTHON_VALIDATE_INTERPRETER) OUTPUT_STRIP_TRAILING_WHITESPACE) if (result OR NOT size EQUAL CMAKE_SIZEOF_VOID_P) # interpreter not usable or has wrong architecture + if (result) + set (_${_PYTHON_PREFIX}_Interpreter_REASON_FAILURE "Cannot use the interpreter \"${_${_PYTHON_PREFIX}_EXECUTABLE}\"") + else() + set (_${_PYTHON_PREFIX}_Interpreter_REASON_FAILURE "Wrong architecture for the interpreter \"${_${_PYTHON_PREFIX}_EXECUTABLE}\"") + endif() set_property (CACHE _${_PYTHON_PREFIX}_EXECUTABLE PROPERTY VALUE "_${_PYTHON_PREFIX}_EXECUTABLE-NOTFOUND") return() endif() @@ -500,6 +517,7 @@ function (_PYTHON_VALIDATE_COMPILER expected_version) if (_PVC_CHECK_EXISTS AND NOT EXISTS "${_${_PYTHON_PREFIX}_COMPILER}") # Compiler does not exist anymore + set (_${_PYTHON_PREFIX}_Compiler_REASON_FAILURE "Cannot find the compiler \"${_${_PYTHON_PREFIX}_COMPILER}\"") set_property (CACHE _${_PYTHON_PREFIX}_COMPILER PROPERTY VALUE "_${_PYTHON_PREFIX}_COMPILER-NOTFOUND") return() endif() @@ -526,6 +544,11 @@ function (_PYTHON_VALIDATE_COMPILER expected_version) if (result OR (_PVC_EXACT AND NOT version VERSION_EQUAL expected_version) OR (version VERSION_LESS expected_version)) # Compiler not usable or has wrong version + if (result) + set (_${_PYTHON_PREFIX}_Compiler_REASON_FAILURE "Cannot use the compiler \"${_${_PYTHON_PREFIX}_COMPILER}\"") + else() + set (_${_PYTHON_PREFIX}_Compiler_REASON_FAILURE "Wrong version for the compiler \"${_${_PYTHON_PREFIX}_COMPILER}\"") + endif() set_property (CACHE _${_PYTHON_PREFIX}_COMPILER PROPERTY VALUE "_${_PYTHON_PREFIX}_COMPILER-NOTFOUND") endif() endfunction() @@ -545,6 +568,7 @@ function (_PYTHON_VALIDATE_LIBRARY) if (_PVL_CHECK_EXISTS AND NOT EXISTS "${_${_PYTHON_PREFIX}_LIBRARY_RELEASE}") # library does not exist anymore + set (_${_PYTHON_PREFIX}_Development_REASON_FAILURE "Cannot find the library \"${_${_PYTHON_PREFIX}_LIBRARY_RELEASE}\"") set_property (CACHE _${_PYTHON_PREFIX}_LIBRARY_RELEASE PROPERTY VALUE "_${_PYTHON_PREFIX}_LIBRARY_RELEASE-NOTFOUND") if (WIN32) set_property (CACHE _${_PYTHON_PREFIX}_LIBRARY_DEBUG PROPERTY VALUE "_${_PYTHON_PREFIX}_LIBRARY_DEBUG-NOTFOUND") @@ -558,16 +582,19 @@ function (_PYTHON_VALIDATE_LIBRARY) if (DEFINED _${_PYTHON_PREFIX}_FIND_ABI AND NOT lib_ABI IN_LIST _${_PYTHON_PREFIX}_ABIFLAGS) # incompatible ABI + set (_${_PYTHON_PREFIX}_Development_REASON_FAILURE "Wrong ABI for the library \"${_${_PYTHON_PREFIX}_LIBRARY_RELEASE}\"") set_property (CACHE _${_PYTHON_PREFIX}_LIBRARY_RELEASE PROPERTY VALUE "_${_PYTHON_PREFIX}_LIBRARY_RELEASE-NOTFOUND") else() if (expected_version) if ((_PVL_EXACT AND NOT lib_VERSION VERSION_EQUAL expected_version) OR (lib_VERSION VERSION_LESS expected_version)) # library has wrong version + set (_${_PYTHON_PREFIX}_Development_REASON_FAILURE "Wrong version for the library \"${_${_PYTHON_PREFIX}_LIBRARY_RELEASE}\"") set_property (CACHE _${_PYTHON_PREFIX}_LIBRARY_RELEASE PROPERTY VALUE "_${_PYTHON_PREFIX}_LIBRARY_RELEASE-NOTFOUND") endif() else() if (NOT lib_VERSION_MAJOR VERSION_EQUAL _${_PYTHON_PREFIX}_REQUIRED_VERSION_MAJOR) # library has wrong major version + set (_${_PYTHON_PREFIX}_Development_REASON_FAILURE "Wrong major version for the library \"${_${_PYTHON_PREFIX}_LIBRARY_RELEASE}\"") set_property (CACHE _${_PYTHON_PREFIX}_LIBRARY_RELEASE PROPERTY VALUE "_${_PYTHON_PREFIX}_LIBRARY_RELEASE-NOTFOUND") endif() endif() @@ -596,6 +623,7 @@ function (_PYTHON_VALIDATE_INCLUDE_DIR) if (_PVID_CHECK_EXISTS AND NOT EXISTS "${_${_PYTHON_PREFIX}_INCLUDE_DIR}") # include file does not exist anymore + set (_${_PYTHON_PREFIX}_Development_REASON_FAILURE "Cannot find the directory \"${_${_PYTHON_PREFIX}_INCLUDE_DIR}\"") set_property (CACHE _${_PYTHON_PREFIX}_INCLUDE_DIR PROPERTY VALUE "_${_PYTHON_PREFIX}_INCLUDE_DIR-NOTFOUND") return() endif() @@ -605,16 +633,19 @@ function (_PYTHON_VALIDATE_INCLUDE_DIR) if (DEFINED _${_PYTHON_PREFIX}_FIND_ABI AND NOT inc_ABI IN_LIST _${_PYTHON_PREFIX}_ABIFLAGS) # incompatible ABI + set (_${_PYTHON_PREFIX}_Development_REASON_FAILURE "Wrong ABI for the directory \"${_${_PYTHON_PREFIX}_INCLUDE_DIR}\"") set_property (CACHE _${_PYTHON_PREFIX}_INCLUDE_DIR PROPERTY VALUE "_${_PYTHON_PREFIX}_INCLUDE_DIR-NOTFOUND") else() if (expected_version) if ((_PVID_EXACT AND NOT inc_VERSION VERSION_EQUAL expected_version) OR (inc_VERSION VERSION_LESS expected_version)) # include dir has wrong version + set (_${_PYTHON_PREFIX}_Development_REASON_FAILURE "Wrong version for the directory \"${_${_PYTHON_PREFIX}_INCLUDE_DIR}\"") set_property (CACHE _${_PYTHON_PREFIX}_INCLUDE_DIR PROPERTY VALUE "_${_PYTHON_PREFIX}_INCLUDE_DIR-NOTFOUND") endif() else() if (NOT inc_VERSION_MAJOR VERSION_EQUAL _${_PYTHON_PREFIX}_REQUIRED_VERSION_MAJOR) # include dir has wrong major version + set (_${_PYTHON_PREFIX}_Development_REASON_FAILURE "Wrong major version for the directory \"${_${_PYTHON_PREFIX}_INCLUDE_DIR}\"") set_property (CACHE _${_PYTHON_PREFIX}_INCLUDE_DIR PROPERTY VALUE "_${_PYTHON_PREFIX}_INCLUDE_DIR-NOTFOUND") endif() endif() @@ -836,6 +867,10 @@ endif() unset (_${_PYTHON_PREFIX}_REQUIRED_VARS) unset (_${_PYTHON_PREFIX}_CACHED_VARS) +unset (_${_PYTHON_PREFIX}_Interpreter_REASON_FAILURE) +unset (_${_PYTHON_PREFIX}_Compiler_REASON_FAILURE) +unset (_${_PYTHON_PREFIX}_Development_REASON_FAILURE) +unset (_${_PYTHON_PREFIX}_NumPy_REASON_FAILURE) # first step, search for the interpreter @@ -1161,6 +1196,7 @@ if ("Interpreter" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS) # Interpreter is not usable set (_${_PYTHON_PREFIX}_EXECUTABLE_USABLE FALSE) unset (${_PYTHON_PREFIX}_VERSION) + set (_${_PYTHON_PREFIX}_Interpreter_REASON_FAILURE "Cannot run the interpreter \"${_${_PYTHON_PREFIX}_EXECUTABLE}\"") endif() endif() @@ -1416,6 +1452,7 @@ if ("Compiler" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS) else() # compiler not usable set (_${_PYTHON_PREFIX}_COMPILER_USABLE FALSE) + set (_${_PYTHON_PREFIX}_Compiler_REASON_FAILURE "Cannot run the compiler \"${_${_PYTHON_PREFIX}_COMPILER}\"") endif() file (REMOVE_RECURSE "${_${_PYTHON_PREFIX}_VERSION_DIR}") endif() @@ -1914,6 +1951,7 @@ if ("Development" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS set (${_PYTHON_PREFIX}_LIBRARY_RELEASE "${_${_PYTHON_PREFIX}_LIBRARY_RELEASE}" CACHE FILEPATH "Path to a library." FORCE) if (_${_PYTHON_PREFIX}_LIBRARY_RELEASE AND NOT EXISTS "${_${_PYTHON_PREFIX}_LIBRARY_RELEASE}") + set (_${_PYTHON_PREFIX}_Development_REASON_FAILURE "Cannot find the library \"${_${_PYTHON_PREFIX}_LIBRARY_RELEASE}\"") set_property (CACHE _${_PYTHON_PREFIX}_LIBRARY_RELEASE PROPERTY VALUE "_${_PYTHON_PREFIX}_LIBRARY_RELEASE-NOTFOUND") endif() @@ -2046,6 +2084,7 @@ if ("Development" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS set (${_PYTHON_PREFIX}_INCLUDE_DIRS "${_${_PYTHON_PREFIX}_INCLUDE_DIR}") if (_${_PYTHON_PREFIX}_INCLUDE_DIR AND NOT EXISTS "${_${_PYTHON_PREFIX}_INCLUDE_DIR}") + set (_${_PYTHON_PREFIX}_Development_REASON_FAILURE "Cannot find the directory \"${_${_PYTHON_PREFIX}_INCLUDE_DIR}\"") set_property (CACHE _${_PYTHON_PREFIX}_INCLUDE_DIR PROPERTY VALUE "_${_PYTHON_PREFIX}_INCLUDE_DIR-NOTFOUND") endif() @@ -2169,6 +2208,7 @@ if ("NumPy" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS AND ${_PYTHON_PREFIX}_Inte set (${_PYTHON_PREFIX}_NumPy_INCLUDE_DIRS "${_${_PYTHON_PREFIX}_NumPy_INCLUDE_DIR}") if(_${_PYTHON_PREFIX}_NumPy_INCLUDE_DIR AND NOT EXISTS "${_${_PYTHON_PREFIX}_NumPy_INCLUDE_DIR}") + set (_${_PYTHON_PREFIX}_NumPy_REASON_FAILURE "Cannot find the directory \"${_${_PYTHON_PREFIX}_NumPy_INCLUDE_DIR}\"") set_property (CACHE _${_PYTHON_PREFIX}_NumPy_INCLUDE_DIR PROPERTY VALUE "_${_PYTHON_PREFIX}_NumPy_INCLUDE_DIR-NOTFOUND") endif() @@ -2207,11 +2247,19 @@ if (${_PYTHON_PREFIX}_VERSION_MAJOR AND _python_display_failure ("Could NOT find ${_PYTHON_PREFIX}: Found unsuitable major version \"${${_PYTHON_PREFIX}_VERSION_MAJOR}\", but required major version is exact version \"${_${_PYTHON_PREFIX}_REQUIRED_VERSION_MAJOR}\"") endif() +unset (_${_PYTHON_PREFIX}_REASON_FAILURE) +foreach (_${_PYTHON_PREFIX}_COMPONENT IN ITEMS Interpreter Compiler Development NumPy) + if (_${_PYTHON_PREFIX}_${_${_PYTHON_PREFIX}_COMPONENT}_REASON_FAILURE) + string (APPEND _${_PYTHON_PREFIX}_REASON_FAILURE "\n ${_${_PYTHON_PREFIX}_COMPONENT}: ${_${_PYTHON_PREFIX}_${_${_PYTHON_PREFIX}_COMPONENT}_REASON_FAILURE}") + endif() +endforeach() + include (${CMAKE_CURRENT_LIST_DIR}/../FindPackageHandleStandardArgs.cmake) find_package_handle_standard_args (${_PYTHON_PREFIX} REQUIRED_VARS ${_${_PYTHON_PREFIX}_REQUIRED_VARS} VERSION_VAR ${_PYTHON_PREFIX}_VERSION - HANDLE_COMPONENTS) + HANDLE_COMPONENTS + REASON_FAILURE_MESSAGE "${_${_PYTHON_PREFIX}_REASON_FAILURE}") # Create imported targets and helper functions if(_${_PYTHON_PREFIX}_CMAKE_ROLE STREQUAL "PROJECT") diff --git a/Modules/FindThreads.cmake b/Modules/FindThreads.cmake index b0c91b2..85174d9 100644 --- a/Modules/FindThreads.cmake +++ b/Modules/FindThreads.cmake @@ -63,6 +63,7 @@ int main(void) pthread_t thread; pthread_create(&thread, NULL, test_func, NULL); pthread_detach(thread); + pthread_cancel(thread); pthread_join(thread, NULL); pthread_atfork(NULL, NULL, NULL); pthread_exit(NULL); @@ -90,7 +91,7 @@ macro(_check_pthreads_flag) if(NOT Threads_FOUND) # If we did not found -lpthread, -lpthread, or -lthread, look for -pthread if(NOT DEFINED THREADS_HAVE_PTHREAD_ARG) - message(STATUS "Check if compiler accepts -pthread") + message(CHECK_START "Check if compiler accepts -pthread") if(CMAKE_C_COMPILER_LOADED) set(_threads_src ${CMAKE_CURRENT_LIST_DIR}/CheckForPthreads.c) elseif(CMAKE_CXX_COMPILER_LOADED) @@ -106,9 +107,9 @@ macro(_check_pthreads_flag) if(THREADS_HAVE_PTHREAD_ARG) set(Threads_FOUND TRUE) - message(STATUS "Check if compiler accepts -pthread - yes") + message(CHECK_PASS "yes") else() - message(STATUS "Check if compiler accepts -pthread - no") + message(CHECK_FAIL "no") file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log "Determining if compiler accepts -pthread failed with the following output:\n${OUTPUT}\n\n") diff --git a/Modules/FortranCInterface.cmake b/Modules/FortranCInterface.cmake index 893a96f..547346b 100644 --- a/Modules/FortranCInterface.cmake +++ b/Modules/FortranCInterface.cmake @@ -341,7 +341,7 @@ function(FortranCInterface_VERIFY) # Build the verification project if not yet built. if(NOT DEFINED FortranCInterface_VERIFIED_${lang}) set(_desc "Verifying Fortran/${lang} Compiler Compatibility") - message(STATUS "${_desc}") + message(CHECK_START "${_desc}") # Build a sample project which reports symbols. set(CMAKE_TRY_COMPILE_CONFIGURATION Release) @@ -363,12 +363,12 @@ function(FortranCInterface_VERIFY) # Report results. if(FortranCInterface_VERIFY_${lang}_COMPILED) - message(STATUS "${_desc} - Success") + message(CHECK_PASS "Success") file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log "${_desc} passed with the following output:\n${_output}\n\n") set(FortranCInterface_VERIFIED_${lang} 1 CACHE INTERNAL "Fortran/${lang} compatibility") else() - message(STATUS "${_desc} - Failed") + message(CHECK_FAIL "Failed") file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log "${_desc} failed with the following output:\n${_output}\n\n") set(FortranCInterface_VERIFIED_${lang} 0 CACHE INTERNAL "Fortran/${lang} compatibility") diff --git a/Modules/FortranCInterface/Detect.cmake b/Modules/FortranCInterface/Detect.cmake index 7789785..33de6c6 100644 --- a/Modules/FortranCInterface/Detect.cmake +++ b/Modules/FortranCInterface/Detect.cmake @@ -15,7 +15,7 @@ if(${FortranCInterface_BINARY_DIR}/Input.cmake OR ${CMAKE_CURRENT_LIST_FILE} IS_NEWER_THAN ${FortranCInterface_BINARY_DIR}/Output.cmake ) - message(STATUS "Detecting Fortran/C Interface") + message(CHECK_START "Detecting Fortran/C Interface") else() return() endif() @@ -172,7 +172,9 @@ if(FortranCInterface_GLOBAL_FOUND) else() set(_result "Found GLOBAL but not MODULE mangling") endif() + set(_result_type CHECK_PASS) elseif(NOT _result) set(_result "Failed to recognize symbols") + set(_result_type CHECK_FAIL) endif() -message(STATUS "Detecting Fortran/C Interface - ${_result}") +message(${_result_type} "${_result}") diff --git a/Modules/Internal/CPack/CPackDeb.cmake b/Modules/Internal/CPack/CPackDeb.cmake index ad8e078..fe0fe09 100644 --- a/Modules/Internal/CPack/CPackDeb.cmake +++ b/Modules/Internal/CPack/CPackDeb.cmake @@ -546,8 +546,8 @@ function(cpack_deb_prepare_package_vars) ) # Homepage: (optional) - if(NOT CPACK_DEBIAN_PACKAGE_HOMEPAGE AND CMAKE_PROJECT_HOMEPAGE_URL) - set(CPACK_DEBIAN_PACKAGE_HOMEPAGE "${CMAKE_PROJECT_HOMEPAGE_URL}") + if(NOT CPACK_DEBIAN_PACKAGE_HOMEPAGE AND CPACK_PACKAGE_HOMEPAGE_URL) + set(CPACK_DEBIAN_PACKAGE_HOMEPAGE "${CPACK_PACKAGE_HOMEPAGE_URL}") endif() # Section: (recommended) diff --git a/Modules/Internal/CPack/CPackFreeBSD.cmake b/Modules/Internal/CPack/CPackFreeBSD.cmake index 16f906c..ae40532 100644 --- a/Modules/Internal/CPack/CPackFreeBSD.cmake +++ b/Modules/Internal/CPack/CPackFreeBSD.cmake @@ -68,7 +68,7 @@ _cpack_freebsd_fallback_var("CPACK_FREEBSD_PACKAGE_DESCRIPTION" # There's really only one homepage for a project, so # re-use the Debian setting if it's there. _cpack_freebsd_fallback_var("CPACK_FREEBSD_PACKAGE_WWW" - "CMAKE_PROJECT_HOMEPAGE_URL" + "CPACK_PACKAGE_HOMEPAGE_URL" "CPACK_DEBIAN_PACKAGE_HOMEPAGE" "_cpack_freebsd_fallback_www" ) diff --git a/Modules/Internal/CPack/CPackNuGet.cmake b/Modules/Internal/CPack/CPackNuGet.cmake index 82053b2..1f4bcfd 100644 --- a/Modules/Internal/CPack/CPackNuGet.cmake +++ b/Modules/Internal/CPack/CPackNuGet.cmake @@ -230,31 +230,22 @@ function(_cpack_nuget_render_spec) foreach(_dep IN LISTS _deps) _cpack_nuget_debug(" checking dependency `${_dep}`") - string(MAKE_C_IDENTIFIER "${_dep}" _dep_id) - - _cpack_nuget_variable_fallback(_ver DEPENDENCIES_${_dep_id}_VERSION) + _cpack_nuget_variable_fallback(_ver DEPENDENCIES_${_dep}_VERSION) if(NOT _ver) - string(TOUPPER "${_dep_id}" _dep_id) - _cpack_nuget_variable_fallback(_ver DEPENDENCIES_${_dep_id}_VERSION) + string(TOUPPER "${_dep}" _dep_upper) + _cpack_nuget_variable_fallback(_ver DEPENDENCIES_${_dep_upper}_VERSION) endif() if(_ver) _cpack_nuget_debug(" got `${_dep}` dependency version ${_ver}") - list(APPEND _collected_deps "<dependency id=\"${_dep}\" version=\"${_ver}\" />") + string(CONCAT _collected_deps "${_collected_deps}" " <dependency id=\"${_dep}\" version=\"${_ver}\" />\n") endif() endforeach() # Render deps into the variable if(_collected_deps) - set(_CPACK_NUGET_DEPENDENCIES_TAG "<dependencies>\n") - foreach(_line IN LISTS _collected_deps) - string( - APPEND _CPACK_NUGET_DEPENDENCIES_TAG - " ${_line}\n" - ) - endforeach() - string(APPEND _CPACK_NUGET_DEPENDENCIES_TAG " </dependencies>") + string(CONCAT _CPACK_NUGET_DEPENDENCIES_TAG "<dependencies>\n" "${_collected_deps}" " </dependencies>") endif() # Render the spec file diff --git a/Modules/Internal/CPack/CPackRPM.cmake b/Modules/Internal/CPack/CPackRPM.cmake index ffb24e2..3485e7d 100644 --- a/Modules/Internal/CPack/CPackRPM.cmake +++ b/Modules/Internal/CPack/CPackRPM.cmake @@ -844,8 +844,8 @@ function(cpack_rpm_generate_package) endif() endif() - if(NOT CPACK_RPM_PACKAGE_URL AND CMAKE_PROJECT_HOMEPAGE_URL) - set(CPACK_RPM_PACKAGE_URL "${CMAKE_PROJECT_HOMEPAGE_URL}") + if(NOT CPACK_RPM_PACKAGE_URL AND CPACK_PACKAGE_HOMEPAGE_URL) + set(CPACK_RPM_PACKAGE_URL "${CPACK_PACKAGE_HOMEPAGE_URL}") endif() # CPACK_RPM_PACKAGE_NAME (mandatory) diff --git a/Modules/Internal/CPack/NSIS.template.in b/Modules/Internal/CPack/NSIS.template.in index f75ae78..23bb0018 100644 --- a/Modules/Internal/CPack/NSIS.template.in +++ b/Modules/Internal/CPack/NSIS.template.in @@ -542,6 +542,8 @@ FunctionEnd ;-------------------------------- ;Pages + @CPACK_NSIS_INSTALLER_WELCOME_TITLE_CODE@ + @CPACK_NSIS_INSTALLER_WELCOME_TITLE_3LINES_CODE@ !insertmacro MUI_PAGE_WELCOME !insertmacro MUI_PAGE_LICENSE "@CPACK_RESOURCE_FILE_LICENSE@" @@ -557,6 +559,8 @@ FunctionEnd @CPACK_NSIS_PAGE_COMPONENTS@ !insertmacro MUI_PAGE_INSTFILES + @CPACK_NSIS_INSTALLER_FINISH_TITLE_CODE@ + @CPACK_NSIS_INSTALLER_FINISH_TITLE_3LINES_CODE@ !insertmacro MUI_PAGE_FINISH !insertmacro MUI_UNPAGE_CONFIRM @@ -642,7 +646,7 @@ Section "-Core installation" WriteRegStr SHCTX "Software\@CPACK_PACKAGE_VENDOR@\@CPACK_PACKAGE_INSTALL_REGISTRY_KEY@" "" $INSTDIR ;Create uninstaller - WriteUninstaller "$INSTDIR\Uninstall.exe" + WriteUninstaller "$INSTDIR\@CPACK_NSIS_UNINSTALL_NAME@.exe" Push "DisplayName" Push "@CPACK_NSIS_DISPLAY_NAME@" Call ConditionalAddToRegisty @@ -653,7 +657,7 @@ Section "-Core installation" Push "@CPACK_PACKAGE_VENDOR@" Call ConditionalAddToRegisty Push "UninstallString" - Push "$INSTDIR\Uninstall.exe" + Push "$INSTDIR\@CPACK_NSIS_UNINSTALL_NAME@.exe" Call ConditionalAddToRegisty Push "NoRepair" Push "1" @@ -690,7 +694,7 @@ Section "-Core installation" CreateDirectory "$SMPROGRAMS\$STARTMENU_FOLDER" @CPACK_NSIS_CREATE_ICONS@ @CPACK_NSIS_CREATE_ICONS_EXTRA@ - CreateShortCut "$SMPROGRAMS\$STARTMENU_FOLDER\Uninstall.lnk" "$INSTDIR\Uninstall.exe" + CreateShortCut "$SMPROGRAMS\$STARTMENU_FOLDER\Uninstall.lnk" "$INSTDIR\@CPACK_NSIS_UNINSTALL_NAME@.exe" ;Read a value from an InstallOptions INI file !insertmacro MUI_INSTALLOPTIONS_READ $DO_NOT_ADD_TO_PATH "NSIS.InstallOptions.ini" "Field 2" "State" @@ -829,7 +833,7 @@ Section "Uninstall" !endif ;Remove the uninstaller itself. - Delete "$INSTDIR\Uninstall.exe" + Delete "$INSTDIR\@CPACK_NSIS_UNINSTALL_NAME@.exe" DeleteRegKey SHCTX "Software\Microsoft\Windows\CurrentVersion\Uninstall\@CPACK_PACKAGE_INSTALL_REGISTRY_KEY@" ;Remove the installation directory if it is empty. diff --git a/Modules/Internal/FeatureTesting.cmake b/Modules/Internal/FeatureTesting.cmake index 75be473..72d96b3 100644 --- a/Modules/Internal/FeatureTesting.cmake +++ b/Modules/Internal/FeatureTesting.cmake @@ -89,6 +89,16 @@ macro(_record_compiler_features_cxx std) unset(lang_level_has_features) endmacro() +macro(_record_compiler_features_cuda std) + list(APPEND CMAKE_CUDA${std}_COMPILE_FEATURES cuda_std_${std}) + + get_property(lang_level_has_features GLOBAL PROPERTY CMAKE_CUDA${std}_KNOWN_FEATURES) + if(lang_level_has_features) + _record_compiler_features(CUDA "${CMAKE_CUDA${std}_STANDARD_COMPILE_OPTION}" CMAKE_CUDA${std}_COMPILE_FEATURES) + endif() + unset(lang_level_has_features) +endmacro() + macro(_has_compiler_features lang level compile_flags feature_list) # presume all known features are supported get_property(known_features GLOBAL PROPERTY CMAKE_${lang}${level}_KNOWN_FEATURES) @@ -103,3 +113,7 @@ macro(_has_compiler_features_cxx std) list(APPEND CMAKE_CXX${std}_COMPILE_FEATURES cxx_std_${std}) _has_compiler_features(CXX ${std} "${CMAKE_CXX${std}_STANDARD_COMPILE_OPTION}" CMAKE_CXX${std}_COMPILE_FEATURES) endmacro() +macro(_has_compiler_features_cuda std) + list(APPEND CMAKE_CUDA${std}_COMPILE_FEATURES cuda_std_${std}) + _has_compiler_features(CUDA ${std} "${CMAKE_CUDA${std}_STANDARD_COMPILE_OPTION}" CMAKE_CUDA${std}_COMPILE_FEATURES) +endmacro() diff --git a/Modules/Platform/Android-Clang.cmake b/Modules/Platform/Android-Clang.cmake index 847178f..759448b 100644 --- a/Modules/Platform/Android-Clang.cmake +++ b/Modules/Platform/Android-Clang.cmake @@ -24,6 +24,14 @@ if(CMAKE_SYSTEM_VERSION EQUAL 1) return() endif() +# Natively compiling on an Android host doesn't use the NDK cross-compilation +# tools. +if(CMAKE_HOST_SYSTEM_NAME STREQUAL "Android") + macro(__android_compiler_clang lang) + endmacro() + return() +endif() + include(Platform/Android-Common) # The NDK toolchain configuration files at: diff --git a/Modules/Platform/Android-Determine.cmake b/Modules/Platform/Android-Determine.cmake index e7c1b48..2225897 100644 --- a/Modules/Platform/Android-Determine.cmake +++ b/Modules/Platform/Android-Determine.cmake @@ -18,6 +18,12 @@ if(CMAKE_SYSTEM_VERSION EQUAL 1) return() endif() +# Natively compiling on an Android host doesn't use the NDK cross-compilation +# tools. +if(CMAKE_HOST_SYSTEM_NAME STREQUAL "Android") + return() +endif() + cmake_policy(PUSH) cmake_policy(SET CMP0057 NEW) # if IN_LIST diff --git a/Modules/Platform/Android-Initialize.cmake b/Modules/Platform/Android-Initialize.cmake index a5d2820..b90dd7a 100644 --- a/Modules/Platform/Android-Initialize.cmake +++ b/Modules/Platform/Android-Initialize.cmake @@ -24,6 +24,12 @@ if(CMAKE_ANDROID_NDK_TOOLCHAIN_UNIFIED) return() endif() +# Natively compiling on an Android host doesn't use the NDK cross-compilation +# tools. +if(CMAKE_HOST_SYSTEM_NAME STREQUAL "Android") + return() +endif() + if(NOT CMAKE_SYSROOT) if(CMAKE_ANDROID_NDK) set(CMAKE_SYSROOT "${CMAKE_ANDROID_NDK}/platforms/android-${CMAKE_SYSTEM_VERSION}/arch-${CMAKE_ANDROID_ARCH}") diff --git a/Modules/Platform/Android.cmake b/Modules/Platform/Android.cmake index f08f841..8ffa1b2 100644 --- a/Modules/Platform/Android.cmake +++ b/Modules/Platform/Android.cmake @@ -2,6 +2,11 @@ include(Platform/Linux) set(ANDROID 1) +# Natively compiling on an Android host doesn't need these flags to be reset. +if(CMAKE_HOST_SYSTEM_NAME STREQUAL "Android") + return() +endif() + # Conventionally Android does not use versioned soname # But in modern versions it is acceptable if(NOT DEFINED CMAKE_PLATFORM_NO_VERSIONED_SONAME) diff --git a/Modules/Platform/Android/Determine-Compiler.cmake b/Modules/Platform/Android/Determine-Compiler.cmake index 5c6b97b..f9c2d89 100644 --- a/Modules/Platform/Android/Determine-Compiler.cmake +++ b/Modules/Platform/Android/Determine-Compiler.cmake @@ -31,6 +31,16 @@ elseif(CMAKE_HOST_SYSTEM_NAME STREQUAL "Linux") set(_ANDROID_HOST_EXT "") elseif(CMAKE_HOST_SYSTEM_NAME STREQUAL "Windows") set(_ANDROID_HOST_EXT ".exe") +elseif(CMAKE_HOST_SYSTEM_NAME STREQUAL "Android") + # Natively compiling on an Android host doesn't use the NDK cross-compilation + # tools. + macro(__android_determine_compiler lang) + # Do nothing + endmacro() + if(NOT CMAKE_CXX_COMPILER_NAMES) + set(CMAKE_CXX_COMPILER_NAMES c++) + endif() + return() else() message(FATAL_ERROR "Android: Builds hosted on '${CMAKE_HOST_SYSTEM_NAME}' not supported.") endif() diff --git a/Modules/Platform/Apple-GNU.cmake b/Modules/Platform/Apple-GNU.cmake index 0eb8168..9572736 100644 --- a/Modules/Platform/Apple-GNU.cmake +++ b/Modules/Platform/Apple-GNU.cmake @@ -19,17 +19,17 @@ endmacro() macro(cmake_gnu_set_sysroot_flag lang) if(NOT DEFINED CMAKE_${lang}_SYSROOT_FLAG) set(_doc "${lang} compiler has -isysroot") - message(STATUS "Checking whether ${_doc}") + message(CHECK_START "Checking whether ${_doc}") execute_process( COMMAND ${CMAKE_${lang}_COMPILER} "-v" "--help" OUTPUT_VARIABLE _gcc_help ERROR_VARIABLE _gcc_help ) if("${_gcc_help}" MATCHES "isysroot") - message(STATUS "Checking whether ${_doc} - yes") + message(CHECK_PASS "yes") set(CMAKE_${lang}_SYSROOT_FLAG "-isysroot") else() - message(STATUS "Checking whether ${_doc} - no") + message(CHECK_FAIL "no") set(CMAKE_${lang}_SYSROOT_FLAG "") endif() set(CMAKE_${lang}_SYSROOT_FLAG_CODE "set(CMAKE_${lang}_SYSROOT_FLAG \"${CMAKE_${lang}_SYSROOT_FLAG}\")") @@ -39,17 +39,17 @@ endmacro() macro(cmake_gnu_set_osx_deployment_target_flag lang) if(NOT DEFINED CMAKE_${lang}_OSX_DEPLOYMENT_TARGET_FLAG) set(_doc "${lang} compiler supports OSX deployment target flag") - message(STATUS "Checking whether ${_doc}") + message(CHECK_START "Checking whether ${_doc}") execute_process( COMMAND ${CMAKE_${lang}_COMPILER} "-v" "--help" OUTPUT_VARIABLE _gcc_help ERROR_VARIABLE _gcc_help ) if("${_gcc_help}" MATCHES "macosx-version-min") - message(STATUS "Checking whether ${_doc} - yes") + message(CHECK_PASS "yes") set(CMAKE_${lang}_OSX_DEPLOYMENT_TARGET_FLAG "-mmacosx-version-min=") else() - message(STATUS "Checking whether ${_doc} - no") + message(CHECK_FAIL "no") set(CMAKE_${lang}_OSX_DEPLOYMENT_TARGET_FLAG "") endif() set(CMAKE_${lang}_OSX_DEPLOYMENT_TARGET_FLAG_CODE "set(CMAKE_${lang}_OSX_DEPLOYMENT_TARGET_FLAG \"${CMAKE_${lang}_OSX_DEPLOYMENT_TARGET_FLAG}\")") diff --git a/Modules/Platform/Darwin-Initialize.cmake b/Modules/Platform/Darwin-Initialize.cmake index 2d797f6..729217c 100644 --- a/Modules/Platform/Darwin-Initialize.cmake +++ b/Modules/Platform/Darwin-Initialize.cmake @@ -122,7 +122,97 @@ endforeach() set(CMAKE_OSX_SYSROOT "${_CMAKE_OSX_SYSROOT_DEFAULT}" CACHE ${_CMAKE_OSX_SYSROOT_TYPE} "The product will be built against the headers and libraries located inside the indicated SDK.") -# Transform the cached value to something we can use. +# Resolves the SDK name into a path +function(_apple_resolve_sdk_path sdk_name ret) + execute_process( + COMMAND xcrun -sdk ${sdk_name} --show-sdk-path + OUTPUT_VARIABLE _stdout + OUTPUT_STRIP_TRAILING_WHITESPACE + ERROR_VARIABLE _stderr + RESULT_VARIABLE _failed + ) + set(${ret} "${_stdout}" PARENT_SCOPE) +endfunction() +# Handle multi-arch sysroots. Do this before CMAKE_OSX_SYSROOT is +# transformed into a path, so that we know the sysroot name. +function(_apple_resolve_multi_arch_sysroots) + if(CMAKE_APPLE_ARCH_SYSROOTS) + return() # Already cached + endif() + + list(LENGTH CMAKE_OSX_ARCHITECTURES _num_archs) + if(NOT (_num_archs GREATER 1)) + return() # Only apply to multi-arch + endif() + + if(CMAKE_OSX_SYSROOT STREQUAL "macosx") + # macOS doesn't have a simulator sdk / sysroot, so there is no need to handle per-sdk arches. + return() + endif() + + if(IS_DIRECTORY "${CMAKE_OSX_SYSROOT}") + if(NOT CMAKE_OSX_SYSROOT STREQUAL _CMAKE_OSX_SYSROOT_DEFAULT) + message(WARNING "Can not resolve multi-arch sysroots with CMAKE_OSX_SYSROOT set to path (${CMAKE_OSX_SYSROOT})") + endif() + return() + endif() + + string(REPLACE "os" "simulator" _simulator_sdk ${CMAKE_OSX_SYSROOT}) + set(_sdks "${CMAKE_OSX_SYSROOT};${_simulator_sdk}") + foreach(sdk ${_sdks}) + _apple_resolve_sdk_path(${sdk} _sdk_path) + if(NOT IS_DIRECTORY "${_sdk_path}") + message(WARNING "Failed to resolve SDK path for '${sdk}'") + continue() + endif() + + execute_process( + COMMAND plutil -extract SupportedTargets.${sdk}.Archs json ${_sdk_path}/SDKSettings.plist -o - + OUTPUT_VARIABLE _sdk_archs_json + OUTPUT_STRIP_TRAILING_WHITESPACE + ERROR_VARIABLE _stderr + RESULT_VARIABLE _failed + ) + if(_failed) + # Failure to extract supported architectures for an SDK means that the installed SDK is old + # and does not provide such information (SDKs that come with Xcode >= 10.x started providing + # the information). In such a case, return early, and handle multi-arch builds the old way + # (no per-sdk arches). + return() + endif() + + # Poor man's JSON decoding + string(REGEX REPLACE "[]\\[\"]" "" _sdk_archs ${_sdk_archs_json}) + string(REPLACE "," ";" _sdk_archs ${_sdk_archs}) + + set(_sdk_archs_${sdk} ${_sdk_archs}) + set(_sdk_path_${sdk} ${_sdk_path}) + endforeach() + + foreach(arch ${CMAKE_OSX_ARCHITECTURES}) + set(_arch_sysroot "") + foreach(sdk ${_sdks}) + list(FIND _sdk_archs_${sdk} ${arch} arch_index) + if(NOT arch_index EQUAL -1) + set(_arch_sysroot ${_sdk_path_${sdk}}) + break() + endif() + endforeach() + if(_arch_sysroot) + list(APPEND _arch_sysroots ${_arch_sysroot}) + else() + message(WARNING "No SDK found for architecture '${arch}'") + list(APPEND _arch_sysroots "") # Placeholder + endif() + endforeach() + + set(CMAKE_APPLE_ARCH_SYSROOTS "${_arch_sysroots}" CACHE INTERNAL + "Architecture dependent sysroots, one per CMAKE_OSX_ARCHITECTURES") +endfunction() + +_apple_resolve_multi_arch_sysroots() + +# Transform CMAKE_OSX_SYSROOT to absolute path set(_CMAKE_OSX_SYSROOT_PATH "") if(CMAKE_OSX_SYSROOT) if("x${CMAKE_OSX_SYSROOT}" MATCHES "/") @@ -134,16 +224,9 @@ if(CMAKE_OSX_SYSROOT) endif() set(_CMAKE_OSX_SYSROOT_PATH "${CMAKE_OSX_SYSROOT}") else() - # Transform the sdk name into a path. - execute_process( - COMMAND xcodebuild -sdk ${CMAKE_OSX_SYSROOT} -version Path - OUTPUT_VARIABLE _stdout - OUTPUT_STRIP_TRAILING_WHITESPACE - ERROR_VARIABLE _stderr - RESULT_VARIABLE _failed - ) - if(NOT _failed AND IS_DIRECTORY "${_stdout}") - set(_CMAKE_OSX_SYSROOT_PATH "${_stdout}") + _apple_resolve_sdk_path(${CMAKE_OSX_SYSROOT} _sdk_path) + if(IS_DIRECTORY "${_sdk_path}") + set(_CMAKE_OSX_SYSROOT_PATH "${_sdk_path}") # For non-Xcode generators use the path. if(NOT "${CMAKE_GENERATOR}" MATCHES "Xcode") set(CMAKE_OSX_SYSROOT "${_CMAKE_OSX_SYSROOT_PATH}") diff --git a/Modules/Platform/Generic-SDCC-C.cmake b/Modules/Platform/Generic-SDCC-C.cmake index aef4abf..c51767e 100644 --- a/Modules/Platform/Generic-SDCC-C.cmake +++ b/Modules/Platform/Generic-SDCC-C.cmake @@ -19,14 +19,28 @@ set(CMAKE_DL_LIBS "") set(CMAKE_C_OUTPUT_EXTENSION ".rel") -# find sdcclib as CMAKE_AR -# since cmake may already have searched for "ar", sdcclib has to -# be searched with a different variable name (SDCCLIB_EXECUTABLE) -# and must then be forced into the cache +# find sdar/sdcclib as CMAKE_AR +# since cmake may already have searched for "ar", sdar has to +# be searched with a different variable name (SDCCAR_EXECUTABLE) +# and must then be forced into the cache. +# sdcclib has been deprecated in SDCC 3.2.0 and removed in 3.8.6 +# so we first look for sdar get_filename_component(SDCC_LOCATION "${CMAKE_C_COMPILER}" PATH) -find_program(SDCCLIB_EXECUTABLE sdcclib PATHS "${SDCC_LOCATION}" NO_DEFAULT_PATH) -find_program(SDCCLIB_EXECUTABLE sdcclib) -set(CMAKE_AR "${SDCCLIB_EXECUTABLE}" CACHE FILEPATH "The sdcc librarian" FORCE) +find_program(SDCCAR_EXECUTABLE sdar NAMES sdcclib PATHS "${SDCC_LOCATION}" NO_DEFAULT_PATH) +find_program(SDCCAR_EXECUTABLE sdar NAMES sdcclib) +# for compatibility, in case SDCCLIB_EXECUTABLE is set, we use it +if(DEFINED SDCCLIB_EXECUTABLE) + set(CMAKE_AR "${SDCCLIB_EXECUTABLE}" CACHE FILEPATH "The sdcc librarian" FORCE) +else() + set(CMAKE_AR "${SDCCAR_EXECUTABLE}" CACHE FILEPATH "The sdcc librarian" FORCE) +endif() + + +if("${SDCCAR_EXECUTABLE}" MATCHES "sdcclib") + set(CMAKE_AR_OPTIONS "-a") +else() + set(CMAKE_AR_OPTIONS "-rc") +endif() # CMAKE_C_FLAGS_INIT and CMAKE_EXE_LINKER_FLAGS_INIT should be set in a CMAKE_SYSTEM_PROCESSOR file if(NOT DEFINED CMAKE_C_FLAGS_INIT) @@ -45,10 +59,10 @@ set(CMAKE_C_COMPILE_OBJECT "<CMAKE_C_COMPILER> <DEFINES> <INCLUDES> <FLAGS> -o # link object files to an executable set(CMAKE_C_LINK_EXECUTABLE "<CMAKE_C_COMPILER> <FLAGS> <OBJECTS> -o <TARGET> <CMAKE_C_LINK_FLAGS> <LINK_FLAGS> <LINK_LIBRARIES>") -# needs sdcc 2.7.0 + sddclib from cvs +# needs sdcc + sdar/sdcclib set(CMAKE_C_CREATE_STATIC_LIBRARY "\"${CMAKE_COMMAND}\" -E remove <TARGET>" - "<CMAKE_AR> -a <TARGET> <LINK_FLAGS> <OBJECTS> ") + "<CMAKE_AR> ${CMAKE_AR_OPTIONS} <TARGET> <LINK_FLAGS> <OBJECTS> ") # not supported by sdcc set(CMAKE_C_CREATE_SHARED_LIBRARY "") diff --git a/Modules/Platform/Windows-GNU.cmake b/Modules/Platform/Windows-GNU.cmake index 71189b1..cf85367 100644 --- a/Modules/Platform/Windows-GNU.cmake +++ b/Modules/Platform/Windows-GNU.cmake @@ -124,7 +124,7 @@ macro(__windows_compiler_gnu lang) string(REPLACE "<OBJECTS>" "-Wl,--whole-archive <OBJECT_DIR>/objects.a -Wl,--no-whole-archive" CMAKE_${lang}_${rule} "${CMAKE_${lang}_${rule}}") set(CMAKE_${lang}_${rule} - "<CMAKE_COMMAND> -E remove -f <OBJECT_DIR>/objects.a" + "<CMAKE_COMMAND> -E rm -f <OBJECT_DIR>/objects.a" "<CMAKE_AR> cr <OBJECT_DIR>/objects.a <OBJECTS>" "${CMAKE_${lang}_${rule}}" ) diff --git a/Modules/Platform/Windows-MSVC.cmake b/Modules/Platform/Windows-MSVC.cmake index 34f5d03..e1d6733 100644 --- a/Modules/Platform/Windows-MSVC.cmake +++ b/Modules/Platform/Windows-MSVC.cmake @@ -217,7 +217,7 @@ elseif(WINDOWS_PHONE OR WINDOWS_STORE) else() set(_PLATFORM_DEFINES "/DWIN32") - if(_MSVC_C_ARCHITECTURE_FAMILY STREQUAL "ARM" OR _MSVC_CXX_ARCHITECTURE_FAMILY STREQUAL "ARM" OR _MSVC_C_ARCHITECTURE_FAMILY STREQUAL "ARM64" OR _MSVC_CXX_ARCHITECTURE_FAMILY STREQUAL "ARM64") + if(_MSVC_C_ARCHITECTURE_FAMILY STREQUAL "ARM" OR _MSVC_CXX_ARCHITECTURE_FAMILY STREQUAL "ARM") set(CMAKE_C_STANDARD_LIBRARIES_INIT "kernel32.lib user32.lib") elseif(MSVC_VERSION GREATER 1310) if(CMAKE_VS_PLATFORM_TOOLSET MATCHES "v[0-9]+_clang_.*") diff --git a/Modules/Platform/Windows-NVIDIA-CUDA.cmake b/Modules/Platform/Windows-NVIDIA-CUDA.cmake index 94d77b9..30b5aa9 100644 --- a/Modules/Platform/Windows-NVIDIA-CUDA.cmake +++ b/Modules/Platform/Windows-NVIDIA-CUDA.cmake @@ -1,11 +1,11 @@ include(Platform/Windows-MSVC) set(CMAKE_CUDA_COMPILE_PTX_COMPILATION - "<CMAKE_CUDA_COMPILER> ${CMAKE_CUDA_HOST_FLAGS} <DEFINES> <INCLUDES> <FLAGS> -x cu -ptx <SOURCE> -o <OBJECT> -Xcompiler=-Fd<TARGET_COMPILE_PDB>,-FS") + "<CMAKE_CUDA_COMPILER> ${_CMAKE_CUDA_EXTRA_FLAGS} <DEFINES> <INCLUDES> <FLAGS> -x cu -ptx <SOURCE> -o <OBJECT> -Xcompiler=-Fd<TARGET_COMPILE_PDB>,-FS") set(CMAKE_CUDA_COMPILE_SEPARABLE_COMPILATION - "<CMAKE_CUDA_COMPILER> ${CMAKE_CUDA_HOST_FLAGS} <DEFINES> <INCLUDES> <FLAGS> -x cu -dc <SOURCE> -o <OBJECT> -Xcompiler=-Fd<TARGET_COMPILE_PDB>,-FS") + "<CMAKE_CUDA_COMPILER> ${_CMAKE_CUDA_EXTRA_FLAGS} <DEFINES> <INCLUDES> <FLAGS> -x cu -dc <SOURCE> -o <OBJECT> -Xcompiler=-Fd<TARGET_COMPILE_PDB>,-FS") set(CMAKE_CUDA_COMPILE_WHOLE_COMPILATION - "<CMAKE_CUDA_COMPILER> ${CMAKE_CUDA_HOST_FLAGS} <DEFINES> <INCLUDES> <FLAGS> -x cu -c <SOURCE> -o <OBJECT> -Xcompiler=-Fd<TARGET_COMPILE_PDB>,-FS") + "<CMAKE_CUDA_COMPILER> ${_CMAKE_CUDA_EXTRA_FLAGS} <DEFINES> <INCLUDES> <FLAGS> -x cu -c <SOURCE> -o <OBJECT> -Xcompiler=-Fd<TARGET_COMPILE_PDB>,-FS") set(__IMPLICT_LINKS ) foreach(dir ${CMAKE_CUDA_HOST_IMPLICIT_LINK_DIRECTORIES}) @@ -30,11 +30,6 @@ set(CMAKE_CUDA_LINK_EXECUTABLE unset(_CMAKE_VS_LINK_EXE) unset(_CMAKE_VS_LINK_EXE) -if(CMAKE_CUDA_COMPILER_VERSION VERSION_GREATER_EQUAL "8.0.0") - set(_CMAKE_CUDA_EXTRA_DEVICE_LINK_FLAGS "-Wno-deprecated-gpu-targets") -else() - set(_CMAKE_CUDA_EXTRA_DEVICE_LINK_FLAGS "") -endif() # Add implicit host link directories that contain device libraries # to the device link line. @@ -51,11 +46,9 @@ endforeach() unset(__IMPLICT_DLINK_DIRS) set(CMAKE_CUDA_DEVICE_LINK_LIBRARY - "<CMAKE_CUDA_COMPILER> <LANGUAGE_COMPILE_FLAGS> ${_CMAKE_CUDA_EXTRA_DEVICE_LINK_FLAGS} -shared -dlink <OBJECTS> -o <TARGET> <LINK_LIBRARIES> -Xcompiler=-Fd<TARGET_COMPILE_PDB>,-FS${__IMPLICT_DLINK_FLAGS}") + "<CMAKE_CUDA_COMPILER> ${_CMAKE_CUDA_EXTRA_FLAGS} <LANGUAGE_COMPILE_FLAGS> ${_CMAKE_CUDA_EXTRA_DEVICE_LINK_FLAGS} -shared -dlink <OBJECTS> -o <TARGET> <LINK_LIBRARIES> -Xcompiler=-Fd<TARGET_COMPILE_PDB>,-FS${__IMPLICT_DLINK_FLAGS}") set(CMAKE_CUDA_DEVICE_LINK_EXECUTABLE - "<CMAKE_CUDA_COMPILER> <FLAGS> ${_CMAKE_CUDA_EXTRA_DEVICE_LINK_FLAGS} -shared -dlink <OBJECTS> -o <TARGET> <LINK_LIBRARIES> -Xcompiler=-Fd<TARGET_COMPILE_PDB>,-FS${__IMPLICT_DLINK_FLAGS}") - -unset(_CMAKE_CUDA_EXTRA_DEVICE_LINK_FLAGS) + "<CMAKE_CUDA_COMPILER> ${_CMAKE_CUDA_EXTRA_FLAGS} <FLAGS> ${_CMAKE_CUDA_EXTRA_DEVICE_LINK_FLAGS} -shared -dlink <OBJECTS> -o <TARGET> <LINK_LIBRARIES> -Xcompiler=-Fd<TARGET_COMPILE_PDB>,-FS${__IMPLICT_DLINK_FLAGS}") unset(__IMPLICT_DLINK_FLAGS) string(REPLACE "/D" "-D" _PLATFORM_DEFINES_CUDA "${_PLATFORM_DEFINES}${_PLATFORM_DEFINES_CXX}") diff --git a/Modules/TestBigEndian.cmake b/Modules/TestBigEndian.cmake index 0c6e188..8a769b7 100644 --- a/Modules/TestBigEndian.cmake +++ b/Modules/TestBigEndian.cmake @@ -19,8 +19,8 @@ include(CheckTypeSize) macro(TEST_BIG_ENDIAN VARIABLE) if(NOT DEFINED HAVE_${VARIABLE}) - message(STATUS "Check if the system is big endian") - message(STATUS "Searching 16 bit integer") + message(CHECK_START "Check if the system is big endian") + message(CHECK_START "Searching 16 bit integer") if(CMAKE_C_COMPILER_LOADED) set(_test_language "C") @@ -32,19 +32,19 @@ macro(TEST_BIG_ENDIAN VARIABLE) CHECK_TYPE_SIZE("unsigned short" CMAKE_SIZEOF_UNSIGNED_SHORT LANGUAGE ${_test_language}) if(CMAKE_SIZEOF_UNSIGNED_SHORT EQUAL 2) - message(STATUS "Using unsigned short") + message(CHECK_PASS "Using unsigned short") set(CMAKE_16BIT_TYPE "unsigned short") else() CHECK_TYPE_SIZE("unsigned int" CMAKE_SIZEOF_UNSIGNED_INT LANGUAGE ${_test_language}) if(CMAKE_SIZEOF_UNSIGNED_INT) - message(STATUS "Using unsigned int") + message(CHECK_PASS "Using unsigned int") set(CMAKE_16BIT_TYPE "unsigned int") else() CHECK_TYPE_SIZE("unsigned long" CMAKE_SIZEOF_UNSIGNED_LONG LANGUAGE ${_test_language}) if(CMAKE_SIZEOF_UNSIGNED_LONG) - message(STATUS "Using unsigned long") + message(CHECK_PASS "Using unsigned long") set(CMAKE_16BIT_TYPE "unsigned long") else() message(FATAL_ERROR "no suitable type found") @@ -95,15 +95,16 @@ macro(TEST_BIG_ENDIAN VARIABLE) if(CMAKE_TEST_ENDIANESS_STRINGS_LE) set(${VARIABLE} 0 CACHE INTERNAL "Result of TEST_BIG_ENDIAN" FORCE) - message(STATUS "Check if the system is big endian - little endian") + message(CHECK_PASS "little endian") endif() if(CMAKE_TEST_ENDIANESS_STRINGS_BE) set(${VARIABLE} 1 CACHE INTERNAL "Result of TEST_BIG_ENDIAN" FORCE) - message(STATUS "Check if the system is big endian - big endian") + message(CHECK_PASS "big endian") endif() if(NOT CMAKE_TEST_ENDIANESS_STRINGS_BE AND NOT CMAKE_TEST_ENDIANESS_STRINGS_LE) + message(CHECK_FAIL "TEST_BIG_ENDIAN found no result!") message(SEND_ERROR "TEST_BIG_ENDIAN found no result!") endif() @@ -111,7 +112,7 @@ macro(TEST_BIG_ENDIAN VARIABLE) "Determining if the system is big endian passed with the following output:\n${OUTPUT}\nTestEndianess.c:\n${TEST_ENDIANESS_FILE_CONTENT}\n\n") else() - message(STATUS "Check if the system is big endian - failed") + message(CHECK_FAIL "failed") file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log "Determining if the system is big endian failed with the following output:\n${OUTPUT}\nTestEndianess.c:\n${TEST_ENDIANESS_FILE_CONTENT}\n\n") set(${VARIABLE}) diff --git a/Modules/TestCXXAcceptsFlag.cmake b/Modules/TestCXXAcceptsFlag.cmake index 92a362e..ce505f3 100644 --- a/Modules/TestCXXAcceptsFlag.cmake +++ b/Modules/TestCXXAcceptsFlag.cmake @@ -23,19 +23,19 @@ Check if the CXX compiler accepts a flag. macro(CHECK_CXX_ACCEPTS_FLAG FLAGS VARIABLE) if(NOT DEFINED ${VARIABLE}) - message(STATUS "Checking to see if CXX compiler accepts flag ${FLAGS}") + message(CHECK_START "Checking to see if CXX compiler accepts flag ${FLAGS}") try_compile(${VARIABLE} ${CMAKE_BINARY_DIR} ${CMAKE_ROOT}/Modules/DummyCXXFile.cxx CMAKE_FLAGS -DCOMPILE_DEFINITIONS:STRING=${FLAGS} OUTPUT_VARIABLE OUTPUT) if(${VARIABLE}) - message(STATUS "Checking to see if CXX compiler accepts flag ${FLAGS} - yes") + message(CHECK_PASS "yes") file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log "Determining if the CXX compiler accepts the flag ${FLAGS} passed with " "the following output:\n${OUTPUT}\n\n") else() - message(STATUS "Checking to see if CXX compiler accepts flag ${FLAGS} - no") + message(CHECK_FAIL "no") file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log "Determining if the CXX compiler accepts the flag ${FLAGS} failed with " "the following output:\n${OUTPUT}\n\n") diff --git a/Modules/TestForANSIForScope.cmake b/Modules/TestForANSIForScope.cmake index 272e4ec..0f2dc01 100644 --- a/Modules/TestForANSIForScope.cmake +++ b/Modules/TestForANSIForScope.cmake @@ -16,19 +16,19 @@ for-init-statement to the loop body. #]=======================================================================] if(NOT DEFINED CMAKE_ANSI_FOR_SCOPE) - message(STATUS "Check for ANSI scope") + message(CHECK_START "Check for ANSI scope") try_compile(CMAKE_ANSI_FOR_SCOPE ${CMAKE_BINARY_DIR} ${CMAKE_ROOT}/Modules/TestForAnsiForScope.cxx OUTPUT_VARIABLE OUTPUT) if (CMAKE_ANSI_FOR_SCOPE) - message(STATUS "Check for ANSI scope - found") + message(CHECK_PASS "found") set (CMAKE_NO_ANSI_FOR_SCOPE 0 CACHE INTERNAL "Does the compiler support ansi for scope.") file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log "Determining if the CXX compiler understands ansi for scopes passed with " "the following output:\n${OUTPUT}\n\n") else () - message(STATUS "Check for ANSI scope - not found") + message(CHECK_FAIL "not found") set (CMAKE_NO_ANSI_FOR_SCOPE 1 CACHE INTERNAL "Does the compiler support ansi for scope.") file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log diff --git a/Modules/TestForSSTREAM.cmake b/Modules/TestForSSTREAM.cmake index e70df00..545b7ec 100644 --- a/Modules/TestForSSTREAM.cmake +++ b/Modules/TestForSSTREAM.cmake @@ -15,19 +15,19 @@ check if the compiler supports the standard ANSI sstream header #]=======================================================================] if(NOT DEFINED CMAKE_HAS_ANSI_STRING_STREAM) - message(STATUS "Check for sstream") + message(CHECK_START "Check for sstream") try_compile(CMAKE_HAS_ANSI_STRING_STREAM ${CMAKE_BINARY_DIR} ${CMAKE_ROOT}/Modules/TestForSSTREAM.cxx OUTPUT_VARIABLE OUTPUT) if (CMAKE_HAS_ANSI_STRING_STREAM) - message(STATUS "Check for sstream - found") + message(CHECK_PASS "found") set (CMAKE_NO_ANSI_STRING_STREAM 0 CACHE INTERNAL "Does the compiler support sstream") file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log "Determining if the CXX compiler has sstream passed with " "the following output:\n${OUTPUT}\n\n") else () - message(STATUS "Check for sstream - not found") + message(CHECK_FAIL "not found") set (CMAKE_NO_ANSI_STRING_STREAM 1 CACHE INTERNAL "Does the compiler support sstream") file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log diff --git a/Modules/TestForSTDNamespace.cmake b/Modules/TestForSTDNamespace.cmake index 703e631..d101c83 100644 --- a/Modules/TestForSTDNamespace.cmake +++ b/Modules/TestForSTDNamespace.cmake @@ -15,19 +15,19 @@ check if the compiler supports std:: on stl classes #]=======================================================================] if(NOT DEFINED CMAKE_STD_NAMESPACE) - message(STATUS "Check for STD namespace") + message(CHECK_START "Check for STD namespace") try_compile(CMAKE_STD_NAMESPACE ${CMAKE_BINARY_DIR} ${CMAKE_ROOT}/Modules/TestForSTDNamespace.cxx OUTPUT_VARIABLE OUTPUT) if (CMAKE_STD_NAMESPACE) - message(STATUS "Check for STD namespace - found") + message(CHECK_PASS "found") set (CMAKE_NO_STD_NAMESPACE 0 CACHE INTERNAL "Does the compiler support std::.") file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log "Determining if the CXX compiler has std namespace passed with " "the following output:\n${OUTPUT}\n\n") else () - message(STATUS "Check for STD namespace - not found") + message(CHECK_FAIL "not found") set (CMAKE_NO_STD_NAMESPACE 1 CACHE INTERNAL "Does the compiler support std::.") file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log diff --git a/Modules/UseJava.cmake b/Modules/UseJava.cmake index 0798488..b668b9e 100644 --- a/Modules/UseJava.cmake +++ b/Modules/UseJava.cmake @@ -405,9 +405,14 @@ endfunction() # define helper scripts set(_JAVA_EXPORT_TARGETS_SCRIPT ${CMAKE_CURRENT_LIST_DIR}/javaTargets.cmake.in) -set(_JAVA_CLASS_FILELIST_SCRIPT ${CMAKE_CURRENT_LIST_DIR}/UseJavaClassFilelist.cmake) set(_JAVA_SYMLINK_SCRIPT ${CMAKE_CURRENT_LIST_DIR}/UseJavaSymlinks.cmake) +if (CMAKE_HOST_WIN32 AND NOT CYGWIN AND CMAKE_HOST_SYSTEM_NAME MATCHES "Windows") + set(_UseJava_PATH_SEP "$<SEMICOLON>") +else () + set(_UseJava_PATH_SEP ":") +endif() + function(add_jar _TARGET_NAME) cmake_parse_arguments(_add_jar @@ -497,14 +502,8 @@ function(add_jar _TARGET_NAME) ${CMAKE_JAVA_LIBRARY_OUTPUT_PATH} ) - if (CMAKE_HOST_WIN32 AND NOT CYGWIN AND CMAKE_HOST_SYSTEM_NAME MATCHES "Windows") - set(CMAKE_JAVA_INCLUDE_FLAG_SEP ";") - else () - set(CMAKE_JAVA_INCLUDE_FLAG_SEP ":") - endif() - foreach (JAVA_INCLUDE_DIR IN LISTS CMAKE_JAVA_INCLUDE_PATH) - string(APPEND CMAKE_JAVA_INCLUDE_PATH_FINAL "${CMAKE_JAVA_INCLUDE_FLAG_SEP}${JAVA_INCLUDE_DIR}") + string(APPEND CMAKE_JAVA_INCLUDE_PATH_FINAL "${_UseJava_PATH_SEP}${JAVA_INCLUDE_DIR}") endforeach() set(CMAKE_JAVA_CLASS_OUTPUT_PATH "${CMAKE_CURRENT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/${_TARGET_NAME}.dir") @@ -576,7 +575,7 @@ function(add_jar _TARGET_NAME) if (TARGET ${_JAVA_INCLUDE_JAR}) get_target_property(_JAVA_JAR_PATH ${_JAVA_INCLUDE_JAR} JAR_FILE) if (_JAVA_JAR_PATH) - string(APPEND CMAKE_JAVA_INCLUDE_PATH_FINAL "${CMAKE_JAVA_INCLUDE_FLAG_SEP}${_JAVA_JAR_PATH}") + string(APPEND CMAKE_JAVA_INCLUDE_PATH_FINAL "${_UseJava_PATH_SEP}${_JAVA_JAR_PATH}") list(APPEND CMAKE_JAVA_INCLUDE_PATH ${_JAVA_JAR_PATH}) list(APPEND _JAVA_DEPENDS ${_JAVA_INCLUDE_JAR}) list(APPEND _JAVA_COMPILE_DEPENDS ${_JAVA_JAR_PATH}) @@ -584,7 +583,7 @@ function(add_jar _TARGET_NAME) message(SEND_ERROR "add_jar: INCLUDE_JARS target ${_JAVA_INCLUDE_JAR} is not a jar") endif () else () - string(APPEND CMAKE_JAVA_INCLUDE_PATH_FINAL "${CMAKE_JAVA_INCLUDE_FLAG_SEP}${_JAVA_INCLUDE_JAR}") + string(APPEND CMAKE_JAVA_INCLUDE_PATH_FINAL "${_UseJava_PATH_SEP}${_JAVA_INCLUDE_JAR}") list(APPEND CMAKE_JAVA_INCLUDE_PATH "${_JAVA_INCLUDE_JAR}") list(APPEND _JAVA_DEPENDS "${_JAVA_INCLUDE_JAR}") list(APPEND _JAVA_COMPILE_DEPENDS "${_JAVA_INCLUDE_JAR}") @@ -627,7 +626,7 @@ function(add_jar _TARGET_NAME) COMMAND ${CMAKE_COMMAND} -DCMAKE_JAVA_CLASS_OUTPUT_PATH=${CMAKE_JAVA_CLASS_OUTPUT_PATH} -DCMAKE_JAR_CLASSES_PREFIX="${CMAKE_JAR_CLASSES_PREFIX}" - -P ${_JAVA_CLASS_FILELIST_SCRIPT} + -P ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/UseJavaClassFilelist.cmake DEPENDS ${CMAKE_JAVA_CLASS_OUTPUT_PATH}/java_compiled_${_TARGET_NAME} WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} ) @@ -1190,55 +1189,40 @@ function(create_javadoc _target) set(_javadoc_options -d ${_javadoc_builddir}) if (_javadoc_sourcepath) - set(_start TRUE) - foreach(_path IN LISTS _javadoc_sourcepath) - if (_start) - set(_sourcepath ${_path}) - set(_start FALSE) - else () - set(_sourcepath ${_sourcepath}:${_path}) - endif () - endforeach() - set(_javadoc_options ${_javadoc_options} -sourcepath ${_sourcepath}) + list(JOIN _javadoc_sourcepath "${_UseJava_PATH_SEP}" _javadoc_sourcepath) + list(APPEND _javadoc_options -sourcepath "\"${_javadoc_sourcepath}\"") endif () if (_javadoc_classpath) - set(_start TRUE) - foreach(_path IN LISTS _javadoc_classpath) - if (_start) - set(_classpath ${_path}) - set(_start FALSE) - else () - set(_classpath ${_classpath}:${_path}) - endif () - endforeach() - set(_javadoc_options ${_javadoc_options} -classpath "${_classpath}") + list(JOIN _javadoc_classpath "${_UseJava_PATH_SEP}" _javadoc_classpath) + list(APPEND _javadoc_options -classpath "\"${_javadoc_classpath}\"") endif () if (_javadoc_doctitle) - set(_javadoc_options ${_javadoc_options} -doctitle '${_javadoc_doctitle}') + list(APPEND _javadoc_options -doctitle '${_javadoc_doctitle}') endif () if (_javadoc_windowtitle) - set(_javadoc_options ${_javadoc_options} -windowtitle '${_javadoc_windowtitle}') + list(APPEND _javadoc_options -windowtitle '${_javadoc_windowtitle}') endif () if (_javadoc_author) - set(_javadoc_options ${_javadoc_options} -author) + list(APPEND _javadoc_options -author) endif () if (_javadoc_use) - set(_javadoc_options ${_javadoc_options} -use) + list(APPEND _javadoc_options -use) endif () if (_javadoc_version) - set(_javadoc_options ${_javadoc_options} -version) + list(APPEND _javadoc_options -version) endif () add_custom_target(${_target}_javadoc ALL - COMMAND ${Java_JAVADOC_EXECUTABLE} ${_javadoc_options} - ${_javadoc_files} - ${_javadoc_packages} + COMMAND ${Java_JAVADOC_EXECUTABLE} + ${_javadoc_options} + ${_javadoc_files} + ${_javadoc_packages} WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} ) @@ -1274,11 +1258,6 @@ function (create_javah) endif() set (_output_files) - if (WIN32 AND NOT CYGWIN AND CMAKE_HOST_SYSTEM_NAME MATCHES "Windows") - set(_classpath_sep "$<SEMICOLON>") - else () - set(_classpath_sep ":") - endif() # handle javah options set (_javah_options) @@ -1304,7 +1283,7 @@ function (create_javah) message(SEND_ERROR "create_javah: CLASSPATH entry ${_path} does not exist.") endif() endforeach() - string (REPLACE ";" "${_classpath_sep}" _classpath "${_classpath}") + string (REPLACE ";" "${_UseJava_PATH_SEP}" _classpath "${_classpath}") list (APPEND _javah_options -classpath "${_classpath}") endif() diff --git a/Source/CMakeLists.txt b/Source/CMakeLists.txt index b1f7b29..ff313d6 100644 --- a/Source/CMakeLists.txt +++ b/Source/CMakeLists.txt @@ -289,6 +289,8 @@ set(SRCS cmGeneratorExpression.h cmGeneratorTarget.cxx cmGeneratorTarget.h + cmLinkItemGraphVisitor.cxx + cmLinkItemGraphVisitor.h cmGetPipes.cxx cmGetPipes.h cmGlobalCommonGenerator.cxx @@ -691,6 +693,8 @@ set(SRCS cmDuration.h cmDuration.cxx + + bindexplib.cxx ) SET_PROPERTY(SOURCE cmProcessOutput.cxx APPEND PROPERTY COMPILE_DEFINITIONS @@ -713,7 +717,6 @@ if (WIN32) set(SRCS ${SRCS} cmCallVisualStudioMacro.cxx cmCallVisualStudioMacro.h - bindexplib.cxx ) if(NOT UNIX) @@ -1193,6 +1196,11 @@ if(WIN32) endforeach() endif() +if(CMake_JOB_POOL_LINK_BIN) + set_property(TARGET ${_tools} PROPERTY JOB_POOL_LINK "link-bin") + set_property(GLOBAL APPEND PROPERTY JOB_POOLS "link-bin=${CMake_JOB_POOL_LINK_BIN}") +endif() + # Install tools foreach(_tool ${_tools}) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index 17eda0d..868a595 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,7 +1,7 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 16) -set(CMake_VERSION_PATCH 2) +set(CMake_VERSION_PATCH 20191219) #set(CMake_VERSION_RC 0) set(CMake_VERSION_IS_DIRTY 0) diff --git a/Source/CPack/cmCPackNSISGenerator.cxx b/Source/CPack/cmCPackNSISGenerator.cxx index 9bf72df..4702639 100644 --- a/Source/CPack/cmCPackNSISGenerator.cxx +++ b/Source/CPack/cmCPackNSISGenerator.cxx @@ -128,14 +128,13 @@ int cmCPackNSISGenerator::PackageFiles() this->IsSet("CPACK_NSIS_MUI_UNIICON")) { std::string installerIconCode; if (this->IsSet("CPACK_NSIS_MUI_ICON")) { - installerIconCode += "!define MUI_ICON \""; - installerIconCode += this->GetOption("CPACK_NSIS_MUI_ICON"); - installerIconCode += "\"\n"; + installerIconCode += cmStrCat( + "!define MUI_ICON \"", this->GetOption("CPACK_NSIS_MUI_ICON"), "\"\n"); } if (this->IsSet("CPACK_NSIS_MUI_UNIICON")) { - installerIconCode += "!define MUI_UNICON \""; - installerIconCode += this->GetOption("CPACK_NSIS_MUI_UNIICON"); - installerIconCode += "\"\n"; + installerIconCode += + cmStrCat("!define MUI_UNICON \"", + this->GetOption("CPACK_NSIS_MUI_UNIICON"), "\"\n"); } this->SetOptionIfNotSet("CPACK_NSIS_INSTALLER_MUI_ICON_CODE", installerIconCode.c_str()); @@ -173,6 +172,32 @@ int cmCPackNSISGenerator::PackageFiles() installerRunCode.c_str()); } + if (this->IsSet("CPACK_NSIS_WELCOME_TITLE")) { + std::string welcomeTitleCode = + cmStrCat("!define MUI_WELCOMEPAGE_TITLE \"", + this->GetOption("CPACK_NSIS_WELCOME_TITLE"), "\""); + this->SetOptionIfNotSet("CPACK_NSIS_INSTALLER_WELCOME_TITLE_CODE", + welcomeTitleCode.c_str()); + } + + if (this->IsSet("CPACK_NSIS_WELCOME_TITLE_3LINES")) { + this->SetOptionIfNotSet("CPACK_NSIS_INSTALLER_WELCOME_TITLE_3LINES_CODE", + "!define MUI_WELCOMEPAGE_TITLE_3LINES"); + } + + if (this->IsSet("CPACK_NSIS_FINISH_TITLE")) { + std::string finishTitleCode = + cmStrCat("!define MUI_FINISHPAGE_TITLE \"", + this->GetOption("CPACK_NSIS_FINISH_TITLE"), "\""); + this->SetOptionIfNotSet("CPACK_NSIS_INSTALLER_FINISH_TITLE_CODE", + finishTitleCode.c_str()); + } + + if (this->IsSet("CPACK_NSIS_FINISH_TITLE_3LINES")) { + this->SetOptionIfNotSet("CPACK_NSIS_INSTALLER_FINISH_TITLE_3LINES_CODE", + "!define MUI_FINISHPAGE_TITLE_3LINES"); + } + // Setup all of the component sections if (this->Components.empty()) { this->SetOptionIfNotSet("CPACK_NSIS_INSTALLATION_TYPES", ""); diff --git a/Source/CPack/cmCPackPKGGenerator.cxx b/Source/CPack/cmCPackPKGGenerator.cxx index dae5ec9..ac3d64d 100644 --- a/Source/CPack/cmCPackPKGGenerator.cxx +++ b/Source/CPack/cmCPackPKGGenerator.cxx @@ -46,7 +46,66 @@ std::string cmCPackPKGGenerator::GetPackageName( return component.ArchiveFile + ".pkg"; } -void cmCPackPKGGenerator::WriteDistributionFile(const char* metapackageFile) +void cmCPackPKGGenerator::CreateBackground(const char* themeName, + const char* metapackageFile, + cm::string_view genName, + cmXMLWriter& xout) +{ + std::string paramSuffix = + (themeName == nullptr) ? "" : cmSystemTools::UpperCase(themeName); + std::string opt = (themeName == nullptr) + ? cmStrCat("CPACK_", genName, "_BACKGROUND") + : cmStrCat("CPACK_", genName, "_BACKGROUND_", paramSuffix); + const char* bgFileName = this->GetOption(opt); + if (bgFileName == nullptr) { + return; + } + + std::string bgFilePath = cmStrCat(metapackageFile, "/Contents/", bgFileName); + + if (!cmSystemTools::FileExists(bgFilePath)) { + cmCPackLogger(cmCPackLog::LOG_ERROR, + "Background image doesn't exist in the resource directory: " + << bgFileName << std::endl); + return; + } + + if (themeName == nullptr) { + xout.StartElement("background"); + } else { + xout.StartElement(cmStrCat("background-", themeName)); + } + + xout.Attribute("file", bgFileName); + + const char* param = this->GetOption(cmStrCat(opt, "_ALIGNMENT")); + if (param != nullptr) { + xout.Attribute("alignment", param); + } + + param = this->GetOption(cmStrCat(opt, "_SCALING")); + if (param != nullptr) { + xout.Attribute("scaling", param); + } + + // Apple docs say that you must provide either mime-type or uti + // attribute for the background, but I've seen examples that + // doesn't have them, so don't make them mandatory. + param = this->GetOption(cmStrCat(opt, "_MIME_TYPE")); + if (param != nullptr) { + xout.Attribute("mime-type", param); + } + + param = this->GetOption(cmStrCat(opt, "_UTI")); + if (param != nullptr) { + xout.Attribute("uti", param); + } + + xout.EndElement(); +} + +void cmCPackPKGGenerator::WriteDistributionFile(const char* metapackageFile, + const char* genName) { std::string distributionTemplate = this->FindTemplate("CPack.distribution.dist.in"); @@ -102,6 +161,11 @@ void cmCPackPKGGenerator::WriteDistributionFile(const char* metapackageFile) CreateChoice(PostFlightComponent, xout); } + // default background + this->CreateBackground(nullptr, metapackageFile, genName, xout); + // Dark Aqua + this->CreateBackground("darkAqua", metapackageFile, genName, xout); + this->SetOption("CPACK_PACKAGEMAKER_CHOICES", choiceOut.str().c_str()); // Create the distribution.dist file in the metapackage to turn it diff --git a/Source/CPack/cmCPackPKGGenerator.h b/Source/CPack/cmCPackPKGGenerator.h index 69286ff..be730ab 100644 --- a/Source/CPack/cmCPackPKGGenerator.h +++ b/Source/CPack/cmCPackPKGGenerator.h @@ -9,6 +9,8 @@ #include <sstream> #include <string> +#include <cm/string_view> + #include "cmCPackComponentGroup.h" #include "cmCPackGenerator.h" @@ -57,7 +59,7 @@ protected: // inter-component dependencies. metapackageFile is the name of the // metapackage for the distribution. Only valid for a // component-based install. - void WriteDistributionFile(const char* metapackageFile); + void WriteDistributionFile(const char* metapackageFile, const char* genName); // Subroutine of WriteDistributionFile that writes out the // dependency attributes for inter-component dependencies. @@ -85,6 +87,10 @@ protected: /// installer GUI. void CreateChoice(const cmCPackComponent& component, cmXMLWriter& xout); + /// Creates a background in the distribution XML. + void CreateBackground(const char* themeName, const char* metapackageFile, + cm::string_view genName, cmXMLWriter& xout); + // The PostFlight component when creating a metapackage cmCPackComponent PostFlightComponent; }; diff --git a/Source/CPack/cmCPackPackageMakerGenerator.cxx b/Source/CPack/cmCPackPackageMakerGenerator.cxx index c5ba726..12ea97b 100644 --- a/Source/CPack/cmCPackPackageMakerGenerator.cxx +++ b/Source/CPack/cmCPackPackageMakerGenerator.cxx @@ -279,7 +279,7 @@ int cmCPackPackageMakerGenerator::PackageFiles() } else { // We have built the package in place. Generate the // distribution.dist file to describe it for the installer. - WriteDistributionFile(packageDirFileName.c_str()); + WriteDistributionFile(packageDirFileName.c_str(), "PACKAGEMAKER"); } std::string tmpFile = cmStrCat(this->GetOption("CPACK_TOPLEVEL_DIRECTORY"), diff --git a/Source/CPack/cmCPackProductBuildGenerator.cxx b/Source/CPack/cmCPackProductBuildGenerator.cxx index dae268c..a3e55de 100644 --- a/Source/CPack/cmCPackProductBuildGenerator.cxx +++ b/Source/CPack/cmCPackProductBuildGenerator.cxx @@ -81,7 +81,7 @@ int cmCPackProductBuildGenerator::PackageFiles() } // combine package(s) into a distribution - WriteDistributionFile(packageDirFileName.c_str()); + WriteDistributionFile(packageDirFileName.c_str(), "PRODUCTBUILD"); std::ostringstream pkgCmd; std::string version = this->GetOption("CPACK_PACKAGE_VERSION"); diff --git a/Source/CPack/cpack.cxx b/Source/CPack/cpack.cxx index 5895652..dc31623 100644 --- a/Source/CPack/cpack.cxx +++ b/Source/CPack/cpack.cxx @@ -115,7 +115,6 @@ int main(int argc, char const* const* argv) argc = args.argc(); argv = args.argv(); - cmSystemTools::EnableMSVCDebugHook(); cmSystemTools::InitializeLibUV(); cmSystemTools::FindCMakeResources(argv[0]); cmCPackLog log; @@ -314,7 +313,7 @@ int main(int argc, char const* const* argv) else { // get a default value (current working directory) cpackProjectDirectory = cmsys::SystemTools::GetCurrentWorkingDirectory(); - // use default value iff no value has been provided by the config file + // use default value if no value has been provided by the config file if (!globalMF.IsSet("CPACK_PACKAGE_DIRECTORY")) { globalMF.AddDefinition("CPACK_PACKAGE_DIRECTORY", cpackProjectDirectory); @@ -324,6 +323,12 @@ int main(int argc, char const* const* argv) globalMF.AddDefinition(cd.first, cd.second); } + // Force CPACK_PACKAGE_DIRECTORY as absolute path + cpackProjectDirectory = globalMF.GetDefinition("CPACK_PACKAGE_DIRECTORY"); + cpackProjectDirectory = + cmSystemTools::CollapseFullPath(cpackProjectDirectory); + globalMF.AddDefinition("CPACK_PACKAGE_DIRECTORY", cpackProjectDirectory); + const char* cpackModulesPath = globalMF.GetDefinition("CPACK_MODULE_PATH"); if (cpackModulesPath) { globalMF.AddDefinition("CMAKE_MODULE_PATH", cpackModulesPath); diff --git a/Source/CTest/cmCTestBZR.cxx b/Source/CTest/cmCTestBZR.cxx index 8640c46..c87fb83b 100644 --- a/Source/CTest/cmCTestBZR.cxx +++ b/Source/CTest/cmCTestBZR.cxx @@ -8,11 +8,12 @@ #include <ostream> #include <vector> +#include <cmext/algorithm> + #include "cmsys/RegularExpression.hxx" #include "cm_expat.h" -#include "cmAlgorithms.h" #include "cmCTest.h" #include "cmCTestVC.h" #include "cmProcessTools.h" @@ -245,7 +246,7 @@ private: void CharacterDataHandler(const char* data, int length) override { - cmAppend(this->CData, data, data + length); + cm::append(this->CData, data, data + length); } void EndElement(const std::string& name) override diff --git a/Source/CTest/cmCTestBuildHandler.cxx b/Source/CTest/cmCTestBuildHandler.cxx index 9cb5449..03a3fd3 100644 --- a/Source/CTest/cmCTestBuildHandler.cxx +++ b/Source/CTest/cmCTestBuildHandler.cxx @@ -7,11 +7,12 @@ #include <set> #include <utility> +#include <cmext/algorithm> + #include "cmsys/Directory.hxx" #include "cmsys/FStream.hxx" #include "cmsys/Process.h" -#include "cmAlgorithms.h" #include "cmCTest.h" #include "cmDuration.h" #include "cmFileTimeCache.h" @@ -969,7 +970,7 @@ void cmCTestBuildHandler::ProcessBuffer(const char* data, size_t length, if (it != queue->end()) { // Create a contiguous array for the line this->CurrentProcessingLine.clear(); - cmAppend(this->CurrentProcessingLine, queue->begin(), it); + cm::append(this->CurrentProcessingLine, queue->begin(), it); this->CurrentProcessingLine.push_back(0); const char* line = this->CurrentProcessingLine.data(); diff --git a/Source/CTest/cmCTestCoverageHandler.cxx b/Source/CTest/cmCTestCoverageHandler.cxx index 4cd783f..2c8f119 100644 --- a/Source/CTest/cmCTestCoverageHandler.cxx +++ b/Source/CTest/cmCTestCoverageHandler.cxx @@ -12,12 +12,13 @@ #include <sstream> #include <utility> +#include <cmext/algorithm> + #include "cmsys/FStream.hxx" #include "cmsys/Glob.hxx" #include "cmsys/Process.h" #include "cmsys/RegularExpression.hxx" -#include "cmAlgorithms.h" #include "cmCTest.h" #include "cmDuration.h" #include "cmGeneratedFileStream.h" @@ -819,7 +820,7 @@ int cmCTestCoverageHandler::HandleJacocoCoverage( std::string binaryDir = this->CTest->GetCTestConfiguration("BuildDirectory"); std::string binCoverageFile = binaryDir + "/*jacoco.xml"; g2.FindFiles(binCoverageFile); - cmAppend(files, g2.GetFiles()); + cm::append(files, g2.GetFiles()); if (!files.empty()) { cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT, @@ -1462,7 +1463,7 @@ int cmCTestCoverageHandler::HandleLCovCoverage( " looking for LCOV files in: " << daGlob << std::endl, this->Quiet); gl.FindFiles(daGlob); // Keep a list of all LCOV files - cmAppend(lcovFiles, gl.GetFiles()); + cm::append(lcovFiles, gl.GetFiles()); for (std::string const& file : lcovFiles) { lcovFile = file; @@ -1599,10 +1600,10 @@ void cmCTestCoverageHandler::FindGCovFiles(std::vector<std::string>& files) " globbing for coverage in: " << lm.first << std::endl, this->Quiet); std::string daGlob = cmStrCat(lm.first, "/*.da"); gl.FindFiles(daGlob); - cmAppend(files, gl.GetFiles()); + cm::append(files, gl.GetFiles()); daGlob = cmStrCat(lm.first, "/*.gcda"); gl.FindFiles(daGlob); - cmAppend(files, gl.GetFiles()); + cm::append(files, gl.GetFiles()); } } @@ -1638,7 +1639,7 @@ bool cmCTestCoverageHandler::FindLCovFiles(std::vector<std::string>& files) "Error while finding files matching " << daGlob << std::endl); return false; } - cmAppend(files, gl.GetFiles()); + cm::append(files, gl.GetFiles()); cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT, "Now searching in: " << daGlob << std::endl, this->Quiet); return true; diff --git a/Source/CTest/cmCTestCurl.cxx b/Source/CTest/cmCTestCurl.cxx index ccac832..3ad4749 100644 --- a/Source/CTest/cmCTestCurl.cxx +++ b/Source/CTest/cmCTestCurl.cxx @@ -5,7 +5,8 @@ #include <cstdio> #include <ostream> -#include "cmAlgorithms.h" +#include <cmext/algorithm> + #include "cmCTest.h" #include "cmCurl.h" #include "cmStringAlgorithms.h" @@ -46,14 +47,14 @@ size_t curlWriteMemoryCallback(void* ptr, size_t size, size_t nmemb, { int realsize = static_cast<int>(size * nmemb); const char* chPtr = static_cast<char*>(ptr); - cmAppend(*static_cast<std::vector<char>*>(data), chPtr, chPtr + realsize); + cm::append(*static_cast<std::vector<char>*>(data), chPtr, chPtr + realsize); return realsize; } size_t curlDebugCallback(CURL* /*unused*/, curl_infotype /*unused*/, char* chPtr, size_t size, void* data) { - cmAppend(*static_cast<std::vector<char>*>(data), chPtr, chPtr + size); + cm::append(*static_cast<std::vector<char>*>(data), chPtr, chPtr + size); return size; } } diff --git a/Source/CTest/cmCTestHG.cxx b/Source/CTest/cmCTestHG.cxx index 3265498..5f4581e 100644 --- a/Source/CTest/cmCTestHG.cxx +++ b/Source/CTest/cmCTestHG.cxx @@ -5,9 +5,10 @@ #include <ostream> #include <vector> +#include <cmext/algorithm> + #include "cmsys/RegularExpression.hxx" -#include "cmAlgorithms.h" #include "cmCTest.h" #include "cmCTestVC.h" #include "cmProcessTools.h" @@ -204,7 +205,7 @@ private: void CharacterDataHandler(const char* data, int length) override { - cmAppend(this->CData, data, data + length); + cm::append(this->CData, data, data + length); } void EndElement(const std::string& name) override diff --git a/Source/CTest/cmCTestMemCheckHandler.cxx b/Source/CTest/cmCTestMemCheckHandler.cxx index a5ec1ae..c1ecaf1 100644 --- a/Source/CTest/cmCTestMemCheckHandler.cxx +++ b/Source/CTest/cmCTestMemCheckHandler.cxx @@ -2,9 +2,11 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmCTestMemCheckHandler.h" +#include <algorithm> #include <chrono> #include <cstring> #include <iostream> +#include <iterator> #include <sstream> #include <utility> @@ -12,6 +14,7 @@ #include "cmsys/Glob.hxx" #include "cmsys/RegularExpression.hxx" +#include "cmAlgorithms.h" #include "cmCTest.h" #include "cmDuration.h" #include "cmSystemTools.h" @@ -162,12 +165,13 @@ int cmCTestMemCheckHandler::PostProcessHandler() void cmCTestMemCheckHandler::GenerateTestCommand( std::vector<std::string>& args, int test) { - std::string index; - std::ostringstream stream; + std::string index = std::to_string(test); std::string memcheckcommand = cmSystemTools::ConvertToOutputPath(this->MemoryTester); - stream << test; - index = stream.str(); + + std::vector<std::string> dirs; + bool nextArgIsDir = false; + for (std::string arg : this->MemoryTesterDynamicOptions) { std::string::size_type pos = arg.find("??"); if (pos != std::string::npos) { @@ -177,6 +181,16 @@ void cmCTestMemCheckHandler::GenerateTestCommand( memcheckcommand += " \""; memcheckcommand += arg; memcheckcommand += "\""; + + if (nextArgIsDir) { + nextArgIsDir = false; + dirs.push_back(arg); + } + + if (this->MemoryTesterStyle == cmCTestMemCheckHandler::DRMEMORY && + (arg == "-logdir" || arg == "-symcache_dir")) { + nextArgIsDir = true; + } } // Create a copy of the memory tester environment variable. // This is used for memory testing programs that pass options @@ -208,6 +222,11 @@ void cmCTestMemCheckHandler::GenerateTestCommand( memcheckcommand += " " + memTesterEnvironmentVariable; args.push_back(memTesterEnvironmentVariable); } + + for (std::string const& dir : dirs) { + cmSystemTools::MakeDirectory(dir); + } + cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT, "Memory check command: " << memcheckcommand << std::endl, this->Quiet); @@ -300,6 +319,9 @@ void cmCTestMemCheckHandler::GenerateDartOutput(cmXMLWriter& xml) case cmCTestMemCheckHandler::VALGRIND: xml.Attribute("Checker", "Valgrind"); break; + case cmCTestMemCheckHandler::DRMEMORY: + xml.Attribute("Checker", "DrMemory"); + break; case cmCTestMemCheckHandler::PURIFY: xml.Attribute("Checker", "Purify"); break; @@ -387,11 +409,11 @@ void cmCTestMemCheckHandler::GenerateDartOutput(cmXMLWriter& xml) } cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT, "MemCheck log files can be found here: " - "( * corresponds to test number)" + "(<#> corresponds to test number)" << std::endl, this->Quiet); std::string output = this->MemoryTesterOutputFile; - cmSystemTools::ReplaceString(output, "??", "*"); + cmSystemTools::ReplaceString(output, "??", "<#>"); cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT, output << std::endl, this->Quiet); cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT, @@ -437,6 +459,10 @@ bool cmCTestMemCheckHandler::InitializeMemoryChecking() if (testerName.find("valgrind") != std::string::npos || this->CTest->GetCTestConfiguration("MemoryCheckType") == "Valgrind") { this->MemoryTesterStyle = cmCTestMemCheckHandler::VALGRIND; + } else if (testerName.find("drmemory") != std::string::npos || + this->CTest->GetCTestConfiguration("MemoryCheckType") == + "DrMemory") { + this->MemoryTesterStyle = cmCTestMemCheckHandler::DRMEMORY; } else if (testerName.find("purify") != std::string::npos) { this->MemoryTesterStyle = cmCTestMemCheckHandler::PURIFY; } else if (testerName.find("BC") != std::string::npos) { @@ -453,6 +479,10 @@ bool cmCTestMemCheckHandler::InitializeMemoryChecking() this->MemoryTester = this->CTest->GetCTestConfiguration("ValgrindCommand"); this->MemoryTesterStyle = cmCTestMemCheckHandler::VALGRIND; } else if (cmSystemTools::FileExists( + this->CTest->GetCTestConfiguration("DrMemoryCommand"))) { + this->MemoryTester = this->CTest->GetCTestConfiguration("DrMemoryCommand"); + this->MemoryTesterStyle = cmCTestMemCheckHandler::DRMEMORY; + } else if (cmSystemTools::FileExists( this->CTest->GetCTestConfiguration("BoundsCheckerCommand"))) { this->MemoryTester = this->CTest->GetCTestConfiguration("BoundsCheckerCommand"); @@ -498,6 +528,8 @@ bool cmCTestMemCheckHandler::InitializeMemoryChecking() this->MemoryTesterStyle = cmCTestMemCheckHandler::BOUNDS_CHECKER; } else if (checkType == "Valgrind") { this->MemoryTesterStyle = cmCTestMemCheckHandler::VALGRIND; + } else if (checkType == "DrMemory") { + this->MemoryTesterStyle = cmCTestMemCheckHandler::DRMEMORY; } } if (this->MemoryTester.empty()) { @@ -519,6 +551,10 @@ bool cmCTestMemCheckHandler::InitializeMemoryChecking() .empty()) { memoryTesterOptions = this->CTest->GetCTestConfiguration("ValgrindCommandOptions"); + } else if (!this->CTest->GetCTestConfiguration("DrMemoryCommandOptions") + .empty()) { + memoryTesterOptions = + this->CTest->GetCTestConfiguration("DrMemoryCommandOptions"); } this->MemoryTesterOptions = cmSystemTools::ParseArguments(memoryTesterOptions); @@ -554,6 +590,64 @@ bool cmCTestMemCheckHandler::InitializeMemoryChecking() this->MemoryTesterOutputFile); break; } + case cmCTestMemCheckHandler::DRMEMORY: { + std::string tempDrMemoryDir = + this->CTest->GetBinaryDir() + "/Testing/Temporary/DrMemory"; + + if (!cmContains(this->MemoryTesterOptions, "-quiet")) { + this->MemoryTesterOptions.emplace_back("-quiet"); + } + + if (!cmContains(this->MemoryTesterOptions, "-batch")) { + this->MemoryTesterOptions.emplace_back("-batch"); + } + + this->MemoryTesterDynamicOptions.emplace_back("-logdir"); + auto logdirOption = + std::find(this->MemoryTesterOptions.begin(), + this->MemoryTesterOptions.end(), "-logdir"); + if (logdirOption == this->MemoryTesterOptions.end()) { + // No logdir found in memory tester options + std::string drMemoryLogDir = tempDrMemoryDir + "/??"; + this->MemoryTesterDynamicOptions.push_back(drMemoryLogDir); + this->MemoryTesterOutputFile = drMemoryLogDir; + } else { + // Use logdir found in memory tester options + auto logdirLocation = std::next(logdirOption); + this->MemoryTesterOutputFile = *logdirLocation; + this->MemoryTesterDynamicOptions.push_back(*logdirLocation); + this->MemoryTesterOptions.erase(logdirOption, logdirLocation + 1); + } + this->MemoryTesterOutputFile += "/*/results.txt"; + + if (std::find(this->MemoryTesterOptions.begin(), + this->MemoryTesterOptions.end(), + "-symcache_dir") == this->MemoryTesterOptions.end()) { + this->MemoryTesterDynamicOptions.emplace_back("-symcache_dir"); + std::string drMemoryCacheDir = tempDrMemoryDir + "/cache"; + this->MemoryTesterDynamicOptions.push_back(drMemoryCacheDir); + } + + if (!this->CTest->GetCTestConfiguration("MemoryCheckSuppressionFile") + .empty()) { + if (!cmSystemTools::FileExists(this->CTest->GetCTestConfiguration( + "MemoryCheckSuppressionFile"))) { + cmCTestLog(this->CTest, ERROR_MESSAGE, + "Cannot find memory checker suppression file: " + << this->CTest->GetCTestConfiguration( + "MemoryCheckSuppressionFile") + << std::endl); + return false; + } + this->MemoryTesterOptions.emplace_back("-suppress"); + this->MemoryTesterOptions.push_back( + this->CTest->GetCTestConfiguration("MemoryCheckSuppressionFile")); + } + + this->MemoryTesterOptions.emplace_back("--"); + + break; + } case cmCTestMemCheckHandler::PURIFY: { std::string outputFile; #ifdef _WIN32 @@ -667,6 +761,8 @@ bool cmCTestMemCheckHandler::ProcessMemCheckOutput(const std::string& str, switch (this->MemoryTesterStyle) { case cmCTestMemCheckHandler::VALGRIND: return this->ProcessMemCheckValgrindOutput(str, log, results); + case cmCTestMemCheckHandler::DRMEMORY: + return this->ProcessMemCheckDrMemoryOutput(str, log, results); case cmCTestMemCheckHandler::PURIFY: return this->ProcessMemCheckPurifyOutput(str, log, results); case cmCTestMemCheckHandler::ADDRESS_SANITIZER: @@ -932,6 +1028,47 @@ bool cmCTestMemCheckHandler::ProcessMemCheckValgrindOutput( return defects == 0; } +bool cmCTestMemCheckHandler::ProcessMemCheckDrMemoryOutput( + const std::string& str, std::string& log, std::vector<int>& results) +{ + std::vector<std::string> lines; + cmsys::SystemTools::Split(str, lines); + + cmsys::RegularExpression drMemoryError("^Error #[0-9]+"); + + cmsys::RegularExpression unaddressableAccess("UNADDRESSABLE ACCESS"); + cmsys::RegularExpression uninitializedRead("UNINITIALIZED READ"); + cmsys::RegularExpression invalidHeapArgument("INVALID HEAP ARGUMENT"); + cmsys::RegularExpression leak("LEAK"); + cmsys::RegularExpression handleLeak("HANDLE LEAK"); + + int defects = 0; + + std::ostringstream ostr; + for (const auto& l : lines) { + ostr << l << std::endl; + if (drMemoryError.find(l)) { + defects++; + if (unaddressableAccess.find(l)) { + results[cmCTestMemCheckHandler::UMR]++; + } else if (uninitializedRead.find(l)) { + results[cmCTestMemCheckHandler::UMR]++; + } else if (leak.find(l)) { + results[cmCTestMemCheckHandler::MLK]++; + } else if (handleLeak.find(l)) { + results[cmCTestMemCheckHandler::MLK]++; + } else if (invalidHeapArgument.find(l)) { + results[cmCTestMemCheckHandler::FMM]++; + } + } + } + + log = ostr.str(); + + this->DefectCount += defects; + return defects == 0; +} + bool cmCTestMemCheckHandler::ProcessMemCheckBoundsCheckerOutput( const std::string& str, std::string& log, std::vector<int>& results) { @@ -991,6 +1128,8 @@ void cmCTestMemCheckHandler::PostProcessTest(cmCTestTestResult& res, int test) this->Quiet); if (this->MemoryTesterStyle == cmCTestMemCheckHandler::BOUNDS_CHECKER) { this->PostProcessBoundsCheckerTest(res, test); + } else if (this->MemoryTesterStyle == cmCTestMemCheckHandler::DRMEMORY) { + this->PostProcessDrMemoryTest(res, test); } else { std::vector<std::string> files; this->TestOutputFileNames(test, files); @@ -1045,6 +1184,37 @@ void cmCTestMemCheckHandler::PostProcessBoundsCheckerTest( this->Quiet); } +void cmCTestMemCheckHandler::PostProcessDrMemoryTest( + cmCTestTestHandler::cmCTestTestResult& res, int test) +{ + std::string drMemoryLogDir = this->MemoryTesterOutputFile.substr( + 0, this->MemoryTesterOutputFile.find("/*/results.txt")); + + // replace placeholder of test + std::string::size_type pos = drMemoryLogDir.find("??"); + if (pos != std::string::npos) { + drMemoryLogDir.replace(pos, 2, std::to_string(test)); + } + + cmsys::Glob g; + g.FindFiles(drMemoryLogDir + "/resfile.*"); + const std::vector<std::string>& files = g.GetFiles(); + + for (const std::string& f : files) { + cmsys::ifstream ifs(f.c_str()); + if (!ifs) { + std::string log = "Cannot read memory tester output file: " + f; + cmCTestLog(this->CTest, ERROR_MESSAGE, log << std::endl); + return; + } + std::string resultFileLocation; + cmSystemTools::GetLineFromStream(ifs, resultFileLocation); + this->AppendMemTesterOutput(res, resultFileLocation); + ifs.close(); + cmSystemTools::RemoveFile(f); + } +} + void cmCTestMemCheckHandler::AppendMemTesterOutput(cmCTestTestResult& res, std::string const& ofile) { diff --git a/Source/CTest/cmCTestMemCheckHandler.h b/Source/CTest/cmCTestMemCheckHandler.h index eda65f7..52667f8 100644 --- a/Source/CTest/cmCTestMemCheckHandler.h +++ b/Source/CTest/cmCTestMemCheckHandler.h @@ -43,6 +43,7 @@ private: UNKNOWN = 0, VALGRIND, PURIFY, + DRMEMORY, BOUNDS_CHECKER, // checkers after here do not use the standard error list ADDRESS_SANITIZER, @@ -132,6 +133,8 @@ private: std::vector<int>& results); bool ProcessMemCheckValgrindOutput(const std::string& str, std::string& log, std::vector<int>& results); + bool ProcessMemCheckDrMemoryOutput(const std::string& str, std::string& log, + std::vector<int>& results); bool ProcessMemCheckPurifyOutput(const std::string& str, std::string& log, std::vector<int>& results); bool ProcessMemCheckSanitizerOutput(const std::string& str, std::string& log, @@ -142,6 +145,7 @@ private: void PostProcessTest(cmCTestTestResult& res, int test); void PostProcessBoundsCheckerTest(cmCTestTestResult& res, int test); + void PostProcessDrMemoryTest(cmCTestTestResult& res, int test); //! append MemoryTesterOutputFile to the test log void AppendMemTesterOutput(cmCTestTestHandler::cmCTestTestResult& res, diff --git a/Source/CTest/cmCTestMultiProcessHandler.cxx b/Source/CTest/cmCTestMultiProcessHandler.cxx index 02d396e..37679b9 100644 --- a/Source/CTest/cmCTestMultiProcessHandler.cxx +++ b/Source/CTest/cmCTestMultiProcessHandler.cxx @@ -19,6 +19,8 @@ #include <utility> #include <vector> +#include <cmext/algorithm> + #include "cmsys/FStream.hxx" #include "cmsys/SystemInformation.hxx" @@ -171,9 +173,9 @@ bool cmCTestMultiProcessHandler::StartTestProcess(int test) this->RunningCount += GetProcessorsUsed(test); cmCTestRunTest* testRun = new cmCTestRunTest(*this); - if (this->CTest->GetRepeatUntilFail()) { - testRun->SetRunUntilFailOn(); - testRun->SetNumberOfRuns(this->CTest->GetTestRepeat()); + if (this->RepeatMode != cmCTest::Repeat::Never) { + testRun->SetRepeatMode(this->RepeatMode); + testRun->SetNumberOfRuns(this->RepeatCount); } testRun->SetIndex(test); testRun->SetTestProperties(this->Properties[test]); @@ -788,7 +790,7 @@ void cmCTestMultiProcessHandler::CreateParallelTestCostList() // Sort tests within each level by COST and append them to the cost list. for (TestSet const& currentSet : cmReverseRange(priorityStack)) { TestList sortedCopy; - cmAppend(sortedCopy, currentSet); + cm::append(sortedCopy, currentSet); std::stable_sort(sortedCopy.begin(), sortedCopy.end(), TestComparator(this)); @@ -1154,7 +1156,7 @@ static Json::Value DumpCTestInfo( const std::vector<std::string>& args = testRun.GetArguments(); if (!args.empty()) { commandAndArgs.reserve(args.size() + 1); - cmAppend(commandAndArgs, args); + cm::append(commandAndArgs, args); } testInfo["command"] = DumpToJsonArray(commandAndArgs); } diff --git a/Source/CTest/cmCTestMultiProcessHandler.h b/Source/CTest/cmCTestMultiProcessHandler.h index 1db4bfd..4837401 100644 --- a/Source/CTest/cmCTestMultiProcessHandler.h +++ b/Source/CTest/cmCTestMultiProcessHandler.h @@ -14,11 +14,11 @@ #include "cm_uv.h" +#include "cmCTest.h" #include "cmCTestResourceAllocator.h" #include "cmCTestTestHandler.h" #include "cmUVHandlePtr.h" -class cmCTest; struct cmCTestBinPackerAllocation; class cmCTestResourceSpec; class cmCTestRunTest; @@ -85,6 +85,12 @@ public: cmCTestTestHandler* GetTestHandler() { return this->TestHandler; } + void SetRepeatMode(cmCTest::Repeat mode, int count) + { + this->RepeatMode = mode; + this->RepeatCount = count; + } + void SetQuiet(bool b) { this->Quiet = b; } void InitResourceAllocator(const cmCTestResourceSpec& spec) @@ -179,6 +185,8 @@ protected: cmCTestTestHandler* TestHandler; cmCTest* CTest; bool HasCycles; + cmCTest::Repeat RepeatMode = cmCTest::Repeat::Never; + int RepeatCount = 1; bool Quiet; bool SerialTestRunning; }; diff --git a/Source/CTest/cmCTestP4.cxx b/Source/CTest/cmCTestP4.cxx index e2063e1..1375be4 100644 --- a/Source/CTest/cmCTestP4.cxx +++ b/Source/CTest/cmCTestP4.cxx @@ -7,9 +7,10 @@ #include <ostream> #include <utility> +#include <cmext/algorithm> + #include "cmsys/RegularExpression.hxx" -#include "cmAlgorithms.h" #include "cmCTest.h" #include "cmCTestVC.h" #include "cmProcessTools.h" @@ -326,7 +327,7 @@ void cmCTestP4::SetP4Options(std::vector<char const*>& CommandOptions) // The CTEST_P4_OPTIONS variable adds additional Perforce command line // options before the main command std::string opts = this->CTest->GetCTestConfiguration("P4Options"); - cmAppend(P4Options, cmSystemTools::ParseArguments(opts)); + cm::append(P4Options, cmSystemTools::ParseArguments(opts)); } CommandOptions.clear(); diff --git a/Source/CTest/cmCTestRunTest.cxx b/Source/CTest/cmCTestRunTest.cxx index 3091050..cc5de43 100644 --- a/Source/CTest/cmCTestRunTest.cxx +++ b/Source/CTest/cmCTestRunTest.cxx @@ -34,9 +34,6 @@ cmCTestRunTest::cmCTestRunTest(cmCTestMultiProcessHandler& multiHandler) this->TestResult.Status = cmCTestTestHandler::NOT_RUN; this->TestResult.TestCount = 0; this->TestResult.Properties = nullptr; - this->NumberOfRunsLeft = 1; // default to 1 run of the test - this->RunUntilFail = false; // default to run the test once - this->RunAgain = false; // default to not having to run again } void cmCTestRunTest::CheckOutput(std::string const& line) @@ -310,7 +307,7 @@ bool cmCTestRunTest::EndTest(size_t completed, size_t total, bool started) } // If the test does not need to rerun push the current TestResult onto the // TestHandler vector - if (!this->NeedsToRerun()) { + if (!this->NeedsToRepeat()) { this->TestHandler->TestResults.push_back(this->TestResult); } this->TestProcess.reset(); @@ -336,17 +333,21 @@ bool cmCTestRunTest::StartAgain(size_t completed) return true; } -bool cmCTestRunTest::NeedsToRerun() +bool cmCTestRunTest::NeedsToRepeat() { this->NumberOfRunsLeft--; if (this->NumberOfRunsLeft == 0) { return false; } // if number of runs left is not 0, and we are running until - // we find a failed test, then return true so the test can be + // we find a failed (or passed) test, then return true so the test can be // restarted - if (this->RunUntilFail && - this->TestResult.Status == cmCTestTestHandler::COMPLETED) { + if ((this->RepeatMode == cmCTest::Repeat::UntilFail && + this->TestResult.Status == cmCTestTestHandler::COMPLETED) || + (this->RepeatMode == cmCTest::Repeat::UntilPass && + this->TestResult.Status != cmCTestTestHandler::COMPLETED) || + (this->RepeatMode == cmCTest::Repeat::AfterTimeout && + this->TestResult.Status == cmCTestTestHandler::TIMEOUT)) { this->RunAgain = true; return true; } @@ -746,7 +747,12 @@ void cmCTestRunTest::WriteLogOutputTop(size_t completed, size_t total) // then it will never print out the completed / total, same would // got for run until pass. Trick is when this is called we don't // yet know if we are passing or failing. - if (this->NumberOfRunsLeft == 1 || this->CTest->GetTestProgressOutput()) { + bool const progressOnLast = + (this->RepeatMode != cmCTest::Repeat::UntilPass && + this->RepeatMode != cmCTest::Repeat::AfterTimeout); + if ((progressOnLast && this->NumberOfRunsLeft == 1) || + (!progressOnLast && this->NumberOfRunsLeft == this->NumberOfRunsTotal) || + this->CTest->GetTestProgressOutput()) { outputStream << std::setw(getNumWidth(total)) << completed << "/"; outputStream << std::setw(getNumWidth(total)) << total << " "; } diff --git a/Source/CTest/cmCTestRunTest.h b/Source/CTest/cmCTestRunTest.h index f781c7a..7eeaebd 100644 --- a/Source/CTest/cmCTestRunTest.h +++ b/Source/CTest/cmCTestRunTest.h @@ -13,13 +13,12 @@ #include <stddef.h> +#include "cmCTest.h" #include "cmCTestMultiProcessHandler.h" #include "cmCTestTestHandler.h" #include "cmDuration.h" #include "cmProcess.h" -class cmCTest; - /** \class cmRunTest * \brief represents a single test to be run * @@ -30,8 +29,13 @@ class cmCTestRunTest public: explicit cmCTestRunTest(cmCTestMultiProcessHandler& multiHandler); - void SetNumberOfRuns(int n) { this->NumberOfRunsLeft = n; } - void SetRunUntilFailOn() { this->RunUntilFail = true; } + void SetNumberOfRuns(int n) + { + this->NumberOfRunsLeft = n; + this->NumberOfRunsTotal = n; + } + + void SetRepeatMode(cmCTest::Repeat r) { this->RepeatMode = r; } void SetTestProperties(cmCTestTestHandler::cmCTestTestProperties* prop) { this->TestProperties = prop; @@ -98,7 +102,7 @@ public: } private: - bool NeedsToRerun(); + bool NeedsToRepeat(); void DartProcessing(); void ExeNotFound(std::string exe); bool ForkProcess(cmDuration testTimeOut, bool explicitTimeout, @@ -132,9 +136,10 @@ private: std::vector<std::map< std::string, std::vector<cmCTestMultiProcessHandler::ResourceAllocation>>> AllocatedResources; - bool RunUntilFail; - int NumberOfRunsLeft; - bool RunAgain; + cmCTest::Repeat RepeatMode = cmCTest::Repeat::Never; + int NumberOfRunsLeft = 1; // default to 1 run of the test + int NumberOfRunsTotal = 1; // default to 1 run of the test + bool RunAgain = false; // default to not having to run again size_t TotalNumberOfTests; }; diff --git a/Source/CTest/cmCTestSVN.cxx b/Source/CTest/cmCTestSVN.cxx index 34395c9..44dfab2 100644 --- a/Source/CTest/cmCTestSVN.cxx +++ b/Source/CTest/cmCTestSVN.cxx @@ -7,9 +7,10 @@ #include <map> #include <ostream> +#include <cmext/algorithm> + #include "cmsys/RegularExpression.hxx" -#include "cmAlgorithms.h" #include "cmCTest.h" #include "cmCTestVC.h" #include "cmProcessTools.h" @@ -271,7 +272,7 @@ bool cmCTestSVN::RunSVNCommand(std::vector<char const*> const& parameters, std::vector<char const*> args; args.push_back(this->CommandLineTool.c_str()); - cmAppend(args, parameters); + cm::append(args, parameters); args.push_back("--non-interactive"); std::string userOptions = this->CTest->GetCTestConfiguration("SVNOptions"); @@ -344,7 +345,7 @@ private: void CharacterDataHandler(const char* data, int length) override { - cmAppend(this->CData, data, data + length); + cm::append(this->CData, data, data + length); } void EndElement(const std::string& name) override diff --git a/Source/CTest/cmCTestScriptHandler.cxx b/Source/CTest/cmCTestScriptHandler.cxx index 60facbd..7803e37 100644 --- a/Source/CTest/cmCTestScriptHandler.cxx +++ b/Source/CTest/cmCTestScriptHandler.cxx @@ -340,6 +340,13 @@ int cmCTestScriptHandler::ReadInScript(const std::string& total_script_arg) this->SetRunCurrentScript(true); this->UpdateElapsedTime(); + // set the CTEST_CONFIGURATION_TYPE variable to the current value of the + // the -C argument on the command line. + if (!this->CTest->GetConfigType().empty()) { + this->Makefile->AddDefinition("CTEST_CONFIGURATION_TYPE", + this->CTest->GetConfigType()); + } + // add the script arg if defined if (!script_arg.empty()) { this->Makefile->AddDefinition("CTEST_SCRIPT_ARG", script_arg); diff --git a/Source/CTest/cmCTestSubmitHandler.cxx b/Source/CTest/cmCTestSubmitHandler.cxx index 2ac5af6..a8f201a 100644 --- a/Source/CTest/cmCTestSubmitHandler.cxx +++ b/Source/CTest/cmCTestSubmitHandler.cxx @@ -7,6 +7,8 @@ #include <cstdlib> #include <sstream> +#include <cmext/algorithm> + #include "cm_curl.h" #include "cm_jsoncpp_reader.h" #include "cm_jsoncpp_value.h" @@ -65,7 +67,7 @@ private: void CharacterDataHandler(const char* data, int length) override { - cmAppend(this->CurrentValue, data, data + length); + cm::append(this->CurrentValue, data, data + length); } void EndElement(const std::string& name) override @@ -96,8 +98,8 @@ static size_t cmCTestSubmitHandlerWriteMemoryCallback(void* ptr, size_t size, { int realsize = static_cast<int>(size * nmemb); const char* chPtr = static_cast<char*>(ptr); - cmAppend(*static_cast<cmCTestSubmitHandlerVectorOfChar*>(data), chPtr, - chPtr + realsize); + cm::append(*static_cast<cmCTestSubmitHandlerVectorOfChar*>(data), chPtr, + chPtr + realsize); return realsize; } @@ -106,8 +108,8 @@ static size_t cmCTestSubmitHandlerCurlDebugCallback(CURL* /*unused*/, char* chPtr, size_t size, void* data) { - cmAppend(*static_cast<cmCTestSubmitHandlerVectorOfChar*>(data), chPtr, - chPtr + size); + cm::append(*static_cast<cmCTestSubmitHandlerVectorOfChar*>(data), chPtr, + chPtr + size); return size; } @@ -768,7 +770,7 @@ int cmCTestSubmitHandler::ProcessHandler() if (!this->Files.empty()) { // Submit the explicitly selected files: - cmAppend(files, this->Files); + cm::append(files, this->Files); } // Add to the list of files to submit from any selected, existing parts: @@ -814,7 +816,7 @@ int cmCTestSubmitHandler::ProcessHandler() } // Submit files from this part. - cmAppend(files, this->CTest->GetSubmitFiles(p)); + cm::append(files, this->CTest->GetSubmitFiles(p)); } // Make sure files are unique, but preserve order. diff --git a/Source/CTest/cmCTestTestCommand.cxx b/Source/CTest/cmCTestTestCommand.cxx index 9784214..0f9b695 100644 --- a/Source/CTest/cmCTestTestCommand.cxx +++ b/Source/CTest/cmCTestTestCommand.cxx @@ -29,6 +29,7 @@ void cmCTestTestCommand::BindArguments() this->Bind("EXCLUDE_FIXTURE_SETUP"_s, this->ExcludeFixtureSetup); this->Bind("EXCLUDE_FIXTURE_CLEANUP"_s, this->ExcludeFixtureCleanup); this->Bind("PARALLEL_LEVEL"_s, this->ParallelLevel); + this->Bind("REPEAT"_s, this->Repeat); this->Bind("SCHEDULE_RANDOM"_s, this->ScheduleRandom); this->Bind("STOP_TIME"_s, this->StopTime); this->Bind("TEST_LOAD"_s, this->TestLoad); @@ -85,6 +86,9 @@ cmCTestGenericHandler* cmCTestTestCommand::InitializeHandler() if (!this->ParallelLevel.empty()) { handler->SetOption("ParallelLevel", this->ParallelLevel.c_str()); } + if (!this->Repeat.empty()) { + handler->SetOption("Repeat", this->Repeat.c_str()); + } if (!this->ScheduleRandom.empty()) { handler->SetOption("ScheduleRandom", this->ScheduleRandom.c_str()); } diff --git a/Source/CTest/cmCTestTestCommand.h b/Source/CTest/cmCTestTestCommand.h index 4019694..2345afb 100644 --- a/Source/CTest/cmCTestTestCommand.h +++ b/Source/CTest/cmCTestTestCommand.h @@ -55,6 +55,7 @@ protected: std::string ExcludeFixtureSetup; std::string ExcludeFixtureCleanup; std::string ParallelLevel; + std::string Repeat; std::string ScheduleRandom; std::string StopTime; std::string TestLoad; diff --git a/Source/CTest/cmCTestTestHandler.cxx b/Source/CTest/cmCTestTestHandler.cxx index 8e3ac22..37c7154 100644 --- a/Source/CTest/cmCTestTestHandler.cxx +++ b/Source/CTest/cmCTestTestHandler.cxx @@ -471,6 +471,30 @@ bool cmCTestTestHandler::ProcessOptions() if (cmIsOn(this->GetOption("ScheduleRandom"))) { this->CTest->SetScheduleType("Random"); } + if (const char* repeat = this->GetOption("Repeat")) { + cmsys::RegularExpression repeatRegex( + "^(UNTIL_FAIL|UNTIL_PASS|AFTER_TIMEOUT):([0-9]+)$"); + if (repeatRegex.find(repeat)) { + std::string const& count = repeatRegex.match(2); + unsigned long n = 1; + cmStrToULong(count, &n); // regex guarantees success + this->RepeatCount = static_cast<int>(n); + if (this->RepeatCount > 1) { + std::string const& mode = repeatRegex.match(1); + if (mode == "UNTIL_FAIL") { + this->RepeatMode = cmCTest::Repeat::UntilFail; + } else if (mode == "UNTIL_PASS") { + this->RepeatMode = cmCTest::Repeat::UntilPass; + } else if (mode == "AFTER_TIMEOUT") { + this->RepeatMode = cmCTest::Repeat::AfterTimeout; + } + } + } else { + cmCTestLog(this->CTest, ERROR_MESSAGE, + "Repeat option invalid value: " << repeat << std::endl); + return false; + } + } if (this->GetOption("ParallelLevel")) { this->CTest->SetParallelLevel(atoi(this->GetOption("ParallelLevel"))); } @@ -1231,6 +1255,12 @@ void cmCTestTestHandler::ProcessDirectory(std::vector<std::string>& passed, parallel->SetCTest(this->CTest); parallel->SetParallelLevel(this->CTest->GetParallelLevel()); parallel->SetTestHandler(this); + if (this->RepeatMode != cmCTest::Repeat::Never) { + parallel->SetRepeatMode(this->RepeatMode, this->RepeatCount); + } else { + parallel->SetRepeatMode(this->CTest->GetRepeatMode(), + this->CTest->GetRepeatCount()); + } parallel->SetQuiet(this->Quiet); if (this->TestLoad > 0) { parallel->SetTestLoad(this->TestLoad); diff --git a/Source/CTest/cmCTestTestHandler.h b/Source/CTest/cmCTestTestHandler.h index eab75d0..55237f9 100644 --- a/Source/CTest/cmCTestTestHandler.h +++ b/Source/CTest/cmCTestTestHandler.h @@ -18,12 +18,12 @@ #include "cmsys/RegularExpression.hxx" +#include "cmCTest.h" #include "cmCTestGenericHandler.h" #include "cmCTestResourceSpec.h" #include "cmDuration.h" #include "cmListFileCache.h" -class cmCTest; class cmMakefile; class cmXMLWriter; @@ -353,6 +353,8 @@ private: std::ostream* LogFile; + cmCTest::Repeat RepeatMode = cmCTest::Repeat::Never; + int RepeatCount = 1; bool RerunFailed; }; diff --git a/Source/CTest/cmProcess.cxx b/Source/CTest/cmProcess.cxx index 87f7147..2ec9622 100644 --- a/Source/CTest/cmProcess.cxx +++ b/Source/CTest/cmProcess.cxx @@ -6,9 +6,10 @@ #include <iostream> #include <string> +#include <cmext/algorithm> + #include "cmsys/Process.h" -#include "cmAlgorithms.h" #include "cmCTest.h" #include "cmCTestRunTest.h" #include "cmCTestTestHandler.h" @@ -218,7 +219,7 @@ void cmProcess::OnRead(ssize_t nread, const uv_buf_t* buf) if (nread > 0) { std::string strdata; this->Conv.DecodeText(buf->base, static_cast<size_t>(nread), strdata); - cmAppend(this->Output, strdata); + cm::append(this->Output, strdata); while (this->Output.GetLine(line)) { this->Runner.CheckOutput(line); diff --git a/Source/Checks/Curses.cmake b/Source/Checks/Curses.cmake index 2942b66..d35dd2a 100644 --- a/Source/Checks/Curses.cmake +++ b/Source/Checks/Curses.cmake @@ -1,4 +1,7 @@ -message(STATUS "Checking for curses support") +include(${CMAKE_CURRENT_LIST_DIR}/cm_message_checks_compat.cmake) +cm_message_checks_compat( + "Checking for curses support" __checkStart __checkPass __checkFail) +message(${__checkStart}) # Try compiling a simple project using curses. # Pass in any cache entries that the user may have set. @@ -31,11 +34,11 @@ set(CMakeCheckCurses_COMPILED "${CMakeCheckCurses_COMPILED}") unset(CMakeCheckCurses_COMPILED CACHE) if(CMakeCheckCurses_COMPILED) - message(STATUS "Checking for curses support - Success") + message(${__checkPass} "Success") file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log "Checking for curses support passed with the following output:\n${CMakeCheckCurses_OUTPUT}\n\n") else() - message(STATUS "Checking for curses support - Failed") + message(${__checkFail} "Failed") file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log "Checking for curses support failed with the following output:\n${CMakeCheckCurses_OUTPUT}\n\n") endif() diff --git a/Source/Checks/cm_c11_thread_local.cmake b/Source/Checks/cm_c11_thread_local.cmake index 6b8d10b..2263be3 100644 --- a/Source/Checks/cm_c11_thread_local.cmake +++ b/Source/Checks/cm_c11_thread_local.cmake @@ -1,7 +1,11 @@ set(CMake_C11_THREAD_LOCAL_BROKEN 0) if(CMAKE_CXX_COMPILER_ID MATCHES "GNU" AND CMAKE_C11_STANDARD_COMPILE_OPTION) if(NOT DEFINED CMake_C11_THREAD_LOCAL_WORKS) - message(STATUS "Checking if compiler supports C11 _Thread_local") + include(${CMAKE_CURRENT_LIST_DIR}/cm_message_checks_compat.cmake) + cm_message_checks_compat( + "Checking if compiler supports C11 _Thread_local" + __checkStart __checkPass __checkFail) + message(${__checkStart}) try_compile(CMake_C11_THREAD_LOCAL_WORKS ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_LIST_DIR}/cm_c11_thread_local.c @@ -12,14 +16,14 @@ if(CMAKE_CXX_COMPILER_ID MATCHES "GNU" AND CMAKE_C11_STANDARD_COMPILE_OPTION) set_property(CACHE CMake_C11_THREAD_LOCAL_WORKS PROPERTY VALUE 0) endif() if(CMake_C11_THREAD_LOCAL_WORKS) - message(STATUS "Checking if compiler supports C11 _Thread_local - yes") + message(${__checkPass} "yes") file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log "Determining if compiler supports C11 _Thread_local passed with the following output:\n" "${OUTPUT}\n" "\n" ) else() - message(STATUS "Checking if compiler supports C11 _Thread_local - no") + message(${__checkFail} "no") file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log "Determining if compiler supports C11 _Thread_local failed with the following output:\n" "${OUTPUT}\n" diff --git a/Source/Checks/cm_cxx14_check.cmake b/Source/Checks/cm_cxx14_check.cmake index 38606b9..e5656bf 100644 --- a/Source/Checks/cm_cxx14_check.cmake +++ b/Source/Checks/cm_cxx14_check.cmake @@ -1,10 +1,14 @@ set(CMake_CXX14_BROKEN 0) -if(CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang|PGI") +if(CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang|PGI|Intel") if(NOT CMAKE_CXX14_STANDARD_COMPILE_OPTION) set(CMake_CXX14_WORKS 0) endif() if(NOT DEFINED CMake_CXX14_WORKS) - message(STATUS "Checking if compiler supports needed C++14 constructs") + include(${CMAKE_CURRENT_LIST_DIR}/cm_message_checks_compat.cmake) + cm_message_checks_compat( + "Checking if compiler supports needed C++14 constructs" + __checkStart __checkPass __checkFail) + message(${__checkStart}) try_compile(CMake_CXX14_WORKS ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_LIST_DIR}/cm_cxx14_check.cpp @@ -15,14 +19,14 @@ if(CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang|PGI") set_property(CACHE CMake_CXX14_WORKS PROPERTY VALUE 0) endif() if(CMake_CXX14_WORKS) - message(STATUS "Checking if compiler supports needed C++14 constructs - yes") + message(${__checkPass} "yes") file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log "Determining if compiler supports needed C++14 constructs passed with the following output:\n" "${OUTPUT}\n" "\n" ) else() - message(STATUS "Checking if compiler supports needed C++14 constructs - no") + message(${__checkFail} "no") file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log "Determining if compiler supports needed C++14 constructs failed with the following output:\n" "${OUTPUT}\n" diff --git a/Source/Checks/cm_cxx17_check.cmake b/Source/Checks/cm_cxx17_check.cmake index 4da2fd7..dba3eaf 100644 --- a/Source/Checks/cm_cxx17_check.cmake +++ b/Source/Checks/cm_cxx17_check.cmake @@ -1,10 +1,14 @@ set(CMake_CXX17_BROKEN 0) -if(CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang|PGI") +if(CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang|PGI|Intel") if(NOT CMAKE_CXX17_STANDARD_COMPILE_OPTION) set(CMake_CXX17_WORKS 0) endif() if(NOT DEFINED CMake_CXX17_WORKS) - message(STATUS "Checking if compiler supports needed C++17 constructs") + include(${CMAKE_CURRENT_LIST_DIR}/cm_message_checks_compat.cmake) + cm_message_checks_compat( + "Checking if compiler supports needed C++17 constructs" + __checkStart __checkPass __checkFail) + message(${__checkStart}) try_compile(CMake_CXX17_WORKS ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_LIST_DIR}/cm_cxx17_check.cpp @@ -15,14 +19,14 @@ if(CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang|PGI") set_property(CACHE CMake_CXX17_WORKS PROPERTY VALUE 0) endif() if(CMake_CXX17_WORKS) - message(STATUS "Checking if compiler supports needed C++17 constructs - yes") + message(${__checkPass} "yes") file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log "Determining if compiler supports needed C++17 constructs passed with the following output:\n" "${OUTPUT}\n" "\n" ) else() - message(STATUS "Checking if compiler supports needed C++17 constructs - no") + message(${__checkFail} "no") file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log "Determining if compiler supports needed C++17 constructs failed with the following output:\n" "${OUTPUT}\n" diff --git a/Source/Checks/cm_cxx17_check.cpp b/Source/Checks/cm_cxx17_check.cpp index 29863b1..abbe22c 100644 --- a/Source/Checks/cm_cxx17_check.cpp +++ b/Source/Checks/cm_cxx17_check.cpp @@ -8,6 +8,13 @@ # include <comdef.h> #endif +template <typename T, + typename std::invoke_result<decltype(&T::get), T>::type = nullptr> +typename T::pointer get_ptr(T& item) +{ + return item.get(); +} + int main() { int a[] = { 0, 1, 2 }; @@ -20,6 +27,9 @@ int main() std::unique_ptr<int> u(new int(0)); + // Intel compiler do not handle correctly 'decltype' inside 'invoke_result' + get_ptr(u); + #ifdef _MSC_VER // clang-cl has problems instantiating this constructor in C++17 mode // error: indirection requires pointer operand ('const _GUID' invalid) diff --git a/Source/Checks/cm_cxx_features.cmake b/Source/Checks/cm_cxx_features.cmake index fb68ed7..3b00dfb 100644 --- a/Source/Checks/cm_cxx_features.cmake +++ b/Source/Checks/cm_cxx_features.cmake @@ -1,8 +1,12 @@ +include(${CMAKE_CURRENT_LIST_DIR}/cm_message_checks_compat.cmake) function(cm_check_cxx_feature name) string(TOUPPER ${name} FEATURE) if(NOT DEFINED CMake_HAVE_CXX_${FEATURE}) - message(STATUS "Checking if compiler supports C++ ${name}") + cm_message_checks_compat( + "Checking if compiler supports C++ ${name}" + __checkStart __checkPass __checkFail) + message(${__checkStart}) if(CMAKE_CXX_STANDARD) set(maybe_cxx_standard -DCMAKE_CXX_STANDARD=${CMAKE_CXX_STANDARD}) else() @@ -26,19 +30,21 @@ function(cm_check_cxx_feature name) string(REGEX REPLACE "[^\n]*warning:[^\n]*sprintf\\(\\) is often misused, please use snprintf[^\n]*" "" check_output "${check_output}") # Filter out xcodebuild warnings. string(REGEX REPLACE "[^\n]* xcodebuild\\[[0-9]*:[0-9]*\\] warning: [^\n]*" "" check_output "${check_output}") + # Filter out ld warnings. + string(REGEX REPLACE "[^\n]*ld: warning: [^\n]*" "" check_output "${check_output}") # If using the feature causes warnings, treat it as broken/unavailable. if(check_output MATCHES "(^|[ :])[Ww][Aa][Rr][Nn][Ii][Nn][Gg]") set(CMake_HAVE_CXX_${FEATURE} OFF CACHE INTERNAL "TRY_COMPILE" FORCE) endif() if(CMake_HAVE_CXX_${FEATURE}) - message(STATUS "Checking if compiler supports C++ ${name} - yes") + message(${__checkPass} "yes") file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log "Determining if compiler supports C++ ${name} passed with the following output:\n" "${OUTPUT}\n" "\n" ) else() - message(STATUS "Checking if compiler supports C++ ${name} - no") + message(${__checkFail} "no") file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log "Determining if compiler supports C++ ${name} failed with the following output:\n" "${OUTPUT}\n" diff --git a/Source/Checks/cm_message_checks_compat.cmake b/Source/Checks/cm_message_checks_compat.cmake new file mode 100644 index 0000000..024c397 --- /dev/null +++ b/Source/Checks/cm_message_checks_compat.cmake @@ -0,0 +1,13 @@ +# Supporting using the CHECK_... message modes if available +# and fall back to the older behavior if not +macro(cm_message_checks_compat description startVar passVar failVar) + if(CMAKE_VERSION VERSION_GREATER 3.16.2019) + set(${startVar} CHECK_START "${description}") + set(${passVar} CHECK_PASS) + set(${failVar} CHECK_FAIL) + else() + set(${startVar} STATUS "${description}") + set(${passVar} STATUS "${description} - ") + set(${failVar} STATUS "${description} - ") + endif() +endmacro() diff --git a/Source/CursesDialog/CMakeLists.txt b/Source/CursesDialog/CMakeLists.txt index 7009717..c24ee76 100644 --- a/Source/CursesDialog/CMakeLists.txt +++ b/Source/CursesDialog/CMakeLists.txt @@ -5,6 +5,7 @@ add_executable(ccmake ccmake.cxx cmCursesBoolWidget.cxx cmCursesCacheEntryComposite.cxx + cmCursesColor.cxx cmCursesDummyWidget.cxx cmCursesFilePathWidget.cxx cmCursesForm.cxx @@ -17,21 +18,45 @@ add_executable(ccmake cmCursesWidget.cxx ) target_include_directories(ccmake PRIVATE ${CURSES_INCLUDE_PATH}) +set(CMAKE_REQUIRED_INCLUDES ${CURSES_INCLUDE_PATH}) target_link_libraries(ccmake CMakeLib) if(CMAKE_USE_SYSTEM_FORM) find_path(CURSES_FORM_INCLUDE_DIR NAMES form.h HINTS ${CURSES_INCLUDE_PATH} ${CURSES_INCLUDE_PATH}/ncurses) if(CURSES_FORM_INCLUDE_DIR) target_include_directories(ccmake PRIVATE ${CURSES_FORM_INCLUDE_DIR}) + list(APPEND CMAKE_REQUIRED_INCLUDES ${CURSES_FORM_INCLUDE_DIR}) endif() target_link_libraries(ccmake ${CURSES_FORM_LIBRARY} ${CURSES_LIBRARY} ) + set(CMAKE_REQUIRED_LIBRARIES + ${CURSES_FORM_LIBRARY} + ${CURSES_LIBRARY} + ) if(CURSES_EXTRA_LIBRARY) target_link_libraries(ccmake ${CURSES_EXTRA_LIBRARY}) + list(APPEND CMAKE_REQUIRED_LIBRARIES ${CURSES_EXTRA_LIBRARY}) endif() else() target_link_libraries(ccmake cmForm) + get_target_property(cmFormIncludeDirs cmForm INTERFACE_INCLUDE_DIRECTORIES) + list(APPEND CMAKE_REQUIRED_INCLUDES ${cmFormIncludeDirs}) + get_target_property(cmFormLibraries cmForm INTERFACE_LINK_LIBRARIES) + set(CMAKE_REQUIRED_LIBRARIES ${cmFormLibraries}) +endif() + +include(CheckSymbolExists) +check_symbol_exists(use_default_colors + "form.h" + HAVE_CURSES_USE_DEFAULT_COLORS) +if(HAVE_CURSES_USE_DEFAULT_COLORS) + set_source_files_properties(cmCursesColor.cxx + PROPERTIES COMPILE_DEFINITIONS HAVE_CURSES_USE_DEFAULT_COLORS) +endif() + +if(CMake_JOB_POOL_LINK_BIN) + set_property(TARGET ccmake PROPERTY JOB_POOL_LINK "link-bin") endif() CMake_OPTIONAL_COMPONENT(ccmake) diff --git a/Source/CursesDialog/ccmake.cxx b/Source/CursesDialog/ccmake.cxx index 9e9dfbd..01fce85 100644 --- a/Source/CursesDialog/ccmake.cxx +++ b/Source/CursesDialog/ccmake.cxx @@ -9,6 +9,7 @@ #include "cmsys/Encoding.hxx" +#include "cmCursesColor.h" #include "cmCursesForm.h" #include "cmCursesMainForm.h" #include "cmCursesStandardIncludes.h" @@ -126,6 +127,7 @@ int main(int argc, char const* const* argv) noecho(); /* Echo off */ cbreak(); /* nl- or cr not needed */ keypad(stdscr, true); /* Use key symbols as KEY_DOWN */ + cmCursesColor::InitColors(); signal(SIGWINCH, onsig); @@ -153,10 +155,28 @@ int main(int argc, char const* const* argv) return 1; } + /* + * The message is stored in a list by the form which will be + * joined by '\n' before display. + * Removing any trailing '\n' avoid extra empty lines in the final results + */ + auto cleanMessage = [](const std::string& message) -> std::string { + auto msg = message; + if (!msg.empty() && msg.back() == '\n') { + msg.pop_back(); + } + return msg; + }; cmSystemTools::SetMessageCallback( - [myform](const std::string& message, const char* title) { - myform->AddError(message, title); + [&](const std::string& message, const char* title) { + myform->AddError(cleanMessage(message), title); }); + cmSystemTools::SetStderrCallback([&](const std::string& message) { + myform->AddError(cleanMessage(message), ""); + }); + cmSystemTools::SetStdoutCallback([&](const std::string& message) { + myform->UpdateProgress(cleanMessage(message), -1); + }); cmCursesForm::CurrentForm = myform; diff --git a/Source/CursesDialog/cmCursesBoolWidget.cxx b/Source/CursesDialog/cmCursesBoolWidget.cxx index 97b0811..c4dbed8 100644 --- a/Source/CursesDialog/cmCursesBoolWidget.cxx +++ b/Source/CursesDialog/cmCursesBoolWidget.cxx @@ -4,6 +4,7 @@ #include <string> +#include "cmCursesColor.h" #include "cmCursesWidget.h" #include "cmStateTypes.h" @@ -12,8 +13,10 @@ cmCursesBoolWidget::cmCursesBoolWidget(int width, int height, int left, : cmCursesWidget(width, height, left, top) { this->Type = cmStateEnums::BOOL; - set_field_fore(this->Field, A_NORMAL); - set_field_back(this->Field, A_STANDOUT); + if (!cmCursesColor::HasColors()) { + set_field_fore(this->Field, A_NORMAL); + set_field_back(this->Field, A_STANDOUT); + } field_opts_off(this->Field, O_STATIC); this->SetValueAsBool(false); } @@ -42,8 +45,16 @@ void cmCursesBoolWidget::SetValueAsBool(bool value) { if (value) { this->SetValue("ON"); + if (cmCursesColor::HasColors()) { + set_field_fore(this->Field, COLOR_PAIR(cmCursesColor::BoolOn)); + set_field_back(this->Field, COLOR_PAIR(cmCursesColor::BoolOn)); + } } else { this->SetValue("OFF"); + if (cmCursesColor::HasColors()) { + set_field_fore(this->Field, COLOR_PAIR(cmCursesColor::BoolOff)); + set_field_back(this->Field, COLOR_PAIR(cmCursesColor::BoolOff)); + } } } diff --git a/Source/CursesDialog/cmCursesColor.cxx b/Source/CursesDialog/cmCursesColor.cxx new file mode 100644 index 0000000..641d48c --- /dev/null +++ b/Source/CursesDialog/cmCursesColor.cxx @@ -0,0 +1,29 @@ +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing for details. */ +#include "cmCursesColor.h" + +#include "cmCursesStandardIncludes.h" + +bool cmCursesColor::HasColors() +{ +#ifdef HAVE_CURSES_USE_DEFAULT_COLORS + return has_colors(); +#else + return false; +#endif +} + +void cmCursesColor::InitColors() +{ +#ifdef HAVE_CURSES_USE_DEFAULT_COLORS + if (HasColors()) { + start_color(); + use_default_colors(); + init_pair(cmCursesColor::BoolOff, COLOR_RED, -1); + init_pair(cmCursesColor::BoolOn, COLOR_GREEN, -1); + init_pair(cmCursesColor::String, COLOR_BLUE, -1); + init_pair(cmCursesColor::Path, COLOR_YELLOW, -1); + init_pair(cmCursesColor::Options, COLOR_MAGENTA, -1); + } +#endif +} diff --git a/Source/CursesDialog/cmCursesColor.h b/Source/CursesDialog/cmCursesColor.h new file mode 100644 index 0000000..78ca52c --- /dev/null +++ b/Source/CursesDialog/cmCursesColor.h @@ -0,0 +1,24 @@ +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing for details. */ +#ifndef cmCursesColor_h +#define cmCursesColor_h + +class cmCursesColor +{ +public: + enum Color + { + // Default color is pair 0 + BoolOff = 1, + BoolOn, + String, + Path, + Options + }; + + static bool HasColors(); + + static void InitColors(); +}; + +#endif // cmCursesColor_h diff --git a/Source/CursesDialog/cmCursesLongMessageForm.cxx b/Source/CursesDialog/cmCursesLongMessageForm.cxx index e2d8d06..806e663 100644 --- a/Source/CursesDialog/cmCursesLongMessageForm.cxx +++ b/Source/CursesDialog/cmCursesLongMessageForm.cxx @@ -8,6 +8,7 @@ #include "cmCursesForm.h" #include "cmCursesMainForm.h" #include "cmCursesStandardIncludes.h" +#include "cmStringAlgorithms.h" #include "cmVersion.h" inline int ctrl(int z) @@ -16,14 +17,12 @@ inline int ctrl(int z) } cmCursesLongMessageForm::cmCursesLongMessageForm( - std::vector<std::string> const& messages, const char* title) + std::vector<std::string> const& messages, const char* title, + ScrollBehavior scrollBehavior) + : Scrolling(scrollBehavior) { // Append all messages into on big string - for (std::string const& message : messages) { - this->Messages += message; - // Add one blank line after each message - this->Messages += "\n\n"; - } + this->Messages = cmJoin(messages, "\n"); this->Title = title; this->Fields[0] = nullptr; this->Fields[1] = nullptr; @@ -48,7 +47,7 @@ void cmCursesLongMessageForm::UpdateStatusBar() size = cmCursesMainForm::MAX_WIDTH - 1; } strncpy(bar, this->Title.c_str(), size); - for (size_t i = size - 1; i < cmCursesMainForm::MAX_WIDTH; i++) { + for (size_t i = size; i < cmCursesMainForm::MAX_WIDTH; i++) { bar[i] = ' '; } int width; @@ -89,7 +88,7 @@ void cmCursesLongMessageForm::PrintKeys() return; } char firstLine[512]; - sprintf(firstLine, "Press [e] to exit help"); + sprintf(firstLine, "Press [e] to exit screen"); char fmt_s[] = "%s"; curses_move(y - 2, 0); @@ -112,8 +111,6 @@ void cmCursesLongMessageForm::Render(int /*left*/, int /*top*/, int /*width*/, const char* msg = this->Messages.c_str(); - curses_clear(); - if (this->Fields[0]) { free_field(this->Fields[0]); this->Fields[0] = nullptr; @@ -136,10 +133,13 @@ void cmCursesLongMessageForm::Render(int /*left*/, int /*top*/, int /*width*/, } i++; } - form_driver(this->Form, REQ_BEG_FIELD); + if (this->Scrolling == ScrollBehavior::ScrollDown) { + form_driver(this->Form, REQ_END_FIELD); + } else { + form_driver(this->Form, REQ_BEG_FIELD); + } this->UpdateStatusBar(); - this->PrintKeys(); touchwin(stdscr); refresh(); } @@ -153,6 +153,7 @@ void cmCursesLongMessageForm::HandleInput() char debugMessage[128]; for (;;) { + this->PrintKeys(); int key = getch(); sprintf(debugMessage, "Message widget handling input, key: %d", key); @@ -173,7 +174,6 @@ void cmCursesLongMessageForm::HandleInput() } this->UpdateStatusBar(); - this->PrintKeys(); touchwin(stdscr); wrefresh(stdscr); } diff --git a/Source/CursesDialog/cmCursesLongMessageForm.h b/Source/CursesDialog/cmCursesLongMessageForm.h index 42f9c71..88efe62 100644 --- a/Source/CursesDialog/cmCursesLongMessageForm.h +++ b/Source/CursesDialog/cmCursesLongMessageForm.h @@ -14,8 +14,14 @@ class cmCursesLongMessageForm : public cmCursesForm { public: + enum class ScrollBehavior + { + NoScroll, + ScrollDown + }; + cmCursesLongMessageForm(std::vector<std::string> const& messages, - const char* title); + const char* title, ScrollBehavior scrollBehavior); ~cmCursesLongMessageForm() override; cmCursesLongMessageForm(cmCursesLongMessageForm const&) = delete; @@ -43,6 +49,7 @@ public: protected: std::string Messages; std::string Title; + ScrollBehavior Scrolling; FIELD* Fields[2]; }; diff --git a/Source/CursesDialog/cmCursesMainForm.cxx b/Source/CursesDialog/cmCursesMainForm.cxx index 6b71e8a..2c92835 100644 --- a/Source/CursesDialog/cmCursesMainForm.cxx +++ b/Source/CursesDialog/cmCursesMainForm.cxx @@ -34,6 +34,7 @@ cmCursesMainForm::cmCursesMainForm(std::vector<std::string> args, : Args(std::move(args)) , InitialWidth(initWidth) { + this->HasNonStatusOutputs = false; this->NumberOfPages = 0; this->AdvancedMode = false; this->NumberOfVisibleEntries = 0; @@ -321,25 +322,25 @@ void cmCursesMainForm::PrintKeys(int process /* = 0 */) } else { if (this->OkToGenerate) { sprintf(firstLine, - "Press [c] to configure Press [g] to generate and exit"); + " [l] Show log output [c] Configure" + " [g] Generate "); } else { sprintf(firstLine, - "Press [c] to configure "); + " [l] Show log output [c] Configure" + " "); } { const char* toggleKeyInstruction = - "Press [t] to toggle advanced mode (Currently %s)"; + " [t] Toggle advanced mode (currently %s)"; sprintf(thirdLine, toggleKeyInstruction, - this->AdvancedMode ? "On" : "Off"); + this->AdvancedMode ? "on" : "off"); } sprintf(secondLine, - "Press [h] for help " - "Press [q] to quit without generating"); + " [h] Help [q] Quit without generating"); } curses_move(y - 4, 0); - char fmt[512] = - "Press [enter] to edit option Press [d] to delete an entry"; + char fmt[512] = "Keys: [enter] Edit an entry [d] Delete an entry"; if (process) { memset(fmt, ' ', 57); } @@ -364,7 +365,7 @@ void cmCursesMainForm::PrintKeys(int process /* = 0 */) // Print the key of the current entry and the CMake version // on the status bar. Designed for a width of 80 chars. -void cmCursesMainForm::UpdateStatusBar(const char* message) +void cmCursesMainForm::UpdateStatusBar(cm::optional<std::string> message) { int x; int y; @@ -385,119 +386,91 @@ void cmCursesMainForm::UpdateStatusBar(const char* message) return; } - // Get the key of the current entry - FIELD* cur = current_field(this->Form); - int findex = field_index(cur); - cmCursesWidget* lbl = nullptr; - if (findex >= 0) { - lbl = reinterpret_cast<cmCursesWidget*>( - field_userptr(this->Fields[findex - 2])); - } - char help[128] = ""; - const char* curField = ""; - if (lbl) { - curField = lbl->GetValue(); + // Find the current label index + // Field are grouped by 3, the label should be 2 less than the current index + using size_type = decltype(this->Fields)::size_type; + size_type currentLabelIndex = field_index(current_field(this->Form)) - 2; + + // Use the status message if any, otherwise join the key and help string + std::string bar; + if (message) { + bar = *message; + } else { + // Get the key of the current entry + cmCursesWidget* labelWidget = reinterpret_cast<cmCursesWidget*>( + field_userptr(this->Fields[currentLabelIndex])); + std::string labelValue = labelWidget->GetValue(); + bar = labelValue + ": "; // Get the help string of the current entry // and add it to the help string - const char* existingValue = - this->CMakeInstance->GetState()->GetCacheEntryValue(curField); + auto cmakeState = this->CMakeInstance->GetState(); + const char* existingValue = cmakeState->GetCacheEntryValue(labelValue); if (existingValue) { - const char* hs = this->CMakeInstance->GetState()->GetCacheEntryProperty( - curField, "HELPSTRING"); - if (hs) { - strncpy(help, hs, 127); - help[127] = '\0'; - } else { - help[0] = 0; + auto help = cmakeState->GetCacheEntryProperty(labelValue, "HELPSTRING"); + if (help) { + bar += help; } - } else { - sprintf(help, " "); } } + // Pad with spaces to erase any previous text, + // or truncate as necessary to fit the screen + bar.resize(x, ' '); + curses_move(y - 5, 0); + attron(A_STANDOUT); + char fmt_s[] = "%s"; + printw(fmt_s, bar.c_str()); + attroff(A_STANDOUT); - // Join the key, help string and pad with spaces - // (or truncate) as necessary - char bar[cmCursesMainForm::MAX_WIDTH]; - size_t curFieldLen = strlen(curField); - size_t helpLen = strlen(help); - - size_t width = std::min<size_t>(x, cmCursesMainForm::MAX_WIDTH); - - if (message) { - curField = message; - curFieldLen = strlen(message); - strncpy(bar, curField, width); - if (curFieldLen < width) { - memset(bar + curFieldLen, ' ', width - curFieldLen); - } - } else { - strncpy(bar, curField, width); - if (curFieldLen < width) { - bar[curFieldLen] = ':'; - bar[curFieldLen + 1] = ' '; - strncpy(bar + curFieldLen + 2, help, width - curFieldLen - 2); - if (curFieldLen + helpLen + 2 < width) { - memset(bar + curFieldLen + helpLen + 2, ' ', - width - (curFieldLen + helpLen + 2)); - } - } + // Highlight the current label, reset others + // Fields are grouped by 3, the first one being the label + // so start at 0 and move up by 3 avoiding the last null entry + for (size_type index = 0; index < this->Fields.size() - 1; index += 3) { + bool currentLabel = index == currentLabelIndex; + set_field_fore(this->Fields[index], currentLabel ? A_STANDOUT : A_NORMAL); } - bar[width] = '\0'; - - // Display CMake version info on the next line + // Display CMake version under the status bar // We want to display this on the right - char version[cmCursesMainForm::MAX_WIDTH]; - char vertmp[128]; - sprintf(vertmp, "CMake Version %s", cmVersion::GetCMakeVersion()); - size_t sideSpace = (width - strlen(vertmp)); - memset(version, ' ', sideSpace); - sprintf(version + sideSpace, "%s", vertmp); - version[width] = '\0'; - - // Now print both lines - char fmt_s[] = "%s"; - curses_move(y - 5, 0); - attron(A_STANDOUT); - printw(fmt_s, bar); - attroff(A_STANDOUT); - curses_move(y - 4, 0); - printw(fmt_s, version); + std::string version = "CMake Version "; + version += cmVersion::GetCMakeVersion(); + version.resize(std::min<std::string::size_type>(x, version.size())); + curses_move(y - 4, x - static_cast<int>(version.size())); + printw(fmt_s, version.c_str()); + pos_form_cursor(this->Form); } void cmCursesMainForm::UpdateProgress(const std::string& msg, float prog) { - char tmp[1024]; - const char* cmsg = tmp; if (prog >= 0) { - sprintf(tmp, "%s %i%%", msg.c_str(), static_cast<int>(100 * prog)); + constexpr int progressBarWidth = 40; + int progressBarCompleted = static_cast<int>(progressBarWidth * prog); + int percentCompleted = static_cast<int>(100 * prog); + this->LastProgress = (percentCompleted < 100 ? " " : ""); + this->LastProgress += (percentCompleted < 10 ? " " : ""); + this->LastProgress += std::to_string(percentCompleted) + "% ["; + this->LastProgress.append(progressBarCompleted, '#'); + this->LastProgress.append(progressBarWidth - progressBarCompleted, ' '); + this->LastProgress += "] " + msg + "..."; } else { - cmsg = msg.c_str(); + this->Outputs.emplace_back(msg); } - this->UpdateStatusBar(cmsg); - this->PrintKeys(1); - curses_move(1, 1); - touchwin(stdscr); - refresh(); + + this->DisplayOutputs(); } int cmCursesMainForm::Configure(int noconfigure) { - int xi; - int yi; - getmaxyx(stdscr, yi, xi); - - curses_move(1, 1); - this->UpdateStatusBar("Configuring, please wait..."); - this->PrintKeys(1); - touchwin(stdscr); - refresh(); - this->CMakeInstance->SetProgressCallback( - [this](const std::string& msg, float prog) { - this->UpdateProgress(msg, prog); - }); + this->ResetOutputs(); + + if (noconfigure == 0) { + this->UpdateProgress("Configuring", 0); + this->CMakeInstance->SetProgressCallback( + [this](const std::string& msg, float prog) { + this->UpdateProgress(msg, prog); + }); + } // always save the current gui values to disk this->FillCacheManagerFromUI(); @@ -505,9 +478,6 @@ int cmCursesMainForm::Configure(int noconfigure) this->CMakeInstance->GetHomeOutputDirectory()); this->LoadCache(nullptr); - // Get rid of previous errors - this->Errors = std::vector<std::string>(); - // run the generate process this->OkToGenerate = true; int retVal; @@ -524,7 +494,7 @@ int cmCursesMainForm::Configure(int noconfigure) keypad(stdscr, true); /* Use key symbols as KEY_DOWN */ - if (retVal != 0 || !this->Errors.empty()) { + if (retVal != 0 || this->HasNonStatusOutputs) { // see if there was an error if (cmSystemTools::GetErrorOccuredFlag()) { this->OkToGenerate = false; @@ -532,11 +502,13 @@ int cmCursesMainForm::Configure(int noconfigure) int xx; int yy; getmaxyx(stdscr, yy, xx); - cmCursesLongMessageForm* msgs = - new cmCursesLongMessageForm(this->Errors, - cmSystemTools::GetErrorOccuredFlag() - ? "Errors occurred during the last pass." - : "CMake produced the following output."); + const char* title = "Configure produced the following output"; + if (cmSystemTools::GetErrorOccuredFlag()) { + title = "Configure failed with the following output"; + } + cmCursesLongMessageForm* msgs = new cmCursesLongMessageForm( + this->Outputs, title, + cmCursesLongMessageForm::ScrollBehavior::ScrollDown); // reset error condition cmSystemTools::ResetErrorOccuredFlag(); CurrentForm = msgs; @@ -547,11 +519,13 @@ int cmCursesMainForm::Configure(int noconfigure) if (retVal == -2) { return retVal; } - CurrentForm = this; - this->Render(1, 1, xx, yy); } this->InitializeUI(); + CurrentForm = this; + int xi; + int yi; + getmaxyx(stdscr, yi, xi); this->Render(1, 1, xi, yi); return 0; @@ -559,30 +533,21 @@ int cmCursesMainForm::Configure(int noconfigure) int cmCursesMainForm::Generate() { - int xi; - int yi; - getmaxyx(stdscr, yi, xi); + this->ResetOutputs(); - curses_move(1, 1); - this->UpdateStatusBar("Generating, please wait..."); - this->PrintKeys(1); - touchwin(stdscr); - refresh(); + this->UpdateProgress("Generating", 0); this->CMakeInstance->SetProgressCallback( [this](const std::string& msg, float prog) { this->UpdateProgress(msg, prog); }); - // Get rid of previous errors - this->Errors = std::vector<std::string>(); - // run the generate process int retVal = this->CMakeInstance->Generate(); this->CMakeInstance->SetProgressCallback(nullptr); keypad(stdscr, true); /* Use key symbols as KEY_DOWN */ - if (retVal != 0 || !this->Errors.empty()) { + if (retVal != 0 || this->HasNonStatusOutputs) { // see if there was an error if (cmSystemTools::GetErrorOccuredFlag()) { this->OkToGenerate = false; @@ -592,12 +557,13 @@ int cmCursesMainForm::Generate() int xx; int yy; getmaxyx(stdscr, yy, xx); - const char* title = "Messages during last pass."; + const char* title = "Generate produced the following output"; if (cmSystemTools::GetErrorOccuredFlag()) { - title = "Errors occurred during the last pass."; + title = "Generate failed with the following output"; } - cmCursesLongMessageForm* msgs = - new cmCursesLongMessageForm(this->Errors, title); + cmCursesLongMessageForm* msgs = new cmCursesLongMessageForm( + this->Outputs, title, + cmCursesLongMessageForm::ScrollBehavior::ScrollDown); CurrentForm = msgs; msgs->Render(1, 1, xx, yy); msgs->HandleInput(); @@ -606,11 +572,13 @@ int cmCursesMainForm::Generate() if (retVal == -2) { return retVal; } - CurrentForm = this; - this->Render(1, 1, xx, yy); } this->InitializeUI(); + CurrentForm = this; + int xi; + int yi; + getmaxyx(stdscr, yi, xi); this->Render(1, 1, xi, yi); return 0; @@ -619,7 +587,9 @@ int cmCursesMainForm::Generate() void cmCursesMainForm::AddError(const std::string& message, const char* /*unused*/) { - this->Errors.emplace_back(message); + this->Outputs.emplace_back(message); + this->HasNonStatusOutputs = true; + this->DisplayOutputs(); } void cmCursesMainForm::RemoveEntry(const char* value) @@ -704,7 +674,7 @@ void cmCursesMainForm::HandleInput() this->PrintKeys(); if (this->SearchMode) { std::string searchstr = "Search: " + this->SearchString; - this->UpdateStatusBar(searchstr.c_str()); + this->UpdateStatusBar(searchstr); this->PrintKeys(1); curses_move(y - 5, static_cast<unsigned int>(searchstr.size())); // curses_move(1,1); @@ -848,8 +818,9 @@ void cmCursesMainForm::HandleInput() this->HelpMessage[1] = ""; } - cmCursesLongMessageForm* msgs = - new cmCursesLongMessageForm(this->HelpMessage, "Help."); + cmCursesLongMessageForm* msgs = new cmCursesLongMessageForm( + this->HelpMessage, "Help", + cmCursesLongMessageForm::ScrollBehavior::NoScroll); CurrentForm = msgs; msgs->Render(1, 1, x, y); msgs->HandleInput(); @@ -861,7 +832,8 @@ void cmCursesMainForm::HandleInput() else if (key == 'l') { getmaxyx(stdscr, y, x); cmCursesLongMessageForm* msgs = new cmCursesLongMessageForm( - this->Errors, "Errors occurred during the last pass."); + this->Outputs, "CMake produced the following output", + cmCursesLongMessageForm::ScrollBehavior::NoScroll); CurrentForm = msgs; msgs->Render(1, 1, x, y); msgs->HandleInput(); @@ -1007,15 +979,6 @@ void cmCursesMainForm::JumpToCacheEntry(const char* astr) } else { form_driver(this->Form, REQ_NEXT_FIELD); } - /* - char buffer[1024]; - sprintf(buffer, "Line: %d != %d / %d\n", findex, idx, - this->NumberOfVisibleEntries); - touchwin(stdscr); - refresh(); - this->UpdateStatusBar( buffer ); - usleep(100000); - */ cur = current_field(this->Form); findex = field_index(cur); if (findex == start_index) { @@ -1024,6 +987,28 @@ void cmCursesMainForm::JumpToCacheEntry(const char* astr) } } +void cmCursesMainForm::ResetOutputs() +{ + this->LogForm.reset(); + this->Outputs.clear(); + this->HasNonStatusOutputs = false; + this->LastProgress.clear(); +} + +void cmCursesMainForm::DisplayOutputs() +{ + int xi; + int yi; + getmaxyx(stdscr, yi, xi); + + auto newLogForm = new cmCursesLongMessageForm( + this->Outputs, this->LastProgress.c_str(), + cmCursesLongMessageForm::ScrollBehavior::ScrollDown); + CurrentForm = newLogForm; + this->LogForm.reset(newLogForm); + this->LogForm->Render(1, 1, xi, yi); +} + const char* cmCursesMainForm::s_ConstHelpMessage = "CMake is used to configure and generate build files for software projects. " "The basic steps for configuring a project with ccmake are as follows:\n\n" @@ -1080,7 +1065,7 @@ const char* cmCursesMainForm::s_ConstHelpMessage = " c : process the configuration files with the current options\n" " g : generate build files and exit, only available when there are no " "new options and no errors have been detected during last configuration.\n" - " l : shows last errors\n" + " l : shows cmake output\n" " d : delete an option\n" " t : toggles advanced mode. In normal mode, only the most important " "options are shown. In advanced mode, all options are shown. We recommend " diff --git a/Source/CursesDialog/cmCursesMainForm.h b/Source/CursesDialog/cmCursesMainForm.h index b8769b7..b7c204d 100644 --- a/Source/CursesDialog/cmCursesMainForm.h +++ b/Source/CursesDialog/cmCursesMainForm.h @@ -10,12 +10,15 @@ #include <string> #include <vector> +#include <cm/optional> + #include "cmCursesCacheEntryComposite.h" #include "cmCursesForm.h" #include "cmCursesStandardIncludes.h" #include "cmStateTypes.h" class cmake; +class cmCursesLongMessageForm; /** \class cmCursesMainForm * \brief The main page of ccmake @@ -66,8 +69,8 @@ public: * exception is during a resize. The optional argument specifies the * string to be displayed in the status bar. */ - void UpdateStatusBar() override { this->UpdateStatusBar(nullptr); } - virtual void UpdateStatusBar(const char* message); + void UpdateStatusBar() override { this->UpdateStatusBar(cm::nullopt); } + void UpdateStatusBar(cm::optional<std::string> message); /** * Display current commands and their keys on the toolbar. This @@ -122,10 +125,24 @@ protected: // Jump to the cache entry whose name matches the string. void JumpToCacheEntry(const char* str); + // Clear and reset the output log and state + void ResetOutputs(); + + // Display the current progress and output + void DisplayOutputs(); + // Copies of cache entries stored in the user interface std::vector<cmCursesCacheEntryComposite> Entries; - // Errors produced during last run of cmake - std::vector<std::string> Errors; + + // The form used to display logs during processing + std::unique_ptr<cmCursesLongMessageForm> LogForm; + // Output produced by the last pass + std::vector<std::string> Outputs; + // Did the last pass produced outputs of interest (errors, warnings, ...) + bool HasNonStatusOutputs; + // Last progress bar + std::string LastProgress; + // Command line arguments to be passed to cmake each time // it is run std::vector<std::string> Args; diff --git a/Source/CursesDialog/cmCursesOptionsWidget.cxx b/Source/CursesDialog/cmCursesOptionsWidget.cxx index eb773ad..a15241f 100644 --- a/Source/CursesDialog/cmCursesOptionsWidget.cxx +++ b/Source/CursesDialog/cmCursesOptionsWidget.cxx @@ -2,6 +2,7 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmCursesOptionsWidget.h" +#include "cmCursesColor.h" #include "cmCursesWidget.h" #include "cmStateTypes.h" @@ -15,8 +16,13 @@ cmCursesOptionsWidget::cmCursesOptionsWidget(int width, int height, int left, // there is no option type, and string type causes ccmake to cast // the widget into a string widget at some point. BOOL is safe for // now. - set_field_fore(this->Field, A_NORMAL); - set_field_back(this->Field, A_STANDOUT); + if (cmCursesColor::HasColors()) { + set_field_fore(this->Field, COLOR_PAIR(cmCursesColor::Options)); + set_field_back(this->Field, COLOR_PAIR(cmCursesColor::Options)); + } else { + set_field_fore(this->Field, A_NORMAL); + set_field_back(this->Field, A_STANDOUT); + } field_opts_off(this->Field, O_STATIC); } diff --git a/Source/CursesDialog/cmCursesPathWidget.cxx b/Source/CursesDialog/cmCursesPathWidget.cxx index bb3808e..8ed42de 100644 --- a/Source/CursesDialog/cmCursesPathWidget.cxx +++ b/Source/CursesDialog/cmCursesPathWidget.cxx @@ -4,6 +4,7 @@ #include <vector> +#include "cmCursesColor.h" #include "cmCursesMainForm.h" #include "cmCursesStringWidget.h" #include "cmStateTypes.h" @@ -16,6 +17,13 @@ cmCursesPathWidget::cmCursesPathWidget(int width, int height, int left, this->Type = cmStateEnums::PATH; this->Cycle = false; this->CurrentIndex = 0; + if (cmCursesColor::HasColors()) { + set_field_fore(this->Field, COLOR_PAIR(cmCursesColor::Path)); + set_field_back(this->Field, COLOR_PAIR(cmCursesColor::Path)); + } else { + set_field_fore(this->Field, A_NORMAL); + set_field_back(this->Field, A_STANDOUT); + } } void cmCursesPathWidget::OnType(int& key, cmCursesMainForm* fm, WINDOW* w) diff --git a/Source/CursesDialog/cmCursesStringWidget.cxx b/Source/CursesDialog/cmCursesStringWidget.cxx index 6296af2..c629478 100644 --- a/Source/CursesDialog/cmCursesStringWidget.cxx +++ b/Source/CursesDialog/cmCursesStringWidget.cxx @@ -4,6 +4,7 @@ #include <cstdio> +#include "cmCursesColor.h" #include "cmCursesForm.h" #include "cmCursesMainForm.h" #include "cmCursesStandardIncludes.h" @@ -21,8 +22,13 @@ cmCursesStringWidget::cmCursesStringWidget(int width, int height, int left, { this->InEdit = false; this->Type = cmStateEnums::STRING; - set_field_fore(this->Field, A_NORMAL); - set_field_back(this->Field, A_STANDOUT); + if (cmCursesColor::HasColors()) { + set_field_fore(this->Field, COLOR_PAIR(cmCursesColor::String)); + set_field_back(this->Field, COLOR_PAIR(cmCursesColor::String)); + } else { + set_field_fore(this->Field, A_NORMAL); + set_field_back(this->Field, A_STANDOUT); + } field_opts_off(this->Field, O_STATIC); } diff --git a/Source/LexerParser/cmCommandArgumentParser.cxx b/Source/LexerParser/cmCommandArgumentParser.cxx index ae7fb42..34dc8ec 100644 --- a/Source/LexerParser/cmCommandArgumentParser.cxx +++ b/Source/LexerParser/cmCommandArgumentParser.cxx @@ -1,4 +1,4 @@ -/* A Bison parser, made by GNU Bison 3.3.2. */ +/* A Bison parser, made by GNU Bison 3.4.2. */ /* Bison implementation for Yacc-like parsers in C @@ -48,7 +48,7 @@ #define YYBISON 1 /* Bison version. */ -#define YYBISON_VERSION "3.3.2" +#define YYBISON_VERSION "3.4.2" /* Skeleton name. */ #define YYSKELETON_NAME "yacc.c" @@ -72,7 +72,7 @@ /* First part of user prologue. */ -#line 1 "cmCommandArgumentParser.y" /* yacc.c:337 */ +#line 1 "cmCommandArgumentParser.y" /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ @@ -134,7 +134,8 @@ static void cmCommandArgument_yyerror(yyscan_t yyscanner, const char* message); # pragma GCC diagnostic ignored "-Wconversion" #endif -#line 138 "cmCommandArgumentParser.cxx" /* yacc.c:337 */ +#line 138 "cmCommandArgumentParser.cxx" + # ifndef YY_NULLPTR # if defined __cplusplus # if 201103L <= __cplusplus @@ -155,8 +156,8 @@ static void cmCommandArgument_yyerror(yyscan_t yyscanner, const char* message); # define YYERROR_VERBOSE 1 #endif -/* In a future release of Bison, this section will be replaced - by #include "cmCommandArgumentParserTokens.h". */ +/* Use api.header.include to #include this header + instead of duplicating it here. */ #ifndef YY_CMCOMMANDARGUMENT_YY_CMCOMMANDARGUMENTPARSERTOKENS_H_INCLUDED # define YY_CMCOMMANDARGUMENT_YY_CMCOMMANDARGUMENTPARSERTOKENS_H_INCLUDED /* Debug traces. */ @@ -310,6 +311,8 @@ typedef short yytype_int16; #endif +#define YY_ASSERT(E) ((void) (0 && (E))) + #if ! defined yyoverflow || YYERROR_VERBOSE /* The parser invokes alloca or malloc; define the necessary symbols. */ @@ -700,7 +703,9 @@ yy_symbol_value_print (FILE *yyo, int yytype, YYSTYPE const * const yyvaluep, yy if (yytype < YYNTOKENS) YYPRINT (yyo, yytoknum[yytype], *yyvaluep); # endif + YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN YYUSE (yytype); + YY_IGNORE_MAYBE_UNINITIALIZED_END } @@ -1138,6 +1143,8 @@ yynewstate: | yynewstate -- set current state (the top of the stack) to yystate. | `--------------------------------------------------------------------*/ yysetstate: + YYDPRINTF ((stderr, "Entering state %d\n", yystate)); + YY_ASSERT (0 <= yystate && yystate < YYNSTATES); *yyssp = (yytype_int16) yystate; if (yyss + yystacksize - 1 <= yyssp) @@ -1200,8 +1207,6 @@ yysetstate: } #endif /* !defined yyoverflow && !defined YYSTACK_RELOCATE */ - YYDPRINTF ((stderr, "Entering state %d\n", yystate)); - if (yystate == YYFINAL) YYACCEPT; @@ -1269,7 +1274,6 @@ yybackup: YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN *++yyvsp = yylval; YY_IGNORE_MAYBE_UNINITIALIZED_END - goto yynewstate; @@ -1304,193 +1308,194 @@ yyreduce: YY_REDUCE_PRINT (yyn); switch (yyn) { - case 2: -#line 99 "cmCommandArgumentParser.y" /* yacc.c:1652 */ + case 2: +#line 99 "cmCommandArgumentParser.y" { (yyval.str) = 0; yyGetParser->SetResult((yyvsp[0].str)); } -#line 1314 "cmCommandArgumentParser.cxx" /* yacc.c:1652 */ +#line 1318 "cmCommandArgumentParser.cxx" break; case 3: -#line 105 "cmCommandArgumentParser.y" /* yacc.c:1652 */ +#line 105 "cmCommandArgumentParser.y" { (yyval.str) = (yyvsp[0].str); } -#line 1322 "cmCommandArgumentParser.cxx" /* yacc.c:1652 */ +#line 1326 "cmCommandArgumentParser.cxx" break; case 4: -#line 108 "cmCommandArgumentParser.y" /* yacc.c:1652 */ +#line 108 "cmCommandArgumentParser.y" { (yyval.str) = yyGetParser->CombineUnions((yyvsp[-1].str), (yyvsp[0].str)); } -#line 1330 "cmCommandArgumentParser.cxx" /* yacc.c:1652 */ +#line 1334 "cmCommandArgumentParser.cxx" break; case 5: -#line 113 "cmCommandArgumentParser.y" /* yacc.c:1652 */ +#line 113 "cmCommandArgumentParser.y" { (yyval.str) = 0; } -#line 1338 "cmCommandArgumentParser.cxx" /* yacc.c:1652 */ +#line 1342 "cmCommandArgumentParser.cxx" break; case 6: -#line 116 "cmCommandArgumentParser.y" /* yacc.c:1652 */ +#line 116 "cmCommandArgumentParser.y" { (yyval.str) = yyGetParser->CombineUnions((yyvsp[-1].str), (yyvsp[0].str)); } -#line 1346 "cmCommandArgumentParser.cxx" /* yacc.c:1652 */ +#line 1350 "cmCommandArgumentParser.cxx" break; case 7: -#line 121 "cmCommandArgumentParser.y" /* yacc.c:1652 */ +#line 121 "cmCommandArgumentParser.y" { (yyval.str) = (yyvsp[0].str); } -#line 1354 "cmCommandArgumentParser.cxx" /* yacc.c:1652 */ +#line 1358 "cmCommandArgumentParser.cxx" break; case 8: -#line 124 "cmCommandArgumentParser.y" /* yacc.c:1652 */ +#line 124 "cmCommandArgumentParser.y" { (yyval.str) = (yyvsp[0].str); } -#line 1362 "cmCommandArgumentParser.cxx" /* yacc.c:1652 */ +#line 1366 "cmCommandArgumentParser.cxx" break; case 9: -#line 129 "cmCommandArgumentParser.y" /* yacc.c:1652 */ +#line 129 "cmCommandArgumentParser.y" { (yyval.str) = (yyvsp[0].str); } -#line 1370 "cmCommandArgumentParser.cxx" /* yacc.c:1652 */ +#line 1374 "cmCommandArgumentParser.cxx" break; case 10: -#line 132 "cmCommandArgumentParser.y" /* yacc.c:1652 */ +#line 132 "cmCommandArgumentParser.y" { (yyval.str) = (yyvsp[0].str); } -#line 1378 "cmCommandArgumentParser.cxx" /* yacc.c:1652 */ +#line 1382 "cmCommandArgumentParser.cxx" break; case 11: -#line 135 "cmCommandArgumentParser.y" /* yacc.c:1652 */ +#line 135 "cmCommandArgumentParser.y" { (yyval.str) = (yyvsp[0].str); } -#line 1386 "cmCommandArgumentParser.cxx" /* yacc.c:1652 */ +#line 1390 "cmCommandArgumentParser.cxx" break; case 12: -#line 138 "cmCommandArgumentParser.y" /* yacc.c:1652 */ +#line 138 "cmCommandArgumentParser.y" { (yyval.str) = (yyvsp[0].str); } -#line 1394 "cmCommandArgumentParser.cxx" /* yacc.c:1652 */ +#line 1398 "cmCommandArgumentParser.cxx" break; case 13: -#line 141 "cmCommandArgumentParser.y" /* yacc.c:1652 */ +#line 141 "cmCommandArgumentParser.y" { (yyval.str) = (yyvsp[0].str); } -#line 1402 "cmCommandArgumentParser.cxx" /* yacc.c:1652 */ +#line 1406 "cmCommandArgumentParser.cxx" break; case 14: -#line 144 "cmCommandArgumentParser.y" /* yacc.c:1652 */ +#line 144 "cmCommandArgumentParser.y" { (yyval.str) = (yyvsp[0].str); } -#line 1410 "cmCommandArgumentParser.cxx" /* yacc.c:1652 */ +#line 1414 "cmCommandArgumentParser.cxx" break; case 15: -#line 149 "cmCommandArgumentParser.y" /* yacc.c:1652 */ +#line 149 "cmCommandArgumentParser.y" { (yyval.str) = yyGetParser->ExpandSpecialVariable((yyvsp[-2].str), (yyvsp[-1].str)); } -#line 1418 "cmCommandArgumentParser.cxx" /* yacc.c:1652 */ +#line 1422 "cmCommandArgumentParser.cxx" break; case 16: -#line 152 "cmCommandArgumentParser.y" /* yacc.c:1652 */ +#line 152 "cmCommandArgumentParser.y" { (yyval.str) = yyGetParser->ExpandSpecialVariable((yyvsp[-2].str), (yyvsp[-1].str)); } -#line 1426 "cmCommandArgumentParser.cxx" /* yacc.c:1652 */ +#line 1430 "cmCommandArgumentParser.cxx" break; case 17: -#line 155 "cmCommandArgumentParser.y" /* yacc.c:1652 */ +#line 155 "cmCommandArgumentParser.y" { (yyval.str) = yyGetParser->ExpandVariable((yyvsp[-1].str)); } -#line 1434 "cmCommandArgumentParser.cxx" /* yacc.c:1652 */ +#line 1438 "cmCommandArgumentParser.cxx" break; case 18: -#line 158 "cmCommandArgumentParser.y" /* yacc.c:1652 */ +#line 158 "cmCommandArgumentParser.y" { (yyval.str) = yyGetParser->ExpandVariableForAt((yyvsp[0].str)); } -#line 1442 "cmCommandArgumentParser.cxx" /* yacc.c:1652 */ +#line 1446 "cmCommandArgumentParser.cxx" break; case 19: -#line 163 "cmCommandArgumentParser.y" /* yacc.c:1652 */ +#line 163 "cmCommandArgumentParser.y" { (yyval.str) = (yyvsp[0].str); } -#line 1450 "cmCommandArgumentParser.cxx" /* yacc.c:1652 */ +#line 1454 "cmCommandArgumentParser.cxx" break; case 20: -#line 166 "cmCommandArgumentParser.y" /* yacc.c:1652 */ +#line 166 "cmCommandArgumentParser.y" { (yyval.str) = (yyvsp[-1].str); } -#line 1458 "cmCommandArgumentParser.cxx" /* yacc.c:1652 */ +#line 1462 "cmCommandArgumentParser.cxx" break; case 21: -#line 171 "cmCommandArgumentParser.y" /* yacc.c:1652 */ +#line 171 "cmCommandArgumentParser.y" { (yyval.str) = 0; } -#line 1466 "cmCommandArgumentParser.cxx" /* yacc.c:1652 */ +#line 1470 "cmCommandArgumentParser.cxx" break; case 22: -#line 174 "cmCommandArgumentParser.y" /* yacc.c:1652 */ +#line 174 "cmCommandArgumentParser.y" { (yyval.str) = yyGetParser->CombineUnions((yyvsp[-1].str), (yyvsp[0].str)); } -#line 1474 "cmCommandArgumentParser.cxx" /* yacc.c:1652 */ +#line 1478 "cmCommandArgumentParser.cxx" break; case 23: -#line 179 "cmCommandArgumentParser.y" /* yacc.c:1652 */ +#line 179 "cmCommandArgumentParser.y" { (yyval.str) = (yyvsp[0].str); } -#line 1482 "cmCommandArgumentParser.cxx" /* yacc.c:1652 */ +#line 1486 "cmCommandArgumentParser.cxx" break; case 24: -#line 182 "cmCommandArgumentParser.y" /* yacc.c:1652 */ +#line 182 "cmCommandArgumentParser.y" { (yyval.str) = (yyvsp[0].str); } -#line 1490 "cmCommandArgumentParser.cxx" /* yacc.c:1652 */ +#line 1494 "cmCommandArgumentParser.cxx" break; -#line 1494 "cmCommandArgumentParser.cxx" /* yacc.c:1652 */ +#line 1498 "cmCommandArgumentParser.cxx" + default: break; } /* User semantic actions sometimes alter yychar, and that requires @@ -1723,7 +1728,7 @@ yyreturn: #endif return yyresult; } -#line 187 "cmCommandArgumentParser.y" /* yacc.c:1918 */ +#line 187 "cmCommandArgumentParser.y" /* End of grammar */ diff --git a/Source/LexerParser/cmCommandArgumentParserTokens.h b/Source/LexerParser/cmCommandArgumentParserTokens.h index 56c9794..033b899 100644 --- a/Source/LexerParser/cmCommandArgumentParserTokens.h +++ b/Source/LexerParser/cmCommandArgumentParserTokens.h @@ -1,4 +1,4 @@ -/* A Bison parser, made by GNU Bison 3.3.2. */ +/* A Bison parser, made by GNU Bison 3.4.2. */ /* Bison interface for Yacc-like parsers in C diff --git a/Source/LexerParser/cmDependsJavaParser.cxx b/Source/LexerParser/cmDependsJavaParser.cxx index 6c1fb2c..b15082d 100644 --- a/Source/LexerParser/cmDependsJavaParser.cxx +++ b/Source/LexerParser/cmDependsJavaParser.cxx @@ -1,4 +1,4 @@ -/* A Bison parser, made by GNU Bison 3.3.2. */ +/* A Bison parser, made by GNU Bison 3.4.2. */ /* Bison implementation for Yacc-like parsers in C @@ -48,7 +48,7 @@ #define YYBISON 1 /* Bison version. */ -#define YYBISON_VERSION "3.3.2" +#define YYBISON_VERSION "3.4.2" /* Skeleton name. */ #define YYSKELETON_NAME "yacc.c" @@ -72,7 +72,7 @@ /* First part of user prologue. */ -#line 1 "cmDependsJavaParser.y" /* yacc.c:337 */ +#line 1 "cmDependsJavaParser.y" /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ @@ -123,7 +123,8 @@ static void cmDependsJava_yyerror(yyscan_t yyscanner, const char* message); # pragma GCC diagnostic ignored "-Wconversion" #endif -#line 127 "cmDependsJavaParser.cxx" /* yacc.c:337 */ +#line 127 "cmDependsJavaParser.cxx" + # ifndef YY_NULLPTR # if defined __cplusplus # if 201103L <= __cplusplus @@ -144,8 +145,8 @@ static void cmDependsJava_yyerror(yyscan_t yyscanner, const char* message); # define YYERROR_VERBOSE 1 #endif -/* In a future release of Bison, this section will be replaced - by #include "cmDependsJavaParserTokens.h". */ +/* Use api.header.include to #include this header + instead of duplicating it here. */ #ifndef YY_CMDEPENDSJAVA_YY_CMDEPENDSJAVAPARSERTOKENS_H_INCLUDED # define YY_CMDEPENDSJAVA_YY_CMDEPENDSJAVAPARSERTOKENS_H_INCLUDED /* Debug traces. */ @@ -481,6 +482,8 @@ typedef short yytype_int16; #endif +#define YY_ASSERT(E) ((void) (0 && (E))) + #if ! defined yyoverflow || YYERROR_VERBOSE /* The parser invokes alloca or malloc; define the necessary symbols. */ @@ -1685,7 +1688,9 @@ yy_symbol_value_print (FILE *yyo, int yytype, YYSTYPE const * const yyvaluep, yy if (yytype < YYNTOKENS) YYPRINT (yyo, yytoknum[yytype], *yyvaluep); # endif + YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN YYUSE (yytype); + YY_IGNORE_MAYBE_UNINITIALIZED_END } @@ -2123,6 +2128,8 @@ yynewstate: | yynewstate -- set current state (the top of the stack) to yystate. | `--------------------------------------------------------------------*/ yysetstate: + YYDPRINTF ((stderr, "Entering state %d\n", yystate)); + YY_ASSERT (0 <= yystate && yystate < YYNSTATES); *yyssp = (yytype_int16) yystate; if (yyss + yystacksize - 1 <= yyssp) @@ -2185,8 +2192,6 @@ yysetstate: } #endif /* !defined yyoverflow && !defined YYSTACK_RELOCATE */ - YYDPRINTF ((stderr, "Entering state %d\n", yystate)); - if (yystate == YYFINAL) YYACCEPT; @@ -2254,7 +2259,6 @@ yybackup: YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN *++yyvsp = yylval; YY_IGNORE_MAYBE_UNINITIALIZED_END - goto yynewstate; @@ -2289,215 +2293,215 @@ yyreduce: YY_REDUCE_PRINT (yyn); switch (yyn) { - case 2: -#line 183 "cmDependsJavaParser.y" /* yacc.c:1652 */ + case 2: +#line 183 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2301 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 2305 "cmDependsJavaParser.cxx" break; case 3: -#line 192 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 192 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2312 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 2316 "cmDependsJavaParser.cxx" break; case 4: -#line 200 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 200 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2323 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 2327 "cmDependsJavaParser.cxx" break; case 5: -#line 208 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 208 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2334 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 2338 "cmDependsJavaParser.cxx" break; case 6: -#line 216 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 216 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2345 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 2349 "cmDependsJavaParser.cxx" break; case 7: -#line 224 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 224 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2356 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 2360 "cmDependsJavaParser.cxx" break; case 8: -#line 232 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 232 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2367 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 2371 "cmDependsJavaParser.cxx" break; case 9: -#line 241 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 241 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2378 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 2382 "cmDependsJavaParser.cxx" break; case 10: -#line 249 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 249 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2389 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 2393 "cmDependsJavaParser.cxx" break; case 11: -#line 258 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 258 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2400 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 2404 "cmDependsJavaParser.cxx" break; case 12: -#line 266 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 266 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2411 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 2415 "cmDependsJavaParser.cxx" break; case 13: -#line 275 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 275 "cmDependsJavaParser.y" { jpElementStart(0); } -#line 2419 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 2423 "cmDependsJavaParser.cxx" break; case 14: -#line 280 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 280 "cmDependsJavaParser.y" { jpElementStart(0); } -#line 2427 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 2431 "cmDependsJavaParser.cxx" break; case 15: -#line 285 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 285 "cmDependsJavaParser.y" { jpElementStart(0); } -#line 2435 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 2439 "cmDependsJavaParser.cxx" break; case 16: -#line 290 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 290 "cmDependsJavaParser.y" { jpElementStart(0); } -#line 2443 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 2447 "cmDependsJavaParser.cxx" break; case 17: -#line 295 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 295 "cmDependsJavaParser.y" { jpElementStart(0); } -#line 2451 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 2455 "cmDependsJavaParser.cxx" break; case 18: -#line 300 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 300 "cmDependsJavaParser.y" { jpElementStart(0); } -#line 2459 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 2463 "cmDependsJavaParser.cxx" break; case 19: -#line 305 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 305 "cmDependsJavaParser.y" { jpElementStart(0); } -#line 2467 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 2471 "cmDependsJavaParser.cxx" break; case 20: -#line 310 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 310 "cmDependsJavaParser.y" { jpElementStart(0); } -#line 2475 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 2479 "cmDependsJavaParser.cxx" break; case 21: -#line 316 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 316 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2486 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 2490 "cmDependsJavaParser.cxx" break; case 22: -#line 324 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 324 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2497 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 2501 "cmDependsJavaParser.cxx" break; case 23: -#line 333 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 333 "cmDependsJavaParser.y" { jpElementStart(1); jpStoreClass((yyvsp[0].str)); @@ -2505,44 +2509,44 @@ yyreduce: (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2509 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 2513 "cmDependsJavaParser.cxx" break; case 24: -#line 343 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 343 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2520 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 2524 "cmDependsJavaParser.cxx" break; case 25: -#line 352 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 352 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2531 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 2535 "cmDependsJavaParser.cxx" break; case 26: -#line 361 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 361 "cmDependsJavaParser.y" { jpElementStart(2); jpCheckEmpty(2); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2542 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 2546 "cmDependsJavaParser.cxx" break; case 27: -#line 369 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 369 "cmDependsJavaParser.y" { jpElementStart(2); jpStoreClass((yyvsp[-1].str)); @@ -2550,56 +2554,56 @@ yyreduce: (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2554 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 2558 "cmDependsJavaParser.cxx" break; case 28: -#line 379 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 379 "cmDependsJavaParser.y" { jpElementStart(1); (yyval.str) = (yyvsp[0].str); } -#line 2563 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 2567 "cmDependsJavaParser.cxx" break; case 29: -#line 385 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 385 "cmDependsJavaParser.y" { jpElementStart(1); (yyval.str) = (yyvsp[0].str); } -#line 2572 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 2576 "cmDependsJavaParser.cxx" break; case 30: -#line 392 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 392 "cmDependsJavaParser.y" { jpElementStart(1); (yyval.str) = (yyvsp[0].str); } -#line 2581 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 2585 "cmDependsJavaParser.cxx" break; case 31: -#line 399 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 399 "cmDependsJavaParser.y" { jpElementStart(1); (yyval.str) = (yyvsp[0].str); } -#line 2590 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 2594 "cmDependsJavaParser.cxx" break; case 32: -#line 405 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 405 "cmDependsJavaParser.y" { jpElementStart(2); (yyval.str) = (yyvsp[0].str); } -#line 2599 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 2603 "cmDependsJavaParser.cxx" break; case 33: -#line 412 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 412 "cmDependsJavaParser.y" { jpElementStart(3); yyGetParser->AddClassFound((yyvsp[-2].str)); @@ -2607,11 +2611,11 @@ yyreduce: yyGetParser->DeallocateParserType(&((yyvsp[-2].str))); (yyval.str) = const_cast<char*>(yyGetParser->GetCurrentCombine()); } -#line 2611 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 2615 "cmDependsJavaParser.cxx" break; case 34: -#line 421 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 421 "cmDependsJavaParser.y" { jpElementStart(3); jpStoreClass((yyvsp[-2].str)); @@ -2620,11 +2624,11 @@ yyreduce: (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2624 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 2628 "cmDependsJavaParser.cxx" break; case 35: -#line 431 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 431 "cmDependsJavaParser.y" { jpElementStart(3); jpStoreClass((yyvsp[-2].str)); @@ -2633,118 +2637,118 @@ yyreduce: (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2637 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 2641 "cmDependsJavaParser.cxx" break; case 36: -#line 441 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 441 "cmDependsJavaParser.y" { jpElementStart(3); jpCheckEmpty(3); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2648 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 2652 "cmDependsJavaParser.cxx" break; case 37: -#line 450 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 450 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2659 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 2663 "cmDependsJavaParser.cxx" break; case 38: -#line 458 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 458 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2670 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 2674 "cmDependsJavaParser.cxx" break; case 39: -#line 467 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 467 "cmDependsJavaParser.y" { jpElementStart(3); jpCheckEmpty(3); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2681 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 2685 "cmDependsJavaParser.cxx" break; case 40: -#line 475 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 475 "cmDependsJavaParser.y" { jpElementStart(0); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2691 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 2695 "cmDependsJavaParser.cxx" break; case 41: -#line 482 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 482 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2702 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 2706 "cmDependsJavaParser.cxx" break; case 42: -#line 490 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 490 "cmDependsJavaParser.y" { jpElementStart(0); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2712 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 2716 "cmDependsJavaParser.cxx" break; case 43: -#line 497 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 497 "cmDependsJavaParser.y" { jpElementStart(2); jpCheckEmpty(2); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2723 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 2727 "cmDependsJavaParser.cxx" break; case 44: -#line 505 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 505 "cmDependsJavaParser.y" { jpElementStart(0); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2733 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 2737 "cmDependsJavaParser.cxx" break; case 45: -#line 512 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 512 "cmDependsJavaParser.y" { jpElementStart(2); jpCheckEmpty(2); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2744 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 2748 "cmDependsJavaParser.cxx" break; case 46: -#line 521 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 521 "cmDependsJavaParser.y" { jpElementStart(3); yyGetParser->SetCurrentPackage((yyvsp[-1].str)); @@ -2754,33 +2758,33 @@ yyreduce: (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2758 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 2762 "cmDependsJavaParser.cxx" break; case 47: -#line 533 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 533 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2769 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 2773 "cmDependsJavaParser.cxx" break; case 48: -#line 541 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 541 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2780 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 2784 "cmDependsJavaParser.cxx" break; case 49: -#line 550 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 550 "cmDependsJavaParser.y" { jpElementStart(3); yyGetParser->AddPackagesImport((yyvsp[-1].str)); @@ -2790,11 +2794,11 @@ yyreduce: (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2794 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 2798 "cmDependsJavaParser.cxx" break; case 50: -#line 562 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 562 "cmDependsJavaParser.y" { jpElementStart(5); std::string str = (yyvsp[-3].str); @@ -2805,77 +2809,77 @@ yyreduce: (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2809 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 2813 "cmDependsJavaParser.cxx" break; case 51: -#line 575 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 575 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2820 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 2824 "cmDependsJavaParser.cxx" break; case 52: -#line 583 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 583 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2831 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 2835 "cmDependsJavaParser.cxx" break; case 53: -#line 591 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 591 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2842 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 2846 "cmDependsJavaParser.cxx" break; case 54: -#line 600 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 600 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2853 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 2857 "cmDependsJavaParser.cxx" break; case 55: -#line 608 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 608 "cmDependsJavaParser.y" { jpElementStart(2); jpCheckEmpty(2); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2864 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 2868 "cmDependsJavaParser.cxx" break; case 67: -#line 623 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 623 "cmDependsJavaParser.y" { yyGetParser->StartClass((yyvsp[0].str)); jpElementStart(3); yyGetParser->DeallocateParserType(&((yyvsp[0].str))); jpCheckEmpty(3); } -#line 2875 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 2879 "cmDependsJavaParser.cxx" break; case 68: -#line 633 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 633 "cmDependsJavaParser.y" { jpElementStart(2); jpCheckEmpty(2); @@ -2883,11 +2887,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); yyGetParser->EndClass(); } -#line 2887 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 2891 "cmDependsJavaParser.cxx" break; case 69: -#line 642 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 642 "cmDependsJavaParser.y" { jpElementStart(3); jpCheckEmpty(2); @@ -2895,11 +2899,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); yyGetParser->EndClass(); } -#line 2899 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 2903 "cmDependsJavaParser.cxx" break; case 70: -#line 651 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 651 "cmDependsJavaParser.y" { jpElementStart(3); jpCheckEmpty(3); @@ -2907,11 +2911,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); yyGetParser->EndClass(); } -#line 2911 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 2915 "cmDependsJavaParser.cxx" break; case 71: -#line 660 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 660 "cmDependsJavaParser.y" { jpElementStart(4); jpCheckEmpty(4); @@ -2919,226 +2923,226 @@ yyreduce: yyGetParser->SetCurrentCombine(""); yyGetParser->EndClass(); } -#line 2923 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 2927 "cmDependsJavaParser.cxx" break; case 72: -#line 669 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 669 "cmDependsJavaParser.y" { jpElementStart(0); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2933 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 2937 "cmDependsJavaParser.cxx" break; case 73: -#line 676 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 676 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2944 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 2948 "cmDependsJavaParser.cxx" break; case 74: -#line 685 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 685 "cmDependsJavaParser.y" { jpElementStart(2); jpCheckEmpty(2); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2955 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 2959 "cmDependsJavaParser.cxx" break; case 75: -#line 694 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 694 "cmDependsJavaParser.y" { jpElementStart(2); jpCheckEmpty(2); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2966 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 2970 "cmDependsJavaParser.cxx" break; case 76: -#line 703 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 703 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2977 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 2981 "cmDependsJavaParser.cxx" break; case 77: -#line 711 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 711 "cmDependsJavaParser.y" { jpElementStart(3); jpCheckEmpty(3); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2988 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 2992 "cmDependsJavaParser.cxx" break; case 78: -#line 720 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 720 "cmDependsJavaParser.y" { jpElementStart(3); jpCheckEmpty(3); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2999 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 3003 "cmDependsJavaParser.cxx" break; case 79: -#line 728 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 728 "cmDependsJavaParser.y" { jpElementStart(1); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 3009 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 3013 "cmDependsJavaParser.cxx" break; case 80: -#line 735 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 735 "cmDependsJavaParser.y" { jpElementStart(2); jpCheckEmpty(2); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 3020 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 3024 "cmDependsJavaParser.cxx" break; case 81: -#line 744 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 744 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 3031 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 3035 "cmDependsJavaParser.cxx" break; case 82: -#line 752 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 752 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 3042 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 3046 "cmDependsJavaParser.cxx" break; case 83: -#line 760 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 760 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 3053 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 3057 "cmDependsJavaParser.cxx" break; case 84: -#line 768 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 768 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 3064 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 3068 "cmDependsJavaParser.cxx" break; case 85: -#line 777 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 777 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 3075 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 3079 "cmDependsJavaParser.cxx" break; case 86: -#line 785 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 785 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 3086 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 3090 "cmDependsJavaParser.cxx" break; case 87: -#line 794 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 794 "cmDependsJavaParser.y" { jpElementStart(4); } -#line 3094 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 3098 "cmDependsJavaParser.cxx" break; case 88: -#line 800 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 800 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 3105 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 3109 "cmDependsJavaParser.cxx" break; case 89: -#line 808 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 808 "cmDependsJavaParser.y" { jpElementStart(3); jpCheckEmpty(3); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 3116 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 3120 "cmDependsJavaParser.cxx" break; case 90: -#line 817 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 817 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 3127 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 3131 "cmDependsJavaParser.cxx" break; case 91: -#line 825 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 825 "cmDependsJavaParser.y" { jpElementStart(3); jpCheckEmpty(3); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 3138 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 3142 "cmDependsJavaParser.cxx" break; case 92: -#line 834 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 834 "cmDependsJavaParser.y" { jpElementStart(1); yyGetParser->DeallocateParserType(&((yyvsp[0].str))); @@ -3146,77 +3150,77 @@ yyreduce: (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 3150 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 3154 "cmDependsJavaParser.cxx" break; case 93: -#line 843 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 843 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 3161 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 3165 "cmDependsJavaParser.cxx" break; case 94: -#line 852 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 852 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 3172 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 3176 "cmDependsJavaParser.cxx" break; case 95: -#line 860 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 860 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 3183 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 3187 "cmDependsJavaParser.cxx" break; case 96: -#line 869 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 869 "cmDependsJavaParser.y" { jpElementStart(2); jpCheckEmpty(2); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 3194 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 3198 "cmDependsJavaParser.cxx" break; case 97: -#line 877 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 877 "cmDependsJavaParser.y" { jpElementStart(2); jpCheckEmpty(2); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 3205 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 3209 "cmDependsJavaParser.cxx" break; case 98: -#line 885 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 885 "cmDependsJavaParser.y" { jpElementStart(3); jpCheckEmpty(3); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 3216 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 3220 "cmDependsJavaParser.cxx" break; case 99: -#line 894 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 894 "cmDependsJavaParser.y" { jpElementStart(4); jpCheckEmpty(4); @@ -3224,11 +3228,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3228 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 3232 "cmDependsJavaParser.cxx" break; case 100: -#line 903 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 903 "cmDependsJavaParser.y" { jpElementStart(4); jpCheckEmpty(4); @@ -3236,22 +3240,22 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3240 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 3244 "cmDependsJavaParser.cxx" break; case 101: -#line 912 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 912 "cmDependsJavaParser.y" { jpElementStart(0); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 3251 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 3255 "cmDependsJavaParser.cxx" break; case 102: -#line 920 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 920 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -3259,11 +3263,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3263 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 3267 "cmDependsJavaParser.cxx" break; case 103: -#line 930 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 930 "cmDependsJavaParser.y" { jpElementStart(4); yyGetParser->DeallocateParserType(&((yyvsp[-3].str))); @@ -3272,40 +3276,40 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3276 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 3280 "cmDependsJavaParser.cxx" break; case 104: -#line 940 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 940 "cmDependsJavaParser.y" { jpElementStart(3); } -#line 3285 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 3289 "cmDependsJavaParser.cxx" break; case 105: -#line 946 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 946 "cmDependsJavaParser.y" { jpElementStart(0); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 3296 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 3300 "cmDependsJavaParser.cxx" break; case 107: -#line 957 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 957 "cmDependsJavaParser.y" { jpElementStart(1); } -#line 3305 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 3309 "cmDependsJavaParser.cxx" break; case 108: -#line 963 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 963 "cmDependsJavaParser.y" { jpElementStart(3); jpCheckEmpty(3); @@ -3313,11 +3317,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3317 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 3321 "cmDependsJavaParser.cxx" break; case 109: -#line 973 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 973 "cmDependsJavaParser.y" { jpElementStart(3); jpCheckEmpty(3); @@ -3325,11 +3329,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3329 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 3333 "cmDependsJavaParser.cxx" break; case 110: -#line 983 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 983 "cmDependsJavaParser.y" { jpElementStart(2); jpCheckEmpty(2); @@ -3337,20 +3341,20 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3341 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 3345 "cmDependsJavaParser.cxx" break; case 111: -#line 993 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 993 "cmDependsJavaParser.y" { jpElementStart(1); } -#line 3350 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 3354 "cmDependsJavaParser.cxx" break; case 112: -#line 999 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 999 "cmDependsJavaParser.y" { jpElementStart(3); jpCheckEmpty(3); @@ -3358,11 +3362,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3362 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 3366 "cmDependsJavaParser.cxx" break; case 113: -#line 1009 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 1009 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -3370,11 +3374,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3374 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 3378 "cmDependsJavaParser.cxx" break; case 114: -#line 1019 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 1019 "cmDependsJavaParser.y" { jpElementStart(2); jpCheckEmpty(2); @@ -3382,11 +3386,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3386 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 3390 "cmDependsJavaParser.cxx" break; case 115: -#line 1029 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 1029 "cmDependsJavaParser.y" { jpElementStart(4); jpCheckEmpty(4); @@ -3394,11 +3398,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3398 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 3402 "cmDependsJavaParser.cxx" break; case 116: -#line 1038 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 1038 "cmDependsJavaParser.y" { jpElementStart(5); jpCheckEmpty(5); @@ -3406,11 +3410,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3410 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 3414 "cmDependsJavaParser.cxx" break; case 117: -#line 1048 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 1048 "cmDependsJavaParser.y" { jpElementStart(4); yyGetParser->DeallocateParserType(&((yyvsp[-3].str))); @@ -3419,11 +3423,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3423 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 3427 "cmDependsJavaParser.cxx" break; case 118: -#line 1059 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 1059 "cmDependsJavaParser.y" { jpElementStart(4); jpCheckEmpty(4); @@ -3431,22 +3435,22 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3435 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 3439 "cmDependsJavaParser.cxx" break; case 119: -#line 1068 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 1068 "cmDependsJavaParser.y" { jpElementStart(0); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 3446 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 3450 "cmDependsJavaParser.cxx" break; case 120: -#line 1076 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 1076 "cmDependsJavaParser.y" { jpElementStart(2); jpCheckEmpty(2); @@ -3454,11 +3458,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3458 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 3462 "cmDependsJavaParser.cxx" break; case 121: -#line 1086 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 1086 "cmDependsJavaParser.y" { jpElementStart(5); jpCheckEmpty(5); @@ -3466,11 +3470,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3470 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 3474 "cmDependsJavaParser.cxx" break; case 122: -#line 1095 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 1095 "cmDependsJavaParser.y" { jpElementStart(5); jpCheckEmpty(5); @@ -3478,22 +3482,22 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3482 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 3486 "cmDependsJavaParser.cxx" break; case 123: -#line 1105 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 1105 "cmDependsJavaParser.y" { yyGetParser->StartClass((yyvsp[0].str)); jpElementStart(3); yyGetParser->DeallocateParserType(&((yyvsp[0].str))); jpCheckEmpty(3); } -#line 3493 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 3497 "cmDependsJavaParser.cxx" break; case 124: -#line 1114 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 1114 "cmDependsJavaParser.y" { jpElementStart(2); jpCheckEmpty(2); @@ -3501,21 +3505,21 @@ yyreduce: yyGetParser->SetCurrentCombine(""); yyGetParser->EndClass(); } -#line 3505 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 3509 "cmDependsJavaParser.cxx" break; case 125: -#line 1123 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 1123 "cmDependsJavaParser.y" { jpElementStart(0); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 3515 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 3519 "cmDependsJavaParser.cxx" break; case 126: -#line 1130 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 1130 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -3523,11 +3527,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3527 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 3531 "cmDependsJavaParser.cxx" break; case 127: -#line 1140 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 1140 "cmDependsJavaParser.y" { jpElementStart(2); jpCheckEmpty(2); @@ -3535,11 +3539,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3539 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 3543 "cmDependsJavaParser.cxx" break; case 128: -#line 1149 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 1149 "cmDependsJavaParser.y" { jpElementStart(3); jpCheckEmpty(3); @@ -3547,11 +3551,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3551 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 3555 "cmDependsJavaParser.cxx" break; case 129: -#line 1159 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 1159 "cmDependsJavaParser.y" { jpElementStart(3); jpCheckEmpty(3); @@ -3559,33 +3563,33 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3563 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 3567 "cmDependsJavaParser.cxx" break; case 130: -#line 1168 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 1168 "cmDependsJavaParser.y" { jpElementStart(0); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 3574 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 3578 "cmDependsJavaParser.cxx" break; case 131: -#line 1176 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 1176 "cmDependsJavaParser.y" { jpElementStart(2); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 3585 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 3589 "cmDependsJavaParser.cxx" break; case 132: -#line 1185 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 1185 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -3593,11 +3597,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3597 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 3601 "cmDependsJavaParser.cxx" break; case 133: -#line 1194 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 1194 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -3605,11 +3609,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3609 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 3613 "cmDependsJavaParser.cxx" break; case 134: -#line 1203 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 1203 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -3617,22 +3621,22 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3621 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 3625 "cmDependsJavaParser.cxx" break; case 135: -#line 1212 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 1212 "cmDependsJavaParser.y" { jpElementStart(2); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 3632 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 3636 "cmDependsJavaParser.cxx" break; case 136: -#line 1220 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 1220 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -3640,22 +3644,22 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3644 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 3648 "cmDependsJavaParser.cxx" break; case 137: -#line 1229 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 1229 "cmDependsJavaParser.y" { jpElementStart(2); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 3655 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 3659 "cmDependsJavaParser.cxx" break; case 138: -#line 1238 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 1238 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -3663,11 +3667,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3667 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 3671 "cmDependsJavaParser.cxx" break; case 139: -#line 1248 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 1248 "cmDependsJavaParser.y" { jpElementStart(2); jpCheckEmpty(2); @@ -3675,11 +3679,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3679 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 3683 "cmDependsJavaParser.cxx" break; case 140: -#line 1258 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 1258 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -3687,11 +3691,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3691 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 3695 "cmDependsJavaParser.cxx" break; case 141: -#line 1267 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 1267 "cmDependsJavaParser.y" { jpElementStart(2); jpCheckEmpty(2); @@ -3699,11 +3703,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3703 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 3707 "cmDependsJavaParser.cxx" break; case 142: -#line 1277 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 1277 "cmDependsJavaParser.y" { jpElementStart(3); jpCheckEmpty(3); @@ -3711,22 +3715,22 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3715 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 3719 "cmDependsJavaParser.cxx" break; case 143: -#line 1286 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 1286 "cmDependsJavaParser.y" { jpElementStart(1); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 3726 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 3730 "cmDependsJavaParser.cxx" break; case 144: -#line 1294 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 1294 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -3734,11 +3738,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3738 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 3742 "cmDependsJavaParser.cxx" break; case 145: -#line 1303 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 1303 "cmDependsJavaParser.y" { jpElementStart(2); jpCheckEmpty(2); @@ -3746,11 +3750,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3750 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 3754 "cmDependsJavaParser.cxx" break; case 146: -#line 1313 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 1313 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -3758,11 +3762,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3762 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 3766 "cmDependsJavaParser.cxx" break; case 147: -#line 1322 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 1322 "cmDependsJavaParser.y" { jpElementStart(3); jpCheckEmpty(3); @@ -3770,33 +3774,33 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3774 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 3778 "cmDependsJavaParser.cxx" break; case 148: -#line 1332 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 1332 "cmDependsJavaParser.y" { jpElementStart(4); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 3785 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 3789 "cmDependsJavaParser.cxx" break; case 149: -#line 1340 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 1340 "cmDependsJavaParser.y" { jpElementStart(1); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 3796 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 3800 "cmDependsJavaParser.cxx" break; case 150: -#line 1348 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 1348 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -3804,11 +3808,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3808 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 3812 "cmDependsJavaParser.cxx" break; case 151: -#line 1358 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 1358 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -3816,11 +3820,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3820 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 3824 "cmDependsJavaParser.cxx" break; case 152: -#line 1367 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 1367 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(2); @@ -3828,11 +3832,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3832 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 3836 "cmDependsJavaParser.cxx" break; case 153: -#line 1377 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 1377 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -3840,11 +3844,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3844 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 3848 "cmDependsJavaParser.cxx" break; case 154: -#line 1386 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 1386 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -3852,11 +3856,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3856 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 3860 "cmDependsJavaParser.cxx" break; case 155: -#line 1395 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 1395 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -3864,11 +3868,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3868 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 3872 "cmDependsJavaParser.cxx" break; case 156: -#line 1405 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 1405 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(2); @@ -3876,11 +3880,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3880 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 3884 "cmDependsJavaParser.cxx" break; case 157: -#line 1415 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 1415 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(3); @@ -3888,11 +3892,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3892 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 3896 "cmDependsJavaParser.cxx" break; case 158: -#line 1424 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 1424 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(2); @@ -3900,11 +3904,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3904 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 3908 "cmDependsJavaParser.cxx" break; case 159: -#line 1434 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 1434 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -3912,11 +3916,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3916 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 3920 "cmDependsJavaParser.cxx" break; case 160: -#line 1443 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 1443 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -3924,11 +3928,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3928 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 3932 "cmDependsJavaParser.cxx" break; case 161: -#line 1452 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 1452 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -3936,11 +3940,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3940 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 3944 "cmDependsJavaParser.cxx" break; case 162: -#line 1461 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 1461 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -3948,11 +3952,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3952 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 3956 "cmDependsJavaParser.cxx" break; case 163: -#line 1470 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 1470 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -3960,11 +3964,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3964 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 3968 "cmDependsJavaParser.cxx" break; case 164: -#line 1479 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 1479 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -3972,11 +3976,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3976 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 3980 "cmDependsJavaParser.cxx" break; case 165: -#line 1489 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 1489 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -3984,11 +3988,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3988 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 3992 "cmDependsJavaParser.cxx" break; case 166: -#line 1498 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 1498 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -3996,11 +4000,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4000 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 4004 "cmDependsJavaParser.cxx" break; case 167: -#line 1507 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 1507 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -4008,11 +4012,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4012 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 4016 "cmDependsJavaParser.cxx" break; case 168: -#line 1516 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 1516 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -4020,11 +4024,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4024 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 4028 "cmDependsJavaParser.cxx" break; case 169: -#line 1525 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 1525 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -4032,11 +4036,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4036 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 4040 "cmDependsJavaParser.cxx" break; case 170: -#line 1535 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 1535 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -4044,11 +4048,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4048 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 4052 "cmDependsJavaParser.cxx" break; case 171: -#line 1544 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 1544 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -4056,11 +4060,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4060 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 4064 "cmDependsJavaParser.cxx" break; case 172: -#line 1553 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 1553 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -4068,11 +4072,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4072 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 4076 "cmDependsJavaParser.cxx" break; case 173: -#line 1562 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 1562 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -4080,11 +4084,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4084 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 4088 "cmDependsJavaParser.cxx" break; case 174: -#line 1571 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 1571 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -4092,11 +4096,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4096 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 4100 "cmDependsJavaParser.cxx" break; case 175: -#line 1580 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 1580 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -4104,11 +4108,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4108 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 4112 "cmDependsJavaParser.cxx" break; case 176: -#line 1589 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 1589 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -4116,11 +4120,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4120 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 4124 "cmDependsJavaParser.cxx" break; case 177: -#line 1598 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 1598 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -4128,11 +4132,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4132 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 4136 "cmDependsJavaParser.cxx" break; case 178: -#line 1607 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 1607 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -4140,11 +4144,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4144 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 4148 "cmDependsJavaParser.cxx" break; case 179: -#line 1616 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 1616 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -4152,11 +4156,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4156 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 4160 "cmDependsJavaParser.cxx" break; case 180: -#line 1625 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 1625 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -4164,11 +4168,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4168 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 4172 "cmDependsJavaParser.cxx" break; case 181: -#line 1634 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 1634 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -4176,11 +4180,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4180 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 4184 "cmDependsJavaParser.cxx" break; case 182: -#line 1644 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 1644 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -4188,11 +4192,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4192 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 4196 "cmDependsJavaParser.cxx" break; case 183: -#line 1654 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 1654 "cmDependsJavaParser.y" { jpElementStart(3); yyGetParser->DeallocateParserType(&((yyvsp[-2].str))); @@ -4201,11 +4205,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4205 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 4209 "cmDependsJavaParser.cxx" break; case 184: -#line 1665 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 1665 "cmDependsJavaParser.y" { jpElementStart(3); jpCheckEmpty(3); @@ -4213,11 +4217,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4217 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 4221 "cmDependsJavaParser.cxx" break; case 185: -#line 1675 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 1675 "cmDependsJavaParser.y" { jpElementStart(2); jpCheckEmpty(2); @@ -4225,11 +4229,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4229 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 4233 "cmDependsJavaParser.cxx" break; case 186: -#line 1685 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 1685 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -4237,11 +4241,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4241 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 4245 "cmDependsJavaParser.cxx" break; case 187: -#line 1694 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 1694 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -4249,11 +4253,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4253 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 4257 "cmDependsJavaParser.cxx" break; case 188: -#line 1703 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 1703 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -4261,11 +4265,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4265 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 4269 "cmDependsJavaParser.cxx" break; case 189: -#line 1712 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 1712 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -4273,11 +4277,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4277 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 4281 "cmDependsJavaParser.cxx" break; case 190: -#line 1721 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 1721 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -4285,11 +4289,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4289 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 4293 "cmDependsJavaParser.cxx" break; case 191: -#line 1730 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 1730 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -4297,11 +4301,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4301 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 4305 "cmDependsJavaParser.cxx" break; case 192: -#line 1739 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 1739 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -4309,11 +4313,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4313 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 4317 "cmDependsJavaParser.cxx" break; case 193: -#line 1749 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 1749 "cmDependsJavaParser.y" { jpElementStart(5); jpCheckEmpty(5); @@ -4321,11 +4325,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4325 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 4329 "cmDependsJavaParser.cxx" break; case 194: -#line 1759 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 1759 "cmDependsJavaParser.y" { jpElementStart(7); jpCheckEmpty(7); @@ -4333,11 +4337,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4337 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 4341 "cmDependsJavaParser.cxx" break; case 195: -#line 1769 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 1769 "cmDependsJavaParser.y" { jpElementStart(7); jpCheckEmpty(7); @@ -4345,40 +4349,40 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4349 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 4353 "cmDependsJavaParser.cxx" break; case 196: -#line 1779 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 1779 "cmDependsJavaParser.y" { jpElementStart(5); } -#line 4358 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 4362 "cmDependsJavaParser.cxx" break; case 197: -#line 1786 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 1786 "cmDependsJavaParser.y" { jpElementStart(4); } -#line 4367 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 4371 "cmDependsJavaParser.cxx" break; case 198: -#line 1792 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 1792 "cmDependsJavaParser.y" { jpElementStart(0); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 4378 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 4382 "cmDependsJavaParser.cxx" break; case 199: -#line 1800 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 1800 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -4386,22 +4390,22 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4390 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 4394 "cmDependsJavaParser.cxx" break; case 200: -#line 1809 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 1809 "cmDependsJavaParser.y" { jpElementStart(0); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 4401 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 4405 "cmDependsJavaParser.cxx" break; case 201: -#line 1817 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 1817 "cmDependsJavaParser.y" { jpElementStart(2); jpCheckEmpty(2); @@ -4409,11 +4413,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4413 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 4417 "cmDependsJavaParser.cxx" break; case 202: -#line 1827 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 1827 "cmDependsJavaParser.y" { jpElementStart(2); jpCheckEmpty(2); @@ -4421,11 +4425,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4425 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 4429 "cmDependsJavaParser.cxx" break; case 203: -#line 1837 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 1837 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -4433,11 +4437,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4437 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 4441 "cmDependsJavaParser.cxx" break; case 204: -#line 1846 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 1846 "cmDependsJavaParser.y" { jpElementStart(2); jpCheckEmpty(2); @@ -4445,11 +4449,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4449 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 4453 "cmDependsJavaParser.cxx" break; case 205: -#line 1856 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 1856 "cmDependsJavaParser.y" { jpElementStart(3); jpCheckEmpty(3); @@ -4457,11 +4461,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4461 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 4465 "cmDependsJavaParser.cxx" break; case 206: -#line 1865 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 1865 "cmDependsJavaParser.y" { jpElementStart(2); jpCheckEmpty(2); @@ -4469,58 +4473,58 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4473 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 4477 "cmDependsJavaParser.cxx" break; case 207: -#line 1875 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 1875 "cmDependsJavaParser.y" { jpElementStart(5); } -#line 4482 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 4486 "cmDependsJavaParser.cxx" break; case 208: -#line 1882 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 1882 "cmDependsJavaParser.y" { jpElementStart(5); } -#line 4491 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 4495 "cmDependsJavaParser.cxx" break; case 209: -#line 1889 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 1889 "cmDependsJavaParser.y" { jpElementStart(7); } -#line 4500 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 4504 "cmDependsJavaParser.cxx" break; case 210: -#line 1897 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 1897 "cmDependsJavaParser.y" { jpElementStart(9); } -#line 4509 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 4513 "cmDependsJavaParser.cxx" break; case 211: -#line 1903 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 1903 "cmDependsJavaParser.y" { jpElementStart(1); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 4520 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 4524 "cmDependsJavaParser.cxx" break; case 212: -#line 1911 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 1911 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -4528,22 +4532,22 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4532 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 4536 "cmDependsJavaParser.cxx" break; case 213: -#line 1920 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 1920 "cmDependsJavaParser.y" { jpElementStart(0); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 4543 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 4547 "cmDependsJavaParser.cxx" break; case 214: -#line 1928 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 1928 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -4551,33 +4555,33 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4555 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 4559 "cmDependsJavaParser.cxx" break; case 215: -#line 1939 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 1939 "cmDependsJavaParser.y" { jpElementStart(9); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 4566 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 4570 "cmDependsJavaParser.cxx" break; case 216: -#line 1947 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 1947 "cmDependsJavaParser.y" { jpElementStart(0); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 4577 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 4581 "cmDependsJavaParser.cxx" break; case 217: -#line 1955 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 1955 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -4585,11 +4589,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4589 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 4593 "cmDependsJavaParser.cxx" break; case 218: -#line 1965 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 1965 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -4597,11 +4601,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4601 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 4605 "cmDependsJavaParser.cxx" break; case 219: -#line 1974 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 1974 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -4609,11 +4613,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4613 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 4617 "cmDependsJavaParser.cxx" break; case 220: -#line 1984 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 1984 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -4621,11 +4625,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4625 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 4629 "cmDependsJavaParser.cxx" break; case 221: -#line 1994 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 1994 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -4633,11 +4637,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4637 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 4641 "cmDependsJavaParser.cxx" break; case 222: -#line 2003 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 2003 "cmDependsJavaParser.y" { jpElementStart(3); jpCheckEmpty(3); @@ -4645,11 +4649,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4649 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 4653 "cmDependsJavaParser.cxx" break; case 223: -#line 2013 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 2013 "cmDependsJavaParser.y" { jpElementStart(3); jpCheckEmpty(3); @@ -4657,11 +4661,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4661 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 4665 "cmDependsJavaParser.cxx" break; case 224: -#line 2022 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 2022 "cmDependsJavaParser.y" { jpElementStart(5); jpCheckEmpty(5); @@ -4669,11 +4673,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4673 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 4677 "cmDependsJavaParser.cxx" break; case 225: -#line 2032 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 2032 "cmDependsJavaParser.y" { jpElementStart(3); yyGetParser->DeallocateParserType(&((yyvsp[-1].str))); @@ -4682,31 +4686,31 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4686 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 4690 "cmDependsJavaParser.cxx" break; case 226: -#line 2042 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 2042 "cmDependsJavaParser.y" { jpElementStart(0); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 4697 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 4701 "cmDependsJavaParser.cxx" break; case 227: -#line 2050 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 2050 "cmDependsJavaParser.y" { jpElementStart(1); } -#line 4706 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 4710 "cmDependsJavaParser.cxx" break; case 228: -#line 2057 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 2057 "cmDependsJavaParser.y" { jpElementStart(3); yyGetParser->DeallocateParserType(&((yyvsp[-1].str))); @@ -4715,11 +4719,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4719 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 4723 "cmDependsJavaParser.cxx" break; case 229: -#line 2068 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 2068 "cmDependsJavaParser.y" { jpElementStart(3); jpCheckEmpty(3); @@ -4727,11 +4731,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4731 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 4735 "cmDependsJavaParser.cxx" break; case 230: -#line 2078 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 2078 "cmDependsJavaParser.y" { jpElementStart(3); jpCheckEmpty(3); @@ -4739,11 +4743,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4743 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 4747 "cmDependsJavaParser.cxx" break; case 231: -#line 2088 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 2088 "cmDependsJavaParser.y" { jpElementStart(5); jpCheckEmpty(5); @@ -4751,11 +4755,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4755 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 4759 "cmDependsJavaParser.cxx" break; case 232: -#line 2098 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 2098 "cmDependsJavaParser.y" { jpElementStart(3); jpCheckEmpty(3); @@ -4763,11 +4767,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4767 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 4771 "cmDependsJavaParser.cxx" break; case 233: -#line 2107 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 2107 "cmDependsJavaParser.y" { jpElementStart(4); jpCheckEmpty(4); @@ -4775,22 +4779,22 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4779 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 4783 "cmDependsJavaParser.cxx" break; case 234: -#line 2116 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 2116 "cmDependsJavaParser.y" { jpElementStart(1); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 4790 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 4794 "cmDependsJavaParser.cxx" break; case 235: -#line 2124 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 2124 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -4798,11 +4802,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4802 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 4806 "cmDependsJavaParser.cxx" break; case 236: -#line 2134 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 2134 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -4810,11 +4814,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4814 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 4818 "cmDependsJavaParser.cxx" break; case 237: -#line 2143 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 2143 "cmDependsJavaParser.y" { jpElementStart(2); jpCheckEmpty(2); @@ -4822,20 +4826,20 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4826 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 4830 "cmDependsJavaParser.cxx" break; case 238: -#line 2153 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 2153 "cmDependsJavaParser.y" { jpElementStart(5); } -#line 4835 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 4839 "cmDependsJavaParser.cxx" break; case 239: -#line 2160 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 2160 "cmDependsJavaParser.y" { jpElementStart(2); jpCheckEmpty(2); @@ -4843,11 +4847,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4847 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 4851 "cmDependsJavaParser.cxx" break; case 240: -#line 2170 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 2170 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -4855,11 +4859,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4859 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 4863 "cmDependsJavaParser.cxx" break; case 241: -#line 2179 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 2179 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -4867,11 +4871,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4871 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 4875 "cmDependsJavaParser.cxx" break; case 242: -#line 2189 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 2189 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -4879,20 +4883,20 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4883 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 4887 "cmDependsJavaParser.cxx" break; case 243: -#line 2198 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 2198 "cmDependsJavaParser.y" { jpElementStart(1); } -#line 4892 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 4896 "cmDependsJavaParser.cxx" break; case 244: -#line 2204 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 2204 "cmDependsJavaParser.y" { jpElementStart(3); jpCheckEmpty(3); @@ -4900,11 +4904,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4904 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 4908 "cmDependsJavaParser.cxx" break; case 245: -#line 2213 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 2213 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -4912,11 +4916,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4916 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 4920 "cmDependsJavaParser.cxx" break; case 246: -#line 2222 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 2222 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -4924,11 +4928,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4928 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 4932 "cmDependsJavaParser.cxx" break; case 247: -#line 2231 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 2231 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -4936,11 +4940,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4940 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 4944 "cmDependsJavaParser.cxx" break; case 248: -#line 2240 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 2240 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -4948,11 +4952,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4952 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 4956 "cmDependsJavaParser.cxx" break; case 249: -#line 2250 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 2250 "cmDependsJavaParser.y" { jpElementStart(6); jpCheckEmpty(6); @@ -4960,22 +4964,22 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4964 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 4968 "cmDependsJavaParser.cxx" break; case 250: -#line 2259 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 2259 "cmDependsJavaParser.y" { jpElementStart(0); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 4975 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 4979 "cmDependsJavaParser.cxx" break; case 251: -#line 2267 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 2267 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -4983,22 +4987,22 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4987 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 4991 "cmDependsJavaParser.cxx" break; case 252: -#line 2276 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 2276 "cmDependsJavaParser.y" { jpElementStart(0); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 4998 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 5002 "cmDependsJavaParser.cxx" break; case 253: -#line 2284 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 2284 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -5006,11 +5010,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5010 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 5014 "cmDependsJavaParser.cxx" break; case 254: -#line 2294 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 2294 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -5018,11 +5022,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5022 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 5026 "cmDependsJavaParser.cxx" break; case 255: -#line 2303 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 2303 "cmDependsJavaParser.y" { jpElementStart(3); jpCheckEmpty(3); @@ -5030,11 +5034,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5034 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 5038 "cmDependsJavaParser.cxx" break; case 256: -#line 2313 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 2313 "cmDependsJavaParser.y" { jpElementStart(4); jpCheckEmpty(4); @@ -5042,11 +5046,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5046 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 5050 "cmDependsJavaParser.cxx" break; case 257: -#line 2322 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 2322 "cmDependsJavaParser.y" { jpElementStart(4); jpCheckEmpty(4); @@ -5054,11 +5058,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5058 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 5062 "cmDependsJavaParser.cxx" break; case 258: -#line 2331 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 2331 "cmDependsJavaParser.y" { jpElementStart(4); jpCheckEmpty(4); @@ -5066,11 +5070,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5070 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 5074 "cmDependsJavaParser.cxx" break; case 259: -#line 2340 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 2340 "cmDependsJavaParser.y" { jpElementStart(4); jpCheckEmpty(4); @@ -5078,22 +5082,22 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5082 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 5086 "cmDependsJavaParser.cxx" break; case 260: -#line 2349 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 2349 "cmDependsJavaParser.y" { jpElementStart(0); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 5093 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 5097 "cmDependsJavaParser.cxx" break; case 261: -#line 2357 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 2357 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -5101,11 +5105,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5105 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 5109 "cmDependsJavaParser.cxx" break; case 262: -#line 2367 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 2367 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -5113,11 +5117,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5117 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 5121 "cmDependsJavaParser.cxx" break; case 263: -#line 2376 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 2376 "cmDependsJavaParser.y" { jpElementStart(2); jpCheckEmpty(2); @@ -5125,11 +5129,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5129 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 5133 "cmDependsJavaParser.cxx" break; case 264: -#line 2386 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 2386 "cmDependsJavaParser.y" { jpElementStart(3); jpCheckEmpty(3); @@ -5137,29 +5141,29 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5141 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 5145 "cmDependsJavaParser.cxx" break; case 265: -#line 2396 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 2396 "cmDependsJavaParser.y" { jpElementStart(2); } -#line 5150 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 5154 "cmDependsJavaParser.cxx" break; case 266: -#line 2402 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 2402 "cmDependsJavaParser.y" { jpElementStart(3); } -#line 5159 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 5163 "cmDependsJavaParser.cxx" break; case 267: -#line 2409 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 2409 "cmDependsJavaParser.y" { jpElementStart(3); yyGetParser->DeallocateParserType(&((yyvsp[0].str))); @@ -5168,11 +5172,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5172 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 5176 "cmDependsJavaParser.cxx" break; case 268: -#line 2419 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 2419 "cmDependsJavaParser.y" { jpElementStart(3); yyGetParser->DeallocateParserType(&((yyvsp[0].str))); @@ -5181,11 +5185,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5185 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 5189 "cmDependsJavaParser.cxx" break; case 269: -#line 2429 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 2429 "cmDependsJavaParser.y" { jpElementStart(3); yyGetParser->DeallocateParserType(&((yyvsp[0].str))); @@ -5194,11 +5198,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5198 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 5202 "cmDependsJavaParser.cxx" break; case 270: -#line 2439 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 2439 "cmDependsJavaParser.y" { jpElementStart(3); yyGetParser->DeallocateParserType(&((yyvsp[0].str))); @@ -5207,11 +5211,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5211 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 5215 "cmDependsJavaParser.cxx" break; case 271: -#line 2450 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 2450 "cmDependsJavaParser.y" { jpElementStart(4); yyGetParser->DeallocateParserType(&((yyvsp[-3].str))); @@ -5220,11 +5224,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5224 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 5228 "cmDependsJavaParser.cxx" break; case 272: -#line 2460 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 2460 "cmDependsJavaParser.y" { jpElementStart(6); yyGetParser->DeallocateParserType(&((yyvsp[-5].str))); @@ -5234,11 +5238,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5238 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 5242 "cmDependsJavaParser.cxx" break; case 273: -#line 2471 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 2471 "cmDependsJavaParser.y" { jpElementStart(6); yyGetParser->DeallocateParserType(&((yyvsp[-3].str))); @@ -5247,11 +5251,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5251 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 5255 "cmDependsJavaParser.cxx" break; case 274: -#line 2481 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 2481 "cmDependsJavaParser.y" { jpElementStart(6); yyGetParser->DeallocateParserType(&((yyvsp[-3].str))); @@ -5260,11 +5264,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5264 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 5268 "cmDependsJavaParser.cxx" break; case 275: -#line 2492 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 2492 "cmDependsJavaParser.y" { jpElementStart(4); yyGetParser->DeallocateParserType(&((yyvsp[-3].str))); @@ -5273,11 +5277,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5277 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 5281 "cmDependsJavaParser.cxx" break; case 276: -#line 2502 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 2502 "cmDependsJavaParser.y" { jpElementStart(4); jpCheckEmpty(4); @@ -5285,11 +5289,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5289 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 5293 "cmDependsJavaParser.cxx" break; case 277: -#line 2512 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 2512 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -5297,11 +5301,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5301 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 5305 "cmDependsJavaParser.cxx" break; case 278: -#line 2521 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 2521 "cmDependsJavaParser.y" { jpElementStart(1); yyGetParser->DeallocateParserType(&((yyvsp[0].str))); @@ -5309,11 +5313,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5313 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 5317 "cmDependsJavaParser.cxx" break; case 279: -#line 2530 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 2530 "cmDependsJavaParser.y" { jpElementStart(3); jpCheckEmpty(3); @@ -5321,11 +5325,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5325 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 5329 "cmDependsJavaParser.cxx" break; case 280: -#line 2539 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 2539 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -5333,11 +5337,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5337 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 5341 "cmDependsJavaParser.cxx" break; case 281: -#line 2548 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 2548 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -5345,11 +5349,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5349 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 5353 "cmDependsJavaParser.cxx" break; case 282: -#line 2558 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 2558 "cmDependsJavaParser.y" { jpElementStart(2); jpCheckEmpty(2); @@ -5357,11 +5361,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5361 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 5365 "cmDependsJavaParser.cxx" break; case 283: -#line 2568 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 2568 "cmDependsJavaParser.y" { jpElementStart(2); jpCheckEmpty(2); @@ -5369,11 +5373,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5373 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 5377 "cmDependsJavaParser.cxx" break; case 284: -#line 2578 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 2578 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -5381,11 +5385,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5385 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 5389 "cmDependsJavaParser.cxx" break; case 285: -#line 2587 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 2587 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -5393,11 +5397,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5397 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 5401 "cmDependsJavaParser.cxx" break; case 286: -#line 2596 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 2596 "cmDependsJavaParser.y" { jpElementStart(2); jpCheckEmpty(2); @@ -5405,11 +5409,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5409 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 5413 "cmDependsJavaParser.cxx" break; case 287: -#line 2605 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 2605 "cmDependsJavaParser.y" { jpElementStart(2); jpCheckEmpty(2); @@ -5417,11 +5421,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5421 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 5425 "cmDependsJavaParser.cxx" break; case 288: -#line 2614 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 2614 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -5429,11 +5433,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5433 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 5437 "cmDependsJavaParser.cxx" break; case 289: -#line 2624 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 2624 "cmDependsJavaParser.y" { jpElementStart(2); jpCheckEmpty(2); @@ -5441,11 +5445,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5445 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 5449 "cmDependsJavaParser.cxx" break; case 290: -#line 2634 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 2634 "cmDependsJavaParser.y" { jpElementStart(2); jpCheckEmpty(2); @@ -5453,11 +5457,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5457 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 5461 "cmDependsJavaParser.cxx" break; case 291: -#line 2644 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 2644 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -5465,11 +5469,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5469 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 5473 "cmDependsJavaParser.cxx" break; case 292: -#line 2653 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 2653 "cmDependsJavaParser.y" { jpElementStart(2); jpCheckEmpty(2); @@ -5477,11 +5481,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5481 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 5485 "cmDependsJavaParser.cxx" break; case 293: -#line 2662 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 2662 "cmDependsJavaParser.y" { jpElementStart(2); jpCheckEmpty(2); @@ -5489,11 +5493,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5493 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 5497 "cmDependsJavaParser.cxx" break; case 294: -#line 2671 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 2671 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -5501,11 +5505,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5505 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 5509 "cmDependsJavaParser.cxx" break; case 295: -#line 2681 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 2681 "cmDependsJavaParser.y" { jpElementStart(5); jpCheckEmpty(5); @@ -5513,11 +5517,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5517 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 5521 "cmDependsJavaParser.cxx" break; case 296: -#line 2690 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 2690 "cmDependsJavaParser.y" { jpElementStart(4); jpCheckEmpty(4); @@ -5525,20 +5529,20 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5529 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 5533 "cmDependsJavaParser.cxx" break; case 297: -#line 2699 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 2699 "cmDependsJavaParser.y" { jpElementStart(5); } -#line 5538 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 5542 "cmDependsJavaParser.cxx" break; case 298: -#line 2706 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 2706 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -5546,11 +5550,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5550 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 5554 "cmDependsJavaParser.cxx" break; case 299: -#line 2715 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 2715 "cmDependsJavaParser.y" { jpElementStart(3); jpCheckEmpty(3); @@ -5558,11 +5562,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5562 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 5566 "cmDependsJavaParser.cxx" break; case 300: -#line 2724 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 2724 "cmDependsJavaParser.y" { jpElementStart(3); jpCheckEmpty(3); @@ -5570,11 +5574,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5574 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 5578 "cmDependsJavaParser.cxx" break; case 301: -#line 2733 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 2733 "cmDependsJavaParser.y" { jpElementStart(3); jpCheckEmpty(3); @@ -5582,11 +5586,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5586 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 5590 "cmDependsJavaParser.cxx" break; case 302: -#line 2743 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 2743 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -5594,11 +5598,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5598 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 5602 "cmDependsJavaParser.cxx" break; case 303: -#line 2752 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 2752 "cmDependsJavaParser.y" { jpElementStart(3); jpCheckEmpty(3); @@ -5606,11 +5610,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5610 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 5614 "cmDependsJavaParser.cxx" break; case 304: -#line 2761 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 2761 "cmDependsJavaParser.y" { jpElementStart(3); jpCheckEmpty(3); @@ -5618,11 +5622,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5622 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 5626 "cmDependsJavaParser.cxx" break; case 305: -#line 2771 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 2771 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -5630,11 +5634,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5634 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 5638 "cmDependsJavaParser.cxx" break; case 306: -#line 2780 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 2780 "cmDependsJavaParser.y" { jpElementStart(3); jpCheckEmpty(3); @@ -5642,11 +5646,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5646 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 5650 "cmDependsJavaParser.cxx" break; case 307: -#line 2789 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 2789 "cmDependsJavaParser.y" { jpElementStart(3); jpCheckEmpty(3); @@ -5654,11 +5658,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5658 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 5662 "cmDependsJavaParser.cxx" break; case 308: -#line 2798 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 2798 "cmDependsJavaParser.y" { jpElementStart(3); jpCheckEmpty(3); @@ -5666,11 +5670,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5670 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 5674 "cmDependsJavaParser.cxx" break; case 309: -#line 2808 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 2808 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -5678,11 +5682,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5682 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 5686 "cmDependsJavaParser.cxx" break; case 310: -#line 2817 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 2817 "cmDependsJavaParser.y" { jpElementStart(3); jpCheckEmpty(3); @@ -5690,11 +5694,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5694 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 5698 "cmDependsJavaParser.cxx" break; case 311: -#line 2826 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 2826 "cmDependsJavaParser.y" { jpElementStart(3); jpCheckEmpty(3); @@ -5702,11 +5706,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5706 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 5710 "cmDependsJavaParser.cxx" break; case 312: -#line 2835 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 2835 "cmDependsJavaParser.y" { jpElementStart(3); jpCheckEmpty(3); @@ -5714,11 +5718,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5718 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 5722 "cmDependsJavaParser.cxx" break; case 313: -#line 2844 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 2844 "cmDependsJavaParser.y" { jpElementStart(3); jpCheckEmpty(3); @@ -5726,11 +5730,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5730 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 5734 "cmDependsJavaParser.cxx" break; case 314: -#line 2853 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 2853 "cmDependsJavaParser.y" { jpElementStart(3); jpCheckEmpty(3); @@ -5738,11 +5742,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5742 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 5746 "cmDependsJavaParser.cxx" break; case 315: -#line 2863 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 2863 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -5750,11 +5754,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5754 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 5758 "cmDependsJavaParser.cxx" break; case 316: -#line 2872 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 2872 "cmDependsJavaParser.y" { jpElementStart(3); jpCheckEmpty(3); @@ -5762,11 +5766,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5766 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 5770 "cmDependsJavaParser.cxx" break; case 317: -#line 2881 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 2881 "cmDependsJavaParser.y" { jpElementStart(3); jpCheckEmpty(3); @@ -5774,11 +5778,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5778 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 5782 "cmDependsJavaParser.cxx" break; case 318: -#line 2891 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 2891 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -5786,11 +5790,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5790 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 5794 "cmDependsJavaParser.cxx" break; case 319: -#line 2900 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 2900 "cmDependsJavaParser.y" { jpElementStart(3); jpCheckEmpty(3); @@ -5798,11 +5802,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5802 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 5806 "cmDependsJavaParser.cxx" break; case 320: -#line 2910 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 2910 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -5810,11 +5814,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5814 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 5818 "cmDependsJavaParser.cxx" break; case 321: -#line 2919 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 2919 "cmDependsJavaParser.y" { jpElementStart(3); jpCheckEmpty(3); @@ -5822,11 +5826,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5826 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 5830 "cmDependsJavaParser.cxx" break; case 322: -#line 2929 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 2929 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -5834,11 +5838,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5838 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 5842 "cmDependsJavaParser.cxx" break; case 323: -#line 2938 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 2938 "cmDependsJavaParser.y" { jpElementStart(3); jpCheckEmpty(3); @@ -5846,11 +5850,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5850 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 5854 "cmDependsJavaParser.cxx" break; case 324: -#line 2948 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 2948 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -5858,11 +5862,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5862 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 5866 "cmDependsJavaParser.cxx" break; case 325: -#line 2957 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 2957 "cmDependsJavaParser.y" { jpElementStart(3); jpCheckEmpty(3); @@ -5870,11 +5874,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5874 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 5878 "cmDependsJavaParser.cxx" break; case 326: -#line 2967 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 2967 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -5882,11 +5886,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5886 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 5890 "cmDependsJavaParser.cxx" break; case 327: -#line 2976 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 2976 "cmDependsJavaParser.y" { jpElementStart(3); jpCheckEmpty(3); @@ -5894,11 +5898,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5898 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 5902 "cmDependsJavaParser.cxx" break; case 328: -#line 2986 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 2986 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -5906,11 +5910,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5910 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 5914 "cmDependsJavaParser.cxx" break; case 329: -#line 2995 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 2995 "cmDependsJavaParser.y" { jpElementStart(5); jpCheckEmpty(5); @@ -5918,11 +5922,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5922 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 5926 "cmDependsJavaParser.cxx" break; case 330: -#line 3005 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 3005 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -5930,11 +5934,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5934 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 5938 "cmDependsJavaParser.cxx" break; case 331: -#line 3014 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 3014 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -5942,11 +5946,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5946 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 5950 "cmDependsJavaParser.cxx" break; case 332: -#line 3024 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 3024 "cmDependsJavaParser.y" { jpElementStart(3); jpCheckEmpty(3); @@ -5954,11 +5958,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5958 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 5962 "cmDependsJavaParser.cxx" break; case 333: -#line 3034 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 3034 "cmDependsJavaParser.y" { jpElementStart(1); yyGetParser->DeallocateParserType(&((yyvsp[0].str))); @@ -5967,11 +5971,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5971 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 5975 "cmDependsJavaParser.cxx" break; case 334: -#line 3044 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 3044 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -5979,11 +5983,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5983 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 5987 "cmDependsJavaParser.cxx" break; case 335: -#line 3053 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 3053 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -5991,11 +5995,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5995 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 5999 "cmDependsJavaParser.cxx" break; case 336: -#line 3063 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 3063 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -6003,11 +6007,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 6007 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 6011 "cmDependsJavaParser.cxx" break; case 337: -#line 3072 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 3072 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -6015,11 +6019,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 6019 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 6023 "cmDependsJavaParser.cxx" break; case 338: -#line 3081 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 3081 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -6027,11 +6031,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 6031 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 6035 "cmDependsJavaParser.cxx" break; case 339: -#line 3090 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 3090 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -6039,11 +6043,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 6043 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 6047 "cmDependsJavaParser.cxx" break; case 340: -#line 3099 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 3099 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -6051,11 +6055,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 6055 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 6059 "cmDependsJavaParser.cxx" break; case 341: -#line 3108 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 3108 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -6063,11 +6067,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 6067 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 6071 "cmDependsJavaParser.cxx" break; case 342: -#line 3117 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 3117 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -6075,11 +6079,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 6079 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 6083 "cmDependsJavaParser.cxx" break; case 343: -#line 3126 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 3126 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -6087,11 +6091,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 6091 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 6095 "cmDependsJavaParser.cxx" break; case 344: -#line 3135 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 3135 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -6099,11 +6103,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 6103 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 6107 "cmDependsJavaParser.cxx" break; case 345: -#line 3144 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 3144 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -6111,11 +6115,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 6115 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 6119 "cmDependsJavaParser.cxx" break; case 346: -#line 3153 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 3153 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -6123,11 +6127,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 6127 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 6131 "cmDependsJavaParser.cxx" break; case 347: -#line 3162 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 3162 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -6135,11 +6139,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 6139 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 6143 "cmDependsJavaParser.cxx" break; case 348: -#line 3172 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 3172 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -6147,11 +6151,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 6151 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 6155 "cmDependsJavaParser.cxx" break; case 349: -#line 3182 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 3182 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -6159,11 +6163,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 6163 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 6167 "cmDependsJavaParser.cxx" break; case 350: -#line 3192 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 3192 "cmDependsJavaParser.y" { jpElementStart(1); jpCheckEmpty(1); @@ -6171,11 +6175,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 6175 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 6179 "cmDependsJavaParser.cxx" break; case 351: -#line 3201 "cmDependsJavaParser.y" /* yacc.c:1652 */ +#line 3201 "cmDependsJavaParser.y" { jpElementStart(3); jpStoreClass((yyvsp[-2].str)); @@ -6184,11 +6188,12 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 6188 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 6192 "cmDependsJavaParser.cxx" break; -#line 6192 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ +#line 6196 "cmDependsJavaParser.cxx" + default: break; } /* User semantic actions sometimes alter yychar, and that requires @@ -6421,7 +6426,7 @@ yyreturn: #endif return yyresult; } -#line 3210 "cmDependsJavaParser.y" /* yacc.c:1918 */ +#line 3210 "cmDependsJavaParser.y" /* End of grammar */ diff --git a/Source/LexerParser/cmDependsJavaParserTokens.h b/Source/LexerParser/cmDependsJavaParserTokens.h index 6bbc084..e0dfa01 100644 --- a/Source/LexerParser/cmDependsJavaParserTokens.h +++ b/Source/LexerParser/cmDependsJavaParserTokens.h @@ -1,4 +1,4 @@ -/* A Bison parser, made by GNU Bison 3.3.2. */ +/* A Bison parser, made by GNU Bison 3.4.2. */ /* Bison interface for Yacc-like parsers in C diff --git a/Source/LexerParser/cmExprParser.cxx b/Source/LexerParser/cmExprParser.cxx index 8416e72..562b35b 100644 --- a/Source/LexerParser/cmExprParser.cxx +++ b/Source/LexerParser/cmExprParser.cxx @@ -1,4 +1,4 @@ -/* A Bison parser, made by GNU Bison 3.3.2. */ +/* A Bison parser, made by GNU Bison 3.4.2. */ /* Bison implementation for Yacc-like parsers in C @@ -48,7 +48,7 @@ #define YYBISON 1 /* Bison version. */ -#define YYBISON_VERSION "3.3.2" +#define YYBISON_VERSION "3.4.2" /* Skeleton name. */ #define YYSKELETON_NAME "yacc.c" @@ -72,7 +72,7 @@ /* First part of user prologue. */ -#line 1 "cmExprParser.y" /* yacc.c:337 */ +#line 1 "cmExprParser.y" /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ @@ -116,7 +116,8 @@ static void cmExpr_yyerror(yyscan_t yyscanner, const char* message); # pragma GCC diagnostic ignored "-Wconversion" #endif -#line 120 "cmExprParser.cxx" /* yacc.c:337 */ +#line 120 "cmExprParser.cxx" + # ifndef YY_NULLPTR # if defined __cplusplus # if 201103L <= __cplusplus @@ -137,8 +138,8 @@ static void cmExpr_yyerror(yyscan_t yyscanner, const char* message); # define YYERROR_VERBOSE 1 #endif -/* In a future release of Bison, this section will be replaced - by #include "cmExprParserTokens.h". */ +/* Use api.header.include to #include this header + instead of duplicating it here. */ #ifndef YY_CMEXPR_YY_CMEXPRPARSERTOKENS_H_INCLUDED # define YY_CMEXPR_YY_CMEXPRPARSERTOKENS_H_INCLUDED /* Debug traces. */ @@ -296,6 +297,8 @@ typedef short yytype_int16; #endif +#define YY_ASSERT(E) ((void) (0 && (E))) + #if ! defined yyoverflow || YYERROR_VERBOSE /* The parser invokes alloca or malloc; define the necessary symbols. */ @@ -688,7 +691,9 @@ yy_symbol_value_print (FILE *yyo, int yytype, YYSTYPE const * const yyvaluep, yy if (yytype < YYNTOKENS) YYPRINT (yyo, yytoknum[yytype], *yyvaluep); # endif + YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN YYUSE (yytype); + YY_IGNORE_MAYBE_UNINITIALIZED_END } @@ -1126,6 +1131,8 @@ yynewstate: | yynewstate -- set current state (the top of the stack) to yystate. | `--------------------------------------------------------------------*/ yysetstate: + YYDPRINTF ((stderr, "Entering state %d\n", yystate)); + YY_ASSERT (0 <= yystate && yystate < YYNSTATES); *yyssp = (yytype_int16) yystate; if (yyss + yystacksize - 1 <= yyssp) @@ -1188,8 +1195,6 @@ yysetstate: } #endif /* !defined yyoverflow && !defined YYSTACK_RELOCATE */ - YYDPRINTF ((stderr, "Entering state %d\n", yystate)); - if (yystate == YYFINAL) YYACCEPT; @@ -1257,7 +1262,6 @@ yybackup: YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN *++yyvsp = yylval; YY_IGNORE_MAYBE_UNINITIALIZED_END - goto yynewstate; @@ -1292,195 +1296,196 @@ yyreduce: YY_REDUCE_PRINT (yyn); switch (yyn) { - case 2: -#line 77 "cmExprParser.y" /* yacc.c:1652 */ + case 2: +#line 77 "cmExprParser.y" { cmExpr_yyget_extra(yyscanner)->SetResult((yyvsp[0].Number)); } -#line 1301 "cmExprParser.cxx" /* yacc.c:1652 */ +#line 1305 "cmExprParser.cxx" break; case 3: -#line 82 "cmExprParser.y" /* yacc.c:1652 */ +#line 82 "cmExprParser.y" { (yyval.Number) = (yyvsp[0].Number); } -#line 1309 "cmExprParser.cxx" /* yacc.c:1652 */ +#line 1313 "cmExprParser.cxx" break; case 4: -#line 85 "cmExprParser.y" /* yacc.c:1652 */ +#line 85 "cmExprParser.y" { (yyval.Number) = (yyvsp[-2].Number) | (yyvsp[0].Number); } -#line 1317 "cmExprParser.cxx" /* yacc.c:1652 */ +#line 1321 "cmExprParser.cxx" break; case 5: -#line 90 "cmExprParser.y" /* yacc.c:1652 */ +#line 90 "cmExprParser.y" { (yyval.Number) = (yyvsp[0].Number); } -#line 1325 "cmExprParser.cxx" /* yacc.c:1652 */ +#line 1329 "cmExprParser.cxx" break; case 6: -#line 93 "cmExprParser.y" /* yacc.c:1652 */ +#line 93 "cmExprParser.y" { (yyval.Number) = (yyvsp[-2].Number) ^ (yyvsp[0].Number); } -#line 1333 "cmExprParser.cxx" /* yacc.c:1652 */ +#line 1337 "cmExprParser.cxx" break; case 7: -#line 98 "cmExprParser.y" /* yacc.c:1652 */ +#line 98 "cmExprParser.y" { (yyval.Number) = (yyvsp[0].Number); } -#line 1341 "cmExprParser.cxx" /* yacc.c:1652 */ +#line 1345 "cmExprParser.cxx" break; case 8: -#line 101 "cmExprParser.y" /* yacc.c:1652 */ +#line 101 "cmExprParser.y" { (yyval.Number) = (yyvsp[-2].Number) & (yyvsp[0].Number); } -#line 1349 "cmExprParser.cxx" /* yacc.c:1652 */ +#line 1353 "cmExprParser.cxx" break; case 9: -#line 106 "cmExprParser.y" /* yacc.c:1652 */ +#line 106 "cmExprParser.y" { (yyval.Number) = (yyvsp[0].Number); } -#line 1357 "cmExprParser.cxx" /* yacc.c:1652 */ +#line 1361 "cmExprParser.cxx" break; case 10: -#line 109 "cmExprParser.y" /* yacc.c:1652 */ +#line 109 "cmExprParser.y" { (yyval.Number) = (yyvsp[-2].Number) << (yyvsp[0].Number); } -#line 1365 "cmExprParser.cxx" /* yacc.c:1652 */ +#line 1369 "cmExprParser.cxx" break; case 11: -#line 112 "cmExprParser.y" /* yacc.c:1652 */ +#line 112 "cmExprParser.y" { (yyval.Number) = (yyvsp[-2].Number) >> (yyvsp[0].Number); } -#line 1373 "cmExprParser.cxx" /* yacc.c:1652 */ +#line 1377 "cmExprParser.cxx" break; case 12: -#line 117 "cmExprParser.y" /* yacc.c:1652 */ +#line 117 "cmExprParser.y" { (yyval.Number) = (yyvsp[0].Number); } -#line 1381 "cmExprParser.cxx" /* yacc.c:1652 */ +#line 1385 "cmExprParser.cxx" break; case 13: -#line 120 "cmExprParser.y" /* yacc.c:1652 */ +#line 120 "cmExprParser.y" { (yyval.Number) = (yyvsp[-2].Number) + (yyvsp[0].Number); } -#line 1389 "cmExprParser.cxx" /* yacc.c:1652 */ +#line 1393 "cmExprParser.cxx" break; case 14: -#line 123 "cmExprParser.y" /* yacc.c:1652 */ +#line 123 "cmExprParser.y" { (yyval.Number) = (yyvsp[-2].Number) - (yyvsp[0].Number); } -#line 1397 "cmExprParser.cxx" /* yacc.c:1652 */ +#line 1401 "cmExprParser.cxx" break; case 15: -#line 128 "cmExprParser.y" /* yacc.c:1652 */ +#line 128 "cmExprParser.y" { (yyval.Number) = (yyvsp[0].Number); } -#line 1405 "cmExprParser.cxx" /* yacc.c:1652 */ +#line 1409 "cmExprParser.cxx" break; case 16: -#line 131 "cmExprParser.y" /* yacc.c:1652 */ +#line 131 "cmExprParser.y" { (yyval.Number) = (yyvsp[-2].Number) * (yyvsp[0].Number); } -#line 1413 "cmExprParser.cxx" /* yacc.c:1652 */ +#line 1417 "cmExprParser.cxx" break; case 17: -#line 134 "cmExprParser.y" /* yacc.c:1652 */ +#line 134 "cmExprParser.y" { if (yyvsp[0].Number == 0) { throw std::overflow_error("divide by zero"); } (yyval.Number) = (yyvsp[-2].Number) / (yyvsp[0].Number); } -#line 1424 "cmExprParser.cxx" /* yacc.c:1652 */ +#line 1428 "cmExprParser.cxx" break; case 18: -#line 140 "cmExprParser.y" /* yacc.c:1652 */ +#line 140 "cmExprParser.y" { (yyval.Number) = (yyvsp[-2].Number) % (yyvsp[0].Number); } -#line 1432 "cmExprParser.cxx" /* yacc.c:1652 */ +#line 1436 "cmExprParser.cxx" break; case 19: -#line 145 "cmExprParser.y" /* yacc.c:1652 */ +#line 145 "cmExprParser.y" { (yyval.Number) = (yyvsp[0].Number); } -#line 1440 "cmExprParser.cxx" /* yacc.c:1652 */ +#line 1444 "cmExprParser.cxx" break; case 20: -#line 148 "cmExprParser.y" /* yacc.c:1652 */ +#line 148 "cmExprParser.y" { (yyval.Number) = + (yyvsp[0].Number); } -#line 1448 "cmExprParser.cxx" /* yacc.c:1652 */ +#line 1452 "cmExprParser.cxx" break; case 21: -#line 151 "cmExprParser.y" /* yacc.c:1652 */ +#line 151 "cmExprParser.y" { (yyval.Number) = - (yyvsp[0].Number); } -#line 1456 "cmExprParser.cxx" /* yacc.c:1652 */ +#line 1460 "cmExprParser.cxx" break; case 22: -#line 154 "cmExprParser.y" /* yacc.c:1652 */ +#line 154 "cmExprParser.y" { (yyval.Number) = ~ (yyvsp[0].Number); } -#line 1464 "cmExprParser.cxx" /* yacc.c:1652 */ +#line 1468 "cmExprParser.cxx" break; case 23: -#line 159 "cmExprParser.y" /* yacc.c:1652 */ +#line 159 "cmExprParser.y" { (yyval.Number) = (yyvsp[0].Number); } -#line 1472 "cmExprParser.cxx" /* yacc.c:1652 */ +#line 1476 "cmExprParser.cxx" break; case 24: -#line 162 "cmExprParser.y" /* yacc.c:1652 */ +#line 162 "cmExprParser.y" { (yyval.Number) = (yyvsp[-1].Number); } -#line 1480 "cmExprParser.cxx" /* yacc.c:1652 */ +#line 1484 "cmExprParser.cxx" break; -#line 1484 "cmExprParser.cxx" /* yacc.c:1652 */ +#line 1488 "cmExprParser.cxx" + default: break; } /* User semantic actions sometimes alter yychar, and that requires @@ -1713,7 +1718,7 @@ yyreturn: #endif return yyresult; } -#line 167 "cmExprParser.y" /* yacc.c:1918 */ +#line 167 "cmExprParser.y" /* End of grammar */ diff --git a/Source/LexerParser/cmExprParserTokens.h b/Source/LexerParser/cmExprParserTokens.h index 5ffd7c5..e30a832 100644 --- a/Source/LexerParser/cmExprParserTokens.h +++ b/Source/LexerParser/cmExprParserTokens.h @@ -1,4 +1,4 @@ -/* A Bison parser, made by GNU Bison 3.3.2. */ +/* A Bison parser, made by GNU Bison 3.4.2. */ /* Bison interface for Yacc-like parsers in C diff --git a/Source/LexerParser/cmFortranParser.cxx b/Source/LexerParser/cmFortranParser.cxx index 2ca7927..2494aad 100644 --- a/Source/LexerParser/cmFortranParser.cxx +++ b/Source/LexerParser/cmFortranParser.cxx @@ -1,4 +1,4 @@ -/* A Bison parser, made by GNU Bison 3.3.2. */ +/* A Bison parser, made by GNU Bison 3.4.2. */ /* Bison implementation for Yacc-like parsers in C @@ -48,7 +48,7 @@ #define YYBISON 1 /* Bison version. */ -#define YYBISON_VERSION "3.3.2" +#define YYBISON_VERSION "3.4.2" /* Skeleton name. */ #define YYSKELETON_NAME "yacc.c" @@ -72,7 +72,7 @@ /* First part of user prologue. */ -#line 1 "cmFortranParser.y" /* yacc.c:337 */ +#line 1 "cmFortranParser.y" /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ @@ -135,7 +135,8 @@ static void cmFortran_yyerror(yyscan_t yyscanner, const char* message) # pragma GCC diagnostic ignored "-Wconversion" #endif -#line 139 "cmFortranParser.cxx" /* yacc.c:337 */ +#line 139 "cmFortranParser.cxx" + # ifndef YY_NULLPTR # if defined __cplusplus # if 201103L <= __cplusplus @@ -156,8 +157,8 @@ static void cmFortran_yyerror(yyscan_t yyscanner, const char* message) # define YYERROR_VERBOSE 1 #endif -/* In a future release of Bison, this section will be replaced - by #include "cmFortranParserTokens.h". */ +/* Use api.header.include to #include this header + instead of duplicating it here. */ #ifndef YY_CMFORTRAN_YY_CMFORTRANPARSERTOKENS_H_INCLUDED # define YY_CMFORTRAN_YY_CMFORTRANPARSERTOKENS_H_INCLUDED /* Debug traces. */ @@ -255,16 +256,15 @@ extern int cmFortran_yydebug; /* Value type. */ #if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED - union YYSTYPE { -#line 73 "cmFortranParser.y" /* yacc.c:352 */ +#line 73 "cmFortranParser.y" char* string; -#line 266 "cmFortranParser.cxx" /* yacc.c:352 */ -}; +#line 266 "cmFortranParser.cxx" +}; typedef union YYSTYPE YYSTYPE; # define YYSTYPE_IS_TRIVIAL 1 # define YYSTYPE_IS_DECLARED 1 @@ -378,6 +378,8 @@ typedef short yytype_int16; #endif +#define YY_ASSERT(E) ((void) (0 && (E))) + #if ! defined yyoverflow || YYERROR_VERBOSE /* The parser invokes alloca or malloc; define the necessary symbols. */ @@ -509,16 +511,16 @@ union yyalloc /* YYFINAL -- State number of the termination state. */ #define YYFINAL 2 /* YYLAST -- Last index in YYTABLE. */ -#define YYLAST 593 +#define YYLAST 594 /* YYNTOKENS -- Number of terminals. */ #define YYNTOKENS 41 /* YYNNTS -- Number of nonterminals. */ #define YYNNTS 14 /* YYNRULES -- Number of rules. */ -#define YYNRULES 63 +#define YYNRULES 64 /* YYNSTATES -- Number of states. */ -#define YYNSTATES 126 +#define YYNSTATES 127 #define YYUNDEFTOK 2 #define YYMAXUTOK 295 @@ -574,7 +576,7 @@ static const yytype_uint8 yyrline[] = 220, 220, 221, 221, 222, 222, 223, 223, 224, 224, 225, 225, 226, 226, 227, 227, 228, 228, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, - 243, 244, 245, 246 + 243, 244, 245, 246, 247 }; #endif @@ -626,16 +628,16 @@ static const yytype_int16 yypact[] = -39, 21, -39, 1, -39, -20, -39, -39, -39, -39, -39, -39, -39, -39, -39, -39, -39, -39, -39, -39, -39, -39, -39, -39, -39, -39, -24, -18, 20, -8, - -3, 39, -39, 15, 16, 18, 19, 33, -39, -39, + -3, 40, -39, 15, 16, 17, 19, 34, -39, -39, -39, -39, -39, -39, 59, -39, -39, -39, -39, -39, - 35, 36, 37, -39, -39, -39, -39, -39, -39, 76, - 114, 129, 167, 182, -39, -39, -39, -39, -39, -39, + 36, 37, 38, -39, -39, -39, -39, -39, -39, 77, + 115, 130, 168, 183, -39, -39, -39, -39, -39, -39, -39, -39, -39, -39, -39, -39, -39, -39, -39, -39, - -39, -39, 220, 235, 273, 288, -21, 26, -39, 326, - 341, 379, 394, 432, 447, -39, -39, -39, -39, -39, - -39, -39, -39, -39, 38, 40, 41, 485, -39, -39, - -39, -39, -39, -39, 45, -39, -39, -39, 43, 500, - 538, -39, -39, -39, 553, -39 + -39, -39, -39, 221, 236, 274, 289, -21, 26, -39, + 327, 342, 380, 395, 433, 448, -39, -39, -39, -39, + -39, -39, -39, -39, -39, 39, 41, 42, 486, -39, + -39, -39, -39, -39, -39, 18, -39, -39, -39, 43, + 501, 539, -39, -39, -39, 554, -39 }; /* YYDEFACT[STATE-NUM] -- Default reduction number in state STATE-NUM. @@ -649,13 +651,13 @@ static const yytype_uint8 yydefact[] = 0, 0, 3, 0, 0, 0, 0, 0, 46, 46, 46, 46, 26, 46, 0, 46, 46, 4, 46, 46, 0, 0, 0, 46, 46, 46, 46, 46, 46, 0, - 0, 0, 0, 0, 15, 57, 56, 62, 58, 59, - 60, 61, 63, 55, 48, 49, 50, 51, 52, 53, - 54, 47, 0, 0, 0, 0, 0, 0, 46, 0, - 0, 0, 0, 0, 0, 21, 22, 23, 24, 14, - 10, 13, 9, 6, 0, 0, 0, 0, 5, 16, - 17, 18, 19, 20, 0, 46, 46, 11, 0, 0, - 0, 46, 7, 12, 0, 8 + 0, 0, 0, 0, 15, 57, 56, 64, 62, 58, + 59, 60, 61, 63, 55, 48, 49, 50, 51, 52, + 53, 54, 47, 0, 0, 0, 0, 0, 0, 46, + 0, 0, 0, 0, 0, 0, 21, 22, 23, 24, + 14, 10, 13, 9, 6, 0, 0, 0, 0, 5, + 16, 17, 18, 19, 20, 0, 46, 46, 11, 0, + 0, 0, 46, 7, 12, 0, 8 }; /* YYPGOTO[NTERM-NUM]. */ @@ -669,7 +671,7 @@ static const yytype_int8 yypgoto[] = static const yytype_int8 yydefgoto[] = { -1, 1, 32, 33, 34, 35, 36, 37, 38, 39, - 40, 41, 44, 81 + 40, 41, 44, 82 }; /* YYTABLE[YYPACT[STATE-NUM]] -- What to do in state STATE-NUM. If @@ -677,66 +679,66 @@ static const yytype_int8 yydefgoto[] = number is the opposite. If YYTABLE_NINF, syntax error. */ static const yytype_uint8 yytable[] = { - 59, 60, 61, 62, 42, 63, 104, 82, 83, 105, - 84, 85, 43, 45, 46, 89, 90, 91, 92, 93, - 94, 2, 3, 47, 4, 49, 50, 5, 6, 7, + 59, 60, 61, 62, 42, 63, 105, 83, 84, 106, + 85, 86, 43, 45, 46, 90, 91, 92, 93, 94, + 95, 2, 3, 47, 4, 49, 50, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, - 18, 19, 20, 21, 22, 23, 24, 54, 0, 55, - 107, 56, 57, 48, 106, 25, 26, 27, 28, 29, - 30, 31, 64, 65, 66, 51, 58, 52, 86, 87, - 88, 114, 53, 115, 116, 118, 121, 119, 120, 95, - 65, 66, 0, 124, 0, 67, 68, 69, 70, 71, - 72, 73, 74, 0, 75, 76, 77, 78, 79, 80, - 0, 0, 67, 68, 69, 70, 71, 72, 73, 74, - 0, 75, 76, 77, 78, 79, 80, 96, 65, 66, + 18, 19, 20, 21, 22, 23, 24, 54, 119, 55, + 56, 108, 57, 48, 107, 25, 26, 27, 28, 29, + 30, 31, 64, 65, 66, 67, 51, 58, 52, 87, + 88, 89, 115, 53, 116, 117, 122, 0, 120, 121, + 96, 65, 66, 67, 125, 68, 69, 70, 71, 72, + 73, 74, 75, 0, 76, 77, 78, 79, 80, 81, + 0, 0, 0, 68, 69, 70, 71, 72, 73, 74, + 75, 0, 76, 77, 78, 79, 80, 81, 97, 65, + 66, 67, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 98, 65, 66, 67, 0, 0, 0, + 0, 68, 69, 70, 71, 72, 73, 74, 75, 0, + 76, 77, 78, 79, 80, 81, 68, 69, 70, 71, + 72, 73, 74, 75, 0, 76, 77, 78, 79, 80, + 81, 99, 65, 66, 67, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 100, 65, 66, 67, + 0, 0, 0, 0, 68, 69, 70, 71, 72, 73, + 74, 75, 0, 76, 77, 78, 79, 80, 81, 68, + 69, 70, 71, 72, 73, 74, 75, 0, 76, 77, + 78, 79, 80, 81, 101, 65, 66, 67, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 102, + 65, 66, 67, 0, 0, 0, 0, 68, 69, 70, + 71, 72, 73, 74, 75, 0, 76, 77, 78, 79, + 80, 81, 68, 69, 70, 71, 72, 73, 74, 75, + 0, 76, 77, 78, 79, 80, 81, 103, 65, 66, + 67, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 104, 65, 66, 67, 0, 0, 0, 0, + 68, 69, 70, 71, 72, 73, 74, 75, 0, 76, + 77, 78, 79, 80, 81, 68, 69, 70, 71, 72, + 73, 74, 75, 0, 76, 77, 78, 79, 80, 81, + 109, 65, 66, 67, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 110, 65, 66, 67, 0, + 0, 0, 0, 68, 69, 70, 71, 72, 73, 74, + 75, 0, 76, 77, 78, 79, 80, 81, 68, 69, + 70, 71, 72, 73, 74, 75, 0, 76, 77, 78, + 79, 80, 81, 111, 65, 66, 67, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 112, 65, + 66, 67, 0, 0, 0, 0, 68, 69, 70, 71, + 72, 73, 74, 75, 0, 76, 77, 78, 79, 80, + 81, 68, 69, 70, 71, 72, 73, 74, 75, 0, + 76, 77, 78, 79, 80, 81, 113, 65, 66, 67, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 97, 65, 66, 0, 0, 0, 0, 0, - 67, 68, 69, 70, 71, 72, 73, 74, 0, 75, - 76, 77, 78, 79, 80, 67, 68, 69, 70, 71, - 72, 73, 74, 0, 75, 76, 77, 78, 79, 80, - 98, 65, 66, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 99, 65, 66, 0, 0, - 0, 0, 0, 67, 68, 69, 70, 71, 72, 73, - 74, 0, 75, 76, 77, 78, 79, 80, 67, 68, - 69, 70, 71, 72, 73, 74, 0, 75, 76, 77, - 78, 79, 80, 100, 65, 66, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 101, 65, - 66, 0, 0, 0, 0, 0, 67, 68, 69, 70, - 71, 72, 73, 74, 0, 75, 76, 77, 78, 79, - 80, 67, 68, 69, 70, 71, 72, 73, 74, 0, - 75, 76, 77, 78, 79, 80, 102, 65, 66, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 103, 65, 66, 0, 0, 0, 0, 0, 67, - 68, 69, 70, 71, 72, 73, 74, 0, 75, 76, - 77, 78, 79, 80, 67, 68, 69, 70, 71, 72, - 73, 74, 0, 75, 76, 77, 78, 79, 80, 108, - 65, 66, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 109, 65, 66, 0, 0, 0, - 0, 0, 67, 68, 69, 70, 71, 72, 73, 74, - 0, 75, 76, 77, 78, 79, 80, 67, 68, 69, - 70, 71, 72, 73, 74, 0, 75, 76, 77, 78, - 79, 80, 110, 65, 66, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 111, 65, 66, - 0, 0, 0, 0, 0, 67, 68, 69, 70, 71, - 72, 73, 74, 0, 75, 76, 77, 78, 79, 80, - 67, 68, 69, 70, 71, 72, 73, 74, 0, 75, - 76, 77, 78, 79, 80, 112, 65, 66, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 113, 65, 66, 0, 0, 0, 0, 0, 67, 68, - 69, 70, 71, 72, 73, 74, 0, 75, 76, 77, - 78, 79, 80, 67, 68, 69, 70, 71, 72, 73, - 74, 0, 75, 76, 77, 78, 79, 80, 117, 65, - 66, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 122, 65, 66, 0, 0, 0, 0, - 0, 67, 68, 69, 70, 71, 72, 73, 74, 0, - 75, 76, 77, 78, 79, 80, 67, 68, 69, 70, - 71, 72, 73, 74, 0, 75, 76, 77, 78, 79, - 80, 123, 65, 66, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 125, 65, 66, 0, - 0, 0, 0, 0, 67, 68, 69, 70, 71, 72, - 73, 74, 0, 75, 76, 77, 78, 79, 80, 67, - 68, 69, 70, 71, 72, 73, 74, 0, 75, 76, - 77, 78, 79, 80 + 0, 114, 65, 66, 67, 0, 0, 0, 0, 68, + 69, 70, 71, 72, 73, 74, 75, 0, 76, 77, + 78, 79, 80, 81, 68, 69, 70, 71, 72, 73, + 74, 75, 0, 76, 77, 78, 79, 80, 81, 118, + 65, 66, 67, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 123, 65, 66, 67, 0, 0, + 0, 0, 68, 69, 70, 71, 72, 73, 74, 75, + 0, 76, 77, 78, 79, 80, 81, 68, 69, 70, + 71, 72, 73, 74, 75, 0, 76, 77, 78, 79, + 80, 81, 124, 65, 66, 67, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 126, 65, 66, + 67, 0, 0, 0, 0, 68, 69, 70, 71, 72, + 73, 74, 75, 0, 76, 77, 78, 79, 80, 81, + 68, 69, 70, 71, 72, 73, 74, 75, 0, 76, + 77, 78, 79, 80, 81 }; static const yytype_int8 yycheck[] = @@ -745,62 +747,62 @@ static const yytype_int8 yycheck[] = 48, 49, 32, 37, 32, 53, 54, 55, 56, 57, 58, 0, 1, 3, 3, 33, 29, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, - 19, 20, 21, 22, 23, 24, 25, 32, -1, 33, - 88, 33, 33, 33, 28, 34, 35, 36, 37, 38, - 39, 40, 3, 4, 5, 26, 33, 28, 33, 33, - 33, 33, 33, 33, 33, 30, 33, 115, 116, 3, - 4, 5, -1, 121, -1, 26, 27, 28, 29, 30, + 19, 20, 21, 22, 23, 24, 25, 32, 30, 33, + 33, 89, 33, 33, 28, 34, 35, 36, 37, 38, + 39, 40, 3, 4, 5, 6, 26, 33, 28, 33, + 33, 33, 33, 33, 33, 33, 33, -1, 116, 117, + 3, 4, 5, 6, 122, 26, 27, 28, 29, 30, 31, 32, 33, -1, 35, 36, 37, 38, 39, 40, - -1, -1, 26, 27, 28, 29, 30, 31, 32, 33, + -1, -1, -1, 26, 27, 28, 29, 30, 31, 32, + 33, -1, 35, 36, 37, 38, 39, 40, 3, 4, + 5, 6, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, 3, 4, 5, 6, -1, -1, -1, + -1, 26, 27, 28, 29, 30, 31, 32, 33, -1, + 35, 36, 37, 38, 39, 40, 26, 27, 28, 29, + 30, 31, 32, 33, -1, 35, 36, 37, 38, 39, + 40, 3, 4, 5, 6, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 3, 4, 5, 6, + -1, -1, -1, -1, 26, 27, 28, 29, 30, 31, + 32, 33, -1, 35, 36, 37, 38, 39, 40, 26, + 27, 28, 29, 30, 31, 32, 33, -1, 35, 36, + 37, 38, 39, 40, 3, 4, 5, 6, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, 3, + 4, 5, 6, -1, -1, -1, -1, 26, 27, 28, + 29, 30, 31, 32, 33, -1, 35, 36, 37, 38, + 39, 40, 26, 27, 28, 29, 30, 31, 32, 33, -1, 35, 36, 37, 38, 39, 40, 3, 4, 5, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, 3, 4, 5, -1, -1, -1, -1, -1, + 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, 3, 4, 5, 6, -1, -1, -1, -1, 26, 27, 28, 29, 30, 31, 32, 33, -1, 35, 36, 37, 38, 39, 40, 26, 27, 28, 29, 30, 31, 32, 33, -1, 35, 36, 37, 38, 39, 40, - 3, 4, 5, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 3, 4, 5, -1, -1, + 3, 4, 5, 6, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 3, 4, 5, 6, -1, -1, -1, -1, 26, 27, 28, 29, 30, 31, 32, 33, -1, 35, 36, 37, 38, 39, 40, 26, 27, 28, 29, 30, 31, 32, 33, -1, 35, 36, 37, - 38, 39, 40, 3, 4, 5, -1, -1, -1, -1, + 38, 39, 40, 3, 4, 5, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 3, 4, - 5, -1, -1, -1, -1, -1, 26, 27, 28, 29, + 5, 6, -1, -1, -1, -1, 26, 27, 28, 29, 30, 31, 32, 33, -1, 35, 36, 37, 38, 39, 40, 26, 27, 28, 29, 30, 31, 32, 33, -1, - 35, 36, 37, 38, 39, 40, 3, 4, 5, -1, + 35, 36, 37, 38, 39, 40, 3, 4, 5, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, 3, 4, 5, -1, -1, -1, -1, -1, 26, + -1, 3, 4, 5, 6, -1, -1, -1, -1, 26, 27, 28, 29, 30, 31, 32, 33, -1, 35, 36, 37, 38, 39, 40, 26, 27, 28, 29, 30, 31, 32, 33, -1, 35, 36, 37, 38, 39, 40, 3, - 4, 5, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, 3, 4, 5, -1, -1, -1, + 4, 5, 6, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 3, 4, 5, 6, -1, -1, -1, -1, 26, 27, 28, 29, 30, 31, 32, 33, -1, 35, 36, 37, 38, 39, 40, 26, 27, 28, 29, 30, 31, 32, 33, -1, 35, 36, 37, 38, - 39, 40, 3, 4, 5, -1, -1, -1, -1, -1, + 39, 40, 3, 4, 5, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 3, 4, 5, - -1, -1, -1, -1, -1, 26, 27, 28, 29, 30, + 6, -1, -1, -1, -1, 26, 27, 28, 29, 30, 31, 32, 33, -1, 35, 36, 37, 38, 39, 40, 26, 27, 28, 29, 30, 31, 32, 33, -1, 35, - 36, 37, 38, 39, 40, 3, 4, 5, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - 3, 4, 5, -1, -1, -1, -1, -1, 26, 27, - 28, 29, 30, 31, 32, 33, -1, 35, 36, 37, - 38, 39, 40, 26, 27, 28, 29, 30, 31, 32, - 33, -1, 35, 36, 37, 38, 39, 40, 3, 4, - 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, 3, 4, 5, -1, -1, -1, -1, - -1, 26, 27, 28, 29, 30, 31, 32, 33, -1, - 35, 36, 37, 38, 39, 40, 26, 27, 28, 29, - 30, 31, 32, 33, -1, 35, 36, 37, 38, 39, - 40, 3, 4, 5, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, 3, 4, 5, -1, - -1, -1, -1, -1, 26, 27, 28, 29, 30, 31, - 32, 33, -1, 35, 36, 37, 38, 39, 40, 26, - 27, 28, 29, 30, 31, 32, 33, -1, 35, 36, - 37, 38, 39, 40 + 36, 37, 38, 39, 40 }; /* YYSTOS[STATE-NUM] -- The (internal number of the) accessing @@ -813,13 +815,13 @@ static const yytype_uint8 yystos[] = 39, 40, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 3, 32, 53, 37, 32, 3, 33, 33, 29, 26, 28, 33, 32, 33, 33, 33, 33, 53, - 53, 53, 53, 53, 3, 4, 5, 26, 27, 28, - 29, 30, 31, 32, 33, 35, 36, 37, 38, 39, - 40, 54, 53, 53, 53, 53, 33, 33, 33, 53, - 53, 53, 53, 53, 53, 3, 3, 3, 3, 3, - 3, 3, 3, 3, 27, 30, 28, 53, 3, 3, - 3, 3, 3, 3, 33, 33, 33, 3, 30, 53, - 53, 33, 3, 3, 53, 3 + 53, 53, 53, 53, 3, 4, 5, 6, 26, 27, + 28, 29, 30, 31, 32, 33, 35, 36, 37, 38, + 39, 40, 54, 53, 53, 53, 53, 33, 33, 33, + 53, 53, 53, 53, 53, 53, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 27, 30, 28, 53, 3, + 3, 3, 3, 3, 3, 33, 33, 33, 3, 30, + 53, 53, 33, 3, 3, 53, 3 }; /* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */ @@ -831,7 +833,7 @@ static const yytype_uint8 yyr1[] = 45, 45, 46, 46, 47, 47, 48, 48, 49, 49, 50, 50, 51, 51, 52, 52, 53, 53, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, - 54, 54, 54, 54 + 54, 54, 54, 54, 54 }; /* YYR2[YYN] -- Number of symbols on the right hand side of rule YYN. */ @@ -843,7 +845,7 @@ static const yytype_uint8 yyr2[] = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1 + 1, 1, 1, 1, 1 }; @@ -930,7 +932,9 @@ yy_symbol_value_print (FILE *yyo, int yytype, YYSTYPE const * const yyvaluep, yy if (yytype < YYNTOKENS) YYPRINT (yyo, yytoknum[yytype], *yyvaluep); # endif + YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN YYUSE (yytype); + YY_IGNORE_MAYBE_UNINITIALIZED_END } @@ -1368,6 +1372,8 @@ yynewstate: | yynewstate -- set current state (the top of the stack) to yystate. | `--------------------------------------------------------------------*/ yysetstate: + YYDPRINTF ((stderr, "Entering state %d\n", yystate)); + YY_ASSERT (0 <= yystate && yystate < YYNSTATES); *yyssp = (yytype_int16) yystate; if (yyss + yystacksize - 1 <= yyssp) @@ -1430,8 +1436,6 @@ yysetstate: } #endif /* !defined yyoverflow && !defined YYSTACK_RELOCATE */ - YYDPRINTF ((stderr, "Entering state %d\n", yystate)); - if (yystate == YYFINAL) YYACCEPT; @@ -1499,7 +1503,6 @@ yybackup: YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN *++yyvsp = yylval; YY_IGNORE_MAYBE_UNINITIALIZED_END - goto yynewstate; @@ -1534,27 +1537,27 @@ yyreduce: YY_REDUCE_PRINT (yyn); switch (yyn) { - case 4: -#line 104 "cmFortranParser.y" /* yacc.c:1652 */ + case 4: +#line 104 "cmFortranParser.y" { cmFortranParser* parser = cmFortran_yyget_extra(yyscanner); cmFortranParser_SetInInterface(parser, true); } -#line 1544 "cmFortranParser.cxx" /* yacc.c:1652 */ +#line 1547 "cmFortranParser.cxx" break; case 5: -#line 108 "cmFortranParser.y" /* yacc.c:1652 */ +#line 108 "cmFortranParser.y" { cmFortranParser* parser = cmFortran_yyget_extra(yyscanner); cmFortranParser_RuleUse(parser, (yyvsp[-2].string)); free((yyvsp[-2].string)); } -#line 1554 "cmFortranParser.cxx" /* yacc.c:1652 */ +#line 1557 "cmFortranParser.cxx" break; case 6: -#line 113 "cmFortranParser.y" /* yacc.c:1652 */ +#line 113 "cmFortranParser.y" { cmFortranParser* parser = cmFortran_yyget_extra(yyscanner); if (cmsysString_strcasecmp((yyvsp[-2].string), "function") != 0 && @@ -1564,22 +1567,22 @@ yyreduce: } free((yyvsp[-2].string)); } -#line 1568 "cmFortranParser.cxx" /* yacc.c:1652 */ +#line 1571 "cmFortranParser.cxx" break; case 7: -#line 122 "cmFortranParser.y" /* yacc.c:1652 */ +#line 122 "cmFortranParser.y" { cmFortranParser* parser = cmFortran_yyget_extra(yyscanner); cmFortranParser_RuleSubmodule(parser, (yyvsp[-4].string), (yyvsp[-2].string)); free((yyvsp[-4].string)); free((yyvsp[-2].string)); } -#line 1579 "cmFortranParser.cxx" /* yacc.c:1652 */ +#line 1582 "cmFortranParser.cxx" break; case 8: -#line 128 "cmFortranParser.y" /* yacc.c:1652 */ +#line 128 "cmFortranParser.y" { cmFortranParser* parser = cmFortran_yyget_extra(yyscanner); cmFortranParser_RuleSubmoduleNested(parser, (yyvsp[-6].string), (yyvsp[-4].string), (yyvsp[-2].string)); @@ -1587,40 +1590,40 @@ yyreduce: free((yyvsp[-4].string)); free((yyvsp[-2].string)); } -#line 1591 "cmFortranParser.cxx" /* yacc.c:1652 */ +#line 1594 "cmFortranParser.cxx" break; case 9: -#line 135 "cmFortranParser.y" /* yacc.c:1652 */ +#line 135 "cmFortranParser.y" { cmFortranParser* parser = cmFortran_yyget_extra(yyscanner); cmFortranParser_SetInInterface(parser, true); free((yyvsp[-2].string)); } -#line 1601 "cmFortranParser.cxx" /* yacc.c:1652 */ +#line 1604 "cmFortranParser.cxx" break; case 10: -#line 140 "cmFortranParser.y" /* yacc.c:1652 */ +#line 140 "cmFortranParser.y" { cmFortranParser* parser = cmFortran_yyget_extra(yyscanner); cmFortranParser_SetInInterface(parser, false); } -#line 1610 "cmFortranParser.cxx" /* yacc.c:1652 */ +#line 1613 "cmFortranParser.cxx" break; case 11: -#line 144 "cmFortranParser.y" /* yacc.c:1652 */ +#line 144 "cmFortranParser.y" { cmFortranParser* parser = cmFortran_yyget_extra(yyscanner); cmFortranParser_RuleUse(parser, (yyvsp[-2].string)); free((yyvsp[-2].string)); } -#line 1620 "cmFortranParser.cxx" /* yacc.c:1652 */ +#line 1623 "cmFortranParser.cxx" break; case 12: -#line 149 "cmFortranParser.y" /* yacc.c:1652 */ +#line 149 "cmFortranParser.y" { if (cmsysString_strcasecmp((yyvsp[-4].string), "non_intrinsic") == 0) { cmFortranParser* parser = cmFortran_yyget_extra(yyscanner); @@ -1629,139 +1632,140 @@ yyreduce: free((yyvsp[-4].string)); free((yyvsp[-2].string)); } -#line 1633 "cmFortranParser.cxx" /* yacc.c:1652 */ +#line 1636 "cmFortranParser.cxx" break; case 13: -#line 157 "cmFortranParser.y" /* yacc.c:1652 */ +#line 157 "cmFortranParser.y" { cmFortranParser* parser = cmFortran_yyget_extra(yyscanner); cmFortranParser_RuleInclude(parser, (yyvsp[-2].string)); free((yyvsp[-2].string)); } -#line 1643 "cmFortranParser.cxx" /* yacc.c:1652 */ +#line 1646 "cmFortranParser.cxx" break; case 14: -#line 162 "cmFortranParser.y" /* yacc.c:1652 */ +#line 162 "cmFortranParser.y" { cmFortranParser* parser = cmFortran_yyget_extra(yyscanner); cmFortranParser_RuleLineDirective(parser, (yyvsp[-2].string)); free((yyvsp[-2].string)); } -#line 1653 "cmFortranParser.cxx" /* yacc.c:1652 */ +#line 1656 "cmFortranParser.cxx" break; case 15: -#line 167 "cmFortranParser.y" /* yacc.c:1652 */ +#line 167 "cmFortranParser.y" { cmFortranParser* parser = cmFortran_yyget_extra(yyscanner); cmFortranParser_RuleInclude(parser, (yyvsp[-2].string)); free((yyvsp[-2].string)); } -#line 1663 "cmFortranParser.cxx" /* yacc.c:1652 */ +#line 1666 "cmFortranParser.cxx" break; case 16: -#line 172 "cmFortranParser.y" /* yacc.c:1652 */ +#line 172 "cmFortranParser.y" { cmFortranParser* parser = cmFortran_yyget_extra(yyscanner); cmFortranParser_RuleInclude(parser, (yyvsp[-2].string)); free((yyvsp[-2].string)); } -#line 1673 "cmFortranParser.cxx" /* yacc.c:1652 */ +#line 1676 "cmFortranParser.cxx" break; case 17: -#line 177 "cmFortranParser.y" /* yacc.c:1652 */ +#line 177 "cmFortranParser.y" { cmFortranParser* parser = cmFortran_yyget_extra(yyscanner); cmFortranParser_RuleDefine(parser, (yyvsp[-2].string)); free((yyvsp[-2].string)); } -#line 1683 "cmFortranParser.cxx" /* yacc.c:1652 */ +#line 1686 "cmFortranParser.cxx" break; case 18: -#line 182 "cmFortranParser.y" /* yacc.c:1652 */ +#line 182 "cmFortranParser.y" { cmFortranParser* parser = cmFortran_yyget_extra(yyscanner); cmFortranParser_RuleUndef(parser, (yyvsp[-2].string)); free((yyvsp[-2].string)); } -#line 1693 "cmFortranParser.cxx" /* yacc.c:1652 */ +#line 1696 "cmFortranParser.cxx" break; case 19: -#line 187 "cmFortranParser.y" /* yacc.c:1652 */ +#line 187 "cmFortranParser.y" { cmFortranParser* parser = cmFortran_yyget_extra(yyscanner); cmFortranParser_RuleIfdef(parser, (yyvsp[-2].string)); free((yyvsp[-2].string)); } -#line 1703 "cmFortranParser.cxx" /* yacc.c:1652 */ +#line 1706 "cmFortranParser.cxx" break; case 20: -#line 192 "cmFortranParser.y" /* yacc.c:1652 */ +#line 192 "cmFortranParser.y" { cmFortranParser* parser = cmFortran_yyget_extra(yyscanner); cmFortranParser_RuleIfndef(parser, (yyvsp[-2].string)); free((yyvsp[-2].string)); } -#line 1713 "cmFortranParser.cxx" /* yacc.c:1652 */ +#line 1716 "cmFortranParser.cxx" break; case 21: -#line 197 "cmFortranParser.y" /* yacc.c:1652 */ +#line 197 "cmFortranParser.y" { cmFortranParser* parser = cmFortran_yyget_extra(yyscanner); cmFortranParser_RuleIf(parser); } -#line 1722 "cmFortranParser.cxx" /* yacc.c:1652 */ +#line 1725 "cmFortranParser.cxx" break; case 22: -#line 201 "cmFortranParser.y" /* yacc.c:1652 */ +#line 201 "cmFortranParser.y" { cmFortranParser* parser = cmFortran_yyget_extra(yyscanner); cmFortranParser_RuleElif(parser); } -#line 1731 "cmFortranParser.cxx" /* yacc.c:1652 */ +#line 1734 "cmFortranParser.cxx" break; case 23: -#line 205 "cmFortranParser.y" /* yacc.c:1652 */ +#line 205 "cmFortranParser.y" { cmFortranParser* parser = cmFortran_yyget_extra(yyscanner); cmFortranParser_RuleElse(parser); } -#line 1740 "cmFortranParser.cxx" /* yacc.c:1652 */ +#line 1743 "cmFortranParser.cxx" break; case 24: -#line 209 "cmFortranParser.y" /* yacc.c:1652 */ +#line 209 "cmFortranParser.y" { cmFortranParser* parser = cmFortran_yyget_extra(yyscanner); cmFortranParser_RuleEndif(parser); } -#line 1749 "cmFortranParser.cxx" /* yacc.c:1652 */ +#line 1752 "cmFortranParser.cxx" break; case 48: -#line 231 "cmFortranParser.y" /* yacc.c:1652 */ +#line 231 "cmFortranParser.y" { free ((yyvsp[0].string)); } -#line 1755 "cmFortranParser.cxx" /* yacc.c:1652 */ +#line 1758 "cmFortranParser.cxx" break; case 55: -#line 238 "cmFortranParser.y" /* yacc.c:1652 */ +#line 238 "cmFortranParser.y" { free ((yyvsp[0].string)); } -#line 1761 "cmFortranParser.cxx" /* yacc.c:1652 */ +#line 1764 "cmFortranParser.cxx" break; -#line 1765 "cmFortranParser.cxx" /* yacc.c:1652 */ +#line 1768 "cmFortranParser.cxx" + default: break; } /* User semantic actions sometimes alter yychar, and that requires @@ -1994,6 +1998,6 @@ yyreturn: #endif return yyresult; } -#line 249 "cmFortranParser.y" /* yacc.c:1918 */ +#line 250 "cmFortranParser.y" /* End of grammar */ diff --git a/Source/LexerParser/cmFortranParser.y b/Source/LexerParser/cmFortranParser.y index 87f3e0a..1b54dd9 100644 --- a/Source/LexerParser/cmFortranParser.y +++ b/Source/LexerParser/cmFortranParser.y @@ -244,6 +244,7 @@ misc_code: | RPAREN | COMMA | UNTERMINATED_STRING +| CPP_LINE_DIRECTIVE ; %% diff --git a/Source/LexerParser/cmFortranParserTokens.h b/Source/LexerParser/cmFortranParserTokens.h index 0da4c1c..f66a15c 100644 --- a/Source/LexerParser/cmFortranParserTokens.h +++ b/Source/LexerParser/cmFortranParserTokens.h @@ -1,4 +1,4 @@ -/* A Bison parser, made by GNU Bison 3.3.2. */ +/* A Bison parser, made by GNU Bison 3.4.2. */ /* Bison interface for Yacc-like parsers in C @@ -131,16 +131,15 @@ extern int cmFortran_yydebug; /* Value type. */ #if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED - union YYSTYPE { -#line 73 "cmFortranParser.y" /* yacc.c:1921 */ +#line 73 "cmFortranParser.y" char* string; -#line 142 "cmFortranParserTokens.h" /* yacc.c:1921 */ -}; +#line 141 "cmFortranParserTokens.h" +}; typedef union YYSTYPE YYSTYPE; # define YYSTYPE_IS_TRIVIAL 1 # define YYSTYPE_IS_DECLARED 1 diff --git a/Source/QtDialog/CMakeLists.txt b/Source/QtDialog/CMakeLists.txt index cb89d19..98dd0e2 100644 --- a/Source/QtDialog/CMakeLists.txt +++ b/Source/QtDialog/CMakeLists.txt @@ -178,6 +178,10 @@ if(WIN32) target_sources(cmake-gui PRIVATE $<TARGET_OBJECTS:CMakeVersion>) endif() +if(CMake_JOB_POOL_LINK_BIN) + set_property(TARGET cmake-gui PROPERTY JOB_POOL_LINK "link-bin") +endif() + # cmake-gui has not been updated for `include-what-you-use`. # Block the tool until this is done. set_target_properties(cmake-gui PROPERTIES diff --git a/Source/bindexplib.cxx b/Source/bindexplib.cxx index b85cc33..0b2750d 100644 --- a/Source/bindexplib.cxx +++ b/Source/bindexplib.cxx @@ -64,32 +64,36 @@ */ #include "bindexplib.h" -#include <iostream> +#include <cstddef> #include <sstream> #include <vector> -#include <windows.h> +#ifdef _WIN32 +# include <windows.h> + +# include "cmsys/Encoding.hxx" +#endif -#include "cmsys/Encoding.hxx" #include "cmsys/FStream.hxx" #include "cmSystemTools.h" -#ifndef IMAGE_FILE_MACHINE_ARM -# define IMAGE_FILE_MACHINE_ARM 0x01c0 // ARM Little-Endian -#endif +#ifdef _WIN32 +# ifndef IMAGE_FILE_MACHINE_ARM +# define IMAGE_FILE_MACHINE_ARM 0x01c0 // ARM Little-Endian +# endif -#ifndef IMAGE_FILE_MACHINE_THUMB -# define IMAGE_FILE_MACHINE_THUMB 0x01c2 // ARM Thumb/Thumb-2 Little-Endian -#endif +# ifndef IMAGE_FILE_MACHINE_THUMB +# define IMAGE_FILE_MACHINE_THUMB 0x01c2 // ARM Thumb/Thumb-2 Little-Endian +# endif -#ifndef IMAGE_FILE_MACHINE_ARMNT -# define IMAGE_FILE_MACHINE_ARMNT 0x01c4 // ARM Thumb-2 Little-Endian -#endif +# ifndef IMAGE_FILE_MACHINE_ARMNT +# define IMAGE_FILE_MACHINE_ARMNT 0x01c4 // ARM Thumb-2 Little-Endian +# endif -#ifndef IMAGE_FILE_MACHINE_ARM64 -# define IMAGE_FILE_MACHINE_ARM64 0xaa64 // ARM64 Little-Endian -#endif +# ifndef IMAGE_FILE_MACHINE_ARM64 +# define IMAGE_FILE_MACHINE_ARM64 0xaa64 // ARM64 Little-Endian +# endif typedef struct cmANON_OBJECT_HEADER_BIGOBJ { @@ -306,6 +310,7 @@ private: SymbolTableType* SymbolTable; bool IsI386; }; +#endif bool DumpFileWithLlvmNm(std::string const& nmPath, const char* filename, std::set<std::string>& symbols, @@ -315,15 +320,15 @@ bool DumpFileWithLlvmNm(std::string const& nmPath, const char* filename, // break up command line into a vector std::vector<std::string> command; command.push_back(nmPath); - command.push_back("--no-weak"); - command.push_back("--defined-only"); - command.push_back("--format=posix"); - command.push_back(filename); + command.emplace_back("--no-weak"); + command.emplace_back("--defined-only"); + command.emplace_back("--format=posix"); + command.emplace_back(filename); // run the command int exit_code = 0; - cmSystemTools::RunSingleCommand(command, &output, &output, &exit_code, "", - cmSystemTools::OUTPUT_NONE); + cmSystemTools::RunSingleCommand(command, &output, &output, &exit_code, + nullptr, cmSystemTools::OUTPUT_NONE); if (exit_code != 0) { fprintf(stderr, "llvm-nm returned an error: %s\n", output.c_str()); @@ -336,7 +341,7 @@ bool DumpFileWithLlvmNm(std::string const& nmPath, const char* filename, if (line.empty()) { // last line continue; } - size_t sym_end = line.find(" "); + size_t sym_end = line.find(' '); if (sym_end == std::string::npos) { fprintf(stderr, "Couldn't parse llvm-nm output line: %s\n", line.c_str()); @@ -366,6 +371,9 @@ bool DumpFile(std::string const& nmPath, const char* filename, std::set<std::string>& symbols, std::set<std::string>& dataSymbols) { +#ifndef _WIN32 + return DumpFileWithLlvmNm(nmPath, filename, symbols, dataSymbols); +#else HANDLE hFile; HANDLE hFileMapping; LPVOID lpFileBase; @@ -446,6 +454,7 @@ bool DumpFile(std::string const& nmPath, const char* filename, CloseHandle(hFileMapping); CloseHandle(hFile); return true; +#endif } bool bindexplib::AddObjectFile(const char* filename) diff --git a/Source/cmAddCustomCommandCommand.cxx b/Source/cmAddCustomCommandCommand.cxx index 6e04ce5..52fc5d5 100644 --- a/Source/cmAddCustomCommandCommand.cxx +++ b/Source/cmAddCustomCommandCommand.cxx @@ -343,7 +343,7 @@ bool cmAddCustomCommandCommand(std::vector<std::string> const& args, // Target is empty, use the output. mf.AddCustomCommandToOutput( output, byproducts, depends, main_dependency, implicit_depends, - commandLines, comment, working.c_str(), false, escapeOldStyle, + commandLines, comment, working.c_str(), nullptr, false, escapeOldStyle, uses_terminal, command_expand_lists, depfile, job_pool); } else if (!byproducts.empty()) { status.SetError("BYPRODUCTS may not be specified with SOURCE signatures"); diff --git a/Source/cmAddCustomTargetCommand.cxx b/Source/cmAddCustomTargetCommand.cxx index e27b126..aa98d89 100644 --- a/Source/cmAddCustomTargetCommand.cxx +++ b/Source/cmAddCustomTargetCommand.cxx @@ -6,7 +6,6 @@ #include "cmCheckCustomOutputs.h" #include "cmCustomCommandLines.h" -#include "cmCustomCommandTypes.h" #include "cmExecutionStatus.h" #include "cmGeneratorExpression.h" #include "cmGlobalGenerator.h" @@ -215,9 +214,9 @@ bool cmAddCustomTargetCommand(std::vector<std::string> const& args, // Add the utility target to the makefile. bool escapeOldStyle = !verbatim; cmTarget* target = mf.AddUtilityCommand( - targetName, cmCommandOrigin::Project, excludeFromAll, - working_directory.c_str(), byproducts, depends, commandLines, - escapeOldStyle, comment, uses_terminal, command_expand_lists, job_pool); + targetName, excludeFromAll, working_directory.c_str(), byproducts, depends, + commandLines, escapeOldStyle, comment, uses_terminal, command_expand_lists, + job_pool); // Add additional user-specified source files to the target. target->AddSources(sources); diff --git a/Source/cmAddLibraryCommand.cxx b/Source/cmAddLibraryCommand.cxx index 0439c51..f443fc6 100644 --- a/Source/cmAddLibraryCommand.cxx +++ b/Source/cmAddLibraryCommand.cxx @@ -2,7 +2,8 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmAddLibraryCommand.h" -#include "cmAlgorithms.h" +#include <cmext/algorithm> + #include "cmExecutionStatus.h" #include "cmGeneratorExpression.h" #include "cmGlobalGenerator.h" @@ -309,7 +310,7 @@ bool cmAddLibraryCommand(std::vector<std::string> const& args, return true; } - cmAppend(srclists, s, args.end()); + cm::append(srclists, s, args.end()); mf.AddLibrary(libName, type, srclists, excludeFromAll); diff --git a/Source/cmAlgorithms.h b/Source/cmAlgorithms.h index e0d27ee..a179acb 100644 --- a/Source/cmAlgorithms.h +++ b/Source/cmAlgorithms.h @@ -8,6 +8,7 @@ #include <algorithm> #include <functional> #include <iterator> +#include <memory> #include <unordered_set> #include <utility> #include <vector> @@ -144,18 +145,6 @@ void cmDeleteAll(Range const& r) ContainerAlgorithms::DefaultDeleter<Range>()); } -template <typename T, typename Range> -void cmAppend(std::vector<T>& v, Range const& r) -{ - v.insert(v.end(), r.begin(), r.end()); -} - -template <typename T, typename InputIt> -void cmAppend(std::vector<T>& v, InputIt first, InputIt last) -{ - v.insert(v.end(), first, last); -} - template <typename Range> typename Range::const_iterator cmRemoveN(Range& r, size_t n) { diff --git a/Source/cmCPluginAPI.cxx b/Source/cmCPluginAPI.cxx index 177bca8..b5c7e96 100644 --- a/Source/cmCPluginAPI.cxx +++ b/Source/cmCPluginAPI.cxx @@ -221,10 +221,10 @@ void CCONV cmAddUtilityCommand(void* arg, const char* utilityName, // Pass the call to the makefile instance. std::vector<std::string> no_byproducts; - mf->AddUtilityCommand(utilityName, cmCommandOrigin::Project, - (all ? false : true), nullptr, no_byproducts, depends2, - commandLines); + mf->AddUtilityCommand(utilityName, (all ? false : true), nullptr, + no_byproducts, depends2, commandLines); } + void CCONV cmAddCustomCommand(void* arg, const char* source, const char* command, int numArgs, const char** args, int numDepends, diff --git a/Source/cmCPluginAPI.h b/Source/cmCPluginAPI.h index 6a95148..19626f0 100644 --- a/Source/cmCPluginAPI.h +++ b/Source/cmCPluginAPI.h @@ -36,7 +36,7 @@ typedef struct of functions are utility functions that are specific to the plugin API =========================================================================*/ /* set/Get the ClientData in the cmLoadedCommandInfo structure, this is how - information is passed from the InitialPass to FInalPass for commands + information is passed from the InitialPass to FinalPass for commands that need a FinalPass and need information from the InitialPass */ void*(CCONV* GetClientData)(void* info); /* return the summed size in characters of all the arguments */ @@ -44,7 +44,7 @@ typedef struct /* free all the memory associated with an argc, argv pair */ void(CCONV* FreeArguments)(int argc, char** argv); /* set/Get the ClientData in the cmLoadedCommandInfo structure, this is how - information is passed from the InitialPass to FInalPass for commands + information is passed from the InitialPass to FinalPass for commands that need a FinalPass and need information from the InitialPass */ void(CCONV* SetClientData)(void* info, void* cd); /* when an error occurs, call this function to set the error string */ diff --git a/Source/cmCTest.cxx b/Source/cmCTest.cxx index 6eae26e..22a6e38 100644 --- a/Source/cmCTest.cxx +++ b/Source/cmCTest.cxx @@ -21,6 +21,7 @@ #include "cmsys/FStream.hxx" #include "cmsys/Glob.hxx" #include "cmsys/Process.h" +#include "cmsys/RegularExpression.hxx" #include "cmsys/SystemInformation.hxx" #include "cm_curl.h" @@ -32,8 +33,8 @@ #endif #include <cm/memory> +#include <cmext/algorithm> -#include "cmAlgorithms.h" #include "cmCTestBuildAndTestHandler.h" #include "cmCTestBuildHandler.h" #include "cmCTestConfigureHandler.h" @@ -83,8 +84,8 @@ struct cmCTest::Private std::string Name; }; - int RepeatTests = 1; // default to run each test once - bool RepeatUntilFail = false; + int RepeatCount = 1; // default to run each test once + cmCTest::Repeat RepeatMode = cmCTest::Repeat::Never; std::string ConfigType; std::string ScheduleType; std::chrono::system_clock::time_point StopTime; @@ -1279,7 +1280,7 @@ int cmCTest::RunTest(std::vector<const char*> argv, std::string* output, while (cmsysProcess_WaitForData(cp, &data, &length, nullptr)) { processOutput.DecodeText(data, length, strdata); if (output) { - cmAppend(tempOutput, data, data + length); + cm::append(tempOutput, data, data + length); } cmCTestLog(this, HANDLER_VERBOSE_OUTPUT, cmCTestLogWrite(strdata.c_str(), strdata.size())); @@ -1839,11 +1840,16 @@ bool cmCTest::HandleCommandLineArguments(size_t& i, this->SetParallelLevel(plevel); this->Impl->ParallelLevelSetInCli = true; } + if (this->CheckArgument(arg, "--repeat-until-fail")) { if (i >= args.size() - 1) { errormsg = "'--repeat-until-fail' requires an argument"; return false; } + if (this->Impl->RepeatMode != cmCTest::Repeat::Never) { + errormsg = "At most one '--repeat' option may be used."; + return false; + } i++; long repeat = 1; if (!cmStrToLong(args[i], &repeat)) { @@ -1851,9 +1857,42 @@ bool cmCTest::HandleCommandLineArguments(size_t& i, "'--repeat-until-fail' given non-integer value '" + args[i] + "'"; return false; } - this->Impl->RepeatTests = static_cast<int>(repeat); + this->Impl->RepeatCount = static_cast<int>(repeat); if (repeat > 1) { - this->Impl->RepeatUntilFail = true; + this->Impl->RepeatMode = cmCTest::Repeat::UntilFail; + } + } + + if (this->CheckArgument(arg, "--repeat")) { + if (i >= args.size() - 1) { + errormsg = "'--repeat' requires an argument"; + return false; + } + if (this->Impl->RepeatMode != cmCTest::Repeat::Never) { + errormsg = "At most one '--repeat' option may be used."; + return false; + } + i++; + cmsys::RegularExpression repeatRegex( + "^(until-fail|until-pass|after-timeout):([0-9]+)$"); + if (repeatRegex.find(args[i])) { + std::string const& count = repeatRegex.match(2); + unsigned long n = 1; + cmStrToULong(count, &n); // regex guarantees success + this->Impl->RepeatCount = static_cast<int>(n); + if (this->Impl->RepeatCount > 1) { + std::string const& mode = repeatRegex.match(1); + if (mode == "until-fail") { + this->Impl->RepeatMode = cmCTest::Repeat::UntilFail; + } else if (mode == "until-pass") { + this->Impl->RepeatMode = cmCTest::Repeat::UntilPass; + } else if (mode == "after-timeout") { + this->Impl->RepeatMode = cmCTest::Repeat::AfterTimeout; + } + } + } else { + errormsg = "'--repeat' given invalid value '" + args[i] + "'"; + return false; } } @@ -2204,7 +2243,7 @@ int cmCTest::Run(std::vector<std::string>& args, std::string* output) bool SRArgumentSpecified = false; // copy the command line - cmAppend(this->Impl->InitialCommandLineArguments, args); + cm::append(this->Impl->InitialCommandLineArguments, args); // process the command line arguments for (size_t i = 1; i < args.size(); ++i) { @@ -2847,14 +2886,14 @@ const std::map<std::string, std::string>& cmCTest::GetDefinitions() const return this->Impl->Definitions; } -int cmCTest::GetTestRepeat() const +int cmCTest::GetRepeatCount() const { - return this->Impl->RepeatTests; + return this->Impl->RepeatCount; } -bool cmCTest::GetRepeatUntilFail() const +cmCTest::Repeat cmCTest::GetRepeatMode() const { - return this->Impl->RepeatUntilFail; + return this->Impl->RepeatMode; } void cmCTest::SetBuildID(const std::string& id) @@ -2964,10 +3003,10 @@ bool cmCTest::RunCommand(std::vector<std::string> const& args, res = cmsysProcess_WaitForData(cp, &data, &length, nullptr); switch (res) { case cmsysProcess_Pipe_STDOUT: - cmAppend(tempOutput, data, data + length); + cm::append(tempOutput, data, data + length); break; case cmsysProcess_Pipe_STDERR: - cmAppend(tempError, data, data + length); + cm::append(tempError, data, data + length); break; default: done = true; diff --git a/Source/cmCTest.h b/Source/cmCTest.h index 82a6f4c..e0ae100 100644 --- a/Source/cmCTest.h +++ b/Source/cmCTest.h @@ -431,10 +431,16 @@ public: const std::map<std::string, std::string>& GetDefinitions() const; /** Return the number of times a test should be run */ - int GetTestRepeat() const; + int GetRepeatCount() const; - /** Return true if test should run until fail */ - bool GetRepeatUntilFail() const; + enum class Repeat + { + Never, + UntilFail, + UntilPass, + AfterTimeout, + }; + Repeat GetRepeatMode() const; void GenerateSubprojectsOutput(cmXMLWriter& xml); std::vector<std::string> GetLabelsForSubprojects(); diff --git a/Source/cmCommands.cxx b/Source/cmCommands.cxx index 6f19697..896b6a9 100644 --- a/Source/cmCommands.cxx +++ b/Source/cmCommands.cxx @@ -198,6 +198,7 @@ void GetScriptingCommands(cmState* state) #if !defined(CMAKE_BOOTSTRAP) state->AddBuiltinCommand("cmake_host_system_information", cmCMakeHostSystemInformationCommand); + state->AddBuiltinCommand("load_cache", cmLoadCacheCommand); state->AddBuiltinCommand("remove", cmRemoveCommand); state->AddBuiltinCommand("variable_watch", cmVariableWatchCommand); state->AddBuiltinCommand("write_file", cmWriteFileCommand); @@ -279,7 +280,6 @@ void GetProjectCommands(cmState* state) state->AddBuiltinCommand("link_libraries", cmLinkLibrariesCommand); state->AddBuiltinCommand("target_link_directories", cmTargetLinkDirectoriesCommand); - state->AddBuiltinCommand("load_cache", cmLoadCacheCommand); state->AddBuiltinCommand("qt_wrap_cpp", cmQTWrapCPPCommand); state->AddBuiltinCommand("qt_wrap_ui", cmQTWrapUICommand); state->AddBuiltinCommand("remove_definitions", cmRemoveDefinitionsCommand); @@ -339,7 +339,6 @@ void GetProjectCommandsInScriptMode(cmState* state) CM_UNEXPECTED_PROJECT_COMMAND("install"); CM_UNEXPECTED_PROJECT_COMMAND("link_directories"); CM_UNEXPECTED_PROJECT_COMMAND("link_libraries"); - CM_UNEXPECTED_PROJECT_COMMAND("load_cache"); CM_UNEXPECTED_PROJECT_COMMAND("project"); CM_UNEXPECTED_PROJECT_COMMAND("qt_wrap_cpp"); CM_UNEXPECTED_PROJECT_COMMAND("qt_wrap_ui"); diff --git a/Source/cmCommonTargetGenerator.cxx b/Source/cmCommonTargetGenerator.cxx index 19a096b..9106e70 100644 --- a/Source/cmCommonTargetGenerator.cxx +++ b/Source/cmCommonTargetGenerator.cxx @@ -25,27 +25,29 @@ cmCommonTargetGenerator::cmCommonTargetGenerator(cmGeneratorTarget* gt) static_cast<cmLocalCommonGenerator*>(gt->LocalGenerator)) , GlobalCommonGenerator(static_cast<cmGlobalCommonGenerator*>( gt->LocalGenerator->GetGlobalGenerator())) - , ConfigName(LocalCommonGenerator->GetConfigName()) + , ConfigNames(LocalCommonGenerator->GetConfigNames()) { } cmCommonTargetGenerator::~cmCommonTargetGenerator() = default; -std::string const& cmCommonTargetGenerator::GetConfigName() const +std::vector<std::string> const& cmCommonTargetGenerator::GetConfigNames() const { - return this->ConfigName; + return this->ConfigNames; } -const char* cmCommonTargetGenerator::GetFeature(const std::string& feature) +const char* cmCommonTargetGenerator::GetFeature(const std::string& feature, + const std::string& config) { - return this->GeneratorTarget->GetFeature(feature, this->ConfigName); + return this->GeneratorTarget->GetFeature(feature, config); } void cmCommonTargetGenerator::AddModuleDefinitionFlag( - cmLinkLineComputer* linkLineComputer, std::string& flags) + cmLinkLineComputer* linkLineComputer, std::string& flags, + const std::string& config) { cmGeneratorTarget::ModuleDefinitionInfo const* mdi = - this->GeneratorTarget->GetModuleDefinitionInfo(this->GetConfigName()); + this->GeneratorTarget->GetModuleDefinitionInfo(config); if (!mdi || mdi->DefFile.empty()) { return; } @@ -94,57 +96,60 @@ void cmCommonTargetGenerator::AppendFortranFormatFlags( } } -std::string cmCommonTargetGenerator::GetFlags(const std::string& l) +std::string cmCommonTargetGenerator::GetFlags(const std::string& l, + const std::string& config) { - auto i = this->FlagsByLanguage.find(l); - if (i == this->FlagsByLanguage.end()) { + auto i = this->Configs[config].FlagsByLanguage.find(l); + if (i == this->Configs[config].FlagsByLanguage.end()) { std::string flags; - this->LocalCommonGenerator->GetTargetCompileFlags( - this->GeneratorTarget, this->ConfigName, l, flags); + this->LocalCommonGenerator->GetTargetCompileFlags(this->GeneratorTarget, + config, l, flags); ByLanguageMap::value_type entry(l, flags); - i = this->FlagsByLanguage.insert(entry).first; + i = this->Configs[config].FlagsByLanguage.insert(entry).first; } return i->second; } -std::string cmCommonTargetGenerator::GetDefines(const std::string& l) +std::string cmCommonTargetGenerator::GetDefines(const std::string& l, + const std::string& config) { - auto i = this->DefinesByLanguage.find(l); - if (i == this->DefinesByLanguage.end()) { + auto i = this->Configs[config].DefinesByLanguage.find(l); + if (i == this->Configs[config].DefinesByLanguage.end()) { std::set<std::string> defines; - this->LocalCommonGenerator->GetTargetDefines(this->GeneratorTarget, - this->ConfigName, l, defines); + this->LocalCommonGenerator->GetTargetDefines(this->GeneratorTarget, config, + l, defines); std::string definesString; this->LocalCommonGenerator->JoinDefines(defines, definesString, l); ByLanguageMap::value_type entry(l, definesString); - i = this->DefinesByLanguage.insert(entry).first; + i = this->Configs[config].DefinesByLanguage.insert(entry).first; } return i->second; } -std::string cmCommonTargetGenerator::GetIncludes(std::string const& l) +std::string cmCommonTargetGenerator::GetIncludes(std::string const& l, + const std::string& config) { - auto i = this->IncludesByLanguage.find(l); - if (i == this->IncludesByLanguage.end()) { + auto i = this->Configs[config].IncludesByLanguage.find(l); + if (i == this->Configs[config].IncludesByLanguage.end()) { std::string includes; - this->AddIncludeFlags(includes, l); + this->AddIncludeFlags(includes, l, config); ByLanguageMap::value_type entry(l, includes); - i = this->IncludesByLanguage.insert(entry).first; + i = this->Configs[config].IncludesByLanguage.insert(entry).first; } return i->second; } -std::vector<std::string> cmCommonTargetGenerator::GetLinkedTargetDirectories() - const +std::vector<std::string> cmCommonTargetGenerator::GetLinkedTargetDirectories( + const std::string& config) const { std::vector<std::string> dirs; std::set<cmGeneratorTarget const*> emitted; if (cmComputeLinkInformation* cli = - this->GeneratorTarget->GetLinkInformation(this->ConfigName)) { + this->GeneratorTarget->GetLinkInformation(config)) { cmComputeLinkInformation::ItemVector const& items = cli->GetItems(); for (auto const& item : items) { cmGeneratorTarget const* linkee = item.Target; @@ -165,19 +170,24 @@ std::vector<std::string> cmCommonTargetGenerator::GetLinkedTargetDirectories() return dirs; } -std::string cmCommonTargetGenerator::ComputeTargetCompilePDB() const +std::string cmCommonTargetGenerator::ComputeTargetCompilePDB( + const std::string& config) const { std::string compilePdbPath; if (this->GeneratorTarget->GetType() > cmStateEnums::OBJECT_LIBRARY) { return compilePdbPath; } - compilePdbPath = - this->GeneratorTarget->GetCompilePDBPath(this->GetConfigName()); + compilePdbPath = this->GeneratorTarget->GetCompilePDBPath(config); if (compilePdbPath.empty()) { // Match VS default: `$(IntDir)vc$(PlatformToolsetVersion).pdb`. // A trailing slash tells the toolchain to add its default file name. - compilePdbPath = this->GeneratorTarget->GetSupportDirectory() + "/"; + compilePdbPath = this->GeneratorTarget->GetSupportDirectory(); + if (this->GlobalCommonGenerator->IsMultiConfig()) { + compilePdbPath += "/"; + compilePdbPath += config; + } + compilePdbPath += "/"; if (this->GeneratorTarget->GetType() == cmStateEnums::STATIC_LIBRARY) { // Match VS default for static libs: `$(IntDir)$(ProjectName).pdb`. compilePdbPath += this->GeneratorTarget->GetName(); @@ -188,10 +198,10 @@ std::string cmCommonTargetGenerator::ComputeTargetCompilePDB() const return compilePdbPath; } -std::string cmCommonTargetGenerator::GetManifests() +std::string cmCommonTargetGenerator::GetManifests(const std::string& config) { std::vector<cmSourceFile const*> manifest_srcs; - this->GeneratorTarget->GetManifests(manifest_srcs, this->ConfigName); + this->GeneratorTarget->GetManifests(manifest_srcs, config); std::vector<std::string> manifests; manifests.reserve(manifest_srcs.size()); diff --git a/Source/cmCommonTargetGenerator.h b/Source/cmCommonTargetGenerator.h index 17792d6..2796470 100644 --- a/Source/cmCommonTargetGenerator.h +++ b/Source/cmCommonTargetGenerator.h @@ -25,42 +25,50 @@ public: cmCommonTargetGenerator(cmGeneratorTarget* gt); virtual ~cmCommonTargetGenerator(); - std::string const& GetConfigName() const; + std::vector<std::string> const& GetConfigNames() const; protected: // Feature query methods. - const char* GetFeature(const std::string& feature); + const char* GetFeature(const std::string& feature, + const std::string& config); // Helper to add flag for windows .def file. void AddModuleDefinitionFlag(cmLinkLineComputer* linkLineComputer, - std::string& flags); + std::string& flags, const std::string& config); cmGeneratorTarget* GeneratorTarget; cmMakefile* Makefile; cmLocalCommonGenerator* LocalCommonGenerator; cmGlobalCommonGenerator* GlobalCommonGenerator; - std::string ConfigName; + std::vector<std::string> ConfigNames; void AppendFortranFormatFlags(std::string& flags, cmSourceFile const& source); - virtual void AddIncludeFlags(std::string& flags, - std::string const& lang) = 0; + virtual void AddIncludeFlags(std::string& flags, std::string const& lang, + const std::string& config) = 0; void AppendOSXVerFlag(std::string& flags, const std::string& lang, const char* name, bool so); - using ByLanguageMap = std::map<std::string, std::string>; - std::string GetFlags(const std::string& l); - ByLanguageMap FlagsByLanguage; - std::string GetDefines(const std::string& l); - ByLanguageMap DefinesByLanguage; - std::string GetIncludes(std::string const& l); - ByLanguageMap IncludesByLanguage; - std::string GetManifests(); + std::string GetFlags(const std::string& l, const std::string& config); + std::string GetDefines(const std::string& l, const std::string& config); + std::string GetIncludes(std::string const& l, const std::string& config); + std::string GetManifests(const std::string& config); + + std::vector<std::string> GetLinkedTargetDirectories( + const std::string& config) const; + std::string ComputeTargetCompilePDB(const std::string& config) const; - std::vector<std::string> GetLinkedTargetDirectories() const; - std::string ComputeTargetCompilePDB() const; +private: + using ByLanguageMap = std::map<std::string, std::string>; + struct ByConfig + { + ByLanguageMap FlagsByLanguage; + ByLanguageMap DefinesByLanguage; + ByLanguageMap IncludesByLanguage; + }; + std::map<std::string, ByConfig> Configs; }; #endif diff --git a/Source/cmComputeTargetDepends.cxx b/Source/cmComputeTargetDepends.cxx index 162bab2..58ec53a 100644 --- a/Source/cmComputeTargetDepends.cxx +++ b/Source/cmComputeTargetDepends.cxx @@ -4,6 +4,7 @@ #include <cassert> #include <cstdio> +#include <memory> #include <sstream> #include <utility> @@ -157,15 +158,12 @@ void cmComputeTargetDepends::GetTargetDirectDepends(cmGeneratorTarget const* t, void cmComputeTargetDepends::CollectTargets() { // Collect all targets from all generators. - std::vector<cmLocalGenerator*> const& lgens = - this->GlobalGenerator->GetLocalGenerators(); - for (cmLocalGenerator* lgen : lgens) { - const std::vector<cmGeneratorTarget*>& targets = - lgen->GetGeneratorTargets(); - for (cmGeneratorTarget const* ti : targets) { + auto const& lgens = this->GlobalGenerator->GetLocalGenerators(); + for (const auto& lgen : lgens) { + for (const auto& ti : lgen->GetGeneratorTargets()) { int index = static_cast<int>(this->Targets.size()); - this->TargetIndex[ti] = index; - this->Targets.push_back(ti); + this->TargetIndex[ti.get()] = index; + this->Targets.push_back(ti.get()); } } } diff --git a/Source/cmConditionEvaluator.cxx b/Source/cmConditionEvaluator.cxx index 003e60d..fda687f 100644 --- a/Source/cmConditionEvaluator.cxx +++ b/Source/cmConditionEvaluator.cxx @@ -9,6 +9,8 @@ #include <sstream> #include <utility> +#include <cmext/algorithm> + #include "cmsys/RegularExpression.hxx" #include "cmAlgorithms.h" @@ -396,7 +398,7 @@ bool cmConditionEvaluator::HandleLevel0(cmArgumentList& newArgs, // copy to the list structure auto argP1 = arg; argP1++; - cmAppend(newArgs2, argP1, argClose); + cm::append(newArgs2, argP1, argClose); newArgs2.pop_back(); // now recursively invoke IsTrue to handle the values inside the // parenthetical expression diff --git a/Source/cmCoreTryCompile.cxx b/Source/cmCoreTryCompile.cxx index 5711cae..4715cfa 100644 --- a/Source/cmCoreTryCompile.cxx +++ b/Source/cmCoreTryCompile.cxx @@ -51,6 +51,8 @@ static std::string const kCMAKE_OSX_ARCHITECTURES = "CMAKE_OSX_ARCHITECTURES"; static std::string const kCMAKE_OSX_DEPLOYMENT_TARGET = "CMAKE_OSX_DEPLOYMENT_TARGET"; static std::string const kCMAKE_OSX_SYSROOT = "CMAKE_OSX_SYSROOT"; +static std::string const kCMAKE_APPLE_ARCH_SYSROOTS = + "CMAKE_APPLE_ARCH_SYSROOTS"; static std::string const kCMAKE_POSITION_INDEPENDENT_CODE = "CMAKE_POSITION_INDEPENDENT_CODE"; static std::string const kCMAKE_SYSROOT = "CMAKE_SYSROOT"; @@ -723,6 +725,7 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv, vars.insert(kCMAKE_OSX_ARCHITECTURES); vars.insert(kCMAKE_OSX_DEPLOYMENT_TARGET); vars.insert(kCMAKE_OSX_SYSROOT); + vars.insert(kCMAKE_APPLE_ARCH_SYSROOTS); vars.insert(kCMAKE_POSITION_INDEPENDENT_CODE); vars.insert(kCMAKE_SYSROOT); vars.insert(kCMAKE_SYSROOT_COMPILE); diff --git a/Source/cmCustomCommand.cxx b/Source/cmCustomCommand.cxx index 09d269b..0dd8722 100644 --- a/Source/cmCustomCommand.cxx +++ b/Source/cmCustomCommand.cxx @@ -4,27 +4,23 @@ #include <utility> -#include "cmAlgorithms.h" -#include "cmMakefile.h" +#include <cmext/algorithm> -cmCustomCommand::cmCustomCommand(cmMakefile const* mf, - std::vector<std::string> outputs, +cmCustomCommand::cmCustomCommand(std::vector<std::string> outputs, std::vector<std::string> byproducts, std::vector<std::string> depends, cmCustomCommandLines commandLines, - const char* comment, + cmListFileBacktrace lfbt, const char* comment, const char* workingDirectory) : Outputs(std::move(outputs)) , Byproducts(std::move(byproducts)) , Depends(std::move(depends)) , CommandLines(std::move(commandLines)) + , Backtrace(std::move(lfbt)) , Comment(comment ? comment : "") , WorkingDirectory(workingDirectory ? workingDirectory : "") , HaveComment(comment != nullptr) { - if (mf) { - this->Backtrace = mf->GetBacktrace(); - } } const std::vector<std::string>& cmCustomCommand::GetOutputs() const @@ -55,12 +51,12 @@ const char* cmCustomCommand::GetComment() const void cmCustomCommand::AppendCommands(const cmCustomCommandLines& commandLines) { - cmAppend(this->CommandLines, commandLines); + cm::append(this->CommandLines, commandLines); } void cmCustomCommand::AppendDepends(const std::vector<std::string>& depends) { - cmAppend(this->Depends, depends); + cm::append(this->Depends, depends); } bool cmCustomCommand::GetEscapeOldStyle() const @@ -100,7 +96,7 @@ void cmCustomCommand::SetImplicitDepends(cmImplicitDependsList const& l) void cmCustomCommand::AppendImplicitDepends(cmImplicitDependsList const& l) { - cmAppend(this->ImplicitDepends, l); + cm::append(this->ImplicitDepends, l); } bool cmCustomCommand::GetUsesTerminal() const diff --git a/Source/cmCustomCommand.h b/Source/cmCustomCommand.h index 4689ace..d300fa5 100644 --- a/Source/cmCustomCommand.h +++ b/Source/cmCustomCommand.h @@ -12,8 +12,6 @@ #include "cmCustomCommandLines.h" #include "cmListFileCache.h" -class cmMakefile; - class cmImplicitDependsList : public std::vector<std::pair<std::string, std::string>> { @@ -28,11 +26,11 @@ class cmCustomCommand { public: /** Main constructor specifies all information for the command. */ - cmCustomCommand(cmMakefile const* mf, std::vector<std::string> outputs, + cmCustomCommand(std::vector<std::string> outputs, std::vector<std::string> byproducts, std::vector<std::string> depends, - cmCustomCommandLines commandLines, const char* comment, - const char* workingDirectory); + cmCustomCommandLines commandLines, cmListFileBacktrace lfbt, + const char* comment, const char* workingDirectory); /** Get the output file produced by the command. */ const std::vector<std::string>& GetOutputs() const; diff --git a/Source/cmCustomCommandGenerator.cxx b/Source/cmCustomCommandGenerator.cxx index c1f412d..bce27c2 100644 --- a/Source/cmCustomCommandGenerator.cxx +++ b/Source/cmCustomCommandGenerator.cxx @@ -6,7 +6,8 @@ #include <memory> #include <utility> -#include "cmAlgorithms.h" +#include <cmext/algorithm> + #include "cmCustomCommand.h" #include "cmCustomCommandLines.h" #include "cmGeneratorExpression.h" @@ -32,7 +33,7 @@ void AppendPaths(const std::vector<std::string>& inputs, it = cmSystemTools::CollapseFullPath(it); } } - cmAppend(output, result); + cm::append(output, result); } } } @@ -56,7 +57,7 @@ cmCustomCommandGenerator::cmCustomCommandGenerator(cmCustomCommand const& cc, std::unique_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(clarg); std::string parsed_arg = cge->Evaluate(this->LG, this->Config); if (this->CC.GetCommandExpandLists()) { - cmAppend(argv, cmExpandedList(parsed_arg)); + cm::append(argv, cmExpandedList(parsed_arg)); } else { argv.push_back(std::move(parsed_arg)); } @@ -201,7 +202,9 @@ void cmCustomCommandGenerator::AppendArguments(unsigned int c, if (this->OldStyle) { cmd += escapeForShellOldStyle(emulator[j]); } else { - cmd += this->LG->EscapeForShell(emulator[j], this->MakeVars); + cmd += + this->LG->EscapeForShell(emulator[j], this->MakeVars, false, false, + this->MakeVars && this->LG->IsNinjaMulti()); } } @@ -222,7 +225,9 @@ void cmCustomCommandGenerator::AppendArguments(unsigned int c, if (this->OldStyle) { cmd += escapeForShellOldStyle(arg); } else { - cmd += this->LG->EscapeForShell(arg, this->MakeVars); + cmd += + this->LG->EscapeForShell(arg, this->MakeVars, false, false, + this->MakeVars && this->LG->IsNinjaMulti()); } } } diff --git a/Source/cmDocumentationSection.h b/Source/cmDocumentationSection.h index 15cada6..641263d 100644 --- a/Source/cmDocumentationSection.h +++ b/Source/cmDocumentationSection.h @@ -8,7 +8,8 @@ #include <string> #include <vector> -#include "cmAlgorithms.h" +#include <cmext/algorithm> + #include "cmDocumentationEntry.h" // Low-level interface for custom documents: @@ -47,7 +48,7 @@ public: } void Append(const std::vector<cmDocumentationEntry>& entries) { - cmAppend(this->Entries, entries); + cm::append(this->Entries, entries); } /** Append an entry to this section using NULL terminated chars */ diff --git a/Source/cmELF.cxx b/Source/cmELF.cxx index 5976b2f..202b205 100644 --- a/Source/cmELF.cxx +++ b/Source/cmELF.cxx @@ -10,13 +10,12 @@ #include <vector> #include <cm/memory> +#include <cmext/algorithm> #include "cmsys/FStream.hxx" #include "cm_kwiml.h" -#include "cmAlgorithms.h" - // Include the ELF format information system header. #if defined(__OpenBSD__) # include <elf_abi.h> @@ -578,7 +577,7 @@ std::vector<char> cmELFInternalImpl<Types>::EncodeDynamicEntries( } char* pdyn = reinterpret_cast<char*>(&dyn); - cmAppend(result, pdyn, pdyn + sizeof(ELF_Dyn)); + cm::append(result, pdyn, pdyn + sizeof(ELF_Dyn)); } return result; diff --git a/Source/cmExecuteProcessCommand.cxx b/Source/cmExecuteProcessCommand.cxx index 80e4bcd..5be5bce 100644 --- a/Source/cmExecuteProcessCommand.cxx +++ b/Source/cmExecuteProcessCommand.cxx @@ -9,11 +9,12 @@ #include <memory> #include <vector> +#include <cmext/algorithm> + #include "cmsys/Process.h" #include "cm_static_string_view.hxx" -#include "cmAlgorithms.h" #include "cmArgumentParser.h" #include "cmExecutionStatus.h" #include "cmMakefile.h" @@ -402,6 +403,6 @@ void cmExecuteProcessCommandAppend(std::vector<char>& output, const char* data, --length; } #endif - cmAppend(output, data, data + length); + cm::append(output, data, data + length); } } diff --git a/Source/cmExportBuildFileGenerator.cxx b/Source/cmExportBuildFileGenerator.cxx index 7e9a987..dbe5a5e 100644 --- a/Source/cmExportBuildFileGenerator.cxx +++ b/Source/cmExportBuildFileGenerator.cxx @@ -8,6 +8,7 @@ #include <sstream> #include <utility> +#include "cmAlgorithms.h" #include "cmExportSet.h" #include "cmGeneratorExpression.h" #include "cmGeneratorTarget.h" diff --git a/Source/cmExportBuildFileGenerator.h b/Source/cmExportBuildFileGenerator.h index 11fbd02..66e8cbb 100644 --- a/Source/cmExportBuildFileGenerator.h +++ b/Source/cmExportBuildFileGenerator.h @@ -10,7 +10,8 @@ #include <utility> #include <vector> -#include "cmAlgorithms.h" +#include <cmext/algorithm> + #include "cmExportFileGenerator.h" #include "cmStateTypes.h" @@ -41,7 +42,7 @@ public: void GetTargets(std::vector<std::string>& targets) const; void AppendTargets(std::vector<std::string> const& targets) { - cmAppend(this->Targets, targets); + cm::append(this->Targets, targets); } void SetExportSet(cmExportSet*); diff --git a/Source/cmExportInstallAndroidMKGenerator.cxx b/Source/cmExportInstallAndroidMKGenerator.cxx index 2d732c1..9702e0e 100644 --- a/Source/cmExportInstallAndroidMKGenerator.cxx +++ b/Source/cmExportInstallAndroidMKGenerator.cxx @@ -49,7 +49,7 @@ void cmExportInstallAndroidMKGenerator::GenerateImportHeaderCode( if (te->ArchiveGenerator) { dest = te->ArchiveGenerator->GetDestination(""); } - te->Target->Target->SetProperty("__dest", dest.c_str()); + te->Target->Target->SetProperty("__dest", dest); } } diff --git a/Source/cmExportInstallFileGenerator.cxx b/Source/cmExportInstallFileGenerator.cxx index 6d29c99..987ec9e 100644 --- a/Source/cmExportInstallFileGenerator.cxx +++ b/Source/cmExportInstallFileGenerator.cxx @@ -258,15 +258,7 @@ void cmExportInstallFileGenerator::LoadConfigFiles(std::ostream& os) void cmExportInstallFileGenerator::ReplaceInstallPrefix(std::string& input) { - std::string::size_type pos = 0; - std::string::size_type lastPos = pos; - - while ((pos = input.find("$<INSTALL_PREFIX>", lastPos)) != - std::string::npos) { - std::string::size_type endPos = pos + sizeof("$<INSTALL_PREFIX>") - 1; - input.replace(pos, endPos - pos, "${_IMPORT_PREFIX}"); - lastPos = endPos; - } + cmGeneratorExpression::ReplaceInstallPrefix(input, "${_IMPORT_PREFIX}"); } bool cmExportInstallFileGenerator::GenerateImportFileConfig( @@ -525,13 +517,14 @@ void cmExportInstallFileGenerator::ComplainAboutMissingTarget( } std::string cmExportInstallFileGenerator::InstallNameDir( - cmGeneratorTarget* target, const std::string& /*config*/) + cmGeneratorTarget* target, const std::string& config) { std::string install_name_dir; cmMakefile* mf = target->Target->GetMakefile(); if (mf->IsOn("CMAKE_PLATFORM_HAS_INSTALLNAME")) { - install_name_dir = target->GetInstallNameDirForInstallTree(); + install_name_dir = + target->GetInstallNameDirForInstallTree(config, "${_IMPORT_PREFIX}"); } return install_name_dir; diff --git a/Source/cmExportLibraryDependenciesCommand.cxx b/Source/cmExportLibraryDependenciesCommand.cxx index 89093e9..dfc8de5 100644 --- a/Source/cmExportLibraryDependenciesCommand.cxx +++ b/Source/cmExportLibraryDependenciesCommand.cxx @@ -12,6 +12,7 @@ #include "cmExecutionStatus.h" #include "cmGeneratedFileStream.h" #include "cmGlobalGenerator.h" +#include "cmLocalGenerator.h" #include "cmMakefile.h" #include "cmStateTypes.h" #include "cmStringAlgorithms.h" @@ -20,6 +21,8 @@ #include "cmTargetLinkLibraryType.h" #include "cmake.h" +class cmListFileBacktrace; + static void FinalAction(cmMakefile& makefile, std::string const& filename, bool append) { @@ -150,9 +153,9 @@ bool cmExportLibraryDependenciesCommand(std::vector<std::string> const& args, std::string const& filename = args[0]; bool const append = args.size() > 1 && args[1] == "APPEND"; - status.GetMakefile().AddFinalAction( - [filename, append](cmMakefile& makefile) { - FinalAction(makefile, filename, append); + status.GetMakefile().AddGeneratorAction( + [filename, append](cmLocalGenerator& lg, const cmListFileBacktrace&) { + FinalAction(*lg.GetMakefile(), filename, append); }); return true; diff --git a/Source/cmExportTryCompileFileGenerator.cxx b/Source/cmExportTryCompileFileGenerator.cxx index fafa51b..3df6a5c 100644 --- a/Source/cmExportTryCompileFileGenerator.cxx +++ b/Source/cmExportTryCompileFileGenerator.cxx @@ -70,7 +70,8 @@ std::string cmExportTryCompileFileGenerator::FindTargets( std::unique_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(prop); cmTarget dummyHead("try_compile_dummy_exe", cmStateEnums::EXECUTABLE, - cmTarget::VisibilityNormal, tgt->Target->GetMakefile()); + cmTarget::VisibilityNormal, tgt->Target->GetMakefile(), + true); cmGeneratorTarget gDummyHead(&dummyHead, tgt->GetLocalGenerator()); diff --git a/Source/cmExtraCodeBlocksGenerator.cxx b/Source/cmExtraCodeBlocksGenerator.cxx index 5a5d959..b710467 100644 --- a/Source/cmExtraCodeBlocksGenerator.cxx +++ b/Source/cmExtraCodeBlocksGenerator.cxx @@ -3,10 +3,13 @@ #include "cmExtraCodeBlocksGenerator.h" #include <map> +#include <memory> #include <ostream> #include <set> #include <utility> +#include <cmext/algorithm> + #include "cmAlgorithms.h" #include "cmGeneratedFileStream.h" #include "cmGeneratorTarget.h" @@ -209,7 +212,7 @@ void cmExtraCodeBlocksGenerator::CreateNewProjectFile( // Collect all files std::vector<std::string> listFiles; for (cmLocalGenerator* lg : it.second) { - cmAppend(listFiles, lg->GetMakefile()->GetListFiles()); + cm::append(listFiles, lg->GetMakefile()->GetListFiles()); } // Convert @@ -283,8 +286,8 @@ void cmExtraCodeBlocksGenerator::CreateNewProjectFile( // add all executable and library targets and some of the GLOBAL // and UTILITY targets for (cmLocalGenerator* lg : lgs) { - const std::vector<cmGeneratorTarget*>& targets = lg->GetGeneratorTargets(); - for (cmGeneratorTarget* target : targets) { + const auto& targets = lg->GetGeneratorTargets(); + for (const auto& target : targets) { std::string targetName = target->GetName(); switch (target->GetType()) { case cmStateEnums::GLOBAL_TARGET: { @@ -315,7 +318,7 @@ void cmExtraCodeBlocksGenerator::CreateNewProjectFile( case cmStateEnums::SHARED_LIBRARY: case cmStateEnums::MODULE_LIBRARY: case cmStateEnums::OBJECT_LIBRARY: { - cmGeneratorTarget* gt = target; + cmGeneratorTarget* gt = target.get(); this->AppendTarget(xml, targetName, gt, make, lg, compiler, makeArgs); std::string fastTarget = cmStrCat(targetName, "/fast"); @@ -341,8 +344,8 @@ void cmExtraCodeBlocksGenerator::CreateNewProjectFile( for (cmLocalGenerator* lg : lgs) { cmMakefile* makefile = lg->GetMakefile(); - const std::vector<cmGeneratorTarget*>& targets = lg->GetGeneratorTargets(); - for (cmGeneratorTarget* target : targets) { + const auto& targets = lg->GetGeneratorTargets(); + for (const auto& target : targets) { switch (target->GetType()) { case cmStateEnums::EXECUTABLE: case cmStateEnums::STATIC_LIBRARY: @@ -352,13 +355,12 @@ void cmExtraCodeBlocksGenerator::CreateNewProjectFile( case cmStateEnums::UTILITY: // can have sources since 2.6.3 { std::vector<cmSourceFile*> sources; - cmGeneratorTarget* gt = target; - gt->GetSourceFiles(sources, - makefile->GetSafeDefinition("CMAKE_BUILD_TYPE")); + target->GetSourceFiles( + sources, makefile->GetSafeDefinition("CMAKE_BUILD_TYPE")); for (cmSourceFile* s : sources) { // don't add source files from UTILITY target which have the // GENERATED property set: - if (gt->GetType() == cmStateEnums::UTILITY && + if (target->GetType() == cmStateEnums::UTILITY && s->GetIsGenerated()) { continue; } @@ -391,7 +393,7 @@ void cmExtraCodeBlocksGenerator::CreateNewProjectFile( } CbpUnit& cbpUnit = allFiles[fullPath]; - cbpUnit.Targets.push_back(target); + cbpUnit.Targets.push_back(target.get()); } } default: // intended fallthrough @@ -558,19 +560,19 @@ void cmExtraCodeBlocksGenerator::AppendTarget( { std::vector<std::string> includes; lg->GetIncludeDirectories(includes, target, "C", buildType); - cmAppend(allIncludeDirs, includes); + cm::append(allIncludeDirs, includes); } std::string systemIncludeDirs = makefile->GetSafeDefinition( "CMAKE_EXTRA_GENERATOR_CXX_SYSTEM_INCLUDE_DIRS"); if (!systemIncludeDirs.empty()) { - cmAppend(allIncludeDirs, cmExpandedList(systemIncludeDirs)); + cm::append(allIncludeDirs, cmExpandedList(systemIncludeDirs)); } systemIncludeDirs = makefile->GetSafeDefinition( "CMAKE_EXTRA_GENERATOR_C_SYSTEM_INCLUDE_DIRS"); if (!systemIncludeDirs.empty()) { - cmAppend(allIncludeDirs, cmExpandedList(systemIncludeDirs)); + cm::append(allIncludeDirs, cmExpandedList(systemIncludeDirs)); } auto end = cmRemoveDuplicates(allIncludeDirs); diff --git a/Source/cmExtraCodeLiteGenerator.cxx b/Source/cmExtraCodeLiteGenerator.cxx index c7b7457..de40c77 100644 --- a/Source/cmExtraCodeLiteGenerator.cxx +++ b/Source/cmExtraCodeLiteGenerator.cxx @@ -4,6 +4,7 @@ #include <cstring> #include <map> +#include <memory> #include <set> #include <sstream> #include <utility> @@ -116,10 +117,9 @@ std::vector<std::string> cmExtraCodeLiteGenerator::CreateProjectsByTarget( { std::vector<std::string> retval; // for each target in the workspace create a codelite project - const std::vector<cmLocalGenerator*>& lgs = - this->GlobalGenerator->GetLocalGenerators(); - for (cmLocalGenerator* lg : lgs) { - for (cmGeneratorTarget* lt : lg->GetGeneratorTargets()) { + const auto& lgs = this->GlobalGenerator->GetLocalGenerators(); + for (const auto& lg : lgs) { + for (const auto& lt : lg->GetGeneratorTargets()) { cmStateEnums::TargetType type = lt->GetType(); std::string const& outputDir = lg->GetCurrentBinaryDirectory(); std::string targetName = lt->GetName(); @@ -142,7 +142,7 @@ std::vector<std::string> cmExtraCodeLiteGenerator::CreateProjectsByTarget( xml->Attribute("Active", "No"); xml->EndElement(); - CreateNewProjectFile(lt, filename); + CreateNewProjectFile(lt.get(), filename); break; default: break; @@ -269,9 +269,9 @@ void cmExtraCodeLiteGenerator::CreateNewProjectFile( for (cmLocalGenerator* lg : lgs) { cmMakefile* makefile = lg->GetMakefile(); - const std::vector<cmGeneratorTarget*>& targets = lg->GetGeneratorTargets(); - for (cmGeneratorTarget* target : targets) { - projectType = CollectSourceFiles(makefile, target, cFiles, otherFiles); + for (const auto& target : lg->GetGeneratorTargets()) { + projectType = + CollectSourceFiles(makefile, target.get(), cFiles, otherFiles); } } @@ -634,7 +634,10 @@ std::string cmExtraCodeLiteGenerator::GetBuildCommand( if (generator == "NMake Makefiles" || generator == "Ninja") { ss << make; } else if (generator == "MinGW Makefiles" || generator == "Unix Makefiles") { - ss << make << " -f$(ProjectPath)/Makefile -j " << this->CpuCount; + ss << make << " -f$(ProjectPath)/Makefile"; + if (this->CpuCount > 0) { + ss << " -j " << this->CpuCount; + } } if (!targetName.empty()) { ss << " " << targetName; diff --git a/Source/cmExtraEclipseCDT4Generator.cxx b/Source/cmExtraEclipseCDT4Generator.cxx index b286acf..78cabce 100644 --- a/Source/cmExtraEclipseCDT4Generator.cxx +++ b/Source/cmExtraEclipseCDT4Generator.cxx @@ -6,6 +6,7 @@ #include <cassert> #include <cstdio> #include <map> +#include <memory> #include <sstream> #include <utility> @@ -98,7 +99,7 @@ void cmExtraEclipseCDT4Generator::EnableLanguage( void cmExtraEclipseCDT4Generator::Generate() { - cmLocalGenerator* lg = this->GlobalGenerator->GetLocalGenerators()[0]; + const auto& lg = this->GlobalGenerator->GetLocalGenerators()[0]; const cmMakefile* mf = lg->GetMakefile(); std::string eclipseVersion = mf->GetSafeDefinition("CMAKE_ECLIPSE_VERSION"); @@ -175,7 +176,7 @@ void cmExtraEclipseCDT4Generator::Generate() void cmExtraEclipseCDT4Generator::CreateSettingsResourcePrefsFile() { - cmLocalGenerator* lg = this->GlobalGenerator->GetLocalGenerators()[0]; + const auto& lg = this->GlobalGenerator->GetLocalGenerators()[0]; cmMakefile* mf = lg->GetMakefile(); const std::string filename = @@ -198,7 +199,7 @@ void cmExtraEclipseCDT4Generator::CreateSourceProjectFile() assert(this->HomeDirectory != this->HomeOutputDirectory); // set up the project name: <project>-Source@<baseSourcePathName> - cmLocalGenerator* lg = this->GlobalGenerator->GetLocalGenerators()[0]; + const auto& lg = this->GlobalGenerator->GetLocalGenerators()[0]; std::string name = cmExtraEclipseCDT4Generator::GenerateProjectName( lg->GetProjectName(), "Source", cmExtraEclipseCDT4Generator::GetPathBasename(this->HomeDirectory)); @@ -231,9 +232,9 @@ void cmExtraEclipseCDT4Generator::CreateSourceProjectFile() void cmExtraEclipseCDT4Generator::AddEnvVar(std::ostream& out, const char* envVar, - cmLocalGenerator* lg) + cmLocalGenerator& lg) { - cmMakefile* mf = lg->GetMakefile(); + cmMakefile* mf = lg.GetMakefile(); // get the variables from the environment and from the cache and then // figure out which one to use: @@ -243,7 +244,7 @@ void cmExtraEclipseCDT4Generator::AddEnvVar(std::ostream& out, std::string cacheEntryName = cmStrCat("CMAKE_ECLIPSE_ENVVAR_", envVar); const std::string* cacheValue = - lg->GetState()->GetInitializedCacheValue(cacheEntryName); + lg.GetState()->GetInitializedCacheValue(cacheEntryName); // now we have both, decide which one to use std::string valueToUse; @@ -256,7 +257,7 @@ void cmExtraEclipseCDT4Generator::AddEnvVar(std::ostream& out, valueToUse = envVarValue; mf->AddCacheDefinition(cacheEntryName, valueToUse.c_str(), cacheEntryName.c_str(), cmStateEnums::STRING, true); - mf->GetCMakeInstance()->SaveCache(lg->GetBinaryDirectory()); + mf->GetCMakeInstance()->SaveCache(lg.GetBinaryDirectory()); } else if (!envVarSet && cacheValue != nullptr) { // It is already in the cache, but not in the env, so use it from the cache valueToUse = *cacheValue; @@ -272,7 +273,7 @@ void cmExtraEclipseCDT4Generator::AddEnvVar(std::ostream& out, mf->AddCacheDefinition(cacheEntryName, valueToUse.c_str(), cacheEntryName.c_str(), cmStateEnums::STRING, true); - mf->GetCMakeInstance()->SaveCache(lg->GetBinaryDirectory()); + mf->GetCMakeInstance()->SaveCache(lg.GetBinaryDirectory()); } } @@ -283,7 +284,7 @@ void cmExtraEclipseCDT4Generator::AddEnvVar(std::ostream& out, void cmExtraEclipseCDT4Generator::CreateProjectFile() { - cmLocalGenerator* lg = this->GlobalGenerator->GetLocalGenerators()[0]; + const auto& lg = this->GlobalGenerator->GetLocalGenerators()[0]; cmMakefile* mf = lg->GetMakefile(); const std::string filename = this->HomeOutputDirectory + "/.project"; @@ -350,15 +351,15 @@ void cmExtraEclipseCDT4Generator::CreateProjectFile() // set vsvars32.bat environment available at CMake time, // but not necessarily when eclipse is open if (compilerId == "MSVC") { - AddEnvVar(environment, "PATH", lg); - AddEnvVar(environment, "INCLUDE", lg); - AddEnvVar(environment, "LIB", lg); - AddEnvVar(environment, "LIBPATH", lg); + AddEnvVar(environment, "PATH", *lg); + AddEnvVar(environment, "INCLUDE", *lg); + AddEnvVar(environment, "LIB", *lg); + AddEnvVar(environment, "LIBPATH", *lg); } else if (compilerId == "Intel") { // if the env.var is set, use this one and put it in the cache // if the env.var is not set, but the value is in the cache, // use it from the cache: - AddEnvVar(environment, "INTEL_LICENSE_FILE", lg); + AddEnvVar(environment, "INTEL_LICENSE_FILE", *lg); } AppendDictionary(xml, "org.eclipse.cdt.make.core.environment", environment.str()); @@ -494,11 +495,11 @@ void cmExtraEclipseCDT4Generator::CreateLinksForTargets(cmXMLWriter& xml) cmExtraEclipseCDT4Generator::AppendLinkedResource( xml, linkName, "virtual:/virtual", VirtualFolder); - for (cmLocalGenerator* lg : this->GlobalGenerator->GetLocalGenerators()) { + for (const auto& lg : this->GlobalGenerator->GetLocalGenerators()) { cmMakefile* makefile = lg->GetMakefile(); - const std::vector<cmGeneratorTarget*>& targets = lg->GetGeneratorTargets(); + const auto& targets = lg->GetGeneratorTargets(); - for (cmGeneratorTarget* target : targets) { + for (const auto& target : targets) { std::string linkName2 = cmStrCat(linkName, '/'); switch (target->GetType()) { case cmStateEnums::EXECUTABLE: @@ -519,10 +520,9 @@ void cmExtraEclipseCDT4Generator::CreateLinksForTargets(cmXMLWriter& xml) std::vector<cmSourceGroup> sourceGroups = makefile->GetSourceGroups(); // get the files from the source lists then add them to the groups - cmGeneratorTarget* gt = const_cast<cmGeneratorTarget*>(target); std::vector<cmSourceFile*> files; - gt->GetSourceFiles(files, - makefile->GetSafeDefinition("CMAKE_BUILD_TYPE")); + target->GetSourceFiles( + files, makefile->GetSafeDefinition("CMAKE_BUILD_TYPE")); for (cmSourceFile* sf : files) { // Add the file to the list of sources. std::string const& source = sf->ResolveFullPath(); @@ -606,7 +606,7 @@ void cmExtraEclipseCDT4Generator::CreateCProjectFile() const { std::set<std::string> emmited; - cmLocalGenerator* lg = this->GlobalGenerator->GetLocalGenerators()[0]; + const auto& lg = this->GlobalGenerator->GetLocalGenerators()[0]; const cmMakefile* mf = lg->GetMakefile(); const std::string filename = this->HomeOutputDirectory + "/.cproject"; @@ -752,7 +752,7 @@ void cmExtraEclipseCDT4Generator::CreateCProjectFile() const // add pre-processor definitions to allow eclipse to gray out sections emmited.clear(); - for (cmLocalGenerator* lgen : this->GlobalGenerator->GetLocalGenerators()) { + for (const auto& lgen : this->GlobalGenerator->GetLocalGenerators()) { if (const char* cdefs = lgen->GetMakefile()->GetProperty("COMPILE_DEFINITIONS")) { @@ -859,16 +859,15 @@ void cmExtraEclipseCDT4Generator::CreateCProjectFile() const // include dirs emmited.clear(); - for (cmLocalGenerator* lgen : this->GlobalGenerator->GetLocalGenerators()) { - const std::vector<cmGeneratorTarget*>& targets = - lgen->GetGeneratorTargets(); - for (cmGeneratorTarget* target : targets) { + for (const auto& lgen : this->GlobalGenerator->GetLocalGenerators()) { + const auto& targets = lgen->GetGeneratorTargets(); + for (const auto& target : targets) { if (target->GetType() == cmStateEnums::INTERFACE_LIBRARY) { continue; } std::vector<std::string> includeDirs; std::string config = mf->GetSafeDefinition("CMAKE_BUILD_TYPE"); - lgen->GetIncludeDirectories(includeDirs, target, "C", config); + lgen->GetIncludeDirectories(includeDirs, target.get(), "C", config); this->AppendIncludeDirectories(xml, includeDirs, emmited); } } @@ -915,16 +914,15 @@ void cmExtraEclipseCDT4Generator::CreateCProjectFile() const // add all executable and library targets and some of the GLOBAL // and UTILITY targets - for (cmLocalGenerator* lgen : this->GlobalGenerator->GetLocalGenerators()) { - const std::vector<cmGeneratorTarget*>& targets = - lgen->GetGeneratorTargets(); + for (const auto& lgen : this->GlobalGenerator->GetLocalGenerators()) { + const auto& targets = lgen->GetGeneratorTargets(); std::string subdir = lgen->MaybeConvertToRelativePath( this->HomeOutputDirectory, lgen->GetCurrentBinaryDirectory()); if (subdir == ".") { subdir.clear(); } - for (cmGeneratorTarget* target : targets) { + for (const auto& target : targets) { std::string targetName = target->GetName(); switch (target->GetType()) { case cmStateEnums::GLOBAL_TARGET: { @@ -975,8 +973,7 @@ void cmExtraEclipseCDT4Generator::CreateCProjectFile() const std::string cleanArgs = cmStrCat("-E chdir \"", lgen->GetCurrentBinaryDirectory(), "\" \"", cmSystemTools::GetCMakeCommand(), "\" -P \""); - cmGeneratorTarget* gt = target; - cleanArgs += lgen->GetTargetDirectory(gt); + cleanArgs += lgen->GetTargetDirectory(target.get()); cleanArgs += "/cmake_clean.cmake\""; cmExtraEclipseCDT4Generator::AppendTarget( xml, "Clean", cmSystemTools::GetCMakeCommand(), cleanArgs, diff --git a/Source/cmExtraEclipseCDT4Generator.h b/Source/cmExtraEclipseCDT4Generator.h index ff4c59e..a7aa549 100644 --- a/Source/cmExtraEclipseCDT4Generator.h +++ b/Source/cmExtraEclipseCDT4Generator.h @@ -86,7 +86,7 @@ private: std::set<std::string>& emittedDirs); static void AddEnvVar(std::ostream& out, const char* envVar, - cmLocalGenerator* lg); + cmLocalGenerator& lg); void WriteGroups(std::vector<cmSourceGroup> const& sourceGroups, std::string& linkName, cmXMLWriter& xml); diff --git a/Source/cmExtraKateGenerator.cxx b/Source/cmExtraKateGenerator.cxx index e8c9dd0..e463420 100644 --- a/Source/cmExtraKateGenerator.cxx +++ b/Source/cmExtraKateGenerator.cxx @@ -3,6 +3,7 @@ #include "cmExtraKateGenerator.h" #include <cstring> +#include <memory> #include <ostream> #include <set> #include <vector> @@ -40,21 +41,21 @@ cmExternalMakefileProjectGeneratorFactory* cmExtraKateGenerator::GetFactory() void cmExtraKateGenerator::Generate() { - cmLocalGenerator* lg = this->GlobalGenerator->GetLocalGenerators()[0]; + const auto& lg = this->GlobalGenerator->GetLocalGenerators()[0]; const cmMakefile* mf = lg->GetMakefile(); this->ProjectName = this->GenerateProjectName( lg->GetProjectName(), mf->GetSafeDefinition("CMAKE_BUILD_TYPE"), this->GetPathBasename(lg->GetBinaryDirectory())); this->UseNinja = (this->GlobalGenerator->GetName() == "Ninja"); - this->CreateKateProjectFile(lg); - this->CreateDummyKateProjectFile(lg); + this->CreateKateProjectFile(*lg); + this->CreateDummyKateProjectFile(*lg); } void cmExtraKateGenerator::CreateKateProjectFile( - const cmLocalGenerator* lg) const + const cmLocalGenerator& lg) const { - std::string filename = cmStrCat(lg->GetBinaryDirectory(), "/.kateproject"); + std::string filename = cmStrCat(lg.GetBinaryDirectory(), "/.kateproject"); cmGeneratedFileStream fout(filename); if (!fout) { return; @@ -64,21 +65,21 @@ void cmExtraKateGenerator::CreateKateProjectFile( fout << "{\n" "\t\"name\": \"" << this->ProjectName << "\",\n" - "\t\"directory\": \"" << lg->GetSourceDirectory() << "\",\n" + "\t\"directory\": \"" << lg.GetSourceDirectory() << "\",\n" "\t\"files\": [ { " << this->GenerateFilesString(lg) << "} ],\n"; /* clang-format on */ this->WriteTargets(lg, fout); fout << "}\n"; } -void cmExtraKateGenerator::WriteTargets(const cmLocalGenerator* lg, +void cmExtraKateGenerator::WriteTargets(const cmLocalGenerator& lg, cmGeneratedFileStream& fout) const { - cmMakefile const* mf = lg->GetMakefile(); + cmMakefile const* mf = lg.GetMakefile(); const std::string& make = mf->GetRequiredDefinition("CMAKE_MAKE_PROGRAM"); const std::string& makeArgs = mf->GetSafeDefinition("CMAKE_KATE_MAKE_ARGUMENTS"); - std::string const& homeOutputDir = lg->GetBinaryDirectory(); + std::string const& homeOutputDir = lg.GetBinaryDirectory(); /* clang-format off */ fout << @@ -109,14 +110,12 @@ void cmExtraKateGenerator::WriteTargets(const cmLocalGenerator* lg, // add all executable and library targets and some of the GLOBAL // and UTILITY targets - for (cmLocalGenerator* localGen : - this->GlobalGenerator->GetLocalGenerators()) { - const std::vector<cmGeneratorTarget*>& targets = - localGen->GetGeneratorTargets(); + for (const auto& localGen : this->GlobalGenerator->GetLocalGenerators()) { + const auto& targets = localGen->GetGeneratorTargets(); std::string currentDir = localGen->GetCurrentBinaryDirectory(); bool topLevel = (currentDir == localGen->GetBinaryDirectory()); - for (cmGeneratorTarget* target : targets) { + for (const auto& target : targets) { std::string const& targetName = target->GetName(); switch (target->GetType()) { case cmStateEnums::GLOBAL_TARGET: { @@ -205,10 +204,10 @@ void cmExtraKateGenerator::AppendTarget(cmGeneratedFileStream& fout, } void cmExtraKateGenerator::CreateDummyKateProjectFile( - const cmLocalGenerator* lg) const + const cmLocalGenerator& lg) const { std::string filename = - cmStrCat(lg->GetBinaryDirectory(), '/', this->ProjectName, ".kateproject"); + cmStrCat(lg.GetBinaryDirectory(), '/', this->ProjectName, ".kateproject"); cmGeneratedFileStream fout(filename); if (!fout) { return; @@ -219,26 +218,25 @@ void cmExtraKateGenerator::CreateDummyKateProjectFile( } std::string cmExtraKateGenerator::GenerateFilesString( - const cmLocalGenerator* lg) const + const cmLocalGenerator& lg) const { - std::string s = cmStrCat(lg->GetSourceDirectory(), "/.git"); + std::string s = cmStrCat(lg.GetSourceDirectory(), "/.git"); if (cmSystemTools::FileExists(s)) { return "\"git\": 1 "; } - s = cmStrCat(lg->GetSourceDirectory(), "/.svn"); + s = cmStrCat(lg.GetSourceDirectory(), "/.svn"); if (cmSystemTools::FileExists(s)) { return "\"svn\": 1 "; } - s = cmStrCat(lg->GetSourceDirectory(), '/'); + s = cmStrCat(lg.GetSourceDirectory(), '/'); std::set<std::string> files; std::string tmp; - const std::vector<cmLocalGenerator*>& lgs = - this->GlobalGenerator->GetLocalGenerators(); + const auto& lgs = this->GlobalGenerator->GetLocalGenerators(); - for (cmLocalGenerator* lgen : lgs) { + for (const auto& lgen : lgs) { cmMakefile* makefile = lgen->GetMakefile(); const std::vector<std::string>& listFiles = makefile->GetListFiles(); for (std::string const& listFile : listFiles) { diff --git a/Source/cmExtraKateGenerator.h b/Source/cmExtraKateGenerator.h index be1376a..1fb81b4 100644 --- a/Source/cmExtraKateGenerator.h +++ b/Source/cmExtraKateGenerator.h @@ -25,16 +25,16 @@ public: void Generate() override; private: - void CreateKateProjectFile(const cmLocalGenerator* lg) const; - void CreateDummyKateProjectFile(const cmLocalGenerator* lg) const; - void WriteTargets(const cmLocalGenerator* lg, + void CreateKateProjectFile(const cmLocalGenerator& lg) const; + void CreateDummyKateProjectFile(const cmLocalGenerator& lg) const; + void WriteTargets(const cmLocalGenerator& lg, cmGeneratedFileStream& fout) const; void AppendTarget(cmGeneratedFileStream& fout, const std::string& target, const std::string& make, const std::string& makeArgs, const std::string& path, const std::string& homeOutputDir) const; - std::string GenerateFilesString(const cmLocalGenerator* lg) const; + std::string GenerateFilesString(const cmLocalGenerator& lg) const; std::string GetPathBasename(const std::string& path) const; std::string GenerateProjectName(const std::string& name, const std::string& type, diff --git a/Source/cmExtraSublimeTextGenerator.cxx b/Source/cmExtraSublimeTextGenerator.cxx index 495324c..603fea3 100644 --- a/Source/cmExtraSublimeTextGenerator.cxx +++ b/Source/cmExtraSublimeTextGenerator.cxx @@ -3,6 +3,7 @@ #include "cmExtraSublimeTextGenerator.h" #include <cstring> +#include <memory> #include <set> #include <sstream> #include <utility> @@ -182,8 +183,8 @@ void cmExtraSublimeTextGenerator::AppendAllTargets( // and UTILITY targets for (cmLocalGenerator* lg : lgs) { cmMakefile* makefile = lg->GetMakefile(); - const std::vector<cmGeneratorTarget*>& targets = lg->GetGeneratorTargets(); - for (cmGeneratorTarget* target : targets) { + const auto& targets = lg->GetGeneratorTargets(); + for (const auto& target : targets) { std::string targetName = target->GetName(); switch (target->GetType()) { case cmStateEnums::GLOBAL_TARGET: { @@ -216,11 +217,11 @@ void cmExtraSublimeTextGenerator::AppendAllTargets( case cmStateEnums::SHARED_LIBRARY: case cmStateEnums::MODULE_LIBRARY: case cmStateEnums::OBJECT_LIBRARY: { - this->AppendTarget(fout, targetName, lg, target, make.c_str(), + this->AppendTarget(fout, targetName, lg, target.get(), make.c_str(), makefile, compiler.c_str(), sourceFileFlags, false); std::string fastTarget = cmStrCat(targetName, "/fast"); - this->AppendTarget(fout, fastTarget, lg, target, make.c_str(), + this->AppendTarget(fout, fastTarget, lg, target.get(), make.c_str(), makefile, compiler.c_str(), sourceFileFlags, false); } break; diff --git a/Source/cmFLTKWrapUICommand.cxx b/Source/cmFLTKWrapUICommand.cxx index 11844e4..d88617a 100644 --- a/Source/cmFLTKWrapUICommand.cxx +++ b/Source/cmFLTKWrapUICommand.cxx @@ -6,15 +6,20 @@ #include "cmCustomCommandLines.h" #include "cmExecutionStatus.h" +#include "cmListFileCache.h" +#include "cmLocalGenerator.h" #include "cmMakefile.h" +#include "cmMessageType.h" #include "cmRange.h" #include "cmSourceFile.h" #include "cmStringAlgorithms.h" #include "cmSystemTools.h" +#include "cmake.h" class cmTarget; -static void FinalAction(cmMakefile& makefile, std::string const& name) +static void FinalAction(cmMakefile& makefile, std::string const& name, + const cmListFileBacktrace& lfbt) { // people should add the srcs to the target themselves, but the old command // didn't support that, so check and see if they added the files in and if @@ -26,7 +31,8 @@ static void FinalAction(cmMakefile& makefile, std::string const& name) ". The problem was found while processing the source directory: ", makefile.GetCurrentSourceDirectory(), ". This FLTK_WRAP_UI call will be ignored."); - cmSystemTools::Message(msg, "Warning"); + makefile.GetCMakeInstance()->IssueMessage(MessageType::AUTHOR_ERROR, msg, + lfbt); } } @@ -116,7 +122,9 @@ bool cmFLTKWrapUICommand(std::vector<std::string> const& args, std::string const varName = target + "_FLTK_UI_SRCS"; mf.AddDefinition(varName, sourceListValue); - mf.AddFinalAction( - [target](cmMakefile& makefile) { FinalAction(makefile, target); }); + mf.AddGeneratorAction( + [target](cmLocalGenerator& lg, const cmListFileBacktrace& lfbt) { + FinalAction(*lg.GetMakefile(), target, lfbt); + }); return true; } diff --git a/Source/cmFileAPICMakeFiles.cxx b/Source/cmFileAPICMakeFiles.cxx index f419997..44ba96c 100644 --- a/Source/cmFileAPICMakeFiles.cxx +++ b/Source/cmFileAPICMakeFiles.cxx @@ -2,6 +2,7 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmFileAPICMakeFiles.h" +#include <memory> #include <string> #include <vector> @@ -67,7 +68,7 @@ Json::Value CMakeFiles::DumpInputs() cmGlobalGenerator* gg = this->FileAPI.GetCMakeInstance()->GetGlobalGenerator(); - for (cmLocalGenerator const* lg : gg->GetLocalGenerators()) { + for (const auto& lg : gg->GetLocalGenerators()) { cmMakefile const* mf = lg->GetMakefile(); for (std::string const& file : mf->GetListFiles()) { inputs.append(this->DumpInput(file)); diff --git a/Source/cmFileAPICodemodel.cxx b/Source/cmFileAPICodemodel.cxx index d7993c7..7a2d9d5 100644 --- a/Source/cmFileAPICodemodel.cxx +++ b/Source/cmFileAPICodemodel.cxx @@ -15,9 +15,10 @@ #include <utility> #include <vector> +#include <cmext/algorithm> + #include "cm_jsoncpp_value.h" -#include "cmAlgorithms.h" #include "cmCryptoHash.h" #include "cmFileAPI.h" #include "cmGeneratorExpression.h" @@ -469,17 +470,17 @@ void CodemodelConfig::ProcessDirectories() { cmGlobalGenerator* gg = this->FileAPI.GetCMakeInstance()->GetGlobalGenerator(); - std::vector<cmLocalGenerator*> const& localGens = gg->GetLocalGenerators(); + auto const& localGens = gg->GetLocalGenerators(); // Add directories in forward order to process parents before children. this->Directories.reserve(localGens.size()); - for (cmLocalGenerator* lg : localGens) { + for (const auto& lg : localGens) { auto directoryIndex = static_cast<Json::ArrayIndex>(this->Directories.size()); this->Directories.emplace_back(); Directory& d = this->Directories[directoryIndex]; d.Snapshot = lg->GetStateSnapshot().GetBuildsystemDirectory(); - d.LocalGenerator = lg; + d.LocalGenerator = lg.get(); this->DirectoryMap[d.Snapshot] = directoryIndex; d.ProjectIndex = this->AddProject(d.Snapshot); @@ -554,8 +555,8 @@ Json::Value CodemodelConfig::DumpTargets() std::vector<cmGeneratorTarget*> targetList; cmGlobalGenerator* gg = this->FileAPI.GetCMakeInstance()->GetGlobalGenerator(); - for (cmLocalGenerator const* lg : gg->GetLocalGenerators()) { - cmAppend(targetList, lg->GetGeneratorTargets()); + for (const auto& lg : gg->GetLocalGenerators()) { + cm::append(targetList, lg->GetGeneratorTargets()); } std::sort(targetList.begin(), targetList.end(), [](cmGeneratorTarget* l, cmGeneratorTarget* r) { diff --git a/Source/cmFileCommand.cxx b/Source/cmFileCommand.cxx index d55b959..1fdfa87 100644 --- a/Source/cmFileCommand.cxx +++ b/Source/cmFileCommand.cxx @@ -15,6 +15,7 @@ #include <vector> #include <cm/memory> +#include <cmext/algorithm> #include "cmsys/FStream.hxx" #include "cmsys/Glob.hxx" @@ -24,7 +25,6 @@ #include "cm_static_string_view.hxx" #include "cm_sys_stat.h" -#include "cmAlgorithms.h" #include "cmArgumentParser.h" #include "cmCryptoHash.h" #include "cmExecutionStatus.h" @@ -783,7 +783,7 @@ bool HandleGlobImpl(std::vector<std::string> const& args, bool recurse, } std::vector<std::string>& foundFiles = g.GetFiles(); - cmAppend(files, foundFiles); + cm::append(files, foundFiles); if (configureDepends) { std::sort(foundFiles.begin(), foundFiles.end()); @@ -1394,8 +1394,8 @@ size_t cmWriteToMemoryCallback(void* ptr, size_t size, size_t nmemb, { int realsize = static_cast<int>(size * nmemb); const char* chPtr = static_cast<char*>(ptr); - cmAppend(*static_cast<cmFileCommandVectorOfChar*>(data), chPtr, - chPtr + realsize); + cm::append(*static_cast<cmFileCommandVectorOfChar*>(data), chPtr, + chPtr + realsize); return realsize; } @@ -1408,7 +1408,7 @@ size_t cmFileCommandCurlDebugCallback(CURL*, curl_infotype type, char* chPtr, case CURLINFO_TEXT: case CURLINFO_HEADER_IN: case CURLINFO_HEADER_OUT: - cmAppend(vec, chPtr, chPtr + size); + cm::append(vec, chPtr, chPtr + size); break; case CURLINFO_DATA_IN: case CURLINFO_DATA_OUT: @@ -1418,7 +1418,7 @@ size_t cmFileCommandCurlDebugCallback(CURL*, curl_infotype type, char* chPtr, int n = sprintf(buf, "[%" KWIML_INT_PRIu64 " bytes data]\n", static_cast<KWIML_INT_uint64_t>(size)); if (n > 0) { - cmAppend(vec, buf, buf + n); + cm::append(vec, buf, buf + n); } } break; default: diff --git a/Source/cmFileLock.cxx b/Source/cmFileLock.cxx index e90f571..6010233 100644 --- a/Source/cmFileLock.cxx +++ b/Source/cmFileLock.cxx @@ -3,11 +3,23 @@ #include "cmFileLock.h" #include <cassert> +#include <utility> #include "cmFileLockResult.h" // Common implementation +cmFileLock::cmFileLock(cmFileLock&& other) noexcept +{ + this->File = other.File; +#if defined(_WIN32) + other.File = INVALID_HANDLE_VALUE; +#else + other.File = -1; +#endif + this->Filename = std::move(other.Filename); +} + cmFileLock::~cmFileLock() { if (!this->Filename.empty()) { @@ -17,6 +29,19 @@ cmFileLock::~cmFileLock() } } +cmFileLock& cmFileLock::operator=(cmFileLock&& other) noexcept +{ + this->File = other.File; +#if defined(_WIN32) + other.File = INVALID_HANDLE_VALUE; +#else + other.File = -1; +#endif + this->Filename = std::move(other.Filename); + + return *this; +} + cmFileLockResult cmFileLock::Lock(const std::string& filename, unsigned long timeout) { diff --git a/Source/cmFileLock.h b/Source/cmFileLock.h index 2130d65..5fe068e 100644 --- a/Source/cmFileLock.h +++ b/Source/cmFileLock.h @@ -26,7 +26,9 @@ public: ~cmFileLock(); cmFileLock(cmFileLock const&) = delete; + cmFileLock(cmFileLock&&) noexcept; cmFileLock& operator=(cmFileLock const&) = delete; + cmFileLock& operator=(cmFileLock&&) noexcept; /** * @brief Lock the file. diff --git a/Source/cmFileLockPool.cxx b/Source/cmFileLockPool.cxx index 8db2db2..e1f6e94 100644 --- a/Source/cmFileLockPool.cxx +++ b/Source/cmFileLockPool.cxx @@ -3,40 +3,34 @@ #include "cmFileLockPool.h" #include <cassert> +#include <utility> -#include "cmAlgorithms.h" #include "cmFileLock.h" #include "cmFileLockResult.h" cmFileLockPool::cmFileLockPool() = default; -cmFileLockPool::~cmFileLockPool() -{ - cmDeleteAll(this->FunctionScopes); - cmDeleteAll(this->FileScopes); -} +cmFileLockPool::~cmFileLockPool() = default; void cmFileLockPool::PushFunctionScope() { - this->FunctionScopes.push_back(new ScopePool()); + this->FunctionScopes.push_back(ScopePool()); } void cmFileLockPool::PopFunctionScope() { assert(!this->FunctionScopes.empty()); - delete this->FunctionScopes.back(); this->FunctionScopes.pop_back(); } void cmFileLockPool::PushFileScope() { - this->FileScopes.push_back(new ScopePool()); + this->FileScopes.push_back(ScopePool()); } void cmFileLockPool::PopFileScope() { assert(!this->FileScopes.empty()); - delete this->FileScopes.back(); this->FileScopes.pop_back(); } @@ -49,7 +43,7 @@ cmFileLockResult cmFileLockPool::LockFunctionScope(const std::string& filename, if (this->FunctionScopes.empty()) { return cmFileLockResult::MakeNoFunction(); } - return this->FunctionScopes.back()->Lock(filename, timeoutSec); + return this->FunctionScopes.back().Lock(filename, timeoutSec); } cmFileLockResult cmFileLockPool::LockFileScope(const std::string& filename, @@ -59,7 +53,7 @@ cmFileLockResult cmFileLockPool::LockFileScope(const std::string& filename, return cmFileLockResult::MakeAlreadyLocked(); } assert(!this->FileScopes.empty()); - return this->FileScopes.back()->Lock(filename, timeoutSec); + return this->FileScopes.back().Lock(filename, timeoutSec); } cmFileLockResult cmFileLockPool::LockProcessScope(const std::string& filename, @@ -74,14 +68,14 @@ cmFileLockResult cmFileLockPool::LockProcessScope(const std::string& filename, cmFileLockResult cmFileLockPool::Release(const std::string& filename) { for (auto& funcScope : this->FunctionScopes) { - const cmFileLockResult result = funcScope->Release(filename); + const cmFileLockResult result = funcScope.Release(filename); if (!result.IsOk()) { return result; } } for (auto& fileScope : this->FileScopes) { - const cmFileLockResult result = fileScope->Release(filename); + const cmFileLockResult result = fileScope.Release(filename); if (!result.IsOk()) { return result; } @@ -93,14 +87,14 @@ cmFileLockResult cmFileLockPool::Release(const std::string& filename) bool cmFileLockPool::IsAlreadyLocked(const std::string& filename) const { for (auto const& funcScope : this->FunctionScopes) { - const bool result = funcScope->IsAlreadyLocked(filename); + const bool result = funcScope.IsAlreadyLocked(filename); if (result) { return true; } } for (auto const& fileScope : this->FileScopes) { - const bool result = fileScope->IsAlreadyLocked(filename); + const bool result = fileScope.IsAlreadyLocked(filename); if (result) { return true; } @@ -111,21 +105,29 @@ bool cmFileLockPool::IsAlreadyLocked(const std::string& filename) const cmFileLockPool::ScopePool::ScopePool() = default; -cmFileLockPool::ScopePool::~ScopePool() +cmFileLockPool::ScopePool::~ScopePool() = default; + +cmFileLockPool::ScopePool::ScopePool(ScopePool&&) noexcept = default; + +cmFileLockPool::ScopePool& cmFileLockPool::ScopePool::operator=( + ScopePool&& other) noexcept { - cmDeleteAll(this->Locks); + if (this != &other) { + this->Locks = std::move(other.Locks); + } + + return *this; } cmFileLockResult cmFileLockPool::ScopePool::Lock(const std::string& filename, unsigned long timeoutSec) { - cmFileLock* lock = new cmFileLock(); - const cmFileLockResult result = lock->Lock(filename, timeoutSec); + cmFileLock lock; + const cmFileLockResult result = lock.Lock(filename, timeoutSec); if (result.IsOk()) { - this->Locks.push_back(lock); + this->Locks.push_back(std::move(lock)); return cmFileLockResult::MakeOk(); } - delete lock; return result; } @@ -133,8 +135,8 @@ cmFileLockResult cmFileLockPool::ScopePool::Release( const std::string& filename) { for (auto& lock : this->Locks) { - if (lock->IsLocked(filename)) { - return lock->Release(); + if (lock.IsLocked(filename)) { + return lock.Release(); } } return cmFileLockResult::MakeOk(); @@ -144,7 +146,7 @@ bool cmFileLockPool::ScopePool::IsAlreadyLocked( const std::string& filename) const { for (auto const& lock : this->Locks) { - if (lock->IsLocked(filename)) { + if (lock.IsLocked(filename)) { return true; } } diff --git a/Source/cmFileLockPool.h b/Source/cmFileLockPool.h index dae68dd..d45c82c 100644 --- a/Source/cmFileLockPool.h +++ b/Source/cmFileLockPool.h @@ -8,7 +8,8 @@ #include <string> #include <vector> -class cmFileLock; +#include "cmFileLock.h" + class cmFileLockResult; class cmFileLockPool @@ -64,7 +65,9 @@ private: ~ScopePool(); ScopePool(ScopePool const&) = delete; + ScopePool(ScopePool&&) noexcept; ScopePool& operator=(ScopePool const&) = delete; + ScopePool& operator=(ScopePool&&) noexcept; cmFileLockResult Lock(const std::string& filename, unsigned long timeoutSec); @@ -72,17 +75,12 @@ private: bool IsAlreadyLocked(const std::string& filename) const; private: - using List = std::vector<cmFileLock*>; - using It = List::iterator; - using CIt = List::const_iterator; + using List = std::vector<cmFileLock>; List Locks; }; - using List = std::vector<ScopePool*>; - - using It = List::iterator; - using CIt = List::const_iterator; + using List = std::vector<ScopePool>; List FunctionScopes; List FileScopes; diff --git a/Source/cmFindBase.cxx b/Source/cmFindBase.cxx index 7d74118..97f6e14 100644 --- a/Source/cmFindBase.cxx +++ b/Source/cmFindBase.cxx @@ -7,7 +7,8 @@ #include <iostream> #include <map> -#include "cmAlgorithms.h" +#include <cmext/algorithm> + #include "cmMakefile.h" #include "cmRange.h" #include "cmSearchPath.h" @@ -153,7 +154,7 @@ bool cmFindBase::ParseArguments(std::vector<std::string> const& argsIn) std::vector<std::string> shortArgs = this->Names; this->Names.clear(); // clear out any values in Names this->Names.push_back(shortArgs[0]); - cmAppend(this->UserGuessArgs, shortArgs.begin() + 1, shortArgs.end()); + cm::append(this->UserGuessArgs, shortArgs.begin() + 1, shortArgs.end()); } this->ExpandPaths(); diff --git a/Source/cmFindCommon.cxx b/Source/cmFindCommon.cxx index badec55..2a33bbb 100644 --- a/Source/cmFindCommon.cxx +++ b/Source/cmFindCommon.cxx @@ -7,7 +7,8 @@ #include <cstring> #include <utility> -#include "cmAlgorithms.h" +#include <cmext/algorithm> + #include "cmExecutionStatus.h" #include "cmMakefile.h" #include "cmStringAlgorithms.h" @@ -249,7 +250,7 @@ void cmFindCommon::RerootPaths(std::vector<std::string>& paths) // If searching both rooted and unrooted paths add the original // paths again. if (this->FindRootPathMode == RootPathModeBoth) { - cmAppend(paths, unrootedPaths); + cm::append(paths, unrootedPaths); } } diff --git a/Source/cmForEachCommand.cxx b/Source/cmForEachCommand.cxx index 44392ba..ac48287 100644 --- a/Source/cmForEachCommand.cxx +++ b/Source/cmForEachCommand.cxx @@ -2,8 +2,16 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmForEachCommand.h" -#include <cstdio> +#include <algorithm> +#include <cassert> +#include <cstddef> +// NOTE The declaration of `std::abs` has moved to `cmath` since C++17 +// See https://en.cppreference.com/w/cpp/numeric/math/abs +// ALERT But IWYU used to lint `#include`s do not "understand" +// conditional compilation (i.e. `#if __cplusplus >= 201703L`) #include <cstdlib> +#include <iterator> +#include <map> #include <utility> #include <cm/memory> @@ -21,12 +29,10 @@ #include "cmSystemTools.h" namespace { -bool HandleInMode(std::vector<std::string> const& args, cmMakefile& makefile); - class cmForEachFunctionBlocker : public cmFunctionBlocker { public: - cmForEachFunctionBlocker(cmMakefile* mf); + explicit cmForEachFunctionBlocker(cmMakefile* mf); ~cmForEachFunctionBlocker() override; cm::string_view StartCommandName() const override { return "foreach"_s; } @@ -38,10 +44,33 @@ public: bool Replay(std::vector<cmListFileFunction> functions, cmExecutionStatus& inStatus) override; + void SetIterationVarsCount(const std::size_t varsCount) + { + this->IterationVarsCount = varsCount; + } + void SetZipLists() { this->ZipLists = true; } + std::vector<std::string> Args; private: + struct InvokeResult + { + bool Restore; + bool Break; + }; + + bool ReplayItems(std::vector<cmListFileFunction> const& functions, + cmExecutionStatus& inStatus); + + bool ReplayZipLists(std::vector<cmListFileFunction> const& functions, + cmExecutionStatus& inStatus); + + InvokeResult invoke(std::vector<cmListFileFunction> const& functions, + cmExecutionStatus& inStatus, cmMakefile& mf); + cmMakefile* Makefile; + std::size_t IterationVarsCount = 0u; + bool ZipLists = false; }; cmForEachFunctionBlocker::cmForEachFunctionBlocker(cmMakefile* mf) @@ -60,52 +89,272 @@ bool cmForEachFunctionBlocker::ArgumentsMatch(cmListFileFunction const& lff, { std::vector<std::string> expandedArguments; mf.ExpandArguments(lff.Arguments, expandedArguments); - return expandedArguments.empty() || expandedArguments[0] == this->Args[0]; + return expandedArguments.empty() || + expandedArguments.front() == this->Args.front(); } bool cmForEachFunctionBlocker::Replay( std::vector<cmListFileFunction> functions, cmExecutionStatus& inStatus) { - cmMakefile& mf = inStatus.GetMakefile(); - // at end of for each execute recorded commands + return this->ZipLists ? this->ReplayZipLists(functions, inStatus) + : this->ReplayItems(functions, inStatus); +} + +bool cmForEachFunctionBlocker::ReplayItems( + std::vector<cmListFileFunction> const& functions, + cmExecutionStatus& inStatus) +{ + assert("Unexpected number of iteration variables" && + this->IterationVarsCount == 1); + + auto& mf = inStatus.GetMakefile(); + + // At end of for each execute recorded commands // store the old value std::string oldDef; - if (mf.GetDefinition(this->Args[0])) { - oldDef = mf.GetDefinition(this->Args[0]); + if (mf.GetDefinition(this->Args.front())) { + oldDef = mf.GetDefinition(this->Args.front()); } + auto restore = false; for (std::string const& arg : cmMakeRange(this->Args).advance(1)) { - // set the variable to the loop value - mf.AddDefinition(this->Args[0], arg); + // Set the variable to the loop value + mf.AddDefinition(this->Args.front(), arg); // Invoke all the functions that were collected in the block. - for (cmListFileFunction const& func : functions) { - cmExecutionStatus status(mf); - mf.ExecuteCommand(func, status); - if (status.GetReturnInvoked()) { - inStatus.SetReturnInvoked(); - // restore the variable to its prior value - mf.AddDefinition(this->Args[0], oldDef); + auto r = this->invoke(functions, inStatus, mf); + restore = r.Restore; + if (r.Break) { + break; + } + } + + if (restore) { + // restore the variable to its prior value + mf.AddDefinition(this->Args.front(), oldDef); + } + return true; +} + +bool cmForEachFunctionBlocker::ReplayZipLists( + std::vector<cmListFileFunction> const& functions, + cmExecutionStatus& inStatus) +{ + assert("Unexpected number of iteration variables" && + this->IterationVarsCount >= 1); + + auto& mf = inStatus.GetMakefile(); + + // Expand the list of list-variables into a list of lists of strings + std::vector<std::vector<std::string>> values; + values.reserve(this->Args.size() - this->IterationVarsCount); + // Also track the longest list size + std::size_t maxItems = 0u; + for (auto const& var : + cmMakeRange(this->Args).advance(this->IterationVarsCount)) { + std::vector<std::string> items; + auto const& value = mf.GetSafeDefinition(var); + if (!value.empty()) { + cmExpandList(value, items, true); + } + maxItems = std::max(maxItems, items.size()); + values.emplace_back(std::move(items)); + } + + // Form the list of iteration variables + std::vector<std::string> iterationVars; + if (this->IterationVarsCount > 1) { + // If multiple iteration variables has given, + // just copy them to the `iterationVars` list. + iterationVars.reserve(values.size()); + std::copy(this->Args.begin(), + this->Args.begin() + this->IterationVarsCount, + std::back_inserter(iterationVars)); + } else { + // In case of the only iteration variable, + // generate names as `var_name_N`, + // where `N` is the count of lists to zip + iterationVars.resize(values.size()); + const auto iter_var_prefix = this->Args.front() + "_"; + auto i = 0u; + std::generate( + iterationVars.begin(), iterationVars.end(), + [&]() -> std::string { return iter_var_prefix + std::to_string(i++); }); + } + assert("Sanity check" && iterationVars.size() == values.size()); + + // Store old values for iteration variables + std::map<std::string, std::string> oldDefs; + for (auto i = 0u; i < values.size(); ++i) { + if (mf.GetDefinition(iterationVars[i])) { + oldDefs.emplace(iterationVars[i], mf.GetDefinition(iterationVars[i])); + } + } + + // Form a vector of current positions in all lists (Ok, vectors) of values + std::vector<decltype(values)::value_type::iterator> positions; + positions.reserve(values.size()); + std::transform( + values.begin(), values.end(), std::back_inserter(positions), + // Set the initial position to the beginning of every list + [](decltype(values)::value_type& list) { return list.begin(); }); + assert("Sanity check" && positions.size() == values.size()); + + auto restore = false; + // Iterate over all the lists simulateneously + for (auto i = 0u; i < maxItems; ++i) { + // Declare iteration variables + for (auto j = 0u; j < values.size(); ++j) { + // Define (or not) the iteration variable if the current position + // still not at the end... + if (positions[j] != values[j].end()) { + mf.AddDefinition(iterationVars[j], *positions[j]); + ++positions[j]; + } else { + mf.RemoveDefinition(iterationVars[j]); + } + } + // Invoke all the functions that were collected in the block. + auto r = this->invoke(functions, inStatus, mf); + restore = r.Restore; + if (r.Break) { + break; + } + } + + // Restore the variables to its prior value + if (restore) { + for (auto const& p : oldDefs) { + mf.AddDefinition(p.first, p.second); + } + } + return true; +} + +auto cmForEachFunctionBlocker::invoke( + std::vector<cmListFileFunction> const& functions, + cmExecutionStatus& inStatus, cmMakefile& mf) -> InvokeResult +{ + InvokeResult result = { true, false }; + // Invoke all the functions that were collected in the block. + for (cmListFileFunction const& func : functions) { + cmExecutionStatus status(mf); + mf.ExecuteCommand(func, status); + if (status.GetReturnInvoked()) { + inStatus.SetReturnInvoked(); + result.Break = true; + break; + } + if (status.GetBreakInvoked()) { + result.Break = true; + break; + } + if (status.GetContinueInvoked()) { + break; + } + if (cmSystemTools::GetFatalErrorOccured()) { + result.Restore = false; + result.Break = true; + break; + } + } + return result; +} + +bool HandleInMode(std::vector<std::string> const& args, + std::vector<std::string>::const_iterator kwInIter, + cmMakefile& makefile) +{ + assert("A valid iterator expected" && kwInIter != args.end()); + + auto fb = cm::make_unique<cmForEachFunctionBlocker>(&makefile); + + // Copy iteration variable names first + std::copy(args.begin(), kwInIter, std::back_inserter(fb->Args)); + // Remember the count of given iteration variable names + const auto varsCount = fb->Args.size(); + fb->SetIterationVarsCount(varsCount); + + enum Doing + { + DoingNone, + DoingLists, + DoingItems, + DoingZipLists + }; + Doing doing = DoingNone; + // Iterate over arguments past the "IN" keyword + for (std::string const& arg : cmMakeRange(++kwInIter, args.end())) { + if (arg == "LISTS") { + if (doing == DoingZipLists) { + makefile.IssueMessage(MessageType::FATAL_ERROR, + "ZIP_LISTS can not be used with LISTS or ITEMS"); return true; } - if (status.GetBreakInvoked()) { - // restore the variable to its prior value - mf.AddDefinition(this->Args[0], oldDef); + if (varsCount != 1u) { + makefile.IssueMessage( + MessageType::FATAL_ERROR, + "ITEMS or LISTS require exactly one iteration variable"); return true; } - if (status.GetContinueInvoked()) { - break; + doing = DoingLists; + + } else if (arg == "ITEMS") { + if (doing == DoingZipLists) { + makefile.IssueMessage(MessageType::FATAL_ERROR, + "ZIP_LISTS can not be used with LISTS or ITEMS"); + return true; } - if (cmSystemTools::GetFatalErrorOccured()) { + if (varsCount != 1u) { + makefile.IssueMessage( + MessageType::FATAL_ERROR, + "ITEMS or LISTS require exactly one iteration variable"); return true; } + doing = DoingItems; + + } else if (arg == "ZIP_LISTS") { + if (doing != DoingNone) { + makefile.IssueMessage(MessageType::FATAL_ERROR, + "ZIP_LISTS can not be used with LISTS or ITEMS"); + return true; + } + doing = DoingZipLists; + fb->SetZipLists(); + + } else if (doing == DoingLists) { + auto const& value = makefile.GetSafeDefinition(arg); + if (!value.empty()) { + cmExpandList(value, fb->Args, true); + } + + } else if (doing == DoingItems || doing == DoingZipLists) { + fb->Args.push_back(arg); + + } else { + makefile.IssueMessage(MessageType::FATAL_ERROR, + cmStrCat("Unknown argument:\n", " ", arg, "\n")); + return true; } } - // restore the variable to its prior value - mf.AddDefinition(this->Args[0], oldDef); + // If `ZIP_LISTS` given and variables count more than 1, + // make sure the given lists count matches variables... + if (doing == DoingZipLists && varsCount > 1u && + (2u * varsCount) != fb->Args.size()) { + makefile.IssueMessage( + MessageType::FATAL_ERROR, + cmStrCat("Expected ", std::to_string(varsCount), + " list variables, but given ", + std::to_string(fb->Args.size() - varsCount))); + return true; + } + + makefile.AddFunctionBlocker(std::move(fb)); + return true; } -} + +} // anonymous namespace bool cmForEachCommand(std::vector<std::string> const& args, cmExecutionStatus& status) @@ -114,8 +363,9 @@ bool cmForEachCommand(std::vector<std::string> const& args, status.SetError("called with incorrect number of arguments"); return false; } - if (args.size() > 1 && args[1] == "IN") { - return HandleInMode(args, status.GetMakefile()); + auto kwInIter = std::find(args.begin(), args.end(), "IN"); + if (kwInIter != args.end()) { + return HandleInMode(args, kwInIter, status.GetMakefile()); } // create a function blocker @@ -126,16 +376,16 @@ bool cmForEachCommand(std::vector<std::string> const& args, int stop = 0; int step = 0; if (args.size() == 3) { - stop = atoi(args[2].c_str()); + stop = std::stoi(args[2]); } if (args.size() == 4) { - start = atoi(args[2].c_str()); - stop = atoi(args[3].c_str()); + start = std::stoi(args[2]); + stop = std::stoi(args[3]); } if (args.size() == 5) { - start = atoi(args[2].c_str()); - stop = atoi(args[3].c_str()); - step = atoi(args[4].c_str()); + start = std::stoi(args[2]); + stop = std::stoi(args[3]); + step = std::stoi(args[4]); } if (step == 0) { if (start > stop) { @@ -151,67 +401,33 @@ bool cmForEachCommand(std::vector<std::string> const& args, ", stop ", stop, ", step ", step)); return false; } - std::vector<std::string> range; - char buffer[100]; - range.push_back(args[0]); - int cc; - for (cc = start;; cc += step) { - if ((step > 0 && cc > stop) || (step < 0 && cc < stop)) { - break; - } - sprintf(buffer, "%d", cc); - range.emplace_back(buffer); - if (cc == stop) { - break; - } - } - fb->Args = range; + + // Calculate expected iterations count and reserve enough space + // in the `fb->Args` vector. The first item is the iteration variable + // name... + const std::size_t iter_cnt = 2u + + int(start < stop) * (stop - start) / std::abs(step) + + int(start > stop) * (start - stop) / std::abs(step); + fb->Args.resize(iter_cnt); + fb->Args.front() = args.front(); + auto cc = start; + auto generator = [&cc, step]() -> std::string { + auto result = std::to_string(cc); + cc += step; + return result; + }; + // Fill the `range` vector w/ generated string values + // (starting from 2nd position) + std::generate(++fb->Args.begin(), fb->Args.end(), generator); } else { fb->Args = args; } } else { fb->Args = args; } - status.GetMakefile().AddFunctionBlocker(std::move(fb)); - - return true; -} -namespace { -bool HandleInMode(std::vector<std::string> const& args, cmMakefile& makefile) -{ - auto fb = cm::make_unique<cmForEachFunctionBlocker>(&makefile); - fb->Args.push_back(args[0]); - - enum Doing - { - DoingNone, - DoingLists, - DoingItems - }; - Doing doing = DoingNone; - for (unsigned int i = 2; i < args.size(); ++i) { - if (doing == DoingItems) { - fb->Args.push_back(args[i]); - } else if (args[i] == "LISTS") { - doing = DoingLists; - } else if (args[i] == "ITEMS") { - doing = DoingItems; - } else if (doing == DoingLists) { - const char* value = makefile.GetDefinition(args[i]); - if (value && *value) { - cmExpandList(value, fb->Args, true); - } - } else { - makefile.IssueMessage( - MessageType::FATAL_ERROR, - cmStrCat("Unknown argument:\n", " ", args[i], "\n")); - return true; - } - } - - makefile.AddFunctionBlocker(std::move(fb)); + fb->SetIterationVarsCount(1u); + status.GetMakefile().AddFunctionBlocker(std::move(fb)); return true; } -} diff --git a/Source/cmFunctionCommand.cxx b/Source/cmFunctionCommand.cxx index b3ddfe0..a4c9072 100644 --- a/Source/cmFunctionCommand.cxx +++ b/Source/cmFunctionCommand.cxx @@ -2,15 +2,14 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmFunctionCommand.h" -#include <sstream> #include <utility> #include <cm/memory> #include <cm/string_view> +#include <cmext/algorithm> #include "cm_static_string_view.hxx" -#include "cmAlgorithms.h" #include "cmExecutionStatus.h" #include "cmFunctionBlocker.h" #include "cmListFileCache.h" @@ -19,8 +18,20 @@ #include "cmRange.h" #include "cmState.h" #include "cmStringAlgorithms.h" +#include "cmSystemTools.h" namespace { +std::string const ARGC = "ARGC"; +std::string const ARGN = "ARGN"; +std::string const ARGV = "ARGV"; +std::string const CMAKE_CURRENT_FUNCTION = "CMAKE_CURRENT_FUNCTION"; +std::string const CMAKE_CURRENT_FUNCTION_LIST_FILE = + "CMAKE_CURRENT_FUNCTION_LIST_FILE"; +std::string const CMAKE_CURRENT_FUNCTION_LIST_DIR = + "CMAKE_CURRENT_FUNCTION_LIST_DIR"; +std::string const CMAKE_CURRENT_FUNCTION_LIST_LINE = + "CMAKE_CURRENT_FUNCTION_LIST_LINE"; + // define the class for function commands class cmFunctionHelperCommand { @@ -36,8 +47,8 @@ public: std::vector<cmListFileFunction> Functions; cmPolicies::PolicyMap Policies; std::string FilePath; + long Line; }; -} bool cmFunctionHelperCommand::operator()( std::vector<cmListFileArgument> const& args, @@ -52,9 +63,9 @@ bool cmFunctionHelperCommand::operator()( // make sure the number of arguments passed is at least the number // required by the signature if (expandedArgs.size() < this->Args.size() - 1) { - std::string errorMsg = cmStrCat( + auto const errorMsg = cmStrCat( "Function invoked with incorrect arguments for function named: ", - this->Args[0]); + this->Args.front()); inStatus.SetError(errorMsg); return false; } @@ -63,30 +74,40 @@ bool cmFunctionHelperCommand::operator()( this->Policies); // set the value of argc - makefile.AddDefinition("ARGC", std::to_string(expandedArgs.size())); - makefile.MarkVariableAsUsed("ARGC"); + makefile.AddDefinition(ARGC, std::to_string(expandedArgs.size())); + makefile.MarkVariableAsUsed(ARGC); // set the values for ARGV0 ARGV1 ... - for (unsigned int t = 0; t < expandedArgs.size(); ++t) { - std::ostringstream tmpStream; - tmpStream << "ARGV" << t; - makefile.AddDefinition(tmpStream.str(), expandedArgs[t]); - makefile.MarkVariableAsUsed(tmpStream.str()); + for (auto t = 0u; t < expandedArgs.size(); ++t) { + auto const value = cmStrCat(ARGV, std::to_string(t)); + makefile.AddDefinition(value, expandedArgs[t]); + makefile.MarkVariableAsUsed(value); } // define the formal arguments - for (unsigned int j = 1; j < this->Args.size(); ++j) { + for (auto j = 1u; j < this->Args.size(); ++j) { makefile.AddDefinition(this->Args[j], expandedArgs[j - 1]); } // define ARGV and ARGN - std::string argvDef = cmJoin(expandedArgs, ";"); - auto eit = expandedArgs.begin() + (this->Args.size() - 1); - std::string argnDef = cmJoin(cmMakeRange(eit, expandedArgs.end()), ";"); - makefile.AddDefinition("ARGV", argvDef); - makefile.MarkVariableAsUsed("ARGV"); - makefile.AddDefinition("ARGN", argnDef); - makefile.MarkVariableAsUsed("ARGN"); + auto const argvDef = cmJoin(expandedArgs, ";"); + auto const eit = expandedArgs.begin() + (this->Args.size() - 1); + auto const argnDef = cmJoin(cmMakeRange(eit, expandedArgs.end()), ";"); + makefile.AddDefinition(ARGV, argvDef); + makefile.MarkVariableAsUsed(ARGV); + makefile.AddDefinition(ARGN, argnDef); + makefile.MarkVariableAsUsed(ARGN); + + makefile.AddDefinition(CMAKE_CURRENT_FUNCTION, this->Args.front()); + makefile.MarkVariableAsUsed(CMAKE_CURRENT_FUNCTION); + makefile.AddDefinition(CMAKE_CURRENT_FUNCTION_LIST_FILE, this->FilePath); + makefile.MarkVariableAsUsed(CMAKE_CURRENT_FUNCTION_LIST_FILE); + makefile.AddDefinition(CMAKE_CURRENT_FUNCTION_LIST_DIR, + cmSystemTools::GetFilenamePath(this->FilePath)); + makefile.MarkVariableAsUsed(CMAKE_CURRENT_FUNCTION_LIST_DIR); + makefile.AddDefinition(CMAKE_CURRENT_FUNCTION_LIST_LINE, + std::to_string(this->Line)); + makefile.MarkVariableAsUsed(CMAKE_CURRENT_FUNCTION_LIST_LINE); // Invoke all the functions that were collected in the block. // for each function @@ -100,7 +121,7 @@ bool cmFunctionHelperCommand::operator()( return false; } if (status.GetReturnInvoked()) { - return true; + break; } } @@ -129,7 +150,8 @@ bool cmFunctionFunctionBlocker::ArgumentsMatch(cmListFileFunction const& lff, std::vector<std::string> expandedArguments; mf.ExpandArguments(lff.Arguments, expandedArguments, this->GetStartingContext().FilePath.c_str()); - return expandedArguments.empty() || expandedArguments[0] == this->Args[0]; + return expandedArguments.empty() || + expandedArguments.front() == this->Args.front(); } bool cmFunctionFunctionBlocker::Replay( @@ -141,11 +163,14 @@ bool cmFunctionFunctionBlocker::Replay( f.Args = this->Args; f.Functions = std::move(functions); f.FilePath = this->GetStartingContext().FilePath; + f.Line = this->GetStartingContext().Line; mf.RecordPolicies(f.Policies); - mf.GetState()->AddScriptedCommand(this->Args[0], std::move(f)); + mf.GetState()->AddScriptedCommand(this->Args.front(), std::move(f)); return true; } +} // anonymous namespace + bool cmFunctionCommand(std::vector<std::string> const& args, cmExecutionStatus& status) { @@ -155,10 +180,9 @@ bool cmFunctionCommand(std::vector<std::string> const& args, } // create a function blocker - { - auto fb = cm::make_unique<cmFunctionFunctionBlocker>(); - cmAppend(fb->Args, args); - status.GetMakefile().AddFunctionBlocker(std::move(fb)); - } + auto fb = cm::make_unique<cmFunctionFunctionBlocker>(); + cm::append(fb->Args, args); + status.GetMakefile().AddFunctionBlocker(std::move(fb)); + return true; } diff --git a/Source/cmGeneratorExpression.cxx b/Source/cmGeneratorExpression.cxx index b7f7d1d..81d1e46 100644 --- a/Source/cmGeneratorExpression.cxx +++ b/Source/cmGeneratorExpression.cxx @@ -8,7 +8,6 @@ #include "cmsys/RegularExpression.hxx" -#include "cmAlgorithms.h" #include "cmGeneratorExpressionContext.h" #include "cmGeneratorExpressionDAGChecker.h" #include "cmGeneratorExpressionEvaluator.h" @@ -22,6 +21,8 @@ cmGeneratorExpression::cmGeneratorExpression(cmListFileBacktrace backtrace) { } +cmCompiledGeneratorExpression::~cmCompiledGeneratorExpression() = default; + cmGeneratorExpression::~cmGeneratorExpression() = default; std::unique_ptr<cmCompiledGeneratorExpression> cmGeneratorExpression::Parse( @@ -86,7 +87,7 @@ const std::string& cmCompiledGeneratorExpression::EvaluateWithContext( this->Output.clear(); - for (const cmGeneratorExpressionEvaluator* it : this->Evaluators) { + for (const auto& it : this->Evaluators) { this->Output += it->Evaluate(&context, dagChecker); this->SeenTargetProperties.insert(context.SeenTargetProperties.cbegin(), @@ -129,11 +130,6 @@ cmCompiledGeneratorExpression::cmCompiledGeneratorExpression( } } -cmCompiledGeneratorExpression::~cmCompiledGeneratorExpression() -{ - cmDeleteAll(this->Evaluators); -} - std::string cmGeneratorExpression::StripEmptyListElements( const std::string& input) { @@ -385,6 +381,20 @@ bool cmGeneratorExpression::IsValidTargetName(const std::string& input) return targetNameValidator.find(input); } +void cmGeneratorExpression::ReplaceInstallPrefix( + std::string& input, const std::string& replacement) +{ + std::string::size_type pos = 0; + std::string::size_type lastPos = pos; + + while ((pos = input.find("$<INSTALL_PREFIX>", lastPos)) != + std::string::npos) { + std::string::size_type endPos = pos + sizeof("$<INSTALL_PREFIX>") - 1; + input.replace(pos, endPos - pos, replacement); + lastPos = endPos; + } +} + void cmCompiledGeneratorExpression::GetMaxLanguageStandard( const cmGeneratorTarget* tgt, std::map<std::string, std::string>& mapping) { diff --git a/Source/cmGeneratorExpression.h b/Source/cmGeneratorExpression.h index 4bd1c9f..c4be3a1 100644 --- a/Source/cmGeneratorExpression.h +++ b/Source/cmGeneratorExpression.h @@ -87,6 +87,9 @@ public: return input != nullptr && input[0] == '$' && input[1] == '<'; } + static void ReplaceInstallPrefix(std::string& input, + const std::string& replacement); + private: cmListFileBacktrace Backtrace; }; @@ -160,7 +163,7 @@ private: friend class cmGeneratorExpression; cmListFileBacktrace Backtrace; - std::vector<cmGeneratorExpressionEvaluator*> Evaluators; + std::vector<std::unique_ptr<cmGeneratorExpressionEvaluator>> Evaluators; const std::string Input; bool NeedsEvaluation; bool EvaluateForBuildsystem; diff --git a/Source/cmGeneratorExpressionEvaluator.cxx b/Source/cmGeneratorExpressionEvaluator.cxx index e0ae170..4129a0c 100644 --- a/Source/cmGeneratorExpressionEvaluator.cxx +++ b/Source/cmGeneratorExpressionEvaluator.cxx @@ -2,10 +2,8 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmGeneratorExpressionEvaluator.h" -#include <algorithm> #include <sstream> -#include "cmAlgorithms.h" #include "cmGeneratorExpressionContext.h" #include "cmGeneratorExpressionNode.h" @@ -16,6 +14,8 @@ GeneratorExpressionContent::GeneratorExpressionContent( { } +GeneratorExpressionContent::~GeneratorExpressionContent() = default; + std::string GeneratorExpressionContent::GetOriginalExpression() const { return std::string(this->StartContent, this->ContentLength); @@ -25,14 +25,13 @@ std::string GeneratorExpressionContent::ProcessArbitraryContent( const cmGeneratorExpressionNode* node, const std::string& identifier, cmGeneratorExpressionContext* context, cmGeneratorExpressionDAGChecker* dagChecker, - std::vector<std::vector<cmGeneratorExpressionEvaluator*>>::const_iterator - pit) const + std::vector<cmGeneratorExpressionEvaluatorVector>::const_iterator pit) const { std::string result; const auto pend = this->ParamChildren.end(); for (; pit != pend; ++pit) { - for (cmGeneratorExpressionEvaluator* pExprEval : *pit) { + for (auto& pExprEval : *pit) { if (node->RequiresLiteralInput()) { if (pExprEval->GetType() != cmGeneratorExpressionEvaluator::Text) { reportError(context, this->GetOriginalExpression(), @@ -64,8 +63,7 @@ std::string GeneratorExpressionContent::Evaluate( { std::string identifier; { - for (cmGeneratorExpressionEvaluator* pExprEval : - this->IdentifierChildren) { + for (auto& pExprEval : this->IdentifierChildren) { identifier += pExprEval->Evaluate(context, dagChecker); if (context->HadError) { return std::string(); @@ -126,7 +124,7 @@ std::string GeneratorExpressionContent::EvaluateParameters( return std::string(); } std::string parameter; - for (cmGeneratorExpressionEvaluator* pExprEval : *pit) { + for (auto& pExprEval : *pit) { parameter += pExprEval->Evaluate(context, dagChecker); if (context->HadError) { return std::string(); @@ -174,10 +172,3 @@ std::string GeneratorExpressionContent::EvaluateParameters( } return std::string(); } - -GeneratorExpressionContent::~GeneratorExpressionContent() -{ - cmDeleteAll(this->IdentifierChildren); - std::for_each(this->ParamChildren.begin(), this->ParamChildren.end(), - cmDeleteAll<std::vector<cmGeneratorExpressionEvaluator*>>); -} diff --git a/Source/cmGeneratorExpressionEvaluator.h b/Source/cmGeneratorExpressionEvaluator.h index b10bb5b..10496fd 100644 --- a/Source/cmGeneratorExpressionEvaluator.h +++ b/Source/cmGeneratorExpressionEvaluator.h @@ -6,6 +6,7 @@ #include "cmConfigure.h" // IWYU pragma: keep #include <cstddef> +#include <memory> #include <string> #include <utility> #include <vector> @@ -36,6 +37,9 @@ struct cmGeneratorExpressionEvaluator cmGeneratorExpressionDAGChecker*) const = 0; }; +using cmGeneratorExpressionEvaluatorVector = + std::vector<std::unique_ptr<cmGeneratorExpressionEvaluator>>; + struct TextContent : public cmGeneratorExpressionEvaluator { TextContent(const char* start, size_t length) @@ -68,13 +72,13 @@ struct GeneratorExpressionContent : public cmGeneratorExpressionEvaluator { GeneratorExpressionContent(const char* startContent, size_t length); - void SetIdentifier(std::vector<cmGeneratorExpressionEvaluator*> identifier) + void SetIdentifier(cmGeneratorExpressionEvaluatorVector&& identifier) { this->IdentifierChildren = std::move(identifier); } void SetParameters( - std::vector<std::vector<cmGeneratorExpressionEvaluator*>> parameters) + std::vector<cmGeneratorExpressionEvaluatorVector>&& parameters) { this->ParamChildren = std::move(parameters); } @@ -102,12 +106,12 @@ private: const cmGeneratorExpressionNode* node, const std::string& identifier, cmGeneratorExpressionContext* context, cmGeneratorExpressionDAGChecker* dagChecker, - std::vector<std::vector<cmGeneratorExpressionEvaluator*>>::const_iterator - pit) const; + std::vector<cmGeneratorExpressionEvaluatorVector>::const_iterator pit) + const; private: - std::vector<cmGeneratorExpressionEvaluator*> IdentifierChildren; - std::vector<std::vector<cmGeneratorExpressionEvaluator*>> ParamChildren; + cmGeneratorExpressionEvaluatorVector IdentifierChildren; + std::vector<cmGeneratorExpressionEvaluatorVector> ParamChildren; const char* StartContent; size_t ContentLength; }; diff --git a/Source/cmGeneratorExpressionParser.cxx b/Source/cmGeneratorExpressionParser.cxx index d6cc6ab..c2c9ef7 100644 --- a/Source/cmGeneratorExpressionParser.cxx +++ b/Source/cmGeneratorExpressionParser.cxx @@ -6,7 +6,10 @@ #include <cstddef> #include <utility> -#include "cmAlgorithms.h" +#include <cm/memory> +#include <cmext/algorithm> +#include <cmext/memory> + #include "cmGeneratorExpressionEvaluator.h" cmGeneratorExpressionParser::cmGeneratorExpressionParser( @@ -17,7 +20,7 @@ cmGeneratorExpressionParser::cmGeneratorExpressionParser( } void cmGeneratorExpressionParser::Parse( - std::vector<cmGeneratorExpressionEvaluator*>& result) + cmGeneratorExpressionEvaluatorVector& result) { it = this->Tokens.begin(); @@ -27,40 +30,38 @@ void cmGeneratorExpressionParser::Parse( } static void extendText( - std::vector<cmGeneratorExpressionEvaluator*>& result, + cmGeneratorExpressionEvaluatorVector& result, std::vector<cmGeneratorExpressionToken>::const_iterator it) { if (!result.empty() && (*(result.end() - 1))->GetType() == cmGeneratorExpressionEvaluator::Text) { - TextContent* textContent = static_cast<TextContent*>(*(result.end() - 1)); - textContent->Extend(it->Length); + cm::static_reference_cast<TextContent>(*(result.end() - 1)) + .Extend(it->Length); } else { - TextContent* textContent = new TextContent(it->Content, it->Length); - result.push_back(textContent); + auto textContent = cm::make_unique<TextContent>(it->Content, it->Length); + result.push_back(std::move(textContent)); } } static void extendResult( - std::vector<cmGeneratorExpressionEvaluator*>& result, - const std::vector<cmGeneratorExpressionEvaluator*>& contents) + cmGeneratorExpressionParser::cmGeneratorExpressionEvaluatorVector& result, + cmGeneratorExpressionParser::cmGeneratorExpressionEvaluatorVector&& contents) { if (!result.empty() && (*(result.end() - 1))->GetType() == cmGeneratorExpressionEvaluator::Text && contents.front()->GetType() == cmGeneratorExpressionEvaluator::Text) { - TextContent* textContent = static_cast<TextContent*>(*(result.end() - 1)); - textContent->Extend( - static_cast<TextContent*>(contents.front())->GetLength()); - delete contents.front(); - cmAppend(result, contents.begin() + 1, contents.end()); - } else { - cmAppend(result, contents); + cm::static_reference_cast<TextContent>(*(result.end() - 1)) + .Extend( + cm::static_reference_cast<TextContent>(contents.front()).GetLength()); + contents.erase(contents.begin()); } + cm::append(result, std::move(contents)); } void cmGeneratorExpressionParser::ParseGeneratorExpression( - std::vector<cmGeneratorExpressionEvaluator*>& result) + cmGeneratorExpressionEvaluatorVector& result) { assert(this->it != this->Tokens.end()); unsigned int nestedLevel = this->NestingLevel; @@ -68,7 +69,7 @@ void cmGeneratorExpressionParser::ParseGeneratorExpression( auto startToken = this->it - 1; - std::vector<cmGeneratorExpressionEvaluator*> identifier; + cmGeneratorExpressionEvaluatorVector identifier; while (this->it->TokenType != cmGeneratorExpressionToken::EndExpression && this->it->TokenType != cmGeneratorExpressionToken::ColonSeparator) { if (this->it->TokenType == cmGeneratorExpressionToken::CommaSeparator) { @@ -87,18 +88,18 @@ void cmGeneratorExpressionParser::ParseGeneratorExpression( if (this->it != this->Tokens.end() && this->it->TokenType == cmGeneratorExpressionToken::EndExpression) { - GeneratorExpressionContent* content = new GeneratorExpressionContent( + auto content = cm::make_unique<GeneratorExpressionContent>( startToken->Content, this->it->Content - startToken->Content + this->it->Length); assert(this->it != this->Tokens.end()); ++this->it; --this->NestingLevel; content->SetIdentifier(std::move(identifier)); - result.push_back(content); + result.push_back(std::move(content)); return; } - std::vector<std::vector<cmGeneratorExpressionEvaluator*>> parameters; + std::vector<cmGeneratorExpressionEvaluatorVector> parameters; std::vector<std::vector<cmGeneratorExpressionToken>::const_iterator> commaTokens; std::vector<cmGeneratorExpressionToken>::const_iterator colonToken; @@ -169,7 +170,7 @@ void cmGeneratorExpressionParser::ParseGeneratorExpression( // treat the '$<' as having been plain text, along with the // corresponding : and , tokens that might have been found. extendText(result, startToken); - extendResult(result, identifier); + extendResult(result, std::move(identifier)); if (!parameters.empty()) { extendText(result, colonToken); @@ -179,7 +180,7 @@ void cmGeneratorExpressionParser::ParseGeneratorExpression( assert(parameters.size() > commaTokens.size()); for (; pit != pend; ++pit, ++commaIt) { if (!pit->empty() && !emptyParamTermination) { - extendResult(result, *pit); + extendResult(result, std::move(*pit)); } if (commaIt != commaTokens.end()) { extendText(result, *commaIt); @@ -193,15 +194,15 @@ void cmGeneratorExpressionParser::ParseGeneratorExpression( size_t contentLength = ((this->it - 1)->Content - startToken->Content) + (this->it - 1)->Length; - GeneratorExpressionContent* content = - new GeneratorExpressionContent(startToken->Content, contentLength); + auto content = cm::make_unique<GeneratorExpressionContent>( + startToken->Content, contentLength); content->SetIdentifier(std::move(identifier)); content->SetParameters(std::move(parameters)); - result.push_back(content); + result.push_back(std::move(content)); } void cmGeneratorExpressionParser::ParseContent( - std::vector<cmGeneratorExpressionEvaluator*>& result) + cmGeneratorExpressionEvaluatorVector& result) { assert(this->it != this->Tokens.end()); switch (this->it->TokenType) { @@ -213,17 +214,16 @@ void cmGeneratorExpressionParser::ParseContent( // A comma in 'plain text' could have split text that should // otherwise be continuous. Extend the last text content instead of // creating a new one. - TextContent* textContent = - static_cast<TextContent*>(*(result.end() - 1)); - textContent->Extend(this->it->Length); + cm::static_reference_cast<TextContent>(*(result.end() - 1)) + .Extend(this->it->Length); assert(this->it != this->Tokens.end()); ++this->it; return; } } - cmGeneratorExpressionEvaluator* n = - new TextContent(this->it->Content, this->it->Length); - result.push_back(n); + auto n = + cm::make_unique<TextContent>(this->it->Content, this->it->Length); + result.push_back(std::move(n)); assert(this->it != this->Tokens.end()); ++this->it; return; diff --git a/Source/cmGeneratorExpressionParser.h b/Source/cmGeneratorExpressionParser.h index e663496..1ba1654 100644 --- a/Source/cmGeneratorExpressionParser.h +++ b/Source/cmGeneratorExpressionParser.h @@ -5,6 +5,7 @@ #include "cmConfigure.h" // IWYU pragma: keep +#include <memory> #include <vector> #include "cmGeneratorExpressionLexer.h" @@ -15,11 +16,14 @@ struct cmGeneratorExpressionParser { cmGeneratorExpressionParser(std::vector<cmGeneratorExpressionToken> tokens); - void Parse(std::vector<cmGeneratorExpressionEvaluator*>& result); + using cmGeneratorExpressionEvaluatorVector = + std::vector<std::unique_ptr<cmGeneratorExpressionEvaluator>>; + + void Parse(cmGeneratorExpressionEvaluatorVector& result); private: - void ParseContent(std::vector<cmGeneratorExpressionEvaluator*>&); - void ParseGeneratorExpression(std::vector<cmGeneratorExpressionEvaluator*>&); + void ParseContent(cmGeneratorExpressionEvaluatorVector&); + void ParseGeneratorExpression(cmGeneratorExpressionEvaluatorVector&); private: std::vector<cmGeneratorExpressionToken>::const_iterator it; diff --git a/Source/cmGeneratorTarget.cxx b/Source/cmGeneratorTarget.cxx index 171c3ed..19d5b4d 100644 --- a/Source/cmGeneratorTarget.cxx +++ b/Source/cmGeneratorTarget.cxx @@ -10,11 +10,11 @@ #include <cstdlib> #include <cstring> #include <iterator> -#include <memory> #include <sstream> #include <unordered_set> #include <utility> +#include <cm/memory> #include <cm/string_view> #include <queue> @@ -162,7 +162,8 @@ private: cmListFileBacktrace Backtrace; }; -cmGeneratorTarget::TargetPropertyEntry* CreateTargetPropertyEntry( +std::unique_ptr<cmGeneratorTarget::TargetPropertyEntry> +CreateTargetPropertyEntry( const std::string& propertyValue, cmListFileBacktrace backtrace = cmListFileBacktrace(), bool evaluateForBuildsystem = false) @@ -172,15 +173,18 @@ cmGeneratorTarget::TargetPropertyEntry* CreateTargetPropertyEntry( std::unique_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(propertyValue); cge->SetEvaluateForBuildsystem(evaluateForBuildsystem); - return new TargetPropertyEntryGenex(std::move(cge)); + return std::unique_ptr<cmGeneratorTarget::TargetPropertyEntry>( + cm::make_unique<TargetPropertyEntryGenex>(std::move(cge))); } - return new TargetPropertyEntryString(propertyValue, std::move(backtrace)); + return std::unique_ptr<cmGeneratorTarget::TargetPropertyEntry>( + cm::make_unique<TargetPropertyEntryString>(propertyValue, + std::move(backtrace))); } void CreatePropertyGeneratorExpressions( cmStringRange entries, cmBacktraceRange backtraces, - std::vector<cmGeneratorTarget::TargetPropertyEntry*>& items, + std::vector<std::unique_ptr<cmGeneratorTarget::TargetPropertyEntry>>& items, bool evaluateForBuildsystem = false) { auto btIt = backtraces.begin(); @@ -219,13 +223,13 @@ struct EvaluatedTargetPropertyEntry EvaluatedTargetPropertyEntry EvaluateTargetPropertyEntry( cmGeneratorTarget const* thisTarget, std::string const& config, std::string const& lang, cmGeneratorExpressionDAGChecker* dagChecker, - cmGeneratorTarget::TargetPropertyEntry* entry) + cmGeneratorTarget::TargetPropertyEntry& entry) { - EvaluatedTargetPropertyEntry ee(entry->LinkImplItem, entry->GetBacktrace()); - cmExpandList(entry->Evaluate(thisTarget->GetLocalGenerator(), config, - thisTarget, dagChecker, lang), + EvaluatedTargetPropertyEntry ee(entry.LinkImplItem, entry.GetBacktrace()); + cmExpandList(entry.Evaluate(thisTarget->GetLocalGenerator(), config, + thisTarget, dagChecker, lang), ee.Values); - if (entry->GetHadContextSensitiveCondition()) { + if (entry.GetHadContextSensitiveCondition()) { ee.ContextDependent = true; } return ee; @@ -234,13 +238,14 @@ EvaluatedTargetPropertyEntry EvaluateTargetPropertyEntry( std::vector<EvaluatedTargetPropertyEntry> EvaluateTargetPropertyEntries( cmGeneratorTarget const* thisTarget, std::string const& config, std::string const& lang, cmGeneratorExpressionDAGChecker* dagChecker, - std::vector<cmGeneratorTarget::TargetPropertyEntry*> const& in) + std::vector<std::unique_ptr<cmGeneratorTarget::TargetPropertyEntry>> const& + in) { std::vector<EvaluatedTargetPropertyEntry> out; out.reserve(in.size()); - for (cmGeneratorTarget::TargetPropertyEntry* entry : in) { + for (auto& entry : in) { out.emplace_back(EvaluateTargetPropertyEntry(thisTarget, config, lang, - dagChecker, entry)); + dagChecker, *entry)); } return out; } @@ -304,23 +309,12 @@ cmGeneratorTarget::cmGeneratorTarget(cmTarget* t, cmLocalGenerator* lg) this->PolicyMap = t->GetPolicyMap(); } -cmGeneratorTarget::~cmGeneratorTarget() -{ - cmDeleteAll(this->IncludeDirectoriesEntries); - cmDeleteAll(this->CompileOptionsEntries); - cmDeleteAll(this->CompileFeaturesEntries); - cmDeleteAll(this->CompileDefinitionsEntries); - cmDeleteAll(this->LinkOptionsEntries); - cmDeleteAll(this->LinkDirectoriesEntries); - cmDeleteAll(this->PrecompileHeadersEntries); - cmDeleteAll(this->SourceEntries); - cmDeleteAll(this->LinkInformation); -} +cmGeneratorTarget::~cmGeneratorTarget() = default; const char* cmGeneratorTarget::GetSourcesProperty() const { std::vector<std::string> values; - for (TargetPropertyEntry* se : this->SourceEntries) { + for (auto& se : this->SourceEntries) { values.push_back(se->GetInput()); } static std::string value; @@ -655,6 +649,7 @@ void cmGeneratorTarget::ClearSourcesCache() this->KindedSourcesMap.clear(); this->LinkImplementationLanguageIsContextDependent = true; this->Objects.clear(); + this->VisitedConfigsForObjects.clear(); } void cmGeneratorTarget::AddSourceCommon(const std::string& src, bool before) @@ -744,7 +739,7 @@ void cmGeneratorTarget::GetObjectSources( { IMPLEMENT_VISIT(SourceKindObjectSource); - if (!this->Objects.empty()) { + if (this->VisitedConfigsForObjects.count(config)) { return; } @@ -753,16 +748,17 @@ void cmGeneratorTarget::GetObjectSources( } this->LocalGenerator->ComputeObjectFilenames(this->Objects, this); + this->VisitedConfigsForObjects.insert(config); } void cmGeneratorTarget::ComputeObjectMapping() { - if (!this->Objects.empty()) { + auto const& configs = this->Makefile->GetGeneratorConfigs(); + std::set<std::string> configSet(configs.begin(), configs.end()); + if (configSet == this->VisitedConfigsForObjects) { return; } - std::vector<std::string> const& configs = - this->Makefile->GetGeneratorConfigs(); for (std::string const& c : configs) { std::vector<cmSourceFile const*> sourceFiles; this->GetObjectSources(sourceFiles, c); @@ -1122,7 +1118,8 @@ bool cmGeneratorTarget::GetPropertyAsBool(const std::string& prop) const } bool cmGeneratorTarget::MaybeHaveInterfaceProperty( - std::string const& prop, cmGeneratorExpressionContext* context) const + std::string const& prop, cmGeneratorExpressionContext* context, + bool usage_requirements_only) const { std::string const key = prop + '@' + context->Config; auto i = this->MaybeInterfacePropertyExists.find(key); @@ -1141,7 +1138,7 @@ bool cmGeneratorTarget::MaybeHaveInterfaceProperty( context->HeadTarget ? context->HeadTarget : this; if (cmLinkInterfaceLibraries const* iface = this->GetLinkInterfaceLibraries(context->Config, headTarget, - true)) { + usage_requirements_only)) { if (iface->HadHeadSensitiveCondition) { // With a different head target we may get to a library with // this interface property. @@ -1151,7 +1148,8 @@ bool cmGeneratorTarget::MaybeHaveInterfaceProperty( // head target, so we can follow them. for (cmLinkItem const& lib : iface->Libraries) { if (lib.Target && - lib.Target->MaybeHaveInterfaceProperty(prop, context)) { + lib.Target->MaybeHaveInterfaceProperty( + prop, context, usage_requirements_only)) { maybeInterfaceProp = true; break; } @@ -1165,12 +1163,14 @@ bool cmGeneratorTarget::MaybeHaveInterfaceProperty( std::string cmGeneratorTarget::EvaluateInterfaceProperty( std::string const& prop, cmGeneratorExpressionContext* context, - cmGeneratorExpressionDAGChecker* dagCheckerParent) const + cmGeneratorExpressionDAGChecker* dagCheckerParent, + bool usage_requirements_only) const { std::string result; // If the property does not appear transitively at all, we are done. - if (!this->MaybeHaveInterfaceProperty(prop, context)) { + if (!this->MaybeHaveInterfaceProperty(prop, context, + usage_requirements_only)) { return result; } @@ -1202,8 +1202,8 @@ std::string cmGeneratorTarget::EvaluateInterfaceProperty( p, context->LG, context, headTarget, &dagChecker, this); } - if (cmLinkInterfaceLibraries const* iface = - this->GetLinkInterfaceLibraries(context->Config, headTarget, true)) { + if (cmLinkInterfaceLibraries const* iface = this->GetLinkInterfaceLibraries( + context->Config, headTarget, usage_requirements_only)) { for (cmLinkItem const& lib : iface->Libraries) { // Broken code can have a target in its own link interface. // Don't follow such link interface entries so as not to create a @@ -1217,8 +1217,8 @@ std::string cmGeneratorTarget::EvaluateInterfaceProperty( context->EvaluateForBuildsystem, context->Backtrace, context->Language); std::string libResult = cmGeneratorExpression::StripEmptyListElements( - lib.Target->EvaluateInterfaceProperty(prop, &libContext, - &dagChecker)); + lib.Target->EvaluateInterfaceProperty(prop, &libContext, &dagChecker, + usage_requirements_only)); if (!libResult.empty()) { if (result.empty()) { result = std::move(libResult); @@ -1246,7 +1246,8 @@ void AddInterfaceEntries(cmGeneratorTarget const* headTarget, std::string const& config, std::string const& prop, std::string const& lang, cmGeneratorExpressionDAGChecker* dagChecker, - std::vector<EvaluatedTargetPropertyEntry>& entries) + std::vector<EvaluatedTargetPropertyEntry>& entries, + bool usage_requirements_only = true) { if (cmLinkImplementationLibraries const* impl = headTarget->GetLinkImplementationLibraries(config)) { @@ -1259,9 +1260,9 @@ void AddInterfaceEntries(cmGeneratorTarget const* headTarget, cmGeneratorExpressionContext context( headTarget->GetLocalGenerator(), config, false, headTarget, headTarget, true, lib.Backtrace, lang); - cmExpandList( - lib.Target->EvaluateInterfaceProperty(prop, &context, dagChecker), - ee.Values); + cmExpandList(lib.Target->EvaluateInterfaceProperty( + prop, &context, dagChecker, usage_requirements_only), + ee.Values); ee.ContextDependent = context.HadContextSensitiveCondition; entries.emplace_back(std::move(ee)); } @@ -1672,6 +1673,19 @@ void cmGeneratorTarget::ComputeAllConfigSources() const } } +std::set<std::string> cmGeneratorTarget::GetAllConfigCompileLanguages() const +{ + std::set<std::string> languages; + std::vector<AllConfigSource> const& sources = this->GetAllConfigSources(); + for (AllConfigSource const& si : sources) { + std::string const& lang = si.Source->GetOrDetermineLanguage(); + if (!lang.empty()) { + languages.emplace(lang); + } + } + return languages; +} + std::string cmGeneratorTarget::GetCompilePDBName( const std::string& config) const { @@ -2114,7 +2128,9 @@ std::string cmGeneratorTarget::GetInstallNameDirForBuildTree( // If building directly for installation then the build tree install_name // is the same as the install tree. if (this->MacOSXUseInstallNameDir()) { - return this->GetInstallNameDirForInstallTree(); + std::string installPrefix = + this->Makefile->GetSafeDefinition("CMAKE_INSTALL_PREFIX"); + return this->GetInstallNameDirForInstallTree(config, installPrefix); } // Use the build tree directory for the target. @@ -2132,7 +2148,8 @@ std::string cmGeneratorTarget::GetInstallNameDirForBuildTree( return ""; } -std::string cmGeneratorTarget::GetInstallNameDirForInstallTree() const +std::string cmGeneratorTarget::GetInstallNameDirForInstallTree( + const std::string& config, const std::string& installPrefix) const { if (this->Makefile->IsOn("CMAKE_PLATFORM_HAS_INSTALLNAME")) { std::string dir; @@ -2140,7 +2157,13 @@ std::string cmGeneratorTarget::GetInstallNameDirForInstallTree() const if (this->CanGenerateInstallNameDir(INSTALL_NAME_FOR_INSTALL)) { if (install_name_dir && *install_name_dir) { - dir = cmStrCat(install_name_dir, '/'); + dir = install_name_dir; + cmGeneratorExpression::ReplaceInstallPrefix(dir, installPrefix); + dir = + cmGeneratorExpression::Evaluate(dir, this->LocalGenerator, config); + if (!dir.empty()) { + dir = cmStrCat(dir, '/'); + } } } if (!install_name_dir) { @@ -2492,11 +2515,11 @@ void cmGeneratorTarget::ComputeModuleDefinitionInfo( info.WindowsExportAllSymbols = this->Makefile->IsOn("CMAKE_SUPPORT_WINDOWS_EXPORT_ALL_SYMBOLS") && this->GetPropertyAsBool("WINDOWS_EXPORT_ALL_SYMBOLS"); -#if defined(_WIN32) && !defined(CMAKE_BOOTSTRAP) +#if !defined(CMAKE_BOOTSTRAP) info.DefFileGenerated = info.WindowsExportAllSymbols || info.Sources.size() > 1; #else - // Our __create_def helper is only available on Windows. + // Our __create_def helper is not available during CMake bootstrap. info.DefFileGenerated = false; #endif if (info.DefFileGenerated) { @@ -3277,10 +3300,10 @@ std::vector<BT<std::string>> cmGeneratorTarget::GetCompileDefinitions( CM_FALLTHROUGH; } case cmPolicies::OLD: { - std::unique_ptr<TargetPropertyEntry> entry( - CreateTargetPropertyEntry(configProp)); + std::unique_ptr<TargetPropertyEntry> entry = + CreateTargetPropertyEntry(configProp); entries.emplace_back(EvaluateTargetPropertyEntry( - this, config, language, &dagChecker, entry.get())); + this, config, language, &dagChecker, *entry)); } break; case cmPolicies::NEW: case cmPolicies::REQUIRED_ALWAYS: @@ -3647,7 +3670,8 @@ std::vector<BT<std::string>> cmGeneratorTarget::GetLinkOptions( this->LinkOptionsEntries); AddInterfaceEntries(this, config, "INTERFACE_LINK_OPTIONS", language, - &dagChecker, entries); + &dagChecker, entries, + this->GetPolicyStatusCMP0099() != cmPolicies::NEW); processOptions(this, entries, result, uniqueOptions, debugOptions, "link options", OptionsParse::Shell); @@ -3779,10 +3803,10 @@ std::vector<BT<std::string>> cmGeneratorTarget::GetStaticLibraryLinkOptions( if (const char* linkOptions = this->GetProperty("STATIC_LIBRARY_OPTIONS")) { std::vector<std::string> options = cmExpandedList(linkOptions); for (const auto& option : options) { - std::unique_ptr<TargetPropertyEntry> entry( - CreateTargetPropertyEntry(option)); - entries.emplace_back(EvaluateTargetPropertyEntry( - this, config, language, &dagChecker, entry.get())); + std::unique_ptr<TargetPropertyEntry> entry = + CreateTargetPropertyEntry(option); + entries.emplace_back(EvaluateTargetPropertyEntry(this, config, language, + &dagChecker, *entry)); } } processOptions(this, entries, result, uniqueOptions, false, @@ -3902,7 +3926,8 @@ std::vector<BT<std::string>> cmGeneratorTarget::GetLinkDirectories( this->LinkDirectoriesEntries); AddInterfaceEntries(this, config, "INTERFACE_LINK_DIRECTORIES", language, - &dagChecker, entries); + &dagChecker, entries, + this->GetPolicyStatusCMP0099() != cmPolicies::NEW); processLinkDirectories(this, entries, result, uniqueDirectories, debugDirectories); @@ -3933,14 +3958,15 @@ std::vector<BT<std::string>> cmGeneratorTarget::GetLinkDepends( if (const char* linkDepends = this->GetProperty("LINK_DEPENDS")) { std::vector<std::string> depends = cmExpandedList(linkDepends); for (const auto& depend : depends) { - std::unique_ptr<TargetPropertyEntry> entry( - CreateTargetPropertyEntry(depend)); - entries.emplace_back(EvaluateTargetPropertyEntry( - this, config, language, &dagChecker, entry.get())); + std::unique_ptr<TargetPropertyEntry> entry = + CreateTargetPropertyEntry(depend); + entries.emplace_back(EvaluateTargetPropertyEntry(this, config, language, + &dagChecker, *entry)); } } AddInterfaceEntries(this, config, "INTERFACE_LINK_DEPENDS", language, - &dagChecker, entries); + &dagChecker, entries, + this->GetPolicyStatusCMP0099() != cmPolicies::NEW); processOptions(this, entries, result, uniqueOptions, false, "link depends", OptionsParse::None); @@ -4720,9 +4746,9 @@ std::string intersect(const std::set<std::string>& s1, } void cmGeneratorTarget::CheckPropertyCompatibility( - cmComputeLinkInformation* info, const std::string& config) const + cmComputeLinkInformation& info, const std::string& config) const { - const cmComputeLinkInformation::ItemVector& deps = info->GetItems(); + const cmComputeLinkInformation::ItemVector& deps = info.GetItems(); std::set<std::string> emittedBools; static const std::string strBool = "COMPATIBLE_INTERFACE_BOOL"; @@ -5067,10 +5093,11 @@ PropertyType checkInterfacePropertyCompatibility(cmGeneratorTarget const* tgt, } std::string interfaceProperty = "INTERFACE_" + p; - std::unique_ptr<cmGeneratorExpressionInterpreter> genexInterpreter( - p == "POSITION_INDEPENDENT_CODE" ? new cmGeneratorExpressionInterpreter( - tgt->GetLocalGenerator(), config, tgt) - : nullptr); + std::unique_ptr<cmGeneratorExpressionInterpreter> genexInterpreter; + if (p == "POSITION_INDEPENDENT_CODE") { + genexInterpreter = cm::make_unique<cmGeneratorExpressionInterpreter>( + tgt->GetLocalGenerator(), config, tgt); + } for (cmGeneratorTarget const* theTarget : deps) { // An error should be reported if one dependency @@ -5217,22 +5244,19 @@ cmComputeLinkInformation* cmGeneratorTarget::GetLinkInformation( auto i = this->LinkInformation.find(key); if (i == this->LinkInformation.end()) { // Compute information for this configuration. - cmComputeLinkInformation* info = - new cmComputeLinkInformation(this, config); - if (!info || !info->Compute()) { - delete info; - info = nullptr; + auto info = cm::make_unique<cmComputeLinkInformation>(this, config); + if (info && !info->Compute()) { + info.reset(); } // Store the information for this configuration. - cmTargetLinkInformationMap::value_type entry(key, info); - i = this->LinkInformation.insert(entry).first; + i = this->LinkInformation.emplace(key, std::move(info)).first; - if (info) { - this->CheckPropertyCompatibility(info, config); + if (i->second) { + this->CheckPropertyCompatibility(*i->second, config); } } - return i->second; + return i->second.get(); } void cmGeneratorTarget::GetTargetVersion(int& major, int& minor) const @@ -6379,8 +6403,7 @@ bool cmGeneratorTarget::IsCSharpOnly() const this->GetType() != cmStateEnums::EXECUTABLE) { return false; } - std::set<std::string> languages; - this->GetLanguages(languages, ""); + std::set<std::string> languages = this->GetAllConfigCompileLanguages(); // Consider an explicit linker language property, but *not* the // computed linker language that may depend on linked targets. const char* linkLang = this->GetProperty("LINKER_LANGUAGE"); diff --git a/Source/cmGeneratorTarget.h b/Source/cmGeneratorTarget.h index 493eafc..eabd3fa9 100644 --- a/Source/cmGeneratorTarget.h +++ b/Source/cmGeneratorTarget.h @@ -7,6 +7,7 @@ #include <cstddef> #include <map> +#include <memory> #include <set> #include <string> #include <unordered_map> @@ -125,7 +126,7 @@ public: struct AllConfigSource { - cmSourceFile const* Source; + cmSourceFile* Source; cmGeneratorTarget::SourceKind Kind; std::vector<size_t> Configs; }; @@ -134,6 +135,10 @@ public: per-source configurations assigned. */ std::vector<AllConfigSource> const& GetAllConfigSources() const; + /** Get all languages used to compile sources in any configuration. + This excludes the languages of objects from object libraries. */ + std::set<std::string> GetAllConfigCompileLanguages() const; + void GetObjectSources(std::vector<cmSourceFile const*>&, const std::string& config) const; const std::string& GetObjectName(cmSourceFile const* file); @@ -274,7 +279,8 @@ public: /** Return the install name directory for the target in the * install tree. For example: "\@rpath/" or "\@loader_path/". */ - std::string GetInstallNameDirForInstallTree() const; + std::string GetInstallNameDirForInstallTree( + const std::string& config, const std::string& installPrefix) const; cmListFileBacktrace GetBacktrace() const; @@ -701,7 +707,8 @@ public: std::string EvaluateInterfaceProperty( std::string const& prop, cmGeneratorExpressionContext* context, - cmGeneratorExpressionDAGChecker* dagCheckerParent) const; + cmGeneratorExpressionDAGChecker* dagCheckerParent, + bool usage_requirements_only = true) const; bool HaveInstallTreeRPATH(const std::string& config) const; @@ -760,6 +767,7 @@ private: }; using SourceEntriesType = std::map<cmSourceFile const*, SourceEntry>; SourceEntriesType SourceDepends; + mutable std::set<std::string> VisitedConfigsForObjects; mutable std::map<cmSourceFile const*, std::string> Objects; std::set<cmSourceFile const*> ExplicitObjectName; mutable std::map<std::string, std::vector<std::string>> SystemIncludesCache; @@ -816,10 +824,10 @@ private: mutable std::map<std::string, CompatibleInterfaces> CompatibleInterfacesMap; using cmTargetLinkInformationMap = - std::map<std::string, cmComputeLinkInformation*>; + std::map<std::string, std::unique_ptr<cmComputeLinkInformation>>; mutable cmTargetLinkInformationMap LinkInformation; - void CheckPropertyCompatibility(cmComputeLinkInformation* info, + void CheckPropertyCompatibility(cmComputeLinkInformation& info, const std::string& config) const; struct LinkImplClosure : public std::vector<cmGeneratorTarget const*> @@ -880,16 +888,20 @@ private: mutable std::unordered_map<std::string, bool> MaybeInterfacePropertyExists; bool MaybeHaveInterfaceProperty(std::string const& prop, - cmGeneratorExpressionContext* context) const; - - std::vector<TargetPropertyEntry*> IncludeDirectoriesEntries; - std::vector<TargetPropertyEntry*> CompileOptionsEntries; - std::vector<TargetPropertyEntry*> CompileFeaturesEntries; - std::vector<TargetPropertyEntry*> CompileDefinitionsEntries; - std::vector<TargetPropertyEntry*> LinkOptionsEntries; - std::vector<TargetPropertyEntry*> LinkDirectoriesEntries; - std::vector<TargetPropertyEntry*> PrecompileHeadersEntries; - std::vector<TargetPropertyEntry*> SourceEntries; + cmGeneratorExpressionContext* context, + bool usage_requirements_only) const; + + using TargetPropertyEntryVector = + std::vector<std::unique_ptr<TargetPropertyEntry>>; + + TargetPropertyEntryVector IncludeDirectoriesEntries; + TargetPropertyEntryVector CompileOptionsEntries; + TargetPropertyEntryVector CompileFeaturesEntries; + TargetPropertyEntryVector CompileDefinitionsEntries; + TargetPropertyEntryVector LinkOptionsEntries; + TargetPropertyEntryVector LinkDirectoriesEntries; + TargetPropertyEntryVector PrecompileHeadersEntries; + TargetPropertyEntryVector SourceEntries; mutable std::set<std::string> LinkImplicitNullProperties; mutable std::map<std::string, std::string> PchHeaders; mutable std::map<std::string, std::string> PchSources; diff --git a/Source/cmGhsMultiTargetGenerator.cxx b/Source/cmGhsMultiTargetGenerator.cxx index 8e4352e..f7c542f 100644 --- a/Source/cmGhsMultiTargetGenerator.cxx +++ b/Source/cmGhsMultiTargetGenerator.cxx @@ -113,7 +113,7 @@ void cmGhsMultiTargetGenerator::Generate() // Tell the global generator the name of the project file this->GeneratorTarget->Target->SetProperty("GENERATOR_FILE_NAME", - this->Name.c_str()); + this->Name); this->GeneratorTarget->Target->SetProperty( "GENERATOR_FILE_NAME_EXT", GhsMultiGpj::GetGpjTag(this->TagType)); diff --git a/Source/cmGlobalBorlandMakefileGenerator.cxx b/Source/cmGlobalBorlandMakefileGenerator.cxx index 51d681d..06943e7 100644 --- a/Source/cmGlobalBorlandMakefileGenerator.cxx +++ b/Source/cmGlobalBorlandMakefileGenerator.cxx @@ -2,6 +2,10 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmGlobalBorlandMakefileGenerator.h" +#include <utility> + +#include <cm/memory> + #include "cmDocumentationEntry.h" #include "cmLocalUnixMakefileGenerator3.h" #include "cmMakefile.h" @@ -35,15 +39,14 @@ void cmGlobalBorlandMakefileGenerator::EnableLanguage( } //! Create a local generator appropriate to this Global Generator -cmLocalGenerator* cmGlobalBorlandMakefileGenerator::CreateLocalGenerator( - cmMakefile* mf) +std::unique_ptr<cmLocalGenerator> +cmGlobalBorlandMakefileGenerator::CreateLocalGenerator(cmMakefile* mf) { - cmLocalUnixMakefileGenerator3* lg = - new cmLocalUnixMakefileGenerator3(this, mf); + auto lg = cm::make_unique<cmLocalUnixMakefileGenerator3>(this, mf); lg->SetMakefileVariableSize(32); lg->SetMakeCommandEscapeTargetTwice(true); lg->SetBorlandMakeCurlyHack(true); - return lg; + return std::unique_ptr<cmLocalGenerator>(std::move(lg)); } void cmGlobalBorlandMakefileGenerator::GetDocumentation( diff --git a/Source/cmGlobalBorlandMakefileGenerator.h b/Source/cmGlobalBorlandMakefileGenerator.h index da04743..291220c 100644 --- a/Source/cmGlobalBorlandMakefileGenerator.h +++ b/Source/cmGlobalBorlandMakefileGenerator.h @@ -4,6 +4,7 @@ #define cmGlobalBorlandMakefileGenerator_h #include <iosfwd> +#include <memory> #include "cmGlobalNMakeMakefileGenerator.h" @@ -33,7 +34,8 @@ public: static void GetDocumentation(cmDocumentationEntry& entry); //! Create a local generator appropriate to this Global Generator - cmLocalGenerator* CreateLocalGenerator(cmMakefile* mf) override; + std::unique_ptr<cmLocalGenerator> CreateLocalGenerator( + cmMakefile* mf) override; /** * Try to determine system information such as shared library diff --git a/Source/cmGlobalCommonGenerator.cxx b/Source/cmGlobalCommonGenerator.cxx index 9fa4467..e04eef1 100644 --- a/Source/cmGlobalCommonGenerator.cxx +++ b/Source/cmGlobalCommonGenerator.cxx @@ -2,6 +2,7 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmGlobalCommonGenerator.h" +#include <memory> #include <utility> #include "cmGeneratorTarget.h" @@ -24,15 +25,15 @@ std::map<std::string, cmGlobalCommonGenerator::DirectoryTarget> cmGlobalCommonGenerator::ComputeDirectoryTargets() const { std::map<std::string, DirectoryTarget> dirTargets; - for (cmLocalGenerator* lg : this->LocalGenerators) { + for (const auto& lg : this->LocalGenerators) { std::string const& currentBinaryDir( lg->GetStateSnapshot().GetDirectory().GetCurrentBinary()); DirectoryTarget& dirTarget = dirTargets[currentBinaryDir]; - dirTarget.LG = lg; + dirTarget.LG = lg.get(); // The directory-level rule should depend on the target-level rules // for all targets in the directory. - for (auto gt : lg->GetGeneratorTargets()) { + for (const auto& gt : lg->GetGeneratorTargets()) { cmStateEnums::TargetType const type = gt->GetType(); if (type != cmStateEnums::EXECUTABLE && type != cmStateEnums::STATIC_LIBRARY && @@ -43,7 +44,7 @@ cmGlobalCommonGenerator::ComputeDirectoryTargets() const continue; } DirectoryTarget::Target t; - t.GT = gt; + t.GT = gt.get(); if (const char* exclude = gt->GetProperty("EXCLUDE_FROM_ALL")) { if (cmIsOn(exclude)) { // This target has been explicitly excluded. diff --git a/Source/cmGlobalGenerator.cxx b/Source/cmGlobalGenerator.cxx index 09fb87d..bcc9050 100644 --- a/Source/cmGlobalGenerator.cxx +++ b/Source/cmGlobalGenerator.cxx @@ -10,6 +10,9 @@ #include <initializer_list> #include <iterator> #include <sstream> +#include <utility> + +#include <cm/memory> #include "cmsys/Directory.hxx" #include "cmsys/FStream.hxx" @@ -31,6 +34,7 @@ #include "cmGeneratorTarget.h" #include "cmInstallGenerator.h" #include "cmLinkLineComputer.h" +#include "cmListFileCache.h" #include "cmLocalGenerator.h" #include "cmMSVC60LinkLineComputer.h" #include "cmMakefile.h" @@ -121,6 +125,7 @@ Json::Value cmGlobalGenerator::GetJson() const { Json::Value generator = Json::objectValue; generator["name"] = this->GetName(); + generator["multiConfig"] = this->IsMultiConfig(); return generator; } #endif @@ -165,7 +170,7 @@ bool cmGlobalGenerator::SetGeneratorPlatform(std::string const& p, return false; } -bool cmGlobalGenerator::SetGeneratorToolset(std::string const& ts, +bool cmGlobalGenerator::SetGeneratorToolset(std::string const& ts, bool, cmMakefile* mf) { if (ts.empty()) { @@ -295,8 +300,8 @@ void cmGlobalGenerator::ForceLinkerLanguages() bool cmGlobalGenerator::CheckTargetsForMissingSources() const { bool failed = false; - for (cmLocalGenerator* localGen : this->LocalGenerators) { - for (cmGeneratorTarget* target : localGen->GetGeneratorTargets()) { + for (const auto& localGen : this->LocalGenerators) { + for (const auto& target : localGen->GetGeneratorTargets()) { if (target->GetType() == cmStateEnums::TargetType::GLOBAL_TARGET || target->GetType() == cmStateEnums::TargetType::INTERFACE_LIBRARY || target->GetType() == cmStateEnums::TargetType::UTILITY || @@ -335,8 +340,8 @@ bool cmGlobalGenerator::CheckTargetsForType() const return false; } bool failed = false; - for (cmLocalGenerator* generator : this->LocalGenerators) { - for (cmGeneratorTarget* target : generator->GetGeneratorTargets()) { + for (const auto& generator : this->LocalGenerators) { + for (const auto& target : generator->GetGeneratorTargets()) { if (target->GetType() == cmStateEnums::EXECUTABLE && target->GetPropertyAsBool("WIN32_EXECUTABLE")) { std::vector<std::string> const& configs = @@ -363,8 +368,8 @@ bool cmGlobalGenerator::CheckTargetsForPchCompilePdb() const return false; } bool failed = false; - for (cmLocalGenerator* generator : this->LocalGenerators) { - for (cmGeneratorTarget* target : generator->GetGeneratorTargets()) { + for (const auto& generator : this->LocalGenerators) { + for (const auto& target : generator->GetGeneratorTargets()) { if (target->GetType() == cmStateEnums::TargetType::GLOBAL_TARGET || target->GetType() == cmStateEnums::TargetType::INTERFACE_LIBRARY || target->GetType() == cmStateEnums::TargetType::UTILITY || @@ -650,7 +655,7 @@ void cmGlobalGenerator::EnableLanguage( // Tell the generator about the toolset, if any. std::string toolset = mf->GetSafeDefinition("CMAKE_GENERATOR_TOOLSET"); - if (!this->SetGeneratorToolset(toolset, mf)) { + if (!this->SetGeneratorToolset(toolset, false, mf)) { cmSystemTools::SetFatalErrorOccured(); return; } @@ -1199,13 +1204,12 @@ void cmGlobalGenerator::ClearEnabledLanguages() void cmGlobalGenerator::CreateLocalGenerators() { this->LocalGeneratorSearchIndex.clear(); - cmDeleteAll(this->LocalGenerators); this->LocalGenerators.clear(); this->LocalGenerators.reserve(this->Makefiles.size()); for (cmMakefile* m : this->Makefiles) { - cmLocalGenerator* lg = this->CreateLocalGenerator(m); - this->LocalGenerators.push_back(lg); - this->IndexLocalGenerator(lg); + auto lg = this->CreateLocalGenerator(m); + this->IndexLocalGenerator(lg.get()); + this->LocalGenerators.push_back(std::move(lg)); } } @@ -1258,10 +1262,6 @@ void cmGlobalGenerator::Configure() "number of local generators", cmStateEnums::INTERNAL); - // check for link libraries and include directories containing "NOTFOUND" - // and for infinite loops - this->CheckTargetProperties(); - if (this->CMakeInstance->GetWorkingMode() == cmake::NORMAL_MODE) { std::ostringstream msg; if (cmSystemTools::GetErrorOccuredFlag()) { @@ -1284,6 +1284,10 @@ void cmGlobalGenerator::Configure() void cmGlobalGenerator::CreateGenerationObjects(TargetTypes targetTypes) { this->CreateLocalGenerators(); + // Commit side effects only if we are actually generating + if (this->GetConfigureDoneCMP0026()) { + this->CheckTargetProperties(); + } this->CreateGeneratorTargets(targetTypes); this->ComputeBuildFileGenerators(); } @@ -1295,7 +1299,7 @@ void cmGlobalGenerator::CreateImportedGenerationObjects( this->CreateGenerationObjects(ImportedOnly); auto const mfit = std::find(this->Makefiles.begin(), this->Makefiles.end(), mf); - cmLocalGenerator* lg = + auto& lg = this->LocalGenerators[std::distance(this->Makefiles.begin(), mfit)]; for (std::string const& t : targets) { cmGeneratorTarget* gt = lg->FindGeneratorTargetToUse(t); @@ -1348,7 +1352,7 @@ void cmGlobalGenerator::ComputeBuildFileGenerators() std::vector<cmExportBuildFileGenerator*> gens = this->Makefiles[i]->GetExportBuildFileGenerators(); for (cmExportBuildFileGenerator* g : gens) { - g->Compute(this->LocalGenerators[i]); + g->Compute(this->LocalGenerators[i].get()); } } } @@ -1387,7 +1391,7 @@ bool cmGlobalGenerator::Compute() } // Add generator specific helper commands - for (cmLocalGenerator* localGen : this->LocalGenerators) { + for (const auto& localGen : this->LocalGenerators) { localGen->AddHelperCommands(); } @@ -1397,16 +1401,16 @@ bool cmGlobalGenerator::Compute() // on the original cmTarget instance. It accumulates features // across all configurations. Some refactoring is needed to // compute a per-config resulta purely during generation. - for (cmLocalGenerator* localGen : this->LocalGenerators) { + for (const auto& localGen : this->LocalGenerators) { if (!localGen->ComputeTargetCompileFeatures()) { return false; } } - for (cmLocalGenerator* localGen : this->LocalGenerators) { + for (const auto& localGen : this->LocalGenerators) { cmMakefile* mf = localGen->GetMakefile(); for (cmInstallGenerator* g : mf->GetInstallGenerators()) { - if (!g->Compute(localGen)) { + if (!g->Compute(localGen.get())) { return false; } } @@ -1416,7 +1420,7 @@ bool cmGlobalGenerator::Compute() // Trace the dependencies, after that no custom commands should be added // because their dependencies might not be handled correctly - for (cmLocalGenerator* localGen : this->LocalGenerators) { + for (const auto& localGen : this->LocalGenerators) { localGen->TraceDependencies(); } @@ -1428,7 +1432,7 @@ bool cmGlobalGenerator::Compute() this->ForceLinkerLanguages(); // Compute the manifest of main targets generated. - for (cmLocalGenerator* localGen : this->LocalGenerators) { + for (const auto& localGen : this->LocalGenerators) { localGen->ComputeTargetManifest(); } @@ -1445,7 +1449,7 @@ bool cmGlobalGenerator::Compute() return false; } - for (cmLocalGenerator* localGen : this->LocalGenerators) { + for (const auto& localGen : this->LocalGenerators) { localGen->ComputeHomeRelativeOutputPath(); } @@ -1460,6 +1464,8 @@ void cmGlobalGenerator::Generate() this->ProcessEvaluationFiles(); + this->CMakeInstance->UpdateProgress("Generating", 0.1f); + // Generate project files for (unsigned int i = 0; i < this->LocalGenerators.size(); ++i) { this->SetCurrentMakefile(this->LocalGenerators[i]->GetMakefile()); @@ -1471,8 +1477,9 @@ void cmGlobalGenerator::Generate() this->LocalGenerators[i]->GenerateTestFiles(); this->CMakeInstance->UpdateProgress( "Generating", - (static_cast<float>(i) + 1.0f) / - static_cast<float>(this->LocalGenerators.size())); + 0.1f + + 0.9f * (static_cast<float>(i) + 1.0f) / + static_cast<float>(this->LocalGenerators.size())); } this->SetCurrentMakefile(nullptr); @@ -1555,24 +1562,24 @@ bool cmGlobalGenerator::QtAutoGen() bool cmGlobalGenerator::AddAutomaticSources() { - for (cmLocalGenerator* lg : this->LocalGenerators) { + for (const auto& lg : this->LocalGenerators) { lg->CreateEvaluationFileOutputs(); - for (cmGeneratorTarget* gt : lg->GetGeneratorTargets()) { + for (const auto& gt : lg->GetGeneratorTargets()) { if (gt->GetType() == cmStateEnums::INTERFACE_LIBRARY || gt->GetType() == cmStateEnums::UTILITY || gt->GetType() == cmStateEnums::GLOBAL_TARGET) { continue; } - lg->AddUnityBuild(gt); - lg->AddPchDependencies(gt); + lg->AddUnityBuild(gt.get()); + lg->AddPchDependencies(gt.get()); } } // The above transformations may have changed the classification of sources. // Clear the source list and classification cache (KindedSources) of all // targets so that it will be recomputed correctly by the generators later // now that the above transformations are done for all targets. - for (cmLocalGenerator* lg : this->LocalGenerators) { - for (cmGeneratorTarget* gt : lg->GetGeneratorTargets()) { + for (const auto& lg : this->LocalGenerators) { + for (const auto& gt : lg->GetGeneratorTargets()) { gt->ClearSourcesCache(); } } @@ -1661,8 +1668,7 @@ void cmGlobalGenerator::CreateGeneratorTargets( if (targetTypes == AllTargets) { for (auto& target : mf->GetTargets()) { cmTarget* t = &target.second; - cmGeneratorTarget* gt = new cmGeneratorTarget(t, lg); - lg->AddGeneratorTarget(gt); + lg->AddGeneratorTarget(cm::make_unique<cmGeneratorTarget>(t, lg)); } } @@ -1677,17 +1683,17 @@ void cmGlobalGenerator::CreateGeneratorTargets(TargetTypes targetTypes) for (unsigned int i = 0; i < this->Makefiles.size(); ++i) { cmMakefile* mf = this->Makefiles[i]; for (cmTarget* ownedImpTgt : mf->GetOwnedImportedTargets()) { - cmLocalGenerator* lg = this->LocalGenerators[i]; - cmGeneratorTarget* gt = new cmGeneratorTarget(ownedImpTgt, lg); - lg->AddOwnedImportedGeneratorTarget(gt); - importedMap[ownedImpTgt] = gt; + cmLocalGenerator* lg = this->LocalGenerators[i].get(); + auto gt = cm::make_unique<cmGeneratorTarget>(ownedImpTgt, lg); + importedMap[ownedImpTgt] = gt.get(); + lg->AddOwnedImportedGeneratorTarget(std::move(gt)); } } // Construct per-target generator information. for (unsigned int i = 0; i < this->LocalGenerators.size(); ++i) { this->CreateGeneratorTargets(targetTypes, this->Makefiles[i], - this->LocalGenerators[i], importedMap); + this->LocalGenerators[i].get(), importedMap); } } @@ -1699,7 +1705,6 @@ void cmGlobalGenerator::ClearGeneratorMembers() cmDeleteAll(this->Makefiles); this->Makefiles.clear(); - cmDeleteAll(this->LocalGenerators); this->LocalGenerators.clear(); this->AliasTargets.clear(); @@ -1722,12 +1727,12 @@ void cmGlobalGenerator::ComputeTargetObjectDirectory( void cmGlobalGenerator::CheckTargetProperties() { + // check for link libraries and include directories containing "NOTFOUND" + // and for infinite loops std::map<std::string, std::string> notFoundMap; - // std::set<std::string> notFoundMap; - // after it is all done do a ConfigureFinalPass cmState* state = this->GetCMakeInstance()->GetState(); for (unsigned int i = 0; i < this->Makefiles.size(); ++i) { - this->Makefiles[i]->ConfigureFinalPass(); + this->Makefiles[i]->Generate(*this->LocalGenerators[i]); for (auto const& target : this->Makefiles[i]->GetTargets()) { if (target.second.GetType() == cmStateEnums::INTERFACE_LIBRARY) { continue; @@ -1771,11 +1776,6 @@ void cmGlobalGenerator::CheckTargetProperties() } } } - this->CMakeInstance->UpdateProgress( - "Configuring", - 0.9f + - 0.1f * (static_cast<float>(i) + 1.0f) / - static_cast<float>(this->Makefiles.size())); } if (!notFoundMap.empty()) { @@ -2025,10 +2025,10 @@ void cmGlobalGenerator::AddMakefile(cmMakefile* mf) } int numGen = atoi(numGenC->c_str()); - float prog = 0.9f * static_cast<float>(this->Makefiles.size()) / - static_cast<float>(numGen); - if (prog > 0.9f) { - prog = 0.9f; + float prog = + static_cast<float>(this->Makefiles.size()) / static_cast<float>(numGen); + if (prog > 1.0f) { + prog = 1.0f; } this->CMakeInstance->UpdateProgress("Configuring", prog); } @@ -2045,9 +2045,10 @@ void cmGlobalGenerator::EnableInstallTarget() this->InstallTargetEnabled = true; } -cmLocalGenerator* cmGlobalGenerator::CreateLocalGenerator(cmMakefile* mf) +std::unique_ptr<cmLocalGenerator> cmGlobalGenerator::CreateLocalGenerator( + cmMakefile* mf) { - return new cmLocalGenerator(this, mf); + return cm::make_unique<cmLocalGenerator>(this, mf); } void cmGlobalGenerator::EnableLanguagesFromGenerator(cmGlobalGenerator* gen, @@ -2142,7 +2143,7 @@ int cmGlobalGenerator::GetLinkerPreference(const std::string& lang) const void cmGlobalGenerator::FillProjectMap() { this->ProjectMap.clear(); // make sure we start with a clean map - for (cmLocalGenerator* localGen : this->LocalGenerators) { + for (const auto& localGen : this->LocalGenerators) { // for each local generator add all projects cmStateSnapshot snp = localGen->GetStateSnapshot(); std::string name; @@ -2150,7 +2151,7 @@ void cmGlobalGenerator::FillProjectMap() std::string snpProjName = snp.GetProjectName(); if (name != snpProjName) { name = snpProjName; - this->ProjectMap[name].push_back(localGen); + this->ProjectMap[name].push_back(localGen.get()); } snp = snp.GetBuildsystemDirectoryParent(); } while (snp.IsValid()); @@ -2475,6 +2476,7 @@ void cmGlobalGenerator::AddGlobalTarget_EditCache( } GlobalTargetInfo gti; gti.Name = editCacheTargetName; + gti.PerConfig = false; cmCustomCommandLine singleLine; // Use generator preference for the edit_cache rule if it is defined. @@ -2509,6 +2511,7 @@ void cmGlobalGenerator::AddGlobalTarget_RebuildCache( gti.Name = rebuildCacheTargetName; gti.Message = "Running CMake to regenerate build system..."; gti.UsesTerminal = true; + gti.PerConfig = false; cmCustomCommandLine singleLine; singleLine.push_back(cmSystemTools::GetCMakeCommand()); singleLine.push_back("-S$(CMAKE_SOURCE_DIR)"); @@ -2653,19 +2656,19 @@ cmTarget cmGlobalGenerator::CreateGlobalTarget(GlobalTargetInfo const& gti, { // Package cmTarget target(gti.Name, cmStateEnums::GLOBAL_TARGET, - cmTarget::VisibilityNormal, mf); + cmTarget::VisibilityNormal, mf, gti.PerConfig); target.SetProperty("EXCLUDE_FROM_ALL", "TRUE"); std::vector<std::string> no_outputs; std::vector<std::string> no_byproducts; std::vector<std::string> no_depends; // Store the custom command in the target. - cmCustomCommand cc(nullptr, no_outputs, no_byproducts, no_depends, - gti.CommandLines, nullptr, gti.WorkingDir.c_str()); + cmCustomCommand cc(no_outputs, no_byproducts, no_depends, gti.CommandLines, + cmListFileBacktrace(), nullptr, gti.WorkingDir.c_str()); cc.SetUsesTerminal(gti.UsesTerminal); target.AddPostBuildCommand(std::move(cc)); if (!gti.Message.empty()) { - target.SetProperty("EchoString", gti.Message.c_str()); + target.SetProperty("EchoString", gti.Message); } for (std::string const& d : gti.Depends) { target.AddUtility(d); @@ -2765,27 +2768,26 @@ void cmGlobalGenerator::GetFilesReplacedDuringGenerate( std::back_inserter(filenames)); } -void cmGlobalGenerator::GetTargetSets(TargetDependSet& projectTargets, - TargetDependSet& originalTargets, - cmLocalGenerator* root, - GeneratorVector const& generators) +void cmGlobalGenerator::GetTargetSets( + TargetDependSet& projectTargets, TargetDependSet& originalTargets, + cmLocalGenerator* root, std::vector<cmLocalGenerator*>& generators) { // loop over all local generators - for (cmLocalGenerator* generator : generators) { + for (auto generator : generators) { // check to make sure generator is not excluded if (this->IsExcluded(root, generator)) { continue; } // loop over all the generator targets in the makefile - for (cmGeneratorTarget* target : generator->GetGeneratorTargets()) { - if (this->IsRootOnlyTarget(target) && + for (const auto& target : generator->GetGeneratorTargets()) { + if (this->IsRootOnlyTarget(target.get()) && target->GetLocalGenerator() != root) { continue; } // put the target in the set of original targets - originalTargets.insert(target); + originalTargets.insert(target.get()); // Get the set of targets that depend on target - this->AddTargetDepends(target, projectTargets); + this->AddTargetDepends(target.get(), projectTargets); } } } @@ -2961,12 +2963,12 @@ void cmGlobalGenerator::WriteSummary() "/CMakeFiles/TargetDirectories.txt"); cmGeneratedFileStream fout(fname); - for (cmLocalGenerator* lg : this->LocalGenerators) { - for (cmGeneratorTarget* tgt : lg->GetGeneratorTargets()) { + for (const auto& lg : this->LocalGenerators) { + for (const auto& tgt : lg->GetGeneratorTargets()) { if (tgt->GetType() == cmStateEnums::INTERFACE_LIBRARY) { continue; } - this->WriteSummary(tgt); + this->WriteSummary(tgt.get()); fout << tgt->GetSupportDirectory() << "\n"; } } @@ -3111,7 +3113,7 @@ cmGlobalGenerator::GetFilenameTargetDepends(cmSourceFile* sf) const void cmGlobalGenerator::ProcessEvaluationFiles() { std::vector<std::string> generatedFiles; - for (cmLocalGenerator* localGen : this->LocalGenerators) { + for (auto& localGen : this->LocalGenerators) { localGen->ProcessEvaluationFiles(generatedFiles); } } @@ -3127,7 +3129,7 @@ bool cmGlobalGenerator::GenerateCPackPropertiesFile() cmake::InstalledFilesMap const& installedFiles = this->CMakeInstance->GetInstalledFiles(); - cmLocalGenerator* lg = this->LocalGenerators[0]; + const auto& lg = this->LocalGenerators[0]; cmMakefile* mf = lg->GetMakefile(); std::vector<std::string> configs; @@ -3146,8 +3148,8 @@ bool cmGlobalGenerator::GenerateCPackPropertiesFile() for (auto const& i : installedFiles) { cmInstalledFile const& installedFile = i.second; - cmCPackPropertiesGenerator cpackPropertiesGenerator(lg, installedFile, - configs); + cmCPackPropertiesGenerator cpackPropertiesGenerator( + lg.get(), installedFile, configs); cpackPropertiesGenerator.Generate(file, config, configs); } diff --git a/Source/cmGlobalGenerator.h b/Source/cmGlobalGenerator.h index f25ff7b..f3078ac 100644 --- a/Source/cmGlobalGenerator.h +++ b/Source/cmGlobalGenerator.h @@ -14,9 +14,10 @@ #include <utility> #include <vector> +#include <cmext/algorithm> + #include "cm_codecvt.hxx" -#include "cmAlgorithms.h" #include "cmCustomCommandLines.h" #include "cmDuration.h" #include "cmExportSet.h" @@ -71,7 +72,7 @@ struct GeneratedMakeCommand void Add(std::vector<std::string>::const_iterator start, std::vector<std::string>::const_iterator end) { - cmAppend(PrimaryCommand, start, end); + cm::append(PrimaryCommand, start, end); } std::string Printable() const { return cmJoin(PrimaryCommand, " "); } @@ -90,11 +91,14 @@ struct GeneratedMakeCommand class cmGlobalGenerator { public: + using LocalGeneratorVector = std::vector<std::unique_ptr<cmLocalGenerator>>; + //! Free any memory allocated with the GlobalGenerator cmGlobalGenerator(cmake* cm); virtual ~cmGlobalGenerator(); - virtual cmLocalGenerator* CreateLocalGenerator(cmMakefile* mf); + virtual std::unique_ptr<cmLocalGenerator> CreateLocalGenerator( + cmMakefile* mf); //! Get the name for this generator virtual std::string GetName() const { return "Generic"; } @@ -128,7 +132,8 @@ public: /** Set the generator-specific toolset name. Returns true if toolset is supported and false otherwise. */ - virtual bool SetGeneratorToolset(std::string const& ts, cmMakefile* mf); + virtual bool SetGeneratorToolset(std::string const& ts, bool build, + cmMakefile* mf); /** * Create LocalGenerators and process the CMakeLists files. This does not @@ -248,7 +253,7 @@ public: { return this->Makefiles; } - const std::vector<cmLocalGenerator*>& GetLocalGenerators() const + const LocalGeneratorVector& GetLocalGenerators() const { return this->LocalGenerators; } @@ -475,13 +480,17 @@ public: int RecursionDepth; + virtual void GetQtAutoGenConfigs(std::vector<std::string>& configs) const + { + configs.emplace_back("$<CONFIG>"); + } + protected: - using GeneratorVector = std::vector<cmLocalGenerator*>; // for a project collect all its targets by following depend // information, and also collect all the targets void GetTargetSets(TargetDependSet& projectTargets, TargetDependSet& originalTargets, cmLocalGenerator* root, - GeneratorVector const&); + std::vector<cmLocalGenerator*>& generators); bool IsRootOnlyTarget(cmGeneratorTarget* target) const; void AddTargetDepends(const cmGeneratorTarget* target, TargetDependSet& projectTargets); @@ -524,6 +533,7 @@ protected: std::vector<std::string> Depends; std::string WorkingDir; bool UsesTerminal = false; + bool PerConfig = true; }; void CreateDefaultGlobalTargets(std::vector<GlobalTargetInfo>& targets); @@ -540,7 +550,7 @@ protected: std::string ConfiguredFilesPath; cmake* CMakeInstance; std::vector<cmMakefile*> Makefiles; - std::vector<cmLocalGenerator*> LocalGenerators; + LocalGeneratorVector LocalGenerators; cmMakefile* CurrentConfigureMakefile; // map from project name to vector of local generators in that project std::map<std::string, std::vector<cmLocalGenerator*>> ProjectMap; diff --git a/Source/cmGlobalGhsMultiGenerator.cxx b/Source/cmGlobalGhsMultiGenerator.cxx index 5a708ab..bb9dd37 100644 --- a/Source/cmGlobalGhsMultiGenerator.cxx +++ b/Source/cmGlobalGhsMultiGenerator.cxx @@ -8,6 +8,8 @@ #include <ostream> #include <utility> +#include <cm/memory> + #include "cmAlgorithms.h" #include "cmDocumentationEntry.h" #include "cmGeneratedFileStream.h" @@ -40,10 +42,11 @@ cmGlobalGhsMultiGenerator::cmGlobalGhsMultiGenerator(cmake* cm) cmGlobalGhsMultiGenerator::~cmGlobalGhsMultiGenerator() = default; -cmLocalGenerator* cmGlobalGhsMultiGenerator::CreateLocalGenerator( - cmMakefile* mf) +std::unique_ptr<cmLocalGenerator> +cmGlobalGhsMultiGenerator::CreateLocalGenerator(cmMakefile* mf) { - return new cmLocalGhsMultiGenerator(this, mf); + return std::unique_ptr<cmLocalGenerator>( + cm::make_unique<cmLocalGhsMultiGenerator>(this, mf)); } void cmGlobalGhsMultiGenerator::GetDocumentation(cmDocumentationEntry& entry) @@ -64,8 +67,11 @@ void cmGlobalGhsMultiGenerator::ComputeTargetObjectDirectory( } bool cmGlobalGhsMultiGenerator::SetGeneratorToolset(std::string const& ts, - cmMakefile* mf) + bool build, cmMakefile* mf) { + if (build) { + return true; + } std::string tsp; /* toolset path */ this->GetToolset(mf, tsp, ts); diff --git a/Source/cmGlobalGhsMultiGenerator.h b/Source/cmGlobalGhsMultiGenerator.h index ccfe073..989b12c 100644 --- a/Source/cmGlobalGhsMultiGenerator.h +++ b/Source/cmGlobalGhsMultiGenerator.h @@ -4,6 +4,7 @@ #define cmGhsMultiGenerator_h #include <iosfwd> +#include <memory> #include <set> #include <string> #include <utility> @@ -34,7 +35,8 @@ public: } //! create the correct local generator - cmLocalGenerator* CreateLocalGenerator(cmMakefile* mf) override; + std::unique_ptr<cmLocalGenerator> CreateLocalGenerator( + cmMakefile* mf) override; /// @return the name of this generator. static std::string GetActualName() { return "Green Hills MULTI"; } @@ -58,7 +60,8 @@ public: static bool SupportsPlatform() { return true; } // Toolset / Platform Support - bool SetGeneratorToolset(std::string const& ts, cmMakefile* mf) override; + bool SetGeneratorToolset(std::string const& ts, bool build, + cmMakefile* mf) override; bool SetGeneratorPlatform(std::string const& p, cmMakefile* mf) override; /** diff --git a/Source/cmGlobalJOMMakefileGenerator.cxx b/Source/cmGlobalJOMMakefileGenerator.cxx index ff54288..fc3123a 100644 --- a/Source/cmGlobalJOMMakefileGenerator.cxx +++ b/Source/cmGlobalJOMMakefileGenerator.cxx @@ -66,7 +66,7 @@ cmGlobalJOMMakefileGenerator::GenerateBuildCommand( // Since we have full control over the invocation of JOM, let us // make it quiet. jomMakeOptions.push_back(this->MakeSilentFlag); - cmAppend(jomMakeOptions, makeOptions); + cm::append(jomMakeOptions, makeOptions); // JOM does parallel builds by default, the -j is only needed if a specific // number is given diff --git a/Source/cmGlobalNMakeMakefileGenerator.cxx b/Source/cmGlobalNMakeMakefileGenerator.cxx index 2273c00..c4bec23 100644 --- a/Source/cmGlobalNMakeMakefileGenerator.cxx +++ b/Source/cmGlobalNMakeMakefileGenerator.cxx @@ -66,7 +66,7 @@ cmGlobalNMakeMakefileGenerator::GenerateBuildCommand( // Since we have full control over the invocation of nmake, let us // make it quiet. nmakeMakeOptions.push_back(this->MakeSilentFlag); - cmAppend(nmakeMakeOptions, makeOptions); + cm::append(nmakeMakeOptions, makeOptions); return this->cmGlobalUnixMakefileGenerator3::GenerateBuildCommand( makeProgram, projectName, projectDir, targetNames, config, fast, diff --git a/Source/cmGlobalNinjaGenerator.cxx b/Source/cmGlobalNinjaGenerator.cxx index da21d6c..2a59708 100644 --- a/Source/cmGlobalNinjaGenerator.cxx +++ b/Source/cmGlobalNinjaGenerator.cxx @@ -9,6 +9,8 @@ #include <sstream> #include <cm/memory> +#include <cmext/algorithm> +#include <cmext/memory> #include "cmsys/FStream.hxx" @@ -114,6 +116,11 @@ std::string cmGlobalNinjaGenerator::EncodeLiteral(const std::string& lit) std::string result = lit; cmSystemTools::ReplaceString(result, "$", "$$"); cmSystemTools::ReplaceString(result, "\n", "$\n"); + if (this->IsMultiConfig()) { + cmSystemTools::ReplaceString(result, + cmStrCat('$', this->GetCMakeCFGIntDir()), + this->GetCMakeCFGIntDir()); + } return result; } @@ -248,8 +255,8 @@ void cmGlobalNinjaGenerator::WriteCustomCommandBuild( const std::string& command, const std::string& description, const std::string& comment, const std::string& depfile, const std::string& job_pool, bool uses_terminal, bool restat, - const cmNinjaDeps& outputs, const cmNinjaDeps& explicitDeps, - const cmNinjaDeps& orderOnlyDeps) + const cmNinjaDeps& outputs, const std::string& config, + const cmNinjaDeps& explicitDeps, const cmNinjaDeps& orderOnlyDeps) { this->AddCustomCommandRule(); @@ -282,7 +289,11 @@ void cmGlobalNinjaGenerator::WriteCustomCommandBuild( if (!depfile.empty()) { vars["depfile"] = depfile; } - this->WriteBuild(*this->BuildFileStream, build); + if (config.empty()) { + this->WriteBuild(*this->GetCommonFileStream(), build); + } else { + this->WriteBuild(*this->GetConfigFileStream(config), build); + } } if (this->ComputingUnknownDependencies) { @@ -304,14 +315,15 @@ void cmGlobalNinjaGenerator::AddMacOSXContentRule() } void cmGlobalNinjaGenerator::WriteMacOSXContentBuild(std::string input, - std::string output) + std::string output, + const std::string& config) { this->AddMacOSXContentRule(); { cmNinjaBuild build("COPY_OSX_CONTENT"); build.Outputs.push_back(std::move(output)); build.ExplicitDeps.push_back(std::move(input)); - this->WriteBuild(*this->BuildFileStream, build); + this->WriteBuild(*this->GetConfigFileStream(config), build); } } @@ -429,9 +441,11 @@ cmGlobalNinjaGenerator::cmGlobalNinjaGenerator(cmake* cm) // Virtual public methods. -cmLocalGenerator* cmGlobalNinjaGenerator::CreateLocalGenerator(cmMakefile* mf) +std::unique_ptr<cmLocalGenerator> cmGlobalNinjaGenerator::CreateLocalGenerator( + cmMakefile* mf) { - return new cmLocalNinjaGenerator(this, mf); + return std::unique_ptr<cmLocalGenerator>( + cm::make_unique<cmLocalNinjaGenerator>(this, mf)); } codecvt::Encoding cmGlobalNinjaGenerator::GetMakefileEncoding() const @@ -470,14 +484,16 @@ void cmGlobalNinjaGenerator::Generate() msg.str()); return; } - if (!this->OpenBuildFileStream()) { + if (!this->OpenBuildFileStreams()) { return; } if (!this->OpenRulesFileStream()) { return; } - this->TargetDependsClosures.clear(); + for (auto& it : this->Configs) { + it.second.TargetDependsClosures.clear(); + } this->InitOutputPathPrefix(); this->TargetAll = this->NinjaOutputPath("all"); @@ -493,19 +509,26 @@ void cmGlobalNinjaGenerator::Generate() this->cmGlobalGenerator::Generate(); this->WriteAssumedSourceDependencies(); - this->WriteTargetAliases(*this->BuildFileStream); - this->WriteFolderTargets(*this->BuildFileStream); - this->WriteUnknownExplicitDependencies(*this->BuildFileStream); - this->WriteBuiltinTargets(*this->BuildFileStream); + this->WriteTargetAliases(*this->GetCommonFileStream()); + this->WriteFolderTargets(*this->GetCommonFileStream()); + this->WriteUnknownExplicitDependencies(*this->GetCommonFileStream()); + this->WriteBuiltinTargets(*this->GetCommonFileStream()); if (cmSystemTools::GetErrorOccuredFlag()) { this->RulesFileStream->setstate(std::ios::failbit); - this->BuildFileStream->setstate(std::ios::failbit); + for (auto const& config : this->Makefiles[0]->GetGeneratorConfigs()) { + this->GetConfigFileStream(config)->setstate(std::ios::failbit); + } + this->GetCommonFileStream()->setstate(std::ios::failbit); } this->CloseCompileCommandsStream(); this->CloseRulesFileStream(); - this->CloseBuildFileStream(); + this->CloseBuildFileStreams(); + + if (!this->WriteDefaultBuildFile()) { + return; + } } bool cmGlobalNinjaGenerator::FindMakeProgram(cmMakefile* mf) @@ -609,6 +632,17 @@ bool cmGlobalNinjaGenerator::CheckFortran(cmMakefile* mf) const void cmGlobalNinjaGenerator::EnableLanguage( std::vector<std::string> const& langs, cmMakefile* mf, bool optional) { + if (this->IsMultiConfig()) { + if (!mf->GetDefinition("CMAKE_CONFIGURATION_TYPES")) { + mf->AddCacheDefinition( + "CMAKE_CONFIGURATION_TYPES", "Debug;Release;MinSizeRel;RelWithDebInfo", + "Semicolon separated list of supported configuration types, only " + "supports Debug, Release, MinSizeRel, and RelWithDebInfo, anything " + "else will be ignored", + cmStateEnums::STRING); + } + } + this->cmGlobalGenerator::EnableLanguage(langs, mf, optional); for (std::string const& l : langs) { if (l == "NONE") { @@ -650,7 +684,7 @@ std::vector<cmGlobalGenerator::GeneratedMakeCommand> cmGlobalNinjaGenerator::GenerateBuildCommand( const std::string& makeProgram, const std::string& /*projectName*/, const std::string& /*projectDir*/, - std::vector<std::string> const& targetNames, const std::string& /*config*/, + std::vector<std::string> const& targetNames, const std::string& config, bool /*fast*/, int jobs, bool verbose, std::vector<std::string> const& makeOptions) { @@ -666,6 +700,9 @@ cmGlobalNinjaGenerator::GenerateBuildCommand( makeCommand.Add("-j", std::to_string(jobs)); } + this->AppendNinjaFileArgument(makeCommand, + config.empty() ? "Debug" : config); + makeCommand.Add(makeOptions.begin(), makeOptions.end()); for (const auto& tname : targetNames) { if (!tname.empty()) { @@ -707,44 +744,53 @@ void cmGlobalNinjaGenerator::ComputeTargetObjectDirectory( cmGeneratorTarget* gt) const { // Compute full path to object file directory for this target. - std::string dir = - cmStrCat(gt->LocalGenerator->GetCurrentBinaryDirectory(), '/', - gt->LocalGenerator->GetTargetDirectory(gt), '/'); + std::string dir = cmStrCat(gt->LocalGenerator->GetCurrentBinaryDirectory(), + '/', gt->LocalGenerator->GetTargetDirectory(gt), + '/', this->GetCMakeCFGIntDir(), '/'); gt->ObjectDirectory = dir; } // Private methods -bool cmGlobalNinjaGenerator::OpenBuildFileStream() +bool cmGlobalNinjaGenerator::OpenBuildFileStreams() { - // Compute Ninja's build file path. - std::string buildFilePath = - cmStrCat(this->GetCMakeInstance()->GetHomeOutputDirectory(), '/', - cmGlobalNinjaGenerator::NINJA_BUILD_FILE); + if (!this->OpenFileStream(this->BuildFileStream, + cmGlobalNinjaGenerator::NINJA_BUILD_FILE)) { + return false; + } + + // Write a comment about this file. + *this->BuildFileStream + << "# This file contains all the build statements describing the\n" + << "# compilation DAG.\n\n"; + + return true; +} +bool cmGlobalNinjaGenerator::OpenFileStream( + std::unique_ptr<cmGeneratedFileStream>& stream, const std::string& name) +{ // Get a stream where to generate things. - if (!this->BuildFileStream) { - this->BuildFileStream = cm::make_unique<cmGeneratedFileStream>( - buildFilePath, false, this->GetMakefileEncoding()); - if (!(*this->BuildFileStream)) { + if (!stream) { + // Compute Ninja's build file path. + std::string path = + cmStrCat(this->GetCMakeInstance()->GetHomeOutputDirectory(), '/', name); + stream = cm::make_unique<cmGeneratedFileStream>( + path, false, this->GetMakefileEncoding()); + if (!(*stream)) { // An error message is generated by the constructor if it cannot // open the file. return false; } - } - - // Write the do not edit header. - this->WriteDisclaimer(*this->BuildFileStream); - // Write a comment about this file. - *this->BuildFileStream - << "# This file contains all the build statements describing the\n" - << "# compilation DAG.\n\n"; + // Write the do not edit header. + this->WriteDisclaimer(*stream); + } return true; } -void cmGlobalNinjaGenerator::CloseBuildFileStream() +void cmGlobalNinjaGenerator::CloseBuildFileStreams() { if (this->BuildFileStream) { this->BuildFileStream.reset(); @@ -755,25 +801,11 @@ void cmGlobalNinjaGenerator::CloseBuildFileStream() bool cmGlobalNinjaGenerator::OpenRulesFileStream() { - // Compute Ninja's build file path. - std::string rulesFilePath = - cmStrCat(this->GetCMakeInstance()->GetHomeOutputDirectory(), '/', - cmGlobalNinjaGenerator::NINJA_RULES_FILE); - - // Get a stream where to generate things. - if (!this->RulesFileStream) { - this->RulesFileStream = cm::make_unique<cmGeneratedFileStream>( - rulesFilePath, false, this->GetMakefileEncoding()); - if (!(*this->RulesFileStream)) { - // An error message is generated by the constructor if it cannot - // open the file. - return false; - } + if (!this->OpenFileStream(this->RulesFileStream, + cmGlobalNinjaGenerator::NINJA_RULES_FILE)) { + return false; } - // Write the do not edit header. - this->WriteDisclaimer(*this->RulesFileStream); - // Write comment about this file. /* clang-format off */ *this->RulesFileStream @@ -819,10 +851,10 @@ std::string const& cmGlobalNinjaGenerator::ConvertToNinjaPath( return f->second; } - cmLocalNinjaGenerator* ng = - static_cast<cmLocalNinjaGenerator*>(this->LocalGenerators[0]); - std::string const& bin_dir = ng->GetState()->GetBinaryDirectory(); - std::string convPath = ng->MaybeConvertToRelativePath(bin_dir, path); + const auto& ng = + cm::static_reference_cast<cmLocalNinjaGenerator>(this->LocalGenerators[0]); + std::string const& bin_dir = ng.GetState()->GetBinaryDirectory(); + std::string convPath = ng.MaybeConvertToRelativePath(bin_dir, path); convPath = this->NinjaOutputPath(convPath); #ifdef _WIN32 std::replace(convPath.begin(), convPath.end(), '/', '\\'); @@ -831,9 +863,10 @@ std::string const& cmGlobalNinjaGenerator::ConvertToNinjaPath( .first->second; } -void cmGlobalNinjaGenerator::AddAdditionalCleanFile(std::string fileName) +void cmGlobalNinjaGenerator::AddAdditionalCleanFile(std::string fileName, + const std::string& config) { - this->AdditionalCleanFiles.emplace(std::move(fileName)); + this->Configs[config].AdditionalCleanFiles.emplace(std::move(fileName)); } void cmGlobalNinjaGenerator::AddCXXCompileCommand( @@ -901,23 +934,22 @@ void cmGlobalNinjaGenerator::WriteAssumedSourceDependencies() "Assume dependencies for generated source file.", /*depfile*/ "", /*job_pool*/ "", /*uses_terminal*/ false, - /*restat*/ true, cmNinjaDeps(1, asd.first), + /*restat*/ true, cmNinjaDeps(1, asd.first), "", cmNinjaDeps(), orderOnlyDeps); } } -std::string OrderDependsTargetForTarget(cmGeneratorTarget const* target) +std::string cmGlobalNinjaGenerator::OrderDependsTargetForTarget( + cmGeneratorTarget const* target, const std::string& config) { - return "cmake_object_order_depends_target_" + target->GetName(); + return "cmake_object_order_depends_target_" + target->GetName() + "_" + + config; } void cmGlobalNinjaGenerator::AppendTargetOutputs( cmGeneratorTarget const* target, cmNinjaDeps& outputs, - cmNinjaTargetDepends depends) + const std::string& config, cmNinjaTargetDepends depends) { - std::string configName = - target->Target->GetMakefile()->GetSafeDefinition("CMAKE_BUILD_TYPE"); - // for frameworks, we want the real name, not smple name // frameworks always appear versioned, and the build.ninja // will always attempt to manage symbolic links instead @@ -929,19 +961,19 @@ void cmGlobalNinjaGenerator::AppendTargetOutputs( case cmStateEnums::STATIC_LIBRARY: case cmStateEnums::MODULE_LIBRARY: { if (depends == DependOnTargetOrdering) { - outputs.push_back(OrderDependsTargetForTarget(target)); + outputs.push_back(OrderDependsTargetForTarget(target, config)); break; } } // FALLTHROUGH case cmStateEnums::EXECUTABLE: { outputs.push_back(this->ConvertToNinjaPath(target->GetFullPath( - configName, cmStateEnums::RuntimeBinaryArtifact, realname))); + config, cmStateEnums::RuntimeBinaryArtifact, realname))); break; } case cmStateEnums::OBJECT_LIBRARY: { if (depends == DependOnTargetOrdering) { - outputs.push_back(OrderDependsTargetForTarget(target)); + outputs.push_back(OrderDependsTargetForTarget(target, config)); break; } } @@ -951,7 +983,11 @@ void cmGlobalNinjaGenerator::AppendTargetOutputs( std::string path = target->GetLocalGenerator()->GetCurrentBinaryDirectory() + std::string("/") + target->GetName(); - outputs.push_back(this->ConvertToNinjaPath(path)); + std::string output = this->ConvertToNinjaPath(path); + if (target->Target->IsPerConfig()) { + output = this->BuildAlias(output, config); + } + outputs.push_back(output); break; } @@ -962,6 +998,7 @@ void cmGlobalNinjaGenerator::AppendTargetOutputs( void cmGlobalNinjaGenerator::AppendTargetDepends( cmGeneratorTarget const* target, cmNinjaDeps& outputs, + const std::string& config, const std::string& fileConfig, cmNinjaTargetDepends depends) { if (target->GetType() == cmStateEnums::GLOBAL_TARGET) { @@ -970,7 +1007,7 @@ void cmGlobalNinjaGenerator::AppendTargetDepends( std::string d = target->GetLocalGenerator()->GetCurrentBinaryDirectory() + "/" + util.Value; - outputs.push_back(this->ConvertToNinjaPath(d)); + outputs.push_back(this->BuildAlias(this->ConvertToNinjaPath(d), config)); } } else { cmNinjaDeps outs; @@ -979,29 +1016,39 @@ void cmGlobalNinjaGenerator::AppendTargetDepends( if (targetDep->GetType() == cmStateEnums::INTERFACE_LIBRARY) { continue; } - this->AppendTargetOutputs(targetDep, outs, depends); + // For some reason, object libraries show up as "utility" dependencies + // even though they're used for linking. Treat them as link dependencies. + if (targetDep.IsUtil() && + targetDep->GetType() != cmStateEnums::OBJECT_LIBRARY) { + this->AppendTargetOutputs(targetDep, outs, fileConfig, depends); + } else { + this->AppendTargetOutputs(targetDep, outs, config, depends); + } } std::sort(outs.begin(), outs.end()); - cmAppend(outputs, outs); + cm::append(outputs, outs); } } void cmGlobalNinjaGenerator::AppendTargetDependsClosure( - cmGeneratorTarget const* target, cmNinjaDeps& outputs) + cmGeneratorTarget const* target, cmNinjaDeps& outputs, + const std::string& config) { cmNinjaOuts outs; - this->AppendTargetDependsClosure(target, outs, true); - cmAppend(outputs, outs); + this->AppendTargetDependsClosure(target, outs, config, true); + cm::append(outputs, outs); } void cmGlobalNinjaGenerator::AppendTargetDependsClosure( - cmGeneratorTarget const* target, cmNinjaOuts& outputs, bool omit_self) + cmGeneratorTarget const* target, cmNinjaOuts& outputs, + const std::string& config, bool omit_self) { // try to locate the target in the cache - auto find = this->TargetDependsClosures.lower_bound(target); + auto find = this->Configs[config].TargetDependsClosures.lower_bound(target); - if (find == this->TargetDependsClosures.end() || find->first != target) { + if (find == this->Configs[config].TargetDependsClosures.end() || + find->first != target) { // We now calculate the closure outputs by inspecting the dependent // targets recursively. // For that we have to distinguish between a local result set that is only @@ -1016,10 +1063,10 @@ void cmGlobalNinjaGenerator::AppendTargetDependsClosure( } // Collect the dependent targets for _this_ target - this->AppendTargetDependsClosure(dep_target, this_outs, false); + this->AppendTargetDependsClosure(dep_target, this_outs, config, false); } - find = this->TargetDependsClosures.emplace_hint(find, target, - std::move(this_outs)); + find = this->Configs[config].TargetDependsClosures.emplace_hint( + find, target, std::move(this_outs)); } // now fill the outputs of the final result from the newly generated cache @@ -1029,29 +1076,48 @@ void cmGlobalNinjaGenerator::AppendTargetDependsClosure( // finally generate the outputs of the target itself, if applicable cmNinjaDeps outs; if (!omit_self) { - this->AppendTargetOutputs(target, outs); + this->AppendTargetOutputs(target, outs, config); } outputs.insert(outs.begin(), outs.end()); } void cmGlobalNinjaGenerator::AddTargetAlias(const std::string& alias, - cmGeneratorTarget* target) + cmGeneratorTarget* target, + const std::string& config) { - std::string buildAlias = this->NinjaOutputPath(alias); + std::string outputPath = this->NinjaOutputPath(alias); + std::string buildAlias = this->BuildAlias(outputPath, config); cmNinjaDeps outputs; - this->AppendTargetOutputs(target, outputs); - // Mark the target's outputs as ambiguous to ensure that no other target uses - // the output as an alias. + this->AppendTargetOutputs(target, outputs, config); + // Mark the target's outputs as ambiguous to ensure that no other target + // uses the output as an alias. for (std::string const& output : outputs) { - TargetAliases[output] = nullptr; + this->TargetAliases[output].GeneratorTarget = nullptr; + for (const std::string& config2 : + this->Makefiles.front()->GetGeneratorConfigs()) { + this->Configs[config2].TargetAliases[output].GeneratorTarget = nullptr; + } } // Insert the alias into the map. If the alias was already present in the // map and referred to another target, mark it as ambiguous. - std::pair<TargetAliasMap::iterator, bool> newAlias = - TargetAliases.insert(std::make_pair(buildAlias, target)); - if (newAlias.second && newAlias.first->second != target) { - newAlias.first->second = nullptr; + TargetAlias ta; + ta.GeneratorTarget = target; + ta.Config = config; + std::pair<TargetAliasMap::iterator, bool> newAliasGlobal = + this->TargetAliases.insert(std::make_pair(buildAlias, ta)); + if (newAliasGlobal.second && + newAliasGlobal.first->second.GeneratorTarget != target) { + newAliasGlobal.first->second.GeneratorTarget = nullptr; + } + if (config != "all") { + std::pair<TargetAliasMap::iterator, bool> newAliasConfig = + this->Configs[config].TargetAliases.insert( + std::make_pair(outputPath, ta)); + if (newAliasConfig.second && + newAliasConfig.first->second.GeneratorTarget != target) { + newAliasConfig.first->second.GeneratorTarget = nullptr; + } } } @@ -1061,10 +1127,10 @@ void cmGlobalNinjaGenerator::WriteTargetAliases(std::ostream& os) os << "# Target aliases.\n\n"; cmNinjaBuild build("phony"); - build.Outputs.emplace_back(""); - for (auto const& ta : TargetAliases) { + build.Outputs.emplace_back(); + for (auto const& ta : this->TargetAliases) { // Don't write ambiguous aliases. - if (!ta.second) { + if (!ta.second.GeneratorTarget) { continue; } @@ -1074,14 +1140,43 @@ void cmGlobalNinjaGenerator::WriteTargetAliases(std::ostream& os) continue; } - // Outputs - build.Outputs[0] = ta.first; - // Explicit depdendencies + build.Outputs.front() = ta.first; build.ExplicitDeps.clear(); - this->AppendTargetOutputs(ta.second, build.ExplicitDeps); - // Write + if (ta.second.Config == "all") { + for (auto const& config : + ta.second.GeneratorTarget->Makefile->GetGeneratorConfigs()) { + this->AppendTargetOutputs(ta.second.GeneratorTarget, + build.ExplicitDeps, config); + } + } else { + this->AppendTargetOutputs(ta.second.GeneratorTarget, build.ExplicitDeps, + ta.second.Config); + } this->WriteBuild(os, build); } + + if (this->IsMultiConfig()) { + for (auto const& config : this->Makefiles.front()->GetGeneratorConfigs()) { + for (auto const& ta : this->Configs[config].TargetAliases) { + // Don't write ambiguous aliases. + if (!ta.second.GeneratorTarget) { + continue; + } + + // Don't write alias if there is a already a custom command with + // matching output + if (this->HasCustomCommandOutput(ta.first)) { + continue; + } + + build.Outputs.front() = ta.first; + build.ExplicitDeps.clear(); + this->AppendTargetOutputs(ta.second.GeneratorTarget, + build.ExplicitDeps, config); + this->WriteBuild(*this->GetConfigFileStream(config), build); + } + } + } } void cmGlobalNinjaGenerator::WriteFolderTargets(std::ostream& os) @@ -1097,24 +1192,58 @@ void cmGlobalNinjaGenerator::WriteFolderTargets(std::ostream& os) cmGlobalNinjaGenerator::WriteDivider(os); std::string const& currentBinaryDir = it.first; DirectoryTarget const& dt = it.second; + std::vector<std::string> configs; + dt.LG->GetMakefile()->GetConfigurations(configs, true); + if (configs.empty()) { + configs.emplace_back(); + } // Setup target + cmNinjaDeps configDeps; build.Comment = "Folder: " + currentBinaryDir; - build.Outputs.emplace_back( - this->ConvertToNinjaPath(currentBinaryDir + "/all")); - for (DirectoryTarget::Target const& t : dt.Targets) { - if (!t.ExcludeFromAll) { - this->AppendTargetOutputs(t.GT, build.ExplicitDeps); + build.Outputs.emplace_back(); + for (auto const& config : configs) { + build.ExplicitDeps.clear(); + build.Outputs.front() = this->BuildAlias( + this->ConvertToNinjaPath(currentBinaryDir + "/all"), config); + configDeps.emplace_back(build.Outputs.front()); + for (DirectoryTarget::Target const& t : dt.Targets) { + if (!t.ExcludeFromAll) { + this->AppendTargetOutputs(t.GT, build.ExplicitDeps, config); + } } + for (DirectoryTarget::Dir const& d : dt.Children) { + if (!d.ExcludeFromAll) { + build.ExplicitDeps.emplace_back(this->BuildAlias( + this->ConvertToNinjaPath(d.Path + "/all"), config)); + } + } + // Write target + this->WriteBuild(os, build); } - for (DirectoryTarget::Dir const& d : dt.Children) { - if (!d.ExcludeFromAll) { - build.ExplicitDeps.emplace_back( - this->ConvertToNinjaPath(d.Path + "/all")); + + // Add shortcut target + if (this->IsMultiConfig()) { + for (auto const& config : configs) { + build.ExplicitDeps = { this->BuildAlias( + this->ConvertToNinjaPath(currentBinaryDir + "/all"), config) }; + build.Outputs.front() = + this->ConvertToNinjaPath(currentBinaryDir + "/all"); + this->WriteBuild(*this->GetConfigFileStream(config), build); } } - // Write target - this->WriteBuild(os, build); + + // Add target for all configs + if (this->IsMultiConfig()) { + build.ExplicitDeps.clear(); + for (auto const& config : configs) { + build.ExplicitDeps.push_back(this->BuildAlias( + this->ConvertToNinjaPath(currentBinaryDir + "/all"), config)); + } + build.Outputs.front() = this->BuildAlias( + this->ConvertToNinjaPath(currentBinaryDir + "/all"), "all"); + this->WriteBuild(*this->GetCommonFileStream(), build); + } } } @@ -1148,7 +1277,7 @@ void cmGlobalNinjaGenerator::WriteUnknownExplicitDependencies(std::ostream& os) // get the list of files that cmake itself has generated as a // product of configuration. - for (cmLocalGenerator* lg : this->LocalGenerators) { + for (const auto& lg : this->LocalGenerators) { // get the vector of files created by this makefile and convert them // to ninja paths, which are all relative in respect to the build directory for (std::string const& file : lg->GetMakefile()->GetOutputFiles()) { @@ -1247,10 +1376,13 @@ void cmGlobalNinjaGenerator::WriteBuiltinTargets(std::ostream& os) cmGlobalNinjaGenerator::WriteDivider(os); os << "# Built-in targets\n\n"; - this->WriteTargetDefault(os); this->WriteTargetRebuildManifest(os); this->WriteTargetClean(os); this->WriteTargetHelp(os); + + for (auto const& config : this->Makefiles[0]->GetGeneratorConfigs()) { + this->WriteTargetDefault(*this->GetConfigFileStream(config)); + } } void cmGlobalNinjaGenerator::WriteTargetDefault(std::ostream& os) @@ -1268,7 +1400,7 @@ void cmGlobalNinjaGenerator::WriteTargetRebuildManifest(std::ostream& os) if (this->GlobalSettingIsOn("CMAKE_SUPPRESS_REGENERATION")) { return; } - cmLocalGenerator* lg = this->LocalGenerators[0]; + const auto& lg = this->LocalGenerators[0]; { cmNinjaRule rule("RERUN_CMAKE"); @@ -1287,9 +1419,9 @@ void cmGlobalNinjaGenerator::WriteTargetRebuildManifest(std::ostream& os) cmNinjaBuild reBuild("RERUN_CMAKE"); reBuild.Comment = "Re-run CMake if any of its inputs changed."; - reBuild.Outputs.push_back(this->NinjaOutputPath(NINJA_BUILD_FILE)); + this->AddRebuildManifestOutputs(reBuild.Outputs); - for (cmLocalGenerator* localGen : this->LocalGenerators) { + for (const auto& localGen : this->LocalGenerators) { for (std::string const& fi : localGen->GetMakefile()->GetListFiles()) { reBuild.ImplicitDeps.push_back(this->ConvertToNinjaPath(fi)); } @@ -1376,14 +1508,14 @@ void cmGlobalNinjaGenerator::WriteTargetRebuildManifest(std::ostream& os) std::string cmGlobalNinjaGenerator::CMakeCmd() const { - cmLocalGenerator* lgen = this->LocalGenerators.at(0); + const auto& lgen = this->LocalGenerators.at(0); return lgen->ConvertToOutputFormat(cmSystemTools::GetCMakeCommand(), cmOutputConverter::SHELL); } std::string cmGlobalNinjaGenerator::NinjaCmd() const { - cmLocalGenerator* lgen = this->LocalGenerators[0]; + const auto& lgen = this->LocalGenerators[0]; if (lgen != nullptr) { return lgen->ConvertToOutputFormat(this->NinjaCommand, cmOutputConverter::SHELL); @@ -1413,13 +1545,27 @@ bool cmGlobalNinjaGenerator::SupportsMultilineDepfile() const bool cmGlobalNinjaGenerator::WriteTargetCleanAdditional(std::ostream& os) { - cmLocalGenerator* lgr = this->LocalGenerators.at(0); + const auto& lgr = this->LocalGenerators.at(0); std::string cleanScriptRel = "CMakeFiles/clean_additional.cmake"; std::string cleanScriptAbs = cmStrCat(lgr->GetBinaryDirectory(), '/', cleanScriptRel); + std::vector<std::string> configs; + this->Makefiles[0]->GetConfigurations(configs, true); + if (configs.empty()) { + configs.emplace_back(); + } // Check if there are additional files to clean - if (this->AdditionalCleanFiles.empty()) { + bool empty = true; + for (auto const& config : configs) { + auto const it = this->Configs.find(config); + if (it != this->Configs.end() && + !it->second.AdditionalCleanFiles.empty()) { + empty = false; + break; + } + } + if (empty) { // Remove cmake clean script file if it exists cmSystemTools::RemoveFile(cleanScriptAbs); return false; @@ -1431,14 +1577,23 @@ bool cmGlobalNinjaGenerator::WriteTargetCleanAdditional(std::ostream& os) if (!fout) { return false; } - fout << "# Additional clean files\n\n"; - fout << "file(REMOVE_RECURSE\n"; - for (std::string const& acf : this->AdditionalCleanFiles) { - fout << " " - << cmOutputConverter::EscapeForCMake(ConvertToNinjaPath(acf)) - << '\n'; + fout << "# Additional clean files\ncmake_minimum_required(VERSION 3.16)\n"; + for (auto const& config : configs) { + auto const it = this->Configs.find(config); + if (it != this->Configs.end() && + !it->second.AdditionalCleanFiles.empty()) { + fout << "\nif(\"${CONFIG}\" STREQUAL \"\" OR \"${CONFIG}\" STREQUAL \"" + << config << "\")\n"; + fout << " file(REMOVE_RECURSE\n"; + for (std::string const& acf : it->second.AdditionalCleanFiles) { + fout << " " + << cmOutputConverter::EscapeForCMake(ConvertToNinjaPath(acf)) + << '\n'; + } + fout << " )\n"; + fout << "endif()\n"; + } } - fout << ")\n"; } // Register clean script file lgr->GetMakefile()->AddCMakeOutputFile(cleanScriptAbs); @@ -1447,7 +1602,7 @@ bool cmGlobalNinjaGenerator::WriteTargetCleanAdditional(std::ostream& os) { cmNinjaRule rule("CLEAN_ADDITIONAL"); rule.Command = cmStrCat( - CMakeCmd(), " -P ", + CMakeCmd(), " -DCONFIG=$CONFIG -P ", lgr->ConvertToOutputFormat(this->NinjaOutputPath(cleanScriptRel), cmOutputConverter::SHELL)); rule.Description = "Cleaning additional files..."; @@ -1459,9 +1614,19 @@ bool cmGlobalNinjaGenerator::WriteTargetCleanAdditional(std::ostream& os) { cmNinjaBuild build("CLEAN_ADDITIONAL"); build.Comment = "Clean additional files."; - build.Outputs.push_back( - this->NinjaOutputPath(this->GetAdditionalCleanTargetName())); - WriteBuild(os, build); + build.Outputs.emplace_back(); + for (auto const& config : configs) { + build.Outputs.front() = this->BuildAlias( + this->NinjaOutputPath(this->GetAdditionalCleanTargetName()), config); + build.Variables["CONFIG"] = config; + WriteBuild(os, build); + } + if (this->IsMultiConfig()) { + build.Outputs.front() = + this->NinjaOutputPath(this->GetAdditionalCleanTargetName()); + build.Variables["CONFIG"] = ""; + WriteBuild(os, build); + } } // Return success return true; @@ -1476,22 +1641,91 @@ void cmGlobalNinjaGenerator::WriteTargetClean(std::ostream& os) // Write rule { cmNinjaRule rule("CLEAN"); - rule.Command = NinjaCmd() + " -t clean"; + rule.Command = NinjaCmd() + " $FILE_ARG -t clean $TARGETS"; rule.Description = "Cleaning all built files..."; rule.Comment = "Rule for cleaning all built files."; WriteRule(*this->RulesFileStream, rule); } + auto const configs = this->Makefiles.front()->GetGeneratorConfigs(); + // Write build { cmNinjaBuild build("CLEAN"); build.Comment = "Clean all the built files."; - build.Outputs.push_back(this->NinjaOutputPath(this->GetCleanTargetName())); - if (additionalFiles) { - build.ExplicitDeps.push_back( - this->NinjaOutputPath(this->GetAdditionalCleanTargetName())); + build.Outputs.emplace_back(); + + for (auto const& config : configs) { + build.Outputs.front() = this->BuildAlias( + this->NinjaOutputPath(this->GetCleanTargetName()), config); + if (this->IsMultiConfig()) { + build.Variables["TARGETS"] = + cmStrCat(this->BuildAlias(GetByproductsForCleanTargetName(), config), + " ", GetByproductsForCleanTargetName()); + } + build.ExplicitDeps.clear(); + if (additionalFiles) { + build.ExplicitDeps.push_back(this->BuildAlias( + this->NinjaOutputPath(this->GetAdditionalCleanTargetName()), + config)); + } + for (auto const& fileConfig : configs) { + if (this->IsMultiConfig()) { + build.Variables["FILE_ARG"] = cmStrCat( + "-f ", cmGlobalNinjaMultiGenerator::GetNinjaFilename(fileConfig)); + } + this->WriteBuild(*this->GetConfigFileStream(fileConfig), build); + } } + + if (this->IsMultiConfig()) { + build.Outputs.front() = this->BuildAlias( + this->NinjaOutputPath(this->GetCleanTargetName()), "all"); + build.ExplicitDeps.clear(); + + if (additionalFiles) { + build.ExplicitDeps.push_back( + this->NinjaOutputPath(this->GetAdditionalCleanTargetName())); + } + + build.Variables["TARGETS"] = ""; + + for (auto const& fileConfig : configs) { + build.Variables["FILE_ARG"] = cmStrCat( + "-f ", cmGlobalNinjaMultiGenerator::GetNinjaFilename(fileConfig)); + this->WriteBuild(*this->GetConfigFileStream(fileConfig), build); + } + } + } + + if (this->IsMultiConfig()) { + cmNinjaBuild build("phony"); + build.Outputs.emplace_back( + this->NinjaOutputPath(this->GetCleanTargetName())); + build.ExplicitDeps.emplace_back(); + + for (auto const& config : configs) { + build.ExplicitDeps.front() = this->BuildAlias( + this->NinjaOutputPath(this->GetCleanTargetName()), config); + this->WriteBuild(*this->GetConfigFileStream(config), build); + } + } + + // Write byproducts + if (this->IsMultiConfig()) { + cmNinjaBuild build("phony"); + build.Comment = "Clean byproducts."; + build.Outputs.emplace_back( + this->ConvertToNinjaPath(GetByproductsForCleanTargetName())); + build.ExplicitDeps = this->ByproductsForCleanTarget; WriteBuild(os, build); + + for (auto const& config : configs) { + build.Outputs.front() = this->BuildAlias( + this->ConvertToNinjaPath(GetByproductsForCleanTargetName()), config); + build.ExplicitDeps = this->Configs[config].ByproductsForCleanTarget; + WriteBuild(os, build); + } } } @@ -1809,11 +2043,9 @@ bool cmGlobalNinjaGenerator::WriteDyndepFile( snapshot.GetDirectory().SetRelativePathTopSource(dir_top_src.c_str()); snapshot.GetDirectory().SetRelativePathTopBinary(dir_top_bld.c_str()); auto mfd = cm::make_unique<cmMakefile>(this, snapshot); - std::unique_ptr<cmLocalNinjaGenerator> lgd( - static_cast<cmLocalNinjaGenerator*>( - this->CreateLocalGenerator(mfd.get()))); + auto lgd = this->CreateLocalGenerator(mfd.get()); this->Makefiles.push_back(mfd.release()); - this->LocalGenerators.push_back(lgd.release()); + this->LocalGenerators.push_back(std::move(lgd)); } std::vector<cmDyndepObjectInfo> objects; @@ -2000,3 +2232,137 @@ int cmcmd_cmake_ninja_dyndep(std::vector<std::string>::const_iterator argBeg, } return 0; } + +void cmGlobalNinjaGenerator::AppendDirectoryForConfig( + const std::string& prefix, const std::string& config, + const std::string& suffix, std::string& dir) +{ + if (!config.empty() && this->IsMultiConfig()) { + dir += prefix; + dir += config; + dir += suffix; + } +} + +const char* cmGlobalNinjaMultiGenerator::NINJA_COMMON_FILE = "common.ninja"; +const char* cmGlobalNinjaMultiGenerator::NINJA_FILE_EXTENSION = ".ninja"; + +cmGlobalNinjaMultiGenerator::cmGlobalNinjaMultiGenerator(cmake* cm) + : cmGlobalNinjaGenerator(cm) +{ + cm->GetState()->SetIsGeneratorMultiConfig(true); + cm->GetState()->SetNinjaMulti(true); +} + +void cmGlobalNinjaMultiGenerator::GetDocumentation(cmDocumentationEntry& entry) +{ + entry.Name = cmGlobalNinjaMultiGenerator::GetActualName(); + entry.Brief = "Generates build-<Config>.ninja files."; +} + +std::string cmGlobalNinjaMultiGenerator::ExpandCFGIntDir( + const std::string& str, const std::string& config) const +{ + std::string result = str; + cmSystemTools::ReplaceString(result, this->GetCMakeCFGIntDir(), config); + return result; +} + +bool cmGlobalNinjaMultiGenerator::OpenBuildFileStreams() +{ + if (!this->OpenFileStream(this->CommonFileStream, + cmGlobalNinjaMultiGenerator::NINJA_COMMON_FILE)) { + return false; + } + + // Write a comment about this file. + *this->CommonFileStream + << "# This file contains build statements common to all " + "configurations.\n\n"; + + for (auto const& config : this->Makefiles[0]->GetGeneratorConfigs()) { + if (!this->OpenFileStream(this->ConfigFileStreams[config], + GetNinjaFilename(config))) { + return false; + } + + // Write a comment about this file. + *this->ConfigFileStreams[config] + << "# This file contains build statements specific to the \"" << config + << "\"\n# configuration.\n\n"; + } + + return true; +} + +void cmGlobalNinjaMultiGenerator::CloseBuildFileStreams() +{ + if (this->CommonFileStream) { + this->CommonFileStream.reset(); + } else { + cmSystemTools::Error("Common file stream was not open."); + } + + for (auto const& config : this->Makefiles[0]->GetGeneratorConfigs()) { + if (this->ConfigFileStreams[config]) { + this->ConfigFileStreams[config].reset(); + } else { + cmSystemTools::Error( + cmStrCat("Config file stream for \"", config, "\" was not open.")); + } + } +} + +void cmGlobalNinjaMultiGenerator::AppendNinjaFileArgument( + GeneratedMakeCommand& command, const std::string& config) const +{ + command.Add("-f"); + command.Add(GetNinjaFilename(config)); +} + +std::string cmGlobalNinjaMultiGenerator::GetNinjaFilename( + const std::string& config) +{ + return cmStrCat("build-", config, + cmGlobalNinjaMultiGenerator::NINJA_FILE_EXTENSION); +} + +void cmGlobalNinjaMultiGenerator::AddRebuildManifestOutputs( + cmNinjaDeps& outputs) const +{ + for (auto const& config : this->Makefiles.front()->GetGeneratorConfigs()) { + outputs.push_back(this->NinjaOutputPath(GetNinjaFilename(config))); + } + if (this->Makefiles.front()->GetDefinition( + "CMAKE_NINJA_MULTI_DEFAULT_BUILD_TYPE")) { + outputs.push_back(this->NinjaOutputPath(NINJA_BUILD_FILE)); + } +} + +void cmGlobalNinjaMultiGenerator::GetQtAutoGenConfigs( + std::vector<std::string>& configs) const +{ + auto const oldSize = configs.size(); + this->Makefiles.front()->GetConfigurations(configs); + if (configs.size() == oldSize) { + configs.emplace_back(); + } +} + +bool cmGlobalNinjaMultiGenerator::WriteDefaultBuildFile() +{ + auto const* defaultConfig = this->Makefiles.front()->GetDefinition( + "CMAKE_NINJA_MULTI_DEFAULT_BUILD_TYPE"); + if (defaultConfig) { + std::unique_ptr<cmGeneratedFileStream> defaultStream; + if (!this->OpenFileStream(defaultStream, NINJA_BUILD_FILE)) { + return false; + } + *defaultStream << "# This file is a convenience file generated by\n" + << "# CMAKE_NINJA_MULTI_DEFAULT_BUILD_TYPE.\n\n" + << "include " << this->GetNinjaFilename(defaultConfig) + << "\n"; + } + + return true; +} diff --git a/Source/cmGlobalNinjaGenerator.h b/Source/cmGlobalNinjaGenerator.h index 244e9fd..6ebb31d 100644 --- a/Source/cmGlobalNinjaGenerator.h +++ b/Source/cmGlobalNinjaGenerator.h @@ -22,6 +22,7 @@ #include "cmGlobalGeneratorFactory.h" #include "cmNinjaTypes.h" #include "cmPolicies.h" +#include "cmStringAlgorithms.h" class cmCustomCommand; class cmGeneratorTarget; @@ -73,7 +74,7 @@ public: static void WriteDivider(std::ostream& os); static std::string EncodeRuleName(std::string const& name); - static std::string EncodeLiteral(const std::string& lit); + std::string EncodeLiteral(const std::string& lit); std::string EncodePath(const std::string& path); cmLinkLineComputer* CreateLinkLineComputer( @@ -111,11 +112,12 @@ public: const std::string& command, const std::string& description, const std::string& comment, const std::string& depfile, const std::string& pool, bool uses_terminal, bool restat, - const cmNinjaDeps& outputs, + const cmNinjaDeps& outputs, const std::string& config, const cmNinjaDeps& explicitDeps = cmNinjaDeps(), const cmNinjaDeps& orderOnlyDeps = cmNinjaDeps()); - void WriteMacOSXContentBuild(std::string input, std::string output); + void WriteMacOSXContentBuild(std::string input, std::string output, + const std::string& config); /** * Write a rule statement to @a os. @@ -156,7 +158,8 @@ public: return new cmGlobalGeneratorSimpleFactory<cmGlobalNinjaGenerator>(); } - cmLocalGenerator* CreateLocalGenerator(cmMakefile* mf) override; + std::unique_ptr<cmLocalGenerator> CreateLocalGenerator( + cmMakefile* mf) override; std::string GetName() const override { @@ -204,7 +207,13 @@ public: } const char* GetCleanTargetName() const override { return "clean"; } - cmGeneratedFileStream* GetBuildFileStream() const + virtual cmGeneratedFileStream* GetConfigFileStream( + const std::string& /*config*/) const + { + return this->BuildFileStream.get(); + } + + virtual cmGeneratedFileStream* GetCommonFileStream() const { return this->BuildFileStream.get(); } @@ -231,12 +240,17 @@ public: MapToNinjaPathImpl MapToNinjaPath() { return { this }; } // -- Additional clean files - void AddAdditionalCleanFile(std::string fileName); + void AddAdditionalCleanFile(std::string fileName, const std::string& config); const char* GetAdditionalCleanTargetName() const { return "CMakeFiles/clean.additional"; } + static const char* GetByproductsForCleanTargetName() + { + return "CMakeFiles/cmake_byproducts_for_clean_target"; + } + void AddCXXCompileCommand(const std::string& commandLine, const std::string& sourceFile); @@ -260,9 +274,9 @@ public: /// Called when we have seen the given custom command. Returns true /// if we has seen it before. - bool SeenCustomCommand(cmCustomCommand const* cc) + bool SeenCustomCommand(cmCustomCommand const* cc, const std::string& config) { - return !this->CustomCommands.insert(cc).second; + return !this->Configs[config].CustomCommands.insert(cc).second; } /// Called when we have seen the given custom command output. @@ -284,25 +298,43 @@ public: ASD.insert(deps.begin(), deps.end()); } + static std::string OrderDependsTargetForTarget( + cmGeneratorTarget const* target, const std::string& config); + void AppendTargetOutputs( cmGeneratorTarget const* target, cmNinjaDeps& outputs, + const std::string& config, cmNinjaTargetDepends depends = DependOnTargetArtifact); void AppendTargetDepends( cmGeneratorTarget const* target, cmNinjaDeps& outputs, + const std::string& config, const std::string& fileConfig, cmNinjaTargetDepends depends = DependOnTargetArtifact); void AppendTargetDependsClosure(cmGeneratorTarget const* target, - cmNinjaDeps& outputs); + cmNinjaDeps& outputs, + const std::string& config); void AppendTargetDependsClosure(cmGeneratorTarget const* target, - cmNinjaOuts& outputs, bool omit_self); + cmNinjaOuts& outputs, + const std::string& config, bool omit_self); + + void AppendDirectoryForConfig(const std::string& prefix, + const std::string& config, + const std::string& suffix, + std::string& dir) override; + + virtual void AppendNinjaFileArgument(GeneratedMakeCommand& /*command*/, + const std::string& /*config*/) const + { + } - const std::vector<cmLocalGenerator*>& GetLocalGenerators() const + virtual void AddRebuildManifestOutputs(cmNinjaDeps& outputs) const { - return LocalGenerators; + outputs.push_back(this->NinjaOutputPath(NINJA_BUILD_FILE)); } int GetRuleCmdLength(const std::string& name) { return RuleCmdLength[name]; } - void AddTargetAlias(const std::string& alias, cmGeneratorTarget* target); + void AddTargetAlias(const std::string& alias, cmGeneratorTarget* target, + const std::string& config); void ComputeTargetObjectDirectory(cmGeneratorTarget* gt) const override; @@ -335,11 +367,39 @@ public: std::vector<std::string> const& linked_target_dirs, std::string const& arg_lang); + virtual std::string BuildAlias(const std::string& alias, + const std::string& /*config*/) const + { + return alias; + } + + virtual std::string ConfigDirectory(const std::string& /*config*/) const + { + return ""; + } + + cmNinjaDeps& GetByproductsForCleanTarget() + { + return this->ByproductsForCleanTarget; + } + + cmNinjaDeps& GetByproductsForCleanTarget(const std::string& config) + { + return this->Configs[config].ByproductsForCleanTarget; + } + protected: void Generate() override; bool CheckALLOW_DUPLICATE_CUSTOM_TARGETS() const override { return true; } + virtual bool OpenBuildFileStreams(); + virtual void CloseBuildFileStreams(); + virtual bool WriteDefaultBuildFile() { return true; } + + bool OpenFileStream(std::unique_ptr<cmGeneratedFileStream>& stream, + const std::string& name); + private: std::string GetEditCacheCommand() const override; bool FindMakeProgram(cmMakefile* mf) override; @@ -348,9 +408,6 @@ private: cmMakefile* mf) const override; bool CheckFortran(cmMakefile* mf) const; - bool OpenBuildFileStream(); - void CloseBuildFileStream(); - void CloseCompileCommandsStream(); bool OpenRulesFileStream(); @@ -395,9 +452,6 @@ private: bool UsingGCCOnWindows = false; - /// The set of custom commands we have seen. - std::set<cmCustomCommand const*> CustomCommands; - /// The set of custom command outputs we have seen. std::set<std::string> CustomCommandOutputs; @@ -416,11 +470,14 @@ private: /// The mapping from source file to assumed dependencies. std::map<std::string, std::set<std::string>> AssumedSourceDependencies; - using TargetAliasMap = std::map<std::string, cmGeneratorTarget*>; + struct TargetAlias + { + cmGeneratorTarget* GeneratorTarget; + std::string Config; + }; + using TargetAliasMap = std::map<std::string, TargetAlias>; TargetAliasMap TargetAliases; - std::map<cmGeneratorTarget const*, cmNinjaOuts> TargetDependsClosures; - /// the local cache for calls to ConvertToNinjaPath mutable std::unordered_map<std::string, std::string> ConvertToNinjaPathCache; @@ -438,7 +495,101 @@ private: std::string OutputPathPrefix; std::string TargetAll; std::string CMakeCacheFile; - std::set<std::string> AdditionalCleanFiles; + + struct ByConfig + { + std::set<std::string> AdditionalCleanFiles; + + /// The set of custom commands we have seen. + std::set<cmCustomCommand const*> CustomCommands; + + std::map<cmGeneratorTarget const*, cmNinjaOuts> TargetDependsClosures; + + TargetAliasMap TargetAliases; + + cmNinjaDeps ByproductsForCleanTarget; + }; + std::map<std::string, ByConfig> Configs; + + cmNinjaDeps ByproductsForCleanTarget; +}; + +class cmGlobalNinjaMultiGenerator : public cmGlobalNinjaGenerator +{ +public: + /// The default name of Ninja's common file. Typically: common.ninja. + static const char* NINJA_COMMON_FILE; + /// The default file extension to use for per-config Ninja files. + static const char* NINJA_FILE_EXTENSION; + + cmGlobalNinjaMultiGenerator(cmake* cm); + bool IsMultiConfig() const override { return true; } + static cmGlobalGeneratorFactory* NewFactory() + { + return new cmGlobalGeneratorSimpleFactory<cmGlobalNinjaMultiGenerator>(); + } + + static void GetDocumentation(cmDocumentationEntry& entry); + + std::string GetName() const override + { + return cmGlobalNinjaMultiGenerator::GetActualName(); + } + + static std::string GetActualName() { return "Ninja Multi-Config"; } + + std::string BuildAlias(const std::string& alias, + const std::string& config) const override + { + if (config.empty()) { + return alias; + } + return cmStrCat(alias, ":", config); + } + + std::string ConfigDirectory(const std::string& config) const override + { + if (!config.empty()) { + return cmStrCat('/', config); + } + return ""; + } + + const char* GetCMakeCFGIntDir() const override { return "${CONFIGURATION}"; } + + std::string ExpandCFGIntDir(const std::string& str, + const std::string& config) const override; + + cmGeneratedFileStream* GetConfigFileStream( + const std::string& config) const override + { + return this->ConfigFileStreams.at(config).get(); + } + + cmGeneratedFileStream* GetCommonFileStream() const override + { + return this->CommonFileStream.get(); + } + + void AppendNinjaFileArgument(GeneratedMakeCommand& command, + const std::string& config) const override; + + static std::string GetNinjaFilename(const std::string& config); + + void AddRebuildManifestOutputs(cmNinjaDeps& outputs) const override; + + void GetQtAutoGenConfigs(std::vector<std::string>& configs) const override; + + bool WriteDefaultBuildFile() override; + +protected: + bool OpenBuildFileStreams() override; + void CloseBuildFileStreams() override; + +private: + std::map<std::string, std::unique_ptr<cmGeneratedFileStream>> + ConfigFileStreams; + std::unique_ptr<cmGeneratedFileStream> CommonFileStream; }; #endif // ! cmGlobalNinjaGenerator_h diff --git a/Source/cmGlobalUnixMakefileGenerator3.cxx b/Source/cmGlobalUnixMakefileGenerator3.cxx index 4c2d69f..f2595ea 100644 --- a/Source/cmGlobalUnixMakefileGenerator3.cxx +++ b/Source/cmGlobalUnixMakefileGenerator3.cxx @@ -8,8 +8,9 @@ #include <utility> #include <cm/memory> +#include <cmext/algorithm> +#include <cmext/memory> -#include "cmAlgorithms.h" #include "cmDocumentationEntry.h" #include "cmGeneratedFileStream.h" #include "cmGeneratorTarget.h" @@ -61,10 +62,11 @@ void cmGlobalUnixMakefileGenerator3::EnableLanguage( } //! Create a local generator appropriate to this Global Generator -cmLocalGenerator* cmGlobalUnixMakefileGenerator3::CreateLocalGenerator( - cmMakefile* mf) +std::unique_ptr<cmLocalGenerator> +cmGlobalUnixMakefileGenerator3::CreateLocalGenerator(cmMakefile* mf) { - return new cmLocalUnixMakefileGenerator3(this, mf); + return std::unique_ptr<cmLocalGenerator>( + cm::make_unique<cmLocalUnixMakefileGenerator3>(this, mf)); } void cmGlobalUnixMakefileGenerator3::GetDocumentation( @@ -144,11 +146,11 @@ void cmGlobalUnixMakefileGenerator3::Generate() for (auto& pmi : this->ProgressMap) { pmi.second.WriteProgressVariables(total, current); } - for (cmLocalGenerator* lg : this->LocalGenerators) { + for (const auto& lg : this->LocalGenerators) { std::string markFileName = cmStrCat(lg->GetCurrentBinaryDirectory(), "/CMakeFiles/progress.marks"); cmGeneratedFileStream markFile(markFileName); - markFile << this->CountProgressMarksInAll(lg) << "\n"; + markFile << this->CountProgressMarksInAll(*lg) << "\n"; } // write the main makefile @@ -203,11 +205,11 @@ void cmGlobalUnixMakefileGenerator3::WriteMainMakefile2() } // get a local generator for some useful methods - cmLocalUnixMakefileGenerator3* lg = - static_cast<cmLocalUnixMakefileGenerator3*>(this->LocalGenerators[0]); + auto& lg = cm::static_reference_cast<cmLocalUnixMakefileGenerator3>( + this->LocalGenerators[0]); // Write the do not edit header. - lg->WriteDisclaimer(makefileStream); + lg.WriteDisclaimer(makefileStream); // Write the main entry point target. This must be the VERY first // target so that make with no arguments will run it. @@ -217,10 +219,10 @@ void cmGlobalUnixMakefileGenerator3::WriteMainMakefile2() depends.emplace_back("all"); // Write the rule. - lg->WriteMakeRule(makefileStream, - "Default target executed when no arguments are " - "given to make.", - "default_target", depends, no_commands, true); + lg.WriteMakeRule(makefileStream, + "Default target executed when no arguments are " + "given to make.", + "default_target", depends, no_commands, true); depends.clear(); @@ -231,7 +233,7 @@ void cmGlobalUnixMakefileGenerator3::WriteMainMakefile2() } // Write out the "special" stuff - lg->WriteSpecialTargetsTop(makefileStream); + lg.WriteSpecialTargetsTop(makefileStream); // Write the directory level rules. for (auto const& it : this->ComputeDirectoryTargets()) { @@ -239,13 +241,14 @@ void cmGlobalUnixMakefileGenerator3::WriteMainMakefile2() } // Write the target convenience rules - for (cmLocalGenerator* localGen : this->LocalGenerators) { + for (const auto& localGen : this->LocalGenerators) { this->WriteConvenienceRules2( - makefileStream, static_cast<cmLocalUnixMakefileGenerator3*>(localGen)); + makefileStream, + cm::static_reference_cast<cmLocalUnixMakefileGenerator3>(localGen)); } // Write special bottom targets - lg->WriteSpecialTargetsBottom(makefileStream); + lg.WriteSpecialTargetsBottom(makefileStream); } void cmGlobalUnixMakefileGenerator3::WriteMainCMakefile() @@ -268,12 +271,14 @@ void cmGlobalUnixMakefileGenerator3::WriteMainCMakefile() std::string makefileName = cmStrCat(this->GetCMakeInstance()->GetHomeOutputDirectory(), "/Makefile"); - // get a local generator for some useful methods - cmLocalUnixMakefileGenerator3* lg = - static_cast<cmLocalUnixMakefileGenerator3*>(this->LocalGenerators[0]); + { + // get a local generator for some useful methods + auto& lg = cm::static_reference_cast<cmLocalUnixMakefileGenerator3>( + this->LocalGenerators[0]); - // Write the do not edit header. - lg->WriteDisclaimer(cmakefileStream); + // Write the do not edit header. + lg.WriteDisclaimer(cmakefileStream); + } // Save the generator name cmakefileStream << "# The generator used is:\n" @@ -282,9 +287,9 @@ void cmGlobalUnixMakefileGenerator3::WriteMainCMakefile() // for each cmMakefile get its list of dependencies std::vector<std::string> lfiles; - for (cmLocalGenerator* localGen : this->LocalGenerators) { + for (const auto& localGen : this->LocalGenerators) { // Get the list of files contributing to this generation step. - cmAppend(lfiles, localGen->GetMakefile()->GetListFiles()); + cm::append(lfiles, localGen->GetMakefile()->GetListFiles()); } cmake* cm = this->GetCMakeInstance(); @@ -300,59 +305,61 @@ void cmGlobalUnixMakefileGenerator3::WriteMainCMakefile() lfiles.erase(new_end, lfiles.end()); #endif - // reset lg to the first makefile - lg = static_cast<cmLocalUnixMakefileGenerator3*>(this->LocalGenerators[0]); - - std::string currentBinDir = lg->GetCurrentBinaryDirectory(); - // Save the list to the cmake file. - cmakefileStream - << "# The top level Makefile was generated from the following files:\n" - << "set(CMAKE_MAKEFILE_DEPENDS\n" - << " \"CMakeCache.txt\"\n"; - for (std::string const& f : lfiles) { - cmakefileStream << " \"" - << lg->MaybeConvertToRelativePath(currentBinDir, f) - << "\"\n"; - } - cmakefileStream << " )\n\n"; - - // Build the path to the cache check file. - std::string check = - cmStrCat(this->GetCMakeInstance()->GetHomeOutputDirectory(), - "/CMakeFiles/cmake.check_cache"); - - // Set the corresponding makefile in the cmake file. - cmakefileStream << "# The corresponding makefile is:\n" - << "set(CMAKE_MAKEFILE_OUTPUTS\n" - << " \"" - << lg->MaybeConvertToRelativePath(currentBinDir, - makefileName) - << "\"\n" - << " \"" - << lg->MaybeConvertToRelativePath(currentBinDir, check) - << "\"\n"; - cmakefileStream << " )\n\n"; - - const std::string binDir = lg->GetBinaryDirectory(); - - // CMake must rerun if a byproduct is missing. { - cmakefileStream << "# Byproducts of CMake generate step:\n" - << "set(CMAKE_MAKEFILE_PRODUCTS\n"; - for (std::string const& outfile : lg->GetMakefile()->GetOutputFiles()) { + // reset lg to the first makefile + const auto& lg = cm::static_reference_cast<cmLocalUnixMakefileGenerator3>( + this->LocalGenerators[0]); + + const std::string& currentBinDir = lg.GetCurrentBinaryDirectory(); + // Save the list to the cmake file. + cmakefileStream + << "# The top level Makefile was generated from the following files:\n" + << "set(CMAKE_MAKEFILE_DEPENDS\n" + << " \"CMakeCache.txt\"\n"; + for (std::string const& f : lfiles) { cmakefileStream << " \"" - << lg->MaybeConvertToRelativePath(binDir, outfile) + << lg.MaybeConvertToRelativePath(currentBinDir, f) << "\"\n"; } + cmakefileStream << " )\n\n"; + + // Build the path to the cache check file. + std::string check = + cmStrCat(this->GetCMakeInstance()->GetHomeOutputDirectory(), + "/CMakeFiles/cmake.check_cache"); + + // Set the corresponding makefile in the cmake file. + cmakefileStream << "# The corresponding makefile is:\n" + << "set(CMAKE_MAKEFILE_OUTPUTS\n" + << " \"" + << lg.MaybeConvertToRelativePath(currentBinDir, + makefileName) + << "\"\n" + << " \"" + << lg.MaybeConvertToRelativePath(currentBinDir, check) + << "\"\n"; + cmakefileStream << " )\n\n"; + + const std::string& binDir = lg.GetBinaryDirectory(); + + // CMake must rerun if a byproduct is missing. + { + cmakefileStream << "# Byproducts of CMake generate step:\n" + << "set(CMAKE_MAKEFILE_PRODUCTS\n"; + for (std::string const& outfile : lg.GetMakefile()->GetOutputFiles()) { + cmakefileStream << " \"" + << lg.MaybeConvertToRelativePath(binDir, outfile) + << "\"\n"; + } + } // add in all the directory information files std::string tmpStr; - for (cmLocalGenerator* localGen : this->LocalGenerators) { - lg = static_cast<cmLocalUnixMakefileGenerator3*>(localGen); - tmpStr = cmStrCat(lg->GetCurrentBinaryDirectory(), + for (const auto& localGen : this->LocalGenerators) { + tmpStr = cmStrCat(localGen->GetCurrentBinaryDirectory(), "/CMakeFiles/CMakeDirectoryInformation.cmake"); cmakefileStream << " \"" - << lg->MaybeConvertToRelativePath(binDir, tmpStr) + << localGen->MaybeConvertToRelativePath(binDir, tmpStr) << "\"\n"; } cmakefileStream << " )\n\n"; @@ -364,26 +371,24 @@ void cmGlobalUnixMakefileGenerator3::WriteMainCMakefile() void cmGlobalUnixMakefileGenerator3::WriteMainCMakefileLanguageRules( cmGeneratedFileStream& cmakefileStream, - std::vector<cmLocalGenerator*>& lGenerators) + std::vector<std::unique_ptr<cmLocalGenerator>>& lGenerators) { - cmLocalUnixMakefileGenerator3* lg; - // now list all the target info files cmakefileStream << "# Dependency information for all targets:\n"; cmakefileStream << "set(CMAKE_DEPEND_INFO_FILES\n"; - for (cmLocalGenerator* lGenerator : lGenerators) { - lg = static_cast<cmLocalUnixMakefileGenerator3*>(lGenerator); + for (const auto& lGenerator : lGenerators) { + const auto& lg = + cm::static_reference_cast<cmLocalUnixMakefileGenerator3>(lGenerator); // for all of out targets - for (cmGeneratorTarget* tgt : lg->GetGeneratorTargets()) { + for (const auto& tgt : lg.GetGeneratorTargets()) { if ((tgt->GetType() == cmStateEnums::EXECUTABLE) || (tgt->GetType() == cmStateEnums::STATIC_LIBRARY) || (tgt->GetType() == cmStateEnums::SHARED_LIBRARY) || (tgt->GetType() == cmStateEnums::MODULE_LIBRARY) || (tgt->GetType() == cmStateEnums::OBJECT_LIBRARY) || (tgt->GetType() == cmStateEnums::UTILITY)) { - cmGeneratorTarget* gt = tgt; - std::string tname = - cmStrCat(lg->GetRelativeTargetDirectory(gt), "/DependInfo.cmake"); + std::string tname = cmStrCat(lg.GetRelativeTargetDirectory(tgt.get()), + "/DependInfo.cmake"); cmSystemTools::ConvertToUnixSlashes(tname); cmakefileStream << " \"" << tname << "\"\n"; } @@ -545,11 +550,11 @@ void cmGlobalUnixMakefileGenerator3::WriteConvenienceRules( } // write the target convenience rules - for (cmLocalGenerator* localGen : this->LocalGenerators) { - cmLocalUnixMakefileGenerator3* lg = - static_cast<cmLocalUnixMakefileGenerator3*>(localGen); + for (const auto& localGen : this->LocalGenerators) { + auto& lg = + cm::static_reference_cast<cmLocalUnixMakefileGenerator3>(localGen); // for each target Generate the rule files for each target. - for (cmGeneratorTarget* gtarget : lg->GetGeneratorTargets()) { + for (const auto& gtarget : lg.GetGeneratorTargets()) { // Don't emit the same rule twice (e.g. two targets with the same // simple name) int type = gtarget->GetType(); @@ -564,23 +569,23 @@ void cmGlobalUnixMakefileGenerator3::WriteConvenienceRules( (type == cmStateEnums::OBJECT_LIBRARY) || (type == cmStateEnums::UTILITY))) { // Add a rule to build the target by name. - lg->WriteDivider(ruleFileStream); + lg.WriteDivider(ruleFileStream); ruleFileStream << "# Target rules for targets named " << name << "\n\n"; // Write the rule. commands.clear(); std::string tmp = "CMakeFiles/Makefile2"; - commands.push_back(lg->GetRecursiveMakeCall(tmp, name)); + commands.push_back(lg.GetRecursiveMakeCall(tmp, name)); depends.clear(); if (regenerate) { depends.emplace_back("cmake_check_build_system"); } - lg->WriteMakeRule(ruleFileStream, "Build rule for target.", name, - depends, commands, true); + lg.WriteMakeRule(ruleFileStream, "Build rule for target.", name, + depends, commands, true); // Add a fast rule to build the target - std::string localName = lg->GetRelativeTargetDirectory(gtarget); + std::string localName = lg.GetRelativeTargetDirectory(gtarget.get()); std::string makefileName; makefileName = cmStrCat(localName, "/build.make"); depends.clear(); @@ -588,23 +593,23 @@ void cmGlobalUnixMakefileGenerator3::WriteConvenienceRules( std::string makeTargetName = cmStrCat(localName, "/build"); localName = cmStrCat(name, "/fast"); commands.push_back( - lg->GetRecursiveMakeCall(makefileName, makeTargetName)); - lg->WriteMakeRule(ruleFileStream, "fast build rule for target.", - localName, depends, commands, true); + lg.GetRecursiveMakeCall(makefileName, makeTargetName)); + lg.WriteMakeRule(ruleFileStream, "fast build rule for target.", + localName, depends, commands, true); // Add a local name for the rule to relink the target before // installation. - if (gtarget->NeedRelinkBeforeInstall(lg->GetConfigName())) { - makeTargetName = - cmStrCat(lg->GetRelativeTargetDirectory(gtarget), "/preinstall"); + if (gtarget->NeedRelinkBeforeInstall(lg.GetConfigName())) { + makeTargetName = cmStrCat( + lg.GetRelativeTargetDirectory(gtarget.get()), "/preinstall"); localName = cmStrCat(name, "/preinstall"); depends.clear(); commands.clear(); commands.push_back( - lg->GetRecursiveMakeCall(makefileName, makeTargetName)); - lg->WriteMakeRule(ruleFileStream, - "Manual pre-install relink rule for target.", - localName, depends, commands, true); + lg.GetRecursiveMakeCall(makefileName, makeTargetName)); + lg.WriteMakeRule(ruleFileStream, + "Manual pre-install relink rule for target.", + localName, depends, commands, true); } } } @@ -612,7 +617,7 @@ void cmGlobalUnixMakefileGenerator3::WriteConvenienceRules( } void cmGlobalUnixMakefileGenerator3::WriteConvenienceRules2( - std::ostream& ruleFileStream, cmLocalUnixMakefileGenerator3* lg) + std::ostream& ruleFileStream, cmLocalUnixMakefileGenerator3& lg) { std::vector<std::string> depends; std::vector<std::string> commands; @@ -625,7 +630,7 @@ void cmGlobalUnixMakefileGenerator3::WriteConvenienceRules2( } // for each target Generate the rule files for each target. - for (cmGeneratorTarget* gtarget : lg->GetGeneratorTargets()) { + for (const auto& gtarget : lg.GetGeneratorTargets()) { int type = gtarget->GetType(); std::string name = gtarget->GetName(); if (!name.empty() && @@ -637,31 +642,31 @@ void cmGlobalUnixMakefileGenerator3::WriteConvenienceRules2( (type == cmStateEnums::UTILITY))) { std::string makefileName; // Add a rule to build the target by name. - localName = lg->GetRelativeTargetDirectory(gtarget); + localName = lg.GetRelativeTargetDirectory(gtarget.get()); makefileName = cmStrCat(localName, "/build.make"); - lg->WriteDivider(ruleFileStream); + lg.WriteDivider(ruleFileStream); ruleFileStream << "# Target rules for target " << localName << "\n\n"; commands.clear(); makeTargetName = cmStrCat(localName, "/depend"); commands.push_back( - lg->GetRecursiveMakeCall(makefileName, makeTargetName)); + lg.GetRecursiveMakeCall(makefileName, makeTargetName)); makeTargetName = cmStrCat(localName, "/build"); commands.push_back( - lg->GetRecursiveMakeCall(makefileName, makeTargetName)); + lg.GetRecursiveMakeCall(makefileName, makeTargetName)); // Write the rule. localName += "/all"; depends.clear(); cmLocalUnixMakefileGenerator3::EchoProgress progress; - progress.Dir = cmStrCat(lg->GetBinaryDirectory(), "/CMakeFiles"); + progress.Dir = cmStrCat(lg.GetBinaryDirectory(), "/CMakeFiles"); { std::ostringstream progressArg; const char* sep = ""; - for (unsigned long progFile : this->ProgressMap[gtarget].Marks) { + for (unsigned long progFile : this->ProgressMap[gtarget.get()].Marks) { progressArg << sep << progFile; sep = ","; } @@ -676,13 +681,13 @@ void cmGlobalUnixMakefileGenerator3::WriteConvenienceRules2( } if (targetMessages) { - lg->AppendEcho(commands, "Built target " + name, - cmLocalUnixMakefileGenerator3::EchoNormal, &progress); + lg.AppendEcho(commands, "Built target " + name, + cmLocalUnixMakefileGenerator3::EchoNormal, &progress); } - this->AppendGlobalTargetDepends(depends, gtarget); - lg->WriteMakeRule(ruleFileStream, "All Build rule for target.", - localName, depends, commands, true); + this->AppendGlobalTargetDepends(depends, gtarget.get()); + lg.WriteMakeRule(ruleFileStream, "All Build rule for target.", localName, + depends, commands, true); // Write the rule. commands.clear(); @@ -692,20 +697,21 @@ void cmGlobalUnixMakefileGenerator3::WriteConvenienceRules2( std::ostringstream progCmd; progCmd << "$(CMAKE_COMMAND) -E cmake_progress_start "; // # in target - progCmd << lg->ConvertToOutputFormat( + progCmd << lg.ConvertToOutputFormat( cmSystemTools::CollapseFullPath(progress.Dir), cmOutputConverter::SHELL); // std::set<cmGeneratorTarget const*> emitted; - progCmd << " " << this->CountProgressMarksInTarget(gtarget, emitted); + progCmd << " " + << this->CountProgressMarksInTarget(gtarget.get(), emitted); commands.push_back(progCmd.str()); } std::string tmp = "CMakeFiles/Makefile2"; - commands.push_back(lg->GetRecursiveMakeCall(tmp, localName)); + commands.push_back(lg.GetRecursiveMakeCall(tmp, localName)); { std::ostringstream progCmd; progCmd << "$(CMAKE_COMMAND) -E cmake_progress_start "; // # 0 - progCmd << lg->ConvertToOutputFormat( + progCmd << lg.ConvertToOutputFormat( cmSystemTools::CollapseFullPath(progress.Dir), cmOutputConverter::SHELL); progCmd << " 0"; @@ -715,39 +721,39 @@ void cmGlobalUnixMakefileGenerator3::WriteConvenienceRules2( if (regenerate) { depends.emplace_back("cmake_check_build_system"); } - localName = cmStrCat(lg->GetRelativeTargetDirectory(gtarget), "/rule"); - lg->WriteMakeRule(ruleFileStream, - "Build rule for subdir invocation for target.", - localName, depends, commands, true); + localName = + cmStrCat(lg.GetRelativeTargetDirectory(gtarget.get()), "/rule"); + lg.WriteMakeRule(ruleFileStream, + "Build rule for subdir invocation for target.", + localName, depends, commands, true); // Add a target with the canonical name (no prefix, suffix or path). commands.clear(); depends.clear(); depends.push_back(localName); - lg->WriteMakeRule(ruleFileStream, "Convenience name for target.", name, - depends, commands, true); + lg.WriteMakeRule(ruleFileStream, "Convenience name for target.", name, + depends, commands, true); // Add rules to prepare the target for installation. - if (gtarget->NeedRelinkBeforeInstall(lg->GetConfigName())) { - localName = - cmStrCat(lg->GetRelativeTargetDirectory(gtarget), "/preinstall"); + if (gtarget->NeedRelinkBeforeInstall(lg.GetConfigName())) { + localName = cmStrCat(lg.GetRelativeTargetDirectory(gtarget.get()), + "/preinstall"); depends.clear(); commands.clear(); - commands.push_back(lg->GetRecursiveMakeCall(makefileName, localName)); - lg->WriteMakeRule(ruleFileStream, - "Pre-install relink rule for target.", localName, - depends, commands, true); + commands.push_back(lg.GetRecursiveMakeCall(makefileName, localName)); + lg.WriteMakeRule(ruleFileStream, "Pre-install relink rule for target.", + localName, depends, commands, true); } // add the clean rule - localName = lg->GetRelativeTargetDirectory(gtarget); + localName = lg.GetRelativeTargetDirectory(gtarget.get()); makeTargetName = cmStrCat(localName, "/clean"); depends.clear(); commands.clear(); commands.push_back( - lg->GetRecursiveMakeCall(makefileName, makeTargetName)); - lg->WriteMakeRule(ruleFileStream, "clean rule for target.", - makeTargetName, depends, commands, true); + lg.GetRecursiveMakeCall(makefileName, makeTargetName)); + lg.WriteMakeRule(ruleFileStream, "clean rule for target.", + makeTargetName, depends, commands, true); commands.clear(); } } @@ -759,8 +765,8 @@ void cmGlobalUnixMakefileGenerator3::InitializeProgressMarks() { this->DirectoryTargetsMap.clear(); // Loop over all targets in all local generators. - for (cmLocalGenerator* lg : this->LocalGenerators) { - for (cmGeneratorTarget* gt : lg->GetGeneratorTargets()) { + for (const auto& lg : this->LocalGenerators) { + for (const auto& gt : lg->GetGeneratorTargets()) { cmLocalGenerator* tlg = gt->GetLocalGenerator(); if (gt->GetType() == cmStateEnums::INTERFACE_LIBRARY || @@ -778,12 +784,13 @@ void cmGlobalUnixMakefileGenerator3::InitializeProgressMarks() // This local generator includes the target. std::set<cmGeneratorTarget const*>& targetSet = this->DirectoryTargetsMap[csnp]; - targetSet.insert(gt); + targetSet.insert(gt.get()); // Add dependencies of the included target. An excluded // target may still be included if it is a dependency of a // non-excluded target. - for (cmTargetDepend const& tgtdep : this->GetTargetDirectDepends(gt)) { + for (cmTargetDepend const& tgtdep : + this->GetTargetDirectDepends(gt.get())) { targetSet.insert(tgtdep); } } @@ -808,12 +815,12 @@ size_t cmGlobalUnixMakefileGenerator3::CountProgressMarksInTarget( } size_t cmGlobalUnixMakefileGenerator3::CountProgressMarksInAll( - cmLocalGenerator* lg) + const cmLocalGenerator& lg) { size_t count = 0; std::set<cmGeneratorTarget const*> emitted; for (cmGeneratorTarget const* target : - this->DirectoryTargetsMap[lg->GetStateSnapshot()]) { + this->DirectoryTargetsMap[lg.GetStateSnapshot()]) { count += this->CountProgressMarksInTarget(target, emitted); } return count; @@ -887,14 +894,14 @@ void cmGlobalUnixMakefileGenerator3::WriteHelpRule( std::set<std::string> emittedTargets; // for each local generator - for (cmLocalGenerator* localGen : this->LocalGenerators) { - cmLocalUnixMakefileGenerator3* lg2 = - static_cast<cmLocalUnixMakefileGenerator3*>(localGen); + for (const auto& localGen : this->LocalGenerators) { + const auto& lg2 = + cm::static_reference_cast<cmLocalUnixMakefileGenerator3>(localGen); // for the passed in makefile or if this is the top Makefile wripte out // the targets - if (lg2 == lg || lg->IsRootMakefile()) { + if (&lg2 == lg || lg->IsRootMakefile()) { // for each target Generate the rule files for each target. - for (cmGeneratorTarget* target : lg2->GetGeneratorTargets()) { + for (const auto& target : lg2.GetGeneratorTargets()) { cmStateEnums::TargetType type = target->GetType(); if ((type == cmStateEnums::EXECUTABLE) || (type == cmStateEnums::STATIC_LIBRARY) || diff --git a/Source/cmGlobalUnixMakefileGenerator3.h b/Source/cmGlobalUnixMakefileGenerator3.h index 79db30e..5608baf 100644 --- a/Source/cmGlobalUnixMakefileGenerator3.h +++ b/Source/cmGlobalUnixMakefileGenerator3.h @@ -8,6 +8,7 @@ #include <cstddef> #include <iosfwd> #include <map> +#include <memory> #include <set> #include <string> #include <vector> @@ -89,7 +90,8 @@ public: /** Get the documentation entry for this generator. */ static void GetDocumentation(cmDocumentationEntry& entry); - cmLocalGenerator* CreateLocalGenerator(cmMakefile* mf) override; + std::unique_ptr<cmLocalGenerator> CreateLocalGenerator( + cmMakefile* mf) override; /** * Try to determine system information such as shared library @@ -107,8 +109,9 @@ public: */ void Generate() override; - void WriteMainCMakefileLanguageRules(cmGeneratedFileStream& cmakefileStream, - std::vector<cmLocalGenerator*>&); + void WriteMainCMakefileLanguageRules( + cmGeneratedFileStream& cmakefileStream, + std::vector<std::unique_ptr<cmLocalGenerator>>&); // write out the help rule listing the valid targets void WriteHelpRule(std::ostream& ruleFileStream, @@ -161,7 +164,7 @@ protected: void WriteMainCMakefile(); void WriteConvenienceRules2(std::ostream& ruleFileStream, - cmLocalUnixMakefileGenerator3*); + cmLocalUnixMakefileGenerator3&); void WriteDirectoryRule2(std::ostream& ruleFileStream, DirectoryTarget const& dt, const char* pass, @@ -227,7 +230,7 @@ protected: size_t CountProgressMarksInTarget( cmGeneratorTarget const* target, std::set<cmGeneratorTarget const*>& emitted); - size_t CountProgressMarksInAll(cmLocalGenerator* lg); + size_t CountProgressMarksInAll(const cmLocalGenerator& lg); cmGeneratedFileStream* CommandDatabase; diff --git a/Source/cmGlobalVisualStudio10Generator.cxx b/Source/cmGlobalVisualStudio10Generator.cxx index 09a49e1..bdf4cf2 100644 --- a/Source/cmGlobalVisualStudio10Generator.cxx +++ b/Source/cmGlobalVisualStudio10Generator.cxx @@ -4,6 +4,8 @@ #include <algorithm> +#include <cm/memory> + #include "cmsys/FStream.hxx" #include "cmsys/Glob.hxx" #include "cmsys/RegularExpression.hxx" @@ -26,6 +28,16 @@ static const char vs10generatorName[] = "Visual Studio 10 2010"; static std::map<std::string, std::vector<cmIDEFlagTable>> loadedFlagJsonFiles; +static void ConvertToWindowsSlashes(std::string& s) +{ + // first convert all of the slashes + for (auto& ch : s) { + if (ch == '/') { + ch = '\\'; + } + } +} + // Map generator name without year to name with year. static const char* cmVS10GenName(const std::string& name, std::string& genName) { @@ -193,7 +205,7 @@ static void cmCudaToolVersion(std::string& s) } bool cmGlobalVisualStudio10Generator::SetGeneratorToolset( - std::string const& ts, cmMakefile* mf) + std::string const& ts, bool build, cmMakefile* mf) { if (this->SystemIsWindowsCE && ts.empty() && this->DefaultPlatformToolset.empty()) { @@ -208,7 +220,11 @@ bool cmGlobalVisualStudio10Generator::SetGeneratorToolset( return false; } - if (!this->FindVCTargetsPath(mf)) { + if (build) { + return true; + } + + if (this->CustomVCTargetsPath.empty() && !this->FindVCTargetsPath(mf)) { return false; } @@ -349,6 +365,11 @@ bool cmGlobalVisualStudio10Generator::SetGeneratorToolset( if (const char* cudaDir = this->GetPlatformToolsetCudaCustomDir()) { mf->AddDefinition("CMAKE_VS_PLATFORM_TOOLSET_CUDA_CUSTOM_DIR", cudaDir); } + if (const char* vcTargetsDir = this->GetCustomVCTargetsPath()) { + mf->AddDefinition("CMAKE_VS_PLATFORM_TOOLSET_VCTARGETS_CUSTOM_DIR", + vcTargetsDir); + } + return true; } @@ -442,6 +463,11 @@ bool cmGlobalVisualStudio10Generator::ProcessGeneratorToolsetField( this->GeneratorToolsetVersion = value; return true; } + if (key == "VCTargetsPath") { + this->CustomVCTargetsPath = value; + ConvertToWindowsSlashes(this->CustomVCTargetsPath); + return true; + } return false; } @@ -550,10 +576,11 @@ std::string cmGlobalVisualStudio10Generator::SelectWindowsCEToolset() const } //! Create a local generator appropriate to this Global Generator -cmLocalGenerator* cmGlobalVisualStudio10Generator::CreateLocalGenerator( - cmMakefile* mf) +std::unique_ptr<cmLocalGenerator> +cmGlobalVisualStudio10Generator::CreateLocalGenerator(cmMakefile* mf) { - return new cmLocalVisualStudio10Generator(this, mf); + return std::unique_ptr<cmLocalGenerator>( + cm::make_unique<cmLocalVisualStudio10Generator>(this, mf)); } void cmGlobalVisualStudio10Generator::Generate() @@ -603,6 +630,14 @@ void cmGlobalVisualStudio10Generator::EnableLanguage( cmGlobalVisualStudio8Generator::EnableLanguage(lang, mf, optional); } +const char* cmGlobalVisualStudio10Generator::GetCustomVCTargetsPath() const +{ + if (this->CustomVCTargetsPath.empty()) { + return nullptr; + } + return this->CustomVCTargetsPath.c_str(); +} + const char* cmGlobalVisualStudio10Generator::GetPlatformToolset() const { std::string const& toolset = this->GetPlatformToolsetString(); diff --git a/Source/cmGlobalVisualStudio10Generator.h b/Source/cmGlobalVisualStudio10Generator.h index 9adcf08..c991c76 100644 --- a/Source/cmGlobalVisualStudio10Generator.h +++ b/Source/cmGlobalVisualStudio10Generator.h @@ -3,6 +3,8 @@ #ifndef cmGlobalVisualStudio10Generator_h #define cmGlobalVisualStudio10Generator_h +#include <memory> + #include "cmGlobalVisualStudio8Generator.h" #include "cmVisualStudio10ToolsetOptions.h" @@ -20,7 +22,8 @@ public: bool SetSystemName(std::string const& s, cmMakefile* mf) override; bool SetGeneratorPlatform(std::string const& p, cmMakefile* mf) override; - bool SetGeneratorToolset(std::string const& ts, cmMakefile* mf) override; + bool SetGeneratorToolset(std::string const& ts, bool build, + cmMakefile* mf) override; std::vector<GeneratedMakeCommand> GenerateBuildCommand( const std::string& makeProgram, const std::string& projectName, @@ -30,7 +33,8 @@ public: std::vector<std::string>()) override; //! create the correct local generator - cmLocalGenerator* CreateLocalGenerator(cmMakefile* mf) override; + std::unique_ptr<cmLocalGenerator> CreateLocalGenerator( + cmMakefile* mf) override; /** * Try to determine system information such as shared library @@ -45,6 +49,9 @@ public: bool IsNsightTegra() const; std::string GetNsightTegraVersion() const; + /** The vctargets path for the target platform. */ + const char* GetCustomVCTargetsPath() const; + /** The toolset name for the target platform. */ const char* GetPlatformToolset() const; std::string const& GetPlatformToolsetString() const; @@ -155,6 +162,7 @@ protected: std::string GeneratorToolset; std::string GeneratorToolsetVersion; std::string GeneratorToolsetHostArchitecture; + std::string GeneratorToolsetCustomVCTargetsDir; std::string GeneratorToolsetCuda; std::string GeneratorToolsetCudaCustomDir; std::string DefaultPlatformToolset; @@ -206,6 +214,7 @@ private: bool ParseGeneratorToolset(std::string const& ts, cmMakefile* mf); + std::string CustomVCTargetsPath; std::string VCTargetsPath; bool FindVCTargetsPath(cmMakefile* mf); diff --git a/Source/cmGlobalVisualStudio7Generator.cxx b/Source/cmGlobalVisualStudio7Generator.cxx index 40b214c..04ec7b3 100644 --- a/Source/cmGlobalVisualStudio7Generator.cxx +++ b/Source/cmGlobalVisualStudio7Generator.cxx @@ -2,8 +2,10 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmGlobalVisualStudio7Generator.h" +#include <utility> #include <vector> +#include <cm/memory> #include <cm/string_view> #include <windows.h> @@ -263,12 +265,11 @@ cmGlobalVisualStudio7Generator::GenerateBuildCommand( } //! Create a local generator appropriate to this Global Generator -cmLocalGenerator* cmGlobalVisualStudio7Generator::CreateLocalGenerator( - cmMakefile* mf) +std::unique_ptr<cmLocalGenerator> +cmGlobalVisualStudio7Generator::CreateLocalGenerator(cmMakefile* mf) { - cmLocalVisualStudio7Generator* lg = - new cmLocalVisualStudio7Generator(this, mf); - return lg; + auto lg = cm::make_unique<cmLocalVisualStudio7Generator>(this, mf); + return std::unique_ptr<cmLocalGenerator>(std::move(lg)); } #if !defined(CMAKE_BOOTSTRAP) @@ -300,7 +301,7 @@ void cmGlobalVisualStudio7Generator::Generate() if (!cmSystemTools::GetErrorOccuredFlag() && !this->LocalGenerators.empty()) { this->CallVisualStudioMacro(MacroReload, - GetSLNFile(this->LocalGenerators[0])); + GetSLNFile(this->LocalGenerators[0].get())); } } diff --git a/Source/cmGlobalVisualStudio7Generator.h b/Source/cmGlobalVisualStudio7Generator.h index 7a9fcef..974bb1d 100644 --- a/Source/cmGlobalVisualStudio7Generator.h +++ b/Source/cmGlobalVisualStudio7Generator.h @@ -3,6 +3,8 @@ #ifndef cmGlobalVisualStudio7Generator_h #define cmGlobalVisualStudio7Generator_h +#include <memory> + #include "cmGlobalGeneratorFactory.h" #include "cmGlobalVisualStudioGenerator.h" @@ -20,7 +22,8 @@ public: ~cmGlobalVisualStudio7Generator(); //! Create a local generator appropriate to this Global Generator - cmLocalGenerator* CreateLocalGenerator(cmMakefile* mf) override; + std::unique_ptr<cmLocalGenerator> CreateLocalGenerator( + cmMakefile* mf) override; #if !defined(CMAKE_BOOTSTRAP) Json::Value GetJson() const override; diff --git a/Source/cmGlobalVisualStudio8Generator.cxx b/Source/cmGlobalVisualStudio8Generator.cxx index 8e6125b..ba54f98 100644 --- a/Source/cmGlobalVisualStudio8Generator.cxx +++ b/Source/cmGlobalVisualStudio8Generator.cxx @@ -2,6 +2,9 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmGlobalVisualStudio8Generator.h" +#include <cm/memory> +#include <cmext/memory> + #include "cmCustomCommand.h" #include "cmCustomCommandLines.h" #include "cmDocumentationEntry.h" @@ -96,21 +99,22 @@ bool cmGlobalVisualStudio8Generator::AddCheckTarget() return false; } - std::vector<cmLocalGenerator*> const& generators = this->LocalGenerators; - cmLocalVisualStudio7Generator* lg = - static_cast<cmLocalVisualStudio7Generator*>(generators[0]); - cmMakefile* mf = lg->GetMakefile(); + std::vector<std::unique_ptr<cmLocalGenerator>> const& generators = + this->LocalGenerators; + auto& lg = + cm::static_reference_cast<cmLocalVisualStudio7Generator>(generators[0]); const char* no_working_directory = nullptr; std::vector<std::string> no_byproducts; std::vector<std::string> no_depends; cmCustomCommandLines no_commands; - cmTarget* tgt = mf->AddUtilityCommand( - CMAKE_CHECK_BUILD_SYSTEM_TARGET, cmCommandOrigin::Generator, false, - no_working_directory, no_byproducts, no_depends, no_commands); + cmTarget* tgt = lg.AddUtilityCommand(CMAKE_CHECK_BUILD_SYSTEM_TARGET, false, + no_working_directory, no_byproducts, + no_depends, no_commands); - cmGeneratorTarget* gt = new cmGeneratorTarget(tgt, lg); - lg->AddGeneratorTarget(gt); + auto ptr = cm::make_unique<cmGeneratorTarget>(tgt, &lg); + auto gt = ptr.get(); + lg.AddGeneratorTarget(std::move(ptr)); // Organize in the "predefined targets" folder: // @@ -128,7 +132,7 @@ bool cmGlobalVisualStudio8Generator::AddCheckTarget() stampList); std::string stampFile; cmGeneratedFileStream fout(stampListFile.c_str()); - for (cmLocalGenerator const* gi : generators) { + for (const auto& gi : generators) { stampFile = cmStrCat(gi->GetMakefile()->GetCurrentBinaryDirectory(), "/CMakeFiles/generate.stamp"); fout << stampFile << "\n"; @@ -141,8 +145,8 @@ bool cmGlobalVisualStudio8Generator::AddCheckTarget() // Collect the input files used to generate all targets in this // project. std::vector<std::string> listFiles; - for (cmLocalGenerator* gen : generators) { - cmAppend(listFiles, gen->GetMakefile()->GetListFiles()); + for (const auto& gen : generators) { + cm::append(listFiles, gen->GetMakefile()->GetListFiles()); } // Add a custom prebuild target to run the VerifyGlobs script. @@ -153,7 +157,7 @@ bool cmGlobalVisualStudio8Generator::AddCheckTarget() std::vector<std::string> byproducts; byproducts.push_back(cm->GetGlobVerifyStamp()); - mf->AddCustomCommandToTarget( + lg.AddCustomCommandToTarget( CMAKE_CHECK_BUILD_SYSTEM_TARGET, byproducts, no_depends, verifyCommandLines, cmCustomCommandType::PRE_BUILD, "Checking File Globs", no_working_directory, false); @@ -171,10 +175,10 @@ bool cmGlobalVisualStudio8Generator::AddCheckTarget() listFiles.erase(new_end, listFiles.end()); // Create a rule to re-run CMake. - std::string argS = cmStrCat("-S", lg->GetSourceDirectory()); - std::string argB = cmStrCat("-B", lg->GetBinaryDirectory()); + std::string argS = cmStrCat("-S", lg.GetSourceDirectory()); + std::string argB = cmStrCat("-B", lg.GetBinaryDirectory()); std::string const sln = - lg->GetBinaryDirectory() + "/" + lg->GetProjectName() + ".sln"; + lg.GetBinaryDirectory() + "/" + lg.GetProjectName() + ".sln"; cmCustomCommandLines commandLines = cmMakeSingleCommandLine( { cmSystemTools::GetCMakeCommand(), argS, argB, "--check-stamp-list", stampList, "--vs-solution-file", sln }); @@ -185,7 +189,7 @@ bool cmGlobalVisualStudio8Generator::AddCheckTarget() // (this could be avoided with per-target source files) std::string no_main_dependency; cmImplicitDependsList no_implicit_depends; - if (cmSourceFile* file = mf->AddCustomCommandToOutput( + if (cmSourceFile* file = lg.AddCustomCommandToOutput( stamps, no_byproducts, listFiles, no_main_dependency, no_implicit_depends, commandLines, "Checking Build System", no_working_directory, true, false)) { @@ -203,10 +207,9 @@ void cmGlobalVisualStudio8Generator::AddExtraIDETargets() cmGlobalVisualStudio7Generator::AddExtraIDETargets(); if (this->AddCheckTarget()) { for (unsigned int i = 0; i < this->LocalGenerators.size(); ++i) { - const std::vector<cmGeneratorTarget*>& tgts = - this->LocalGenerators[i]->GetGeneratorTargets(); + const auto& tgts = this->LocalGenerators[i]->GetGeneratorTargets(); // All targets depend on the build-system check target. - for (cmGeneratorTarget const* ti : tgts) { + for (const auto& ti : tgts) { if (ti->GetName() != CMAKE_CHECK_BUILD_SYSTEM_TARGET) { ti->Target->AddUtility(CMAKE_CHECK_BUILD_SYSTEM_TARGET); } diff --git a/Source/cmGlobalVisualStudioGenerator.cxx b/Source/cmGlobalVisualStudioGenerator.cxx index ed0cba7..be5cfd4 100644 --- a/Source/cmGlobalVisualStudioGenerator.cxx +++ b/Source/cmGlobalVisualStudioGenerator.cxx @@ -7,6 +7,7 @@ #include <iostream> #include <cm/iterator> +#include <cm/memory> #include <windows.h> @@ -196,12 +197,12 @@ void cmGlobalVisualStudioGenerator::AddExtraIDETargets() if (!gen.empty()) { // Use no actual command lines so that the target itself is not // considered always out of date. - cmTarget* allBuild = gen[0]->GetMakefile()->AddUtilityCommand( - "ALL_BUILD", cmCommandOrigin::Generator, true, no_working_dir, - no_byproducts, no_depends, no_commands, false, "Build all projects"); + cmTarget* allBuild = gen[0]->AddUtilityCommand( + "ALL_BUILD", true, no_working_dir, no_byproducts, no_depends, + no_commands, false, "Build all projects"); - cmGeneratorTarget* gt = new cmGeneratorTarget(allBuild, gen[0]); - gen[0]->AddGeneratorTarget(gt); + gen[0]->AddGeneratorTarget( + cm::make_unique<cmGeneratorTarget>(allBuild, gen[0])); // // Organize in the "predefined targets" folder: @@ -212,12 +213,12 @@ void cmGlobalVisualStudioGenerator::AddExtraIDETargets() // Now make all targets depend on the ALL_BUILD target for (cmLocalGenerator const* i : gen) { - for (cmGeneratorTarget* tgt : i->GetGeneratorTargets()) { + for (const auto& tgt : i->GetGeneratorTargets()) { if (tgt->GetType() == cmStateEnums::GLOBAL_TARGET || tgt->IsImported()) { continue; } - if (!this->IsExcluded(gen[0], tgt)) { + if (!this->IsExcluded(gen[0], tgt.get())) { allBuild->AddUtility(tgt->GetName()); } } @@ -389,8 +390,8 @@ bool cmGlobalVisualStudioGenerator::ComputeTargetDepends() } for (auto const& it : this->ProjectMap) { for (const cmLocalGenerator* i : it.second) { - for (cmGeneratorTarget* ti : i->GetGeneratorTargets()) { - this->ComputeVSTargetDepends(ti); + for (const auto& ti : i->GetGeneratorTargets()) { + this->ComputeVSTargetDepends(ti.get()); } } } @@ -799,19 +800,9 @@ void RegisterVisualStudioMacros(const std::string& macrosFile, bool cmGlobalVisualStudioGenerator::TargetIsFortranOnly( cmGeneratorTarget const* gt) { - // check to see if this is a fortran build - { - // Issue diagnostic if the source files depend on the config. - std::vector<cmSourceFile*> sources; - if (!gt->GetConfigCommonSourceFiles(sources)) { - return false; - } - } - // If there's only one source language, Fortran has to be used // in order for the sources to compile. - std::set<std::string> languages; - gt->GetLanguages(languages, ""); + std::set<std::string> languages = gt->GetAllConfigCompileLanguages(); // Consider an explicit linker language property, but *not* the // computed linker language that may depend on linked targets. // This allows the project to control the language choice in @@ -939,9 +930,10 @@ void cmGlobalVisualStudioGenerator::AddSymbolExportCommand( cmCustomCommandLines commandLines = cmMakeSingleCommandLine( { cmakeCommand, "-E", "__create_def", mdi->DefFile, objs_file }); - cmCustomCommand command(gt->Target->GetMakefile(), outputs, empty, empty, - commandLines, "Auto build dll exports", "."); - commands.push_back(command); + cmCustomCommand command(outputs, empty, empty, commandLines, + gt->Target->GetMakefile()->GetBacktrace(), + "Auto build dll exports", "."); + commands.push_back(std::move(command)); } static bool OpenSolution(std::string sln) diff --git a/Source/cmGlobalXCodeGenerator.cxx b/Source/cmGlobalXCodeGenerator.cxx index 3002b2a..dcd9705 100644 --- a/Source/cmGlobalXCodeGenerator.cxx +++ b/Source/cmGlobalXCodeGenerator.cxx @@ -2,6 +2,7 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmGlobalXCodeGenerator.h" +#include <algorithm> #include <cassert> #include <cstdio> #include <cstring> @@ -9,6 +10,7 @@ #include <sstream> #include <cm/memory> +#include <cmext/algorithm> #include "cmsys/RegularExpression.hxx" @@ -267,7 +269,7 @@ std::string cmGlobalXCodeGenerator::FindXcodeBuildCommand() } bool cmGlobalXCodeGenerator::SetGeneratorToolset(std::string const& ts, - cmMakefile* mf) + bool build, cmMakefile* mf) { if (ts.find_first_of(",=") != std::string::npos) { std::ostringstream e; @@ -283,6 +285,9 @@ bool cmGlobalXCodeGenerator::SetGeneratorToolset(std::string const& ts, return false; } this->GeneratorToolset = ts; + if (build) { + return true; + } if (!this->GeneratorToolset.empty()) { mf->AddDefinition("CMAKE_XCODE_PLATFORM_TOOLSET", this->GeneratorToolset); } @@ -388,9 +393,11 @@ cmGlobalXCodeGenerator::GenerateBuildCommand( } //! Create a local generator appropriate to this Global Generator -cmLocalGenerator* cmGlobalXCodeGenerator::CreateLocalGenerator(cmMakefile* mf) +std::unique_ptr<cmLocalGenerator> cmGlobalXCodeGenerator::CreateLocalGenerator( + cmMakefile* mf) { - return new cmLocalXCodeGenerator(this, mf); + return std::unique_ptr<cmLocalGenerator>( + cm::make_unique<cmLocalXCodeGenerator>(this, mf)); } void cmGlobalXCodeGenerator::AddExtraIDETargets() @@ -409,10 +416,10 @@ void cmGlobalXCodeGenerator::ComputeTargetOrder() { size_t index = 0; auto const& lgens = this->GetLocalGenerators(); - for (cmLocalGenerator* lgen : lgens) { - auto const& targets = lgen->GetGeneratorTargets(); - for (cmGeneratorTarget const* gt : targets) { - this->ComputeTargetOrder(gt, index); + for (auto const& lgen : lgens) { + const auto& targets = lgen->GetGeneratorTargets(); + for (const auto& gt : targets) { + this->ComputeTargetOrder(gt.get(), index); } } assert(index == this->TargetOrderIndex.size()); @@ -496,20 +503,16 @@ std::string cmGlobalXCodeGenerator::PostBuildMakeTarget( void cmGlobalXCodeGenerator::AddExtraTargets( cmLocalGenerator* root, std::vector<cmLocalGenerator*>& gens) { - cmMakefile* mf = root->GetMakefile(); - const char* no_working_directory = nullptr; std::vector<std::string> no_byproducts; std::vector<std::string> no_depends; // Add ALL_BUILD - cmTarget* allbuild = mf->AddUtilityCommand( - "ALL_BUILD", cmCommandOrigin::Generator, true, no_working_directory, - no_byproducts, no_depends, + cmTarget* allbuild = root->AddUtilityCommand( + "ALL_BUILD", true, no_working_directory, no_byproducts, no_depends, cmMakeSingleCommandLine({ "echo", "Build all projects" })); - cmGeneratorTarget* allBuildGt = new cmGeneratorTarget(allbuild, root); - root->AddGeneratorTarget(allBuildGt); + root->AddGeneratorTarget(cm::make_unique<cmGeneratorTarget>(allbuild, root)); // Add XCODE depend helper std::string dir = root->GetCurrentBinaryDirectory(); @@ -520,7 +523,7 @@ void cmGlobalXCodeGenerator::AddExtraTargets( // Add ZERO_CHECK bool regenerate = !this->GlobalSettingIsOn("CMAKE_SUPPRESS_REGENERATION"); bool generateTopLevelProjectOnly = - mf->IsOn("CMAKE_XCODE_GENERATE_TOP_LEVEL_PROJECT_ONLY"); + root->GetMakefile()->IsOn("CMAKE_XCODE_GENERATE_TOP_LEVEL_PROJECT_ONLY"); bool isTopLevel = !root->GetStateSnapshot().GetBuildsystemDirectoryParent().IsValid(); if (regenerate && (isTopLevel || !generateTopLevelProjectOnly)) { @@ -528,19 +531,18 @@ void cmGlobalXCodeGenerator::AddExtraTargets( std::string file = this->ConvertToRelativeForMake(this->CurrentReRunCMakeMakefile); cmSystemTools::ReplaceString(file, "\\ ", " "); - cmTarget* check = mf->AddUtilityCommand( - CMAKE_CHECK_BUILD_SYSTEM_TARGET, cmCommandOrigin::Generator, true, - no_working_directory, no_byproducts, no_depends, - cmMakeSingleCommandLine({ "make", "-f", file })); + cmTarget* check = + root->AddUtilityCommand(CMAKE_CHECK_BUILD_SYSTEM_TARGET, true, + no_working_directory, no_byproducts, no_depends, + cmMakeSingleCommandLine({ "make", "-f", file })); - cmGeneratorTarget* checkGt = new cmGeneratorTarget(check, root); - root->AddGeneratorTarget(checkGt); + root->AddGeneratorTarget(cm::make_unique<cmGeneratorTarget>(check, root)); } // now make the allbuild depend on all the non-utility targets // in the project for (auto& gen : gens) { - for (auto target : gen->GetGeneratorTargets()) { + for (const auto& target : gen->GetGeneratorTargets()) { if (target->GetType() == cmStateEnums::GLOBAL_TARGET) { continue; } @@ -557,14 +559,14 @@ void cmGlobalXCodeGenerator::AddExtraTargets( if (target->GetType() == cmStateEnums::OBJECT_LIBRARY) { commandLines.front().back() = // fill placeholder this->PostBuildMakeTarget(target->GetName(), "$(CONFIGURATION)"); - gen->GetMakefile()->AddCustomCommandToTarget( + gen->AddCustomCommandToTarget( target->GetName(), no_byproducts, no_depends, commandLines, cmCustomCommandType::POST_BUILD, "Depend check for xcode", dir.c_str(), true, false, "", "", false, cmObjectLibraryCommands::Accept); } - if (!this->IsExcluded(gens[0], target)) { + if (!this->IsExcluded(gens[0], target.get())) { allbuild->AddUtility(target->GetName()); } } @@ -576,7 +578,7 @@ void cmGlobalXCodeGenerator::CreateReRunCMakeFile( { std::vector<std::string> lfiles; for (auto gen : gens) { - cmAppend(lfiles, gen->GetMakefile()->GetListFiles()); + cm::append(lfiles, gen->GetMakefile()->GetListFiles()); } // sort the array @@ -1093,8 +1095,8 @@ bool cmGlobalXCodeGenerator::CreateXCodeTargets( cmLocalGenerator* gen, std::vector<cmXCodeObject*>& targets) { this->SetCurrentLocalGenerator(gen); - std::vector<cmGeneratorTarget*> gts = - this->CurrentLocalGenerator->GetGeneratorTargets(); + std::vector<cmGeneratorTarget*> gts; + cm::append(gts, this->CurrentLocalGenerator->GetGeneratorTargets()); std::sort(gts.begin(), gts.end(), [this](cmGeneratorTarget const* l, cmGeneratorTarget const* r) { return this->TargetOrderIndex[l] < this->TargetOrderIndex[r]; @@ -1364,11 +1366,11 @@ bool cmGlobalXCodeGenerator::CreateXCodeTarget( void cmGlobalXCodeGenerator::ForceLinkerLanguages() { - for (auto localGenerator : this->LocalGenerators) { + for (const auto& localGenerator : this->LocalGenerators) { // All targets depend on the build-system check target. - for (auto tgt : localGenerator->GetGeneratorTargets()) { + for (const auto& tgt : localGenerator->GetGeneratorTargets()) { // This makes sure all targets link using the proper language. - this->ForceLinkerLanguage(tgt); + this->ForceLinkerLanguage(tgt.get()); } } } @@ -1460,12 +1462,12 @@ void cmGlobalXCodeGenerator::CreateCustomCommands( { cmSystemTools::GetCMakeCommand(), "-E", "cmake_symlink_library", str_file, str_so_file, str_link_file }); - cmCustomCommand command(this->CurrentMakefile, std::vector<std::string>(), - std::vector<std::string>(), - std::vector<std::string>(), cmd, - "Creating symlinks", ""); + cmCustomCommand command( + std::vector<std::string>(), std::vector<std::string>(), + std::vector<std::string>(), cmd, this->CurrentMakefile->GetBacktrace(), + "Creating symlinks", ""); - postbuild.push_back(command); + postbuild.push_back(std::move(command)); } std::vector<cmSourceFile*> classes; @@ -2834,7 +2836,7 @@ bool cmGlobalXCodeGenerator::CreateGroups( for (auto& generator : generators) { cmMakefile* mf = generator->GetMakefile(); std::vector<cmSourceGroup> sourceGroups = mf->GetSourceGroups(); - for (auto gtgt : generator->GetGeneratorTargets()) { + for (const auto& gtgt : generator->GetGeneratorTargets()) { // Same skipping logic here as in CreateXCodeTargets so that we do not // end up with (empty anyhow) ZERO_CHECK, install, or test source // groups: @@ -2849,11 +2851,12 @@ bool cmGlobalXCodeGenerator::CreateGroups( continue; } - auto addSourceToGroup = [this, mf, gtgt, + auto addSourceToGroup = [this, mf, >gt, &sourceGroups](std::string const& source) { cmSourceGroup* sourceGroup = mf->FindSourceGroup(source, sourceGroups); - cmXCodeObject* pbxgroup = this->CreateOrGetPBXGroup(gtgt, sourceGroup); - std::string key = GetGroupMapKeyFromPath(gtgt, source); + cmXCodeObject* pbxgroup = + this->CreateOrGetPBXGroup(gtgt.get(), sourceGroup); + std::string key = GetGroupMapKeyFromPath(gtgt.get(), source); this->GroupMap[key] = pbxgroup; }; @@ -2879,7 +2882,7 @@ bool cmGlobalXCodeGenerator::CreateGroups( // Add the Info.plist we are about to generate for an App Bundle. if (gtgt->GetPropertyAsBool("MACOSX_BUNDLE")) { - std::string plist = this->ComputeInfoPListLocation(gtgt); + std::string plist = this->ComputeInfoPListLocation(gtgt.get()); cmSourceFile* sf = gtgt->Makefile->GetOrCreateSource( plist, true, cmSourceFileLocationKind::Known); addSourceToGroup(sf->ResolveFullPath()); @@ -3415,7 +3418,7 @@ bool cmGlobalXCodeGenerator::OutputXCodeSharedSchemes( (root->GetMakefile()->GetCMakeInstance()->GetIsInTryCompile() || obj->GetTarget()->GetPropertyAsBool("XCODE_GENERATE_SCHEME"))) { const std::string& targetName = obj->GetTarget()->GetName(); - cmXCodeScheme schm(obj, testables[targetName], + cmXCodeScheme schm(root, obj, testables[targetName], this->CurrentConfigurationTypes, this->XcodeVersion); schm.WriteXCodeSharedScheme(xcProjDir, diff --git a/Source/cmGlobalXCodeGenerator.h b/Source/cmGlobalXCodeGenerator.h index af905d0..a12021d 100644 --- a/Source/cmGlobalXCodeGenerator.h +++ b/Source/cmGlobalXCodeGenerator.h @@ -7,6 +7,7 @@ #include <iosfwd> #include <map> +#include <memory> #include <set> #include <string> #include <vector> @@ -47,7 +48,8 @@ public: static void GetDocumentation(cmDocumentationEntry& entry); //! Create a local generator appropriate to this Global Generator - cmLocalGenerator* CreateLocalGenerator(cmMakefile* mf) override; + std::unique_ptr<cmLocalGenerator> CreateLocalGenerator( + cmMakefile* mf) override; /** * Try to determine system information such as shared library @@ -103,7 +105,8 @@ public: bool ShouldStripResourcePath(cmMakefile*) const override; - bool SetGeneratorToolset(std::string const& ts, cmMakefile* mf) override; + bool SetGeneratorToolset(std::string const& ts, bool build, + cmMakefile* mf) override; void AppendFlag(std::string& flags, std::string const& flag) const; protected: diff --git a/Source/cmGraphVizWriter.cxx b/Source/cmGraphVizWriter.cxx index e0d545d..f48789a 100644 --- a/Source/cmGraphVizWriter.cxx +++ b/Source/cmGraphVizWriter.cxx @@ -2,174 +2,190 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmGraphVizWriter.h" -#include <cstddef> +#include <cctype> #include <iostream> #include <memory> -#include <sstream> +#include <set> #include <utility> +#include <cm/memory> + #include "cmGeneratedFileStream.h" #include "cmGeneratorTarget.h" #include "cmGlobalGenerator.h" +#include "cmLinkItem.h" #include "cmLocalGenerator.h" #include "cmMakefile.h" #include "cmState.h" #include "cmStateSnapshot.h" #include "cmStringAlgorithms.h" #include "cmSystemTools.h" -#include "cmTarget.h" #include "cmake.h" namespace { -enum LinkLibraryScopeType -{ - LLT_SCOPE_PUBLIC, - LLT_SCOPE_PRIVATE, - LLT_SCOPE_INTERFACE -}; -const char* const GRAPHVIZ_PRIVATE_EDEGE_STYLE = "dashed"; -const char* const GRAPHVIZ_INTERFACE_EDEGE_STYLE = "dotted"; +char const* const GRAPHVIZ_EDGE_STYLE_PUBLIC = "solid"; +char const* const GRAPHVIZ_EDGE_STYLE_INTERFACE = "dashed"; +char const* const GRAPHVIZ_EDGE_STYLE_PRIVATE = "dotted"; -std::string getLinkLibraryStyle(const LinkLibraryScopeType& type) -{ - std::string style; - switch (type) { - case LLT_SCOPE_PRIVATE: - style = "[style = " + std::string(GRAPHVIZ_PRIVATE_EDEGE_STYLE) + "]"; - break; - case LLT_SCOPE_INTERFACE: - style = "[style = " + std::string(GRAPHVIZ_INTERFACE_EDEGE_STYLE) + "]"; - break; - default: - break; - } - return style; -} +char const* const GRAPHVIZ_NODE_SHAPE_EXECUTABLE = "egg"; // egg-xecutable + +// Normal libraries. +char const* const GRAPHVIZ_NODE_SHAPE_LIBRARY_STATIC = "octagon"; +char const* const GRAPHVIZ_NODE_SHAPE_LIBRARY_SHARED = "doubleoctagon"; +char const* const GRAPHVIZ_NODE_SHAPE_LIBRARY_MODULE = "tripleoctagon"; -const char* getShapeForTarget(const cmGeneratorTarget* target) +char const* const GRAPHVIZ_NODE_SHAPE_LIBRARY_INTERFACE = "pentagon"; +char const* const GRAPHVIZ_NODE_SHAPE_LIBRARY_OBJECT = "hexagon"; +char const* const GRAPHVIZ_NODE_SHAPE_LIBRARY_UNKNOWN = "septagon"; + +char const* const GRAPHVIZ_NODE_SHAPE_UTILITY = "box"; + +const char* getShapeForTarget(const cmLinkItem& item) { - if (!target) { - return "ellipse"; + if (item.Target == nullptr) { + return GRAPHVIZ_NODE_SHAPE_LIBRARY_UNKNOWN; } - switch (target->GetType()) { + switch (item.Target->GetType()) { case cmStateEnums::EXECUTABLE: - return "house"; + return GRAPHVIZ_NODE_SHAPE_EXECUTABLE; case cmStateEnums::STATIC_LIBRARY: - return "diamond"; + return GRAPHVIZ_NODE_SHAPE_LIBRARY_STATIC; case cmStateEnums::SHARED_LIBRARY: - return "polygon"; + return GRAPHVIZ_NODE_SHAPE_LIBRARY_SHARED; case cmStateEnums::MODULE_LIBRARY: - return "octagon"; + return GRAPHVIZ_NODE_SHAPE_LIBRARY_MODULE; + case cmStateEnums::OBJECT_LIBRARY: + return GRAPHVIZ_NODE_SHAPE_LIBRARY_OBJECT; + case cmStateEnums::UTILITY: + return GRAPHVIZ_NODE_SHAPE_UTILITY; + case cmStateEnums::INTERFACE_LIBRARY: + return GRAPHVIZ_NODE_SHAPE_LIBRARY_INTERFACE; + case cmStateEnums::UNKNOWN_LIBRARY: default: - break; + return GRAPHVIZ_NODE_SHAPE_LIBRARY_UNKNOWN; } +} +} - return "box"; +cmGraphVizWriter::cmGraphVizWriter(std::string const& fileName, + const cmGlobalGenerator* globalGenerator) + : FileName(fileName) + , GlobalFileStream(fileName) + , GraphName(globalGenerator->GetSafeGlobalSetting("CMAKE_PROJECT_NAME")) + , GraphHeader("node [\n fontsize = \"12\"\n];") + , GraphNodePrefix("node") + , GlobalGenerator(globalGenerator) + , NextNodeId(0) + , GenerateForExecutables(true) + , GenerateForStaticLibs(true) + , GenerateForSharedLibs(true) + , GenerateForModuleLibs(true) + , GenerateForInterfaceLibs(true) + , GenerateForObjectLibs(true) + , GenerateForUnknownLibs(true) + , GenerateForCustomTargets(false) + , GenerateForExternals(true) + , GeneratePerTarget(true) + , GenerateDependers(true) +{ } -std::map<std::string, LinkLibraryScopeType> getScopedLinkLibrariesFromTarget( - cmTarget* Target, const cmGlobalGenerator* globalGenerator) +cmGraphVizWriter::~cmGraphVizWriter() { - char sep = ';'; - std::map<std::string, LinkLibraryScopeType> tokens; - size_t start = 0; - size_t end = 0; + this->WriteFooter(this->GlobalFileStream); - const char* pInterfaceLinkLibraries = - Target->GetProperty("INTERFACE_LINK_LIBRARIES"); - const char* pLinkLibraries = Target->GetProperty("LINK_LIBRARIES"); + for (auto& fileStream : this->PerTargetFileStreams) { + this->WriteFooter(*fileStream.second); + } - if (!pInterfaceLinkLibraries && !pLinkLibraries) { - return tokens; // target is not linked against any other libraries + for (auto& fileStream : this->TargetDependersFileStreams) { + this->WriteFooter(*fileStream.second); } +} - // make sure we don't touch a null-ptr - auto interfaceLinkLibraries = - std::string(pInterfaceLinkLibraries ? pInterfaceLinkLibraries : ""); - auto linkLibraries = std::string(pLinkLibraries ? pLinkLibraries : ""); +void cmGraphVizWriter::VisitGraph(std::string const&) +{ + this->WriteHeader(GlobalFileStream, this->GraphName); + this->WriteLegend(GlobalFileStream); +} - // first extract interfaceLinkLibraries - while (start < interfaceLinkLibraries.length()) { +void cmGraphVizWriter::OnItem(cmLinkItem const& item) +{ + if (this->ItemExcluded(item)) { + return; + } - if ((end = interfaceLinkLibraries.find(sep, start)) == std::string::npos) { - end = interfaceLinkLibraries.length(); - } + NodeNames[item.AsStr()] = cmStrCat(GraphNodePrefix, NextNodeId); + ++NextNodeId; - std::string element = interfaceLinkLibraries.substr(start, end - start); - if (globalGenerator->IsAlias(element)) { - const auto tgt = globalGenerator->FindTarget(element); - if (tgt) { - element = tgt->GetName(); - } - } + this->WriteNode(this->GlobalFileStream, item); - if (std::string::npos == element.find("$<LINK_ONLY:", 0)) { - // we assume first, that this library is an interface library. - // if we find it again in the linklibraries property, we promote it to an - // public library. - tokens[element] = LLT_SCOPE_INTERFACE; - } else { - // this is an private linked static library. - // we take care of this case in the second iterator. - } - start = end + 1; + if (this->GeneratePerTarget) { + this->CreateTargetFile(this->PerTargetFileStreams, item); } - // second extract linkLibraries - start = 0; - while (start < linkLibraries.length()) { - - if ((end = linkLibraries.find(sep, start)) == std::string::npos) { - end = linkLibraries.length(); - } + if (this->GenerateDependers) { + this->CreateTargetFile(this->TargetDependersFileStreams, item, + ".dependers"); + } +} - std::string element = linkLibraries.substr(start, end - start); - if (globalGenerator->IsAlias(element)) { - const auto tgt = globalGenerator->FindTarget(element); - if (tgt) { - element = tgt->GetName(); - } - } +void cmGraphVizWriter::CreateTargetFile(FileStreamMap& fileStreamMap, + cmLinkItem const& item, + std::string const& fileNameSuffix) +{ + auto const pathSafeItemName = PathSafeString(item.AsStr()); + auto const perTargetFileName = + cmStrCat(this->FileName, '.', pathSafeItemName, fileNameSuffix); + auto perTargetFileStream = + cm::make_unique<cmGeneratedFileStream>(perTargetFileName); - if (tokens.find(element) == tokens.end()) { - // this library is not found in interfaceLinkLibraries but in - // linkLibraries. - // this results in a private linked library. - tokens[element] = LLT_SCOPE_PRIVATE; - } else if (LLT_SCOPE_INTERFACE == tokens[element]) { - // this library is found in interfaceLinkLibraries and linkLibraries. - // this results in a public linked library. - tokens[element] = LLT_SCOPE_PUBLIC; - } else { - // private and public linked libraries should not be changed anymore. - } + this->WriteHeader(*perTargetFileStream, item.AsStr()); + this->WriteNode(*perTargetFileStream, item); - start = end + 1; - } + fileStreamMap.emplace(item.AsStr(), std::move(perTargetFileStream)); +} - return tokens; +void cmGraphVizWriter::OnDirectLink(cmLinkItem const& depender, + cmLinkItem const& dependee, + DependencyType dt) +{ + this->VisitLink(depender, dependee, true, GetEdgeStyle(dt)); } + +void cmGraphVizWriter::OnIndirectLink(cmLinkItem const& depender, + cmLinkItem const& dependee) +{ + this->VisitLink(depender, dependee, false); } -cmGraphVizWriter::cmGraphVizWriter(const cmGlobalGenerator* globalGenerator) - : GraphType("digraph") - , GraphName("GG") - , GraphHeader("node [\n fontsize = \"12\"\n];") - , GraphNodePrefix("node") - , GlobalGenerator(globalGenerator) - , LocalGenerators(globalGenerator->GetLocalGenerators()) - , GenerateForExecutables(true) - , GenerateForStaticLibs(true) - , GenerateForSharedLibs(true) - , GenerateForModuleLibs(true) - , GenerateForInterface(true) - , GenerateForExternals(true) - , GeneratePerTarget(true) - , GenerateDependers(true) - , HaveTargetsAndLibs(false) +void cmGraphVizWriter::VisitLink(cmLinkItem const& depender, + cmLinkItem const& dependee, bool isDirectLink, + std::string const& scopeType) { + if (this->ItemExcluded(depender) || this->ItemExcluded(dependee)) { + return; + } + + if (!isDirectLink) { + return; + } + + this->WriteConnection(this->GlobalFileStream, depender, dependee, scopeType); + + if (this->GeneratePerTarget) { + auto fileStream = PerTargetFileStreams[depender.AsStr()].get(); + this->WriteNode(*fileStream, dependee); + this->WriteConnection(*fileStream, depender, dependee, scopeType); + } + + if (this->GenerateDependers) { + auto fileStream = TargetDependersFileStreams[dependee.AsStr()].get(); + this->WriteNode(*fileStream, depender); + this->WriteConnection(*fileStream, depender, dependee, scopeType); + } } void cmGraphVizWriter::ReadSettings( @@ -208,7 +224,6 @@ void cmGraphVizWriter::ReadSettings( } \ } while (false) - __set_if_set(this->GraphType, "GRAPHVIZ_GRAPH_TYPE"); __set_if_set(this->GraphName, "GRAPHVIZ_GRAPH_NAME"); __set_if_set(this->GraphHeader, "GRAPHVIZ_GRAPH_HEADER"); __set_if_set(this->GraphNodePrefix, "GRAPHVIZ_NODE_PREFIX"); @@ -225,7 +240,10 @@ void cmGraphVizWriter::ReadSettings( __set_bool_if_set(this->GenerateForStaticLibs, "GRAPHVIZ_STATIC_LIBS"); __set_bool_if_set(this->GenerateForSharedLibs, "GRAPHVIZ_SHARED_LIBS"); __set_bool_if_set(this->GenerateForModuleLibs, "GRAPHVIZ_MODULE_LIBS"); - __set_bool_if_set(this->GenerateForInterface, "GRAPHVIZ_INTERFACE"); + __set_bool_if_set(this->GenerateForInterfaceLibs, "GRAPHVIZ_INTERFACE_LIBS"); + __set_bool_if_set(this->GenerateForObjectLibs, "GRAPHVIZ_OBJECT_LIBS"); + __set_bool_if_set(this->GenerateForUnknownLibs, "GRAPHVIZ_UNKNOWN_LIBS"); + __set_bool_if_set(this->GenerateForCustomTargets, "GRAPHVIZ_CUSTOM_TARGETS"); __set_bool_if_set(this->GenerateForExternals, "GRAPHVIZ_EXTERNAL_LIBS"); __set_bool_if_set(this->GeneratePerTarget, "GRAPHVIZ_GENERATE_PER_TARGET"); __set_bool_if_set(this->GenerateDependers, "GRAPHVIZ_GENERATE_DEPENDERS"); @@ -248,329 +266,170 @@ void cmGraphVizWriter::ReadSettings( } } -// Iterate over all targets and write for each one a graph which shows -// which other targets depend on it. -void cmGraphVizWriter::WriteTargetDependersFiles(const std::string& fileName) +void cmGraphVizWriter::Write() { - if (!this->GenerateDependers) { - return; - } - - this->CollectTargetsAndLibs(); - - for (auto const& ptr : this->TargetPtrs) { - if (ptr.second == nullptr) { - continue; - } - - if (!this->GenerateForTargetType(ptr.second->GetType())) { - continue; - } - - std::string currentFilename = - cmStrCat(fileName, '.', ptr.first, ".dependers"); - - cmGeneratedFileStream str(currentFilename); - if (!str) { - return; + auto gg = this->GlobalGenerator; + + this->VisitGraph(gg->GetName()); + + // We want to traverse in a determined order, such that the output is always + // the same for a given project (this makes tests reproducible, etc.) + std::set<cmGeneratorTarget const*, cmGeneratorTarget::StrictTargetComparison> + sortedGeneratorTargets; + + for (const auto& lg : gg->GetLocalGenerators()) { + for (const auto& gt : lg->GetGeneratorTargets()) { + // Reserved targets have inconsistent names across platforms (e.g. 'all' + // vs. 'ALL_BUILD'), which can disrupt the traversal ordering. + // We don't need or want them anyway. + if (!cmGlobalGenerator::IsReservedTarget(gt->GetName())) { + sortedGeneratorTargets.insert(gt.get()); + } } - - std::set<std::string> insertedConnections; - std::set<std::string> insertedNodes; - - std::cout << "Writing " << currentFilename << "..." << std::endl; - this->WriteHeader(str); - - this->WriteDependerConnections(ptr.first, insertedNodes, - insertedConnections, str); - - this->WriteFooter(str); - } -} - -// Iterate over all targets and write for each one a graph which shows -// on which targets it depends. -void cmGraphVizWriter::WritePerTargetFiles(const std::string& fileName) -{ - if (!this->GeneratePerTarget) { - return; } - this->CollectTargetsAndLibs(); - - for (auto const& ptr : this->TargetPtrs) { - if (ptr.second == nullptr) { - continue; - } - - if (!this->GenerateForTargetType(ptr.second->GetType())) { - continue; - } - - std::set<std::string> insertedConnections; - std::set<std::string> insertedNodes; - - std::string currentFilename = cmStrCat(fileName, '.', ptr.first); - cmGeneratedFileStream str(currentFilename); - if (!str) { - return; - } - - std::cout << "Writing " << currentFilename << "..." << std::endl; - this->WriteHeader(str); - - this->WriteConnections(ptr.first, insertedNodes, insertedConnections, str); - this->WriteFooter(str); + for (auto const gt : sortedGeneratorTargets) { + auto item = cmLinkItem(gt, gt->GetBacktrace()); + this->VisitItem(item); } } -void cmGraphVizWriter::WriteGlobalFile(const std::string& fileName) +void cmGraphVizWriter::WriteHeader(cmGeneratedFileStream& fs, + const std::string& name) { - this->CollectTargetsAndLibs(); - - cmGeneratedFileStream str(fileName); - if (!str) { - return; - } - this->WriteHeader(str); - - std::cout << "Writing " << fileName << "..." << std::endl; - - std::set<std::string> insertedConnections; - std::set<std::string> insertedNodes; - - for (auto const& ptr : this->TargetPtrs) { - if (ptr.second == nullptr) { - continue; - } - - if (!this->GenerateForTargetType(ptr.second->GetType())) { - continue; - } - - this->WriteConnections(ptr.first, insertedNodes, insertedConnections, str); - } - this->WriteFooter(str); + auto const escapedGraphName = EscapeForDotFile(name); + fs << "digraph \"" << escapedGraphName << "\" {" << std::endl; + fs << this->GraphHeader << std::endl; } -void cmGraphVizWriter::WriteHeader(cmGeneratedFileStream& str) const +void cmGraphVizWriter::WriteFooter(cmGeneratedFileStream& fs) { - str << this->GraphType << " \"" << this->GraphName << "\" {" << std::endl; - str << this->GraphHeader << std::endl; + fs << "}" << std::endl; } -void cmGraphVizWriter::WriteFooter(cmGeneratedFileStream& str) const +void cmGraphVizWriter::WriteLegend(cmGeneratedFileStream& fs) { - str << "}" << std::endl; + // Note that the subgraph name must start with "cluster", as done here, to + // make Graphviz layout engines do the right thing and keep the nodes + // together. + fs << "subgraph clusterLegend {" << std::endl; + fs << " label = \"Legend\";" << std::endl; + // Set the color of the box surrounding the legend. + fs << " color = black;" << std::endl; + // We use invisible edges just to enforce the layout. + fs << " edge [ style = invis ];" << std::endl; + + // Nodes. + fs << " legendNode0 [ label = \"Executable\", shape = " + << GRAPHVIZ_NODE_SHAPE_EXECUTABLE << " ];" << std::endl; + + fs << " legendNode1 [ label = \"Static Library\", shape = " + << GRAPHVIZ_NODE_SHAPE_LIBRARY_STATIC << " ];" << std::endl; + fs << " legendNode2 [ label = \"Shared Library\", shape = " + << GRAPHVIZ_NODE_SHAPE_LIBRARY_SHARED << " ];" << std::endl; + fs << " legendNode3 [ label = \"Module Library\", shape = " + << GRAPHVIZ_NODE_SHAPE_LIBRARY_MODULE << " ];" << std::endl; + + fs << " legendNode4 [ label = \"Interface Library\", shape = " + << GRAPHVIZ_NODE_SHAPE_LIBRARY_INTERFACE << " ];" << std::endl; + fs << " legendNode5 [ label = \"Object Library\", shape = " + << GRAPHVIZ_NODE_SHAPE_LIBRARY_OBJECT << " ];" << std::endl; + fs << " legendNode6 [ label = \"Unknown Library\", shape = " + << GRAPHVIZ_NODE_SHAPE_LIBRARY_UNKNOWN << " ];" << std::endl; + + fs << " legendNode7 [ label = \"Custom Target\", shape = " + << GRAPHVIZ_NODE_SHAPE_UTILITY << " ];" << std::endl; + + // Edges. + // Some of those are dummy (invisible) edges to enforce a layout. + fs << " legendNode0 -> legendNode1 [ style = " << GRAPHVIZ_EDGE_STYLE_PUBLIC + << " ];" << std::endl; + fs << " legendNode0 -> legendNode2 [ style = " << GRAPHVIZ_EDGE_STYLE_PUBLIC + << " ];" << std::endl; + fs << " legendNode0 -> legendNode3;" << std::endl; + + fs << " legendNode1 -> legendNode4 [ label = \"Interface\", style = " + << GRAPHVIZ_EDGE_STYLE_INTERFACE << " ];" << std::endl; + fs << " legendNode2 -> legendNode5 [ label = \"Private\", style = " + << GRAPHVIZ_EDGE_STYLE_PRIVATE << " ];" << std::endl; + fs << " legendNode3 -> legendNode6 [ style = " << GRAPHVIZ_EDGE_STYLE_PUBLIC + << " ];" << std::endl; + + fs << " legendNode0 -> legendNode7;" << std::endl; + + fs << "}" << std::endl; } -void cmGraphVizWriter::WriteConnections( - const std::string& targetName, std::set<std::string>& insertedNodes, - std::set<std::string>& insertedConnections, cmGeneratedFileStream& str) const +void cmGraphVizWriter::WriteNode(cmGeneratedFileStream& fs, + cmLinkItem const& item) { - auto targetPtrIt = this->TargetPtrs.find(targetName); + auto const& itemName = item.AsStr(); + auto const& nodeName = this->NodeNames[itemName]; - if (targetPtrIt == this->TargetPtrs.end()) // not found at all - { - return; - } - - this->WriteNode(targetName, targetPtrIt->second, insertedNodes, str); - - if (targetPtrIt->second == nullptr) // it's an external library - { - return; - } + auto const itemNameWithAliases = ItemNameWithAliases(itemName); + auto const escapedLabel = EscapeForDotFile(itemNameWithAliases); - std::string myNodeName = this->TargetNamesNodes.find(targetName)->second; - std::map<std::string, LinkLibraryScopeType> ll = - getScopedLinkLibrariesFromTarget(targetPtrIt->second->Target, - GlobalGenerator); - - for (auto const& llit : ll) { - const std::string& libName = llit.first; - auto libNameIt = this->TargetNamesNodes.find(libName); - - // can happen e.g. if GRAPHVIZ_TARGET_IGNORE_REGEX is used - if (libNameIt == this->TargetNamesNodes.end()) { - continue; - } + fs << " \"" << nodeName << "\" [ label = \"" << escapedLabel + << "\", shape = " << getShapeForTarget(item) << " ];" << std::endl; +} - std::string connectionName = cmStrCat(myNodeName, '-', libNameIt->second); - if (insertedConnections.find(connectionName) == - insertedConnections.end()) { - insertedConnections.insert(connectionName); - this->WriteNode(libName, this->TargetPtrs.find(libName)->second, - insertedNodes, str); +void cmGraphVizWriter::WriteConnection(cmGeneratedFileStream& fs, + cmLinkItem const& depender, + cmLinkItem const& dependee, + std::string const& edgeStyle) +{ + auto const& dependerName = depender.AsStr(); + auto const& dependeeName = dependee.AsStr(); - str << " \"" << myNodeName << "\" -> \"" << libNameIt->second << "\""; + fs << " \"" << this->NodeNames[dependerName] << "\" -> \"" + << this->NodeNames[dependeeName] << "\" "; - str << getLinkLibraryStyle(llit.second); + fs << edgeStyle; - str << " // " << targetName << " -> " << libName << std::endl; - this->WriteConnections(libName, insertedNodes, insertedConnections, str); - } - } + fs << " // " << dependerName << " -> " << dependeeName << std::endl; } -void cmGraphVizWriter::WriteDependerConnections( - const std::string& targetName, std::set<std::string>& insertedNodes, - std::set<std::string>& insertedConnections, cmGeneratedFileStream& str) const +bool cmGraphVizWriter::ItemExcluded(cmLinkItem const& item) { - auto targetPtrIt = this->TargetPtrs.find(targetName); + auto const itemName = item.AsStr(); - if (targetPtrIt == this->TargetPtrs.end()) // not found at all - { - return; + if (this->ItemNameFilteredOut(itemName)) { + return true; } - this->WriteNode(targetName, targetPtrIt->second, insertedNodes, str); - - if (targetPtrIt->second == nullptr) // it's an external library - { - return; + if (item.Target == nullptr) { + return !this->GenerateForExternals; } - std::string myNodeName = this->TargetNamesNodes.find(targetName)->second; - - // now search who links against me - for (auto const& tptr : this->TargetPtrs) { - if (tptr.second == nullptr) { - continue; - } - - if (!this->GenerateForTargetType(tptr.second->GetType())) { - continue; - } - - // Now we have a target, check whether it links against targetName. - // If so, draw a connection, and then continue with dependers on that one. - std::map<std::string, LinkLibraryScopeType> ll = - getScopedLinkLibrariesFromTarget(tptr.second->Target, GlobalGenerator); - - for (auto const& llit : ll) { - if (llit.first == targetName) { - // So this target links against targetName. - auto dependerNodeNameIt = this->TargetNamesNodes.find(tptr.first); - - if (dependerNodeNameIt != this->TargetNamesNodes.end()) { - std::string connectionName = - cmStrCat(dependerNodeNameIt->second, '-', myNodeName); - - if (insertedConnections.find(connectionName) == - insertedConnections.end()) { - insertedConnections.insert(connectionName); - this->WriteNode(tptr.first, tptr.second, insertedNodes, str); - - str << " \"" << dependerNodeNameIt->second << "\" -> \"" - << myNodeName << "\""; - str << " // " << targetName << " -> " << tptr.first << std::endl; - str << getLinkLibraryStyle(llit.second); - this->WriteDependerConnections(tptr.first, insertedNodes, - insertedConnections, str); - } - } - break; - } + if (item.Target->GetType() == cmStateEnums::UTILITY) { + if ((itemName.find("Nightly") == 0) || + (itemName.find("Continuous") == 0) || + (itemName.find("Experimental") == 0)) { + return true; } } -} -void cmGraphVizWriter::WriteNode(const std::string& targetName, - const cmGeneratorTarget* target, - std::set<std::string>& insertedNodes, - cmGeneratedFileStream& str) const -{ - if (insertedNodes.find(targetName) == insertedNodes.end()) { - insertedNodes.insert(targetName); - auto nameIt = this->TargetNamesNodes.find(targetName); - - str << " \"" << nameIt->second << "\" [ label=\"" << targetName - << "\" shape=\"" << getShapeForTarget(target) << "\"];" << std::endl; + if (item.Target->IsImported() && !this->GenerateForExternals) { + return true; } -} -void cmGraphVizWriter::CollectTargetsAndLibs() -{ - if (!this->HaveTargetsAndLibs) { - this->HaveTargetsAndLibs = true; - int cnt = this->CollectAllTargets(); - if (this->GenerateForExternals) { - this->CollectAllExternalLibs(cnt); - } - } + return !this->TargetTypeEnabled(item.Target->GetType()); } -int cmGraphVizWriter::CollectAllTargets() +bool cmGraphVizWriter::ItemNameFilteredOut(std::string const& itemName) { - int cnt = 0; - // First pass get the list of all cmake targets - for (cmLocalGenerator* lg : this->LocalGenerators) { - const std::vector<cmGeneratorTarget*>& targets = lg->GetGeneratorTargets(); - for (cmGeneratorTarget* target : targets) { - const std::string& realTargetName = target->GetName(); - if (this->IgnoreThisTarget(realTargetName)) { - // Skip ignored targets - continue; - } - // std::cout << "Found target: " << tit->first << std::endl; - std::ostringstream ostr; - ostr << this->GraphNodePrefix << cnt++; - this->TargetNamesNodes[realTargetName] = ostr.str(); - this->TargetPtrs[realTargetName] = target; - } + if (itemName == ">") { + // FIXME: why do we even receive such a target here? + return true; } - return cnt; -} - -int cmGraphVizWriter::CollectAllExternalLibs(int cnt) -{ - // Ok, now find all the stuff we link to that is not in cmake - for (cmLocalGenerator* lg : this->LocalGenerators) { - const std::vector<cmGeneratorTarget*>& targets = lg->GetGeneratorTargets(); - for (cmGeneratorTarget* target : targets) { - const std::string& realTargetName = target->GetName(); - if (this->IgnoreThisTarget(realTargetName)) { - // Skip ignored targets - continue; - } - const cmTarget::LinkLibraryVectorType* ll = - &(target->Target->GetOriginalLinkLibraries()); - for (auto const& llit : *ll) { - std::string libName = llit.first; - if (this->IgnoreThisTarget(libName)) { - // Skip ignored targets - continue; - } - - if (GlobalGenerator->IsAlias(libName)) { - const auto tgt = GlobalGenerator->FindTarget(libName); - if (tgt) { - libName = tgt->GetName(); - } - } - - auto tarIt = this->TargetPtrs.find(libName); - if (tarIt == this->TargetPtrs.end()) { - std::ostringstream ostr; - ostr << this->GraphNodePrefix << cnt++; - this->TargetNamesNodes[libName] = ostr.str(); - this->TargetPtrs[libName] = nullptr; - // str << " \"" << ostr << "\" [ label=\"" << libName - // << "\" shape=\"ellipse\"];" << std::endl; - } - } - } + if (cmGlobalGenerator::IsReservedTarget(itemName)) { + return true; } - return cnt; -} -bool cmGraphVizWriter::IgnoreThisTarget(const std::string& name) -{ for (cmsys::RegularExpression& regEx : this->TargetsToIgnoreRegex) { if (regEx.is_valid()) { - if (regEx.find(name)) { + if (regEx.find(itemName)) { return true; } } @@ -579,7 +438,7 @@ bool cmGraphVizWriter::IgnoreThisTarget(const std::string& name) return false; } -bool cmGraphVizWriter::GenerateForTargetType( +bool cmGraphVizWriter::TargetTypeEnabled( cmStateEnums::TargetType targetType) const { switch (targetType) { @@ -592,9 +451,73 @@ bool cmGraphVizWriter::GenerateForTargetType( case cmStateEnums::MODULE_LIBRARY: return this->GenerateForModuleLibs; case cmStateEnums::INTERFACE_LIBRARY: - return this->GenerateForInterface; + return this->GenerateForInterfaceLibs; + case cmStateEnums::OBJECT_LIBRARY: + return this->GenerateForObjectLibs; + case cmStateEnums::UNKNOWN_LIBRARY: + return this->GenerateForUnknownLibs; + case cmStateEnums::UTILITY: + return this->GenerateForCustomTargets; + case cmStateEnums::GLOBAL_TARGET: + // Built-in targets like edit_cache, etc. + // We don't need/want those in the dot file. + return false; default: break; } return false; } + +std::string cmGraphVizWriter::ItemNameWithAliases( + std::string const& itemName) const +{ + auto nameWithAliases = itemName; + + for (auto const& lg : this->GlobalGenerator->GetLocalGenerators()) { + for (auto const& aliasTargets : lg->GetMakefile()->GetAliasTargets()) { + if (aliasTargets.second == itemName) { + nameWithAliases += "\\n(" + aliasTargets.first + ")"; + } + } + } + + return nameWithAliases; +} + +std::string cmGraphVizWriter::GetEdgeStyle(DependencyType dt) +{ + std::string style; + switch (dt) { + case DependencyType::LinkPrivate: + style = "[ style = " + std::string(GRAPHVIZ_EDGE_STYLE_PRIVATE) + " ]"; + break; + case DependencyType::LinkInterface: + style = "[ style = " + std::string(GRAPHVIZ_EDGE_STYLE_INTERFACE) + " ]"; + break; + default: + break; + } + return style; +} + +std::string cmGraphVizWriter::EscapeForDotFile(std::string const& str) +{ + return cmSystemTools::EscapeChars(str.data(), "\""); +} + +std::string cmGraphVizWriter::PathSafeString(std::string const& str) +{ + std::string pathSafeStr; + + // We'll only keep alphanumerical characters, plus the following ones that + // are common, and safe on all platforms: + auto const extra_chars = std::set<char>{ '.', '-', '_' }; + + for (char c : str) { + if (std::isalnum(c) || extra_chars.find(c) != extra_chars.cend()) { + pathSafeStr += c; + } + } + + return pathSafeStr; +} diff --git a/Source/cmGraphVizWriter.h b/Source/cmGraphVizWriter.h index 9c3051f..578660d 100644 --- a/Source/cmGraphVizWriter.h +++ b/Source/cmGraphVizWriter.h @@ -6,87 +6,106 @@ #include "cmConfigure.h" // IWYU pragma: keep #include <map> -#include <set> +#include <memory> #include <string> #include <vector> #include "cmsys/RegularExpression.hxx" +#include "cmGeneratedFileStream.h" +#include "cmLinkItemGraphVisitor.h" #include "cmStateTypes.h" -class cmGeneratedFileStream; -class cmGeneratorTarget; -class cmLocalGenerator; +class cmLinkItem; class cmGlobalGenerator; /** This class implements writing files for graphviz (dot) for graphs * representing the dependencies between the targets in the project. */ -class cmGraphVizWriter +class cmGraphVizWriter : public cmLinkItemGraphVisitor { public: - cmGraphVizWriter(const cmGlobalGenerator* globalGenerator); + cmGraphVizWriter(std::string const& fileName, + const cmGlobalGenerator* globalGenerator); + ~cmGraphVizWriter() override; + + void VisitGraph(std::string const& name) override; + + void OnItem(cmLinkItem const& item) override; + + void OnDirectLink(cmLinkItem const& depender, cmLinkItem const& dependee, + DependencyType dt) override; + + void OnIndirectLink(cmLinkItem const& depender, + cmLinkItem const& dependee) override; void ReadSettings(const std::string& settingsFileName, const std::string& fallbackSettingsFileName); - void WritePerTargetFiles(const std::string& fileName); - void WriteTargetDependersFiles(const std::string& fileName); + void Write(); + +private: + using FileStreamMap = + std::map<std::string, std::unique_ptr<cmGeneratedFileStream>>; + + void VisitLink(cmLinkItem const& depender, cmLinkItem const& dependee, + bool isDirectLink, std::string const& scopeType = ""); + + void WriteHeader(cmGeneratedFileStream& fs, std::string const& name); - void WriteGlobalFile(const std::string& fileName); + void WriteFooter(cmGeneratedFileStream& fs); -protected: - void CollectTargetsAndLibs(); + void WriteLegend(cmGeneratedFileStream& fs); - int CollectAllTargets(); + void WriteNode(cmGeneratedFileStream& fs, cmLinkItem const& item); - int CollectAllExternalLibs(int cnt); + void CreateTargetFile(FileStreamMap& fileStreamMap, cmLinkItem const& target, + std::string const& fileNameSuffix = ""); - void WriteHeader(cmGeneratedFileStream& str) const; + void WriteConnection(cmGeneratedFileStream& fs, + cmLinkItem const& dependerTargetName, + cmLinkItem const& dependeeTargetName, + std::string const& edgeStyle); - void WriteConnections(const std::string& targetName, - std::set<std::string>& insertedNodes, - std::set<std::string>& insertedConnections, - cmGeneratedFileStream& str) const; + bool ItemExcluded(cmLinkItem const& item); + bool ItemNameFilteredOut(std::string const& itemName); + bool TargetTypeEnabled(cmStateEnums::TargetType targetType) const; - void WriteDependerConnections(const std::string& targetName, - std::set<std::string>& insertedNodes, - std::set<std::string>& insertedConnections, - cmGeneratedFileStream& str) const; + std::string ItemNameWithAliases(std::string const& itemName) const; - void WriteNode(const std::string& targetName, - const cmGeneratorTarget* target, - std::set<std::string>& insertedNodes, - cmGeneratedFileStream& str) const; + static std::string GetEdgeStyle(DependencyType dt); - void WriteFooter(cmGeneratedFileStream& str) const; + static std::string EscapeForDotFile(std::string const& str); - bool IgnoreThisTarget(const std::string& name); + static std::string PathSafeString(std::string const& str); - bool GenerateForTargetType(cmStateEnums::TargetType targetType) const; + std::string FileName; + cmGeneratedFileStream GlobalFileStream; + FileStreamMap PerTargetFileStreams; + FileStreamMap TargetDependersFileStreams; - std::string GraphType; std::string GraphName; std::string GraphHeader; std::string GraphNodePrefix; std::vector<cmsys::RegularExpression> TargetsToIgnoreRegex; - const cmGlobalGenerator* GlobalGenerator; - const std::vector<cmLocalGenerator*>& LocalGenerators; + cmGlobalGenerator const* GlobalGenerator; - std::map<std::string, const cmGeneratorTarget*> TargetPtrs; - // maps from the actual target names to node names in dot: - std::map<std::string, std::string> TargetNamesNodes; + int NextNodeId; + // maps from the actual item names to node names in dot: + std::map<std::string, std::string> NodeNames; bool GenerateForExecutables; bool GenerateForStaticLibs; bool GenerateForSharedLibs; bool GenerateForModuleLibs; - bool GenerateForInterface; + bool GenerateForInterfaceLibs; + bool GenerateForObjectLibs; + bool GenerateForUnknownLibs; + bool GenerateForCustomTargets; bool GenerateForExternals; bool GeneratePerTarget; bool GenerateDependers; - bool HaveTargetsAndLibs; }; #endif diff --git a/Source/cmIDEOptions.cxx b/Source/cmIDEOptions.cxx index 71326d2..b53319f 100644 --- a/Source/cmIDEOptions.cxx +++ b/Source/cmIDEOptions.cxx @@ -4,6 +4,8 @@ #include <iterator> +#include <cmext/algorithm> + #include <string.h> #include "cmsys/String.h" @@ -173,7 +175,7 @@ void cmIDEOptions::AddDefines(std::string const& defines) } void cmIDEOptions::AddDefines(const std::vector<std::string>& defines) { - cmAppend(this->Defines, defines); + cm::append(this->Defines, defines); } std::vector<std::string> const& cmIDEOptions::GetDefines() const @@ -195,7 +197,7 @@ void cmIDEOptions::AddIncludes(std::string const& includes) } void cmIDEOptions::AddIncludes(const std::vector<std::string>& includes) { - cmAppend(this->Includes, includes); + cm::append(this->Includes, includes); } std::vector<std::string> const& cmIDEOptions::GetIncludes() const diff --git a/Source/cmIncludeDirectoryCommand.cxx b/Source/cmIncludeDirectoryCommand.cxx index 170aea1..b408f72 100644 --- a/Source/cmIncludeDirectoryCommand.cxx +++ b/Source/cmIncludeDirectoryCommand.cxx @@ -6,7 +6,8 @@ #include <set> #include <utility> -#include "cmAlgorithms.h" +#include <cmext/algorithm> + #include "cmExecutionStatus.h" #include "cmGeneratorExpression.h" #include "cmMakefile.h" @@ -58,9 +59,9 @@ bool cmIncludeDirectoryCommand(std::vector<std::string> const& args, GetIncludes(mf, *i, includes); if (before) { - cmAppend(beforeIncludes, includes); + cm::append(beforeIncludes, includes); } else { - cmAppend(afterIncludes, includes); + cm::append(afterIncludes, includes); } if (system) { systemIncludes.insert(includes.begin(), includes.end()); diff --git a/Source/cmIncludeExternalMSProjectCommand.cxx b/Source/cmIncludeExternalMSProjectCommand.cxx index fa1e8bc..e59c428 100644 --- a/Source/cmIncludeExternalMSProjectCommand.cxx +++ b/Source/cmIncludeExternalMSProjectCommand.cxx @@ -83,22 +83,21 @@ bool cmIncludeExternalMSProjectCommand(std::vector<std::string> const& args, } // Create a target instance for this utility. - cmTarget* target = - mf.AddNewTarget(cmStateEnums::UTILITY, utility_name.c_str()); + cmTarget* target = mf.AddNewTarget(cmStateEnums::UTILITY, utility_name); if (mf.GetPropertyAsBool("EXCLUDE_FROM_ALL")) { target->SetProperty("EXCLUDE_FROM_ALL", "TRUE"); } - target->SetProperty("GENERATOR_FILE_NAME", utility_name.c_str()); - target->SetProperty("EXTERNAL_MSPROJECT", path.c_str()); + target->SetProperty("GENERATOR_FILE_NAME", utility_name); + target->SetProperty("EXTERNAL_MSPROJECT", path); if (!customType.empty()) - target->SetProperty("VS_PROJECT_TYPE", customType.c_str()); + target->SetProperty("VS_PROJECT_TYPE", customType); if (!platformMapping.empty()) - target->SetProperty("VS_PLATFORM_MAPPING", platformMapping.c_str()); + target->SetProperty("VS_PLATFORM_MAPPING", platformMapping); for (std::string const& d : depends) { - target->AddUtility(d.c_str()); + target->AddUtility(d); } } #endif diff --git a/Source/cmInstallFilesCommand.cxx b/Source/cmInstallFilesCommand.cxx index d623943..efbcb98 100644 --- a/Source/cmInstallFilesCommand.cxx +++ b/Source/cmInstallFilesCommand.cxx @@ -7,11 +7,14 @@ #include "cmGlobalGenerator.h" #include "cmInstallFilesGenerator.h" #include "cmInstallGenerator.h" +#include "cmLocalGenerator.h" #include "cmMakefile.h" #include "cmRange.h" #include "cmStringAlgorithms.h" #include "cmSystemTools.h" +class cmListFileBacktrace; + static std::string FindInstallSource(cmMakefile& makefile, const char* name); static void CreateInstallGenerator(cmMakefile& makefile, std::string const& dest, @@ -43,9 +46,10 @@ bool cmInstallFilesCommand(std::vector<std::string> const& args, CreateInstallGenerator(mf, dest, files); } else { std::vector<std::string> finalArgs(args.begin() + 1, args.end()); - mf.AddFinalAction([dest, finalArgs](cmMakefile& makefile) { - FinalAction(makefile, dest, finalArgs); - }); + mf.AddGeneratorAction( + [dest, finalArgs](cmLocalGenerator& lg, const cmListFileBacktrace&) { + FinalAction(*lg.GetMakefile(), dest, finalArgs); + }); } mf.GetGlobalGenerator()->AddInstallComponent( diff --git a/Source/cmInstallProgramsCommand.cxx b/Source/cmInstallProgramsCommand.cxx index 6bb4409..2088eae 100644 --- a/Source/cmInstallProgramsCommand.cxx +++ b/Source/cmInstallProgramsCommand.cxx @@ -7,10 +7,13 @@ #include "cmGlobalGenerator.h" #include "cmInstallFilesGenerator.h" #include "cmInstallGenerator.h" +#include "cmLocalGenerator.h" #include "cmMakefile.h" #include "cmStringAlgorithms.h" #include "cmSystemTools.h" +class cmListFileBacktrace; + static void FinalAction(cmMakefile& makefile, std::string const& dest, std::vector<std::string> const& args); static std::string FindInstallSource(cmMakefile& makefile, const char* name); @@ -33,9 +36,10 @@ bool cmInstallProgramsCommand(std::vector<std::string> const& args, std::string const& dest = args[0]; std::vector<std::string> const finalArgs(args.begin() + 1, args.end()); - mf.AddFinalAction([dest, finalArgs](cmMakefile& makefile) { - FinalAction(makefile, dest, finalArgs); - }); + mf.AddGeneratorAction( + [dest, finalArgs](cmLocalGenerator& lg, const cmListFileBacktrace&) { + FinalAction(*lg.GetMakefile(), dest, finalArgs); + }); return true; } diff --git a/Source/cmInstallTargetGenerator.cxx b/Source/cmInstallTargetGenerator.cxx index aa92fa7..69c9b7e 100644 --- a/Source/cmInstallTargetGenerator.cxx +++ b/Source/cmInstallTargetGenerator.cxx @@ -554,7 +554,8 @@ void cmInstallTargetGenerator::AddInstallNamePatchRule( // components of the install_name field then we need to create a // mapping to be applied after installation. std::string for_build = tgt->GetInstallNameDirForBuildTree(config); - std::string for_install = tgt->GetInstallNameDirForInstallTree(); + std::string for_install = tgt->GetInstallNameDirForInstallTree( + config, "${CMAKE_INSTALL_PREFIX}"); if (for_build != for_install) { // The directory portions differ. Append the filename to // create the mapping. @@ -577,7 +578,8 @@ void cmInstallTargetGenerator::AddInstallNamePatchRule( if (this->Target->GetType() == cmStateEnums::SHARED_LIBRARY) { std::string for_build = this->Target->GetInstallNameDirForBuildTree(config); - std::string for_install = this->Target->GetInstallNameDirForInstallTree(); + std::string for_install = this->Target->GetInstallNameDirForInstallTree( + config, "${CMAKE_INSTALL_PREFIX}"); if (this->Target->IsFrameworkOnApple() && for_install.empty()) { // Frameworks seem to have an id corresponding to their own full diff --git a/Source/cmJsonObjects.cxx b/Source/cmJsonObjects.cxx index b23ab43..5f86d85 100644 --- a/Source/cmJsonObjects.cxx +++ b/Source/cmJsonObjects.cxx @@ -14,7 +14,8 @@ #include <utility> #include <vector> -#include "cmAlgorithms.h" +#include <cmext/algorithm> + #include "cmGeneratorExpression.h" #include "cmGeneratorTarget.h" #include "cmGlobalGenerator.h" @@ -601,7 +602,7 @@ static Json::Value DumpTargetsList( std::vector<cmGeneratorTarget*> targetList; for (auto const& lgIt : generators) { - cmAppend(targetList, lgIt->GetGeneratorTargets()); + cm::append(targetList, lgIt->GetGeneratorTargets()); } std::sort(targetList.begin(), targetList.end()); diff --git a/Source/cmLinkItemGraphVisitor.cxx b/Source/cmLinkItemGraphVisitor.cxx new file mode 100644 index 0000000..ab2cf9e --- /dev/null +++ b/Source/cmLinkItemGraphVisitor.cxx @@ -0,0 +1,142 @@ +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing for details. */ +#include "cmLinkItemGraphVisitor.h" + +#include <map> +#include <utility> +#include <vector> + +#include "cmGeneratorTarget.h" +#include "cmLinkItem.h" +#include "cmMakefile.h" + +void cmLinkItemGraphVisitor::VisitItem(cmLinkItem const& item) +{ + if (this->ItemVisited(item)) { + return; + } + + this->OnItem(item); + + this->VisitLinks(item, item); +} + +void cmLinkItemGraphVisitor::VisitLinks(cmLinkItem const& item, + cmLinkItem const& rootItem) +{ + if (this->LinkVisited(item, rootItem)) { + return; + } + + if (item.Target == nullptr) { + return; + } + + for (auto const& config : item.Target->Makefile->GetGeneratorConfigs()) { + this->VisitLinks(item, rootItem, config); + } +} + +void cmLinkItemGraphVisitor::VisitLinks(cmLinkItem const& item, + cmLinkItem const& rootItem, + std::string const& config) +{ + auto const& target = *item.Target; + + DependencyMap dependencies; + cmLinkItemGraphVisitor::GetDependencies(target, config, dependencies); + + for (auto const& d : dependencies) { + auto const& dependency = d.second; + auto const& dependencyType = dependency.first; + auto const& dependee = dependency.second; + this->VisitItem(dependee); + + if (this->LinkVisited(item, dependee)) { + continue; + } + + this->OnDirectLink(item, dependee, dependencyType); + + if (rootItem.AsStr() != item.AsStr()) { + this->OnIndirectLink(rootItem, dependee); + } + + // Visit all the direct and indirect links. + this->VisitLinks(dependee, dependee); + this->VisitLinks(dependee, item); + this->VisitLinks(dependee, rootItem); + } +} + +bool cmLinkItemGraphVisitor::ItemVisited(cmLinkItem const& item) +{ + auto& collection = this->VisitedItems; + + bool const visited = collection.find(item.AsStr()) != collection.cend(); + + if (!visited) { + collection.insert(item.AsStr()); + } + + return visited; +} + +bool cmLinkItemGraphVisitor::LinkVisited(cmLinkItem const& depender, + cmLinkItem const& dependee) +{ + auto const link = std::make_pair<>(depender.AsStr(), dependee.AsStr()); + + bool const linkVisited = + this->VisitedLinks.find(link) != this->VisitedLinks.cend(); + + if (!linkVisited) { + this->VisitedLinks.insert(link); + } + + return linkVisited; +} + +void cmLinkItemGraphVisitor::GetDependencies(cmGeneratorTarget const& target, + std::string const& config, + DependencyMap& dependencies) +{ + auto implementationLibraries = target.GetLinkImplementationLibraries(config); + if (implementationLibraries != nullptr) { + for (auto const& lib : implementationLibraries->Libraries) { + auto const& name = lib.AsStr(); + dependencies[name] = Dependency(DependencyType::LinkPrivate, lib); + } + } + + auto interfaceLibraries = + target.GetLinkInterfaceLibraries(config, &target, true); + if (interfaceLibraries != nullptr) { + for (auto const& lib : interfaceLibraries->Libraries) { + auto const& name = lib.AsStr(); + if (dependencies.find(name) != dependencies.cend()) { + dependencies[name] = Dependency(DependencyType::LinkPublic, lib); + } else { + dependencies[name] = Dependency(DependencyType::LinkInterface, lib); + } + } + } + + std::vector<cmGeneratorTarget*> objectLibraries; + target.GetObjectLibrariesCMP0026(objectLibraries); + for (auto const& lib : objectLibraries) { + auto const& name = lib->GetName(); + if (dependencies.find(name) == dependencies.cend()) { + auto objectItem = cmLinkItem(lib, lib->GetBacktrace()); + dependencies[name] = Dependency(DependencyType::Object, objectItem); + } + } + + auto const& utilityItems = target.GetUtilityItems(); + for (auto const& item : utilityItems) { + auto const& name = item.AsStr(); + if (dependencies.find(name) == dependencies.cend()) { + dependencies[name] = Dependency(DependencyType::Utility, item); + } + } +} diff --git a/Source/cmLinkItemGraphVisitor.h b/Source/cmLinkItemGraphVisitor.h new file mode 100644 index 0000000..21dc659 --- /dev/null +++ b/Source/cmLinkItemGraphVisitor.h @@ -0,0 +1,75 @@ +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing for details. */ +#ifndef cmLinkItemGraphVisitor_h +#define cmLinkItemGraphVisitor_h + +#include <map> +#include <set> +#include <string> +#include <utility> + +#include "cmLinkItem.h" + +class cmGeneratorTarget; + +/** \class cmLinkItemGraphVisitor + * \brief Visits a graph of linked items. + * + * Allows to visit items and dependency links (direct and indirect) between + * those items. + * This abstract class takes care of the graph traversal, making sure that: + * - it terminates even in the presence of cycles; + * - it visits every object once (and only once); + * - it visits the objects in the same order every time. + * + * Children classes only have to implement OnItem() etc. to handle whatever + * logic they care about. + */ +class cmLinkItemGraphVisitor +{ +public: + virtual ~cmLinkItemGraphVisitor() = default; + + virtual void VisitGraph(std::string const& name) = 0; + + void VisitItem(cmLinkItem const& item); + +protected: + enum class DependencyType + { + LinkInterface, + LinkPublic, + LinkPrivate, + Object, + Utility + }; + + virtual void OnItem(cmLinkItem const& item) = 0; + + virtual void OnDirectLink(cmLinkItem const& depender, + cmLinkItem const& dependee, DependencyType dt) = 0; + + virtual void OnIndirectLink(cmLinkItem const& depender, + cmLinkItem const& dependee) = 0; + +private: + std::set<std::string> VisitedItems; + + std::set<std::pair<std::string, std::string>> VisitedLinks; + + void VisitLinks(cmLinkItem const& item, cmLinkItem const& rootItem); + void VisitLinks(cmLinkItem const& item, cmLinkItem const& rootItem, + std::string const& config); + + using Dependency = std::pair<DependencyType, cmLinkItem>; + using DependencyMap = std::map<std::string, Dependency>; + + bool ItemVisited(cmLinkItem const& item); + bool LinkVisited(cmLinkItem const& depender, cmLinkItem const& dependee); + + static void GetDependencies(cmGeneratorTarget const& target, + std::string const& config, + DependencyMap& dependencies); +}; + +#endif diff --git a/Source/cmLinkLineComputer.cxx b/Source/cmLinkLineComputer.cxx index 0dc6236..4320010 100644 --- a/Source/cmLinkLineComputer.cxx +++ b/Source/cmLinkLineComputer.cxx @@ -23,6 +23,7 @@ cmLinkLineComputer::cmLinkLineComputer(cmOutputConverter* outputConverter, , OutputConverter(outputConverter) , ForResponse(false) , UseWatcomQuote(false) + , UseNinjaMulti(false) , Relink(false) { } @@ -34,6 +35,11 @@ void cmLinkLineComputer::SetUseWatcomQuote(bool useWatcomQuote) this->UseWatcomQuote = useWatcomQuote; } +void cmLinkLineComputer::SetUseNinjaMulti(bool useNinjaMulti) +{ + this->UseNinjaMulti = useNinjaMulti; +} + void cmLinkLineComputer::SetForResponse(bool forResponse) { this->ForResponse = forResponse; @@ -106,10 +112,14 @@ void cmLinkLineComputer::ComputeLinkLibs( std::string cmLinkLineComputer::ConvertToOutputFormat(std::string const& input) { - cmOutputConverter::OutputFormat shellFormat = (this->ForResponse) - ? cmOutputConverter::RESPONSE - : ((this->UseWatcomQuote) ? cmOutputConverter::WATCOMQUOTE - : cmOutputConverter::SHELL); + cmOutputConverter::OutputFormat shellFormat = cmOutputConverter::SHELL; + if (this->ForResponse) { + shellFormat = cmOutputConverter::RESPONSE; + } else if (this->UseWatcomQuote) { + shellFormat = cmOutputConverter::WATCOMQUOTE; + } else if (this->UseNinjaMulti) { + shellFormat = cmOutputConverter::NINJAMULTI; + } return this->OutputConverter->ConvertToOutputFormat(input, shellFormat); } @@ -117,10 +127,14 @@ std::string cmLinkLineComputer::ConvertToOutputFormat(std::string const& input) std::string cmLinkLineComputer::ConvertToOutputForExisting( std::string const& input) { - cmOutputConverter::OutputFormat shellFormat = (this->ForResponse) - ? cmOutputConverter::RESPONSE - : ((this->UseWatcomQuote) ? cmOutputConverter::WATCOMQUOTE - : cmOutputConverter::SHELL); + cmOutputConverter::OutputFormat shellFormat = cmOutputConverter::SHELL; + if (this->ForResponse) { + shellFormat = cmOutputConverter::RESPONSE; + } else if (this->UseWatcomQuote) { + shellFormat = cmOutputConverter::WATCOMQUOTE; + } else if (this->UseNinjaMulti) { + shellFormat = cmOutputConverter::NINJAMULTI; + } return this->OutputConverter->ConvertToOutputForExisting(input, shellFormat); } diff --git a/Source/cmLinkLineComputer.h b/Source/cmLinkLineComputer.h index f426976..df42468 100644 --- a/Source/cmLinkLineComputer.h +++ b/Source/cmLinkLineComputer.h @@ -28,6 +28,7 @@ public: cmLinkLineComputer& operator=(cmLinkLineComputer const&) = delete; void SetUseWatcomQuote(bool useWatcomQuote); + void SetUseNinjaMulti(bool useNinjaMulti); void SetForResponse(bool forResponse); void SetRelink(bool relink); @@ -69,6 +70,7 @@ protected: bool ForResponse; bool UseWatcomQuote; + bool UseNinjaMulti; bool Relink; }; diff --git a/Source/cmLoadCacheCommand.cxx b/Source/cmLoadCacheCommand.cxx index 1184bcb..d49e711 100644 --- a/Source/cmLoadCacheCommand.cxx +++ b/Source/cmLoadCacheCommand.cxx @@ -24,12 +24,20 @@ bool cmLoadCacheCommand(std::vector<std::string> const& args, { if (args.empty()) { status.SetError("called with wrong number of arguments."); + return false; } if (args.size() >= 2 && args[1] == "READ_WITH_PREFIX") { return ReadWithPrefix(args, status); } + if (status.GetMakefile().GetCMakeInstance()->GetWorkingMode() == + cmake::SCRIPT_MODE) { + status.SetError( + "Only load_cache(READ_WITH_PREFIX) may be used in script mode"); + return false; + } + // Cache entries to be excluded from the import list. // If this set is empty, all cache entries are brought in // and they can not be overridden. diff --git a/Source/cmLoadCommandCommand.cxx b/Source/cmLoadCommandCommand.cxx index 23ace64..92258e2 100644 --- a/Source/cmLoadCommandCommand.cxx +++ b/Source/cmLoadCommandCommand.cxx @@ -14,6 +14,7 @@ #include "cmCommand.h" #include "cmDynamicLoader.h" #include "cmExecutionStatus.h" +#include "cmLocalGenerator.h" #include "cmMakefile.h" #include "cmState.h" #include "cmStringAlgorithms.h" @@ -25,6 +26,8 @@ # include <malloc.h> /* for malloc/free on QNX */ #endif +class cmListFileBacktrace; + namespace { const char* LastName = nullptr; @@ -158,8 +161,10 @@ bool cmLoadedCommand::InitialPass(std::vector<std::string> const& args, if (result) { if (this->Impl->FinalPass) { auto impl = this->Impl; - this->Makefile->AddFinalAction( - [impl](cmMakefile& makefile) { impl->DoFinalPass(&makefile); }); + this->Makefile->AddGeneratorAction( + [impl](cmLocalGenerator& lg, const cmListFileBacktrace&) { + impl->DoFinalPass(lg.GetMakefile()); + }); } return true; } diff --git a/Source/cmLocalCommonGenerator.cxx b/Source/cmLocalCommonGenerator.cxx index f86955d..025ef7e 100644 --- a/Source/cmLocalCommonGenerator.cxx +++ b/Source/cmLocalCommonGenerator.cxx @@ -17,13 +17,9 @@ cmLocalCommonGenerator::cmLocalCommonGenerator(cmGlobalGenerator* gg, : cmLocalGenerator(gg, mf) , WorkingDirectory(std::move(wd)) { - // Store the configuration name that will be generated. - if (const char* config = this->Makefile->GetDefinition("CMAKE_BUILD_TYPE")) { - // Use the build type given by the user. - this->ConfigName = config; - } else { - // No configuration type given. - this->ConfigName.clear(); + this->Makefile->GetConfigurations(this->ConfigNames); + if (this->ConfigNames.empty()) { + this->ConfigNames.emplace_back(); } } diff --git a/Source/cmLocalCommonGenerator.h b/Source/cmLocalCommonGenerator.h index eaef6ab..378ca63 100644 --- a/Source/cmLocalCommonGenerator.h +++ b/Source/cmLocalCommonGenerator.h @@ -7,6 +7,7 @@ #include <map> #include <string> +#include <vector> #include "cmLocalGenerator.h" @@ -25,7 +26,10 @@ public: std::string wd); ~cmLocalCommonGenerator() override; - std::string const& GetConfigName() const { return this->ConfigName; } + std::vector<std::string> const& GetConfigNames() const + { + return this->ConfigNames; + } std::string GetWorkingDirectory() const { return this->WorkingDirectory; } @@ -39,7 +43,7 @@ public: protected: std::string WorkingDirectory; - std::string ConfigName; + std::vector<std::string> ConfigNames; friend class cmCommonTargetGenerator; }; diff --git a/Source/cmLocalGenerator.cxx b/Source/cmLocalGenerator.cxx index 1754421..1da6efe 100644 --- a/Source/cmLocalGenerator.cxx +++ b/Source/cmLocalGenerator.cxx @@ -2,6 +2,22 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmLocalGenerator.h" +#include <algorithm> +#include <cassert> +#include <cstdio> +#include <cstdlib> +#include <cstring> +#include <initializer_list> +#include <iterator> +#include <sstream> +#include <unordered_set> +#include <utility> +#include <vector> + +#include <cm/memory> +#include <cm/string_view> +#include <cmext/algorithm> + #include "cmsys/RegularExpression.hxx" #include "cmAlgorithms.h" @@ -40,20 +56,6 @@ # include "cmCryptoHash.h" #endif -#include <algorithm> -#include <cassert> -#include <cstdio> -#include <cstdlib> -#include <cstring> -#include <initializer_list> -#include <iterator> -#include <sstream> -#include <unordered_set> -#include <utility> -#include <vector> - -#include <cm/string_view> - #if defined(__HAIKU__) # include <FindDirectory.h> # include <StorageDefs.h> @@ -181,11 +183,7 @@ cmRulePlaceholderExpander* cmLocalGenerator::CreateRulePlaceholderExpander() this->LinkerSysroot); } -cmLocalGenerator::~cmLocalGenerator() -{ - cmDeleteAll(this->GeneratorTargets); - cmDeleteAll(this->OwnedImportedGeneratorTargets); -} +cmLocalGenerator::~cmLocalGenerator() = default; void cmLocalGenerator::IssueMessage(MessageType t, std::string const& text) const @@ -263,8 +261,8 @@ static void MoveSystemIncludesToEnd(std::vector<BT<std::string>>& includeDirs, void cmLocalGenerator::TraceDependencies() { // Generate the rule files for each target. - const std::vector<cmGeneratorTarget*>& targets = this->GetGeneratorTargets(); - for (cmGeneratorTarget* target : targets) { + const auto& targets = this->GetGeneratorTargets(); + for (const auto& target : targets) { if (target->GetType() == cmStateEnums::INTERFACE_LIBRARY) { continue; } @@ -395,7 +393,7 @@ void cmLocalGenerator::ProcessEvaluationFiles( return; } - cmAppend(generatedFiles, files); + cm::append(generatedFiles, files); std::inplace_merge(generatedFiles.begin(), generatedFiles.end() - files.size(), generatedFiles.end()); @@ -635,11 +633,14 @@ void cmLocalGenerator::GenerateInstallRules() } } -void cmLocalGenerator::AddGeneratorTarget(cmGeneratorTarget* gt) +void cmLocalGenerator::AddGeneratorTarget( + std::unique_ptr<cmGeneratorTarget> gt) { - this->GeneratorTargets.push_back(gt); - this->GeneratorTargetSearchIndex.emplace(gt->GetName(), gt); - this->GlobalGenerator->IndexGeneratorTarget(gt); + cmGeneratorTarget* gt_ptr = gt.get(); + + this->GeneratorTargets.push_back(std::move(gt)); + this->GeneratorTargetSearchIndex.emplace(gt_ptr->GetName(), gt_ptr); + this->GlobalGenerator->IndexGeneratorTarget(gt_ptr); } void cmLocalGenerator::AddImportedGeneratorTarget(cmGeneratorTarget* gt) @@ -648,9 +649,10 @@ void cmLocalGenerator::AddImportedGeneratorTarget(cmGeneratorTarget* gt) this->GlobalGenerator->IndexGeneratorTarget(gt); } -void cmLocalGenerator::AddOwnedImportedGeneratorTarget(cmGeneratorTarget* gt) +void cmLocalGenerator::AddOwnedImportedGeneratorTarget( + std::unique_ptr<cmGeneratorTarget> gt) { - this->OwnedImportedGeneratorTargets.push_back(gt); + this->OwnedImportedGeneratorTargets.push_back(std::move(gt)); } cmGeneratorTarget* cmLocalGenerator::FindLocalNonAliasGeneratorTarget( @@ -673,8 +675,8 @@ void cmLocalGenerator::ComputeTargetManifest() } // Add our targets to the manifest for each configuration. - const std::vector<cmGeneratorTarget*>& targets = this->GetGeneratorTargets(); - for (cmGeneratorTarget* target : targets) { + const auto& targets = this->GetGeneratorTargets(); + for (const auto& target : targets) { if (target->GetType() == cmStateEnums::INTERFACE_LIBRARY) { continue; } @@ -695,17 +697,18 @@ bool cmLocalGenerator::ComputeTargetCompileFeatures() using LanguagePair = std::pair<std::string, std::string>; std::vector<LanguagePair> pairedLanguages{ { "OBJC", "C" }, - { "OBJCXX", "CXX" } }; - std::set<LanguagePair> objcEnabledLanguages; + { "OBJCXX", "CXX" }, + { "CUDA", "CXX" } }; + std::set<LanguagePair> inferredEnabledLanguages; for (auto const& lang : pairedLanguages) { if (this->Makefile->GetState()->GetLanguageEnabled(lang.first)) { - objcEnabledLanguages.insert(lang); + inferredEnabledLanguages.insert(lang); } } // Process compile features of all targets. - const std::vector<cmGeneratorTarget*>& targets = this->GetGeneratorTargets(); - for (cmGeneratorTarget* target : targets) { + const auto& targets = this->GetGeneratorTargets(); + for (const auto& target : targets) { for (std::string const& c : configNames) { if (!target->ComputeCompileFeatures(c)) { return false; @@ -738,12 +741,17 @@ bool cmLocalGenerator::ComputeTargetCompileFeatures() target->GetProperty(cmStrCat(lang.second, property))); } }; - for (auto const& lang : objcEnabledLanguages) { + for (auto const& lang : pairedLanguages) { if (copyStandardToObjLang(lang)) { copyPropertyToObjLang(lang, "_STANDARD_REQUIRED"); copyPropertyToObjLang(lang, "_EXTENSIONS"); } } + if (const char* standard = target->GetProperty("CUDA_STANDARD")) { + if (std::string{ standard } == "98") { + target->Target->SetProperty("CUDA_STANDARD", "03"); + } + } } } @@ -988,6 +996,91 @@ void cmLocalGenerator::AddCompileOptions(std::vector<BT<std::string>>& flags, } } +cmTarget* cmLocalGenerator::AddCustomCommandToTarget( + const std::string& target, const std::vector<std::string>& byproducts, + const std::vector<std::string>& depends, + const cmCustomCommandLines& commandLines, cmCustomCommandType type, + const char* comment, const char* workingDir, bool escapeOldStyle, + bool uses_terminal, const std::string& depfile, const std::string& job_pool, + bool command_expand_lists, cmObjectLibraryCommands objLibCommands) +{ + cmTarget* t = this->Makefile->GetCustomCommandTarget( + target, objLibCommands, this->DirectoryBacktrace); + if (!t) { + return nullptr; + } + + detail::AddCustomCommandToTarget( + *this, this->DirectoryBacktrace, cmCommandOrigin::Generator, t, byproducts, + depends, commandLines, type, comment, workingDir, escapeOldStyle, + uses_terminal, depfile, job_pool, command_expand_lists); + + return t; +} + +cmSourceFile* cmLocalGenerator::AddCustomCommandToOutput( + const std::string& output, const std::vector<std::string>& depends, + const std::string& main_dependency, const cmCustomCommandLines& commandLines, + const char* comment, const char* workingDir, bool replace, + bool escapeOldStyle, bool uses_terminal, bool command_expand_lists, + const std::string& depfile, const std::string& job_pool) +{ + std::vector<std::string> no_byproducts; + cmImplicitDependsList no_implicit_depends; + return this->AddCustomCommandToOutput( + { output }, no_byproducts, depends, main_dependency, no_implicit_depends, + commandLines, comment, workingDir, replace, escapeOldStyle, uses_terminal, + command_expand_lists, depfile, job_pool); +} + +cmSourceFile* cmLocalGenerator::AddCustomCommandToOutput( + const std::vector<std::string>& outputs, + const std::vector<std::string>& byproducts, + const std::vector<std::string>& depends, const std::string& main_dependency, + const cmImplicitDependsList& implicit_depends, + const cmCustomCommandLines& commandLines, const char* comment, + const char* workingDir, bool replace, bool escapeOldStyle, + bool uses_terminal, bool command_expand_lists, const std::string& depfile, + const std::string& job_pool) +{ + // Make sure there is at least one output. + if (outputs.empty()) { + cmSystemTools::Error("Attempt to add a custom rule with no output!"); + return nullptr; + } + + return detail::AddCustomCommandToOutput( + *this, this->DirectoryBacktrace, cmCommandOrigin::Generator, outputs, + byproducts, depends, main_dependency, implicit_depends, commandLines, + comment, workingDir, replace, escapeOldStyle, uses_terminal, + command_expand_lists, depfile, job_pool); +} + +cmTarget* cmLocalGenerator::AddUtilityCommand( + const std::string& utilityName, bool excludeFromAll, const char* workingDir, + const std::vector<std::string>& byproducts, + const std::vector<std::string>& depends, + const cmCustomCommandLines& commandLines, bool escapeOldStyle, + const char* comment, bool uses_terminal, bool command_expand_lists, + const std::string& job_pool) +{ + cmTarget* target = + this->Makefile->AddNewUtilityTarget(utilityName, excludeFromAll); + target->SetIsGeneratorProvided(true); + + if (commandLines.empty() && depends.empty()) { + return target; + } + + detail::AddUtilityCommand( + *this, this->DirectoryBacktrace, cmCommandOrigin::Generator, target, + this->Makefile->GetUtilityOutput(target), workingDir, byproducts, depends, + commandLines, escapeOldStyle, comment, uses_terminal, command_expand_lists, + job_pool); + + return target; +} + std::vector<BT<std::string>> cmLocalGenerator::GetIncludeDirectoriesImplicit( cmGeneratorTarget const* target, std::string const& lang, std::string const& config, bool stripImplicitDirs, @@ -1685,10 +1778,18 @@ void cmLocalGenerator::AddArchitectureFlags(std::string& flags, const std::string& lang, const std::string& config) { - // Only add macOS specific flags on Darwin platforms (macOS and iOS): + // Only add Apple specific flags on Apple platforms if (this->Makefile->IsOn("APPLE") && this->EmitUniversalBinaryFlags) { std::vector<std::string> archs; target->GetAppleArchs(config, archs); + if (!archs.empty() && !lang.empty() && + (lang[0] == 'C' || lang[0] == 'F' || lang[0] == 'O')) { + for (std::string const& arch : archs) { + flags += " -arch "; + flags += arch; + } + } + const char* sysroot = this->Makefile->GetDefinition("CMAKE_OSX_SYSROOT"); if (sysroot && sysroot[0] == '/' && !sysroot[1]) { sysroot = nullptr; @@ -1696,27 +1797,37 @@ void cmLocalGenerator::AddArchitectureFlags(std::string& flags, std::string sysrootFlagVar = std::string("CMAKE_") + lang + "_SYSROOT_FLAG"; const char* sysrootFlag = this->Makefile->GetDefinition(sysrootFlagVar); + if (sysrootFlag && *sysrootFlag) { + std::vector<std::string> arch_sysroots; + if (const char* arch_sysroots_str = + this->Makefile->GetDefinition("CMAKE_APPLE_ARCH_SYSROOTS")) { + cmExpandList(std::string(arch_sysroots_str), arch_sysroots, true); + } + if (!arch_sysroots.empty()) { + assert(arch_sysroots.size() == archs.size()); + for (size_t i = 0; i < archs.size(); ++i) { + if (arch_sysroots[i].empty()) { + continue; + } + flags += " -Xarch_" + archs[i] + " "; + // Combine sysroot flag and path to work with -Xarch + std::string arch_sysroot = sysrootFlag + arch_sysroots[i]; + flags += this->ConvertToOutputFormat(arch_sysroot, SHELL); + } + } else if (sysroot && *sysroot) { + flags += " "; + flags += sysrootFlag; + flags += " "; + flags += this->ConvertToOutputFormat(sysroot, SHELL); + } + } + const char* deploymentTarget = this->Makefile->GetDefinition("CMAKE_OSX_DEPLOYMENT_TARGET"); std::string deploymentTargetFlagVar = std::string("CMAKE_") + lang + "_OSX_DEPLOYMENT_TARGET_FLAG"; const char* deploymentTargetFlag = this->Makefile->GetDefinition(deploymentTargetFlagVar); - if (!archs.empty() && !lang.empty() && - (lang[0] == 'C' || lang[0] == 'F' || lang[0] == 'O')) { - for (std::string const& arch : archs) { - flags += " -arch "; - flags += arch; - } - } - - if (sysrootFlag && *sysrootFlag && sysroot && *sysroot) { - flags += " "; - flags += sysrootFlag; - flags += " "; - flags += this->ConvertToOutputFormat(sysroot, SHELL); - } - if (deploymentTargetFlag && *deploymentTargetFlag && deploymentTarget && *deploymentTarget) { flags += " "; @@ -2004,17 +2115,22 @@ void cmLocalGenerator::AddCompilerRequirementFlag( langStdMap["OBJC"].emplace_back("99"); langStdMap["OBJC"].emplace_back("90"); + langStdMap["CUDA"].emplace_back("20"); + langStdMap["CUDA"].emplace_back("17"); langStdMap["CUDA"].emplace_back("14"); langStdMap["CUDA"].emplace_back("11"); - langStdMap["CUDA"].emplace_back("98"); + langStdMap["CUDA"].emplace_back("03"); } std::string standard(standardProp); - + if (lang == "CUDA" && standard == "98") { + standard = "03"; + } std::vector<std::string>& stds = langStdMap[lang]; auto stdIt = std::find(stds.begin(), stds.end(), standard); if (stdIt == stds.end()) { + std::string e = lang + "_STANDARD is set to invalid value '" + standard + "'"; this->GetGlobalGenerator()->GetCMakeInstance()->IssueMessage( @@ -2295,7 +2411,9 @@ void cmLocalGenerator::AppendFlags( void cmLocalGenerator::AppendFlagEscape(std::string& flags, const std::string& rawFlag) const { - this->AppendFlags(flags, this->EscapeForShell(rawFlag)); + this->AppendFlags( + flags, + this->EscapeForShell(rawFlag, false, false, false, this->IsNinjaMulti())); } void cmLocalGenerator::AddPchDependencies(cmGeneratorTarget* target) @@ -2404,13 +2522,9 @@ void cmLocalGenerator::AddPchDependencies(cmGeneratorTarget* target) file << "endif()\n"; } - cmCustomCommandLines commandLines; - cmCustomCommandLine currentLine; - currentLine.push_back(cmSystemTools::GetCMakeCommand()); - currentLine.push_back(cmStrCat("-DPDB_PREFIX=", pdb_prefix)); - currentLine.push_back("-P"); - currentLine.push_back(copy_script); - commandLines.push_back(std::move(currentLine)); + cmCustomCommandLines commandLines = cmMakeSingleCommandLine( + { cmSystemTools::GetCMakeCommand(), + cmStrCat("-DPDB_PREFIX=", pdb_prefix), "-P", copy_script }); const std::string no_main_dependency; const std::vector<std::string> no_deps; @@ -2423,16 +2537,14 @@ void cmLocalGenerator::AddPchDependencies(cmGeneratorTarget* target) pchReuseFrom, ".pdb")); if (this->GetGlobalGenerator()->IsMultiConfig()) { - this->Makefile->AddCustomCommandToTarget( + this->AddCustomCommandToTarget( target->GetName(), outputs, no_deps, commandLines, cmCustomCommandType::PRE_BUILD, no_message, no_current_dir); } else { cmImplicitDependsList no_implicit_depends; - cmSourceFile* copy_rule = - this->Makefile->AddCustomCommandToOutput( - outputs, no_byproducts, no_deps, no_main_dependency, - no_implicit_depends, commandLines, no_message, - no_current_dir); + cmSourceFile* copy_rule = this->AddCustomCommandToOutput( + outputs, no_byproducts, no_deps, no_main_dependency, + no_implicit_depends, commandLines, no_message, no_current_dir); if (copy_rule) { target->AddSource(copy_rule->ResolveFullPath()); @@ -2440,7 +2552,7 @@ void cmLocalGenerator::AddPchDependencies(cmGeneratorTarget* target) } target->Target->SetProperty("COMPILE_PDB_OUTPUT_DIRECTORY", - target_compile_pdb_dir.c_str()); + target_compile_pdb_dir); } std::string pchSourceObj = @@ -2449,8 +2561,7 @@ void cmLocalGenerator::AddPchDependencies(cmGeneratorTarget* target) // Link to the pch object file target->Target->AppendProperty( "LINK_FLAGS", - cmStrCat(" ", this->ConvertToOutputFormat(pchSourceObj, SHELL)) - .c_str(), + cmStrCat(" ", this->ConvertToOutputFormat(pchSourceObj, SHELL)), true); } } else { @@ -2515,8 +2626,7 @@ void cmLocalGenerator::AddUnityBuild(cmGeneratorTarget* target) batchSize = filtered_sources.size(); } - for (size_t itemsLeft = filtered_sources.size(), chunk = batchSize, - batch = 0; + for (size_t itemsLeft = filtered_sources.size(), chunk, batch = 0; itemsLeft > 0; itemsLeft -= chunk, ++batch) { chunk = std::min(itemsLeft, batchSize); @@ -2900,8 +3010,8 @@ void cmLocalGenerator::GenerateTargetInstallRules( { // Convert the old-style install specification from each target to // an install generator and run it. - const std::vector<cmGeneratorTarget*>& tgts = this->GetGeneratorTargets(); - for (cmGeneratorTarget* l : tgts) { + const auto& tgts = this->GetGeneratorTargets(); + for (const auto& l : tgts) { if (l->GetType() == cmStateEnums::INTERFACE_LIBRARY) { continue; } @@ -3117,6 +3227,11 @@ bool cmLocalGenerator::IsNMake() const return this->GetState()->UseNMake(); } +bool cmLocalGenerator::IsNinjaMulti() const +{ + return this->GetState()->UseNinjaMulti(); +} + std::string cmLocalGenerator::GetObjectFileNameWithoutTarget( const cmSourceFile& source, std::string const& dir_max, bool* hasSourceExtension, char const* customOutputExtension) @@ -3444,3 +3559,245 @@ void cmLocalGenerator::GenerateFrameworkInfoPList( cmLGInfoProp(mf, target, "MACOSX_FRAMEWORK_BUNDLE_VERSION"); mf->ConfigureFile(inFile, fname, false, false, false); } + +namespace { +void CreateGeneratedSource(cmLocalGenerator& lg, const std::string& output, + cmCommandOrigin origin, + const cmListFileBacktrace& lfbt) +{ + if (cmGeneratorExpression::Find(output) == std::string::npos) { + // Outputs without generator expressions from the project are already + // created and marked as generated. Do not mark them again, because + // other commands might have overwritten the property. + if (origin == cmCommandOrigin::Generator) { + lg.GetMakefile()->GetOrCreateGeneratedSource(output); + } + } else { + lg.GetCMakeInstance()->IssueMessage( + MessageType::FATAL_ERROR, + "Generator expressions in custom command outputs are not implemented!", + lfbt); + } +} + +void CreateGeneratedSources(cmLocalGenerator& lg, + const std::vector<std::string>& outputs, + cmCommandOrigin origin, + const cmListFileBacktrace& lfbt) +{ + for (std::string const& o : outputs) { + CreateGeneratedSource(lg, o, origin, lfbt); + } +} + +cmSourceFile* AddCustomCommand( + cmLocalGenerator& lg, const cmListFileBacktrace& lfbt, + const std::vector<std::string>& outputs, + const std::vector<std::string>& byproducts, + const std::vector<std::string>& depends, const std::string& main_dependency, + const cmImplicitDependsList& implicit_depends, + const cmCustomCommandLines& commandLines, const char* comment, + const char* workingDir, bool replace, bool escapeOldStyle, + bool uses_terminal, bool command_expand_lists, const std::string& depfile, + const std::string& job_pool) +{ + cmMakefile* mf = lg.GetMakefile(); + + // Choose a source file on which to store the custom command. + cmSourceFile* file = nullptr; + if (!commandLines.empty() && !main_dependency.empty()) { + // The main dependency was specified. Use it unless a different + // custom command already used it. + file = mf->GetSource(main_dependency); + if (file && file->GetCustomCommand() && !replace) { + // The main dependency already has a custom command. + if (commandLines == file->GetCustomCommand()->GetCommandLines()) { + // The existing custom command is identical. Silently ignore + // the duplicate. + return file; + } + // The existing custom command is different. We need to + // generate a rule file for this new command. + file = nullptr; + } else if (!file) { + file = mf->CreateSource(main_dependency); + } + } + + // Generate a rule file if the main dependency is not available. + if (!file) { + cmGlobalGenerator* gg = lg.GetGlobalGenerator(); + + // Construct a rule file associated with the first output produced. + std::string outName = gg->GenerateRuleFile(outputs[0]); + + // Check if the rule file already exists. + file = mf->GetSource(outName, cmSourceFileLocationKind::Known); + if (file && file->GetCustomCommand() && !replace) { + // The rule file already exists. + if (commandLines != file->GetCustomCommand()->GetCommandLines()) { + lg.GetCMakeInstance()->IssueMessage( + MessageType::FATAL_ERROR, + cmStrCat("Attempt to add a custom rule to output\n ", outName, + "\nwhich already has a custom rule."), + lfbt); + } + return file; + } + + // Create a cmSourceFile for the rule file. + if (!file) { + file = mf->CreateSource(outName, true, cmSourceFileLocationKind::Known); + } + file->SetProperty("__CMAKE_RULE", "1"); + } + + // Attach the custom command to the file. + if (file) { + // Construct a complete list of dependencies. + std::vector<std::string> depends2(depends); + if (!main_dependency.empty()) { + depends2.push_back(main_dependency); + } + + std::unique_ptr<cmCustomCommand> cc = cm::make_unique<cmCustomCommand>( + outputs, byproducts, depends2, commandLines, lfbt, comment, workingDir); + cc->SetEscapeOldStyle(escapeOldStyle); + cc->SetEscapeAllowMakeVars(true); + cc->SetImplicitDepends(implicit_depends); + cc->SetUsesTerminal(uses_terminal); + cc->SetCommandExpandLists(command_expand_lists); + cc->SetDepfile(depfile); + cc->SetJobPool(job_pool); + file->SetCustomCommand(std::move(cc)); + + mf->AddSourceOutputs(file, outputs, byproducts); + } + return file; +} +} + +namespace detail { +void AddCustomCommandToTarget(cmLocalGenerator& lg, + const cmListFileBacktrace& lfbt, + cmCommandOrigin origin, cmTarget* target, + const std::vector<std::string>& byproducts, + const std::vector<std::string>& depends, + const cmCustomCommandLines& commandLines, + cmCustomCommandType type, const char* comment, + const char* workingDir, bool escapeOldStyle, + bool uses_terminal, const std::string& depfile, + const std::string& job_pool, + bool command_expand_lists) +{ + cmMakefile* mf = lg.GetMakefile(); + + // Always create the byproduct sources and mark them generated. + CreateGeneratedSources(lg, byproducts, origin, lfbt); + + // Add the command to the appropriate build step for the target. + std::vector<std::string> no_output; + cmCustomCommand cc(no_output, byproducts, depends, commandLines, lfbt, + comment, workingDir); + cc.SetEscapeOldStyle(escapeOldStyle); + cc.SetEscapeAllowMakeVars(true); + cc.SetUsesTerminal(uses_terminal); + cc.SetCommandExpandLists(command_expand_lists); + cc.SetDepfile(depfile); + cc.SetJobPool(job_pool); + switch (type) { + case cmCustomCommandType::PRE_BUILD: + target->AddPreBuildCommand(std::move(cc)); + break; + case cmCustomCommandType::PRE_LINK: + target->AddPreLinkCommand(std::move(cc)); + break; + case cmCustomCommandType::POST_BUILD: + target->AddPostBuildCommand(std::move(cc)); + break; + } + + mf->AddTargetByproducts(target, byproducts); +} + +cmSourceFile* AddCustomCommandToOutput( + cmLocalGenerator& lg, const cmListFileBacktrace& lfbt, + cmCommandOrigin origin, const std::vector<std::string>& outputs, + const std::vector<std::string>& byproducts, + const std::vector<std::string>& depends, const std::string& main_dependency, + const cmImplicitDependsList& implicit_depends, + const cmCustomCommandLines& commandLines, const char* comment, + const char* workingDir, bool replace, bool escapeOldStyle, + bool uses_terminal, bool command_expand_lists, const std::string& depfile, + const std::string& job_pool) +{ + // Always create the output sources and mark them generated. + CreateGeneratedSources(lg, outputs, origin, lfbt); + CreateGeneratedSources(lg, byproducts, origin, lfbt); + + return AddCustomCommand( + lg, lfbt, outputs, byproducts, depends, main_dependency, implicit_depends, + commandLines, comment, workingDir, replace, escapeOldStyle, uses_terminal, + command_expand_lists, depfile, job_pool); +} + +void AppendCustomCommandToOutput(cmLocalGenerator& lg, + const cmListFileBacktrace& lfbt, + const std::string& output, + const std::vector<std::string>& depends, + const cmImplicitDependsList& implicit_depends, + const cmCustomCommandLines& commandLines) +{ + // Lookup an existing command. + if (cmSourceFile* sf = lg.GetMakefile()->GetSourceFileWithOutput(output)) { + if (cmCustomCommand* cc = sf->GetCustomCommand()) { + cc->AppendCommands(commandLines); + cc->AppendDepends(depends); + cc->AppendImplicitDepends(implicit_depends); + return; + } + } + + // No existing command found. + lg.GetCMakeInstance()->IssueMessage( + MessageType::FATAL_ERROR, + cmStrCat("Attempt to append to output\n ", output, + "\nwhich is not already a custom command output."), + lfbt); +} + +void AddUtilityCommand(cmLocalGenerator& lg, const cmListFileBacktrace& lfbt, + cmCommandOrigin origin, cmTarget* target, + const cmUtilityOutput& force, const char* workingDir, + const std::vector<std::string>& byproducts, + const std::vector<std::string>& depends, + const cmCustomCommandLines& commandLines, + bool escapeOldStyle, const char* comment, + bool uses_terminal, bool command_expand_lists, + const std::string& job_pool) +{ + // Always create the byproduct sources and mark them generated. + CreateGeneratedSource(lg, force.Name, origin, lfbt); + CreateGeneratedSources(lg, byproducts, origin, lfbt); + + // Use an empty comment to avoid generation of default comment. + if (!comment) { + comment = ""; + } + + std::string no_main_dependency; + cmImplicitDependsList no_implicit_depends; + cmSourceFile* rule = AddCustomCommand( + lg, lfbt, { force.Name }, byproducts, depends, no_main_dependency, + no_implicit_depends, commandLines, comment, workingDir, /*replace=*/false, + escapeOldStyle, uses_terminal, command_expand_lists, /*depfile=*/"", + job_pool); + if (rule) { + lg.GetMakefile()->AddTargetByproducts(target, byproducts); + } + + if (!force.NameCMP0049.empty()) { + target->AddSource(force.NameCMP0049); + } +} +} diff --git a/Source/cmLocalGenerator.h b/Source/cmLocalGenerator.h index 12359db..b91d5f7 100644 --- a/Source/cmLocalGenerator.h +++ b/Source/cmLocalGenerator.h @@ -7,6 +7,7 @@ #include <iosfwd> #include <map> +#include <memory> #include <set> #include <string> #include <unordered_map> @@ -14,6 +15,7 @@ #include "cm_kwiml.h" +#include "cmCustomCommandTypes.h" #include "cmListFileCache.h" #include "cmMessageType.h" #include "cmOutputConverter.h" @@ -22,13 +24,16 @@ class cmComputeLinkInformation; class cmCustomCommandGenerator; +class cmCustomCommandLines; class cmGeneratorTarget; class cmGlobalGenerator; +class cmImplicitDependsList; class cmLinkLineComputer; class cmMakefile; class cmRulePlaceholderExpander; class cmSourceFile; class cmState; +class cmTarget; class cmake; /** \class cmLocalGenerator @@ -143,14 +148,16 @@ public: bool forResponseFile = false, const std::string& config = ""); - const std::vector<cmGeneratorTarget*>& GetGeneratorTargets() const + using GeneratorTargetVector = + std::vector<std::unique_ptr<cmGeneratorTarget>>; + const GeneratorTargetVector& GetGeneratorTargets() const { return this->GeneratorTargets; } - void AddGeneratorTarget(cmGeneratorTarget* gt); + void AddGeneratorTarget(std::unique_ptr<cmGeneratorTarget> gt); void AddImportedGeneratorTarget(cmGeneratorTarget* gt); - void AddOwnedImportedGeneratorTarget(cmGeneratorTarget* gt); + void AddOwnedImportedGeneratorTarget(std::unique_ptr<cmGeneratorTarget> gt); cmGeneratorTarget* FindLocalNonAliasGeneratorTarget( const std::string& name) const; @@ -292,6 +299,51 @@ public: cmGeneratorTarget* target, const std::string& lang, const std::string& config); + /** + * Add a custom PRE_BUILD, PRE_LINK, or POST_BUILD command to a target. + */ + cmTarget* AddCustomCommandToTarget( + const std::string& target, const std::vector<std::string>& byproducts, + const std::vector<std::string>& depends, + const cmCustomCommandLines& commandLines, cmCustomCommandType type, + const char* comment, const char* workingDir, bool escapeOldStyle = true, + bool uses_terminal = false, const std::string& depfile = "", + const std::string& job_pool = "", bool command_expand_lists = false, + cmObjectLibraryCommands objLibCommands = cmObjectLibraryCommands::Reject); + + /** + * Add a custom command to a source file. + */ + cmSourceFile* AddCustomCommandToOutput( + const std::string& output, const std::vector<std::string>& depends, + const std::string& main_dependency, + const cmCustomCommandLines& commandLines, const char* comment, + const char* workingDir, bool replace = false, bool escapeOldStyle = true, + bool uses_terminal = false, bool command_expand_lists = false, + const std::string& depfile = "", const std::string& job_pool = ""); + cmSourceFile* AddCustomCommandToOutput( + const std::vector<std::string>& outputs, + const std::vector<std::string>& byproducts, + const std::vector<std::string>& depends, + const std::string& main_dependency, + const cmImplicitDependsList& implicit_depends, + const cmCustomCommandLines& commandLines, const char* comment, + const char* workingDir, bool replace = false, bool escapeOldStyle = true, + bool uses_terminal = false, bool command_expand_lists = false, + const std::string& depfile = "", const std::string& job_pool = ""); + + /** + * Add a utility to the build. A utility target is a command that is run + * every time the target is built. + */ + cmTarget* AddUtilityCommand( + const std::string& utilityName, bool excludeFromAll, + const char* workingDir, const std::vector<std::string>& byproducts, + const std::vector<std::string>& depends, + const cmCustomCommandLines& commandLines, bool escapeOldStyle = true, + const char* comment = nullptr, bool uses_terminal = false, + bool command_expand_lists = false, const std::string& job_pool = ""); + std::string GetProjectName() const; /** Compute the language used to compile the given source file. */ @@ -414,6 +466,7 @@ public: bool IsWatcomWMake() const; bool IsMinGWMake() const; bool IsNMake() const; + bool IsNinjaMulti() const; void IssueMessage(MessageType t, std::string const& text) const; @@ -461,11 +514,11 @@ protected: using GeneratorTargetMap = std::unordered_map<std::string, cmGeneratorTarget*>; GeneratorTargetMap GeneratorTargetSearchIndex; - std::vector<cmGeneratorTarget*> GeneratorTargets; + GeneratorTargetVector GeneratorTargets; std::set<cmGeneratorTarget const*> WarnCMP0063; GeneratorTargetMap ImportedGeneratorTargets; - std::vector<cmGeneratorTarget*> OwnedImportedGeneratorTargets; + GeneratorTargetVector OwnedImportedGeneratorTargets; std::map<std::string, std::string> AliasTargets; std::map<std::string, std::string> Compilers; @@ -494,4 +547,46 @@ bool cmLocalGeneratorCheckObjectName(std::string& objName, std::string::size_type max_total_len); #endif +namespace detail { +void AddCustomCommandToTarget(cmLocalGenerator& lg, + const cmListFileBacktrace& lfbt, + cmCommandOrigin origin, cmTarget* target, + const std::vector<std::string>& byproducts, + const std::vector<std::string>& depends, + const cmCustomCommandLines& commandLines, + cmCustomCommandType type, const char* comment, + const char* workingDir, bool escapeOldStyle, + bool uses_terminal, const std::string& depfile, + const std::string& job_pool, + bool command_expand_lists); + +cmSourceFile* AddCustomCommandToOutput( + cmLocalGenerator& lg, const cmListFileBacktrace& lfbt, + cmCommandOrigin origin, const std::vector<std::string>& outputs, + const std::vector<std::string>& byproducts, + const std::vector<std::string>& depends, const std::string& main_dependency, + const cmImplicitDependsList& implicit_depends, + const cmCustomCommandLines& commandLines, const char* comment, + const char* workingDir, bool replace, bool escapeOldStyle, + bool uses_terminal, bool command_expand_lists, const std::string& depfile, + const std::string& job_pool); + +void AppendCustomCommandToOutput(cmLocalGenerator& lg, + const cmListFileBacktrace& lfbt, + const std::string& output, + const std::vector<std::string>& depends, + const cmImplicitDependsList& implicit_depends, + const cmCustomCommandLines& commandLines); + +void AddUtilityCommand(cmLocalGenerator& lg, const cmListFileBacktrace& lfbt, + cmCommandOrigin origin, cmTarget* target, + const cmUtilityOutput& force, const char* workingDir, + const std::vector<std::string>& byproducts, + const std::vector<std::string>& depends, + const cmCustomCommandLines& commandLines, + bool escapeOldStyle, const char* comment, + bool uses_terminal, bool command_expand_lists, + const std::string& job_pool); +} + #endif diff --git a/Source/cmLocalGhsMultiGenerator.cxx b/Source/cmLocalGhsMultiGenerator.cxx index 4b10798..098fa5a 100644 --- a/Source/cmLocalGhsMultiGenerator.cxx +++ b/Source/cmLocalGhsMultiGenerator.cxx @@ -5,6 +5,8 @@ #include <algorithm> #include <utility> +#include <cmext/algorithm> + #include "cmGeneratorTarget.h" #include "cmGhsMultiTargetGenerator.h" #include "cmGlobalGenerator.h" @@ -50,10 +52,11 @@ void cmLocalGhsMultiGenerator::GenerateTargetsDepthFirst( void cmLocalGhsMultiGenerator::Generate() { - std::vector<cmGeneratorTarget*> remaining = this->GetGeneratorTargets(); + std::vector<cmGeneratorTarget*> remaining; + cm::append(remaining, this->GetGeneratorTargets()); for (auto& t : remaining) { if (t) { - GenerateTargetsDepthFirst(t, remaining); + this->GenerateTargetsDepthFirst(t, remaining); } } } diff --git a/Source/cmLocalNinjaGenerator.cxx b/Source/cmLocalNinjaGenerator.cxx index 134bbe1..6967097 100644 --- a/Source/cmLocalNinjaGenerator.cxx +++ b/Source/cmLocalNinjaGenerator.cxx @@ -29,6 +29,7 @@ #include "cmStateTypes.h" #include "cmStringAlgorithms.h" #include "cmSystemTools.h" +#include "cmTarget.h" #include "cmake.h" cmLocalNinjaGenerator::cmLocalNinjaGenerator(cmGlobalGenerator* gg, @@ -61,7 +62,12 @@ void cmLocalNinjaGenerator::Generate() this->HomeRelativeOutputPath.clear(); } - this->WriteProcessedMakefile(this->GetBuildFileStream()); + if (this->GetGlobalGenerator()->IsMultiConfig()) { + for (auto const& config : this->GetConfigNames()) { + this->WriteProcessedMakefile(this->GetConfigFileStream(config)); + } + } + this->WriteProcessedMakefile(this->GetCommonFileStream()); #ifdef NINJA_GEN_VERBOSE_FILES this->WriteProcessedMakefile(this->GetRulesFileStream()); #endif @@ -82,18 +88,26 @@ void cmLocalNinjaGenerator::Generate() } } - for (cmGeneratorTarget* target : this->GetGeneratorTargets()) { + for (const auto& target : this->GetGeneratorTargets()) { if (target->GetType() == cmStateEnums::INTERFACE_LIBRARY) { continue; } - auto tg = cmNinjaTargetGenerator::New(target); + auto tg = cmNinjaTargetGenerator::New(target.get()); if (tg) { - tg->Generate(); + if (target->Target->IsPerConfig()) { + for (auto const& config : this->GetConfigNames()) { + tg->Generate(config); + } + } else { + tg->Generate(""); + } } } - this->WriteCustomCommandBuildStatements(); - this->AdditionalCleanFiles(); + for (auto const& config : this->GetConfigNames()) { + this->WriteCustomCommandBuildStatements(config); + this->AdditionalCleanFiles(config); + } } // TODO: Picked up from cmLocalUnixMakefileGenerator3. Refactor it. @@ -140,9 +154,15 @@ std::string cmLocalNinjaGenerator::ConvertToIncludeReference( // Private methods. -cmGeneratedFileStream& cmLocalNinjaGenerator::GetBuildFileStream() const +cmGeneratedFileStream& cmLocalNinjaGenerator::GetConfigFileStream( + const std::string& config) const { - return *this->GetGlobalNinjaGenerator()->GetBuildFileStream(); + return *this->GetGlobalNinjaGenerator()->GetConfigFileStream(config); +} + +cmGeneratedFileStream& cmLocalNinjaGenerator::GetCommonFileStream() const +{ + return *this->GetGlobalNinjaGenerator()->GetCommonFileStream(); } cmGeneratedFileStream& cmLocalNinjaGenerator::GetRulesFileStream() const @@ -162,10 +182,22 @@ cmake* cmLocalNinjaGenerator::GetCMakeInstance() void cmLocalNinjaGenerator::WriteBuildFileTop() { - // For the build file. - this->WriteProjectHeader(this->GetBuildFileStream()); - this->WriteNinjaRequiredVersion(this->GetBuildFileStream()); - this->WriteNinjaFilesInclusion(this->GetBuildFileStream()); + this->WriteProjectHeader(this->GetCommonFileStream()); + + if (this->GetGlobalGenerator()->IsMultiConfig()) { + for (auto const& config : this->GetConfigNames()) { + auto& stream = this->GetConfigFileStream(config); + this->WriteProjectHeader(stream); + this->WriteNinjaRequiredVersion(stream); + this->WriteNinjaConfigurationVariable(stream, config); + this->WriteNinjaFilesInclusionConfig(stream); + } + } else { + this->WriteNinjaRequiredVersion(this->GetCommonFileStream()); + this->WriteNinjaConfigurationVariable(this->GetCommonFileStream(), + this->GetConfigNames().front()); + } + this->WriteNinjaFilesInclusionCommon(this->GetCommonFileStream()); // For the rule file. this->WriteProjectHeader(this->GetRulesFileStream()); @@ -175,7 +207,8 @@ void cmLocalNinjaGenerator::WriteProjectHeader(std::ostream& os) { cmGlobalNinjaGenerator::WriteDivider(os); os << "# Project: " << this->GetProjectName() << std::endl - << "# Configuration: " << this->ConfigName << std::endl; + << "# Configurations: " << cmJoin(this->GetConfigNames(), ", ") + << std::endl; cmGlobalNinjaGenerator::WriteDivider(os); } @@ -206,6 +239,14 @@ void cmLocalNinjaGenerator::WriteNinjaRequiredVersion(std::ostream& os) << std::endl; } +void cmLocalNinjaGenerator::WriteNinjaConfigurationVariable( + std::ostream& os, const std::string& config) +{ + cmGlobalNinjaGenerator::WriteVariable( + os, "CONFIGURATION", config, + "Set configuration variable for custom commands."); +} + void cmLocalNinjaGenerator::WritePools(std::ostream& os) { cmGlobalNinjaGenerator::WriteDivider(os); @@ -235,7 +276,21 @@ void cmLocalNinjaGenerator::WritePools(std::ostream& os) } } -void cmLocalNinjaGenerator::WriteNinjaFilesInclusion(std::ostream& os) +void cmLocalNinjaGenerator::WriteNinjaFilesInclusionConfig(std::ostream& os) +{ + cmGlobalNinjaGenerator::WriteDivider(os); + os << "# Include auxiliary files.\n" + << "\n"; + cmGlobalNinjaGenerator* ng = this->GetGlobalNinjaGenerator(); + std::string const ninjaCommonFile = + ng->NinjaOutputPath(cmGlobalNinjaMultiGenerator::NINJA_COMMON_FILE); + std::string const commonFilePath = ng->EncodePath(ninjaCommonFile); + cmGlobalNinjaGenerator::WriteInclude(os, commonFilePath, + "Include common file."); + os << "\n"; +} + +void cmLocalNinjaGenerator::WriteNinjaFilesInclusionCommon(std::ostream& os) { cmGlobalNinjaGenerator::WriteDivider(os); os << "# Include auxiliary files.\n" @@ -263,25 +318,30 @@ void cmLocalNinjaGenerator::WriteProcessedMakefile(std::ostream& os) } void cmLocalNinjaGenerator::AppendTargetOutputs(cmGeneratorTarget* target, - cmNinjaDeps& outputs) + cmNinjaDeps& outputs, + const std::string& config) { - this->GetGlobalNinjaGenerator()->AppendTargetOutputs(target, outputs); + this->GetGlobalNinjaGenerator()->AppendTargetOutputs(target, outputs, + config); } void cmLocalNinjaGenerator::AppendTargetDepends(cmGeneratorTarget* target, cmNinjaDeps& outputs, + const std::string& config, + const std::string& fileConfig, cmNinjaTargetDepends depends) { - this->GetGlobalNinjaGenerator()->AppendTargetDepends(target, outputs, - depends); + this->GetGlobalNinjaGenerator()->AppendTargetDepends(target, outputs, config, + fileConfig, depends); } void cmLocalNinjaGenerator::AppendCustomCommandDeps( - cmCustomCommandGenerator const& ccg, cmNinjaDeps& ninjaDeps) + cmCustomCommandGenerator const& ccg, cmNinjaDeps& ninjaDeps, + const std::string& config) { for (std::string const& i : ccg.GetDepends()) { std::string dep; - if (this->GetRealDependency(i, this->GetConfigName(), dep)) { + if (this->GetRealDependency(i, config, dep)) { ninjaDeps.push_back( this->GetGlobalNinjaGenerator()->ConvertToNinjaPath(dep)); } @@ -416,6 +476,8 @@ std::string cmLocalNinjaGenerator::BuildCommandLine( void cmLocalNinjaGenerator::AppendCustomCommandLines( cmCustomCommandGenerator const& ccg, std::vector<std::string>& cmdLines) { + auto* gg = this->GetGlobalNinjaGenerator(); + if (ccg.GetNumberOfCommands() > 0) { std::string wd = ccg.GetWorkingDirectory(); if (wd.empty()) { @@ -437,8 +499,10 @@ void cmLocalNinjaGenerator::AppendCustomCommandLines( for (unsigned i = 0; i != ccg.GetNumberOfCommands(); ++i) { cmdLines.push_back(launcher + - this->ConvertToOutputFormat(ccg.GetCommand(i), - cmOutputConverter::SHELL)); + this->ConvertToOutputFormat( + ccg.GetCommand(i), + gg->IsMultiConfig() ? cmOutputConverter::NINJAMULTI + : cmOutputConverter::SHELL)); std::string& cmd = cmdLines.back(); ccg.AppendArguments(i, cmd); @@ -446,14 +510,15 @@ void cmLocalNinjaGenerator::AppendCustomCommandLines( } void cmLocalNinjaGenerator::WriteCustomCommandBuildStatement( - cmCustomCommand const* cc, const cmNinjaDeps& orderOnlyDeps) + cmCustomCommand const* cc, const cmNinjaDeps& orderOnlyDeps, + const std::string& config) { cmGlobalNinjaGenerator* gg = this->GetGlobalNinjaGenerator(); - if (gg->SeenCustomCommand(cc)) { + if (gg->SeenCustomCommand(cc, config)) { return; } - cmCustomCommandGenerator ccg(*cc, this->GetConfigName(), this); + cmCustomCommandGenerator ccg(*cc, config, this); const std::vector<std::string>& outputs = ccg.GetOutputs(); const std::vector<std::string>& byproducts = ccg.GetByproducts(); @@ -484,7 +549,7 @@ void cmLocalNinjaGenerator::WriteCustomCommandBuildStatement( } cmNinjaDeps ninjaDeps; - this->AppendCustomCommandDeps(ccg, ninjaDeps); + this->AppendCustomCommandDeps(ccg, ninjaDeps, config); std::vector<std::string> cmdLines; this->AppendCustomCommandLines(ccg, cmdLines); @@ -495,7 +560,7 @@ void cmLocalNinjaGenerator::WriteCustomCommandBuildStatement( build.Outputs = std::move(ninjaOutputs); build.ExplicitDeps = std::move(ninjaDeps); build.OrderOnlyDeps = orderOnlyDeps; - gg->WriteBuild(this->GetBuildFileStream(), build); + gg->WriteBuild(this->GetConfigFileStream(config), build); } else { std::string customStep = cmSystemTools::GetFilenameName(ninjaOutputs[0]); // Hash full path to make unique. @@ -507,8 +572,8 @@ void cmLocalNinjaGenerator::WriteCustomCommandBuildStatement( this->BuildCommandLine(cmdLines, customStep), this->ConstructComment(ccg), "Custom command for " + ninjaOutputs[0], cc->GetDepfile(), cc->GetJobPool(), cc->GetUsesTerminal(), - /*restat*/ !symbolic || !byproducts.empty(), ninjaOutputs, ninjaDeps, - orderOnlyDeps); + /*restat*/ !symbolic || !byproducts.empty(), ninjaOutputs, config, + ninjaDeps, orderOnlyDeps); } } @@ -524,7 +589,8 @@ void cmLocalNinjaGenerator::AddCustomCommandTarget(cmCustomCommand const* cc, ins.first->second.insert(target); } -void cmLocalNinjaGenerator::WriteCustomCommandBuildStatements() +void cmLocalNinjaGenerator::WriteCustomCommandBuildStatements( + const std::string& config) { for (cmCustomCommand const* customCommand : this->CustomCommands) { auto i = this->CustomCommandTargets.find(customCommand); @@ -542,15 +608,16 @@ void cmLocalNinjaGenerator::WriteCustomCommandBuildStatements() auto j = i->second.begin(); assert(j != i->second.end()); std::vector<std::string> ccTargetDeps; - this->GetGlobalNinjaGenerator()->AppendTargetDependsClosure(*j, - ccTargetDeps); + this->GetGlobalNinjaGenerator()->AppendTargetDependsClosure( + *j, ccTargetDeps, config); std::sort(ccTargetDeps.begin(), ccTargetDeps.end()); ++j; for (; j != i->second.end(); ++j) { std::vector<std::string> jDeps; std::vector<std::string> depsIntersection; - this->GetGlobalNinjaGenerator()->AppendTargetDependsClosure(*j, jDeps); + this->GetGlobalNinjaGenerator()->AppendTargetDependsClosure(*j, jDeps, + config); std::sort(jDeps.begin(), jDeps.end()); std::set_intersection(ccTargetDeps.begin(), ccTargetDeps.end(), jDeps.begin(), jDeps.end(), @@ -558,7 +625,7 @@ void cmLocalNinjaGenerator::WriteCustomCommandBuildStatements() ccTargetDeps = depsIntersection; } - this->WriteCustomCommandBuildStatement(i->first, ccTargetDeps); + this->WriteCustomCommandBuildStatement(i->first, ccTargetDeps, config); } } @@ -599,15 +666,13 @@ std::string cmLocalNinjaGenerator::MakeCustomLauncher( return launcher; } -void cmLocalNinjaGenerator::AdditionalCleanFiles() +void cmLocalNinjaGenerator::AdditionalCleanFiles(const std::string& config) { if (const char* prop_value = this->Makefile->GetProperty("ADDITIONAL_CLEAN_FILES")) { std::vector<std::string> cleanFiles; { - cmExpandList(cmGeneratorExpression::Evaluate( - prop_value, this, - this->Makefile->GetSafeDefinition("CMAKE_BUILD_TYPE")), + cmExpandList(cmGeneratorExpression::Evaluate(prop_value, this, config), cleanFiles); } std::string const& binaryDir = this->GetCurrentBinaryDirectory(); @@ -615,7 +680,7 @@ void cmLocalNinjaGenerator::AdditionalCleanFiles() for (std::string const& cleanFile : cleanFiles) { // Support relative paths gg->AddAdditionalCleanFile( - cmSystemTools::CollapseFullPath(cleanFile, binaryDir)); + cmSystemTools::CollapseFullPath(cleanFile, binaryDir), config); } } } diff --git a/Source/cmLocalNinjaGenerator.h b/Source/cmLocalNinjaGenerator.h index f64534c..0445879 100644 --- a/Source/cmLocalNinjaGenerator.h +++ b/Source/cmLocalNinjaGenerator.h @@ -64,9 +64,11 @@ public: std::string const& customStep = std::string(), cmGeneratorTarget const* target = nullptr) const; - void AppendTargetOutputs(cmGeneratorTarget* target, cmNinjaDeps& outputs); + void AppendTargetOutputs(cmGeneratorTarget* target, cmNinjaDeps& outputs, + const std::string& config); void AppendTargetDepends( - cmGeneratorTarget* target, cmNinjaDeps& outputs, + cmGeneratorTarget* target, cmNinjaDeps& outputs, const std::string& config, + const std::string& fileConfig, cmNinjaTargetDepends depends = DependOnTargetArtifact); void AddCustomCommandTarget(cmCustomCommand const* cc, @@ -74,7 +76,8 @@ public: void AppendCustomCommandLines(cmCustomCommandGenerator const& ccg, std::vector<std::string>& cmdLines); void AppendCustomCommandDeps(cmCustomCommandGenerator const& ccg, - cmNinjaDeps& ninjaDeps); + cmNinjaDeps& ninjaDeps, + const std::string& config); protected: std::string ConvertToIncludeReference( @@ -83,20 +86,25 @@ protected: bool forceFullPaths = false) override; private: - cmGeneratedFileStream& GetBuildFileStream() const; + cmGeneratedFileStream& GetConfigFileStream(const std::string& config) const; + cmGeneratedFileStream& GetCommonFileStream() const; cmGeneratedFileStream& GetRulesFileStream() const; void WriteBuildFileTop(); void WriteProjectHeader(std::ostream& os); void WriteNinjaRequiredVersion(std::ostream& os); - void WriteNinjaFilesInclusion(std::ostream& os); + void WriteNinjaConfigurationVariable(std::ostream& os, + const std::string& config); + void WriteNinjaFilesInclusionConfig(std::ostream& os); + void WriteNinjaFilesInclusionCommon(std::ostream& os); void WriteProcessedMakefile(std::ostream& os); void WritePools(std::ostream& os); void WriteCustomCommandBuildStatement(cmCustomCommand const* cc, - const cmNinjaDeps& orderOnlyDeps); + const cmNinjaDeps& orderOnlyDeps, + const std::string& config); - void WriteCustomCommandBuildStatements(); + void WriteCustomCommandBuildStatements(const std::string& config); std::string MakeCustomLauncher(cmCustomCommandGenerator const& ccg); @@ -104,7 +112,7 @@ private: std::string const& customStep, cmGeneratorTarget const* target) const; - void AdditionalCleanFiles(); + void AdditionalCleanFiles(const std::string& config); std::string HomeRelativeOutputPath; diff --git a/Source/cmLocalUnixMakefileGenerator3.cxx b/Source/cmLocalUnixMakefileGenerator3.cxx index 4a70248..f6a0e34 100644 --- a/Source/cmLocalUnixMakefileGenerator3.cxx +++ b/Source/cmLocalUnixMakefileGenerator3.cxx @@ -3,11 +3,13 @@ #include "cmLocalUnixMakefileGenerator3.h" #include <algorithm> +#include <cassert> #include <cstdio> #include <sstream> #include <utility> #include <cm/memory> +#include <cmext/algorithm> #include "cmsys/FStream.hxx" #include "cmsys/Terminal.h" @@ -106,6 +108,13 @@ cmLocalUnixMakefileGenerator3::cmLocalUnixMakefileGenerator3( cmLocalUnixMakefileGenerator3::~cmLocalUnixMakefileGenerator3() = default; +std::string cmLocalUnixMakefileGenerator3::GetConfigName() const +{ + auto const& configNames = this->GetConfigNames(); + assert(configNames.size() == 1); + return configNames.front(); +} + void cmLocalUnixMakefileGenerator3::Generate() { // Record whether some options are enabled to avoid checking many @@ -121,12 +130,12 @@ void cmLocalUnixMakefileGenerator3::Generate() // Generate the rule files for each target. cmGlobalUnixMakefileGenerator3* gg = static_cast<cmGlobalUnixMakefileGenerator3*>(this->GlobalGenerator); - for (cmGeneratorTarget* target : this->GetGeneratorTargets()) { + for (const auto& target : this->GetGeneratorTargets()) { if (target->GetType() == cmStateEnums::INTERFACE_LIBRARY) { continue; } std::unique_ptr<cmMakefileTargetGenerator> tg( - cmMakefileTargetGenerator::New(target)); + cmMakefileTargetGenerator::New(target.get())); if (tg) { tg->WriteRuleFiles(); gg->RecordTargetProgress(tg.get()); @@ -157,15 +166,15 @@ void cmLocalUnixMakefileGenerator3::ComputeHomeRelativeOutputPath() void cmLocalUnixMakefileGenerator3::GetLocalObjectFiles( std::map<std::string, LocalObjectInfo>& localObjectFiles) { - for (cmGeneratorTarget* gt : this->GetGeneratorTargets()) { + for (const auto& gt : this->GetGeneratorTargets()) { if (gt->GetType() == cmStateEnums::INTERFACE_LIBRARY) { continue; } std::vector<cmSourceFile const*> objectSources; - gt->GetObjectSources(objectSources, this->ConfigName); + gt->GetObjectSources(objectSources, this->GetConfigName()); // Compute full path to object file directory for this target. std::string dir = cmStrCat(gt->LocalGenerator->GetCurrentBinaryDirectory(), - '/', this->GetTargetDirectory(gt), '/'); + '/', this->GetTargetDirectory(gt.get()), '/'); // Compute the name of each object file. for (cmSourceFile const* sf : objectSources) { bool hasSourceExtension = true; @@ -176,7 +185,7 @@ void cmLocalUnixMakefileGenerator3::GetLocalObjectFiles( } LocalObjectInfo& info = localObjectFiles[objectName]; info.HasSourceExtension = hasSourceExtension; - info.emplace_back(gt, sf->GetLanguage()); + info.emplace_back(gt.get(), sf->GetLanguage()); } } } @@ -352,7 +361,7 @@ void cmLocalUnixMakefileGenerator3::WriteLocalMakefileTargets( // for each target we just provide a rule to cd up to the top and do a make // on the target std::string localName; - for (cmGeneratorTarget* target : this->GetGeneratorTargets()) { + for (const auto& target : this->GetGeneratorTargets()) { if ((target->GetType() == cmStateEnums::EXECUTABLE) || (target->GetType() == cmStateEnums::STATIC_LIBRARY) || (target->GetType() == cmStateEnums::SHARED_LIBRARY) || @@ -362,7 +371,8 @@ void cmLocalUnixMakefileGenerator3::WriteLocalMakefileTargets( emitted.insert(target->GetName()); // for subdirs add a rule to build this specific target by name. - localName = cmStrCat(this->GetRelativeTargetDirectory(target), "/rule"); + localName = + cmStrCat(this->GetRelativeTargetDirectory(target.get()), "/rule"); commands.clear(); depends.clear(); @@ -383,11 +393,11 @@ void cmLocalUnixMakefileGenerator3::WriteLocalMakefileTargets( } // Add a fast rule to build the target - std::string makefileName = - cmStrCat(this->GetRelativeTargetDirectory(target), "/build.make"); + std::string makefileName = cmStrCat( + this->GetRelativeTargetDirectory(target.get()), "/build.make"); // make sure the makefile name is suitable for a makefile std::string makeTargetName = - cmStrCat(this->GetRelativeTargetDirectory(target), "/build"); + cmStrCat(this->GetRelativeTargetDirectory(target.get()), "/build"); localName = cmStrCat(target->GetName(), "/fast"); depends.clear(); commands.clear(); @@ -400,9 +410,9 @@ void cmLocalUnixMakefileGenerator3::WriteLocalMakefileTargets( // Add a local name for the rule to relink the target before // installation. - if (target->NeedRelinkBeforeInstall(this->ConfigName)) { - makeTargetName = - cmStrCat(this->GetRelativeTargetDirectory(target), "/preinstall"); + if (target->NeedRelinkBeforeInstall(this->GetConfigName())) { + makeTargetName = cmStrCat( + this->GetRelativeTargetDirectory(target.get()), "/preinstall"); localName = cmStrCat(target->GetName(), "/preinstall"); depends.clear(); commands.clear(); @@ -628,7 +638,7 @@ void cmLocalUnixMakefileGenerator3::WriteMakeVariables( << "# The command to remove a file.\n" << "RM = " << cmakeShellCommand - << " -E remove -f\n" + << " -E rm -f\n" << "\n"; makefileStream << "# Escaping for special characters.\n" @@ -849,7 +859,7 @@ void cmLocalUnixMakefileGenerator3::AppendRuleDepends( // Add a dependency on the rule file itself unless an option to skip // it is specifically enabled by the user or project. if (!this->Makefile->IsOn("CMAKE_SKIP_RULE_DEPENDENCY")) { - cmAppend(depends, ruleFiles); + cm::append(depends, ruleFiles); } } @@ -857,7 +867,7 @@ void cmLocalUnixMakefileGenerator3::AppendCustomDepends( std::vector<std::string>& depends, const std::vector<cmCustomCommand>& ccs) { for (cmCustomCommand const& cc : ccs) { - cmCustomCommandGenerator ccg(cc, this->ConfigName, this); + cmCustomCommandGenerator ccg(cc, this->GetConfigName(), this); this->AppendCustomDepend(depends, ccg); } } @@ -868,7 +878,7 @@ void cmLocalUnixMakefileGenerator3::AppendCustomDepend( for (std::string const& d : ccg.GetDepends()) { // Lookup the real name of the dependency in case it is a CMake target. std::string dep; - if (this->GetRealDependency(d, this->ConfigName, dep)) { + if (this->GetRealDependency(d, this->GetConfigName(), dep)) { depends.push_back(std::move(dep)); } } @@ -879,7 +889,7 @@ void cmLocalUnixMakefileGenerator3::AppendCustomCommands( cmGeneratorTarget* target, std::string const& relative) { for (cmCustomCommand const& cc : ccs) { - cmCustomCommandGenerator ccg(cc, this->ConfigName, this); + cmCustomCommandGenerator ccg(cc, this->GetConfigName(), this); this->AppendCustomCommand(commands, ccg, target, relative, true); } } @@ -1022,7 +1032,7 @@ void cmLocalUnixMakefileGenerator3::AppendCustomCommand( this->CreateCDCommand(commands1, dir, relative); // push back the custom commands - cmAppend(commands, commands1); + cm::append(commands, commands1); } void cmLocalUnixMakefileGenerator3::AppendCleanCommand( @@ -1093,8 +1103,7 @@ void cmLocalUnixMakefileGenerator3::AppendDirectoryCleanCommand( return; } - cmLocalGenerator* rootLG = - this->GetGlobalGenerator()->GetLocalGenerators().at(0); + const auto& rootLG = this->GetGlobalGenerator()->GetLocalGenerators().at(0); std::string const& binaryDir = rootLG->GetCurrentBinaryDirectory(); std::string const& currentBinaryDir = this->GetCurrentBinaryDirectory(); std::string cleanfile = @@ -1551,8 +1560,8 @@ void cmLocalUnixMakefileGenerator3::WriteLocalAllRules( this->WriteDivider(ruleFileStream); ruleFileStream << "# Targets provided globally by CMake.\n" << "\n"; - const std::vector<cmGeneratorTarget*>& targets = this->GetGeneratorTargets(); - for (cmGeneratorTarget* gt : targets) { + const auto& targets = this->GetGeneratorTargets(); + for (const auto& gt : targets) { if (gt->GetType() == cmStateEnums::GLOBAL_TARGET) { std::string targetString = "Special rule for the target " + gt->GetName(); @@ -1573,10 +1582,10 @@ void cmLocalUnixMakefileGenerator3::WriteLocalAllRules( // Global targets store their rules in pre- and post-build commands. this->AppendCustomDepends(depends, gt->GetPreBuildCommands()); this->AppendCustomDepends(depends, gt->GetPostBuildCommands()); - this->AppendCustomCommands(commands, gt->GetPreBuildCommands(), gt, - this->GetCurrentBinaryDirectory()); - this->AppendCustomCommands(commands, gt->GetPostBuildCommands(), gt, + this->AppendCustomCommands(commands, gt->GetPreBuildCommands(), gt.get(), this->GetCurrentBinaryDirectory()); + this->AppendCustomCommands(commands, gt->GetPostBuildCommands(), + gt.get(), this->GetCurrentBinaryDirectory()); std::string targetName = gt->GetName(); this->WriteMakeRule(ruleFileStream, targetString.c_str(), targetName, depends, commands, true); @@ -1839,7 +1848,7 @@ void cmLocalUnixMakefileGenerator3::WriteDependLanguageInfo( // Build a list of preprocessor definitions for the target. std::set<std::string> defines; - this->GetTargetDefines(target, this->ConfigName, implicitLang.first, + this->GetTargetDefines(target, this->GetConfigName(), implicitLang.first, defines); if (!defines.empty()) { /* clang-format off */ @@ -1863,7 +1872,7 @@ void cmLocalUnixMakefileGenerator3::WriteDependLanguageInfo( std::vector<std::string> includes; this->GetIncludeDirectories(includes, target, implicitLang.first, - this->ConfigName); + this->GetConfigName()); std::string binaryDir = this->GetState()->GetBinaryDirectory(); if (this->Makefile->IsOn("CMAKE_DEPENDS_IN_PROJECT_ONLY")) { std::string const& sourceDir = this->GetState()->GetSourceDirectory(); diff --git a/Source/cmLocalUnixMakefileGenerator3.h b/Source/cmLocalUnixMakefileGenerator3.h index f12ae8b..1629e63 100644 --- a/Source/cmLocalUnixMakefileGenerator3.h +++ b/Source/cmLocalUnixMakefileGenerator3.h @@ -33,6 +33,8 @@ public: cmLocalUnixMakefileGenerator3(cmGlobalGenerator* gg, cmMakefile* mf); ~cmLocalUnixMakefileGenerator3() override; + std::string GetConfigName() const; + void ComputeHomeRelativeOutputPath() override; /** diff --git a/Source/cmLocalVisualStudio10Generator.cxx b/Source/cmLocalVisualStudio10Generator.cxx index f3d828b..6f456c6 100644 --- a/Source/cmLocalVisualStudio10Generator.cxx +++ b/Source/cmLocalVisualStudio10Generator.cxx @@ -2,8 +2,11 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmLocalVisualStudio10Generator.h" +#include <cmext/algorithm> + #include "cm_expat.h" +#include "cmAlgorithms.h" #include "cmGeneratorTarget.h" #include "cmGlobalVisualStudio10Generator.h" #include "cmMakefile.h" @@ -101,10 +104,11 @@ void cmLocalVisualStudio10Generator::GenerateTargetsDepthFirst( void cmLocalVisualStudio10Generator::Generate() { - std::vector<cmGeneratorTarget*> remaining = this->GetGeneratorTargets(); + std::vector<cmGeneratorTarget*> remaining; + cm::append(remaining, this->GetGeneratorTargets()); for (auto& t : remaining) { if (t) { - GenerateTargetsDepthFirst(t, remaining); + this->GenerateTargetsDepthFirst(t, remaining); } } this->WriteStampFiles(); diff --git a/Source/cmLocalVisualStudio7Generator.cxx b/Source/cmLocalVisualStudio7Generator.cxx index ff1eaec..7683855 100644 --- a/Source/cmLocalVisualStudio7Generator.cxx +++ b/Source/cmLocalVisualStudio7Generator.cxx @@ -64,8 +64,8 @@ cmLocalVisualStudio7Generator::~cmLocalVisualStudio7Generator() void cmLocalVisualStudio7Generator::AddHelperCommands() { // Now create GUIDs for targets - const std::vector<cmGeneratorTarget*>& tgts = this->GetGeneratorTargets(); - for (cmGeneratorTarget const* l : tgts) { + const auto& tgts = this->GetGeneratorTargets(); + for (const auto& l : tgts) { if (l->GetType() == cmStateEnums::INTERFACE_LIBRARY) { continue; } @@ -89,8 +89,8 @@ void cmLocalVisualStudio7Generator::FixGlobalTargets() // Visual Studio .NET 2003 Service Pack 1 will not run post-build // commands for targets in which no sources are built. Add dummy // rules to force these targets to build. - const std::vector<cmGeneratorTarget*>& tgts = this->GetGeneratorTargets(); - for (cmGeneratorTarget* l : tgts) { + const auto& tgts = this->GetGeneratorTargets(); + for (auto& l : tgts) { if (l->GetType() == cmStateEnums::GLOBAL_TARGET) { std::vector<std::string> no_depends; cmCustomCommandLines force_commands = @@ -102,9 +102,9 @@ void cmLocalVisualStudio7Generator::FixGlobalTargets() this->Makefile->GetOrCreateGeneratedSource(force)) { sf->SetProperty("SYMBOLIC", "1"); } - if (cmSourceFile* file = this->Makefile->AddCustomCommandToOutput( - force.c_str(), no_depends, no_main_dependency, force_commands, " ", - 0, true)) { + if (cmSourceFile* file = this->AddCustomCommandToOutput( + force, no_depends, no_main_dependency, force_commands, " ", + nullptr, true)) { l->AddSource(file->ResolveFullPath()); } } @@ -125,17 +125,17 @@ void cmLocalVisualStudio7Generator::WriteProjectFiles() } // Get the set of targets in this directory. - const std::vector<cmGeneratorTarget*>& tgts = this->GetGeneratorTargets(); + const auto& tgts = this->GetGeneratorTargets(); // Create the project file for each target. - for (cmGeneratorTarget* l : tgts) { + for (const auto& l : tgts) { if (l->GetType() == cmStateEnums::INTERFACE_LIBRARY) { continue; } // INCLUDE_EXTERNAL_MSPROJECT command only affects the workspace // so don't build a projectfile for it if (!l->GetProperty("EXTERNAL_MSPROJECT")) { - this->CreateSingleVCProj(l->GetName(), l); + this->CreateSingleVCProj(l->GetName(), l.get()); } } } @@ -194,7 +194,7 @@ void cmLocalVisualStudio7Generator::CreateSingleVCProj( } // add to the list of projects - target->Target->SetProperty("GENERATOR_FILE_NAME", lname.c_str()); + target->Target->SetProperty("GENERATOR_FILE_NAME", lname); // create the dsp.cmake file std::string fname; fname = cmStrCat(this->GetCurrentBinaryDirectory(), '/', lname); @@ -259,9 +259,9 @@ cmSourceFile* cmLocalVisualStudio7Generator::CreateVCProjBuildRule() const char* no_working_directory = nullptr; std::string fullpathStampName = cmSystemTools::CollapseFullPath(stampName.c_str()); - this->Makefile->AddCustomCommandToOutput( - fullpathStampName, listFiles, makefileIn, commandLines, comment.c_str(), - no_working_directory, true, false); + this->AddCustomCommandToOutput(fullpathStampName, listFiles, makefileIn, + commandLines, comment.c_str(), + no_working_directory, true, false); if (cmSourceFile* file = this->Makefile->GetSource(makefileIn.c_str())) { // Finalize the source file path now since we're adding this after // the generator validated all project-named sources. @@ -1329,7 +1329,7 @@ void cmLocalVisualStudio7Generator::WriteVCProjFile(std::ostream& fout, // Add CMakeLists.txt file with rule to re-run CMake for user convenience. if (target->GetType() != cmStateEnums::GLOBAL_TARGET && target->GetName() != CMAKE_CHECK_BUILD_SYSTEM_TARGET) { - if (cmSourceFile const* sf = this->CreateVCProjBuildRule()) { + if (cmSourceFile* sf = this->CreateVCProjBuildRule()) { cmGeneratorTarget::AllConfigSource acs; acs.Source = sf; acs.Kind = cmGeneratorTarget::SourceKindCustomCommand; @@ -2053,7 +2053,7 @@ std::string cmLocalVisualStudio7Generator::ConvertToXMLOutputPathSingle( } void cmVS7GeneratorOptions::OutputFlag(std::ostream& fout, int indent, - const char* flag, + const std::string& flag, const std::string& content) { fout.fill('\t'); diff --git a/Source/cmLocalVisualStudio7Generator.h b/Source/cmLocalVisualStudio7Generator.h index 671783f..22a5f9a 100644 --- a/Source/cmLocalVisualStudio7Generator.h +++ b/Source/cmLocalVisualStudio7Generator.h @@ -30,7 +30,7 @@ public: : cmVisualStudioGeneratorOptions(lg, tool, table, extraTable) { } - void OutputFlag(std::ostream& fout, int indent, const char* tag, + void OutputFlag(std::ostream& fout, int indent, const std::string& tag, const std::string& content) override; }; diff --git a/Source/cmLocalVisualStudioGenerator.cxx b/Source/cmLocalVisualStudioGenerator.cxx index 336e3a5..8d50898 100644 --- a/Source/cmLocalVisualStudioGenerator.cxx +++ b/Source/cmLocalVisualStudioGenerator.cxx @@ -104,8 +104,8 @@ cmLocalVisualStudioGenerator::MaybeCreateImplibDir(cmGeneratorTarget* target, std::vector<std::string> no_depends; cmCustomCommandLines commands = cmMakeSingleCommandLine( { cmSystemTools::GetCMakeCommand(), "-E", "make_directory", impDir }); - pcc.reset(new cmCustomCommand(0, no_output, no_byproducts, no_depends, - commands, 0, 0)); + pcc.reset(new cmCustomCommand(no_output, no_byproducts, no_depends, commands, + cmListFileBacktrace(), nullptr, nullptr)); pcc->SetEscapeOldStyle(false); pcc->SetEscapeAllowMakeVars(true); return pcc; diff --git a/Source/cmLocalXCodeGenerator.cxx b/Source/cmLocalXCodeGenerator.cxx index 5a06d4a..ac0d35e 100644 --- a/Source/cmLocalXCodeGenerator.cxx +++ b/Source/cmLocalXCodeGenerator.cxx @@ -40,7 +40,7 @@ void cmLocalXCodeGenerator::Generate() { cmLocalGenerator::Generate(); - for (auto target : this->GetGeneratorTargets()) { + for (const auto& target : this->GetGeneratorTargets()) { target->HasMacOSXRpathInstallNameDir(""); } } @@ -49,7 +49,7 @@ void cmLocalXCodeGenerator::GenerateInstallRules() { cmLocalGenerator::GenerateInstallRules(); - for (auto target : this->GetGeneratorTargets()) { + for (const auto& target : this->GetGeneratorTargets()) { target->HasMacOSXRpathInstallNameDir(""); } } diff --git a/Source/cmMacroCommand.cxx b/Source/cmMacroCommand.cxx index ba9947a..a35dc20 100644 --- a/Source/cmMacroCommand.cxx +++ b/Source/cmMacroCommand.cxx @@ -7,10 +7,10 @@ #include <cm/memory> #include <cm/string_view> +#include <cmext/algorithm> #include "cm_static_string_view.hxx" -#include "cmAlgorithms.h" #include "cmExecutionStatus.h" #include "cmFunctionBlocker.h" #include "cmListFileCache.h" @@ -190,7 +190,7 @@ bool cmMacroCommand(std::vector<std::string> const& args, // create a function blocker { auto fb = cm::make_unique<cmMacroFunctionBlocker>(); - cmAppend(fb->Args, args); + cm::append(fb->Args, args); status.GetMakefile().AddFunctionBlocker(std::move(fb)); } return true; diff --git a/Source/cmMakefile.cxx b/Source/cmMakefile.cxx index f143ef7..75f00fc 100644 --- a/Source/cmMakefile.cxx +++ b/Source/cmMakefile.cxx @@ -14,7 +14,8 @@ #include <utility> #include <cm/iterator> -#include <cm/memory> +#include <cm/optional> +#include <cmext/algorithm> #include "cmsys/FStream.hxx" #include "cmsys/RegularExpression.hxx" @@ -36,6 +37,7 @@ #include "cmInstallGenerator.h" // IWYU pragma: keep #include "cmInstallSubdirectoryGenerator.h" #include "cmListFileCache.h" +#include "cmLocalGenerator.h" #include "cmMessageType.h" #include "cmRange.h" #include "cmSourceFile.h" @@ -146,7 +148,7 @@ void cmMakefile::IssueMessage(MessageType t, std::string const& text) const this->ExecutionStatusStack.back()->SetNestedError(); } } - this->GetCMakeInstance()->IssueMessage(t, text, this->GetBacktrace()); + this->GetCMakeInstance()->IssueMessage(t, text, this->Backtrace); } bool cmMakefile::CheckCMP0037(std::string const& targetName, @@ -780,21 +782,25 @@ struct file_not_persistent }; } -void cmMakefile::AddFinalAction(FinalAction action) +void cmMakefile::AddGeneratorAction(GeneratorAction action) { - this->FinalActions.push_back(std::move(action)); + assert(!this->GeneratorActionsInvoked); + this->GeneratorActions.emplace_back(std::move(action), this->Backtrace); } -void cmMakefile::FinalPass() +void cmMakefile::DoGenerate(cmLocalGenerator& lg) { // do all the variable expansions here this->ExpandVariablesCMP0019(); // give all the commands a chance to do something // after the file has been parsed before generation - for (FinalAction& action : this->FinalActions) { - action(*this); + for (const BT<GeneratorAction>& action : this->GeneratorActions) { + action.Value(lg, action.Backtrace); } + this->GeneratorActionsInvoked = true; + this->DelayedOutputFiles.clear(); + this->DelayedOutputFilesHaveGenex = false; // go through all configured files and see which ones still exist. // we don't want cmake to re-run if a configured file is created and deleted @@ -809,9 +815,9 @@ void cmMakefile::FinalPass() } // Generate the output file -void cmMakefile::ConfigureFinalPass() +void cmMakefile::Generate(cmLocalGenerator& lg) { - this->FinalPass(); + this->DoGenerate(lg); const char* oldValue = this->GetDefinition("CMAKE_BACKWARDS_COMPATIBILITY"); if (oldValue && cmSystemTools::VersionCompare(cmSystemTools::OP_LESS, oldValue, "2.4")) { @@ -825,6 +831,39 @@ void cmMakefile::ConfigureFinalPass() } } +namespace { +// There are still too many implicit backtraces through cmMakefile. As a +// workaround we reset the backtrace temporarily. +struct BacktraceGuard +{ + BacktraceGuard(cmListFileBacktrace& lfbt, cmListFileBacktrace current) + : Backtrace(lfbt) + , Previous(lfbt) + { + this->Backtrace = std::move(current); + } + + ~BacktraceGuard() { this->Backtrace = std::move(Previous); } + +private: + cmListFileBacktrace& Backtrace; + cmListFileBacktrace Previous; +}; + +cm::optional<std::string> MakeOptionalString(const char* str) +{ + if (str) { + return str; + } + return cm::nullopt; +} + +const char* GetCStrOrNull(const cm::optional<std::string>& str) +{ + return str ? str->c_str() : nullptr; +} +} + bool cmMakefile::ValidateCustomCommand( const cmCustomCommandLines& commandLines) const { @@ -842,7 +881,8 @@ bool cmMakefile::ValidateCustomCommand( } cmTarget* cmMakefile::GetCustomCommandTarget( - const std::string& target, cmObjectLibraryCommands objLibCommands) const + const std::string& target, cmObjectLibraryCommands objLibCommands, + const cmListFileBacktrace& lfbt) const { // Find the target to which to add the custom command. auto ti = this->Targets.find(target); @@ -876,7 +916,7 @@ cmTarget* cmMakefile::GetCustomCommandTarget( e << "No TARGET '" << target << "' has been created in this directory."; } - this->IssueMessage(messageType, e.str()); + this->GetCMakeInstance()->IssueMessage(messageType, e.str(), lfbt); } return nullptr; @@ -889,7 +929,8 @@ cmTarget* cmMakefile::GetCustomCommandTarget( e << "Target \"" << target << "\" is an OBJECT library " "that may not have PRE_BUILD, PRE_LINK, or POST_BUILD commands."; - this->IssueMessage(MessageType::FATAL_ERROR, e.str()); + this->GetCMakeInstance()->IssueMessage(MessageType::FATAL_ERROR, e.str(), + lfbt); return nullptr; } if (t->GetType() == cmStateEnums::INTERFACE_LIBRARY) { @@ -897,7 +938,8 @@ cmTarget* cmMakefile::GetCustomCommandTarget( e << "Target \"" << target << "\" is an INTERFACE library " "that may not have PRE_BUILD, PRE_LINK, or POST_BUILD commands."; - this->IssueMessage(MessageType::FATAL_ERROR, e.str()); + this->GetCMakeInstance()->IssueMessage(MessageType::FATAL_ERROR, e.str(), + lfbt); return nullptr; } @@ -910,9 +952,10 @@ cmTarget* cmMakefile::AddCustomCommandToTarget( const cmCustomCommandLines& commandLines, cmCustomCommandType type, const char* comment, const char* workingDir, bool escapeOldStyle, bool uses_terminal, const std::string& depfile, const std::string& job_pool, - bool command_expand_lists, cmObjectLibraryCommands objLibCommands) + bool command_expand_lists) { - cmTarget* t = this->GetCustomCommandTarget(target, objLibCommands); + cmTarget* t = this->GetCustomCommandTarget( + target, cmObjectLibraryCommands::Reject, this->Backtrace); // Validate custom commands. if (!t || !this->ValidateCustomCommand(commandLines)) { @@ -920,175 +963,83 @@ cmTarget* cmMakefile::AddCustomCommandToTarget( } // Always create the byproduct sources and mark them generated. - this->CreateGeneratedSources(byproducts); - - this->CommitCustomCommandToTarget( - t, byproducts, depends, commandLines, type, comment, workingDir, - escapeOldStyle, uses_terminal, depfile, job_pool, command_expand_lists); + this->CreateGeneratedByproducts(byproducts); + + // Strings could be moved into the callback function with C++14. + cm::optional<std::string> commentStr = MakeOptionalString(comment); + cm::optional<std::string> workingStr = MakeOptionalString(workingDir); + + // Dispatch command creation to allow generator expressions in outputs. + this->AddGeneratorAction([=](cmLocalGenerator& lg, + const cmListFileBacktrace& lfbt) { + BacktraceGuard guard(this->Backtrace, lfbt); + detail::AddCustomCommandToTarget( + lg, lfbt, cmCommandOrigin::Project, t, byproducts, depends, commandLines, + type, GetCStrOrNull(commentStr), GetCStrOrNull(workingStr), + escapeOldStyle, uses_terminal, depfile, job_pool, command_expand_lists); + }); return t; } -void cmMakefile::CommitCustomCommandToTarget( - cmTarget* target, const std::vector<std::string>& byproducts, - const std::vector<std::string>& depends, - const cmCustomCommandLines& commandLines, cmCustomCommandType type, - const char* comment, const char* workingDir, bool escapeOldStyle, - bool uses_terminal, const std::string& depfile, const std::string& job_pool, - bool command_expand_lists) -{ - // Add the command to the appropriate build step for the target. - std::vector<std::string> no_output; - cmCustomCommand cc(this, no_output, byproducts, depends, commandLines, - comment, workingDir); - cc.SetEscapeOldStyle(escapeOldStyle); - cc.SetEscapeAllowMakeVars(true); - cc.SetUsesTerminal(uses_terminal); - cc.SetCommandExpandLists(command_expand_lists); - cc.SetDepfile(depfile); - cc.SetJobPool(job_pool); - switch (type) { - case cmCustomCommandType::PRE_BUILD: - target->AddPreBuildCommand(std::move(cc)); - break; - case cmCustomCommandType::PRE_LINK: - target->AddPreLinkCommand(std::move(cc)); - break; - case cmCustomCommandType::POST_BUILD: - target->AddPostBuildCommand(std::move(cc)); - break; - } - - this->AddTargetByproducts(target, byproducts); -} - -cmSourceFile* cmMakefile::AddCustomCommandToOutput( +void cmMakefile::AddCustomCommandToOutput( const std::string& output, const std::vector<std::string>& depends, const std::string& main_dependency, const cmCustomCommandLines& commandLines, - const char* comment, const char* workingDir, bool replace, - bool escapeOldStyle, bool uses_terminal, bool command_expand_lists, - const std::string& depfile, const std::string& job_pool) + const char* comment, const char* workingDir, + const CommandSourceCallback& callback, bool replace, bool escapeOldStyle, + bool uses_terminal, bool command_expand_lists, const std::string& depfile, + const std::string& job_pool) { - std::vector<std::string> outputs; - outputs.push_back(output); std::vector<std::string> no_byproducts; cmImplicitDependsList no_implicit_depends; - return this->AddCustomCommandToOutput( - outputs, no_byproducts, depends, main_dependency, no_implicit_depends, - commandLines, comment, workingDir, replace, escapeOldStyle, uses_terminal, - command_expand_lists, depfile, job_pool); + this->AddCustomCommandToOutput( + { output }, no_byproducts, depends, main_dependency, no_implicit_depends, + commandLines, comment, workingDir, callback, replace, escapeOldStyle, + uses_terminal, command_expand_lists, depfile, job_pool); } -cmSourceFile* cmMakefile::AddCustomCommandToOutput( +void cmMakefile::AddCustomCommandToOutput( const std::vector<std::string>& outputs, const std::vector<std::string>& byproducts, const std::vector<std::string>& depends, const std::string& main_dependency, const cmImplicitDependsList& implicit_depends, const cmCustomCommandLines& commandLines, const char* comment, - const char* workingDir, bool replace, bool escapeOldStyle, - bool uses_terminal, bool command_expand_lists, const std::string& depfile, - const std::string& job_pool) + const char* workingDir, const CommandSourceCallback& callback, bool replace, + bool escapeOldStyle, bool uses_terminal, bool command_expand_lists, + const std::string& depfile, const std::string& job_pool) { // Make sure there is at least one output. if (outputs.empty()) { cmSystemTools::Error("Attempt to add a custom rule with no output!"); - return nullptr; + return; } // Validate custom commands. if (!this->ValidateCustomCommand(commandLines)) { - return nullptr; + return; } // Always create the output sources and mark them generated. - this->CreateGeneratedSources(outputs); - this->CreateGeneratedSources(byproducts); - - return this->CommitCustomCommandToOutput( - outputs, byproducts, depends, main_dependency, implicit_depends, - commandLines, comment, workingDir, replace, escapeOldStyle, uses_terminal, - command_expand_lists, depfile, job_pool); -} - -cmSourceFile* cmMakefile::CommitCustomCommandToOutput( - const std::vector<std::string>& outputs, - const std::vector<std::string>& byproducts, - const std::vector<std::string>& depends, const std::string& main_dependency, - const cmImplicitDependsList& implicit_depends, - const cmCustomCommandLines& commandLines, const char* comment, - const char* workingDir, bool replace, bool escapeOldStyle, - bool uses_terminal, bool command_expand_lists, const std::string& depfile, - const std::string& job_pool) -{ - // Choose a source file on which to store the custom command. - cmSourceFile* file = nullptr; - if (!commandLines.empty() && !main_dependency.empty()) { - // The main dependency was specified. Use it unless a different - // custom command already used it. - file = this->GetSource(main_dependency); - if (file && file->GetCustomCommand() && !replace) { - // The main dependency already has a custom command. - if (commandLines == file->GetCustomCommand()->GetCommandLines()) { - // The existing custom command is identical. Silently ignore - // the duplicate. - return file; - } - // The existing custom command is different. We need to - // generate a rule file for this new command. - file = nullptr; - } else if (!file) { - file = this->CreateSource(main_dependency); - } - } - - // Generate a rule file if the main dependency is not available. - if (!file) { - cmGlobalGenerator* gg = this->GetGlobalGenerator(); - - // Construct a rule file associated with the first output produced. - std::string outName = gg->GenerateRuleFile(outputs[0]); - - // Check if the rule file already exists. - file = this->GetSource(outName, cmSourceFileLocationKind::Known); - if (file && file->GetCustomCommand() && !replace) { - // The rule file already exists. - if (commandLines != file->GetCustomCommand()->GetCommandLines()) { - cmSystemTools::Error("Attempt to add a custom rule to output \"" + - outName + "\" which already has a custom rule."); - } - return file; + this->CreateGeneratedOutputs(outputs); + this->CreateGeneratedByproducts(byproducts); + + // Strings could be moved into the callback function with C++14. + cm::optional<std::string> commentStr = MakeOptionalString(comment); + cm::optional<std::string> workingStr = MakeOptionalString(workingDir); + + // Dispatch command creation to allow generator expressions in outputs. + this->AddGeneratorAction([=](cmLocalGenerator& lg, + const cmListFileBacktrace& lfbt) { + BacktraceGuard guard(this->Backtrace, lfbt); + cmSourceFile* sf = detail::AddCustomCommandToOutput( + lg, lfbt, cmCommandOrigin::Project, outputs, byproducts, depends, + main_dependency, implicit_depends, commandLines, + GetCStrOrNull(commentStr), GetCStrOrNull(workingStr), replace, + escapeOldStyle, uses_terminal, command_expand_lists, depfile, job_pool); + if (callback && sf) { + callback(sf); } - - // Create a cmSourceFile for the rule file. - if (!file) { - file = - this->CreateSource(outName, true, cmSourceFileLocationKind::Known); - } - file->SetProperty("__CMAKE_RULE", "1"); - } - - // Attach the custom command to the file. - if (file) { - // Construct a complete list of dependencies. - std::vector<std::string> depends2(depends); - if (!main_dependency.empty()) { - depends2.push_back(main_dependency); - } - - std::unique_ptr<cmCustomCommand> cc = cm::make_unique<cmCustomCommand>( - this, outputs, byproducts, depends2, commandLines, comment, workingDir); - cc->SetEscapeOldStyle(escapeOldStyle); - cc->SetEscapeAllowMakeVars(true); - cc->SetImplicitDepends(implicit_depends); - cc->SetUsesTerminal(uses_terminal); - cc->SetCommandExpandLists(command_expand_lists); - cc->SetDepfile(depfile); - cc->SetJobPool(job_pool); - file->SetCustomCommand(std::move(cc)); - - this->AddSourceOutputs(file, outputs, byproducts); - } - return file; + }); } void cmMakefile::AddCustomCommandOldStyle( @@ -1136,11 +1087,8 @@ void cmMakefile::AddCustomCommandOldStyle( if (sourceFiles.find(source)) { // The source looks like a real file. Use it as the main dependency. for (std::string const& output : outputs) { - cmSourceFile* sf = this->AddCustomCommandToOutput( - output, depends, source, commandLines, comment, nullptr); - if (sf) { - addRuleFileToTarget(sf); - } + this->AddCustomCommandToOutput(output, depends, source, commandLines, + comment, nullptr, addRuleFileToTarget); } } else { std::string no_main_dependency; @@ -1149,11 +1097,9 @@ void cmMakefile::AddCustomCommandOldStyle( // The source may not be a real file. Do not use a main dependency. for (std::string const& output : outputs) { - cmSourceFile* sf = this->AddCustomCommandToOutput( - output, depends2, no_main_dependency, commandLines, comment, nullptr); - if (sf) { - addRuleFileToTarget(sf); - } + this->AddCustomCommandToOutput(output, depends2, no_main_dependency, + commandLines, comment, nullptr, + addRuleFileToTarget); } } } @@ -1170,29 +1116,18 @@ bool cmMakefile::AppendCustomCommandToOutput( // Validate custom commands. if (this->ValidateCustomCommand(commandLines)) { - // Add command factory to allow generator expressions in output. - this->CommitAppendCustomCommandToOutput(output, depends, implicit_depends, - commandLines); + // Dispatch command creation to allow generator expressions in outputs. + this->AddGeneratorAction( + [=](cmLocalGenerator& lg, const cmListFileBacktrace& lfbt) { + BacktraceGuard guard(this->Backtrace, lfbt); + detail::AppendCustomCommandToOutput(lg, lfbt, output, depends, + implicit_depends, commandLines); + }); } return true; } -void cmMakefile::CommitAppendCustomCommandToOutput( - const std::string& output, const std::vector<std::string>& depends, - const cmImplicitDependsList& implicit_depends, - const cmCustomCommandLines& commandLines) -{ - // Lookup an existing command. - if (cmSourceFile* sf = this->GetSourceFileWithOutput(output)) { - if (cmCustomCommand* cc = sf->GetCustomCommand()) { - cc->AppendCommands(commandLines); - cc->AppendDepends(depends); - cc->AppendImplicitDepends(implicit_depends); - } - } -} - cmUtilityOutput cmMakefile::GetUtilityOutput(cmTarget* target) { std::string force = cmStrCat(this->GetCurrentBinaryDirectory(), @@ -1215,15 +1150,14 @@ cmUtilityOutput cmMakefile::GetUtilityOutput(cmTarget* target) } cmTarget* cmMakefile::AddUtilityCommand( - const std::string& utilityName, cmCommandOrigin origin, bool excludeFromAll, - const char* workingDirectory, const std::vector<std::string>& byproducts, + const std::string& utilityName, bool excludeFromAll, const char* workingDir, + const std::vector<std::string>& byproducts, const std::vector<std::string>& depends, const cmCustomCommandLines& commandLines, bool escapeOldStyle, const char* comment, bool uses_terminal, bool command_expand_lists, const std::string& job_pool) { - cmTarget* target = - this->AddNewUtilityTarget(utilityName, origin, excludeFromAll); + cmTarget* target = this->AddNewUtilityTarget(utilityName, excludeFromAll); // Validate custom commands. if ((commandLines.empty() && depends.empty()) || @@ -1236,45 +1170,26 @@ cmTarget* cmMakefile::AddUtilityCommand( this->GetOrCreateGeneratedSource(force.Name); // Always create the byproduct sources and mark them generated. - this->CreateGeneratedSources(byproducts); - - if (!comment) { - // Use an empty comment to avoid generation of default comment. - comment = ""; - } - - this->CommitUtilityCommand(target, force, workingDirectory, byproducts, - depends, commandLines, escapeOldStyle, comment, - uses_terminal, command_expand_lists, job_pool); + this->CreateGeneratedByproducts(byproducts); + + // Strings could be moved into the callback function with C++14. + cm::optional<std::string> commentStr = MakeOptionalString(comment); + cm::optional<std::string> workingStr = MakeOptionalString(workingDir); + + // Dispatch command creation to allow generator expressions in outputs. + this->AddGeneratorAction( + [=](cmLocalGenerator& lg, const cmListFileBacktrace& lfbt) { + BacktraceGuard guard(this->Backtrace, lfbt); + detail::AddUtilityCommand(lg, lfbt, cmCommandOrigin::Project, target, + force, GetCStrOrNull(workingStr), byproducts, + depends, commandLines, escapeOldStyle, + GetCStrOrNull(commentStr), uses_terminal, + command_expand_lists, job_pool); + }); return target; } -void cmMakefile::CommitUtilityCommand( - cmTarget* target, const cmUtilityOutput& force, const char* workingDirectory, - const std::vector<std::string>& byproducts, - const std::vector<std::string>& depends, - const cmCustomCommandLines& commandLines, bool escapeOldStyle, - const char* comment, bool uses_terminal, bool command_expand_lists, - const std::string& job_pool) -{ - std::vector<std::string> forced; - forced.push_back(force.Name); - std::string no_main_dependency; - cmImplicitDependsList no_implicit_depends; - bool no_replace = false; - cmSourceFile* sf = this->AddCustomCommandToOutput( - forced, byproducts, depends, no_main_dependency, no_implicit_depends, - commandLines, comment, workingDirectory, no_replace, escapeOldStyle, - uses_terminal, command_expand_lists, /*depfile=*/"", job_pool); - if (!force.NameCMP0049.empty()) { - target->AddSource(force.NameCMP0049); - } - if (sf) { - this->AddTargetByproducts(target, byproducts); - } -} - static void s_AddDefineFlag(std::string const& flag, std::string& dflags) { // remove any \n\r @@ -1357,13 +1272,12 @@ void cmMakefile::AddLinkOption(std::string const& option) void cmMakefile::AddLinkDirectory(std::string const& directory, bool before) { - cmListFileBacktrace lfbt = this->GetBacktrace(); if (before) { - this->StateSnapshot.GetDirectory().PrependLinkDirectoriesEntry(directory, - lfbt); + this->StateSnapshot.GetDirectory().PrependLinkDirectoriesEntry( + directory, this->Backtrace); } else { - this->StateSnapshot.GetDirectory().AppendLinkDirectoriesEntry(directory, - lfbt); + this->StateSnapshot.GetDirectory().AppendLinkDirectoriesEntry( + directory, this->Backtrace); } } @@ -1820,20 +1734,19 @@ void cmMakefile::AddIncludeDirectories(const std::vector<std::string>& incs, return; } - cmListFileBacktrace lfbt = this->GetBacktrace(); std::string entryString = cmJoin(incs, ";"); if (before) { this->StateSnapshot.GetDirectory().PrependIncludeDirectoriesEntry( - entryString, lfbt); + entryString, this->Backtrace); } else { this->StateSnapshot.GetDirectory().AppendIncludeDirectoriesEntry( - entryString, lfbt); + entryString, this->Backtrace); } // Property on each target: for (auto& target : this->Targets) { cmTarget& t = target.second; - t.InsertInclude(entryString, lfbt, before); + t.InsertInclude(entryString, this->Backtrace, before); } } @@ -2027,7 +1940,7 @@ void cmMakefile::AddGlobalLinkInformation(cmTarget& target) target.AddLinkLibrary(*this, libraryName, libType); target.AppendProperty( "INTERFACE_LINK_LIBRARIES", - target.GetDebugGeneratorExpressions(libraryName, libType).c_str()); + target.GetDebugGeneratorExpressions(libraryName, libType)); } } } @@ -2080,7 +1993,8 @@ cmTarget* cmMakefile::AddNewTarget(cmStateEnums::TargetType type, { auto it = this->Targets - .emplace(name, cmTarget(name, type, cmTarget::VisibilityNormal, this)) + .emplace(name, + cmTarget(name, type, cmTarget::VisibilityNormal, this, true)) .first; this->OrderedTargets.push_back(&it->second); this->GetGlobalGenerator()->IndexTarget(&it->second); @@ -2089,11 +2003,9 @@ cmTarget* cmMakefile::AddNewTarget(cmStateEnums::TargetType type, } cmTarget* cmMakefile::AddNewUtilityTarget(const std::string& utilityName, - cmCommandOrigin origin, bool excludeFromAll) { cmTarget* target = this->AddNewTarget(cmStateEnums::UTILITY, utilityName); - target->SetIsGeneratorProvided(origin == cmCommandOrigin::Generator); if (excludeFromAll) { target->SetProperty("EXCLUDE_FROM_ALL", "TRUE"); } @@ -2211,8 +2123,8 @@ cmSourceFile* cmMakefile::GetSourceFileWithOutput( (!o->second.Sources.SourceIsByproduct || kind == cmSourceOutputKind::OutputOrByproduct)) { // Source file could also be null pointer for example if we found the - // byproduct of a utility target or a PRE_BUILD, PRE_LINK, or POST_BUILD - // command of a target. + // byproduct of a utility target, a PRE_BUILD, PRE_LINK, or POST_BUILD + // command of a target, or a not yet created custom command. return o->second.Sources.Source; } return nullptr; @@ -2220,12 +2132,20 @@ cmSourceFile* cmMakefile::GetSourceFileWithOutput( bool cmMakefile::MightHaveCustomCommand(const std::string& name) const { - // This will have to be changed for delaying custom command creation, because - // GetSourceFileWithOutput requires the command to be already created. - if (cmSourceFile* sf = this->GetSourceFileWithOutput(name)) { - if (sf->GetCustomCommand()) { - return true; - } + if (this->DelayedOutputFilesHaveGenex || + cmGeneratorExpression::Find(name) != std::string::npos) { + // Could be more restrictive, but for now we assume that there could always + // be a match when generator expressions are involved. + return true; + } + // Also see LinearGetSourceFileWithOutput. + if (!cmSystemTools::FileIsFullPath(name)) { + return AnyOutputMatches(name, this->DelayedOutputFiles); + } + // Otherwise we use an efficient lookup map. + auto o = this->OutputToSource.find(name); + if (o != this->OutputToSource.end()) { + return o->second.SourceMightBeOutput; } return false; } @@ -2278,6 +2198,7 @@ void cmMakefile::UpdateOutputToSourceMap(std::string const& output, SourceEntry entry; entry.Sources.Source = source; entry.Sources.SourceIsByproduct = byproduct; + entry.SourceMightBeOutput = !byproduct; auto pr = this->OutputToSource.emplace(output, entry); if (!pr.second) { @@ -2287,6 +2208,7 @@ void cmMakefile::UpdateOutputToSourceMap(std::string const& output, (current.Sources.SourceIsByproduct && !byproduct)) { current.Sources.Source = source; current.Sources.SourceIsByproduct = false; + current.SourceMightBeOutput = true; } else { // Multiple custom commands produce the same output but may // be attached to a different source file (MAIN_DEPENDENCY). @@ -2478,7 +2400,7 @@ void cmMakefile::ExpandVariablesCMP0019() << " " << dirs << "\n"; /* clang-format on */ } - t.SetProperty("INCLUDE_DIRECTORIES", dirs.c_str()); + t.SetProperty("INCLUDE_DIRECTORIES", dirs); } } @@ -2739,7 +2661,7 @@ const std::string& cmMakefile::GetSafeDefinition(const std::string& name) const std::vector<std::string> cmMakefile::GetDefinitions() const { std::vector<std::string> res = this->StateSnapshot.ClosureKeys(); - cmAppend(res, this->GetState()->GetCacheEntryKeys()); + cm::append(res, this->GetState()->GetCacheEntryKeys()); std::sort(res.begin(), res.end()); return res; } @@ -3553,11 +3475,41 @@ cmSourceFile* cmMakefile::GetOrCreateGeneratedSource( return sf; } -void cmMakefile::CreateGeneratedSources( +void cmMakefile::CreateGeneratedOutputs( const std::vector<std::string>& outputs) { - for (std::string const& output : outputs) { - this->GetOrCreateGeneratedSource(output); + for (std::string const& o : outputs) { + if (cmGeneratorExpression::Find(o) == std::string::npos) { + this->GetOrCreateGeneratedSource(o); + this->AddDelayedOutput(o); + } else { + this->DelayedOutputFilesHaveGenex = true; + } + } +} + +void cmMakefile::CreateGeneratedByproducts( + const std::vector<std::string>& byproducts) +{ + for (std::string const& o : byproducts) { + if (cmGeneratorExpression::Find(o) == std::string::npos) { + this->GetOrCreateGeneratedSource(o); + } + } +} + +void cmMakefile::AddDelayedOutput(std::string const& output) +{ + // Note that this vector might contain the output names in a different order + // than in source file iteration order. + this->DelayedOutputFiles.push_back(output); + + SourceEntry entry; + entry.SourceMightBeOutput = true; + + auto pr = this->OutputToSource.emplace(output, entry); + if (!pr.second) { + pr.first->second.SourceMightBeOutput = true; } } @@ -4029,16 +3981,14 @@ int cmMakefile::ConfigureFile(const std::string& infile, void cmMakefile::SetProperty(const std::string& prop, const char* value) { - cmListFileBacktrace lfbt = this->GetBacktrace(); - this->StateSnapshot.GetDirectory().SetProperty(prop, value, lfbt); + this->StateSnapshot.GetDirectory().SetProperty(prop, value, this->Backtrace); } void cmMakefile::AppendProperty(const std::string& prop, const char* value, bool asString) { - cmListFileBacktrace lfbt = this->GetBacktrace(); this->StateSnapshot.GetDirectory().AppendProperty(prop, value, asString, - lfbt); + this->Backtrace); } const char* cmMakefile::GetProperty(const std::string& prop) const @@ -4214,7 +4164,7 @@ cmTarget* cmMakefile::AddImportedTarget(const std::string& name, new cmTarget(name, type, global ? cmTarget::VisibilityImportedGlobally : cmTarget::VisibilityImported, - this)); + this, true)); // Add to the set of available imported targets. this->ImportedTargets[name] = target.get(); @@ -4487,7 +4437,7 @@ bool cmMakefile::SetPolicy(cmPolicies::PolicyID id, // Deprecate old policies, especially those that require a lot // of code to maintain the old behavior. - if (status == cmPolicies::OLD && id <= cmPolicies::CMP0067 && + if (status == cmPolicies::OLD && id <= cmPolicies::CMP0069 && !(this->GetCMakeInstance()->GetIsInTryCompile() && ( // Policies set by cmCoreTryCompile::TryCompileCode. @@ -4587,17 +4537,21 @@ static const char* const C_FEATURES[] = { nullptr FOR_EACH_C_FEATURE( static const char* const CXX_FEATURES[] = { nullptr FOR_EACH_CXX_FEATURE( FEATURE_STRING) }; + +static const char* const CUDA_FEATURES[] = { nullptr FOR_EACH_CUDA_FEATURE( + FEATURE_STRING) }; #undef FEATURE_STRING static const char* const C_STANDARDS[] = { "90", "99", "11" }; static const char* const CXX_STANDARDS[] = { "98", "11", "14", "17", "20" }; +static const char* const CUDA_STANDARDS[] = { "03", "11", "14", "17", "20" }; bool cmMakefile::AddRequiredTargetFeature(cmTarget* target, const std::string& feature, std::string* error) const { if (cmGeneratorExpression::Find(feature) != std::string::npos) { - target->AppendProperty("COMPILE_FEATURES", feature.c_str()); + target->AppendProperty("COMPILE_FEATURES", feature); return true; } @@ -4628,11 +4582,15 @@ bool cmMakefile::AddRequiredTargetFeature(cmTarget* target, return false; } - target->AppendProperty("COMPILE_FEATURES", feature.c_str()); + target->AppendProperty("COMPILE_FEATURES", feature); - return lang == "C" || lang == "OBJC" - ? this->AddRequiredTargetCFeature(target, feature, lang, error) - : this->AddRequiredTargetCxxFeature(target, feature, lang, error); + if (lang == "C" || lang == "OBJC") { + return this->AddRequiredTargetCFeature(target, feature, lang, error); + } + if (lang == "CUDA") { + return this->AddRequiredTargetCudaFeature(target, feature, lang, error); + } + return this->AddRequiredTargetCxxFeature(target, feature, lang, error); } bool cmMakefile::CompileFeatureKnown(cmTarget const* target, @@ -4656,6 +4614,13 @@ bool cmMakefile::CompileFeatureKnown(cmTarget const* target, lang = "CXX"; return true; } + bool isCudaFeature = + std::find_if(cm::cbegin(CUDA_FEATURES) + 1, cm::cend(CUDA_FEATURES), + cmStrCmp(feature)) != cm::cend(CUDA_FEATURES); + if (isCudaFeature) { + lang = "CUDA"; + return true; + } std::ostringstream e; if (error) { e << "specified"; @@ -4724,9 +4689,13 @@ bool cmMakefile::HaveStandardAvailable(cmTarget const* target, std::string const& lang, const std::string& feature) const { - return lang == "C" || lang == "OBJC" - ? this->HaveCStandardAvailable(target, feature, lang) - : this->HaveCxxStandardAvailable(target, feature, lang); + if (lang == "C" || lang == "OBJC") { + return this->HaveCStandardAvailable(target, feature, lang); + } + if (lang == "CUDA") { + return this->HaveCudaStandardAvailable(target, feature, lang); + } + return this->HaveCxxStandardAvailable(target, feature, lang); } bool cmMakefile::HaveCStandardAvailable(cmTarget const* target, @@ -4809,6 +4778,14 @@ bool cmMakefile::IsLaterStandard(std::string const& lang, return std::find_if(rhsIt, cm::cend(C_STANDARDS), cmStrCmp(lhs)) != cm::cend(C_STANDARDS); } + if (lang == "CUDA") { + const char* const* rhsIt = std::find_if( + cm::cbegin(CUDA_STANDARDS), cm::cend(CUDA_STANDARDS), cmStrCmp(rhs)); + + return std::find_if(rhsIt, cm::cend(CUDA_STANDARDS), cmStrCmp(lhs)) != + cm::cend(CUDA_STANDARDS); + } + const char* const* rhsIt = std::find_if( cm::cbegin(CXX_STANDARDS), cm::cend(CXX_STANDARDS), cmStrCmp(rhs)); @@ -4953,27 +4930,6 @@ bool cmMakefile::AddRequiredTargetCxxFeature(cmTarget* target, } } - const char* existingCudaStandard = target->GetProperty("CUDA_STANDARD"); - const char* const* existingCudaLevel = nullptr; - if (existingCudaStandard) { - existingCudaLevel = - std::find_if(cm::cbegin(CXX_STANDARDS), cm::cend(CXX_STANDARDS), - cmStrCmp(existingCudaStandard)); - if (existingCudaLevel == cm::cend(CXX_STANDARDS)) { - std::ostringstream e; - e << "The CUDA_STANDARD property on target \"" << target->GetName() - << "\" contained an invalid value: \"" << existingCudaStandard - << "\"."; - if (error) { - *error = e.str(); - } else { - this->GetCMakeInstance()->IssueMessage(MessageType::FATAL_ERROR, - e.str(), this->Backtrace); - } - return false; - } - } - /* clang-format off */ const char* const* needCxxLevel = needCxx20 ? &CXX_STANDARDS[4] @@ -4990,11 +4946,164 @@ bool cmMakefile::AddRequiredTargetCxxFeature(cmTarget* target, if (!existingCxxLevel || existingCxxLevel < needCxxLevel) { target->SetProperty(cmStrCat(lang, "_STANDARD"), *needCxxLevel); } + } + + return true; +} + +bool cmMakefile::HaveCudaStandardAvailable(cmTarget const* target, + const std::string& feature, + std::string const& lang) const +{ + const char* defaultCudaStandard = + this->GetDefinition(cmStrCat("CMAKE_", lang, "_STANDARD_DEFAULT")); + if (!defaultCudaStandard) { + this->IssueMessage( + MessageType::INTERNAL_ERROR, + cmStrCat("CMAKE_", lang, + "_STANDARD_DEFAULT is not set. COMPILE_FEATURES support " + "not fully configured for this compiler.")); + // Return true so the caller does not try to lookup the default standard. + return true; + } + if (std::find_if(cm::cbegin(CUDA_STANDARDS), cm::cend(CUDA_STANDARDS), + cmStrCmp(defaultCudaStandard)) == + cm::cend(CUDA_STANDARDS)) { + const std::string e = + cmStrCat("The CMAKE_", lang, "_STANDARD_DEFAULT variable contains an ", + "invalid value: \"", defaultCudaStandard, "\"."); + this->IssueMessage(MessageType::INTERNAL_ERROR, e); + return false; + } + + bool needCuda03 = false; + bool needCuda11 = false; + bool needCuda14 = false; + bool needCuda17 = false; + bool needCuda20 = false; + this->CheckNeededCudaLanguage(feature, lang, needCuda03, needCuda11, + needCuda14, needCuda17, needCuda20); + + const char* existingCudaStandard = + target->GetProperty(cmStrCat(lang, "_STANDARD")); + if (!existingCudaStandard) { + existingCudaStandard = defaultCudaStandard; + } + + const char* const* existingCudaLevel = + std::find_if(cm::cbegin(CUDA_STANDARDS), cm::cend(CUDA_STANDARDS), + cmStrCmp(existingCudaStandard)); + if (existingCudaLevel == cm::cend(CUDA_STANDARDS)) { + const std::string e = cmStrCat( + "The ", lang, "_STANDARD property on target \"", target->GetName(), + "\" contained an invalid value: \"", existingCudaStandard, "\"."); + this->IssueMessage(MessageType::FATAL_ERROR, e); + return false; + } + + /* clang-format off */ + const char* const* needCudaLevel = + needCuda20 ? &CUDA_STANDARDS[4] + : needCuda17 ? &CUDA_STANDARDS[3] + : needCuda14 ? &CUDA_STANDARDS[2] + : needCuda11 ? &CUDA_STANDARDS[1] + : needCuda03 ? &CUDA_STANDARDS[0] + : nullptr; + /* clang-format on */ + + return !needCudaLevel || needCudaLevel <= existingCudaLevel; +} + +void cmMakefile::CheckNeededCudaLanguage(const std::string& feature, + std::string const& lang, + bool& needCuda03, bool& needCuda11, + bool& needCuda14, bool& needCuda17, + bool& needCuda20) const +{ + if (const char* propCuda03 = + this->GetDefinition(cmStrCat("CMAKE_", lang, "03_COMPILE_FEATURES"))) { + std::vector<std::string> props = cmExpandedList(propCuda03); + needCuda03 = cmContains(props, feature); + } + if (const char* propCuda11 = + this->GetDefinition(cmStrCat("CMAKE_", lang, "11_COMPILE_FEATURES"))) { + std::vector<std::string> props = cmExpandedList(propCuda11); + needCuda11 = cmContains(props, feature); + } + if (const char* propCuda14 = + this->GetDefinition(cmStrCat("CMAKE_", lang, "14_COMPILE_FEATURES"))) { + std::vector<std::string> props = cmExpandedList(propCuda14); + needCuda14 = cmContains(props, feature); + } + if (const char* propCuda17 = + this->GetDefinition(cmStrCat("CMAKE_", lang, "17_COMPILE_FEATURES"))) { + std::vector<std::string> props = cmExpandedList(propCuda17); + needCuda17 = cmContains(props, feature); + } + if (const char* propCuda20 = + this->GetDefinition(cmStrCat("CMAKE_", lang, "20_COMPILE_FEATURES"))) { + std::vector<std::string> props = cmExpandedList(propCuda20); + needCuda20 = cmContains(props, feature); + } +} + +bool cmMakefile::AddRequiredTargetCudaFeature(cmTarget* target, + const std::string& feature, + std::string const& lang, + std::string* error) const +{ + bool needCuda03 = false; + bool needCuda11 = false; + bool needCuda14 = false; + bool needCuda17 = false; + bool needCuda20 = false; + + this->CheckNeededCudaLanguage(feature, lang, needCuda03, needCuda11, + needCuda14, needCuda17, needCuda20); + + const char* existingCudaStandard = + target->GetProperty(cmStrCat(lang, "_STANDARD")); + if (existingCudaStandard == nullptr) { + const char* defaultCudaStandard = + this->GetDefinition(cmStrCat("CMAKE_", lang, "_STANDARD_DEFAULT")); + if (defaultCudaStandard && *defaultCudaStandard) { + existingCudaStandard = defaultCudaStandard; + } + } + const char* const* existingCudaLevel = nullptr; + if (existingCudaStandard) { + existingCudaLevel = + std::find_if(cm::cbegin(CUDA_STANDARDS), cm::cend(CUDA_STANDARDS), + cmStrCmp(existingCudaStandard)); + if (existingCudaLevel == cm::cend(CUDA_STANDARDS)) { + const std::string e = cmStrCat( + "The ", lang, "_STANDARD property on target \"", target->GetName(), + "\" contained an invalid value: \"", existingCudaStandard, "\"."); + if (error) { + *error = e; + } else { + this->GetCMakeInstance()->IssueMessage(MessageType::FATAL_ERROR, e, + this->Backtrace); + } + return false; + } + } + /* clang-format off */ + const char* const* needCudaLevel = + needCuda20 ? &CUDA_STANDARDS[4] + : needCuda17 ? &CUDA_STANDARDS[3] + : needCuda14 ? &CUDA_STANDARDS[2] + : needCuda11 ? &CUDA_STANDARDS[1] + : needCuda03 ? &CUDA_STANDARDS[0] + : nullptr; + /* clang-format on */ + + if (needCudaLevel) { // Ensure the CUDA language level is high enough to support - // the needed C++ features. - if (!existingCudaLevel || existingCudaLevel < needCxxLevel) { - target->SetProperty("CUDA_STANDARD", *needCxxLevel); + // the needed CUDA features. + if (!existingCudaLevel || existingCudaLevel < needCudaLevel) { + target->SetProperty("CUDA_STANDARD", *needCudaLevel); } } diff --git a/Source/cmMakefile.h b/Source/cmMakefile.h index 6e59494..672244e 100644 --- a/Source/cmMakefile.h +++ b/Source/cmMakefile.h @@ -49,6 +49,7 @@ class cmGeneratorExpressionEvaluationFile; class cmGlobalGenerator; class cmImplicitDependsList; class cmInstallGenerator; +class cmLocalGenerator; class cmMessenger; class cmSourceFile; class cmState; @@ -151,54 +152,64 @@ public: bool EnforceUniqueName(std::string const& name, std::string& msg, bool isCustom = false) const; - using FinalAction = std::function<void(cmMakefile&)>; + using GeneratorAction = + std::function<void(cmLocalGenerator&, const cmListFileBacktrace&)>; /** - * Register an action that is executed during FinalPass + * Register an action that is executed during Generate */ - void AddFinalAction(FinalAction action); + void AddGeneratorAction(GeneratorAction action); /** - * Perform FinalPass, Library dependency analysis etc before output of the - * makefile. + * Perform generate actions, Library dependency analysis etc before output of + * the makefile. */ - void ConfigureFinalPass(); + void Generate(cmLocalGenerator& lg); /** - * run all FinalActions. + * Get the target for PRE_BUILD, PRE_LINK, or POST_BUILD commands. */ - void FinalPass(); + cmTarget* GetCustomCommandTarget(const std::string& target, + cmObjectLibraryCommands objLibCommands, + const cmListFileBacktrace& lfbt) const; /** - * Get the target for PRE_BUILD, PRE_LINK, or POST_BUILD commands. + * Dispatch adding a custom PRE_BUILD, PRE_LINK, or POST_BUILD command to a + * target. */ - cmTarget* GetCustomCommandTarget( - const std::string& target, cmObjectLibraryCommands objLibCommands) const; - - /** Add a custom command to the build. */ cmTarget* AddCustomCommandToTarget( const std::string& target, const std::vector<std::string>& byproducts, const std::vector<std::string>& depends, const cmCustomCommandLines& commandLines, cmCustomCommandType type, const char* comment, const char* workingDir, bool escapeOldStyle = true, bool uses_terminal = false, const std::string& depfile = "", - const std::string& job_pool = "", bool command_expand_lists = false, - cmObjectLibraryCommands objLibCommands = cmObjectLibraryCommands::Reject); - cmSourceFile* AddCustomCommandToOutput( + const std::string& job_pool = "", bool command_expand_lists = false); + + /** + * Called for each file with custom command. + */ + using CommandSourceCallback = std::function<void(cmSourceFile*)>; + + /** + * Dispatch adding a custom command to a source file. + */ + void AddCustomCommandToOutput( const std::string& output, const std::vector<std::string>& depends, const std::string& main_dependency, const cmCustomCommandLines& commandLines, const char* comment, - const char* workingDir, bool replace = false, bool escapeOldStyle = true, + const char* workingDir, const CommandSourceCallback& callback = nullptr, + bool replace = false, bool escapeOldStyle = true, bool uses_terminal = false, bool command_expand_lists = false, const std::string& depfile = "", const std::string& job_pool = ""); - cmSourceFile* AddCustomCommandToOutput( + void AddCustomCommandToOutput( const std::vector<std::string>& outputs, const std::vector<std::string>& byproducts, const std::vector<std::string>& depends, const std::string& main_dependency, const cmImplicitDependsList& implicit_depends, const cmCustomCommandLines& commandLines, const char* comment, - const char* workingDir, bool replace = false, bool escapeOldStyle = true, + const char* workingDir, const CommandSourceCallback& callback = nullptr, + bool replace = false, bool escapeOldStyle = true, bool uses_terminal = false, bool command_expand_lists = false, const std::string& depfile = "", const std::string& job_pool = ""); void AddCustomCommandOldStyle(const std::string& target, @@ -244,7 +255,7 @@ public: /** Create a target instance for the utility. */ cmTarget* AddNewUtilityTarget(const std::string& utilityName, - cmCommandOrigin origin, bool excludeFromAll); + bool excludeFromAll); /** * Add an executable to the build. @@ -259,13 +270,12 @@ public: cmUtilityOutput GetUtilityOutput(cmTarget* target); /** - * Add a utility to the build. A utility target is a command that - * is run every time the target is built. + * Dispatch adding a utility to the build. A utility target is a command + * that is run every time the target is built. */ cmTarget* AddUtilityCommand( - const std::string& utilityName, cmCommandOrigin origin, - bool excludeFromAll, const char* workingDirectory, - const std::vector<std::string>& byproducts, + const std::string& utilityName, bool excludeFromAll, + const char* workingDir, const std::vector<std::string>& byproducts, const std::vector<std::string>& depends, const cmCustomCommandLines& commandLines, bool escapeOldStyle = true, const char* comment = nullptr, bool uses_terminal = false, @@ -1001,7 +1011,6 @@ protected: size_t ObjectLibrariesSourceGroupIndex; #endif - std::vector<FinalAction> FinalActions; cmGlobalGenerator* GlobalGenerator; bool IsFunctionBlocked(const cmListFileFunction& lff, cmExecutionStatus& status); @@ -1011,6 +1020,8 @@ private: cmListFileBacktrace Backtrace; int RecursionDepth; + void DoGenerate(cmLocalGenerator& lg); + void ReadListFile(cmListFile const& listFile, const std::string& filenametoread); @@ -1080,38 +1091,15 @@ private: bool ValidateCustomCommand(const cmCustomCommandLines& commandLines) const; - void CreateGeneratedSources(const std::vector<std::string>& outputs); + void CreateGeneratedOutputs(const std::vector<std::string>& outputs); + void CreateGeneratedByproducts(const std::vector<std::string>& byproducts); - void CommitCustomCommandToTarget( - cmTarget* target, const std::vector<std::string>& byproducts, - const std::vector<std::string>& depends, - const cmCustomCommandLines& commandLines, cmCustomCommandType type, - const char* comment, const char* workingDir, bool escapeOldStyle, - bool uses_terminal, const std::string& depfile, - const std::string& job_pool, bool command_expand_lists); - cmSourceFile* CommitCustomCommandToOutput( - const std::vector<std::string>& outputs, - const std::vector<std::string>& byproducts, - const std::vector<std::string>& depends, - const std::string& main_dependency, - const cmImplicitDependsList& implicit_depends, - const cmCustomCommandLines& commandLines, const char* comment, - const char* workingDir, bool replace, bool escapeOldStyle, - bool uses_terminal, bool command_expand_lists, const std::string& depfile, - const std::string& job_pool); - void CommitAppendCustomCommandToOutput( - const std::string& output, const std::vector<std::string>& depends, - const cmImplicitDependsList& implicit_depends, - const cmCustomCommandLines& commandLines); + std::vector<BT<GeneratorAction>> GeneratorActions; + bool GeneratorActionsInvoked = false; + bool DelayedOutputFilesHaveGenex = false; + std::vector<std::string> DelayedOutputFiles; - void CommitUtilityCommand(cmTarget* target, const cmUtilityOutput& force, - const char* workingDirectory, - const std::vector<std::string>& byproducts, - const std::vector<std::string>& depends, - const cmCustomCommandLines& commandLines, - bool escapeOldStyle, const char* comment, - bool uses_terminal, bool command_expand_lists, - const std::string& job_pool); + void AddDelayedOutput(std::string const& output); /** * See LinearGetSourceFileWithOutput for background information @@ -1131,6 +1119,7 @@ private: struct SourceEntry { cmSourcesWithOutput Sources; + bool SourceMightBeOutput = false; }; // A map for fast output to input look up. @@ -1149,11 +1138,14 @@ private: bool AddRequiredTargetCFeature(cmTarget* target, const std::string& feature, std::string const& lang, std::string* error = nullptr) const; - bool AddRequiredTargetCxxFeature(cmTarget* target, const std::string& feature, std::string const& lang, std::string* error = nullptr) const; + bool AddRequiredTargetCudaFeature(cmTarget* target, + const std::string& feature, + std::string const& lang, + std::string* error = nullptr) const; void CheckNeededCLanguage(const std::string& feature, std::string const& lang, bool& needC90, @@ -1162,6 +1154,10 @@ private: std::string const& lang, bool& needCxx98, bool& needCxx11, bool& needCxx14, bool& needCxx17, bool& needCxx20) const; + void CheckNeededCudaLanguage(const std::string& feature, + std::string const& lang, bool& needCuda03, + bool& needCuda11, bool& needCuda14, + bool& needCuda17, bool& needCuda20) const; bool HaveCStandardAvailable(cmTarget const* target, const std::string& feature, @@ -1169,6 +1165,9 @@ private: bool HaveCxxStandardAvailable(cmTarget const* target, const std::string& feature, std::string const& lang) const; + bool HaveCudaStandardAvailable(cmTarget const* target, + const std::string& feature, + std::string const& lang) const; void CheckForUnusedVariables() const; diff --git a/Source/cmMakefileExecutableTargetGenerator.cxx b/Source/cmMakefileExecutableTargetGenerator.cxx index 40265ff..5c9608c 100644 --- a/Source/cmMakefileExecutableTargetGenerator.cxx +++ b/Source/cmMakefileExecutableTargetGenerator.cxx @@ -9,8 +9,8 @@ #include <vector> #include <cm/memory> +#include <cmext/algorithm> -#include "cmAlgorithms.h" #include "cmGeneratedFileStream.h" #include "cmGeneratorTarget.h" #include "cmGlobalUnixMakefileGenerator3.h" @@ -35,10 +35,9 @@ cmMakefileExecutableTargetGenerator::cmMakefileExecutableTargetGenerator( { this->CustomCommandDriver = OnDepends; this->TargetNames = - this->GeneratorTarget->GetExecutableNames(this->ConfigName); + this->GeneratorTarget->GetExecutableNames(this->GetConfigName()); - this->OSXBundleGenerator = - cm::make_unique<cmOSXBundleGenerator>(target, this->ConfigName); + this->OSXBundleGenerator = cm::make_unique<cmOSXBundleGenerator>(target); this->OSXBundleGenerator->SetMacContentFolders(&this->MacContentFolders); } @@ -64,7 +63,7 @@ void cmMakefileExecutableTargetGenerator::WriteRuleFiles() // write the link rules this->WriteExecutableRule(false); - if (this->GeneratorTarget->NeedRelinkBeforeInstall(this->ConfigName)) { + if (this->GeneratorTarget->NeedRelinkBeforeInstall(this->GetConfigName())) { // Write rules to link an installable version of the target. this->WriteExecutableRule(true); } @@ -85,7 +84,7 @@ void cmMakefileExecutableTargetGenerator::WriteDeviceExecutableRule( { #ifndef CMAKE_BOOTSTRAP const bool requiresDeviceLinking = requireDeviceLinking( - *this->GeneratorTarget, *this->LocalGenerator, this->ConfigName); + *this->GeneratorTarget, *this->LocalGenerator, this->GetConfigName()); if (!requiresDeviceLinking) { return; } @@ -141,10 +140,10 @@ void cmMakefileExecutableTargetGenerator::WriteDeviceExecutableRule( // Add language feature flags. this->LocalGenerator->AddLanguageFlagsForLinking( - flags, this->GeneratorTarget, linkLanguage, this->ConfigName); + flags, this->GeneratorTarget, linkLanguage, this->GetConfigName()); - this->LocalGenerator->AddArchitectureFlags(flags, this->GeneratorTarget, - linkLanguage, this->ConfigName); + this->LocalGenerator->AddArchitectureFlags( + flags, this->GeneratorTarget, linkLanguage, this->GetConfigName()); // Add target-specific linker flags. this->GetTargetLinkFlags(linkFlags, linkLanguage); @@ -213,7 +212,8 @@ void cmMakefileExecutableTargetGenerator::WriteDeviceExecutableRule( this->LocalGenerator->GetCurrentBinaryDirectory(), targetOutputReal), output); - std::string targetFullPathCompilePDB = this->ComputeTargetCompilePDB(); + std::string targetFullPathCompilePDB = + this->ComputeTargetCompilePDB(this->GetConfigName()); std::string targetOutPathCompilePDB = this->LocalGenerator->ConvertToOutputFormat(targetFullPathCompilePDB, cmOutputConverter::SHELL); @@ -263,7 +263,7 @@ void cmMakefileExecutableTargetGenerator::WriteDeviceExecutableRule( this->LocalGenerator->CreateCDCommand( commands1, this->Makefile->GetCurrentBinaryDirectory(), this->LocalGenerator->GetBinaryDirectory()); - cmAppend(commands, commands1); + cm::append(commands, commands1); commands1.clear(); // Write the build rule. @@ -287,12 +287,14 @@ void cmMakefileExecutableTargetGenerator::WriteExecutableRule(bool relink) // Get the name of the executable to generate. cmGeneratorTarget::Names targetNames = - this->GeneratorTarget->GetExecutableNames(this->ConfigName); + this->GeneratorTarget->GetExecutableNames(this->GetConfigName()); // Construct the full path version of the names. - std::string outpath = this->GeneratorTarget->GetDirectory(this->ConfigName); + std::string outpath = + this->GeneratorTarget->GetDirectory(this->GetConfigName()); if (this->GeneratorTarget->IsAppBundleOnApple()) { - this->OSXBundleGenerator->CreateAppBundle(targetNames.Output, outpath); + this->OSXBundleGenerator->CreateAppBundle(targetNames.Output, outpath, + this->GetConfigName()); } outpath += '/'; std::string outpathImp; @@ -308,18 +310,18 @@ void cmMakefileExecutableTargetGenerator::WriteExecutableRule(bool relink) cmSystemTools::MakeDirectory(outpath); if (!targetNames.ImportLibrary.empty()) { outpathImp = this->GeneratorTarget->GetDirectory( - this->ConfigName, cmStateEnums::ImportLibraryArtifact); + this->GetConfigName(), cmStateEnums::ImportLibraryArtifact); cmSystemTools::MakeDirectory(outpathImp); outpathImp += '/'; } } std::string compilePdbOutputPath = - this->GeneratorTarget->GetCompilePDBDirectory(this->ConfigName); + this->GeneratorTarget->GetCompilePDBDirectory(this->GetConfigName()); cmSystemTools::MakeDirectory(compilePdbOutputPath); std::string pdbOutputPath = - this->GeneratorTarget->GetPDBDirectory(this->ConfigName); + this->GeneratorTarget->GetPDBDirectory(this->GetConfigName()); cmSystemTools::MakeDirectory(pdbOutputPath); pdbOutputPath += '/'; @@ -347,7 +349,7 @@ void cmMakefileExecutableTargetGenerator::WriteExecutableRule(bool relink) // Get the language to use for linking this executable. std::string linkLanguage = - this->GeneratorTarget->GetLinkerLanguage(this->ConfigName); + this->GeneratorTarget->GetLinkerLanguage(this->GetConfigName()); // Make sure we have a link language. if (linkLanguage.empty()) { @@ -380,7 +382,7 @@ void cmMakefileExecutableTargetGenerator::WriteExecutableRule(bool relink) // Add flags to create an executable. this->LocalGenerator->AddConfigVariableFlags( - linkFlags, "CMAKE_EXE_LINKER_FLAGS", this->ConfigName); + linkFlags, "CMAKE_EXE_LINKER_FLAGS", this->GetConfigName()); if (this->GeneratorTarget->GetPropertyAsBool("WIN32_EXECUTABLE")) { this->LocalGenerator->AppendFlags( @@ -409,10 +411,10 @@ void cmMakefileExecutableTargetGenerator::WriteExecutableRule(bool relink) // Add language feature flags. this->LocalGenerator->AddLanguageFlagsForLinking( - flags, this->GeneratorTarget, linkLanguage, this->ConfigName); + flags, this->GeneratorTarget, linkLanguage, this->GetConfigName()); - this->LocalGenerator->AddArchitectureFlags(flags, this->GeneratorTarget, - linkLanguage, this->ConfigName); + this->LocalGenerator->AddArchitectureFlags( + flags, this->GeneratorTarget, linkLanguage, this->GetConfigName()); // Add target-specific linker flags. this->GetTargetLinkFlags(linkFlags, linkLanguage); @@ -423,11 +425,12 @@ void cmMakefileExecutableTargetGenerator::WriteExecutableRule(bool relink) this->LocalGenerator, this->LocalGenerator->GetStateSnapshot().GetDirectory())); - this->AddModuleDefinitionFlag(linkLineComputer.get(), linkFlags); + this->AddModuleDefinitionFlag(linkLineComputer.get(), linkFlags, + this->GetConfigName()); } - this->LocalGenerator->AppendIPOLinkerFlags(linkFlags, this->GeneratorTarget, - this->ConfigName, linkLanguage); + this->LocalGenerator->AppendIPOLinkerFlags( + linkFlags, this->GeneratorTarget, this->GetConfigName(), linkLanguage); // Construct a list of files associated with this executable that // may need to be cleaned. @@ -451,7 +454,7 @@ void cmMakefileExecutableTargetGenerator::WriteExecutableRule(bool relink) targetFullPathImport)); std::string implib; if (this->GeneratorTarget->GetImplibGNUtoMS( - this->ConfigName, targetFullPathImport, implib)) { + this->GetConfigName(), targetFullPathImport, implib)) { exeCleanFiles.push_back(this->LocalGenerator->MaybeConvertToRelativePath( this->LocalGenerator->GetCurrentBinaryDirectory(), implib)); } @@ -479,7 +482,7 @@ void cmMakefileExecutableTargetGenerator::WriteExecutableRule(bool relink) // Construct the main link rule. std::vector<std::string> real_link_commands; std::string linkRuleVar = this->GeneratorTarget->GetCreateRuleVariable( - linkLanguage, this->ConfigName); + linkLanguage, this->GetConfigName()); std::string linkRule = this->GetLinkRule(linkRuleVar); std::vector<std::string> commands1; cmExpandList(linkRule, real_link_commands); @@ -536,7 +539,7 @@ void cmMakefileExecutableTargetGenerator::WriteExecutableRule(bool relink) // maybe create .def file from list of objects this->GenDefFile(real_link_commands); - std::string manifests = this->GetManifests(); + std::string manifests = this->GetManifests(this->GetConfigName()); cmRulePlaceholderExpander::RuleVariables vars; vars.CMTargetName = this->GeneratorTarget->GetName().c_str(); @@ -627,7 +630,7 @@ void cmMakefileExecutableTargetGenerator::WriteExecutableRule(bool relink) this->LocalGenerator->CreateCDCommand( commands1, this->Makefile->GetCurrentBinaryDirectory(), this->LocalGenerator->GetBinaryDirectory()); - cmAppend(commands, commands1); + cm::append(commands, commands1); commands1.clear(); // Add a rule to create necessary symlinks for the library. @@ -639,7 +642,7 @@ void cmMakefileExecutableTargetGenerator::WriteExecutableRule(bool relink) this->LocalGenerator->CreateCDCommand( commands1, this->Makefile->GetCurrentBinaryDirectory(), this->LocalGenerator->GetBinaryDirectory()); - cmAppend(commands, commands1); + cm::append(commands, commands1); commands1.clear(); } diff --git a/Source/cmMakefileLibraryTargetGenerator.cxx b/Source/cmMakefileLibraryTargetGenerator.cxx index 54a6606..e728b67 100644 --- a/Source/cmMakefileLibraryTargetGenerator.cxx +++ b/Source/cmMakefileLibraryTargetGenerator.cxx @@ -9,8 +9,8 @@ #include <vector> #include <cm/memory> +#include <cmext/algorithm> -#include "cmAlgorithms.h" #include "cmGeneratedFileStream.h" #include "cmGeneratorTarget.h" #include "cmGlobalUnixMakefileGenerator3.h" @@ -36,11 +36,10 @@ cmMakefileLibraryTargetGenerator::cmMakefileLibraryTargetGenerator( this->CustomCommandDriver = OnDepends; if (this->GeneratorTarget->GetType() != cmStateEnums::INTERFACE_LIBRARY) { this->TargetNames = - this->GeneratorTarget->GetLibraryNames(this->ConfigName); + this->GeneratorTarget->GetLibraryNames(this->GetConfigName()); } - this->OSXBundleGenerator = - cm::make_unique<cmOSXBundleGenerator>(target, this->ConfigName); + this->OSXBundleGenerator = cm::make_unique<cmOSXBundleGenerator>(target); this->OSXBundleGenerator->SetMacContentFolders(&this->MacContentFolders); } @@ -69,14 +68,16 @@ void cmMakefileLibraryTargetGenerator::WriteRuleFiles() break; case cmStateEnums::SHARED_LIBRARY: this->WriteSharedLibraryRules(false); - if (this->GeneratorTarget->NeedRelinkBeforeInstall(this->ConfigName)) { + if (this->GeneratorTarget->NeedRelinkBeforeInstall( + this->GetConfigName())) { // Write rules to link an installable version of the target. this->WriteSharedLibraryRules(true); } break; case cmStateEnums::MODULE_LIBRARY: this->WriteModuleLibraryRules(false); - if (this->GeneratorTarget->NeedRelinkBeforeInstall(this->ConfigName)) { + if (this->GeneratorTarget->NeedRelinkBeforeInstall( + this->GetConfigName())) { // Write rules to link an installable version of the target. this->WriteModuleLibraryRules(true); } @@ -126,21 +127,21 @@ void cmMakefileLibraryTargetGenerator::WriteObjectLibraryRules() void cmMakefileLibraryTargetGenerator::WriteStaticLibraryRules() { const bool requiresDeviceLinking = requireDeviceLinking( - *this->GeneratorTarget, *this->LocalGenerator, this->ConfigName); + *this->GeneratorTarget, *this->LocalGenerator, this->GetConfigName()); if (requiresDeviceLinking) { std::string linkRuleVar = "CMAKE_CUDA_DEVICE_LINK_LIBRARY"; this->WriteDeviceLibraryRules(linkRuleVar, false); } std::string linkLanguage = - this->GeneratorTarget->GetLinkerLanguage(this->ConfigName); + this->GeneratorTarget->GetLinkerLanguage(this->GetConfigName()); std::string linkRuleVar = this->GeneratorTarget->GetCreateRuleVariable( - linkLanguage, this->ConfigName); + linkLanguage, this->GetConfigName()); std::string extraFlags; this->LocalGenerator->GetStaticLibraryFlags( - extraFlags, cmSystemTools::UpperCase(this->ConfigName), linkLanguage, + extraFlags, cmSystemTools::UpperCase(this->GetConfigName()), linkLanguage, this->GeneratorTarget); this->WriteLibraryRules(linkRuleVar, extraFlags, false); } @@ -154,7 +155,7 @@ void cmMakefileLibraryTargetGenerator::WriteSharedLibraryRules(bool relink) if (!relink) { const bool requiresDeviceLinking = requireDeviceLinking( - *this->GeneratorTarget, *this->LocalGenerator, this->ConfigName); + *this->GeneratorTarget, *this->LocalGenerator, this->GetConfigName()); if (requiresDeviceLinking) { std::string linkRuleVar = "CMAKE_CUDA_DEVICE_LINK_LIBRARY"; this->WriteDeviceLibraryRules(linkRuleVar, relink); @@ -162,21 +163,22 @@ void cmMakefileLibraryTargetGenerator::WriteSharedLibraryRules(bool relink) } std::string linkLanguage = - this->GeneratorTarget->GetLinkerLanguage(this->ConfigName); + this->GeneratorTarget->GetLinkerLanguage(this->GetConfigName()); std::string linkRuleVar = cmStrCat("CMAKE_", linkLanguage, "_CREATE_SHARED_LIBRARY"); std::string extraFlags; this->GetTargetLinkFlags(extraFlags, linkLanguage); this->LocalGenerator->AddConfigVariableFlags( - extraFlags, "CMAKE_SHARED_LINKER_FLAGS", this->ConfigName); + extraFlags, "CMAKE_SHARED_LINKER_FLAGS", this->GetConfigName()); std::unique_ptr<cmLinkLineComputer> linkLineComputer( this->CreateLinkLineComputer( this->LocalGenerator, this->LocalGenerator->GetStateSnapshot().GetDirectory())); - this->AddModuleDefinitionFlag(linkLineComputer.get(), extraFlags); + this->AddModuleDefinitionFlag(linkLineComputer.get(), extraFlags, + this->GetConfigName()); if (this->GeneratorTarget->GetPropertyAsBool("LINK_WHAT_YOU_USE")) { this->LocalGenerator->AppendFlags(extraFlags, " -Wl,--no-as-needed"); @@ -188,7 +190,7 @@ void cmMakefileLibraryTargetGenerator::WriteModuleLibraryRules(bool relink) { if (!relink) { const bool requiresDeviceLinking = requireDeviceLinking( - *this->GeneratorTarget, *this->LocalGenerator, this->ConfigName); + *this->GeneratorTarget, *this->LocalGenerator, this->GetConfigName()); if (requiresDeviceLinking) { std::string linkRuleVar = "CMAKE_CUDA_DEVICE_LINK_LIBRARY"; this->WriteDeviceLibraryRules(linkRuleVar, relink); @@ -196,21 +198,22 @@ void cmMakefileLibraryTargetGenerator::WriteModuleLibraryRules(bool relink) } std::string linkLanguage = - this->GeneratorTarget->GetLinkerLanguage(this->ConfigName); + this->GeneratorTarget->GetLinkerLanguage(this->GetConfigName()); std::string linkRuleVar = cmStrCat("CMAKE_", linkLanguage, "_CREATE_SHARED_MODULE"); std::string extraFlags; this->GetTargetLinkFlags(extraFlags, linkLanguage); this->LocalGenerator->AddConfigVariableFlags( - extraFlags, "CMAKE_MODULE_LINKER_FLAGS", this->ConfigName); + extraFlags, "CMAKE_MODULE_LINKER_FLAGS", this->GetConfigName()); std::unique_ptr<cmLinkLineComputer> linkLineComputer( this->CreateLinkLineComputer( this->LocalGenerator, this->LocalGenerator->GetStateSnapshot().GetDirectory())); - this->AddModuleDefinitionFlag(linkLineComputer.get(), extraFlags); + this->AddModuleDefinitionFlag(linkLineComputer.get(), extraFlags, + this->GetConfigName()); this->WriteLibraryRules(linkRuleVar, extraFlags, relink); } @@ -218,14 +221,14 @@ void cmMakefileLibraryTargetGenerator::WriteModuleLibraryRules(bool relink) void cmMakefileLibraryTargetGenerator::WriteFrameworkRules(bool relink) { std::string linkLanguage = - this->GeneratorTarget->GetLinkerLanguage(this->ConfigName); + this->GeneratorTarget->GetLinkerLanguage(this->GetConfigName()); std::string linkRuleVar = cmStrCat("CMAKE_", linkLanguage, "_CREATE_MACOSX_FRAMEWORK"); std::string extraFlags; this->GetTargetLinkFlags(extraFlags, linkLanguage); this->LocalGenerator->AddConfigVariableFlags( - extraFlags, "CMAKE_MACOSX_FRAMEWORK_LINKER_FLAGS", this->ConfigName); + extraFlags, "CMAKE_MACOSX_FRAMEWORK_LINKER_FLAGS", this->GetConfigName()); this->WriteLibraryRules(linkRuleVar, extraFlags, relink); } @@ -331,7 +334,8 @@ void cmMakefileLibraryTargetGenerator::WriteDeviceLibraryRules( this->LocalGenerator->GetCurrentBinaryDirectory(), targetOutputReal), output); - std::string targetFullPathCompilePDB = this->ComputeTargetCompilePDB(); + std::string targetFullPathCompilePDB = + this->ComputeTargetCompilePDB(this->GetConfigName()); std::string targetOutPathCompilePDB = this->LocalGenerator->ConvertToOutputFormat(targetFullPathCompilePDB, cmOutputConverter::SHELL); @@ -347,7 +351,7 @@ void cmMakefileLibraryTargetGenerator::WriteDeviceLibraryRules( // Add language-specific flags. std::string langFlags; this->LocalGenerator->AddLanguageFlagsForLinking( - langFlags, this->GeneratorTarget, linkLanguage, this->ConfigName); + langFlags, this->GeneratorTarget, linkLanguage, this->GetConfigName()); vars.LanguageCompileFlags = langFlags.c_str(); @@ -393,7 +397,7 @@ void cmMakefileLibraryTargetGenerator::WriteDeviceLibraryRules( this->LocalGenerator->CreateCDCommand( commands1, this->Makefile->GetCurrentBinaryDirectory(), this->LocalGenerator->GetBinaryDirectory()); - cmAppend(commands, commands1); + cm::append(commands, commands1); commands1.clear(); // Compute the list of outputs. @@ -420,7 +424,7 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules( // Get the language to use for linking this library. std::string linkLanguage = - this->GeneratorTarget->GetLinkerLanguage(this->ConfigName); + this->GeneratorTarget->GetLinkerLanguage(this->GetConfigName()); // Make sure we have a link language. if (linkLanguage.empty()) { @@ -439,8 +443,8 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules( // Create set of linking flags. std::string linkFlags; this->LocalGenerator->AppendFlags(linkFlags, extraFlags); - this->LocalGenerator->AppendIPOLinkerFlags(linkFlags, this->GeneratorTarget, - this->ConfigName, linkLanguage); + this->LocalGenerator->AppendIPOLinkerFlags( + linkFlags, this->GeneratorTarget, this->GetConfigName(), linkLanguage); // Add OSX version flags, if any. if (this->GeneratorTarget->GetType() == cmStateEnums::SHARED_LIBRARY || @@ -450,20 +454,20 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules( } // Construct the name of the library. - this->GeneratorTarget->GetLibraryNames(this->ConfigName); + this->GeneratorTarget->GetLibraryNames(this->GetConfigName()); // Construct the full path version of the names. std::string outpath; std::string outpathImp; if (this->GeneratorTarget->IsFrameworkOnApple()) { - outpath = this->GeneratorTarget->GetDirectory(this->ConfigName); + outpath = this->GeneratorTarget->GetDirectory(this->GetConfigName()); this->OSXBundleGenerator->CreateFramework(this->TargetNames.Output, - outpath); + outpath, this->GetConfigName()); outpath += '/'; } else if (this->GeneratorTarget->IsCFBundleOnApple()) { - outpath = this->GeneratorTarget->GetDirectory(this->ConfigName); - this->OSXBundleGenerator->CreateCFBundle(this->TargetNames.Output, - outpath); + outpath = this->GeneratorTarget->GetDirectory(this->GetConfigName()); + this->OSXBundleGenerator->CreateCFBundle(this->TargetNames.Output, outpath, + this->GetConfigName()); outpath += '/'; } else if (relink) { outpath = cmStrCat(this->Makefile->GetCurrentBinaryDirectory(), @@ -474,23 +478,23 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules( outpathImp = outpath; } } else { - outpath = this->GeneratorTarget->GetDirectory(this->ConfigName); + outpath = this->GeneratorTarget->GetDirectory(this->GetConfigName()); cmSystemTools::MakeDirectory(outpath); outpath += '/'; if (!this->TargetNames.ImportLibrary.empty()) { outpathImp = this->GeneratorTarget->GetDirectory( - this->ConfigName, cmStateEnums::ImportLibraryArtifact); + this->GetConfigName(), cmStateEnums::ImportLibraryArtifact); cmSystemTools::MakeDirectory(outpathImp); outpathImp += '/'; } } std::string compilePdbOutputPath = - this->GeneratorTarget->GetCompilePDBDirectory(this->ConfigName); + this->GeneratorTarget->GetCompilePDBDirectory(this->GetConfigName()); cmSystemTools::MakeDirectory(compilePdbOutputPath); std::string pdbOutputPath = - this->GeneratorTarget->GetPDBDirectory(this->ConfigName); + this->GeneratorTarget->GetPDBDirectory(this->GetConfigName()); cmSystemTools::MakeDirectory(pdbOutputPath); pdbOutputPath += "/"; @@ -567,7 +571,7 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules( this->LocalGenerator->CreateCDCommand( commands1, this->Makefile->GetCurrentBinaryDirectory(), this->LocalGenerator->GetBinaryDirectory()); - cmAppend(commands, commands1); + cm::append(commands, commands1); commands1.clear(); } @@ -586,7 +590,7 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules( targetFullPathImport)); std::string implib; if (this->GeneratorTarget->GetImplibGNUtoMS( - this->ConfigName, targetFullPathImport, implib)) { + this->GetConfigName(), targetFullPathImport, implib)) { libCleanFiles.insert(this->LocalGenerator->MaybeConvertToRelativePath( this->LocalGenerator->GetCurrentBinaryDirectory(), implib)); } @@ -638,7 +642,7 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules( cmStrCat("CMAKE_", linkLanguage, "_ARCHIVE_CREATE"); arCreateVar = this->GeneratorTarget->GetFeatureSpecificLinkRuleVariable( - arCreateVar, linkLanguage, this->ConfigName); + arCreateVar, linkLanguage, this->GetConfigName()); if (const char* rule = this->Makefile->GetDefinition(arCreateVar)) { cmExpandList(rule, archiveCreateCommands); @@ -647,7 +651,7 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules( cmStrCat("CMAKE_", linkLanguage, "_ARCHIVE_APPEND"); arAppendVar = this->GeneratorTarget->GetFeatureSpecificLinkRuleVariable( - arAppendVar, linkLanguage, this->ConfigName); + arAppendVar, linkLanguage, this->GetConfigName()); if (const char* rule = this->Makefile->GetDefinition(arAppendVar)) { cmExpandList(rule, archiveAppendCommands); @@ -656,7 +660,7 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules( cmStrCat("CMAKE_", linkLanguage, "_ARCHIVE_FINISH"); arFinishVar = this->GeneratorTarget->GetFeatureSpecificLinkRuleVariable( - arFinishVar, linkLanguage, this->ConfigName); + arFinishVar, linkLanguage, this->GetConfigName()); if (const char* rule = this->Makefile->GetDefinition(arFinishVar)) { cmExpandList(rule, archiveFinishCommands); @@ -726,7 +730,7 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules( // maybe create .def file from list of objects this->GenDefFile(real_link_commands); - std::string manifests = this->GetManifests(); + std::string manifests = this->GetManifests(this->GetConfigName()); cmRulePlaceholderExpander::RuleVariables vars; vars.TargetPDB = targetOutPathPDB.c_str(); @@ -771,7 +775,7 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules( vars.Target = target.c_str(); vars.LinkLibraries = linkLibs.c_str(); vars.ObjectsQuoted = buildObjs.c_str(); - if (this->GeneratorTarget->HasSOName(this->ConfigName)) { + if (this->GeneratorTarget->HasSOName(this->GetConfigName())) { vars.SONameFlag = this->Makefile->GetSONameFlag(linkLanguage); vars.TargetSOName = this->TargetNames.SharedObject.c_str(); } @@ -783,8 +787,8 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules( std::string install_name_dir; if (this->GeneratorTarget->GetType() == cmStateEnums::SHARED_LIBRARY) { // Get the install_name directory for the build tree. - install_name_dir = - this->GeneratorTarget->GetInstallNameDirForBuildTree(this->ConfigName); + install_name_dir = this->GeneratorTarget->GetInstallNameDirForBuildTree( + this->GetConfigName()); // Set the rule variable replacement value. if (install_name_dir.empty()) { @@ -800,10 +804,10 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules( // Add language-specific flags. std::string langFlags; this->LocalGenerator->AddLanguageFlagsForLinking( - langFlags, this->GeneratorTarget, linkLanguage, this->ConfigName); + langFlags, this->GeneratorTarget, linkLanguage, this->GetConfigName()); this->LocalGenerator->AddArchitectureFlags( - langFlags, this->GeneratorTarget, linkLanguage, this->ConfigName); + langFlags, this->GeneratorTarget, linkLanguage, this->GetConfigName()); vars.LanguageCompileFlags = langFlags.c_str(); @@ -903,7 +907,7 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules( this->LocalGenerator->CreateCDCommand( commands1, this->Makefile->GetCurrentBinaryDirectory(), this->LocalGenerator->GetBinaryDirectory()); - cmAppend(commands, commands1); + cm::append(commands, commands1); commands1.clear(); // Add a rule to create necessary symlinks for the library. @@ -917,7 +921,7 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules( this->LocalGenerator->CreateCDCommand( commands1, this->Makefile->GetCurrentBinaryDirectory(), this->LocalGenerator->GetBinaryDirectory()); - cmAppend(commands, commands1); + cm::append(commands, commands1); commands1.clear(); } diff --git a/Source/cmMakefileTargetGenerator.cxx b/Source/cmMakefileTargetGenerator.cxx index 767f4e0..4979da5 100644 --- a/Source/cmMakefileTargetGenerator.cxx +++ b/Source/cmMakefileTargetGenerator.cxx @@ -2,12 +2,14 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmMakefileTargetGenerator.h" +#include <cassert> #include <cstdio> #include <memory> #include <sstream> #include <utility> -#include "cmAlgorithms.h" +#include <cmext/algorithm> + #include "cmComputeLinkInformation.h" #include "cmCustomCommand.h" #include "cmCustomCommandGenerator.h" @@ -85,6 +87,13 @@ cmMakefileTargetGenerator* cmMakefileTargetGenerator::New( return result; } +std::string cmMakefileTargetGenerator::GetConfigName() +{ + auto const& configNames = this->LocalGenerator->GetConfigNames(); + assert(configNames.size() == 1); + return configNames.front(); +} + void cmMakefileTargetGenerator::GetTargetLinkFlags( std::string& flags, const std::string& linkLanguage) { @@ -92,17 +101,18 @@ void cmMakefileTargetGenerator::GetTargetLinkFlags( flags, this->GeneratorTarget->GetSafeProperty("LINK_FLAGS")); std::string linkFlagsConfig = - cmStrCat("LINK_FLAGS_", cmSystemTools::UpperCase(this->ConfigName)); + cmStrCat("LINK_FLAGS_", cmSystemTools::UpperCase(this->GetConfigName())); this->LocalGenerator->AppendFlags( flags, this->GeneratorTarget->GetSafeProperty(linkFlagsConfig)); std::vector<std::string> opts; - this->GeneratorTarget->GetLinkOptions(opts, this->ConfigName, linkLanguage); + this->GeneratorTarget->GetLinkOptions(opts, this->GetConfigName(), + linkLanguage); // LINK_OPTIONS are escaped. this->LocalGenerator->AppendCompileOptions(flags, opts); this->LocalGenerator->AppendPositionIndependentLinkerFlags( - flags, this->GeneratorTarget, this->ConfigName, linkLanguage); + flags, this->GeneratorTarget, this->GetConfigName(), linkLanguage); } void cmMakefileTargetGenerator::CreateRuleFile() @@ -154,10 +164,10 @@ void cmMakefileTargetGenerator::WriteTargetBuildRules() auto evaluatedFiles = [this](const char* prop_value) -> std::vector<std::string> { std::vector<std::string> files; - cmExpandList( - cmGeneratorExpression::Evaluate(prop_value, this->LocalGenerator, - this->ConfigName, this->GeneratorTarget), - files); + cmExpandList(cmGeneratorExpression::Evaluate( + prop_value, this->LocalGenerator, this->GetConfigName(), + this->GeneratorTarget), + files); return files; }; @@ -187,12 +197,13 @@ void cmMakefileTargetGenerator::WriteTargetBuildRules() // First generate the object rule files. Save a list of all object // files for this target. std::vector<cmSourceFile const*> customCommands; - this->GeneratorTarget->GetCustomCommands(customCommands, this->ConfigName); + this->GeneratorTarget->GetCustomCommands(customCommands, + this->GetConfigName()); std::string currentBinDir = this->LocalGenerator->GetCurrentBinaryDirectory(); for (cmSourceFile const* sf : customCommands) { - cmCustomCommandGenerator ccg(*sf->GetCustomCommand(), this->ConfigName, - this->LocalGenerator); + cmCustomCommandGenerator ccg(*sf->GetCustomCommand(), + this->GetConfigName(), this->LocalGenerator); this->GenerateCustomRuleFile(ccg); if (clean) { const std::vector<std::string>& outputs = ccg.GetOutputs(); @@ -215,12 +226,14 @@ void cmMakefileTargetGenerator::WriteTargetBuildRules() std::vector<cmCustomCommand> buildEventCommands = this->GeneratorTarget->GetPreBuildCommands(); - cmAppend(buildEventCommands, this->GeneratorTarget->GetPreLinkCommands()); - cmAppend(buildEventCommands, - this->GeneratorTarget->GetPostBuildCommands()); + cm::append(buildEventCommands, + this->GeneratorTarget->GetPreLinkCommands()); + cm::append(buildEventCommands, + this->GeneratorTarget->GetPostBuildCommands()); for (const auto& be : buildEventCommands) { - cmCustomCommandGenerator beg(be, this->ConfigName, this->LocalGenerator); + cmCustomCommandGenerator beg(be, this->GetConfigName(), + this->LocalGenerator); const std::vector<std::string>& byproducts = beg.GetByproducts(); for (std::string const& byproduct : byproducts) { this->CleanFiles.insert( @@ -230,17 +243,19 @@ void cmMakefileTargetGenerator::WriteTargetBuildRules() } } std::vector<cmSourceFile const*> headerSources; - this->GeneratorTarget->GetHeaderSources(headerSources, this->ConfigName); + this->GeneratorTarget->GetHeaderSources(headerSources, + this->GetConfigName()); this->OSXBundleGenerator->GenerateMacOSXContentStatements( - headerSources, this->MacOSXContentGenerator); + headerSources, this->MacOSXContentGenerator, this->GetConfigName()); std::vector<cmSourceFile const*> extraSources; - this->GeneratorTarget->GetExtraSources(extraSources, this->ConfigName); + this->GeneratorTarget->GetExtraSources(extraSources, this->GetConfigName()); this->OSXBundleGenerator->GenerateMacOSXContentStatements( - extraSources, this->MacOSXContentGenerator); + extraSources, this->MacOSXContentGenerator, this->GetConfigName()); const char* pchExtension = this->Makefile->GetDefinition("CMAKE_PCH_EXTENSION"); std::vector<cmSourceFile const*> externalObjects; - this->GeneratorTarget->GetExternalObjects(externalObjects, this->ConfigName); + this->GeneratorTarget->GetExternalObjects(externalObjects, + this->GetConfigName()); for (cmSourceFile const* sf : externalObjects) { auto const& objectFileName = sf->GetFullPath(); if (!cmSystemTools::StringEndsWith(objectFileName, pchExtension)) { @@ -248,7 +263,8 @@ void cmMakefileTargetGenerator::WriteTargetBuildRules() } } std::vector<cmSourceFile const*> objectSources; - this->GeneratorTarget->GetObjectSources(objectSources, this->ConfigName); + this->GeneratorTarget->GetObjectSources(objectSources, + this->GetConfigName()); for (cmSourceFile const* sf : objectSources) { // Generate this object file's rule file. this->WriteObjectRuleFiles(*sf); @@ -334,9 +350,9 @@ void cmMakefileTargetGenerator::WriteTargetLanguageFlags() } for (std::string const& language : languages) { - std::string flags = this->GetFlags(language); - std::string defines = this->GetDefines(language); - std::string includes = this->GetIncludes(language); + std::string flags = this->GetFlags(language, this->GetConfigName()); + std::string defines = this->GetDefines(language, this->GetConfigName()); + std::string includes = this->GetIncludes(language, this->GetConfigName()); // Escape comment characters so they do not terminate assignment. cmSystemTools::ReplaceString(flags, "#", "\\#"); cmSystemTools::ReplaceString(defines, "#", "\\#"); @@ -348,7 +364,7 @@ void cmMakefileTargetGenerator::WriteTargetLanguageFlags() } void cmMakefileTargetGenerator::MacOSXContentGeneratorType::operator()( - cmSourceFile const& source, const char* pkgloc) + cmSourceFile const& source, const char* pkgloc, const std::string& config) { // Skip OS X content when not building a Framework or Bundle. if (!this->Generator->GetGeneratorTarget()->IsBundleOnApple()) { @@ -356,7 +372,8 @@ void cmMakefileTargetGenerator::MacOSXContentGeneratorType::operator()( } std::string macdir = - this->Generator->OSXBundleGenerator->InitMacOSXContentDirectory(pkgloc); + this->Generator->OSXBundleGenerator->InitMacOSXContentDirectory(pkgloc, + config); // Get the input file location. std::string const& input = source.GetFullPath(); @@ -451,7 +468,7 @@ void cmMakefileTargetGenerator::WriteObjectRuleFiles( // generate the depend scanning rule this->WriteObjectDependRules(source, depends); - std::string config = this->LocalGenerator->GetConfigName(); + std::string config = this->GetConfigName(); std::string configUpper = cmSystemTools::UpperCase(config); // Add precompile headers dependencies @@ -593,16 +610,17 @@ void cmMakefileTargetGenerator::WriteObjectRuleFiles( { std::string targetFullPathReal; std::string targetFullPathPDB; - std::string targetFullPathCompilePDB = this->ComputeTargetCompilePDB(); + std::string targetFullPathCompilePDB = + this->ComputeTargetCompilePDB(this->GetConfigName()); if (this->GeneratorTarget->GetType() == cmStateEnums::EXECUTABLE || this->GeneratorTarget->GetType() == cmStateEnums::STATIC_LIBRARY || this->GeneratorTarget->GetType() == cmStateEnums::SHARED_LIBRARY || this->GeneratorTarget->GetType() == cmStateEnums::MODULE_LIBRARY) { targetFullPathReal = this->GeneratorTarget->GetFullPath( - this->ConfigName, cmStateEnums::RuntimeBinaryArtifact, true); - targetFullPathPDB = - cmStrCat(this->GeneratorTarget->GetPDBDirectory(this->ConfigName), '/', - this->GeneratorTarget->GetPDBName(this->ConfigName)); + this->GetConfigName(), cmStateEnums::RuntimeBinaryArtifact, true); + targetFullPathPDB = cmStrCat( + this->GeneratorTarget->GetPDBDirectory(this->GetConfigName()), '/', + this->GeneratorTarget->GetPDBName(this->GetConfigName())); } targetOutPathReal = this->LocalGenerator->ConvertToOutputFormat( @@ -708,13 +726,15 @@ void cmMakefileTargetGenerator::WriteObjectRuleFiles( std::string workingDirectory = cmSystemTools::CollapseFullPath( this->LocalGenerator->GetCurrentBinaryDirectory()); compileCommand.replace(compileCommand.find(langFlags), langFlags.size(), - this->GetFlags(lang)); + this->GetFlags(lang, this->GetConfigName())); std::string langDefines = std::string("$(") + lang + "_DEFINES)"; compileCommand.replace(compileCommand.find(langDefines), - langDefines.size(), this->GetDefines(lang)); + langDefines.size(), + this->GetDefines(lang, this->GetConfigName())); std::string langIncludes = std::string("$(") + lang + "_INCLUDES)"; compileCommand.replace(compileCommand.find(langIncludes), - langIncludes.size(), this->GetIncludes(lang)); + langIncludes.size(), + this->GetIncludes(lang, this->GetConfigName())); const char* eliminate[] = { this->Makefile->GetDefinition("CMAKE_START_TEMP_FILE"), @@ -823,7 +843,7 @@ void cmMakefileTargetGenerator::WriteObjectRuleFiles( this->LocalGenerator->CreateCDCommand( compileCommands, this->LocalGenerator->GetCurrentBinaryDirectory(), this->LocalGenerator->GetBinaryDirectory()); - cmAppend(commands, compileCommands); + cm::append(commands, compileCommands); } // Check for extra outputs created by the compilation. @@ -882,7 +902,7 @@ void cmMakefileTargetGenerator::WriteObjectRuleFiles( preprocessCommands, this->LocalGenerator->GetCurrentBinaryDirectory(), this->LocalGenerator->GetBinaryDirectory()); - cmAppend(commands, preprocessCommands); + cm::append(commands, preprocessCommands); } else { std::string cmd = cmStrCat("$(CMAKE_COMMAND) -E cmake_unimplemented_variable ", @@ -926,7 +946,7 @@ void cmMakefileTargetGenerator::WriteObjectRuleFiles( this->LocalGenerator->CreateCDCommand( assemblyCommands, this->LocalGenerator->GetCurrentBinaryDirectory(), this->LocalGenerator->GetBinaryDirectory()); - cmAppend(commands, assemblyCommands); + cm::append(commands, assemblyCommands); } else { std::string cmd = cmStrCat("$(CMAKE_COMMAND) -E cmake_unimplemented_variable ", @@ -1068,7 +1088,8 @@ void cmMakefileTargetGenerator::WriteTargetDependRules() << "# Targets to which this target links.\n" << "set(CMAKE_TARGET_LINKED_INFO_FILES\n"; /* clang-format on */ - std::vector<std::string> dirs = this->GetLinkedTargetDirectories(); + std::vector<std::string> dirs = + this->GetLinkedTargetDirectories(this->GetConfigName()); for (std::string const& d : dirs) { *this->InfoFileStream << " \"" << d << "/DependInfo.cmake\"\n"; } @@ -1171,9 +1192,9 @@ void cmMakefileTargetGenerator::DriveCustomCommands( sources, this->Makefile->GetSafeDefinition("CMAKE_BUILD_TYPE")); for (cmSourceFile* source : sources) { if (cmCustomCommand* cc = source->GetCustomCommand()) { - cmCustomCommandGenerator ccg(*cc, this->ConfigName, + cmCustomCommandGenerator ccg(*cc, this->GetConfigName(), this->LocalGenerator); - cmAppend(depends, ccg.GetOutputs()); + cm::append(depends, ccg.GetOutputs()); } } } @@ -1410,7 +1431,7 @@ void cmMakefileTargetGenerator::WriteTargetDriverRule( } // Make sure the extra files are built. - cmAppend(depends, this->ExtraFiles); + cm::append(depends, this->ExtraFiles); } // Write the driver rule. @@ -1429,10 +1450,10 @@ void cmMakefileTargetGenerator::AppendTargetDepends( } // Loop over all library dependencies. - const std::string& cfg = this->LocalGenerator->GetConfigName(); + const std::string& cfg = this->GetConfigName(); if (cmComputeLinkInformation* cli = this->GeneratorTarget->GetLinkInformation(cfg)) { - cmAppend(depends, cli->GetDepends()); + cm::append(depends, cli->GetDepends()); } } @@ -1448,7 +1469,7 @@ void cmMakefileTargetGenerator::AppendObjectDepends( } // Add dependencies on the external object files. - cmAppend(depends, this->ExternalObjects); + cm::append(depends, this->ExternalObjects); // Add a dependency on the rule file itself. this->LocalGenerator->AppendRuleDepend(depends, @@ -1474,13 +1495,13 @@ void cmMakefileTargetGenerator::AppendLinkDepends( // Add a dependency on user-specified manifest files, if any. std::vector<cmSourceFile const*> manifest_srcs; - this->GeneratorTarget->GetManifests(manifest_srcs, this->ConfigName); + this->GeneratorTarget->GetManifests(manifest_srcs, this->GetConfigName()); for (cmSourceFile const* manifest_src : manifest_srcs) { depends.push_back(manifest_src->GetFullPath()); } // Add user-specified dependencies. - this->GeneratorTarget->GetLinkDepends(depends, this->ConfigName, + this->GeneratorTarget->GetLinkDepends(depends, this->GetConfigName(), linkLanguage); } @@ -1488,10 +1509,11 @@ std::string cmMakefileTargetGenerator::GetLinkRule( const std::string& linkRuleVar) { std::string linkRule = this->Makefile->GetRequiredDefinition(linkRuleVar); - if (this->GeneratorTarget->HasImplibGNUtoMS(this->ConfigName)) { - std::string ruleVar = cmStrCat( - "CMAKE_", this->GeneratorTarget->GetLinkerLanguage(this->ConfigName), - "_GNUtoMS_RULE"); + if (this->GeneratorTarget->HasImplibGNUtoMS(this->GetConfigName())) { + std::string ruleVar = + cmStrCat("CMAKE_", + this->GeneratorTarget->GetLinkerLanguage(this->GetConfigName()), + "_GNUtoMS_RULE"); if (const char* rule = this->Makefile->GetDefinition(ruleVar)) { linkRule += rule; } @@ -1630,7 +1652,7 @@ void cmMakefileTargetGenerator::CreateLinkLibs( std::string frameworkPath; std::string linkPath; cmComputeLinkInformation* pcli = - this->GeneratorTarget->GetLinkInformation(this->ConfigName); + this->GeneratorTarget->GetLinkInformation(this->GetConfigName()); this->LocalGenerator->OutputLinkLibraries(pcli, linkLineComputer, linkLibs, frameworkPath, linkPath); linkLibs = frameworkPath + linkPath + linkLibs; @@ -1638,9 +1660,10 @@ void cmMakefileTargetGenerator::CreateLinkLibs( if (useResponseFile && linkLibs.find_first_not_of(' ') != std::string::npos) { // Lookup the response file reference flag. - std::string responseFlagVar = cmStrCat( - "CMAKE_", this->GeneratorTarget->GetLinkerLanguage(this->ConfigName), - "_RESPONSE_FILE_LINK_FLAG"); + std::string responseFlagVar = + cmStrCat("CMAKE_", + this->GeneratorTarget->GetLinkerLanguage(this->GetConfigName()), + "_RESPONSE_FILE_LINK_FLAG"); const char* responseFlag = this->Makefile->GetDefinition(responseFlagVar); if (!responseFlag) { responseFlag = "@"; @@ -1675,9 +1698,10 @@ void cmMakefileTargetGenerator::CreateObjectLists( this->WriteObjectsStrings(object_strings, responseFileLimit); // Lookup the response file reference flag. - std::string responseFlagVar = cmStrCat( - "CMAKE_", this->GeneratorTarget->GetLinkerLanguage(this->ConfigName), - "_RESPONSE_FILE_LINK_FLAG"); + std::string responseFlagVar = + cmStrCat("CMAKE_", + this->GeneratorTarget->GetLinkerLanguage(this->GetConfigName()), + "_RESPONSE_FILE_LINK_FLAG"); const char* responseFlag = this->Makefile->GetDefinition(responseFlagVar); if (!responseFlag) { responseFlag = "@"; @@ -1716,7 +1740,8 @@ void cmMakefileTargetGenerator::CreateObjectLists( } void cmMakefileTargetGenerator::AddIncludeFlags(std::string& flags, - const std::string& lang) + const std::string& lang, + const std::string& /*config*/) { std::string responseVar = cmStrCat("CMAKE_", lang, "_USE_RESPONSE_FILE_FOR_INCLUDES"); @@ -1724,11 +1749,11 @@ void cmMakefileTargetGenerator::AddIncludeFlags(std::string& flags, std::vector<std::string> includes; this->LocalGenerator->GetIncludeDirectories(includes, this->GeneratorTarget, - lang, this->ConfigName); + lang, this->GetConfigName()); std::string includeFlags = this->LocalGenerator->GetIncludeFlags( includes, this->GeneratorTarget, lang, false, useResponseFile, - this->ConfigName); + this->GetConfigName()); if (includeFlags.empty()) { return; } diff --git a/Source/cmMakefileTargetGenerator.h b/Source/cmMakefileTargetGenerator.h index 7b9c7a5..710ef89 100644 --- a/Source/cmMakefileTargetGenerator.h +++ b/Source/cmMakefileTargetGenerator.h @@ -52,6 +52,8 @@ public: cmGeneratorTarget* GetGeneratorTarget() { return this->GeneratorTarget; } + std::string GetConfigName(); + protected: void GetTargetLinkFlags(std::string& flags, const std::string& linkLanguage); @@ -81,7 +83,8 @@ protected: { } - void operator()(cmSourceFile const& source, const char* pkgloc) override; + void operator()(cmSourceFile const& source, const char* pkgloc, + const std::string& config) override; private: cmMakefileTargetGenerator* Generator; @@ -163,7 +166,8 @@ protected: /** Add commands for generate def files */ void GenDefFile(std::vector<std::string>& real_link_commands); - void AddIncludeFlags(std::string& flags, const std::string& lang) override; + void AddIncludeFlags(std::string& flags, const std::string& lang, + const std::string& config) override; virtual void CloseFileStreams(); cmLocalUnixMakefileGenerator3* LocalGenerator; diff --git a/Source/cmMakefileUtilityTargetGenerator.cxx b/Source/cmMakefileUtilityTargetGenerator.cxx index 1625e4f..6c18e48 100644 --- a/Source/cmMakefileUtilityTargetGenerator.cxx +++ b/Source/cmMakefileUtilityTargetGenerator.cxx @@ -22,8 +22,7 @@ cmMakefileUtilityTargetGenerator::cmMakefileUtilityTargetGenerator( : cmMakefileTargetGenerator(target) { this->CustomCommandDriver = OnUtility; - this->OSXBundleGenerator = - cm::make_unique<cmOSXBundleGenerator>(target, this->ConfigName); + this->OSXBundleGenerator = cm::make_unique<cmOSXBundleGenerator>(target); this->OSXBundleGenerator->SetMacContentFolders(&this->MacContentFolders); } diff --git a/Source/cmMessageCommand.cxx b/Source/cmMessageCommand.cxx index 96a6386..bf8183b 100644 --- a/Source/cmMessageCommand.cxx +++ b/Source/cmMessageCommand.cxx @@ -3,6 +3,11 @@ #include "cmMessageCommand.h" #include <cassert> +#include <utility> + +#include <cm/string_view> + +#include "cm_static_string_view.hxx" #include "cmExecutionStatus.h" #include "cmMakefile.h" @@ -13,6 +18,55 @@ #include "cmSystemTools.h" #include "cmake.h" +namespace { + +enum class CheckingType +{ + UNDEFINED, + CHECK_START, + CHECK_PASS, + CHECK_FAIL +}; + +std::string IndentText(std::string text, cmMakefile& mf) +{ + auto indent = + cmJoin(cmExpandedList(mf.GetSafeDefinition("CMAKE_MESSAGE_INDENT")), ""); + + const auto showContext = mf.GetCMakeInstance()->GetShowLogContext() || + mf.IsOn("CMAKE_MESSAGE_CONTEXT_SHOW"); + if (showContext) { + auto context = cmJoin( + cmExpandedList(mf.GetSafeDefinition("CMAKE_MESSAGE_CONTEXT")), "."); + if (!context.empty()) { + indent.insert(0u, cmStrCat("["_s, context, "] "_s)); + } + } + + if (!indent.empty()) { + cmSystemTools::ReplaceString(text, "\n", "\n" + indent); + text.insert(0u, indent); + } + return text; +} + +void ReportCheckResult(cm::string_view what, std::string result, + cmMakefile& mf) +{ + if (mf.GetCMakeInstance()->HasCheckInProgress()) { + auto text = mf.GetCMakeInstance()->GetTopCheckInProgressMessage() + " - " + + std::move(result); + mf.DisplayStatus(IndentText(std::move(text), mf), -1); + } else { + mf.GetMessenger()->DisplayMessage( + MessageType::AUTHOR_WARNING, + cmStrCat("Ignored "_s, what, " without CHECK_START"_s), + mf.GetBacktrace()); + } +} + +} // anonymous namespace + // cmLibraryCommand bool cmMessageCommand(std::vector<std::string> const& args, cmExecutionStatus& status) @@ -21,11 +75,15 @@ bool cmMessageCommand(std::vector<std::string> const& args, status.SetError("called with incorrect number of arguments"); return false; } + + auto& mf = status.GetMakefile(); + auto i = args.cbegin(); auto type = MessageType::MESSAGE; auto fatal = false; auto level = cmake::LogLevel::LOG_UNDEFINED; + auto checkingType = CheckingType::UNDEFINED; if (*i == "SEND_ERROR") { type = MessageType::FATAL_ERROR; level = cmake::LogLevel::LOG_ERROR; @@ -40,19 +98,30 @@ bool cmMessageCommand(std::vector<std::string> const& args, level = cmake::LogLevel::LOG_WARNING; ++i; } else if (*i == "AUTHOR_WARNING") { - if (status.GetMakefile().IsSet("CMAKE_SUPPRESS_DEVELOPER_ERRORS") && - !status.GetMakefile().IsOn("CMAKE_SUPPRESS_DEVELOPER_ERRORS")) { + if (mf.IsSet("CMAKE_SUPPRESS_DEVELOPER_ERRORS") && + !mf.IsOn("CMAKE_SUPPRESS_DEVELOPER_ERRORS")) { fatal = true; type = MessageType::AUTHOR_ERROR; level = cmake::LogLevel::LOG_ERROR; - } else if (!status.GetMakefile().IsOn( - "CMAKE_SUPPRESS_DEVELOPER_WARNINGS")) { + } else if (!mf.IsOn("CMAKE_SUPPRESS_DEVELOPER_WARNINGS")) { type = MessageType::AUTHOR_WARNING; level = cmake::LogLevel::LOG_WARNING; } else { return true; } ++i; + } else if (*i == "CHECK_START") { + level = cmake::LogLevel::LOG_STATUS; + checkingType = CheckingType::CHECK_START; + ++i; + } else if (*i == "CHECK_PASS") { + level = cmake::LogLevel::LOG_STATUS; + checkingType = CheckingType::CHECK_PASS; + ++i; + } else if (*i == "CHECK_FAIL") { + level = cmake::LogLevel::LOG_STATUS; + checkingType = CheckingType::CHECK_FAIL; + ++i; } else if (*i == "STATUS") { level = cmake::LogLevel::LOG_STATUS; ++i; @@ -66,12 +135,12 @@ bool cmMessageCommand(std::vector<std::string> const& args, level = cmake::LogLevel::LOG_TRACE; ++i; } else if (*i == "DEPRECATION") { - if (status.GetMakefile().IsOn("CMAKE_ERROR_DEPRECATED")) { + if (mf.IsOn("CMAKE_ERROR_DEPRECATED")) { fatal = true; type = MessageType::DEPRECATION_ERROR; level = cmake::LogLevel::LOG_ERROR; - } else if (!status.GetMakefile().IsSet("CMAKE_WARN_DEPRECATED") || - status.GetMakefile().IsOn("CMAKE_WARN_DEPRECATED")) { + } else if (!mf.IsSet("CMAKE_WARN_DEPRECATED") || + mf.IsOn("CMAKE_WARN_DEPRECATED")) { type = MessageType::DEPRECATION_WARNING; level = cmake::LogLevel::LOG_WARNING; } else { @@ -89,10 +158,19 @@ bool cmMessageCommand(std::vector<std::string> const& args, assert("Message log level expected to be set" && level != cmake::LogLevel::LOG_UNDEFINED); - auto desiredLevel = status.GetMakefile().GetCMakeInstance()->GetLogLevel(); + auto desiredLevel = mf.GetCMakeInstance()->GetLogLevel(); assert("Expected a valid log level here" && desiredLevel != cmake::LogLevel::LOG_UNDEFINED); + // Command line option takes precedence over the cache variable + if (!mf.GetCMakeInstance()->WasLogLevelSetViaCLI()) { + const auto desiredLevelFromCache = + cmake::StringToLogLevel(mf.GetSafeDefinition("CMAKE_MESSAGE_LOG_LEVEL")); + if (desiredLevelFromCache != cmake::LogLevel::LOG_UNDEFINED) { + desiredLevel = desiredLevelFromCache; + } + } + if (desiredLevel < level) { // Suppress the message return true; @@ -100,37 +178,42 @@ bool cmMessageCommand(std::vector<std::string> const& args, auto message = cmJoin(cmMakeRange(i, args.cend()), ""); - if (cmake::LogLevel::LOG_NOTICE <= level) { - // Check if any indentation has requested: - // `CMAKE_MESSAGE_INDENT` is a list of "padding" pieces - // to be joined and prepended to the message lines. - auto indent = cmJoin(cmExpandedList(status.GetMakefile().GetSafeDefinition( - "CMAKE_MESSAGE_INDENT")), - ""); - // Make every line of the `message` indented - // NOTE Can't reuse `cmDocumentationFormatter::PrintPreformatted` - // here cuz it appends `\n` to the EOM ;-( - cmSystemTools::ReplaceString(message, "\n", "\n" + indent); - message = indent + message; - } - switch (level) { case cmake::LogLevel::LOG_ERROR: case cmake::LogLevel::LOG_WARNING: // we've overridden the message type, above, so display it directly - status.GetMakefile().GetMessenger()->DisplayMessage( - type, message, status.GetMakefile().GetBacktrace()); + mf.GetMessenger()->DisplayMessage(type, message, mf.GetBacktrace()); break; case cmake::LogLevel::LOG_NOTICE: - cmSystemTools::Message(message); + cmSystemTools::Message(IndentText(message, mf)); break; case cmake::LogLevel::LOG_STATUS: + switch (checkingType) { + case CheckingType::CHECK_START: + mf.DisplayStatus(IndentText(message, mf), -1); + mf.GetCMakeInstance()->PushCheckInProgressMessage(message); + break; + + case CheckingType::CHECK_PASS: + ReportCheckResult("CHECK_PASS"_s, message, mf); + break; + + case CheckingType::CHECK_FAIL: + ReportCheckResult("CHECK_FAIL"_s, message, mf); + break; + + default: + mf.DisplayStatus(IndentText(message, mf), -1); + break; + } + break; + case cmake::LogLevel::LOG_VERBOSE: case cmake::LogLevel::LOG_DEBUG: case cmake::LogLevel::LOG_TRACE: - status.GetMakefile().DisplayStatus(message, -1); + mf.DisplayStatus(IndentText(message, mf), -1); break; default: diff --git a/Source/cmNinjaNormalTargetGenerator.cxx b/Source/cmNinjaNormalTargetGenerator.cxx index beedef4..5a12855 100644 --- a/Source/cmNinjaNormalTargetGenerator.cxx +++ b/Source/cmNinjaNormalTargetGenerator.cxx @@ -41,33 +41,25 @@ cmNinjaNormalTargetGenerator::cmNinjaNormalTargetGenerator( cmGeneratorTarget* target) : cmNinjaTargetGenerator(target) - , TargetLinkLanguage("") { - this->TargetLinkLanguage = target->GetLinkerLanguage(this->GetConfigName()); - if (target->GetType() == cmStateEnums::EXECUTABLE) { - this->TargetNames = this->GetGeneratorTarget()->GetExecutableNames( - GetLocalGenerator()->GetConfigName()); - } else { - this->TargetNames = this->GetGeneratorTarget()->GetLibraryNames( - GetLocalGenerator()->GetConfigName()); - } - if (target->GetType() != cmStateEnums::OBJECT_LIBRARY) { // on Windows the output dir is already needed at compile time // ensure the directory exists (OutDir test) - EnsureDirectoryExists(target->GetDirectory(this->GetConfigName())); + for (auto const& config : this->GetConfigNames()) { + EnsureDirectoryExists(target->GetDirectory(config)); + } } - this->OSXBundleGenerator = - cm::make_unique<cmOSXBundleGenerator>(target, this->GetConfigName()); + this->OSXBundleGenerator = cm::make_unique<cmOSXBundleGenerator>(target); this->OSXBundleGenerator->SetMacContentFolders(&this->MacContentFolders); } cmNinjaNormalTargetGenerator::~cmNinjaNormalTargetGenerator() = default; -void cmNinjaNormalTargetGenerator::Generate() +void cmNinjaNormalTargetGenerator::Generate(const std::string& config) { - if (this->TargetLinkLanguage.empty()) { + std::string lang = this->GeneratorTarget->GetLinkerLanguage(config); + if (this->TargetLinkLanguage(config).empty()) { cmSystemTools::Error("CMake can not determine linker language for " "target: " + this->GetGeneratorTarget()->GetName()); @@ -75,25 +67,36 @@ void cmNinjaNormalTargetGenerator::Generate() } // Write the rules for each language. - this->WriteLanguagesRules(); + this->WriteLanguagesRules(config); // Write the build statements - this->WriteObjectBuildStatements(); + bool firstForConfig = true; + for (auto const& fileConfig : this->GetConfigNames()) { + this->WriteObjectBuildStatements(config, fileConfig, firstForConfig); + firstForConfig = false; + } if (this->GetGeneratorTarget()->GetType() == cmStateEnums::OBJECT_LIBRARY) { - this->WriteObjectLibStatement(); + this->WriteObjectLibStatement(config); } else { // If this target has cuda language link inputs, and we need to do // device linking - this->WriteDeviceLinkStatement(); - this->WriteLinkStatement(); + this->WriteDeviceLinkStatement(config); + firstForConfig = true; + for (auto const& fileConfig : this->GetConfigNames()) { + this->WriteLinkStatement(config, fileConfig, firstForConfig); + firstForConfig = false; + } } + this->GetGlobalGenerator()->AddTargetAlias( + this->GetTargetName(), this->GetGeneratorTarget(), "all"); // Find ADDITIONAL_CLEAN_FILES - this->AdditionalCleanFiles(); + this->AdditionalCleanFiles(config); } -void cmNinjaNormalTargetGenerator::WriteLanguagesRules() +void cmNinjaNormalTargetGenerator::WriteLanguagesRules( + const std::string& config) { #ifdef NINJA_GEN_VERBOSE_FILES cmGlobalNinjaGenerator::WriteDivider(this->GetRulesFileStream()); @@ -106,8 +109,7 @@ void cmNinjaNormalTargetGenerator::WriteLanguagesRules() // Write rules for languages compiled in this target. std::set<std::string> languages; std::vector<cmSourceFile const*> sourceFiles; - this->GetGeneratorTarget()->GetObjectSources( - sourceFiles, this->GetMakefile()->GetSafeDefinition("CMAKE_BUILD_TYPE")); + this->GetGeneratorTarget()->GetObjectSources(sourceFiles, config); for (cmSourceFile const* sf : sourceFiles) { std::string const lang = sf->GetLanguage(); if (!lang.empty()) { @@ -115,7 +117,7 @@ void cmNinjaNormalTargetGenerator::WriteLanguagesRules() } } for (std::string const& language : languages) { - this->WriteLanguageRules(language); + this->WriteLanguageRules(language, config); } } @@ -139,22 +141,26 @@ const char* cmNinjaNormalTargetGenerator::GetVisibleTypeName() const } } -std::string cmNinjaNormalTargetGenerator::LanguageLinkerRule() const +std::string cmNinjaNormalTargetGenerator::LanguageLinkerRule( + const std::string& config) const { - return this->TargetLinkLanguage + "_" + + return this->TargetLinkLanguage(config) + "_" + cmState::GetTargetTypeName(this->GetGeneratorTarget()->GetType()) + "_LINKER__" + cmGlobalNinjaGenerator::EncodeRuleName( - this->GetGeneratorTarget()->GetName()); + this->GetGeneratorTarget()->GetName()) + + "_" + config; } -std::string cmNinjaNormalTargetGenerator::LanguageLinkerDeviceRule() const +std::string cmNinjaNormalTargetGenerator::LanguageLinkerDeviceRule( + const std::string& config) const { - return this->TargetLinkLanguage + "_" + + return this->TargetLinkLanguage(config) + "_" + cmState::GetTargetTypeName(this->GetGeneratorTarget()->GetType()) + "_DEVICE_LINKER__" + cmGlobalNinjaGenerator::EncodeRuleName( - this->GetGeneratorTarget()->GetName()); + this->GetGeneratorTarget()->GetName()) + + "_" + config; } struct cmNinjaRemoveNoOpCommands @@ -165,9 +171,10 @@ struct cmNinjaRemoveNoOpCommands } }; -void cmNinjaNormalTargetGenerator::WriteDeviceLinkRule(bool useResponseFile) +void cmNinjaNormalTargetGenerator::WriteDeviceLinkRule( + bool useResponseFile, const std::string& config) { - cmNinjaRule rule(this->LanguageLinkerDeviceRule()); + cmNinjaRule rule(this->LanguageLinkerDeviceRule(config)); if (!this->GetGlobalGenerator()->HasRule(rule.Name)) { cmRulePlaceholderExpander::RuleVariables vars; vars.CMTargetName = this->GetGeneratorTarget()->GetName().c_str(); @@ -241,30 +248,34 @@ void cmNinjaNormalTargetGenerator::WriteDeviceLinkRule(bool useResponseFile) rule.Command = this->GetLocalGenerator()->BuildCommandLine(linkCmds); // Write the linker rule with response file if needed. - rule.Comment = cmStrCat("Rule for linking ", this->TargetLinkLanguage, ' ', - this->GetVisibleTypeName(), '.'); - rule.Description = cmStrCat("Linking ", this->TargetLinkLanguage, ' ', - this->GetVisibleTypeName(), " $TARGET_FILE"); + rule.Comment = + cmStrCat("Rule for linking ", this->TargetLinkLanguage(config), ' ', + this->GetVisibleTypeName(), '.'); + rule.Description = + cmStrCat("Linking ", this->TargetLinkLanguage(config), ' ', + this->GetVisibleTypeName(), " $TARGET_FILE"); rule.Restat = "$RESTAT"; this->GetGlobalGenerator()->AddRule(rule); } } -void cmNinjaNormalTargetGenerator::WriteLinkRule(bool useResponseFile) +void cmNinjaNormalTargetGenerator::WriteLinkRule(bool useResponseFile, + const std::string& config) { cmStateEnums::TargetType targetType = this->GetGeneratorTarget()->GetType(); - std::string linkRuleName = this->LanguageLinkerRule(); + std::string linkRuleName = this->LanguageLinkerRule(config); if (!this->GetGlobalGenerator()->HasRule(linkRuleName)) { cmNinjaRule rule(std::move(linkRuleName)); cmRulePlaceholderExpander::RuleVariables vars; vars.CMTargetName = this->GetGeneratorTarget()->GetName().c_str(); vars.CMTargetType = cmState::GetTargetTypeName(targetType); - vars.Language = this->TargetLinkLanguage.c_str(); + std::string lang = this->TargetLinkLanguage(config); + vars.Language = config.c_str(); - if (this->TargetLinkLanguage == "Swift") { + if (this->TargetLinkLanguage(config) == "Swift") { vars.SwiftLibraryName = "$SWIFT_LIBRARY_NAME"; vars.SwiftModule = "$SWIFT_MODULE"; vars.SwiftModuleName = "$SWIFT_MODULE_NAME"; @@ -278,7 +289,8 @@ void cmNinjaNormalTargetGenerator::WriteLinkRule(bool useResponseFile) std::string responseFlag; - std::string cmakeVarLang = cmStrCat("CMAKE_", this->TargetLinkLanguage); + std::string cmakeVarLang = + cmStrCat("CMAKE_", this->TargetLinkLanguage(config)); // build response file name std::string cmakeLinkVar = cmakeVarLang + "_RESPONSE_FILE_LINK_FLAG"; @@ -286,7 +298,7 @@ void cmNinjaNormalTargetGenerator::WriteLinkRule(bool useResponseFile) if (flag) { responseFlag = flag; - } else if (this->TargetLinkLanguage != "CUDA") { + } else if (this->TargetLinkLanguage(config) != "CUDA") { responseFlag = "@"; } @@ -304,7 +316,7 @@ void cmNinjaNormalTargetGenerator::WriteLinkRule(bool useResponseFile) rule.RspContent = "$in_newline"; } rule.RspContent += " $LINK_PATH $LINK_LIBRARIES"; - if (this->TargetLinkLanguage == "Swift") { + if (this->TargetLinkLanguage(config) == "Swift") { vars.SwiftSources = responseFlag.c_str(); } else { vars.Objects = responseFlag.c_str(); @@ -359,7 +371,7 @@ void cmNinjaNormalTargetGenerator::WriteLinkRule(bool useResponseFile) this->GetLocalGenerator()->CreateRulePlaceholderExpander()); // Rule for linking library/executable. - std::vector<std::string> linkCmds = this->ComputeLinkCmd(); + std::vector<std::string> linkCmds = this->ComputeLinkCmd(config); for (std::string& linkCmd : linkCmds) { linkCmd = cmStrCat(launcher, linkCmd); rulePlaceholderExpander->ExpandRuleVariables(this->GetLocalGenerator(), @@ -374,15 +386,18 @@ void cmNinjaNormalTargetGenerator::WriteLinkRule(bool useResponseFile) rule.Command = this->GetLocalGenerator()->BuildCommandLine(linkCmds); // Write the linker rule with response file if needed. - rule.Comment = cmStrCat("Rule for linking ", this->TargetLinkLanguage, ' ', - this->GetVisibleTypeName(), '.'); - rule.Description = cmStrCat("Linking ", this->TargetLinkLanguage, ' ', - this->GetVisibleTypeName(), " $TARGET_FILE"); + rule.Comment = + cmStrCat("Rule for linking ", this->TargetLinkLanguage(config), ' ', + this->GetVisibleTypeName(), '.'); + rule.Description = + cmStrCat("Linking ", this->TargetLinkLanguage(config), ' ', + this->GetVisibleTypeName(), " $TARGET_FILE"); rule.Restat = "$RESTAT"; this->GetGlobalGenerator()->AddRule(rule); } - if (this->TargetNames.Output != this->TargetNames.Real && + auto const tgtNames = this->TargetNames(config); + if (tgtNames.Output != tgtNames.Real && !this->GetGeneratorTarget()->IsFrameworkOnApple()) { std::string cmakeCommand = this->GetLocalGenerator()->ConvertToOutputFormat( @@ -441,7 +456,8 @@ std::vector<std::string> cmNinjaNormalTargetGenerator::ComputeDeviceLinkCmd() return linkCmds; } -std::vector<std::string> cmNinjaNormalTargetGenerator::ComputeLinkCmd() +std::vector<std::string> cmNinjaNormalTargetGenerator::ComputeLinkCmd( + const std::string& config) { std::vector<std::string> linkCmds; cmMakefile* mf = this->GetMakefile(); @@ -450,14 +466,14 @@ std::vector<std::string> cmNinjaNormalTargetGenerator::ComputeLinkCmd() // this occurs when things like IPO is enabled, and we need to use the // CMAKE_<lang>_CREATE_STATIC_LIBRARY_IPO define instead. std::string linkCmdVar = this->GetGeneratorTarget()->GetCreateRuleVariable( - this->TargetLinkLanguage, this->GetConfigName()); + this->TargetLinkLanguage(config), config); const char* linkCmd = mf->GetDefinition(linkCmdVar); if (linkCmd) { std::string linkCmdStr = linkCmd; - if (this->GetGeneratorTarget()->HasImplibGNUtoMS(this->ConfigName)) { - std::string ruleVar = cmStrCat( - "CMAKE_", this->GeneratorTarget->GetLinkerLanguage(this->ConfigName), - "_GNUtoMS_RULE"); + if (this->GetGeneratorTarget()->HasImplibGNUtoMS(config)) { + std::string ruleVar = + cmStrCat("CMAKE_", this->GeneratorTarget->GetLinkerLanguage(config), + "_GNUtoMS_RULE"); if (const char* rule = this->Makefile->GetDefinition(ruleVar)) { linkCmdStr += rule; } @@ -469,9 +485,8 @@ std::vector<std::string> cmNinjaNormalTargetGenerator::ComputeLinkCmd() cmSystemTools::GetCMakeCommand(), cmLocalGenerator::SHELL), " -E __run_co_compile --lwyu="); cmGeneratorTarget& gt = *this->GetGeneratorTarget(); - const std::string cfgName = this->GetConfigName(); std::string targetOutputReal = this->ConvertToNinjaPath( - gt.GetFullPath(cfgName, cmStateEnums::RuntimeBinaryArtifact, + gt.GetFullPath(config, cmStateEnums::RuntimeBinaryArtifact, /*realname=*/true)); cmakeCommand += targetOutputReal; linkCmds.push_back(std::move(cmakeCommand)); @@ -486,25 +501,25 @@ std::vector<std::string> cmNinjaNormalTargetGenerator::ComputeLinkCmd() std::string cmakeCommand = this->GetLocalGenerator()->ConvertToOutputFormat( cmSystemTools::GetCMakeCommand(), cmOutputConverter::SHELL); - linkCmds.push_back(cmakeCommand + " -E remove $TARGET_FILE"); + linkCmds.push_back(cmakeCommand + " -E rm -f $TARGET_FILE"); } // TODO: Use ARCHIVE_APPEND for archives over a certain size. { - std::string linkCmdVar = - cmStrCat("CMAKE_", this->TargetLinkLanguage, "_ARCHIVE_CREATE"); + std::string linkCmdVar = cmStrCat( + "CMAKE_", this->TargetLinkLanguage(config), "_ARCHIVE_CREATE"); linkCmdVar = this->GeneratorTarget->GetFeatureSpecificLinkRuleVariable( - linkCmdVar, this->TargetLinkLanguage, this->GetConfigName()); + linkCmdVar, this->TargetLinkLanguage(config), config); std::string const& linkCmd = mf->GetRequiredDefinition(linkCmdVar); cmExpandList(linkCmd, linkCmds); } { - std::string linkCmdVar = - cmStrCat("CMAKE_", this->TargetLinkLanguage, "_ARCHIVE_FINISH"); + std::string linkCmdVar = cmStrCat( + "CMAKE_", this->TargetLinkLanguage(config), "_ARCHIVE_FINISH"); linkCmdVar = this->GeneratorTarget->GetFeatureSpecificLinkRuleVariable( - linkCmdVar, this->TargetLinkLanguage, this->GetConfigName()); + linkCmdVar, this->TargetLinkLanguage(config), config); std::string const& linkCmd = mf->GetRequiredDefinition(linkCmdVar); cmExpandList(linkCmd, linkCmds); @@ -535,7 +550,8 @@ std::vector<std::string> cmNinjaNormalTargetGenerator::ComputeLinkCmd() return std::vector<std::string>(); } -void cmNinjaNormalTargetGenerator::WriteDeviceLinkStatement() +void cmNinjaNormalTargetGenerator::WriteDeviceLinkStatement( + const std::string& config) { cmGlobalNinjaGenerator* globalGen = this->GetGlobalGenerator(); if (!globalGen->GetLanguageEnabled("CUDA")) { @@ -545,7 +561,7 @@ void cmNinjaNormalTargetGenerator::WriteDeviceLinkStatement() cmGeneratorTarget* genTarget = this->GetGeneratorTarget(); bool requiresDeviceLinking = requireDeviceLinking( - *this->GeneratorTarget, *this->GetLocalGenerator(), this->ConfigName); + *this->GeneratorTarget, *this->GetLocalGenerator(), config); if (!requiresDeviceLinking) { return; } @@ -558,24 +574,23 @@ void cmNinjaNormalTargetGenerator::WriteDeviceLinkStatement() std::string const& objExt = this->Makefile->GetSafeDefinition("CMAKE_CUDA_OUTPUT_EXTENSION"); - std::string const cfgName = this->GetConfigName(); std::string const targetOutputReal = ConvertToNinjaPath( genTarget->ObjectDirectory + "cmake_device_link" + objExt); std::string const targetOutputImplib = ConvertToNinjaPath( - genTarget->GetFullPath(cfgName, cmStateEnums::ImportLibraryArtifact)); + genTarget->GetFullPath(config, cmStateEnums::ImportLibraryArtifact)); this->DeviceLinkObject = targetOutputReal; // Write comments. - cmGlobalNinjaGenerator::WriteDivider(this->GetBuildFileStream()); + cmGlobalNinjaGenerator::WriteDivider(this->GetCommonFileStream()); const cmStateEnums::TargetType targetType = genTarget->GetType(); - this->GetBuildFileStream() << "# Device Link build statements for " - << cmState::GetTargetTypeName(targetType) - << " target " << this->GetTargetName() << "\n\n"; + this->GetCommonFileStream() << "# Device Link build statements for " + << cmState::GetTargetTypeName(targetType) + << " target " << this->GetTargetName() << "\n\n"; // Compute the comment. - cmNinjaBuild build(this->LanguageLinkerDeviceRule()); + cmNinjaBuild build(this->LanguageLinkerDeviceRule(config)); build.Comment = cmStrCat("Link the ", this->GetVisibleTypeName(), ' ', targetOutputReal); @@ -584,14 +599,15 @@ void cmNinjaNormalTargetGenerator::WriteDeviceLinkStatement() // Compute outputs. build.Outputs.push_back(targetOutputReal); // Compute specific libraries to link with. - build.ExplicitDeps = this->GetObjects(); - build.ImplicitDeps = this->ComputeLinkDeps(this->TargetLinkLanguage); + build.ExplicitDeps = this->GetObjects(config); + build.ImplicitDeps = + this->ComputeLinkDeps(this->TargetLinkLanguage(config), config); std::string frameworkPath; std::string linkPath; - std::string createRule = genTarget->GetCreateRuleVariable( - this->TargetLinkLanguage, this->GetConfigName()); + std::string createRule = + genTarget->GetCreateRuleVariable(this->TargetLinkLanguage(config), config); const bool useWatcomQuote = this->GetMakefile()->IsOn(createRule + "_USE_WATCOM_QUOTE"); cmLocalNinjaGenerator& localGen = *this->GetLocalGenerator(); @@ -605,17 +621,17 @@ void cmNinjaNormalTargetGenerator::WriteDeviceLinkStatement() this->GetLocalGenerator()->GetStateSnapshot().GetDirectory(), globalGen)); linkLineComputer->SetUseWatcomQuote(useWatcomQuote); + linkLineComputer->SetUseNinjaMulti(globalGen->IsMultiConfig()); localGen.GetTargetFlags( - linkLineComputer.get(), this->GetConfigName(), vars["LINK_LIBRARIES"], - vars["FLAGS"], vars["LINK_FLAGS"], frameworkPath, linkPath, genTarget); + linkLineComputer.get(), config, vars["LINK_LIBRARIES"], vars["FLAGS"], + vars["LINK_FLAGS"], frameworkPath, linkPath, genTarget); this->addPoolNinjaVariable("JOB_POOL_LINK", genTarget, vars); - vars["LINK_FLAGS"] = - cmGlobalNinjaGenerator::EncodeLiteral(vars["LINK_FLAGS"]); + vars["LINK_FLAGS"] = globalGen->EncodeLiteral(vars["LINK_FLAGS"]); - vars["MANIFESTS"] = this->GetManifests(); + vars["MANIFESTS"] = this->GetManifests(config); vars["LINK_PATH"] = frameworkPath + linkPath; @@ -624,24 +640,25 @@ void cmNinjaNormalTargetGenerator::WriteDeviceLinkStatement() // code between the Makefile executable and library generators. if (targetType == cmStateEnums::EXECUTABLE) { std::string t = vars["FLAGS"]; - localGen.AddArchitectureFlags(t, genTarget, cudaLinkLanguage, cfgName); + localGen.AddArchitectureFlags(t, genTarget, cudaLinkLanguage, config); vars["FLAGS"] = t; } else { std::string t = vars["ARCH_FLAGS"]; - localGen.AddArchitectureFlags(t, genTarget, cudaLinkLanguage, cfgName); + localGen.AddArchitectureFlags(t, genTarget, cudaLinkLanguage, config); vars["ARCH_FLAGS"] = t; t.clear(); localGen.AddLanguageFlagsForLinking(t, genTarget, cudaLinkLanguage, - cfgName); + config); vars["LANGUAGE_COMPILE_FLAGS"] = t; } - if (genTarget->HasSOName(cfgName)) { + auto const tgtNames = this->TargetNames(config); + if (genTarget->HasSOName(config)) { vars["SONAME_FLAG"] = - this->GetMakefile()->GetSONameFlag(this->TargetLinkLanguage); - vars["SONAME"] = this->TargetNames.SharedObject; + this->GetMakefile()->GetSONameFlag(this->TargetLinkLanguage(config)); + vars["SONAME"] = tgtNames.SharedObject; if (targetType == cmStateEnums::SHARED_LIBRARY) { std::string install_dir = - this->GetGeneratorTarget()->GetInstallNameDirForBuildTree(cfgName); + this->GetGeneratorTarget()->GetInstallNameDirForBuildTree(config); if (!install_dir.empty()) { vars["INSTALLNAME_DIR"] = localGen.ConvertToOutputFormat( install_dir, cmOutputConverter::SHELL); @@ -649,25 +666,28 @@ void cmNinjaNormalTargetGenerator::WriteDeviceLinkStatement() } } - if (!this->TargetNames.ImportLibrary.empty()) { + if (!tgtNames.ImportLibrary.empty()) { const std::string impLibPath = localGen.ConvertToOutputFormat( targetOutputImplib, cmOutputConverter::SHELL); vars["TARGET_IMPLIB"] = impLibPath; EnsureParentDirectoryExists(impLibPath); } - const std::string objPath = GetGeneratorTarget()->GetSupportDirectory(); + const std::string objPath = + cmStrCat(GetGeneratorTarget()->GetSupportDirectory(), + globalGen->ConfigDirectory(config)); + vars["OBJECT_DIR"] = this->GetLocalGenerator()->ConvertToOutputFormat( this->ConvertToNinjaPath(objPath), cmOutputConverter::SHELL); EnsureDirectoryExists(objPath); - this->SetMsvcTargetPdbVariable(vars); + this->SetMsvcTargetPdbVariable(vars, config); + std::string& linkLibraries = vars["LINK_LIBRARIES"]; + std::string& link_path = vars["LINK_PATH"]; if (globalGen->IsGCCOnWindows()) { // ar.exe can't handle backslashes in rsp files (implicitly used by gcc) - std::string& linkLibraries = vars["LINK_LIBRARIES"]; std::replace(linkLibraries.begin(), linkLibraries.end(), '\\', '/'); - std::string& link_path = vars["LINK_PATH"]; std::replace(link_path.begin(), link_path.end(), '\\', '/'); } @@ -675,65 +695,88 @@ void cmNinjaNormalTargetGenerator::WriteDeviceLinkStatement() // do not check if the user has explicitly forced a response file. int const commandLineLengthLimit = static_cast<int>(cmSystemTools::CalculateCommandLineLengthLimit()) - - globalGen->GetRuleCmdLength(this->LanguageLinkerDeviceRule()); + globalGen->GetRuleCmdLength(this->LanguageLinkerDeviceRule(config)); build.RspFile = this->ConvertToNinjaPath(std::string("CMakeFiles/") + genTarget->GetName() + ".rsp"); // Gather order-only dependencies. - this->GetLocalGenerator()->AppendTargetDepends(this->GetGeneratorTarget(), - build.OrderOnlyDeps); + this->GetLocalGenerator()->AppendTargetDepends( + this->GetGeneratorTarget(), build.OrderOnlyDeps, config, config); // Write the build statement for this target. bool usedResponseFile = false; - globalGen->WriteBuild(this->GetBuildFileStream(), build, + globalGen->WriteBuild(this->GetCommonFileStream(), build, commandLineLengthLimit, &usedResponseFile); - this->WriteDeviceLinkRule(usedResponseFile); + this->WriteDeviceLinkRule(usedResponseFile, config); } -void cmNinjaNormalTargetGenerator::WriteLinkStatement() +void cmNinjaNormalTargetGenerator::WriteLinkStatement( + const std::string& config, const std::string& fileConfig, + bool firstForConfig) { cmMakefile* mf = this->GetMakefile(); cmGlobalNinjaGenerator* globalGen = this->GetGlobalGenerator(); cmGeneratorTarget* gt = this->GetGeneratorTarget(); - const std::string cfgName = this->GetConfigName(); - std::string targetOutput = ConvertToNinjaPath(gt->GetFullPath(cfgName)); + std::string targetOutput = ConvertToNinjaPath(gt->GetFullPath(config)); std::string targetOutputReal = ConvertToNinjaPath( - gt->GetFullPath(cfgName, cmStateEnums::RuntimeBinaryArtifact, + gt->GetFullPath(config, cmStateEnums::RuntimeBinaryArtifact, /*realname=*/true)); std::string targetOutputImplib = ConvertToNinjaPath( - gt->GetFullPath(cfgName, cmStateEnums::ImportLibraryArtifact)); + gt->GetFullPath(config, cmStateEnums::ImportLibraryArtifact)); + if (config != fileConfig) { + if (targetOutput == ConvertToNinjaPath(gt->GetFullPath(fileConfig))) { + return; + } + if (targetOutputReal == + ConvertToNinjaPath(gt->GetFullPath(fileConfig, + cmStateEnums::RuntimeBinaryArtifact, + /*realname=*/true))) { + return; + } + if (!gt->GetFullName(config, cmStateEnums::ImportLibraryArtifact) + .empty() && + !gt->GetFullName(fileConfig, cmStateEnums::ImportLibraryArtifact) + .empty() && + targetOutputImplib == + ConvertToNinjaPath(gt->GetFullPath( + fileConfig, cmStateEnums::ImportLibraryArtifact))) { + return; + } + } + + auto const tgtNames = this->TargetNames(config); if (gt->IsAppBundleOnApple()) { // Create the app bundle - std::string outpath = gt->GetDirectory(cfgName); - this->OSXBundleGenerator->CreateAppBundle(this->TargetNames.Output, - outpath); + std::string outpath = gt->GetDirectory(config); + this->OSXBundleGenerator->CreateAppBundle(tgtNames.Output, outpath, + config); // Calculate the output path - targetOutput = cmStrCat(outpath, '/', this->TargetNames.Output); + targetOutput = cmStrCat(outpath, '/', tgtNames.Output); targetOutput = this->ConvertToNinjaPath(targetOutput); - targetOutputReal = cmStrCat(outpath, '/', this->TargetNames.Real); + targetOutputReal = cmStrCat(outpath, '/', tgtNames.Real); targetOutputReal = this->ConvertToNinjaPath(targetOutputReal); } else if (gt->IsFrameworkOnApple()) { // Create the library framework. - this->OSXBundleGenerator->CreateFramework(this->TargetNames.Output, - gt->GetDirectory(cfgName)); + this->OSXBundleGenerator->CreateFramework( + tgtNames.Output, gt->GetDirectory(config), config); } else if (gt->IsCFBundleOnApple()) { // Create the core foundation bundle. - this->OSXBundleGenerator->CreateCFBundle(this->TargetNames.Output, - gt->GetDirectory(cfgName)); + this->OSXBundleGenerator->CreateCFBundle(tgtNames.Output, + gt->GetDirectory(config), config); } // Write comments. - cmGlobalNinjaGenerator::WriteDivider(this->GetBuildFileStream()); + cmGlobalNinjaGenerator::WriteDivider(this->GetConfigFileStream(fileConfig)); const cmStateEnums::TargetType targetType = gt->GetType(); - this->GetBuildFileStream() + this->GetConfigFileStream(fileConfig) << "# Link build statements for " << cmState::GetTargetTypeName(targetType) << " target " << this->GetTargetName() << "\n\n"; - cmNinjaBuild linkBuild(this->LanguageLinkerRule()); + cmNinjaBuild linkBuild(this->LanguageLinkerRule(config)); cmNinjaVars& vars = linkBuild.Variables; // Compute the comment. @@ -742,11 +785,14 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement() // Compute outputs. linkBuild.Outputs.push_back(targetOutputReal); + if (firstForConfig) { + globalGen->GetByproductsForCleanTarget(config).push_back(targetOutputReal); + } - if (this->TargetLinkLanguage == "Swift") { - vars["SWIFT_LIBRARY_NAME"] = [this]() -> std::string { + if (this->TargetLinkLanguage(config) == "Swift") { + vars["SWIFT_LIBRARY_NAME"] = [this, config]() -> std::string { cmGeneratorTarget::Names targetNames = - this->GetGeneratorTarget()->GetLibraryNames(this->GetConfigName()); + this->GetGeneratorTarget()->GetLibraryNames(config); return targetNames.Base; }(); @@ -782,12 +828,11 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement() "/output-file-map.json"), cmOutputConverter::SHELL); - vars["SWIFT_SOURCES"] = [this]() -> std::string { + vars["SWIFT_SOURCES"] = [this, config]() -> std::string { std::vector<cmSourceFile const*> sources; std::stringstream oss; - this->GetGeneratorTarget()->GetObjectSources(sources, - this->GetConfigName()); + this->GetGeneratorTarget()->GetObjectSources(sources, config); cmLocalGenerator const* LocalGen = this->GetLocalGenerator(); for (const auto& source : sources) { oss << " " @@ -801,27 +846,28 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement() // Since we do not perform object builds, compute the // defines/flags/includes here so that they can be passed along // appropriately. - vars["DEFINES"] = this->GetDefines("Swift"); - vars["FLAGS"] = this->GetFlags("Swift"); - vars["INCLUDES"] = this->GetIncludes("Swift"); + vars["DEFINES"] = this->GetDefines("Swift", config); + vars["FLAGS"] = this->GetFlags("Swift", config); + vars["INCLUDES"] = this->GetIncludes("Swift", config); } // Compute specific libraries to link with. - if (this->TargetLinkLanguage == "Swift") { + if (this->TargetLinkLanguage(config) == "Swift") { std::vector<cmSourceFile const*> sources; - gt->GetObjectSources(sources, this->GetConfigName()); + gt->GetObjectSources(sources, config); for (const auto& source : sources) { linkBuild.Outputs.push_back( - this->ConvertToNinjaPath(this->GetObjectFilePath(source))); + this->ConvertToNinjaPath(this->GetObjectFilePath(source, config))); linkBuild.ExplicitDeps.push_back( this->ConvertToNinjaPath(this->GetSourceFilePath(source))); } linkBuild.Outputs.push_back(vars["SWIFT_MODULE"]); } else { - linkBuild.ExplicitDeps = this->GetObjects(); + linkBuild.ExplicitDeps = this->GetObjects(config); } - linkBuild.ImplicitDeps = this->ComputeLinkDeps(this->TargetLinkLanguage); + linkBuild.ImplicitDeps = + this->ComputeLinkDeps(this->TargetLinkLanguage(config), config); if (!this->DeviceLinkObject.empty()) { linkBuild.ExplicitDeps.push_back(this->DeviceLinkObject); @@ -831,7 +877,7 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement() std::string linkPath; std::string createRule = - gt->GetCreateRuleVariable(this->TargetLinkLanguage, this->GetConfigName()); + gt->GetCreateRuleVariable(this->TargetLinkLanguage(config), config); bool useWatcomQuote = mf->IsOn(createRule + "_USE_WATCOM_QUOTE"); cmLocalNinjaGenerator& localGen = *this->GetLocalGenerator(); @@ -843,27 +889,29 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement() this->GetLocalGenerator(), this->GetLocalGenerator()->GetStateSnapshot().GetDirectory())); linkLineComputer->SetUseWatcomQuote(useWatcomQuote); + linkLineComputer->SetUseNinjaMulti(globalGen->IsMultiConfig()); - localGen.GetTargetFlags(linkLineComputer.get(), this->GetConfigName(), + localGen.GetTargetFlags(linkLineComputer.get(), config, vars["LINK_LIBRARIES"], vars["FLAGS"], vars["LINK_FLAGS"], frameworkPath, linkPath, gt); // Add OS X version flags, if any. if (this->GeneratorTarget->GetType() == cmStateEnums::SHARED_LIBRARY || this->GeneratorTarget->GetType() == cmStateEnums::MODULE_LIBRARY) { - this->AppendOSXVerFlag(vars["LINK_FLAGS"], this->TargetLinkLanguage, - "COMPATIBILITY", true); - this->AppendOSXVerFlag(vars["LINK_FLAGS"], this->TargetLinkLanguage, - "CURRENT", false); + this->AppendOSXVerFlag(vars["LINK_FLAGS"], + this->TargetLinkLanguage(config), "COMPATIBILITY", + true); + this->AppendOSXVerFlag(vars["LINK_FLAGS"], + this->TargetLinkLanguage(config), "CURRENT", false); } this->addPoolNinjaVariable("JOB_POOL_LINK", gt, vars); - this->AddModuleDefinitionFlag(linkLineComputer.get(), vars["LINK_FLAGS"]); - vars["LINK_FLAGS"] = - cmGlobalNinjaGenerator::EncodeLiteral(vars["LINK_FLAGS"]); + this->AddModuleDefinitionFlag(linkLineComputer.get(), vars["LINK_FLAGS"], + config); + vars["LINK_FLAGS"] = globalGen->EncodeLiteral(vars["LINK_FLAGS"]); - vars["MANIFESTS"] = this->GetManifests(); + vars["MANIFESTS"] = this->GetManifests(config); vars["LINK_PATH"] = frameworkPath + linkPath; std::string lwyuFlags; @@ -876,23 +924,26 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement() // code between the Makefile executable and library generators. if (targetType == cmStateEnums::EXECUTABLE) { std::string t = vars["FLAGS"]; - localGen.AddArchitectureFlags(t, gt, TargetLinkLanguage, cfgName); + localGen.AddArchitectureFlags(t, gt, this->TargetLinkLanguage(config), + config); t += lwyuFlags; vars["FLAGS"] = t; } else { std::string t = vars["ARCH_FLAGS"]; - localGen.AddArchitectureFlags(t, gt, TargetLinkLanguage, cfgName); + localGen.AddArchitectureFlags(t, gt, this->TargetLinkLanguage(config), + config); vars["ARCH_FLAGS"] = t; t.clear(); t += lwyuFlags; - localGen.AddLanguageFlagsForLinking(t, gt, TargetLinkLanguage, cfgName); + localGen.AddLanguageFlagsForLinking( + t, gt, this->TargetLinkLanguage(config), config); vars["LANGUAGE_COMPILE_FLAGS"] = t; } - if (gt->HasSOName(cfgName)) { - vars["SONAME_FLAG"] = mf->GetSONameFlag(this->TargetLinkLanguage); - vars["SONAME"] = this->TargetNames.SharedObject; + if (gt->HasSOName(config)) { + vars["SONAME_FLAG"] = mf->GetSONameFlag(this->TargetLinkLanguage(config)); + vars["SONAME"] = tgtNames.SharedObject; if (targetType == cmStateEnums::SHARED_LIBRARY) { - std::string install_dir = gt->GetInstallNameDirForBuildTree(cfgName); + std::string install_dir = gt->GetInstallNameDirForBuildTree(config); if (!install_dir.empty()) { vars["INSTALLNAME_DIR"] = localGen.ConvertToOutputFormat( install_dir, cmOutputConverter::SHELL); @@ -902,17 +953,21 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement() cmNinjaDeps byproducts; - if (!this->TargetNames.ImportLibrary.empty()) { + if (!tgtNames.ImportLibrary.empty()) { const std::string impLibPath = localGen.ConvertToOutputFormat( targetOutputImplib, cmOutputConverter::SHELL); vars["TARGET_IMPLIB"] = impLibPath; EnsureParentDirectoryExists(impLibPath); - if (gt->HasImportLibrary(cfgName)) { + if (gt->HasImportLibrary(config)) { byproducts.push_back(targetOutputImplib); + if (firstForConfig) { + globalGen->GetByproductsForCleanTarget(config).push_back( + targetOutputImplib); + } } } - if (!this->SetMsvcTargetPdbVariable(vars)) { + if (!this->SetMsvcTargetPdbVariable(vars, config)) { // It is common to place debug symbols at a specific place, // so we need a plain target name in the rule available. std::string prefix; @@ -927,16 +982,17 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement() vars["TARGET_PDB"] = base + suffix + dbg_suffix; } - const std::string objPath = gt->GetSupportDirectory(); + const std::string objPath = + cmStrCat(gt->GetSupportDirectory(), globalGen->ConfigDirectory(config)); vars["OBJECT_DIR"] = this->GetLocalGenerator()->ConvertToOutputFormat( this->ConvertToNinjaPath(objPath), cmOutputConverter::SHELL); EnsureDirectoryExists(objPath); + std::string& linkLibraries = vars["LINK_LIBRARIES"]; + std::string& link_path = vars["LINK_PATH"]; if (globalGen->IsGCCOnWindows()) { // ar.exe can't handle backslashes in rsp files (implicitly used by gcc) - std::string& linkLibraries = vars["LINK_LIBRARIES"]; std::replace(linkLibraries.begin(), linkLibraries.end(), '\\', '/'); - std::string& link_path = vars["LINK_PATH"]; std::replace(link_path.begin(), link_path.end(), '\\', '/'); } @@ -947,23 +1003,30 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement() std::vector<std::string> preLinkCmdLines; std::vector<std::string> postBuildCmdLines; - std::vector<std::string>* cmdLineLists[3] = { &preLinkCmdLines, - &preLinkCmdLines, - &postBuildCmdLines }; - - for (unsigned i = 0; i != 3; ++i) { - for (cmCustomCommand const& cc : *cmdLists[i]) { - cmCustomCommandGenerator ccg(cc, cfgName, this->GetLocalGenerator()); - localGen.AppendCustomCommandLines(ccg, *cmdLineLists[i]); - std::vector<std::string> const& ccByproducts = ccg.GetByproducts(); - std::transform(ccByproducts.begin(), ccByproducts.end(), - std::back_inserter(byproducts), MapToNinjaPath()); + + if (config == fileConfig) { + std::vector<std::string>* cmdLineLists[3] = { &preLinkCmdLines, + &preLinkCmdLines, + &postBuildCmdLines }; + + for (unsigned i = 0; i != 3; ++i) { + for (cmCustomCommand const& cc : *cmdLists[i]) { + cmCustomCommandGenerator ccg(cc, config, this->GetLocalGenerator()); + localGen.AppendCustomCommandLines(ccg, *cmdLineLists[i]); + std::vector<std::string> const& ccByproducts = ccg.GetByproducts(); + std::transform(ccByproducts.begin(), ccByproducts.end(), + std::back_inserter(byproducts), MapToNinjaPath()); + std::transform( + ccByproducts.begin(), ccByproducts.end(), + std::back_inserter(globalGen->GetByproductsForCleanTarget()), + MapToNinjaPath()); + } } } // maybe create .def file from list of objects cmGeneratorTarget::ModuleDefinitionInfo const* mdi = - gt->GetModuleDefinitionInfo(this->GetConfigName()); + gt->GetModuleDefinitionInfo(config); if (mdi && mdi->DefFileGenerated) { std::string cmakeCommand = this->GetLocalGenerator()->ConvertToOutputFormat( @@ -989,7 +1052,7 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement() cmGeneratedFileStream fout(obj_list_file); if (mdi->WindowsExportAllSymbols) { - cmNinjaDeps objs = this->GetObjects(); + cmNinjaDeps objs = this->GetObjects(config); for (std::string const& obj : objs) { if (cmHasLiteralSuffix(obj, ".obj")) { fout << obj << "\n"; @@ -1024,7 +1087,8 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement() symlinkVars["POST_BUILD"] = postBuildCmdLine; } - std::string cmakeVarLang = cmStrCat("CMAKE_", this->TargetLinkLanguage); + std::string cmakeVarLang = + cmStrCat("CMAKE_", this->TargetLinkLanguage(config)); // build response file name std::string cmakeLinkVar = cmakeVarLang + "_RESPONSE_FILE_LINK_FLAG"; @@ -1032,8 +1096,8 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement() const char* flag = GetMakefile()->GetDefinition(cmakeLinkVar); bool const lang_supports_response = - !(this->TargetLinkLanguage == "RC" || - (this->TargetLinkLanguage == "CUDA" && !flag)); + !(this->TargetLinkLanguage(config) == "RC" || + (this->TargetLinkLanguage(config) == "CUDA" && !flag)); int commandLineLengthLimit = -1; if (!lang_supports_response || !this->ForceResponseFile()) { commandLineLengthLimit = @@ -1045,18 +1109,19 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement() gt->GetName() + ".rsp"); // Gather order-only dependencies. - this->GetLocalGenerator()->AppendTargetDepends(gt, linkBuild.OrderOnlyDeps); + this->GetLocalGenerator()->AppendTargetDepends(gt, linkBuild.OrderOnlyDeps, + config, fileConfig); // Add order-only dependencies on versioning symlinks of shared libs we link. if (!this->GeneratorTarget->IsDLLPlatform()) { if (cmComputeLinkInformation* cli = - this->GeneratorTarget->GetLinkInformation(this->GetConfigName())) { + this->GeneratorTarget->GetLinkInformation(config)) { for (auto const& item : cli->GetItems()) { if (item.Target && item.Target->GetType() == cmStateEnums::SHARED_LIBRARY && !item.Target->IsFrameworkOnApple()) { - std::string const& lib = this->ConvertToNinjaPath( - item.Target->GetFullPath(this->GetConfigName())); + std::string const& lib = + this->ConvertToNinjaPath(item.Target->GetFullPath(config)); if (std::find(linkBuild.ImplicitDeps.begin(), linkBuild.ImplicitDeps.end(), lib) == linkBuild.ImplicitDeps.end()) { @@ -1077,24 +1142,27 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement() // Write the build statement for this target. bool usedResponseFile = false; - globalGen->WriteBuild(this->GetBuildFileStream(), linkBuild, + globalGen->WriteBuild(this->GetConfigFileStream(fileConfig), linkBuild, commandLineLengthLimit, &usedResponseFile); - this->WriteLinkRule(usedResponseFile); + this->WriteLinkRule(usedResponseFile, config); if (symlinkNeeded) { if (targetType == cmStateEnums::EXECUTABLE) { cmNinjaBuild build("CMAKE_SYMLINK_EXECUTABLE"); build.Comment = "Create executable symlink " + targetOutput; build.Outputs.push_back(targetOutput); + if (firstForConfig) { + globalGen->GetByproductsForCleanTarget(config).push_back(targetOutput); + } build.ExplicitDeps.push_back(targetOutputReal); build.Variables = std::move(symlinkVars); - globalGen->WriteBuild(this->GetBuildFileStream(), build); + globalGen->WriteBuild(this->GetConfigFileStream(fileConfig), build); } else { cmNinjaBuild build("CMAKE_SYMLINK_LIBRARY"); build.Comment = "Create library symlink " + targetOutput; std::string const soName = this->ConvertToNinjaPath( - this->GetTargetFilePath(this->TargetNames.SharedObject)); + this->GetTargetFilePath(tgtNames.SharedObject, config)); // If one link has to be created. if (targetOutputReal == soName || targetOutput == soName) { symlinkVars["SONAME"] = @@ -1103,33 +1171,58 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement() } else { symlinkVars["SONAME"].clear(); build.Outputs.push_back(soName); + if (firstForConfig) { + globalGen->GetByproductsForCleanTarget(config).push_back(soName); + } } build.Outputs.push_back(targetOutput); + if (firstForConfig) { + globalGen->GetByproductsForCleanTarget(config).push_back(targetOutput); + } build.ExplicitDeps.push_back(targetOutputReal); build.Variables = std::move(symlinkVars); - globalGen->WriteBuild(this->GetBuildFileStream(), build); + globalGen->WriteBuild(this->GetConfigFileStream(fileConfig), build); } } // Add aliases for the file name and the target name. - globalGen->AddTargetAlias(this->TargetNames.Output, gt); - globalGen->AddTargetAlias(this->GetTargetName(), gt); + globalGen->AddTargetAlias(tgtNames.Output, gt, config); + globalGen->AddTargetAlias(this->GetTargetName(), gt, config); } -void cmNinjaNormalTargetGenerator::WriteObjectLibStatement() +void cmNinjaNormalTargetGenerator::WriteObjectLibStatement( + const std::string& config) { // Write a phony output that depends on all object files. { cmNinjaBuild build("phony"); build.Comment = "Object library " + this->GetTargetName(); this->GetLocalGenerator()->AppendTargetOutputs(this->GetGeneratorTarget(), - build.Outputs); - build.ExplicitDeps = this->GetObjects(); - this->GetGlobalGenerator()->WriteBuild(this->GetBuildFileStream(), build); + build.Outputs, config); + this->GetLocalGenerator()->AppendTargetOutputs( + this->GetGeneratorTarget(), + this->GetGlobalGenerator()->GetByproductsForCleanTarget(config), config); + build.ExplicitDeps = this->GetObjects(config); + this->GetGlobalGenerator()->WriteBuild(this->GetCommonFileStream(), build); } // Add aliases for the target name. - this->GetGlobalGenerator()->AddTargetAlias(this->GetTargetName(), - this->GetGeneratorTarget()); + this->GetGlobalGenerator()->AddTargetAlias( + this->GetTargetName(), this->GetGeneratorTarget(), config); +} + +cmGeneratorTarget::Names cmNinjaNormalTargetGenerator::TargetNames( + const std::string& config) const +{ + if (this->GeneratorTarget->GetType() == cmStateEnums::EXECUTABLE) { + return this->GeneratorTarget->GetExecutableNames(config); + } + return this->GeneratorTarget->GetLibraryNames(config); +} + +std::string cmNinjaNormalTargetGenerator::TargetLinkLanguage( + const std::string& config) const +{ + return this->GeneratorTarget->GetLinkerLanguage(config); } diff --git a/Source/cmNinjaNormalTargetGenerator.h b/Source/cmNinjaNormalTargetGenerator.h index ebc1268..cda76d8 100644 --- a/Source/cmNinjaNormalTargetGenerator.h +++ b/Source/cmNinjaNormalTargetGenerator.h @@ -17,30 +17,31 @@ public: cmNinjaNormalTargetGenerator(cmGeneratorTarget* target); ~cmNinjaNormalTargetGenerator() override; - void Generate() override; + void Generate(const std::string& config) override; private: - std::string LanguageLinkerRule() const; - std::string LanguageLinkerDeviceRule() const; + std::string LanguageLinkerRule(const std::string& config) const; + std::string LanguageLinkerDeviceRule(const std::string& config) const; const char* GetVisibleTypeName() const; - void WriteLanguagesRules(); + void WriteLanguagesRules(const std::string& config); - void WriteLinkRule(bool useResponseFile); - void WriteDeviceLinkRule(bool useResponseFile); + void WriteLinkRule(bool useResponseFile, const std::string& config); + void WriteDeviceLinkRule(bool useResponseFile, const std::string& config); - void WriteLinkStatement(); - void WriteDeviceLinkStatement(); + void WriteLinkStatement(const std::string& config, + const std::string& fileConfig, bool firstForConfig); + void WriteDeviceLinkStatement(const std::string& config); - void WriteObjectLibStatement(); + void WriteObjectLibStatement(const std::string& config); - std::vector<std::string> ComputeLinkCmd(); + std::vector<std::string> ComputeLinkCmd(const std::string& config); std::vector<std::string> ComputeDeviceLinkCmd(); private: // Target name info. - cmGeneratorTarget::Names TargetNames; - std::string TargetLinkLanguage; + cmGeneratorTarget::Names TargetNames(const std::string& config) const; + std::string TargetLinkLanguage(const std::string& config) const; std::string DeviceLinkObject; }; diff --git a/Source/cmNinjaTargetGenerator.cxx b/Source/cmNinjaTargetGenerator.cxx index 919a5db..3f1dbe8 100644 --- a/Source/cmNinjaTargetGenerator.cxx +++ b/Source/cmNinjaTargetGenerator.cxx @@ -10,11 +10,11 @@ #include <utility> #include <cm/memory> +#include <cmext/algorithm> #include "cm_jsoncpp_value.h" #include "cm_jsoncpp_writer.h" -#include "cmAlgorithms.h" #include "cmComputeLinkInformation.h" #include "cmCustomCommandGenerator.h" #include "cmGeneratedFileStream.h" @@ -68,9 +68,15 @@ cmNinjaTargetGenerator::cmNinjaTargetGenerator(cmGeneratorTarget* target) cmNinjaTargetGenerator::~cmNinjaTargetGenerator() = default; -cmGeneratedFileStream& cmNinjaTargetGenerator::GetBuildFileStream() const +cmGeneratedFileStream& cmNinjaTargetGenerator::GetConfigFileStream( + const std::string& config) const { - return *this->GetGlobalGenerator()->GetBuildFileStream(); + return *this->GetGlobalGenerator()->GetConfigFileStream(config); +} + +cmGeneratedFileStream& cmNinjaTargetGenerator::GetCommonFileStream() const +{ + return *this->GetGlobalGenerator()->GetCommonFileStream(); } cmGeneratedFileStream& cmNinjaTargetGenerator::GetRulesFileStream() const @@ -84,17 +90,19 @@ cmGlobalNinjaGenerator* cmNinjaTargetGenerator::GetGlobalGenerator() const } std::string cmNinjaTargetGenerator::LanguageCompilerRule( - const std::string& lang) const + const std::string& lang, const std::string& config) const { return lang + "_COMPILER__" + - cmGlobalNinjaGenerator::EncodeRuleName(this->GeneratorTarget->GetName()); + cmGlobalNinjaGenerator::EncodeRuleName(this->GeneratorTarget->GetName()) + + "_" + config; } std::string cmNinjaTargetGenerator::LanguagePreprocessRule( - std::string const& lang) const + std::string const& lang, const std::string& config) const { return lang + "_PREPROCESS__" + - cmGlobalNinjaGenerator::EncodeRuleName(this->GeneratorTarget->GetName()); + cmGlobalNinjaGenerator::EncodeRuleName(this->GeneratorTarget->GetName()) + + "_" + config; } bool cmNinjaTargetGenerator::NeedExplicitPreprocessing( @@ -117,10 +125,11 @@ bool cmNinjaTargetGenerator::CompilePreprocessedSourceWithDefines( } std::string cmNinjaTargetGenerator::LanguageDyndepRule( - const std::string& lang) const + const std::string& lang, const std::string& config) const { return lang + "_DYNDEP__" + - cmGlobalNinjaGenerator::EncodeRuleName(this->GeneratorTarget->GetName()); + cmGlobalNinjaGenerator::EncodeRuleName(this->GeneratorTarget->GetName()) + + "_" + config; } bool cmNinjaTargetGenerator::NeedDyndep(std::string const& lang) const @@ -128,9 +137,11 @@ bool cmNinjaTargetGenerator::NeedDyndep(std::string const& lang) const return lang == "Fortran"; } -std::string cmNinjaTargetGenerator::OrderDependsTargetForTarget() +std::string cmNinjaTargetGenerator::OrderDependsTargetForTarget( + const std::string& config) { - return "cmake_object_order_depends_target_" + this->GetTargetName(); + return cmGlobalNinjaGenerator::OrderDependsTargetForTarget( + this->GeneratorTarget, config); } // TODO: Most of the code is picked up from @@ -138,10 +149,10 @@ std::string cmNinjaTargetGenerator::OrderDependsTargetForTarget() // void cmMakefileTargetGenerator::WriteTargetLanguageFlags() // Refactor it. std::string cmNinjaTargetGenerator::ComputeFlagsForObject( - cmSourceFile const* source, const std::string& language) + cmSourceFile const* source, const std::string& language, + const std::string& config) { - std::string flags = this->GetFlags(language); - const std::string configName = this->LocalGenerator->GetConfigName(); + std::string flags = this->GetFlags(language, config); // Add Fortran format flags. if (language == "Fortran") { @@ -150,7 +161,7 @@ std::string cmNinjaTargetGenerator::ComputeFlagsForObject( // Add source file specific flags. cmGeneratorExpressionInterpreter genexInterpreter( - this->LocalGenerator, configName, this->GeneratorTarget, language); + this->LocalGenerator, config, this->GeneratorTarget, language); const std::string COMPILE_FLAGS("COMPILE_FLAGS"); if (const char* cflags = source->GetProperty(COMPILE_FLAGS)) { @@ -166,16 +177,16 @@ std::string cmNinjaTargetGenerator::ComputeFlagsForObject( // Add precompile headers compile options. const std::string pchSource = - this->GeneratorTarget->GetPchSource(configName, language); + this->GeneratorTarget->GetPchSource(config, language); if (!pchSource.empty() && !source->GetProperty("SKIP_PRECOMPILE_HEADERS")) { std::string pchOptions; if (source->GetFullPath() == pchSource) { - pchOptions = this->GeneratorTarget->GetPchCreateCompileOptions( - configName, language); + pchOptions = + this->GeneratorTarget->GetPchCreateCompileOptions(config, language); } else { pchOptions = - this->GeneratorTarget->GetPchUseCompileOptions(configName, language); + this->GeneratorTarget->GetPchUseCompileOptions(config, language); } this->LocalGenerator->AppendCompileOptions( @@ -186,16 +197,17 @@ std::string cmNinjaTargetGenerator::ComputeFlagsForObject( } void cmNinjaTargetGenerator::AddIncludeFlags(std::string& languageFlags, - std::string const& language) + std::string const& language, + const std::string& config) { std::vector<std::string> includes; this->LocalGenerator->GetIncludeDirectories(includes, this->GeneratorTarget, - language, this->GetConfigName()); + language, config); // Add include directory flags. std::string includeFlags = this->LocalGenerator->GetIncludeFlags( includes, this->GeneratorTarget, language, language == "RC", // full include paths for RC needed by cmcldeps - false, this->GetConfigName()); + false, config); if (this->GetGlobalGenerator()->IsGCCOnWindows()) { std::replace(includeFlags.begin(), includeFlags.end(), '\\', '/'); } @@ -232,13 +244,18 @@ bool cmNinjaTargetGenerator::NeedDepTypeMSVC(const std::string& lang) const // TODO: Refactor with // void cmMakefileTargetGenerator::WriteTargetLanguageFlags(). std::string cmNinjaTargetGenerator::ComputeDefines(cmSourceFile const* source, - const std::string& language) + const std::string& language, + const std::string& config) { std::set<std::string> defines; - const std::string config = this->LocalGenerator->GetConfigName(); cmGeneratorExpressionInterpreter genexInterpreter( this->LocalGenerator, config, this->GeneratorTarget, language); + // Seriously?? + if (this->GetGlobalGenerator()->IsMultiConfig()) { + defines.insert(cmStrCat("CMAKE_INTDIR=\"", config, '"')); + } + const std::string COMPILE_DEFINITIONS("COMPILE_DEFINITIONS"); if (const char* compile_defs = source->GetProperty(COMPILE_DEFINITIONS)) { this->LocalGenerator->AppendDefines( @@ -253,17 +270,17 @@ std::string cmNinjaTargetGenerator::ComputeDefines(cmSourceFile const* source, genexInterpreter.Evaluate(config_compile_defs, COMPILE_DEFINITIONS)); } - std::string definesString = this->GetDefines(language); + std::string definesString = this->GetDefines(language, config); this->LocalGenerator->JoinDefines(defines, definesString, language); return definesString; } std::string cmNinjaTargetGenerator::ComputeIncludes( - cmSourceFile const* source, const std::string& language) + cmSourceFile const* source, const std::string& language, + const std::string& config) { std::vector<std::string> includes; - const std::string config = this->LocalGenerator->GetConfigName(); cmGeneratorExpressionInterpreter genexInterpreter( this->LocalGenerator, config, this->GeneratorTarget, language); @@ -277,13 +294,13 @@ std::string cmNinjaTargetGenerator::ComputeIncludes( std::string includesString = this->LocalGenerator->GetIncludeFlags( includes, this->GeneratorTarget, language, true, false, config); this->LocalGenerator->AppendFlags(includesString, - this->GetIncludes(language)); + this->GetIncludes(language, config)); return includesString; } cmNinjaDeps cmNinjaTargetGenerator::ComputeLinkDeps( - const std::string& linkLanguage) const + const std::string& linkLanguage, const std::string& config) const { // Static libraries never depend on other targets for linking. if (this->GeneratorTarget->GetType() == cmStateEnums::STATIC_LIBRARY || @@ -292,7 +309,7 @@ cmNinjaDeps cmNinjaTargetGenerator::ComputeLinkDeps( } cmComputeLinkInformation* cli = - this->GeneratorTarget->GetLinkInformation(this->GetConfigName()); + this->GeneratorTarget->GetLinkInformation(config); if (!cli) { return cmNinjaDeps(); } @@ -303,8 +320,7 @@ cmNinjaDeps cmNinjaTargetGenerator::ComputeLinkDeps( // Add a dependency on the link definitions file, if any. if (cmGeneratorTarget::ModuleDefinitionInfo const* mdi = - this->GeneratorTarget->GetModuleDefinitionInfo( - this->GetConfigName())) { + this->GeneratorTarget->GetModuleDefinitionInfo(config)) { for (cmSourceFile const* src : mdi->Sources) { result.push_back(this->ConvertToNinjaPath(src->GetFullPath())); } @@ -312,15 +328,14 @@ cmNinjaDeps cmNinjaTargetGenerator::ComputeLinkDeps( // Add a dependency on user-specified manifest files, if any. std::vector<cmSourceFile const*> manifest_srcs; - this->GeneratorTarget->GetManifests(manifest_srcs, this->ConfigName); + this->GeneratorTarget->GetManifests(manifest_srcs, config); for (cmSourceFile const* manifest_src : manifest_srcs) { result.push_back(this->ConvertToNinjaPath(manifest_src->GetFullPath())); } // Add user-specified dependencies. std::vector<std::string> linkDeps; - this->GeneratorTarget->GetLinkDepends(linkDeps, this->ConfigName, - linkLanguage); + this->GeneratorTarget->GetLinkDepends(linkDeps, config, linkLanguage); std::transform(linkDeps.begin(), linkDeps.end(), std::back_inserter(result), MapToNinjaPath()); @@ -334,7 +349,7 @@ std::string cmNinjaTargetGenerator::GetSourceFilePath( } std::string cmNinjaTargetGenerator::GetObjectFilePath( - cmSourceFile const* source) const + cmSourceFile const* source, const std::string& config) const { std::string path = this->LocalGenerator->GetHomeRelativeOutputPath(); if (!path.empty()) { @@ -342,13 +357,14 @@ std::string cmNinjaTargetGenerator::GetObjectFilePath( } std::string const& objectName = this->GeneratorTarget->GetObjectName(source); path += this->LocalGenerator->GetTargetDirectory(this->GeneratorTarget); + path += this->GetGlobalGenerator()->ConfigDirectory(config); path += "/"; path += objectName; return path; } std::string cmNinjaTargetGenerator::GetPreprocessedFilePath( - cmSourceFile const* source) const + cmSourceFile const* source, const std::string& config) const { // Choose an extension to compile already-preprocessed source. std::string ppExt = source->GetExtension(); @@ -378,19 +394,21 @@ std::string cmNinjaTargetGenerator::GetPreprocessedFilePath( path += "/"; } path += this->LocalGenerator->GetTargetDirectory(this->GeneratorTarget); + path += this->GetGlobalGenerator()->ConfigDirectory(config); path += "/"; path += ppName; return path; } std::string cmNinjaTargetGenerator::GetDyndepFilePath( - std::string const& lang) const + std::string const& lang, const std::string& config) const { std::string path = this->LocalGenerator->GetHomeRelativeOutputPath(); if (!path.empty()) { path += "/"; } path += this->LocalGenerator->GetTargetDirectory(this->GeneratorTarget); + path += this->GetGlobalGenerator()->ConfigDirectory(config); path += "/"; path += lang; path += ".dd"; @@ -398,25 +416,27 @@ std::string cmNinjaTargetGenerator::GetDyndepFilePath( } std::string cmNinjaTargetGenerator::GetTargetDependInfoPath( - std::string const& lang) const + std::string const& lang, const std::string& config) const { std::string path = cmStrCat(this->Makefile->GetCurrentBinaryDirectory(), '/', this->LocalGenerator->GetTargetDirectory(this->GeneratorTarget), - '/', lang, "DependInfo.json"); + this->GetGlobalGenerator()->ConfigDirectory(config), '/', lang, + "DependInfo.json"); return path; } -std::string cmNinjaTargetGenerator::GetTargetOutputDir() const +std::string cmNinjaTargetGenerator::GetTargetOutputDir( + const std::string& config) const { - std::string dir = this->GeneratorTarget->GetDirectory(this->GetConfigName()); + std::string dir = this->GeneratorTarget->GetDirectory(config); return ConvertToNinjaPath(dir); } std::string cmNinjaTargetGenerator::GetTargetFilePath( - const std::string& name) const + const std::string& name, const std::string& config) const { - std::string path = this->GetTargetOutputDir(); + std::string path = this->GetTargetOutputDir(config); if (path.empty() || path == ".") { return name; } @@ -430,21 +450,21 @@ std::string cmNinjaTargetGenerator::GetTargetName() const return this->GeneratorTarget->GetName(); } -bool cmNinjaTargetGenerator::SetMsvcTargetPdbVariable(cmNinjaVars& vars) const +bool cmNinjaTargetGenerator::SetMsvcTargetPdbVariable( + cmNinjaVars& vars, const std::string& config) const { cmMakefile* mf = this->GetMakefile(); if (mf->GetDefinition("MSVC_C_ARCHITECTURE_ID") || mf->GetDefinition("MSVC_CXX_ARCHITECTURE_ID") || mf->GetDefinition("MSVC_CUDA_ARCHITECTURE_ID")) { std::string pdbPath; - std::string compilePdbPath = this->ComputeTargetCompilePDB(); + std::string compilePdbPath = this->ComputeTargetCompilePDB(config); if (this->GeneratorTarget->GetType() == cmStateEnums::EXECUTABLE || this->GeneratorTarget->GetType() == cmStateEnums::STATIC_LIBRARY || this->GeneratorTarget->GetType() == cmStateEnums::SHARED_LIBRARY || this->GeneratorTarget->GetType() == cmStateEnums::MODULE_LIBRARY) { - pdbPath = cmStrCat( - this->GeneratorTarget->GetPDBDirectory(this->GetConfigName()), '/', - this->GeneratorTarget->GetPDBName(this->GetConfigName())); + pdbPath = cmStrCat(this->GeneratorTarget->GetPDBDirectory(config), '/', + this->GeneratorTarget->GetPDBName(config)); } vars["TARGET_PDB"] = this->GetLocalGenerator()->ConvertToOutputFormat( @@ -460,15 +480,17 @@ bool cmNinjaTargetGenerator::SetMsvcTargetPdbVariable(cmNinjaVars& vars) const return false; } -void cmNinjaTargetGenerator::WriteLanguageRules(const std::string& language) +void cmNinjaTargetGenerator::WriteLanguageRules(const std::string& language, + const std::string& config) { #ifdef NINJA_GEN_VERBOSE_FILES this->GetRulesFileStream() << "# Rules for language " << language << "\n\n"; #endif - this->WriteCompileRule(language); + this->WriteCompileRule(language, config); } -void cmNinjaTargetGenerator::WriteCompileRule(const std::string& lang) +void cmNinjaTargetGenerator::WriteCompileRule(const std::string& lang, + const std::string& config) { cmRulePlaceholderExpander::RuleVariables vars; vars.CMTargetName = this->GetGeneratorTarget()->GetName().c_str(); @@ -509,7 +531,7 @@ void cmNinjaTargetGenerator::WriteCompileRule(const std::string& lang) this->GetLocalGenerator()->CreateRulePlaceholderExpander()); std::string const tdi = this->GetLocalGenerator()->ConvertToOutputFormat( - ConvertToNinjaPath(this->GetTargetDependInfoPath(lang)), + ConvertToNinjaPath(this->GetTargetDependInfoPath(lang, config)), cmLocalGenerator::SHELL); std::string launcher; @@ -524,7 +546,7 @@ void cmNinjaTargetGenerator::WriteCompileRule(const std::string& lang) cmSystemTools::GetCMakeCommand(), cmLocalGenerator::SHELL); if (explicitPP) { - cmNinjaRule rule(this->LanguagePreprocessRule(lang)); + cmNinjaRule rule(this->LanguagePreprocessRule(lang, config)); // Explicit preprocessing always uses a depfile. rule.DepType = ""; // no deps= for multiple outputs rule.DepFile = "$DEP_FILE"; @@ -604,7 +626,7 @@ void cmNinjaTargetGenerator::WriteCompileRule(const std::string& lang) if (needDyndep) { // Write the rule for ninja dyndep file generation. - cmNinjaRule rule(this->LanguageDyndepRule(lang)); + cmNinjaRule rule(this->LanguageDyndepRule(lang, config)); // Command line length is almost always limited -> use response file for // dyndep rules rule.RspFile = "$out.rsp"; @@ -628,7 +650,7 @@ void cmNinjaTargetGenerator::WriteCompileRule(const std::string& lang) this->GetGlobalGenerator()->AddRule(rule); } - cmNinjaRule rule(this->LanguageCompilerRule(lang)); + cmNinjaRule rule(this->LanguageCompilerRule(lang, config)); // If using a response file, move defines, includes, and flags into it. if (!responseFlag.empty()) { rule.RspFile = "$RSP_FILE"; @@ -787,50 +809,52 @@ void cmNinjaTargetGenerator::WriteCompileRule(const std::string& lang) this->GetGlobalGenerator()->AddRule(rule); } -void cmNinjaTargetGenerator::WriteObjectBuildStatements() +void cmNinjaTargetGenerator::WriteObjectBuildStatements( + const std::string& config, const std::string& fileConfig, + bool firstForConfig) { // Write comments. - cmGlobalNinjaGenerator::WriteDivider(this->GetBuildFileStream()); - this->GetBuildFileStream() + cmGlobalNinjaGenerator::WriteDivider(this->GetConfigFileStream(fileConfig)); + this->GetConfigFileStream(fileConfig) << "# Object build statements for " << cmState::GetTargetTypeName(this->GetGeneratorTarget()->GetType()) << " target " << this->GetTargetName() << "\n\n"; { std::vector<cmSourceFile const*> customCommands; - this->GeneratorTarget->GetCustomCommands(customCommands, this->ConfigName); + this->GeneratorTarget->GetCustomCommands(customCommands, config); for (cmSourceFile const* sf : customCommands) { cmCustomCommand const* cc = sf->GetCustomCommand(); this->GetLocalGenerator()->AddCustomCommandTarget( cc, this->GetGeneratorTarget()); // Record the custom commands for this target. The container is used // in WriteObjectBuildStatement when called in a loop below. - this->CustomCommands.push_back(cc); + this->Configs[config].CustomCommands.push_back(cc); } } { std::vector<cmSourceFile const*> headerSources; - this->GeneratorTarget->GetHeaderSources(headerSources, this->ConfigName); + this->GeneratorTarget->GetHeaderSources(headerSources, config); this->OSXBundleGenerator->GenerateMacOSXContentStatements( - headerSources, this->MacOSXContentGenerator.get()); + headerSources, this->MacOSXContentGenerator.get(), config); } { std::vector<cmSourceFile const*> extraSources; - this->GeneratorTarget->GetExtraSources(extraSources, this->ConfigName); + this->GeneratorTarget->GetExtraSources(extraSources, config); this->OSXBundleGenerator->GenerateMacOSXContentStatements( - extraSources, this->MacOSXContentGenerator.get()); + extraSources, this->MacOSXContentGenerator.get(), config); } - { + if (firstForConfig) { const char* pchExtension = GetMakefile()->GetDefinition("CMAKE_PCH_EXTENSION"); std::vector<cmSourceFile const*> externalObjects; - this->GeneratorTarget->GetExternalObjects(externalObjects, - this->ConfigName); + this->GeneratorTarget->GetExternalObjects(externalObjects, config); for (cmSourceFile const* sf : externalObjects) { - const auto objectFileName = this->GetSourceFilePath(sf); + auto objectFileName = this->GetGlobalGenerator()->ExpandCFGIntDir( + this->GetSourceFilePath(sf), config); if (!cmSystemTools::StringEndsWith(objectFileName, pchExtension)) { - this->Objects.push_back(objectFileName); + this->Configs[config].Objects.push_back(objectFileName); } } } @@ -838,19 +862,19 @@ void cmNinjaTargetGenerator::WriteObjectBuildStatements() { cmNinjaBuild build("phony"); build.Comment = "Order-only phony target for " + this->GetTargetName(); - build.Outputs.push_back(this->OrderDependsTargetForTarget()); + build.Outputs.push_back(this->OrderDependsTargetForTarget(config)); cmNinjaDeps& orderOnlyDeps = build.OrderOnlyDeps; this->GetLocalGenerator()->AppendTargetDepends( - this->GeneratorTarget, orderOnlyDeps, DependOnTargetOrdering); + this->GeneratorTarget, orderOnlyDeps, config, fileConfig, + DependOnTargetOrdering); // Add order-only dependencies on other files associated with the target. - cmAppend(orderOnlyDeps, this->ExtraFiles); + cm::append(orderOnlyDeps, this->Configs[config].ExtraFiles); // Add order-only dependencies on custom command outputs. - for (cmCustomCommand const* cc : this->CustomCommands) { - cmCustomCommandGenerator ccg(*cc, this->GetConfigName(), - this->GetLocalGenerator()); + for (cmCustomCommand const* cc : this->Configs[config].CustomCommands) { + cmCustomCommandGenerator ccg(*cc, config, this->GetLocalGenerator()); const std::vector<std::string>& ccoutputs = ccg.GetOutputs(); const std::vector<std::string>& ccbyproducts = ccg.GetByproducts(); std::transform(ccoutputs.begin(), ccoutputs.end(), @@ -876,26 +900,27 @@ void cmNinjaTargetGenerator::WriteObjectBuildStatements() orderOnlyDeps.push_back(this->ConvertToNinjaPath(tgtDir)); } - this->GetGlobalGenerator()->WriteBuild(this->GetBuildFileStream(), build); + this->GetGlobalGenerator()->WriteBuild( + this->GetConfigFileStream(fileConfig), build); } { std::vector<cmSourceFile const*> objectSources; - this->GeneratorTarget->GetObjectSources(objectSources, this->ConfigName); + this->GeneratorTarget->GetObjectSources(objectSources, config); for (cmSourceFile const* sf : objectSources) { - this->WriteObjectBuildStatement(sf); + this->WriteObjectBuildStatement(sf, config, fileConfig, firstForConfig); } } - for (auto const& langDDIFiles : this->DDIFiles) { + for (auto const& langDDIFiles : this->Configs[config].DDIFiles) { std::string const& language = langDDIFiles.first; cmNinjaDeps const& ddiFiles = langDDIFiles.second; - cmNinjaBuild build(this->LanguageDyndepRule(language)); - build.Outputs.push_back(this->GetDyndepFilePath(language)); + cmNinjaBuild build(this->LanguageDyndepRule(language, config)); + build.Outputs.push_back(this->GetDyndepFilePath(language, config)); build.ExplicitDeps = ddiFiles; - this->WriteTargetDependInfo(language); + this->WriteTargetDependInfo(language, config); // Make sure dyndep files for all our dependencies have already // been generated so that the '<LANG>Modules.json' files they @@ -906,46 +931,51 @@ void cmNinjaTargetGenerator::WriteObjectBuildStatements() // refactoring the Ninja generator to generate targets in // dependency order so that we can collect the needed information. this->GetLocalGenerator()->AppendTargetDepends( - this->GeneratorTarget, build.OrderOnlyDeps, DependOnTargetArtifact); + this->GeneratorTarget, build.OrderOnlyDeps, config, fileConfig, + DependOnTargetArtifact); - this->GetGlobalGenerator()->WriteBuild(this->GetBuildFileStream(), build); + this->GetGlobalGenerator()->WriteBuild( + this->GetConfigFileStream(fileConfig), build); } - this->GetBuildFileStream() << "\n"; + this->GetConfigFileStream(fileConfig) << "\n"; - if (!this->SwiftOutputMap.empty()) { + if (!this->Configs[config].SwiftOutputMap.empty()) { std::string const mapFilePath = this->GeneratorTarget->GetSupportDirectory() + "/output-file-map.json"; - std::string const targetSwiftDepsPath = [this]() -> std::string { + std::string const targetSwiftDepsPath = [this, config]() -> std::string { cmGeneratorTarget const* target = this->GeneratorTarget; if (const char* name = target->GetProperty("Swift_DEPENDENCIES_FILE")) { return name; } return this->ConvertToNinjaPath(target->GetSupportDirectory() + "/" + - target->GetName() + ".swiftdeps"); + config + "/" + target->GetName() + + ".swiftdeps"); }(); // build the global target dependencies // https://github.com/apple/swift/blob/master/docs/Driver.md#output-file-maps Json::Value deps(Json::objectValue); deps["swift-dependencies"] = targetSwiftDepsPath; - this->SwiftOutputMap[""] = deps; + this->Configs[config].SwiftOutputMap[""] = deps; cmGeneratedFileStream output(mapFilePath); - output << this->SwiftOutputMap; + output << this->Configs[config].SwiftOutputMap; } } void cmNinjaTargetGenerator::WriteObjectBuildStatement( - cmSourceFile const* source) + cmSourceFile const* source, const std::string& config, + const std::string& fileConfig, bool firstForConfig) { std::string const language = source->GetLanguage(); std::string const sourceFileName = language == "RC" ? source->GetFullPath() : this->GetSourceFilePath(source); - std::string const objectDir = - this->ConvertToNinjaPath(this->GeneratorTarget->GetSupportDirectory()); + std::string const objectDir = this->ConvertToNinjaPath( + cmStrCat(this->GeneratorTarget->GetSupportDirectory(), + this->GetGlobalGenerator()->ConfigDirectory(config))); std::string const objectFileName = - this->ConvertToNinjaPath(this->GetObjectFilePath(source)); + this->ConvertToNinjaPath(this->GetObjectFilePath(source, config)); std::string const objectFileDir = cmSystemTools::GetFilenamePath(objectFileName); @@ -961,11 +991,11 @@ void cmNinjaTargetGenerator::WriteObjectBuildStatement( int const commandLineLengthLimit = ((lang_supports_response && this->ForceResponseFile())) ? -1 : 0; - cmNinjaBuild objBuild(this->LanguageCompilerRule(language)); + cmNinjaBuild objBuild(this->LanguageCompilerRule(language, config)); cmNinjaVars& vars = objBuild.Variables; - vars["FLAGS"] = this->ComputeFlagsForObject(source, language); - vars["DEFINES"] = this->ComputeDefines(source, language); - vars["INCLUDES"] = this->ComputeIncludes(source, language); + vars["FLAGS"] = this->ComputeFlagsForObject(source, language, config); + vars["DEFINES"] = this->ComputeDefines(source, language, config); + vars["INCLUDES"] = this->ComputeIncludes(source, language, config); if (!this->NeedDepTypeMSVC(language)) { bool replaceExt(false); @@ -993,11 +1023,13 @@ void cmNinjaTargetGenerator::WriteObjectBuildStatement( vars["FLAGS"], vars["DEFINES"], vars["INCLUDES"]); objBuild.Outputs.push_back(objectFileName); - const char* pchExtension = - this->GetMakefile()->GetDefinition("CMAKE_PCH_EXTENSION"); - if (!cmSystemTools::StringEndsWith(objectFileName, pchExtension)) { - // Add this object to the list of object files. - this->Objects.push_back(objectFileName); + if (firstForConfig) { + const char* pchExtension = + this->GetMakefile()->GetDefinition("CMAKE_PCH_EXTENSION"); + if (!cmSystemTools::StringEndsWith(objectFileName, pchExtension)) { + // Add this object to the list of object files. + this->Configs[config].Objects.push_back(objectFileName); + } } objBuild.ExplicitDeps.push_back(sourceFileName); @@ -1006,13 +1038,11 @@ void cmNinjaTargetGenerator::WriteObjectBuildStatement( std::vector<std::string> depList; const std::string pchSource = - this->GeneratorTarget->GetPchSource(this->GetConfigName(), language); + this->GeneratorTarget->GetPchSource(config, language); if (!pchSource.empty() && !source->GetProperty("SKIP_PRECOMPILE_HEADERS")) { - depList.push_back( - this->GeneratorTarget->GetPchHeader(this->GetConfigName(), language)); + depList.push_back(this->GeneratorTarget->GetPchHeader(config, language)); if (source->GetFullPath() != pchSource) { - depList.push_back( - this->GeneratorTarget->GetPchFile(this->GetConfigName(), language)); + depList.push_back(this->GeneratorTarget->GetPchFile(config, language)); } } @@ -1033,7 +1063,7 @@ void cmNinjaTargetGenerator::WriteObjectBuildStatement( MapToNinjaPath()); } - objBuild.OrderOnlyDeps.push_back(this->OrderDependsTargetForTarget()); + objBuild.OrderOnlyDeps.push_back(this->OrderDependsTargetForTarget(config)); // If the source file is GENERATED and does not have a custom command // (either attached to this source file or another one), assume that one of @@ -1053,10 +1083,10 @@ void cmNinjaTargetGenerator::WriteObjectBuildStatement( // For some cases we do an explicit preprocessor invocation. bool const explicitPP = this->NeedExplicitPreprocessing(language); if (explicitPP) { - cmNinjaBuild ppBuild(this->LanguagePreprocessRule(language)); + cmNinjaBuild ppBuild(this->LanguagePreprocessRule(language, config)); std::string const ppFileName = - this->ConvertToNinjaPath(this->GetPreprocessedFilePath(source)); + this->ConvertToNinjaPath(this->GetPreprocessedFilePath(source, config)); ppBuild.Outputs.push_back(ppFileName); ppBuild.RspFile = ppFileName + ".rsp"; @@ -1114,7 +1144,7 @@ void cmNinjaTargetGenerator::WriteObjectBuildStatement( std::string sourceDirectoryFlag = this->LocalGenerator->GetIncludeFlags( sourceDirectory, this->GeneratorTarget, language, false, false, - this->GetConfigName()); + config); vars["INCLUDES"] = sourceDirectoryFlag + " " + vars["INCLUDES"]; } @@ -1138,17 +1168,19 @@ void cmNinjaTargetGenerator::WriteObjectBuildStatement( std::string const ddiFile = objectFileName + ".ddi"; ppBuild.Variables["DYNDEP_INTERMEDIATE_FILE"] = ddiFile; ppBuild.ImplicitOuts.push_back(ddiFile); - this->DDIFiles[language].push_back(ddiFile); + if (firstForConfig) { + this->Configs[config].DDIFiles[language].push_back(ddiFile); + } } this->addPoolNinjaVariable("JOB_POOL_COMPILE", this->GetGeneratorTarget(), ppBuild.Variables); - this->GetGlobalGenerator()->WriteBuild(this->GetBuildFileStream(), ppBuild, - commandLineLengthLimit); + this->GetGlobalGenerator()->WriteBuild( + this->GetConfigFileStream(fileConfig), ppBuild, commandLineLengthLimit); } if (needDyndep) { - std::string const dyndep = this->GetDyndepFilePath(language); + std::string const dyndep = this->GetDyndepFilePath(language, config); objBuild.OrderOnlyDeps.push_back(dyndep); vars["dyndep"] = dyndep; } @@ -1163,15 +1195,15 @@ void cmNinjaTargetGenerator::WriteObjectBuildStatement( this->addPoolNinjaVariable("JOB_POOL_COMPILE", this->GetGeneratorTarget(), vars); - this->SetMsvcTargetPdbVariable(vars); + this->SetMsvcTargetPdbVariable(vars, config); objBuild.RspFile = objectFileName + ".rsp"; if (language == "Swift") { - this->EmitSwiftDependencyInfo(source); + this->EmitSwiftDependencyInfo(source, config); } else { - this->GetGlobalGenerator()->WriteBuild(this->GetBuildFileStream(), - objBuild, commandLineLengthLimit); + this->GetGlobalGenerator()->WriteBuild( + this->GetConfigFileStream(fileConfig), objBuild, commandLineLengthLimit); } if (const char* objectOutputs = source->GetProperty("OBJECT_OUTPUTS")) { @@ -1181,11 +1213,13 @@ void cmNinjaTargetGenerator::WriteObjectBuildStatement( std::transform(build.Outputs.begin(), build.Outputs.end(), build.Outputs.begin(), MapToNinjaPath()); build.ExplicitDeps = objBuild.Outputs; - this->GetGlobalGenerator()->WriteBuild(this->GetBuildFileStream(), build); + this->GetGlobalGenerator()->WriteBuild( + this->GetConfigFileStream(fileConfig), build); } } -void cmNinjaTargetGenerator::WriteTargetDependInfo(std::string const& lang) +void cmNinjaTargetGenerator::WriteTargetDependInfo(std::string const& lang, + const std::string& config) { Json::Value tdi(Json::objectValue); tdi["language"] = lang; @@ -1213,7 +1247,7 @@ void cmNinjaTargetGenerator::WriteTargetDependInfo(std::string const& lang) Json::Value& tdi_include_dirs = tdi["include-dirs"] = Json::arrayValue; std::vector<std::string> includes; this->LocalGenerator->GetIncludeDirectories(includes, this->GeneratorTarget, - lang, this->GetConfigName()); + lang, config); for (std::string const& i : includes) { // Convert the include directories the same way we do for -I flags. // See upstream ninja issue 1251. @@ -1222,22 +1256,22 @@ void cmNinjaTargetGenerator::WriteTargetDependInfo(std::string const& lang) Json::Value& tdi_linked_target_dirs = tdi["linked-target-dirs"] = Json::arrayValue; - for (std::string const& l : this->GetLinkedTargetDirectories()) { + for (std::string const& l : this->GetLinkedTargetDirectories(config)) { tdi_linked_target_dirs.append(l); } - std::string const tdin = this->GetTargetDependInfoPath(lang); + std::string const tdin = this->GetTargetDependInfoPath(lang, config); cmGeneratedFileStream tdif(tdin); tdif << tdi; } void cmNinjaTargetGenerator::EmitSwiftDependencyInfo( - cmSourceFile const* source) + cmSourceFile const* source, const std::string& config) { std::string const sourceFilePath = this->ConvertToNinjaPath(this->GetSourceFilePath(source)); std::string const objectFilePath = - this->ConvertToNinjaPath(this->GetObjectFilePath(source)); + this->ConvertToNinjaPath(this->GetObjectFilePath(source, config)); std::string const swiftDepsPath = [source, objectFilePath]() -> std::string { if (const char* name = source->GetProperty("Swift_DEPENDENCIES_FILE")) { return name; @@ -1250,10 +1284,10 @@ void cmNinjaTargetGenerator::EmitSwiftDependencyInfo( } return objectFilePath + ".dia"; }(); - std::string const makeDepsPath = [this, source]() -> std::string { + std::string const makeDepsPath = [this, source, config]() -> std::string { cmLocalNinjaGenerator const* local = this->GetLocalGenerator(); std::string const objectFileName = - this->ConvertToNinjaPath(this->GetObjectFilePath(source)); + this->ConvertToNinjaPath(this->GetObjectFilePath(source, config)); std::string const objectFileDir = cmSystemTools::GetFilenamePath(objectFileName); @@ -1274,7 +1308,7 @@ void cmNinjaTargetGenerator::EmitSwiftDependencyInfo( entry["dependencies"] = makeDepsPath; entry["swift-dependencies"] = swiftDepsPath; entry["diagnostics"] = swiftDiaPath; - SwiftOutputMap[sourceFilePath] = entry; + this->Configs[config].SwiftOutputMap[sourceFilePath] = entry; } void cmNinjaTargetGenerator::ExportObjectCompileCommand( @@ -1349,27 +1383,34 @@ void cmNinjaTargetGenerator::ExportObjectCompileCommand( this->GetGlobalGenerator()->AddCXXCompileCommand(cmdLine, sourceFileName); } -void cmNinjaTargetGenerator::AdditionalCleanFiles() +void cmNinjaTargetGenerator::AdditionalCleanFiles(const std::string& config) { if (const char* prop_value = this->GeneratorTarget->GetProperty("ADDITIONAL_CLEAN_FILES")) { cmLocalNinjaGenerator* lg = this->LocalGenerator; std::vector<std::string> cleanFiles; - cmExpandList(cmGeneratorExpression::Evaluate( - prop_value, lg, - this->Makefile->GetSafeDefinition("CMAKE_BUILD_TYPE"), - this->GeneratorTarget), + cmExpandList(cmGeneratorExpression::Evaluate(prop_value, lg, config, + this->GeneratorTarget), cleanFiles); std::string const& binaryDir = lg->GetCurrentBinaryDirectory(); cmGlobalNinjaGenerator* gg = lg->GetGlobalNinjaGenerator(); for (std::string const& cleanFile : cleanFiles) { // Support relative paths gg->AddAdditionalCleanFile( - cmSystemTools::CollapseFullPath(cleanFile, binaryDir)); + cmSystemTools::CollapseFullPath(cleanFile, binaryDir), config); } } } +cmNinjaDeps cmNinjaTargetGenerator::GetObjects(const std::string& config) const +{ + auto const it = this->Configs.find(config); + if (it != this->Configs.end()) { + return it->second.Objects; + } + return {}; +} + void cmNinjaTargetGenerator::EnsureDirectoryExists( const std::string& path) const { @@ -1392,7 +1433,7 @@ void cmNinjaTargetGenerator::EnsureParentDirectoryExists( } void cmNinjaTargetGenerator::MacOSXContentGeneratorType::operator()( - cmSourceFile const& source, const char* pkgloc) + cmSourceFile const& source, const char* pkgloc, const std::string& config) { // Skip OS X content when not building a Framework or Bundle. if (!this->Generator->GetGeneratorTarget()->IsBundleOnApple()) { @@ -1400,7 +1441,8 @@ void cmNinjaTargetGenerator::MacOSXContentGeneratorType::operator()( } std::string macdir = - this->Generator->OSXBundleGenerator->InitMacOSXContentDirectory(pkgloc); + this->Generator->OSXBundleGenerator->InitMacOSXContentDirectory(pkgloc, + config); // Get the input file location. std::string input = source.GetFullPath(); @@ -1412,11 +1454,11 @@ void cmNinjaTargetGenerator::MacOSXContentGeneratorType::operator()( output = this->Generator->GetGlobalGenerator()->ConvertToNinjaPath(output); // Write a build statement to copy the content into the bundle. - this->Generator->GetGlobalGenerator()->WriteMacOSXContentBuild(input, - output); + this->Generator->GetGlobalGenerator()->WriteMacOSXContentBuild(input, output, + config); // Add as a dependency to the target so that it gets called. - this->Generator->ExtraFiles.push_back(std::move(output)); + this->Generator->Configs[config].ExtraFiles.push_back(std::move(output)); } void cmNinjaTargetGenerator::addPoolNinjaVariable( diff --git a/Source/cmNinjaTargetGenerator.h b/Source/cmNinjaTargetGenerator.h index 4627bcd..22dd7b8 100644 --- a/Source/cmNinjaTargetGenerator.h +++ b/Source/cmNinjaTargetGenerator.h @@ -38,16 +38,17 @@ public: /// Destructor. ~cmNinjaTargetGenerator() override; - virtual void Generate() = 0; + virtual void Generate(const std::string& config) = 0; std::string GetTargetName() const; bool NeedDepTypeMSVC(const std::string& lang) const; protected: - bool SetMsvcTargetPdbVariable(cmNinjaVars&) const; + bool SetMsvcTargetPdbVariable(cmNinjaVars&, const std::string& config) const; - cmGeneratedFileStream& GetBuildFileStream() const; + cmGeneratedFileStream& GetConfigFileStream(const std::string& config) const; + cmGeneratedFileStream& GetCommonFileStream() const; cmGeneratedFileStream& GetRulesFileStream() const; cmGeneratorTarget* GetGeneratorTarget() const @@ -64,15 +65,18 @@ protected: cmMakefile* GetMakefile() const { return this->Makefile; } - std::string LanguageCompilerRule(const std::string& lang) const; - std::string LanguagePreprocessRule(std::string const& lang) const; + std::string LanguageCompilerRule(const std::string& lang, + const std::string& config) const; + std::string LanguagePreprocessRule(std::string const& lang, + const std::string& config) const; bool NeedExplicitPreprocessing(std::string const& lang) const; - std::string LanguageDyndepRule(std::string const& lang) const; + std::string LanguageDyndepRule(std::string const& lang, + const std::string& config) const; bool NeedDyndep(std::string const& lang) const; bool UsePreprocessedSource(std::string const& lang) const; bool CompilePreprocessedSourceWithDefines(std::string const& lang) const; - std::string OrderDependsTargetForTarget(); + std::string OrderDependsTargetForTarget(const std::string& config); std::string ComputeOrderDependsForTarget(); @@ -82,15 +86,19 @@ protected: * by LanguageFlagsVarName(). */ std::string ComputeFlagsForObject(cmSourceFile const* source, - const std::string& language); + const std::string& language, + const std::string& config); - void AddIncludeFlags(std::string& flags, std::string const& lang) override; + void AddIncludeFlags(std::string& flags, std::string const& lang, + const std::string& config) override; std::string ComputeDefines(cmSourceFile const* source, - const std::string& language); + const std::string& language, + const std::string& config); std::string ComputeIncludes(cmSourceFile const* source, - const std::string& language); + const std::string& language, + const std::string& config); std::string ConvertToNinjaPath(const std::string& path) const { @@ -102,36 +110,51 @@ protected: } /// @return the list of link dependency for the given target @a target. - cmNinjaDeps ComputeLinkDeps(const std::string& linkLanguage) const; + cmNinjaDeps ComputeLinkDeps(const std::string& linkLanguage, + const std::string& config) const; /// @return the source file path for the given @a source. std::string GetSourceFilePath(cmSourceFile const* source) const; /// @return the object file path for the given @a source. - std::string GetObjectFilePath(cmSourceFile const* source) const; + std::string GetObjectFilePath(cmSourceFile const* source, + const std::string& config) const; /// @return the preprocessed source file path for the given @a source. - std::string GetPreprocessedFilePath(cmSourceFile const* source) const; + std::string GetPreprocessedFilePath(cmSourceFile const* source, + const std::string& config) const; /// @return the dyndep file path for this target. - std::string GetDyndepFilePath(std::string const& lang) const; + std::string GetDyndepFilePath(std::string const& lang, + const std::string& config) const; /// @return the target dependency scanner info file path - std::string GetTargetDependInfoPath(std::string const& lang) const; + std::string GetTargetDependInfoPath(std::string const& lang, + const std::string& config) const; /// @return the file path where the target named @a name is generated. - std::string GetTargetFilePath(const std::string& name) const; + std::string GetTargetFilePath(const std::string& name, + const std::string& config) const; /// @return the output path for the target. - virtual std::string GetTargetOutputDir() const; - - void WriteLanguageRules(const std::string& language); - void WriteCompileRule(const std::string& language); - void WriteObjectBuildStatements(); - void WriteObjectBuildStatement(cmSourceFile const* source); - void WriteTargetDependInfo(std::string const& lang); - - void EmitSwiftDependencyInfo(cmSourceFile const* source); + virtual std::string GetTargetOutputDir(const std::string& config) const; + + void WriteLanguageRules(const std::string& language, + const std::string& config); + void WriteCompileRule(const std::string& language, + const std::string& config); + void WriteObjectBuildStatements(const std::string& config, + const std::string& fileConfig, + bool firstForConfig); + void WriteObjectBuildStatement(cmSourceFile const* source, + const std::string& config, + const std::string& fileConfig, + bool firstForConfig); + void WriteTargetDependInfo(std::string const& lang, + const std::string& config); + + void EmitSwiftDependencyInfo(cmSourceFile const* source, + const std::string& config); void ExportObjectCompileCommand( std::string const& language, std::string const& sourceFileName, @@ -139,9 +162,9 @@ protected: std::string const& objectFileDir, std::string const& flags, std::string const& defines, std::string const& includes); - void AdditionalCleanFiles(); + void AdditionalCleanFiles(const std::string& config); - cmNinjaDeps GetObjects() const { return this->Objects; } + cmNinjaDeps GetObjects(const std::string& config) const; void EnsureDirectoryExists(const std::string& dir) const; void EnsureParentDirectoryExists(const std::string& path) const; @@ -155,7 +178,8 @@ protected: { } - void operator()(cmSourceFile const& source, const char* pkgloc) override; + void operator()(cmSourceFile const& source, const char* pkgloc, + const std::string& config) override; private: cmNinjaTargetGenerator* Generator; @@ -174,14 +198,20 @@ protected: private: cmLocalNinjaGenerator* LocalGenerator; - /// List of object files for this target. - cmNinjaDeps Objects; - // Fortran Support - std::map<std::string, cmNinjaDeps> DDIFiles; - // Swift Support - Json::Value SwiftOutputMap; - std::vector<cmCustomCommand const*> CustomCommands; - cmNinjaDeps ExtraFiles; + + struct ByConfig + { + /// List of object files for this target. + cmNinjaDeps Objects; + // Fortran Support + std::map<std::string, cmNinjaDeps> DDIFiles; + // Swift Support + Json::Value SwiftOutputMap; + std::vector<cmCustomCommand const*> CustomCommands; + cmNinjaDeps ExtraFiles; + }; + + std::map<std::string, ByConfig> Configs; }; #endif // ! cmNinjaTargetGenerator_h diff --git a/Source/cmNinjaUtilityTargetGenerator.cxx b/Source/cmNinjaUtilityTargetGenerator.cxx index 5259037..0cddb12 100644 --- a/Source/cmNinjaUtilityTargetGenerator.cxx +++ b/Source/cmNinjaUtilityTargetGenerator.cxx @@ -15,13 +15,13 @@ #include "cmGeneratorTarget.h" #include "cmGlobalNinjaGenerator.h" #include "cmLocalNinjaGenerator.h" -#include "cmMakefile.h" #include "cmNinjaTypes.h" #include "cmOutputConverter.h" #include "cmSourceFile.h" #include "cmStateTypes.h" #include "cmStringAlgorithms.h" #include "cmSystemTools.h" +#include "cmTarget.h" cmNinjaUtilityTargetGenerator::cmNinjaUtilityTargetGenerator( cmGeneratorTarget* target) @@ -31,14 +31,18 @@ cmNinjaUtilityTargetGenerator::cmNinjaUtilityTargetGenerator( cmNinjaUtilityTargetGenerator::~cmNinjaUtilityTargetGenerator() = default; -void cmNinjaUtilityTargetGenerator::Generate() +void cmNinjaUtilityTargetGenerator::Generate(const std::string& config) { cmGlobalNinjaGenerator* gg = this->GetGlobalGenerator(); cmLocalNinjaGenerator* lg = this->GetLocalGenerator(); cmGeneratorTarget* genTarget = this->GetGeneratorTarget(); + std::string configDir; + if (genTarget->Target->IsPerConfig()) { + configDir = gg->ConfigDirectory(config); + } std::string utilCommandName = - cmStrCat(lg->GetCurrentBinaryDirectory(), "/CMakeFiles/", + cmStrCat(lg->GetCurrentBinaryDirectory(), "/CMakeFiles", configDir, "/", this->GetTargetName(), ".util"); utilCommandName = this->ConvertToNinjaPath(utilCommandName); @@ -55,8 +59,8 @@ void cmNinjaUtilityTargetGenerator::Generate() for (std::vector<cmCustomCommand> const* cmdList : cmdLists) { for (cmCustomCommand const& ci : *cmdList) { - cmCustomCommandGenerator ccg(ci, this->GetConfigName(), lg); - lg->AppendCustomCommandDeps(ccg, deps); + cmCustomCommandGenerator ccg(ci, config, lg); + lg->AppendCustomCommandDeps(ccg, deps, config); lg->AppendCustomCommandLines(ccg, commands); std::vector<std::string> const& ccByproducts = ccg.GetByproducts(); std::transform(ccByproducts.begin(), ccByproducts.end(), @@ -69,13 +73,11 @@ void cmNinjaUtilityTargetGenerator::Generate() } { - std::string const& config = - this->GetMakefile()->GetSafeDefinition("CMAKE_BUILD_TYPE"); std::vector<cmSourceFile*> sources; genTarget->GetSourceFiles(sources, config); for (cmSourceFile const* source : sources) { if (cmCustomCommand const* cc = source->GetCustomCommand()) { - cmCustomCommandGenerator ccg(*cc, this->GetConfigName(), lg); + cmCustomCommandGenerator ccg(*cc, config, lg); lg->AddCustomCommandTarget(cc, genTarget); // Depend on all custom command outputs. @@ -89,13 +91,21 @@ void cmNinjaUtilityTargetGenerator::Generate() } } - lg->AppendTargetOutputs(genTarget, phonyBuild.Outputs); - lg->AppendTargetDepends(genTarget, deps); + std::string outputConfig; + if (genTarget->Target->IsPerConfig()) { + outputConfig = config; + } + lg->AppendTargetOutputs(genTarget, phonyBuild.Outputs, outputConfig); + if (genTarget->Target->GetType() != cmStateEnums::GLOBAL_TARGET) { + lg->AppendTargetOutputs(genTarget, gg->GetByproductsForCleanTarget(), + config); + } + lg->AppendTargetDepends(genTarget, deps, config, config); if (commands.empty()) { phonyBuild.Comment = "Utility command for " + this->GetTargetName(); phonyBuild.ExplicitDeps = std::move(deps); - gg->WriteBuild(this->GetBuildFileStream(), phonyBuild); + gg->WriteBuild(this->GetCommonFileStream(), phonyBuild); } else { std::string command = lg->BuildCommandLine(commands, "utility", this->GeneratorTarget); @@ -118,6 +128,7 @@ void cmNinjaUtilityTargetGenerator::Generate() lg->ConvertToOutputFormat(lg->GetBinaryDirectory(), cmOutputConverter::SHELL)); cmSystemTools::ReplaceString(command, "$(ARGS)", ""); + command = gg->ExpandCFGIntDir(command, config); if (command.find('$') != std::string::npos) { return; @@ -127,22 +138,32 @@ void cmNinjaUtilityTargetGenerator::Generate() gg->SeenCustomCommandOutput(util_output); } + std::string ccConfig; + if (genTarget->Target->IsPerConfig() && + genTarget->GetType() != cmStateEnums::GLOBAL_TARGET) { + ccConfig = config; + } gg->WriteCustomCommandBuild(command, desc, "Utility command for " + this->GetTargetName(), /*depfile*/ "", /*job_pool*/ "", uses_terminal, - /*restat*/ true, util_outputs, deps); + /*restat*/ true, util_outputs, ccConfig, deps); phonyBuild.ExplicitDeps.push_back(utilCommandName); - gg->WriteBuild(this->GetBuildFileStream(), phonyBuild); + gg->WriteBuild(this->GetCommonFileStream(), phonyBuild); } // Find ADDITIONAL_CLEAN_FILES - this->AdditionalCleanFiles(); + this->AdditionalCleanFiles(config); // Add an alias for the logical target name regardless of what directory // contains it. Skip this for GLOBAL_TARGET because they are meant to // be per-directory and have one at the top-level anyway. if (genTarget->GetType() != cmStateEnums::GLOBAL_TARGET) { - gg->AddTargetAlias(this->GetTargetName(), genTarget); + gg->AddTargetAlias(this->GetTargetName(), genTarget, config); + } else if (gg->IsMultiConfig() && genTarget->Target->IsPerConfig()) { + cmNinjaBuild phonyAlias("phony"); + gg->AppendTargetOutputs(genTarget, phonyAlias.Outputs, ""); + phonyAlias.ExplicitDeps = phonyBuild.Outputs; + gg->WriteBuild(this->GetConfigFileStream(config), phonyAlias); } } diff --git a/Source/cmNinjaUtilityTargetGenerator.h b/Source/cmNinjaUtilityTargetGenerator.h index 01cc459..ca3f0a4 100644 --- a/Source/cmNinjaUtilityTargetGenerator.h +++ b/Source/cmNinjaUtilityTargetGenerator.h @@ -5,6 +5,8 @@ #include "cmConfigure.h" // IWYU pragma: keep +#include <string> + #include "cmNinjaTargetGenerator.h" class cmGeneratorTarget; @@ -15,7 +17,7 @@ public: cmNinjaUtilityTargetGenerator(cmGeneratorTarget* target); ~cmNinjaUtilityTargetGenerator() override; - void Generate() override; + void Generate(const std::string& config) override; }; #endif // ! cmNinjaUtilityTargetGenerator_h diff --git a/Source/cmOSXBundleGenerator.cxx b/Source/cmOSXBundleGenerator.cxx index a6f4e51..382b563 100644 --- a/Source/cmOSXBundleGenerator.cxx +++ b/Source/cmOSXBundleGenerator.cxx @@ -3,7 +3,6 @@ #include "cmOSXBundleGenerator.h" #include <cassert> -#include <utility> #include "cmGeneratorTarget.h" #include "cmLocalGenerator.h" @@ -15,12 +14,10 @@ class cmSourceFile; -cmOSXBundleGenerator::cmOSXBundleGenerator(cmGeneratorTarget* target, - std::string configName) +cmOSXBundleGenerator::cmOSXBundleGenerator(cmGeneratorTarget* target) : GT(target) , Makefile(target->Target->GetMakefile()) , LocalGenerator(target->GetLocalGenerator()) - , ConfigName(std::move(configName)) , MacContentFolders(nullptr) { if (this->MustSkip()) { @@ -34,34 +31,34 @@ bool cmOSXBundleGenerator::MustSkip() } void cmOSXBundleGenerator::CreateAppBundle(const std::string& targetName, - std::string& outpath) + std::string& outpath, + const std::string& config) { if (this->MustSkip()) { return; } // Compute bundle directory names. - std::string out = - cmStrCat(outpath, '/', - this->GT->GetAppBundleDirectory(this->ConfigName, - cmGeneratorTarget::FullLevel)); + std::string out = cmStrCat( + outpath, '/', + this->GT->GetAppBundleDirectory(config, cmGeneratorTarget::FullLevel)); cmSystemTools::MakeDirectory(out); this->Makefile->AddCMakeOutputFile(out); // Configure the Info.plist file. Note that it needs the executable name // to be set. - std::string plist = - cmStrCat(outpath, '/', - this->GT->GetAppBundleDirectory(this->ConfigName, - cmGeneratorTarget::ContentLevel), - "/Info.plist"); + std::string plist = cmStrCat( + outpath, '/', + this->GT->GetAppBundleDirectory(config, cmGeneratorTarget::ContentLevel), + "/Info.plist"); this->LocalGenerator->GenerateAppleInfoPList(this->GT, targetName, plist); this->Makefile->AddCMakeOutputFile(plist); outpath = out; } void cmOSXBundleGenerator::CreateFramework(const std::string& targetName, - const std::string& outpath) + const std::string& outpath, + const std::string& config) { if (this->MustSkip()) { return; @@ -70,15 +67,13 @@ void cmOSXBundleGenerator::CreateFramework(const std::string& targetName, assert(this->MacContentFolders); // Compute the location of the top-level foo.framework directory. - std::string contentdir = - cmStrCat(outpath, '/', - this->GT->GetFrameworkDirectory(this->ConfigName, - cmGeneratorTarget::ContentLevel), - '/'); + std::string contentdir = cmStrCat( + outpath, '/', + this->GT->GetFrameworkDirectory(config, cmGeneratorTarget::ContentLevel), + '/'); std::string newoutpath = outpath + "/" + - this->GT->GetFrameworkDirectory(this->ConfigName, - cmGeneratorTarget::FullLevel); + this->GT->GetFrameworkDirectory(config, cmGeneratorTarget::FullLevel); std::string frameworkVersion = this->GT->GetFrameworkVersion(); @@ -156,27 +151,26 @@ void cmOSXBundleGenerator::CreateFramework(const std::string& targetName, } void cmOSXBundleGenerator::CreateCFBundle(const std::string& targetName, - const std::string& root) + const std::string& root, + const std::string& config) { if (this->MustSkip()) { return; } // Compute bundle directory names. - std::string out = - cmStrCat(root, '/', - this->GT->GetCFBundleDirectory(this->ConfigName, - cmGeneratorTarget::FullLevel)); + std::string out = cmStrCat( + root, '/', + this->GT->GetCFBundleDirectory(config, cmGeneratorTarget::FullLevel)); cmSystemTools::MakeDirectory(out); this->Makefile->AddCMakeOutputFile(out); // Configure the Info.plist file. Note that it needs the executable name // to be set. - std::string plist = - cmStrCat(root, '/', - this->GT->GetCFBundleDirectory(this->ConfigName, - cmGeneratorTarget::ContentLevel), - "/Info.plist"); + std::string plist = cmStrCat( + root, '/', + this->GT->GetCFBundleDirectory(config, cmGeneratorTarget::ContentLevel), + "/Info.plist"); std::string name = cmSystemTools::GetFilenameName(targetName); this->LocalGenerator->GenerateAppleInfoPList(this->GT, name, plist); this->Makefile->AddCMakeOutputFile(plist); @@ -184,7 +178,7 @@ void cmOSXBundleGenerator::CreateCFBundle(const std::string& targetName, void cmOSXBundleGenerator::GenerateMacOSXContentStatements( std::vector<cmSourceFile const*> const& sources, - MacOSXContentGeneratorType* generator) + MacOSXContentGeneratorType* generator, const std::string& config) { if (this->MustSkip()) { return; @@ -194,20 +188,19 @@ void cmOSXBundleGenerator::GenerateMacOSXContentStatements( cmGeneratorTarget::SourceFileFlags tsFlags = this->GT->GetTargetSourceFileFlags(source); if (tsFlags.Type != cmGeneratorTarget::SourceFileTypeNormal) { - (*generator)(*source, tsFlags.MacFolder); + (*generator)(*source, tsFlags.MacFolder, config); } } } std::string cmOSXBundleGenerator::InitMacOSXContentDirectory( - const char* pkgloc) + const char* pkgloc, const std::string& config) { // Construct the full path to the content subdirectory. - std::string macdir = - cmStrCat(this->GT->GetMacContentDirectory( - this->ConfigName, cmStateEnums::RuntimeBinaryArtifact), - '/', pkgloc); + std::string macdir = cmStrCat(this->GT->GetMacContentDirectory( + config, cmStateEnums::RuntimeBinaryArtifact), + '/', pkgloc); cmSystemTools::MakeDirectory(macdir); // Record use of this content location. Only the first level diff --git a/Source/cmOSXBundleGenerator.h b/Source/cmOSXBundleGenerator.h index 3dea6cc..232be48 100644 --- a/Source/cmOSXBundleGenerator.h +++ b/Source/cmOSXBundleGenerator.h @@ -17,29 +17,33 @@ class cmSourceFile; class cmOSXBundleGenerator { public: - cmOSXBundleGenerator(cmGeneratorTarget* target, std::string configName); + cmOSXBundleGenerator(cmGeneratorTarget* target); // create an app bundle at a given root, and return // the directory within the bundle that contains the executable - void CreateAppBundle(const std::string& targetName, std::string& root); + void CreateAppBundle(const std::string& targetName, std::string& root, + const std::string& config); // create a framework at a given root - void CreateFramework(const std::string& targetName, const std::string& root); + void CreateFramework(const std::string& targetName, const std::string& root, + const std::string& config); // create a cf bundle at a given root - void CreateCFBundle(const std::string& targetName, const std::string& root); + void CreateCFBundle(const std::string& targetName, const std::string& root, + const std::string& config); struct MacOSXContentGeneratorType { virtual ~MacOSXContentGeneratorType() = default; - virtual void operator()(cmSourceFile const& source, - const char* pkgloc) = 0; + virtual void operator()(cmSourceFile const& source, const char* pkgloc, + const std::string& config) = 0; }; void GenerateMacOSXContentStatements( std::vector<cmSourceFile const*> const& sources, - MacOSXContentGeneratorType* generator); - std::string InitMacOSXContentDirectory(const char* pkgloc); + MacOSXContentGeneratorType* generator, const std::string& config); + std::string InitMacOSXContentDirectory(const char* pkgloc, + const std::string& config); void SetMacContentFolders(std::set<std::string>* macContentFolders) { @@ -53,7 +57,6 @@ private: cmGeneratorTarget* GT; cmMakefile* Makefile; cmLocalGenerator* LocalGenerator; - std::string ConfigName; std::set<std::string>* MacContentFolders; }; diff --git a/Source/cmOrderDirectories.cxx b/Source/cmOrderDirectories.cxx index 073222c..9ee7127 100644 --- a/Source/cmOrderDirectories.cxx +++ b/Source/cmOrderDirectories.cxx @@ -8,6 +8,8 @@ #include <sstream> #include <vector> +#include <cmext/algorithm> + #include "cmAlgorithms.h" #include "cmGeneratorTarget.h" #include "cmGlobalGenerator.h" @@ -328,13 +330,13 @@ void cmOrderDirectories::AddLinkLibrary(std::string const& fullPath) void cmOrderDirectories::AddUserDirectories( std::vector<std::string> const& extra) { - cmAppend(this->UserDirectories, extra); + cm::append(this->UserDirectories, extra); } void cmOrderDirectories::AddLanguageDirectories( std::vector<std::string> const& dirs) { - cmAppend(this->LanguageDirectories, dirs); + cm::append(this->LanguageDirectories, dirs); } void cmOrderDirectories::SetImplicitDirectories( diff --git a/Source/cmOutputConverter.cxx b/Source/cmOutputConverter.cxx index e602a6d..1c6fad1 100644 --- a/Source/cmOutputConverter.cxx +++ b/Source/cmOutputConverter.cxx @@ -43,9 +43,10 @@ std::string cmOutputConverter::ConvertToOutputFormat(cm::string_view source, { std::string result(source); // Convert it to an output path. - if (output == SHELL || output == WATCOMQUOTE) { + if (output == SHELL || output == WATCOMQUOTE || output == NINJAMULTI) { result = this->ConvertDirectorySeparatorsForShell(source); - result = this->EscapeForShell(result, true, false, output == WATCOMQUOTE); + result = this->EscapeForShell(result, true, false, output == WATCOMQUOTE, + output == NINJAMULTI); } else if (output == RESPONSE) { result = this->EscapeForShell(result, false, false, false); } @@ -79,9 +80,9 @@ static bool cmOutputConverterIsShellOperator(cm::string_view str) return (shellOperators.count(str) != 0); } -std::string cmOutputConverter::EscapeForShell(cm::string_view str, - bool makeVars, bool forEcho, - bool useWatcomQuote) const +std::string cmOutputConverter::EscapeForShell( + cm::string_view str, bool makeVars, bool forEcho, bool useWatcomQuote, + bool unescapeNinjaConfiguration) const { // Do not escape shell operators. if (cmOutputConverterIsShellOperator(str)) { @@ -95,6 +96,9 @@ std::string cmOutputConverter::EscapeForShell(cm::string_view str, } else if (!this->LinkScriptShell) { flags |= Shell_Flag_Make; } + if (unescapeNinjaConfiguration) { + flags |= Shell_Flag_UnescapeNinjaConfiguration; + } if (makeVars) { flags |= Shell_Flag_AllowMakeVariables; } @@ -511,5 +515,14 @@ std::string cmOutputConverter::Shell__GetArgument(cm::string_view in, } } + if (flags & Shell_Flag_UnescapeNinjaConfiguration) { + std::string ninjaConfigReplace; + if (flags & Shell_Flag_IsUnix) { + ninjaConfigReplace += '\\'; + } + ninjaConfigReplace += "$${CONFIGURATION}"; + cmSystemTools::ReplaceString(out, ninjaConfigReplace, "${CONFIGURATION}"); + } + return out; } diff --git a/Source/cmOutputConverter.h b/Source/cmOutputConverter.h index 349a069..6583ab5 100644 --- a/Source/cmOutputConverter.h +++ b/Source/cmOutputConverter.h @@ -22,6 +22,7 @@ public: { SHELL, WATCOMQUOTE, + NINJAMULTI, RESPONSE }; std::string ConvertToOutputFormat(cm::string_view source, @@ -70,12 +71,14 @@ public: /** The target shell quoting uses extra single Quotes for Watcom tools. */ Shell_Flag_WatcomQuote = (1 << 7), - Shell_Flag_IsUnix = (1 << 8) + Shell_Flag_IsUnix = (1 << 8), + + Shell_Flag_UnescapeNinjaConfiguration = (1 << 9), }; std::string EscapeForShell(cm::string_view str, bool makeVars = false, - bool forEcho = false, - bool useWatcomQuote = false) const; + bool forEcho = false, bool useWatcomQuote = false, + bool unescapeNinjaConfiguration = false) const; static std::string EscapeForCMake(cm::string_view str); diff --git a/Source/cmOutputRequiredFilesCommand.cxx b/Source/cmOutputRequiredFilesCommand.cxx index e093be0..147f97f 100644 --- a/Source/cmOutputRequiredFilesCommand.cxx +++ b/Source/cmOutputRequiredFilesCommand.cxx @@ -7,10 +7,11 @@ #include <set> #include <utility> +#include <cm/memory> + #include "cmsys/FStream.hxx" #include "cmsys/RegularExpression.hxx" -#include "cmAlgorithms.h" #include "cmExecutionStatus.h" #include "cmGeneratorExpression.h" #include "cmMakefile.h" @@ -94,7 +95,7 @@ public: /** * Destructor. */ - ~cmLBDepend() { cmDeleteAll(this->DependInformationMap); } + ~cmLBDepend() = default; cmLBDepend(const cmLBDepend&) = delete; cmLBDepend& operator=(const cmLBDepend&) = delete; @@ -152,9 +153,9 @@ public: * Generate dependencies for the file given. Returns a pointer to * the cmDependInformation object for the file. */ - const cmDependInformation* FindDependencies(const char* file) + const cmDependInformation* FindDependencies(const std::string& file) { - cmDependInformation* info = this->GetDependInformation(file, nullptr); + cmDependInformation* info = this->GetDependInformation(file, ""); this->GenerateDependInformation(info); return info; } @@ -203,7 +204,7 @@ protected: } // Add this file and all its dependencies. - this->AddDependency(info, includeFile.c_str()); + this->AddDependency(info, includeFile); /// add the cxx file if it exists std::string cxxFile = includeFile; std::string::size_type pos = cxxFile.rfind('.'); @@ -254,7 +255,7 @@ protected: } } if (found) { - this->AddDependency(info, cxxFile.c_str()); + this->AddDependency(info, cxxFile); } } } @@ -264,10 +265,10 @@ protected: /** * Add a dependency. Possibly walk it for more dependencies. */ - void AddDependency(cmDependInformation* info, const char* file) + void AddDependency(cmDependInformation* info, const std::string& file) { cmDependInformation* dependInfo = - this->GetDependInformation(file, info->PathOnly.c_str()); + this->GetDependInformation(file, info->PathOnly); this->GenerateDependInformation(dependInfo); info->AddDependencies(dependInfo); } @@ -313,7 +314,7 @@ protected: // Dependency hints have been given. Use them to begin the // recursion. for (std::string const& file : cFile.GetDepends()) { - this->AddDependency(info, file.c_str()); + this->AddDependency(info, file); } // Found dependency information. We are done. @@ -361,8 +362,8 @@ protected: * Get an instance of cmDependInformation corresponding to the given file * name. */ - cmDependInformation* GetDependInformation(const char* file, - const char* extraPath) + cmDependInformation* GetDependInformation(const std::string& file, + const std::string& extraPath) { // Get the full path for the file so that lookup is unambiguous. std::string fullPath = this->FullPath(file, extraPath); @@ -371,15 +372,16 @@ protected: auto result = this->DependInformationMap.find(fullPath); if (result != this->DependInformationMap.end()) { // Found an instance, return it. - return result->second; + return result->second.get(); } // Didn't find an instance. Create a new one and save it. - cmDependInformation* info = new cmDependInformation; + auto info = cm::make_unique<cmDependInformation>(); + auto ptr = info.get(); info->FullPath = fullPath; info->PathOnly = cmSystemTools::GetFilenamePath(fullPath); info->IncludeName = file; - this->DependInformationMap[fullPath] = info; - return info; + this->DependInformationMap[fullPath] = std::move(info); + return ptr; } /** @@ -387,14 +389,9 @@ protected: * This uses the include directories. * TODO: Cache path conversions to reduce FileExists calls. */ - std::string FullPath(const char* fname, const char* extraPath) + std::string FullPath(const std::string& fname, const std::string& extraPath) { - DirectoryToFileToPathMapType::iterator m; - if (extraPath) { - m = this->DirectoryToFileToPathMap.find(extraPath); - } else { - m = this->DirectoryToFileToPathMap.find(""); - } + auto m = this->DirectoryToFileToPathMap.find(extraPath); if (m != this->DirectoryToFileToPathMap.end()) { FileToPathMapType& map = m->second; @@ -406,7 +403,7 @@ protected: if (cmSystemTools::FileExists(fname, true)) { std::string fp = cmSystemTools::CollapseFullPath(fname); - this->DirectoryToFileToPathMap[extraPath ? extraPath : ""][fname] = fp; + this->DirectoryToFileToPathMap[extraPath][fname] = fp; return fp; } @@ -418,12 +415,12 @@ protected: if (cmSystemTools::FileExists(path, true) && !cmSystemTools::FileIsDirectory(path)) { std::string fp = cmSystemTools::CollapseFullPath(path); - this->DirectoryToFileToPathMap[extraPath ? extraPath : ""][fname] = fp; + this->DirectoryToFileToPathMap[extraPath][fname] = fp; return fp; } } - if (extraPath) { + if (!extraPath.empty()) { std::string path = extraPath; if (!path.empty() && path.back() != '/') { path = path + "/"; @@ -438,7 +435,7 @@ protected: } // Couldn't find the file. - return std::string(fname); + return fname; } cmMakefile* Makefile; @@ -449,7 +446,8 @@ protected: using FileToPathMapType = std::map<std::string, std::string>; using DirectoryToFileToPathMapType = std::map<std::string, FileToPathMapType>; - using DependInformationMapType = std::map<std::string, cmDependInformation*>; + using DependInformationMapType = + std::map<std::string, std::unique_ptr<cmDependInformation>>; DependInformationMapType DependInformationMap; DirectoryToFileToPathMapType DirectoryToFileToPathMap; }; @@ -476,7 +474,7 @@ bool cmOutputRequiredFilesCommand(std::vector<std::string> const& args, md.SetMakefile(&status.GetMakefile()); md.AddSearchPath(status.GetMakefile().GetCurrentSourceDirectory()); // find the depends for a file - const cmDependInformation* info = md.FindDependencies(file.c_str()); + const cmDependInformation* info = md.FindDependencies(file); if (info) { // write them out FILE* fout = cmsys::SystemTools::Fopen(outputFile, "w"); diff --git a/Source/cmPolicies.h b/Source/cmPolicies.h index 92c80bb..ecf892b 100644 --- a/Source/cmPolicies.h +++ b/Source/cmPolicies.h @@ -290,7 +290,14 @@ class cmMakefile; SELECT(POLICY, CMP0097, \ "ExternalProject_Add with GIT_SUBMODULES \"\" initializes no " \ "submodules.", \ - 3, 16, 0, cmPolicies::WARN) + 3, 16, 0, cmPolicies::WARN) \ + SELECT(POLICY, CMP0098, \ + "FindFLEX runs flex in CMAKE_CURRENT_BINARY_DIR when executing.", 3, \ + 17, 0, cmPolicies::WARN) \ + SELECT(POLICY, CMP0099, \ + "Link properties are transitive over private dependency on static " \ + "libraries.", \ + 3, 17, 0, cmPolicies::WARN) #define CM_SELECT_ID(F, A1, A2, A3, A4, A5, A6) F(A1) #define CM_FOR_EACH_POLICY_ID(POLICY) \ @@ -319,7 +326,8 @@ class cmMakefile; F(CMP0076) \ F(CMP0081) \ F(CMP0083) \ - F(CMP0095) + F(CMP0095) \ + F(CMP0099) /** \class cmPolicies * \brief Handles changes in CMake behavior and policies diff --git a/Source/cmProjectCommand.cxx b/Source/cmProjectCommand.cxx index 7bb5209..a25fd42 100644 --- a/Source/cmProjectCommand.cxx +++ b/Source/cmProjectCommand.cxx @@ -39,6 +39,11 @@ bool cmProjectCommand(std::vector<std::string> const& args, std::string const& projectName = args[0]; + if (!IncludeByVariable(status, + "CMAKE_PROJECT_" + projectName + "_INCLUDE_BEFORE")) { + return false; + } + mf.SetProjectName(projectName); mf.AddCacheDefinition(projectName + "_BINARY_DIR", diff --git a/Source/cmQtAutoGen.cxx b/Source/cmQtAutoGen.cxx index eb7c900..d5891c4 100644 --- a/Source/cmQtAutoGen.cxx +++ b/Source/cmQtAutoGen.cxx @@ -8,6 +8,8 @@ #include <sstream> #include <utility> +#include <cmext/algorithm> + #include "cmsys/FStream.hxx" #include "cmsys/RegularExpression.hxx" @@ -67,7 +69,7 @@ void MergeOptions(std::vector<std::string>& baseOpts, } } // Append options - cmAppend(baseOpts, extraOpts); + cm::append(baseOpts, extraOpts); } // - Class definitions @@ -328,7 +330,7 @@ bool cmQtAutoGen::RccLister::list(std::string const& qrcFile, { std::vector<std::string> cmd; cmd.emplace_back(this->RccExcutable_); - cmAppend(cmd, this->ListOptions_); + cm::append(cmd, this->ListOptions_); cmd.emplace_back(cmSystemTools::GetFilenameName(qrcFile)); // Log command diff --git a/Source/cmQtAutoGenGlobalInitializer.cxx b/Source/cmQtAutoGenGlobalInitializer.cxx index ef6b886..db5a8ba 100644 --- a/Source/cmQtAutoGenGlobalInitializer.cxx +++ b/Source/cmQtAutoGenGlobalInitializer.cxx @@ -7,7 +7,6 @@ #include <cm/memory> #include "cmCustomCommandLines.h" -#include "cmCustomCommandTypes.h" #include "cmDuration.h" #include "cmGeneratorTarget.h" #include "cmLocalGenerator.h" @@ -41,9 +40,9 @@ cmQtAutoGenGlobalInitializer::Keywords::Keywords() } cmQtAutoGenGlobalInitializer::cmQtAutoGenGlobalInitializer( - std::vector<cmLocalGenerator*> const& localGenerators) + std::vector<std::unique_ptr<cmLocalGenerator>> const& localGenerators) { - for (cmLocalGenerator* localGen : localGenerators) { + for (const auto& localGen : localGenerators) { // Detect global autogen and autorcc target names bool globalAutoGenTarget = false; bool globalAutoRccTarget = false; @@ -56,7 +55,7 @@ cmQtAutoGenGlobalInitializer::cmQtAutoGenGlobalInitializer( if (targetName.empty()) { targetName = "autogen"; } - GlobalAutoGenTargets_.emplace(localGen, std::move(targetName)); + GlobalAutoGenTargets_.emplace(localGen.get(), std::move(targetName)); globalAutoGenTarget = true; } @@ -67,13 +66,13 @@ cmQtAutoGenGlobalInitializer::cmQtAutoGenGlobalInitializer( if (targetName.empty()) { targetName = "autorcc"; } - GlobalAutoRccTargets_.emplace(localGen, std::move(targetName)); + GlobalAutoRccTargets_.emplace(localGen.get(), std::move(targetName)); globalAutoRccTarget = true; } } // Find targets that require AUTOMOC/UIC/RCC processing - for (cmGeneratorTarget* target : localGen->GetGeneratorTargets()) { + for (const auto& target : localGen->GetGeneratorTargets()) { // Process only certain target types switch (target->GetType()) { case cmStateEnums::EXECUTABLE: @@ -104,7 +103,7 @@ cmQtAutoGenGlobalInitializer::cmQtAutoGenGlobalInitializer( target->GetSafeProperty(kw().AUTORCC_EXECUTABLE); // We support Qt4, Qt5 and Qt6 - auto qtVersion = cmQtAutoGenInitializer::GetQtVersion(target); + auto qtVersion = cmQtAutoGenInitializer::GetQtVersion(target.get()); bool const validQt = (qtVersion.first.Major == 4) || (qtVersion.first.Major == 5) || (qtVersion.first.Major == 6); @@ -135,8 +134,8 @@ cmQtAutoGenGlobalInitializer::cmQtAutoGenGlobalInitializer( if (mocIsValid || uicIsValid || rccIsValid) { // Create autogen target initializer Initializers_.emplace_back(cm::make_unique<cmQtAutoGenInitializer>( - this, target, qtVersion.first, mocIsValid, uicIsValid, rccIsValid, - globalAutoGenTarget, globalAutoRccTarget)); + this, target.get(), qtVersion.first, mocIsValid, uicIsValid, + rccIsValid, globalAutoGenTarget, globalAutoRccTarget)); } } } @@ -154,13 +153,14 @@ void cmQtAutoGenGlobalInitializer::GetOrCreateGlobalTarget( cmMakefile* makefile = localGen->GetMakefile(); // Create utility target - cmTarget* target = makefile->AddUtilityCommand( - name, cmCommandOrigin::Generator, true, - makefile->GetHomeOutputDirectory().c_str() /*work dir*/, - std::vector<std::string>() /*output*/, - std::vector<std::string>() /*depends*/, cmCustomCommandLines(), false, - comment.c_str()); - localGen->AddGeneratorTarget(new cmGeneratorTarget(target, localGen)); + std::vector<std::string> no_byproducts; + std::vector<std::string> no_depends; + cmCustomCommandLines no_commands; + cmTarget* target = localGen->AddUtilityCommand( + name, true, makefile->GetHomeOutputDirectory().c_str(), no_byproducts, + no_depends, no_commands, false, comment.c_str()); + localGen->AddGeneratorTarget( + cm::make_unique<cmGeneratorTarget>(target, localGen)); // Set FOLDER property in the target { diff --git a/Source/cmQtAutoGenGlobalInitializer.h b/Source/cmQtAutoGenGlobalInitializer.h index 806725a..2f6e581 100644 --- a/Source/cmQtAutoGenGlobalInitializer.h +++ b/Source/cmQtAutoGenGlobalInitializer.h @@ -48,7 +48,7 @@ public: public: cmQtAutoGenGlobalInitializer( - std::vector<cmLocalGenerator*> const& localGenerators); + std::vector<std::unique_ptr<cmLocalGenerator>> const& localGenerators); ~cmQtAutoGenGlobalInitializer(); Keywords const& kw() const { return Keywords_; }; diff --git a/Source/cmQtAutoGenInitializer.cxx b/Source/cmQtAutoGenInitializer.cxx index 6b0fc1e..ab47f3f 100644 --- a/Source/cmQtAutoGenInitializer.cxx +++ b/Source/cmQtAutoGenInitializer.cxx @@ -25,7 +25,6 @@ #include "cmAlgorithms.h" #include "cmCustomCommand.h" #include "cmCustomCommandLines.h" -#include "cmCustomCommandTypes.h" #include "cmGeneratedFileStream.h" #include "cmGeneratorExpression.h" #include "cmGeneratorTarget.h" @@ -1045,9 +1044,16 @@ bool cmQtAutoGenInitializer::InitAutogenTarget() } // Compose command lines - cmCustomCommandLines commandLines = cmMakeSingleCommandLine( - { cmSystemTools::GetCMakeCommand(), "-E", "cmake_autogen", - this->AutogenTarget.InfoFile, "$<CONFIGURATION>" }); + // TODO: Refactor autogen to output a per-config mocs_compilation.cpp instead + // of fiddling with the include directories + std::vector<std::string> configs; + this->GlobalGen->GetQtAutoGenConfigs(configs); + cmCustomCommandLines commandLines; + for (auto const& config : configs) { + commandLines.push_back(cmMakeCommandLine( + { cmSystemTools::GetCMakeCommand(), "-E", "cmake_autogen", + this->AutogenTarget.InfoFile, config })); + } // Use PRE_BUILD on demand bool usePRE_BUILD = false; @@ -1084,8 +1090,8 @@ bool cmQtAutoGenInitializer::InitAutogenTarget() // PRE_BUILD does not support file dependencies! const std::vector<std::string> no_output; const std::vector<std::string> no_deps; - cmCustomCommand cc(this->Makefile, no_output, autogenProvides, no_deps, - commandLines, autogenComment.c_str(), + cmCustomCommand cc(no_output, autogenProvides, no_deps, commandLines, + this->Makefile->GetBacktrace(), autogenComment.c_str(), this->Dir.Work.c_str()); cc.SetEscapeOldStyle(false); cc.SetEscapeAllowMakeVars(true); @@ -1120,15 +1126,15 @@ bool cmQtAutoGenInitializer::InitAutogenTarget() } // Create autogen target - cmTarget* autogenTarget = this->Makefile->AddUtilityCommand( - this->AutogenTarget.Name, cmCommandOrigin::Generator, true, - this->Dir.Work.c_str(), /*byproducts=*/autogenProvides, + cmTarget* autogenTarget = this->LocalGen->AddUtilityCommand( + this->AutogenTarget.Name, true, this->Dir.Work.c_str(), + /*byproducts=*/autogenProvides, std::vector<std::string>(this->AutogenTarget.DependFiles.begin(), this->AutogenTarget.DependFiles.end()), commandLines, false, autogenComment.c_str()); // Create autogen generator target this->LocalGen->AddGeneratorTarget( - new cmGeneratorTarget(autogenTarget, this->LocalGen)); + cm::make_unique<cmGeneratorTarget>(autogenTarget, this->LocalGen)); // Forward origin utilities to autogen target if (this->AutogenTarget.DependOrigin) { @@ -1143,7 +1149,7 @@ bool cmQtAutoGenInitializer::InitAutogenTarget() // Set FOLDER property in autogen target if (!this->TargetsFolder.empty()) { - autogenTarget->SetProperty("FOLDER", this->TargetsFolder.c_str()); + autogenTarget->SetProperty("FOLDER", this->TargetsFolder); } // Add autogen target to the origin target dependencies @@ -1202,17 +1208,17 @@ bool cmQtAutoGenInitializer::InitRccTargets() ccName += cmStrCat('_', qrc.QrcPathChecksum); } - cmTarget* autoRccTarget = this->Makefile->AddUtilityCommand( - ccName, cmCommandOrigin::Generator, true, this->Dir.Work.c_str(), - ccOutput, ccDepends, commandLines, false, ccComment.c_str()); + cmTarget* autoRccTarget = this->LocalGen->AddUtilityCommand( + ccName, true, this->Dir.Work.c_str(), ccOutput, ccDepends, + commandLines, false, ccComment.c_str()); // Create autogen generator target this->LocalGen->AddGeneratorTarget( - new cmGeneratorTarget(autoRccTarget, this->LocalGen)); + cm::make_unique<cmGeneratorTarget>(autoRccTarget, this->LocalGen)); // Set FOLDER property in autogen target if (!this->TargetsFolder.empty()) { - autoRccTarget->SetProperty("FOLDER", this->TargetsFolder.c_str()); + autoRccTarget->SetProperty("FOLDER", this->TargetsFolder); } if (!this->Rcc.ExecutableTargetName.empty()) { autoRccTarget->AddUtility(this->Rcc.ExecutableTargetName, @@ -1241,7 +1247,7 @@ bool cmQtAutoGenInitializer::InitRccTargets() } std::string no_main_dependency; cmImplicitDependsList no_implicit_depends; - this->Makefile->AddCustomCommandToOutput( + this->LocalGen->AddCustomCommandToOutput( ccOutput, ccByproducts, ccDepends, no_main_dependency, no_implicit_depends, commandLines, ccComment.c_str(), this->Dir.Work.c_str()); @@ -1524,8 +1530,8 @@ bool cmQtAutoGenInitializer::AddToSourceGroup(std::string const& fileName, void cmQtAutoGenInitializer::AddCleanFile(std::string const& fileName) { - this->GenTarget->Target->AppendProperty("ADDITIONAL_CLEAN_FILES", - fileName.c_str(), false); + this->GenTarget->Target->AppendProperty("ADDITIONAL_CLEAN_FILES", fileName, + false); } void cmQtAutoGenInitializer::ConfigFileNames(ConfigString& configString, diff --git a/Source/cmQtAutoMocUic.cxx b/Source/cmQtAutoMocUic.cxx index f8b8981..fa5129d 100644 --- a/Source/cmQtAutoMocUic.cxx +++ b/Source/cmQtAutoMocUic.cxx @@ -16,13 +16,13 @@ #include <cm/memory> #include <cm/string_view> +#include <cmext/algorithm> #include "cmsys/FStream.hxx" #include "cmsys/RegularExpression.hxx" #include "cm_jsoncpp_value.h" -#include "cmAlgorithms.h" #include "cmCryptoHash.h" #include "cmFileTime.h" #include "cmGeneratedFileStream.h" @@ -808,9 +808,9 @@ void cmQtAutoMocUicT::JobMocPredefsT::Process() // Compose command std::vector<std::string> cmd = MocConst().PredefsCmd; // Add definitions - cmAppend(cmd, MocConst().OptionsDefinitions); + cm::append(cmd, MocConst().OptionsDefinitions); // Add includes - cmAppend(cmd, MocConst().OptionsIncludes); + cm::append(cmd, MocConst().OptionsIncludes); // Execute command if (!RunProcess(GenT::MOC, result, cmd, reason.get())) { LogCommandError(GenT::MOC, @@ -1916,9 +1916,9 @@ void cmQtAutoMocUicT::JobCompileMocT::Process() MocConst().OptionsExtra.size() + 16); cmd.push_back(MocConst().Executable); // Add definitions - cmAppend(cmd, MocConst().OptionsDefinitions); + cm::append(cmd, MocConst().OptionsDefinitions); // Add includes - cmAppend(cmd, MocConst().OptionsIncludes); + cm::append(cmd, MocConst().OptionsIncludes); // Add predefs include if (!MocConst().PredefsFileAbs.empty()) { cmd.emplace_back("--include"); @@ -1946,7 +1946,7 @@ void cmQtAutoMocUicT::JobCompileMocT::Process() } } // Add extra options - cmAppend(cmd, MocConst().OptionsExtra); + cm::append(cmd, MocConst().OptionsExtra); // Add output file cmd.emplace_back("-o"); cmd.push_back(outputFile); @@ -1994,7 +1994,7 @@ void cmQtAutoMocUicT::JobCompileUicT::Process() UicMergeOptions(allOpts, optionIt->second.Options, (BaseConst().QtVersionMajor == 5)); } - cmAppend(cmd, allOpts); + cm::append(cmd, allOpts); } cmd.emplace_back("-o"); cmd.emplace_back(outputFile); diff --git a/Source/cmQtAutoRcc.cxx b/Source/cmQtAutoRcc.cxx index 3af81ad..08eb4b5 100644 --- a/Source/cmQtAutoRcc.cxx +++ b/Source/cmQtAutoRcc.cxx @@ -6,7 +6,8 @@ #include <string> #include <vector> -#include "cmAlgorithms.h" +#include <cmext/algorithm> + #include "cmCryptoHash.h" #include "cmDuration.h" #include "cmFileLock.h" @@ -405,7 +406,7 @@ bool cmQtAutoRccT::GenerateRcc() // Compose rcc command std::vector<std::string> cmd; cmd.push_back(RccExecutable_); - cmAppend(cmd, Options_); + cm::append(cmd, Options_); cmd.emplace_back("-o"); cmd.push_back(RccFileOutput_); cmd.push_back(QrcFile_); diff --git a/Source/cmSetTargetPropertiesCommand.cxx b/Source/cmSetTargetPropertiesCommand.cxx index 8d917db..cd0fa40 100644 --- a/Source/cmSetTargetPropertiesCommand.cxx +++ b/Source/cmSetTargetPropertiesCommand.cxx @@ -4,7 +4,8 @@ #include <iterator> -#include "cmAlgorithms.h" +#include <cmext/algorithm> + #include "cmExecutionStatus.h" #include "cmMakefile.h" #include "cmStringAlgorithms.h" @@ -33,7 +34,7 @@ bool cmSetTargetPropertiesCommand(std::vector<std::string> const& args, status.SetError("called with incorrect number of arguments."); return false; } - cmAppend(propertyPairs, j, args.end()); + cm::append(propertyPairs, j, args.end()); break; } numFiles++; @@ -70,7 +71,7 @@ static bool SetOneTarget(const std::string& tname, // now loop through all the props and set them unsigned int k; for (k = 0; k < propertyPairs.size(); k = k + 2) { - target->SetProperty(propertyPairs[k], propertyPairs[k + 1].c_str()); + target->SetProperty(propertyPairs[k], propertyPairs[k + 1]); target->CheckProperty(propertyPairs[k], mf); } } diff --git a/Source/cmSetTestsPropertiesCommand.cxx b/Source/cmSetTestsPropertiesCommand.cxx index de61eda..2e7aeca 100644 --- a/Source/cmSetTestsPropertiesCommand.cxx +++ b/Source/cmSetTestsPropertiesCommand.cxx @@ -4,7 +4,8 @@ #include <iterator> -#include "cmAlgorithms.h" +#include <cmext/algorithm> + #include "cmExecutionStatus.h" #include "cmMakefile.h" #include "cmStringAlgorithms.h" @@ -36,7 +37,7 @@ bool cmSetTestsPropertiesCommand(std::vector<std::string> const& args, status.SetError("called with incorrect number of arguments."); return false; } - cmAppend(propertyPairs, j, args.end()); + cm::append(propertyPairs, j, args.end()); break; } numFiles++; diff --git a/Source/cmSourceFile.h b/Source/cmSourceFile.h index 82a3625..19a0d29 100644 --- a/Source/cmSourceFile.h +++ b/Source/cmSourceFile.h @@ -154,9 +154,8 @@ private: #define CM_HEADER_REGEX "\\.(h|hh|h\\+\\+|hm|hpp|hxx|in|txx|inl)$" #define CM_SOURCE_REGEX \ - "\\.(C|M|c|c\\+\\+|cc|cpp|cxx|cu|f|f90|for|fpp|ftn|m|mm|rc|def|r|odl|idl|" \ - "hpj" \ - "|bat)$" + "\\.(C|F|M|c|c\\+\\+|cc|cpp|cxx|cu|f|f90|for|fpp|ftn|m|mm|" \ + "rc|def|r|odl|idl|hpj|bat)$" #define CM_PCH_REGEX "cmake_pch\\.(h|hxx)$" diff --git a/Source/cmState.cxx b/Source/cmState.cxx index f9b5ed1..72f663d 100644 --- a/Source/cmState.cxx +++ b/Source/cmState.cxx @@ -615,6 +615,9 @@ const char* cmState::GetGlobalProperty(const std::string& prop) if (prop == "CMAKE_CXX14_KNOWN_FEATURES") { return &FOR_EACH_CXX14_FEATURE(STRING_LIST_ELEMENT)[1]; } + if (prop == "CMAKE_CUDA_KNOWN_FEATURES") { + return &FOR_EACH_CUDA_FEATURE(STRING_LIST_ELEMENT)[1]; + } #undef STRING_LIST_ELEMENT return this->GlobalProperties.GetPropertyValue(prop); @@ -712,6 +715,16 @@ bool cmState::UseMSYSShell() const return this->MSYSShell; } +void cmState::SetNinjaMulti(bool ninjaMulti) +{ + this->NinjaMulti = ninjaMulti; +} + +bool cmState::UseNinjaMulti() const +{ + return this->NinjaMulti; +} + unsigned int cmState::GetCacheMajorVersion() const { return this->CacheManager->GetCacheMajorVersion(); diff --git a/Source/cmState.h b/Source/cmState.h index a7ca015..cd871b9 100644 --- a/Source/cmState.h +++ b/Source/cmState.h @@ -190,6 +190,8 @@ public: bool UseNMake() const; void SetMSYSShell(bool mSYSShell); bool UseMSYSShell() const; + void SetNinjaMulti(bool ninjaMulti); + bool UseNinjaMulti() const; unsigned int GetCacheMajorVersion() const; unsigned int GetCacheMinorVersion() const; @@ -245,6 +247,7 @@ private: bool MinGWMake = false; bool NMake = false; bool MSYSShell = false; + bool NinjaMulti = false; Mode CurrentMode = Unknown; }; diff --git a/Source/cmStateDirectory.cxx b/Source/cmStateDirectory.cxx index 1262f53..97fdbbe 100644 --- a/Source/cmStateDirectory.cxx +++ b/Source/cmStateDirectory.cxx @@ -8,6 +8,7 @@ #include <vector> #include <cm/iterator> +#include <cmext/algorithm> #include "cmAlgorithms.h" #include "cmProperty.h" @@ -607,7 +608,7 @@ const char* cmStateDirectory::GetProperty(const std::string& prop, } if (prop == "VARIABLES") { std::vector<std::string> res = this->Snapshot_.ClosureKeys(); - cmAppend(res, this->Snapshot_.State->GetCacheEntryKeys()); + cm::append(res, this->Snapshot_.State->GetCacheEntryKeys()); std::sort(res.begin(), res.end()); output = cmJoin(res, ";"); return output.c_str(); diff --git a/Source/cmStateSnapshot.cxx b/Source/cmStateSnapshot.cxx index 645907c..832e74e 100644 --- a/Source/cmStateSnapshot.cxx +++ b/Source/cmStateSnapshot.cxx @@ -315,10 +315,14 @@ void cmStateSnapshot::SetDefaultDefinitions() this->SetDefinition("UNIX", "1"); this->SetDefinition("CMAKE_HOST_UNIX", "1"); +# if defined(__ANDROID__) + this->SetDefinition("CMAKE_HOST_SYSTEM_NAME", "Android"); +# else struct utsname uts_name; if (uname(&uts_name) >= 0) { this->SetDefinition("CMAKE_HOST_SYSTEM_NAME", uts_name.sysname); } +# endif #endif #if defined(__CYGWIN__) std::string legacy; diff --git a/Source/cmSystemTools.cxx b/Source/cmSystemTools.cxx index c4a4220..9127c50 100644 --- a/Source/cmSystemTools.cxx +++ b/Source/cmSystemTools.cxx @@ -2,9 +2,10 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmSystemTools.h" +#include <cmext/algorithm> + #include "cm_uv.h" -#include "cmAlgorithms.h" #include "cmDuration.h" #include "cmProcessOutput.h" #include "cmRange.h" @@ -360,7 +361,7 @@ std::vector<std::string> cmSystemTools::HandleResponseFile( #else cmSystemTools::ParseUnixCommandLine(line.c_str(), args2); #endif - cmAppend(arg_full, args2); + cm::append(arg_full, args2); } } else { arg_full.push_back(arg); @@ -585,7 +586,7 @@ bool cmSystemTools::RunSingleCommand(std::vector<std::string> const& command, cmSystemTools::Stdout(strdata); } if (captureStdOut) { - cmAppend(tempStdOut, data, data + length); + cm::append(tempStdOut, data, data + length); } } else if (pipe == cmsysProcess_Pipe_STDERR) { if (outputflag != OUTPUT_NONE) { @@ -593,7 +594,7 @@ bool cmSystemTools::RunSingleCommand(std::vector<std::string> const& command, cmSystemTools::Stderr(strdata); } if (captureStdErr) { - cmAppend(tempStdErr, data, data + length); + cm::append(tempStdErr, data, data + length); } } } @@ -814,6 +815,8 @@ void cmSystemTools::InitializeLibUV() # else _fmode = _O_TEXT; # endif + // Replace libuv's report handler with our own to suppress popups. + cmSystemTools::EnableMSVCDebugHook(); #endif } @@ -1710,26 +1713,26 @@ int cmSystemTools::WaitForLine(cmsysProcess* process, std::string& line, processOutput.DecodeText(data, length, strdata, 1); // Append to the stdout buffer. std::vector<char>::size_type size = out.size(); - cmAppend(out, strdata); + cm::append(out, strdata); outiter = out.begin() + size; } else if (pipe == cmsysProcess_Pipe_STDERR) { processOutput.DecodeText(data, length, strdata, 2); // Append to the stderr buffer. std::vector<char>::size_type size = err.size(); - cmAppend(err, strdata); + cm::append(err, strdata); erriter = err.begin() + size; } else if (pipe == cmsysProcess_Pipe_None) { // Both stdout and stderr pipes have broken. Return leftover data. processOutput.DecodeText(std::string(), strdata, 1); if (!strdata.empty()) { std::vector<char>::size_type size = out.size(); - cmAppend(out, strdata); + cm::append(out, strdata); outiter = out.begin() + size; } processOutput.DecodeText(std::string(), strdata, 2); if (!strdata.empty()) { std::vector<char>::size_type size = err.size(); - cmAppend(err, strdata); + cm::append(err, strdata); erriter = err.begin() + size; } if (!out.empty()) { diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx index 2db89de..d2693b8 100644 --- a/Source/cmTarget.cxx +++ b/Source/cmTarget.cxx @@ -12,6 +12,7 @@ #include <unordered_set> #include <cm/memory> +#include <cmext/algorithm> #include "cmsys/RegularExpression.hxx" @@ -176,6 +177,7 @@ public: bool IsImportedTarget; bool ImportedGloballyVisible; bool BuildInterfaceIncludesAppended; + bool PerConfig; std::set<BT<std::string>> Utilities; std::vector<cmCustomCommand> PreBuildCommands; std::vector<cmCustomCommand> PreLinkCommands; @@ -213,7 +215,7 @@ public: }; cmTarget::cmTarget(std::string const& name, cmStateEnums::TargetType type, - Visibility vis, cmMakefile* mf) + Visibility vis, cmMakefile* mf, bool perConfig) : impl(cm::make_unique<cmTargetInternals>()) { assert(mf); @@ -229,6 +231,7 @@ cmTarget::cmTarget(std::string const& name, cmStateEnums::TargetType type, (vis == VisibilityImported || vis == VisibilityImportedGlobally); impl->ImportedGloballyVisible = vis == VisibilityImportedGlobally; impl->BuildInterfaceIncludesAppended = false; + impl->PerConfig = perConfig; // Check whether this is a DLL platform. impl->IsDLLPlatform = @@ -371,6 +374,7 @@ cmTarget::cmTarget(std::string const& name, cmStateEnums::TargetType type, initProp("XCODE_SCHEME_THREAD_SANITIZER_STOP"); initProp("XCODE_SCHEME_UNDEFINED_BEHAVIOUR_SANITIZER"); initProp("XCODE_SCHEME_UNDEFINED_BEHAVIOUR_SANITIZER_STOP"); + initProp("XCODE_SCHEME_WORKING_DIRECTORY"); initProp("XCODE_SCHEME_DISABLE_MAIN_THREAD_CHECKER"); initProp("XCODE_SCHEME_MAIN_THREAD_CHECKER_STOP"); initProp("XCODE_SCHEME_MALLOC_SCRIBBLE"); @@ -380,6 +384,7 @@ cmTarget::cmTarget(std::string const& name, cmStateEnums::TargetType type, initProp("XCODE_SCHEME_MALLOC_STACK"); initProp("XCODE_SCHEME_DYNAMIC_LINKER_API_USAGE"); initProp("XCODE_SCHEME_DYNAMIC_LIBRARY_LOADS"); + initProp("XCODE_SCHEME_ENVIRONMENT"); } #endif } @@ -435,30 +440,30 @@ cmTarget::cmTarget(std::string const& name, cmStateEnums::TargetType type, if (!this->IsImported()) { // Initialize the INCLUDE_DIRECTORIES property based on the current value // of the same directory property: - cmAppend(impl->IncludeDirectoriesEntries, - impl->Makefile->GetIncludeDirectoriesEntries()); - cmAppend(impl->IncludeDirectoriesBacktraces, - impl->Makefile->GetIncludeDirectoriesBacktraces()); + cm::append(impl->IncludeDirectoriesEntries, + impl->Makefile->GetIncludeDirectoriesEntries()); + cm::append(impl->IncludeDirectoriesBacktraces, + impl->Makefile->GetIncludeDirectoriesBacktraces()); { auto const& sysInc = impl->Makefile->GetSystemIncludeDirectories(); impl->SystemIncludeDirectories.insert(sysInc.begin(), sysInc.end()); } - cmAppend(impl->CompileOptionsEntries, - impl->Makefile->GetCompileOptionsEntries()); - cmAppend(impl->CompileOptionsBacktraces, - impl->Makefile->GetCompileOptionsBacktraces()); + cm::append(impl->CompileOptionsEntries, + impl->Makefile->GetCompileOptionsEntries()); + cm::append(impl->CompileOptionsBacktraces, + impl->Makefile->GetCompileOptionsBacktraces()); - cmAppend(impl->LinkOptionsEntries, - impl->Makefile->GetLinkOptionsEntries()); - cmAppend(impl->LinkOptionsBacktraces, - impl->Makefile->GetLinkOptionsBacktraces()); + cm::append(impl->LinkOptionsEntries, + impl->Makefile->GetLinkOptionsEntries()); + cm::append(impl->LinkOptionsBacktraces, + impl->Makefile->GetLinkOptionsBacktraces()); - cmAppend(impl->LinkDirectoriesEntries, - impl->Makefile->GetLinkDirectoriesEntries()); - cmAppend(impl->LinkDirectoriesBacktraces, - impl->Makefile->GetLinkDirectoriesBacktraces()); + cm::append(impl->LinkDirectoriesEntries, + impl->Makefile->GetLinkDirectoriesEntries()); + cm::append(impl->LinkDirectoriesBacktraces, + impl->Makefile->GetLinkDirectoriesBacktraces()); } if (this->GetType() != cmStateEnums::INTERFACE_LIBRARY && @@ -511,8 +516,7 @@ cmTarget::cmTarget(std::string const& name, cmStateEnums::TargetType type, initProp("DOTNET_TARGET_FRAMEWORK_VERSION"); } - if (this->GetType() != cmStateEnums::INTERFACE_LIBRARY && - this->GetType() != cmStateEnums::UTILITY) { + if (this->GetType() != cmStateEnums::INTERFACE_LIBRARY) { // check for "CMAKE_VS_GLOBALS" variable and set up target properties // if any @@ -948,9 +952,8 @@ void cmTarget::AddLinkLibrary(cmMakefile& mf, std::string const& lib, (isNonImportedTarget && llt != GENERAL_LibraryType) ? targetNameGenex(libRef) : libRef; - this->AppendProperty( - "LINK_LIBRARIES", - this->GetDebugGeneratorExpressions(libName, llt).c_str()); + this->AppendProperty("LINK_LIBRARIES", + this->GetDebugGeneratorExpressions(libName, llt)); } if (cmGeneratorExpression::Find(lib) != std::string::npos || lib != libRef || @@ -1284,9 +1287,9 @@ void cmTarget::SetProperty(const std::string& prop, const char* value) impl->Properties.SetProperty(prop, reusedFrom.c_str()); - reusedTarget->SetProperty("COMPILE_PDB_NAME", reusedFrom.c_str()); + reusedTarget->SetProperty("COMPILE_PDB_NAME", reusedFrom); reusedTarget->SetProperty("COMPILE_PDB_OUTPUT_DIRECTORY", - cmStrCat(reusedFrom, ".dir/").c_str()); + cmStrCat(reusedFrom, ".dir/")); this->SetProperty("COMPILE_PDB_NAME", reusedTarget->GetProperty("COMPILE_PDB_NAME")); @@ -1421,7 +1424,7 @@ void cmTarget::AppendBuildInterfaceIncludes() dirs += impl->Makefile->GetCurrentSourceDirectory(); if (!dirs.empty()) { this->AppendProperty("INTERFACE_INCLUDE_DIRECTORIES", - ("$<BUILD_INTERFACE:" + dirs + ">").c_str()); + ("$<BUILD_INTERFACE:" + dirs + ">")); } } } @@ -1799,6 +1802,11 @@ bool cmTarget::IsImportedGloballyVisible() const return impl->ImportedGloballyVisible; } +bool cmTarget::IsPerConfig() const +{ + return impl->PerConfig; +} + const char* cmTarget::GetSuffixVariableInternal( cmStateEnums::ArtifactType artifact) const { diff --git a/Source/cmTarget.h b/Source/cmTarget.h index 65a1ce3..bdf8c0f 100644 --- a/Source/cmTarget.h +++ b/Source/cmTarget.h @@ -44,7 +44,7 @@ public: }; cmTarget(std::string const& name, cmStateEnums::TargetType type, - Visibility vis, cmMakefile* mf); + Visibility vis, cmMakefile* mf, bool perConfig); cmTarget(cmTarget const&) = delete; cmTarget(cmTarget&&) noexcept; @@ -164,8 +164,17 @@ public: //! Set/Get a property of this target file void SetProperty(const std::string& prop, const char* value); + void SetProperty(const std::string& prop, const std::string& value) + { + SetProperty(prop, value.c_str()); + } void AppendProperty(const std::string& prop, const char* value, bool asString = false); + void AppendProperty(const std::string& prop, const std::string& value, + bool asString = false) + { + AppendProperty(prop, value.c_str(), asString); + } //! Might return a nullptr if the property is not set or invalid const char* GetProperty(const std::string& prop) const; //! Always returns a valid pointer @@ -186,6 +195,7 @@ public: bool IsImported() const; bool IsImportedGloballyVisible() const; + bool IsPerConfig() const; bool GetMappedConfig(std::string const& desired_config, const char** loc, const char** imp, std::string& suffix) const; diff --git a/Source/cmTargetCompileDefinitionsCommand.cxx b/Source/cmTargetCompileDefinitionsCommand.cxx index edee167..b56b245 100644 --- a/Source/cmTargetCompileDefinitionsCommand.cxx +++ b/Source/cmTargetCompileDefinitionsCommand.cxx @@ -28,7 +28,7 @@ private: const std::vector<std::string>& content, bool /*prepend*/, bool /*system*/) override { - tgt->AppendProperty("COMPILE_DEFINITIONS", this->Join(content).c_str()); + tgt->AppendProperty("COMPILE_DEFINITIONS", this->Join(content)); return true; // Successfully handled. } diff --git a/Source/cmTargetIncludeDirectoriesCommand.cxx b/Source/cmTargetIncludeDirectoriesCommand.cxx index 95b69f3..35635b9 100644 --- a/Source/cmTargetIncludeDirectoriesCommand.cxx +++ b/Source/cmTargetIncludeDirectoriesCommand.cxx @@ -88,8 +88,7 @@ void TargetIncludeDirectoriesImpl::HandleInterfaceContent( system); if (system) { std::string joined = this->Join(content); - tgt->AppendProperty("INTERFACE_SYSTEM_INCLUDE_DIRECTORIES", - joined.c_str()); + tgt->AppendProperty("INTERFACE_SYSTEM_INCLUDE_DIRECTORIES", joined); } } diff --git a/Source/cmTargetLinkLibrariesCommand.cxx b/Source/cmTargetLinkLibrariesCommand.cxx index 0d2383a..e1ac6a8 100644 --- a/Source/cmTargetLinkLibrariesCommand.cxx +++ b/Source/cmTargetLinkLibrariesCommand.cxx @@ -480,7 +480,7 @@ static bool HandleLibrary(cmMakefile& mf, cmTarget* target, cmGeneratorExpression::Find(lib) != std::string::npos) { configLib = "$<LINK_ONLY:" + configLib + ">"; } - target->AppendProperty("INTERFACE_LINK_LIBRARIES", configLib.c_str()); + target->AppendProperty("INTERFACE_LINK_LIBRARIES", configLib); } return true; } @@ -488,9 +488,8 @@ static bool HandleLibrary(cmMakefile& mf, cmTarget* target, // Handle general case where the command was called with another keyword than // PRIVATE / LINK_PRIVATE or none at all. (The "INTERFACE_LINK_LIBRARIES" // property of the target on the LHS shall be populated.) - target->AppendProperty( - "INTERFACE_LINK_LIBRARIES", - target->GetDebugGeneratorExpressions(libRef, llt).c_str()); + target->AppendProperty("INTERFACE_LINK_LIBRARIES", + target->GetDebugGeneratorExpressions(libRef, llt)); // Stop processing if called without any keyword. if (currentProcessingState == ProcessingLinkLibraries) { @@ -522,12 +521,12 @@ static bool HandleLibrary(cmMakefile& mf, cmTarget* target, // Put in the DEBUG configuration interfaces. for (std::string const& dc : debugConfigs) { prop = cmStrCat("LINK_INTERFACE_LIBRARIES_", dc); - target->AppendProperty(prop, libRef.c_str()); + target->AppendProperty(prop, libRef); } } if (llt == OPTIMIZED_LibraryType || llt == GENERAL_LibraryType) { // Put in the non-DEBUG configuration interfaces. - target->AppendProperty("LINK_INTERFACE_LIBRARIES", libRef.c_str()); + target->AppendProperty("LINK_INTERFACE_LIBRARIES", libRef); // Make sure the DEBUG configuration interfaces exist so that the // general one will not be used as a fall-back. diff --git a/Source/cmTargetPrecompileHeadersCommand.cxx b/Source/cmTargetPrecompileHeadersCommand.cxx index c6e2e5c..0670bd9 100644 --- a/Source/cmTargetPrecompileHeadersCommand.cxx +++ b/Source/cmTargetPrecompileHeadersCommand.cxx @@ -47,9 +47,8 @@ private: bool /*prepend*/, bool /*system*/) override { std::string const& base = this->Makefile->GetCurrentSourceDirectory(); - tgt->AppendProperty( - "PRECOMPILE_HEADERS", - this->Join(ConvertToAbsoluteContent(content, base)).c_str()); + tgt->AppendProperty("PRECOMPILE_HEADERS", + this->Join(ConvertToAbsoluteContent(content, base))); return true; } diff --git a/Source/cmTargetPropCommandBase.cxx b/Source/cmTargetPropCommandBase.cxx index bbc1e16..0de8d6d 100644 --- a/Source/cmTargetPropCommandBase.cxx +++ b/Source/cmTargetPropCommandBase.cxx @@ -84,9 +84,7 @@ bool cmTargetPropCommandBase::HandleArguments( } ++argIndex; - this->Target->SetProperty("PRECOMPILE_HEADERS_REUSE_FROM", - args[argIndex].c_str()); - + this->Target->SetProperty("PRECOMPILE_HEADERS_REUSE_FROM", args[argIndex]); ++argIndex; } @@ -162,9 +160,8 @@ void cmTargetPropCommandBase::HandleInterfaceContent( const char* propValue = tgt->GetProperty(propName); const std::string totalContent = this->Join(content) + (propValue ? std::string(";") + propValue : std::string()); - tgt->SetProperty(propName, totalContent.c_str()); + tgt->SetProperty(propName, totalContent); } else { - tgt->AppendProperty("INTERFACE_" + this->Property, - this->Join(content).c_str()); + tgt->AppendProperty("INTERFACE_" + this->Property, this->Join(content)); } } diff --git a/Source/cmTargetSourcesCommand.cxx b/Source/cmTargetSourcesCommand.cxx index c2e0b28..a1fbc9b 100644 --- a/Source/cmTargetSourcesCommand.cxx +++ b/Source/cmTargetSourcesCommand.cxx @@ -43,8 +43,7 @@ private: bool /*prepend*/, bool /*system*/) override { tgt->AppendProperty( - "SOURCES", - this->Join(ConvertToAbsoluteContent(tgt, content, false)).c_str()); + "SOURCES", this->Join(ConvertToAbsoluteContent(tgt, content, false))); return true; // Successfully handled. } diff --git a/Source/cmVariableWatch.cxx b/Source/cmVariableWatch.cxx index 4995da9..35e1c8c 100644 --- a/Source/cmVariableWatch.cxx +++ b/Source/cmVariableWatch.cxx @@ -2,19 +2,19 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmVariableWatch.h" +#include <array> #include <memory> #include <utility> #include <vector> -static const char* const cmVariableWatchAccessStrings[] = { - "READ_ACCESS", "UNKNOWN_READ_ACCESS", "UNKNOWN_DEFINED_ACCESS", - "MODIFIED_ACCESS", "REMOVED_ACCESS", "NO_ACCESS" -}; - -const char* cmVariableWatch::GetAccessAsString(int access_type) +const std::string& cmVariableWatch::GetAccessAsString(int access_type) { + static const std::array<std::string, 6> cmVariableWatchAccessStrings = { + { "READ_ACCESS", "UNKNOWN_READ_ACCESS", "UNKNOWN_DEFINED_ACCESS", + "MODIFIED_ACCESS", "REMOVED_ACCESS", "NO_ACCESS" } + }; if (access_type < 0 || access_type >= cmVariableWatch::NO_ACCESS) { - return "NO_ACCESS"; + access_type = cmVariableWatch::NO_ACCESS; } return cmVariableWatchAccessStrings[access_type]; } diff --git a/Source/cmVariableWatch.h b/Source/cmVariableWatch.h index e4b3b7c..6c418ed 100644 --- a/Source/cmVariableWatch.h +++ b/Source/cmVariableWatch.h @@ -46,7 +46,7 @@ public: */ enum { - VARIABLE_READ_ACCESS = 0, + VARIABLE_READ_ACCESS, UNKNOWN_VARIABLE_READ_ACCESS, UNKNOWN_VARIABLE_DEFINED_ACCESS, VARIABLE_MODIFIED_ACCESS, @@ -57,7 +57,7 @@ public: /** * Return the access as string */ - static const char* GetAccessAsString(int access_type); + static const std::string& GetAccessAsString(int access_type); protected: struct Pair diff --git a/Source/cmVariableWatchCommand.cxx b/Source/cmVariableWatchCommand.cxx index f2c8f3c..35b9a1d 100644 --- a/Source/cmVariableWatchCommand.cxx +++ b/Source/cmVariableWatchCommand.cxx @@ -2,6 +2,7 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmVariableWatchCommand.h" +#include <limits> #include <memory> #include <utility> @@ -14,17 +15,19 @@ #include "cmVariableWatch.h" #include "cmake.h" +class cmLocalGenerator; + +namespace { struct cmVariableWatchCallbackData { bool InCallback; std::string Command; }; -static void cmVariableWatchCommandVariableAccessed(const std::string& variable, - int access_type, - void* client_data, - const char* newValue, - const cmMakefile* mf) +void cmVariableWatchCommandVariableAccessed(const std::string& variable, + int access_type, void* client_data, + const char* newValue, + const cmMakefile* mf) { cmVariableWatchCallbackData* data = static_cast<cmVariableWatchCallbackData*>(client_data); @@ -34,40 +37,35 @@ static void cmVariableWatchCommandVariableAccessed(const std::string& variable, } data->InCallback = true; - cmListFileFunction newLFF; - cmListFileArgument arg; - bool processed = false; - const char* accessString = cmVariableWatch::GetAccessAsString(access_type); - const char* currentListFile = mf->GetDefinition("CMAKE_CURRENT_LIST_FILE"); + auto accessString = cmVariableWatch::GetAccessAsString(access_type); /// Ultra bad!! cmMakefile* makefile = const_cast<cmMakefile*>(mf); std::string stack = makefile->GetProperty("LISTFILE_STACK"); if (!data->Command.empty()) { - newLFF.Arguments.clear(); - newLFF.Arguments.emplace_back(variable, cmListFileArgument::Quoted, 9999); - newLFF.Arguments.emplace_back(accessString, cmListFileArgument::Quoted, - 9999); - newLFF.Arguments.emplace_back(newValue ? newValue : "", - cmListFileArgument::Quoted, 9999); - newLFF.Arguments.emplace_back(currentListFile, cmListFileArgument::Quoted, - 9999); - newLFF.Arguments.emplace_back(stack, cmListFileArgument::Quoted, 9999); + cmListFileFunction newLFF; + const char* const currentListFile = + mf->GetDefinition("CMAKE_CURRENT_LIST_FILE"); + const auto fakeLineNo = + std::numeric_limits<decltype(cmListFileArgument::Line)>::max(); + newLFF.Arguments = { + { variable, cmListFileArgument::Quoted, fakeLineNo }, + { accessString, cmListFileArgument::Quoted, fakeLineNo }, + { newValue ? newValue : "", cmListFileArgument::Quoted, fakeLineNo }, + { currentListFile, cmListFileArgument::Quoted, fakeLineNo }, + { stack, cmListFileArgument::Quoted, fakeLineNo } + }; newLFF.Name = data->Command; - newLFF.Line = 9999; + newLFF.Line = fakeLineNo; cmExecutionStatus status(*makefile); if (!makefile->ExecuteCommand(newLFF, status)) { cmSystemTools::Error( cmStrCat("Error in cmake code at\nUnknown:0:\nA command failed " "during the invocation of callback \"", data->Command, "\".")); - data->InCallback = false; - return; } - processed = true; - } - if (!processed) { + } else { makefile->IssueMessage( MessageType::LOG, cmStrCat("Variable \"", variable, "\" was accessed using ", accessString, @@ -77,7 +75,7 @@ static void cmVariableWatchCommandVariableAccessed(const std::string& variable, data->InCallback = false; } -static void deleteVariableWatchCallbackData(void* client_data) +void deleteVariableWatchCallbackData(void* client_data) { cmVariableWatchCallbackData* data = static_cast<cmVariableWatchCallbackData*>(client_data); @@ -91,18 +89,18 @@ class FinalAction public: /* NOLINTNEXTLINE(performance-unnecessary-value-param) */ FinalAction(cmMakefile* makefile, std::string variable) - : Action(std::make_shared<Impl>(makefile, std::move(variable))) + : Action{ std::make_shared<Impl>(makefile, std::move(variable)) } { } - void operator()(cmMakefile&) const {} + void operator()(cmLocalGenerator&, const cmListFileBacktrace&) const {} private: struct Impl { Impl(cmMakefile* makefile, std::string variable) - : Makefile(makefile) - , Variable(std::move(variable)) + : Makefile{ makefile } + , Variable{ std::move(variable) } { } @@ -112,12 +110,13 @@ private: this->Variable, cmVariableWatchCommandVariableAccessed); } - cmMakefile* Makefile; - std::string Variable; + cmMakefile* const Makefile; + std::string const Variable; }; std::shared_ptr<Impl const> Action; }; +} // anonymous namespace bool cmVariableWatchCommand(std::vector<std::string> const& args, cmExecutionStatus& status) @@ -136,10 +135,10 @@ bool cmVariableWatchCommand(std::vector<std::string> const& args, return false; } - cmVariableWatchCallbackData* data = new cmVariableWatchCallbackData; + auto* const data = new cmVariableWatchCallbackData; data->InCallback = false; - data->Command = command; + data->Command = std::move(command); if (!status.GetMakefile().GetCMakeInstance()->GetVariableWatch()->AddWatch( variable, cmVariableWatchCommandVariableAccessed, data, @@ -148,7 +147,7 @@ bool cmVariableWatchCommand(std::vector<std::string> const& args, return false; } - status.GetMakefile().AddFinalAction( - FinalAction(&status.GetMakefile(), variable)); + status.GetMakefile().AddGeneratorAction( + FinalAction{ &status.GetMakefile(), variable }); return true; } diff --git a/Source/cmVisualStudio10TargetGenerator.cxx b/Source/cmVisualStudio10TargetGenerator.cxx index 53fc93c..f707bb4 100644 --- a/Source/cmVisualStudio10TargetGenerator.cxx +++ b/Source/cmVisualStudio10TargetGenerator.cxx @@ -52,7 +52,7 @@ struct cmVisualStudio10TargetGenerator::Elem bool HasContent = false; std::string Tag; - Elem(std::ostream& s, const char* tag) + Elem(std::ostream& s, const std::string& tag) : S(s) , Indent(0) , Tag(tag) @@ -60,7 +60,7 @@ struct cmVisualStudio10TargetGenerator::Elem this->StartElement(); } Elem(const Elem&) = delete; - Elem(Elem& par, const char* tag) + Elem(Elem& par, const std::string& tag) : S(par.S) , Indent(par.Indent + 1) , Tag(tag) @@ -71,13 +71,13 @@ struct cmVisualStudio10TargetGenerator::Elem void SetHasElements() { if (!HasElements) { - this->S << ">\n"; + this->S << ">"; HasElements = true; } } std::ostream& WriteString(const char* line); void StartElement() { this->WriteString("<") << this->Tag; } - void Element(const char* tag, const std::string& val) + void Element(const std::string& tag, const std::string& val) { Elem(*this, tag).Content(val); } @@ -103,19 +103,14 @@ struct cmVisualStudio10TargetGenerator::Elem if (HasElements) { this->WriteString("</") << this->Tag << ">"; - if (this->Indent > 0) { - this->S << '\n'; - } else { - // special case: don't print EOL at EOF - } } else if (HasContent) { - this->S << "</" << this->Tag << ">\n"; + this->S << "</" << this->Tag << ">"; } else { - this->S << " />\n"; + this->S << " />"; } } - void WritePlatformConfigTag(const char* tag, const std::string& cond, + void WritePlatformConfigTag(const std::string& tag, const std::string& cond, const std::string& content); }; @@ -131,8 +126,8 @@ public: { } - void OutputFlag(std::ostream& /*fout*/, int /*indent*/, const char* tag, - const std::string& content) override + void OutputFlag(std::ostream& /*fout*/, int /*indent*/, + const std::string& tag, const std::string& content) override { if (!this->GetConfiguration().empty()) { // if there are configuration specific flags, then @@ -274,7 +269,7 @@ std::string cmVisualStudio10TargetGenerator::CalcCondition( } void cmVisualStudio10TargetGenerator::Elem::WritePlatformConfigTag( - const char* tag, const std::string& cond, const std::string& content) + const std::string& tag, const std::string& cond, const std::string& content) { Elem(*this, tag).Attribute("Condition", cond).Content(content); } @@ -282,6 +277,7 @@ void cmVisualStudio10TargetGenerator::Elem::WritePlatformConfigTag( std::ostream& cmVisualStudio10TargetGenerator::Elem::WriteString( const char* line) { + this->S << '\n'; this->S.fill(' '); this->S.width(this->Indent * 2); // write an empty string to get the fill level indent to print @@ -334,9 +330,9 @@ void cmVisualStudio10TargetGenerator::Generate() } // Tell the global generator the name of the project file this->GeneratorTarget->Target->SetProperty("GENERATOR_FILE_NAME", - this->Name.c_str()); + this->Name); this->GeneratorTarget->Target->SetProperty("GENERATOR_FILE_NAME_EXT", - ProjectFileExtension.c_str()); + ProjectFileExtension); this->DotNetHintReferences.clear(); this->AdditionalUsingDirectories.clear(); if (this->GeneratorTarget->GetType() <= cmStateEnums::OBJECT_LIBRARY) { @@ -376,8 +372,7 @@ void cmVisualStudio10TargetGenerator::Generate() char magic[] = { char(0xEF), char(0xBB), char(0xBF) }; BuildFileStream.write(magic, 3); BuildFileStream << "<?xml version=\"1.0\" encoding=\"" - << this->GlobalGenerator->Encoding() << "\"?>" - << "\n"; + << this->GlobalGenerator->Encoding() << "\"?>"; { Elem e0(BuildFileStream, "Project"); e0.Attribute("DefaultTargets", "Build"); @@ -543,6 +538,11 @@ void cmVisualStudio10TargetGenerator::Generate() e1.Element("VCProjectUpgraderObjectName", "NoUpgrade"); } + if (const char* vcTargetsPath = + this->GlobalGenerator->GetCustomVCTargetsPath()) { + e1.Element("VCTargetsPath", vcTargetsPath); + } + std::vector<std::string> keys = this->GeneratorTarget->GetPropertyKeys(); for (std::string const& keyIt : keys) { static const char* prefix = "VS_GLOBAL_"; @@ -557,7 +557,7 @@ void cmVisualStudio10TargetGenerator::Generate() const char* value = this->GeneratorTarget->GetProperty(keyIt); if (!value) continue; - e1.Element(globalKey.c_str(), value); + e1.Element(globalKey, value); } if (this->Managed) { @@ -676,6 +676,8 @@ void cmVisualStudio10TargetGenerator::Generate() this->WritePlatformExtensions(e1); } + + this->WriteDotNetDocumentationFile(e0); Elem(e0, "PropertyGroup").Attribute("Label", "UserMacros"); this->WriteWinRTPackageCertificateKeyFile(e0); this->WritePathAndIncrementalLinkOptions(e0); @@ -906,7 +908,19 @@ void cmVisualStudio10TargetGenerator::WriteDotNetReferenceCustomTags( } } for (auto const& tag : tags) { - e2.Element(tag.first.c_str(), tag.second); + e2.Element(tag.first, tag.second); + } +} + +void cmVisualStudio10TargetGenerator::WriteDotNetDocumentationFile(Elem& e0) +{ + std::string const documentationFile = + this->GeneratorTarget->GetSafeProperty("VS_DOTNET_DOCUMENTATION_FILE"); + + if (this->ProjectType == csproj && !documentationFile.empty()) { + Elem e1(e0, "PropertyGroup"); + Elem e2(e1, "DocumentationFile"); + e2.Content(documentationFile); } } @@ -1000,7 +1014,7 @@ void cmVisualStudio10TargetGenerator::WriteEmbeddedResourceGroup(Elem& e0) if (!tagName.empty()) { std::string value = props.GetPropertyValue(p); if (!value.empty()) { - e2.Element(tagName.c_str(), value); + e2.Element(tagName, value); } } } @@ -1592,8 +1606,7 @@ void cmVisualStudio10TargetGenerator::WriteGroups() fout.write(magic, 3); fout << "<?xml version=\"1.0\" encoding=\"" - << this->GlobalGenerator->Encoding() << "\"?>" - << "\n"; + << this->GlobalGenerator->Encoding() << "\"?>"; { Elem e0(fout, "Project"); e0.Attribute("ToolsVersion", this->GlobalGenerator->GetToolsVersion()); @@ -1732,7 +1745,7 @@ void cmVisualStudio10TargetGenerator::WriteGroupSources( std::string const& filter = sourceGroup->GetFullName(); std::string path = this->ConvertPath(source, s.RelativePath); ConvertToWindowsSlash(path); - Elem e2(e1, name.c_str()); + Elem e2(e1, name); e2.Attribute("Include", path); if (!filter.empty()) { e2.Element("Filter", filter); @@ -2622,9 +2635,9 @@ void cmVisualStudio10TargetGenerator::OutputLinkIncremental( // Some link options belong here. Use them now and remove them so that // WriteLinkOptions does not use them. - const char* flags[] = { "LinkDelaySign", "LinkKeyFile", 0 }; - for (const char** f = flags; *f; ++f) { - const char* flag = *f; + static const std::vector<std::string> flags{ "LinkDelaySign", + "LinkKeyFile" }; + for (const std::string& flag : flags) { if (const char* value = linkOptions.GetFlag(flag)) { e1.WritePlatformConfigTag(flag, cond, value); linkOptions.RemoveFlag(flag); @@ -2816,10 +2829,8 @@ bool cmVisualStudio10TargetGenerator::ComputeClOptions( } if (this->MSTools) { - // If we have the VS_WINRT_COMPONENT or CMAKE_VS_WINRT_BY_DEFAULT - // set then force Compile as WinRT. - if (this->GeneratorTarget->GetPropertyAsBool("VS_WINRT_COMPONENT") || - this->Makefile->IsOn("CMAKE_VS_WINRT_BY_DEFAULT")) { + // If we have the VS_WINRT_COMPONENT set then force Compile as WinRT + if (this->GeneratorTarget->GetPropertyAsBool("VS_WINRT_COMPONENT")) { clOptions.AddFlag("CompileAsWinRT", "true"); // For WinRT components, add the _WINRT_DLL define to produce a lib if (this->GeneratorTarget->GetType() == cmStateEnums::SHARED_LIBRARY || @@ -2827,7 +2838,8 @@ bool cmVisualStudio10TargetGenerator::ComputeClOptions( clOptions.AddDefine("_WINRT_DLL"); } } else if (this->GlobalGenerator->TargetsWindowsStore() || - this->GlobalGenerator->TargetsWindowsPhone()) { + this->GlobalGenerator->TargetsWindowsPhone() || + this->Makefile->IsOn("CMAKE_VS_WINRT_BY_DEFAULT")) { if (!clOptions.IsWinRt()) { clOptions.AddFlag("CompileAsWinRT", "false"); } @@ -4025,8 +4037,8 @@ void cmVisualStudio10TargetGenerator::WriteEvents( } void cmVisualStudio10TargetGenerator::WriteEvent( - Elem& e1, const char* name, std::vector<cmCustomCommand> const& commands, - std::string const& configName) + Elem& e1, const std::string& name, + std::vector<cmCustomCommand> const& commands, std::string const& configName) { if (commands.empty()) { return; @@ -4845,7 +4857,7 @@ void cmVisualStudio10TargetGenerator::WriteCSharpSourceProperties( Elem& e2, const std::map<std::string, std::string>& tags) { for (const auto& i : tags) { - e2.Element(i.first.c_str(), i.second); + e2.Element(i.first, i.second); } } diff --git a/Source/cmVisualStudio10TargetGenerator.h b/Source/cmVisualStudio10TargetGenerator.h index a18a33d..30027c9 100644 --- a/Source/cmVisualStudio10TargetGenerator.h +++ b/Source/cmVisualStudio10TargetGenerator.h @@ -79,6 +79,7 @@ private: void WriteDotNetReference(Elem& e1, std::string const& ref, std::string const& hint, std::string const& config); + void WriteDotNetDocumentationFile(Elem& e0); void WriteImports(Elem& e0); void WriteDotNetReferenceCustomTags(Elem& e2, std::string const& ref); void WriteEmbeddedResourceGroup(Elem& e0); @@ -164,7 +165,7 @@ private: void WriteLibOptions(Elem& e1, std::string const& config); void WriteManifestOptions(Elem& e1, std::string const& config); void WriteEvents(Elem& e1, std::string const& configName); - void WriteEvent(Elem& e1, const char* name, + void WriteEvent(Elem& e1, std::string const& name, std::vector<cmCustomCommand> const& commands, std::string const& configName); void WriteGroupSources(Elem& e0, std::string const& name, diff --git a/Source/cmVisualStudioGeneratorOptions.cxx b/Source/cmVisualStudioGeneratorOptions.cxx index 1139aa9..18c19b7 100644 --- a/Source/cmVisualStudioGeneratorOptions.cxx +++ b/Source/cmVisualStudioGeneratorOptions.cxx @@ -431,7 +431,7 @@ void cmVisualStudioGeneratorOptions::OutputPreprocessorDefinitions( if (this->Defines.empty()) { return; } - const char* tag = "PreprocessorDefinitions"; + std::string tag = "PreprocessorDefinitions"; if (lang == "CUDA") { tag = "Defines"; } @@ -473,7 +473,7 @@ void cmVisualStudioGeneratorOptions::OutputAdditionalIncludeDirectories( return; } - const char* tag = "AdditionalIncludeDirectories"; + std::string tag = "AdditionalIncludeDirectories"; if (lang == "CUDA") { tag = "Include"; } else if (lang == "ASM_MASM" || lang == "ASM_NASM") { @@ -528,6 +528,6 @@ void cmVisualStudioGeneratorOptions::OutputFlagMap(std::ostream& fout, sep = ";"; } - this->OutputFlag(fout, indent, m.first.c_str(), oss.str()); + this->OutputFlag(fout, indent, m.first, oss.str()); } } diff --git a/Source/cmVisualStudioGeneratorOptions.h b/Source/cmVisualStudioGeneratorOptions.h index 560593e..d8dcfe2 100644 --- a/Source/cmVisualStudioGeneratorOptions.h +++ b/Source/cmVisualStudioGeneratorOptions.h @@ -86,7 +86,8 @@ public: const std::string& GetConfiguration() const; protected: - virtual void OutputFlag(std::ostream& fout, int indent, const char* tag, + virtual void OutputFlag(std::ostream& fout, int indent, + const std::string& tag, const std::string& content) = 0; private: diff --git a/Source/cmXCodeScheme.cxx b/Source/cmXCodeScheme.cxx index afc95f5..b34c2f6 100644 --- a/Source/cmXCodeScheme.cxx +++ b/Source/cmXCodeScheme.cxx @@ -8,13 +8,16 @@ #include <utility> #include "cmGeneratedFileStream.h" +#include "cmGeneratorExpression.h" #include "cmGeneratorTarget.h" #include "cmXMLSafe.h" -cmXCodeScheme::cmXCodeScheme(cmXCodeObject* xcObj, TestObjects tests, +cmXCodeScheme::cmXCodeScheme(cmLocalGenerator* lg, cmXCodeObject* xcObj, + TestObjects tests, const std::vector<std::string>& configList, unsigned int xcVersion) - : Target(xcObj) + : LocalGenerator(lg) + , Target(xcObj) , Tests(std::move(tests)) , TargetName(xcObj->GetTarget()->GetName()) , ConfigList(configList) @@ -135,7 +138,8 @@ void cmXCodeScheme::WriteLaunchAction(cmXMLWriter& xout, xout.Attribute("selectedLauncherIdentifier", "Xcode.DebuggerFoundation.Launcher.LLDB"); xout.Attribute("launchStyle", "0"); - xout.Attribute("useCustomWorkingDirectory", "NO"); + WriteCustomWorkingDirectory(xout, configuration); + xout.Attribute("ignoresPersistentStateOnLaunch", "NO"); WriteLaunchActionBooleanAttribute(xout, "debugDocumentVersioning", "XCODE_SCHEME_DEBUG_DOCUMENT_VERSIONING", @@ -355,7 +359,7 @@ void cmXCodeScheme::WriteProfileAction(cmXMLWriter& xout, xout.Attribute("buildConfiguration", configuration); xout.Attribute("shouldUseLaunchSchemeArgsEnv", "YES"); xout.Attribute("savedToolIdentifier", ""); - xout.Attribute("useCustomWorkingDirectory", "NO"); + WriteCustomWorkingDirectory(xout, configuration); WriteLaunchActionBooleanAttribute(xout, "debugDocumentVersioning", "XCODE_SCHEME_DEBUG_DOCUMENT_VERSIONING", true); @@ -395,6 +399,22 @@ void cmXCodeScheme::WriteBuildableReference(cmXMLWriter& xout, xout.EndElement(); } +void cmXCodeScheme::WriteCustomWorkingDirectory( + cmXMLWriter& xout, const std::string& configuration) +{ + std::string propertyValue = this->Target->GetTarget()->GetSafeProperty( + "XCODE_SCHEME_WORKING_DIRECTORY"); + if (propertyValue.empty()) { + xout.Attribute("useCustomWorkingDirectory", "NO"); + } else { + xout.Attribute("useCustomWorkingDirectory", "YES"); + + auto customWorkingDirectory = cmGeneratorExpression::Evaluate( + propertyValue, this->LocalGenerator, configuration); + xout.Attribute("customWorkingDirectory", customWorkingDirectory); + } +} + std::string cmXCodeScheme::WriteVersionString() { std::ostringstream v; diff --git a/Source/cmXCodeScheme.h b/Source/cmXCodeScheme.h index dff5e35..da40856 100644 --- a/Source/cmXCodeScheme.h +++ b/Source/cmXCodeScheme.h @@ -20,7 +20,7 @@ class cmXCodeScheme public: using TestObjects = std::vector<const cmXCodeObject*>; - cmXCodeScheme(cmXCodeObject* xcObj, TestObjects tests, + cmXCodeScheme(cmLocalGenerator* lg, cmXCodeObject* xcObj, TestObjects tests, const std::vector<std::string>& configList, unsigned int xcVersion); @@ -28,6 +28,7 @@ public: const std::string& container); private: + cmLocalGenerator* const LocalGenerator; const cmXCodeObject* const Target; const TestObjects Tests; const std::string& TargetName; @@ -63,6 +64,9 @@ private: void WriteBuildableReference(cmXMLWriter& xout, const cmXCodeObject* xcObj, const std::string& container); + void WriteCustomWorkingDirectory(cmXMLWriter& xout, + const std::string& configuration); + std::string WriteVersionString(); std::string FindConfiguration(const std::string& name); diff --git a/Source/cmake.cxx b/Source/cmake.cxx index f63a264..fdb3687 100644 --- a/Source/cmake.cxx +++ b/Source/cmake.cxx @@ -8,6 +8,8 @@ # include <cm/iterator> #endif +#include <cmext/algorithm> + #include "cm_sys_stat.h" #include "cmAlgorithms.h" @@ -330,9 +332,8 @@ bool cmake::SetCacheArgs(const std::vector<std::string>& args) } } } else { - std::cerr << "Parse error in command line argument: " << arg << "\n" - << "Should be: VAR:type=value\n"; - cmSystemTools::Error("No cmake script provided."); + cmSystemTools::Error("Parse error in command line argument: " + arg + + "\n" + "Should be: VAR:type=value\n"); return false; } } else if (cmHasLiteralPrefix(arg, "-W")) { @@ -422,7 +423,7 @@ bool cmake::SetCacheArgs(const std::vector<std::string>& args) return false; } } - std::cout << "loading initial cache file " << path << "\n"; + cmSystemTools::Stdout("loading initial cache file " + path + "\n"); // Resolve script path specified on command line relative to $PWD. path = cmSystemTools::CollapseFullPath(path); this->ReadListFile(args, path); @@ -539,7 +540,7 @@ bool cmake::FindPackage(const std::vector<std::string>& args) std::vector<std::string> includeDirs = cmExpandedList(includes); gg->CreateGenerationObjects(); - cmLocalGenerator* lg = gg->LocalGenerators[0]; + const auto& lg = gg->LocalGenerators[0]; std::string includeFlags = lg->GetIncludeFlags(includeDirs, nullptr, language); @@ -549,7 +550,7 @@ bool cmake::FindPackage(const std::vector<std::string>& args) const char* targetName = "dummy"; std::vector<std::string> srcs; cmTarget* tgt = mf->AddExecutable(targetName, srcs, true); - tgt->SetProperty("LINKER_LANGUAGE", language.c_str()); + tgt->SetProperty("LINKER_LANGUAGE", language); std::string libs = mf->GetSafeDefinition("PACKAGE_LIBRARIES"); std::vector<std::string> libList = cmExpandedList(libs); @@ -735,6 +736,7 @@ void cmake::SetArgs(const std::vector<std::string>& args) return; } this->SetLogLevel(logLevel); + this->LogLevelWasSetViaCLI = true; } else if (arg.find("--loglevel=", 0) == 0) { // This is supported for backward compatibility. This option only // appeared in the 3.15.x release series and was renamed to @@ -746,6 +748,9 @@ void cmake::SetArgs(const std::vector<std::string>& args) return; } this->SetLogLevel(logLevel); + this->LogLevelWasSetViaCLI = true; + } else if (arg == "--log-context") { + this->SetShowLogContext(true); } else if (arg.find("--trace-expand", 0) == 0) { std::cout << "Running with expanded trace output on.\n"; this->SetTrace(true); @@ -1046,7 +1051,7 @@ void cmake::GetRegisteredGenerators(std::vector<GeneratorInfo>& generators, std::vector<std::string> names = gen->GetGeneratorNames(); if (includeNamesWithPlatform) { - cmAppend(names, gen->GetGeneratorNamesWithPlatform()); + cm::append(names, gen->GetGeneratorNamesWithPlatform()); } for (std::string const& name : names) { @@ -1916,6 +1921,7 @@ void cmake::AddDefaultGenerators() this->Generators.push_back(cmGlobalGhsMultiGenerator::NewFactory()); # endif this->Generators.push_back(cmGlobalNinjaGenerator::NewFactory()); + this->Generators.push_back(cmGlobalNinjaMultiGenerator::NewFactory()); #endif #if defined(CMAKE_USE_WMAKE) this->Generators.push_back(cmGlobalWatcomWMakeGenerator::NewFactory()); @@ -2166,7 +2172,7 @@ int cmake::CheckBuildSystem() if (ggd) { cm.GetCurrentSnapshot().SetDefaultDefinitions(); cmMakefile mfd(ggd.get(), cm.GetCurrentSnapshot()); - std::unique_ptr<cmLocalGenerator> lgd(ggd->CreateLocalGenerator(&mfd)); + auto lgd = ggd->CreateLocalGenerator(&mfd); lgd->ClearDependencies(&mfd, verbose); } } @@ -2287,7 +2293,7 @@ void cmake::MarkCliAsUsed(const std::string& variable) void cmake::GenerateGraphViz(const std::string& fileName) const { #ifndef CMAKE_BOOTSTRAP - cmGraphVizWriter gvWriter(this->GetGlobalGenerator()); + cmGraphVizWriter gvWriter(fileName, this->GetGlobalGenerator()); std::string settingsFile = cmStrCat(this->GetHomeOutputDirectory(), "/CMakeGraphVizOptions.cmake"); @@ -2295,9 +2301,8 @@ void cmake::GenerateGraphViz(const std::string& fileName) const cmStrCat(this->GetHomeDirectory(), "/CMakeGraphVizOptions.cmake"); gvWriter.ReadSettings(settingsFile, fallbackSettingsFile); - gvWriter.WritePerTargetFiles(fileName); - gvWriter.WriteTargetDependersFiles(fileName); - gvWriter.WriteGlobalFile(fileName); + + gvWriter.Write(); #endif } @@ -2616,6 +2621,14 @@ int cmake::Build(int jobs, const std::string& dir, return 1; } } + const char* cachedGeneratorToolset = + this->State->GetCacheEntryValue("CMAKE_GENERATOR_TOOLSET"); + if (cachedGeneratorToolset) { + cmMakefile mf(gen, this->GetCurrentSnapshot()); + if (!gen->SetGeneratorToolset(cachedGeneratorToolset, true, &mf)) { + return 1; + } + } std::string output; std::string projName; const char* cachedProjectName = diff --git a/Source/cmake.h b/Source/cmake.h index 687c105..02de4c1 100644 --- a/Source/cmake.h +++ b/Source/cmake.h @@ -5,12 +5,15 @@ #include "cmConfigure.h" // IWYU pragma: keep +#include <cstddef> #include <functional> #include <map> #include <memory> #include <set> +#include <stack> #include <string> #include <unordered_set> +#include <utility> #include <vector> #include "cmGeneratedFileStream.h" @@ -380,15 +383,40 @@ public: */ cmFileTimeCache* GetFileTimeCache() { return this->FileTimeCache.get(); } + bool WasLogLevelSetViaCLI() const { return this->LogLevelWasSetViaCLI; } + //! Get the selected log level for `message()` commands during the cmake run. LogLevel GetLogLevel() const { return this->MessageLogLevel; } void SetLogLevel(LogLevel level) { this->MessageLogLevel = level; } static LogLevel StringToLogLevel(const std::string& levelStr); + bool HasCheckInProgress() const + { + return !this->CheckInProgressMessages.empty(); + } + std::size_t GetCheckInProgressSize() const + { + return this->CheckInProgressMessages.size(); + } + std::string GetTopCheckInProgressMessage() + { + auto message = this->CheckInProgressMessages.top(); + this->CheckInProgressMessages.pop(); + return message; + } + void PushCheckInProgressMessage(std::string message) + { + this->CheckInProgressMessages.emplace(std::move(message)); + } + //! Do we want debug output during the cmake run. bool GetDebugOutput() { return this->DebugOutput; } void SetDebugOutputOn(bool b) { this->DebugOutput = b; } + //! Should `message` command display context. + bool GetShowLogContext() const { return this->LogContext; } + void SetShowLogContext(bool b) { this->LogContext = b; } + //! Do we want trace output during the cmake run. bool GetTrace() { return this->Trace; } void SetTrace(bool b) { this->Trace = b; } @@ -587,6 +615,10 @@ private: std::vector<std::string> TraceOnlyThisSources; LogLevel MessageLogLevel = LogLevel::LOG_STATUS; + bool LogLevelWasSetViaCLI = false; + bool LogContext = false; + + std::stack<std::string> CheckInProgressMessages; void UpdateConversionPathTable(); @@ -714,4 +746,11 @@ private: FOR_EACH_CXX11_FEATURE(F) \ FOR_EACH_CXX14_FEATURE(F) +#define FOR_EACH_CUDA_FEATURE(F) \ + F(cuda_std_03) \ + F(cuda_std_11) \ + F(cuda_std_14) \ + F(cuda_std_17) \ + F(cuda_std_20) + #endif diff --git a/Source/cmakemain.cxx b/Source/cmakemain.cxx index 6d3e6ee..0fc39ba 100644 --- a/Source/cmakemain.cxx +++ b/Source/cmakemain.cxx @@ -1,7 +1,16 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#include "cmAlgorithms.h" +#include <cassert> +#include <cctype> +#include <climits> +#include <cstring> +#include <iostream> +#include <string> +#include <vector> + +#include <cmext/algorithm> + #include "cmDocumentationEntry.h" // IWYU pragma: keep #include "cmGlobalGenerator.h" #include "cmMakefile.h" @@ -24,14 +33,6 @@ # include "cmsys/ConsoleBuf.hxx" #endif -#include <cassert> -#include <cctype> -#include <climits> -#include <cstring> -#include <iostream> -#include <string> -#include <vector> - namespace { #ifndef CMAKE_BOOTSTRAP const char* cmDocumentationName[][2] = { @@ -73,6 +74,7 @@ const char* cmDocumentationOptions[][2] = { { "--log-level=<ERROR|WARNING|NOTICE|STATUS|VERBOSE|DEBUG|TRACE>", "Set the verbosity of messages from CMake files. " "--loglevel is also accepted for backward compatibility reasons." }, + { "--log-context", "Prepend log messages with context, if given" }, { "--debug-trycompile", "Do not delete the try_compile build tree. Only " "useful on one try_compile at a time." }, @@ -99,7 +101,7 @@ int do_command(int ac, char const* const* av) std::vector<std::string> args; args.reserve(ac - 1); args.emplace_back(av[0]); - cmAppend(args, av + 2, av + ac); + cm::append(args, av + 2, av + ac); return cmcmd::ExecuteCMakeCommand(args); } @@ -682,7 +684,6 @@ int main(int ac, char const* const* av) ac = args.argc(); av = args.argv(); - cmSystemTools::EnableMSVCDebugHook(); cmSystemTools::InitializeLibUV(); cmSystemTools::FindCMakeResources(av[0]); if (ac > 1) { diff --git a/Source/cmcmd.cxx b/Source/cmcmd.cxx index d05e3c8..9a07aef 100644 --- a/Source/cmcmd.cxx +++ b/Source/cmcmd.cxx @@ -2,6 +2,8 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmcmd.h" +#include <cmext/algorithm> + #include "cmAlgorithms.h" #include "cmDuration.h" #include "cmGlobalGenerator.h" @@ -21,16 +23,15 @@ #if !defined(CMAKE_BOOTSTRAP) # include "cmDependsFortran.h" // For -E cmake_copy_f90_mod callback. +# include "cmFileTime.h" # include "cmServer.h" # include "cmServerConnection.h" + +# include "bindexplib.h" #endif #if !defined(CMAKE_BOOTSTRAP) && defined(_WIN32) # include "cmsys/ConsoleBuf.hxx" - -# include "cmFileTime.h" - -# include "bindexplib.h" #endif #if !defined(CMAKE_BOOTSTRAP) && defined(_WIN32) && !defined(__CYGWIN__) @@ -107,10 +108,12 @@ void CMakeCommandUsage(const char* program) << " sha384sum <file>... - create SHA384 checksum of files\n" << " sha512sum <file>... - create SHA512 checksum of files\n" << " remove [-f] <file>... - remove the file(s), use -f to force " - "it\n" - << " remove_directory <dir>... - remove directories and their contents\n" + "it (deprecated: use rm instead)\n" + << " remove_directory <dir>... - remove directories and their contents (deprecated: use rm instead)\n" << " rename oldname newname - rename a file or directory " "(on one volume)\n" + << " rm [-rRf] <file/dir>... - remove files or directories, use -f to " + "force it, r or R to remove directories and their contents recursively\n" << " server - start cmake in server mode\n" << " sleep <number>... - sleep for given number of seconds\n" << " tar [cxt][vf][zjJ] file.tar [file/dir1 file/dir2 ...]\n" @@ -172,6 +175,24 @@ static bool cmTarFilesFrom(std::string const& file, return true; } +static bool cmRemoveDirectory(const std::string& dir, bool recursive = true) +{ + if (cmSystemTools::FileIsSymlink(dir)) { + if (!cmSystemTools::RemoveFile(dir)) { + std::cerr << "Error removing directory symlink \"" << dir << "\".\n"; + return false; + } + } else if (!recursive) { + std::cerr << "Error removing directory \"" << dir + << "\" without recursive option.\n"; + return false; + } else if (!cmSystemTools::RemoveADirectory(dir)) { + std::cerr << "Error removing directory \"" << dir << "\".\n"; + return false; + } + return true; +} + static int HandleIWYU(const std::string& runCmd, const std::string& /* sourceFile */, const std::vector<std::string>& orig_cmd) @@ -179,7 +200,7 @@ static int HandleIWYU(const std::string& runCmd, // Construct the iwyu command line by taking what was given // and adding all the arguments we give to the compiler. std::vector<std::string> iwyu_cmd = cmExpandedList(runCmd, true); - cmAppend(iwyu_cmd, orig_cmd.begin() + 1, orig_cmd.end()); + cm::append(iwyu_cmd, orig_cmd.begin() + 1, orig_cmd.end()); // Run the iwyu command line. Capture its stderr and hide its stdout. // Ignore its return code because the tool always returns non-zero. std::string stdErr; @@ -210,7 +231,7 @@ static int HandleTidy(const std::string& runCmd, const std::string& sourceFile, std::vector<std::string> tidy_cmd = cmExpandedList(runCmd, true); tidy_cmd.push_back(sourceFile); tidy_cmd.emplace_back("--"); - cmAppend(tidy_cmd, orig_cmd); + cm::append(tidy_cmd, orig_cmd); // Run the tidy command line. Capture its stdout and hide its stderr. std::string stdOut; @@ -561,11 +582,11 @@ int cmcmd::ExecuteCMakeCommand(std::vector<std::string> const& args) return 0; } -#if defined(_WIN32) && !defined(CMAKE_BOOTSTRAP) - else if (args[1] == "__create_def") { +#if !defined(CMAKE_BOOTSTRAP) + if (args[1] == "__create_def") { if (args.size() < 4) { std::cerr << "__create_def Usage: -E __create_def outfile.def " - "objlistfile [-nm=nm-path]\n"; + "objlistfile [--nm=nm-path]\n"; return 1; } cmsys::ifstream fin(args[3].c_str(), std::ios::in | std::ios::binary); @@ -592,7 +613,7 @@ int cmcmd::ExecuteCMakeCommand(std::vector<std::string> const& args) return 0; } } - FILE* fout = cmsys::SystemTools::Fopen(args[2].c_str(), "w+"); + FILE* fout = cmsys::SystemTools::Fopen(args[2], "w+"); if (!fout) { std::cerr << "could not open output .def file: " << args[2].c_str() << "\n"; @@ -706,14 +727,7 @@ int cmcmd::ExecuteCMakeCommand(std::vector<std::string> const& args) bool return_value = false; for (auto const& arg : cmMakeRange(args).advance(2)) { if (cmSystemTools::FileIsDirectory(arg)) { - if (cmSystemTools::FileIsSymlink(arg)) { - if (!cmSystemTools::RemoveFile(arg)) { - std::cerr << "Error removing directory symlink \"" << arg - << "\".\n"; - return_value = true; - } - } else if (!cmSystemTools::RemoveADirectory(arg)) { - std::cerr << "Error removing directory \"" << arg << "\".\n"; + if (!cmRemoveDirectory(arg)) { return_value = true; } } @@ -739,6 +753,65 @@ int cmcmd::ExecuteCMakeCommand(std::vector<std::string> const& args) return 0; } + // Remove directories or files with rm + if (args[1] == "rm" && args.size() > 2) { + // If an error occurs, we want to continue removing the remaining + // files/directories. + int return_value = 0; + bool force = false; + bool recursive = false; + bool doing_options = true; + bool at_least_one_file = false; + for (auto const& arg : cmMakeRange(args).advance(2)) { + if (doing_options && cmHasLiteralPrefix(arg, "-")) { + if (arg == "--") { + doing_options = false; + } + if (arg.find('f') != std::string::npos) { + force = true; + } + if (arg.find_first_of("rR") != std::string::npos) { + recursive = true; + } + if (arg.find_first_not_of("-frR") != std::string::npos) { + cmSystemTools::Error("Unknown -E rm argument: " + arg); + return 1; + } + } else { + if (arg.empty()) { + continue; + } + at_least_one_file = true; + // Complain if the -f option was not given and + // either file does not exist or + // file could not be removed and still exists + bool file_exists_or_forced_remove = cmSystemTools::FileExists(arg) || + cmSystemTools::FileIsSymlink(arg) || force; + if (cmSystemTools::FileIsDirectory(arg)) { + if (!cmRemoveDirectory(arg, recursive)) { + return_value = 1; + } + } else if ((!file_exists_or_forced_remove) || + (!cmSystemTools::RemoveFile(arg) && + cmSystemTools::FileExists(arg))) { + if (!file_exists_or_forced_remove) { + cmSystemTools::Error( + "File to remove does not exist and force is not set: " + arg); + } else { + cmSystemTools::Error("File can't be removed and still exist: " + + arg); + } + return_value = 1; + } + } + } + if (!at_least_one_file) { + cmSystemTools::Error("Missing file/directory to remove"); + return 1; + } + return return_value; + } + // Touch file if (args[1] == "touch" && args.size() > 2) { for (auto const& arg : cmMakeRange(args).advance(2)) { @@ -1013,7 +1086,7 @@ int cmcmd::ExecuteCMakeCommand(std::vector<std::string> const& args) snapshot.GetDirectory().SetCurrentBinary(startOutDir); snapshot.GetDirectory().SetCurrentSource(startDir); cmMakefile mf(ggd, snapshot); - std::unique_ptr<cmLocalGenerator> lgd(ggd->CreateLocalGenerator(&mf)); + auto lgd = ggd->CreateLocalGenerator(&mf); // Actually scan dependencies. return lgd->UpdateDependencies(depInfo, verbose, color) ? 0 : 2; @@ -1956,7 +2029,7 @@ int cmVSLink::RunMT(std::string const& out, bool notify) if (this->LinkGeneratesManifest) { mtCommand.push_back(this->LinkerManifestFile); } - cmAppend(mtCommand, this->UserManifests); + cm::append(mtCommand, this->UserManifests); mtCommand.push_back(out); if (notify) { // Add an undocumented option that enables a special return diff --git a/Source/ctest.cxx b/Source/ctest.cxx index 0d65902..9b45bb0 100644 --- a/Source/ctest.cxx +++ b/Source/ctest.cxx @@ -98,9 +98,12 @@ static const char* cmDocumentationOptions[][2] = { "Run a specific number of tests by number." }, { "-U, --union", "Take the Union of -I and -R" }, { "--rerun-failed", "Run only the tests that failed previously" }, - { "--repeat-until-fail <n>", - "Require each test to run <n> " - "times without failing in order to pass" }, + { "--repeat until-fail:<n>, --repeat-until-fail <n>", + "Require each test to run <n> times without failing in order to pass" }, + { "--repeat until-pass:<n>", + "Allow each test to run up to <n> times in order to pass" }, + { "--repeat after-timeout:<n>", + "Allow each test to run up to <n> times if it times out" }, { "--max-width <width>", "Set the max width for a test name to output" }, { "--interactive-debug-mode [0|1]", "Set the interactive mode to 0 or 1." }, { "--resource-spec-file <file>", "Set the resource spec file to use." }, @@ -161,7 +164,6 @@ int main(int argc, char const* const* argv) argv = encoding_args.argv(); cmSystemTools::DoNotInheritStdPipes(); - cmSystemTools::EnableMSVCDebugHook(); cmSystemTools::InitializeLibUV(); cmSystemTools::FindCMakeResources(argv[0]); diff --git a/Source/kwsys/CTestCustom.cmake.in b/Source/kwsys/CTestCustom.cmake.in index 760221b..c07f0f3 100644 --- a/Source/kwsys/CTestCustom.cmake.in +++ b/Source/kwsys/CTestCustom.cmake.in @@ -12,3 +12,7 @@ list(APPEND CTEST_CUSTOM_MEMCHECK_IGNORE kwsys.testProcess-10 ) + +list(APPEND CTEST_CUSTOM_WARNING_EXCEPTION + "LICENSE WARNING" + ) diff --git a/Source/kwsys/Encoding.hxx.in b/Source/kwsys/Encoding.hxx.in index b067521..75a2d4d 100644 --- a/Source/kwsys/Encoding.hxx.in +++ b/Source/kwsys/Encoding.hxx.in @@ -68,6 +68,8 @@ public: * absolute paths with Windows-style backslashes. **/ static std::wstring ToWindowsExtendedPath(std::string const&); + static std::wstring ToWindowsExtendedPath(const char* source); + static std::wstring ToWindowsExtendedPath(std::wstring const& wsource); # endif #endif // @KWSYS_NAMESPACE@_STL_HAS_WSTRING diff --git a/Source/kwsys/EncodingCXX.cxx b/Source/kwsys/EncodingCXX.cxx index 4593c92..5cad934 100644 --- a/Source/kwsys/EncodingCXX.cxx +++ b/Source/kwsys/EncodingCXX.cxx @@ -221,8 +221,18 @@ std::string Encoding::ToNarrow(const wchar_t* wcstr) // Convert local paths to UNC style paths std::wstring Encoding::ToWindowsExtendedPath(std::string const& source) { - std::wstring wsource = Encoding::ToWide(source); + return ToWindowsExtendedPath(ToWide(source)); +} +// Convert local paths to UNC style paths +std::wstring Encoding::ToWindowsExtendedPath(const char* source) +{ + return ToWindowsExtendedPath(ToWide(source)); +} + +// Convert local paths to UNC style paths +std::wstring Encoding::ToWindowsExtendedPath(std::wstring const& wsource) +{ // Resolve any relative paths DWORD wfull_len; @@ -269,7 +279,7 @@ std::wstring Encoding::ToWindowsExtendedPath(std::string const& source) // If this case has been reached, then the path is invalid. Leave it // unchanged - return Encoding::ToWide(source); + return wsource; } # endif diff --git a/Source/kwsys/FStream.hxx.in b/Source/kwsys/FStream.hxx.in index d79bbdf..b424488 100644 --- a/Source/kwsys/FStream.hxx.in +++ b/Source/kwsys/FStream.hxx.in @@ -87,7 +87,7 @@ public: bool _open(char const* file_name, std::ios_base::openmode mode) { - if (is_open() || file_) { + if (_is_open() || file_) { return false; } # if defined(_MSC_VER) @@ -108,7 +108,7 @@ public: return success; } - bool is_open() + bool _is_open() { if (!buf_) { return false; @@ -116,7 +116,7 @@ public: return buf_->is_open(); } - bool is_open() const + bool _is_open() const { if (!buf_) { return false; @@ -198,9 +198,11 @@ public: this->_set_state(this->_open(file_name, mode), this, this); } + bool is_open() { return this->_is_open(); } + void close() { this->_set_state(this->_close(), this, this); } - using basic_efilebuf<CharType, Traits>::is_open; + using basic_efilebuf<CharType, Traits>::_is_open; internal_buffer_type* rdbuf() const { return this->buf_; } @@ -212,7 +214,7 @@ class basic_ofstream : public std::basic_ostream<CharType, Traits> , public basic_efilebuf<CharType, Traits> { - using basic_efilebuf<CharType, Traits>::is_open; + using basic_efilebuf<CharType, Traits>::_is_open; public: typedef typename basic_efilebuf<CharType, Traits>::internal_buffer_type @@ -242,6 +244,8 @@ public: void close() { this->_set_state(this->_close(), this, this); } + bool is_open() { return this->_is_open(); } + internal_buffer_type* rdbuf() const { return this->buf_; } ~basic_ofstream() @KWSYS_NAMESPACE@_FStream_NOEXCEPT { close(); } diff --git a/Source/kwsys/RegularExpression.hxx.in b/Source/kwsys/RegularExpression.hxx.in index df7eb45..d11db88 100644 --- a/Source/kwsys/RegularExpression.hxx.in +++ b/Source/kwsys/RegularExpression.hxx.in @@ -66,16 +66,27 @@ private: const char* searchstring; }; +#ifdef _MSC_VER +# pragma warning(push) +# if _MSC_VER < 1900 +# pragma warning(disable : 4351) /* new behavior */ +# endif +#endif + /** * \brief Creates an invalid match object */ inline RegularExpressionMatch::RegularExpressionMatch() + : startp{} + , endp{} + , searchstring{} { - startp[0] = nullptr; - endp[0] = nullptr; - searchstring = nullptr; } +#ifdef _MSC_VER +# pragma warning(pop) +#endif + /** * \brief Returns true if the match pointers are valid */ diff --git a/Source/kwsys/SystemTools.cxx b/Source/kwsys/SystemTools.cxx index ce4d6ef..39873e6 100644 --- a/Source/kwsys/SystemTools.cxx +++ b/Source/kwsys/SystemTools.cxx @@ -2326,14 +2326,8 @@ bool SystemTools::TextFilesDiffer(const std::string& path1, static bool CopyFileContentBlockwise(const std::string& source, const std::string& destination) { -// Open files -#if defined(_WIN32) - kwsys::ifstream fin( - Encoding::ToNarrow(Encoding::ToWindowsExtendedPath(source)).c_str(), - std::ios::in | std::ios::binary); -#else + // Open files kwsys::ifstream fin(source.c_str(), std::ios::in | std::ios::binary); -#endif if (!fin) { return false; } @@ -2344,14 +2338,8 @@ static bool CopyFileContentBlockwise(const std::string& source, // that do not allow file removal can be modified. SystemTools::RemoveFile(destination); -#if defined(_WIN32) - kwsys::ofstream fout( - Encoding::ToNarrow(Encoding::ToWindowsExtendedPath(destination)).c_str(), - std::ios::out | std::ios::trunc | std::ios::binary); -#else kwsys::ofstream fout(destination.c_str(), std::ios::out | std::ios::trunc | std::ios::binary); -#endif if (!fout) { return false; } @@ -4678,8 +4666,12 @@ void SystemTools::ClassFinalize() # include <stdlib.h> namespace KWSYS_NAMESPACE { -static int SystemToolsDebugReport(int, char* message, int*) +static int SystemToolsDebugReport(int, char* message, int* ret) { + if (ret) { + // Pretend user clicked on Retry button in popup. + *ret = 1; + } fprintf(stderr, "%s", message); fflush(stderr); return 1; // no further reporting required diff --git a/Source/kwsys/Terminal.c b/Source/kwsys/Terminal.c index 4dd2461..c9515ee 100644 --- a/Source/kwsys/Terminal.c +++ b/Source/kwsys/Terminal.c @@ -172,6 +172,14 @@ static int kwsysTerminalStreamIsVT100(FILE* stream, int default_vt100, } } + /* GNU make 4.1+ may tell us that its output is destined for a TTY. */ + { + const char* termout = getenv("MAKE_TERMOUT"); + if (termout && *termout != '\0') { + return 1; + } + } + /* If running inside emacs the terminal is not VT100. Some emacs seem to claim the TERM is xterm even though they do not support VT100 escapes. */ diff --git a/Tests/CMakeLib/CMakeLists.txt b/Tests/CMakeLib/CMakeLists.txt index 840afc1..25d2de6 100644 --- a/Tests/CMakeLib/CMakeLists.txt +++ b/Tests/CMakeLib/CMakeLists.txt @@ -25,6 +25,8 @@ set(CMakeLib_TESTS testUVProcessChain.cxx testUVRAII.cxx testUVStreambuf.cxx + testCMExtMemory.cxx + testCMExtAlgorithm.cxx ) add_executable(testUVProcessChainHelper testUVProcessChainHelper.cxx) diff --git a/Tests/CMakeLib/testCMExtAlgorithm.cxx b/Tests/CMakeLib/testCMExtAlgorithm.cxx new file mode 100644 index 0000000..c731b72 --- /dev/null +++ b/Tests/CMakeLib/testCMExtAlgorithm.cxx @@ -0,0 +1,117 @@ +#include <iostream> +#include <memory> +#include <utility> +#include <vector> + +#include <cmext/algorithm> + +namespace { + +int failed = 0; + +void testAppend() +{ + std::cout << "testAppend()" << std::endl; + + // ---------------------------------------------------- + // cm::append(Vector, Iterator, Iterator) + { + std::vector<int> v1{ 1, 2, 3 }; + std::vector<int> v1_ref{ 1, 2, 3, 4, 5, 6 }; + std::vector<int> v2{ 4, 5, 6 }; + std::vector<int> v2_ref{ 4, 5, 6 }; + + cm::append(v1, v2.begin(), v2.end()); + + if (v1 != v1_ref || v2 != v2_ref) { + ++failed; + } + } + + // ---------------------------------------------------- + // cm::append(Vector, Range) + { + std::vector<int> v1{ 1, 2, 3 }; + std::vector<int> v1_ref{ 1, 2, 3, 4, 5, 6 }; + std::vector<int> v2{ 4, 5, 6 }; + std::vector<int> v2_ref{ 4, 5, 6 }; + + cm::append(v1, v2); + + if (v1 != v1_ref || v2 != v2_ref) { + ++failed; + } + } + + // ---------------------------------------------------- + // cm::append(Vector<*>, Vector<unique_ptr>) + { + std::vector<int*> v1{ new int(1), new int(2), new int(3) }; + std::vector<int*> v1_ref = v1; + std::vector<std::unique_ptr<int>> v2; + + v2.emplace_back(new int(4)); + v2.emplace_back(new int(5)); + v2.emplace_back(new int(6)); + + cm::append(v1, v2); + + if (v1.size() == 6 && v2.size() == 3) { + for (int i = 0; i < 3; i++) { + if (v1[i] != v1_ref[i]) { + ++failed; + break; + } + } + for (int i = 0; i < 3; i++) { + if (v1[i + 3] != v2[i].get()) { + ++failed; + break; + } + } + } else { + ++failed; + } + + // free memory to please memory sanitizer + delete v1[0]; + delete v1[1]; + delete v1[2]; + } + + // ---------------------------------------------------- + // cm::append(Vector<unique_ptr>, Vector<unique_ptr>) + { + std::vector<std::unique_ptr<int>> v1; + std::vector<std::unique_ptr<int>> v2; + + v1.emplace_back(new int(1)); + v1.emplace_back(new int(2)); + v1.emplace_back(new int(3)); + + v2.emplace_back(new int(4)); + v2.emplace_back(new int(5)); + v2.emplace_back(new int(6)); + + cm::append(v1, std::move(v2)); + + if (v1.size() == 6 && v2.empty()) { + for (int i = 0; i < 6; i++) { + if (*v1[i] != i + 1) { + ++failed; + break; + } + } + } else { + ++failed; + } + } +} +} + +int testCMExtAlgorithm(int /*unused*/, char* /*unused*/ []) +{ + testAppend(); + + return failed; +} diff --git a/Tests/CMakeLib/testCMExtMemory.cxx b/Tests/CMakeLib/testCMExtMemory.cxx new file mode 100644 index 0000000..6663c17 --- /dev/null +++ b/Tests/CMakeLib/testCMExtMemory.cxx @@ -0,0 +1,65 @@ +#include <iostream> +#include <memory> + +#include <cmext/memory> + +namespace { +class Base +{ +public: + virtual ~Base() = default; +}; + +class Derived : public Base +{ +public: + ~Derived() = default; + + void method() {} +}; + +template <typename T> +class Wrapper +{ +public: + Wrapper(T* v) + : value(v) + { + } + ~Wrapper() { delete value; } + + T* get() const { return value; } + +private: + T* value; +}; + +bool testReferenceCast() +{ + std::cout << "testReferenceCast()" << std::endl; + + std::unique_ptr<Base> u(new Derived); + cm::static_reference_cast<Derived>(u).method(); + cm::dynamic_reference_cast<Derived>(u).method(); + + std::shared_ptr<Base> s(new Derived); + cm::static_reference_cast<Derived>(s).method(); + cm::dynamic_reference_cast<Derived>(s).method(); + + // can also be used with custom wrappers + Wrapper<Base> w(new Derived); + cm::static_reference_cast<Derived>(w).method(); + cm::dynamic_reference_cast<Derived>(w).method(); + + return true; +} +} + +int testCMExtMemory(int /*unused*/, char* /*unused*/ []) +{ + if (!testReferenceCast()) { + return 1; + } + + return 0; +} diff --git a/Tests/CMakeLib/testUTF8.cxx b/Tests/CMakeLib/testUTF8.cxx index 986f595..1bf88cf 100644 --- a/Tests/CMakeLib/testUTF8.cxx +++ b/Tests/CMakeLib/testUTF8.cxx @@ -9,9 +9,11 @@ typedef char test_utf8_char[5]; static void test_utf8_char_print(test_utf8_char const c) { unsigned char const* d = reinterpret_cast<unsigned char const*>(c); +#ifndef __clang_analyzer__ // somehow thinks arguments are not initialized printf("[0x%02X,0x%02X,0x%02X,0x%02X]", static_cast<int>(d[0]), static_cast<int>(d[1]), static_cast<int>(d[2]), static_cast<int>(d[3])); +#endif } static void byte_array_print(char const* s) diff --git a/Tests/CMakeLists.txt b/Tests/CMakeLists.txt index 57fa7fc..59f5c73 100644 --- a/Tests/CMakeLists.txt +++ b/Tests/CMakeLists.txt @@ -211,6 +211,13 @@ if(BUILD_TESTING) #--------------------------------------------------------------------------- # Add tests below here. + if(NOT DEFINED CMake_TEST_Qt5) + set(CMake_TEST_Qt5 1) + endif() + if(CMake_TEST_Qt5) + find_package(Qt5Widgets QUIET NO_MODULE) + endif() + if(NOT CMake_TEST_EXTERNAL_CMAKE) add_subdirectory(CMakeLib) @@ -436,7 +443,9 @@ if(BUILD_TESTING) ADD_TEST_MACRO(Assembler HelloAsm) ADD_TEST_MACRO(SourceGroups SourceGroups) ADD_TEST_MACRO(Preprocess Preprocess) - set(ExportImport_BUILD_OPTIONS -DCMake_TEST_NESTED_MAKE_PROGRAM:FILEPATH=${CMake_TEST_EXPLICIT_MAKE_PROGRAM}) + set(ExportImport_BUILD_OPTIONS -DCMake_TEST_NESTED_MAKE_PROGRAM:FILEPATH=${CMake_TEST_EXPLICIT_MAKE_PROGRAM} + -DCMake_TEST_CUDA:BOOL=${CMake_TEST_CUDA} + ) ADD_TEST_MACRO(ExportImport ExportImport) ADD_TEST_MACRO(Unset Unset) ADD_TEST_MACRO(PolicyScope PolicyScope) @@ -451,8 +460,12 @@ if(BUILD_TESTING) ADD_TEST_MACRO(StagingPrefix StagingPrefix) ADD_TEST_MACRO(ImportedSameName ImportedSameName) ADD_TEST_MACRO(InterfaceLibrary InterfaceLibrary) - if(NOT _isMultiConfig) - set(ConfigSources_BUILD_OPTIONS -DCMAKE_BUILD_TYPE=$<CONFIGURATION>) + if(NOT CMAKE_GENERATOR STREQUAL "Xcode") + if(_isMultiConfig) + set(ConfigSources_CTEST_OPTIONS --build-config $<CONFIGURATION>) + else() + set(ConfigSources_BUILD_OPTIONS -DCMAKE_BUILD_TYPE=$<CONFIGURATION>) + endif() ADD_TEST_MACRO(ConfigSources ConfigSources) endif() ADD_TEST_MACRO(SourcesProperty SourcesProperty) @@ -1128,8 +1141,8 @@ ${CMake_SOURCE_DIR}/Utilities/Release/push.bash --dir dev -- '${CMake_BUILD_NIGH foreach(CPackDEBConfiguration IN LISTS DEB_CONFIGURATIONS_TO_TEST) set(CPackRun_CPackDEBConfiguration "-DCPackDEBConfiguration=${CPackDEBConfiguration}") - add_test(${DEB_TEST_NAMES}-${CPackDEBConfiguration} - ${CMAKE_CTEST_COMMAND} -C \${CTEST_CONFIGURATION_TYPE} + add_test(NAME ${DEB_TEST_NAMES}-${CPackDEBConfiguration} COMMAND + ${CMAKE_CTEST_COMMAND} -C $<CONFIG> --build-and-test "${CMake_SOURCE_DIR}/Tests/${DEB_TEST_NAMES}" "${CMake_BINARY_DIR}/Tests/${DEB_TEST_NAMES}/build${CPackGen}-${CPackDEBConfiguration}" @@ -1146,6 +1159,7 @@ ${CMake_SOURCE_DIR}/Utilities/Release/push.bash --dir dev -- '${CMake_BUILD_NIGH "-D${DEB_TEST_NAMES}_BINARY_DIR:PATH=${CMake_BINARY_DIR}/Tests/${DEB_TEST_NAMES}/build${CPackGen}-${CPackDEBConfiguration}" "${CPackRun_CPackGen}" "${CPackRun_CPackDEBConfiguration}" + "-DCONFIG=$<CONFIG>" -P "${CMake_SOURCE_DIR}/Tests/${DEB_TEST_NAMES}/RunCPackVerifyResult-${CPackDEBConfiguration}.cmake") list(APPEND TEST_BUILD_DIRS "${CMake_BINARY_DIR}/Tests/${DEB_TEST_NAMES}/build${CPackGen}-${CPackDEBConfiguration}") endforeach() @@ -1325,12 +1339,6 @@ ${CMake_SOURCE_DIR}/Utilities/Release/push.bash --dir dev -- '${CMake_BUILD_NIGH ) list(APPEND TEST_BUILD_DIRS "${CMake_BINARY_DIR}/Tests/QtAutomocNoQt") - if(NOT DEFINED CMake_TEST_Qt5) - set(CMake_TEST_Qt5 1) - endif() - if(CMake_TEST_Qt5) - find_package(Qt5Widgets QUIET NO_MODULE) - endif() if(CMake_TEST_Qt5 AND Qt5Widgets_FOUND) add_subdirectory(Qt5Autogen) endif() @@ -1401,6 +1409,7 @@ ${CMake_SOURCE_DIR}/Utilities/Release/push.bash --dir dev -- '${CMake_BUILD_NIGH ICU JPEG JsonCpp + LibArchive LibLZMA LibRHash Libinput @@ -1861,7 +1870,7 @@ ${CMake_SOURCE_DIR}/Utilities/Release/push.bash --dir dev -- '${CMake_BUILD_NIGH ADD_TEST_MACRO(CheckCompilerRelatedVariables CheckCompilerRelatedVariables) if("${CMAKE_GENERATOR}" MATCHES "Makefile" OR - "${CMAKE_GENERATOR}" MATCHES "Ninja") + "${CMAKE_GENERATOR}" MATCHES "^Ninja$") add_test(MakeClean ${CMAKE_CTEST_COMMAND} --build-and-test "${CMake_SOURCE_DIR}/Tests/MakeClean" diff --git a/Tests/CMakeOnly/CMakeLists.txt b/Tests/CMakeOnly/CMakeLists.txt index 03babd2..85b9694 100644 --- a/Tests/CMakeOnly/CMakeLists.txt +++ b/Tests/CMakeOnly/CMakeLists.txt @@ -75,6 +75,12 @@ add_test(CMakeOnly.ProjectIncludeAny ${CMAKE_CMAKE_COMMAND} add_test(CMakeOnly.ProjectIncludeBefore ${CMAKE_CMAKE_COMMAND} -DTEST=ProjectIncludeBefore + -DCMAKE_ARGS=-DCMAKE_PROJECT_ProjectInclude_INCLUDE_BEFORE=${CMAKE_CURRENT_SOURCE_DIR}/ProjectIncludeBefore/include.cmake + -P ${CMAKE_CURRENT_BINARY_DIR}/Test.cmake + ) + +add_test(CMakeOnly.ProjectIncludeBeforeAny ${CMAKE_CMAKE_COMMAND} + -DTEST=ProjectIncludeBeforeAny -DCMAKE_ARGS=-DCMAKE_PROJECT_INCLUDE_BEFORE=${CMAKE_CURRENT_SOURCE_DIR}/ProjectIncludeBefore/include.cmake -P ${CMAKE_CURRENT_BINARY_DIR}/Test.cmake ) diff --git a/Tests/CMakeOnly/ProjectIncludeBeforeAny/CMakeLists.txt b/Tests/CMakeOnly/ProjectIncludeBeforeAny/CMakeLists.txt new file mode 100644 index 0000000..5cd9cba --- /dev/null +++ b/Tests/CMakeOnly/ProjectIncludeBeforeAny/CMakeLists.txt @@ -0,0 +1,5 @@ +set(FOO TRUE) +project(ProjectInclude LANGUAGES NONE) +if(NOT AUTO_INCLUDE) + message(FATAL_ERROR "include file not found") +endif() diff --git a/Tests/CMakeOnly/ProjectIncludeBeforeAny/include.cmake b/Tests/CMakeOnly/ProjectIncludeBeforeAny/include.cmake new file mode 100644 index 0000000..0a4799d --- /dev/null +++ b/Tests/CMakeOnly/ProjectIncludeBeforeAny/include.cmake @@ -0,0 +1,9 @@ +if(NOT FOO) + message(FATAL_ERROR "FOO is not set") +endif() + +if(NOT "${PROJECT_NAME}" STREQUAL "") + message(FATAL_ERROR "PROJECT_NAME should be empty") +endif() + +set(AUTO_INCLUDE TRUE) diff --git a/Tests/CMakeTestMultipleConfigures/RunCMake.cmake b/Tests/CMakeTestMultipleConfigures/RunCMake.cmake index 9632664..a79bfcb 100644 --- a/Tests/CMakeTestMultipleConfigures/RunCMake.cmake +++ b/Tests/CMakeTestMultipleConfigures/RunCMake.cmake @@ -21,11 +21,11 @@ set(N 7) # First setup source and binary trees: # -execute_process(COMMAND ${CMAKE_COMMAND} -E remove_directory +execute_process(COMMAND ${CMAKE_COMMAND} -E rm -rf ${dir}/Source ) -execute_process(COMMAND ${CMAKE_COMMAND} -E remove_directory +execute_process(COMMAND ${CMAKE_COMMAND} -E rm -rf ${dir}/Build ) @@ -69,7 +69,7 @@ foreach(i RANGE 1 ${N}) # Save this iteration of the Build directory: # - execute_process(COMMAND ${CMAKE_COMMAND} -E remove_directory + execute_process(COMMAND ${CMAKE_COMMAND} -E rm -rf ${dir}/b${i} ) execute_process(COMMAND ${CMAKE_COMMAND} -E copy_directory diff --git a/Tests/CPackComponentsDEB/CMakeLists.txt b/Tests/CPackComponentsDEB/CMakeLists.txt index bc5b6a9..4363f1b 100644 --- a/Tests/CPackComponentsDEB/CMakeLists.txt +++ b/Tests/CPackComponentsDEB/CMakeLists.txt @@ -104,7 +104,7 @@ install(FILES ${CPackComponentsDEB_BINARY_DIR}/symtest COMPONENT applications) if(EXISTS "./dirtest") - execute_process(COMMAND ${CMAKE_COMMAND} -E remove_directory ./dirtest) + execute_process(COMMAND ${CMAKE_COMMAND} -E rm -rf ./dirtest) endif() # NOTE: directory left empty on purpose execute_process(COMMAND ${CMAKE_COMMAND} -E make_directory ./dirtest) diff --git a/Tests/CPackComponentsDEB/RunCPackVerifyResult.cmake b/Tests/CPackComponentsDEB/RunCPackVerifyResult.cmake index b172da2..3bc8d2a 100644 --- a/Tests/CPackComponentsDEB/RunCPackVerifyResult.cmake +++ b/Tests/CPackComponentsDEB/RunCPackVerifyResult.cmake @@ -45,7 +45,7 @@ function(run_cpack output_expected_file CPack_output_parent CPack_error_parent) message("config_args = ${run_cpack_deb_CONFIG_ARGS}") message("config_verbose = ${run_cpack_deb_CONFIG_VERBOSE}") - execute_process(COMMAND ${CMAKE_CPACK_COMMAND} ${run_cpack_deb_CONFIG_VERBOSE} -G ${CPackGen} ${run_cpack_deb_CONFIG_ARGS} + execute_process(COMMAND ${CMAKE_CPACK_COMMAND} ${run_cpack_deb_CONFIG_VERBOSE} -G ${CPackGen} -C "${CONFIG}" ${run_cpack_deb_CONFIG_ARGS} RESULT_VARIABLE CPack_result OUTPUT_VARIABLE CPack_output ERROR_VARIABLE CPack_error diff --git a/Tests/Complex/CMakeLists.txt b/Tests/Complex/CMakeLists.txt index 2e41754..9fd85be 100644 --- a/Tests/Complex/CMakeLists.txt +++ b/Tests/Complex/CMakeLists.txt @@ -324,7 +324,7 @@ if (WIN32) ${file} "[${hkey}]" DOC "Registry_Test_Path") exec_program(${CMAKE_COMMAND} ARGS "-E delete_regv \"${hkey}\"") - exec_program(${CMAKE_COMMAND} ARGS "-E remove \"${dir}/${file}\"") + exec_program(${CMAKE_COMMAND} ARGS "-E rm -f \"${dir}/${file}\"") endif () endif () diff --git a/Tests/Complex/Library/CMakeLists.txt b/Tests/Complex/Library/CMakeLists.txt index 64f6dc8..df874ef 100644 --- a/Tests/Complex/Library/CMakeLists.txt +++ b/Tests/Complex/Library/CMakeLists.txt @@ -131,7 +131,7 @@ if("${CMAKE_GENERATOR}" MATCHES "Makefile" AND CMAKE_MAKE_PROGRAM) # Custom target to try preprocessing invocation. add_custom_target(test_preprocess ${MAYBE_ALL} - COMMAND ${CMAKE_COMMAND} -E remove CMakeFiles/create_file.dir/create_file.i + COMMAND ${CMAKE_COMMAND} -E rm -f CMakeFiles/create_file.dir/create_file.i COMMAND ${CMAKE_MAKE_PROGRAM} create_file.i COMMAND ${CMAKE_COMMAND} -P ${CMAKE_CURRENT_SOURCE_DIR}/test_preprocess.cmake WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} diff --git a/Tests/ComplexOneConfig/CMakeLists.txt b/Tests/ComplexOneConfig/CMakeLists.txt index 628cd4e..28b73af 100644 --- a/Tests/ComplexOneConfig/CMakeLists.txt +++ b/Tests/ComplexOneConfig/CMakeLists.txt @@ -281,7 +281,7 @@ if (WIN32) ${file} "[${hkey}]" DOC "Registry_Test_Path") exec_program(${CMAKE_COMMAND} ARGS "-E delete_regv \"${hkey}\"") - exec_program(${CMAKE_COMMAND} ARGS "-E remove \"${dir}/${file}\"") + exec_program(${CMAKE_COMMAND} ARGS "-E rm -f \"${dir}/${file}\"") endif () endif () diff --git a/Tests/ComplexOneConfig/Library/CMakeLists.txt b/Tests/ComplexOneConfig/Library/CMakeLists.txt index 64f6dc8..df874ef 100644 --- a/Tests/ComplexOneConfig/Library/CMakeLists.txt +++ b/Tests/ComplexOneConfig/Library/CMakeLists.txt @@ -131,7 +131,7 @@ if("${CMAKE_GENERATOR}" MATCHES "Makefile" AND CMAKE_MAKE_PROGRAM) # Custom target to try preprocessing invocation. add_custom_target(test_preprocess ${MAYBE_ALL} - COMMAND ${CMAKE_COMMAND} -E remove CMakeFiles/create_file.dir/create_file.i + COMMAND ${CMAKE_COMMAND} -E rm -f CMakeFiles/create_file.dir/create_file.i COMMAND ${CMAKE_MAKE_PROGRAM} create_file.i COMMAND ${CMAKE_COMMAND} -P ${CMAKE_CURRENT_SOURCE_DIR}/test_preprocess.cmake WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} diff --git a/Tests/Contracts/VTK/CMakeLists.txt b/Tests/Contracts/VTK/CMakeLists.txt index c946499..6ae2732 100644 --- a/Tests/Contracts/VTK/CMakeLists.txt +++ b/Tests/Contracts/VTK/CMakeLists.txt @@ -21,7 +21,7 @@ configure_file( # build & test VTK's release branch ExternalProject_Add(${PROJECT_NAME} - GIT_REPOSITORY "git://vtk.org/VTK.git" + GIT_REPOSITORY "https://gitlab.kitware.com/vtk/vtk.git" GIT_TAG "release" PREFIX ${base_dir} CONFIGURE_COMMAND "" diff --git a/Tests/Cuda/CMakeLists.txt b/Tests/Cuda/CMakeLists.txt index a30071f..35b9022 100644 --- a/Tests/Cuda/CMakeLists.txt +++ b/Tests/Cuda/CMakeLists.txt @@ -1,10 +1,16 @@ ADD_TEST_MACRO(Cuda.Complex CudaComplex) ADD_TEST_MACRO(Cuda.ConsumeCompileFeatures CudaConsumeCompileFeatures) +ADD_TEST_MACRO(Cuda.CXXStandardSetTwice CXXStandardSetTwice) ADD_TEST_MACRO(Cuda.ObjectLibrary CudaObjectLibrary) -ADD_TEST_MACRO(Cuda.MixedStandardLevels MixedStandardLevels) +ADD_TEST_MACRO(Cuda.MixedStandardLevels1 MixedStandardLevels1) +ADD_TEST_MACRO(Cuda.MixedStandardLevels2 MixedStandardLevels2) +ADD_TEST_MACRO(Cuda.MixedStandardLevels3 MixedStandardLevels3) +ADD_TEST_MACRO(Cuda.MixedStandardLevels4 MixedStandardLevels4) +ADD_TEST_MACRO(Cuda.MixedStandardLevels5 MixedStandardLevels5) ADD_TEST_MACRO(Cuda.NotEnabled CudaNotEnabled) -ADD_TEST_MACRO(Cuda.ToolkitInclude CudaToolkitInclude) +ADD_TEST_MACRO(Cuda.Toolkit Toolkit) +ADD_TEST_MACRO(Cuda.IncludePathNoToolkit IncludePathNoToolkit) ADD_TEST_MACRO(Cuda.ProperDeviceLibraries ProperDeviceLibraries) ADD_TEST_MACRO(Cuda.ProperLinkFlags ProperLinkFlags) ADD_TEST_MACRO(Cuda.WithC CudaWithC) diff --git a/Tests/Cuda/MixedStandardLevels/CMakeLists.txt b/Tests/Cuda/CXXStandardSetTwice/CMakeLists.txt index b399662..1941c49 100644 --- a/Tests/Cuda/MixedStandardLevels/CMakeLists.txt +++ b/Tests/Cuda/CXXStandardSetTwice/CMakeLists.txt @@ -1,14 +1,14 @@ cmake_minimum_required(VERSION 3.7) -project(MixedStandardLevels CXX CUDA) +project(CXXStandardSetTwice CXX CUDA) string(APPEND CMAKE_CUDA_FLAGS " -gencode arch=compute_30,code=compute_30") set(CMAKE_CXX_STANDARD 11) -add_executable(MixedStandardLevels main.cu) -target_compile_features(MixedStandardLevels PUBLIC cxx_std_11) +add_executable(CXXStandardSetTwice main.cu) +target_compile_features(CXXStandardSetTwice PUBLIC cxx_std_11) if(APPLE) # Help the static cuda runtime find the driver (libcuda.dyllib) at runtime. - set_property(TARGET MixedStandardLevels PROPERTY BUILD_RPATH ${CMAKE_CUDA_IMPLICIT_LINK_DIRECTORIES}) + set_property(TARGET CXXStandardSetTwice PROPERTY BUILD_RPATH ${CMAKE_CUDA_IMPLICIT_LINK_DIRECTORIES}) endif() diff --git a/Tests/Cuda/MixedStandardLevels/main.cu b/Tests/Cuda/CXXStandardSetTwice/main.cu index d57c05a..d57c05a 100644 --- a/Tests/Cuda/MixedStandardLevels/main.cu +++ b/Tests/Cuda/CXXStandardSetTwice/main.cu diff --git a/Tests/Cuda/ToolkitInclude/CMakeLists.txt b/Tests/Cuda/IncludePathNoToolkit/CMakeLists.txt index f246b54..7be1561 100644 --- a/Tests/Cuda/ToolkitInclude/CMakeLists.txt +++ b/Tests/Cuda/IncludePathNoToolkit/CMakeLists.txt @@ -1,11 +1,11 @@ cmake_minimum_required(VERSION 3.8) -project (ToolkitInclude CXX CUDA) +project (IncludePathNoToolkit CXX CUDA) #Goal for this example: # Validate that between the CXX implicit include directories and the # CMAKE_CUDA_TOOLKIT_INCLUDE_DIRECTORIES directories we can find # the cuda runtime headers -add_executable(CudaToolkitInclude main.cpp) -target_include_directories(CudaToolkitInclude PRIVATE +add_executable(IncludePathNoToolkit main.cpp) +target_include_directories(IncludePathNoToolkit PRIVATE ${CMAKE_CUDA_TOOLKIT_INCLUDE_DIRECTORIES}) diff --git a/Tests/Cuda/ToolkitInclude/main.cpp b/Tests/Cuda/IncludePathNoToolkit/main.cpp index c8d5c6b..c8d5c6b 100644 --- a/Tests/Cuda/ToolkitInclude/main.cpp +++ b/Tests/Cuda/IncludePathNoToolkit/main.cpp diff --git a/Tests/Cuda/MixedStandardLevels1/CMakeLists.txt b/Tests/Cuda/MixedStandardLevels1/CMakeLists.txt new file mode 100644 index 0000000..b03e51e --- /dev/null +++ b/Tests/Cuda/MixedStandardLevels1/CMakeLists.txt @@ -0,0 +1,14 @@ +cmake_minimum_required(VERSION 3.7) +project(MixedStandardLevels1 CXX CUDA) + +string(APPEND CMAKE_CUDA_FLAGS " -gencode arch=compute_30,code=compute_30") + +set(CMAKE_CXX_STANDARD 14) +set(CMAKE_CUDA_STANDARD 11) + +add_executable(MixedStandardLevels1 main.cu lib.cpp) + +if(APPLE) + # Help the static cuda runtime find the driver (libcuda.dyllib) at runtime. + set_property(TARGET MixedStandardLevels1 PROPERTY BUILD_RPATH ${CMAKE_CUDA_IMPLICIT_LINK_DIRECTORIES}) +endif() diff --git a/Tests/Cuda/MixedStandardLevels1/lib.cpp b/Tests/Cuda/MixedStandardLevels1/lib.cpp new file mode 100644 index 0000000..cabbacb --- /dev/null +++ b/Tests/Cuda/MixedStandardLevels1/lib.cpp @@ -0,0 +1,7 @@ + +int func(int A, int B) +{ + // Verify that we have at least c++14 + auto mult_func = [](auto a, auto b) { return a * b; }; + return mult_func(A, B); +} diff --git a/Tests/Cuda/MixedStandardLevels1/main.cu b/Tests/Cuda/MixedStandardLevels1/main.cu new file mode 100644 index 0000000..bc02c6d --- /dev/null +++ b/Tests/Cuda/MixedStandardLevels1/main.cu @@ -0,0 +1,9 @@ + +#include <type_traits> + +int main(int argc, char** argv) +{ + // Verify that we have at least c++11 + using returnv = std::integral_constant<int, 0>; + return returnv::value; +} diff --git a/Tests/Cuda/MixedStandardLevels2/CMakeLists.txt b/Tests/Cuda/MixedStandardLevels2/CMakeLists.txt new file mode 100644 index 0000000..12dd328 --- /dev/null +++ b/Tests/Cuda/MixedStandardLevels2/CMakeLists.txt @@ -0,0 +1,14 @@ +cmake_minimum_required(VERSION 3.7) +project(MixedStandardLevels2 CXX CUDA) + +string(APPEND CMAKE_CUDA_FLAGS " -gencode arch=compute_30,code=compute_30") + +set(CMAKE_CXX_STANDARD 17) #this can decay + +add_executable(MixedStandardLevels2 main.cu lib.cpp) +target_compile_features(MixedStandardLevels2 PUBLIC cuda_std_11) + +if(APPLE) + # Help the static cuda runtime find the driver (libcuda.dyllib) at runtime. + set_property(TARGET MixedStandardLevels2 PROPERTY BUILD_RPATH ${CMAKE_CUDA_IMPLICIT_LINK_DIRECTORIES}) +endif() diff --git a/Tests/Cuda/MixedStandardLevels2/lib.cpp b/Tests/Cuda/MixedStandardLevels2/lib.cpp new file mode 100644 index 0000000..cabbacb --- /dev/null +++ b/Tests/Cuda/MixedStandardLevels2/lib.cpp @@ -0,0 +1,7 @@ + +int func(int A, int B) +{ + // Verify that we have at least c++14 + auto mult_func = [](auto a, auto b) { return a * b; }; + return mult_func(A, B); +} diff --git a/Tests/Cuda/MixedStandardLevels2/main.cu b/Tests/Cuda/MixedStandardLevels2/main.cu new file mode 100644 index 0000000..a97a41e --- /dev/null +++ b/Tests/Cuda/MixedStandardLevels2/main.cu @@ -0,0 +1,11 @@ + +#if __cplusplus < 201103L && !defined(_MSC_VER) +# error "invalid standard value" +#endif +#include <type_traits> + +int main(int argc, char** argv) +{ + using returnv = std::integral_constant<int, 0>; + return returnv::value; +} diff --git a/Tests/Cuda/MixedStandardLevels3/CMakeLists.txt b/Tests/Cuda/MixedStandardLevels3/CMakeLists.txt new file mode 100644 index 0000000..2b611be --- /dev/null +++ b/Tests/Cuda/MixedStandardLevels3/CMakeLists.txt @@ -0,0 +1,12 @@ +cmake_minimum_required(VERSION 3.7) +project(MixedStandardLevels3 CXX CUDA) + +string(APPEND CMAKE_CUDA_FLAGS " -gencode arch=compute_30,code=compute_30") + +add_executable(MixedStandardLevels3 main.cu lib.cpp) +target_compile_features(MixedStandardLevels3 PUBLIC cuda_std_03 cxx_std_14) + +if(APPLE) + # Help the static cuda runtime find the driver (libcuda.dyllib) at runtime. + set_property(TARGET MixedStandardLevels3 PROPERTY BUILD_RPATH ${CMAKE_CUDA_IMPLICIT_LINK_DIRECTORIES}) +endif() diff --git a/Tests/Cuda/MixedStandardLevels3/lib.cpp b/Tests/Cuda/MixedStandardLevels3/lib.cpp new file mode 100644 index 0000000..cabbacb --- /dev/null +++ b/Tests/Cuda/MixedStandardLevels3/lib.cpp @@ -0,0 +1,7 @@ + +int func(int A, int B) +{ + // Verify that we have at least c++14 + auto mult_func = [](auto a, auto b) { return a * b; }; + return mult_func(A, B); +} diff --git a/Tests/Cuda/MixedStandardLevels3/main.cu b/Tests/Cuda/MixedStandardLevels3/main.cu new file mode 100644 index 0000000..1c19e8d --- /dev/null +++ b/Tests/Cuda/MixedStandardLevels3/main.cu @@ -0,0 +1,5 @@ + +int main(int argc, char** argv) +{ + return 0; +} diff --git a/Tests/Cuda/MixedStandardLevels4/CMakeLists.txt b/Tests/Cuda/MixedStandardLevels4/CMakeLists.txt new file mode 100644 index 0000000..faf6869 --- /dev/null +++ b/Tests/Cuda/MixedStandardLevels4/CMakeLists.txt @@ -0,0 +1,14 @@ +cmake_minimum_required(VERSION 3.7) +project(MixedStandardLevels4 CXX CUDA) + +string(APPEND CMAKE_CUDA_FLAGS " -gencode arch=compute_30,code=compute_30") + +set(CMAKE_CUDA_STANDARD 03) + +add_executable(MixedStandardLevels4 main.cu lib.cpp) +target_compile_features(MixedStandardLevels4 PUBLIC cxx_std_14) + +if(APPLE) + # Help the static cuda runtime find the driver (libcuda.dyllib) at runtime. + set_property(TARGET MixedStandardLevels4 PROPERTY BUILD_RPATH ${CMAKE_CUDA_IMPLICIT_LINK_DIRECTORIES}) +endif() diff --git a/Tests/Cuda/MixedStandardLevels4/lib.cpp b/Tests/Cuda/MixedStandardLevels4/lib.cpp new file mode 100644 index 0000000..ef6fc20 --- /dev/null +++ b/Tests/Cuda/MixedStandardLevels4/lib.cpp @@ -0,0 +1,16 @@ + + +constexpr int func(int A, int B) +{ +#if defined(_MSC_VER) && _MSC_VER < 1913 + // no suppport for extended constexpr + return B * A; +#else + // Verify that we have at least c++14 + if (A < B) { + return A + B; + } else { + return B * A; + } +#endif +} diff --git a/Tests/Cuda/MixedStandardLevels4/main.cu b/Tests/Cuda/MixedStandardLevels4/main.cu new file mode 100644 index 0000000..1c19e8d --- /dev/null +++ b/Tests/Cuda/MixedStandardLevels4/main.cu @@ -0,0 +1,5 @@ + +int main(int argc, char** argv) +{ + return 0; +} diff --git a/Tests/Cuda/MixedStandardLevels5/CMakeLists.txt b/Tests/Cuda/MixedStandardLevels5/CMakeLists.txt new file mode 100644 index 0000000..7209f60 --- /dev/null +++ b/Tests/Cuda/MixedStandardLevels5/CMakeLists.txt @@ -0,0 +1,13 @@ +cmake_minimum_required(VERSION 3.7) +project(MixedStandardLevels5 CXX CUDA) + +string(APPEND CMAKE_CUDA_FLAGS " -gencode arch=compute_30,code=compute_30") + +set(CMAKE_CXX_STANDARD 98) + +add_executable(MixedStandardLevels5 main.cu lib.cpp) + +if(APPLE) + # Help the static cuda runtime find the driver (libcuda.dyllib) at runtime. + set_property(TARGET MixedStandardLevels5 PROPERTY BUILD_RPATH ${CMAKE_CUDA_IMPLICIT_LINK_DIRECTORIES}) +endif() diff --git a/Tests/Cuda/MixedStandardLevels5/lib.cpp b/Tests/Cuda/MixedStandardLevels5/lib.cpp new file mode 100644 index 0000000..dd7b31b --- /dev/null +++ b/Tests/Cuda/MixedStandardLevels5/lib.cpp @@ -0,0 +1,13 @@ + +#if __cplusplus >= 201103L +# error "invalid standard value" +#endif +int func(int A, int B) +{ + // Verify that we have at least c++14 + if (A < B) { + return A + B; + } else { + return B * A; + } +} diff --git a/Tests/Cuda/MixedStandardLevels5/main.cu b/Tests/Cuda/MixedStandardLevels5/main.cu new file mode 100644 index 0000000..c79afd6 --- /dev/null +++ b/Tests/Cuda/MixedStandardLevels5/main.cu @@ -0,0 +1,8 @@ + +#if __cplusplus >= 201103L +# error "invalid standard value" +#endif +int main(int argc, char** argv) +{ + return 0; +} diff --git a/Tests/Cuda/Toolkit/CMakeLists.txt b/Tests/Cuda/Toolkit/CMakeLists.txt new file mode 100644 index 0000000..86b4652 --- /dev/null +++ b/Tests/Cuda/Toolkit/CMakeLists.txt @@ -0,0 +1,38 @@ +cmake_minimum_required(VERSION 3.15) +project(Toolkit CXX) + +#Goal for this example: +# Validate that we can use CUDAToolkit to find cuda include paths +find_package(CUDAToolkit REQUIRED) + +message(STATUS "CUDAToolkit_VERSION: ${CUDAToolkit_VERSION}") +message(STATUS "CUDAToolkit_VERSION_MAJOR: ${CUDAToolkit_VERSION_MAJOR}") +message(STATUS "CUDAToolkit_VERSION_MINOR: ${CUDAToolkit_VERSION_MINOR}") +message(STATUS "CUDAToolkit_VERSION_PATCH: ${CUDAToolkit_VERSION_PATCH}") +message(STATUS "CUDAToolkit_BIN_DIR: ${CUDAToolkit_BIN_DIR}") +message(STATUS "CUDAToolkit_INCLUDE_DIRS: ${CUDAToolkit_INCLUDE_DIRS}") +message(STATUS "CUDAToolkit_LIBRARY_DIR: ${CUDAToolkit_LIBRARY_DIR}") +message(STATUS "CUDAToolkit_NVCC_EXECUTABLE ${CUDAToolkit_NVCC_EXECUTABLE}") + +# Verify that all the CUDA:: targets exist even when the CUDA language isn't enabled + +foreach (cuda_lib cudart cuda_driver cublas cufft cufftw curand cusolver cusparse nvgraph) + if(NOT TARGET CUDA::${cuda_lib}) + message(FATAL_ERROR "The CUDA::${cuda_lib} target was expected but couldn't be found") + endif() +endforeach() + +foreach (cuda_lib nppc nppial nppicc nppidei nppif nppig nppim nppist nppitc npps nppicom nppisu) + if(NOT TARGET CUDA::${cuda_lib}) + message(FATAL_ERROR "The CUDA::${cuda_lib} target was expected but couldn't be found") + endif() +endforeach() + +foreach (cuda_lib nvrtc nvToolsExt OpenCL) + if(NOT TARGET CUDA::${cuda_lib}) + message(FATAL_ERROR "The CUDA::${cuda_lib} target was expected but couldn't be found") + endif() +endforeach() + +add_executable(Toolkit main.cpp) +target_link_libraries(Toolkit PRIVATE CUDA::toolkit) diff --git a/Tests/Cuda/Toolkit/main.cpp b/Tests/Cuda/Toolkit/main.cpp new file mode 100644 index 0000000..c8d5c6b --- /dev/null +++ b/Tests/Cuda/Toolkit/main.cpp @@ -0,0 +1,8 @@ +// Only thing we care about is that these headers are found +#include <cuda.h> +#include <cuda_runtime_api.h> + +int main() +{ + return 0; +} diff --git a/Tests/CudaOnly/CMakeLists.txt b/Tests/CudaOnly/CMakeLists.txt index f1fd344..a0575cd 100644 --- a/Tests/CudaOnly/CMakeLists.txt +++ b/Tests/CudaOnly/CMakeLists.txt @@ -5,6 +5,8 @@ ADD_TEST_MACRO(CudaOnly.ExportPTX CudaOnlyExportPTX) ADD_TEST_MACRO(CudaOnly.GPUDebugFlag CudaOnlyGPUDebugFlag) ADD_TEST_MACRO(CudaOnly.ResolveDeviceSymbols CudaOnlyResolveDeviceSymbols) ADD_TEST_MACRO(CudaOnly.SeparateCompilation CudaOnlySeparateCompilation) +ADD_TEST_MACRO(CudaOnly.Standard98 CudaOnlyStandard98) +ADD_TEST_MACRO(CudaOnly.Toolkit CudaOnlyToolkit) ADD_TEST_MACRO(CudaOnly.WithDefs CudaOnlyWithDefs) add_test(NAME CudaOnly.DontResolveDeviceSymbols COMMAND diff --git a/Tests/CudaOnly/EnableStandard/CMakeLists.txt b/Tests/CudaOnly/EnableStandard/CMakeLists.txt index 54e2c14..dfcb8da 100644 --- a/Tests/CudaOnly/EnableStandard/CMakeLists.txt +++ b/Tests/CudaOnly/EnableStandard/CMakeLists.txt @@ -11,8 +11,9 @@ add_library(CUDADynamic11 SHARED shared.cu) add_executable(CudaOnlyEnableStandard main.cu) target_link_libraries(CudaOnlyEnableStandard PRIVATE CUDAStatic11 CUDADynamic11) -set_target_properties(CUDAStatic11 CUDADynamic11 PROPERTIES CUDA_STANDARD 11) -set_target_properties(CUDAStatic11 CUDADynamic11 PROPERTIES CUDA_STANDARD_REQUIRED TRUE) +target_compile_features(CUDADynamic11 PRIVATE cuda_std_11) +set_target_properties(CUDAStatic11 PROPERTIES CUDA_STANDARD 11) +set_target_properties(CUDAStatic11 PROPERTIES CUDA_STANDARD_REQUIRED TRUE) #Verify CMAKE_CUDA_TOOLKIT_INCLUDE_DIRECTORIES foreach(dir ${CMAKE_CUDA_TOOLKIT_INCLUDE_DIRECTORIES}) diff --git a/Tests/CudaOnly/ResolveDeviceSymbols/CMakeLists.txt b/Tests/CudaOnly/ResolveDeviceSymbols/CMakeLists.txt index 64845c5..57aa0b9 100644 --- a/Tests/CudaOnly/ResolveDeviceSymbols/CMakeLists.txt +++ b/Tests/CudaOnly/ResolveDeviceSymbols/CMakeLists.txt @@ -22,11 +22,11 @@ endif() # 3. Verify that we can't use those device symbols from anything that links # to the static library string(APPEND CMAKE_CUDA_FLAGS " -gencode arch=compute_30,code=[sm_30] -gencode arch=compute_50,code=\\\"compute_50\\\"") -set(CMAKE_CXX_STANDARD 11) -set(CMAKE_CUDA_STANDARD 11) add_library(CUDAResolveDeviceDepsA STATIC file1.cu) add_library(CUDAResolveDeviceDepsB STATIC file2.cu) +target_compile_features(CUDAResolveDeviceDepsA PUBLIC cuda_std_11) +target_compile_features(CUDAResolveDeviceDepsB PUBLIC cuda_std_11) set_target_properties(CUDAResolveDeviceDepsA CUDAResolveDeviceDepsB PROPERTIES CUDA_SEPARABLE_COMPILATION ON diff --git a/Tests/CudaOnly/SeparateCompilation/CMakeLists.txt b/Tests/CudaOnly/SeparateCompilation/CMakeLists.txt index 1e574d6..c1bd64a 100644 --- a/Tests/CudaOnly/SeparateCompilation/CMakeLists.txt +++ b/Tests/CudaOnly/SeparateCompilation/CMakeLists.txt @@ -11,11 +11,10 @@ project (SeparateCompilation CUDA) #all containing cuda separable compilation code links properly string(APPEND CMAKE_CUDA_FLAGS " -gencode arch=compute_30,code=\\\"compute_30,sm_30,sm_35\\\"") string(APPEND CMAKE_CUDA_FLAGS " --generate-code=arch=compute_50,code=[compute_50,sm_50,sm_52]") -set(CMAKE_CXX_STANDARD 11) -set(CMAKE_CUDA_STANDARD 11) set(CMAKE_CUDA_SEPARABLE_COMPILATION ON) add_library(CUDASeparateLibA STATIC file1.cu file2.cu file3.cu) +target_compile_features(CUDASeparateLibA PRIVATE cuda_std_11) get_property(sep_comp TARGET CUDASeparateLibA PROPERTY CUDA_SEPARABLE_COMPILATION) if(NOT sep_comp) message(FATAL_ERROR "CUDA_SEPARABLE_COMPILATION not initialized") @@ -36,11 +35,14 @@ endif() #cause a segv when trying to run the executable # add_library(CUDASeparateLibB STATIC file4.cu file5.cu) +target_compile_features(CUDASeparateLibB PRIVATE cuda_std_11) target_link_libraries(CUDASeparateLibB PRIVATE CUDASeparateLibA) add_executable(CudaOnlySeparateCompilation main.cu) target_link_libraries(CudaOnlySeparateCompilation PRIVATE CUDASeparateLibB) +set_target_properties(CudaOnlySeparateCompilation PROPERTIES CUDA_STANDARD 11) +set_target_properties(CudaOnlySeparateCompilation PROPERTIES CUDA_STANDARD_REQUIRED TRUE) set_target_properties(CUDASeparateLibA CUDASeparateLibB diff --git a/Tests/CudaOnly/Standard98/CMakeLists.txt b/Tests/CudaOnly/Standard98/CMakeLists.txt new file mode 100644 index 0000000..ef9a685 --- /dev/null +++ b/Tests/CudaOnly/Standard98/CMakeLists.txt @@ -0,0 +1,15 @@ +cmake_minimum_required(VERSION 3.7) +project(CudaOnlyStandard98 CUDA) + +string(APPEND CMAKE_CUDA_FLAGS " -gencode arch=compute_30,code=compute_30") + +# Support setting CUDA Standard to 98 which internally gets transformed to +# CUDA03 +set(CMAKE_CUDA_STANDARD 98) + +add_executable(CudaOnlyStandard98 main.cu) + +if(APPLE) + # Help the static cuda runtime find the driver (libcuda.dyllib) at runtime. + set_property(TARGET CudaOnlyStandard98 PROPERTY BUILD_RPATH ${CMAKE_CUDA_IMPLICIT_LINK_DIRECTORIES}) +endif() diff --git a/Tests/CudaOnly/Standard98/main.cu b/Tests/CudaOnly/Standard98/main.cu new file mode 100644 index 0000000..c79afd6 --- /dev/null +++ b/Tests/CudaOnly/Standard98/main.cu @@ -0,0 +1,8 @@ + +#if __cplusplus >= 201103L +# error "invalid standard value" +#endif +int main(int argc, char** argv) +{ + return 0; +} diff --git a/Tests/CudaOnly/Toolkit/CMakeLists.txt b/Tests/CudaOnly/Toolkit/CMakeLists.txt new file mode 100644 index 0000000..0d5d574 --- /dev/null +++ b/Tests/CudaOnly/Toolkit/CMakeLists.txt @@ -0,0 +1,44 @@ +cmake_minimum_required(VERSION 3.15) +project(CudaOnlyToolkit CUDA) +find_package(CUDAToolkit REQUIRED) + +message(STATUS "CUDAToolkit_VERSION: ${CUDAToolkit_VERSION}") +message(STATUS "CUDAToolkit_VERSION_MAJOR: ${CUDAToolkit_VERSION_MAJOR}") +message(STATUS "CUDAToolkit_VERSION_MINOR: ${CUDAToolkit_VERSION_MINOR}") +message(STATUS "CUDAToolkit_VERSION_PATCH: ${CUDAToolkit_VERSION_PATCH}") +message(STATUS "CUDAToolkit_BIN_DIR: ${CUDAToolkit_BIN_DIR}") +message(STATUS "CUDAToolkit_INCLUDE_DIRS: ${CUDAToolkit_INCLUDE_DIRS}") +message(STATUS "CUDAToolkit_LIBRARY_DIR: ${CUDAToolkit_LIBRARY_DIR}") +message(STATUS "CUDAToolkit_NVCC_EXECUTABLE ${CUDAToolkit_NVCC_EXECUTABLE}") + +# Verify that all the CUDA:: targets and variables exist +foreach (cuda_lib cudart cuda_driver cublas cufft cufftw curand cusolver cusparse nvgraph) + if(NOT CUDA_${cuda_lib}_LIBRARY) + message(FATAL_ERROR "expected CUDAToolkit variable CUDA_${cuda_lib}_LIBRARY not found") + endif() + if(NOT TARGET CUDA::${cuda_lib}) + message(FATAL_ERROR "expected CUDAToolkit target CUDA::${cuda_lib} not found") + endif() +endforeach() + +foreach (cuda_lib nppc nppial nppicc nppidei nppif nppig nppim nppist nppitc npps nppicom nppisu) + if(NOT CUDA_${cuda_lib}_LIBRARY) + message(FATAL_ERROR "expected CUDAToolkit variable CUDA_${cuda_lib}_LIBRARY not found") + endif() + if(NOT TARGET CUDA::${cuda_lib}) + message(FATAL_ERROR "expected CUDAToolkit target CUDA::${cuda_lib} not found") + endif() +endforeach() + +foreach (cuda_lib nvrtc nvToolsExt OpenCL) + if(NOT CUDA_${cuda_lib}_LIBRARY) + message(FATAL_ERROR "expected CUDAToolkit variable CUDA_${cuda_lib}_LIBRARY not found") + endif() + + if(NOT TARGET CUDA::${cuda_lib}) + message(FATAL_ERROR "expected CUDAToolkit target CUDA::${cuda_lib} not found") + endif() +endforeach() + +add_executable(CudaOnlyToolkit main.cu) +target_link_libraries(CudaOnlyToolkit PRIVATE CUDA::toolkit) diff --git a/Tests/CudaOnly/Toolkit/main.cu b/Tests/CudaOnly/Toolkit/main.cu new file mode 100644 index 0000000..0f3ccdc --- /dev/null +++ b/Tests/CudaOnly/Toolkit/main.cu @@ -0,0 +1,8 @@ +// Only thing we care about is that these headers are found +#include <cuda.h> +#include <cuda_runtime_api.h> + +int main(int argc, char** argv) +{ + return 0; +} diff --git a/Tests/CustomCommand/CMakeLists.txt b/Tests/CustomCommand/CMakeLists.txt index e9a9f52..e4b50d0 100644 --- a/Tests/CustomCommand/CMakeLists.txt +++ b/Tests/CustomCommand/CMakeLists.txt @@ -70,7 +70,7 @@ add_custom_command(OUTPUT ${PROJECT_BINARY_DIR}/doc1.h APPEND COMMAND ${CMAKE_COMMAND} -E copy ${PROJECT_BINARY_DIR}/doc1temp.h ${PROJECT_BINARY_DIR}/doc1.h COMMAND ${CMAKE_COMMAND} -E echo " Removing doc1temp.h." - COMMAND ${CMAKE_COMMAND} -E remove -f ${PROJECT_BINARY_DIR}/doc1temp.h + COMMAND ${CMAKE_COMMAND} -E rm -f ${PROJECT_BINARY_DIR}/doc1temp.h ) # Add custom command to generate foo.h. @@ -412,7 +412,7 @@ add_custom_target(do_check_command_line ALL add_dependencies(do_check_command_line check_command_line) add_custom_target(pre_check_command_line - COMMAND ${CMAKE_COMMAND} -E remove ${CMAKE_CURRENT_BINARY_DIR}/check_mark.txt + COMMAND ${CMAKE_COMMAND} -E rm -f ${CMAKE_CURRENT_BINARY_DIR}/check_mark.txt ) add_dependencies(do_check_command_line pre_check_command_line) diff --git a/Tests/EnforceConfig.cmake.in b/Tests/EnforceConfig.cmake.in index b7587aa..7781ded 100644 --- a/Tests/EnforceConfig.cmake.in +++ b/Tests/EnforceConfig.cmake.in @@ -33,5 +33,6 @@ unset(ENV{CMAKE_GENERATOR}) unset(ENV{CMAKE_GENERATOR_INSTANCE}) unset(ENV{CMAKE_GENERATOR_PLATFORM}) unset(ENV{CMAKE_GENERATOR_TOOLSET}) +unset(ENV{CMAKE_EXPORT_COMPILE_COMMANDS}) @TEST_HOME_ENV_CODE@ diff --git a/Tests/ExportImport/CMakeLists.txt b/Tests/ExportImport/CMakeLists.txt index dc621eb..d88eb11 100644 --- a/Tests/ExportImport/CMakeLists.txt +++ b/Tests/ExportImport/CMakeLists.txt @@ -7,7 +7,7 @@ endif() # Wipe out the install tree to make sure the exporter works. add_custom_command( OUTPUT ${ExportImport_BINARY_DIR}/CleanupProject - COMMAND ${CMAKE_COMMAND} -E remove_directory ${ExportImport_BINARY_DIR}/Root + COMMAND ${CMAKE_COMMAND} -E rm -rf ${ExportImport_BINARY_DIR}/Root ) add_custom_target(CleanupTarget ALL DEPENDS ${ExportImport_BINARY_DIR}/CleanupProject) set_property( diff --git a/Tests/ExportImport/Export/CMakeLists.txt b/Tests/ExportImport/Export/CMakeLists.txt index 9d8a248..4d411a9 100644 --- a/Tests/ExportImport/Export/CMakeLists.txt +++ b/Tests/ExportImport/Export/CMakeLists.txt @@ -646,6 +646,18 @@ if(CMAKE_GENERATOR MATCHES "Make|Ninja") export(TARGETS testLinkDepends NAMESPACE bld_ APPEND FILE ExportBuildTree.cmake) endif() +#------------------------------------------------------------------------------ +# test export of CUDA language +if(CMake_TEST_CUDA) + enable_language(CUDA) + add_library(cudaInterfaceLib INTERFACE) + target_compile_features(cudaInterfaceLib INTERFACE $<BUILD_INTERFACE:cuda_std_11> $<INSTALL_INTERFACE:cuda_std_14>) + + install(TARGETS cudaInterfaceLib + EXPORT RequiredExp DESTINATION lib) + export(TARGETS cudaInterfaceLib NAMESPACE bld_ APPEND FILE ExportBuildTree.cmake) +endif() + # Test the presence of targets named the same as languages. # IMPORTED_LINK_INTERFACE_LANGUAGES entries should not be targets. add_library(C INTERFACE) diff --git a/Tests/ExportImport/Import/A/CMakeLists.txt b/Tests/ExportImport/Import/A/CMakeLists.txt index b5df961..c5304da 100644 --- a/Tests/ExportImport/Import/A/CMakeLists.txt +++ b/Tests/ExportImport/Import/A/CMakeLists.txt @@ -499,3 +499,10 @@ if(CMAKE_GENERATOR MATCHES "Make|Ninja") checkForProperty(bld_testLinkDepends "INTERFACE_LINK_DEPENDS" "BUILD_LINK_DEPENDS") checkForProperty(Req::testLinkDepends "INTERFACE_LINK_DEPENDS" "${CMAKE_INSTALL_PREFIX}/INSTALL_LINK_DEPENDS") endif() + +#------------------------------------------------------------------------------ +# test import of CUDA language level +if(CMake_TEST_CUDA) + checkForProperty(bld_cudaInterfaceLib "INTERFACE_COMPILE_FEATURES" "cuda_std_11") + checkForProperty(Req::cudaInterfaceLib "INTERFACE_COMPILE_FEATURES" "cuda_std_14") +endif() diff --git a/Tests/ExportImport/InitialCache.cmake.in b/Tests/ExportImport/InitialCache.cmake.in index f600d90..44cd179 100644 --- a/Tests/ExportImport/InitialCache.cmake.in +++ b/Tests/ExportImport/InitialCache.cmake.in @@ -14,3 +14,4 @@ set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "@CMAKE_CXX_FLAGS_RELWITHDEBINFO@" CACHE STRI set(CMAKE_INSTALL_PREFIX "@ExportImport_BINARY_DIR@/Root" CACHE STRING "Installation Prefix") set(CMAKE_SKIP_RPATH ON CACHE BOOL "No RPATH") set(CMAKE_GNUtoMS "@ExportImport_GNUtoMS@" CACHE BOOL "CMAKE_GNUtoMS") +set(CMake_TEST_CUDA "@CMake_TEST_CUDA@" CACHE BOOL "CMake_TEST_CUDA") diff --git a/Tests/ExternalProject/CMakeLists.txt b/Tests/ExternalProject/CMakeLists.txt index 093391e..ef81169 100644 --- a/Tests/ExternalProject/CMakeLists.txt +++ b/Tests/ExternalProject/CMakeLists.txt @@ -482,6 +482,66 @@ if(do_git_tests) ) set_property(TARGET ${proj} PROPERTY FOLDER "GIT") + # Unzip/untar the git repository in our source folder so that other + # projects below may use it to test git args of ExternalProject_Add + # + set(proj SetupLocalGITRepositoryWithRecursiveSubmodules) + ExternalProject_Add(${proj} + SOURCE_DIR ${CMAKE_CURRENT_BINARY_DIR}/LocalRepositories/GIT-with-recursive-submodules + URL ${CMAKE_CURRENT_SOURCE_DIR}/gitrepo-sub-rec.tgz + BUILD_COMMAND "" + CONFIGURE_COMMAND "${GIT_EXECUTABLE}" --version + INSTALL_COMMAND "" + ) + set_property(TARGET ${proj} + PROPERTY FOLDER "SetupRepos/Local/Deeply/Nested/For/Testing") + + set(local_git_repo "../../LocalRepositories/GIT-with-recursive-submodules") + + set(proj TS1-GIT-RECURSIVE_SUBMODULES-default) + ExternalProject_Add(${proj} + GIT_REPOSITORY "${local_git_repo}" + CMAKE_GENERATOR "${CMAKE_GENERATOR}" + CMAKE_ARGS -DCMAKE_INSTALL_PREFIX:PATH=<INSTALL_DIR> + -DWITH_RECURSIVE:BOOL=ON + BUILD_COMMAND "" + INSTALL_COMMAND "" + DEPENDS "SetupLocalGITRepository" + "SetupLocalGITRepositoryWithSubmodules" + "SetupLocalGITRepositoryWithRecursiveSubmodules" + ) + set_property(TARGET ${proj} PROPERTY FOLDER "GIT") + + set(proj TS1-GIT-RECURSIVE_SUBMODULES-exclusive) + ExternalProject_Add(${proj} + GIT_REPOSITORY "${local_git_repo}" + GIT_SUBMODULES_RECURSE TRUE + CMAKE_GENERATOR "${CMAKE_GENERATOR}" + CMAKE_ARGS -DCMAKE_INSTALL_PREFIX:PATH=<INSTALL_DIR> + -DWITH_RECURSIVE:BOOL=ON + BUILD_COMMAND "" + INSTALL_COMMAND "" + DEPENDS "SetupLocalGITRepository" + "SetupLocalGITRepositoryWithSubmodules" + "SetupLocalGITRepositoryWithRecursiveSubmodules" + ) + set_property(TARGET ${proj} PROPERTY FOLDER "GIT") + + set(proj TS1-GIT-RECURSIVE_SUBMODULES-off) + ExternalProject_Add(${proj} + GIT_REPOSITORY "${local_git_repo}" + GIT_SUBMODULES_RECURSE FALSE + CMAKE_GENERATOR "${CMAKE_GENERATOR}" + CMAKE_ARGS -DCMAKE_INSTALL_PREFIX:PATH=<INSTALL_DIR> + -DWITH_RECURSIVE:BOOL=OFF + BUILD_COMMAND "" + INSTALL_COMMAND "" + DEPENDS "SetupLocalGITRepository" + "SetupLocalGITRepositoryWithSubmodules" + "SetupLocalGITRepositoryWithRecursiveSubmodules" + ) + set_property(TARGET ${proj} PROPERTY FOLDER "GIT") + endif() set(do_hg_tests 0) diff --git a/Tests/ExternalProject/gitrepo-sub-rec.tgz b/Tests/ExternalProject/gitrepo-sub-rec.tgz Binary files differnew file mode 100644 index 0000000..b0f3f18 --- /dev/null +++ b/Tests/ExternalProject/gitrepo-sub-rec.tgz diff --git a/Tests/FindLibArchive/CMakeLists.txt b/Tests/FindLibArchive/CMakeLists.txt new file mode 100644 index 0000000..f532ef2 --- /dev/null +++ b/Tests/FindLibArchive/CMakeLists.txt @@ -0,0 +1,10 @@ +add_test(NAME FindLibArchive.Test COMMAND + ${CMAKE_CTEST_COMMAND} -C $<CONFIGURATION> + --build-and-test + "${CMake_SOURCE_DIR}/Tests/FindLibArchive/Test" + "${CMake_BINARY_DIR}/Tests/FindLibArchive/Test" + ${build_generator_args} + --build-project TestFindLibArchive + --build-options ${build_options} + --test-command ${CMAKE_CTEST_COMMAND} -V -C $<CONFIGURATION> + ) diff --git a/Tests/FindLibArchive/Test/CMakeLists.txt b/Tests/FindLibArchive/Test/CMakeLists.txt new file mode 100644 index 0000000..35843bb --- /dev/null +++ b/Tests/FindLibArchive/Test/CMakeLists.txt @@ -0,0 +1,14 @@ +cmake_minimum_required(VERSION 3.12) +project(TestFindLibArchive C) +include(CTest) + +find_package(LibArchive REQUIRED) + +add_executable(test_libarchive_tgt main.c) +target_link_libraries(test_libarchive_tgt LibArchive::LibArchive) +add_test(NAME test_libarchive_tgt COMMAND test_libarchive_tgt) + +add_executable(test_libarchive_var main.c) +target_include_directories(test_libarchive_var PRIVATE ${LibArchive_INCLUDE_DIRS}) +target_link_libraries(test_libarchive_var PRIVATE ${LibArchive_LIBRARIES}) +add_test(NAME test_libarchive_var COMMAND test_libarchive_var) diff --git a/Tests/FindLibArchive/Test/main.c b/Tests/FindLibArchive/Test/main.c new file mode 100644 index 0000000..03e7ece --- /dev/null +++ b/Tests/FindLibArchive/Test/main.c @@ -0,0 +1,7 @@ +#include <archive.h> + +int main(void) +{ + archive_read_free(archive_read_new()); + return 0; +} diff --git a/Tests/FindPackageModeMakefileTest/CMakeLists.txt b/Tests/FindPackageModeMakefileTest/CMakeLists.txt index 23832da..8a87a8c 100644 --- a/Tests/FindPackageModeMakefileTest/CMakeLists.txt +++ b/Tests/FindPackageModeMakefileTest/CMakeLists.txt @@ -19,6 +19,14 @@ if(UNIX AND "${CMAKE_GENERATOR}" MATCHES "Makefile" AND # configure a FindFoo.cmake so it knows where the library can be found configure_file(FindFoo.cmake.in ${CMAKE_CURRENT_BINARY_DIR}/FindFoo.cmake @ONLY) + # Need the -isysroot flag on recentish macOS after command line tools + # no longer provide headers in /usr/include + if(APPLE AND CMAKE_OSX_SYSROOT) + set(__EXTRA_OSX_SYSROOT_FLAGS "-isysroot ${CMAKE_OSX_SYSROOT}") + else() + set(__EXTRA_OSX_SYSROOT_FLAGS "") + endif() + # now set up the test: file(GENERATE OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/cmakeExecutable.mk" CONTENT "CMAKE = \"$<TARGET_FILE:cmake>\"\n" diff --git a/Tests/FindPackageModeMakefileTest/Makefile.in b/Tests/FindPackageModeMakefileTest/Makefile.in index 8e7ff72..5ef67d0 100644 --- a/Tests/FindPackageModeMakefileTest/Makefile.in +++ b/Tests/FindPackageModeMakefileTest/Makefile.in @@ -5,6 +5,7 @@ CMAKE_CURRENT_BINARY_DIR = "@CMAKE_CURRENT_BINARY_DIR@" CMAKE_CXX_COMPILER = "@CMAKE_CXX_COMPILER@" CMAKE_CXX_COMPILER_ID = "@CMAKE_CXX_COMPILER_ID@" CMAKE_CXX_FLAGS = @CMAKE_CXX_FLAGS@ +__EXTRA_OSX_SYSROOT_FLAGS = @__EXTRA_OSX_SYSROOT_FLAGS@ CMAKE_FOO = $(CMAKE) --find-package -DCMAKE_MODULE_PATH=$(CMAKE_CURRENT_BINARY_DIR) -DNAME=Foo -DLANGUAGE=CXX -DCOMPILER_ID=$(CMAKE_CXX_COMPILER_ID) @@ -15,7 +16,7 @@ all: pngtest main.o: clean main.cpp @$(CMAKE_FOO) -DMODE=COMPILE >$(tmp) @foo="`cat $(tmp)`"; \ - printf '"%s" %s %s -c main.cpp\n' $(CMAKE_CXX_COMPILER) "$(CMAKE_CXX_FLAGS)" "$$foo" >$(tmp) + printf '"%s" %s %s %s -c main.cpp\n' $(CMAKE_CXX_COMPILER) "$(CMAKE_CXX_FLAGS)" "$(__EXTRA_OSX_SYSROOT_FLAGS)" "$$foo" >$(tmp) @cat $(tmp) @sh $(tmp) @rm -f $(tmp) diff --git a/Tests/FindPython/CMakeLists.txt b/Tests/FindPython/CMakeLists.txt index 868cfe0..10c98c5 100644 --- a/Tests/FindPython/CMakeLists.txt +++ b/Tests/FindPython/CMakeLists.txt @@ -134,6 +134,20 @@ if(CMake_TEST_FindPython) --test-command ${CMAKE_CTEST_COMMAND} -V -C $<CONFIGURATION> ) + add_test(NAME FindPython.CustomFailureMessage COMMAND + ${CMAKE_CTEST_COMMAND} -C $<CONFIGURATION> + --build-and-test + "${CMake_SOURCE_DIR}/Tests/FindPython/CustomFailureMessage" + "${CMake_BINARY_DIR}/Tests/FindPython/CustomFailureMessage" + ${build_generator_args} + --build-project TestCustomFailureMessage + --build-options ${build_options} "-Dbuild_generator_args=${build_generator_args}" + "-DCMake_SOURCE_DIR=${CMake_SOURCE_DIR}" + "-DCMake_BINARY_DIR=${CMake_BINARY_DIR}" + "-DCMake_TEST_FindPython_NumPy=${CMake_TEST_FindPython_NumPy}" + --test-command ${CMAKE_CTEST_COMMAND} -V -C $<CONFIGURATION> + ) + endif() if(CMake_TEST_FindPython_NumPy) diff --git a/Tests/FindPython/CustomFailureMessage/CMakeLists.txt b/Tests/FindPython/CustomFailureMessage/CMakeLists.txt new file mode 100644 index 0000000..a0d8eb2 --- /dev/null +++ b/Tests/FindPython/CustomFailureMessage/CMakeLists.txt @@ -0,0 +1,79 @@ +cmake_minimum_required(VERSION 3.1) + +project(TestCustomFailureMessage LANGUAGES NONE) + +include(CTest) + +add_test(NAME FindPython.CustomFailureMessage.Interpreter COMMAND + ${CMAKE_CTEST_COMMAND} -C $<CONFIGURATION> + --build-and-test + "${CMake_SOURCE_DIR}/Tests/FindPython/CustomFailureMessage/Check" + "${CMake_BINARY_DIR}/Tests/FindPython/CustomFailureMessage/Interpreter" + ${build_generator_args} + --build-project TestCustomFailureMessage.Check + --build-options "-DCHECK_COMPONENTS=Interpreter" + "-DPython3_EXECUTABLE=/not/found/interpreter" + --test-command ${CMAKE_CTEST_COMMAND} -V -C $<CONFIGURATION> + ) +set_tests_properties(FindPython.CustomFailureMessage.Interpreter PROPERTIES + PASS_REGULAR_EXPRESSION "Reason given by package:.+Interpreter: Cannot run the interpreter") + +add_test(NAME FindPython.CustomFailureMessage.Library COMMAND + ${CMAKE_CTEST_COMMAND} -C $<CONFIGURATION> + --build-and-test + "${CMake_SOURCE_DIR}/Tests/FindPython/CustomFailureMessage/Check" + "${CMake_BINARY_DIR}/Tests/FindPython/CustomFailureMessage/Library" + ${build_generator_args} + --build-project TestCustomFailureMessage.Check + --build-options "-DCHECK_COMPONENTS=Development" + "-DPython3_LIBRARY=/not/found/library" + --test-command ${CMAKE_CTEST_COMMAND} -V -C $<CONFIGURATION> + ) +set_tests_properties(FindPython.CustomFailureMessage.Library PROPERTIES + PASS_REGULAR_EXPRESSION "Reason given by package:.+Development: Cannot find the library") + +add_test(NAME FindPython.CustomFailureMessage.Include COMMAND + ${CMAKE_CTEST_COMMAND} -C $<CONFIGURATION> + --build-and-test + "${CMake_SOURCE_DIR}/Tests/FindPython/CustomFailureMessage/Check" + "${CMake_BINARY_DIR}/Tests/FindPython/CustomFailureMessage/Include" + ${build_generator_args} + --build-project TestCustomFailureMessage.Check + --build-options "-DCHECK_COMPONENTS=Development" + "-DPython3_INCLUDE_DIR=/not/found/include" + --test-command ${CMAKE_CTEST_COMMAND} -V -C $<CONFIGURATION> + ) +set_tests_properties(FindPython.CustomFailureMessage.Include PROPERTIES + PASS_REGULAR_EXPRESSION "Reason given by package:.+Development: Cannot find the directory") + +add_test(NAME FindPython.CustomFailureMessage.Multiple COMMAND + ${CMAKE_CTEST_COMMAND} -C $<CONFIGURATION> + --build-and-test + "${CMake_SOURCE_DIR}/Tests/FindPython/CustomFailureMessage/Check" + "${CMake_BINARY_DIR}/Tests/FindPython/CustomFailureMessage/Multiple" + ${build_generator_args} + --build-project TestCustomFailureMessage.Check + --build-options "-DCHECK_COMPONENTS=Interpreter;Development" + "-DPython3_EXECUTABLE=/not/found/interpreter" + "-DPython3_LIBRARY=/not/found/library" + --test-command ${CMAKE_CTEST_COMMAND} -V -C $<CONFIGURATION> + ) +set_tests_properties(FindPython.CustomFailureMessage.Multiple PROPERTIES + PASS_REGULAR_EXPRESSION "Reason given by package:.+Interpreter: Cannot run the interpreter.+Development: Cannot find the library") + + +if (CMake_TEST_FindPython_NumPy) + add_test(NAME FindPython.CustomFailureMessage.NumPy COMMAND + ${CMAKE_CTEST_COMMAND} -C $<CONFIGURATION> + --build-and-test + "${CMake_SOURCE_DIR}/Tests/FindPython/CustomFailureMessage/Check" + "${CMake_BINARY_DIR}/Tests/FindPython/CustomFailureMessage/NumPy" + ${build_generator_args} + --build-project TestCustomFailureMessage.Check + --build-options "-DCHECK_COMPONENTS=Interpreter;Development;NumPy" + "-DPython3_NumPy_INCLUDE_DIR=/not/found/numpy/include" + --test-command ${CMAKE_CTEST_COMMAND} -V -C $<CONFIGURATION> + ) + set_tests_properties(FindPython.CustomFailureMessage.NumPy PROPERTIES + PASS_REGULAR_EXPRESSION "Reason given by package:.+NumPy: Cannot find the directory") +endif() diff --git a/Tests/FindPython/CustomFailureMessage/Check/CMakeLists.txt b/Tests/FindPython/CustomFailureMessage/Check/CMakeLists.txt new file mode 100644 index 0000000..fed963e --- /dev/null +++ b/Tests/FindPython/CustomFailureMessage/Check/CMakeLists.txt @@ -0,0 +1,5 @@ +cmake_minimum_required(VERSION 3.1) + +project(TestCustomFailureMessage.Check LANGUAGES C) + +find_package (Python3 REQUIRED COMPONENTS ${CHECK_COMPONENTS}) diff --git a/Tests/FortranModules/Executable/CMakeLists.txt b/Tests/FortranModules/Executable/CMakeLists.txt index de08d86..f31a3e6 100644 --- a/Tests/FortranModules/Executable/CMakeLists.txt +++ b/Tests/FortranModules/Executable/CMakeLists.txt @@ -1,6 +1,6 @@ include_directories(${Library_MODDIR}) include_directories(${External_BINARY_DIR}) -link_directories(${External_BINARY_DIR}) +link_directories(${External_BINARY_DIR}/${CMAKE_CFG_INTDIR}) add_executable(subdir_exe2 main.f90) target_link_libraries(subdir_exe2 subdir_mods subdir_mods2) diff --git a/Tests/FortranOnly/CMakeLists.txt b/Tests/FortranOnly/CMakeLists.txt index de887fa..d945375 100644 --- a/Tests/FortranOnly/CMakeLists.txt +++ b/Tests/FortranOnly/CMakeLists.txt @@ -103,11 +103,11 @@ if("${CMAKE_GENERATOR}" MATCHES "Makefile" AND CMAKE_MAKE_PROGRAM) # Custom target to try preprocessing invocation. add_custom_target(test_preprocess ${MAYBE_ALL} - COMMAND ${CMAKE_COMMAND} -E remove CMakeFiles/preprocess.dir/preprocess.F.i + COMMAND ${CMAKE_COMMAND} -E rm -f CMakeFiles/preprocess.dir/preprocess.F.i COMMAND ${CMAKE_MAKE_PROGRAM} preprocess.i COMMAND ${CMAKE_COMMAND} -P ${CMAKE_CURRENT_SOURCE_DIR}/test_preprocess.cmake # Remove bogus file some compilers leave behind. - COMMAND ${CMAKE_COMMAND} -E remove ${CMAKE_CURRENT_SOURCE_DIR}/preprocess.s + COMMAND ${CMAKE_COMMAND} -E rm -f ${CMAKE_CURRENT_SOURCE_DIR}/preprocess.s WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} ) endif() diff --git a/Tests/IncludeDirectories/CMakeLists.txt b/Tests/IncludeDirectories/CMakeLists.txt index 761c405..fa3309f 100644 --- a/Tests/IncludeDirectories/CMakeLists.txt +++ b/Tests/IncludeDirectories/CMakeLists.txt @@ -94,6 +94,6 @@ if (NOT incs STREQUAL ";/one/two") message(SEND_ERROR "Empty include_directories entry was not ignored.") endif() -if(NOT CMAKE_GENERATOR STREQUAL Xcode AND NOT CMAKE_GENERATOR STREQUAL Ninja) +if(NOT CMAKE_GENERATOR STREQUAL "Xcode" AND NOT CMAKE_GENERATOR MATCHES "Ninja") add_subdirectory(CMP0021) endif() diff --git a/Tests/InterfaceLibrary/CMakeLists.txt b/Tests/InterfaceLibrary/CMakeLists.txt index 954c02d..311ca2a 100644 --- a/Tests/InterfaceLibrary/CMakeLists.txt +++ b/Tests/InterfaceLibrary/CMakeLists.txt @@ -3,6 +3,12 @@ cmake_minimum_required(VERSION 2.8) project(InterfaceLibrary) +set(cfg_dir) +get_property(_isMultiConfig GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG) +if(_isMultiConfig) + set(cfg_dir /$<CONFIG>) +endif() + add_library(iface_nodepends INTERFACE) target_compile_definitions(iface_nodepends INTERFACE IFACE_DEFINE) @@ -32,7 +38,7 @@ add_library(item_iface INTERFACE IMPORTED) set_property(TARGET item_iface PROPERTY IMPORTED_LIBNAME item_real) add_dependencies(item_iface item_real) get_property(item_iface_dependencies TARGET item_iface PROPERTY MANUALLY_ADDED_DEPENDENCIES) -link_directories(${CMAKE_CURRENT_BINARY_DIR}) +link_directories(${CMAKE_CURRENT_BINARY_DIR}${cfg_dir}) add_executable(InterfaceLibrary definetestexe.cpp) target_link_libraries(InterfaceLibrary diff --git a/Tests/JavaExportImport/CMakeLists.txt b/Tests/JavaExportImport/CMakeLists.txt index c70704a..7a2d020 100644 --- a/Tests/JavaExportImport/CMakeLists.txt +++ b/Tests/JavaExportImport/CMakeLists.txt @@ -9,7 +9,7 @@ find_package(Java COMPONENTS Development) # Wipe out the install tree to make sure the exporter works. add_custom_command( OUTPUT ${JavaExportImport_BINARY_DIR}/CleanupProject - COMMAND ${CMAKE_COMMAND} -E remove_directory ${JavaExportImport_BINARY_DIR}/Root + COMMAND ${CMAKE_COMMAND} -E rm -rf ${JavaExportImport_BINARY_DIR}/Root ) add_custom_target(CleanupTarget ALL DEPENDS ${JavaExportImport_BINARY_DIR}/CleanupProject) set_property( diff --git a/Tests/LinkDirectory/CMakeLists.txt b/Tests/LinkDirectory/CMakeLists.txt index c60de84..c7a2700 100644 --- a/Tests/LinkDirectory/CMakeLists.txt +++ b/Tests/LinkDirectory/CMakeLists.txt @@ -33,7 +33,7 @@ ExternalProject_Add(ExternalTarget # directly because it does not know the full paths to the libraries. # (The purpose of this test is to check that link_directories works.) ExternalProject_Add_Step(ExternalTarget cleanup - COMMAND ${CMAKE_COMMAND} -E remove_directory ${LinkDirectory_BINARY_DIR}/bin + COMMAND ${CMAKE_COMMAND} -E rm -rf ${LinkDirectory_BINARY_DIR}/bin DEPENDEES download DEPENDERS configure DEPENDS mylibA mylibB diff --git a/Tests/LinkDirectory/External/CMakeLists.txt b/Tests/LinkDirectory/External/CMakeLists.txt index d2a1f9f..c877913 100644 --- a/Tests/LinkDirectory/External/CMakeLists.txt +++ b/Tests/LinkDirectory/External/CMakeLists.txt @@ -2,13 +2,19 @@ cmake_minimum_required(VERSION 2.8) project(LinkDirectoryExternal C) +set(cfg_dir) +get_property(_isMultiConfig GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG) +if(_isMultiConfig) + set(cfg_dir /$<CONFIG>) +endif() + add_executable(myexe2 myexe.c) set_property(TARGET myexe2 PROPERTY OUTPUT_NAME LinkDirectory2) -target_link_directories(myexe2 PRIVATE lib "${CMAKE_CURRENT_SOURCE_DIR}/../lib") +target_link_directories(myexe2 PRIVATE lib${cfg_dir} "${CMAKE_CURRENT_SOURCE_DIR}/../lib${cfg_dir}") target_link_libraries(myexe2 PRIVATE mylibA mylibB) add_library (mylibs INTERFACE) -target_link_directories(mylibs INTERFACE lib "${CMAKE_CURRENT_SOURCE_DIR}/../lib") +target_link_directories(mylibs INTERFACE lib${cfg_dir} "${CMAKE_CURRENT_SOURCE_DIR}/../lib${cfg_dir}") target_link_libraries(mylibs INTERFACE mylibA mylibB) add_executable(myexe3 myexe.c) set_property(TARGET myexe3 PROPERTY OUTPUT_NAME LinkDirectory3) @@ -17,11 +23,11 @@ target_link_libraries(myexe3 PRIVATE mylibs) # Test CMP0015 OLD behavior: -L../lib cmake_policy(SET CMP0015 OLD) -link_directories(../lib) +link_directories(../lib${cfg_dir}) # Test CMP0015 NEW behavior: -L${CMAKE_CURRENT_SOURCE_DIR}/lib cmake_policy(SET CMP0015 NEW) -link_directories(lib) +link_directories(lib${cfg_dir}) add_executable(myexe myexe.c) set_property(TARGET myexe PROPERTY OUTPUT_NAME LinkDirectory) diff --git a/Tests/MacRuntimePath/CMakeLists.txt b/Tests/MacRuntimePath/CMakeLists.txt index a3c6fd9..9f1bf1a 100644 --- a/Tests/MacRuntimePath/CMakeLists.txt +++ b/Tests/MacRuntimePath/CMakeLists.txt @@ -7,7 +7,7 @@ endif() # Wipe out the install tree to make sure the exporter works. add_custom_command( OUTPUT ${MacRuntimePath_BINARY_DIR}/CleanupProject - COMMAND ${CMAKE_COMMAND} -E remove_directory ${MacRuntimePath_BINARY_DIR}/Root + COMMAND ${CMAKE_COMMAND} -E rm -rf ${MacRuntimePath_BINARY_DIR}/Root ) add_custom_target(CleanupTarget ALL DEPENDS ${MacRuntimePath_BINARY_DIR}/CleanupProject) set_property( diff --git a/Tests/OutDir/CMakeLists.txt b/Tests/OutDir/CMakeLists.txt index 823ab08..8afe036 100644 --- a/Tests/OutDir/CMakeLists.txt +++ b/Tests/OutDir/CMakeLists.txt @@ -20,7 +20,7 @@ set(top "${OutDir_BINARY_DIR}") foreach(config ${configs}) foreach(type archive runtime library) string(TOUPPER "${type}" TYPE) - set(CMAKE_${TYPE}_OUTPUT_DIRECTORY_${config} "${top}/${type}") + set(CMAKE_${TYPE}_OUTPUT_DIRECTORY_${config} "${top}/${type}/$<CONFIG>") file(REMOVE_RECURSE "${top}/${type}") endforeach() endforeach() @@ -29,7 +29,7 @@ add_subdirectory(../COnly COnly) add_custom_command( OUTPUT OutDir.h - COMMAND ${CMAKE_COMMAND} -Dtop=${top} -P ${OutDir_SOURCE_DIR}/OutDir.cmake + COMMAND ${CMAKE_COMMAND} -Dtop=${top} -Dcfg_dir=$<CONFIG> -P ${OutDir_SOURCE_DIR}/OutDir.cmake DEPENDS COnly ${OutDir_SOURCE_DIR}/OutDir.cmake ) include_directories(${top}) diff --git a/Tests/OutDir/OutDir.cmake b/Tests/OutDir/OutDir.cmake index a1f13e7..2a003b8 100644 --- a/Tests/OutDir/OutDir.cmake +++ b/Tests/OutDir/OutDir.cmake @@ -3,17 +3,17 @@ set(CMAKE_FIND_LIBRARY_SUFFIXES ".lib" ".a" ".so" ".sl" ".dylib" ".dll.a") find_library(TESTC1_LIB NAMES testc1 testc1_test_debug_postfix - PATHS ${top}/archive + PATHS ${top}/archive/${cfg_dir} NO_DEFAULT_PATH) find_library(TESTC2_LIB NAMES testc2 testc2_test_debug_postfix - PATHS ${top}/archive ${top}/library + PATHS ${top}/archive/${cfg_dir} ${top}/library/${cfg_dir} NO_DEFAULT_PATH) find_program(CONLY_EXE NAMES COnly - PATHS ${top}/runtime + PATHS ${top}/runtime/${cfg_dir} NO_DEFAULT_PATH) file(RELATIVE_PATH TESTC1_LIB_FILE "${top}" "${TESTC1_LIB}") diff --git a/Tests/RunCMake/CMP0068/CMP0068-OLD-stderr.txt b/Tests/RunCMake/CMP0068/CMP0068-OLD-stderr.txt new file mode 100644 index 0000000..a736129 --- /dev/null +++ b/Tests/RunCMake/CMP0068/CMP0068-OLD-stderr.txt @@ -0,0 +1,10 @@ +^CMake Deprecation Warning at CMP0068-OLD.cmake:[0-9]+ \(cmake_policy\): + The OLD behavior for policy CMP0068 will be removed from a future version + of CMake. + + The cmake-policies\(7\) manual explains that the OLD behaviors of all + policies are deprecated and that a policy should be set to OLD only under + specific short-term circumstances. Projects should be ported to the NEW + behavior and not rely on setting a policy to OLD. +Call Stack \(most recent call first\): + CMakeLists.txt:[0-9]+ \(include\)$ diff --git a/Tests/RunCMake/CMP0069/CMP0069-OLD-stderr.txt b/Tests/RunCMake/CMP0069/CMP0069-OLD-stderr.txt new file mode 100644 index 0000000..f51a6f4 --- /dev/null +++ b/Tests/RunCMake/CMP0069/CMP0069-OLD-stderr.txt @@ -0,0 +1,10 @@ +^CMake Deprecation Warning at CMP0069-OLD.cmake:[0-9]+ \(cmake_policy\): + The OLD behavior for policy CMP0069 will be removed from a future version + of CMake. + + The cmake-policies\(7\) manual explains that the OLD behaviors of all + policies are deprecated and that a policy should be set to OLD only under + specific short-term circumstances. Projects should be ported to the NEW + behavior and not rely on setting a policy to OLD. +Call Stack \(most recent call first\): + CMakeLists.txt:[0-9]+ \(include\)$ diff --git a/Tests/RunCMake/CMakeLists.txt b/Tests/RunCMake/CMakeLists.txt index 6b2f117..10e4c6f 100644 --- a/Tests/RunCMake/CMakeLists.txt +++ b/Tests/RunCMake/CMakeLists.txt @@ -125,7 +125,7 @@ endif() if(CMAKE_GENERATOR MATCHES "Make") add_RunCMake_test(Make -DMAKE_IS_GNU=${MAKE_IS_GNU}) endif() -if(CMAKE_GENERATOR STREQUAL "Ninja") +if(CMAKE_GENERATOR MATCHES "Ninja") set(Ninja_ARGS -DCMAKE_C_OUTPUT_EXTENSION=${CMAKE_C_OUTPUT_EXTENSION} -DCMAKE_SHARED_LIBRARY_PREFIX=${CMAKE_SHARED_LIBRARY_PREFIX} @@ -134,6 +134,13 @@ if(CMAKE_GENERATOR STREQUAL "Ninja") list(APPEND Ninja_ARGS -DTEST_Fortran=1) endif() add_RunCMake_test(Ninja) + set(NinjaMultiConfig_ARGS + -DCYGWIN=${CYGWIN} + ) + if(CMake_TEST_Qt5 AND Qt5Core_FOUND) + list(APPEND NinjaMultiConfig_ARGS -DCMake_TEST_Qt5=1) + endif() + add_RunCMake_test(NinjaMultiConfig) endif() add_RunCMake_test(CTest) @@ -189,6 +196,7 @@ add_RunCMake_test(GeneratorToolset) add_RunCMake_test(GetPrerequisites) add_RunCMake_test(GNUInstallDirs -DSYSTEM_NAME=${CMAKE_SYSTEM_NAME}) add_RunCMake_test(GoogleTest) # Note: does not actually depend on Google Test +add_RunCMake_test(Graphviz) add_RunCMake_test(TargetPropertyGeneratorExpressions) add_RunCMake_test(Languages) add_RunCMake_test(LinkStatic) @@ -271,6 +279,7 @@ add_RunCMake_test(find_package) add_RunCMake_test(find_path) add_RunCMake_test(find_program -DCMAKE_SYSTEM_NAME=${CMAKE_SYSTEM_NAME}) add_RunCMake_test(foreach) +add_RunCMake_test(function) add_RunCMake_test(get_filename_component) add_RunCMake_test(get_property) add_RunCMake_test(if) @@ -278,6 +287,7 @@ add_RunCMake_test(include) add_RunCMake_test(include_directories) add_RunCMake_test(include_guard) add_RunCMake_test(list) +add_RunCMake_test(load_cache) add_RunCMake_test(math) add_RunCMake_test(message) add_RunCMake_test(option) @@ -289,6 +299,9 @@ add_RunCMake_test(set_property) add_RunCMake_test(string) add_RunCMake_test(test_include_dirs) add_RunCMake_test(BundleUtilities) +if(APPLE) + add_RunCMake_test(INSTALL_NAME_DIR) +endif() function(add_RunCMake_test_try_compile) if(CMAKE_VERSION VERSION_LESS 3.9.20170907 AND "x${CMAKE_CXX_COMPILER_ID}" STREQUAL "xMSVC") @@ -441,7 +454,7 @@ add_RunCMake_test(target_include_directories) add_RunCMake_test(target_sources) add_RunCMake_test(CheckModules) add_RunCMake_test(CheckIPOSupported) -add_RunCMake_test(CommandLine -DCMAKE_SYSTEM_NAME=${CMAKE_SYSTEM_NAME}) +add_RunCMake_test(CommandLine -DCMAKE_SYSTEM_NAME=${CMAKE_SYSTEM_NAME} -DCYGWIN=${CYGWIN}) add_RunCMake_test(CommandLineTar) if(CMAKE_PLATFORM_NO_VERSIONED_SONAME OR (NOT CMAKE_SHARED_LIBRARY_SONAME_FLAG AND NOT CMAKE_SHARED_LIBRARY_SONAME_C_FLAG)) @@ -551,6 +564,7 @@ set(cpack_tests DEB.MD5SUMS DEB.DEB_PACKAGE_VERSION_BACK_COMPATIBILITY DEB.DEB_DESCRIPTION + DEB.PROJECT_META RPM.CUSTOM_BINARY_SPEC_FILE RPM.CUSTOM_NAMES @@ -571,6 +585,7 @@ set(cpack_tests RPM.SUGGESTS RPM.SYMLINKS RPM.USER_FILELIST + RPM.PROJECT_META 7Z TBZ2 diff --git a/Tests/RunCMake/CPack/CPackTestHelpers.cmake b/Tests/RunCMake/CPack/CPackTestHelpers.cmake index f65cb9d..24f54c6 100644 --- a/Tests/RunCMake/CPack/CPackTestHelpers.cmake +++ b/Tests/RunCMake/CPack/CPackTestHelpers.cmake @@ -75,7 +75,7 @@ function(run_cpack_test_common_ TEST_NAME types build SUBTEST_SUFFIX source PACK if(package_target) set(cpack_command_ ${CMAKE_COMMAND} --build "${RunCMake_TEST_BINARY_DIR}" --target package) else() - set(cpack_command_ ${CMAKE_CPACK_COMMAND} ${pack_params_}) + set(cpack_command_ ${CMAKE_CPACK_COMMAND} ${pack_params_} -C Debug) endif() # execute cpack diff --git a/Tests/RunCMake/CPack/RunCMakeTest.cmake b/Tests/RunCMake/CPack/RunCMakeTest.cmake index b154c79..76d16e1 100644 --- a/Tests/RunCMake/CPack/RunCMakeTest.cmake +++ b/Tests/RunCMake/CPack/RunCMakeTest.cmake @@ -43,3 +43,4 @@ run_cpack_test_subtests( false "MONOLITHIC;COMPONENT" ) +run_cpack_test(PROJECT_META "RPM.PROJECT_META;DEB.PROJECT_META" false "MONOLITHIC;COMPONENT") diff --git a/Tests/RunCMake/CPack/tests/EXTERNAL/expected-json-1.0.txt b/Tests/RunCMake/CPack/tests/EXTERNAL/expected-json-1.0.txt index 18bf617..ca25b1e 100644 --- a/Tests/RunCMake/CPack/tests/EXTERNAL/expected-json-1.0.txt +++ b/Tests/RunCMake/CPack/tests/EXTERNAL/expected-json-1.0.txt @@ -1,5 +1,6 @@ ^\{ - "componentGroups" :[ ] + ("buildConfig" : "Debug", +)? "componentGroups" :[ ] \{ "f12" :[ ] \{ diff --git a/Tests/RunCMake/CPack/tests/PROJECT_META/ExpectedFiles.cmake b/Tests/RunCMake/CPack/tests/PROJECT_META/ExpectedFiles.cmake new file mode 100644 index 0000000..448ed2b --- /dev/null +++ b/Tests/RunCMake/CPack/tests/PROJECT_META/ExpectedFiles.cmake @@ -0,0 +1,9 @@ +if(GENERATOR_TYPE STREQUAL DEB) + set(EXPECTED_FILE_1 "project_meta-1.2.3*.deb") +elseif(GENERATOR_TYPE STREQUAL RPM) + set(EXPECTED_FILE_1 "project_meta-1.2.3*.rpm") +else() + message(FATAL_ERROR "Unexpected CPack generator") +endif() +set(EXPECTED_FILES_COUNT "1") +set(EXPECTED_FILE_CONTENT_1_LIST "/foo;/foo/CMakeLists.txt") diff --git a/Tests/RunCMake/CPack/tests/PROJECT_META/VerifyResult.cmake b/Tests/RunCMake/CPack/tests/PROJECT_META/VerifyResult.cmake new file mode 100644 index 0000000..b3accb5 --- /dev/null +++ b/Tests/RunCMake/CPack/tests/PROJECT_META/VerifyResult.cmake @@ -0,0 +1,30 @@ +function(checkPackageURL FILE TAG EXPECTED_URL) + getPackageInfo("${FILE}" "_file_info") + string(REPLACE "\n" ";" _file_info "${_file_info}") + + set(_seen_url FALSE) + foreach(_line IN LISTS _file_info) + if(_line MATCHES "${TAG}: (.*)") + set(_seen_url TRUE) + if(NOT CMAKE_MATCH_1 STREQUAL EXPECTED_URL) + message(FATAL_ERROR "Unexpected `Homepage` URL: `${CMAKE_MATCH_1}` != `${EXPECTED_URL}`") + endif() + break() + endif() + endforeach() + if(NOT _seen_url) + message(FATAL_ERROR "The packge `${FILE}` do not have URL as expected") + endif() +endfunction() + +if(GENERATOR_TYPE STREQUAL DEB) + set(_tag " Homepage") # NOTE The leading space +elseif(GENERATOR_TYPE STREQUAL RPM) + set(_tag "URL.*") +else() + message(FATAL_ERROR "Unexpected CPack generator") +endif() + +checkPackageURL("${FOUND_FILE_1}" "${_tag}" "https://meta.test.info") + +# kate: indent-width 2; diff --git a/Tests/RunCMake/CPack/tests/PROJECT_META/test.cmake b/Tests/RunCMake/CPack/tests/PROJECT_META/test.cmake new file mode 100644 index 0000000..9c5266a --- /dev/null +++ b/Tests/RunCMake/CPack/tests/PROJECT_META/test.cmake @@ -0,0 +1,11 @@ +project( + MetaInfoTest + VERSION 1.2.3 + DESCRIPTION "This is going to be a summary" + HOMEPAGE_URL "https://meta.test.info" +) +install(FILES CMakeLists.txt DESTINATION foo COMPONENT test) + +if(PACKAGING_TYPE STREQUAL "COMPONENT") + set(CPACK_COMPONENTS_ALL test) +endif() diff --git a/Tests/RunCMake/CTestCommandLine/CMakeLists.txt.in b/Tests/RunCMake/CTestCommandLine/CMakeLists.txt.in new file mode 100644 index 0000000..5437800 --- /dev/null +++ b/Tests/RunCMake/CTestCommandLine/CMakeLists.txt.in @@ -0,0 +1,4 @@ +cmake_minimum_required(VERSION 3.1) +project(CTestCommandLine@CASE_NAME@ NONE) +include(CTest) +add_test(NAME RunCMakeVersion COMMAND "${CMAKE_COMMAND}" --version) diff --git a/Tests/RunCMake/CTestCommandLine/RunCMakeTest.cmake b/Tests/RunCMake/CTestCommandLine/RunCMakeTest.cmake index 6b23162..b2de596 100644 --- a/Tests/RunCMake/CTestCommandLine/RunCMakeTest.cmake +++ b/Tests/RunCMake/CTestCommandLine/RunCMakeTest.cmake @@ -1,9 +1,33 @@ include(RunCMake) +include(RunCTest) + set(RunCMake_TEST_TIMEOUT 60) unset(ENV{CTEST_PARALLEL_LEVEL}) unset(ENV{CTEST_OUTPUT_ON_FAILURE}) +run_cmake_command(repeat-opt-bad1 + ${CMAKE_CTEST_COMMAND} --repeat until-pass + ) +run_cmake_command(repeat-opt-bad2 + ${CMAKE_CTEST_COMMAND} --repeat until-pass:foo + ) +run_cmake_command(repeat-opt-bad3 + ${CMAKE_CTEST_COMMAND} --repeat until-fail:2 --repeat-until-fail 2 + ) +run_cmake_command(repeat-opt-bad4 + ${CMAKE_CTEST_COMMAND} --repeat-until-fail 2 --repeat until-fail:2 + ) +run_cmake_command(repeat-opt-until-pass + ${CMAKE_CTEST_COMMAND} --repeat until-pass:2 + ) +run_cmake_command(repeat-opt-until-fail + ${CMAKE_CTEST_COMMAND} --repeat until-fail:2 + ) +run_cmake_command(repeat-opt-after-timeout + ${CMAKE_CTEST_COMMAND} --repeat after-timeout:2 + ) + run_cmake_command(repeat-until-fail-bad1 ${CMAKE_CTEST_COMMAND} --repeat-until-fail ) @@ -14,19 +38,39 @@ run_cmake_command(repeat-until-fail-good ${CMAKE_CTEST_COMMAND} --repeat-until-fail 2 ) -function(run_repeat_until_fail_tests) +function(run_repeat_until_pass_tests) # Use a single build tree for a few tests without cleaning. - set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/repeat-until-fail-build) + set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/repeat-until-pass-build) + run_cmake(repeat-until-pass-cmake) set(RunCMake_TEST_NO_CLEAN 1) - file(REMOVE_RECURSE "${RunCMake_TEST_BINARY_DIR}") - file(MAKE_DIRECTORY "${RunCMake_TEST_BINARY_DIR}") + run_cmake_command(repeat-until-pass-ctest + ${CMAKE_CTEST_COMMAND} -C Debug --repeat until-pass:3 + ) +endfunction() +run_repeat_until_pass_tests() + +function(run_repeat_after_timeout_tests) + # Use a single build tree for a few tests without cleaning. + set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/repeat-after-timeout-build) + run_cmake(repeat-after-timeout-cmake) + set(RunCMake_TEST_NO_CLEAN 1) + run_cmake_command(repeat-after-timeout-ctest + ${CMAKE_CTEST_COMMAND} -C Debug --repeat after-timeout:3 + ) +endfunction() +run_repeat_after_timeout_tests() +function(run_repeat_until_fail_tests) + # Use a single build tree for a few tests without cleaning. + set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/repeat-until-fail-build) run_cmake(repeat-until-fail-cmake) + set(RunCMake_TEST_NO_CLEAN 1) run_cmake_command(repeat-until-fail-ctest - ${CMAKE_CTEST_COMMAND} -C Debug --repeat-until-fail 3 + ${CMAKE_CTEST_COMMAND} -C Debug ${ARGN} ) endfunction() -run_repeat_until_fail_tests() +run_repeat_until_fail_tests(--repeat-until-fail 3) +run_repeat_until_fail_tests(--repeat until-fail:3) function(run_BadCTestTestfile) set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/BadCTestTestfile) @@ -269,3 +313,6 @@ function(run_ShowOnly) run_cmake_command(show-only_json-v1 ${CMAKE_CTEST_COMMAND} --show-only=json-v1) endfunction() run_ShowOnly() + +# Check the configuration type variable is passed +run_ctest(check-configuration-type) diff --git a/Tests/RunCMake/CTestCommandLine/check-configuration-type-stderr.txt b/Tests/RunCMake/CTestCommandLine/check-configuration-type-stderr.txt new file mode 100644 index 0000000..b2c1a45 --- /dev/null +++ b/Tests/RunCMake/CTestCommandLine/check-configuration-type-stderr.txt @@ -0,0 +1,2 @@ +Command line CTEST_CONFIGURATION_TYPE=Debug +set CTEST_CONFIGURATION_TYPE=Release diff --git a/Tests/RunCMake/CTestCommandLine/repeat-after-timeout-cmake.cmake b/Tests/RunCMake/CTestCommandLine/repeat-after-timeout-cmake.cmake new file mode 100644 index 0000000..873c0bd --- /dev/null +++ b/Tests/RunCMake/CTestCommandLine/repeat-after-timeout-cmake.cmake @@ -0,0 +1,15 @@ +enable_testing() + +set(TEST_OUTPUT_FILE "${CMAKE_CURRENT_BINARY_DIR}/test_output.txt") +add_test(NAME initialization + COMMAND ${CMAKE_COMMAND} + "-DTEST_OUTPUT_FILE=${TEST_OUTPUT_FILE}" + -P "${CMAKE_CURRENT_SOURCE_DIR}/init.cmake") +add_test(NAME test1 + COMMAND ${CMAKE_COMMAND} + "-DTEST_OUTPUT_FILE=${TEST_OUTPUT_FILE}" + -P "${CMAKE_CURRENT_SOURCE_DIR}/test1-timeout.cmake") +set_tests_properties(test1 PROPERTIES DEPENDS "initialization" TIMEOUT 5) + +add_test(hello ${CMAKE_COMMAND} -E echo hello) +add_test(goodbye ${CMAKE_COMMAND} -E echo goodbye) diff --git a/Tests/RunCMake/CTestCommandLine/repeat-after-timeout-ctest-stdout.txt b/Tests/RunCMake/CTestCommandLine/repeat-after-timeout-ctest-stdout.txt new file mode 100644 index 0000000..d0a5487 --- /dev/null +++ b/Tests/RunCMake/CTestCommandLine/repeat-after-timeout-ctest-stdout.txt @@ -0,0 +1,15 @@ +^Test project .*/Tests/RunCMake/CTestCommandLine/repeat-after-timeout-build + Start 1: initialization +1/4 Test #1: initialization ................... Passed +[0-9.]+ sec + Start 2: test1 +2/4 Test #2: test1 ............................\*\*\*Timeout +[0-9.]+ sec + Start 2: test1 + Test #2: test1 ............................ Passed +[0-9.]+ sec + Start 3: hello +3/4 Test #3: hello ............................ Passed +[0-9.]+ sec + Start 4: goodbye +4/4 Test #4: goodbye .......................... Passed +[0-9.]+ sec + +100% tests passed, 0 tests failed out of 4 + +Total Test time \(real\) = +[0-9.]+ sec$ diff --git a/Tests/RunCMake/CTestCommandLine/repeat-opt-after-timeout-stderr.txt b/Tests/RunCMake/CTestCommandLine/repeat-opt-after-timeout-stderr.txt new file mode 100644 index 0000000..a7c4b11 --- /dev/null +++ b/Tests/RunCMake/CTestCommandLine/repeat-opt-after-timeout-stderr.txt @@ -0,0 +1 @@ +^No tests were found!!!$ diff --git a/Tests/RunCMake/CTestCommandLine/repeat-opt-bad1-result.txt b/Tests/RunCMake/CTestCommandLine/repeat-opt-bad1-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/CTestCommandLine/repeat-opt-bad1-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/CTestCommandLine/repeat-opt-bad1-stderr.txt b/Tests/RunCMake/CTestCommandLine/repeat-opt-bad1-stderr.txt new file mode 100644 index 0000000..f6f3241 --- /dev/null +++ b/Tests/RunCMake/CTestCommandLine/repeat-opt-bad1-stderr.txt @@ -0,0 +1 @@ +^CMake Error: '--repeat' given invalid value 'until-pass'$ diff --git a/Tests/RunCMake/CTestCommandLine/repeat-opt-bad2-result.txt b/Tests/RunCMake/CTestCommandLine/repeat-opt-bad2-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/CTestCommandLine/repeat-opt-bad2-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/CTestCommandLine/repeat-opt-bad2-stderr.txt b/Tests/RunCMake/CTestCommandLine/repeat-opt-bad2-stderr.txt new file mode 100644 index 0000000..2f9f32a --- /dev/null +++ b/Tests/RunCMake/CTestCommandLine/repeat-opt-bad2-stderr.txt @@ -0,0 +1 @@ +^CMake Error: '--repeat' given invalid value 'until-pass:foo'$ diff --git a/Tests/RunCMake/CTestCommandLine/repeat-opt-bad3-result.txt b/Tests/RunCMake/CTestCommandLine/repeat-opt-bad3-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/CTestCommandLine/repeat-opt-bad3-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/CTestCommandLine/repeat-opt-bad3-stderr.txt b/Tests/RunCMake/CTestCommandLine/repeat-opt-bad3-stderr.txt new file mode 100644 index 0000000..de4e11b --- /dev/null +++ b/Tests/RunCMake/CTestCommandLine/repeat-opt-bad3-stderr.txt @@ -0,0 +1 @@ +^CMake Error: At most one '--repeat' option may be used\.$ diff --git a/Tests/RunCMake/CTestCommandLine/repeat-opt-bad4-result.txt b/Tests/RunCMake/CTestCommandLine/repeat-opt-bad4-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/CTestCommandLine/repeat-opt-bad4-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/CTestCommandLine/repeat-opt-bad4-stderr.txt b/Tests/RunCMake/CTestCommandLine/repeat-opt-bad4-stderr.txt new file mode 100644 index 0000000..de4e11b --- /dev/null +++ b/Tests/RunCMake/CTestCommandLine/repeat-opt-bad4-stderr.txt @@ -0,0 +1 @@ +^CMake Error: At most one '--repeat' option may be used\.$ diff --git a/Tests/RunCMake/CTestCommandLine/repeat-opt-until-fail-stderr.txt b/Tests/RunCMake/CTestCommandLine/repeat-opt-until-fail-stderr.txt new file mode 100644 index 0000000..a7c4b11 --- /dev/null +++ b/Tests/RunCMake/CTestCommandLine/repeat-opt-until-fail-stderr.txt @@ -0,0 +1 @@ +^No tests were found!!!$ diff --git a/Tests/RunCMake/CTestCommandLine/repeat-opt-until-pass-stderr.txt b/Tests/RunCMake/CTestCommandLine/repeat-opt-until-pass-stderr.txt new file mode 100644 index 0000000..a7c4b11 --- /dev/null +++ b/Tests/RunCMake/CTestCommandLine/repeat-opt-until-pass-stderr.txt @@ -0,0 +1 @@ +^No tests were found!!!$ diff --git a/Tests/RunCMake/CTestCommandLine/repeat-until-pass-cmake.cmake b/Tests/RunCMake/CTestCommandLine/repeat-until-pass-cmake.cmake new file mode 100644 index 0000000..d109551 --- /dev/null +++ b/Tests/RunCMake/CTestCommandLine/repeat-until-pass-cmake.cmake @@ -0,0 +1,15 @@ +enable_testing() + +set(TEST_OUTPUT_FILE "${CMAKE_CURRENT_BINARY_DIR}/test_output.txt") +add_test(NAME initialization + COMMAND ${CMAKE_COMMAND} + "-DTEST_OUTPUT_FILE=${TEST_OUTPUT_FILE}" + -P "${CMAKE_CURRENT_SOURCE_DIR}/init.cmake") +add_test(NAME test1 + COMMAND ${CMAKE_COMMAND} + "-DTEST_OUTPUT_FILE=${TEST_OUTPUT_FILE}" + -P "${CMAKE_CURRENT_SOURCE_DIR}/test1-pass.cmake") +set_tests_properties(test1 PROPERTIES DEPENDS "initialization") + +add_test(hello ${CMAKE_COMMAND} -E echo hello) +add_test(goodbye ${CMAKE_COMMAND} -E echo goodbye) diff --git a/Tests/RunCMake/CTestCommandLine/repeat-until-pass-ctest-stdout.txt b/Tests/RunCMake/CTestCommandLine/repeat-until-pass-ctest-stdout.txt new file mode 100644 index 0000000..3745dc2 --- /dev/null +++ b/Tests/RunCMake/CTestCommandLine/repeat-until-pass-ctest-stdout.txt @@ -0,0 +1,15 @@ +^Test project .*/Tests/RunCMake/CTestCommandLine/repeat-until-pass-build + Start 1: initialization +1/4 Test #1: initialization ................... Passed +[0-9.]+ sec + Start 2: test1 +2/4 Test #2: test1 ............................\*\*\*Failed +[0-9.]+ sec + Start 2: test1 + Test #2: test1 ............................ Passed +[0-9.]+ sec + Start 3: hello +3/4 Test #3: hello ............................ Passed +[0-9.]+ sec + Start 4: goodbye +4/4 Test #4: goodbye .......................... Passed +[0-9.]+ sec + +100% tests passed, 0 tests failed out of 4 + +Total Test time \(real\) = +[0-9.]+ sec$ diff --git a/Tests/RunCMake/CTestCommandLine/test.cmake.in b/Tests/RunCMake/CTestCommandLine/test.cmake.in new file mode 100644 index 0000000..b82968a --- /dev/null +++ b/Tests/RunCMake/CTestCommandLine/test.cmake.in @@ -0,0 +1,19 @@ +cmake_minimum_required(VERSION 3.1) + +set(CTEST_SITE "test-site") +set(CTEST_BUILD_NAME "test-build-name") +set(CTEST_SOURCE_DIRECTORY "@RunCMake_BINARY_DIR@/@CASE_NAME@") +set(CTEST_BINARY_DIRECTORY "@RunCMake_BINARY_DIR@/@CASE_NAME@-build") +set(CTEST_CMAKE_GENERATOR "@RunCMake_GENERATOR@") +set(CTEST_CMAKE_GENERATOR_PLATFORM "@RunCMake_GENERATOR_PLATFORM@") +set(CTEST_CMAKE_GENERATOR_TOOLSET "@RunCMake_GENERATOR_TOOLSET@") +set(CTEST_NIGHTLY_START_TIME "01:00:00 UTC") +set(CTEST_COMMAND "@CMAKE_CTEST_COMMAND@") + +if("@CASE_NAME@" MATCHES "^check-configuration-type") + message("Command line CTEST_CONFIGURATION_TYPE=" ${CTEST_CONFIGURATION_TYPE}) + set(CTEST_CONFIGURATION_TYPE "Release") + message("set CTEST_CONFIGURATION_TYPE=" ${CTEST_CONFIGURATION_TYPE}) + + ctest_start(Experimental) +endif() diff --git a/Tests/RunCMake/CTestCommandLine/test1-pass.cmake b/Tests/RunCMake/CTestCommandLine/test1-pass.cmake new file mode 100644 index 0000000..dda8dea --- /dev/null +++ b/Tests/RunCMake/CTestCommandLine/test1-pass.cmake @@ -0,0 +1,13 @@ +# This is run by test test1 in repeat-until-pass-cmake.cmake with cmake -P. +# It reads the file TEST_OUTPUT_FILE and increments the number +# found in the file by 1. Unless the number is 2, then the +# code sends out a cmake error causing the test to pass only on +# the second time it is run. +message("TEST_OUTPUT_FILE = ${TEST_OUTPUT_FILE}") +file(READ "${TEST_OUTPUT_FILE}" COUNT) +message("COUNT= ${COUNT}") +math(EXPR COUNT "${COUNT} + 1") +file(WRITE "${TEST_OUTPUT_FILE}" "${COUNT}") +if(NOT COUNT EQUAL 2) + message(FATAL_ERROR "this test passes only on the 2nd run") +endif() diff --git a/Tests/RunCMake/CTestCommandLine/test1-timeout.cmake b/Tests/RunCMake/CTestCommandLine/test1-timeout.cmake new file mode 100644 index 0000000..fbf2ccc --- /dev/null +++ b/Tests/RunCMake/CTestCommandLine/test1-timeout.cmake @@ -0,0 +1,14 @@ +# This is run by test test1 in repeat-after-timeout-cmake.cmake with cmake -P. +# It reads the file TEST_OUTPUT_FILE and increments the number +# found in the file by 1. Unless the number is 2, then the +# code sends out a cmake error causing the test to not timeout only on +# the second time it is run. +message("TEST_OUTPUT_FILE = ${TEST_OUTPUT_FILE}") +file(READ "${TEST_OUTPUT_FILE}" COUNT) +message("COUNT= ${COUNT}") +math(EXPR COUNT "${COUNT} + 1") +file(WRITE "${TEST_OUTPUT_FILE}" "${COUNT}") +if(NOT COUNT EQUAL 2) + message("this test times out except on the 2nd run") + execute_process(COMMAND ${CMAKE_COMMAND} -E sleep 10) +endif() diff --git a/Tests/RunCMake/CTestResourceAllocation/ResourceCommon.cmake b/Tests/RunCMake/CTestResourceAllocation/ResourceCommon.cmake index 7d63299..ef79dce 100644 --- a/Tests/RunCMake/CTestResourceAllocation/ResourceCommon.cmake +++ b/Tests/RunCMake/CTestResourceAllocation/ResourceCommon.cmake @@ -1,6 +1,6 @@ function(setup_resource_tests) if(CTEST_RESOURCE_ALLOC_ENABLED) - add_test(NAME ResourceSetup COMMAND "${CMAKE_COMMAND}" -E remove -f "${CMAKE_BINARY_DIR}/ctresalloc.log") + add_test(NAME ResourceSetup COMMAND "${CMAKE_COMMAND}" -E rm -f "${CMAKE_BINARY_DIR}/ctresalloc.log") endif() endfunction() diff --git a/Tests/RunCMake/CheckIPOSupported/cmp0069-is-old-stderr.txt b/Tests/RunCMake/CheckIPOSupported/cmp0069-is-old-stderr.txt index f183594..1baa63a 100644 --- a/Tests/RunCMake/CheckIPOSupported/cmp0069-is-old-stderr.txt +++ b/Tests/RunCMake/CheckIPOSupported/cmp0069-is-old-stderr.txt @@ -1,4 +1,15 @@ -^CMake Error at .*/Modules/CheckIPOSupported\.cmake:[0-9]+ \(message\): +^CMake Deprecation Warning at cmp0069-is-old.cmake:[0-9]+ \(cmake_policy\): + The OLD behavior for policy CMP0069 will be removed from a future version + of CMake. + + The cmake-policies\(7\) manual explains that the OLD behaviors of all + policies are deprecated and that a policy should be set to OLD only under + specific short-term circumstances. Projects should be ported to the NEW + behavior and not rely on setting a policy to OLD. +Call Stack \(most recent call first\): + CMakeLists.txt:[0-9]+ \(include\) ++ +CMake Error at .*/Modules/CheckIPOSupported\.cmake:[0-9]+ \(message\): Policy CMP0069 set to OLD Call Stack \(most recent call first\): cmp0069-is-old\.cmake:[0-9]+ \(check_ipo_supported\) diff --git a/Tests/RunCMake/CommandLine/E_rm_bad_argument-result.txt b/Tests/RunCMake/CommandLine/E_rm_bad_argument-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/CommandLine/E_rm_bad_argument-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/CommandLine/E_rm_bad_argument-stderr.txt b/Tests/RunCMake/CommandLine/E_rm_bad_argument-stderr.txt new file mode 100644 index 0000000..62b963a --- /dev/null +++ b/Tests/RunCMake/CommandLine/E_rm_bad_argument-stderr.txt @@ -0,0 +1 @@ +^CMake Error: Unknown -E rm argument: -rd$ diff --git a/Tests/RunCMake/CommandLine/E_rm_directory_link_existing-check.cmake b/Tests/RunCMake/CommandLine/E_rm_directory_link_existing-check.cmake new file mode 100644 index 0000000..b1a29a2 --- /dev/null +++ b/Tests/RunCMake/CommandLine/E_rm_directory_link_existing-check.cmake @@ -0,0 +1,3 @@ +if(NOT EXISTS ${out}/dir/existing.txt) + set(RunCMake_TEST_FAILED "${out}/dir/existing.txt should exist (we only removed the link to dir folder)") +endif() diff --git a/Tests/RunCMake/CommandLine/E_rm_directory_link_existing-result.txt b/Tests/RunCMake/CommandLine/E_rm_directory_link_existing-result.txt new file mode 100644 index 0000000..573541a --- /dev/null +++ b/Tests/RunCMake/CommandLine/E_rm_directory_link_existing-result.txt @@ -0,0 +1 @@ +0 diff --git a/Tests/RunCMake/CommandLine/E_rm_empty_file_specified-stderr.txt b/Tests/RunCMake/CommandLine/E_rm_empty_file_specified-stderr.txt new file mode 100644 index 0000000..1ac7dba --- /dev/null +++ b/Tests/RunCMake/CommandLine/E_rm_empty_file_specified-stderr.txt @@ -0,0 +1 @@ +^CMake Error: Missing file/directory to remove$ diff --git a/Tests/RunCMake/CommandLine/E_rm_empty_file_specified.cmake b/Tests/RunCMake/CommandLine/E_rm_empty_file_specified.cmake new file mode 100644 index 0000000..6cd4edd --- /dev/null +++ b/Tests/RunCMake/CommandLine/E_rm_empty_file_specified.cmake @@ -0,0 +1,8 @@ +execute_process( + COMMAND ${CMAKE_COMMAND} -E rm "" + RESULT_VARIABLE actual_result + ) + +if(NOT "${actual_result}" EQUAL "1") + message(SEND_ERROR "cmake -E rm \"\" should have returned 1, got ${actual_result}") +endif() diff --git a/Tests/RunCMake/CommandLine/E_rm_file_force_existing-check.cmake b/Tests/RunCMake/CommandLine/E_rm_file_force_existing-check.cmake new file mode 100644 index 0000000..e28b160 --- /dev/null +++ b/Tests/RunCMake/CommandLine/E_rm_file_force_existing-check.cmake @@ -0,0 +1,3 @@ +if(EXISTS ${out}/existing.txt) + set(RunCMake_TEST_FAILED "${out}/existing.txt not removed") +endif() diff --git a/Tests/RunCMake/CommandLine/E_rm_file_force_existing-result.txt b/Tests/RunCMake/CommandLine/E_rm_file_force_existing-result.txt new file mode 100644 index 0000000..573541a --- /dev/null +++ b/Tests/RunCMake/CommandLine/E_rm_file_force_existing-result.txt @@ -0,0 +1 @@ +0 diff --git a/Tests/RunCMake/CommandLine/E_rm_file_force_non_existing-result.txt b/Tests/RunCMake/CommandLine/E_rm_file_force_non_existing-result.txt new file mode 100644 index 0000000..573541a --- /dev/null +++ b/Tests/RunCMake/CommandLine/E_rm_file_force_non_existing-result.txt @@ -0,0 +1 @@ +0 diff --git a/Tests/RunCMake/CommandLine/E_rm_file_link_existing-check.cmake b/Tests/RunCMake/CommandLine/E_rm_file_link_existing-check.cmake new file mode 100644 index 0000000..a0a9b20 --- /dev/null +++ b/Tests/RunCMake/CommandLine/E_rm_file_link_existing-check.cmake @@ -0,0 +1,3 @@ +if(NOT EXISTS ${out}/existing.txt) + set(RunCMake_TEST_FAILED "${out}/existing.txt should exist (we only removed the link)") +endif() diff --git a/Tests/RunCMake/CommandLine/E_rm_file_link_existing-result.txt b/Tests/RunCMake/CommandLine/E_rm_file_link_existing-result.txt new file mode 100644 index 0000000..573541a --- /dev/null +++ b/Tests/RunCMake/CommandLine/E_rm_file_link_existing-result.txt @@ -0,0 +1 @@ +0 diff --git a/Tests/RunCMake/CommandLine/E_rm_file_link_non_existing-result.txt b/Tests/RunCMake/CommandLine/E_rm_file_link_non_existing-result.txt new file mode 100644 index 0000000..573541a --- /dev/null +++ b/Tests/RunCMake/CommandLine/E_rm_file_link_non_existing-result.txt @@ -0,0 +1 @@ +0 diff --git a/Tests/RunCMake/CommandLine/E_rm_file_non_force_existing-check.cmake b/Tests/RunCMake/CommandLine/E_rm_file_non_force_existing-check.cmake new file mode 100644 index 0000000..e28b160 --- /dev/null +++ b/Tests/RunCMake/CommandLine/E_rm_file_non_force_existing-check.cmake @@ -0,0 +1,3 @@ +if(EXISTS ${out}/existing.txt) + set(RunCMake_TEST_FAILED "${out}/existing.txt not removed") +endif() diff --git a/Tests/RunCMake/CommandLine/E_rm_file_non_force_existing-result.txt b/Tests/RunCMake/CommandLine/E_rm_file_non_force_existing-result.txt new file mode 100644 index 0000000..573541a --- /dev/null +++ b/Tests/RunCMake/CommandLine/E_rm_file_non_force_existing-result.txt @@ -0,0 +1 @@ +0 diff --git a/Tests/RunCMake/CommandLine/E_rm_file_non_force_non_existing-result.txt b/Tests/RunCMake/CommandLine/E_rm_file_non_force_non_existing-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/CommandLine/E_rm_file_non_force_non_existing-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/CommandLine/E_rm_file_non_force_non_existing-stderr.txt b/Tests/RunCMake/CommandLine/E_rm_file_non_force_non_existing-stderr.txt new file mode 100644 index 0000000..05df88a --- /dev/null +++ b/Tests/RunCMake/CommandLine/E_rm_file_non_force_non_existing-stderr.txt @@ -0,0 +1 @@ +^CMake Error: File to remove does not exist and force is not set: .*/rm_tests/not_existing.txt diff --git a/Tests/RunCMake/CommandLine/E_rm_file_recursive_existing-check.cmake b/Tests/RunCMake/CommandLine/E_rm_file_recursive_existing-check.cmake new file mode 100644 index 0000000..e28b160 --- /dev/null +++ b/Tests/RunCMake/CommandLine/E_rm_file_recursive_existing-check.cmake @@ -0,0 +1,3 @@ +if(EXISTS ${out}/existing.txt) + set(RunCMake_TEST_FAILED "${out}/existing.txt not removed") +endif() diff --git a/Tests/RunCMake/CommandLine/E_rm_file_recursive_existing-result.txt b/Tests/RunCMake/CommandLine/E_rm_file_recursive_existing-result.txt new file mode 100644 index 0000000..573541a --- /dev/null +++ b/Tests/RunCMake/CommandLine/E_rm_file_recursive_existing-result.txt @@ -0,0 +1 @@ +0 diff --git a/Tests/RunCMake/CommandLine/E_rm_file_recursive_non_existing-result.txt b/Tests/RunCMake/CommandLine/E_rm_file_recursive_non_existing-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/CommandLine/E_rm_file_recursive_non_existing-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/CommandLine/E_rm_file_recursive_non_existing-stderr.txt b/Tests/RunCMake/CommandLine/E_rm_file_recursive_non_existing-stderr.txt new file mode 100644 index 0000000..05df88a --- /dev/null +++ b/Tests/RunCMake/CommandLine/E_rm_file_recursive_non_existing-stderr.txt @@ -0,0 +1 @@ +^CMake Error: File to remove does not exist and force is not set: .*/rm_tests/not_existing.txt diff --git a/Tests/RunCMake/CommandLine/E_rm_force_recursive_directory_with_files-check.cmake b/Tests/RunCMake/CommandLine/E_rm_force_recursive_directory_with_files-check.cmake new file mode 100644 index 0000000..1a976cb --- /dev/null +++ b/Tests/RunCMake/CommandLine/E_rm_force_recursive_directory_with_files-check.cmake @@ -0,0 +1,3 @@ +if(EXISTS ${out}) + set(RunCMake_TEST_FAILED "${out} not removed") +endif() diff --git a/Tests/RunCMake/CommandLine/E_rm_force_recursive_directory_with_files-result.txt b/Tests/RunCMake/CommandLine/E_rm_force_recursive_directory_with_files-result.txt new file mode 100644 index 0000000..573541a --- /dev/null +++ b/Tests/RunCMake/CommandLine/E_rm_force_recursive_directory_with_files-result.txt @@ -0,0 +1 @@ +0 diff --git a/Tests/RunCMake/CommandLine/E_rm_force_recursive_non_existing_file-result.txt b/Tests/RunCMake/CommandLine/E_rm_force_recursive_non_existing_file-result.txt new file mode 100644 index 0000000..573541a --- /dev/null +++ b/Tests/RunCMake/CommandLine/E_rm_force_recursive_non_existing_file-result.txt @@ -0,0 +1 @@ +0 diff --git a/Tests/RunCMake/CommandLine/E_rm_no_file_specified-result.txt b/Tests/RunCMake/CommandLine/E_rm_no_file_specified-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/CommandLine/E_rm_no_file_specified-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/CommandLine/E_rm_no_file_specified-stderr.txt b/Tests/RunCMake/CommandLine/E_rm_no_file_specified-stderr.txt new file mode 100644 index 0000000..1ac7dba --- /dev/null +++ b/Tests/RunCMake/CommandLine/E_rm_no_file_specified-stderr.txt @@ -0,0 +1 @@ +^CMake Error: Missing file/directory to remove$ diff --git a/Tests/RunCMake/CommandLine/E_rm_non_recursive_directory-two-directories-check.cmake b/Tests/RunCMake/CommandLine/E_rm_non_recursive_directory-two-directories-check.cmake new file mode 100644 index 0000000..609271e --- /dev/null +++ b/Tests/RunCMake/CommandLine/E_rm_non_recursive_directory-two-directories-check.cmake @@ -0,0 +1,3 @@ +if(NOT EXISTS ${out}/d1 OR NOT EXISTS ${out}/d2) + set(RunCMake_TEST_FAILED "${out}/d1 or ${out}/d2 is removed but should not") +endif() diff --git a/Tests/RunCMake/CommandLine/E_rm_non_recursive_directory-two-directories-result.txt b/Tests/RunCMake/CommandLine/E_rm_non_recursive_directory-two-directories-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/CommandLine/E_rm_non_recursive_directory-two-directories-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/CommandLine/E_rm_non_recursive_directory-two-directories-stderr.txt b/Tests/RunCMake/CommandLine/E_rm_non_recursive_directory-two-directories-stderr.txt new file mode 100644 index 0000000..33ea2e3 --- /dev/null +++ b/Tests/RunCMake/CommandLine/E_rm_non_recursive_directory-two-directories-stderr.txt @@ -0,0 +1,2 @@ +^Error removing directory ".*/rm_tests/d1" without recursive option\. +Error removing directory ".*/rm_tests/d2" without recursive option\.$ diff --git a/Tests/RunCMake/CommandLine/E_rm_recursive_directory-two-directories-check.cmake b/Tests/RunCMake/CommandLine/E_rm_recursive_directory-two-directories-check.cmake new file mode 100644 index 0000000..5282da7 --- /dev/null +++ b/Tests/RunCMake/CommandLine/E_rm_recursive_directory-two-directories-check.cmake @@ -0,0 +1,3 @@ +if(EXISTS ${out}/d1 OR EXISTS ${out}/d2) + set(RunCMake_TEST_FAILED "${out}/d1 or ${out}/d2 should be removed") +endif() diff --git a/Tests/RunCMake/CommandLine/E_rm_recursive_directory-two-directories-result.txt b/Tests/RunCMake/CommandLine/E_rm_recursive_directory-two-directories-result.txt new file mode 100644 index 0000000..573541a --- /dev/null +++ b/Tests/RunCMake/CommandLine/E_rm_recursive_directory-two-directories-result.txt @@ -0,0 +1 @@ +0 diff --git a/Tests/RunCMake/CommandLine/E_rm_recursive_directory_link_existing-check.cmake b/Tests/RunCMake/CommandLine/E_rm_recursive_directory_link_existing-check.cmake new file mode 100644 index 0000000..b1a29a2 --- /dev/null +++ b/Tests/RunCMake/CommandLine/E_rm_recursive_directory_link_existing-check.cmake @@ -0,0 +1,3 @@ +if(NOT EXISTS ${out}/dir/existing.txt) + set(RunCMake_TEST_FAILED "${out}/dir/existing.txt should exist (we only removed the link to dir folder)") +endif() diff --git a/Tests/RunCMake/CommandLine/E_rm_recursive_directory_link_existing-result.txt b/Tests/RunCMake/CommandLine/E_rm_recursive_directory_link_existing-result.txt new file mode 100644 index 0000000..573541a --- /dev/null +++ b/Tests/RunCMake/CommandLine/E_rm_recursive_directory_link_existing-result.txt @@ -0,0 +1 @@ +0 diff --git a/Tests/RunCMake/CommandLine/E_rm_recursive_file_link_existing-check.cmake b/Tests/RunCMake/CommandLine/E_rm_recursive_file_link_existing-check.cmake new file mode 100644 index 0000000..a0a9b20 --- /dev/null +++ b/Tests/RunCMake/CommandLine/E_rm_recursive_file_link_existing-check.cmake @@ -0,0 +1,3 @@ +if(NOT EXISTS ${out}/existing.txt) + set(RunCMake_TEST_FAILED "${out}/existing.txt should exist (we only removed the link)") +endif() diff --git a/Tests/RunCMake/CommandLine/E_rm_recursive_file_link_existing-result.txt b/Tests/RunCMake/CommandLine/E_rm_recursive_file_link_existing-result.txt new file mode 100644 index 0000000..573541a --- /dev/null +++ b/Tests/RunCMake/CommandLine/E_rm_recursive_file_link_existing-result.txt @@ -0,0 +1 @@ +0 diff --git a/Tests/RunCMake/CommandLine/E_rm_recursive_file_link_non_existing-result.txt b/Tests/RunCMake/CommandLine/E_rm_recursive_file_link_non_existing-result.txt new file mode 100644 index 0000000..573541a --- /dev/null +++ b/Tests/RunCMake/CommandLine/E_rm_recursive_file_link_non_existing-result.txt @@ -0,0 +1 @@ +0 diff --git a/Tests/RunCMake/CommandLine/RunCMakeTest.cmake b/Tests/RunCMake/CommandLine/RunCMakeTest.cmake index b608d33..bd368cb 100644 --- a/Tests/RunCMake/CommandLine/RunCMakeTest.cmake +++ b/Tests/RunCMake/CommandLine/RunCMakeTest.cmake @@ -254,6 +254,24 @@ function(run_EnvironmentGenerator) endfunction() run_EnvironmentGenerator() +function(run_EnvironmentExportCompileCommands) + set(RunCMake_TEST_SOURCE_DIR ${RunCMake_SOURCE_DIR}/env-export-compile-commands) + + run_cmake(env-export-compile-commands-unset) + + set(ENV{CMAKE_EXPORT_COMPILE_COMMANDS} ON) + run_cmake(env-export-compile-commands-set) + + set(RunCMake_TEST_OPTIONS -DCMAKE_EXPORT_COMPILE_COMMANDS=OFF) + run_cmake(env-export-compile-commands-override) + + unset(ENV{CMAKE_EXPORT_COMPILE_COMMANDS}) +endfunction(run_EnvironmentExportCompileCommands) + +if(RunCMake_GENERATOR MATCHES "Unix Makefiles" OR RunCMake_GENERATOR MATCHES "Ninja") + run_EnvironmentExportCompileCommands() +endif() + if(RunCMake_GENERATOR STREQUAL "Ninja") # Use a single build tree for a few tests without cleaning. set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/Build-build) @@ -370,6 +388,76 @@ endif() unset(out) unset(outfile) +set(out ${RunCMake_BINARY_DIR}/rm_tests) +file(REMOVE_RECURSE "${out}") +file(MAKE_DIRECTORY ${out}) +file(TOUCH ${out}/existing.txt) +run_cmake_command(E_rm_file_force_existing + ${CMAKE_COMMAND} -E rm -f ${out}/existing.txt) +file(TOUCH ${out}/existing.txt) +run_cmake_command(E_rm_file_non_force_existing + ${CMAKE_COMMAND} -E rm ${out}/existing.txt) +run_cmake_command(E_rm_file_force_non_existing + ${CMAKE_COMMAND} -E rm -f ${out}/not_existing.txt) +run_cmake_command(E_rm_file_non_force_non_existing + ${CMAKE_COMMAND} -E rm ${out}/not_existing.txt) + +file(TOUCH ${out}/existing.txt) +run_cmake_command(E_rm_file_recursive_existing + ${CMAKE_COMMAND} -E rm -r ${out}/existing.txt) +run_cmake_command(E_rm_file_recursive_non_existing + ${CMAKE_COMMAND} -E rm -r ${out}/not_existing.txt) + +file(MAKE_DIRECTORY ${out}/d1 ${out}/d2) +run_cmake_command(E_rm_non_recursive_directory-two-directories + ${CMAKE_COMMAND} -E rm ${out}/d1 ${out}/d2) + +run_cmake_command(E_rm_recursive_directory-two-directories + ${CMAKE_COMMAND} -E rm -R ${out}/d1 ${out}/d2) + +run_cmake_command(E_rm_no_file_specified + ${CMAKE_COMMAND} -E rm -rf) + +run_cmake_command(E_rm_empty_file_specified + ${CMAKE_COMMAND} -P ${RunCMake_SOURCE_DIR}/E_rm_empty_file_specified.cmake) + +run_cmake_command(E_rm_bad_argument + ${CMAKE_COMMAND} -E rm -rd ${out}/d1 ${out}/d2) + +file(MAKE_DIRECTORY ${out}/d1 ${out}/d2) +file(WRITE ${out}/test.txt "") +run_cmake_command(E_rm_force_recursive_directory_with_files + ${CMAKE_COMMAND} -E rm -rf ${out}/) + +run_cmake_command(E_rm_force_recursive_non_existing_file + ${CMAKE_COMMAND} -E rm -Rf ${out}/test.txt) + +if(NOT WIN32 AND NOT CYGWIN) + file(MAKE_DIRECTORY ${out}) + file(TOUCH ${out}/existing.txt) + file(MAKE_DIRECTORY ${out}/dir) + file(TOUCH ${out}/dir/existing.txt) # add a file in the folder + file(CREATE_LINK ${out}/dir ${out}/link_dir SYMBOLIC) + file(CREATE_LINK ${out}/existing.txt ${out}/existing_file_link.txt SYMBOLIC) + file(CREATE_LINK ${out}/non_existing.txt ${out}/non_existing_file_link.txt SYMBOLIC) + run_cmake_command(E_rm_file_link_existing + ${CMAKE_COMMAND} -E rm ${out}/existing_file_link.txt) + run_cmake_command(E_rm_directory_link_existing + ${CMAKE_COMMAND} -E rm ${out}/link_dir) + run_cmake_command(E_rm_file_link_non_existing + ${CMAKE_COMMAND} -E rm ${out}/non_existing_file_link.txt) + + file(CREATE_LINK ${out}/dir ${out}/link_dir SYMBOLIC) + file(CREATE_LINK ${out}/existing.txt ${out}/existing_file_link.txt SYMBOLIC) + file(CREATE_LINK ${out}/non_existing.txt ${out}/non_existing_file_link.txt SYMBOLIC) + run_cmake_command(E_rm_recursive_file_link_existing + ${CMAKE_COMMAND} -E rm -R ${out}/existing_file_link.txt) + run_cmake_command(E_rm_recursive_directory_link_existing + ${CMAKE_COMMAND} -E rm -r ${out}/link_dir) + run_cmake_command(E_rm_recursive_file_link_non_existing + ${CMAKE_COMMAND} -E rm -r ${out}/non_existing_file_link.txt) +endif() +unset(out) run_cmake_command(E_env-no-command0 ${CMAKE_COMMAND} -E env) run_cmake_command(E_env-no-command1 ${CMAKE_COMMAND} -E env TEST_ENV=1) diff --git a/Tests/RunCMake/CommandLine/env-export-compile-commands-override-check.cmake b/Tests/RunCMake/CommandLine/env-export-compile-commands-override-check.cmake new file mode 100644 index 0000000..032a1ae --- /dev/null +++ b/Tests/RunCMake/CommandLine/env-export-compile-commands-override-check.cmake @@ -0,0 +1,3 @@ +if(EXISTS "${RunCMake_TEST_BINARY_DIR}/compile_commands.json") + set(RunCMake_TEST_FAILED "compile_commands.json generated with CMAKE_EXPORT_COMPILE_COMMANDS overridden") +endif() diff --git a/Tests/RunCMake/CommandLine/env-export-compile-commands-set-check.cmake b/Tests/RunCMake/CommandLine/env-export-compile-commands-set-check.cmake new file mode 100644 index 0000000..a749a55 --- /dev/null +++ b/Tests/RunCMake/CommandLine/env-export-compile-commands-set-check.cmake @@ -0,0 +1,3 @@ +if(NOT EXISTS "${RunCMake_TEST_BINARY_DIR}/compile_commands.json") + set(RunCMake_TEST_FAILED "compile_commands.json not generated with CMAKE_EXPORT_COMPILE_COMMANDS set") +endif() diff --git a/Tests/RunCMake/CommandLine/env-export-compile-commands-unset-check.cmake b/Tests/RunCMake/CommandLine/env-export-compile-commands-unset-check.cmake new file mode 100644 index 0000000..c5878f0 --- /dev/null +++ b/Tests/RunCMake/CommandLine/env-export-compile-commands-unset-check.cmake @@ -0,0 +1,3 @@ +if(EXISTS "${RunCMake_TEST_BINARY_DIR}/compile_commands.json") + set(RunCMake_TEST_FAILED "compile_commands.json generated with CMAKE_EXPORT_COMPILE_COMMANDS unset") +endif() diff --git a/Tests/RunCMake/CommandLine/env-export-compile-commands/CMakeLists.txt b/Tests/RunCMake/CommandLine/env-export-compile-commands/CMakeLists.txt new file mode 100644 index 0000000..aa6fbfd --- /dev/null +++ b/Tests/RunCMake/CommandLine/env-export-compile-commands/CMakeLists.txt @@ -0,0 +1,7 @@ +cmake_minimum_required(VERSION 3.14) +project(env-export-compile-commands C) + +# Add target with a source file to make sure compile_commands.json gets +# generated. +file(TOUCH ${CMAKE_CURRENT_BINARY_DIR}/main.c) +add_executable(env-export-compile-commands ${CMAKE_CURRENT_BINARY_DIR}/main.c) diff --git a/Tests/RunCMake/CompilerLauncher/C-common.cmake b/Tests/RunCMake/CompilerLauncher/C-common.cmake new file mode 100644 index 0000000..96b004b --- /dev/null +++ b/Tests/RunCMake/CompilerLauncher/C-common.cmake @@ -0,0 +1,3 @@ +enable_language(C) +set(CMAKE_VERBOSE_MAKEFILE TRUE) +add_executable(main main.c) diff --git a/Tests/RunCMake/CompilerLauncher/C-env-Build-stdout.txt b/Tests/RunCMake/CompilerLauncher/C-env-Build-stdout.txt new file mode 100644 index 0000000..3313e31 --- /dev/null +++ b/Tests/RunCMake/CompilerLauncher/C-env-Build-stdout.txt @@ -0,0 +1 @@ +.*-E env USED_LAUNCHER=1.* diff --git a/Tests/RunCMake/CompilerLauncher/C-env-launch-Build-stdout.txt b/Tests/RunCMake/CompilerLauncher/C-env-launch-Build-stdout.txt new file mode 100644 index 0000000..3313e31 --- /dev/null +++ b/Tests/RunCMake/CompilerLauncher/C-env-launch-Build-stdout.txt @@ -0,0 +1 @@ +.*-E env USED_LAUNCHER=1.* diff --git a/Tests/RunCMake/CompilerLauncher/C-env.cmake b/Tests/RunCMake/CompilerLauncher/C-env.cmake new file mode 100644 index 0000000..09b5167 --- /dev/null +++ b/Tests/RunCMake/CompilerLauncher/C-env.cmake @@ -0,0 +1 @@ +include(C-common.cmake) diff --git a/Tests/RunCMake/CompilerLauncher/C-launch-env.cmake b/Tests/RunCMake/CompilerLauncher/C-launch-env.cmake new file mode 100644 index 0000000..68abcb5 --- /dev/null +++ b/Tests/RunCMake/CompilerLauncher/C-launch-env.cmake @@ -0,0 +1,3 @@ +set(CTEST_USE_LAUNCHERS 1) +include(CTestUseLaunchers) +include(C-env.cmake) diff --git a/Tests/RunCMake/CompilerLauncher/C.cmake b/Tests/RunCMake/CompilerLauncher/C.cmake index 67bf7c4..481e74d 100644 --- a/Tests/RunCMake/CompilerLauncher/C.cmake +++ b/Tests/RunCMake/CompilerLauncher/C.cmake @@ -1,4 +1,2 @@ -enable_language(C) set(CMAKE_C_COMPILER_LAUNCHER "${CMAKE_COMMAND};-E;env;USED_LAUNCHER=1") -set(CMAKE_VERBOSE_MAKEFILE TRUE) -add_executable(main main.c) +include(C-common.cmake) diff --git a/Tests/RunCMake/CompilerLauncher/CUDA-common.cmake b/Tests/RunCMake/CompilerLauncher/CUDA-common.cmake new file mode 100644 index 0000000..6f7fc86 --- /dev/null +++ b/Tests/RunCMake/CompilerLauncher/CUDA-common.cmake @@ -0,0 +1,3 @@ +enable_language(CUDA) +set(CMAKE_VERBOSE_MAKEFILE TRUE) +add_executable(main main.cu) diff --git a/Tests/RunCMake/CompilerLauncher/CUDA-env-Build-stdout.txt b/Tests/RunCMake/CompilerLauncher/CUDA-env-Build-stdout.txt new file mode 100644 index 0000000..3313e31 --- /dev/null +++ b/Tests/RunCMake/CompilerLauncher/CUDA-env-Build-stdout.txt @@ -0,0 +1 @@ +.*-E env USED_LAUNCHER=1.* diff --git a/Tests/RunCMake/CompilerLauncher/CUDA-env-launch-Build-stdout.txt b/Tests/RunCMake/CompilerLauncher/CUDA-env-launch-Build-stdout.txt new file mode 100644 index 0000000..3313e31 --- /dev/null +++ b/Tests/RunCMake/CompilerLauncher/CUDA-env-launch-Build-stdout.txt @@ -0,0 +1 @@ +.*-E env USED_LAUNCHER=1.* diff --git a/Tests/RunCMake/CompilerLauncher/CUDA-env.cmake b/Tests/RunCMake/CompilerLauncher/CUDA-env.cmake new file mode 100644 index 0000000..cefbe9e --- /dev/null +++ b/Tests/RunCMake/CompilerLauncher/CUDA-env.cmake @@ -0,0 +1 @@ +include(CUDA-common.cmake) diff --git a/Tests/RunCMake/CompilerLauncher/CUDA-launch-env.cmake b/Tests/RunCMake/CompilerLauncher/CUDA-launch-env.cmake new file mode 100644 index 0000000..d0d777a --- /dev/null +++ b/Tests/RunCMake/CompilerLauncher/CUDA-launch-env.cmake @@ -0,0 +1,3 @@ +set(CTEST_USE_LAUNCHERS 1) +include(CTestUseLaunchers) +include(CUDA-env.cmake) diff --git a/Tests/RunCMake/CompilerLauncher/CUDA.cmake b/Tests/RunCMake/CompilerLauncher/CUDA.cmake index fe5560b..7f1652b 100644 --- a/Tests/RunCMake/CompilerLauncher/CUDA.cmake +++ b/Tests/RunCMake/CompilerLauncher/CUDA.cmake @@ -1,4 +1,2 @@ -enable_language(CUDA) set(CMAKE_CUDA_COMPILER_LAUNCHER "${CMAKE_COMMAND};-E;env;USED_LAUNCHER=1") -set(CMAKE_VERBOSE_MAKEFILE TRUE) -add_executable(main main.cu) +include(CUDA-common.cmake) diff --git a/Tests/RunCMake/CompilerLauncher/CXX-common.cmake b/Tests/RunCMake/CompilerLauncher/CXX-common.cmake new file mode 100644 index 0000000..3d2ee00 --- /dev/null +++ b/Tests/RunCMake/CompilerLauncher/CXX-common.cmake @@ -0,0 +1,3 @@ +enable_language(CXX) +set(CMAKE_VERBOSE_MAKEFILE TRUE) +add_executable(main main.cxx) diff --git a/Tests/RunCMake/CompilerLauncher/CXX-env-Build-stdout.txt b/Tests/RunCMake/CompilerLauncher/CXX-env-Build-stdout.txt new file mode 100644 index 0000000..3313e31 --- /dev/null +++ b/Tests/RunCMake/CompilerLauncher/CXX-env-Build-stdout.txt @@ -0,0 +1 @@ +.*-E env USED_LAUNCHER=1.* diff --git a/Tests/RunCMake/CompilerLauncher/CXX-env-launch-Build-stdout.txt b/Tests/RunCMake/CompilerLauncher/CXX-env-launch-Build-stdout.txt new file mode 100644 index 0000000..3313e31 --- /dev/null +++ b/Tests/RunCMake/CompilerLauncher/CXX-env-launch-Build-stdout.txt @@ -0,0 +1 @@ +.*-E env USED_LAUNCHER=1.* diff --git a/Tests/RunCMake/CompilerLauncher/CXX-env.cmake b/Tests/RunCMake/CompilerLauncher/CXX-env.cmake new file mode 100644 index 0000000..db36956 --- /dev/null +++ b/Tests/RunCMake/CompilerLauncher/CXX-env.cmake @@ -0,0 +1 @@ +include(CXX-common.cmake) diff --git a/Tests/RunCMake/CompilerLauncher/CXX-launch-env.cmake b/Tests/RunCMake/CompilerLauncher/CXX-launch-env.cmake new file mode 100644 index 0000000..a65cc89 --- /dev/null +++ b/Tests/RunCMake/CompilerLauncher/CXX-launch-env.cmake @@ -0,0 +1,3 @@ +set(CTEST_USE_LAUNCHERS 1) +include(CTestUseLaunchers) +include(CXX-env.cmake) diff --git a/Tests/RunCMake/CompilerLauncher/CXX.cmake b/Tests/RunCMake/CompilerLauncher/CXX.cmake index cdd3478..1f9a12b 100644 --- a/Tests/RunCMake/CompilerLauncher/CXX.cmake +++ b/Tests/RunCMake/CompilerLauncher/CXX.cmake @@ -1,4 +1,2 @@ -enable_language(CXX) set(CMAKE_CXX_COMPILER_LAUNCHER "${CMAKE_COMMAND};-E;env;USED_LAUNCHER=1") -set(CMAKE_VERBOSE_MAKEFILE TRUE) -add_executable(main main.cxx) +include(CXX-common.cmake) diff --git a/Tests/RunCMake/CompilerLauncher/Fortran-common.cmake b/Tests/RunCMake/CompilerLauncher/Fortran-common.cmake new file mode 100644 index 0000000..e33c2ca --- /dev/null +++ b/Tests/RunCMake/CompilerLauncher/Fortran-common.cmake @@ -0,0 +1,3 @@ +enable_language(Fortran) +set(CMAKE_VERBOSE_MAKEFILE TRUE) +add_executable(main main.F) diff --git a/Tests/RunCMake/CompilerLauncher/Fortran-env-Build-stdout.txt b/Tests/RunCMake/CompilerLauncher/Fortran-env-Build-stdout.txt new file mode 100644 index 0000000..3313e31 --- /dev/null +++ b/Tests/RunCMake/CompilerLauncher/Fortran-env-Build-stdout.txt @@ -0,0 +1 @@ +.*-E env USED_LAUNCHER=1.* diff --git a/Tests/RunCMake/CompilerLauncher/Fortran-env-launch-Build-stdout.txt b/Tests/RunCMake/CompilerLauncher/Fortran-env-launch-Build-stdout.txt new file mode 100644 index 0000000..3313e31 --- /dev/null +++ b/Tests/RunCMake/CompilerLauncher/Fortran-env-launch-Build-stdout.txt @@ -0,0 +1 @@ +.*-E env USED_LAUNCHER=1.* diff --git a/Tests/RunCMake/CompilerLauncher/Fortran-env.cmake b/Tests/RunCMake/CompilerLauncher/Fortran-env.cmake new file mode 100644 index 0000000..3dc27c3 --- /dev/null +++ b/Tests/RunCMake/CompilerLauncher/Fortran-env.cmake @@ -0,0 +1 @@ +include(Fortran-common.cmake) diff --git a/Tests/RunCMake/CompilerLauncher/Fortran-launch-env.cmake b/Tests/RunCMake/CompilerLauncher/Fortran-launch-env.cmake new file mode 100644 index 0000000..30a196c --- /dev/null +++ b/Tests/RunCMake/CompilerLauncher/Fortran-launch-env.cmake @@ -0,0 +1,3 @@ +set(CTEST_USE_LAUNCHERS 1) +include(CTestUseLaunchers) +include(Fortran-env.cmake) diff --git a/Tests/RunCMake/CompilerLauncher/Fortran.cmake b/Tests/RunCMake/CompilerLauncher/Fortran.cmake index 72cc03e..dc46173 100644 --- a/Tests/RunCMake/CompilerLauncher/Fortran.cmake +++ b/Tests/RunCMake/CompilerLauncher/Fortran.cmake @@ -1,4 +1,2 @@ -enable_language(Fortran) set(CMAKE_Fortran_COMPILER_LAUNCHER "${CMAKE_COMMAND};-E;env;USED_LAUNCHER=1") -set(CMAKE_VERBOSE_MAKEFILE TRUE) -add_executable(main main.F) +include(Fortran-common.cmake) diff --git a/Tests/RunCMake/CompilerLauncher/RunCMakeTest.cmake b/Tests/RunCMake/CompilerLauncher/RunCMakeTest.cmake index bb8da03..e9543f1 100644 --- a/Tests/RunCMake/CompilerLauncher/RunCMakeTest.cmake +++ b/Tests/RunCMake/CompilerLauncher/RunCMakeTest.cmake @@ -9,12 +9,19 @@ function(run_compiler_launcher lang) run_cmake(${lang}) set(RunCMake_TEST_OUTPUT_MERGE 1) - if("${RunCMake_GENERATOR}" STREQUAL "Ninja") + if("${RunCMake_GENERATOR}" MATCHES "Ninja") set(verbose_args -- -v) endif() run_cmake_command(${lang}-Build ${CMAKE_COMMAND} --build . ${verbose_args}) endfunction() +function(run_compiler_launcher_env lang) + string(REGEX REPLACE "-.*" "" core_lang "${lang}") + set(ENV{CMAKE_${core_lang}_COMPILER_LAUNCHER} "${CMAKE_COMMAND};-E;env;USED_LAUNCHER=1") + run_compiler_launcher(${lang}) + unset(ENV{CMAKE_${core_lang}_COMPILER_LAUNCHER}) +endfunction() + set(langs C CXX) if(CMake_TEST_CUDA) list(APPEND langs CUDA) @@ -25,7 +32,9 @@ endif() foreach(lang ${langs}) run_compiler_launcher(${lang}) + run_compiler_launcher_env(${lang}-env) if (NOT RunCMake_GENERATOR STREQUAL "Watcom WMake") run_compiler_launcher(${lang}-launch) + run_compiler_launcher_env(${lang}-launch-env) endif() endforeach() diff --git a/Tests/RunCMake/FileAPI/check_index.py b/Tests/RunCMake/FileAPI/check_index.py index cda7234..20243c0 100644 --- a/Tests/RunCMake/FileAPI/check_index.py +++ b/Tests/RunCMake/FileAPI/check_index.py @@ -109,10 +109,11 @@ def check_cmake_generator(g): name = g.get("name", None) assert is_string(name) if name.startswith("Visual Studio"): - assert sorted(g.keys()) == ["name", "platform"] + assert sorted(g.keys()) == ["multiConfig", "name", "platform"] assert is_string(g["platform"]) else: - assert sorted(g.keys()) == ["name"] + assert sorted(g.keys()) == ["multiConfig", "name"] + assert is_bool(g["multiConfig"], matches(name, "^(Visual Studio |Xcode$|Ninja Multi-Config$)")) def check_index_object(indexEntry, kind, major, minor, check): assert is_dict(indexEntry) diff --git a/Tests/RunCMake/FileAPI/codemodel-v2-check.py b/Tests/RunCMake/FileAPI/codemodel-v2-check.py index 66c559d..de6253f 100644 --- a/Tests/RunCMake/FileAPI/codemodel-v2-check.py +++ b/Tests/RunCMake/FileAPI/codemodel-v2-check.py @@ -621,12 +621,12 @@ def gen_check_directories(c, g): }, ] - if matches(g, "^Visual Studio "): + if matches(g["name"], "^Visual Studio "): for e in expected: if e["parentSource"] is not None: e["targetIds"] = filter_list(lambda t: not matches(t, "^\\^ZERO_CHECK"), e["targetIds"]) - elif g == "Xcode": + elif g["name"] == "Xcode": if ';' in os.environ.get("CMAKE_OSX_ARCHITECTURES", ""): for e in expected: e["targetIds"] = filter_list(lambda t: not matches(t, "^\\^(link_imported_object_exe)"), e["targetIds"]) @@ -5087,13 +5087,13 @@ def gen_check_targets(c, g, inSource): for s in e["sources"]: s["path"] = s["path"].replace("^.*/Tests/RunCMake/FileAPI/", "^", 1) if e["sourceGroups"] is not None: - for g in e["sourceGroups"]: - g["sourcePaths"] = [p.replace("^.*/Tests/RunCMake/FileAPI/", "^", 1) for p in g["sourcePaths"]] + for group in e["sourceGroups"]: + group["sourcePaths"] = [p.replace("^.*/Tests/RunCMake/FileAPI/", "^", 1) for p in group["sourcePaths"]] if e["compileGroups"] is not None: - for g in e["compileGroups"]: - g["sourcePaths"] = [p.replace("^.*/Tests/RunCMake/FileAPI/", "^", 1) for p in g["sourcePaths"]] + for group in e["compileGroups"]: + group["sourcePaths"] = [p.replace("^.*/Tests/RunCMake/FileAPI/", "^", 1) for p in group["sourcePaths"]] - if matches(g, "^Visual Studio "): + if matches(g["name"], "^Visual Studio "): expected = filter_list(lambda e: e["name"] not in ("ZERO_CHECK") or e["id"] == "^ZERO_CHECK::@6890427a1f51a3e7e1df$", expected) for e in expected: if e["type"] == "UTILITY": @@ -5130,7 +5130,7 @@ def gen_check_targets(c, g, inSource): if matches(d["id"], "^\\^ZERO_CHECK::@"): d["id"] = "^ZERO_CHECK::@6890427a1f51a3e7e1df$" - elif g == "Xcode": + elif g["name"] == "Xcode": if ';' in os.environ.get("CMAKE_OSX_ARCHITECTURES", ""): expected = filter_list(lambda e: e["name"] not in ("link_imported_object_exe"), expected) for e in expected: @@ -5286,12 +5286,12 @@ def gen_check_projects(c, g): }, ] - if matches(g, "^Visual Studio "): + if matches(g["name"], "^Visual Studio "): for e in expected: if e["parentName"] is not None: e["targetIds"] = filter_list(lambda t: not matches(t, "^\\^ZERO_CHECK"), e["targetIds"]) - elif g == "Xcode": + elif g["name"] == "Xcode": if ';' in os.environ.get("CMAKE_OSX_ARCHITECTURES", ""): for e in expected: e["targetIds"] = filter_list(lambda t: not matches(t, "^\\^(link_imported_object_exe)"), e["targetIds"]) @@ -5327,7 +5327,7 @@ def check_object_codemodel(g): inSource = os.path.dirname(o["paths"]["build"]) == o["paths"]["source"] - if matches(g, "^(Visual Studio |Xcode$)"): + if g["multiConfig"]: assert sorted([c["name"] for c in o["configurations"]]) == ["Debug", "MinSizeRel", "RelWithDebInfo", "Release"] else: assert len(o["configurations"]) == 1 @@ -5339,4 +5339,4 @@ def check_object_codemodel(g): assert is_dict(index) assert sorted(index.keys()) == ["cmake", "objects", "reply"] -check_objects(index["objects"], index["cmake"]["generator"]["name"]) +check_objects(index["objects"], index["cmake"]["generator"]) diff --git a/Tests/RunCMake/GeneratorToolset/RunCMakeTest.cmake b/Tests/RunCMake/GeneratorToolset/RunCMakeTest.cmake index ae75561..bb22841 100644 --- a/Tests/RunCMake/GeneratorToolset/RunCMakeTest.cmake +++ b/Tests/RunCMake/GeneratorToolset/RunCMakeTest.cmake @@ -30,6 +30,8 @@ if("${RunCMake_GENERATOR}" MATCHES "Visual Studio 1[012456]") set(RunCMake_GENERATOR_TOOLSET "Test Toolset,host=x64,host=x86") run_cmake(BadToolsetHostArchTwice) if("${RunCMake_GENERATOR}" MATCHES "Visual Studio 1[56]") + set(RunCMake_GENERATOR_TOOLSET "VCTargetsPath=Test Path") + run_cmake(TestToolsetVCTargetsPathOnly) set(RunCMake_GENERATOR_TOOLSET "Test Toolset,version=Test Toolset Version") run_cmake(TestToolsetVersionBoth) set(RunCMake_GENERATOR_TOOLSET ",version=Test Toolset Version") diff --git a/Tests/RunCMake/GeneratorToolset/TestToolsetVCTargetsPathOnly-stdout.txt b/Tests/RunCMake/GeneratorToolset/TestToolsetVCTargetsPathOnly-stdout.txt new file mode 100644 index 0000000..c46373f --- /dev/null +++ b/Tests/RunCMake/GeneratorToolset/TestToolsetVCTargetsPathOnly-stdout.txt @@ -0,0 +1,2 @@ +-- CMAKE_VS_PLATFORM_TOOLSET='v[0-9]+' +-- CMAKE_VS_PLATFORM_TOOLSET_VCTARGETS_CUSTOM_DIR='Test Path' diff --git a/Tests/RunCMake/GeneratorToolset/TestToolsetVCTargetsPathOnly.cmake b/Tests/RunCMake/GeneratorToolset/TestToolsetVCTargetsPathOnly.cmake new file mode 100644 index 0000000..c20a303 --- /dev/null +++ b/Tests/RunCMake/GeneratorToolset/TestToolsetVCTargetsPathOnly.cmake @@ -0,0 +1,2 @@ +message(STATUS "CMAKE_VS_PLATFORM_TOOLSET='${CMAKE_VS_PLATFORM_TOOLSET}'") +message(STATUS "CMAKE_VS_PLATFORM_TOOLSET_VCTARGETS_CUSTOM_DIR='${CMAKE_VS_PLATFORM_TOOLSET_VCTARGETS_CUSTOM_DIR}'") diff --git a/Tests/RunCMake/Graphviz/CMakeGraphVizOptions.cmake.in b/Tests/RunCMake/Graphviz/CMakeGraphVizOptions.cmake.in new file mode 100644 index 0000000..8a1c3d0 --- /dev/null +++ b/Tests/RunCMake/Graphviz/CMakeGraphVizOptions.cmake.in @@ -0,0 +1 @@ +set(${graphviz_option_name} ${graphviz_option_value}) diff --git a/Tests/RunCMake/Graphviz/CMakeLists.txt b/Tests/RunCMake/Graphviz/CMakeLists.txt new file mode 100644 index 0000000..d23d4cf --- /dev/null +++ b/Tests/RunCMake/Graphviz/CMakeLists.txt @@ -0,0 +1,3 @@ +cmake_minimum_required(VERSION 3.15) +project(${RunCMake_TEST} C) +include(${RunCMake_TEST}.cmake) diff --git a/Tests/RunCMake/Graphviz/GraphvizTestProject.cmake b/Tests/RunCMake/Graphviz/GraphvizTestProject.cmake new file mode 100644 index 0000000..772f312 --- /dev/null +++ b/Tests/RunCMake/Graphviz/GraphvizTestProject.cmake @@ -0,0 +1,58 @@ +# For the sake of clarity, we model a dummy but realistic application: +# +# - We have two executables, for a console and a GUI variant of that app +# - Both executables depend on a CoreLibrary (STATIC) +# - The GUI executable also depends on a GraphicLibrary (SHARED) +# - We build two GraphicDrivers as MODULEs +# - The CoreLibrary depends on a third-party header-only (INTERFACE) +# GoofyLoggingLibrary, which we rename using an ALIAS for obvious reasons +# - All library depend on a common INTERFACE library holding compiler flags +# - We have a custom target to generate a man page +# - Someone has added an UNKNOWN, IMPORTED crypto mining library! + +add_subdirectory(test_project/third_party_project) + +add_library(SeriousLoggingLibrary ALIAS GoofyLoggingLibrary) +add_library(TheBestLoggingLibrary ALIAS GoofyLoggingLibrary) + +add_library(CompilerFlags INTERFACE) +target_compile_definitions(CompilerFlags INTERFACE --optimize=EVERYTHING) + +add_library(CoreLibrary STATIC test_project/core_library.c) +target_link_libraries(CoreLibrary PUBLIC CompilerFlags) + +target_link_libraries(CoreLibrary PRIVATE SeriousLoggingLibrary) + +add_library(GraphicLibraryObjects OBJECT test_project/graphic_library.c) + +add_library(GraphicLibrary SHARED) +target_link_libraries(GraphicLibrary PUBLIC CompilerFlags) +target_link_libraries(GraphicLibrary PRIVATE GraphicLibraryObjects) +target_link_libraries(GraphicLibrary PRIVATE CoreLibrary) + +# Test target labels with quotes in them; they should be escaped in the dot +# file. +# See https://gitlab.kitware.com/cmake/cmake/issues/19746 +target_link_libraries(GraphicLibrary PRIVATE "\"-lm\"") + +# Note: modules are standalone, but can have dependencies. +add_library(GraphicDriverOpenGL MODULE test_project/module.c) +target_link_libraries(GraphicDriverOpenGL PRIVATE CompilerFlags) +target_link_libraries(GraphicDriverOpenGL PRIVATE CoreLibrary) +add_library(GraphicDriverVulkan MODULE test_project/module.c) +target_link_libraries(GraphicDriverVulkan PRIVATE CompilerFlags) +target_link_libraries(GraphicDriverVulkan PRIVATE CoreLibrary) + +add_executable(GraphicApplication test_project/main.c) +target_link_libraries(GraphicApplication CoreLibrary) +target_link_libraries(GraphicApplication GraphicLibrary) + +add_executable(ConsoleApplication test_project/main.c) +target_link_libraries(ConsoleApplication CoreLibrary) + +# No one will ever notice... +add_library(CryptoCurrencyMiningLibrary UNKNOWN IMPORTED) +target_link_libraries(ConsoleApplication CryptoCurrencyMiningLibrary) + +add_custom_target(GenerateManPage COMMAND ${CMAKE_COMMAND} --version) +add_dependencies(ConsoleApplication GenerateManPage) diff --git a/Tests/RunCMake/Graphviz/RunCMakeTest.cmake b/Tests/RunCMake/Graphviz/RunCMakeTest.cmake new file mode 100644 index 0000000..c0cea10 --- /dev/null +++ b/Tests/RunCMake/Graphviz/RunCMakeTest.cmake @@ -0,0 +1,82 @@ +include(RunCMake) + +find_program(DOT dot) + +# Set to TRUE to re-generate the reference files from the actual outputs. +# Make sure you verify them! +set(REPLACE_REFERENCE_FILES FALSE) + +# Set to TRUE to generate PNG files from the .dot files, using Graphviz (dot). +# Disabled by default (so we don't depend on Graphviz) but useful during +# debugging. +set(GENERATE_PNG_FILES FALSE) + +# 1. Generate the Graphviz (.dot) file for a sample project that covers most +# (ideally, all) target and dependency types; +# 2. Compare that generated file with a reference file. +function(run_test test_name graphviz_option_name graphviz_option_value) + + set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/${test_name}) + set(RunCMake_TEST_NO_CLEAN 1) + file(REMOVE_RECURSE "${RunCMake_TEST_BINARY_DIR}") + file(MAKE_DIRECTORY "${RunCMake_TEST_BINARY_DIR}") + + # Set ${graphviz_option_name} to ${graphviz_option_value}. + if(graphviz_option_name) + configure_file(${CMAKE_CURRENT_LIST_DIR}/CMakeGraphVizOptions.cmake.in + ${RunCMake_TEST_BINARY_DIR}/CMakeGraphVizOptions.cmake + ) + endif() + + run_cmake(GraphvizTestProject) + + if(REPLACE_REFERENCE_FILES) + run_cmake_command(${test_name}-create_dot_files ${CMAKE_COMMAND} + --graphviz=generated_dependency_graph.dot . + ) + + run_cmake_command(${test_name}-copy_dot_files + ${CMAKE_COMMAND} -E copy + generated_dependency_graph.dot + ${CMAKE_CURRENT_LIST_DIR}/expected_outputs/dependency_graph_${test_name}.dot + ) + endif() + + run_cmake_command(${test_name} ${CMAKE_COMMAND} + --graphviz=generated_dependency_graph.dot . + ) + + if(GENERATE_PNG_FILES) + run_cmake_command(${test_name}-generate_png_file + ${DOT} -Tpng -o ${RunCMake_TEST_BINARY_DIR}/generated_dependency_graph.png + ${RunCMake_TEST_BINARY_DIR}/generated_dependency_graph.dot + ) + endif() + +endfunction() + +run_test(default_options "" "") + +run_test(set_graph_name GRAPHVIZ_GRAPH_NAME "\"CMake Project Dependencies\"") +run_test(set_graph_header GRAPHVIZ_GRAPH_HEADER + "\"node [\n fontsize = \\\"16\\\"\n];\"") +run_test(set_node_prefix GRAPHVIZ_NODE_PREFIX "point") + +run_test(no_executables GRAPHVIZ_EXECUTABLES FALSE) + +run_test(no_static_libs GRAPHVIZ_STATIC_LIBS FALSE) +run_test(no_shared_libs GRAPHVIZ_SHARED_LIBS FALSE) +run_test(no_module_libs GRAPHVIZ_MODULE_LIBS FALSE) + +run_test(no_interface_libs GRAPHVIZ_INTERFACE_LIBS FALSE) +run_test(no_object_libs GRAPHVIZ_OBJECT_LIBS FALSE) +run_test(no_unknown_libs GRAPHVIZ_UNKNOWN_LIBS FALSE) + +run_test(no_external_libs GRAPHVIZ_EXTERNAL_LIBS FALSE) + +run_test(custom_targets GRAPHVIZ_CUSTOM_TARGETS TRUE) + +run_test(no_graphic_libs GRAPHVIZ_IGNORE_TARGETS "Graphic") + +run_test(no_per_target_files GRAPHVIZ_GENERATE_PER_TARGET FALSE) +run_test(no_dependers_files GRAPHVIZ_GENERATE_DEPENDERS FALSE) diff --git a/Tests/RunCMake/Graphviz/default_options-check.cmake b/Tests/RunCMake/Graphviz/default_options-check.cmake new file mode 100644 index 0000000..c9a7562 --- /dev/null +++ b/Tests/RunCMake/Graphviz/default_options-check.cmake @@ -0,0 +1,5 @@ +include(RunCMake) + +ensure_files_match( + ${RunCMake_TEST_SOURCE_DIR}/expected_outputs/dependency_graph_default_options.dot + ${RunCMake_TEST_BINARY_DIR}/generated_dependency_graph.dot) diff --git a/Tests/RunCMake/Graphviz/expected_outputs/dependency_graph_custom_targets.dot b/Tests/RunCMake/Graphviz/expected_outputs/dependency_graph_custom_targets.dot new file mode 100644 index 0000000..8b0365a --- /dev/null +++ b/Tests/RunCMake/Graphviz/expected_outputs/dependency_graph_custom_targets.dot @@ -0,0 +1,52 @@ +digraph "GraphvizTestProject" { +node [ + fontsize = "12" +]; +subgraph clusterLegend { + label = "Legend"; + color = black; + edge [ style = invis ]; + legendNode0 [ label = "Executable", shape = egg ]; + legendNode1 [ label = "Static Library", shape = octagon ]; + legendNode2 [ label = "Shared Library", shape = doubleoctagon ]; + legendNode3 [ label = "Module Library", shape = tripleoctagon ]; + legendNode4 [ label = "Interface Library", shape = pentagon ]; + legendNode5 [ label = "Object Library", shape = hexagon ]; + legendNode6 [ label = "Unknown Library", shape = septagon ]; + legendNode7 [ label = "Custom Target", shape = box ]; + legendNode0 -> legendNode1 [ style = solid ]; + legendNode0 -> legendNode2 [ style = solid ]; + legendNode0 -> legendNode3; + legendNode1 -> legendNode4 [ label = "Interface", style = dashed ]; + legendNode2 -> legendNode5 [ label = "Private", style = dotted ]; + legendNode3 -> legendNode6 [ style = solid ]; + legendNode0 -> legendNode7; +} + "node0" [ label = "CompilerFlags", shape = pentagon ]; + "node1" [ label = "ConsoleApplication", shape = egg ]; + "node2" [ label = "CoreLibrary", shape = octagon ]; + "node2" -> "node0" // CoreLibrary -> CompilerFlags + "node3" [ label = "GoofyLoggingLibrary\n(SeriousLoggingLibrary)\n(TheBestLoggingLibrary)", shape = pentagon ]; + "node2" -> "node3" [ style = dotted ] // CoreLibrary -> GoofyLoggingLibrary + "node1" -> "node2" [ style = dotted ] // ConsoleApplication -> CoreLibrary + "node4" [ label = "CryptoCurrencyMiningLibrary", shape = septagon ]; + "node1" -> "node4" [ style = dotted ] // ConsoleApplication -> CryptoCurrencyMiningLibrary + "node5" [ label = "GenerateManPage", shape = box ]; + "node1" -> "node5" // ConsoleApplication -> GenerateManPage + "node6" [ label = "GraphicApplication", shape = egg ]; + "node6" -> "node2" [ style = dotted ] // GraphicApplication -> CoreLibrary + "node7" [ label = "GraphicLibrary", shape = doubleoctagon ]; + "node8" [ label = "\"-lm\"", shape = septagon ]; + "node7" -> "node8" [ style = dotted ] // GraphicLibrary -> "-lm" + "node7" -> "node0" // GraphicLibrary -> CompilerFlags + "node7" -> "node2" [ style = dotted ] // GraphicLibrary -> CoreLibrary + "node9" [ label = "GraphicLibraryObjects", shape = hexagon ]; + "node7" -> "node9" [ style = dotted ] // GraphicLibrary -> GraphicLibraryObjects + "node6" -> "node7" [ style = dotted ] // GraphicApplication -> GraphicLibrary + "node10" [ label = "GraphicDriverOpenGL", shape = tripleoctagon ]; + "node10" -> "node0" [ style = dotted ] // GraphicDriverOpenGL -> CompilerFlags + "node10" -> "node2" [ style = dotted ] // GraphicDriverOpenGL -> CoreLibrary + "node11" [ label = "GraphicDriverVulkan", shape = tripleoctagon ]; + "node11" -> "node0" [ style = dotted ] // GraphicDriverVulkan -> CompilerFlags + "node11" -> "node2" [ style = dotted ] // GraphicDriverVulkan -> CoreLibrary +} diff --git a/Tests/RunCMake/Graphviz/expected_outputs/dependency_graph_default_options.dot b/Tests/RunCMake/Graphviz/expected_outputs/dependency_graph_default_options.dot new file mode 100644 index 0000000..1bbf25a --- /dev/null +++ b/Tests/RunCMake/Graphviz/expected_outputs/dependency_graph_default_options.dot @@ -0,0 +1,50 @@ +digraph "GraphvizTestProject" { +node [ + fontsize = "12" +]; +subgraph clusterLegend { + label = "Legend"; + color = black; + edge [ style = invis ]; + legendNode0 [ label = "Executable", shape = egg ]; + legendNode1 [ label = "Static Library", shape = octagon ]; + legendNode2 [ label = "Shared Library", shape = doubleoctagon ]; + legendNode3 [ label = "Module Library", shape = tripleoctagon ]; + legendNode4 [ label = "Interface Library", shape = pentagon ]; + legendNode5 [ label = "Object Library", shape = hexagon ]; + legendNode6 [ label = "Unknown Library", shape = septagon ]; + legendNode7 [ label = "Custom Target", shape = box ]; + legendNode0 -> legendNode1 [ style = solid ]; + legendNode0 -> legendNode2 [ style = solid ]; + legendNode0 -> legendNode3; + legendNode1 -> legendNode4 [ label = "Interface", style = dashed ]; + legendNode2 -> legendNode5 [ label = "Private", style = dotted ]; + legendNode3 -> legendNode6 [ style = solid ]; + legendNode0 -> legendNode7; +} + "node0" [ label = "CompilerFlags", shape = pentagon ]; + "node1" [ label = "ConsoleApplication", shape = egg ]; + "node2" [ label = "CoreLibrary", shape = octagon ]; + "node2" -> "node0" // CoreLibrary -> CompilerFlags + "node3" [ label = "GoofyLoggingLibrary\n(SeriousLoggingLibrary)\n(TheBestLoggingLibrary)", shape = pentagon ]; + "node2" -> "node3" [ style = dotted ] // CoreLibrary -> GoofyLoggingLibrary + "node1" -> "node2" [ style = dotted ] // ConsoleApplication -> CoreLibrary + "node4" [ label = "CryptoCurrencyMiningLibrary", shape = septagon ]; + "node1" -> "node4" [ style = dotted ] // ConsoleApplication -> CryptoCurrencyMiningLibrary + "node5" [ label = "GraphicApplication", shape = egg ]; + "node5" -> "node2" [ style = dotted ] // GraphicApplication -> CoreLibrary + "node6" [ label = "GraphicLibrary", shape = doubleoctagon ]; + "node7" [ label = "\"-lm\"", shape = septagon ]; + "node6" -> "node7" [ style = dotted ] // GraphicLibrary -> "-lm" + "node6" -> "node0" // GraphicLibrary -> CompilerFlags + "node6" -> "node2" [ style = dotted ] // GraphicLibrary -> CoreLibrary + "node8" [ label = "GraphicLibraryObjects", shape = hexagon ]; + "node6" -> "node8" [ style = dotted ] // GraphicLibrary -> GraphicLibraryObjects + "node5" -> "node6" [ style = dotted ] // GraphicApplication -> GraphicLibrary + "node9" [ label = "GraphicDriverOpenGL", shape = tripleoctagon ]; + "node9" -> "node0" [ style = dotted ] // GraphicDriverOpenGL -> CompilerFlags + "node9" -> "node2" [ style = dotted ] // GraphicDriverOpenGL -> CoreLibrary + "node10" [ label = "GraphicDriverVulkan", shape = tripleoctagon ]; + "node10" -> "node0" [ style = dotted ] // GraphicDriverVulkan -> CompilerFlags + "node10" -> "node2" [ style = dotted ] // GraphicDriverVulkan -> CoreLibrary +} diff --git a/Tests/RunCMake/Graphviz/expected_outputs/dependency_graph_no_dependers_files.dot b/Tests/RunCMake/Graphviz/expected_outputs/dependency_graph_no_dependers_files.dot new file mode 100644 index 0000000..1bbf25a --- /dev/null +++ b/Tests/RunCMake/Graphviz/expected_outputs/dependency_graph_no_dependers_files.dot @@ -0,0 +1,50 @@ +digraph "GraphvizTestProject" { +node [ + fontsize = "12" +]; +subgraph clusterLegend { + label = "Legend"; + color = black; + edge [ style = invis ]; + legendNode0 [ label = "Executable", shape = egg ]; + legendNode1 [ label = "Static Library", shape = octagon ]; + legendNode2 [ label = "Shared Library", shape = doubleoctagon ]; + legendNode3 [ label = "Module Library", shape = tripleoctagon ]; + legendNode4 [ label = "Interface Library", shape = pentagon ]; + legendNode5 [ label = "Object Library", shape = hexagon ]; + legendNode6 [ label = "Unknown Library", shape = septagon ]; + legendNode7 [ label = "Custom Target", shape = box ]; + legendNode0 -> legendNode1 [ style = solid ]; + legendNode0 -> legendNode2 [ style = solid ]; + legendNode0 -> legendNode3; + legendNode1 -> legendNode4 [ label = "Interface", style = dashed ]; + legendNode2 -> legendNode5 [ label = "Private", style = dotted ]; + legendNode3 -> legendNode6 [ style = solid ]; + legendNode0 -> legendNode7; +} + "node0" [ label = "CompilerFlags", shape = pentagon ]; + "node1" [ label = "ConsoleApplication", shape = egg ]; + "node2" [ label = "CoreLibrary", shape = octagon ]; + "node2" -> "node0" // CoreLibrary -> CompilerFlags + "node3" [ label = "GoofyLoggingLibrary\n(SeriousLoggingLibrary)\n(TheBestLoggingLibrary)", shape = pentagon ]; + "node2" -> "node3" [ style = dotted ] // CoreLibrary -> GoofyLoggingLibrary + "node1" -> "node2" [ style = dotted ] // ConsoleApplication -> CoreLibrary + "node4" [ label = "CryptoCurrencyMiningLibrary", shape = septagon ]; + "node1" -> "node4" [ style = dotted ] // ConsoleApplication -> CryptoCurrencyMiningLibrary + "node5" [ label = "GraphicApplication", shape = egg ]; + "node5" -> "node2" [ style = dotted ] // GraphicApplication -> CoreLibrary + "node6" [ label = "GraphicLibrary", shape = doubleoctagon ]; + "node7" [ label = "\"-lm\"", shape = septagon ]; + "node6" -> "node7" [ style = dotted ] // GraphicLibrary -> "-lm" + "node6" -> "node0" // GraphicLibrary -> CompilerFlags + "node6" -> "node2" [ style = dotted ] // GraphicLibrary -> CoreLibrary + "node8" [ label = "GraphicLibraryObjects", shape = hexagon ]; + "node6" -> "node8" [ style = dotted ] // GraphicLibrary -> GraphicLibraryObjects + "node5" -> "node6" [ style = dotted ] // GraphicApplication -> GraphicLibrary + "node9" [ label = "GraphicDriverOpenGL", shape = tripleoctagon ]; + "node9" -> "node0" [ style = dotted ] // GraphicDriverOpenGL -> CompilerFlags + "node9" -> "node2" [ style = dotted ] // GraphicDriverOpenGL -> CoreLibrary + "node10" [ label = "GraphicDriverVulkan", shape = tripleoctagon ]; + "node10" -> "node0" [ style = dotted ] // GraphicDriverVulkan -> CompilerFlags + "node10" -> "node2" [ style = dotted ] // GraphicDriverVulkan -> CoreLibrary +} diff --git a/Tests/RunCMake/Graphviz/expected_outputs/dependency_graph_no_executables.dot b/Tests/RunCMake/Graphviz/expected_outputs/dependency_graph_no_executables.dot new file mode 100644 index 0000000..558a470 --- /dev/null +++ b/Tests/RunCMake/Graphviz/expected_outputs/dependency_graph_no_executables.dot @@ -0,0 +1,44 @@ +digraph "GraphvizTestProject" { +node [ + fontsize = "12" +]; +subgraph clusterLegend { + label = "Legend"; + color = black; + edge [ style = invis ]; + legendNode0 [ label = "Executable", shape = egg ]; + legendNode1 [ label = "Static Library", shape = octagon ]; + legendNode2 [ label = "Shared Library", shape = doubleoctagon ]; + legendNode3 [ label = "Module Library", shape = tripleoctagon ]; + legendNode4 [ label = "Interface Library", shape = pentagon ]; + legendNode5 [ label = "Object Library", shape = hexagon ]; + legendNode6 [ label = "Unknown Library", shape = septagon ]; + legendNode7 [ label = "Custom Target", shape = box ]; + legendNode0 -> legendNode1 [ style = solid ]; + legendNode0 -> legendNode2 [ style = solid ]; + legendNode0 -> legendNode3; + legendNode1 -> legendNode4 [ label = "Interface", style = dashed ]; + legendNode2 -> legendNode5 [ label = "Private", style = dotted ]; + legendNode3 -> legendNode6 [ style = solid ]; + legendNode0 -> legendNode7; +} + "node0" [ label = "CompilerFlags", shape = pentagon ]; + "node1" [ label = "CoreLibrary", shape = octagon ]; + "node1" -> "node0" // CoreLibrary -> CompilerFlags + "node2" [ label = "GoofyLoggingLibrary\n(SeriousLoggingLibrary)\n(TheBestLoggingLibrary)", shape = pentagon ]; + "node1" -> "node2" [ style = dotted ] // CoreLibrary -> GoofyLoggingLibrary + "node3" [ label = "CryptoCurrencyMiningLibrary", shape = septagon ]; + "node4" [ label = "GraphicLibrary", shape = doubleoctagon ]; + "node5" [ label = "\"-lm\"", shape = septagon ]; + "node4" -> "node5" [ style = dotted ] // GraphicLibrary -> "-lm" + "node4" -> "node0" // GraphicLibrary -> CompilerFlags + "node4" -> "node1" [ style = dotted ] // GraphicLibrary -> CoreLibrary + "node6" [ label = "GraphicLibraryObjects", shape = hexagon ]; + "node4" -> "node6" [ style = dotted ] // GraphicLibrary -> GraphicLibraryObjects + "node7" [ label = "GraphicDriverOpenGL", shape = tripleoctagon ]; + "node7" -> "node0" [ style = dotted ] // GraphicDriverOpenGL -> CompilerFlags + "node7" -> "node1" [ style = dotted ] // GraphicDriverOpenGL -> CoreLibrary + "node8" [ label = "GraphicDriverVulkan", shape = tripleoctagon ]; + "node8" -> "node0" [ style = dotted ] // GraphicDriverVulkan -> CompilerFlags + "node8" -> "node1" [ style = dotted ] // GraphicDriverVulkan -> CoreLibrary +} diff --git a/Tests/RunCMake/Graphviz/expected_outputs/dependency_graph_no_external_libs.dot b/Tests/RunCMake/Graphviz/expected_outputs/dependency_graph_no_external_libs.dot new file mode 100644 index 0000000..660af37 --- /dev/null +++ b/Tests/RunCMake/Graphviz/expected_outputs/dependency_graph_no_external_libs.dot @@ -0,0 +1,46 @@ +digraph "GraphvizTestProject" { +node [ + fontsize = "12" +]; +subgraph clusterLegend { + label = "Legend"; + color = black; + edge [ style = invis ]; + legendNode0 [ label = "Executable", shape = egg ]; + legendNode1 [ label = "Static Library", shape = octagon ]; + legendNode2 [ label = "Shared Library", shape = doubleoctagon ]; + legendNode3 [ label = "Module Library", shape = tripleoctagon ]; + legendNode4 [ label = "Interface Library", shape = pentagon ]; + legendNode5 [ label = "Object Library", shape = hexagon ]; + legendNode6 [ label = "Unknown Library", shape = septagon ]; + legendNode7 [ label = "Custom Target", shape = box ]; + legendNode0 -> legendNode1 [ style = solid ]; + legendNode0 -> legendNode2 [ style = solid ]; + legendNode0 -> legendNode3; + legendNode1 -> legendNode4 [ label = "Interface", style = dashed ]; + legendNode2 -> legendNode5 [ label = "Private", style = dotted ]; + legendNode3 -> legendNode6 [ style = solid ]; + legendNode0 -> legendNode7; +} + "node0" [ label = "CompilerFlags", shape = pentagon ]; + "node1" [ label = "ConsoleApplication", shape = egg ]; + "node2" [ label = "CoreLibrary", shape = octagon ]; + "node2" -> "node0" // CoreLibrary -> CompilerFlags + "node3" [ label = "GoofyLoggingLibrary\n(SeriousLoggingLibrary)\n(TheBestLoggingLibrary)", shape = pentagon ]; + "node2" -> "node3" [ style = dotted ] // CoreLibrary -> GoofyLoggingLibrary + "node1" -> "node2" [ style = dotted ] // ConsoleApplication -> CoreLibrary + "node4" [ label = "GraphicApplication", shape = egg ]; + "node4" -> "node2" [ style = dotted ] // GraphicApplication -> CoreLibrary + "node5" [ label = "GraphicLibrary", shape = doubleoctagon ]; + "node5" -> "node0" // GraphicLibrary -> CompilerFlags + "node5" -> "node2" [ style = dotted ] // GraphicLibrary -> CoreLibrary + "node6" [ label = "GraphicLibraryObjects", shape = hexagon ]; + "node5" -> "node6" [ style = dotted ] // GraphicLibrary -> GraphicLibraryObjects + "node4" -> "node5" [ style = dotted ] // GraphicApplication -> GraphicLibrary + "node7" [ label = "GraphicDriverOpenGL", shape = tripleoctagon ]; + "node7" -> "node0" [ style = dotted ] // GraphicDriverOpenGL -> CompilerFlags + "node7" -> "node2" [ style = dotted ] // GraphicDriverOpenGL -> CoreLibrary + "node8" [ label = "GraphicDriverVulkan", shape = tripleoctagon ]; + "node8" -> "node0" [ style = dotted ] // GraphicDriverVulkan -> CompilerFlags + "node8" -> "node2" [ style = dotted ] // GraphicDriverVulkan -> CoreLibrary +} diff --git a/Tests/RunCMake/Graphviz/expected_outputs/dependency_graph_no_graphic_libs.dot b/Tests/RunCMake/Graphviz/expected_outputs/dependency_graph_no_graphic_libs.dot new file mode 100644 index 0000000..5af7fec --- /dev/null +++ b/Tests/RunCMake/Graphviz/expected_outputs/dependency_graph_no_graphic_libs.dot @@ -0,0 +1,35 @@ +digraph "GraphvizTestProject" { +node [ + fontsize = "12" +]; +subgraph clusterLegend { + label = "Legend"; + color = black; + edge [ style = invis ]; + legendNode0 [ label = "Executable", shape = egg ]; + legendNode1 [ label = "Static Library", shape = octagon ]; + legendNode2 [ label = "Shared Library", shape = doubleoctagon ]; + legendNode3 [ label = "Module Library", shape = tripleoctagon ]; + legendNode4 [ label = "Interface Library", shape = pentagon ]; + legendNode5 [ label = "Object Library", shape = hexagon ]; + legendNode6 [ label = "Unknown Library", shape = septagon ]; + legendNode7 [ label = "Custom Target", shape = box ]; + legendNode0 -> legendNode1 [ style = solid ]; + legendNode0 -> legendNode2 [ style = solid ]; + legendNode0 -> legendNode3; + legendNode1 -> legendNode4 [ label = "Interface", style = dashed ]; + legendNode2 -> legendNode5 [ label = "Private", style = dotted ]; + legendNode3 -> legendNode6 [ style = solid ]; + legendNode0 -> legendNode7; +} + "node0" [ label = "CompilerFlags", shape = pentagon ]; + "node1" [ label = "ConsoleApplication", shape = egg ]; + "node2" [ label = "CoreLibrary", shape = octagon ]; + "node2" -> "node0" // CoreLibrary -> CompilerFlags + "node3" [ label = "GoofyLoggingLibrary\n(SeriousLoggingLibrary)\n(TheBestLoggingLibrary)", shape = pentagon ]; + "node2" -> "node3" [ style = dotted ] // CoreLibrary -> GoofyLoggingLibrary + "node1" -> "node2" [ style = dotted ] // ConsoleApplication -> CoreLibrary + "node4" [ label = "CryptoCurrencyMiningLibrary", shape = septagon ]; + "node1" -> "node4" [ style = dotted ] // ConsoleApplication -> CryptoCurrencyMiningLibrary + "node5" [ label = "\"-lm\"", shape = septagon ]; +} diff --git a/Tests/RunCMake/Graphviz/expected_outputs/dependency_graph_no_interface_libs.dot b/Tests/RunCMake/Graphviz/expected_outputs/dependency_graph_no_interface_libs.dot new file mode 100644 index 0000000..94ec41c --- /dev/null +++ b/Tests/RunCMake/Graphviz/expected_outputs/dependency_graph_no_interface_libs.dot @@ -0,0 +1,43 @@ +digraph "GraphvizTestProject" { +node [ + fontsize = "12" +]; +subgraph clusterLegend { + label = "Legend"; + color = black; + edge [ style = invis ]; + legendNode0 [ label = "Executable", shape = egg ]; + legendNode1 [ label = "Static Library", shape = octagon ]; + legendNode2 [ label = "Shared Library", shape = doubleoctagon ]; + legendNode3 [ label = "Module Library", shape = tripleoctagon ]; + legendNode4 [ label = "Interface Library", shape = pentagon ]; + legendNode5 [ label = "Object Library", shape = hexagon ]; + legendNode6 [ label = "Unknown Library", shape = septagon ]; + legendNode7 [ label = "Custom Target", shape = box ]; + legendNode0 -> legendNode1 [ style = solid ]; + legendNode0 -> legendNode2 [ style = solid ]; + legendNode0 -> legendNode3; + legendNode1 -> legendNode4 [ label = "Interface", style = dashed ]; + legendNode2 -> legendNode5 [ label = "Private", style = dotted ]; + legendNode3 -> legendNode6 [ style = solid ]; + legendNode0 -> legendNode7; +} + "node0" [ label = "ConsoleApplication", shape = egg ]; + "node1" [ label = "CoreLibrary", shape = octagon ]; + "node0" -> "node1" [ style = dotted ] // ConsoleApplication -> CoreLibrary + "node2" [ label = "CryptoCurrencyMiningLibrary", shape = septagon ]; + "node0" -> "node2" [ style = dotted ] // ConsoleApplication -> CryptoCurrencyMiningLibrary + "node3" [ label = "GraphicApplication", shape = egg ]; + "node3" -> "node1" [ style = dotted ] // GraphicApplication -> CoreLibrary + "node4" [ label = "GraphicLibrary", shape = doubleoctagon ]; + "node5" [ label = "\"-lm\"", shape = septagon ]; + "node4" -> "node5" [ style = dotted ] // GraphicLibrary -> "-lm" + "node4" -> "node1" [ style = dotted ] // GraphicLibrary -> CoreLibrary + "node6" [ label = "GraphicLibraryObjects", shape = hexagon ]; + "node4" -> "node6" [ style = dotted ] // GraphicLibrary -> GraphicLibraryObjects + "node3" -> "node4" [ style = dotted ] // GraphicApplication -> GraphicLibrary + "node7" [ label = "GraphicDriverOpenGL", shape = tripleoctagon ]; + "node7" -> "node1" [ style = dotted ] // GraphicDriverOpenGL -> CoreLibrary + "node8" [ label = "GraphicDriverVulkan", shape = tripleoctagon ]; + "node8" -> "node1" [ style = dotted ] // GraphicDriverVulkan -> CoreLibrary +} diff --git a/Tests/RunCMake/Graphviz/expected_outputs/dependency_graph_no_module_libs.dot b/Tests/RunCMake/Graphviz/expected_outputs/dependency_graph_no_module_libs.dot new file mode 100644 index 0000000..65b7a71 --- /dev/null +++ b/Tests/RunCMake/Graphviz/expected_outputs/dependency_graph_no_module_libs.dot @@ -0,0 +1,44 @@ +digraph "GraphvizTestProject" { +node [ + fontsize = "12" +]; +subgraph clusterLegend { + label = "Legend"; + color = black; + edge [ style = invis ]; + legendNode0 [ label = "Executable", shape = egg ]; + legendNode1 [ label = "Static Library", shape = octagon ]; + legendNode2 [ label = "Shared Library", shape = doubleoctagon ]; + legendNode3 [ label = "Module Library", shape = tripleoctagon ]; + legendNode4 [ label = "Interface Library", shape = pentagon ]; + legendNode5 [ label = "Object Library", shape = hexagon ]; + legendNode6 [ label = "Unknown Library", shape = septagon ]; + legendNode7 [ label = "Custom Target", shape = box ]; + legendNode0 -> legendNode1 [ style = solid ]; + legendNode0 -> legendNode2 [ style = solid ]; + legendNode0 -> legendNode3; + legendNode1 -> legendNode4 [ label = "Interface", style = dashed ]; + legendNode2 -> legendNode5 [ label = "Private", style = dotted ]; + legendNode3 -> legendNode6 [ style = solid ]; + legendNode0 -> legendNode7; +} + "node0" [ label = "CompilerFlags", shape = pentagon ]; + "node1" [ label = "ConsoleApplication", shape = egg ]; + "node2" [ label = "CoreLibrary", shape = octagon ]; + "node2" -> "node0" // CoreLibrary -> CompilerFlags + "node3" [ label = "GoofyLoggingLibrary\n(SeriousLoggingLibrary)\n(TheBestLoggingLibrary)", shape = pentagon ]; + "node2" -> "node3" [ style = dotted ] // CoreLibrary -> GoofyLoggingLibrary + "node1" -> "node2" [ style = dotted ] // ConsoleApplication -> CoreLibrary + "node4" [ label = "CryptoCurrencyMiningLibrary", shape = septagon ]; + "node1" -> "node4" [ style = dotted ] // ConsoleApplication -> CryptoCurrencyMiningLibrary + "node5" [ label = "GraphicApplication", shape = egg ]; + "node5" -> "node2" [ style = dotted ] // GraphicApplication -> CoreLibrary + "node6" [ label = "GraphicLibrary", shape = doubleoctagon ]; + "node7" [ label = "\"-lm\"", shape = septagon ]; + "node6" -> "node7" [ style = dotted ] // GraphicLibrary -> "-lm" + "node6" -> "node0" // GraphicLibrary -> CompilerFlags + "node6" -> "node2" [ style = dotted ] // GraphicLibrary -> CoreLibrary + "node8" [ label = "GraphicLibraryObjects", shape = hexagon ]; + "node6" -> "node8" [ style = dotted ] // GraphicLibrary -> GraphicLibraryObjects + "node5" -> "node6" [ style = dotted ] // GraphicApplication -> GraphicLibrary +} diff --git a/Tests/RunCMake/Graphviz/expected_outputs/dependency_graph_no_object_libs.dot b/Tests/RunCMake/Graphviz/expected_outputs/dependency_graph_no_object_libs.dot new file mode 100644 index 0000000..8116bc9 --- /dev/null +++ b/Tests/RunCMake/Graphviz/expected_outputs/dependency_graph_no_object_libs.dot @@ -0,0 +1,48 @@ +digraph "GraphvizTestProject" { +node [ + fontsize = "12" +]; +subgraph clusterLegend { + label = "Legend"; + color = black; + edge [ style = invis ]; + legendNode0 [ label = "Executable", shape = egg ]; + legendNode1 [ label = "Static Library", shape = octagon ]; + legendNode2 [ label = "Shared Library", shape = doubleoctagon ]; + legendNode3 [ label = "Module Library", shape = tripleoctagon ]; + legendNode4 [ label = "Interface Library", shape = pentagon ]; + legendNode5 [ label = "Object Library", shape = hexagon ]; + legendNode6 [ label = "Unknown Library", shape = septagon ]; + legendNode7 [ label = "Custom Target", shape = box ]; + legendNode0 -> legendNode1 [ style = solid ]; + legendNode0 -> legendNode2 [ style = solid ]; + legendNode0 -> legendNode3; + legendNode1 -> legendNode4 [ label = "Interface", style = dashed ]; + legendNode2 -> legendNode5 [ label = "Private", style = dotted ]; + legendNode3 -> legendNode6 [ style = solid ]; + legendNode0 -> legendNode7; +} + "node0" [ label = "CompilerFlags", shape = pentagon ]; + "node1" [ label = "ConsoleApplication", shape = egg ]; + "node2" [ label = "CoreLibrary", shape = octagon ]; + "node2" -> "node0" // CoreLibrary -> CompilerFlags + "node3" [ label = "GoofyLoggingLibrary\n(SeriousLoggingLibrary)\n(TheBestLoggingLibrary)", shape = pentagon ]; + "node2" -> "node3" [ style = dotted ] // CoreLibrary -> GoofyLoggingLibrary + "node1" -> "node2" [ style = dotted ] // ConsoleApplication -> CoreLibrary + "node4" [ label = "CryptoCurrencyMiningLibrary", shape = septagon ]; + "node1" -> "node4" [ style = dotted ] // ConsoleApplication -> CryptoCurrencyMiningLibrary + "node5" [ label = "GraphicApplication", shape = egg ]; + "node5" -> "node2" [ style = dotted ] // GraphicApplication -> CoreLibrary + "node6" [ label = "GraphicLibrary", shape = doubleoctagon ]; + "node7" [ label = "\"-lm\"", shape = septagon ]; + "node6" -> "node7" [ style = dotted ] // GraphicLibrary -> "-lm" + "node6" -> "node0" // GraphicLibrary -> CompilerFlags + "node6" -> "node2" [ style = dotted ] // GraphicLibrary -> CoreLibrary + "node5" -> "node6" [ style = dotted ] // GraphicApplication -> GraphicLibrary + "node8" [ label = "GraphicDriverOpenGL", shape = tripleoctagon ]; + "node8" -> "node0" [ style = dotted ] // GraphicDriverOpenGL -> CompilerFlags + "node8" -> "node2" [ style = dotted ] // GraphicDriverOpenGL -> CoreLibrary + "node9" [ label = "GraphicDriverVulkan", shape = tripleoctagon ]; + "node9" -> "node0" [ style = dotted ] // GraphicDriverVulkan -> CompilerFlags + "node9" -> "node2" [ style = dotted ] // GraphicDriverVulkan -> CoreLibrary +} diff --git a/Tests/RunCMake/Graphviz/expected_outputs/dependency_graph_no_per_target_files.dot b/Tests/RunCMake/Graphviz/expected_outputs/dependency_graph_no_per_target_files.dot new file mode 100644 index 0000000..1bbf25a --- /dev/null +++ b/Tests/RunCMake/Graphviz/expected_outputs/dependency_graph_no_per_target_files.dot @@ -0,0 +1,50 @@ +digraph "GraphvizTestProject" { +node [ + fontsize = "12" +]; +subgraph clusterLegend { + label = "Legend"; + color = black; + edge [ style = invis ]; + legendNode0 [ label = "Executable", shape = egg ]; + legendNode1 [ label = "Static Library", shape = octagon ]; + legendNode2 [ label = "Shared Library", shape = doubleoctagon ]; + legendNode3 [ label = "Module Library", shape = tripleoctagon ]; + legendNode4 [ label = "Interface Library", shape = pentagon ]; + legendNode5 [ label = "Object Library", shape = hexagon ]; + legendNode6 [ label = "Unknown Library", shape = septagon ]; + legendNode7 [ label = "Custom Target", shape = box ]; + legendNode0 -> legendNode1 [ style = solid ]; + legendNode0 -> legendNode2 [ style = solid ]; + legendNode0 -> legendNode3; + legendNode1 -> legendNode4 [ label = "Interface", style = dashed ]; + legendNode2 -> legendNode5 [ label = "Private", style = dotted ]; + legendNode3 -> legendNode6 [ style = solid ]; + legendNode0 -> legendNode7; +} + "node0" [ label = "CompilerFlags", shape = pentagon ]; + "node1" [ label = "ConsoleApplication", shape = egg ]; + "node2" [ label = "CoreLibrary", shape = octagon ]; + "node2" -> "node0" // CoreLibrary -> CompilerFlags + "node3" [ label = "GoofyLoggingLibrary\n(SeriousLoggingLibrary)\n(TheBestLoggingLibrary)", shape = pentagon ]; + "node2" -> "node3" [ style = dotted ] // CoreLibrary -> GoofyLoggingLibrary + "node1" -> "node2" [ style = dotted ] // ConsoleApplication -> CoreLibrary + "node4" [ label = "CryptoCurrencyMiningLibrary", shape = septagon ]; + "node1" -> "node4" [ style = dotted ] // ConsoleApplication -> CryptoCurrencyMiningLibrary + "node5" [ label = "GraphicApplication", shape = egg ]; + "node5" -> "node2" [ style = dotted ] // GraphicApplication -> CoreLibrary + "node6" [ label = "GraphicLibrary", shape = doubleoctagon ]; + "node7" [ label = "\"-lm\"", shape = septagon ]; + "node6" -> "node7" [ style = dotted ] // GraphicLibrary -> "-lm" + "node6" -> "node0" // GraphicLibrary -> CompilerFlags + "node6" -> "node2" [ style = dotted ] // GraphicLibrary -> CoreLibrary + "node8" [ label = "GraphicLibraryObjects", shape = hexagon ]; + "node6" -> "node8" [ style = dotted ] // GraphicLibrary -> GraphicLibraryObjects + "node5" -> "node6" [ style = dotted ] // GraphicApplication -> GraphicLibrary + "node9" [ label = "GraphicDriverOpenGL", shape = tripleoctagon ]; + "node9" -> "node0" [ style = dotted ] // GraphicDriverOpenGL -> CompilerFlags + "node9" -> "node2" [ style = dotted ] // GraphicDriverOpenGL -> CoreLibrary + "node10" [ label = "GraphicDriverVulkan", shape = tripleoctagon ]; + "node10" -> "node0" [ style = dotted ] // GraphicDriverVulkan -> CompilerFlags + "node10" -> "node2" [ style = dotted ] // GraphicDriverVulkan -> CoreLibrary +} diff --git a/Tests/RunCMake/Graphviz/expected_outputs/dependency_graph_no_shared_libs.dot b/Tests/RunCMake/Graphviz/expected_outputs/dependency_graph_no_shared_libs.dot new file mode 100644 index 0000000..439d1f7 --- /dev/null +++ b/Tests/RunCMake/Graphviz/expected_outputs/dependency_graph_no_shared_libs.dot @@ -0,0 +1,44 @@ +digraph "GraphvizTestProject" { +node [ + fontsize = "12" +]; +subgraph clusterLegend { + label = "Legend"; + color = black; + edge [ style = invis ]; + legendNode0 [ label = "Executable", shape = egg ]; + legendNode1 [ label = "Static Library", shape = octagon ]; + legendNode2 [ label = "Shared Library", shape = doubleoctagon ]; + legendNode3 [ label = "Module Library", shape = tripleoctagon ]; + legendNode4 [ label = "Interface Library", shape = pentagon ]; + legendNode5 [ label = "Object Library", shape = hexagon ]; + legendNode6 [ label = "Unknown Library", shape = septagon ]; + legendNode7 [ label = "Custom Target", shape = box ]; + legendNode0 -> legendNode1 [ style = solid ]; + legendNode0 -> legendNode2 [ style = solid ]; + legendNode0 -> legendNode3; + legendNode1 -> legendNode4 [ label = "Interface", style = dashed ]; + legendNode2 -> legendNode5 [ label = "Private", style = dotted ]; + legendNode3 -> legendNode6 [ style = solid ]; + legendNode0 -> legendNode7; +} + "node0" [ label = "CompilerFlags", shape = pentagon ]; + "node1" [ label = "ConsoleApplication", shape = egg ]; + "node2" [ label = "CoreLibrary", shape = octagon ]; + "node2" -> "node0" // CoreLibrary -> CompilerFlags + "node3" [ label = "GoofyLoggingLibrary\n(SeriousLoggingLibrary)\n(TheBestLoggingLibrary)", shape = pentagon ]; + "node2" -> "node3" [ style = dotted ] // CoreLibrary -> GoofyLoggingLibrary + "node1" -> "node2" [ style = dotted ] // ConsoleApplication -> CoreLibrary + "node4" [ label = "CryptoCurrencyMiningLibrary", shape = septagon ]; + "node1" -> "node4" [ style = dotted ] // ConsoleApplication -> CryptoCurrencyMiningLibrary + "node5" [ label = "GraphicApplication", shape = egg ]; + "node5" -> "node2" [ style = dotted ] // GraphicApplication -> CoreLibrary + "node6" [ label = "\"-lm\"", shape = septagon ]; + "node7" [ label = "GraphicLibraryObjects", shape = hexagon ]; + "node8" [ label = "GraphicDriverOpenGL", shape = tripleoctagon ]; + "node8" -> "node0" [ style = dotted ] // GraphicDriverOpenGL -> CompilerFlags + "node8" -> "node2" [ style = dotted ] // GraphicDriverOpenGL -> CoreLibrary + "node9" [ label = "GraphicDriverVulkan", shape = tripleoctagon ]; + "node9" -> "node0" [ style = dotted ] // GraphicDriverVulkan -> CompilerFlags + "node9" -> "node2" [ style = dotted ] // GraphicDriverVulkan -> CoreLibrary +} diff --git a/Tests/RunCMake/Graphviz/expected_outputs/dependency_graph_no_static_libs.dot b/Tests/RunCMake/Graphviz/expected_outputs/dependency_graph_no_static_libs.dot new file mode 100644 index 0000000..81199a2 --- /dev/null +++ b/Tests/RunCMake/Graphviz/expected_outputs/dependency_graph_no_static_libs.dot @@ -0,0 +1,42 @@ +digraph "GraphvizTestProject" { +node [ + fontsize = "12" +]; +subgraph clusterLegend { + label = "Legend"; + color = black; + edge [ style = invis ]; + legendNode0 [ label = "Executable", shape = egg ]; + legendNode1 [ label = "Static Library", shape = octagon ]; + legendNode2 [ label = "Shared Library", shape = doubleoctagon ]; + legendNode3 [ label = "Module Library", shape = tripleoctagon ]; + legendNode4 [ label = "Interface Library", shape = pentagon ]; + legendNode5 [ label = "Object Library", shape = hexagon ]; + legendNode6 [ label = "Unknown Library", shape = septagon ]; + legendNode7 [ label = "Custom Target", shape = box ]; + legendNode0 -> legendNode1 [ style = solid ]; + legendNode0 -> legendNode2 [ style = solid ]; + legendNode0 -> legendNode3; + legendNode1 -> legendNode4 [ label = "Interface", style = dashed ]; + legendNode2 -> legendNode5 [ label = "Private", style = dotted ]; + legendNode3 -> legendNode6 [ style = solid ]; + legendNode0 -> legendNode7; +} + "node0" [ label = "CompilerFlags", shape = pentagon ]; + "node1" [ label = "ConsoleApplication", shape = egg ]; + "node2" [ label = "GoofyLoggingLibrary\n(SeriousLoggingLibrary)\n(TheBestLoggingLibrary)", shape = pentagon ]; + "node3" [ label = "CryptoCurrencyMiningLibrary", shape = septagon ]; + "node1" -> "node3" [ style = dotted ] // ConsoleApplication -> CryptoCurrencyMiningLibrary + "node4" [ label = "GraphicApplication", shape = egg ]; + "node5" [ label = "GraphicLibrary", shape = doubleoctagon ]; + "node6" [ label = "\"-lm\"", shape = septagon ]; + "node5" -> "node6" [ style = dotted ] // GraphicLibrary -> "-lm" + "node5" -> "node0" // GraphicLibrary -> CompilerFlags + "node7" [ label = "GraphicLibraryObjects", shape = hexagon ]; + "node5" -> "node7" [ style = dotted ] // GraphicLibrary -> GraphicLibraryObjects + "node4" -> "node5" [ style = dotted ] // GraphicApplication -> GraphicLibrary + "node8" [ label = "GraphicDriverOpenGL", shape = tripleoctagon ]; + "node8" -> "node0" [ style = dotted ] // GraphicDriverOpenGL -> CompilerFlags + "node9" [ label = "GraphicDriverVulkan", shape = tripleoctagon ]; + "node9" -> "node0" [ style = dotted ] // GraphicDriverVulkan -> CompilerFlags +} diff --git a/Tests/RunCMake/Graphviz/expected_outputs/dependency_graph_no_unknown_libs.dot b/Tests/RunCMake/Graphviz/expected_outputs/dependency_graph_no_unknown_libs.dot new file mode 100644 index 0000000..1be6550 --- /dev/null +++ b/Tests/RunCMake/Graphviz/expected_outputs/dependency_graph_no_unknown_libs.dot @@ -0,0 +1,48 @@ +digraph "GraphvizTestProject" { +node [ + fontsize = "12" +]; +subgraph clusterLegend { + label = "Legend"; + color = black; + edge [ style = invis ]; + legendNode0 [ label = "Executable", shape = egg ]; + legendNode1 [ label = "Static Library", shape = octagon ]; + legendNode2 [ label = "Shared Library", shape = doubleoctagon ]; + legendNode3 [ label = "Module Library", shape = tripleoctagon ]; + legendNode4 [ label = "Interface Library", shape = pentagon ]; + legendNode5 [ label = "Object Library", shape = hexagon ]; + legendNode6 [ label = "Unknown Library", shape = septagon ]; + legendNode7 [ label = "Custom Target", shape = box ]; + legendNode0 -> legendNode1 [ style = solid ]; + legendNode0 -> legendNode2 [ style = solid ]; + legendNode0 -> legendNode3; + legendNode1 -> legendNode4 [ label = "Interface", style = dashed ]; + legendNode2 -> legendNode5 [ label = "Private", style = dotted ]; + legendNode3 -> legendNode6 [ style = solid ]; + legendNode0 -> legendNode7; +} + "node0" [ label = "CompilerFlags", shape = pentagon ]; + "node1" [ label = "ConsoleApplication", shape = egg ]; + "node2" [ label = "CoreLibrary", shape = octagon ]; + "node2" -> "node0" // CoreLibrary -> CompilerFlags + "node3" [ label = "GoofyLoggingLibrary\n(SeriousLoggingLibrary)\n(TheBestLoggingLibrary)", shape = pentagon ]; + "node2" -> "node3" [ style = dotted ] // CoreLibrary -> GoofyLoggingLibrary + "node1" -> "node2" [ style = dotted ] // ConsoleApplication -> CoreLibrary + "node4" [ label = "GraphicApplication", shape = egg ]; + "node4" -> "node2" [ style = dotted ] // GraphicApplication -> CoreLibrary + "node5" [ label = "GraphicLibrary", shape = doubleoctagon ]; + "node6" [ label = "\"-lm\"", shape = septagon ]; + "node5" -> "node6" [ style = dotted ] // GraphicLibrary -> "-lm" + "node5" -> "node0" // GraphicLibrary -> CompilerFlags + "node5" -> "node2" [ style = dotted ] // GraphicLibrary -> CoreLibrary + "node7" [ label = "GraphicLibraryObjects", shape = hexagon ]; + "node5" -> "node7" [ style = dotted ] // GraphicLibrary -> GraphicLibraryObjects + "node4" -> "node5" [ style = dotted ] // GraphicApplication -> GraphicLibrary + "node8" [ label = "GraphicDriverOpenGL", shape = tripleoctagon ]; + "node8" -> "node0" [ style = dotted ] // GraphicDriverOpenGL -> CompilerFlags + "node8" -> "node2" [ style = dotted ] // GraphicDriverOpenGL -> CoreLibrary + "node9" [ label = "GraphicDriverVulkan", shape = tripleoctagon ]; + "node9" -> "node0" [ style = dotted ] // GraphicDriverVulkan -> CompilerFlags + "node9" -> "node2" [ style = dotted ] // GraphicDriverVulkan -> CoreLibrary +} diff --git a/Tests/RunCMake/Graphviz/expected_outputs/dependency_graph_set_graph_header.dot b/Tests/RunCMake/Graphviz/expected_outputs/dependency_graph_set_graph_header.dot new file mode 100644 index 0000000..1cfbe0f --- /dev/null +++ b/Tests/RunCMake/Graphviz/expected_outputs/dependency_graph_set_graph_header.dot @@ -0,0 +1,50 @@ +digraph "GraphvizTestProject" { +node [ + fontsize = "16" +]; +subgraph clusterLegend { + label = "Legend"; + color = black; + edge [ style = invis ]; + legendNode0 [ label = "Executable", shape = egg ]; + legendNode1 [ label = "Static Library", shape = octagon ]; + legendNode2 [ label = "Shared Library", shape = doubleoctagon ]; + legendNode3 [ label = "Module Library", shape = tripleoctagon ]; + legendNode4 [ label = "Interface Library", shape = pentagon ]; + legendNode5 [ label = "Object Library", shape = hexagon ]; + legendNode6 [ label = "Unknown Library", shape = septagon ]; + legendNode7 [ label = "Custom Target", shape = box ]; + legendNode0 -> legendNode1 [ style = solid ]; + legendNode0 -> legendNode2 [ style = solid ]; + legendNode0 -> legendNode3; + legendNode1 -> legendNode4 [ label = "Interface", style = dashed ]; + legendNode2 -> legendNode5 [ label = "Private", style = dotted ]; + legendNode3 -> legendNode6 [ style = solid ]; + legendNode0 -> legendNode7; +} + "node0" [ label = "CompilerFlags", shape = pentagon ]; + "node1" [ label = "ConsoleApplication", shape = egg ]; + "node2" [ label = "CoreLibrary", shape = octagon ]; + "node2" -> "node0" // CoreLibrary -> CompilerFlags + "node3" [ label = "GoofyLoggingLibrary\n(SeriousLoggingLibrary)\n(TheBestLoggingLibrary)", shape = pentagon ]; + "node2" -> "node3" [ style = dotted ] // CoreLibrary -> GoofyLoggingLibrary + "node1" -> "node2" [ style = dotted ] // ConsoleApplication -> CoreLibrary + "node4" [ label = "CryptoCurrencyMiningLibrary", shape = septagon ]; + "node1" -> "node4" [ style = dotted ] // ConsoleApplication -> CryptoCurrencyMiningLibrary + "node5" [ label = "GraphicApplication", shape = egg ]; + "node5" -> "node2" [ style = dotted ] // GraphicApplication -> CoreLibrary + "node6" [ label = "GraphicLibrary", shape = doubleoctagon ]; + "node7" [ label = "\"-lm\"", shape = septagon ]; + "node6" -> "node7" [ style = dotted ] // GraphicLibrary -> "-lm" + "node6" -> "node0" // GraphicLibrary -> CompilerFlags + "node6" -> "node2" [ style = dotted ] // GraphicLibrary -> CoreLibrary + "node8" [ label = "GraphicLibraryObjects", shape = hexagon ]; + "node6" -> "node8" [ style = dotted ] // GraphicLibrary -> GraphicLibraryObjects + "node5" -> "node6" [ style = dotted ] // GraphicApplication -> GraphicLibrary + "node9" [ label = "GraphicDriverOpenGL", shape = tripleoctagon ]; + "node9" -> "node0" [ style = dotted ] // GraphicDriverOpenGL -> CompilerFlags + "node9" -> "node2" [ style = dotted ] // GraphicDriverOpenGL -> CoreLibrary + "node10" [ label = "GraphicDriverVulkan", shape = tripleoctagon ]; + "node10" -> "node0" [ style = dotted ] // GraphicDriverVulkan -> CompilerFlags + "node10" -> "node2" [ style = dotted ] // GraphicDriverVulkan -> CoreLibrary +} diff --git a/Tests/RunCMake/Graphviz/expected_outputs/dependency_graph_set_graph_name.dot b/Tests/RunCMake/Graphviz/expected_outputs/dependency_graph_set_graph_name.dot new file mode 100644 index 0000000..9653c33 --- /dev/null +++ b/Tests/RunCMake/Graphviz/expected_outputs/dependency_graph_set_graph_name.dot @@ -0,0 +1,50 @@ +digraph "CMake Project Dependencies" { +node [ + fontsize = "12" +]; +subgraph clusterLegend { + label = "Legend"; + color = black; + edge [ style = invis ]; + legendNode0 [ label = "Executable", shape = egg ]; + legendNode1 [ label = "Static Library", shape = octagon ]; + legendNode2 [ label = "Shared Library", shape = doubleoctagon ]; + legendNode3 [ label = "Module Library", shape = tripleoctagon ]; + legendNode4 [ label = "Interface Library", shape = pentagon ]; + legendNode5 [ label = "Object Library", shape = hexagon ]; + legendNode6 [ label = "Unknown Library", shape = septagon ]; + legendNode7 [ label = "Custom Target", shape = box ]; + legendNode0 -> legendNode1 [ style = solid ]; + legendNode0 -> legendNode2 [ style = solid ]; + legendNode0 -> legendNode3; + legendNode1 -> legendNode4 [ label = "Interface", style = dashed ]; + legendNode2 -> legendNode5 [ label = "Private", style = dotted ]; + legendNode3 -> legendNode6 [ style = solid ]; + legendNode0 -> legendNode7; +} + "node0" [ label = "CompilerFlags", shape = pentagon ]; + "node1" [ label = "ConsoleApplication", shape = egg ]; + "node2" [ label = "CoreLibrary", shape = octagon ]; + "node2" -> "node0" // CoreLibrary -> CompilerFlags + "node3" [ label = "GoofyLoggingLibrary\n(SeriousLoggingLibrary)\n(TheBestLoggingLibrary)", shape = pentagon ]; + "node2" -> "node3" [ style = dotted ] // CoreLibrary -> GoofyLoggingLibrary + "node1" -> "node2" [ style = dotted ] // ConsoleApplication -> CoreLibrary + "node4" [ label = "CryptoCurrencyMiningLibrary", shape = septagon ]; + "node1" -> "node4" [ style = dotted ] // ConsoleApplication -> CryptoCurrencyMiningLibrary + "node5" [ label = "GraphicApplication", shape = egg ]; + "node5" -> "node2" [ style = dotted ] // GraphicApplication -> CoreLibrary + "node6" [ label = "GraphicLibrary", shape = doubleoctagon ]; + "node7" [ label = "\"-lm\"", shape = septagon ]; + "node6" -> "node7" [ style = dotted ] // GraphicLibrary -> "-lm" + "node6" -> "node0" // GraphicLibrary -> CompilerFlags + "node6" -> "node2" [ style = dotted ] // GraphicLibrary -> CoreLibrary + "node8" [ label = "GraphicLibraryObjects", shape = hexagon ]; + "node6" -> "node8" [ style = dotted ] // GraphicLibrary -> GraphicLibraryObjects + "node5" -> "node6" [ style = dotted ] // GraphicApplication -> GraphicLibrary + "node9" [ label = "GraphicDriverOpenGL", shape = tripleoctagon ]; + "node9" -> "node0" [ style = dotted ] // GraphicDriverOpenGL -> CompilerFlags + "node9" -> "node2" [ style = dotted ] // GraphicDriverOpenGL -> CoreLibrary + "node10" [ label = "GraphicDriverVulkan", shape = tripleoctagon ]; + "node10" -> "node0" [ style = dotted ] // GraphicDriverVulkan -> CompilerFlags + "node10" -> "node2" [ style = dotted ] // GraphicDriverVulkan -> CoreLibrary +} diff --git a/Tests/RunCMake/Graphviz/expected_outputs/dependency_graph_set_node_prefix.dot b/Tests/RunCMake/Graphviz/expected_outputs/dependency_graph_set_node_prefix.dot new file mode 100644 index 0000000..82d96d0 --- /dev/null +++ b/Tests/RunCMake/Graphviz/expected_outputs/dependency_graph_set_node_prefix.dot @@ -0,0 +1,50 @@ +digraph "GraphvizTestProject" { +node [ + fontsize = "12" +]; +subgraph clusterLegend { + label = "Legend"; + color = black; + edge [ style = invis ]; + legendNode0 [ label = "Executable", shape = egg ]; + legendNode1 [ label = "Static Library", shape = octagon ]; + legendNode2 [ label = "Shared Library", shape = doubleoctagon ]; + legendNode3 [ label = "Module Library", shape = tripleoctagon ]; + legendNode4 [ label = "Interface Library", shape = pentagon ]; + legendNode5 [ label = "Object Library", shape = hexagon ]; + legendNode6 [ label = "Unknown Library", shape = septagon ]; + legendNode7 [ label = "Custom Target", shape = box ]; + legendNode0 -> legendNode1 [ style = solid ]; + legendNode0 -> legendNode2 [ style = solid ]; + legendNode0 -> legendNode3; + legendNode1 -> legendNode4 [ label = "Interface", style = dashed ]; + legendNode2 -> legendNode5 [ label = "Private", style = dotted ]; + legendNode3 -> legendNode6 [ style = solid ]; + legendNode0 -> legendNode7; +} + "point0" [ label = "CompilerFlags", shape = pentagon ]; + "point1" [ label = "ConsoleApplication", shape = egg ]; + "point2" [ label = "CoreLibrary", shape = octagon ]; + "point2" -> "point0" // CoreLibrary -> CompilerFlags + "point3" [ label = "GoofyLoggingLibrary\n(SeriousLoggingLibrary)\n(TheBestLoggingLibrary)", shape = pentagon ]; + "point2" -> "point3" [ style = dotted ] // CoreLibrary -> GoofyLoggingLibrary + "point1" -> "point2" [ style = dotted ] // ConsoleApplication -> CoreLibrary + "point4" [ label = "CryptoCurrencyMiningLibrary", shape = septagon ]; + "point1" -> "point4" [ style = dotted ] // ConsoleApplication -> CryptoCurrencyMiningLibrary + "point5" [ label = "GraphicApplication", shape = egg ]; + "point5" -> "point2" [ style = dotted ] // GraphicApplication -> CoreLibrary + "point6" [ label = "GraphicLibrary", shape = doubleoctagon ]; + "point7" [ label = "\"-lm\"", shape = septagon ]; + "point6" -> "point7" [ style = dotted ] // GraphicLibrary -> "-lm" + "point6" -> "point0" // GraphicLibrary -> CompilerFlags + "point6" -> "point2" [ style = dotted ] // GraphicLibrary -> CoreLibrary + "point8" [ label = "GraphicLibraryObjects", shape = hexagon ]; + "point6" -> "point8" [ style = dotted ] // GraphicLibrary -> GraphicLibraryObjects + "point5" -> "point6" [ style = dotted ] // GraphicApplication -> GraphicLibrary + "point9" [ label = "GraphicDriverOpenGL", shape = tripleoctagon ]; + "point9" -> "point0" [ style = dotted ] // GraphicDriverOpenGL -> CompilerFlags + "point9" -> "point2" [ style = dotted ] // GraphicDriverOpenGL -> CoreLibrary + "point10" [ label = "GraphicDriverVulkan", shape = tripleoctagon ]; + "point10" -> "point0" [ style = dotted ] // GraphicDriverVulkan -> CompilerFlags + "point10" -> "point2" [ style = dotted ] // GraphicDriverVulkan -> CoreLibrary +} diff --git a/Tests/RunCMake/Graphviz/no_dependers_files-check.cmake b/Tests/RunCMake/Graphviz/no_dependers_files-check.cmake new file mode 100644 index 0000000..f4a43b6 --- /dev/null +++ b/Tests/RunCMake/Graphviz/no_dependers_files-check.cmake @@ -0,0 +1,4 @@ +file(GLOB dependers_files ${RunCMake_TEST_BINARY_DIR}/*.dependers) +if(${dependers_files}) + set(RunCMake_TEST_FAILED "Found *.dependers files despite GRAPHVIZ_GENERATE_DEPENDERS set to FALSE.") +endif() diff --git a/Tests/RunCMake/Graphviz/no_executables-check.cmake b/Tests/RunCMake/Graphviz/no_executables-check.cmake new file mode 100644 index 0000000..be29a4f --- /dev/null +++ b/Tests/RunCMake/Graphviz/no_executables-check.cmake @@ -0,0 +1,5 @@ +include(RunCMake) + +ensure_files_match( + ${RunCMake_TEST_SOURCE_DIR}/expected_outputs/dependency_graph_no_executables.dot + ${RunCMake_TEST_BINARY_DIR}/generated_dependency_graph.dot) diff --git a/Tests/RunCMake/Graphviz/no_external_libs-check.cmake b/Tests/RunCMake/Graphviz/no_external_libs-check.cmake new file mode 100644 index 0000000..518ef7b --- /dev/null +++ b/Tests/RunCMake/Graphviz/no_external_libs-check.cmake @@ -0,0 +1,5 @@ +include(RunCMake) + +ensure_files_match( + ${RunCMake_TEST_SOURCE_DIR}/expected_outputs/dependency_graph_no_external_libs.dot + ${RunCMake_TEST_BINARY_DIR}/generated_dependency_graph.dot) diff --git a/Tests/RunCMake/Graphviz/no_graphic_libs-check.cmake b/Tests/RunCMake/Graphviz/no_graphic_libs-check.cmake new file mode 100644 index 0000000..0f5aa47 --- /dev/null +++ b/Tests/RunCMake/Graphviz/no_graphic_libs-check.cmake @@ -0,0 +1,5 @@ +include(RunCMake) + +ensure_files_match( + ${RunCMake_TEST_SOURCE_DIR}/expected_outputs/dependency_graph_no_graphic_libs.dot + ${RunCMake_TEST_BINARY_DIR}/generated_dependency_graph.dot) diff --git a/Tests/RunCMake/Graphviz/no_interface_libs-check.cmake b/Tests/RunCMake/Graphviz/no_interface_libs-check.cmake new file mode 100644 index 0000000..018fef0 --- /dev/null +++ b/Tests/RunCMake/Graphviz/no_interface_libs-check.cmake @@ -0,0 +1,5 @@ +include(RunCMake) + +ensure_files_match( + ${RunCMake_TEST_SOURCE_DIR}/expected_outputs/dependency_graph_no_interface_libs.dot + ${RunCMake_TEST_BINARY_DIR}/generated_dependency_graph.dot) diff --git a/Tests/RunCMake/Graphviz/no_module_libs-check.cmake b/Tests/RunCMake/Graphviz/no_module_libs-check.cmake new file mode 100644 index 0000000..e185cb1 --- /dev/null +++ b/Tests/RunCMake/Graphviz/no_module_libs-check.cmake @@ -0,0 +1,5 @@ +include(RunCMake) + +ensure_files_match( + ${RunCMake_TEST_SOURCE_DIR}/expected_outputs/dependency_graph_no_module_libs.dot + ${RunCMake_TEST_BINARY_DIR}/generated_dependency_graph.dot) diff --git a/Tests/RunCMake/Graphviz/no_object_libs-check.cmake b/Tests/RunCMake/Graphviz/no_object_libs-check.cmake new file mode 100644 index 0000000..90e7ecb --- /dev/null +++ b/Tests/RunCMake/Graphviz/no_object_libs-check.cmake @@ -0,0 +1,5 @@ +include(RunCMake) + +ensure_files_match( + ${RunCMake_TEST_SOURCE_DIR}/expected_outputs/dependency_graph_no_object_libs.dot + ${RunCMake_TEST_BINARY_DIR}/generated_dependency_graph.dot) diff --git a/Tests/RunCMake/Graphviz/no_per_target_files-check.cmake b/Tests/RunCMake/Graphviz/no_per_target_files-check.cmake new file mode 100644 index 0000000..95d05a1 --- /dev/null +++ b/Tests/RunCMake/Graphviz/no_per_target_files-check.cmake @@ -0,0 +1,5 @@ +file(GLOB per_target_files ${RunCMake_TEST_BINARY_DIR}/*.dot.*) +list(FILTER per_target_files EXCLUDE REGEX ".*\\.dependers$") +if(per_target_files) + set(RunCMake_TEST_FAILED "Found per-target .dot files despite GRAPHVIZ_GENERATE_PER_TARGET set to FALSE.") +endif() diff --git a/Tests/RunCMake/Graphviz/no_shared_libs-check.cmake b/Tests/RunCMake/Graphviz/no_shared_libs-check.cmake new file mode 100644 index 0000000..b45da2e --- /dev/null +++ b/Tests/RunCMake/Graphviz/no_shared_libs-check.cmake @@ -0,0 +1,5 @@ +include(RunCMake) + +ensure_files_match( + ${RunCMake_TEST_SOURCE_DIR}/expected_outputs/dependency_graph_no_shared_libs.dot + ${RunCMake_TEST_BINARY_DIR}/generated_dependency_graph.dot) diff --git a/Tests/RunCMake/Graphviz/no_static_libs-check.cmake b/Tests/RunCMake/Graphviz/no_static_libs-check.cmake new file mode 100644 index 0000000..befc11b --- /dev/null +++ b/Tests/RunCMake/Graphviz/no_static_libs-check.cmake @@ -0,0 +1,5 @@ +include(RunCMake) + +ensure_files_match( + ${RunCMake_TEST_SOURCE_DIR}/expected_outputs/dependency_graph_no_static_libs.dot + ${RunCMake_TEST_BINARY_DIR}/generated_dependency_graph.dot) diff --git a/Tests/RunCMake/Graphviz/no_unknown_libs-check.cmake b/Tests/RunCMake/Graphviz/no_unknown_libs-check.cmake new file mode 100644 index 0000000..95286bc --- /dev/null +++ b/Tests/RunCMake/Graphviz/no_unknown_libs-check.cmake @@ -0,0 +1,5 @@ +include(RunCMake) + +ensure_files_match( + ${RunCMake_TEST_SOURCE_DIR}/expected_outputs/dependency_graph_no_unknown_libs.dot + ${RunCMake_TEST_BINARY_DIR}/generated_dependency_graph.dot) diff --git a/Tests/RunCMake/Graphviz/set_graph_header-check.cmake b/Tests/RunCMake/Graphviz/set_graph_header-check.cmake new file mode 100644 index 0000000..1396484 --- /dev/null +++ b/Tests/RunCMake/Graphviz/set_graph_header-check.cmake @@ -0,0 +1,5 @@ +include(RunCMake) + +ensure_files_match( + ${RunCMake_TEST_SOURCE_DIR}/expected_outputs/dependency_graph_set_graph_header.dot + ${RunCMake_TEST_BINARY_DIR}/generated_dependency_graph.dot) diff --git a/Tests/RunCMake/Graphviz/set_graph_name-check.cmake b/Tests/RunCMake/Graphviz/set_graph_name-check.cmake new file mode 100644 index 0000000..0c522e9 --- /dev/null +++ b/Tests/RunCMake/Graphviz/set_graph_name-check.cmake @@ -0,0 +1,5 @@ +include(RunCMake) + +ensure_files_match( + ${RunCMake_TEST_SOURCE_DIR}/expected_outputs/dependency_graph_set_graph_name.dot + ${RunCMake_TEST_BINARY_DIR}/generated_dependency_graph.dot) diff --git a/Tests/RunCMake/Graphviz/set_node_prefix-check.cmake b/Tests/RunCMake/Graphviz/set_node_prefix-check.cmake new file mode 100644 index 0000000..61e9b24 --- /dev/null +++ b/Tests/RunCMake/Graphviz/set_node_prefix-check.cmake @@ -0,0 +1,5 @@ +include(RunCMake) + +ensure_files_match( + ${RunCMake_TEST_SOURCE_DIR}/expected_outputs/dependency_graph_set_node_prefix.dot + ${RunCMake_TEST_BINARY_DIR}/generated_dependency_graph.dot) diff --git a/Tests/RunCMake/Graphviz/test_project/core_library.c b/Tests/RunCMake/Graphviz/test_project/core_library.c new file mode 100644 index 0000000..e8a8844 --- /dev/null +++ b/Tests/RunCMake/Graphviz/test_project/core_library.c @@ -0,0 +1,3 @@ +void log_something() +{ +} diff --git a/Tests/RunCMake/Graphviz/test_project/graphic_library.c b/Tests/RunCMake/Graphviz/test_project/graphic_library.c new file mode 100644 index 0000000..958c8ab --- /dev/null +++ b/Tests/RunCMake/Graphviz/test_project/graphic_library.c @@ -0,0 +1,3 @@ +void initialize_graphics() +{ +} diff --git a/Tests/RunCMake/Graphviz/test_project/main.c b/Tests/RunCMake/Graphviz/test_project/main.c new file mode 100644 index 0000000..d123e09 --- /dev/null +++ b/Tests/RunCMake/Graphviz/test_project/main.c @@ -0,0 +1,4 @@ +int main(int argc, char** argv) +{ + return 0; +} diff --git a/Tests/RunCMake/Graphviz/test_project/module.c b/Tests/RunCMake/Graphviz/test_project/module.c new file mode 100644 index 0000000..a508b09 --- /dev/null +++ b/Tests/RunCMake/Graphviz/test_project/module.c @@ -0,0 +1,3 @@ +static void some_function() +{ +} diff --git a/Tests/RunCMake/Graphviz/test_project/third_party_project/CMakeLists.txt b/Tests/RunCMake/Graphviz/test_project/third_party_project/CMakeLists.txt new file mode 100644 index 0000000..e381750 --- /dev/null +++ b/Tests/RunCMake/Graphviz/test_project/third_party_project/CMakeLists.txt @@ -0,0 +1,3 @@ +project(ThirdPartyProject) + +add_library(GoofyLoggingLibrary INTERFACE) diff --git a/Tests/RunCMake/INSTALL_NAME_DIR/CMakeLists.txt b/Tests/RunCMake/INSTALL_NAME_DIR/CMakeLists.txt new file mode 100644 index 0000000..5253d34 --- /dev/null +++ b/Tests/RunCMake/INSTALL_NAME_DIR/CMakeLists.txt @@ -0,0 +1,4 @@ +cmake_minimum_required(VERSION 3.16) +project(${RunCMake_TEST} NONE) +include(${CMAKE_CURRENT_LIST_DIR}/INSTALL_NAME_DIR.cmake) +include(${RunCMake_TEST}.cmake) diff --git a/Tests/RunCMake/INSTALL_NAME_DIR/INSTALL_NAME_DIR.cmake b/Tests/RunCMake/INSTALL_NAME_DIR/INSTALL_NAME_DIR.cmake new file mode 100644 index 0000000..eaa0b45 --- /dev/null +++ b/Tests/RunCMake/INSTALL_NAME_DIR/INSTALL_NAME_DIR.cmake @@ -0,0 +1,15 @@ +function(add_install_name_dir_libraries install_name_dir) + add_library(build_dir SHARED test.c) + add_library(install_dir SHARED test.c) + if(NOT install_name_dir STREQUAL "NONE") + set_target_properties(build_dir install_dir PROPERTIES + INSTALL_NAME_DIR "${install_name_dir}" + ) + endif() + set_target_properties(install_dir PROPERTIES + BUILD_WITH_INSTALL_NAME_DIR TRUE + ) + install(TARGETS build_dir install_dir EXPORT InstallNameDirTest DESTINATION lib) + install(EXPORT InstallNameDirTest DESTINATION lib/cmake/InstallNameDirTest FILE InstallNameDirTest-targets.cmake) + file(GENERATE OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/targets.txt" CONTENT "$<TARGET_FILE:build_dir>\n$<TARGET_FILE:install_dir>\n" CONDITION $<CONFIG:Debug>) +endfunction() diff --git a/Tests/RunCMake/INSTALL_NAME_DIR/RunCMakeTest.cmake b/Tests/RunCMake/INSTALL_NAME_DIR/RunCMakeTest.cmake new file mode 100644 index 0000000..2aa03dd --- /dev/null +++ b/Tests/RunCMake/INSTALL_NAME_DIR/RunCMakeTest.cmake @@ -0,0 +1,69 @@ +cmake_minimum_required(VERSION 3.16) + +include(RunCMake) + +function(run_install_test case) + set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/${case}-build) + set(RunCMake_TEST_NO_CLEAN 1) + set(RunCMake_TEST_OPTIONS -DCMAKE_BUILD_TYPE:STRING=Debug "-DCMAKE_INSTALL_PREFIX:PATH=${RunCMake_TEST_BINARY_DIR}/fake_install") + file(REMOVE_RECURSE "${RunCMake_TEST_BINARY_DIR}") + file(MAKE_DIRECTORY "${RunCMake_TEST_BINARY_DIR}") + run_cmake(${case}) + run_cmake_command(${case}-build ${CMAKE_COMMAND} --build . --config Debug) + run_cmake_command(${case}-install ${CMAKE_COMMAND} --install . --config Debug --prefix "${RunCMake_TEST_BINARY_DIR}/real_install") +endfunction() + +find_program(OTOOL_COMMAND otool) + +function(check_install_name_dir file expected) + execute_process(COMMAND ${OTOOL_COMMAND} -l ${file} RESULT_VARIABLE _result OUTPUT_VARIABLE _output) + if(_result) + string(APPEND RunCMake_TEST_FAILED "Could not run otool on ${file}\n") + elseif(_output MATCHES "cmd LC_ID_DYLIB\n[^\n]*\n *name ([^\n]*) \\(offset [0-9]+\\)\n") + set(_install_name "${CMAKE_MATCH_1}") + if(NOT _install_name MATCHES "${expected}") + string(APPEND RunCMake_TEST_FAILED "Install name of ${file} did not match ${expected} (actual: ${_install_name})\n") + endif() + else() + string(APPEND RunCMake_TEST_FAILED "otool did not print install name for ${file}\n") + endif() + + set(RunCMake_TEST_FAILED "${RunCMake_TEST_FAILED}" PARENT_SCOPE) +endfunction() + +function(check_imported_soname contents target expected) + if(contents MATCHES "set_target_properties\\(${target} PROPERTIES\n[^\n]*\n *IMPORTED_SONAME_DEBUG \"([^\n]*)\"\n") + set(_soname "${CMAKE_MATCH_1}") + set(_regex "^${expected}lib${target}\\.dylib$") + if(NOT _soname MATCHES "${_regex}") + string(APPEND RunCMake_TEST_FAILED "Target ${target}'s IMPORTED_SONAME_DEBUG did not match ${_regex} (actual: ${_soname})\n") + endif() + else() + string(APPEND RunCMake_TEST_FAILED "Could not find IMPORTED_SONAME_DEBUG for target ${target} in package config file\n") + endif() + + set(RunCMake_TEST_FAILED "${RunCMake_TEST_FAILED}" PARENT_SCOPE) +endfunction() + +function(check_libraries fake_install real_install soname_prefix) + file(STRINGS "${RunCMake_TEST_BINARY_DIR}/targets.txt" _targets) + list(GET _targets 0 _build_dir) + list(GET _targets 1 _install_dir) + check_install_name_dir("${_build_dir}" "^@rpath/libbuild_dir\\.dylib$") + check_install_name_dir("${_install_dir}" "^${fake_install}libinstall_dir\\.dylib$") + check_install_name_dir("${RunCMake_TEST_BINARY_DIR}/real_install/lib/libbuild_dir.dylib" "^${real_install}libbuild_dir\\.dylib$") + check_install_name_dir("${RunCMake_TEST_BINARY_DIR}/real_install/lib/libinstall_dir.dylib" "^${real_install}libinstall_dir\\.dylib$") + + file(READ "${RunCMake_TEST_BINARY_DIR}/real_install/lib/cmake/InstallNameDirTest/InstallNameDirTest-targets-debug.cmake" _targets) + check_imported_soname("${_targets}" build_dir "${soname_prefix}") + check_imported_soname("${_targets}" install_dir "${soname_prefix}") + + set(RunCMake_TEST_FAILED "${RunCMake_TEST_FAILED}" PARENT_SCOPE) +endfunction() + +run_install_test(none) +run_install_test(empty) +run_install_test(simple) +run_install_test(simple_genex) +run_install_test(prefix_genex) +run_install_test(empty_genex) diff --git a/Tests/RunCMake/INSTALL_NAME_DIR/empty-install-check.cmake b/Tests/RunCMake/INSTALL_NAME_DIR/empty-install-check.cmake new file mode 100644 index 0000000..db87d2c --- /dev/null +++ b/Tests/RunCMake/INSTALL_NAME_DIR/empty-install-check.cmake @@ -0,0 +1 @@ +check_libraries("" "" "") diff --git a/Tests/RunCMake/INSTALL_NAME_DIR/empty.cmake b/Tests/RunCMake/INSTALL_NAME_DIR/empty.cmake new file mode 100644 index 0000000..0cde4d1 --- /dev/null +++ b/Tests/RunCMake/INSTALL_NAME_DIR/empty.cmake @@ -0,0 +1,3 @@ +enable_language(C) + +add_install_name_dir_libraries("") diff --git a/Tests/RunCMake/INSTALL_NAME_DIR/empty_genex-install-check.cmake b/Tests/RunCMake/INSTALL_NAME_DIR/empty_genex-install-check.cmake new file mode 100644 index 0000000..db87d2c --- /dev/null +++ b/Tests/RunCMake/INSTALL_NAME_DIR/empty_genex-install-check.cmake @@ -0,0 +1 @@ +check_libraries("" "" "") diff --git a/Tests/RunCMake/INSTALL_NAME_DIR/empty_genex.cmake b/Tests/RunCMake/INSTALL_NAME_DIR/empty_genex.cmake new file mode 100644 index 0000000..321c8d1 --- /dev/null +++ b/Tests/RunCMake/INSTALL_NAME_DIR/empty_genex.cmake @@ -0,0 +1,3 @@ +enable_language(C) + +add_install_name_dir_libraries($<0:/usr/local/lib>) diff --git a/Tests/RunCMake/INSTALL_NAME_DIR/none-install-check.cmake b/Tests/RunCMake/INSTALL_NAME_DIR/none-install-check.cmake new file mode 100644 index 0000000..c3e7ac4 --- /dev/null +++ b/Tests/RunCMake/INSTALL_NAME_DIR/none-install-check.cmake @@ -0,0 +1 @@ +check_libraries(@rpath/ @rpath/ @rpath/) diff --git a/Tests/RunCMake/INSTALL_NAME_DIR/none.cmake b/Tests/RunCMake/INSTALL_NAME_DIR/none.cmake new file mode 100644 index 0000000..79c5e7d --- /dev/null +++ b/Tests/RunCMake/INSTALL_NAME_DIR/none.cmake @@ -0,0 +1,3 @@ +enable_language(C) + +add_install_name_dir_libraries(NONE) diff --git a/Tests/RunCMake/INSTALL_NAME_DIR/prefix_genex-install-check.cmake b/Tests/RunCMake/INSTALL_NAME_DIR/prefix_genex-install-check.cmake new file mode 100644 index 0000000..8cf7db8 --- /dev/null +++ b/Tests/RunCMake/INSTALL_NAME_DIR/prefix_genex-install-check.cmake @@ -0,0 +1,6 @@ +check_libraries( + ".*/Tests/RunCMake/INSTALL_NAME_DIR/prefix_genex-build/fake_install/lib/" + ".*/Tests/RunCMake/INSTALL_NAME_DIR/prefix_genex-build/real_install/lib/" + # "$" has to be escaped twice because of its significance in regexes. + "\\\${_IMPORT_PREFIX}/lib/" + ) diff --git a/Tests/RunCMake/INSTALL_NAME_DIR/prefix_genex.cmake b/Tests/RunCMake/INSTALL_NAME_DIR/prefix_genex.cmake new file mode 100644 index 0000000..7e26208 --- /dev/null +++ b/Tests/RunCMake/INSTALL_NAME_DIR/prefix_genex.cmake @@ -0,0 +1,3 @@ +enable_language(C) + +add_install_name_dir_libraries($<1:$<INSTALL_PREFIX>/lib>) diff --git a/Tests/RunCMake/INSTALL_NAME_DIR/simple-install-check.cmake b/Tests/RunCMake/INSTALL_NAME_DIR/simple-install-check.cmake new file mode 100644 index 0000000..5f737cb --- /dev/null +++ b/Tests/RunCMake/INSTALL_NAME_DIR/simple-install-check.cmake @@ -0,0 +1 @@ +check_libraries(/usr/local/lib/ /usr/local/lib/ /usr/local/lib/) diff --git a/Tests/RunCMake/INSTALL_NAME_DIR/simple.cmake b/Tests/RunCMake/INSTALL_NAME_DIR/simple.cmake new file mode 100644 index 0000000..d019875 --- /dev/null +++ b/Tests/RunCMake/INSTALL_NAME_DIR/simple.cmake @@ -0,0 +1,3 @@ +enable_language(C) + +add_install_name_dir_libraries(/usr/local/lib) diff --git a/Tests/RunCMake/INSTALL_NAME_DIR/simple_genex-install-check.cmake b/Tests/RunCMake/INSTALL_NAME_DIR/simple_genex-install-check.cmake new file mode 100644 index 0000000..5f737cb --- /dev/null +++ b/Tests/RunCMake/INSTALL_NAME_DIR/simple_genex-install-check.cmake @@ -0,0 +1 @@ +check_libraries(/usr/local/lib/ /usr/local/lib/ /usr/local/lib/) diff --git a/Tests/RunCMake/INSTALL_NAME_DIR/simple_genex.cmake b/Tests/RunCMake/INSTALL_NAME_DIR/simple_genex.cmake new file mode 100644 index 0000000..1e729e8 --- /dev/null +++ b/Tests/RunCMake/INSTALL_NAME_DIR/simple_genex.cmake @@ -0,0 +1,3 @@ +enable_language(C) + +add_install_name_dir_libraries($<1:/usr/local/lib>) diff --git a/Tests/RunCMake/INSTALL_NAME_DIR/test.c b/Tests/RunCMake/INSTALL_NAME_DIR/test.c new file mode 100644 index 0000000..c2db61c --- /dev/null +++ b/Tests/RunCMake/INSTALL_NAME_DIR/test.c @@ -0,0 +1,3 @@ +void test(void) +{ +} diff --git a/Tests/RunCMake/MaxRecursionDepth/variable_watch-default-script-stderr.txt b/Tests/RunCMake/MaxRecursionDepth/variable_watch-default-script-stderr.txt index 4dddc96..07deee2 100644 --- a/Tests/RunCMake/MaxRecursionDepth/variable_watch-default-script-stderr.txt +++ b/Tests/RunCMake/MaxRecursionDepth/variable_watch-default-script-stderr.txt @@ -1,6 +1,6 @@ [0-9]+ -CMake Error at .*/variable_watch\.cmake:9999 \(update_x\): +CMake Error at .*/variable_watch\.cmake:[0-9]+ \(update_x\): Maximum recursion depth of [0-9]+ exceeded Call Stack \(most recent call first\): .*/variable_watch\.cmake:5 \(set\) - .*/variable_watch\.cmake:9999 \(update_x\) + .*/variable_watch\.cmake:[0-9]+ \(update_x\) diff --git a/Tests/RunCMake/MaxRecursionDepth/variable_watch-default-stderr.txt b/Tests/RunCMake/MaxRecursionDepth/variable_watch-default-stderr.txt index a8b4756..b2395b3 100644 --- a/Tests/RunCMake/MaxRecursionDepth/variable_watch-default-stderr.txt +++ b/Tests/RunCMake/MaxRecursionDepth/variable_watch-default-stderr.txt @@ -1,6 +1,6 @@ [0-9]+ -CMake Error at variable_watch\.cmake:9999 \(update_x\): +CMake Error at variable_watch\.cmake:[0-9]+ \(update_x\): Maximum recursion depth of [0-9]+ exceeded Call Stack \(most recent call first\): variable_watch\.cmake:5 \(set\) - variable_watch\.cmake:9999 \(update_x\) + variable_watch\.cmake:[0-9]+ \(update_x\) diff --git a/Tests/RunCMake/MaxRecursionDepth/variable_watch-invalid-var-script-stderr.txt b/Tests/RunCMake/MaxRecursionDepth/variable_watch-invalid-var-script-stderr.txt index 4dddc96..07deee2 100644 --- a/Tests/RunCMake/MaxRecursionDepth/variable_watch-invalid-var-script-stderr.txt +++ b/Tests/RunCMake/MaxRecursionDepth/variable_watch-invalid-var-script-stderr.txt @@ -1,6 +1,6 @@ [0-9]+ -CMake Error at .*/variable_watch\.cmake:9999 \(update_x\): +CMake Error at .*/variable_watch\.cmake:[0-9]+ \(update_x\): Maximum recursion depth of [0-9]+ exceeded Call Stack \(most recent call first\): .*/variable_watch\.cmake:5 \(set\) - .*/variable_watch\.cmake:9999 \(update_x\) + .*/variable_watch\.cmake:[0-9]+ \(update_x\) diff --git a/Tests/RunCMake/MaxRecursionDepth/variable_watch-invalid-var-stderr.txt b/Tests/RunCMake/MaxRecursionDepth/variable_watch-invalid-var-stderr.txt index a8b4756..b2395b3 100644 --- a/Tests/RunCMake/MaxRecursionDepth/variable_watch-invalid-var-stderr.txt +++ b/Tests/RunCMake/MaxRecursionDepth/variable_watch-invalid-var-stderr.txt @@ -1,6 +1,6 @@ [0-9]+ -CMake Error at variable_watch\.cmake:9999 \(update_x\): +CMake Error at variable_watch\.cmake:[0-9]+ \(update_x\): Maximum recursion depth of [0-9]+ exceeded Call Stack \(most recent call first\): variable_watch\.cmake:5 \(set\) - variable_watch\.cmake:9999 \(update_x\) + variable_watch\.cmake:[0-9]+ \(update_x\) diff --git a/Tests/RunCMake/MaxRecursionDepth/variable_watch-var-script-stderr.txt b/Tests/RunCMake/MaxRecursionDepth/variable_watch-var-script-stderr.txt index 00b2b3c..52fedd3 100644 --- a/Tests/RunCMake/MaxRecursionDepth/variable_watch-var-script-stderr.txt +++ b/Tests/RunCMake/MaxRecursionDepth/variable_watch-var-script-stderr.txt @@ -2,17 +2,17 @@ 6 8 10 -CMake Error at .*/variable_watch\.cmake:9999 \(update_x\): +CMake Error at .*/variable_watch\.cmake:[0-9]+ \(update_x\): Maximum recursion depth of 10 exceeded Call Stack \(most recent call first\): .*/variable_watch\.cmake:5 \(set\) - .*/variable_watch\.cmake:9999 \(update_x\) + .*/variable_watch\.cmake:[0-9]+ \(update_x\) .*/variable_watch\.cmake:5 \(set\) - .*/variable_watch\.cmake:9999 \(update_x\) + .*/variable_watch\.cmake:[0-9]+ \(update_x\) .*/variable_watch\.cmake:5 \(set\) - .*/variable_watch\.cmake:9999 \(update_x\) + .*/variable_watch\.cmake:[0-9]+ \(update_x\) .*/variable_watch\.cmake:5 \(set\) - .*/variable_watch\.cmake:9999 \(update_x\) + .*/variable_watch\.cmake:[0-9]+ \(update_x\) .*/variable_watch\.cmake:9 \(set\) .*/CMakeLists\.txt:5 \(include\) diff --git a/Tests/RunCMake/MaxRecursionDepth/variable_watch-var-stderr.txt b/Tests/RunCMake/MaxRecursionDepth/variable_watch-var-stderr.txt index 8f27bf1..1427f1d 100644 --- a/Tests/RunCMake/MaxRecursionDepth/variable_watch-var-stderr.txt +++ b/Tests/RunCMake/MaxRecursionDepth/variable_watch-var-stderr.txt @@ -2,17 +2,17 @@ 6 8 10 -CMake Error at variable_watch\.cmake:9999 \(update_x\): +CMake Error at variable_watch\.cmake:[0-9]+ \(update_x\): Maximum recursion depth of 10 exceeded Call Stack \(most recent call first\): variable_watch\.cmake:5 \(set\) - variable_watch\.cmake:9999 \(update_x\) + variable_watch\.cmake:[0-9]+ \(update_x\) variable_watch\.cmake:5 \(set\) - variable_watch\.cmake:9999 \(update_x\) + variable_watch\.cmake:[0-9]+ \(update_x\) variable_watch\.cmake:5 \(set\) - variable_watch\.cmake:9999 \(update_x\) + variable_watch\.cmake:[0-9]+ \(update_x\) variable_watch\.cmake:5 \(set\) - variable_watch\.cmake:9999 \(update_x\) + variable_watch\.cmake:[0-9]+ \(update_x\) variable_watch\.cmake:9 \(set\) CMakeLists\.txt:5 \(include\) diff --git a/Tests/RunCMake/Ninja/RunCMakeTest.cmake b/Tests/RunCMake/Ninja/RunCMakeTest.cmake index 808a872..a00d830 100644 --- a/Tests/RunCMake/Ninja/RunCMakeTest.cmake +++ b/Tests/RunCMake/Ninja/RunCMakeTest.cmake @@ -1,5 +1,8 @@ include(RunCMake) +set(RunCMake_GENERATOR "Ninja") +set(RunCMake_GENERATOR_IS_MULTI_CONFIG 0) + # Detect ninja version so we know what tests can be supported. execute_process( COMMAND "${RunCMake_MAKE_PROGRAM}" --version diff --git a/Tests/RunCMake/NinjaMultiConfig/AdditionalCleanFiles-all-clean-ninja-check.cmake b/Tests/RunCMake/NinjaMultiConfig/AdditionalCleanFiles-all-clean-ninja-check.cmake new file mode 100644 index 0000000..012dc2f --- /dev/null +++ b/Tests/RunCMake/NinjaMultiConfig/AdditionalCleanFiles-all-clean-ninja-check.cmake @@ -0,0 +1,4 @@ +check_files("${RunCMake_TEST_BINARY_DIR}" + INCLUDE + # Intentionally empty + ) diff --git a/Tests/RunCMake/NinjaMultiConfig/AdditionalCleanFiles-check.cmake b/Tests/RunCMake/NinjaMultiConfig/AdditionalCleanFiles-check.cmake new file mode 100644 index 0000000..77412f1 --- /dev/null +++ b/Tests/RunCMake/NinjaMultiConfig/AdditionalCleanFiles-check.cmake @@ -0,0 +1,8 @@ +check_files("${RunCMake_TEST_BINARY_DIR}" + INCLUDE + ${RunCMake_TEST_BINARY_DIR}/global.txt + ${RunCMake_TEST_BINARY_DIR}/Debug.txt + ${RunCMake_TEST_BINARY_DIR}/Release.txt + ${RunCMake_TEST_BINARY_DIR}/MinSizeRel.txt + ${RunCMake_TEST_BINARY_DIR}/RelWithDebInfo.txt + ) diff --git a/Tests/RunCMake/NinjaMultiConfig/AdditionalCleanFiles-release-clean-build-check.cmake b/Tests/RunCMake/NinjaMultiConfig/AdditionalCleanFiles-release-clean-build-check.cmake new file mode 100644 index 0000000..f211223 --- /dev/null +++ b/Tests/RunCMake/NinjaMultiConfig/AdditionalCleanFiles-release-clean-build-check.cmake @@ -0,0 +1,6 @@ +check_files("${RunCMake_TEST_BINARY_DIR}" + INCLUDE + ${RunCMake_TEST_BINARY_DIR}/Debug.txt + ${RunCMake_TEST_BINARY_DIR}/MinSizeRel.txt + ${RunCMake_TEST_BINARY_DIR}/RelWithDebInfo.txt + ) diff --git a/Tests/RunCMake/NinjaMultiConfig/AdditionalCleanFiles.cmake b/Tests/RunCMake/NinjaMultiConfig/AdditionalCleanFiles.cmake new file mode 100644 index 0000000..983a494 --- /dev/null +++ b/Tests/RunCMake/NinjaMultiConfig/AdditionalCleanFiles.cmake @@ -0,0 +1,3 @@ +file(GENERATE OUTPUT $<CONFIG>.txt CONTENT "$<CONFIG>\n") +file(TOUCH ${CMAKE_BINARY_DIR}/global.txt) +set_directory_properties(PROPERTIES ADDITIONAL_CLEAN_FILES "$<CONFIG>.txt;global.txt") diff --git a/Tests/RunCMake/NinjaMultiConfig/AutoMocExecutable.cmake b/Tests/RunCMake/NinjaMultiConfig/AutoMocExecutable.cmake new file mode 100644 index 0000000..950e18e --- /dev/null +++ b/Tests/RunCMake/NinjaMultiConfig/AutoMocExecutable.cmake @@ -0,0 +1,10 @@ +enable_language(C) + +add_executable(badmoc badmoc.c) +target_compile_definitions(badmoc PRIVATE "CONFIG=\"$<CONFIG>\"") + +add_executable(exe main.c) +set_target_properties(exe PROPERTIES + AUTOMOC ON + AUTOMOC_EXECUTABLE $<TARGET_FILE:badmoc> + ) diff --git a/Tests/RunCMake/NinjaMultiConfig/CMakeLists.txt b/Tests/RunCMake/NinjaMultiConfig/CMakeLists.txt new file mode 100644 index 0000000..2632ffa --- /dev/null +++ b/Tests/RunCMake/NinjaMultiConfig/CMakeLists.txt @@ -0,0 +1,3 @@ +cmake_minimum_required(VERSION 3.16) +project(${RunCMake_TEST} NONE) +include(${RunCMake_TEST}.cmake) diff --git a/Tests/RunCMake/NinjaMultiConfig/Clean-release-build-check.cmake b/Tests/RunCMake/NinjaMultiConfig/Clean-release-build-check.cmake new file mode 100644 index 0000000..cfe6984 --- /dev/null +++ b/Tests/RunCMake/NinjaMultiConfig/Clean-release-build-check.cmake @@ -0,0 +1,16 @@ +check_files("${RunCMake_TEST_BINARY_DIR}" + INCLUDE + ${TARGET_FILE_mylib_Release} + ${TARGET_LINKER_FILE_mylib_Release} + ${TARGET_SONAME_FILE_mylib_Release} + ${TARGET_OBJECT_FILES_mylib_Release} + + ${TARGET_OBJECT_FILES_myobj_Release} + + ${TARGET_FILE_exeall_Release} + ${TARGET_EXE_FILE_exeall_Release} + ${TARGET_OBJECT_FILES_exeall_Release} + + EXCLUDE + ${TARGET_OBJECT_FILES_exenotall_Release} + ) diff --git a/Tests/RunCMake/NinjaMultiConfig/Clean-release-clean-build-check.cmake b/Tests/RunCMake/NinjaMultiConfig/Clean-release-clean-build-check.cmake new file mode 100644 index 0000000..06b3fb6 --- /dev/null +++ b/Tests/RunCMake/NinjaMultiConfig/Clean-release-clean-build-check.cmake @@ -0,0 +1,7 @@ +check_files("${RunCMake_TEST_BINARY_DIR}" + EXCLUDE + ${TARGET_OBJECT_FILES_exeall_Release} + ${TARGET_OBJECT_FILES_exenotall_Release} + ${TARGET_OBJECT_FILES_mylib_Release} + ${TARGET_OBJECT_FILES_myobj_Release} + ) diff --git a/Tests/RunCMake/NinjaMultiConfig/Clean-release-notall-ninja-check.cmake b/Tests/RunCMake/NinjaMultiConfig/Clean-release-notall-ninja-check.cmake new file mode 100644 index 0000000..42d6a78 --- /dev/null +++ b/Tests/RunCMake/NinjaMultiConfig/Clean-release-notall-ninja-check.cmake @@ -0,0 +1,16 @@ +check_files("${RunCMake_TEST_BINARY_DIR}" + INCLUDE + ${TARGET_FILE_mylib_Release} + ${TARGET_LINKER_FILE_mylib_Release} + ${TARGET_SONAME_FILE_mylib_Release} + ${TARGET_OBJECT_FILES_mylib_Release} + + ${TARGET_OBJECT_FILES_myobj_Release} + + ${TARGET_FILE_exeall_Release} + ${TARGET_EXE_FILE_exeall_Release} + ${TARGET_OBJECT_FILES_exeall_Release} + + ${TARGET_FILE_exenotall_Release} + ${TARGET_OBJECT_FILES_exenotall_Release} + ) diff --git a/Tests/RunCMake/NinjaMultiConfig/Clean.cmake b/Tests/RunCMake/NinjaMultiConfig/Clean.cmake new file mode 100644 index 0000000..2258d2b --- /dev/null +++ b/Tests/RunCMake/NinjaMultiConfig/Clean.cmake @@ -0,0 +1,17 @@ +enable_language(C) + +add_executable(exeall main.c) +set_target_properties(exeall PROPERTIES VERSION 1.0.0) +add_executable(exenotall main.c) +set_target_properties(exenotall PROPERTIES EXCLUDE_FROM_ALL TRUE) + +add_library(mylib SHARED simplelib.c) +set_target_properties(mylib PROPERTIES + VERSION 1.0.0 + SOVERSION 1 + ) + +add_library(myobj OBJECT simplelib.c) + +include(${CMAKE_CURRENT_LIST_DIR}/Common.cmake) +generate_output_files(exeall exenotall mylib myobj) diff --git a/Tests/RunCMake/NinjaMultiConfig/Common.cmake b/Tests/RunCMake/NinjaMultiConfig/Common.cmake new file mode 100644 index 0000000..e13bd53 --- /dev/null +++ b/Tests/RunCMake/NinjaMultiConfig/Common.cmake @@ -0,0 +1,57 @@ +function(generate_output_files) + set(content) + foreach(tgt IN LISTS ARGN) + get_property(type TARGET ${tgt} PROPERTY TYPE) + + if(NOT type STREQUAL "OBJECT_LIBRARY") + set(file " [==[$<TARGET_FILE:${tgt}>]==]") + set(filename " [==[$<TARGET_FILE_NAME:${tgt}>]==]") + else() + set(file) + set(filename) + endif() + string(APPEND content "set(TARGET_FILE_${tgt}_$<CONFIG>${file})\n") + string(APPEND content "set(TARGET_FILE_NAME_${tgt}_$<CONFIG>${filename})\n") + + if(type MATCHES "^(STATIC|MODULE|SHARED)_LIBRARY$") + set(linker_file " [==[$<TARGET_LINKER_FILE:${tgt}>]==]") + set(linker_filename " [==[$<TARGET_LINKER_FILE_NAME:${tgt}>]==]") + else() + set(linker_file) + set(linker_filename) + endif() + string(APPEND content "set(TARGET_LINKER_FILE_${tgt}_$<CONFIG>${linker_file})\n") + string(APPEND content "set(TARGET_LINKER_FILE_NAME_${tgt}_$<CONFIG>${linker_filename})\n") + + if(NOT WIN32 AND NOT CYGWIN AND type MATCHES "^(SHARED_LIBRARY)$") + set(soname_file " [==[$<TARGET_SONAME_FILE:${tgt}>]==]") + set(soname_filename " [==[$<TARGET_SONAME_FILE_NAME:${tgt}>]==]") + else() + set(soname_file) + set(soname_filename) + endif() + string(APPEND content "set(TARGET_SONAME_FILE_${tgt}_$<CONFIG>${soname_file})\n") + string(APPEND content "set(TARGET_SONAME_FILE_NAME_${tgt}_$<CONFIG>${soname_filename})\n") + + if(type MATCHES "^(EXECUTABLE)$") + set(exe_file " [==[$<TARGET_FILE_DIR:${tgt}>/$<TARGET_FILE_PREFIX:${tgt}>$<TARGET_FILE_BASE_NAME:${tgt}>$<TARGET_FILE_SUFFIX:${tgt}>]==]") + set(exe_filename " [==[$<TARGET_FILE_PREFIX:${tgt}>$<TARGET_FILE_BASE_NAME:${tgt}>$<TARGET_FILE_SUFFIX:${tgt}>]==]") + else() + set(exe_file) + set(exe_filename) + endif() + string(APPEND content "set(TARGET_EXE_FILE_${tgt}_$<CONFIG>${exe_file})\n") + string(APPEND content "set(TARGET_EXE_FILE_NAME_${tgt}_$<CONFIG>${exe_filename})\n") + + string(APPEND content "set(TARGET_OBJECT_FILES_${tgt}_$<CONFIG> [==[$<TARGET_OBJECTS:${tgt}>]==])\n") + endforeach() + + file(GENERATE OUTPUT "${CMAKE_BINARY_DIR}/target_files_$<CONFIG>.cmake" CONTENT "${content}") + + set(content) + foreach(config IN LISTS CMAKE_CONFIGURATION_TYPES) + string(APPEND content "include(\${CMAKE_CURRENT_LIST_DIR}/target_files_${config}.cmake)\n") + endforeach() + + file(WRITE "${CMAKE_BINARY_DIR}/target_files.cmake" "${content}") +endfunction() diff --git a/Tests/RunCMake/NinjaMultiConfig/CustomCommandGenerator-debug-build-check.cmake b/Tests/RunCMake/NinjaMultiConfig/CustomCommandGenerator-debug-build-check.cmake new file mode 100644 index 0000000..2abdb43 --- /dev/null +++ b/Tests/RunCMake/NinjaMultiConfig/CustomCommandGenerator-debug-build-check.cmake @@ -0,0 +1,38 @@ +check_files("${RunCMake_TEST_BINARY_DIR}" + INCLUDE + ${CONFIG_FILES} + ${GENERATED_FILES} + + ${TARGET_FILE_generator_Debug} + ${TARGET_OBJECT_FILES_generator_Debug} + + ${TARGET_FILE_generated_Debug} + ${TARGET_OBJECT_FILES_generated_Debug} + + ${TARGET_FILE_generatorlib_Debug} + ${TARGET_LINKER_FILE_generatorlib_Debug} + ${TARGET_OBJECT_FILES_generatorlib_Debug} + + ${TARGET_OBJECT_FILES_generatorobj_Debug} + + ${TARGET_OBJECT_FILES_emptyobj_Debug} + + EXCLUDE + ${TARGET_OBJECT_FILES_generator_Release} + ${TARGET_OBJECT_FILES_generated_Release} + ${TARGET_OBJECT_FILES_generatorlib_Release} + ${TARGET_OBJECT_FILES_generatorobj_Release} + ${TARGET_OBJECT_FILES_emptyobj_Release} + + ${TARGET_OBJECT_FILES_generator_MinSizeRel} + ${TARGET_OBJECT_FILES_generated_MinSizeRel} + ${TARGET_OBJECT_FILES_generatorlib_MinSizeRel} + ${TARGET_OBJECT_FILES_generatorobj_MinSizeRel} + ${TARGET_OBJECT_FILES_emptyobj_MinSizeRel} + + ${TARGET_OBJECT_FILES_generator_RelWithDebInfo} + ${TARGET_OBJECT_FILES_generated_RelWithDebInfo} + ${TARGET_OBJECT_FILES_generatorlib_RelWithDebInfo} + ${TARGET_OBJECT_FILES_generatorobj_RelWithDebInfo} + ${TARGET_OBJECT_FILES_emptyobj_RelWithDebInfo} + ) diff --git a/Tests/RunCMake/NinjaMultiConfig/CustomCommandGenerator-debug-clean-ninja-check.cmake b/Tests/RunCMake/NinjaMultiConfig/CustomCommandGenerator-debug-clean-ninja-check.cmake new file mode 100644 index 0000000..aff42c3 --- /dev/null +++ b/Tests/RunCMake/NinjaMultiConfig/CustomCommandGenerator-debug-clean-ninja-check.cmake @@ -0,0 +1,37 @@ +check_files("${RunCMake_TEST_BINARY_DIR}" + INCLUDE + ${CONFIG_FILES} + + ${TARGET_FILE_generator_Release} + ${TARGET_OBJECT_FILES_generator_Release} + + ${TARGET_FILE_generated_Release} + ${TARGET_OBJECT_FILES_generated_Release} + + ${TARGET_FILE_generatorlib_Release} + ${TARGET_LINKER_FILE_generatorlib_Release} + ${TARGET_OBJECT_FILES_generatorlib_Release} + + ${TARGET_OBJECT_FILES_generatorobj_Release} + + ${TARGET_OBJECT_FILES_emptyobj_Release} + + EXCLUDE + ${TARGET_OBJECT_FILES_generator_Debug} + ${TARGET_OBJECT_FILES_generated_Debug} + ${TARGET_OBJECT_FILES_generatorlib_Debug} + ${TARGET_OBJECT_FILES_generatorobj_Debug} + ${TARGET_OBJECT_FILES_emptyobj_Debug} + + ${TARGET_OBJECT_FILES_generator_MinSizeRel} + ${TARGET_OBJECT_FILES_generated_MinSizeRel} + ${TARGET_OBJECT_FILES_generatorlib_MinSizeRel} + ${TARGET_OBJECT_FILES_generatorobj_MinSizeRel} + ${TARGET_OBJECT_FILES_emptyobj_MinSizeRel} + + ${TARGET_OBJECT_FILES_generator_RelWithDebInfo} + ${TARGET_OBJECT_FILES_generated_RelWithDebInfo} + ${TARGET_OBJECT_FILES_generatorlib_RelWithDebInfo} + ${TARGET_OBJECT_FILES_generatorobj_RelWithDebInfo} + ${TARGET_OBJECT_FILES_emptyobj_RelWithDebInfo} + ) diff --git a/Tests/RunCMake/NinjaMultiConfig/CustomCommandGenerator-debug-generated-stdout.txt b/Tests/RunCMake/NinjaMultiConfig/CustomCommandGenerator-debug-generated-stdout.txt new file mode 100644 index 0000000..765d486 --- /dev/null +++ b/Tests/RunCMake/NinjaMultiConfig/CustomCommandGenerator-debug-generated-stdout.txt @@ -0,0 +1,12 @@ +^Generator genex config definition: Debug +Generator genex config include dir: Debug +Generator library genex config definition: Debug +Generator library genex config include dir: Debug +Generator object genex config definition: Debug +Generator object genex config include dir: Debug +Generated genex config definition: Debug +Generated genex config include dir: Debug +Generated library genex config definition: Debug +Generated library genex config include dir: Debug +Generated object genex config definition: Debug +Generated object genex config include dir: Debug$ diff --git a/Tests/RunCMake/NinjaMultiConfig/CustomCommandGenerator-debug-in-release-graph-build-check.cmake b/Tests/RunCMake/NinjaMultiConfig/CustomCommandGenerator-debug-in-release-graph-build-check.cmake new file mode 100644 index 0000000..f534319 --- /dev/null +++ b/Tests/RunCMake/NinjaMultiConfig/CustomCommandGenerator-debug-in-release-graph-build-check.cmake @@ -0,0 +1,44 @@ +check_files("${RunCMake_TEST_BINARY_DIR}" + INCLUDE + ${CONFIG_FILES} + ${GENERATED_FILES} + + ${TARGET_FILE_generated_Debug} + ${TARGET_OBJECT_FILES_generated_Debug} + + ${TARGET_FILE_generatorlib_Debug} + ${TARGET_LINKER_FILE_generatorlib_Debug} + ${TARGET_OBJECT_FILES_generatorlib_Debug} + + ${TARGET_OBJECT_FILES_generatorobj_Debug} + + ${TARGET_OBJECT_FILES_emptyobj_Debug} + + ${TARGET_FILE_generator_Release} + ${TARGET_OBJECT_FILES_generator_Release} + + ${TARGET_FILE_generatorlib_Release} + ${TARGET_LINKER_FILE_generatorlib_Release} + ${TARGET_OBJECT_FILES_generatorlib_Release} + + ${TARGET_OBJECT_FILES_generatorobj_Release} + + ${TARGET_OBJECT_FILES_emptyobj_Release} + + EXCLUDE + ${TARGET_OBJECT_FILES_generator_Debug} + + ${TARGET_OBJECT_FILES_generated_Release} + + ${TARGET_OBJECT_FILES_generator_MinSizeRel} + ${TARGET_OBJECT_FILES_generated_MinSizeRel} + ${TARGET_OBJECT_FILES_generatorlib_MinSizeRel} + ${TARGET_OBJECT_FILES_generatorobj_MinSizeRel} + ${TARGET_OBJECT_FILES_emptyobj_MinSizeRel} + + ${TARGET_OBJECT_FILES_generator_RelWithDebInfo} + ${TARGET_OBJECT_FILES_generated_RelWithDebInfo} + ${TARGET_OBJECT_FILES_generatorlib_RelWithDebInfo} + ${TARGET_OBJECT_FILES_generatorobj_RelWithDebInfo} + ${TARGET_OBJECT_FILES_emptyobj_RelWithDebInfo} + ) diff --git a/Tests/RunCMake/NinjaMultiConfig/CustomCommandGenerator-debug-in-release-graph-clean-ninja-check.cmake b/Tests/RunCMake/NinjaMultiConfig/CustomCommandGenerator-debug-in-release-graph-clean-ninja-check.cmake new file mode 100644 index 0000000..5e30bfe --- /dev/null +++ b/Tests/RunCMake/NinjaMultiConfig/CustomCommandGenerator-debug-in-release-graph-clean-ninja-check.cmake @@ -0,0 +1,36 @@ +check_files("${RunCMake_TEST_BINARY_DIR}" + INCLUDE + ${CONFIG_FILES} + + ${TARGET_FILE_generator_Release} + ${TARGET_OBJECT_FILES_generator_Release} + + ${TARGET_FILE_generatorlib_Release} + ${TARGET_LINKER_FILE_generatorlib_Release} + ${TARGET_OBJECT_FILES_generatorlib_Release} + + ${TARGET_OBJECT_FILES_generatorobj_Release} + + ${TARGET_OBJECT_FILES_emptyobj_Release} + + EXCLUDE + ${TARGET_OBJECT_FILES_generator_Debug} + ${TARGET_OBJECT_FILES_generated_Debug} + ${TARGET_OBJECT_FILES_generatorlib_Debug} + ${TARGET_OBJECT_FILES_generatorobj_Debug} + ${TARGET_OBJECT_FILES_emptyobj_Debug} + + ${TARGET_OBJECT_FILES_generated_Release} + + ${TARGET_OBJECT_FILES_generator_MinSizeRel} + ${TARGET_OBJECT_FILES_generated_MinSizeRel} + ${TARGET_OBJECT_FILES_generatorlib_MinSizeRel} + ${TARGET_OBJECT_FILES_generatorobj_MinSizeRel} + ${TARGET_OBJECT_FILES_emptyobj_MinSizeRel} + + ${TARGET_OBJECT_FILES_generator_RelWithDebInfo} + ${TARGET_OBJECT_FILES_generated_RelWithDebInfo} + ${TARGET_OBJECT_FILES_generatorlib_RelWithDebInfo} + ${TARGET_OBJECT_FILES_generatorobj_RelWithDebInfo} + ${TARGET_OBJECT_FILES_emptyobj_RelWithDebInfo} + ) diff --git a/Tests/RunCMake/NinjaMultiConfig/CustomCommandGenerator-debug-in-release-graph-generated-stdout.txt b/Tests/RunCMake/NinjaMultiConfig/CustomCommandGenerator-debug-in-release-graph-generated-stdout.txt new file mode 100644 index 0000000..1c9abef --- /dev/null +++ b/Tests/RunCMake/NinjaMultiConfig/CustomCommandGenerator-debug-in-release-graph-generated-stdout.txt @@ -0,0 +1,12 @@ +^Generator genex config definition: Release +Generator genex config include dir: Release +Generator library genex config definition: Release +Generator library genex config include dir: Release +Generator object genex config definition: Release +Generator object genex config include dir: Release +Generated genex config definition: Debug +Generated genex config include dir: Debug +Generated library genex config definition: Debug +Generated library genex config include dir: Debug +Generated object genex config definition: Debug +Generated object genex config include dir: Debug$ diff --git a/Tests/RunCMake/NinjaMultiConfig/CustomCommandGenerator-release-clean-build-check.cmake b/Tests/RunCMake/NinjaMultiConfig/CustomCommandGenerator-release-clean-build-check.cmake new file mode 100644 index 0000000..8ba6d68 --- /dev/null +++ b/Tests/RunCMake/NinjaMultiConfig/CustomCommandGenerator-release-clean-build-check.cmake @@ -0,0 +1,29 @@ +check_files("${RunCMake_TEST_BINARY_DIR}" + INCLUDE + ${CONFIG_FILES} + + EXCLUDE + ${TARGET_OBJECT_FILES_generator_Debug} + ${TARGET_OBJECT_FILES_generated_Debug} + ${TARGET_OBJECT_FILES_generatorlib_Debug} + ${TARGET_OBJECT_FILES_generatorobj_Debug} + ${TARGET_OBJECT_FILES_emptyobj_Debug} + + ${TARGET_OBJECT_FILES_generator_Release} + ${TARGET_OBJECT_FILES_generated_Release} + ${TARGET_OBJECT_FILES_generatorlib_Release} + ${TARGET_OBJECT_FILES_generatorobj_Release} + ${TARGET_OBJECT_FILES_emptyobj_Release} + + ${TARGET_OBJECT_FILES_generator_MinSizeRel} + ${TARGET_OBJECT_FILES_generated_MinSizeRel} + ${TARGET_OBJECT_FILES_generatorlib_MinSizeRel} + ${TARGET_OBJECT_FILES_generatorobj_MinSizeRel} + ${TARGET_OBJECT_FILES_emptyobj_MinSizeRel} + + ${TARGET_OBJECT_FILES_generator_RelWithDebInfo} + ${TARGET_OBJECT_FILES_generated_RelWithDebInfo} + ${TARGET_OBJECT_FILES_generatorlib_RelWithDebInfo} + ${TARGET_OBJECT_FILES_generatorobj_RelWithDebInfo} + ${TARGET_OBJECT_FILES_emptyobj_RelWithDebInfo} + ) diff --git a/Tests/RunCMake/NinjaMultiConfig/CustomCommandGenerator-release-generated-stdout.txt b/Tests/RunCMake/NinjaMultiConfig/CustomCommandGenerator-release-generated-stdout.txt new file mode 100644 index 0000000..576ec51 --- /dev/null +++ b/Tests/RunCMake/NinjaMultiConfig/CustomCommandGenerator-release-generated-stdout.txt @@ -0,0 +1,12 @@ +^Generator genex config definition: Release +Generator genex config include dir: Release +Generator library genex config definition: Release +Generator library genex config include dir: Release +Generator object genex config definition: Release +Generator object genex config include dir: Release +Generated genex config definition: Release +Generated genex config include dir: Release +Generated library genex config definition: Release +Generated library genex config include dir: Release +Generated object genex config definition: Release +Generated object genex config include dir: Release$ diff --git a/Tests/RunCMake/NinjaMultiConfig/CustomCommandGenerator-release-in-debug-graph-generated-stdout.txt b/Tests/RunCMake/NinjaMultiConfig/CustomCommandGenerator-release-in-debug-graph-generated-stdout.txt new file mode 100644 index 0000000..25392af --- /dev/null +++ b/Tests/RunCMake/NinjaMultiConfig/CustomCommandGenerator-release-in-debug-graph-generated-stdout.txt @@ -0,0 +1,12 @@ +^Generator genex config definition: Debug +Generator genex config include dir: Debug +Generator library genex config definition: Debug +Generator library genex config include dir: Debug +Generator object genex config definition: Debug +Generator object genex config include dir: Debug +Generated genex config definition: Release +Generated genex config include dir: Release +Generated library genex config definition: Release +Generated library genex config include dir: Release +Generated object genex config definition: Release +Generated object genex config include dir: Release$ diff --git a/Tests/RunCMake/NinjaMultiConfig/CustomCommandGenerator-release-in-debug-graph-ninja-check.cmake b/Tests/RunCMake/NinjaMultiConfig/CustomCommandGenerator-release-in-debug-graph-ninja-check.cmake new file mode 100644 index 0000000..9500cda --- /dev/null +++ b/Tests/RunCMake/NinjaMultiConfig/CustomCommandGenerator-release-in-debug-graph-ninja-check.cmake @@ -0,0 +1,45 @@ +check_files("${RunCMake_TEST_BINARY_DIR}" + INCLUDE + ${CONFIG_FILES} + ${GENERATED_FILES} + + ${TARGET_FILE_generator_Debug} + ${TARGET_OBJECT_FILES_generator_Debug} + + ${TARGET_FILE_generatorlib_Debug} + ${TARGET_LINKER_FILE_generatorlib_Debug} + ${TARGET_OBJECT_FILES_generatorlib_Debug} + + ${TARGET_OBJECT_FILES_generatorobj_Debug} + + ${TARGET_OBJECT_FILES_emptyobj_Debug} + + ${TARGET_FILE_generator_Release} + ${TARGET_OBJECT_FILES_generator_Release} + + ${TARGET_FILE_generated_Release} + ${TARGET_OBJECT_FILES_generated_Release} + + ${TARGET_FILE_generatorlib_Release} + ${TARGET_LINKER_FILE_generatorlib_Release} + ${TARGET_OBJECT_FILES_generatorlib_Release} + + ${TARGET_OBJECT_FILES_generatorobj_Release} + + ${TARGET_OBJECT_FILES_emptyobj_Release} + + EXCLUDE + ${TARGET_OBJECT_FILES_generated_Debug} + + ${TARGET_OBJECT_FILES_generator_MinSizeRel} + ${TARGET_OBJECT_FILES_generated_MinSizeRel} + ${TARGET_OBJECT_FILES_generatorlib_MinSizeRel} + ${TARGET_OBJECT_FILES_generatorobj_MinSizeRel} + ${TARGET_OBJECT_FILES_emptyobj_MinSizeRel} + + ${TARGET_OBJECT_FILES_generator_RelWithDebInfo} + ${TARGET_OBJECT_FILES_generated_RelWithDebInfo} + ${TARGET_OBJECT_FILES_generatorlib_RelWithDebInfo} + ${TARGET_OBJECT_FILES_generatorobj_RelWithDebInfo} + ${TARGET_OBJECT_FILES_emptyobj_RelWithDebInfo} + ) diff --git a/Tests/RunCMake/NinjaMultiConfig/CustomCommandGenerator-release-ninja-check.cmake b/Tests/RunCMake/NinjaMultiConfig/CustomCommandGenerator-release-ninja-check.cmake new file mode 100644 index 0000000..b51a6a7 --- /dev/null +++ b/Tests/RunCMake/NinjaMultiConfig/CustomCommandGenerator-release-ninja-check.cmake @@ -0,0 +1,46 @@ +check_files("${RunCMake_TEST_BINARY_DIR}" + INCLUDE + ${CONFIG_FILES} + ${GENERATED_FILES} + + ${TARGET_FILE_generator_Debug} + ${TARGET_OBJECT_FILES_generator_Debug} + + ${TARGET_FILE_generated_Debug} + ${TARGET_OBJECT_FILES_generated_Debug} + + ${TARGET_FILE_generatorlib_Debug} + ${TARGET_LINKER_FILE_generatorlib_Debug} + ${TARGET_OBJECT_FILES_generatorlib_Debug} + + ${TARGET_OBJECT_FILES_generatorobj_Debug} + + ${TARGET_OBJECT_FILES_emptyobj_Debug} + + ${TARGET_FILE_generator_Release} + ${TARGET_OBJECT_FILES_generator_Release} + + ${TARGET_FILE_generated_Release} + ${TARGET_OBJECT_FILES_generated_Release} + + ${TARGET_FILE_generatorlib_Release} + ${TARGET_LINKER_FILE_generatorlib_Release} + ${TARGET_OBJECT_FILES_generatorlib_Release} + + ${TARGET_OBJECT_FILES_generatorobj_Release} + + ${TARGET_OBJECT_FILES_emptyobj_Release} + + EXCLUDE + ${TARGET_OBJECT_FILES_generator_MinSizeRel} + ${TARGET_OBJECT_FILES_generated_MinSizeRel} + ${TARGET_OBJECT_FILES_generatorlib_MinSizeRel} + ${TARGET_OBJECT_FILES_generatorobj_MinSizeRel} + ${TARGET_OBJECT_FILES_emptyobj_MinSizeRel} + + ${TARGET_OBJECT_FILES_generator_RelWithDebInfo} + ${TARGET_OBJECT_FILES_generated_RelWithDebInfo} + ${TARGET_OBJECT_FILES_generatorlib_RelWithDebInfo} + ${TARGET_OBJECT_FILES_generatorobj_RelWithDebInfo} + ${TARGET_OBJECT_FILES_emptyobj_RelWithDebInfo} + ) diff --git a/Tests/RunCMake/NinjaMultiConfig/CustomCommandGenerator.cmake b/Tests/RunCMake/NinjaMultiConfig/CustomCommandGenerator.cmake new file mode 100644 index 0000000..f4aca5e --- /dev/null +++ b/Tests/RunCMake/NinjaMultiConfig/CustomCommandGenerator.cmake @@ -0,0 +1,56 @@ +enable_language(C) + +add_library(generatorlib STATIC generatorlib.c) +add_library(generatorobj OBJECT generatorobj.c) +add_library(emptyobj OBJECT empty.c) +add_library(emptyobj2 OBJECT empty.c) + +add_executable(generator generator.c $<TARGET_OBJECTS:generatorobj>) +target_link_libraries(generator PRIVATE generatorlib) + +add_custom_command(OUTPUT generated.c COMMAND generator generated.c) +add_executable(generated ${CMAKE_BINARY_DIR}/generated.c $<TARGET_OBJECTS:generatorobj> $<TARGET_OBJECTS:emptyobj>) +target_link_libraries(generated PRIVATE generatorlib) + +file(GENERATE OUTPUT include/genex/$<CONFIG>/genex_config.h CONTENT +"#ifndef GENEX_CONFIG_H +#define GENEX_CONFIG_H + +#define GENEX_CONFIG_INCLUDE_DIR \"$<CONFIG>\" + +#endif /* GENEX_CONFIG_H */ +") +file(GENERATE OUTPUT include/intdir/$<CONFIG>/intdir_config.h CONTENT +"#ifndef INTDIR_CONFIG_H +#define INTDIR_CONFIG_H + +#define INTDIR_CONFIG_INCLUDE_DIR \"$<CONFIG>\" + +#endif /* INTDIR_CONFIG_H */ +") + +foreach(g generatorlib generatorobj generator generated) + target_compile_definitions(${g} PRIVATE + "GENEX_CONFIG_DEFINITION=\"$<CONFIG>\"" + # FIXME Get this working + # "INTDIR_CONFIG_DEFINITION=\"${CMAKE_CFG_INTDIR}\"" + ) + target_include_directories(${g} PRIVATE + "${CMAKE_BINARY_DIR}/include/genex/$<CONFIG>" + # FIXME Get this working + # "${CMAKE_BINARY_DIR}/include/intdir/${CMAKE_CFG_INTDIR}" + ) +endforeach() + +include(${CMAKE_CURRENT_LIST_DIR}/Common.cmake) +generate_output_files(generatorlib generatorobj emptyobj generator generated) + +file(APPEND "${CMAKE_BINARY_DIR}/target_files.cmake" "set(GENERATED_FILES [==[${CMAKE_BINARY_DIR}/generated.c]==])\n") +set(genfiles) +foreach(cfg Debug Release MinSizeRel RelWithDebInfo) + list(APPEND genfiles + ${CMAKE_BINARY_DIR}/include/genex/${cfg}/genex_config.h + ${CMAKE_BINARY_DIR}/include/intdir/${cfg}/intdir_config.h + ) +endforeach() +file(APPEND "${CMAKE_BINARY_DIR}/target_files.cmake" "set(CONFIG_FILES [==[${genfiles}]==])\n") diff --git a/Tests/RunCMake/NinjaMultiConfig/CustomCommandsAndTargets-debug-command-ninja-check.cmake b/Tests/RunCMake/NinjaMultiConfig/CustomCommandsAndTargets-debug-command-ninja-check.cmake new file mode 100644 index 0000000..f5c4020 --- /dev/null +++ b/Tests/RunCMake/NinjaMultiConfig/CustomCommandsAndTargets-debug-command-ninja-check.cmake @@ -0,0 +1,6 @@ +check_files("${RunCMake_TEST_BINARY_DIR}" + INCLUDE + ${TARGET_DEPENDS_SubdirCommand} + ${TARGET_DEPENDS_TopCommand} + ) +check_file_contents("${TARGET_DEPENDS_TopCommand}" "^Genex config: Debug\nINTDIR config: Debug\n$") diff --git a/Tests/RunCMake/NinjaMultiConfig/CustomCommandsAndTargets-debug-in-release-graph-postbuild-build-check.cmake b/Tests/RunCMake/NinjaMultiConfig/CustomCommandsAndTargets-debug-in-release-graph-postbuild-build-check.cmake new file mode 100644 index 0000000..05861b2 --- /dev/null +++ b/Tests/RunCMake/NinjaMultiConfig/CustomCommandsAndTargets-debug-in-release-graph-postbuild-build-check.cmake @@ -0,0 +1,8 @@ +check_files("${RunCMake_TEST_BINARY_DIR}" + INCLUDE + ${TARGET_DEPENDS_SubdirCommand} + ${TARGET_DEPENDS_TopCommand} + ${TARGET_BYPRODUCTS_SubdirTarget} + ${TARGET_BYPRODUCTS_TopTarget} + ${TARGET_FILE_SubdirPostBuild_Debug} + ) diff --git a/Tests/RunCMake/NinjaMultiConfig/CustomCommandsAndTargets-debug-target-build-check.cmake b/Tests/RunCMake/NinjaMultiConfig/CustomCommandsAndTargets-debug-target-build-check.cmake new file mode 100644 index 0000000..52895b2 --- /dev/null +++ b/Tests/RunCMake/NinjaMultiConfig/CustomCommandsAndTargets-debug-target-build-check.cmake @@ -0,0 +1,8 @@ +check_files("${RunCMake_TEST_BINARY_DIR}" + INCLUDE + ${TARGET_DEPENDS_SubdirCommand} + ${TARGET_DEPENDS_TopCommand} + ${TARGET_BYPRODUCTS_SubdirTarget} + ${TARGET_BYPRODUCTS_TopTarget} + ) +check_file_contents("${TARGET_BYPRODUCTS_TopTarget}" "^Genex config: Debug\nINTDIR config: Debug\n$") diff --git a/Tests/RunCMake/NinjaMultiConfig/CustomCommandsAndTargets-debug-targetpostbuild-build-check.cmake b/Tests/RunCMake/NinjaMultiConfig/CustomCommandsAndTargets-debug-targetpostbuild-build-check.cmake new file mode 100644 index 0000000..80439ea --- /dev/null +++ b/Tests/RunCMake/NinjaMultiConfig/CustomCommandsAndTargets-debug-targetpostbuild-build-check.cmake @@ -0,0 +1,12 @@ +check_files("${RunCMake_TEST_BINARY_DIR}" + INCLUDE + ${TARGET_DEPENDS_SubdirCommand} + ${TARGET_DEPENDS_TopCommand} + ${TARGET_BYPRODUCTS_SubdirTarget} + ${TARGET_BYPRODUCTS_TopTarget} + ${TARGET_FILE_SubdirPostBuild_Debug} + ${TARGET_FILE_SubdirPostBuild_Release} + ${TARGET_BYPRODUCTS_SubdirPostBuild} + ${TARGET_BYPRODUCTS_TopTargetPostBuild} + ) +check_file_contents("${TARGET_BYPRODUCTS_TopTargetPostBuild}" "^Genex config: Debug\nINTDIR config: Debug\n$") diff --git a/Tests/RunCMake/NinjaMultiConfig/CustomCommandsAndTargets-minsizerel-command-ninja-check.cmake b/Tests/RunCMake/NinjaMultiConfig/CustomCommandsAndTargets-minsizerel-command-ninja-check.cmake new file mode 100644 index 0000000..2813f02 --- /dev/null +++ b/Tests/RunCMake/NinjaMultiConfig/CustomCommandsAndTargets-minsizerel-command-ninja-check.cmake @@ -0,0 +1,5 @@ +check_files("${RunCMake_TEST_BINARY_DIR}" + INCLUDE + ${TARGET_DEPENDS_SubdirCommand} + ) +check_file_contents("${TARGET_DEPENDS_SubdirCommand}" "^Genex config: MinSizeRel\nINTDIR config: MinSizeRel\n$") diff --git a/Tests/RunCMake/NinjaMultiConfig/CustomCommandsAndTargets-release-command-build-check.cmake b/Tests/RunCMake/NinjaMultiConfig/CustomCommandsAndTargets-release-command-build-check.cmake new file mode 100644 index 0000000..2da9735 --- /dev/null +++ b/Tests/RunCMake/NinjaMultiConfig/CustomCommandsAndTargets-release-command-build-check.cmake @@ -0,0 +1,5 @@ +check_files("${RunCMake_TEST_BINARY_DIR}" + INCLUDE + ${TARGET_DEPENDS_SubdirCommand} + ) +check_file_contents("${TARGET_DEPENDS_SubdirCommand}" "^Genex config: Release\nINTDIR config: Release\n$") diff --git a/Tests/RunCMake/NinjaMultiConfig/CustomCommandsAndTargets-release-postbuild-ninja-check.cmake b/Tests/RunCMake/NinjaMultiConfig/CustomCommandsAndTargets-release-postbuild-ninja-check.cmake new file mode 100644 index 0000000..0916b90 --- /dev/null +++ b/Tests/RunCMake/NinjaMultiConfig/CustomCommandsAndTargets-release-postbuild-ninja-check.cmake @@ -0,0 +1,11 @@ +check_files("${RunCMake_TEST_BINARY_DIR}" + INCLUDE + ${TARGET_DEPENDS_SubdirCommand} + ${TARGET_DEPENDS_TopCommand} + ${TARGET_BYPRODUCTS_SubdirTarget} + ${TARGET_BYPRODUCTS_TopTarget} + ${TARGET_FILE_SubdirPostBuild_Debug} + ${TARGET_FILE_SubdirPostBuild_Release} + ${TARGET_BYPRODUCTS_SubdirPostBuild} + ) +check_file_contents("${TARGET_BYPRODUCTS_SubdirPostBuild}" "^Genex config: Release\nINTDIR config: Release\n$") diff --git a/Tests/RunCMake/NinjaMultiConfig/CustomCommandsAndTargets-release-target-ninja-check.cmake b/Tests/RunCMake/NinjaMultiConfig/CustomCommandsAndTargets-release-target-ninja-check.cmake new file mode 100644 index 0000000..87e78b4 --- /dev/null +++ b/Tests/RunCMake/NinjaMultiConfig/CustomCommandsAndTargets-release-target-ninja-check.cmake @@ -0,0 +1,7 @@ +check_files("${RunCMake_TEST_BINARY_DIR}" + INCLUDE + ${TARGET_DEPENDS_SubdirCommand} + ${TARGET_DEPENDS_TopCommand} + ${TARGET_BYPRODUCTS_SubdirTarget} + ) +check_file_contents("${TARGET_BYPRODUCTS_SubdirTarget}" "^Genex config: Release\nINTDIR config: Release\n$") diff --git a/Tests/RunCMake/NinjaMultiConfig/CustomCommandsAndTargets-release-targetpostbuild-ninja-check.cmake b/Tests/RunCMake/NinjaMultiConfig/CustomCommandsAndTargets-release-targetpostbuild-ninja-check.cmake new file mode 100644 index 0000000..f67d5be --- /dev/null +++ b/Tests/RunCMake/NinjaMultiConfig/CustomCommandsAndTargets-release-targetpostbuild-ninja-check.cmake @@ -0,0 +1,13 @@ +check_files("${RunCMake_TEST_BINARY_DIR}" + INCLUDE + ${TARGET_DEPENDS_SubdirCommand} + ${TARGET_DEPENDS_TopCommand} + ${TARGET_BYPRODUCTS_SubdirTarget} + ${TARGET_BYPRODUCTS_TopTarget} + ${TARGET_FILE_SubdirPostBuild_Debug} + ${TARGET_FILE_SubdirPostBuild_Release} + ${TARGET_BYPRODUCTS_SubdirPostBuild} + ${TARGET_BYPRODUCTS_TopTargetPostBuild} + ${TARGET_BYPRODUCTS_SubdirTargetPostBuild} + ) +check_file_contents("${TARGET_BYPRODUCTS_SubdirTargetPostBuild}" "^Genex config: Release\nINTDIR config: Release\n$") diff --git a/Tests/RunCMake/NinjaMultiConfig/CustomCommandsAndTargets.cmake b/Tests/RunCMake/NinjaMultiConfig/CustomCommandsAndTargets.cmake new file mode 100644 index 0000000..b2b24e8 --- /dev/null +++ b/Tests/RunCMake/NinjaMultiConfig/CustomCommandsAndTargets.cmake @@ -0,0 +1,39 @@ +enable_language(C) + +file(REMOVE "${CMAKE_BINARY_DIR}/target_files_custom.cmake") + +function(get_write_file_command var filename) + set(${var} ${CMAKE_COMMAND} -DOUTPUT_FILE=${filename} -DGENEX_CONFIG=$<CONFIG> -DINTDIR_CONFIG=${CMAKE_CFG_INTDIR} -P ${CMAKE_SOURCE_DIR}/WriteFile.cmake PARENT_SCOPE) +endfunction() + +function(create_targets prefix) + get_write_file_command(cmd ${prefix}Command.txt) + add_custom_command(OUTPUT ${prefix}Command.txt COMMAND ${cmd}) + add_custom_target(${prefix}Command DEPENDS ${prefix}Command.txt) + + get_write_file_command(cmd ${prefix}Target.txt) + add_custom_target(${prefix}Target COMMAND ${cmd} BYPRODUCTS ${prefix}Target.txt) + + get_write_file_command(cmd ${prefix}PostBuild.txt) + add_executable(${prefix}PostBuild ${CMAKE_SOURCE_DIR}/main.c) + add_custom_command(TARGET ${prefix}PostBuild COMMAND ${cmd} BYPRODUCTS ${prefix}PostBuild.txt) + + get_write_file_command(cmd ${prefix}TargetPostBuild.txt) + add_custom_target(${prefix}TargetPostBuild) + add_custom_command(TARGET ${prefix}TargetPostBuild COMMAND ${cmd} BYPRODUCTS ${prefix}TargetPostBuild.txt) + + file(APPEND "${CMAKE_BINARY_DIR}/target_files_custom.cmake" +"set(TARGET_DEPENDS_${prefix}Command [==[${CMAKE_CURRENT_BINARY_DIR}/${prefix}Command.txt]==]) +set(TARGET_BYPRODUCTS_${prefix}Target [==[${CMAKE_CURRENT_BINARY_DIR}/${prefix}Target.txt]==]) +set(TARGET_BYPRODUCTS_${prefix}PostBuild [==[${CMAKE_CURRENT_BINARY_DIR}/${prefix}PostBuild.txt]==]) +set(TARGET_BYPRODUCTS_${prefix}TargetPostBuild [==[${CMAKE_CURRENT_BINARY_DIR}/${prefix}TargetPostBuild.txt]==]) +") +endfunction() + +add_subdirectory(CustomCommandsAndTargetsSubdir) + +create_targets(Top) + +include(${CMAKE_CURRENT_LIST_DIR}/Common.cmake) +generate_output_files(TopPostBuild SubdirPostBuild) +file(APPEND "${CMAKE_BINARY_DIR}/target_files.cmake" "include(\${CMAKE_CURRENT_LIST_DIR}/target_files_custom.cmake)\n") diff --git a/Tests/RunCMake/NinjaMultiConfig/CustomCommandsAndTargetsSubdir/CMakeLists.txt b/Tests/RunCMake/NinjaMultiConfig/CustomCommandsAndTargetsSubdir/CMakeLists.txt new file mode 100644 index 0000000..894e3ed --- /dev/null +++ b/Tests/RunCMake/NinjaMultiConfig/CustomCommandsAndTargetsSubdir/CMakeLists.txt @@ -0,0 +1 @@ +create_targets(Subdir) diff --git a/Tests/RunCMake/NinjaMultiConfig/Install-debug-in-release-graph-install-ninja-check.cmake b/Tests/RunCMake/NinjaMultiConfig/Install-debug-in-release-graph-install-ninja-check.cmake new file mode 100644 index 0000000..bc15a25 --- /dev/null +++ b/Tests/RunCMake/NinjaMultiConfig/Install-debug-in-release-graph-install-ninja-check.cmake @@ -0,0 +1,31 @@ +check_files("${RunCMake_TEST_BINARY_DIR}" + INCLUDE + ${TARGET_FILE_exe_Debug} + ${TARGET_OBJECT_FILES_exe_Debug} + + ${TARGET_FILE_mylib_Release} + ${TARGET_LINKER_FILE_mylib_Debug} + ${TARGET_OBJECT_FILES_mylib_Debug} + + ${RunCMake_TEST_BINARY_DIR}/install/bin/Debug/${TARGET_FILE_NAME_exe_Debug} + ${RunCMake_TEST_BINARY_DIR}/install/lib/Debug/${TARGET_FILE_NAME_mylib_Debug} + ${RunCMake_TEST_BINARY_DIR}/install/lib/Debug/${TARGET_LINKER_FILE_NAME_mylib_Debug} + + ${TARGET_FILE_exe_Release} + ${TARGET_OBJECT_FILES_exe_Release} + + ${TARGET_FILE_mylib_Release} + ${TARGET_LINKER_FILE_mylib_Release} + ${TARGET_OBJECT_FILES_mylib_Release} + + ${RunCMake_TEST_BINARY_DIR}/install/bin/Release/${TARGET_FILE_NAME_exe_Release} + ${RunCMake_TEST_BINARY_DIR}/install/lib/Release/${TARGET_FILE_NAME_mylib_Release} + ${RunCMake_TEST_BINARY_DIR}/install/lib/Release/${TARGET_LINKER_FILE_NAME_mylib_Release} + + EXCLUDE + ${TARGET_OBJECT_FILES_exe_MinSizeRel} + ${TARGET_OBJECT_FILES_mylib_MinSizeRel} + + ${TARGET_OBJECT_FILES_exe_RelWithDebInfo} + ${TARGET_OBJECT_FILES_mylib_RelWithDebInfo} + ) diff --git a/Tests/RunCMake/NinjaMultiConfig/Install-release-install-build-check.cmake b/Tests/RunCMake/NinjaMultiConfig/Install-release-install-build-check.cmake new file mode 100644 index 0000000..3280c89 --- /dev/null +++ b/Tests/RunCMake/NinjaMultiConfig/Install-release-install-build-check.cmake @@ -0,0 +1,23 @@ +check_files("${RunCMake_TEST_BINARY_DIR}" + INCLUDE + ${TARGET_FILE_exe_Release} + ${TARGET_OBJECT_FILES_exe_Release} + + ${TARGET_FILE_mylib_Release} + ${TARGET_LINKER_FILE_mylib_Release} + ${TARGET_OBJECT_FILES_mylib_Release} + + ${RunCMake_TEST_BINARY_DIR}/install/bin/Release/${TARGET_FILE_NAME_exe_Release} + ${RunCMake_TEST_BINARY_DIR}/install/lib/Release/${TARGET_FILE_NAME_mylib_Release} + ${RunCMake_TEST_BINARY_DIR}/install/lib/Release/${TARGET_LINKER_FILE_NAME_mylib_Release} + + EXCLUDE + ${TARGET_OBJECT_FILES_exe_Debug} + ${TARGET_OBJECT_FILES_mylib_Debug} + + ${TARGET_OBJECT_FILES_exe_MinSizeRel} + ${TARGET_OBJECT_FILES_mylib_MinSizeRel} + + ${TARGET_OBJECT_FILES_exe_RelWithDebInfo} + ${TARGET_OBJECT_FILES_mylib_RelWithDebInfo} + ) diff --git a/Tests/RunCMake/NinjaMultiConfig/Install.cmake b/Tests/RunCMake/NinjaMultiConfig/Install.cmake new file mode 100644 index 0000000..e26e3e0 --- /dev/null +++ b/Tests/RunCMake/NinjaMultiConfig/Install.cmake @@ -0,0 +1,10 @@ +enable_language(C) + +add_executable(exe main.c) +add_library(mylib STATIC simplelib.c) + +install(TARGETS exe DESTINATION bin/$<CONFIG>) +install(TARGETS mylib DESTINATION lib/$<CONFIG>) + +include(${CMAKE_CURRENT_LIST_DIR}/Common.cmake) +generate_output_files(exe mylib) diff --git a/Tests/RunCMake/NinjaMultiConfig/PostfixAndLocation-debug-in-release-graph-build-check.cmake b/Tests/RunCMake/NinjaMultiConfig/PostfixAndLocation-debug-in-release-graph-build-check.cmake new file mode 100644 index 0000000..3657b5b --- /dev/null +++ b/Tests/RunCMake/NinjaMultiConfig/PostfixAndLocation-debug-in-release-graph-build-check.cmake @@ -0,0 +1,7 @@ +check_files("${RunCMake_TEST_BINARY_DIR}" + INCLUDE + ${TARGET_FILE_mylib_Release} + ${TARGET_LINKER_FILE_mylib_Release} + ${TARGET_FILE_mylib_Debug} + ${TARGET_LINKER_FILE_mylib_Debug} + ) diff --git a/Tests/RunCMake/NinjaMultiConfig/PostfixAndLocation-release-in-release-graph-build-check.cmake b/Tests/RunCMake/NinjaMultiConfig/PostfixAndLocation-release-in-release-graph-build-check.cmake new file mode 100644 index 0000000..3345ee8 --- /dev/null +++ b/Tests/RunCMake/NinjaMultiConfig/PostfixAndLocation-release-in-release-graph-build-check.cmake @@ -0,0 +1,5 @@ +check_files("${RunCMake_TEST_BINARY_DIR}" + INCLUDE + ${TARGET_FILE_mylib_Release} + ${TARGET_LINKER_FILE_mylib_Release} + ) diff --git a/Tests/RunCMake/NinjaMultiConfig/PostfixAndLocation.cmake b/Tests/RunCMake/NinjaMultiConfig/PostfixAndLocation.cmake new file mode 100644 index 0000000..abef3c8 --- /dev/null +++ b/Tests/RunCMake/NinjaMultiConfig/PostfixAndLocation.cmake @@ -0,0 +1,18 @@ +enable_language(C) + +set(CMAKE_DEBUG_POSTFIX "_debug") + +set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/lib) +set(CMAKE_LIBRARY_OUTPUT_DIRECTORY_DEBUG ${CMAKE_CURRENT_BINARY_DIR}/lib) +set(CMAKE_LIBRARY_OUTPUT_DIRECTORY_RELEASE ${CMAKE_CURRENT_BINARY_DIR}/lib) +set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/bin) +set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_DEBUG ${CMAKE_CURRENT_BINARY_DIR}/bin) +set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_RELEASE ${CMAKE_CURRENT_BINARY_DIR}/bin) +set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/lib) +set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY_DEBUG ${CMAKE_CURRENT_BINARY_DIR}/lib) +set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY_RELEASE ${CMAKE_CURRENT_BINARY_DIR}/lib) + +add_library(mylib SHARED simplelib.c) + +include(${CMAKE_CURRENT_LIST_DIR}/Common.cmake) +generate_output_files(mylib) diff --git a/Tests/RunCMake/NinjaMultiConfig/Qt5-debug-in-release-graph-build-check.cmake b/Tests/RunCMake/NinjaMultiConfig/Qt5-debug-in-release-graph-build-check.cmake new file mode 100644 index 0000000..2d8df13 --- /dev/null +++ b/Tests/RunCMake/NinjaMultiConfig/Qt5-debug-in-release-graph-build-check.cmake @@ -0,0 +1,7 @@ +check_files("${RunCMake_TEST_BINARY_DIR}" + INCLUDE + ${AUTOGEN_FILES} + + ${TARGET_FILE_exe_Debug} + ${TARGET_OBJECT_FILES_exe_Debug} + ) diff --git a/Tests/RunCMake/NinjaMultiConfig/Qt5.cmake b/Tests/RunCMake/NinjaMultiConfig/Qt5.cmake new file mode 100644 index 0000000..6a80b1d --- /dev/null +++ b/Tests/RunCMake/NinjaMultiConfig/Qt5.cmake @@ -0,0 +1,18 @@ +enable_language(CXX) + +find_package(Qt5Core REQUIRED) + +set(CMAKE_AUTOMOC ON) +set(CMAKE_AUTOMOC_COMPILER_PREDEFINES OFF) + +add_executable(exe qt5.cxx) +target_link_libraries(exe PRIVATE Qt5::Core) + +include(${CMAKE_CURRENT_LIST_DIR}/Common.cmake) +generate_output_files(exe) + +set(autogen_files "${CMAKE_BINARY_DIR}/exe_autogen/mocs_compilation.cpp") +foreach(c IN LISTS CMAKE_CONFIGURATION_TYPES) + list(APPEND autogen_files "${CMAKE_BINARY_DIR}/exe_autogen/include_${c}/moc_qt5.cpp") +endforeach() +file(APPEND "${CMAKE_BINARY_DIR}/target_files.cmake" "set(AUTOGEN_FILES [==[${autogen_files}]==])\n") diff --git a/Tests/RunCMake/NinjaMultiConfig/RunCMakeTest.cmake b/Tests/RunCMake/NinjaMultiConfig/RunCMakeTest.cmake new file mode 100644 index 0000000..4b51ddb --- /dev/null +++ b/Tests/RunCMake/NinjaMultiConfig/RunCMakeTest.cmake @@ -0,0 +1,173 @@ +cmake_minimum_required(VERSION 3.16) + +include(RunCMake) + +set(RunCMake_GENERATOR "Ninja Multi-Config") +set(RunCMake_GENERATOR_IS_MULTI_CONFIG 1) + +function(check_files dir) + cmake_parse_arguments(_check_files "" "" "INCLUDE;EXCLUDE" ${ARGN}) + + set(expected ${_check_files_INCLUDE}) + list(FILTER expected EXCLUDE REGEX "^$") + list(REMOVE_DUPLICATES expected) + list(SORT expected) + + file(GLOB_RECURSE actual "${dir}/*") + list(FILTER actual EXCLUDE REGEX "/CMakeFiles/|\\.ninja$|/CMakeCache\\.txt$|/target_files[^/]*\\.cmake$|/\\.ninja_[^/]*$|/cmake_install\\.cmake$|\\.ilk$|\\.manifest$|\\.pdb$|\\.exp$|/install_manifest\\.txt$") + foreach(f IN LISTS _check_files_INCLUDE _check_files_EXCLUDE) + if(EXISTS ${f}) + list(APPEND actual ${f}) + endif() + endforeach() + list(REMOVE_DUPLICATES actual) + list(SORT actual) + + if(NOT "${expected}" STREQUAL "${actual}") + string(REPLACE ";" "\n " expected_formatted "${expected}") + string(REPLACE ";" "\n " actual_formatted "${actual}") + string(APPEND RunCMake_TEST_FAILED "Actual files did not match expected\nExpected:\n ${expected_formatted}\nActual:\n ${actual_formatted}\n") + endif() + + set(RunCMake_TEST_FAILED "${RunCMake_TEST_FAILED}" PARENT_SCOPE) +endfunction() + +function(check_file_contents filename expected) + if(NOT EXISTS "${filename}") + string(APPEND RunCMake_TEST_FAILED "File ${filename} does not exist\n") + else() + file(READ "${filename}" actual) + if(NOT actual MATCHES "${expected}") + string(REPLACE "\n" "\n " expected_formatted "${expected}") + string(REPLACE "\n" "\n " actual_formatted "${actual}") + string(APPEND RunCMake_TEST_FAILED "Contents of ${filename} do not match expected\nExpected:\n ${expected_formatted}\nActual:\n ${actual_formatted}\n") + endif() + endif() + + set(RunCMake_TEST_FAILED "${RunCMake_TEST_FAILED}" PARENT_SCOPE) +endfunction() + +function(run_cmake_configure case) + set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/${case}-build) + set(RunCMake_TEST_NO_CLEAN 1) + file(REMOVE_RECURSE "${RunCMake_TEST_BINARY_DIR}") + file(MAKE_DIRECTORY "${RunCMake_TEST_BINARY_DIR}") + run_cmake(${case}) +endfunction() + +function(run_cmake_build case suffix config) + set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/${case}-build) + set(RunCMake_TEST_NO_CLEAN 1) + set(tgts) + foreach(tgt IN LISTS ARGN) + list(APPEND tgts --target ${tgt}) + endforeach() + run_cmake_command(${case}-${suffix}-build "${CMAKE_COMMAND}" --build . --config ${config} ${tgts}) +endfunction() + +function(run_ninja case suffix file) + set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/${case}-build) + set(RunCMake_TEST_NO_CLEAN 1) + run_cmake_command(${case}-${suffix}-ninja "${RunCMake_MAKE_PROGRAM}" -f "${file}" ${ARGN}) +endfunction() + +############################################################################### + +set(RunCMake_TEST_NO_CLEAN 1) + +set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/Simple-build) +set(RunCMake_TEST_OPTIONS "-DCMAKE_NINJA_MULTI_DEFAULT_BUILD_TYPE=RelWithDebInfo") +run_cmake_configure(Simple) +include(${RunCMake_TEST_BINARY_DIR}/target_files.cmake) +run_cmake_build(Simple debug-target Debug simpleexe) +run_ninja(Simple debug-target build-Debug.ninja simplestatic) +get_filename_component(simpleshared_Release "${TARGET_FILE_simpleshared_Release}" NAME) +run_cmake_build(Simple release-filename Release ${simpleshared_Release}) +file(RELATIVE_PATH simpleexe_Release "${RunCMake_TEST_BINARY_DIR}" "${TARGET_FILE_simpleexe_Release}") +run_ninja(Simple release-file build-Release.ninja ${simpleexe_Release}) +run_cmake_build(Simple all-configs Release simplestatic:all) +run_ninja(Simple default-build-file build.ninja simpleexe) +run_cmake_build(Simple all-clean Release clean:all) +run_cmake_build(Simple debug-subdir Debug SimpleSubdir/all) +run_ninja(Simple release-in-minsizerel-graph-subdir build-MinSizeRel.ninja SimpleSubdir/all:Release) +run_cmake_build(Simple all-subdir Release SimpleSubdir/all:all) +run_ninja(Simple minsizerel-top build-MinSizeRel.ninja all) +run_cmake_build(Simple debug-in-release-graph-top Release all:Debug) +run_ninja(Simple all-clean-again build-Debug.ninja clean:all) +run_ninja(Simple all-top build-RelWithDebInfo.ninja all:all) +# Leave enough time for the timestamp to change on second-resolution systems +execute_process(COMMAND ${CMAKE_COMMAND} -E sleep 1) +file(TOUCH "${RunCMake_TEST_BINARY_DIR}/empty.cmake") +run_ninja(Simple reconfigure-config build-Release.ninja simpleexe) +execute_process(COMMAND ${CMAKE_COMMAND} -E sleep 1) +file(TOUCH "${RunCMake_TEST_BINARY_DIR}/empty.cmake") +run_ninja(Simple reconfigure-noconfig build.ninja simpleexe) + +set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/CustomCommandGenerator-build) +run_cmake_configure(CustomCommandGenerator) +include(${RunCMake_TEST_BINARY_DIR}/target_files.cmake) +run_cmake_build(CustomCommandGenerator debug Debug generated) +run_cmake_command(CustomCommandGenerator-debug-generated "${TARGET_FILE_generated_Debug}") +run_ninja(CustomCommandGenerator release build-Release.ninja generated) +run_cmake_command(CustomCommandGenerator-release-generated "${TARGET_FILE_generated_Release}") +run_ninja(CustomCommandGenerator debug-clean build-Debug.ninja clean) +run_cmake_build(CustomCommandGenerator release-clean Release clean) +run_cmake_build(CustomCommandGenerator debug-in-release-graph Release generated:Debug) +run_cmake_command(CustomCommandGenerator-debug-in-release-graph-generated "${TARGET_FILE_generated_Debug}") +run_ninja(CustomCommandGenerator debug-in-release-graph-clean build-Debug.ninja clean:Debug) +run_ninja(CustomCommandGenerator release-in-debug-graph build-Debug.ninja generated:Release) +run_cmake_command(CustomCommandGenerator-release-in-debug-graph-generated "${TARGET_FILE_generated_Release}") + +set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/CustomCommandsAndTargets-build) +run_cmake_configure(CustomCommandsAndTargets) +include(${RunCMake_TEST_BINARY_DIR}/target_files.cmake) +run_cmake_build(CustomCommandsAndTargets release-command Release SubdirCommand) +#FIXME Get this working +#run_ninja(CustomCommandsAndTargets minsizerel-command build-MinSizeRel.ninja CustomCommandsAndTargetsSubdir/SubdirCommand) +run_ninja(CustomCommandsAndTargets debug-command build-Debug.ninja TopCommand) +run_ninja(CustomCommandsAndTargets release-target build-Release.ninja SubdirTarget) +run_cmake_build(CustomCommandsAndTargets debug-target Debug TopTarget) +run_cmake_build(CustomCommandsAndTargets debug-in-release-graph-postbuild Release SubdirPostBuild:Debug) +run_ninja(CustomCommandsAndTargets release-postbuild build-Release.ninja SubdirPostBuild) +run_cmake_build(CustomCommandsAndTargets debug-targetpostbuild Debug TopTargetPostBuild) +run_ninja(CustomCommandsAndTargets release-targetpostbuild build-Release.ninja SubdirTargetPostBuild) + +set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/PostfixAndLocation-build) +set(RunCMake_TEST_OPTIONS "-DCMAKE_CONFIGURATION_TYPES=Debug\\;Release") +run_cmake_configure(PostfixAndLocation) +set(RunCMake_TEST_OPTIONS) +include(${RunCMake_TEST_BINARY_DIR}/target_files.cmake) +run_cmake_build(PostfixAndLocation release-in-release-graph Release mylib:Release) +run_cmake_build(PostfixAndLocation debug-in-release-graph Release mylib:Debug) + +set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/Clean-build) +run_cmake_configure(Clean) +include(${RunCMake_TEST_BINARY_DIR}/target_files.cmake) +run_cmake_build(Clean release Release) +run_ninja(Clean release-notall build-Release.ninja exenotall) +run_cmake_build(Clean release-clean Release clean) + +set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/AdditionalCleanFiles-build) +run_cmake_configure(AdditionalCleanFiles) +run_cmake_build(AdditionalCleanFiles release-clean Release clean) +run_ninja(AdditionalCleanFiles all-clean build-Debug.ninja clean:all) + +set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/Install-build) +set(RunCMake_TEST_OPTIONS -DCMAKE_INSTALL_PREFIX=${RunCMake_TEST_BINARY_DIR}/install) +run_cmake_configure(Install) +set(RunCMake_TEST_OPTIONS) +include(${RunCMake_TEST_BINARY_DIR}/target_files.cmake) +run_cmake_build(Install release-install Release install) +run_ninja(Install debug-in-release-graph-install build-Release.ninja install:Debug) + +# FIXME Get this working +#set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/AutoMocExecutable-build) +#run_cmake_configure(AutoMocExecutable) +#run_cmake_build(AutoMocExecutable debug-in-release-graph Release exe) + +if(CMake_TEST_Qt5) + set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/Qt5-build) + run_cmake_configure(Qt5) + include(${RunCMake_TEST_BINARY_DIR}/target_files.cmake) + run_cmake_build(Qt5 debug-in-release-graph Release exe:Debug) +endif() diff --git a/Tests/RunCMake/NinjaMultiConfig/Simple-all-clean-again-ninja-check.cmake b/Tests/RunCMake/NinjaMultiConfig/Simple-all-clean-again-ninja-check.cmake new file mode 100644 index 0000000..0f919df --- /dev/null +++ b/Tests/RunCMake/NinjaMultiConfig/Simple-all-clean-again-ninja-check.cmake @@ -0,0 +1,25 @@ +check_files("${RunCMake_TEST_BINARY_DIR}" + INCLUDE + ${GENERATED_FILES} + + EXCLUDE + ${TARGET_OBJECT_FILES_simpleexe_Debug} + ${TARGET_OBJECT_FILES_simpleshared_Debug} + ${TARGET_OBJECT_FILES_simplestatic_Debug} + ${TARGET_OBJECT_FILES_simpleobj_Debug} + + ${TARGET_OBJECT_FILES_simpleexe_Release} + ${TARGET_OBJECT_FILES_simpleshared_Release} + ${TARGET_OBJECT_FILES_simplestatic_Release} + ${TARGET_OBJECT_FILES_simpleobj_Release} + + ${TARGET_OBJECT_FILES_simpleexe_MinSizeRel} + ${TARGET_OBJECT_FILES_simpleshared_MinSizeRel} + ${TARGET_OBJECT_FILES_simplestatic_MinSizeRel} + ${TARGET_OBJECT_FILES_simpleobj_MinSizeRel} + + ${TARGET_OBJECT_FILES_simpleexe_RelWithDebInfo} + ${TARGET_OBJECT_FILES_simpleshared_RelWithDebInfo} + ${TARGET_OBJECT_FILES_simplestatic_RelWithDebInfo} + ${TARGET_OBJECT_FILES_simpleobj_RelWithDebInfo} + ) diff --git a/Tests/RunCMake/NinjaMultiConfig/Simple-all-clean-build-check.cmake b/Tests/RunCMake/NinjaMultiConfig/Simple-all-clean-build-check.cmake new file mode 100644 index 0000000..0f919df --- /dev/null +++ b/Tests/RunCMake/NinjaMultiConfig/Simple-all-clean-build-check.cmake @@ -0,0 +1,25 @@ +check_files("${RunCMake_TEST_BINARY_DIR}" + INCLUDE + ${GENERATED_FILES} + + EXCLUDE + ${TARGET_OBJECT_FILES_simpleexe_Debug} + ${TARGET_OBJECT_FILES_simpleshared_Debug} + ${TARGET_OBJECT_FILES_simplestatic_Debug} + ${TARGET_OBJECT_FILES_simpleobj_Debug} + + ${TARGET_OBJECT_FILES_simpleexe_Release} + ${TARGET_OBJECT_FILES_simpleshared_Release} + ${TARGET_OBJECT_FILES_simplestatic_Release} + ${TARGET_OBJECT_FILES_simpleobj_Release} + + ${TARGET_OBJECT_FILES_simpleexe_MinSizeRel} + ${TARGET_OBJECT_FILES_simpleshared_MinSizeRel} + ${TARGET_OBJECT_FILES_simplestatic_MinSizeRel} + ${TARGET_OBJECT_FILES_simpleobj_MinSizeRel} + + ${TARGET_OBJECT_FILES_simpleexe_RelWithDebInfo} + ${TARGET_OBJECT_FILES_simpleshared_RelWithDebInfo} + ${TARGET_OBJECT_FILES_simplestatic_RelWithDebInfo} + ${TARGET_OBJECT_FILES_simpleobj_RelWithDebInfo} + ) diff --git a/Tests/RunCMake/NinjaMultiConfig/Simple-all-configs-build-check.cmake b/Tests/RunCMake/NinjaMultiConfig/Simple-all-configs-build-check.cmake new file mode 100644 index 0000000..170a0e8 --- /dev/null +++ b/Tests/RunCMake/NinjaMultiConfig/Simple-all-configs-build-check.cmake @@ -0,0 +1,47 @@ +check_files("${RunCMake_TEST_BINARY_DIR}" + INCLUDE + ${GENERATED_FILES} + + ${TARGET_FILE_simpleexe_Debug} + ${TARGET_OBJECT_FILES_simpleexe_Debug} + + ${TARGET_FILE_simpleshared_Debug} + ${TARGET_LINKER_FILE_simpleshared_Debug} + ${TARGET_OBJECT_FILES_simpleshared_Debug} + + ${TARGET_FILE_simplestatic_Debug} + ${TARGET_LINKER_FILE_simplestatic_Debug} + ${TARGET_OBJECT_FILES_simplestatic_Debug} + + ${TARGET_OBJECT_FILES_simpleobj_Debug} + + ${TARGET_FILE_simpleexe_Release} + ${TARGET_OBJECT_FILES_simpleexe_Release} + + ${TARGET_FILE_simpleshared_Release} + ${TARGET_LINKER_FILE_simpleshared_Release} + ${TARGET_OBJECT_FILES_simpleshared_Release} + + ${TARGET_FILE_simplestatic_Release} + ${TARGET_LINKER_FILE_simplestatic_Release} + ${TARGET_OBJECT_FILES_simplestatic_Release} + + ${TARGET_OBJECT_FILES_simpleobj_Release} + + ${TARGET_FILE_simplestatic_MinSizeRel} + ${TARGET_LINKER_FILE_simplestatic_MinSizeRel} + ${TARGET_OBJECT_FILES_simplestatic_MinSizeRel} + + ${TARGET_FILE_simplestatic_RelWithDebInfo} + ${TARGET_LINKER_FILE_simplestatic_RelWithDebInfo} + ${TARGET_OBJECT_FILES_simplestatic_RelWithDebInfo} + + EXCLUDE + ${TARGET_OBJECT_FILES_simpleexe_MinSizeRel} + ${TARGET_OBJECT_FILES_simpleshared_MinSizeRel} + ${TARGET_OBJECT_FILES_simpleobj_MinSizeRel} + + ${TARGET_OBJECT_FILES_simpleexe_RelWithDebInfo} + ${TARGET_OBJECT_FILES_simpleshared_RelWithDebInfo} + ${TARGET_OBJECT_FILES_simpleobj_RelWithDebInfo} + ) diff --git a/Tests/RunCMake/NinjaMultiConfig/Simple-all-subdir-build-check.cmake b/Tests/RunCMake/NinjaMultiConfig/Simple-all-subdir-build-check.cmake new file mode 100644 index 0000000..de4505c --- /dev/null +++ b/Tests/RunCMake/NinjaMultiConfig/Simple-all-subdir-build-check.cmake @@ -0,0 +1,49 @@ +check_files("${RunCMake_TEST_BINARY_DIR}" + INCLUDE + ${GENERATED_FILES} + + ${TARGET_FILE_simpleexe_Debug} + ${TARGET_OBJECT_FILES_simpleexe_Debug} + + ${TARGET_FILE_simpleshared_Debug} + ${TARGET_LINKER_FILE_simpleshared_Debug} + ${TARGET_OBJECT_FILES_simpleshared_Debug} + + ${TARGET_OBJECT_FILES_simpleobj_Debug} + + ${TARGET_FILE_simpleexe_Release} + ${TARGET_OBJECT_FILES_simpleexe_Release} + + ${TARGET_FILE_simpleshared_Release} + ${TARGET_LINKER_FILE_simpleshared_Release} + ${TARGET_OBJECT_FILES_simpleshared_Release} + + ${TARGET_OBJECT_FILES_simpleobj_Release} + + ${TARGET_FILE_simpleexe_MinSizeRel} + ${TARGET_OBJECT_FILES_simpleexe_MinSizeRel} + + ${TARGET_FILE_simpleshared_MinSizeRel} + ${TARGET_LINKER_FILE_simpleshared_MinSizeRel} + ${TARGET_OBJECT_FILES_simpleshared_MinSizeRel} + + ${TARGET_OBJECT_FILES_simpleobj_MinSizeRel} + + ${TARGET_FILE_simpleexe_RelWithDebInfo} + ${TARGET_OBJECT_FILES_simpleexe_RelWithDebInfo} + + ${TARGET_FILE_simpleshared_RelWithDebInfo} + ${TARGET_LINKER_FILE_simpleshared_RelWithDebInfo} + ${TARGET_OBJECT_FILES_simpleshared_RelWithDebInfo} + + ${TARGET_OBJECT_FILES_simpleobj_RelWithDebInfo} + + EXCLUDE + ${TARGET_OBJECT_FILES_simplestatic_Debug} + + ${TARGET_OBJECT_FILES_simplestatic_Release} + + ${TARGET_OBJECT_FILES_simplestatic_MinSizeRel} + + ${TARGET_OBJECT_FILES_simplestatic_RelWithDebInfo} + ) diff --git a/Tests/RunCMake/NinjaMultiConfig/Simple-all-top-ninja-check.cmake b/Tests/RunCMake/NinjaMultiConfig/Simple-all-top-ninja-check.cmake new file mode 100644 index 0000000..c171e3d --- /dev/null +++ b/Tests/RunCMake/NinjaMultiConfig/Simple-all-top-ninja-check.cmake @@ -0,0 +1,56 @@ +check_files("${RunCMake_TEST_BINARY_DIR}" + INCLUDE + ${GENERATED_FILES} + + ${TARGET_FILE_simpleexe_Debug} + ${TARGET_OBJECT_FILES_simpleexe_Debug} + + ${TARGET_FILE_simpleshared_Debug} + ${TARGET_LINKER_FILE_simpleshared_Debug} + ${TARGET_OBJECT_FILES_simpleshared_Debug} + + ${TARGET_FILE_simplestatic_Debug} + ${TARGET_LINKER_FILE_simplestatic_Debug} + ${TARGET_OBJECT_FILES_simplestatic_Debug} + + ${TARGET_OBJECT_FILES_simpleobj_Debug} + + ${TARGET_FILE_simpleexe_Release} + ${TARGET_OBJECT_FILES_simpleexe_Release} + + ${TARGET_FILE_simpleshared_Release} + ${TARGET_LINKER_FILE_simpleshared_Release} + ${TARGET_OBJECT_FILES_simpleshared_Release} + + ${TARGET_FILE_simplestatic_Release} + ${TARGET_LINKER_FILE_simplestatic_Release} + ${TARGET_OBJECT_FILES_simplestatic_Release} + + ${TARGET_OBJECT_FILES_simpleobj_Release} + + ${TARGET_FILE_simpleexe_MinSizeRel} + ${TARGET_OBJECT_FILES_simpleexe_MinSizeRel} + + ${TARGET_FILE_simpleshared_MinSizeRel} + ${TARGET_LINKER_FILE_simpleshared_MinSizeRel} + ${TARGET_OBJECT_FILES_simpleshared_MinSizeRel} + + ${TARGET_FILE_simplestatic_MinSizeRel} + ${TARGET_LINKER_FILE_simplestatic_MinSizeRel} + ${TARGET_OBJECT_FILES_simplestatic_MinSizeRel} + + ${TARGET_OBJECT_FILES_simpleobj_MinSizeRel} + + ${TARGET_FILE_simpleexe_RelWithDebInfo} + ${TARGET_OBJECT_FILES_simpleexe_RelWithDebInfo} + + ${TARGET_FILE_simpleshared_RelWithDebInfo} + ${TARGET_LINKER_FILE_simpleshared_RelWithDebInfo} + ${TARGET_OBJECT_FILES_simpleshared_RelWithDebInfo} + + ${TARGET_FILE_simplestatic_RelWithDebInfo} + ${TARGET_LINKER_FILE_simplestatic_RelWithDebInfo} + ${TARGET_OBJECT_FILES_simplestatic_RelWithDebInfo} + + ${TARGET_OBJECT_FILES_simpleobj_RelWithDebInfo} + ) diff --git a/Tests/RunCMake/NinjaMultiConfig/Simple-debug-in-release-graph-top-build-check.cmake b/Tests/RunCMake/NinjaMultiConfig/Simple-debug-in-release-graph-top-build-check.cmake new file mode 100644 index 0000000..fe980fe --- /dev/null +++ b/Tests/RunCMake/NinjaMultiConfig/Simple-debug-in-release-graph-top-build-check.cmake @@ -0,0 +1,53 @@ +check_files("${RunCMake_TEST_BINARY_DIR}" + INCLUDE + ${GENERATED_FILES} + + ${TARGET_FILE_simpleexe_Debug} + ${TARGET_OBJECT_FILES_simpleexe_Debug} + + ${TARGET_FILE_simpleshared_Debug} + ${TARGET_LINKER_FILE_simpleshared_Debug} + ${TARGET_OBJECT_FILES_simpleshared_Debug} + + ${TARGET_FILE_simplestatic_Debug} + ${TARGET_LINKER_FILE_simplestatic_Debug} + ${TARGET_OBJECT_FILES_simplestatic_Debug} + + ${TARGET_OBJECT_FILES_simpleobj_Debug} + + ${TARGET_FILE_simpleexe_Release} + ${TARGET_OBJECT_FILES_simpleexe_Release} + + ${TARGET_FILE_simpleshared_Release} + ${TARGET_LINKER_FILE_simpleshared_Release} + ${TARGET_OBJECT_FILES_simpleshared_Release} + + ${TARGET_OBJECT_FILES_simpleobj_Release} + + ${TARGET_FILE_simpleexe_MinSizeRel} + ${TARGET_OBJECT_FILES_simpleexe_MinSizeRel} + + ${TARGET_FILE_simpleshared_MinSizeRel} + ${TARGET_LINKER_FILE_simpleshared_MinSizeRel} + ${TARGET_OBJECT_FILES_simpleshared_MinSizeRel} + + ${TARGET_FILE_simplestatic_MinSizeRel} + ${TARGET_LINKER_FILE_simplestatic_MinSizeRel} + ${TARGET_OBJECT_FILES_simplestatic_MinSizeRel} + + ${TARGET_OBJECT_FILES_simpleobj_MinSizeRel} + + ${TARGET_FILE_simpleexe_RelWithDebInfo} + ${TARGET_OBJECT_FILES_simpleexe_RelWithDebInfo} + + ${TARGET_FILE_simpleshared_RelWithDebInfo} + ${TARGET_LINKER_FILE_simpleshared_RelWithDebInfo} + ${TARGET_OBJECT_FILES_simpleshared_RelWithDebInfo} + + ${TARGET_OBJECT_FILES_simpleobj_RelWithDebInfo} + + EXCLUDE + ${TARGET_OBJECT_FILES_simplestatic_Release} + + ${TARGET_OBJECT_FILES_simplestatic_RelWithDebInfo} + ) diff --git a/Tests/RunCMake/NinjaMultiConfig/Simple-debug-subdir-build-check.cmake b/Tests/RunCMake/NinjaMultiConfig/Simple-debug-subdir-build-check.cmake new file mode 100644 index 0000000..6bb7773 --- /dev/null +++ b/Tests/RunCMake/NinjaMultiConfig/Simple-debug-subdir-build-check.cmake @@ -0,0 +1,31 @@ +check_files("${RunCMake_TEST_BINARY_DIR}" + INCLUDE + ${GENERATED_FILES} + + ${TARGET_FILE_simpleexe_Debug} + ${TARGET_OBJECT_FILES_simpleexe_Debug} + + ${TARGET_FILE_simpleshared_Debug} + ${TARGET_LINKER_FILE_simpleshared_Debug} + ${TARGET_OBJECT_FILES_simpleshared_Debug} + + ${TARGET_OBJECT_FILES_simpleobj_Debug} + + EXCLUDE + ${TARGET_OBJECT_FILES_simplestatic_Debug} + + ${TARGET_OBJECT_FILES_simpleexe_Release} + ${TARGET_OBJECT_FILES_simpleshared_Release} + ${TARGET_OBJECT_FILES_simplestatic_Release} + ${TARGET_OBJECT_FILES_simpleobj_Release} + + ${TARGET_OBJECT_FILES_simpleexe_MinSizeRel} + ${TARGET_OBJECT_FILES_simpleshared_MinSizeRel} + ${TARGET_OBJECT_FILES_simplestatic_MinSizeRel} + ${TARGET_OBJECT_FILES_simpleobj_MinSizeRel} + + ${TARGET_OBJECT_FILES_simpleexe_RelWithDebInfo} + ${TARGET_OBJECT_FILES_simpleshared_RelWithDebInfo} + ${TARGET_OBJECT_FILES_simplestatic_RelWithDebInfo} + ${TARGET_OBJECT_FILES_simpleobj_RelWithDebInfo} + ) diff --git a/Tests/RunCMake/NinjaMultiConfig/Simple-debug-target-build-check.cmake b/Tests/RunCMake/NinjaMultiConfig/Simple-debug-target-build-check.cmake new file mode 100644 index 0000000..6bb7773 --- /dev/null +++ b/Tests/RunCMake/NinjaMultiConfig/Simple-debug-target-build-check.cmake @@ -0,0 +1,31 @@ +check_files("${RunCMake_TEST_BINARY_DIR}" + INCLUDE + ${GENERATED_FILES} + + ${TARGET_FILE_simpleexe_Debug} + ${TARGET_OBJECT_FILES_simpleexe_Debug} + + ${TARGET_FILE_simpleshared_Debug} + ${TARGET_LINKER_FILE_simpleshared_Debug} + ${TARGET_OBJECT_FILES_simpleshared_Debug} + + ${TARGET_OBJECT_FILES_simpleobj_Debug} + + EXCLUDE + ${TARGET_OBJECT_FILES_simplestatic_Debug} + + ${TARGET_OBJECT_FILES_simpleexe_Release} + ${TARGET_OBJECT_FILES_simpleshared_Release} + ${TARGET_OBJECT_FILES_simplestatic_Release} + ${TARGET_OBJECT_FILES_simpleobj_Release} + + ${TARGET_OBJECT_FILES_simpleexe_MinSizeRel} + ${TARGET_OBJECT_FILES_simpleshared_MinSizeRel} + ${TARGET_OBJECT_FILES_simplestatic_MinSizeRel} + ${TARGET_OBJECT_FILES_simpleobj_MinSizeRel} + + ${TARGET_OBJECT_FILES_simpleexe_RelWithDebInfo} + ${TARGET_OBJECT_FILES_simpleshared_RelWithDebInfo} + ${TARGET_OBJECT_FILES_simplestatic_RelWithDebInfo} + ${TARGET_OBJECT_FILES_simpleobj_RelWithDebInfo} + ) diff --git a/Tests/RunCMake/NinjaMultiConfig/Simple-debug-target-ninja-check.cmake b/Tests/RunCMake/NinjaMultiConfig/Simple-debug-target-ninja-check.cmake new file mode 100644 index 0000000..f9c1e92 --- /dev/null +++ b/Tests/RunCMake/NinjaMultiConfig/Simple-debug-target-ninja-check.cmake @@ -0,0 +1,33 @@ +check_files("${RunCMake_TEST_BINARY_DIR}" + INCLUDE + ${GENERATED_FILES} + + ${TARGET_FILE_simpleexe_Debug} + ${TARGET_OBJECT_FILES_simpleexe_Debug} + + ${TARGET_FILE_simpleshared_Debug} + ${TARGET_LINKER_FILE_simpleshared_Debug} + ${TARGET_OBJECT_FILES_simpleshared_Debug} + + ${TARGET_FILE_simplestatic_Debug} + ${TARGET_LINKER_FILE_simplestatic_Debug} + ${TARGET_OBJECT_FILES_simplestatic_Debug} + + ${TARGET_OBJECT_FILES_simpleobj_Debug} + + EXCLUDE + ${TARGET_OBJECT_FILES_simpleexe_Release} + ${TARGET_OBJECT_FILES_simpleshared_Release} + ${TARGET_OBJECT_FILES_simplestatic_Release} + ${TARGET_OBJECT_FILES_simpleobj_Release} + + ${TARGET_OBJECT_FILES_simpleexe_MinSizeRel} + ${TARGET_OBJECT_FILES_simpleshared_MinSizeRel} + ${TARGET_OBJECT_FILES_simplestatic_MinSizeRel} + ${TARGET_OBJECT_FILES_simpleobj_MinSizeRel} + + ${TARGET_OBJECT_FILES_simpleexe_RelWithDebInfo} + ${TARGET_OBJECT_FILES_simpleshared_RelWithDebInfo} + ${TARGET_OBJECT_FILES_simplestatic_RelWithDebInfo} + ${TARGET_OBJECT_FILES_simpleobj_RelWithDebInfo} + ) diff --git a/Tests/RunCMake/NinjaMultiConfig/Simple-default-build-file-ninja-check.cmake b/Tests/RunCMake/NinjaMultiConfig/Simple-default-build-file-ninja-check.cmake new file mode 100644 index 0000000..dae1f4d --- /dev/null +++ b/Tests/RunCMake/NinjaMultiConfig/Simple-default-build-file-ninja-check.cmake @@ -0,0 +1,51 @@ +check_files("${RunCMake_TEST_BINARY_DIR}" + INCLUDE + ${GENERATED_FILES} + + ${TARGET_FILE_simpleexe_Debug} + ${TARGET_OBJECT_FILES_simpleexe_Debug} + + ${TARGET_FILE_simpleshared_Debug} + ${TARGET_LINKER_FILE_simpleshared_Debug} + ${TARGET_OBJECT_FILES_simpleshared_Debug} + + ${TARGET_FILE_simplestatic_Debug} + ${TARGET_LINKER_FILE_simplestatic_Debug} + ${TARGET_OBJECT_FILES_simplestatic_Debug} + + ${TARGET_OBJECT_FILES_simpleobj_Debug} + + ${TARGET_FILE_simpleexe_Release} + ${TARGET_OBJECT_FILES_simpleexe_Release} + + ${TARGET_FILE_simpleshared_Release} + ${TARGET_LINKER_FILE_simpleshared_Release} + ${TARGET_OBJECT_FILES_simpleshared_Release} + + ${TARGET_FILE_simplestatic_Release} + ${TARGET_LINKER_FILE_simplestatic_Release} + ${TARGET_OBJECT_FILES_simplestatic_Release} + + ${TARGET_OBJECT_FILES_simpleobj_Release} + + ${TARGET_FILE_simplestatic_MinSizeRel} + ${TARGET_LINKER_FILE_simplestatic_MinSizeRel} + ${TARGET_OBJECT_FILES_simplestatic_MinSizeRel} + + ${TARGET_FILE_simpleexe_RelWithDebInfo} + ${TARGET_OBJECT_FILES_simpleexe_RelWithDebInfo} + + ${TARGET_FILE_simpleshared_RelWithDebInfo} + ${TARGET_LINKER_FILE_simpleshared_RelWithDebInfo} + ${TARGET_OBJECT_FILES_simpleshared_RelWithDebInfo} + + ${TARGET_FILE_simplestatic_RelWithDebInfo} + ${TARGET_LINKER_FILE_simplestatic_RelWithDebInfo} + ${TARGET_OBJECT_FILES_simplestatic_RelWithDebInfo} + + ${TARGET_OBJECT_FILES_simpleobj_RelWithDebInfo} + + EXCLUDE + ${TARGET_OBJECT_FILES_simpleexe_MinSizeRel} + ${TARGET_OBJECT_FILES_simpleshared_MinSizeRel} + ) diff --git a/Tests/RunCMake/NinjaMultiConfig/Simple-minsizerel-top-ninja-check.cmake b/Tests/RunCMake/NinjaMultiConfig/Simple-minsizerel-top-ninja-check.cmake new file mode 100644 index 0000000..bf4be49 --- /dev/null +++ b/Tests/RunCMake/NinjaMultiConfig/Simple-minsizerel-top-ninja-check.cmake @@ -0,0 +1,51 @@ +check_files("${RunCMake_TEST_BINARY_DIR}" + INCLUDE + ${GENERATED_FILES} + + ${TARGET_FILE_simpleexe_Debug} + ${TARGET_OBJECT_FILES_simpleexe_Debug} + + ${TARGET_FILE_simpleshared_Debug} + ${TARGET_LINKER_FILE_simpleshared_Debug} + ${TARGET_OBJECT_FILES_simpleshared_Debug} + + ${TARGET_OBJECT_FILES_simpleobj_Debug} + + ${TARGET_FILE_simpleexe_Release} + ${TARGET_OBJECT_FILES_simpleexe_Release} + + ${TARGET_FILE_simpleshared_Release} + ${TARGET_LINKER_FILE_simpleshared_Release} + ${TARGET_OBJECT_FILES_simpleshared_Release} + + ${TARGET_OBJECT_FILES_simpleobj_Release} + + ${TARGET_FILE_simpleexe_MinSizeRel} + ${TARGET_OBJECT_FILES_simpleexe_MinSizeRel} + + ${TARGET_FILE_simpleshared_MinSizeRel} + ${TARGET_LINKER_FILE_simpleshared_MinSizeRel} + ${TARGET_OBJECT_FILES_simpleshared_MinSizeRel} + + ${TARGET_FILE_simplestatic_MinSizeRel} + ${TARGET_LINKER_FILE_simplestatic_MinSizeRel} + ${TARGET_OBJECT_FILES_simplestatic_MinSizeRel} + + ${TARGET_OBJECT_FILES_simpleobj_MinSizeRel} + + ${TARGET_FILE_simpleexe_RelWithDebInfo} + ${TARGET_OBJECT_FILES_simpleexe_RelWithDebInfo} + + ${TARGET_FILE_simpleshared_RelWithDebInfo} + ${TARGET_LINKER_FILE_simpleshared_RelWithDebInfo} + ${TARGET_OBJECT_FILES_simpleshared_RelWithDebInfo} + + ${TARGET_OBJECT_FILES_simpleobj_RelWithDebInfo} + + EXCLUDE + ${TARGET_OBJECT_FILES_simplestatic_Debug} + + ${TARGET_OBJECT_FILES_simplestatic_Release} + + ${TARGET_OBJECT_FILES_simplestatic_RelWithDebInfo} + ) diff --git a/Tests/RunCMake/NinjaMultiConfig/Simple-reconfigure-config-ninja-stdout.txt b/Tests/RunCMake/NinjaMultiConfig/Simple-reconfigure-config-ninja-stdout.txt new file mode 100644 index 0000000..8877451 --- /dev/null +++ b/Tests/RunCMake/NinjaMultiConfig/Simple-reconfigure-config-ninja-stdout.txt @@ -0,0 +1,4 @@ +-- Configuring done +-- Generating done +-- Build files have been written to: [^ +]*/Tests/RunCMake/NinjaMultiConfig/Simple-build diff --git a/Tests/RunCMake/NinjaMultiConfig/Simple-reconfigure-noconfig-ninja-stdout.txt b/Tests/RunCMake/NinjaMultiConfig/Simple-reconfigure-noconfig-ninja-stdout.txt new file mode 100644 index 0000000..8877451 --- /dev/null +++ b/Tests/RunCMake/NinjaMultiConfig/Simple-reconfigure-noconfig-ninja-stdout.txt @@ -0,0 +1,4 @@ +-- Configuring done +-- Generating done +-- Build files have been written to: [^ +]*/Tests/RunCMake/NinjaMultiConfig/Simple-build diff --git a/Tests/RunCMake/NinjaMultiConfig/Simple-release-file-ninja-check.cmake b/Tests/RunCMake/NinjaMultiConfig/Simple-release-file-ninja-check.cmake new file mode 100644 index 0000000..6e63aae --- /dev/null +++ b/Tests/RunCMake/NinjaMultiConfig/Simple-release-file-ninja-check.cmake @@ -0,0 +1,39 @@ +check_files("${RunCMake_TEST_BINARY_DIR}" + INCLUDE + ${GENERATED_FILES} + + ${TARGET_FILE_simpleexe_Debug} + ${TARGET_OBJECT_FILES_simpleexe_Debug} + + ${TARGET_FILE_simpleshared_Debug} + ${TARGET_LINKER_FILE_simpleshared_Debug} + ${TARGET_OBJECT_FILES_simpleshared_Debug} + + ${TARGET_FILE_simplestatic_Debug} + ${TARGET_LINKER_FILE_simplestatic_Debug} + ${TARGET_OBJECT_FILES_simplestatic_Debug} + + ${TARGET_OBJECT_FILES_simpleobj_Debug} + + ${TARGET_FILE_simpleexe_Release} + ${TARGET_OBJECT_FILES_simpleexe_Release} + + ${TARGET_FILE_simpleshared_Release} + ${TARGET_LINKER_FILE_simpleshared_Release} + ${TARGET_OBJECT_FILES_simpleshared_Release} + + ${TARGET_OBJECT_FILES_simpleobj_Release} + + EXCLUDE + ${TARGET_OBJECT_FILES_simplestatic_Release} + + ${TARGET_OBJECT_FILES_simpleexe_MinSizeRel} + ${TARGET_OBJECT_FILES_simpleshared_MinSizeRel} + ${TARGET_OBJECT_FILES_simplestatic_MinSizeRel} + ${TARGET_OBJECT_FILES_simpleobj_MinSizeRel} + + ${TARGET_OBJECT_FILES_simpleexe_RelWithDebInfo} + ${TARGET_OBJECT_FILES_simpleshared_RelWithDebInfo} + ${TARGET_OBJECT_FILES_simplestatic_RelWithDebInfo} + ${TARGET_OBJECT_FILES_simpleobj_RelWithDebInfo} + ) diff --git a/Tests/RunCMake/NinjaMultiConfig/Simple-release-filename-build-check.cmake b/Tests/RunCMake/NinjaMultiConfig/Simple-release-filename-build-check.cmake new file mode 100644 index 0000000..a9bf42c --- /dev/null +++ b/Tests/RunCMake/NinjaMultiConfig/Simple-release-filename-build-check.cmake @@ -0,0 +1,36 @@ +check_files("${RunCMake_TEST_BINARY_DIR}" + INCLUDE + ${GENERATED_FILES} + + ${TARGET_FILE_simpleexe_Debug} + ${TARGET_OBJECT_FILES_simpleexe_Debug} + + ${TARGET_FILE_simpleshared_Debug} + ${TARGET_LINKER_FILE_simpleshared_Debug} + ${TARGET_OBJECT_FILES_simpleshared_Debug} + + ${TARGET_FILE_simplestatic_Debug} + ${TARGET_LINKER_FILE_simplestatic_Debug} + ${TARGET_OBJECT_FILES_simplestatic_Debug} + + ${TARGET_OBJECT_FILES_simpleobj_Debug} + + ${TARGET_FILE_simpleshared_Release} + ${TARGET_LINKER_FILE_simpleshared_Release} + ${TARGET_OBJECT_FILES_simpleshared_Release} + + EXCLUDE + ${TARGET_OBJECT_FILES_simpleexe_Release} + ${TARGET_OBJECT_FILES_simplestatic_Release} + ${TARGET_OBJECT_FILES_simpleobj_Release} + + ${TARGET_OBJECT_FILES_simpleexe_MinSizeRel} + ${TARGET_OBJECT_FILES_simpleshared_MinSizeRel} + ${TARGET_OBJECT_FILES_simplestatic_MinSizeRel} + ${TARGET_OBJECT_FILES_simpleobj_MinSizeRel} + + ${TARGET_OBJECT_FILES_simpleexe_RelWithDebInfo} + ${TARGET_OBJECT_FILES_simpleshared_RelWithDebInfo} + ${TARGET_OBJECT_FILES_simplestatic_RelWithDebInfo} + ${TARGET_OBJECT_FILES_simpleobj_RelWithDebInfo} + ) diff --git a/Tests/RunCMake/NinjaMultiConfig/Simple-release-in-minsizerel-graph-subdir-ninja-check.cmake b/Tests/RunCMake/NinjaMultiConfig/Simple-release-in-minsizerel-graph-subdir-ninja-check.cmake new file mode 100644 index 0000000..b6c77ab --- /dev/null +++ b/Tests/RunCMake/NinjaMultiConfig/Simple-release-in-minsizerel-graph-subdir-ninja-check.cmake @@ -0,0 +1,37 @@ +check_files("${RunCMake_TEST_BINARY_DIR}" + INCLUDE + ${GENERATED_FILES} + + ${TARGET_FILE_simpleexe_Debug} + ${TARGET_OBJECT_FILES_simpleexe_Debug} + + ${TARGET_FILE_simpleshared_Debug} + ${TARGET_LINKER_FILE_simpleshared_Debug} + ${TARGET_OBJECT_FILES_simpleshared_Debug} + + ${TARGET_OBJECT_FILES_simpleobj_Debug} + + ${TARGET_FILE_simpleexe_Release} + ${TARGET_OBJECT_FILES_simpleexe_Release} + + ${TARGET_FILE_simpleshared_Release} + ${TARGET_LINKER_FILE_simpleshared_Release} + ${TARGET_OBJECT_FILES_simpleshared_Release} + + ${TARGET_OBJECT_FILES_simpleobj_Release} + + EXCLUDE + ${TARGET_OBJECT_FILES_simplestatic_Debug} + + ${TARGET_OBJECT_FILES_simplestatic_Release} + + ${TARGET_OBJECT_FILES_simpleexe_MinSizeRel} + ${TARGET_OBJECT_FILES_simpleshared_MinSizeRel} + ${TARGET_OBJECT_FILES_simplestatic_MinSizeRel} + ${TARGET_OBJECT_FILES_simpleobj_MinSizeRel} + + ${TARGET_OBJECT_FILES_simpleexe_RelWithDebInfo} + ${TARGET_OBJECT_FILES_simpleshared_RelWithDebInfo} + ${TARGET_OBJECT_FILES_simplestatic_RelWithDebInfo} + ${TARGET_OBJECT_FILES_simpleobj_RelWithDebInfo} + ) diff --git a/Tests/RunCMake/NinjaMultiConfig/Simple.cmake b/Tests/RunCMake/NinjaMultiConfig/Simple.cmake new file mode 100644 index 0000000..a32f551 --- /dev/null +++ b/Tests/RunCMake/NinjaMultiConfig/Simple.cmake @@ -0,0 +1,13 @@ +enable_language(C) + +file(TOUCH ${CMAKE_BINARY_DIR}/empty.cmake) +include(${CMAKE_BINARY_DIR}/empty.cmake) + +add_subdirectory(SimpleSubdir) + +add_library(simplestatic STATIC simplelib.c) + +include(${CMAKE_CURRENT_LIST_DIR}/Common.cmake) +generate_output_files(simpleexe simpleshared simplestatic simpleobj) + +file(APPEND "${CMAKE_BINARY_DIR}/target_files.cmake" "set(GENERATED_FILES [==[${CMAKE_BINARY_DIR}/empty.cmake]==])\n") diff --git a/Tests/RunCMake/NinjaMultiConfig/SimpleSubdir/CMakeLists.txt b/Tests/RunCMake/NinjaMultiConfig/SimpleSubdir/CMakeLists.txt new file mode 100644 index 0000000..7e754a3 --- /dev/null +++ b/Tests/RunCMake/NinjaMultiConfig/SimpleSubdir/CMakeLists.txt @@ -0,0 +1,4 @@ +add_library(simpleobj OBJECT ../empty.c) +add_executable(simpleexe ../main.c $<TARGET_OBJECTS:simpleobj>) +add_library(simpleshared SHARED ../simplelib.c) +target_link_libraries(simpleexe PRIVATE simpleshared) diff --git a/Tests/RunCMake/NinjaMultiConfig/WriteFile.cmake b/Tests/RunCMake/NinjaMultiConfig/WriteFile.cmake new file mode 100644 index 0000000..82681a2 --- /dev/null +++ b/Tests/RunCMake/NinjaMultiConfig/WriteFile.cmake @@ -0,0 +1 @@ +file(WRITE "${OUTPUT_FILE}" "Genex config: ${GENEX_CONFIG}\nINTDIR config: ${INTDIR_CONFIG}\n") diff --git a/Tests/RunCMake/NinjaMultiConfig/badmoc.c b/Tests/RunCMake/NinjaMultiConfig/badmoc.c new file mode 100644 index 0000000..aec8dc3 --- /dev/null +++ b/Tests/RunCMake/NinjaMultiConfig/badmoc.c @@ -0,0 +1,7 @@ +#include <stdio.h> + +int main(void) +{ + printf("BadMoc Configuration: " CONFIG "\n"); + return 1; +} diff --git a/Tests/RunCMake/NinjaMultiConfig/empty.c b/Tests/RunCMake/NinjaMultiConfig/empty.c new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/Tests/RunCMake/NinjaMultiConfig/empty.c diff --git a/Tests/RunCMake/NinjaMultiConfig/generator.c b/Tests/RunCMake/NinjaMultiConfig/generator.c new file mode 100644 index 0000000..465ee2f --- /dev/null +++ b/Tests/RunCMake/NinjaMultiConfig/generator.c @@ -0,0 +1,101 @@ +#include <genex_config.h> +#include <stdio.h> +/* FIXME Get this working */ +/*#include <intdir_config.h>*/ + +const char* generatorlib_genex_config_definition(void); +const char* generatorlib_genex_config_include_dir(void); +const char* generatorobj_genex_config_definition(void); +const char* generatorobj_genex_config_include_dir(void); + +static const char contents[] = + /* clang-format off */ +"#include <stdio.h>\n" +"\n" +"#include <genex_config.h>\n" +/* FIXME Get this working */ +/*"#include <intdir_config.h>\n"*/ +"\n" +"const char* generatorlib_genex_config_definition(void);\n" +"const char* generatorlib_genex_config_include_dir(void);\n" +"const char* generatorobj_genex_config_definition(void);\n" +"const char* generatorobj_genex_config_include_dir(void);\n" +"\n" +"int main(void)\n" +"{\n" +" printf(\n" +" \"Generator genex config definition: " + GENEX_CONFIG_DEFINITION "\\n\"\n" +/* FIXME Get this working */ +/*" \"Generator INTDIR config definition: " + INTDIR_CONFIG_DEFINITION "\\n\"\n"*/ +" \"Generator genex config include dir: " + GENEX_CONFIG_INCLUDE_DIR "\\n\"\n" +/* FIXME Get this working */ +/*" \"Generator INTDIR config include dir: " + INTDIR_CONFIG_INCLUDE_DIR "\\n\"\n"*/ +" \"Generator library genex config definition: %s\\n\"\n" +/* FIXME Get this working */ +/*" \"Generator library INTDIR config definition: %s\\n\"\n"*/ +" \"Generator library genex config include dir: %s\\n\"\n" +/* FIXME Get this working */ +/*" \"Generator library INTDIR config include dir: %s\\n\"\n"*/ +" \"Generator object genex config definition: %s\\n\"\n" +/* FIXME Get this working */ +/*" \"Generator object INTDIR config definition: %s\\n\"\n"*/ +" \"Generator object genex config include dir: %s\\n\"\n" +/* FIXME Get this working */ +/*" \"Generator object INTDIR config include dir: %s\\n\"\n"*/ +" \"Generated genex config definition: \"" + " GENEX_CONFIG_DEFINITION \"\\n\"\n" +/* FIXME Get this working */ +/*" \"Generated INTDIR config definition: \"" + " INTDIR_CONFIG_DEFINITION \"\\n\"\n"*/ +" \"Generated genex config include dir: \"" + " GENEX_CONFIG_INCLUDE_DIR \"\\n\"\n" +/* FIXME Get this working */ +/*" \"Generated INTDIR config include dir: \"" + " INTDIR_CONFIG_INCLUDE_DIR \"\\n\"\n"*/ +" \"Generated library genex config definition: %%s\\n\"\n" +/* FIXME Get this working */ +/*" \"Generated library INTDIR config definition: %%s\\n\"\n"*/ +" \"Generated library genex config include dir: %%s\\n\"\n" +/* FIXME Get this working */ +/*" \"Generated library INTDIR config include dir: %%s\\n\"\n"*/ +" \"Generated object genex config definition: %%s\\n\"\n" +/* FIXME Get this working */ +/*" \"Generated object INTDIR config definition: %%s\\n\"\n"*/ +" \"Generated object genex config include dir: %%s\\n\"\n" +/* FIXME Get this working */ +/*" \"Generated object INTDIR config include dir: %%s\\n\"\n"*/ +" , generatorlib_genex_config_definition()\n" +" , generatorlib_genex_config_include_dir()\n" +" , generatorobj_genex_config_definition()\n" +" , generatorobj_genex_config_include_dir());\n" +" return 0;\n" +"}\n"; +/* clang-format on */ + +int main(int argc, char** argv) +{ + const char* filename; + FILE* fout; + + if (argc < 2) { + fprintf(stderr, "Usage: %s <filename>\n", argv[0]); + return 1; + } + + filename = argv[1]; + if (!(fout = fopen(filename, "w"))) { + fprintf(stderr, "Could not open %s for writing\n", filename); + return 1; + } + fprintf(fout, contents, generatorlib_genex_config_definition(), + generatorlib_genex_config_include_dir(), + generatorobj_genex_config_definition(), + generatorobj_genex_config_include_dir()); + fclose(fout); + + return 0; +} diff --git a/Tests/RunCMake/NinjaMultiConfig/generatorlib.c b/Tests/RunCMake/NinjaMultiConfig/generatorlib.c new file mode 100644 index 0000000..de5c8f3 --- /dev/null +++ b/Tests/RunCMake/NinjaMultiConfig/generatorlib.c @@ -0,0 +1,24 @@ +#include <genex_config.h> +/* FIXME Get this working */ +/*#include <intdir_config.h>*/ + +const char* generatorlib_genex_config_definition(void) +{ + return GENEX_CONFIG_DEFINITION; +} + +const char* generatorlib_genex_config_include_dir(void) +{ + return GENEX_CONFIG_INCLUDE_DIR; +} + +/* FIXME Get this working */ +/*const char* generatorlib_intdir_config_definition(void) +{ + return INTDIR_CONFIG_DEFINITION; +} + +const char* generatorlib_intdir_config_include_dir(void) +{ + return INTDIR_CONFIG_INCLUDE_DIR; +}*/ diff --git a/Tests/RunCMake/NinjaMultiConfig/generatorobj.c b/Tests/RunCMake/NinjaMultiConfig/generatorobj.c new file mode 100644 index 0000000..7bb5aa6 --- /dev/null +++ b/Tests/RunCMake/NinjaMultiConfig/generatorobj.c @@ -0,0 +1,24 @@ +#include <genex_config.h> +/* FIXME Get this working */ +/*#include <intdir_config.h>*/ + +const char* generatorobj_genex_config_definition(void) +{ + return GENEX_CONFIG_DEFINITION; +} + +const char* generatorobj_genex_config_include_dir(void) +{ + return GENEX_CONFIG_INCLUDE_DIR; +} + +/* FIXME Get this working */ +/*const char* generatorobj_intdir_config_definition(void) +{ + return INTDIR_CONFIG_DEFINITION; +} + +const char* generatorobj_intdir_config_include_dir(void) +{ + return INTDIR_CONFIG_INCLUDE_DIR; +}*/ diff --git a/Tests/RunCMake/NinjaMultiConfig/main.c b/Tests/RunCMake/NinjaMultiConfig/main.c new file mode 100644 index 0000000..8488f4e --- /dev/null +++ b/Tests/RunCMake/NinjaMultiConfig/main.c @@ -0,0 +1,4 @@ +int main(void) +{ + return 0; +} diff --git a/Tests/RunCMake/NinjaMultiConfig/qt5.cxx b/Tests/RunCMake/NinjaMultiConfig/qt5.cxx new file mode 100644 index 0000000..972227f --- /dev/null +++ b/Tests/RunCMake/NinjaMultiConfig/qt5.cxx @@ -0,0 +1,9 @@ +#include <QCoreApplication> + +int main(int argc, char** argv) +{ + QCoreApplication app(argc, argv); + return app.exec(); +} + +#include "moc_qt5.cpp" diff --git a/Tests/RunCMake/NinjaMultiConfig/qt5.h b/Tests/RunCMake/NinjaMultiConfig/qt5.h new file mode 100644 index 0000000..b365b92 --- /dev/null +++ b/Tests/RunCMake/NinjaMultiConfig/qt5.h @@ -0,0 +1,5 @@ +#include <QObject> +class QBuffer : public QObject +{ + Q_OBJECT +}; diff --git a/Tests/RunCMake/NinjaMultiConfig/simplelib.c b/Tests/RunCMake/NinjaMultiConfig/simplelib.c new file mode 100644 index 0000000..76ff921 --- /dev/null +++ b/Tests/RunCMake/NinjaMultiConfig/simplelib.c @@ -0,0 +1,6 @@ +#ifdef _WIN32 +__declspec(dllexport) +#endif + void simplelib(void) +{ +} diff --git a/Tests/RunCMake/ParseImplicitData/mingw.org-C-GNU-4.9.3.input b/Tests/RunCMake/ParseImplicitData/mingw.org-C-GNU-4.9.3.input index 81e9ee0..b1c4ce0 100644 --- a/Tests/RunCMake/ParseImplicitData/mingw.org-C-GNU-4.9.3.input +++ b/Tests/RunCMake/ParseImplicitData/mingw.org-C-GNU-4.9.3.input @@ -53,7 +53,7 @@ LIBRARY_PATH=c:/DoesNotExist/mingw/bin/../lib/gcc/mingw32/4.9.3/;c:/DoesNotExist COLLECT_GCC_OPTIONS='-v' '-o' 'CMakeFiles\cmTC_ab097.dir\CMakeCCompilerABI.c.obj' '-c' '-mtune=generic' '-march=i586' Linking C executable cmTC_ab097.exe "C:\CMake\bin\cmake.exe" -E cmake_link_script CMakeFiles\cmTC_ab097.dir\link.txt --verbose=1 -"C:\CMake\bin\cmake.exe" -E remove -f CMakeFiles\cmTC_ab097.dir/objects.a +"C:\CMake\bin\cmake.exe" -E rm -f CMakeFiles\cmTC_ab097.dir/objects.a C:\DoesNotExist\MinGW\bin\ar.exe cr CMakeFiles\cmTC_ab097.dir/objects.a @CMakeFiles\cmTC_ab097.dir\objects1.rsp C:\DoesNotExist\MinGW\bin\gcc.exe -v -Wl,--whole-archive CMakeFiles\cmTC_ab097.dir/objects.a -Wl,--no-whole-archive -o cmTC_ab097.exe -Wl,--out-implib,libcmTC_ab097.dll.a -Wl,--major-image-version,0,--minor-image-version,0 Using built-in specs. diff --git a/Tests/RunCMake/ParseImplicitData/mingw.org-CXX-GNU-4.9.3.input b/Tests/RunCMake/ParseImplicitData/mingw.org-CXX-GNU-4.9.3.input index cd77340..aae67bb 100644 --- a/Tests/RunCMake/ParseImplicitData/mingw.org-CXX-GNU-4.9.3.input +++ b/Tests/RunCMake/ParseImplicitData/mingw.org-CXX-GNU-4.9.3.input @@ -59,7 +59,7 @@ LIBRARY_PATH=c:/DoesNotExist/mingw/bin/../lib/gcc/mingw32/4.9.3/;c:/DoesNotExist COLLECT_GCC_OPTIONS='-v' '-o' 'CMakeFiles\cmTC_2b790.dir\CMakeCXXCompilerABI.cpp.obj' '-c' '-shared-libgcc' '-mtune=generic' '-march=i586' Linking CXX executable cmTC_2b790.exe "C:\CMake\bin\cmake.exe" -E cmake_link_script CMakeFiles\cmTC_2b790.dir\link.txt --verbose=1 -"C:\CMake\bin\cmake.exe" -E remove -f CMakeFiles\cmTC_2b790.dir/objects.a +"C:\CMake\bin\cmake.exe" -E rm -f CMakeFiles\cmTC_2b790.dir/objects.a C:\DoesNotExist\MinGW\bin\ar.exe cr CMakeFiles\cmTC_2b790.dir/objects.a @CMakeFiles\cmTC_2b790.dir\objects1.rsp C:\DoesNotExist\MinGW\bin\g++.exe -v -Wl,--whole-archive CMakeFiles\cmTC_2b790.dir/objects.a -Wl,--no-whole-archive -o cmTC_2b790.exe -Wl,--out-implib,libcmTC_2b790.dll.a -Wl,--major-image-version,0,--minor-image-version,0 Using built-in specs. diff --git a/Tests/RunCMake/RunCMake.cmake b/Tests/RunCMake/RunCMake.cmake index da4d1e5..cb20fb1 100644 --- a/Tests/RunCMake/RunCMake.cmake +++ b/Tests/RunCMake/RunCMake.cmake @@ -146,6 +146,12 @@ function(run_cmake test) "|clang[^:]*: warning: the object size sanitizer has no effect at -O0, but is explicitly enabled:" "|Error kstat returned" "|Hit xcodebuild bug" + + "|LICENSE WARNING:" + "|Your license to use PGI[^\n]*expired" + "|Please obtain a new version at" + "|contact PGI Sales at" + "|[^\n]*xcodebuild[^\n]*warning: file type[^\n]*is based on missing file type" "|[^\n]*is a member of multiple groups" "|[^\n]*from Time Machine by path" @@ -204,5 +210,28 @@ function(run_cmake_with_options test) run_cmake(${test}) endfunction() +function(ensure_files_match expected_file actual_file) + if(NOT EXISTS "${expected_file}") + message(FATAL_ERROR "Expected file does not exist:\n ${expected_file}") + endif() + if(NOT EXISTS "${actual_file}") + message(FATAL_ERROR "Actual file does not exist:\n ${actual_file}") + endif() + file(READ "${expected_file}" expected_file_content) + file(READ "${actual_file}" actual_file_content) + if(NOT "${expected_file_content}" STREQUAL "${actual_file_content}") + message(FATAL_ERROR "Actual file content does not match expected:\n + \n + expected file: ${expected_file}\n + expected content:\n + ${expected_file_content}\n + \n + actual file: ${actual_file}\n + actual content:\n + ${actual_file_content}\n + ") + endif() +endfunction() + # Protect RunCMake tests from calling environment. unset(ENV{MAKEFLAGS}) diff --git a/Tests/RunCMake/RuntimePath/Relative.cmake b/Tests/RunCMake/RuntimePath/Relative.cmake index 203241f..80ed189 100644 --- a/Tests/RunCMake/RuntimePath/Relative.cmake +++ b/Tests/RunCMake/RuntimePath/Relative.cmake @@ -1,5 +1,12 @@ enable_language(C) +set(cfg_up) +set(cfg_slash /) +if(cfg_dir) + set(cfg_up /..) + set(cfg_slash) +endif() + if(NOT CMAKE_SHARED_LIBRARY_RPATH_ORIGIN_TOKEN) if(CMAKE_C_PLATFORM_ID STREQUAL "Linux") # Sanity check for platform that is definitely known to support $ORIGIN. @@ -45,25 +52,25 @@ CheckRpath(main "\$ORIGIN") add_executable(main-norel main.c) target_link_libraries(main-norel utils) set_property(TARGET main-norel PROPERTY BUILD_RPATH_USE_ORIGIN OFF) -CheckRpath(main-norel "${CMAKE_CURRENT_BINARY_DIR}") +CheckRpath(main-norel "${CMAKE_CURRENT_BINARY_DIR}${cfg_dir}") add_executable(mainsub main.c) target_link_libraries(mainsub utils) set_property(TARGET mainsub PROPERTY RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/bin) -CheckRpath(mainsub "\$ORIGIN/../") +CheckRpath(mainsub "\$ORIGIN${cfg_up}/..${cfg_dir}${cfg_slash}") add_executable(main-sub main.c) target_link_libraries(main-sub utils-sub) -CheckRpath(main-sub "\$ORIGIN/libs") +CheckRpath(main-sub "\$ORIGIN${cfg_up}/libs${cfg_dir}") add_executable(mainsub-sub main.c) target_link_libraries(mainsub-sub utils-sub) set_property(TARGET mainsub-sub PROPERTY RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/bin) -CheckRpath(mainsub-sub "\$ORIGIN/../libs") +CheckRpath(mainsub-sub "\$ORIGIN${cfg_up}/../libs${cfg_dir}") if(externDir) # Binaries linking to libraries outside the build tree should have an absolute RPATH. add_executable(main-extern main.c) target_link_libraries(main-extern utils-extern) - CheckRpath(main-extern "${externDir}") + CheckRpath(main-extern "${externDir}${cfg_dir}") endif() diff --git a/Tests/RunCMake/RuntimePath/RunCMakeTest.cmake b/Tests/RunCMake/RuntimePath/RunCMakeTest.cmake index 4c9ddcd..ad446e9 100644 --- a/Tests/RunCMake/RuntimePath/RunCMakeTest.cmake +++ b/Tests/RunCMake/RuntimePath/RunCMakeTest.cmake @@ -6,7 +6,9 @@ function(run_RuntimePath name) set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/${name}-build) set(RunCMake_TEST_NO_CLEAN 1) if(NOT RunCMake_GENERATOR_IS_MULTI_CONFIG) - set(RunCMake_TEST_OPTIONS -DCMAKE_BUILD_TYPE=Debug) + set(RunCMake_TEST_OPTIONS -Dcfg_dir= -DCMAKE_BUILD_TYPE=Debug) + else() + set(RunCMake_TEST_OPTIONS -Dcfg_dir=/$<CONFIG>) endif() file(REMOVE_RECURSE "${RunCMake_TEST_BINARY_DIR}") file(MAKE_DIRECTORY "${RunCMake_TEST_BINARY_DIR}") @@ -14,12 +16,16 @@ function(run_RuntimePath name) run_cmake_command(${name}-build ${CMAKE_COMMAND} --build . --config Debug) endfunction() +set(cfg_dir) +if(RunCMake_GENERATOR_IS_MULTI_CONFIG) + set(cfg_dir /Debug) +endif() + run_RuntimePath(SymlinkImplicit) run_cmake_command(SymlinkImplicitCheck - ${CMAKE_COMMAND} -Ddir=${RunCMake_BINARY_DIR}/SymlinkImplicit-build -P ${RunCMake_SOURCE_DIR}/SymlinkImplicitCheck.cmake) + ${CMAKE_COMMAND} -Ddir=${RunCMake_BINARY_DIR}/SymlinkImplicit-build -Dcfg_dir=${cfg_dir} -P ${RunCMake_SOURCE_DIR}/SymlinkImplicitCheck.cmake) run_RuntimePath(Relative) -# FIXME: Run RelativeCheck (appears to be broken currently) run_RuntimePath(Genex) run_cmake_command(GenexCheck diff --git a/Tests/RunCMake/RuntimePath/SymlinkImplicitCheck.cmake b/Tests/RunCMake/RuntimePath/SymlinkImplicitCheck.cmake index d34742e..4f50d4b 100644 --- a/Tests/RunCMake/RuntimePath/SymlinkImplicitCheck.cmake +++ b/Tests/RunCMake/RuntimePath/SymlinkImplicitCheck.cmake @@ -1,2 +1,2 @@ -file(COPY ${dir}/bin/exe DESTINATION ${dir}) +file(COPY ${dir}/bin${cfg_dir}/exe DESTINATION ${dir}) file(RPATH_CHANGE FILE "${dir}/exe" OLD_RPATH "${dir}/libLink" NEW_RPATH "old-should-not-exist") diff --git a/Tests/RunCMake/TargetPolicies/PolicyList-stderr.txt b/Tests/RunCMake/TargetPolicies/PolicyList-stderr.txt index 6d72fac..9a1e027 100644 --- a/Tests/RunCMake/TargetPolicies/PolicyList-stderr.txt +++ b/Tests/RunCMake/TargetPolicies/PolicyList-stderr.txt @@ -28,6 +28,7 @@ \* CMP0081 \* CMP0083 \* CMP0095 + \* CMP0099 Call Stack \(most recent call first\): CMakeLists.txt:3 \(include\) diff --git a/Tests/RunCMake/TargetSources/RunCMakeTest.cmake b/Tests/RunCMake/TargetSources/RunCMakeTest.cmake index bee8c4e..0d462ba 100644 --- a/Tests/RunCMake/TargetSources/RunCMakeTest.cmake +++ b/Tests/RunCMake/TargetSources/RunCMakeTest.cmake @@ -1,6 +1,6 @@ include(RunCMake) -if(RunCMake_GENERATOR MATCHES "Visual Studio|Xcode") +if(RunCMake_GENERATOR STREQUAL "Xcode") run_cmake(ConfigNotAllowed) endif() diff --git a/Tests/RunCMake/VS10Project/RunCMakeTest.cmake b/Tests/RunCMake/VS10Project/RunCMakeTest.cmake index 44ccd6b..5cbe333 100644 --- a/Tests/RunCMake/VS10Project/RunCMakeTest.cmake +++ b/Tests/RunCMake/VS10Project/RunCMakeTest.cmake @@ -1,3 +1,5 @@ +cmake_policy(SET CMP0057 NEW) + include(RunCMake) cmake_policy(SET CMP0054 NEW) @@ -15,6 +17,7 @@ run_cmake(VsDebuggerCommand) run_cmake(VsDebuggerCommandArguments) run_cmake(VsDebuggerEnvironment) run_cmake(VsCSharpCustomTags) +run_cmake(VsCSharpDocumentationFile) run_cmake(VsCSharpReferenceProps) run_cmake(VsCSharpWithoutSources) run_cmake(VsCSharpDeployFiles) @@ -28,6 +31,12 @@ run_cmake(VsDpiAwareBadParam) run_cmake(VsPrecompileHeaders) run_cmake(VsPrecompileHeadersReuseFromCompilePDBName) +run_cmake(VsWinRTByDefault) + +set(RunCMake_GENERATOR_TOOLSET "VCTargetsPath=$(VCTargetsPath)") +run_cmake(VsVCTargetsPath) +unset(RunCMake_GENERATOR_TOOLSET) + if(CMAKE_C_COMPILER_ID STREQUAL "MSVC" AND CMAKE_C_COMPILER_VERSION VERSION_GREATER_EQUAL 19.05) run_cmake(VsJustMyCode) endif() diff --git a/Tests/RunCMake/VS10Project/VsCSharpDocumentationFile-check.cmake b/Tests/RunCMake/VS10Project/VsCSharpDocumentationFile-check.cmake new file mode 100644 index 0000000..0393362 --- /dev/null +++ b/Tests/RunCMake/VS10Project/VsCSharpDocumentationFile-check.cmake @@ -0,0 +1,26 @@ +# +# Check C# VS project for required elements +# +set(csProjectFile "${RunCMake_TEST_BINARY_DIR}/foo.csproj") +if(NOT EXISTS "${csProjectFile}") + set(RunCMake_TEST_FAILED "Project file ${csProjectFile} does not exist.") + return() +endif() + +file(STRINGS "${csProjectFile}" lines) + +set(HAVE_DocumentationFile 0) +foreach(line IN LISTS lines) + if(line MATCHES "^ *<DocumentationFile>([^<>]+)</DocumentationFile>") + if(HAVE_DocumentationFile) + set(RunCMake_TEST_FAILED "Documentation node has been generated more than once for\n ${csProjectFile}") + return() + endif() + set(HAVE_DocumentationFile 1) + endif() +endforeach() + +if(NOT HAVE_DocumentationFile) + set(RunCMake_TEST_FAILED "Documentation node has not been generated for\n ${csProjectFile}") + return() +endif() diff --git a/Tests/RunCMake/VS10Project/VsCSharpDocumentationFile.cmake b/Tests/RunCMake/VS10Project/VsCSharpDocumentationFile.cmake new file mode 100644 index 0000000..83b6b97 --- /dev/null +++ b/Tests/RunCMake/VS10Project/VsCSharpDocumentationFile.cmake @@ -0,0 +1,8 @@ +set(CMAKE_CONFIGURATION_TYPES Debug) +enable_language(CSharp) + +add_library(foo SHARED + foo.cs) + +set_target_properties(foo PROPERTIES + VS_DOTNET_DOCUMENTATION_FILE foo.xml) diff --git a/Tests/RunCMake/VS10Project/VsGlobals-check.cmake b/Tests/RunCMake/VS10Project/VsGlobals-check.cmake index 0e7fd45..6a30099 100644 --- a/Tests/RunCMake/VS10Project/VsGlobals-check.cmake +++ b/Tests/RunCMake/VS10Project/VsGlobals-check.cmake @@ -1,44 +1,65 @@ -set(vcProjectFile "${RunCMake_TEST_BINARY_DIR}/foo.vcxproj") -if(NOT EXISTS "${vcProjectFile}") - set(RunCMake_TEST_FAILED "Project file ${vcProjectFile} does not exist.") - return() -endif() +macro(check_project_file projectFile) + if(NOT EXISTS "${projectFile}") + set(RunCMake_TEST_FAILED "Project file ${projectFile} does not exist.") + return() + endif() + + string(REPLACE "${RunCMake_TEST_BINARY_DIR}/" "" projectName ${projectFile}) -set(InsideGlobals FALSE) -set(DefaultLanguageSet FALSE) -set(MinimumVisualStudioVersionSet FALSE) + set(InsideGlobals FALSE) + set(DefaultLanguageSet FALSE) + set(MinimumVisualStudioVersionSet FALSE) + set(TestPropertySet FALSE) -file(STRINGS "${vcProjectFile}" lines) -foreach(line IN LISTS lines) - if(line MATCHES "^ *<PropertyGroup Label=\"Globals\"> *$") - set(InsideGlobals TRUE) - elseif(line MATCHES "^ *<DefaultLanguage>([a-zA-Z\\-]+)</DefaultLanguage> *$") - if("${CMAKE_MATCH_1}" STREQUAL "en-US") - if(InsideGlobals) - message(STATUS "foo.vcxproj has correct DefaultLanguage global property") - set(DefaultLanguageSet TRUE) - else() - message(STATUS "DefaultLanguage is set but not within \"Globals\" property group") + file(STRINGS "${projectFile}" lines) + foreach(line IN LISTS lines) + if(line MATCHES "^ *<PropertyGroup Label=\"Globals\"> *$") + set(InsideGlobals TRUE) + elseif(line MATCHES "^ *<DefaultLanguage>([a-zA-Z\\-]+)</DefaultLanguage> *$") + if("${CMAKE_MATCH_1}" STREQUAL "en-US") + if(InsideGlobals) + message(STATUS "${projectName} has correct DefaultLanguage global property") + set(DefaultLanguageSet TRUE) + else() + message(STATUS "DefaultLanguage is set but not within \"Globals\" property group") + endif() endif() - endif() - elseif(line MATCHES "^ *<MinimumVisualStudioVersion>([0-9\\.]+)</MinimumVisualStudioVersion> *$") - if("${CMAKE_MATCH_1}" STREQUAL "14.0") - if(InsideGlobals) - message(STATUS "foo.vcxproj has correct MinimumVisualStudioVersion global property") - set(MinimumVisualStudioVersionSet TRUE) - else() - message(STATUS "MinimumVisualStudioVersion is set but not within \"Globals\" property group") + elseif(line MATCHES "^ *<MinimumVisualStudioVersion>([0-9\\.]+)</MinimumVisualStudioVersion> *$") + if("${CMAKE_MATCH_1}" STREQUAL "10.0") + if(InsideGlobals) + message(STATUS "${projectName} has correct MinimumVisualStudioVersion global property") + set(MinimumVisualStudioVersionSet TRUE) + else() + message(STATUS "MinimumVisualStudioVersion is set but not within \"Globals\" property group") + endif() + endif() + elseif(line MATCHES "^ *<TestProperty>(.+)</TestProperty> *$") + if("${CMAKE_MATCH_1}" STREQUAL "TestValue") + if(InsideGlobals) + message(STATUS "${projectName} has correct TestProperty global property") + set(TestPropertySet TRUE) + else() + message(STATUS "TestProperty is set but not within \"Globals\" property group") + endif() endif() endif() + endforeach() + + if(NOT DefaultLanguageSet) + set(RunCMake_TEST_FAILED "DefaultLanguage not found or not set correctly in ${projectName}.") + return() + endif() + + if(NOT MinimumVisualStudioVersionSet) + set(RunCMake_TEST_FAILED "MinimumVisualStudioVersion not found or not set correctly in ${projectName}.") + return() endif() -endforeach() -if(NOT DefaultLanguageSet) - set(RunCMake_TEST_FAILED "DefaultLanguageSet not found or not set correctly.") - return() -endif() + if(NOT TestPropertySet) + set(RunCMake_TEST_FAILED "TestProperty not found or not set correctly in ${projectName}.") + return() + endif() +endmacro() -if(NOT MinimumVisualStudioVersionSet) - set(RunCMake_TEST_FAILED "MinimumVisualStudioVersionSet not found or not set correctly.") - return() -endif() +check_project_file("${RunCMake_TEST_BINARY_DIR}/CMakeFiles/${CMAKE_VERSION}/CompilerIdCXX/CompilerIdCXX.vcxproj") +check_project_file("${RunCMake_TEST_BINARY_DIR}/foo.vcxproj") diff --git a/Tests/RunCMake/VS10Project/VsGlobals.cmake b/Tests/RunCMake/VS10Project/VsGlobals.cmake index a3ed5af..09d806d 100644 --- a/Tests/RunCMake/VS10Project/VsGlobals.cmake +++ b/Tests/RunCMake/VS10Project/VsGlobals.cmake @@ -1,8 +1,9 @@ -enable_language(CXX) - set(CMAKE_VS_GLOBALS "DefaultLanguage=en-US" - "MinimumVisualStudioVersion=14.0" + "MinimumVisualStudioVersion=10.0" + "TestProperty=TestValue" ) +enable_language(CXX) + add_library(foo foo.cpp) diff --git a/Tests/RunCMake/VS10Project/VsVCTargetsPath-check.cmake b/Tests/RunCMake/VS10Project/VsVCTargetsPath-check.cmake new file mode 100644 index 0000000..5b1701c --- /dev/null +++ b/Tests/RunCMake/VS10Project/VsVCTargetsPath-check.cmake @@ -0,0 +1,32 @@ +macro(check_project_file projectFile) + set(insideGlobals FALSE) + set(pathFound FALSE) + + if(NOT EXISTS "${projectFile}") + set(RunCMake_TEST_FAILED "Project file ${projectFile} does not exist.") + return() + endif() + + string(REPLACE "${RunCMake_TEST_BINARY_DIR}/" "" projectName ${projectFile}) + + file(STRINGS "${projectFile}" lines) + foreach(line IN LISTS lines) + if(line MATCHES "^ *<PropertyGroup Label=\"Globals\">.*$") + set(insideGlobals TRUE) + elseif(insideGlobals) + if(line MATCHES "^ *</PropertyGroup>.*$") + set(insideGlobals FALSE) + elseif(line MATCHES "^ *<VCTargetsPath>(.+)</VCTargetsPath>*$") + message(STATUS "Found VCTargetsPath = ${CMAKE_MATCH_1} in PropertyGroup 'Globals' in ${projectName}") + set(pathFound TRUE) + endif() + endif() + endforeach() + if(NOT pathFound) + set(RunCMake_TEST_FAILED "VCTargetsPath not found in \"Globals\" propertygroup in ${projectName}") + return() # This should intentionally return from the caller, not the macro + endif() +endmacro() + +check_project_file("${RunCMake_TEST_BINARY_DIR}/CMakeFiles/${CMAKE_VERSION}/CompilerIdCXX/CompilerIdCXX.vcxproj") +check_project_file("${RunCMake_TEST_BINARY_DIR}/foo.vcxproj") diff --git a/Tests/RunCMake/VS10Project/VsVCTargetsPath.cmake b/Tests/RunCMake/VS10Project/VsVCTargetsPath.cmake new file mode 100644 index 0000000..6a6088f --- /dev/null +++ b/Tests/RunCMake/VS10Project/VsVCTargetsPath.cmake @@ -0,0 +1,3 @@ +enable_language(CXX) + +add_library(foo foo.cpp) diff --git a/Tests/RunCMake/VS10Project/VsWinRTByDefault-check.cmake b/Tests/RunCMake/VS10Project/VsWinRTByDefault-check.cmake new file mode 100644 index 0000000..15bbaf2 --- /dev/null +++ b/Tests/RunCMake/VS10Project/VsWinRTByDefault-check.cmake @@ -0,0 +1,66 @@ +macro(checkCompileAsWinRT projectPath) + if(RunCMake_TEST_FAILED) + return() + endif() + + if (NOT EXISTS "${projectPath}") + set(RunCMake_TEST_FAILED "Project file ${projectPath} does not exist.") + return() + endif() + + get_filename_component(projectName "${projectPath}" NAME_WE) + + cmake_parse_arguments("" "" "GLOBAL" "OVERRIDES_ENABLE;OVERRIDES_DISABLE" ${ARGN}) + + unset(sourceOverride) + + file(STRINGS "${projectPath}" lines) + set(foundGlobalWinRT false) + + foreach(line IN LISTS lines) + if(line MATCHES "^ *<CompileAsWinRT( Condition=\"[^\\\"]+\")?>(true|false)</CompileAsWinRT>$") + set(value ${CMAKE_MATCH_2}) + + if(sourceOverride) + set(expectedList) + + if(value) + set(expectedList _OVERRIDES_ENABLE) + else() + set(expectedList _OVERRIDES_DISABLE) + endif() + + if(NOT sourceOverride IN_LIST ${expectedList}) + set(RunCMake_TEST_FAILED + "${projectName}: Unexpected CompileAsWinRT override ${value} for ${sourceOverride}") + return() + endif() + else() + if (NOT _GLOBAL STREQUAL value) + set(RunCMake_TEST_FAILED + "${projectName}: Global CompileAsWinRT value is ${value}, but expected ${_GLOBAL}") + return() + endif() + + set(foundGlobalWinRT true) + endif() + elseif(line MATCHES "^ *<ClCompile Include=\"([^\"]+)\">$") + get_filename_component(sourceOverride "${CMAKE_MATCH_1}" NAME) + elseif(line MATCHES "^ *</ClCompile>$") + unset(sourceOverride) + endif() + endforeach() + + if(NOT foundGlobalWinRT AND DEFINED _GLOBAL) + set(RunCMake_TEST_FAILED "${projectName}: Global CompileAsWinRT not found or have invalid value, but expected") + return() + endif() +endmacro() + +checkCompileAsWinRT("${RunCMake_TEST_BINARY_DIR}/noFlagOnlyC.vcxproj" GLOBAL false) +checkCompileAsWinRT("${RunCMake_TEST_BINARY_DIR}/noFlagMixedCAndCxx.vcxproj" GLOBAL false) +checkCompileAsWinRT("${RunCMake_TEST_BINARY_DIR}/noFlagOnlyCxx.vcxproj" GLOBAL false) + +checkCompileAsWinRT("${RunCMake_TEST_BINARY_DIR}/flagOnlyC.vcxproj" GLOBAL true OVERRIDES_DISABLE empty.c) +checkCompileAsWinRT("${RunCMake_TEST_BINARY_DIR}/flagMixedCAndCxx.vcxproj" GLOBAL true OVERRIDES_DISABLE empty.c) +checkCompileAsWinRT("${RunCMake_TEST_BINARY_DIR}/flagOnlyCxx.vcxproj" GLOBAL true) diff --git a/Tests/RunCMake/VS10Project/VsWinRTByDefault.cmake b/Tests/RunCMake/VS10Project/VsWinRTByDefault.cmake new file mode 100644 index 0000000..139048b --- /dev/null +++ b/Tests/RunCMake/VS10Project/VsWinRTByDefault.cmake @@ -0,0 +1,16 @@ +set(CMAKE_VS_WINRT_BY_DEFAULT true) + +enable_language(C) +enable_language(CXX) + +add_library(noFlagOnlyC empty.c) +add_library(noFlagMixedCAndCXX empty.c foo.cpp) +add_library(noFlagOnlyCXX foo.cpp) + +add_library(flagOnlyC empty.c) +add_library(flagMixedCAndCXX empty.c foo.cpp) +add_library(flagOnlyCXX foo.cpp) + +target_compile_options(flagOnlyC PRIVATE /ZW) +target_compile_options(flagMixedCAndCXX PRIVATE /ZW) +target_compile_options(flagOnlyCXX PRIVATE /ZW) diff --git a/Tests/RunCMake/XcodeProject/XcodeSchemaProperty-check.cmake b/Tests/RunCMake/XcodeProject/XcodeSchemaProperty-check.cmake index 7d83a70..c742f50 100644 --- a/Tests/RunCMake/XcodeProject/XcodeSchemaProperty-check.cmake +++ b/Tests/RunCMake/XcodeProject/XcodeSchemaProperty-check.cmake @@ -45,6 +45,7 @@ check_property("ENVIRONMENT" [=[key="FOO"]=]) check_property("ENVIRONMENT" [=[value="foo"]=]) check_property("ENVIRONMENT" [=[key="BAR"]=]) check_property("ENVIRONMENT" [=[value="bar"]=]) +check_property("WORKING_DIRECTORY" [=["/working/dir"]=]) expect_no_schema("NoSchema") diff --git a/Tests/RunCMake/XcodeProject/XcodeSchemaProperty.cmake b/Tests/RunCMake/XcodeProject/XcodeSchemaProperty.cmake index be219f4..ce5c0c9 100644 --- a/Tests/RunCMake/XcodeProject/XcodeSchemaProperty.cmake +++ b/Tests/RunCMake/XcodeProject/XcodeSchemaProperty.cmake @@ -35,6 +35,7 @@ endfunction() create_scheme_for_property(EXECUTABLE myExecutable) create_scheme_for_property(ARGUMENTS "--foo;--bar=baz") create_scheme_for_property(ENVIRONMENT "FOO=foo;BAR=bar") +create_scheme_for_property(WORKING_DIRECTORY "/working/dir") add_executable(NoSchema main.cpp) set_target_properties(NoSchema PROPERTIES XCODE_GENERATE_SCHEME OFF) diff --git a/Tests/RunCMake/add_link_options/LINKER_expansion-list.cmake b/Tests/RunCMake/add_link_options/LINKER_expansion-list.cmake index 34dcc67..c77b43c 100644 --- a/Tests/RunCMake/add_link_options/LINKER_expansion-list.cmake +++ b/Tests/RunCMake/add_link_options/LINKER_expansion-list.cmake @@ -11,7 +11,7 @@ string(REPLACE "${CMAKE_END_TEMP_FILE}" "" CMAKE_C_CREATE_SHARED_LIBRARY "${CMAK add_library(example SHARED LinkOptionsLib.c) # use LAUNCH facility to dump linker command -set_property(TARGET example PROPERTY RULE_LAUNCH_LINK "\"${CMAKE_CURRENT_BINARY_DIR}/dump${CMAKE_EXECUTABLE_SUFFIX}\"") +set_property(TARGET example PROPERTY RULE_LAUNCH_LINK "\"${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/dump${CMAKE_EXECUTABLE_SUFFIX}\"") add_dependencies (example dump) diff --git a/Tests/RunCMake/ctest_labels_for_subprojects/CTestScriptVariableCommandLine-stderr.txt b/Tests/RunCMake/ctest_labels_for_subprojects/CTestScriptVariableCommandLine-stderr.txt index 38566fb..206ab21 100644 --- a/Tests/RunCMake/ctest_labels_for_subprojects/CTestScriptVariableCommandLine-stderr.txt +++ b/Tests/RunCMake/ctest_labels_for_subprojects/CTestScriptVariableCommandLine-stderr.txt @@ -1 +1,2 @@ -Unable to find executable:.*MyThirdPartyDependency/src/thirdparty +Unable to find executable:.*MyThirdPartyDependency/src(/[^/ +]+)?/thirdparty diff --git a/Tests/RunCMake/ctest_test/RunCMakeTest.cmake b/Tests/RunCMake/ctest_test/RunCMakeTest.cmake index 6877e6a..84d1d66 100644 --- a/Tests/RunCMake/ctest_test/RunCMakeTest.cmake +++ b/Tests/RunCMake/ctest_test/RunCMakeTest.cmake @@ -1,6 +1,9 @@ include(RunCTest) set(RunCMake_TEST_TIMEOUT 60) +unset(ENV{CTEST_PARALLEL_LEVEL}) +unset(ENV{CTEST_OUTPUT_ON_FAILURE}) + set(CASE_CTEST_TEST_ARGS "") set(CASE_CTEST_TEST_LOAD "") @@ -71,7 +74,24 @@ add_test(NAME PassingTest COMMAND ${CMAKE_COMMAND} -E echo PassingTestOutput) add_test(NAME FailingTest COMMAND ${CMAKE_COMMAND} -E no_such_command) ]]) - unset(ENV{CTEST_PARALLEL_LEVEL}) run_ctest(TestOutputSize) endfunction() run_TestOutputSize() + +run_ctest_test(TestRepeatBad1 REPEAT UNKNOWN:3) +run_ctest_test(TestRepeatBad2 REPEAT UNTIL_FAIL:-1) + +function(run_TestRepeat case) + set(CASE_CTEST_TEST_ARGS EXCLUDE RunCMakeVersion ${ARGN}) + string(CONCAT CASE_CMAKELISTS_SUFFIX_CODE [[ +add_test(NAME testRepeat + COMMAND ${CMAKE_COMMAND} -D COUNT_FILE=${CMAKE_CURRENT_BINARY_DIR}/count.cmake + -P "]] "${RunCMake_SOURCE_DIR}/TestRepeat${case}" [[.cmake") +set_property(TEST testRepeat PROPERTY TIMEOUT 5) + ]]) + + run_ctest(TestRepeat${case}) +endfunction() +run_TestRepeat(UntilFail REPEAT UNTIL_FAIL:3) +run_TestRepeat(UntilPass REPEAT UNTIL_PASS:3) +run_TestRepeat(AfterTimeout REPEAT AFTER_TIMEOUT:3) diff --git a/Tests/RunCMake/ctest_test/TestRepeatAfterTimeout-stdout.txt b/Tests/RunCMake/ctest_test/TestRepeatAfterTimeout-stdout.txt new file mode 100644 index 0000000..17657c5 --- /dev/null +++ b/Tests/RunCMake/ctest_test/TestRepeatAfterTimeout-stdout.txt @@ -0,0 +1,10 @@ +Test project [^ +]*/Tests/RunCMake/ctest_test/TestRepeatAfterTimeout-build + Start 1: testRepeat +1/1 Test #1: testRepeat .......................\*\*\*Timeout +[0-9.]+ sec + Start 1: testRepeat + Test #1: testRepeat ....................... Passed +[0-9.]+ sec ++ +100% tests passed, 0 tests failed out of 1 ++ +Total Test time \(real\) = +[0-9.]+ sec$ diff --git a/Tests/RunCMake/ctest_test/TestRepeatAfterTimeout.cmake b/Tests/RunCMake/ctest_test/TestRepeatAfterTimeout.cmake new file mode 100644 index 0000000..abde4f0 --- /dev/null +++ b/Tests/RunCMake/ctest_test/TestRepeatAfterTimeout.cmake @@ -0,0 +1,10 @@ +include("${COUNT_FILE}" OPTIONAL) +if(NOT COUNT) + set(COUNT 0) +endif() +math(EXPR COUNT "${COUNT} + 1") +file(WRITE "${COUNT_FILE}" "set(COUNT ${COUNT})\n") +if(NOT COUNT EQUAL 2) + message("this test times out except on the 2nd run") + execute_process(COMMAND ${CMAKE_COMMAND} -E sleep 10) +endif() diff --git a/Tests/RunCMake/ctest_test/TestRepeatBad1-result.txt b/Tests/RunCMake/ctest_test/TestRepeatBad1-result.txt new file mode 100644 index 0000000..b57e2de --- /dev/null +++ b/Tests/RunCMake/ctest_test/TestRepeatBad1-result.txt @@ -0,0 +1 @@ +(-1|255) diff --git a/Tests/RunCMake/ctest_test/TestRepeatBad1-stderr.txt b/Tests/RunCMake/ctest_test/TestRepeatBad1-stderr.txt new file mode 100644 index 0000000..37cffbf --- /dev/null +++ b/Tests/RunCMake/ctest_test/TestRepeatBad1-stderr.txt @@ -0,0 +1 @@ +Repeat option invalid value: UNKNOWN:3 diff --git a/Tests/RunCMake/ctest_test/TestRepeatBad2-result.txt b/Tests/RunCMake/ctest_test/TestRepeatBad2-result.txt new file mode 100644 index 0000000..b57e2de --- /dev/null +++ b/Tests/RunCMake/ctest_test/TestRepeatBad2-result.txt @@ -0,0 +1 @@ +(-1|255) diff --git a/Tests/RunCMake/ctest_test/TestRepeatBad2-stderr.txt b/Tests/RunCMake/ctest_test/TestRepeatBad2-stderr.txt new file mode 100644 index 0000000..ca5cef7 --- /dev/null +++ b/Tests/RunCMake/ctest_test/TestRepeatBad2-stderr.txt @@ -0,0 +1 @@ +Repeat option invalid value: UNTIL_FAIL:-1 diff --git a/Tests/RunCMake/ctest_test/TestRepeatUntilFail-stdout.txt b/Tests/RunCMake/ctest_test/TestRepeatUntilFail-stdout.txt new file mode 100644 index 0000000..5f91a67 --- /dev/null +++ b/Tests/RunCMake/ctest_test/TestRepeatUntilFail-stdout.txt @@ -0,0 +1,13 @@ +Test project [^ +]*/Tests/RunCMake/ctest_test/TestRepeatUntilFail-build + Start 1: testRepeat + Test #1: testRepeat ....................... Passed +[0-9.]+ sec + Start 1: testRepeat + Test #1: testRepeat .......................\*\*\*Failed +[0-9.]+ sec ++ +0% tests passed, 1 tests failed out of 1 ++ +Total Test time \(real\) = +[0-9.]+ sec ++ +The following tests FAILED: +[ ]+1 - testRepeat \(Failed\)$ diff --git a/Tests/RunCMake/ctest_test/TestRepeatUntilFail.cmake b/Tests/RunCMake/ctest_test/TestRepeatUntilFail.cmake new file mode 100644 index 0000000..5eb0d8a --- /dev/null +++ b/Tests/RunCMake/ctest_test/TestRepeatUntilFail.cmake @@ -0,0 +1,9 @@ +include("${COUNT_FILE}" OPTIONAL) +if(NOT COUNT) + set(COUNT 0) +endif() +math(EXPR COUNT "${COUNT} + 1") +file(WRITE "${COUNT_FILE}" "set(COUNT ${COUNT})\n") +if(COUNT EQUAL 2) + message(FATAL_ERROR "this test fails on the 2nd run") +endif() diff --git a/Tests/RunCMake/ctest_test/TestRepeatUntilPass-stdout.txt b/Tests/RunCMake/ctest_test/TestRepeatUntilPass-stdout.txt new file mode 100644 index 0000000..bc6939a --- /dev/null +++ b/Tests/RunCMake/ctest_test/TestRepeatUntilPass-stdout.txt @@ -0,0 +1,10 @@ +Test project [^ +]*/Tests/RunCMake/ctest_test/TestRepeatUntilPass-build + Start 1: testRepeat +1/1 Test #1: testRepeat .......................\*\*\*Failed +[0-9.]+ sec + Start 1: testRepeat + Test #1: testRepeat ....................... Passed +[0-9.]+ sec ++ +100% tests passed, 0 tests failed out of 1 ++ +Total Test time \(real\) = +[0-9.]+ sec$ diff --git a/Tests/RunCMake/ctest_test/TestRepeatUntilPass.cmake b/Tests/RunCMake/ctest_test/TestRepeatUntilPass.cmake new file mode 100644 index 0000000..0662522 --- /dev/null +++ b/Tests/RunCMake/ctest_test/TestRepeatUntilPass.cmake @@ -0,0 +1,9 @@ +include("${COUNT_FILE}" OPTIONAL) +if(NOT COUNT) + set(COUNT 0) +endif() +math(EXPR COUNT "${COUNT} + 1") +file(WRITE "${COUNT_FILE}" "set(COUNT ${COUNT})\n") +if(NOT COUNT EQUAL 2) + message(FATAL_ERROR "this test passes only on the 2nd run") +endif() diff --git a/Tests/RunCMake/file/RunCMakeTest.cmake b/Tests/RunCMake/file/RunCMakeTest.cmake index 5db4b3b..8d1b981 100644 --- a/Tests/RunCMake/file/RunCMakeTest.cmake +++ b/Tests/RunCMake/file/RunCMakeTest.cmake @@ -69,7 +69,7 @@ if(NOT WIN32 OR CYGWIN) run_cmake(INSTALL-FOLLOW_SYMLINK_CHAIN) endif() -if(RunCMake_GENERATOR STREQUAL "Ninja") +if(RunCMake_GENERATOR MATCHES "Ninja") # Detect ninja version so we know what tests can be supported. execute_process( COMMAND "${RunCMake_MAKE_PROGRAM}" --version @@ -90,7 +90,7 @@ if(RunCMake_GENERATOR STREQUAL "Ninja") endif() endif() -if(RunCMake_GENERATOR STREQUAL "Ninja" AND "${ninja_version}" VERSION_LESS 1.8) +if(RunCMake_GENERATOR MATCHES "Ninja" AND "${ninja_version}" VERSION_LESS 1.8) run_cmake(GLOB_RECURSE-warn-CONFIGURE_DEPENDS-ninja-version) else() run_cmake(GLOB-warn-CONFIGURE_DEPENDS-late) diff --git a/Tests/RunCMake/foreach/RunCMakeTest.cmake b/Tests/RunCMake/foreach/RunCMakeTest.cmake index 4b74cfe..8f50203 100644 --- a/Tests/RunCMake/foreach/RunCMakeTest.cmake +++ b/Tests/RunCMake/foreach/RunCMakeTest.cmake @@ -1,3 +1,14 @@ include(RunCMake) run_cmake(BadRangeInFunction) +run_cmake(foreach-all-test) +run_cmake(foreach-ITEMS-multiple-iter-vars-test) +run_cmake(foreach-LISTS-multiple-iter-vars-test) +run_cmake(foreach-ZIP_LISTS-test) +run_cmake(foreach-ITEMS-with-ZIP_LISTS-mix-test) +run_cmake(foreach-LISTS-with-ZIP_LISTS-mix-test) +run_cmake(foreach-ZIP_LISTS-with-ITEMS-mix-test) +run_cmake(foreach-ZIP_LISTS-with-LISTS-mix-test) +run_cmake(foreach-ZIP_LISTS-multiple-iter-vars-test) +run_cmake(foreach-ZIP_LISTS-iter-vars-mismatch-test-1) +run_cmake(foreach-ZIP_LISTS-iter-vars-mismatch-test-2) diff --git a/Tests/RunCMake/foreach/foreach-ITEMS-multiple-iter-vars-test-result.txt b/Tests/RunCMake/foreach/foreach-ITEMS-multiple-iter-vars-test-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/foreach/foreach-ITEMS-multiple-iter-vars-test-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/foreach/foreach-ITEMS-multiple-iter-vars-test-stderr.txt b/Tests/RunCMake/foreach/foreach-ITEMS-multiple-iter-vars-test-stderr.txt new file mode 100644 index 0000000..d174bb1 --- /dev/null +++ b/Tests/RunCMake/foreach/foreach-ITEMS-multiple-iter-vars-test-stderr.txt @@ -0,0 +1,4 @@ +^CMake Error at foreach-ITEMS-multiple-iter-vars-test.cmake:1 \(foreach\): + ITEMS or LISTS require exactly one iteration variable +Call Stack \(most recent call first\): + CMakeLists.txt:3 \(include\) diff --git a/Tests/RunCMake/foreach/foreach-ITEMS-multiple-iter-vars-test.cmake b/Tests/RunCMake/foreach/foreach-ITEMS-multiple-iter-vars-test.cmake new file mode 100644 index 0000000..55d33a8 --- /dev/null +++ b/Tests/RunCMake/foreach/foreach-ITEMS-multiple-iter-vars-test.cmake @@ -0,0 +1,2 @@ +foreach(one two IN ITEMS one two) +endforeach() diff --git a/Tests/RunCMake/foreach/foreach-ITEMS-with-ZIP_LISTS-mix-test-result.txt b/Tests/RunCMake/foreach/foreach-ITEMS-with-ZIP_LISTS-mix-test-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/foreach/foreach-ITEMS-with-ZIP_LISTS-mix-test-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/foreach/foreach-ITEMS-with-ZIP_LISTS-mix-test-stderr.txt b/Tests/RunCMake/foreach/foreach-ITEMS-with-ZIP_LISTS-mix-test-stderr.txt new file mode 100644 index 0000000..f7d5ae7 --- /dev/null +++ b/Tests/RunCMake/foreach/foreach-ITEMS-with-ZIP_LISTS-mix-test-stderr.txt @@ -0,0 +1,4 @@ +^CMake Error at foreach-ITEMS-with-ZIP_LISTS-mix-test.cmake:1 \(foreach\): + ZIP_LISTS can not be used with LISTS or ITEMS +Call Stack \(most recent call first\): + CMakeLists.txt:3 \(include\) diff --git a/Tests/RunCMake/foreach/foreach-ITEMS-with-ZIP_LISTS-mix-test.cmake b/Tests/RunCMake/foreach/foreach-ITEMS-with-ZIP_LISTS-mix-test.cmake new file mode 100644 index 0000000..28099a0 --- /dev/null +++ b/Tests/RunCMake/foreach/foreach-ITEMS-with-ZIP_LISTS-mix-test.cmake @@ -0,0 +1,2 @@ +foreach(i IN ITEMS one two three ZIP_LISTS blah) +endforeach() diff --git a/Tests/RunCMake/foreach/foreach-LISTS-multiple-iter-vars-test-result.txt b/Tests/RunCMake/foreach/foreach-LISTS-multiple-iter-vars-test-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/foreach/foreach-LISTS-multiple-iter-vars-test-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/foreach/foreach-LISTS-multiple-iter-vars-test-stderr.txt b/Tests/RunCMake/foreach/foreach-LISTS-multiple-iter-vars-test-stderr.txt new file mode 100644 index 0000000..f2f83c2 --- /dev/null +++ b/Tests/RunCMake/foreach/foreach-LISTS-multiple-iter-vars-test-stderr.txt @@ -0,0 +1,4 @@ +^CMake Error at foreach-LISTS-multiple-iter-vars-test.cmake:1 \(foreach\): + ITEMS or LISTS require exactly one iteration variable +Call Stack \(most recent call first\): + CMakeLists.txt:3 \(include\) diff --git a/Tests/RunCMake/foreach/foreach-LISTS-multiple-iter-vars-test.cmake b/Tests/RunCMake/foreach/foreach-LISTS-multiple-iter-vars-test.cmake new file mode 100644 index 0000000..78f3847 --- /dev/null +++ b/Tests/RunCMake/foreach/foreach-LISTS-multiple-iter-vars-test.cmake @@ -0,0 +1,2 @@ +foreach(one two IN LISTS one two) +endforeach() diff --git a/Tests/RunCMake/foreach/foreach-LISTS-with-ZIP_LISTS-mix-test-result.txt b/Tests/RunCMake/foreach/foreach-LISTS-with-ZIP_LISTS-mix-test-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/foreach/foreach-LISTS-with-ZIP_LISTS-mix-test-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/foreach/foreach-LISTS-with-ZIP_LISTS-mix-test-stderr.txt b/Tests/RunCMake/foreach/foreach-LISTS-with-ZIP_LISTS-mix-test-stderr.txt new file mode 100644 index 0000000..42f8d1e --- /dev/null +++ b/Tests/RunCMake/foreach/foreach-LISTS-with-ZIP_LISTS-mix-test-stderr.txt @@ -0,0 +1,4 @@ +^CMake Error at foreach-LISTS-with-ZIP_LISTS-mix-test.cmake:1 \(foreach\): + ZIP_LISTS can not be used with LISTS or ITEMS +Call Stack \(most recent call first\): + CMakeLists.txt:3 \(include\) diff --git a/Tests/RunCMake/foreach/foreach-LISTS-with-ZIP_LISTS-mix-test.cmake b/Tests/RunCMake/foreach/foreach-LISTS-with-ZIP_LISTS-mix-test.cmake new file mode 100644 index 0000000..8a919dd --- /dev/null +++ b/Tests/RunCMake/foreach/foreach-LISTS-with-ZIP_LISTS-mix-test.cmake @@ -0,0 +1,2 @@ +foreach(i IN LISTS one two three ZIP_LISTS blah) +endforeach() diff --git a/Tests/RunCMake/foreach/foreach-ZIP_LISTS-iter-vars-mismatch-test-1-result.txt b/Tests/RunCMake/foreach/foreach-ZIP_LISTS-iter-vars-mismatch-test-1-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/foreach/foreach-ZIP_LISTS-iter-vars-mismatch-test-1-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/foreach/foreach-ZIP_LISTS-iter-vars-mismatch-test-1-stderr.txt b/Tests/RunCMake/foreach/foreach-ZIP_LISTS-iter-vars-mismatch-test-1-stderr.txt new file mode 100644 index 0000000..fa51e46 --- /dev/null +++ b/Tests/RunCMake/foreach/foreach-ZIP_LISTS-iter-vars-mismatch-test-1-stderr.txt @@ -0,0 +1,4 @@ +^CMake Error at foreach-ZIP_LISTS-iter-vars-mismatch-test-1.cmake:1 \(foreach\): + Expected 3 list variables, but given 4 +Call Stack \(most recent call first\): + CMakeLists.txt:3 \(include\) diff --git a/Tests/RunCMake/foreach/foreach-ZIP_LISTS-iter-vars-mismatch-test-1.cmake b/Tests/RunCMake/foreach/foreach-ZIP_LISTS-iter-vars-mismatch-test-1.cmake new file mode 100644 index 0000000..458b6ca --- /dev/null +++ b/Tests/RunCMake/foreach/foreach-ZIP_LISTS-iter-vars-mismatch-test-1.cmake @@ -0,0 +1,2 @@ +foreach(less than lists IN ZIP_LISTS list_1 list_2 list_3 list_4) +endforeach() diff --git a/Tests/RunCMake/foreach/foreach-ZIP_LISTS-iter-vars-mismatch-test-2-result.txt b/Tests/RunCMake/foreach/foreach-ZIP_LISTS-iter-vars-mismatch-test-2-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/foreach/foreach-ZIP_LISTS-iter-vars-mismatch-test-2-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/foreach/foreach-ZIP_LISTS-iter-vars-mismatch-test-2-stderr.txt b/Tests/RunCMake/foreach/foreach-ZIP_LISTS-iter-vars-mismatch-test-2-stderr.txt new file mode 100644 index 0000000..7b6b484 --- /dev/null +++ b/Tests/RunCMake/foreach/foreach-ZIP_LISTS-iter-vars-mismatch-test-2-stderr.txt @@ -0,0 +1,4 @@ +^CMake Error at foreach-ZIP_LISTS-iter-vars-mismatch-test-2.cmake:1 \(foreach\): + Expected 3 list variables, but given 2 +Call Stack \(most recent call first\): + CMakeLists.txt:3 \(include\) diff --git a/Tests/RunCMake/foreach/foreach-ZIP_LISTS-iter-vars-mismatch-test-2.cmake b/Tests/RunCMake/foreach/foreach-ZIP_LISTS-iter-vars-mismatch-test-2.cmake new file mode 100644 index 0000000..d24d99c --- /dev/null +++ b/Tests/RunCMake/foreach/foreach-ZIP_LISTS-iter-vars-mismatch-test-2.cmake @@ -0,0 +1,2 @@ +foreach(greater than lists IN ZIP_LISTS list_1 list_2) +endforeach() diff --git a/Tests/RunCMake/foreach/foreach-ZIP_LISTS-multiple-iter-vars-test-stdout.txt b/Tests/RunCMake/foreach/foreach-ZIP_LISTS-multiple-iter-vars-test-stdout.txt new file mode 100644 index 0000000..e009d15 --- /dev/null +++ b/Tests/RunCMake/foreach/foreach-ZIP_LISTS-multiple-iter-vars-test-stdout.txt @@ -0,0 +1,6 @@ +-- foreach\(\.\.\. IN ZIP_LISTS\): +-- Begin output +-- | one, satu, raz +-- | two, dua, dva +-- | three, tiga, tri +-- End output diff --git a/Tests/RunCMake/foreach/foreach-ZIP_LISTS-multiple-iter-vars-test.cmake b/Tests/RunCMake/foreach/foreach-ZIP_LISTS-multiple-iter-vars-test.cmake new file mode 100644 index 0000000..9647dea --- /dev/null +++ b/Tests/RunCMake/foreach/foreach-ZIP_LISTS-multiple-iter-vars-test.cmake @@ -0,0 +1,42 @@ +function(foreachTest result list_var_1 list_var_2 list_var_3) + set(_options MUTE) + set(_one_value_args) + set(_multi_value_args) + cmake_parse_arguments(PARSE_ARGV 3 _arg "${_options}" "${_one_value_args}" "${_multi_value_args}") + + set(_has_any_output FALSE) + list(APPEND CMAKE_MESSAGE_INDENT "| ") + foreach(first second third IN ZIP_LISTS ${list_var_1} ${list_var_2} ${list_var_3}) + if(NOT first) + set(first "[undefiend]") + endif() + if(NOT second) + set(second "[undefiend]") + endif() + if(NOT third) + set(third "[undefiend]") + endif() + if(NOT _arg_MUTE) + message(STATUS "${first}, ${second}, ${third}") + endif() + set(_has_any_output TRUE) + endforeach() + set(${result} ${_has_any_output} PARENT_SCOPE) +endfunction() + +function(foreachTestDecorated list_var_1 list_var_2 list_var_3) + list(APPEND CMAKE_MESSAGE_INDENT " ") + message(STATUS "Begin output") + foreachTest(_has_any_output ${list_var_1} ${list_var_2} ${list_var_3}) + if(NOT _has_any_output) + message(STATUS "--> empty-output <--") + endif() + message(STATUS "End output") +endfunction() + +list(APPEND english one two three) +list(APPEND bahasa satu dua tiga) +list(APPEND russian raz dva tri) + +message(STATUS "foreach(... IN ZIP_LISTS):") +foreachTestDecorated(english bahasa russian) diff --git a/Tests/RunCMake/foreach/foreach-ZIP_LISTS-test-stdout.txt b/Tests/RunCMake/foreach/foreach-ZIP_LISTS-test-stdout.txt new file mode 100644 index 0000000..25433fd --- /dev/null +++ b/Tests/RunCMake/foreach/foreach-ZIP_LISTS-test-stdout.txt @@ -0,0 +1,19 @@ +-- foreach\(IN ZIP_LISTS\): +-- <<< empty lists case >>> +-- Begin output +-- --> empty-output <-- +-- End output +-- <<< same lengths lists case >>> +-- Begin output +-- | one, satu, raz +-- | two, dua, dva +-- | three, tiga, tri +-- End output +-- <<< different lengths lists case >>> +-- Begin output +-- | one, satu, raz +-- | two, dua, dva +-- | three, tiga, tri +-- | \[undefiend\], empat, \[undefiend\] +-- End output +-- <<< test variable value restored -- PASSED >>> diff --git a/Tests/RunCMake/foreach/foreach-ZIP_LISTS-test.cmake b/Tests/RunCMake/foreach/foreach-ZIP_LISTS-test.cmake new file mode 100644 index 0000000..56cfe64 --- /dev/null +++ b/Tests/RunCMake/foreach/foreach-ZIP_LISTS-test.cmake @@ -0,0 +1,68 @@ +function(foreachTest result list_var_1 list_var_2 list_var_3) + set(_options MUTE) + set(_one_value_args) + set(_multi_value_args) + cmake_parse_arguments(PARSE_ARGV 3 _arg "${_options}" "${_one_value_args}" "${_multi_value_args}") + + set(_has_any_output FALSE) + list(APPEND CMAKE_MESSAGE_INDENT "| ") + foreach(num IN ZIP_LISTS ${list_var_1} ${list_var_2} ${list_var_3}) + foreach(i RANGE 2) + if(NOT num_${i}) + set(num_${i} "[undefiend]") + endif() + endforeach() + if(NOT _arg_MUTE) + message(STATUS "${num_0}, ${num_1}, ${num_2}") + endif() + set(_has_any_output TRUE) + endforeach() + set(${result} ${_has_any_output} PARENT_SCOPE) +endfunction() + +function(foreachTestDecorated list_var_1 list_var_2 list_var_3) + list(APPEND CMAKE_MESSAGE_INDENT " ") + message(STATUS "Begin output") + foreachTest(_has_any_output ${list_var_1} ${list_var_2} ${list_var_3}) + if(NOT _has_any_output) + message(STATUS "--> empty-output <--") + endif() + message(STATUS "End output") +endfunction() + +message(STATUS "foreach(IN ZIP_LISTS):") +list(APPEND CMAKE_MESSAGE_INDENT " ") + +set(english) +set(bahasa) +set(russian) + +message(STATUS "<<< empty lists case >>>") +foreachTestDecorated(english bahasa russian) + +list(APPEND english one two three) +list(APPEND bahasa satu dua tiga) +list(APPEND russian raz dva tri) + +message(STATUS "<<< same lengths lists case >>>") +foreachTestDecorated(english bahasa russian) + +list(APPEND bahasa empat) + +message(STATUS "<<< different lengths lists case >>>") +foreachTestDecorated(english bahasa russian) + +set(num_0 "old-0") +set(num_1 "old-1") +set(num_2 "old-2") +foreachTest(_ english bahasa russian MUTE) +set(check PASSED) +foreach(i RANGE 2) + if(NOT "${num_${i}}" STREQUAL "old-${i}") + message(SEND_ERROR "num_${i} value is corrupted") + set(check FAILED) + endif() +endforeach() +message(STATUS "<<< test variable value restored -- ${check} >>>") + +list(POP_BACK CMAKE_MESSAGE_INDENT) diff --git a/Tests/RunCMake/foreach/foreach-ZIP_LISTS-with-ITEMS-mix-test-result.txt b/Tests/RunCMake/foreach/foreach-ZIP_LISTS-with-ITEMS-mix-test-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/foreach/foreach-ZIP_LISTS-with-ITEMS-mix-test-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/foreach/foreach-ZIP_LISTS-with-ITEMS-mix-test-stderr.txt b/Tests/RunCMake/foreach/foreach-ZIP_LISTS-with-ITEMS-mix-test-stderr.txt new file mode 100644 index 0000000..0dcab01 --- /dev/null +++ b/Tests/RunCMake/foreach/foreach-ZIP_LISTS-with-ITEMS-mix-test-stderr.txt @@ -0,0 +1,4 @@ +^CMake Error at foreach-ZIP_LISTS-with-ITEMS-mix-test.cmake:1 \(foreach\): + ZIP_LISTS can not be used with LISTS or ITEMS +Call Stack \(most recent call first\): + CMakeLists.txt:3 \(include\) diff --git a/Tests/RunCMake/foreach/foreach-ZIP_LISTS-with-ITEMS-mix-test.cmake b/Tests/RunCMake/foreach/foreach-ZIP_LISTS-with-ITEMS-mix-test.cmake new file mode 100644 index 0000000..71ed842 --- /dev/null +++ b/Tests/RunCMake/foreach/foreach-ZIP_LISTS-with-ITEMS-mix-test.cmake @@ -0,0 +1,2 @@ +foreach(i IN ZIP_LISTS blah ITEMS blah) +endforeach() diff --git a/Tests/RunCMake/foreach/foreach-ZIP_LISTS-with-LISTS-mix-test-result.txt b/Tests/RunCMake/foreach/foreach-ZIP_LISTS-with-LISTS-mix-test-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/foreach/foreach-ZIP_LISTS-with-LISTS-mix-test-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/foreach/foreach-ZIP_LISTS-with-LISTS-mix-test-stderr.txt b/Tests/RunCMake/foreach/foreach-ZIP_LISTS-with-LISTS-mix-test-stderr.txt new file mode 100644 index 0000000..a6b6e9c --- /dev/null +++ b/Tests/RunCMake/foreach/foreach-ZIP_LISTS-with-LISTS-mix-test-stderr.txt @@ -0,0 +1,4 @@ +^CMake Error at foreach-ZIP_LISTS-with-LISTS-mix-test.cmake:1 \(foreach\): + ZIP_LISTS can not be used with LISTS or ITEMS +Call Stack \(most recent call first\): + CMakeLists.txt:3 \(include\) diff --git a/Tests/RunCMake/foreach/foreach-ZIP_LISTS-with-LISTS-mix-test.cmake b/Tests/RunCMake/foreach/foreach-ZIP_LISTS-with-LISTS-mix-test.cmake new file mode 100644 index 0000000..11a97b2 --- /dev/null +++ b/Tests/RunCMake/foreach/foreach-ZIP_LISTS-with-LISTS-mix-test.cmake @@ -0,0 +1,2 @@ +foreach(i IN ZIP_LISTS blah LISTS blah) +endforeach() diff --git a/Tests/RunCMake/foreach/foreach-all-test-stdout.txt b/Tests/RunCMake/foreach/foreach-all-test-stdout.txt new file mode 100644 index 0000000..e8f622d --- /dev/null +++ b/Tests/RunCMake/foreach/foreach-all-test-stdout.txt @@ -0,0 +1,44 @@ +-- foreach\(RANGE\): +-- \[0\.\.1\]/1 +-- < 0 +-- < 1 +-- \[1\.\.1\]/1 +-- < 1 +-- \[0\.\.10\]/2 +-- < 0 +-- < 2 +-- < 4 +-- < 6 +-- < 8 +-- < 10 +-- \[-10\.\.0\]/3 +-- < -10 +-- < -7 +-- < -4 +-- < -1 +-- \[0\.\.-10\]/-5 +-- < 0 +-- < -5 +-- < -10 +-- foreach\(IN ITEMS\): +-- < one +-- < two +-- < three +-- foreach\(IN LISTS\): +-- < satu +-- < dua +-- < tiga +-- foreach\(IN LISTS and ITEMS\): +-- < satu +-- < dua +-- < tiga +-- < one +-- < two +-- < three +-- foreach\(IN ITEMS and LISTS\): +-- < one +-- < two +-- < three +-- < satu +-- < dua +-- < tiga diff --git a/Tests/RunCMake/foreach/foreach-all-test.cmake b/Tests/RunCMake/foreach/foreach-all-test.cmake new file mode 100644 index 0000000..2e377c8 --- /dev/null +++ b/Tests/RunCMake/foreach/foreach-all-test.cmake @@ -0,0 +1,67 @@ +message(STATUS "foreach(RANGE):") +list(APPEND CMAKE_MESSAGE_INDENT " ") + +message(STATUS "[0..1]/1") +list(APPEND CMAKE_MESSAGE_INDENT " < ") +foreach(i RANGE 1) + message(STATUS ${i}) +endforeach() +list(POP_BACK CMAKE_MESSAGE_INDENT) + +message(STATUS "[1..1]/1") +list(APPEND CMAKE_MESSAGE_INDENT " < ") +foreach(i RANGE 1 1) + message(STATUS ${i}) +endforeach() +list(POP_BACK CMAKE_MESSAGE_INDENT) + +message(STATUS "[0..10]/2") +list(APPEND CMAKE_MESSAGE_INDENT " < ") +foreach(i RANGE 0 10 2) + message(STATUS ${i}) +endforeach() +list(POP_BACK CMAKE_MESSAGE_INDENT) + +message(STATUS "[-10..0]/3") +list(APPEND CMAKE_MESSAGE_INDENT " < ") +foreach(i RANGE -10 0 3) + message(STATUS ${i}) +endforeach() +list(POP_BACK CMAKE_MESSAGE_INDENT) + +message(STATUS "[0..-10]/-5") +list(APPEND CMAKE_MESSAGE_INDENT " < ") +foreach(i RANGE 0 -10 -5) + message(STATUS ${i}) +endforeach() +list(POP_BACK CMAKE_MESSAGE_INDENT) +list(POP_BACK CMAKE_MESSAGE_INDENT) + +message(STATUS "foreach(IN ITEMS):") +list(APPEND CMAKE_MESSAGE_INDENT " < ") +foreach(i IN ITEMS one two three) + message(STATUS ${i}) +endforeach() +list(POP_BACK CMAKE_MESSAGE_INDENT) + +message(STATUS "foreach(IN LISTS):") +list(APPEND CMAKE_MESSAGE_INDENT " < ") +list(APPEND count satu dua tiga) +foreach(i IN LISTS count) + message(STATUS ${i}) +endforeach() +list(POP_BACK CMAKE_MESSAGE_INDENT) + +message(STATUS "foreach(IN LISTS and ITEMS):") +list(APPEND CMAKE_MESSAGE_INDENT " < ") +foreach(i IN LISTS count ITEMS one two three) + message(STATUS ${i}) +endforeach() +list(POP_BACK CMAKE_MESSAGE_INDENT) + +message(STATUS "foreach(IN ITEMS and LISTS):") +list(APPEND CMAKE_MESSAGE_INDENT " < ") +foreach(i IN ITEMS one two three LISTS count) + message(STATUS ${i}) +endforeach() +list(POP_BACK CMAKE_MESSAGE_INDENT) diff --git a/Tests/RunCMake/function/CMAKE_CURRENT_FUNCTION-stdout.txt b/Tests/RunCMake/function/CMAKE_CURRENT_FUNCTION-stdout.txt new file mode 100644 index 0000000..5ebc89a --- /dev/null +++ b/Tests/RunCMake/function/CMAKE_CURRENT_FUNCTION-stdout.txt @@ -0,0 +1,7 @@ +function\(print_self\) + file\(STRINGS "\${CMAKE_CURRENT_FUNCTION_LIST_FILE}" _lines\) + math\(EXPR _begin "\${CMAKE_CURRENT_FUNCTION_LIST_LINE} - 1"\) + list\(SUBLIST _lines \${_begin} 7 _lines\) # This function has 7 lines only + list\(JOIN _lines "\\n" _lines\) + message\(STATUS "Print the `\${CMAKE_CURRENT_FUNCTION}` function:\\n\${_lines}"\) +endfunction\(\) diff --git a/Tests/RunCMake/function/CMAKE_CURRENT_FUNCTION.cmake b/Tests/RunCMake/function/CMAKE_CURRENT_FUNCTION.cmake new file mode 100644 index 0000000..38c032f --- /dev/null +++ b/Tests/RunCMake/function/CMAKE_CURRENT_FUNCTION.cmake @@ -0,0 +1,94 @@ +set(_THIS_FILE "${CMAKE_CURRENT_LIST_FILE}") +set(_THIS_DIR "${CMAKE_CURRENT_LIST_DIR}") + +if(CMAKE_CURRENT_FUNCTION) + message(SEND_ERROR "`CMAKE_CURRENT_FUNCTION` is not expected to be set here") +endif() +if(CMAKE_CURRENT_FUNCTION_LIST_FILE) + message(SEND_ERROR "`CMAKE_CURRENT_FUNCTION_LIST_FILE` is not expected to be set here") +endif() +if(CMAKE_CURRENT_FUNCTION_LIST_DIR) + message(SEND_ERROR "`CMAKE_CURRENT_FUNCTION_LIST_DIR` is not expected to be set here") +endif() +if(CMAKE_CURRENT_FUNCTION_LIST_LINE) + message(SEND_ERROR "`CMAKE_CURRENT_FUNCTION_LIST_LINE` is not expected to be set here") +endif() + +function(bar) + if(NOT CMAKE_CURRENT_FUNCTION STREQUAL "bar") + message(SEND_ERROR "Bad value of `CMAKE_CURRENT_FUNCTION`") + endif() + if(NOT CMAKE_CURRENT_FUNCTION_LIST_FILE MATCHES "^.*/CMAKE_CURRENT_FUNCTION.cmake$") + message(SEND_ERROR "Bad value of `CMAKE_CURRENT_FUNCTION_LIST_FILE`") + endif() + if(NOT CMAKE_CURRENT_FUNCTION_LIST_FILE STREQUAL _THIS_FILE) + message(SEND_ERROR "Bad value of `CMAKE_CURRENT_FUNCTION_LIST_FILE`") + endif() + if(NOT CMAKE_CURRENT_FUNCTION_LIST_DIR MATCHES "^.*/Tests/RunCMake/function$") + message(SEND_ERROR "Bad value of `CMAKE_CURRENT_FUNCTION_LIST_DIR`") + endif() + if(NOT CMAKE_CURRENT_FUNCTION_LIST_DIR STREQUAL _THIS_DIR) + message(SEND_ERROR "Bad value of `CMAKE_CURRENT_FUNCTION_LIST_DIR`") + endif() + if(NOT CMAKE_CURRENT_FUNCTION_LIST_LINE EQUAL 17) + message(SEND_ERROR "Bad value of `CMAKE_CURRENT_FUNCTION_LIST_LINE`") + endif() +endfunction() + +function(foo) + if(NOT CMAKE_CURRENT_FUNCTION STREQUAL "foo") + message(SEND_ERROR "Bad value of `CMAKE_CURRENT_FUNCTION`") + endif() + if(NOT CMAKE_CURRENT_FUNCTION_LIST_FILE MATCHES "^.*/function/CMAKE_CURRENT_FUNCTION.cmake$") + message(SEND_ERROR "Bad value of `CMAKE_CURRENT_FUNCTION_LIST_FILE`") + endif() + if(NOT CMAKE_CURRENT_FUNCTION_LIST_FILE STREQUAL _THIS_FILE) + message(SEND_ERROR "Bad value of `CMAKE_CURRENT_FUNCTION_LIST_FILE`") + endif() + if(NOT CMAKE_CURRENT_FUNCTION_LIST_DIR MATCHES "^.*/Tests/RunCMake/function$") + message(SEND_ERROR "Bad value of `CMAKE_CURRENT_FUNCTION_LIST_DIR`") + endif() + if(NOT CMAKE_CURRENT_FUNCTION_LIST_LINE EQUAL 38) + message(SEND_ERROR "Bad value of `CMAKE_CURRENT_FUNCTION_LIST_LINE`") + endif() + if(NOT CMAKE_CURRENT_FUNCTION_LIST_DIR STREQUAL _THIS_DIR) + message(SEND_ERROR "Bad value of `CMAKE_CURRENT_FUNCTION_LIST_DIR`") + endif() + bar() +endfunction() + +foo() + +if(CMAKE_CURRENT_FUNCTION) + message(SEND_ERROR "`CMAKE_CURRENT_FUNCTION` is not expected to be set here") +endif() +if(CMAKE_CURRENT_FUNCTION_LIST_FILE) + message(SEND_ERROR "`CMAKE_CURRENT_FUNCTION_LIST_FILE` is not expected to be set here") +endif() +if(CMAKE_CURRENT_FUNCTION_LIST_DIR) + message(SEND_ERROR "`CMAKE_CURRENT_FUNCTION_LIST_DIR` is not expected to be set here") +endif() +if(CMAKE_CURRENT_FUNCTION_LIST_LINE) + message(SEND_ERROR "`CMAKE_CURRENT_FUNCTION_LIST_LINE` is not expected to be set here") +endif() + +include("${CMAKE_CURRENT_LIST_DIR}/DummyMacro.cmake") + +function(calling_macro) + dummy() +endfunction() + +calling_macro() + +cmake_policy(SET CMP0007 NEW) + +# ATTENTION `CMAKE_CURRENT_LIST_LINE` can't be used in `math()' +function(print_self) + file(STRINGS "${CMAKE_CURRENT_FUNCTION_LIST_FILE}" _lines) + math(EXPR _begin "${CMAKE_CURRENT_FUNCTION_LIST_LINE} - 1") + list(SUBLIST _lines ${_begin} 7 _lines) # This function has 7 lines only + list(JOIN _lines "\n" _lines) + message(STATUS "Print the `${CMAKE_CURRENT_FUNCTION}` function:\n${_lines}") +endfunction() + +print_self() diff --git a/Tests/RunCMake/function/CMakeLists.txt b/Tests/RunCMake/function/CMakeLists.txt new file mode 100644 index 0000000..2632ffa --- /dev/null +++ b/Tests/RunCMake/function/CMakeLists.txt @@ -0,0 +1,3 @@ +cmake_minimum_required(VERSION 3.16) +project(${RunCMake_TEST} NONE) +include(${RunCMake_TEST}.cmake) diff --git a/Tests/RunCMake/function/DummyMacro.cmake b/Tests/RunCMake/function/DummyMacro.cmake new file mode 100644 index 0000000..1ab53e4 --- /dev/null +++ b/Tests/RunCMake/function/DummyMacro.cmake @@ -0,0 +1,20 @@ +macro(dummy) + if(NOT CMAKE_CURRENT_FUNCTION STREQUAL "calling_macro") + message(SEND_ERROR "Bad value of `CMAKE_CURRENT_FUNCTION`") + endif() + if(NOT CMAKE_CURRENT_FUNCTION_LIST_FILE MATCHES "^.*/function/CMAKE_CURRENT_FUNCTION.cmake$") + message(SEND_ERROR "Bad value of `CMAKE_CURRENT_FUNCTION_LIST_FILE`") + endif() + if(NOT CMAKE_CURRENT_FUNCTION_LIST_FILE STREQUAL _THIS_FILE) + message(SEND_ERROR "Bad value of `CMAKE_CURRENT_FUNCTION_LIST_FILE`") + endif() + if(NOT CMAKE_CURRENT_FUNCTION_LIST_DIR MATCHES "^.*/Tests/RunCMake/function$") + message(SEND_ERROR "Bad value of `CMAKE_CURRENT_FUNCTION_LIST_DIR`") + endif() + if(NOT CMAKE_CURRENT_FUNCTION_LIST_LINE EQUAL 77) + message(SEND_ERROR "Bad value of `CMAKE_CURRENT_FUNCTION_LIST_LINE`") + endif() + if(NOT CMAKE_CURRENT_FUNCTION_LIST_DIR STREQUAL _THIS_DIR) + message(SEND_ERROR "Bad value of `CMAKE_CURRENT_FUNCTION_LIST_DIR`") + endif() +endmacro() diff --git a/Tests/RunCMake/function/RunCMakeTest.cmake b/Tests/RunCMake/function/RunCMakeTest.cmake new file mode 100644 index 0000000..88f48af --- /dev/null +++ b/Tests/RunCMake/function/RunCMakeTest.cmake @@ -0,0 +1,3 @@ +include(RunCMake) + +run_cmake(CMAKE_CURRENT_FUNCTION) diff --git a/Tests/RunCMake/get_property/RunCMakeTest.cmake b/Tests/RunCMake/get_property/RunCMakeTest.cmake index 06a0c67..6e36473 100644 --- a/Tests/RunCMake/get_property/RunCMakeTest.cmake +++ b/Tests/RunCMake/get_property/RunCMakeTest.cmake @@ -27,7 +27,7 @@ run_cmake(NoCache) # don't rely on RunCMake_GENERATOR_IS_MULTI_CONFIG being set correctly # and instead explicitly check for a match against those generators we # expect to be multi-config -if(RunCMake_GENERATOR MATCHES "Visual Studio|Xcode") +if(RunCMake_GENERATOR MATCHES "Visual Studio|Xcode|Ninja Multi-Config") run_cmake(IsMultiConfig) else() run_cmake(NotMultiConfig) diff --git a/Tests/RunCMake/install/TARGETS-FILE_RPATH_CHANGE-new_rpath-stderr.txt b/Tests/RunCMake/install/TARGETS-FILE_RPATH_CHANGE-new_rpath-stderr.txt index 1e123f6..2561263 100644 --- a/Tests/RunCMake/install/TARGETS-FILE_RPATH_CHANGE-new_rpath-stderr.txt +++ b/Tests/RunCMake/install/TARGETS-FILE_RPATH_CHANGE-new_rpath-stderr.txt @@ -1,4 +1,4 @@ -^CMake Warning \(dev\) at TARGETS-FILE_RPATH_CHANGE-new_rpath\.cmake:[0-9]+ \(install\): +CMake Warning \(dev\) at TARGETS-FILE_RPATH_CHANGE-new_rpath\.cmake:[0-9]+ \(install\): Policy CMP0095 is not set: RPATH entries are properly escaped in the intermediary CMake install script\. Run "cmake --help-policy CMP0095" for policy details\. Use the cmake_policy command to set the policy and @@ -20,4 +20,4 @@ CMake Warning \(dev\) at TARGETS-FILE_RPATH_CHANGE-new_rpath\.cmake:[0-9]+ \(ins intermediary cmake_install\.cmake script\. Call Stack \(most recent call first\): CMakeLists\.txt:[0-9]+ \(include\) -This warning is for project developers\. Use -Wno-dev to suppress it\.$ +This warning is for project developers\. Use -Wno-dev to suppress it\. diff --git a/Tests/RunCMake/load_cache/CMakeLists.txt b/Tests/RunCMake/load_cache/CMakeLists.txt new file mode 100644 index 0000000..2632ffa --- /dev/null +++ b/Tests/RunCMake/load_cache/CMakeLists.txt @@ -0,0 +1,3 @@ +cmake_minimum_required(VERSION 3.16) +project(${RunCMake_TEST} NONE) +include(${RunCMake_TEST}.cmake) diff --git a/Tests/RunCMake/load_cache/NewForm_Project.cmake b/Tests/RunCMake/load_cache/NewForm_Project.cmake new file mode 100644 index 0000000..13a450b --- /dev/null +++ b/Tests/RunCMake/load_cache/NewForm_Project.cmake @@ -0,0 +1,16 @@ +load_cache(${CMAKE_CURRENT_BINARY_DIR}/../test_project READ_WITH_PREFIX LOAD_CACHE_TEST_ + CACHE_STRING + CACHE_BOOL + CACHE_INTERNAL) + +if(NOT LOAD_CACHE_TEST_CACHE_STRING STREQUAL "cache string") + message(FATAL_ERROR "CACHE_STRING: was ${CACHE_STRING}, expected \"cache string\"") +endif() + +if(NOT LOAD_CACHE_TEST_CACHE_BOOL) + message(FATAL_ERROR "CACHE_BOOL: was falsey, expected ON") +endif() + +if(NOT LOAD_CACHE_TEST_CACHE_INTERNAL STREQUAL "cache internal") + message(FATAL_ERROR "CACHE_INTERNAL: was ${CACHE_INTENRAL}, expected \"cache internal\"") +endif() diff --git a/Tests/RunCMake/load_cache/NewForm_Script.cmake b/Tests/RunCMake/load_cache/NewForm_Script.cmake new file mode 100644 index 0000000..f3cee92 --- /dev/null +++ b/Tests/RunCMake/load_cache/NewForm_Script.cmake @@ -0,0 +1,16 @@ +load_cache(${RunCMake_BINARY_DIR}/test_project READ_WITH_PREFIX LOAD_CACHE_TEST_ + CACHE_STRING + CACHE_BOOL + CACHE_INTERNAL) + +if(NOT LOAD_CACHE_TEST_CACHE_STRING STREQUAL "cache string") + message(FATAL_ERROR "CACHE_STRING: was ${CACHE_STRING}, expected \"cache string\"") +endif() + +if(NOT LOAD_CACHE_TEST_CACHE_BOOL) + message(FATAL_ERROR "CACHE_BOOL: was falsey, expected ON") +endif() + +if(NOT LOAD_CACHE_TEST_CACHE_INTERNAL STREQUAL "cache internal") + message(FATAL_ERROR "CACHE_INTERNAL: was ${CACHE_INTENRAL}, expected \"cache internal\"") +endif() diff --git a/Tests/RunCMake/load_cache/OldForm_Script-result.txt b/Tests/RunCMake/load_cache/OldForm_Script-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/load_cache/OldForm_Script-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/load_cache/OldForm_Script-stderr.txt b/Tests/RunCMake/load_cache/OldForm_Script-stderr.txt new file mode 100644 index 0000000..9ad5c80 --- /dev/null +++ b/Tests/RunCMake/load_cache/OldForm_Script-stderr.txt @@ -0,0 +1,2 @@ +^CMake Error at.*/Tests/RunCMake/load_cache/OldForm_Script.cmake:1 \(load_cache\): + load_cache Only load_cache\(READ_WITH_PREFIX\) may be used in script mode$ diff --git a/Tests/RunCMake/load_cache/OldForm_Script.cmake b/Tests/RunCMake/load_cache/OldForm_Script.cmake new file mode 100644 index 0000000..9560f61 --- /dev/null +++ b/Tests/RunCMake/load_cache/OldForm_Script.cmake @@ -0,0 +1,13 @@ +load_cache(${RunCMake_BINARY_DIR}/test_project INCLUDE_INTERNALS CACHE_INTERNAL) + +if(NOT CACHE_STRING STREQUAL "cache string") + message(FATAL_ERROR "CACHE_STRING: was ${CACHE_STRING}, expected \"cache string\"") +endif() + +if(NOT CACHE_BOOL) + message(FATAL_ERROR "CACHE_BOOL: was falsey, expected ON") +endif() + +if(NOT CACHE_INTERNAL STREQUAL "cache internal") + message(FATAL_ERROR "CACHE_INTERNAL: was ${CACHE_INTENRAL}, expected \"cache internal\"") +endif() diff --git a/Tests/RunCMake/load_cache/RunCMakeTest.cmake b/Tests/RunCMake/load_cache/RunCMakeTest.cmake new file mode 100644 index 0000000..a0d54ea --- /dev/null +++ b/Tests/RunCMake/load_cache/RunCMakeTest.cmake @@ -0,0 +1,13 @@ +include(RunCMake) + +file(WRITE ${RunCMake_BINARY_DIR}/test_project/CMakeCache.txt [[ +CACHE_STRING:STRING=cache string +CACHE_BOOL:BOOL=ON +CACHE_INTERNAL:INTERNAL=cache internal +]]) + +run_cmake(NewForm_Project) +run_cmake_command(NewForm_Script ${CMAKE_COMMAND} -DRunCMake_BINARY_DIR=${RunCMake_BINARY_DIR} + -P "${RunCMake_SOURCE_DIR}/NewForm_Script.cmake") +run_cmake_command(OldForm_Script ${CMAKE_COMMAND} -DRunCMake_BINARY_DIR=${RunCMake_BINARY_DIR} + -P "${RunCMake_SOURCE_DIR}/OldForm_Script.cmake") diff --git a/Tests/RunCMake/message/RunCMakeTest.cmake b/Tests/RunCMake/message/RunCMakeTest.cmake index 681839d..0313ed1 100644 --- a/Tests/RunCMake/message/RunCMakeTest.cmake +++ b/Tests/RunCMake/message/RunCMakeTest.cmake @@ -65,6 +65,11 @@ foreach(opt IN ITEMS loglevel log-level) endforeach() run_cmake_command( + message-log-level-override + ${CMAKE_COMMAND} --log-level=debug -DCMAKE_MESSAGE_LOG_LEVEL=TRACE -P ${RunCMake_SOURCE_DIR}/message-all-loglevels.cmake + ) + +run_cmake_command( message-indent ${CMAKE_COMMAND} -P ${RunCMake_SOURCE_DIR}/message-indent.cmake ) @@ -72,3 +77,23 @@ run_cmake_command( message-indent-multiline ${CMAKE_COMMAND} -P ${RunCMake_SOURCE_DIR}/message-indent-multiline.cmake ) + +run_cmake_command( + message-context-cli + ${CMAKE_COMMAND} --log-level=trace --log-context -P ${RunCMake_SOURCE_DIR}/message-context.cmake + ) + +run_cmake_command( + message-context-cache + ${CMAKE_COMMAND} -DCMAKE_MESSAGE_LOG_LEVEL=TRACE -DCMAKE_MESSAGE_CONTEXT_SHOW=ON -P ${RunCMake_SOURCE_DIR}/message-context.cmake + ) + +run_cmake_command( + message-context-cli-wins-cache + ${CMAKE_COMMAND} --log-level=verbose --log-context -DCMAKE_MESSAGE_CONTEXT_SHOW=OFF -P ${RunCMake_SOURCE_DIR}/message-context.cmake + ) + +run_cmake_command( + message-checks + ${CMAKE_COMMAND} -P ${RunCMake_SOURCE_DIR}/message-checks.cmake + ) diff --git a/Tests/RunCMake/message/message-checks-stderr.txt b/Tests/RunCMake/message/message-checks-stderr.txt new file mode 100644 index 0000000..fdacdb2 --- /dev/null +++ b/Tests/RunCMake/message/message-checks-stderr.txt @@ -0,0 +1,3 @@ +^CMake Warning \(dev\) at.*/Tests/RunCMake/message/message-checks.cmake:13 \(message\): + Ignored CHECK_FAIL without CHECK_START +This warning is for project developers. Use -Wno-dev to suppress it.$ diff --git a/Tests/RunCMake/message/message-checks-stdout.txt b/Tests/RunCMake/message/message-checks-stdout.txt new file mode 100644 index 0000000..4f5f2ef --- /dev/null +++ b/Tests/RunCMake/message/message-checks-stdout.txt @@ -0,0 +1,10 @@ +-- Find `libfoo` +-- Looking for `libfoo\.h` +-- Looking for `libfoo\.h` - found \[/usr/include\] +-- Looking for `libfoo\.so` +-- Looking for `libfoo\.so` - found \[/usr/lib/libfoo\.so\] +-- Getting `libfoo` version +-- Looking for `libfoo/version\.h` +-- Looking for `libfoo/version\.h` - found +-- Getting `libfoo` version - 1\.2\.3 +-- Find `libfoo` - required version 4\.5\.6 but found 1\.2\.3 diff --git a/Tests/RunCMake/message/message-checks.cmake b/Tests/RunCMake/message/message-checks.cmake new file mode 100644 index 0000000..605846e --- /dev/null +++ b/Tests/RunCMake/message/message-checks.cmake @@ -0,0 +1,13 @@ +message(CHECK_START "Find `libfoo`") +message(CHECK_START "Looking for `libfoo.h`") +message(CHECK_PASS "found [/usr/include]") +message(CHECK_START "Looking for `libfoo.so`") +message(CHECK_PASS "found [/usr/lib/libfoo.so]") +message(CHECK_START "Getting `libfoo` version") +message(CHECK_START "Looking for `libfoo/version.h`") +message(CHECK_PASS "found") +message(CHECK_PASS "1.2.3") +message(CHECK_FAIL "required version 4.5.6 but found 1.2.3") + +# Should generate an error, no associated CHECK_START +message(CHECK_FAIL "unmatched check fail case") diff --git a/Tests/RunCMake/message/message-context-cache-stdout.txt b/Tests/RunCMake/message/message-context-cache-stdout.txt new file mode 100644 index 0000000..af18c15 --- /dev/null +++ b/Tests/RunCMake/message/message-context-cache-stdout.txt @@ -0,0 +1,8 @@ +-- Begin context output test +-- \[top\] Top: before +-- \[top\.foo\.bar\] <-- indent -->bar VERBOSE message +-- \[top\.foo\] foo TRACE message +-- \[top\.foo\.baz\] This is the multi-line +\[top\.foo\.baz\] baz DEBUG message +-- \[top\] Top: after +-- End of context output test diff --git a/Tests/RunCMake/message/message-context-cli-stdout.txt b/Tests/RunCMake/message/message-context-cli-stdout.txt new file mode 100644 index 0000000..af18c15 --- /dev/null +++ b/Tests/RunCMake/message/message-context-cli-stdout.txt @@ -0,0 +1,8 @@ +-- Begin context output test +-- \[top\] Top: before +-- \[top\.foo\.bar\] <-- indent -->bar VERBOSE message +-- \[top\.foo\] foo TRACE message +-- \[top\.foo\.baz\] This is the multi-line +\[top\.foo\.baz\] baz DEBUG message +-- \[top\] Top: after +-- End of context output test diff --git a/Tests/RunCMake/message/message-context-cli-wins-cache-stdout.txt b/Tests/RunCMake/message/message-context-cli-wins-cache-stdout.txt new file mode 100644 index 0000000..157db97 --- /dev/null +++ b/Tests/RunCMake/message/message-context-cli-wins-cache-stdout.txt @@ -0,0 +1,5 @@ +-- Begin context output test +-- \[top\] Top: before +-- \[top\.foo\.bar\] <-- indent -->bar VERBOSE message +-- \[top\] Top: after +-- End of context output test diff --git a/Tests/RunCMake/message/message-context.cmake b/Tests/RunCMake/message/message-context.cmake new file mode 100644 index 0000000..93d4cd9 --- /dev/null +++ b/Tests/RunCMake/message/message-context.cmake @@ -0,0 +1,27 @@ +function(bar) + list(APPEND CMAKE_MESSAGE_CONTEXT "bar") + list(APPEND CMAKE_MESSAGE_INDENT "<-- indent -->") + message(VERBOSE "bar VERBOSE message") +endfunction() + +function(baz) + list(APPEND CMAKE_MESSAGE_CONTEXT "baz") + message(DEBUG "This is the multi-line\nbaz DEBUG message") +endfunction() + +function(foo) + list(APPEND CMAKE_MESSAGE_CONTEXT "foo") + bar() + message(TRACE "foo TRACE message") + baz() +endfunction() + +message(STATUS "Begin context output test") +list(APPEND CMAKE_MESSAGE_CONTEXT "top") + +message(STATUS "Top: before") +foo() +message(STATUS "Top: after") + +list(POP_BACK CMAKE_MESSAGE_CONTEXT) +message(STATUS "End of context output test") diff --git a/Tests/RunCMake/message/message-log-level-debug-stdout.txt b/Tests/RunCMake/message/message-log-level-debug-stdout.txt index 1452137..feee110 100644 --- a/Tests/RunCMake/message/message-log-level-debug-stdout.txt +++ b/Tests/RunCMake/message/message-log-level-debug-stdout.txt @@ -1,3 +1,3 @@ -- STATUS message -- VERBOSE message --- DEBUG message +-- DEBUG message$ diff --git a/Tests/RunCMake/message/message-log-level-default-stdout.txt b/Tests/RunCMake/message/message-log-level-default-stdout.txt index 809f4cc..b5d6acb 100644 --- a/Tests/RunCMake/message/message-log-level-default-stdout.txt +++ b/Tests/RunCMake/message/message-log-level-default-stdout.txt @@ -1 +1 @@ --- STATUS message +-- STATUS message$ diff --git a/Tests/RunCMake/message/message-log-level-override-stderr.txt b/Tests/RunCMake/message/message-log-level-override-stderr.txt new file mode 100644 index 0000000..efec736 --- /dev/null +++ b/Tests/RunCMake/message/message-log-level-override-stderr.txt @@ -0,0 +1,12 @@ +^CMake Deprecation Warning at.*/Tests/RunCMake/message/message-all-loglevels\.cmake:2 \(message\): + Deprecation warning ++ +CMake Warning \(dev\) at.*/Tests/RunCMake/message/message-all-loglevels\.cmake:3 \(message\): + Author warning message +This warning is for project developers\. Use -Wno-dev to suppress it\. ++ +CMake Warning at.*/Tests/RunCMake/message/message-all-loglevels\.cmake:4 \(message\): + Warning message ++ +Default NOTICE message +NOTICE message$ diff --git a/Tests/RunCMake/message/message-log-level-override-stdout.txt b/Tests/RunCMake/message/message-log-level-override-stdout.txt new file mode 100644 index 0000000..feee110 --- /dev/null +++ b/Tests/RunCMake/message/message-log-level-override-stdout.txt @@ -0,0 +1,3 @@ +-- STATUS message +-- VERBOSE message +-- DEBUG message$ diff --git a/Tests/RunCMake/message/message-log-level-status-stdout.txt b/Tests/RunCMake/message/message-log-level-status-stdout.txt index 809f4cc..b5d6acb 100644 --- a/Tests/RunCMake/message/message-log-level-status-stdout.txt +++ b/Tests/RunCMake/message/message-log-level-status-stdout.txt @@ -1 +1 @@ --- STATUS message +-- STATUS message$ diff --git a/Tests/RunCMake/message/message-log-level-trace-stdout.txt b/Tests/RunCMake/message/message-log-level-trace-stdout.txt index 1cfce6f..3d36a7f 100644 --- a/Tests/RunCMake/message/message-log-level-trace-stdout.txt +++ b/Tests/RunCMake/message/message-log-level-trace-stdout.txt @@ -1,4 +1,4 @@ -- STATUS message -- VERBOSE message -- DEBUG message --- TRACE message +-- TRACE message$ diff --git a/Tests/RunCMake/message/message-log-level-verbose-stdout.txt b/Tests/RunCMake/message/message-log-level-verbose-stdout.txt index c15d43f..47c0846 100644 --- a/Tests/RunCMake/message/message-log-level-verbose-stdout.txt +++ b/Tests/RunCMake/message/message-log-level-verbose-stdout.txt @@ -1,2 +1,2 @@ -- STATUS message --- VERBOSE message +-- VERBOSE message$ diff --git a/Tests/RunCMake/message/message-loglevel-debug-stdout.txt b/Tests/RunCMake/message/message-loglevel-debug-stdout.txt index 1452137..feee110 100644 --- a/Tests/RunCMake/message/message-loglevel-debug-stdout.txt +++ b/Tests/RunCMake/message/message-loglevel-debug-stdout.txt @@ -1,3 +1,3 @@ -- STATUS message -- VERBOSE message --- DEBUG message +-- DEBUG message$ diff --git a/Tests/RunCMake/message/message-loglevel-default-stdout.txt b/Tests/RunCMake/message/message-loglevel-default-stdout.txt index 809f4cc..b5d6acb 100644 --- a/Tests/RunCMake/message/message-loglevel-default-stdout.txt +++ b/Tests/RunCMake/message/message-loglevel-default-stdout.txt @@ -1 +1 @@ --- STATUS message +-- STATUS message$ diff --git a/Tests/RunCMake/message/message-loglevel-status-stdout.txt b/Tests/RunCMake/message/message-loglevel-status-stdout.txt index 809f4cc..b5d6acb 100644 --- a/Tests/RunCMake/message/message-loglevel-status-stdout.txt +++ b/Tests/RunCMake/message/message-loglevel-status-stdout.txt @@ -1 +1 @@ --- STATUS message +-- STATUS message$ diff --git a/Tests/RunCMake/message/message-loglevel-trace-stdout.txt b/Tests/RunCMake/message/message-loglevel-trace-stdout.txt index 1cfce6f..3d36a7f 100644 --- a/Tests/RunCMake/message/message-loglevel-trace-stdout.txt +++ b/Tests/RunCMake/message/message-loglevel-trace-stdout.txt @@ -1,4 +1,4 @@ -- STATUS message -- VERBOSE message -- DEBUG message --- TRACE message +-- TRACE message$ diff --git a/Tests/RunCMake/message/message-loglevel-verbose-stdout.txt b/Tests/RunCMake/message/message-loglevel-verbose-stdout.txt index c15d43f..47c0846 100644 --- a/Tests/RunCMake/message/message-loglevel-verbose-stdout.txt +++ b/Tests/RunCMake/message/message-loglevel-verbose-stdout.txt @@ -1,2 +1,2 @@ -- STATUS message --- VERBOSE message +-- VERBOSE message$ diff --git a/Tests/RunCMake/target_link_directories/CMP0099-NEW-basic-check.cmake b/Tests/RunCMake/target_link_directories/CMP0099-NEW-basic-check.cmake new file mode 100644 index 0000000..2fffddd --- /dev/null +++ b/Tests/RunCMake/target_link_directories/CMP0099-NEW-basic-check.cmake @@ -0,0 +1,4 @@ + +if (NOT actual_stdout MATCHES "DIR_INTERFACE") + string (APPEND RunCMake_TEST_FAILED "\nNot found expected 'DIR_INTERFACE'.") +endif() diff --git a/Tests/RunCMake/target_link_directories/CMP0099-NEW-basic-result.txt b/Tests/RunCMake/target_link_directories/CMP0099-NEW-basic-result.txt new file mode 100644 index 0000000..8d98f9d --- /dev/null +++ b/Tests/RunCMake/target_link_directories/CMP0099-NEW-basic-result.txt @@ -0,0 +1 @@ +.* diff --git a/Tests/RunCMake/target_link_directories/CMP0099-NEW.cmake b/Tests/RunCMake/target_link_directories/CMP0099-NEW.cmake new file mode 100644 index 0000000..17dd68e --- /dev/null +++ b/Tests/RunCMake/target_link_directories/CMP0099-NEW.cmake @@ -0,0 +1,4 @@ + +cmake_policy(SET CMP0099 NEW) + +include(${CMAKE_CURRENT_SOURCE_DIR}/CMP0099.cmake) diff --git a/Tests/RunCMake/target_link_directories/CMP0099-OLD-basic-check.cmake b/Tests/RunCMake/target_link_directories/CMP0099-OLD-basic-check.cmake new file mode 100644 index 0000000..16573a7 --- /dev/null +++ b/Tests/RunCMake/target_link_directories/CMP0099-OLD-basic-check.cmake @@ -0,0 +1,4 @@ + +if (actual_stdout MATCHES "DIR_INTERFACE") + string (APPEND RunCMake_TEST_FAILED "\nFound unexpected 'DIR_INTERFACE'.") +endif() diff --git a/Tests/RunCMake/target_link_directories/CMP0099-OLD-basic-result.txt b/Tests/RunCMake/target_link_directories/CMP0099-OLD-basic-result.txt new file mode 100644 index 0000000..8d98f9d --- /dev/null +++ b/Tests/RunCMake/target_link_directories/CMP0099-OLD-basic-result.txt @@ -0,0 +1 @@ +.* diff --git a/Tests/RunCMake/target_link_directories/CMP0099-OLD.cmake b/Tests/RunCMake/target_link_directories/CMP0099-OLD.cmake new file mode 100644 index 0000000..193a4c7 --- /dev/null +++ b/Tests/RunCMake/target_link_directories/CMP0099-OLD.cmake @@ -0,0 +1,4 @@ + +cmake_policy(SET CMP0099 OLD) + +include(${CMAKE_CURRENT_SOURCE_DIR}/CMP0099.cmake) diff --git a/Tests/RunCMake/target_link_directories/CMP0099.cmake b/Tests/RunCMake/target_link_directories/CMP0099.cmake new file mode 100644 index 0000000..a2be279 --- /dev/null +++ b/Tests/RunCMake/target_link_directories/CMP0099.cmake @@ -0,0 +1,14 @@ + +enable_language(C) + +set(CMAKE_VERBOSE_MAKEFILE TRUE) +set(CMAKE_C_USE_RESPONSE_FILE_FOR_LIBRARIES FALSE) + +add_library(LinkDirs_interface INTERFACE) +target_link_directories (LinkDirs_interface INTERFACE "/DIR_INTERFACE"}) + +add_library(LinkDirs_static STATIC lib.c) +target_link_libraries (LinkDirs_static PRIVATE LinkDirs_interface) + +add_executable(LinkDirs_exe exe.c) +target_link_libraries (LinkDirs_exe PRIVATE LinkDirs_static) diff --git a/Tests/RunCMake/target_link_directories/RunCMakeTest.cmake b/Tests/RunCMake/target_link_directories/RunCMakeTest.cmake index b67c598..a74ee25 100644 --- a/Tests/RunCMake/target_link_directories/RunCMakeTest.cmake +++ b/Tests/RunCMake/target_link_directories/RunCMakeTest.cmake @@ -1,3 +1,33 @@ include(RunCMake) +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} ${ARGN}) + + unset(RunCMake_TEST_BINARY_DIR) + unset(RunCMake_TEST_NO_CLEAN) +endmacro() + run_cmake(empty_keyword_args) + +if(RunCMake_GENERATOR MATCHES "(Ninja|Makefiles)" AND + NOT RunCMake_GENERATOR MATCHES "(NMake|Borland)") + set(RunCMake_TEST_OUTPUT_MERGE TRUE) + if (NOT RunCMake_GENERATOR_IS_MULTI_CONFIG) + set(RunCMake_TEST_OPTIONS -DCMAKE_BUILD_TYPE=Release) + endif() + if (RunCMake_GENERATOR MATCHES "Ninja") + set(VERBOSE -- -v) + endif() + + run_cmake(CMP0099-NEW) + run_cmake_target(CMP0099-NEW basic LinkDirs_exe ${VERBOSE}) + + + run_cmake(CMP0099-OLD) + run_cmake_target(CMP0099-OLD basic LinkDirs_exe ${VERBOSE}) + + unset(RunCMake_TEST_OPTIONS) + unset(RunCMake_TEST_OUTPUT_MERGE) +endif() diff --git a/Tests/RunCMake/target_link_directories/exe.c b/Tests/RunCMake/target_link_directories/exe.c new file mode 100644 index 0000000..8488f4e --- /dev/null +++ b/Tests/RunCMake/target_link_directories/exe.c @@ -0,0 +1,4 @@ +int main(void) +{ + return 0; +} diff --git a/Tests/RunCMake/target_link_directories/lib.c b/Tests/RunCMake/target_link_directories/lib.c new file mode 100644 index 0000000..9bbd24c --- /dev/null +++ b/Tests/RunCMake/target_link_directories/lib.c @@ -0,0 +1,7 @@ +#if defined(_WIN32) +__declspec(dllexport) +#endif + int flags_lib(void) +{ + return 0; +} diff --git a/Tests/RunCMake/target_link_options/CMP0099-NEW-basic-check.cmake b/Tests/RunCMake/target_link_options/CMP0099-NEW-basic-check.cmake new file mode 100644 index 0000000..555bc37 --- /dev/null +++ b/Tests/RunCMake/target_link_options/CMP0099-NEW-basic-check.cmake @@ -0,0 +1,4 @@ + +if (NOT actual_stdout MATCHES "BADFLAG_INTERFACE") + string (APPEND RunCMake_TEST_FAILED "\nNot found expected 'BADFLAG_INTERFACE'.") +endif() diff --git a/Tests/RunCMake/target_link_options/CMP0099-NEW-basic-result.txt b/Tests/RunCMake/target_link_options/CMP0099-NEW-basic-result.txt new file mode 100644 index 0000000..8d98f9d --- /dev/null +++ b/Tests/RunCMake/target_link_options/CMP0099-NEW-basic-result.txt @@ -0,0 +1 @@ +.* diff --git a/Tests/RunCMake/target_link_options/CMP0099-NEW.cmake b/Tests/RunCMake/target_link_options/CMP0099-NEW.cmake new file mode 100644 index 0000000..17dd68e --- /dev/null +++ b/Tests/RunCMake/target_link_options/CMP0099-NEW.cmake @@ -0,0 +1,4 @@ + +cmake_policy(SET CMP0099 NEW) + +include(${CMAKE_CURRENT_SOURCE_DIR}/CMP0099.cmake) diff --git a/Tests/RunCMake/target_link_options/CMP0099-OLD-basic-check.cmake b/Tests/RunCMake/target_link_options/CMP0099-OLD-basic-check.cmake new file mode 100644 index 0000000..4f159f1 --- /dev/null +++ b/Tests/RunCMake/target_link_options/CMP0099-OLD-basic-check.cmake @@ -0,0 +1,4 @@ + +if (actual_stdout MATCHES "BADFLAG_INTERFACE") + string (APPEND RunCMake_TEST_FAILED "\nFound unexpected 'BADFLAG_INTERFACE'.") +endif() diff --git a/Tests/RunCMake/target_link_options/CMP0099-OLD-basic-result.txt b/Tests/RunCMake/target_link_options/CMP0099-OLD-basic-result.txt new file mode 100644 index 0000000..8d98f9d --- /dev/null +++ b/Tests/RunCMake/target_link_options/CMP0099-OLD-basic-result.txt @@ -0,0 +1 @@ +.* diff --git a/Tests/RunCMake/target_link_options/CMP0099-OLD.cmake b/Tests/RunCMake/target_link_options/CMP0099-OLD.cmake new file mode 100644 index 0000000..193a4c7 --- /dev/null +++ b/Tests/RunCMake/target_link_options/CMP0099-OLD.cmake @@ -0,0 +1,4 @@ + +cmake_policy(SET CMP0099 OLD) + +include(${CMAKE_CURRENT_SOURCE_DIR}/CMP0099.cmake) diff --git a/Tests/RunCMake/target_link_options/CMP0099.cmake b/Tests/RunCMake/target_link_options/CMP0099.cmake new file mode 100644 index 0000000..edb457e --- /dev/null +++ b/Tests/RunCMake/target_link_options/CMP0099.cmake @@ -0,0 +1,19 @@ + +enable_language(C) + +set(obj "${CMAKE_C_OUTPUT_EXTENSION}") +if(BORLAND) + set(pre -) +endif() + +add_library(LinkOptions_interface INTERFACE) +target_link_options (LinkOptions_interface INTERFACE ${pre}BADFLAG_INTERFACE${obj}) + +add_library(LinkOptions_static1 STATIC LinkOptionsLib.c) +target_link_libraries (LinkOptions_static1 PRIVATE LinkOptions_interface) + +add_library(LinkOptions_static2 STATIC LinkOptionsLib.c) +target_link_libraries (LinkOptions_static2 PRIVATE LinkOptions_static1) + +add_executable(LinkOptions_exe LinkOptionsExe.c) +target_link_libraries (LinkOptions_exe PRIVATE LinkOptions_static2) diff --git a/Tests/RunCMake/target_link_options/LINKER_expansion.cmake b/Tests/RunCMake/target_link_options/LINKER_expansion.cmake index b344867..f86d19f 100644 --- a/Tests/RunCMake/target_link_options/LINKER_expansion.cmake +++ b/Tests/RunCMake/target_link_options/LINKER_expansion.cmake @@ -1,6 +1,13 @@ enable_language(C) +set(cfg_dir) +get_property(_isMultiConfig GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG) +if(_isMultiConfig) + set(cfg_dir /Debug) +endif() +set(DUMP_EXE "${CMAKE_CURRENT_BINARY_DIR}${cfg_dir}/dump${CMAKE_EXECUTABLE_SUFFIX}") + add_executable(dump dump.c) # ensure no temp file will be used @@ -13,7 +20,7 @@ add_library(linker SHARED LinkOptionsLib.c) target_link_options(linker PRIVATE "LINKER:-foo,bar") # use LAUNCH facility to dump linker command -set_property(TARGET linker PROPERTY RULE_LAUNCH_LINK "\"${CMAKE_CURRENT_BINARY_DIR}/dump${CMAKE_EXECUTABLE_SUFFIX}\"") +set_property(TARGET linker PROPERTY RULE_LAUNCH_LINK "\"${DUMP_EXE}\"") add_dependencies (linker dump) @@ -23,7 +30,7 @@ add_library(linker_shell SHARED LinkOptionsLib.c) target_link_options(linker_shell PRIVATE "LINKER:SHELL:-foo bar") # use LAUNCH facility to dump linker command -set_property(TARGET linker_shell PROPERTY RULE_LAUNCH_LINK "\"${CMAKE_CURRENT_BINARY_DIR}/dump${CMAKE_EXECUTABLE_SUFFIX}\"") +set_property(TARGET linker_shell PROPERTY RULE_LAUNCH_LINK "\"${DUMP_EXE}\"") add_dependencies (linker_shell dump) diff --git a/Tests/RunCMake/target_link_options/RunCMakeTest.cmake b/Tests/RunCMake/target_link_options/RunCMakeTest.cmake index 1d9ef8b..cdfdd7b 100644 --- a/Tests/RunCMake/target_link_options/RunCMakeTest.cmake +++ b/Tests/RunCMake/target_link_options/RunCMakeTest.cmake @@ -41,3 +41,21 @@ if(RunCMake_GENERATOR MATCHES "(Ninja|Makefile)") endif() run_cmake(empty_keyword_args) + +if (NOT CMAKE_C_COMPILER_ID STREQUAL "Intel") + # Intel compiler does not reject bad flags or objects! + set(RunCMake_TEST_OUTPUT_MERGE TRUE) + if (NOT RunCMake_GENERATOR_IS_MULTI_CONFIG) + set(RunCMake_TEST_OPTIONS -DCMAKE_BUILD_TYPE=Release) + endif() + + run_cmake(CMP0099-NEW) + run_cmake_target(CMP0099-NEW basic LinkOptions_exe) + + + run_cmake(CMP0099-OLD) + run_cmake_target(CMP0099-OLD basic LinkOptions_exe) + + unset(RunCMake_TEST_OPTIONS) + unset(RunCMake_TEST_OUTPUT_MERGE) +endif() diff --git a/Tests/RunCMake/try_compile/RunCMakeTest.cmake b/Tests/RunCMake/try_compile/RunCMakeTest.cmake index 91f014e..e838b2d 100644 --- a/Tests/RunCMake/try_compile/RunCMakeTest.cmake +++ b/Tests/RunCMake/try_compile/RunCMakeTest.cmake @@ -49,11 +49,7 @@ if(CMAKE_OBJCXX_STANDARD_DEFAULT) run_cmake(ObjCxxStandard) endif() if(CMake_TEST_CUDA) - if(CMAKE_HOST_WIN32) - run_cmake(CudaStandardNoDefault) - else() - run_cmake(CudaStandard) - endif() + run_cmake(CudaStandard) endif() if(CMAKE_C_COMPILER_ID STREQUAL "GNU" AND NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 4.4) run_cmake(CStandardGNU) diff --git a/Tests/StagingPrefix/CMakeLists.txt b/Tests/StagingPrefix/CMakeLists.txt index 8d2519e..9ed5c12 100644 --- a/Tests/StagingPrefix/CMakeLists.txt +++ b/Tests/StagingPrefix/CMakeLists.txt @@ -5,7 +5,7 @@ project(StagingPrefix) # Wipe out the install tree add_custom_command( OUTPUT ${CMAKE_BINARY_DIR}/CleanupProject - COMMAND ${CMAKE_COMMAND} -E remove_directory + COMMAND ${CMAKE_COMMAND} -E rm -rf ${CMAKE_BINARY_DIR}/ConsumerBuild ${CMAKE_BINARY_DIR}/ProducerBuild ${CMAKE_BINARY_DIR}/stage diff --git a/Tests/SubDir/Examples/example1/CMakeLists.txt b/Tests/SubDir/Examples/example1/CMakeLists.txt index 20d065e..8ec1c02 100644 --- a/Tests/SubDir/Examples/example1/CMakeLists.txt +++ b/Tests/SubDir/Examples/example1/CMakeLists.txt @@ -3,5 +3,5 @@ project(example1) add_executable(example1 example1.cxx) add_custom_command(TARGET example1 POST_BUILD - COMMAND "${CMAKE_COMMAND}" ARGS -E remove ${SUBDIR_BINARY_DIR}/ShouldBeHere + COMMAND "${CMAKE_COMMAND}" ARGS -E rm -f ${SUBDIR_BINARY_DIR}/ShouldBeHere COMMENT "Remove marker file that should exist because this should not be run") diff --git a/Tests/SubDirSpaces/Some Examples/example1/CMakeLists.txt b/Tests/SubDirSpaces/Some Examples/example1/CMakeLists.txt index 20d065e..8ec1c02 100644 --- a/Tests/SubDirSpaces/Some Examples/example1/CMakeLists.txt +++ b/Tests/SubDirSpaces/Some Examples/example1/CMakeLists.txt @@ -3,5 +3,5 @@ project(example1) add_executable(example1 example1.cxx) add_custom_command(TARGET example1 POST_BUILD - COMMAND "${CMAKE_COMMAND}" ARGS -E remove ${SUBDIR_BINARY_DIR}/ShouldBeHere + COMMAND "${CMAKE_COMMAND}" ARGS -E rm -f ${SUBDIR_BINARY_DIR}/ShouldBeHere COMMENT "Remove marker file that should exist because this should not be run") diff --git a/Tests/VSMidl/CMakeLists.txt b/Tests/VSMidl/CMakeLists.txt index 432506c..3ff7c27 100644 --- a/Tests/VSMidl/CMakeLists.txt +++ b/Tests/VSMidl/CMakeLists.txt @@ -56,8 +56,8 @@ set(source_dir "${base_dir}/src") # ExternalProject_Add(clean-${PROJECT_NAME} DOWNLOAD_COMMAND "" - CONFIGURE_COMMAND ${CMAKE_COMMAND} -E remove_directory "${source_dir}" - BUILD_COMMAND ${CMAKE_COMMAND} -E remove_directory "${binary_dir}" + CONFIGURE_COMMAND ${CMAKE_COMMAND} -E rm -rf "${source_dir}" + BUILD_COMMAND ${CMAKE_COMMAND} -E rm -rf "${binary_dir}" INSTALL_COMMAND "" ) diff --git a/Utilities/CMakeLists.txt b/Utilities/CMakeLists.txt index 0564540..22a3d5a 100644 --- a/Utilities/CMakeLists.txt +++ b/Utilities/CMakeLists.txt @@ -13,7 +13,7 @@ if(CMAKE_DOC_TARBALL) endif() add_custom_command( OUTPUT ${dir}.stamp - COMMAND cmake -E remove_directory ${dir} + COMMAND cmake -E rm -rf ${dir} COMMAND cmake -E tar xf ${CMAKE_DOC_TARBALL} COMMAND cmake -E touch ${dir}.stamp DEPENDS ${CMAKE_DOC_TARBALL} diff --git a/Utilities/GitSetup/setup-user b/Utilities/GitSetup/setup-user index 1af439c..0b98879 100755 --- a/Utilities/GitSetup/setup-user +++ b/Utilities/GitSetup/setup-user @@ -20,12 +20,12 @@ # Project configuration instructions: NONE for (( ; ; )); do - user_name=$(git config user.name || echo '') && - user_email=$(git config user.email || echo '') && - if test -n "$user_name" -a -n "$user_email"; then + ident="$(git var GIT_AUTHOR_IDENT 2>/dev/null | rev | cut -d' ' -f3- | rev)" + + if test -n "$ident"; then echo 'Your commits will record as Author: - '"$user_name <$user_email>"' + '"$ident"' ' && read -ep 'Is the author name and email address above correct? [Y/n] ' correct && if test "$correct" != "n" -a "$correct" != "N"; then diff --git a/Utilities/IWYU/mapping.imp b/Utilities/IWYU/mapping.imp index ef31e8b..3497b53 100644 --- a/Utilities/IWYU/mapping.imp +++ b/Utilities/IWYU/mapping.imp @@ -24,6 +24,7 @@ { include: [ "<bits/shared_ptr.h>", private, "<memory>", public ] }, { include: [ "<bits/std_function.h>", private, "<functional>", public ] }, { include: [ "<bits/refwrap.h>", private, "<functional>", public ] }, + { include: [ "<bits/std_abs.h>", private, "<stdlib.h>", public ] }, { include: [ "<bits/stdint-intn.h>", private, "<stdint.h>", public ] }, { include: [ "<bits/stdint-uintn.h>", private, "<stdint.h>", public ] }, { include: [ "<bits/time.h>", private, "<time.h>", public ] }, @@ -46,6 +47,8 @@ # HACK: iwyu suggests <ext/alloc_traits.h> and <memory> each time vector[] is used. # https://github.com/include-what-you-use/include-what-you-use/issues/166 { include: [ "<ext/alloc_traits.h>", private, "<vector>", public ] }, + { symbol: [ "std::allocator_traits<std::allocator<cmFileLock> >::value_type", private, "<vector>", public ] }, + { symbol: [ "std::allocator_traits<std::allocator<cmFileLockPool::ScopePool> >::value_type", private, "<vector>", public ] }, { symbol: [ "std::allocator_traits<std::allocator<cmComputeComponentGraph::TarjanEntry> >::value_type", private, "<vector>", public ] }, { symbol: [ "std::allocator_traits<std::allocator<cmFortranFile> >::value_type", private, "<vector>", public ] }, { symbol: [ "std::allocator_traits<std::allocator<cmGraphEdgeList> >::value_type", private, "<vector>", public ] }, diff --git a/Utilities/Release/push.bash b/Utilities/Release/push.bash index 1c8efe9..a1c6651 100755 --- a/Utilities/Release/push.bash +++ b/Utilities/Release/push.bash @@ -50,6 +50,9 @@ if test -z "$dir"; then dir="v${version}" fi readonly dir +if ! test -d "${dest}/${dir}"; then + mkdir "${dest}/${dir}" +fi for f in cmake-${version}*; do if ! test -f "${f}"; then diff --git a/Utilities/cmcurl/CMake/cmake_uninstall.cmake.in b/Utilities/cmcurl/CMake/cmake_uninstall.cmake.in index db8e536..5178fd8 100644 --- a/Utilities/cmcurl/CMake/cmake_uninstall.cmake.in +++ b/Utilities/cmcurl/CMake/cmake_uninstall.cmake.in @@ -13,7 +13,7 @@ foreach(file ${files}) message(STATUS "Uninstalling $ENV{DESTDIR}${file}") if(IS_SYMLINK "$ENV{DESTDIR}${file}" OR EXISTS "$ENV{DESTDIR}${file}") exec_program( - "@CMAKE_COMMAND@" ARGS "-E remove \"$ENV{DESTDIR}${file}\"" + "@CMAKE_COMMAND@" ARGS "-E rm -f \"$ENV{DESTDIR}${file}\"" OUTPUT_VARIABLE rm_out RETURN_VALUE rm_retval ) diff --git a/Utilities/std/.gitattributes b/Utilities/std/.gitattributes index cd20549..789a754 100644 --- a/Utilities/std/.gitattributes +++ b/Utilities/std/.gitattributes @@ -1 +1,2 @@ cm/* our-c-style +cmext/* our-c-style diff --git a/Utilities/std/cm/type_traits b/Utilities/std/cm/type_traits new file mode 100644 index 0000000..4dfe17b --- /dev/null +++ b/Utilities/std/cm/type_traits @@ -0,0 +1,53 @@ +// -*-c++-*- +// vim: set ft=cpp: + +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing for details. */ +#ifndef cm_type_traits +#define cm_type_traits + +#include <type_traits> // IWYU pragma: export + +namespace cm { + +#if __cplusplus >= 201402L || (defined(_MSVC_LANG) && _MSVC_LANG >= 201402L) + +// Miscellaneous transformations +template <bool B, typename T = void> +using enable_if_t = std::enable_if_t<B, T>; + +#else + +// Miscellaneous transformations +template <bool B, typename T = void> +using enable_if_t = typename std::enable_if<B, T>::type; + +#endif + +#if __cplusplus >= 201703L || (defined(_MSVC_LANG) && _MSVC_LANG >= 201703) + +// Helper classes +using std::bool_constant; + +// Miscellaneous transformations +using std::invoke_result; +using std::invoke_result_t; + +#else + +// Helper classes +template <bool B> +using bool_constant = std::integral_constant<bool, B>; + +// Miscellaneous transformations +template <typename F, typename... ArgTypes> +using invoke_result = std::result_of<F(ArgTypes...)>; + +template <class F, typename... ArgTypes> +using invoke_result_t = typename invoke_result<F, ArgTypes...>::type; + +#endif + +} // namespace cm + +#endif diff --git a/Utilities/std/cmext/algorithm b/Utilities/std/cmext/algorithm new file mode 100644 index 0000000..609860c --- /dev/null +++ b/Utilities/std/cmext/algorithm @@ -0,0 +1,52 @@ +// -*-c++-*- +// vim: set ft=cpp: + +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing for details. */ +#ifndef cmext_algorithm +#define cmext_algorithm + +#include <algorithm> +#include <iterator> +#include <memory> +#include <utility> +#include <vector> + +#include <cm/type_traits> +#include <cmext/iterator> + +namespace cm { + +template <typename T> +void append(std::vector<std::unique_ptr<T>>& v, + std::vector<std::unique_ptr<T>>&& r) +{ + std::transform(r.begin(), r.end(), std::back_inserter(v), + [](std::unique_ptr<T>& item) { return std::move(item); }); + r.clear(); +} + +template <typename T> +void append(std::vector<T*>& v, std::vector<std::unique_ptr<T>> const& r) +{ + std::transform(r.begin(), r.end(), std::back_inserter(v), + [](const std::unique_ptr<T>& item) { return item.get(); }); +} + +template <typename T, typename InputIt, + cm::enable_if_t<cm::is_input_iterator<InputIt>::value, int> = 0> +void append(std::vector<T>& v, InputIt first, InputIt last) +{ + v.insert(v.end(), first, last); +} + +template <typename T, typename Range, + cm::enable_if_t<cm::is_input_range<Range>::value, int> = 0> +void append(std::vector<T>& v, Range const& r) +{ + v.insert(v.end(), r.begin(), r.end()); +} + +} // namespace cm + +#endif diff --git a/Utilities/std/cmext/iterator b/Utilities/std/cmext/iterator new file mode 100644 index 0000000..ffe94b1 --- /dev/null +++ b/Utilities/std/cmext/iterator @@ -0,0 +1,49 @@ +// -*-c++-*- +// vim: set ft=cpp: + +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing for details. */ +#ifndef cmext_iterator +#define cmext_iterator + +#include <iterator> + +#include <cm/type_traits> + +namespace cm { + +// checks if a type is an iterator type +template <typename I> +using is_iterator = + std::is_integral<typename std::iterator_traits<I>::difference_type>; + +// checks if a type is an input iterator type +template <typename I> +using is_input_iterator = + std::is_base_of<std::input_iterator_tag, + typename std::iterator_traits<I>::iterator_category>; + +// checks if a type is a range type: must have a difference_type type +template <typename Range> +using is_range = cm::bool_constant< + cm::is_iterator<decltype(std::declval<const Range>().begin())>::value && + cm::is_iterator<decltype(std::declval<const Range>().end())>::value>; + +// checks if a type is an input range type: must have methods begin() and end() +// returning an input iterator +template <typename Range> +using is_input_range = +#if defined(_MSC_VER) && _MSC_VER < 1920 + // MS C++ is not able to evaluate complex type introspection, + // so use a simplified version + cm::is_input_iterator<typename Range::const_iterator>; +#else + cm::bool_constant< + cm::is_input_iterator<decltype( + std::declval<const Range>().begin())>::value && + cm::is_input_iterator<decltype(std::declval<const Range>().end())>::value>; +#endif + +} // namespace cm + +#endif diff --git a/Utilities/std/cmext/memory b/Utilities/std/cmext/memory new file mode 100644 index 0000000..540a3de --- /dev/null +++ b/Utilities/std/cmext/memory @@ -0,0 +1,32 @@ +// -*-c++-*- +// vim: set ft=cpp: + +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing for details. */ +#ifndef cmext_memory +#define cmext_memory + +#include <cm/type_traits> + +namespace cm { + +template <typename T, typename O, + cm::enable_if_t< + std::is_pointer<cm::invoke_result_t<decltype(&O::get), O>>::value, + int> = 0> +T& static_reference_cast(O& item) +{ + return *(static_cast<T*>(item.get())); +} +template <typename T, typename O, + cm::enable_if_t< + std::is_pointer<cm::invoke_result_t<decltype(&O::get), O>>::value, + int> = 0> +T& dynamic_reference_cast(O& item) +{ + return *(dynamic_cast<T*>(item.get())); +} + +} // namespace cm + +#endif @@ -294,6 +294,7 @@ CMAKE_CXX_SOURCES="\ cmCreateTestSourceList \ cmCustomCommand \ cmCustomCommandGenerator \ + cmCustomCommandLines \ cmDefinePropertyCommand \ cmDefinitions \ cmDepends \ @@ -372,6 +373,7 @@ CMAKE_CXX_SOURCES="\ cmLDConfigTool \ cmLinkDirectoriesCommand \ cmLinkItem \ + cmLinkItemGraphVisitor \ cmLinkLineComputer \ cmLinkLineDeviceComputer \ cmListCommand \ @@ -1166,10 +1168,20 @@ int check_cxx14() } #endif -#if __cplusplus >= 201703L +#if (__cplusplus >= 201703L || defined(__INTEL_COMPILER) && defined(__cpp_if_constexpr)) #include <optional> +template <typename T, + typename std::invoke_result<decltype(&T::get), T>::type = nullptr> +typename T::pointer get_ptr(T& item) +{ + return item.get(); +} + int check_cxx17() { + // Intel compiler do not handle correctly 'decltype' inside 'invoke_result' + std::unique_ptr<int> u(new int(0)); + get_ptr(u); std::optional<int> oi = 0; return oi.value(); } diff --git a/cmake_uninstall.cmake.in b/cmake_uninstall.cmake.in index d81f62a..b5fc700 100644 --- a/cmake_uninstall.cmake.in +++ b/cmake_uninstall.cmake.in @@ -8,7 +8,7 @@ foreach(file ${files}) message(STATUS "Uninstalling \"$ENV{DESTDIR}${file}\"") if(EXISTS "$ENV{DESTDIR}${file}") exec_program( - "@CMAKE_COMMAND@" ARGS "-E remove \"$ENV{DESTDIR}${file}\"" + "@CMAKE_COMMAND@" ARGS "-E rm -f \"$ENV{DESTDIR}${file}\"" OUTPUT_VARIABLE rm_out RETURN_VALUE rm_retval ) |