diff options
183 files changed, 3025 insertions, 1842 deletions
diff --git a/Auxiliary/bash-completion/cmake b/Auxiliary/bash-completion/cmake index 5d67b0b..8c0c5e8 100644 --- a/Auxiliary/bash-completion/cmake +++ b/Auxiliary/bash-completion/cmake @@ -96,7 +96,7 @@ _cmake() _filedir return ;; - --build|--open) + --build|--install|--open) _filedir -d return ;; diff --git a/Auxiliary/vim/syntax/cmake.vim b/Auxiliary/vim/syntax/cmake.vim index 9610410..7fcdc72 100644 --- a/Auxiliary/vim/syntax/cmake.vim +++ b/Auxiliary/vim/syntax/cmake.vim @@ -353,6 +353,7 @@ syn keyword cmakeProperty contained \ XCODE_EMIT_EFFECTIVE_PLATFORM_NAME \ XCODE_EXPLICIT_FILE_TYPE \ XCODE_FILE_ATTRIBUTES + \ XCODE_GENERATE_SCHEME \ XCODE_LAST_KNOWN_FILE_TYPE \ XCODE_PRODUCT_TYPE \ XCODE_SCHEME_ADDRESS_SANITIZER diff --git a/Help/command/execute_process.rst b/Help/command/execute_process.rst index 3a56dce..2d71352 100644 --- a/Help/command/execute_process.rst +++ b/Help/command/execute_process.rst @@ -22,7 +22,9 @@ Execute one or more child processes. [ERROR_STRIP_TRAILING_WHITESPACE] [ENCODING <name>]) -Runs the given sequence of one or more commands in parallel with the standard +Runs the given sequence of one or more commands. + +Commands are executed concurrently as a pipeline, with the standard output of each process piped to the standard input of the next. A single standard error pipe is used for all processes. @@ -46,8 +48,9 @@ Options: the child processes. ``TIMEOUT`` - The child processes will be terminated if they do not finish in the - specified number of seconds (fractions are allowed). + After the specified number of seconds (fractions allowed), all unfinished + child processes will be terminated, and the ``RESULT_VARIABLE`` will be + set to a string mentioning the "timeout". ``RESULT_VARIABLE`` The variable will be set to contain the result of last child process. @@ -56,9 +59,9 @@ Options: ``RESULTS_VARIABLE <variable>`` The variable will be set to contain the result of all processes as a - :ref:`semicolon-separated list <CMake Language Lists>`, in order of the given ``COMMAND`` - arguments. Each entry will be an integer return code from the - corresponding child or a string describing an error condition. + :ref:`semicolon-separated list <CMake Language Lists>`, in order of the + given ``COMMAND`` arguments. Each entry will be an integer return code + from the corresponding child or a string describing an error condition. ``OUTPUT_VARIABLE``, ``ERROR_VARIABLE`` The variable named will be set with the contents of the standard output diff --git a/Help/command/export.rst b/Help/command/export.rst index b255ee8..ffd60e1 100644 --- a/Help/command/export.rst +++ b/Help/command/export.rst @@ -62,8 +62,13 @@ registry that this command creates works only in conjunction with a package configuration file (``<PackageName>Config.cmake``) that works with the build tree. In some cases, for example for packaging and for system wide installations, it is not desirable to write the user package -registry. If the :variable:`CMAKE_EXPORT_NO_PACKAGE_REGISTRY` variable -is enabled, the ``export(PACKAGE)`` command will do nothing. +registry. + +By default the ``export(PACKAGE)`` command does nothing (see policy +:policy:`CMP0090`) because populating the user package registry has effects +outside the source and build trees. Set the +:variable:`CMAKE_EXPORT_PACKAGE_REGISTRY` variable to add build directories to +the CMake user package registry. .. code-block:: cmake diff --git a/Help/manual/cmake-modules.7.rst b/Help/manual/cmake-modules.7.rst index d9b939f..fc4bfdc 100644 --- a/Help/manual/cmake-modules.7.rst +++ b/Help/manual/cmake-modules.7.rst @@ -125,6 +125,7 @@ They are normally called through the :command:`find_package` command. /module/FindDCMTK /module/FindDevIL /module/FindDoxygen + /module/FindEnvModules /module/FindEXPAT /module/FindFLEX /module/FindFLTK2 diff --git a/Help/manual/cmake-packages.7.rst b/Help/manual/cmake-packages.7.rst index 876ca84..bbe742e 100644 --- a/Help/manual/cmake-packages.7.rst +++ b/Help/manual/cmake-packages.7.rst @@ -647,12 +647,17 @@ Disabling the Package Registry In some cases using the Package Registries is not desirable. CMake allows one to disable them using the following variables: - * :variable:`CMAKE_EXPORT_NO_PACKAGE_REGISTRY` disables the - :command:`export(PACKAGE)` command. - * :variable:`CMAKE_FIND_PACKAGE_NO_PACKAGE_REGISTRY` disables the - User Package Registry in all the :command:`find_package` calls. - * :variable:`CMAKE_FIND_PACKAGE_NO_SYSTEM_PACKAGE_REGISTRY` disables - the System Package Registry in all the :command:`find_package` calls. +* The :command:`export(PACKAGE)` command does not populate the user + package registry when :policy:`CMP0090` is set to ``NEW`` unless the + :variable:`CMAKE_EXPORT_PACKAGE_REGISTRY` variable explicitly enables it. + When :policy:`CMP0090` is *not* set to ``NEW`` then + :command:`export(PACKAGE)` populates the user package registry unless + the :variable:`CMAKE_EXPORT_NO_PACKAGE_REGISTRY` variable explicitly + disables it. +* :variable:`CMAKE_FIND_PACKAGE_NO_PACKAGE_REGISTRY` disables the + User Package Registry in all the :command:`find_package` calls. +* :variable:`CMAKE_FIND_PACKAGE_NO_SYSTEM_PACKAGE_REGISTRY` disables + the System Package Registry in all the :command:`find_package` calls. Package Registry Example ------------------------ diff --git a/Help/manual/cmake-policies.7.rst b/Help/manual/cmake-policies.7.rst index 9470d6c..e89ea3da 100644 --- a/Help/manual/cmake-policies.7.rst +++ b/Help/manual/cmake-policies.7.rst @@ -57,6 +57,7 @@ Policies Introduced by CMake 3.15 .. toctree:: :maxdepth: 1 + CMP0090: export(PACKAGE) does not populate package registry by default. </policy/CMP0090> CMP0089: Compiler id for IBM Clang-based XL compilers is now XLClang. </policy/CMP0089> Policies Introduced by CMake 3.14 @@ -73,6 +74,7 @@ Policies Introduced by CMake 3.14 CMP0083: Add PIE options when linking executable. </policy/CMP0083> CMP0082: Install rules from add_subdirectory() are interleaved with those in caller. </policy/CMP0082> + Policies Introduced by CMake 3.13 ================================= diff --git a/Help/manual/cmake-properties.7.rst b/Help/manual/cmake-properties.7.rst index fce5584..4d4b9ff 100644 --- a/Help/manual/cmake-properties.7.rst +++ b/Help/manual/cmake-properties.7.rst @@ -349,6 +349,7 @@ Properties on Targets /prop_tgt/WINDOWS_EXPORT_ALL_SYMBOLS /prop_tgt/XCODE_ATTRIBUTE_an-attribute /prop_tgt/XCODE_EXPLICIT_FILE_TYPE + /prop_tgt/XCODE_GENERATE_SCHEME /prop_tgt/XCODE_PRODUCT_TYPE /prop_tgt/XCODE_SCHEME_ADDRESS_SANITIZER /prop_tgt/XCODE_SCHEME_ADDRESS_SANITIZER_USE_AFTER_RETURN diff --git a/Help/manual/cmake-variables.7.rst b/Help/manual/cmake-variables.7.rst index 6bb30cb..48d7550 100644 --- a/Help/manual/cmake-variables.7.rst +++ b/Help/manual/cmake-variables.7.rst @@ -159,6 +159,7 @@ Variables that Change Behavior /variable/CMAKE_ERROR_DEPRECATED /variable/CMAKE_ERROR_ON_ABSOLUTE_INSTALL_DESTINATION /variable/CMAKE_EXPORT_COMPILE_COMMANDS + /variable/CMAKE_EXPORT_PACKAGE_REGISTRY /variable/CMAKE_EXPORT_NO_PACKAGE_REGISTRY /variable/CMAKE_FIND_APPBUNDLE /variable/CMAKE_FIND_FRAMEWORK diff --git a/Help/manual/cmake.1.rst b/Help/manual/cmake.1.rst index a3c7834..b67fa3a 100644 --- a/Help/manual/cmake.1.rst +++ b/Help/manual/cmake.1.rst @@ -16,6 +16,9 @@ Synopsis `Build a Project`_ cmake --build <dir> [<options>] [-- <build-tool-options>] + `Install a Project`_ + cmake --install <dir> [<options>] + `Open a Project`_ cmake --open <dir> @@ -39,8 +42,8 @@ buildsystem generator CMake. The above `Synopsis`_ lists various actions the tool can perform as described in sections below. To build a software project with CMake, `Generate a Project Buildsystem`_. -Optionally use **cmake** to `Build a Project`_ or just run the -corresponding build tool (e.g. ``make``) directly. **cmake** can also +Optionally use **cmake** to `Build a Project`_, `Install a Project`_ or just +run the corresponding build tool (e.g. ``make``) directly. **cmake** can also be used to `View Help`_. The other actions are meant for use by software developers writing @@ -302,6 +305,41 @@ following options: Run ``cmake --build`` with no options for quick help. +Install a Project +================= + +CMake provides a command-line signature to install an already-generated +project binary tree: + +.. code-block:: shell + + cmake --install <dir> [<options>] + +This may be used after building a project to run installation without +using the generated build system or the native build tool. +The options are: + +``--install <dir>`` + Project binary directory to install. This is required and must be first. + +``--config <cfg>`` + For multi-configuration tools, choose configuration ``<cfg>``. + +``--component <comp>`` + Component-based install. Only install component ``<comp>``. + +``--prefix <prefix>`` + The installation prefix CMAKE_INSTALL_PREFIX. + +``--strip`` + Strip before installing by setting CMAKE_INSTALL_DO_STRIP. + +``-v, --verbose`` + Enable verbose output. + + This option can be omitted if :envvar:`VERBOSE` environment variable is set. + +Run ``cmake --install`` with no options for quick help. Open a Project ============== @@ -483,6 +521,21 @@ Available commands are: ``tar [cxt][vf][zjJ] file.tar [<options>] [--] [<file>...]`` Create or extract a tar or zip archive. Options are: + ``c`` + Create a new archive containing the specified files. + If used, the <file> argument is mandatory. + ``x`` + Extract to disk from the archive. + ``t`` + List archive contents to stdout. + ``v`` + Produce verbose output. + ``z`` + Compress the resulting archive with gzip. + ``j`` + Compress the resulting archive with bzip2. + ``J`` + Compress the resulting archive with XZ. ``--`` Stop interpreting options and treat all remaining arguments as file names even if they start in ``-``. diff --git a/Help/module/FindEnvModules.rst b/Help/module/FindEnvModules.rst new file mode 100644 index 0000000..72c120f --- /dev/null +++ b/Help/module/FindEnvModules.rst @@ -0,0 +1 @@ +.. cmake-module:: ../../Modules/FindEnvModules.cmake diff --git a/Help/policy/CMP0082.rst b/Help/policy/CMP0082.rst index 7b2ef04..8256444 100644 --- a/Help/policy/CMP0082.rst +++ b/Help/policy/CMP0082.rst @@ -6,9 +6,11 @@ those in caller. CMake 3.13 and lower ran the install rules from :command:`add_subdirectory` after all other install rules, even if :command:`add_subdirectory` was called -before the other install rules. CMake 3.14 and later interleaves these -:command:`add_subdirectory` install rules with the others so that they are -run in the order they are declared. +before the other install rules. CMake 3.14 and above prefer to interleave +these :command:`add_subdirectory` install rules with the others so that +they are run in the order they are declared. This policy provides +compatibility for projects that have not been updated to expect the +new behavior. The ``OLD`` behavior for this policy is to run the install rules from :command:`add_subdirectory` after the other install rules. The ``NEW`` diff --git a/Help/policy/CMP0090.rst b/Help/policy/CMP0090.rst new file mode 100644 index 0000000..720c17c --- /dev/null +++ b/Help/policy/CMP0090.rst @@ -0,0 +1,27 @@ +CMP0090 +------- + +:command:`export(PACKAGE)` does not populate package registry by default. + +In CMake 3.14 and below the :command:`export(PACKAGE)` command populated the +user package registry by default and users needed to set the +:variable:`CMAKE_EXPORT_NO_PACKAGE_REGISTRY` to disable it, e.g. in automated +build and packaging environments. Since the user package registry is stored +outside the build tree, this side effect should not be enabled by default. +Therefore CMake 3.15 and above prefer that :command:`export(PACKAGE)` does +nothing unless an explicit :variable:`CMAKE_EXPORT_PACKAGE_REGISTRY` variable +is set to enable it. This policy provides compatibility with projects that +have not been updated. + +The ``OLD`` behavior for this policy is for :command:`export(PACKAGE)` command +to populate the user package registry unless +:variable:`CMAKE_EXPORT_NO_PACKAGE_REGISTRY` is enabled. +The ``NEW`` behavior is for :command:`export(PACKAGE)` command to do nothing +unless the :variable:`CMAKE_EXPORT_PACKAGE_REGISTRY` is enabled. + +This policy was introduced in CMake version 3.15. Use the +:command:`cmake_policy` command to set it to ``OLD`` or ``NEW`` explicitly. +Unlike most 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_tgt/XCODE_GENERATE_SCHEME.rst b/Help/prop_tgt/XCODE_GENERATE_SCHEME.rst new file mode 100644 index 0000000..a56a210 --- /dev/null +++ b/Help/prop_tgt/XCODE_GENERATE_SCHEME.rst @@ -0,0 +1,39 @@ +XCODE_GENERATE_SCHEME +--------------------- + +If enabled, the Xcode generator will generate schema files. These +are useful to invoke analyze, archive, build-for-testing and test +actions from the command line. + +This property is initialized by the value of the variable +:variable:`CMAKE_XCODE_GENERATE_SCHEME` if it is set when a target +is created. + +The following target properties overwrite the default of the +corresponding settings on the "Diagnostic" tab for each schema file. +Each of those is initialized by the respective ``CMAKE_`` variable +at target creation time. + +- :prop_tgt:`XCODE_SCHEME_ADDRESS_SANITIZER` +- :prop_tgt:`XCODE_SCHEME_ADDRESS_SANITIZER_USE_AFTER_RETURN` +- :prop_tgt:`XCODE_SCHEME_DISABLE_MAIN_THREAD_CHECKER` +- :prop_tgt:`XCODE_SCHEME_DYNAMIC_LIBRARY_LOADS` +- :prop_tgt:`XCODE_SCHEME_DYNAMIC_LINKER_API_USAGE` +- :prop_tgt:`XCODE_SCHEME_GUARD_MALLOC` +- :prop_tgt:`XCODE_SCHEME_MAIN_THREAD_CHECKER_STOP` +- :prop_tgt:`XCODE_SCHEME_MALLOC_GUARD_EDGES` +- :prop_tgt:`XCODE_SCHEME_MALLOC_SCRIBBLE` +- :prop_tgt:`XCODE_SCHEME_MALLOC_STACK` +- :prop_tgt:`XCODE_SCHEME_THREAD_SANITIZER` +- :prop_tgt:`XCODE_SCHEME_THREAD_SANITIZER_STOP` +- :prop_tgt:`XCODE_SCHEME_UNDEFINED_BEHAVIOUR_SANITIZER` +- :prop_tgt:`XCODE_SCHEME_UNDEFINED_BEHAVIOUR_SANITIZER_STOP` +- :prop_tgt:`XCODE_SCHEME_ZOMBIE_OBJECTS` + +The following target properties will be applied on the +"Info" and "Arguments" tab: + +- :prop_tgt:`XCODE_SCHEME_ARGUMENTS` +- :prop_tgt:`XCODE_SCHEME_DEBUG_AS_ROOT` +- :prop_tgt:`XCODE_SCHEME_ENVIRONMENT` +- :prop_tgt:`XCODE_SCHEME_EXECUTABLE` diff --git a/Help/prop_tgt/XCODE_SCHEME_ADDRESS_SANITIZER.rst b/Help/prop_tgt/XCODE_SCHEME_ADDRESS_SANITIZER.rst index 694cd77..cc9bac2 100644 --- a/Help/prop_tgt/XCODE_SCHEME_ADDRESS_SANITIZER.rst +++ b/Help/prop_tgt/XCODE_SCHEME_ADDRESS_SANITIZER.rst @@ -8,5 +8,5 @@ This property is initialized by the value of the variable :variable:`CMAKE_XCODE_SCHEME_ADDRESS_SANITIZER` if it is set when a target is created. -Please refer to the :variable:`CMAKE_XCODE_GENERATE_SCHEME` variable +Please refer to the :prop_tgt:`XCODE_GENERATE_SCHEME` target property documentation to see all Xcode schema related properties. diff --git a/Help/prop_tgt/XCODE_SCHEME_ADDRESS_SANITIZER_USE_AFTER_RETURN.rst b/Help/prop_tgt/XCODE_SCHEME_ADDRESS_SANITIZER_USE_AFTER_RETURN.rst index 2803da0..37a043a 100644 --- a/Help/prop_tgt/XCODE_SCHEME_ADDRESS_SANITIZER_USE_AFTER_RETURN.rst +++ b/Help/prop_tgt/XCODE_SCHEME_ADDRESS_SANITIZER_USE_AFTER_RETURN.rst @@ -8,5 +8,5 @@ This property is initialized by the value of the variable :variable:`CMAKE_XCODE_SCHEME_ADDRESS_SANITIZER_USE_AFTER_RETURN` if it is set when a target is created. -Please refer to the :variable:`CMAKE_XCODE_GENERATE_SCHEME` variable +Please refer to the :prop_tgt:`XCODE_GENERATE_SCHEME` target property documentation to see all Xcode schema related properties. diff --git a/Help/prop_tgt/XCODE_SCHEME_ARGUMENTS.rst b/Help/prop_tgt/XCODE_SCHEME_ARGUMENTS.rst index 2eac4a9..1f228e3 100644 --- a/Help/prop_tgt/XCODE_SCHEME_ARGUMENTS.rst +++ b/Help/prop_tgt/XCODE_SCHEME_ARGUMENTS.rst @@ -6,5 +6,5 @@ section of the generated Xcode scheme. If set to a list of arguments those will be added to the scheme. -Please refer to the :variable:`CMAKE_XCODE_GENERATE_SCHEME` variable +Please refer to the :prop_tgt:`XCODE_GENERATE_SCHEME` target property documentation to see all Xcode schema related properties. diff --git a/Help/prop_tgt/XCODE_SCHEME_DEBUG_AS_ROOT.rst b/Help/prop_tgt/XCODE_SCHEME_DEBUG_AS_ROOT.rst index a53f836..5407e80 100644 --- a/Help/prop_tgt/XCODE_SCHEME_DEBUG_AS_ROOT.rst +++ b/Help/prop_tgt/XCODE_SCHEME_DEBUG_AS_ROOT.rst @@ -3,5 +3,5 @@ XCODE_SCHEME_DEBUG_AS_ROOT Whether to debug the target as 'root'. -Please refer to the :variable:`CMAKE_XCODE_GENERATE_SCHEME` variable +Please refer to the :prop_tgt:`XCODE_GENERATE_SCHEME` target property documentation to see all Xcode schema related properties. diff --git a/Help/prop_tgt/XCODE_SCHEME_DISABLE_MAIN_THREAD_CHECKER.rst b/Help/prop_tgt/XCODE_SCHEME_DISABLE_MAIN_THREAD_CHECKER.rst index 75fc326..1a6fcfd 100644 --- a/Help/prop_tgt/XCODE_SCHEME_DISABLE_MAIN_THREAD_CHECKER.rst +++ b/Help/prop_tgt/XCODE_SCHEME_DISABLE_MAIN_THREAD_CHECKER.rst @@ -8,5 +8,5 @@ This property is initialized by the value of the variable :variable:`CMAKE_XCODE_SCHEME_DISABLE_MAIN_THREAD_CHECKER` if it is set when a target is created. -Please refer to the :variable:`CMAKE_XCODE_GENERATE_SCHEME` variable +Please refer to the :prop_tgt:`XCODE_GENERATE_SCHEME` target property documentation to see all Xcode schema related properties. diff --git a/Help/prop_tgt/XCODE_SCHEME_DYNAMIC_LIBRARY_LOADS.rst b/Help/prop_tgt/XCODE_SCHEME_DYNAMIC_LIBRARY_LOADS.rst index a7fab66..9224022 100644 --- a/Help/prop_tgt/XCODE_SCHEME_DYNAMIC_LIBRARY_LOADS.rst +++ b/Help/prop_tgt/XCODE_SCHEME_DYNAMIC_LIBRARY_LOADS.rst @@ -8,5 +8,5 @@ This property is initialized by the value of the variable :variable:`CMAKE_XCODE_SCHEME_DYNAMIC_LIBRARY_LOADS` if it is set when a target is created. -Please refer to the :variable:`CMAKE_XCODE_GENERATE_SCHEME` variable +Please refer to the :prop_tgt:`XCODE_GENERATE_SCHEME` target property documentation to see all Xcode schema related properties. diff --git a/Help/prop_tgt/XCODE_SCHEME_DYNAMIC_LINKER_API_USAGE.rst b/Help/prop_tgt/XCODE_SCHEME_DYNAMIC_LINKER_API_USAGE.rst index 162fc45..203c803 100644 --- a/Help/prop_tgt/XCODE_SCHEME_DYNAMIC_LINKER_API_USAGE.rst +++ b/Help/prop_tgt/XCODE_SCHEME_DYNAMIC_LINKER_API_USAGE.rst @@ -8,5 +8,5 @@ This property is initialized by the value of the variable :variable:`CMAKE_XCODE_SCHEME_DYNAMIC_LINKER_API_USAGE` if it is set when a target is created. -Please refer to the :variable:`CMAKE_XCODE_GENERATE_SCHEME` variable +Please refer to the :prop_tgt:`XCODE_GENERATE_SCHEME` target property documentation to see all Xcode schema related properties. diff --git a/Help/prop_tgt/XCODE_SCHEME_ENVIRONMENT.rst b/Help/prop_tgt/XCODE_SCHEME_ENVIRONMENT.rst index 1dbd6c4..c6d875e 100644 --- a/Help/prop_tgt/XCODE_SCHEME_ENVIRONMENT.rst +++ b/Help/prop_tgt/XCODE_SCHEME_ENVIRONMENT.rst @@ -8,5 +8,5 @@ If set to a list of environment variables and values of the form ``MYVAR=value`` those environment variables will be added to the scheme. -Please refer to the :variable:`CMAKE_XCODE_GENERATE_SCHEME` variable +Please refer to the :prop_tgt:`XCODE_GENERATE_SCHEME` target property documentation to see all Xcode schema related properties. diff --git a/Help/prop_tgt/XCODE_SCHEME_EXECUTABLE.rst b/Help/prop_tgt/XCODE_SCHEME_EXECUTABLE.rst index d0427e2..104841b 100644 --- a/Help/prop_tgt/XCODE_SCHEME_EXECUTABLE.rst +++ b/Help/prop_tgt/XCODE_SCHEME_EXECUTABLE.rst @@ -5,5 +5,5 @@ Specify path to executable in the Info section of the generated Xcode scheme. If not set the schema generator will select the current target if it is actually executable. -Please refer to the :variable:`CMAKE_XCODE_GENERATE_SCHEME` variable +Please refer to the :prop_tgt:`XCODE_GENERATE_SCHEME` target property documentation to see all Xcode schema related properties. diff --git a/Help/prop_tgt/XCODE_SCHEME_GUARD_MALLOC.rst b/Help/prop_tgt/XCODE_SCHEME_GUARD_MALLOC.rst index 64e1990..c4e83da 100644 --- a/Help/prop_tgt/XCODE_SCHEME_GUARD_MALLOC.rst +++ b/Help/prop_tgt/XCODE_SCHEME_GUARD_MALLOC.rst @@ -8,5 +8,5 @@ This property is initialized by the value of the variable :variable:`CMAKE_XCODE_SCHEME_GUARD_MALLOC` if it is set when a target is created. -Please refer to the :variable:`CMAKE_XCODE_GENERATE_SCHEME` variable +Please refer to the :prop_tgt:`XCODE_GENERATE_SCHEME` target property documentation to see all Xcode schema related properties. diff --git a/Help/prop_tgt/XCODE_SCHEME_MAIN_THREAD_CHECKER_STOP.rst b/Help/prop_tgt/XCODE_SCHEME_MAIN_THREAD_CHECKER_STOP.rst index 99c112f..73992c3 100644 --- a/Help/prop_tgt/XCODE_SCHEME_MAIN_THREAD_CHECKER_STOP.rst +++ b/Help/prop_tgt/XCODE_SCHEME_MAIN_THREAD_CHECKER_STOP.rst @@ -9,5 +9,5 @@ This property is initialized by the value of the variable :variable:`CMAKE_XCODE_SCHEME_MAIN_THREAD_CHECKER_STOP` if it is set when a target is created. -Please refer to the :variable:`CMAKE_XCODE_GENERATE_SCHEME` variable +Please refer to the :prop_tgt:`XCODE_GENERATE_SCHEME` target property documentation to see all Xcode schema related properties. diff --git a/Help/prop_tgt/XCODE_SCHEME_MALLOC_GUARD_EDGES.rst b/Help/prop_tgt/XCODE_SCHEME_MALLOC_GUARD_EDGES.rst index ef3852a..ca761c0 100644 --- a/Help/prop_tgt/XCODE_SCHEME_MALLOC_GUARD_EDGES.rst +++ b/Help/prop_tgt/XCODE_SCHEME_MALLOC_GUARD_EDGES.rst @@ -8,5 +8,5 @@ This property is initialized by the value of the variable :variable:`CMAKE_XCODE_SCHEME_MALLOC_GUARD_EDGES` if it is set when a target is created. -Please refer to the :variable:`CMAKE_XCODE_GENERATE_SCHEME` variable +Please refer to the :prop_tgt:`XCODE_GENERATE_SCHEME` target property documentation to see all Xcode schema related properties. diff --git a/Help/prop_tgt/XCODE_SCHEME_MALLOC_SCRIBBLE.rst b/Help/prop_tgt/XCODE_SCHEME_MALLOC_SCRIBBLE.rst index 75baba2..c5ddb95 100644 --- a/Help/prop_tgt/XCODE_SCHEME_MALLOC_SCRIBBLE.rst +++ b/Help/prop_tgt/XCODE_SCHEME_MALLOC_SCRIBBLE.rst @@ -8,5 +8,5 @@ This property is initialized by the value of the variable :variable:`CMAKE_XCODE_SCHEME_MALLOC_SCRIBBLE` if it is set when a target is created. -Please refer to the :variable:`CMAKE_XCODE_GENERATE_SCHEME` variable +Please refer to the :prop_tgt:`XCODE_GENERATE_SCHEME` target property documentation to see all Xcode schema related properties. diff --git a/Help/prop_tgt/XCODE_SCHEME_MALLOC_STACK.rst b/Help/prop_tgt/XCODE_SCHEME_MALLOC_STACK.rst index 984022c..170f33d 100644 --- a/Help/prop_tgt/XCODE_SCHEME_MALLOC_STACK.rst +++ b/Help/prop_tgt/XCODE_SCHEME_MALLOC_STACK.rst @@ -8,5 +8,5 @@ This property is initialized by the value of the variable :variable:`CMAKE_XCODE_SCHEME_MALLOC_STACK` if it is set when a target is created. -Please refer to the :variable:`CMAKE_XCODE_GENERATE_SCHEME` variable +Please refer to the :prop_tgt:`XCODE_GENERATE_SCHEME` target property documentation to see all Xcode schema related properties. diff --git a/Help/prop_tgt/XCODE_SCHEME_THREAD_SANITIZER.rst b/Help/prop_tgt/XCODE_SCHEME_THREAD_SANITIZER.rst index 825ac5b..bb70141 100644 --- a/Help/prop_tgt/XCODE_SCHEME_THREAD_SANITIZER.rst +++ b/Help/prop_tgt/XCODE_SCHEME_THREAD_SANITIZER.rst @@ -8,5 +8,5 @@ This property is initialized by the value of the variable :variable:`CMAKE_XCODE_SCHEME_THREAD_SANITIZER` if it is set when a target is created. -Please refer to the :variable:`CMAKE_XCODE_GENERATE_SCHEME` variable +Please refer to the :prop_tgt:`XCODE_GENERATE_SCHEME` target property documentation to see all Xcode schema related properties. diff --git a/Help/prop_tgt/XCODE_SCHEME_THREAD_SANITIZER_STOP.rst b/Help/prop_tgt/XCODE_SCHEME_THREAD_SANITIZER_STOP.rst index 86f894e..5deadb1 100644 --- a/Help/prop_tgt/XCODE_SCHEME_THREAD_SANITIZER_STOP.rst +++ b/Help/prop_tgt/XCODE_SCHEME_THREAD_SANITIZER_STOP.rst @@ -8,5 +8,5 @@ This property is initialized by the value of the variable :variable:`CMAKE_XCODE_SCHEME_THREAD_SANITIZER_STOP` if it is set when a target is created. -Please refer to the :variable:`CMAKE_XCODE_GENERATE_SCHEME` variable +Please refer to the :prop_tgt:`XCODE_GENERATE_SCHEME` target property documentation to see all Xcode schema related properties. diff --git a/Help/prop_tgt/XCODE_SCHEME_UNDEFINED_BEHAVIOUR_SANITIZER.rst b/Help/prop_tgt/XCODE_SCHEME_UNDEFINED_BEHAVIOUR_SANITIZER.rst index 829a62e..0cd823d 100644 --- a/Help/prop_tgt/XCODE_SCHEME_UNDEFINED_BEHAVIOUR_SANITIZER.rst +++ b/Help/prop_tgt/XCODE_SCHEME_UNDEFINED_BEHAVIOUR_SANITIZER.rst @@ -8,5 +8,5 @@ This property is initialized by the value of the variable :variable:`CMAKE_XCODE_SCHEME_UNDEFINED_BEHAVIOUR_SANITIZER` if it is set when a target is created. -Please refer to the :variable:`CMAKE_XCODE_GENERATE_SCHEME` variable +Please refer to the :prop_tgt:`XCODE_GENERATE_SCHEME` target property documentation to see all Xcode schema related properties. diff --git a/Help/prop_tgt/XCODE_SCHEME_UNDEFINED_BEHAVIOUR_SANITIZER_STOP.rst b/Help/prop_tgt/XCODE_SCHEME_UNDEFINED_BEHAVIOUR_SANITIZER_STOP.rst index 5e382ca..d1a9bca 100644 --- a/Help/prop_tgt/XCODE_SCHEME_UNDEFINED_BEHAVIOUR_SANITIZER_STOP.rst +++ b/Help/prop_tgt/XCODE_SCHEME_UNDEFINED_BEHAVIOUR_SANITIZER_STOP.rst @@ -9,5 +9,5 @@ This property is initialized by the value of the variable :variable:`CMAKE_XCODE_SCHEME_UNDEFINED_BEHAVIOUR_SANITIZER_STOP` if it is set when a target is created. -Please refer to the :variable:`CMAKE_XCODE_GENERATE_SCHEME` variable +Please refer to the :prop_tgt:`XCODE_GENERATE_SCHEME` target property documentation to see all Xcode schema related properties. diff --git a/Help/prop_tgt/XCODE_SCHEME_ZOMBIE_OBJECTS.rst b/Help/prop_tgt/XCODE_SCHEME_ZOMBIE_OBJECTS.rst index 80b954a..6e70e8b 100644 --- a/Help/prop_tgt/XCODE_SCHEME_ZOMBIE_OBJECTS.rst +++ b/Help/prop_tgt/XCODE_SCHEME_ZOMBIE_OBJECTS.rst @@ -8,5 +8,5 @@ This property is initialized by the value of the variable :variable:`CMAKE_XCODE_SCHEME_ZOMBIE_OBJECTS` if it is set when a target is created. -Please refer to the :variable:`CMAKE_XCODE_GENERATE_SCHEME` variable +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/FindGLEW-updates.rst b/Help/release/dev/FindGLEW-updates.rst new file mode 100644 index 0000000..6487052 --- /dev/null +++ b/Help/release/dev/FindGLEW-updates.rst @@ -0,0 +1,5 @@ +FindGLEW-updates +---------------- + +* The :module:`FindGLEW` module now provides an interface more consistent + with what upstream GLEW provides in its own CMake package files. diff --git a/Help/release/dev/cmake--install_option.rst b/Help/release/dev/cmake--install_option.rst new file mode 100644 index 0000000..8e526a0 --- /dev/null +++ b/Help/release/dev/cmake--install_option.rst @@ -0,0 +1,6 @@ +cmake--install-option +--------------------- + +* A new ``--install`` option was added to :manual:`cmake(1)`. + This may be used after building a project to run installation without + using the generated build system or the native build tool. diff --git a/Help/release/dev/cmake-e-tar-creating-archive.rst b/Help/release/dev/cmake-e-tar-creating-archive.rst new file mode 100644 index 0000000..717855c --- /dev/null +++ b/Help/release/dev/cmake-e-tar-creating-archive.rst @@ -0,0 +1,6 @@ +cmake-e-tar-creating-archive +---------------------------- + +* The :manual:`cmake(1)` ``-E tar`` tool now continues adding files to an + archive, even if some of the files aren't readable. This behavior is more + consistent with the classic ``tar`` tool. diff --git a/Help/release/dev/cmake-e-tar-error-handling.rst b/Help/release/dev/cmake-e-tar-error-handling.rst new file mode 100644 index 0000000..d1f2c72 --- /dev/null +++ b/Help/release/dev/cmake-e-tar-error-handling.rst @@ -0,0 +1,8 @@ +cmake-e-tar-error-handling +-------------------------- + +* The :manual:`cmake(1)` ``-E tar`` tool now parses all flags, and if an + invalid flag was provided, a warning is issued. +* The :manual:`cmake(1)` ``-E tar`` tool now displays an error if no action + flag was specified, along with a list of possible actions: ``t`` (list), + ``c`` (create) or ``x`` (extract). diff --git a/Help/release/dev/cuda-compiler-generator-expressions.rst b/Help/release/dev/cuda-compiler-generator-expressions.rst new file mode 100644 index 0000000..2610a39 --- /dev/null +++ b/Help/release/dev/cuda-compiler-generator-expressions.rst @@ -0,0 +1,5 @@ +cuda-compiler-generator-expressions +----------------------------------- + +* The ``$<CUDA_COMPILER_ID:...>`` and ``$<CUDA_COMPILER_VERSION:...>`` + :manual:`generator expressions <cmake-generator-expressions(7)>` were added. diff --git a/Help/release/dev/environment-modules.rst b/Help/release/dev/environment-modules.rst new file mode 100644 index 0000000..eace35d --- /dev/null +++ b/Help/release/dev/environment-modules.rst @@ -0,0 +1,5 @@ +environment-modules +------------------- + +* The :module:`FindEnvModules` module was added to use Lua- and TCL-based + environment modules in :ref:`CTest Scripts <CTest Script>`. diff --git a/Help/release/dev/export-package-default-off.rst b/Help/release/dev/export-package-default-off.rst new file mode 100644 index 0000000..0868c82 --- /dev/null +++ b/Help/release/dev/export-package-default-off.rst @@ -0,0 +1,6 @@ +export-package-default-off +-------------------------- + +* The :command:`export(PACKAGE)` command now does nothing unless + enabled via :variable:`CMAKE_EXPORT_PACKAGE_REGISTRY`. + See policy :policy:`CMP0090`. diff --git a/Help/release/dev/pkg-config-linker-flags.rst b/Help/release/dev/pkg-config-linker-flags.rst new file mode 100644 index 0000000..85c13be --- /dev/null +++ b/Help/release/dev/pkg-config-linker-flags.rst @@ -0,0 +1,5 @@ +pkg-config-linker-flags +----------------------- + +* The :module:`FindPkgConfig` now populates :prop_tgt:`INTERFACE_LINK_OPTIONS` + property of imported targets with other (non-library) linker flags. diff --git a/Help/release/dev/xcode-scheme-per-target.rst b/Help/release/dev/xcode-scheme-per-target.rst new file mode 100644 index 0000000..3febe79 --- /dev/null +++ b/Help/release/dev/xcode-scheme-per-target.rst @@ -0,0 +1,6 @@ +xcode-scheme-per-target +----------------------- + +* The :generator:`Xcode` generator now supports per-target schemes. + See the :variable:`CMAKE_XCODE_GENERATE_SCHEME` variable and + :prop_tgt:`XCODE_GENERATE_SCHEME` target property. diff --git a/Help/variable/CMAKE_EXPORT_NO_PACKAGE_REGISTRY.rst b/Help/variable/CMAKE_EXPORT_NO_PACKAGE_REGISTRY.rst index ee109ba..768ed64 100644 --- a/Help/variable/CMAKE_EXPORT_NO_PACKAGE_REGISTRY.rst +++ b/Help/variable/CMAKE_EXPORT_NO_PACKAGE_REGISTRY.rst @@ -1,11 +1,16 @@ CMAKE_EXPORT_NO_PACKAGE_REGISTRY -------------------------------- -Disable the :command:`export(PACKAGE)` command. +Disable the :command:`export(PACKAGE)` command when :policy:`CMP0090` +is not set to ``NEW``. In some cases, for example for packaging and for system wide installations, it is not desirable to write the user package registry. -If the :variable:`CMAKE_EXPORT_NO_PACKAGE_REGISTRY` variable is enabled, +If the ``CMAKE_EXPORT_NO_PACKAGE_REGISTRY`` variable is enabled, the :command:`export(PACKAGE)` command will do nothing. +If :policy:`CMP0090` is set to ``NEW`` this variable does nothing, and the +:variable:`CMAKE_EXPORT_PACKAGE_REGISTRY` variable controls the behavior +instead. + See also :ref:`Disabling the Package Registry`. diff --git a/Help/variable/CMAKE_EXPORT_PACKAGE_REGISTRY.rst b/Help/variable/CMAKE_EXPORT_PACKAGE_REGISTRY.rst new file mode 100644 index 0000000..3476a19 --- /dev/null +++ b/Help/variable/CMAKE_EXPORT_PACKAGE_REGISTRY.rst @@ -0,0 +1,15 @@ +CMAKE_EXPORT_PACKAGE_REGISTRY +----------------------------- + +Enables the :command:`export(PACKAGE)` command when :policy:`CMP0090` +is set to ``NEW``. + +The :command:`export(PACKAGE)` command does nothing by default. In some cases +it is desirable to write to the user package registry, so the +``CMAKE_EXPORT_PACKAGE_REGISTRY`` variable may be set to enable it. + +If :policy:`CMP0090` is *not* set to ``NEW`` this variable does nothing, and +the :variable:`CMAKE_EXPORT_NO_PACKAGE_REGISTRY` variable controls the behavior +instead. + +See also :ref:`Disabling the Package Registry`. diff --git a/Help/variable/CMAKE_XCODE_GENERATE_SCHEME.rst b/Help/variable/CMAKE_XCODE_GENERATE_SCHEME.rst index 707c6a0..1fb84d7 100644 --- a/Help/variable/CMAKE_XCODE_GENERATE_SCHEME.rst +++ b/Help/variable/CMAKE_XCODE_GENERATE_SCHEME.rst @@ -5,31 +5,6 @@ If enabled, the Xcode generator will generate schema files. These are useful to invoke analyze, archive, build-for-testing and test actions from the command line. -The following target properties overwrite the default of the -corresponding settings on the "Diagnostic" tab for each schema file. -Each of those is initialized by the respective ``CMAKE_`` variable -at target creation time. - -- :prop_tgt:`XCODE_SCHEME_ADDRESS_SANITIZER` -- :prop_tgt:`XCODE_SCHEME_ADDRESS_SANITIZER_USE_AFTER_RETURN` -- :prop_tgt:`XCODE_SCHEME_DISABLE_MAIN_THREAD_CHECKER` -- :prop_tgt:`XCODE_SCHEME_DYNAMIC_LIBRARY_LOADS` -- :prop_tgt:`XCODE_SCHEME_DYNAMIC_LINKER_API_USAGE` -- :prop_tgt:`XCODE_SCHEME_GUARD_MALLOC` -- :prop_tgt:`XCODE_SCHEME_MAIN_THREAD_CHECKER_STOP` -- :prop_tgt:`XCODE_SCHEME_MALLOC_GUARD_EDGES` -- :prop_tgt:`XCODE_SCHEME_MALLOC_SCRIBBLE` -- :prop_tgt:`XCODE_SCHEME_MALLOC_STACK` -- :prop_tgt:`XCODE_SCHEME_THREAD_SANITIZER` -- :prop_tgt:`XCODE_SCHEME_THREAD_SANITIZER_STOP` -- :prop_tgt:`XCODE_SCHEME_UNDEFINED_BEHAVIOUR_SANITIZER` -- :prop_tgt:`XCODE_SCHEME_UNDEFINED_BEHAVIOUR_SANITIZER_STOP` -- :prop_tgt:`XCODE_SCHEME_ZOMBIE_OBJECTS` - -The following target properties will be applied on the -"Info" and "Arguments" tab: - -- :prop_tgt:`XCODE_SCHEME_ARGUMENTS` -- :prop_tgt:`XCODE_SCHEME_DEBUG_AS_ROOT` -- :prop_tgt:`XCODE_SCHEME_ENVIRONMENT` -- :prop_tgt:`XCODE_SCHEME_EXECUTABLE` +This variable initializes the +:prop_tgt:`XCODE_GENERATE_SCHEME` +target property on all targets. diff --git a/Help/variable/CMAKE_XCODE_SCHEME_ADDRESS_SANITIZER.rst b/Help/variable/CMAKE_XCODE_SCHEME_ADDRESS_SANITIZER.rst index 37dc0ce..b972ba5 100644 --- a/Help/variable/CMAKE_XCODE_SCHEME_ADDRESS_SANITIZER.rst +++ b/Help/variable/CMAKE_XCODE_SCHEME_ADDRESS_SANITIZER.rst @@ -8,5 +8,5 @@ This variable initializes the :prop_tgt:`XCODE_SCHEME_ADDRESS_SANITIZER` property on all targets. -Please refer to the :variable:`CMAKE_XCODE_GENERATE_SCHEME` variable +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_ADDRESS_SANITIZER_USE_AFTER_RETURN.rst b/Help/variable/CMAKE_XCODE_SCHEME_ADDRESS_SANITIZER_USE_AFTER_RETURN.rst index 05949c3..59eb32d 100644 --- a/Help/variable/CMAKE_XCODE_SCHEME_ADDRESS_SANITIZER_USE_AFTER_RETURN.rst +++ b/Help/variable/CMAKE_XCODE_SCHEME_ADDRESS_SANITIZER_USE_AFTER_RETURN.rst @@ -8,5 +8,5 @@ This variable initializes the :prop_tgt:`XCODE_SCHEME_ADDRESS_SANITIZER_USE_AFTER_RETURN` property on all targets. -Please refer to the :variable:`CMAKE_XCODE_GENERATE_SCHEME` variable +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_DISABLE_MAIN_THREAD_CHECKER.rst b/Help/variable/CMAKE_XCODE_SCHEME_DISABLE_MAIN_THREAD_CHECKER.rst index 81f4974..71bcf42 100644 --- a/Help/variable/CMAKE_XCODE_SCHEME_DISABLE_MAIN_THREAD_CHECKER.rst +++ b/Help/variable/CMAKE_XCODE_SCHEME_DISABLE_MAIN_THREAD_CHECKER.rst @@ -8,5 +8,5 @@ This variable initializes the :prop_tgt:`XCODE_SCHEME_DISABLE_MAIN_THREAD_CHECKER` property on all targets. -Please refer to the :variable:`CMAKE_XCODE_GENERATE_SCHEME` variable +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_DYNAMIC_LIBRARY_LOADS.rst b/Help/variable/CMAKE_XCODE_SCHEME_DYNAMIC_LIBRARY_LOADS.rst index 5e133ac..53f55e6 100644 --- a/Help/variable/CMAKE_XCODE_SCHEME_DYNAMIC_LIBRARY_LOADS.rst +++ b/Help/variable/CMAKE_XCODE_SCHEME_DYNAMIC_LIBRARY_LOADS.rst @@ -8,5 +8,5 @@ This variable initializes the :prop_tgt:`XCODE_SCHEME_DYNAMIC_LIBRARY_LOADS` property on all targets. -Please refer to the :variable:`CMAKE_XCODE_GENERATE_SCHEME` variable +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_DYNAMIC_LINKER_API_USAGE.rst b/Help/variable/CMAKE_XCODE_SCHEME_DYNAMIC_LINKER_API_USAGE.rst index 33162d9..784ceb6 100644 --- a/Help/variable/CMAKE_XCODE_SCHEME_DYNAMIC_LINKER_API_USAGE.rst +++ b/Help/variable/CMAKE_XCODE_SCHEME_DYNAMIC_LINKER_API_USAGE.rst @@ -8,5 +8,5 @@ This variable initializes the :prop_tgt:`XCODE_SCHEME_DYNAMIC_LINKER_API_USAGE` property on all targets. -Please refer to the :variable:`CMAKE_XCODE_GENERATE_SCHEME` variable +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_GUARD_MALLOC.rst b/Help/variable/CMAKE_XCODE_SCHEME_GUARD_MALLOC.rst index 03d88c2..9350244 100644 --- a/Help/variable/CMAKE_XCODE_SCHEME_GUARD_MALLOC.rst +++ b/Help/variable/CMAKE_XCODE_SCHEME_GUARD_MALLOC.rst @@ -8,5 +8,5 @@ This variable initializes the :prop_tgt:`XCODE_SCHEME_GUARD_MALLOC` property on all targets. -Please refer to the :variable:`CMAKE_XCODE_GENERATE_SCHEME` variable +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_MAIN_THREAD_CHECKER_STOP.rst b/Help/variable/CMAKE_XCODE_SCHEME_MAIN_THREAD_CHECKER_STOP.rst index fd6135f..45a2dad 100644 --- a/Help/variable/CMAKE_XCODE_SCHEME_MAIN_THREAD_CHECKER_STOP.rst +++ b/Help/variable/CMAKE_XCODE_SCHEME_MAIN_THREAD_CHECKER_STOP.rst @@ -9,5 +9,5 @@ This variable initializes the :prop_tgt:`XCODE_SCHEME_MAIN_THREAD_CHECKER_STOP` property on all targets. -Please refer to the :variable:`CMAKE_XCODE_GENERATE_SCHEME` variable +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_MALLOC_GUARD_EDGES.rst b/Help/variable/CMAKE_XCODE_SCHEME_MALLOC_GUARD_EDGES.rst index 8fedc20..94d1c61 100644 --- a/Help/variable/CMAKE_XCODE_SCHEME_MALLOC_GUARD_EDGES.rst +++ b/Help/variable/CMAKE_XCODE_SCHEME_MALLOC_GUARD_EDGES.rst @@ -8,5 +8,5 @@ This variable initializes the :prop_tgt:`XCODE_SCHEME_MALLOC_GUARD_EDGES` property on all targets. -Please refer to the :variable:`CMAKE_XCODE_GENERATE_SCHEME` variable +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_MALLOC_SCRIBBLE.rst b/Help/variable/CMAKE_XCODE_SCHEME_MALLOC_SCRIBBLE.rst index cddca7c..9bf0eb4 100644 --- a/Help/variable/CMAKE_XCODE_SCHEME_MALLOC_SCRIBBLE.rst +++ b/Help/variable/CMAKE_XCODE_SCHEME_MALLOC_SCRIBBLE.rst @@ -8,5 +8,5 @@ This variable initializes the :prop_tgt:`XCODE_SCHEME_MALLOC_SCRIBBLE` property on all targets. -Please refer to the :variable:`CMAKE_XCODE_GENERATE_SCHEME` variable +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_MALLOC_STACK.rst b/Help/variable/CMAKE_XCODE_SCHEME_MALLOC_STACK.rst index 9c83698..4cc21ee 100644 --- a/Help/variable/CMAKE_XCODE_SCHEME_MALLOC_STACK.rst +++ b/Help/variable/CMAKE_XCODE_SCHEME_MALLOC_STACK.rst @@ -8,5 +8,5 @@ This variable initializes the :prop_tgt:`XCODE_SCHEME_MALLOC_STACK` property on all targets. -Please refer to the :variable:`CMAKE_XCODE_GENERATE_SCHEME` variable +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_THREAD_SANITIZER.rst b/Help/variable/CMAKE_XCODE_SCHEME_THREAD_SANITIZER.rst index c937369..6d1b56e 100644 --- a/Help/variable/CMAKE_XCODE_SCHEME_THREAD_SANITIZER.rst +++ b/Help/variable/CMAKE_XCODE_SCHEME_THREAD_SANITIZER.rst @@ -8,5 +8,5 @@ This variable initializes the :prop_tgt:`XCODE_SCHEME_THREAD_SANITIZER` property on all targets. -Please refer to the :variable:`CMAKE_XCODE_GENERATE_SCHEME` variable +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_THREAD_SANITIZER_STOP.rst b/Help/variable/CMAKE_XCODE_SCHEME_THREAD_SANITIZER_STOP.rst index eed796c..de40478 100644 --- a/Help/variable/CMAKE_XCODE_SCHEME_THREAD_SANITIZER_STOP.rst +++ b/Help/variable/CMAKE_XCODE_SCHEME_THREAD_SANITIZER_STOP.rst @@ -8,5 +8,5 @@ This variable initializes the :prop_tgt:`XCODE_SCHEME_THREAD_SANITIZER_STOP` property on all targets. -Please refer to the :variable:`CMAKE_XCODE_GENERATE_SCHEME` variable +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_UNDEFINED_BEHAVIOUR_SANITIZER.rst b/Help/variable/CMAKE_XCODE_SCHEME_UNDEFINED_BEHAVIOUR_SANITIZER.rst index d14ba3f..ec5df66 100644 --- a/Help/variable/CMAKE_XCODE_SCHEME_UNDEFINED_BEHAVIOUR_SANITIZER.rst +++ b/Help/variable/CMAKE_XCODE_SCHEME_UNDEFINED_BEHAVIOUR_SANITIZER.rst @@ -8,5 +8,5 @@ This variable initializes the :prop_tgt:`XCODE_SCHEME_UNDEFINED_BEHAVIOUR_SANITIZER` property on all targets. -Please refer to the :variable:`CMAKE_XCODE_GENERATE_SCHEME` variable +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_UNDEFINED_BEHAVIOUR_SANITIZER_STOP.rst b/Help/variable/CMAKE_XCODE_SCHEME_UNDEFINED_BEHAVIOUR_SANITIZER_STOP.rst index f8df304..dcec9b0 100644 --- a/Help/variable/CMAKE_XCODE_SCHEME_UNDEFINED_BEHAVIOUR_SANITIZER_STOP.rst +++ b/Help/variable/CMAKE_XCODE_SCHEME_UNDEFINED_BEHAVIOUR_SANITIZER_STOP.rst @@ -9,5 +9,5 @@ This variable initializes the :prop_tgt:`XCODE_SCHEME_UNDEFINED_BEHAVIOUR_SANITIZER_STOP` property on all targets. -Please refer to the :variable:`CMAKE_XCODE_GENERATE_SCHEME` variable +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_ZOMBIE_OBJECTS.rst b/Help/variable/CMAKE_XCODE_SCHEME_ZOMBIE_OBJECTS.rst index efc331a..82e9d76 100644 --- a/Help/variable/CMAKE_XCODE_SCHEME_ZOMBIE_OBJECTS.rst +++ b/Help/variable/CMAKE_XCODE_SCHEME_ZOMBIE_OBJECTS.rst @@ -8,5 +8,5 @@ This variable initializes the :prop_tgt:`XCODE_SCHEME_ZOMBIE_OBJECTS` property on all targets. -Please refer to the :variable:`CMAKE_XCODE_GENERATE_SCHEME` variable +Please refer to the :prop_tgt:`XCODE_GENERATE_SCHEME` target property documentation to see all Xcode schema related properties. diff --git a/Modules/CMakeCheckCompilerFlagCommonPatterns.cmake b/Modules/CMakeCheckCompilerFlagCommonPatterns.cmake index e60ffe0..5b9ed34 100644 --- a/Modules/CMakeCheckCompilerFlagCommonPatterns.cmake +++ b/Modules/CMakeCheckCompilerFlagCommonPatterns.cmake @@ -30,5 +30,6 @@ macro (CHECK_COMPILER_FLAG_COMMON_PATTERNS _VAR) FAIL_REGEX "Incorrect command line option:" # Borland FAIL_REGEX "Warning: illegal option" # SunStudio 12 FAIL_REGEX "[Ww]arning: Invalid suboption" # Fujitsu + FAIL_REGEX "An invalid option .* appears on the command line" # Cray ) endmacro () diff --git a/Modules/CMakeCompilerIdDetection.cmake b/Modules/CMakeCompilerIdDetection.cmake index 7aac846..ed288f5 100644 --- a/Modules/CMakeCompilerIdDetection.cmake +++ b/Modules/CMakeCompilerIdDetection.cmake @@ -74,13 +74,13 @@ function(compiler_id_detection outvar lang) endif() list(APPEND ordered_compilers SCO + ARMCC AppleClang Clang GNU MSVC ADSP IAR - ARMCC ) if (lang STREQUAL C) list(APPEND ordered_compilers diff --git a/Modules/CheckTypeSize.c.in b/Modules/CheckTypeSize.c.in index 2303c4e..82035a3 100644 --- a/Modules/CheckTypeSize.c.in +++ b/Modules/CheckTypeSize.c.in @@ -18,7 +18,7 @@ #endif #define SIZE (sizeof(@type@)) -char info_size[] = {'I', 'N', 'F', 'O', ':', 's','i','z','e','[', +static char info_size[] = {'I', 'N', 'F', 'O', ':', 's','i','z','e','[', ('0' + ((SIZE / 10000)%10)), ('0' + ((SIZE / 1000)%10)), ('0' + ((SIZE / 100)%10)), diff --git a/Modules/ExternalProject.cmake b/Modules/ExternalProject.cmake index 22e0523..948b921 100644 --- a/Modules/ExternalProject.cmake +++ b/Modules/ExternalProject.cmake @@ -251,6 +251,9 @@ External Project Definition The lack of such deterministic behavior makes the main project lose traceability and repeatability. + If ``GIT_SHALLOW`` is enabled then ``GIT_TAG`` works only with + branch names and tags. A commit hash is not allowed. + ``GIT_REMOTE_NAME <name>`` The optional name of the remote. If this option is not specified, it defaults to ``origin``. @@ -1053,11 +1056,6 @@ define_property(DIRECTORY PROPERTY "EP_UPDATE_DISCONNECTED" INHERITED ) function(_ep_write_gitclone_script script_filename source_dir git_EXECUTABLE git_repository git_tag git_remote_name 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.7.10) - set(git_clone_shallow_options "--depth 1 --no-single-branch") - else() - set(git_clone_shallow_options "--depth 1") - endif() 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-- "--") @@ -1067,18 +1065,41 @@ function(_ep_write_gitclone_script script_filename source_dir git_EXECUTABLE git # because that will not search for remote branch names, a common use case. set(git_checkout_explicit-- "") endif() - file(WRITE ${script_filename} -"if(\"${git_tag}\" STREQUAL \"\") - message(FATAL_ERROR \"Tag for git checkout should not be empty.\") -endif() + if("${git_tag}" STREQUAL "") + message(FATAL_ERROR "Tag for git checkout should not be empty.") + endif() + + set(git_clone_options) + if(git_shallow) + if(NOT GIT_VERSION_STRING VERSION_LESS 1.7.10) + list(APPEND git_clone_options "--depth 1 --no-single-branch") + else() + list(APPEND git_clone_options "--depth 1") + endif() + endif() + if(git_progress) + list(APPEND git_clone_options --progress) + endif() + foreach(config IN LISTS git_config) + list(APPEND git_clone_options --config ${config}) + endforeach() + if(NOT ${git_remote_name} STREQUAL "origin") + list(APPEND git_clone_options --origin \"${git_remote_name}\") + endif() -set(run 0) + string (REPLACE ";" " " git_clone_options "${git_clone_options}") -if(\"${gitclone_infofile}\" IS_NEWER_THAN \"${gitclone_stampfile}\") - set(run 1) -endif() + set(git_options) + # disable cert checking if explicitly told not to do it + if(NOT "x${tls_verify}" STREQUAL "x" AND NOT tls_verify) + set(git_options + -c http.sslVerify=false) + endif() + string (REPLACE ";" " " git_options "${git_options}") -if(NOT run) + file(WRITE ${script_filename} +" +if(NOT \"${gitclone_infofile}\" IS_NEWER_THAN \"${gitclone_stampfile}\") message(STATUS \"Avoiding repeated git clone, stamp file is up to date: '${gitclone_stampfile}'\") return() endif() @@ -1091,38 +1112,12 @@ if(error_code) message(FATAL_ERROR \"Failed to remove directory: '${source_dir}'\") endif() -set(git_options) - -# disable cert checking if explicitly told not to do it -set(tls_verify \"${tls_verify}\") -if(NOT \"x${tls_verify}\" STREQUAL \"x\" AND NOT tls_verify) - list(APPEND git_options - -c http.sslVerify=false) -endif() - -set(git_clone_options) - -set(git_shallow \"${git_shallow}\") -if(git_shallow) - list(APPEND git_clone_options ${git_clone_shallow_options}) -endif() - -set(git_progress \"${git_progress}\") -if(git_progress) - list(APPEND git_clone_options --progress) -endif() - -set(git_config \"${git_config}\") -foreach(config IN LISTS git_config) - list(APPEND git_clone_options --config \${config}) -endforeach() - # try the clone 3 times in case there is an odd git clone issue set(error_code 1) set(number_of_tries 0) while(error_code AND number_of_tries LESS 3) execute_process( - COMMAND \"${git_EXECUTABLE}\" \${git_options} clone \${git_clone_options} --origin \"${git_remote_name}\" \"${git_repository}\" \"${src_name}\" + COMMAND \"${git_EXECUTABLE}\" ${git_options} clone ${git_clone_options} \"${git_repository}\" \"${src_name}\" WORKING_DIRECTORY \"${work_dir}\" RESULT_VARIABLE error_code ) @@ -1137,7 +1132,7 @@ if(error_code) endif() execute_process( - COMMAND \"${git_EXECUTABLE}\" \${git_options} checkout ${git_tag} ${git_checkout_explicit--} + COMMAND \"${git_EXECUTABLE}\" ${git_options} checkout ${git_tag} ${git_checkout_explicit--} WORKING_DIRECTORY \"${work_dir}/${src_name}\" RESULT_VARIABLE error_code ) @@ -1146,16 +1141,7 @@ if(error_code) endif() execute_process( - COMMAND \"${git_EXECUTABLE}\" \${git_options} submodule init ${git_submodules} - WORKING_DIRECTORY \"${work_dir}/${src_name}\" - RESULT_VARIABLE error_code - ) -if(error_code) - message(FATAL_ERROR \"Failed to init submodules in: '${work_dir}/${src_name}'\") -endif() - -execute_process( - COMMAND \"${git_EXECUTABLE}\" \${git_options} submodule update --recursive --init ${git_submodules} + COMMAND \"${git_EXECUTABLE}\" ${git_options} submodule update --recursive --init ${git_submodules} WORKING_DIRECTORY \"${work_dir}/${src_name}\" RESULT_VARIABLE error_code ) @@ -1169,7 +1155,6 @@ execute_process( COMMAND \${CMAKE_COMMAND} -E copy \"${gitclone_infofile}\" \"${gitclone_stampfile}\" - WORKING_DIRECTORY \"${work_dir}/${src_name}\" RESULT_VARIABLE error_code ) if(error_code) @@ -1182,18 +1167,12 @@ endif() endfunction() function(_ep_write_hgclone_script script_filename source_dir hg_EXECUTABLE hg_repository hg_tag src_name work_dir hgclone_infofile hgclone_stampfile) + if("${hg_tag}" STREQUAL "") + message(FATAL_ERROR "Tag for hg checkout should not be empty.") + endif() file(WRITE ${script_filename} -"if(\"${hg_tag}\" STREQUAL \"\") - message(FATAL_ERROR \"Tag for hg checkout should not be empty.\") -endif() - -set(run 0) - -if(\"${hgclone_infofile}\" IS_NEWER_THAN \"${hgclone_stampfile}\") - set(run 1) -endif() - -if(NOT run) +" +if(NOT \"${hgclone_infofile}\" IS_NEWER_THAN \"${hgclone_stampfile}\") message(STATUS \"Avoiding repeated hg clone, stamp file is up to date: '${hgclone_stampfile}'\") return() endif() @@ -1230,7 +1209,6 @@ execute_process( COMMAND \${CMAKE_COMMAND} -E copy \"${hgclone_infofile}\" \"${hgclone_stampfile}\" - WORKING_DIRECTORY \"${work_dir}/${src_name}\" RESULT_VARIABLE error_code ) if(error_code) @@ -1244,16 +1222,16 @@ endfunction() function(_ep_write_gitupdate_script script_filename git_EXECUTABLE git_tag git_remote_name git_submodules git_repository work_dir) + if("${git_tag}" STREQUAL "") + message(FATAL_ERROR "Tag for git checkout should not be empty.") + endif() if(NOT GIT_VERSION_STRING VERSION_LESS 1.7.6) set(git_stash_save_options --all --quiet) else() set(git_stash_save_options --quiet) endif() file(WRITE ${script_filename} -"if(\"${git_tag}\" STREQUAL \"\") - message(FATAL_ERROR \"Tag for git checkout should not be empty.\") -endif() - +" execute_process( COMMAND \"${git_EXECUTABLE}\" rev-list --max-count=1 HEAD WORKING_DIRECTORY \"${work_dir}\" @@ -2460,7 +2438,7 @@ function(_ep_add_download_command name) # set(repository ${git_repository}) set(module) - set(tag) + set(tag ${git_remote_name}) configure_file( "${CMAKE_ROOT}/Modules/RepositoryInfo.txt.in" "${stamp_dir}/${name}-gitinfo.txt" diff --git a/Modules/FindBLAS.cmake b/Modules/FindBLAS.cmake index 0aa4f50..bfa449f 100644 --- a/Modules/FindBLAS.cmake +++ b/Modules/FindBLAS.cmake @@ -83,6 +83,13 @@ This module defines the following variables: set(BLA_VENDOR Intel10_64lp) find_package(BLAS) + +Hints +^^^^^ + +Set ``MKLROOT`` environment variable to a directory that contains an MKL +installation. + #]=======================================================================] include(${CMAKE_CURRENT_LIST_DIR}/CheckFunctionExists.cmake) @@ -394,6 +401,24 @@ if (BLA_VENDOR MATCHES "Intel" OR BLA_VENDOR STREQUAL "All") endif () endif () + if (DEFINED ENV{MKLROOT}) + set(_BLAS_MKLROOT_LIB_DIR "$ENV{MKLROOT}") + endif () + if (_BLAS_MKLROOT_LIB_DIR) + if( SIZEOF_INTEGER EQUAL 8 ) + set( _BLAS_MKL_PATH_PREFIX "intel64" ) + else() + set( _BLAS_MKL_PATH_PREFIX "ia32" ) + endif() + if (WIN32) + string(APPEND _BLAS_MKLROOT_LIB_DIR "/lib/${_BLAS_MKL_PATH_PREFIX}_win") + elseif (APPLE) + string(APPEND _BLAS_MKLROOT_LIB_DIR "/lib/${_BLAS_MKL_PATH_PREFIX}_mac") + else () + string(APPEND _BLAS_MKLROOT_LIB_DIR "/lib/${_BLAS_MKL_PATH_PREFIX}_lin") + endif () + endif () + foreach (IT ${BLAS_SEARCH_LIBS}) string(REPLACE " " ";" SEARCH_LIBS ${IT}) if (NOT ${_LIBRARIES}) @@ -404,6 +429,7 @@ if (BLA_VENDOR MATCHES "Intel" OR BLA_VENDOR STREQUAL "All") "" "${SEARCH_LIBS}" "${CMAKE_THREAD_LIBS_INIT};${BLAS_mkl_LM};${BLAS_mkl_LDL}" + "${_BLAS_MKLROOT_LIB_DIR}" ) endif () endforeach () diff --git a/Modules/FindEnvModules.cmake b/Modules/FindEnvModules.cmake new file mode 100644 index 0000000..5d3452d --- /dev/null +++ b/Modules/FindEnvModules.cmake @@ -0,0 +1,333 @@ +# Distributed under the OSI-approved BSD 3-Clause License. See accompanying +# file Copyright.txt or https://cmake.org/licensing for details. + +#[=======================================================================[.rst: +FindEnvModules +-------------- + +Locate an environment module implementation and make commands available to +CMake scripts to use them. This is compatible with both Lua-based Lmod +and TCL-based EnvironmentModules. + +This module is intended for the use case of setting up the compiler and library +environment within a :ref:`CTest Script <CTest Script>` (``ctest -S``). It can +also be used in a :ref:`CMake Script <Script Processing Mode>` (``cmake -P``). + +.. note:: + + The loaded environment will not survive past the end of the calling process. + Do not use this module in project code (``CMakeLists.txt`` files) to load + a compiler environment; it will not be available during the build. Instead + load the environment manually before running CMake or using the generated + build system. + +Example Usage +^^^^^^^^^^^^^ + +.. code-block:: cmake + + set(CTEST_BUILD_NAME "CrayLinux-CrayPE-Cray-dynamic") + set(CTEST_BUILD_CONFIGURATION Release) + set(CTEST_BUILD_FLAGS "-k -j8") + set(CTEST_CMAKE_GENERATOR "Unix Makefiles") + + ... + + find_package(EnvModules REQUIRED) + + env_module(purge) + env_module(load modules) + env_module(load craype) + env_module(load PrgEnv-cray) + env_module(load craype-knl) + env_module(load cray-mpich) + env_module(load cray-libsci) + + set(ENV{CRAYPE_LINK_TYPE} dynamic) + + ... + +Result Variables +^^^^^^^^^^^^^^^^ + +This module will set the following variables in your project: + +``EnvModules_FOUND`` + Found the a compatible environment modules framework + +Cache Variables +^^^^^^^^^^^^^^^ + +The following cache variable will be set: + +``EnvModules_COMMAND`` + The low level module command to use. Currently supported are + implementations are the Lua based Lmod and TCL based EnvironmentModules. + +Environment Variables +^^^^^^^^^^^^^^^^^^^^^ + +``ENV{MODULESHOME}`` + Usually set by the module environment implementation, used as a hint to + locate the module command to execute. + +Provided Functions +^^^^^^^^^^^^^^^^^^ + +This defines the following cmake functions for interacting with environment +modules: + +.. command:: env_module + + Execute an aribitrary module command: + + .. code-block:: cmake + + env_module(cmd arg1 ... argN) + env_module( + COMMAND cmd arg1 ... argN + [OUTPUT_VARIABLE <out-var>] + [RESULT_VARIABLE <ret-var>] + ) + + The options are: + + ``cmd arg1 ... argN`` + The module sub-command and arguments to execute as if they were + passed directly to the module command in your shell environment. + + ``OUTPUT_VARIABLE <out-var>`` + The standard output from executing the module command. + + ``RESULT_VARIABLE <ret-var>`` + The return code from executing the module command. + +.. command:: env_module_swap + + Swap one module for another: + + .. code-block:: cmake + + env_module_swap(out_mod in_mod + [OUTPUT_VARIABLE <out-var>] + [RESULT_VARIABLE <ret-var>] + ) + + This is functionally equivalent to the ``module swap out_mod in_mod`` shell + command. The options are: + + ``OUTPUT_VARIABLE <out-var>`` + The standard output from executing the module command. + + ``RESULT_VARIABLE <ret-var>`` + The return code from executing the module command. + +.. command:: env_module_list + + Retrieve the list of currently loaded modules: + + .. code-block:: cmake + + env_module_list(<out-var>) + + This is functionally equivalent to the ``module list`` shell command. + The result is stored in ``<out-var>`` as a properly formatted CMake + :ref:`semicolon-separated list <CMake Language Lists>` variable. + +.. command:: env_module_avail + + Retrieve the list of available modules: + + .. code-block:: cmake + + env_module_avail([<mod-prefix>] <out-var>) + + This is functionally equivalent to the ``module avail <mod-prefix>`` shell + command. The result is stored in ``<out-var>`` as a properly formatted + CMake :ref:`semicolon-separated list <CMake Language Lists>` variable. + +#]=======================================================================] + +function(env_module) + if(NOT EnvModules_COMMAND) + message(FATAL_ERROR "Failed to process module command. EnvModules_COMMAND not found") + return() + endif() + + set(options) + set(oneValueArgs OUTPUT_VARIABLE RESULT_VARIABLE) + set(multiValueArgs COMMAND) + cmake_parse_arguments(MOD_ARGS + "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGV} + ) + if(NOT MOD_ARGS_COMMAND) + # If no explicit command argument was given, then treat the calling syntax + # as: module(cmd args...) + set(exec_cmd ${ARGV}) + else() + set(exec_cmd ${MOD_ARGS_COMMAND}) + endif() + + if(MOD_ARGS_OUTPUT_VARIABLE) + set(err_var_args ERROR_VARIABLE err_var) + endif() + + execute_process( + COMMAND mktemp -t module.cmake.XXXXXXXXXXXX + OUTPUT_VARIABLE tempfile_name + ) + string(STRIP "${tempfile_name}" tempfile_name) + + # If the $MODULESHOME/init/cmake file exists then assume that the CMake + # "shell" functionality exits + if(EXISTS "$ENV{MODULESHOME}/init/cmake") + execute_process( + COMMAND ${EnvModules_COMMAND} cmake ${exec_cmd} + OUTPUT_FILE ${tempfile_name} + ${err_var_args} + RESULT_VARIABLE ret_var + ) + + else() # fallback to the sh shell and manually convert to CMake + execute_process( + COMMAND ${EnvModules_COMMAND} sh ${exec_cmd} + OUTPUT_VARIABLE out_var + ${err_var_args} + RESULT_VARIABLE ret_var + ) + endif() + + # If we executed successfully then process and cleanup the temp file + if(ret_var EQUAL 0) + # No CMake shell so we need to process the sh output into CMake code + if(NOT EXISTS "$ENV{MODULESHOME}/init/cmake") + file(WRITE ${tempfile_name} "") + string(REPLACE "\n" ";" out_var "${out_var}") + foreach(sh_cmd IN LISTS out_var) + if(sh_cmd MATCHES "^ *unset *([^ ]*)") + set(cmake_cmd "unset(ENV{${CMAKE_MATCH_1}})") + elseif(sh_cmd MATCHES "^ *export *([^ ]*)") + set(cmake_cmd "set(ENV{${CMAKE_MATCH_1}} \"\${${CMAKE_MATCH_1}}\")") + elseif(sh_cmd MATCHES " *([^ =]*) *= *(.*)") + set(var_name "${CMAKE_MATCH_1}") + set(var_value "${CMAKE_MATCH_2}") + if(var_value MATCHES "^\"(.*[^\\])\"") + # If it's in quotes, take the value as is + set(var_value "${CMAKE_MATCH_1}") + else() + # Otherwise, strip trailing spaces + string(REGEX REPLACE "([^\\])? +$" "\\1" var_value "${var_value}") + endif() + string(REPLACE "\\ " " " var_value "${var_value}") + set(cmake_cmd "set(${var_name} \"${var_value}\")") + else() + continue() + endif() + file(APPEND ${tempfile_name} "${cmake_cmd}\n") + endforeach() + endif() + + # Process the change in environment variables + include(${tempfile_name}) + file(REMOVE ${tempfile_name}) + endif() + + # Push the output back out to the calling scope + if(MOD_ARGS_OUTPUT_VARIABLE) + set(${MOD_ARGS_OUTPUT_VARIABLE} "${err_var}" PARENT_SCOPE) + endif() + if(MOD_ARGS_RESULT_VARIABLE) + set(${MOD_ARGS_RESULT_VARIABLE} ${ret_var} PARENT_SCOPE) + endif() +endfunction(env_module) + +#------------------------------------------------------------------------------ +function(env_module_swap out_mod in_mod) + set(options) + set(oneValueArgs OUTPUT_VARIABLE RESULT_VARIABLE) + set(multiValueArgs) + + cmake_parse_arguments(MOD_ARGS + "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGV} + ) + + env_module(COMMAND -t swap ${out_mod} ${in_mod} + OUTPUT_VARIABLE tmp_out + RETURN_VARIABLE tmp_ret + ) + + if(MOD_ARGS_OUTPUT_VARIABLE) + set(${MOD_ARGS_OUTPUT_VARIABLE} "${err_var}" PARENT_SCOPE) + endif() + if(MOD_ARGS_RESULT_VARIABLE) + set(${MOD_ARGS_RESULT_VARIABLE} ${tmp_ret} PARENT_SCOPE) + endif() +endfunction() + +#------------------------------------------------------------------------------ +function(env_module_list out_var) + cmake_policy(SET CMP0007 NEW) + env_module(COMMAND -t list OUTPUT_VARIABLE tmp_out) + + # Convert output into a CMake list + string(REPLACE "\n" ";" ${out_var} "${tmp_out}") + + # Remove title headers and empty entries + list(REMOVE_ITEM ${out_var} "No modules loaded") + if(${out_var}) + list(FILTER ${out_var} EXCLUDE REGEX "^(.*:)?$") + endif() + list(FILTER ${out_var} EXCLUDE REGEX "^(.*:)?$") + + set(${out_var} ${${out_var}} PARENT_SCOPE) +endfunction() + +#------------------------------------------------------------------------------ +function(env_module_avail) + cmake_policy(SET CMP0007 NEW) + + if(ARGC EQUAL 1) + set(mod_prefix) + set(out_var ${ARGV0}) + elseif(ARGC EQUAL 2) + set(mod_prefix ${ARGV0}) + set(out_var ${ARGV1}) + else() + message(FATAL_ERROR "Usage: env_module_avail([mod_prefix] out_var)") + endif() + env_module(COMMAND -t avail ${mod_prefix} OUTPUT_VARIABLE tmp_out) + + # Convert output into a CMake list + string(REPLACE "\n" ";" tmp_out "${tmp_out}") + + set(${out_var}) + foreach(MOD IN LISTS tmp_out) + # Remove directory entries and empty values + if(MOD MATCHES "^(.*:)?$") + continue() + endif() + + # Convert default modules + if(MOD MATCHES "^(.*)/$" ) # "foo/" + list(APPEND ${out_var} ${CMAKE_MATCH_1}) + elseif(MOD MATCHES "^((.*)/.*)\\(default\\)$") # "foo/1.2.3(default)" + list(APPEND ${out_var} ${CMAKE_MATCH_2}) + list(APPEND ${out_var} ${CMAKE_MATCH_1}) + else() + list(APPEND ${out_var} ${MOD}) + endif() + endforeach() + + set(${out_var} ${${out_var}} PARENT_SCOPE) +endfunction() + +#------------------------------------------------------------------------------ +# Make sure we know where the underlying module command is +find_program(EnvModules_COMMAND + NAMES lmod modulecmd + HINTS ENV MODULESHOME + PATH_SUFFIXES libexec +) + +include(${CMAKE_CURRENT_LIST_DIR}/FindPackageHandleStandardArgs.cmake) +find_package_handle_standard_args(EnvModules DEFAULT_MSG EnvModules_COMMAND) diff --git a/Modules/FindGLEW.cmake b/Modules/FindGLEW.cmake index ad8a810..34ee873 100644 --- a/Modules/FindGLEW.cmake +++ b/Modules/FindGLEW.cmake @@ -7,64 +7,300 @@ FindGLEW Find the OpenGL Extension Wrangler Library (GLEW) -IMPORTED Targets +Input Variables +^^^^^^^^^^^^^^^ + +The following variables may be set to influence this module’s behavior: + +``GLEW_USE_STATIC_LIBS`` + to find and create :prop_tgt:`IMPORTED` target for static linkage. + +``GLEW_VERBOSE`` + to output a detailed log of this module. + +Imported Targets ^^^^^^^^^^^^^^^^ -This module defines the :prop_tgt:`IMPORTED` target ``GLEW::GLEW``, -if GLEW has been found. +This module defines the following :ref:`Imported Targets <Imported Targets>`: + + +``GLEW::glew`` + The GLEW shared library. +``GLEW::glew_s`` + The GLEW static library, if ``GLEW_USE_STATIC_LIBS`` is set to ``TRUE``. +``GLEW::GLEW`` + Duplicates either ``GLEW::glew`` or ``GLEW::glew_s`` based on availability. Result Variables ^^^^^^^^^^^^^^^^ This module defines the following variables: -:: +``GLEW_INCLUDE_DIRS`` + include directories for GLEW +``GLEW_LIBRARIES`` + libraries to link against GLEW +``GLEW_SHARED_LIBRARIES`` + libraries to link against shared GLEW +``GLEW_STATIC_LIBRARIES`` + libraries to link against static GLEW +``GLEW_FOUND`` + true if GLEW has been found and can be used +``GLEW_VERSION`` + GLEW version +``GLEW_VERSION_MAJOR`` + GLEW major version +``GLEW_VERSION_MINOR`` + GLEW minor version +``GLEW_VERSION_MICRO`` + GLEW micro version - GLEW_INCLUDE_DIRS - include directories for GLEW - GLEW_LIBRARIES - libraries to link against GLEW - GLEW_FOUND - true if GLEW has been found and can be used #]=======================================================================] +include(${CMAKE_CURRENT_LIST_DIR}/FindPackageHandleStandardArgs.cmake) + +find_package(GLEW CONFIG QUIET) + +if(GLEW_FOUND) + find_package_handle_standard_args(GLEW DEFAULT_MSG GLEW_CONFIG) + return() +endif() + +if(GLEW_VERBOSE) + message(STATUS "FindGLEW: did not find GLEW CMake config file. Searching for libraries.") +endif() + + +function(__glew_set_find_library_suffix shared_or_static) + if(UNIX AND "${shared_or_static}" MATCHES "SHARED") + set(CMAKE_FIND_LIBRARY_SUFFIXES ".so" PARENT_SCOPE) + elseif(UNIX AND "${shared_or_static}" MATCHES "STATIC") + set(CMAKE_FIND_LIBRARY_SUFFIXES ".a" PARENT_SCOPE) + elseif(APPLE AND "${shared_or_static}" MATCHES "SHARED") + set(CMAKE_FIND_LIBRARY_SUFFIXES ".dylib;.so" PARENT_SCOPE) + elseif(APPLE AND "${shared_or_static}" MATCHES "STATIC") + set(CMAKE_FIND_LIBRARY_SUFFIXES ".a" PARENT_SCOPE) + elseif(WIN32 AND "${shared_or_static}" MATCHES "SHARED") + set(CMAKE_FIND_LIBRARY_SUFFIXES ".lib" PARENT_SCOPE) + elseif(WIN32 AND "${shared_or_static}" MATCHES "STATIC") + set(CMAKE_FIND_LIBRARY_SUFFIXES ".lib;.dll.a" PARENT_SCOPE) + endif() + + if(GLEW_VERBOSE) + message(STATUS "FindGLEW: CMAKE_FIND_LIBRARY_SUFFIXES for ${shared_or_static}: ${CMAKE_FIND_LIBRARY_SUFFIXES}") + endif() +endfunction() + + +if(GLEW_VERBOSE) + if(DEFINED GLEW_USE_STATIC_LIBS) + message(STATUS "FindGLEW: GLEW_USE_STATIC_LIBS: ${GLEW_USE_STATIC_LIBS}.") + else() + message(STATUS "FindGLEW: GLEW_USE_STATIC_LIBS is undefined. Treated as FALSE.") + endif() +endif() + find_path(GLEW_INCLUDE_DIR GL/glew.h) +mark_as_advanced(GLEW_INCLUDE_DIR) -if(NOT GLEW_LIBRARY) - find_library(GLEW_LIBRARY_RELEASE NAMES GLEW glew32 glew glew32s PATH_SUFFIXES lib64 libx32) - find_library(GLEW_LIBRARY_DEBUG NAMES GLEWd glew32d glewd PATH_SUFFIXES lib64) +set(GLEW_INCLUDE_DIRS ${GLEW_INCLUDE_DIR}) - include(${CMAKE_CURRENT_LIST_DIR}/SelectLibraryConfigurations.cmake) - select_library_configurations(GLEW) -endif () +if(GLEW_VERBOSE) + message(STATUS "FindGLEW: GLEW_INCLUDE_DIR: ${GLEW_INCLUDE_DIR}") + message(STATUS "FindGLEW: GLEW_INCLUDE_DIRS: ${GLEW_INCLUDE_DIRS}") +endif() + +if("${CMAKE_GENERATOR_PLATFORM}" MATCHES "x64" OR "${CMAKE_GENERATOR}" MATCHES "Win64") + set(_arch "x64") +else() + set(_arch "Win32") +endif() + + +__glew_set_find_library_suffix(SHARED) + +find_library(GLEW_SHARED_LIBRARY_RELEASE + NAMES GLEW glew glew32 + PATH_SUFFIXES lib lib64 libx32 lib/Release/${_arch} + PATHS ENV GLEW_ROOT) + +find_library(GLEW_SHARED_LIBRARY_DEBUG + NAMES GLEWd glewd glew32d + PATH_SUFFIXES lib lib64 + PATHS ENV GLEW_ROOT) + + +__glew_set_find_library_suffix(STATIC) + +find_library(GLEW_STATIC_LIBRARY_RELEASE + NAMES GLEW glew glew32s + PATH_SUFFIXES lib lib64 libx32 lib/Release/${_arch} + PATHS ENV GLEW_ROOT) + +find_library(GLEW_STATIC_LIBRARY_DEBUG + NAMES GLEWds glewds glew32ds + PATH_SUFFIXES lib lib64 + PATHS ENV GLEW_ROOT) + +include(${CMAKE_CURRENT_LIST_DIR}/SelectLibraryConfigurations.cmake) + +select_library_configurations(GLEW_SHARED) +select_library_configurations(GLEW_STATIC) + +if(NOT GLEW_USE_STATIC_LIBS) + set(GLEW_LIBRARIES ${GLEW_SHARED_LIBRARY}) +else() + set(GLEW_LIBRARIES ${GLEW_STATIC_LIBRARY}) +endif() + + +if(GLEW_VERBOSE) + message(STATUS "FindGLEW: GLEW_SHARED_LIBRARY_RELEASE: ${GLEW_SHARED_LIBRARY_RELEASE}") + message(STATUS "FindGLEW: GLEW_STATIC_LIBRARY_RELEASE: ${GLEW_STATIC_LIBRARY_RELEASE}") + message(STATUS "FindGLEW: GLEW_SHARED_LIBRARY_DEBUG: ${GLEW_SHARED_LIBRARY_DEBUG}") + message(STATUS "FindGLEW: GLEW_STATIC_LIBRARY_DEBUG: ${GLEW_STATIC_LIBRARY_DEBUG}") + message(STATUS "FindGLEW: GLEW_SHARED_LIBRARY: ${GLEW_SHARED_LIBRARY}") + message(STATUS "FindGLEW: GLEW_STATIC_LIBRARY: ${GLEW_STATIC_LIBRARY}") + message(STATUS "FindGLEW: GLEW_LIBRARIES: ${GLEW_LIBRARIES}") +endif() + + +# Read version from GL/glew.h file +if(EXISTS "${GLEW_INCLUDE_DIR}/GL/glew.h") + file(STRINGS "${GLEW_INCLUDE_DIR}/GL/glew.h" _contents REGEX "^VERSION_.+ [0-9]+") + if(_contents) + string(REGEX REPLACE ".*VERSION_MAJOR[ \t]+([0-9]+).*" "\\1" GLEW_VERSION_MAJOR "${_contents}") + string(REGEX REPLACE ".*VERSION_MINOR[ \t]+([0-9]+).*" "\\1" GLEW_VERSION_MINOR "${_contents}") + string(REGEX REPLACE ".*VERSION_MICRO[ \t]+([0-9]+).*" "\\1" GLEW_VERSION_MICRO "${_contents}") + set(GLEW_VERSION "${GLEW_VERSION_MAJOR}.${GLEW_VERSION_MINOR}.${GLEW_VERSION_MICRO}") + endif() +endif() + +if(GLEW_VERBOSE) + message(STATUS "FindGLEW: GLEW_VERSION_MAJOR: ${GLEW_VERSION_MAJOR}") + message(STATUS "FindGLEW: GLEW_VERSION_MINOR: ${GLEW_VERSION_MINOR}") + message(STATUS "FindGLEW: GLEW_VERSION_MICRO: ${GLEW_VERSION_MICRO}") + message(STATUS "FindGLEW: GLEW_VERSION: ${GLEW_VERSION}") +endif() -include(${CMAKE_CURRENT_LIST_DIR}/FindPackageHandleStandardArgs.cmake) find_package_handle_standard_args(GLEW - REQUIRED_VARS GLEW_INCLUDE_DIR GLEW_LIBRARY) + REQUIRED_VARS GLEW_INCLUDE_DIRS GLEW_LIBRARIES + VERSION_VAR GLEW_VERSION) -if(GLEW_FOUND) - set(GLEW_INCLUDE_DIRS ${GLEW_INCLUDE_DIR}) +if(NOT GLEW_FOUND) + if(GLEW_VERBOSE) + message(STATUS "FindGLEW: could not found GLEW library.") + endif() + return() +endif() + + +if(NOT TARGET GLEW::glew AND NOT GLEW_USE_STATIC_LIBS) + if(GLEW_VERBOSE) + message(STATUS "FindGLEW: Creating GLEW::glew imported target.") + endif() + + add_library(GLEW::glew UNKNOWN IMPORTED) + + set_target_properties(GLEW::glew + PROPERTIES INTERFACE_INCLUDE_DIRECTORIES "${GLEW_INCLUDE_DIRS}") + + if(GLEW_SHARED_LIBRARY_RELEASE) + set_property(TARGET GLEW::glew + APPEND + PROPERTY IMPORTED_CONFIGURATIONS RELEASE) + + set_target_properties(GLEW::glew + PROPERTIES IMPORTED_LOCATION_RELEASE "${GLEW_SHARED_LIBRARY_RELEASE}") + endif() + + if(GLEW_SHARED_LIBRARY_DEBUG) + set_property(TARGET GLEW::glew + APPEND + PROPERTY IMPORTED_CONFIGURATIONS DEBUG) + + set_target_properties(GLEW::glew + PROPERTIES IMPORTED_LOCATION_DEBUG "${GLEW_SHARED_LIBRARY_DEBUG}") + endif() - if(NOT GLEW_LIBRARIES) - set(GLEW_LIBRARIES ${GLEW_LIBRARY}) +elseif(NOT TARGET GLEW::glew_s AND GLEW_USE_STATIC_LIBS) + if(GLEW_VERBOSE) + message(STATUS "FindGLEW: Creating GLEW::glew_s imported target.") endif() - if (NOT TARGET GLEW::GLEW) - add_library(GLEW::GLEW UNKNOWN IMPORTED) - set_target_properties(GLEW::GLEW PROPERTIES - INTERFACE_INCLUDE_DIRECTORIES "${GLEW_INCLUDE_DIRS}") + add_library(GLEW::glew_s UNKNOWN IMPORTED) - if(GLEW_LIBRARY_RELEASE) - set_property(TARGET GLEW::GLEW APPEND PROPERTY IMPORTED_CONFIGURATIONS RELEASE) - set_target_properties(GLEW::GLEW PROPERTIES IMPORTED_LOCATION_RELEASE "${GLEW_LIBRARY_RELEASE}") + set_target_properties(GLEW::glew_s + PROPERTIES INTERFACE_INCLUDE_DIRECTORIES "${GLEW_INCLUDE_DIRS}") + + if(GLEW_STATIC_LIBRARY_RELEASE) + set_property(TARGET GLEW::glew_s + APPEND + PROPERTY IMPORTED_CONFIGURATIONS RELEASE) + + set_target_properties(GLEW::glew_s + PROPERTIES IMPORTED_LOCATION_RELEASE "${GLEW_STATIC_LIBRARY_RELEASE}") + endif() + + if(GLEW_STATIC_LIBRARY_DEBUG) + set_property(TARGET GLEW::glew_s + APPEND + PROPERTY IMPORTED_CONFIGURATIONS DEBUG) + + set_target_properties(GLEW::glew_s + PROPERTIES IMPORTED_LOCATION_DEBUG "${GLEW_STATIC_LIBRARY_DEBUG}") + endif() +endif() + +if(NOT TARGET GLEW::GLEW) + if(GLEW_VERBOSE) + message(STATUS "FindGLEW: Creating GLEW::GLEW imported target.") + endif() + + add_library(GLEW::GLEW UNKNOWN IMPORTED) + + set_target_properties(GLEW::GLEW + PROPERTIES INTERFACE_INCLUDE_DIRECTORIES "${GLEW_INCLUDE_DIRS}") + + if(TARGET GLEW::glew) + if(GLEW_SHARED_LIBRARY_RELEASE) + set_property(TARGET GLEW::GLEW + APPEND + PROPERTY IMPORTED_CONFIGURATIONS RELEASE) + + set_target_properties(GLEW::GLEW + PROPERTIES IMPORTED_LOCATION_RELEASE "${GLEW_SHARED_LIBRARY_RELEASE}") + endif() + + if(GLEW_SHARED_LIBRARY_DEBUG) + set_property(TARGET GLEW::GLEW + APPEND + PROPERTY IMPORTED_CONFIGURATIONS DEBUG) + + set_target_properties(GLEW::GLEW + PROPERTIES IMPORTED_LOCATION_DEBUG "${GLEW_SHARED_LIBRARY_DEBUG}") endif() - if(GLEW_LIBRARY_DEBUG) - set_property(TARGET GLEW::GLEW APPEND PROPERTY IMPORTED_CONFIGURATIONS DEBUG) - set_target_properties(GLEW::GLEW PROPERTIES IMPORTED_LOCATION_DEBUG "${GLEW_LIBRARY_DEBUG}") + elseif(TARGET GLEW::glew_s) + if(GLEW_STATIC_LIBRARY_RELEASE) + set_property(TARGET GLEW::GLEW + APPEND + PROPERTY IMPORTED_CONFIGURATIONS RELEASE) + + set_target_properties(GLEW::GLEW + PROPERTIES IMPORTED_LOCATION_RELEASE "${GLEW_STATIC_LIBRARY_RELEASE}") endif() - if(NOT GLEW_LIBRARY_RELEASE AND NOT GLEW_LIBRARY_DEBUG) - set_property(TARGET GLEW::GLEW APPEND PROPERTY IMPORTED_LOCATION "${GLEW_LIBRARY}") + if(GLEW_STATIC_LIBRARY_DEBUG AND GLEW_USE_STATIC_LIBS) + set_property(TARGET GLEW::GLEW + APPEND + PROPERTY IMPORTED_CONFIGURATIONS DEBUG) + + set_target_properties(GLEW::GLEW + PROPERTIES IMPORTED_LOCATION_DEBUG "${GLEW_STATIC_LIBRARY_DEBUG}") endif() + + elseif(GLEW_VERBOSE) + message(WARNING "FindGLEW: no `GLEW::glew` or `GLEW::glew_s` target was created. Something went wrong in FindGLEW target creation.") endif() endif() - -mark_as_advanced(GLEW_INCLUDE_DIR) diff --git a/Modules/FindGTK2.cmake b/Modules/FindGTK2.cmake index 6c1897c..3bd61a9 100644 --- a/Modules/FindGTK2.cmake +++ b/Modules/FindGTK2.cmake @@ -303,9 +303,7 @@ function(_GTK2_FIND_INCLUDE_DIR _var _hdr) /opt/gnome/lib /opt/openwin/include /usr/openwin/lib - /sw/include /sw/lib - /opt/local/include /opt/local/lib /usr/pkg/lib /usr/pkg/include/glib @@ -415,7 +413,6 @@ function(_GTK2_FIND_LIBRARY _var _lib _expand_vc _append_version) PATHS /opt/gnome/lib /usr/openwin/lib - /sw/lib $ENV{GTKMM_BASEPATH}/lib [HKEY_CURRENT_USER\\SOFTWARE\\gtkmm\\2.4;Path]/lib [HKEY_LOCAL_MACHINE\\SOFTWARE\\gtkmm\\2.4;Path]/lib diff --git a/Modules/FindLua50.cmake b/Modules/FindLua50.cmake index aafc056..52a54e7 100644 --- a/Modules/FindLua50.cmake +++ b/Modules/FindLua50.cmake @@ -40,9 +40,6 @@ find_path(LUA_INCLUDE_DIR lua.h PATHS ~/Library/Frameworks /Library/Frameworks - /sw # Fink - /opt/local # DarwinPorts - /opt/csw # Blastwave /opt ) @@ -54,9 +51,6 @@ find_library(LUA_LIBRARY_lua PATHS ~/Library/Frameworks /Library/Frameworks - /sw - /opt/local - /opt/csw /opt ) @@ -72,9 +66,6 @@ else() ENV LUA_DIR PATH_SUFFIXES lib PATHS - /sw - /opt/local - /opt/csw /opt ) if(LUA_LIBRARY_lualib AND LUA_LIBRARY_lua) diff --git a/Modules/FindLua51.cmake b/Modules/FindLua51.cmake index 31eaf87..1c9029b 100644 --- a/Modules/FindLua51.cmake +++ b/Modules/FindLua51.cmake @@ -41,9 +41,6 @@ find_path(LUA_INCLUDE_DIR lua.h PATHS ~/Library/Frameworks /Library/Frameworks - /sw # Fink - /opt/local # DarwinPorts - /opt/csw # Blastwave /opt ) @@ -55,9 +52,6 @@ find_library(LUA_LIBRARY PATHS ~/Library/Frameworks /Library/Frameworks - /sw - /opt/local - /opt/csw /opt ) diff --git a/Modules/FindOpenAL.cmake b/Modules/FindOpenAL.cmake index dbd7961..18f3ff6 100644 --- a/Modules/FindOpenAL.cmake +++ b/Modules/FindOpenAL.cmake @@ -63,9 +63,6 @@ find_path(OPENAL_INCLUDE_DIR al.h PATHS ~/Library/Frameworks /Library/Frameworks - /sw # Fink - /opt/local # DarwinPorts - /opt/csw # Blastwave /opt [HKEY_LOCAL_MACHINE\\SOFTWARE\\Creative\ Labs\\OpenAL\ 1.1\ Software\ Development\ Kit\\1.00.0000;InstallDir] ) @@ -84,9 +81,6 @@ find_library(OPENAL_LIBRARY PATHS ~/Library/Frameworks /Library/Frameworks - /sw - /opt/local - /opt/csw /opt [HKEY_LOCAL_MACHINE\\SOFTWARE\\Creative\ Labs\\OpenAL\ 1.1\ Software\ Development\ Kit\\1.00.0000;InstallDir] ) diff --git a/Modules/FindPhysFS.cmake b/Modules/FindPhysFS.cmake index 0366f77..a32f83a 100644 --- a/Modules/FindPhysFS.cmake +++ b/Modules/FindPhysFS.cmake @@ -24,9 +24,6 @@ find_path(PHYSFS_INCLUDE_DIR physfs.h PATHS ~/Library/Frameworks /Library/Frameworks - /sw # Fink - /opt/local # DarwinPorts - /opt/csw # Blastwave /opt ) @@ -38,9 +35,6 @@ find_library(PHYSFS_LIBRARY PATHS ~/Library/Frameworks /Library/Frameworks - /sw - /opt/local - /opt/csw /opt ) diff --git a/Modules/FindPkgConfig.cmake b/Modules/FindPkgConfig.cmake index e192426..cf0ae09 100644 --- a/Modules/FindPkgConfig.cmake +++ b/Modules/FindPkgConfig.cmake @@ -242,7 +242,7 @@ endfunction() function(_pkg_create_imp_target _prefix _imp_target_global) # only create the target if it is linkable, i.e. no executables if (NOT TARGET PkgConfig::${_prefix} - AND ( ${_prefix}_INCLUDE_DIRS OR ${_prefix}_LINK_LIBRARIES OR ${_prefix}_CFLAGS_OTHER )) + AND ( ${_prefix}_INCLUDE_DIRS OR ${_prefix}_LINK_LIBRARIES OR ${_prefix}_LDFLAGS_OTHER OR ${_prefix}_CFLAGS_OTHER )) if(${_imp_target_global}) set(_global_opt "GLOBAL") else() @@ -258,6 +258,10 @@ function(_pkg_create_imp_target _prefix _imp_target_global) set_property(TARGET PkgConfig::${_prefix} PROPERTY INTERFACE_LINK_LIBRARIES "${${_prefix}_LINK_LIBRARIES}") endif() + if(${_prefix}_LDFLAGS_OTHER) + set_property(TARGET PkgConfig::${_prefix} PROPERTY + INTERFACE_LINK_OPTIONS "${${_prefix}_LDFLAGS_OTHER}") + endif() if(${_prefix}_CFLAGS_OTHER) set_property(TARGET PkgConfig::${_prefix} PROPERTY INTERFACE_COMPILE_OPTIONS "${${_prefix}_CFLAGS_OTHER}") diff --git a/Modules/FindProducer.cmake b/Modules/FindProducer.cmake index fba0494..65495b5 100644 --- a/Modules/FindProducer.cmake +++ b/Modules/FindProducer.cmake @@ -45,12 +45,9 @@ find_path(PRODUCER_INCLUDE_DIR Producer/CameraGroup PATHS ~/Library/Frameworks /Library/Frameworks - /sw/include # Fink - /opt/local/include # DarwinPorts - /opt/csw/include # Blastwave - /opt/include - [HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Control\\Session\ Manager\\Environment;OpenThreads_ROOT]/include - [HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Control\\Session\ Manager\\Environment;OSG_ROOT]/include + /opt + [HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Control\\Session\ Manager\\Environment;OpenThreads_ROOT] + [HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Control\\Session\ Manager\\Environment;OSG_ROOT] ) find_library(PRODUCER_LIBRARY @@ -61,9 +58,6 @@ find_library(PRODUCER_LIBRARY ENV OSGDIR PATH_SUFFIXES lib PATHS - /sw - /opt/local - /opt/csw /opt ) diff --git a/Modules/FindPython.cmake b/Modules/FindPython.cmake index f014916..1c134e2 100644 --- a/Modules/FindPython.cmake +++ b/Modules/FindPython.cmake @@ -28,6 +28,13 @@ is searched. To manage concurrent versions 3 and 2 of Python, use :module:`FindPython3` and :module:`FindPython2` modules rather than this one. +.. note:: + + If components ``Interpreter`` and ``Development`` are both specified, this + module search only for interpreter with same platform architecture as the one + defined by ``CMake`` configuration. This contraint does not apply if only + ``Interpreter`` component is specified. + Imported Targets ^^^^^^^^^^^^^^^^ diff --git a/Modules/FindPython/Support.cmake b/Modules/FindPython/Support.cmake index ef8272c..1236bf8 100644 --- a/Modules/FindPython/Support.cmake +++ b/Modules/FindPython/Support.cmake @@ -341,14 +341,14 @@ if ("Interpreter" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS) ${_${_PYTHON_PREFIX}_IRON_PYTHON_NAMES} NAMES_PER_DIR HINTS ${_${_PYTHON_PREFIX}_HINTS} - PATHS [HKEY_CURRENT_USER\\SOFTWARE\\Python\\PythonCore\\${_${_PYTHON_PREFIX}_VERSION}\\InstallPath] - [HKEY_CURRENT_USER\\SOFTWARE\\Python\\PythonCore\\${_${_PYTHON_PREFIX}_VERSION}-${_${_PYTHON_PREFIX}_ARCH}\\InstallPath] + PATHS [HKEY_CURRENT_USER\\SOFTWARE\\Python\\PythonCore\\${_${_PYTHON_PREFIX}_VERSION}-${_${_PYTHON_PREFIX}_ARCH}\\InstallPath] [HKEY_CURRENT_USER\\SOFTWARE\\Python\\PythonCore\\${_${_PYTHON_PREFIX}_VERSION}-${_${_PYTHON_PREFIX}_ARCH2}\\InstallPath] + [HKEY_CURRENT_USER\\SOFTWARE\\Python\\PythonCore\\${_${_PYTHON_PREFIX}_VERSION}\\InstallPath] [HKEY_CURRENT_USER\\SOFTWARE\\Python\\ContinuumAnalytics\\Anaconda${_${_PYTHON_PREFIX}_VERSION_NO_DOTS}-${_${_PYTHON_PREFIX}_ARCH}\\InstallPath] [HKEY_CURRENT_USER\\SOFTWARE\\Python\\ContinuumAnalytics\\Anaconda${_${_PYTHON_PREFIX}_VERSION_NO_DOTS}-${_${_PYTHON_PREFIX}_ARCH2}\\InstallPath] - [HKEY_LOCAL_MACHINE\\SOFTWARE\\Python\\PythonCore\\${_${_PYTHON_PREFIX}_VERSION}\\InstallPath] [HKEY_LOCAL_MACHINE\\SOFTWARE\\Python\\PythonCore\\${_${_PYTHON_PREFIX}_VERSION}-${_${_PYTHON_PREFIX}_ARCH}\\InstallPath] [HKEY_LOCAL_MACHINE\\SOFTWARE\\Python\\PythonCore\\${_${_PYTHON_PREFIX}_VERSION}-${_${_PYTHON_PREFIX}_ARCH2}\\InstallPath] + [HKEY_LOCAL_MACHINE\\SOFTWARE\\Python\\PythonCore\\${_${_PYTHON_PREFIX}_VERSION}\\InstallPath] [HKEY_LOCAL_MACHINE\\SOFTWARE\\Python\\ContinuumAnalytics\\Anaconda${_${_PYTHON_PREFIX}_VERSION_NO_DOTS}-${_${_PYTHON_PREFIX}_ARCH}\\InstallPath] [HKEY_LOCAL_MACHINE\\SOFTWARE\\Python\\ContinuumAnalytics\\Anaconda${_${_PYTHON_PREFIX}_VERSION_NO_DOTS}-${_${_PYTHON_PREFIX}_ARCH2}\\InstallPath] [HKEY_LOCAL_MACHINE\\SOFTWARE\\IronPython\\${_${_PYTHON_PREFIX}_VERSION}\\InstallPath] @@ -402,14 +402,14 @@ if ("Interpreter" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS) python ${_${_PYTHON_PREFIX}_IRON_PYTHON_NAMES} NAMES_PER_DIR - PATHS [HKEY_CURRENT_USER\\SOFTWARE\\Python\\PythonCore\\${_${_PYTHON_PREFIX}_VERSION}\\InstallPath] - [HKEY_CURRENT_USER\\SOFTWARE\\Python\\PythonCore\\${_${_PYTHON_PREFIX}_VERSION}-${_${_PYTHON_PREFIX}_ARCH}\\InstallPath] + PATHS [HKEY_CURRENT_USER\\SOFTWARE\\Python\\PythonCore\\${_${_PYTHON_PREFIX}_VERSION}-${_${_PYTHON_PREFIX}_ARCH}\\InstallPath] [HKEY_CURRENT_USER\\SOFTWARE\\Python\\PythonCore\\${_${_PYTHON_PREFIX}_VERSION}-${_${_PYTHON_PREFIX}_ARCH2}\\InstallPath] + [HKEY_CURRENT_USER\\SOFTWARE\\Python\\PythonCore\\${_${_PYTHON_PREFIX}_VERSION}\\InstallPath] [HKEY_CURRENT_USER\\SOFTWARE\\Python\\ContinuumAnalytics\\Anaconda${_${_PYTHON_PREFIX}_VERSION_NO_DOTS}-${_${_PYTHON_PREFIX}_ARCH}\\InstallPath] [HKEY_CURRENT_USER\\SOFTWARE\\Python\\ContinuumAnalytics\\Anaconda${_${_PYTHON_PREFIX}_VERSION_NO_DOTS}-${_${_PYTHON_PREFIX}_ARCH2}\\InstallPath] - [HKEY_LOCAL_MACHINE\\SOFTWARE\\Python\\PythonCore\\${_${_PYTHON_PREFIX}_VERSION}\\InstallPath] [HKEY_LOCAL_MACHINE\\SOFTWARE\\Python\\PythonCore\\${_${_PYTHON_PREFIX}_VERSION}-${_${_PYTHON_PREFIX}_ARCH}\\InstallPath] [HKEY_LOCAL_MACHINE\\SOFTWARE\\Python\\PythonCore\\${_${_PYTHON_PREFIX}_VERSION}-${_${_PYTHON_PREFIX}_ARCH2}\\InstallPath] + [HKEY_LOCAL_MACHINE\\SOFTWARE\\Python\\PythonCore\\${_${_PYTHON_PREFIX}_VERSION}\\InstallPath] [HKEY_LOCAL_MACHINE\\SOFTWARE\\Python\\ContinuumAnalytics\\Anaconda${_${_PYTHON_PREFIX}_VERSION_NO_DOTS}-${_${_PYTHON_PREFIX}_ARCH}\\InstallPath] [HKEY_LOCAL_MACHINE\\SOFTWARE\\Python\\ContinuumAnalytics\\Anaconda${_${_PYTHON_PREFIX}_VERSION_NO_DOTS}-${_${_PYTHON_PREFIX}_ARCH2}\\InstallPath] [HKEY_LOCAL_MACHINE\\SOFTWARE\\IronPython\\${_${_PYTHON_PREFIX}_VERSION}\\InstallPath] @@ -816,14 +816,14 @@ if ("Development" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS _python_get_frameworks (_${_PYTHON_PREFIX}_FRAMEWORK_PATHS ${_${_PYTHON_PREFIX}_VERSION}) set (_${_PYTHON_PREFIX}_REGISTRY_PATHS - [HKEY_CURRENT_USER\\SOFTWARE\\Python\\PythonCore\\${_${_PYTHON_PREFIX}_VERSION}\\InstallPath] [HKEY_CURRENT_USER\\SOFTWARE\\Python\\PythonCore\\${_${_PYTHON_PREFIX}_VERSION}-${_${_PYTHON_PREFIX}_ARCH}\\InstallPath] [HKEY_CURRENT_USER\\SOFTWARE\\Python\\PythonCore\\${_${_PYTHON_PREFIX}_VERSION}-${_${_PYTHON_PREFIX}_ARCH2}\\InstallPath] + [HKEY_CURRENT_USER\\SOFTWARE\\Python\\PythonCore\\${_${_PYTHON_PREFIX}_VERSION}\\InstallPath] [HKEY_CURRENT_USER\\SOFTWARE\\Python\\ContinuumAnalytics\\Anaconda${_${_PYTHON_PREFIX}_VERSION_NO_DOTS}-${_${_PYTHON_PREFIX}_ARCH}\\InstallPath] [HKEY_CURRENT_USER\\SOFTWARE\\Python\\ContinuumAnalytics\\Anaconda${_${_PYTHON_PREFIX}_VERSION_NO_DOTS}-${_${_PYTHON_PREFIX}_ARCH2}\\InstallPath] - [HKEY_LOCAL_MACHINE\\SOFTWARE\\Python\\PythonCore\\${_${_PYTHON_PREFIX}_VERSION}\\InstallPath] [HKEY_LOCAL_MACHINE\\SOFTWARE\\Python\\PythonCore\\${_${_PYTHON_PREFIX}_VERSION}-${_${_PYTHON_PREFIX}_ARCH}\\InstallPath] [HKEY_LOCAL_MACHINE\\SOFTWARE\\Python\\PythonCore\\${_${_PYTHON_PREFIX}_VERSION}-${_${_PYTHON_PREFIX}_ARCH2}\\InstallPath] + [HKEY_LOCAL_MACHINE\\SOFTWARE\\Python\\PythonCore\\${_${_PYTHON_PREFIX}_VERSION}\\InstallPath] [HKEY_LOCAL_MACHINE\\SOFTWARE\\Python\\ContinuumAnalytics\\Anaconda${_${_PYTHON_PREFIX}_VERSION_NO_DOTS}-${_${_PYTHON_PREFIX}_ARCH}\\InstallPath] [HKEY_LOCAL_MACHINE\\SOFTWARE\\Python\\ContinuumAnalytics\\Anaconda${_${_PYTHON_PREFIX}_VERSION_NO_DOTS}-${_${_PYTHON_PREFIX}_ARCH2}\\InstallPath]) diff --git a/Modules/FindPython2.cmake b/Modules/FindPython2.cmake index 0bb7b28..b9c0b6b 100644 --- a/Modules/FindPython2.cmake +++ b/Modules/FindPython2.cmake @@ -29,6 +29,13 @@ concurrently with :module:`FindPython3` module to use both Python versions. The :module:`FindPython` module can be used if Python version does not matter for you. +.. note:: + + If components ``Interpreter`` and ``Development`` are both specified, this + module search only for interpreter with same platform architecture as the one + defined by ``CMake`` configuration. This contraint does not apply if only + ``Interpreter`` component is specified. + Imported Targets ^^^^^^^^^^^^^^^^ diff --git a/Modules/FindPython3.cmake b/Modules/FindPython3.cmake index b3dfff3..c2f3384 100644 --- a/Modules/FindPython3.cmake +++ b/Modules/FindPython3.cmake @@ -29,6 +29,13 @@ concurrently with :module:`FindPython2` module to use both Python versions. The :module:`FindPython` module can be used if Python version does not matter for you. +.. note:: + + If components ``Interpreter`` and ``Development`` are both specified, this + module search only for interpreter with same platform architecture as the one + defined by ``CMake`` configuration. This contraint does not apply if only + ``Interpreter`` component is specified. + Imported Targets ^^^^^^^^^^^^^^^^ diff --git a/Modules/FindSDL.cmake b/Modules/FindSDL.cmake index 2813831..8d793a9 100644 --- a/Modules/FindSDL.cmake +++ b/Modules/FindSDL.cmake @@ -112,9 +112,6 @@ if(NOT SDL_BUILDING_LIBRARY) ENV SDLDIR PATH_SUFFIXES lib ${VC_LIB_PATH_SUFFIX} PATHS - /sw - /opt/local - /opt/csw /opt ) endif() diff --git a/Modules/FindSDL_sound.cmake b/Modules/FindSDL_sound.cmake index e217981..c986574 100644 --- a/Modules/FindSDL_sound.cmake +++ b/Modules/FindSDL_sound.cmake @@ -208,9 +208,6 @@ if(SDL_FOUND AND SDL_SOUND_INCLUDE_DIR AND SDL_SOUND_LIBRARY) ENV MIKMODDIR ENV SDLSOUNDDIR ENV SDLDIR - /sw - /opt/local - /opt/csw /opt PATH_SUFFIXES lib @@ -228,9 +225,6 @@ if(SDL_FOUND AND SDL_SOUND_INCLUDE_DIR AND SDL_SOUND_LIBRARY) ENV MODPLUGDIR ENV SDLSOUNDDIR ENV SDLDIR - /sw - /opt/local - /opt/csw /opt PATH_SUFFIXES lib @@ -250,9 +244,6 @@ if(SDL_FOUND AND SDL_SOUND_INCLUDE_DIR AND SDL_SOUND_LIBRARY) ENV OGGDIR ENV SDLSOUNDDIR ENV SDLDIR - /sw - /opt/local - /opt/csw /opt PATH_SUFFIXES lib @@ -268,9 +259,6 @@ if(SDL_FOUND AND SDL_SOUND_INCLUDE_DIR AND SDL_SOUND_LIBRARY) ENV VORBISDIR ENV SDLSOUNDDIR ENV SDLDIR - /sw - /opt/local - /opt/csw /opt PATH_SUFFIXES lib @@ -289,9 +277,6 @@ if(SDL_FOUND AND SDL_SOUND_INCLUDE_DIR AND SDL_SOUND_LIBRARY) ENV SMPEGDIR ENV SDLSOUNDDIR ENV SDLDIR - /sw - /opt/local - /opt/csw /opt PATH_SUFFIXES lib @@ -310,9 +295,6 @@ if(SDL_FOUND AND SDL_SOUND_INCLUDE_DIR AND SDL_SOUND_LIBRARY) ENV FLACDIR ENV SDLSOUNDDIR ENV SDLDIR - /sw - /opt/local - /opt/csw /opt PATH_SUFFIXES lib @@ -334,9 +316,6 @@ if(SDL_FOUND AND SDL_SOUND_INCLUDE_DIR AND SDL_SOUND_LIBRARY) ENV SPEEXDIR ENV SDLSOUNDDIR ENV SDLDIR - /sw - /opt/local - /opt/csw /opt PATH_SUFFIXES lib @@ -356,9 +335,6 @@ if(SDL_FOUND AND SDL_SOUND_INCLUDE_DIR AND SDL_SOUND_LIBRARY) ENV SPEEXDIR ENV SDLSOUNDDIR ENV SDLDIR - /sw - /opt/local - /opt/csw /opt PATH_SUFFIXES lib ) diff --git a/Modules/Internal/FeatureTesting.cmake b/Modules/Internal/FeatureTesting.cmake index de336e7..b9c20ec 100644 --- a/Modules/Internal/FeatureTesting.cmake +++ b/Modules/Internal/FeatureTesting.cmake @@ -71,10 +71,20 @@ endmacro() macro(_record_compiler_features_c std) list(APPEND CMAKE_C${std}_COMPILE_FEATURES c_std_${std}) - _record_compiler_features(C "${CMAKE_C${std}_STANDARD_COMPILE_OPTION}" CMAKE_C${std}_COMPILE_FEATURES) + + get_property(lang_level_has_features GLOBAL PROPERTY CMAKE_C${std}_KNOWN_FEATURES) + if(lang_level_has_features) + _record_compiler_features(C "${CMAKE_C${std}_STANDARD_COMPILE_OPTION}" CMAKE_C${std}_COMPILE_FEATURES) + endif() + unset(lang_level_has_features) endmacro() macro(_record_compiler_features_cxx std) list(APPEND CMAKE_CXX${std}_COMPILE_FEATURES cxx_std_${std}) - _record_compiler_features(CXX "${CMAKE_CXX${std}_STANDARD_COMPILE_OPTION}" CMAKE_CXX${std}_COMPILE_FEATURES) + + get_property(lang_level_has_features GLOBAL PROPERTY CMAKE_CXX${std}_KNOWN_FEATURES) + if(lang_level_has_features) + _record_compiler_features(CXX "${CMAKE_CXX${std}_STANDARD_COMPILE_OPTION}" CMAKE_CXX${std}_COMPILE_FEATURES) + endif() + unset(lang_level_has_features) endmacro() diff --git a/Source/CMakeLists.txt b/Source/CMakeLists.txt index f65e78f..52f6742 100644 --- a/Source/CMakeLists.txt +++ b/Source/CMakeLists.txt @@ -236,8 +236,10 @@ set(SRCS cmFileLockResult.h cmFilePathChecksum.cxx cmFilePathChecksum.h - cmFileTimeComparison.cxx - cmFileTimeComparison.h + cmFileTime.cxx + cmFileTime.h + cmFileTimeCache.cxx + cmFileTimeCache.h cmFortranParserImpl.cxx cmFSPermissions.cxx cmFSPermissions.h @@ -804,7 +806,7 @@ foreach(check else() set(CMake_${check} 0) endif() - set_property(SOURCE cmFileTimeComparison.cxx APPEND PROPERTY + set_property(SOURCE cmFileTime.cxx APPEND PROPERTY COMPILE_DEFINITIONS CMake_${check}=${CMake_${check}}) endforeach() diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index 9340c35..672ceae 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,5 +1,5 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 14) -set(CMake_VERSION_PATCH 20190315) +set(CMake_VERSION_PATCH 20190322) #set(CMake_VERSION_RC 1) diff --git a/Source/CPack/cmCPackDebGenerator.cxx b/Source/CPack/cmCPackDebGenerator.cxx index 635de49..cfb5efd 100644 --- a/Source/CPack/cmCPackDebGenerator.cxx +++ b/Source/CPack/cmCPackDebGenerator.cxx @@ -195,7 +195,7 @@ bool DebGenerator::generateDataTar() const // XXX/application/usr/bin/myprogram with GEN_WDIR=XXX/application // should not add XXX/application orderedFiles.insert(currentPath); - currentPath = cmSystemTools::CollapseCombinedPath(currentPath, ".."); + currentPath = cmSystemTools::CollapseFullPath("..", currentPath); } } diff --git a/Source/CPack/cmCPackFreeBSDGenerator.cxx b/Source/CPack/cmCPackFreeBSDGenerator.cxx index fcf8af1..dd8127d 100644 --- a/Source/CPack/cmCPackFreeBSDGenerator.cxx +++ b/Source/CPack/cmCPackFreeBSDGenerator.cxx @@ -325,8 +325,7 @@ int cmCPackFreeBSDGenerator::PackageFiles() ONE_PACKAGE_PER_COMPONENT); } - std::string output_dir = - cmSystemTools::CollapseCombinedPath(toplevel, "../"); + std::string output_dir = cmSystemTools::CollapseFullPath("../", toplevel); pkg_create_from_manifest(output_dir.c_str(), ::TXZ, toplevel.c_str(), manifestname.c_str(), nullptr); diff --git a/Source/CTest/cmCTestBuildCommand.cxx b/Source/CTest/cmCTestBuildCommand.cxx index 32f7496..2eacaf1 100644 --- a/Source/CTest/cmCTestBuildCommand.cxx +++ b/Source/CTest/cmCTestBuildCommand.cxx @@ -4,7 +4,6 @@ #include "cmCTest.h" #include "cmCTestBuildHandler.h" -#include "cmCTestGenericHandler.h" #include "cmGlobalGenerator.h" #include "cmMakefile.h" #include "cmMessageType.h" @@ -39,12 +38,10 @@ cmCTestBuildCommand::~cmCTestBuildCommand() cmCTestGenericHandler* cmCTestBuildCommand::InitializeHandler() { - cmCTestGenericHandler* handler = this->CTest->GetInitializedHandler("build"); - if (!handler) { - this->SetError("internal CTest error. Cannot instantiate build handler"); - return nullptr; - } - this->Handler = static_cast<cmCTestBuildHandler*>(handler); + cmCTestBuildHandler* handler = this->CTest->GetBuildHandler(); + handler->Initialize(); + + this->Handler = handler; const char* ctestBuildCommand = this->Makefile->GetDefinition("CTEST_BUILD_COMMAND"); diff --git a/Source/CTest/cmCTestBuildHandler.cxx b/Source/CTest/cmCTestBuildHandler.cxx index 07bc7e7..8ea9a83 100644 --- a/Source/CTest/cmCTestBuildHandler.cxx +++ b/Source/CTest/cmCTestBuildHandler.cxx @@ -5,7 +5,7 @@ #include "cmAlgorithms.h" #include "cmCTest.h" #include "cmDuration.h" -#include "cmFileTimeComparison.h" +#include "cmFileTimeCache.h" #include "cmGeneratedFileStream.h" #include "cmMakefile.h" #include "cmProcessOutput.h" @@ -503,7 +503,7 @@ void cmCTestBuildHandler::GenerateXMLHeader(cmXMLWriter& xml) class cmCTestBuildHandler::FragmentCompare { public: - FragmentCompare(cmFileTimeComparison* ftc) + FragmentCompare(cmFileTimeCache* ftc) : FTC(ftc) { } @@ -513,14 +513,14 @@ public: // Order files by modification time. Use lexicographic order // among files with the same time. int result; - if (this->FTC->FileTimeCompare(l, r, &result) && result != 0) { + if (this->FTC->Compare(l, r, &result) && result != 0) { return result < 0; } return l < r; } private: - cmFileTimeComparison* FTC = nullptr; + cmFileTimeCache* FTC = nullptr; }; void cmCTestBuildHandler::GenerateXMLLaunched(cmXMLWriter& xml) @@ -530,7 +530,7 @@ void cmCTestBuildHandler::GenerateXMLLaunched(cmXMLWriter& xml) } // Sort XML fragments in chronological order. - cmFileTimeComparison ftc; + cmFileTimeCache ftc; FragmentCompare fragmentCompare(&ftc); typedef std::set<std::string, FragmentCompare> Fragments; Fragments fragments(fragmentCompare); diff --git a/Source/CTest/cmCTestConfigureCommand.cxx b/Source/CTest/cmCTestConfigureCommand.cxx index 7b5c3bc..74a932a 100644 --- a/Source/CTest/cmCTestConfigureCommand.cxx +++ b/Source/CTest/cmCTestConfigureCommand.cxx @@ -3,7 +3,7 @@ #include "cmCTestConfigureCommand.h" #include "cmCTest.h" -#include "cmCTestGenericHandler.h" +#include "cmCTestConfigureHandler.h" #include "cmGlobalGenerator.h" #include "cmMakefile.h" #include "cmSystemTools.h" @@ -142,13 +142,8 @@ cmCTestGenericHandler* cmCTestConfigureCommand::InitializeHandler() labelsForSubprojects, this->Quiet); } - cmCTestGenericHandler* handler = - this->CTest->GetInitializedHandler("configure"); - if (!handler) { - this->SetError( - "internal CTest error. Cannot instantiate configure handler"); - return nullptr; - } + cmCTestConfigureHandler* handler = this->CTest->GetConfigureHandler(); + handler->Initialize(); handler->SetQuiet(this->Quiet); return handler; } diff --git a/Source/CTest/cmCTestCoverageCommand.cxx b/Source/CTest/cmCTestCoverageCommand.cxx index d2003ba..07aae76 100644 --- a/Source/CTest/cmCTestCoverageCommand.cxx +++ b/Source/CTest/cmCTestCoverageCommand.cxx @@ -19,12 +19,8 @@ cmCTestGenericHandler* cmCTestCoverageCommand::InitializeHandler() this->CTest->SetCTestConfigurationFromCMakeVariable( this->Makefile, "CoverageExtraFlags", "CTEST_COVERAGE_EXTRA_FLAGS", this->Quiet); - cmCTestCoverageHandler* handler = static_cast<cmCTestCoverageHandler*>( - this->CTest->GetInitializedHandler("coverage")); - if (!handler) { - this->SetError("internal CTest error. Cannot instantiate test handler"); - return nullptr; - } + cmCTestCoverageHandler* handler = this->CTest->GetCoverageHandler(); + handler->Initialize(); // If a LABELS option was given, select only files with the labels. if (this->LabelsMentioned) { diff --git a/Source/CTest/cmCTestMemCheckCommand.cxx b/Source/CTest/cmCTestMemCheckCommand.cxx index a5d5995..7dad1ce 100644 --- a/Source/CTest/cmCTestMemCheckCommand.cxx +++ b/Source/CTest/cmCTestMemCheckCommand.cxx @@ -7,7 +7,6 @@ #include <vector> #include "cmCTest.h" -#include "cmCTestGenericHandler.h" #include "cmCTestMemCheckHandler.h" #include "cmMakefile.h" @@ -20,8 +19,8 @@ cmCTestMemCheckCommand::cmCTestMemCheckCommand() cmCTestGenericHandler* cmCTestMemCheckCommand::InitializeActualHandler() { - cmCTestGenericHandler* handler = - this->CTest->GetInitializedHandler("memcheck"); + cmCTestMemCheckHandler* handler = this->CTest->GetMemCheckHandler(); + handler->Initialize(); this->CTest->SetCTestConfigurationFromCMakeVariable( this->Makefile, "MemoryCheckType", "CTEST_MEMORYCHECK_TYPE", this->Quiet); diff --git a/Source/CTest/cmCTestRunTest.cxx b/Source/CTest/cmCTestRunTest.cxx index 3bf2087..31976b9 100644 --- a/Source/CTest/cmCTestRunTest.cxx +++ b/Source/CTest/cmCTestRunTest.cxx @@ -132,14 +132,17 @@ bool cmCTestRunTest::EndTest(size_t completed, size_t total, bool started) } else { this->TestResult.Status = cmCTestTestHandler::FAILED; outputStream << "***Failed " << reason; - outputTestErrorsToConsole = this->CTest->OutputTestOutputOnTestFailure; + outputTestErrorsToConsole = + this->CTest->GetOutputTestOutputOnTestFailure(); } } else if (res == cmProcess::State::Expired) { outputStream << "***Timeout "; this->TestResult.Status = cmCTestTestHandler::TIMEOUT; - outputTestErrorsToConsole = this->CTest->OutputTestOutputOnTestFailure; + outputTestErrorsToConsole = + this->CTest->GetOutputTestOutputOnTestFailure(); } else if (res == cmProcess::State::Exception) { - outputTestErrorsToConsole = this->CTest->OutputTestOutputOnTestFailure; + outputTestErrorsToConsole = + this->CTest->GetOutputTestOutputOnTestFailure(); outputStream << "***Exception: "; this->TestResult.ExceptionStatus = this->TestProcess->GetExitExceptionString(); diff --git a/Source/CTest/cmCTestSubmitCommand.cxx b/Source/CTest/cmCTestSubmitCommand.cxx index 00c0610..e31d982 100644 --- a/Source/CTest/cmCTestSubmitCommand.cxx +++ b/Source/CTest/cmCTestSubmitCommand.cxx @@ -3,7 +3,6 @@ #include "cmCTestSubmitCommand.h" #include "cmCTest.h" -#include "cmCTestGenericHandler.h" #include "cmCTestSubmitHandler.h" #include "cmMakefile.h" #include "cmMessageType.h" @@ -42,33 +41,23 @@ cmCTestGenericHandler* cmCTestSubmitCommand::InitializeHandler() this->Makefile->GetDefinition("CTEST_NOTES_FILES"); if (notesFilesVariable) { std::vector<std::string> notesFiles; - cmCTest::VectorOfStrings newNotesFiles; cmSystemTools::ExpandListArgument(notesFilesVariable, notesFiles); - newNotesFiles.insert(newNotesFiles.end(), notesFiles.begin(), - notesFiles.end()); - this->CTest->GenerateNotesFile(newNotesFiles); + this->CTest->GenerateNotesFile(notesFiles); } const char* extraFilesVariable = this->Makefile->GetDefinition("CTEST_EXTRA_SUBMIT_FILES"); if (extraFilesVariable) { std::vector<std::string> extraFiles; - cmCTest::VectorOfStrings newExtraFiles; cmSystemTools::ExpandListArgument(extraFilesVariable, extraFiles); - newExtraFiles.insert(newExtraFiles.end(), extraFiles.begin(), - extraFiles.end()); - if (!this->CTest->SubmitExtraFiles(newExtraFiles)) { + if (!this->CTest->SubmitExtraFiles(extraFiles)) { this->SetError("problem submitting extra files."); return nullptr; } } - cmCTestGenericHandler* handler = - this->CTest->GetInitializedHandler("submit"); - if (!handler) { - this->SetError("internal CTest error. Cannot instantiate submit handler"); - return nullptr; - } + cmCTestSubmitHandler* handler = this->CTest->GetSubmitHandler(); + handler->Initialize(); // If no FILES or PARTS given, *all* PARTS are submitted by default. // @@ -90,38 +79,30 @@ cmCTestGenericHandler* cmCTestSubmitCommand::InitializeHandler() // But FILES with no PARTS mentioned should just submit the FILES // without any of the default parts. // - std::set<cmCTest::Part> noParts; - static_cast<cmCTestSubmitHandler*>(handler)->SelectParts(noParts); - - static_cast<cmCTestSubmitHandler*>(handler)->SelectFiles(this->Files); + handler->SelectParts(std::set<cmCTest::Part>()); + handler->SelectFiles(this->Files); } // If a PARTS option was given, select only the named parts for submission. // if (this->PartsMentioned) { - static_cast<cmCTestSubmitHandler*>(handler)->SelectParts(this->Parts); + handler->SelectParts(this->Parts); } // Pass along any HTTPHEADER to the handler if this option was given. if (!this->HttpHeaders.empty()) { - static_cast<cmCTestSubmitHandler*>(handler)->SetHttpHeaders( - this->HttpHeaders); + handler->SetHttpHeaders(this->HttpHeaders); } - static_cast<cmCTestSubmitHandler*>(handler)->SetOption( - "RetryDelay", this->RetryDelay.c_str()); - static_cast<cmCTestSubmitHandler*>(handler)->SetOption( - "RetryCount", this->RetryCount.c_str()); - static_cast<cmCTestSubmitHandler*>(handler)->SetOption( - "InternalTest", this->InternalTest ? "ON" : "OFF"); + handler->SetOption("RetryDelay", this->RetryDelay.c_str()); + handler->SetOption("RetryCount", this->RetryCount.c_str()); + handler->SetOption("InternalTest", this->InternalTest ? "ON" : "OFF"); handler->SetQuiet(this->Quiet); if (this->CDashUpload) { - static_cast<cmCTestSubmitHandler*>(handler)->SetOption( - "CDashUploadFile", this->CDashUploadFile.c_str()); - static_cast<cmCTestSubmitHandler*>(handler)->SetOption( - "CDashUploadType", this->CDashUploadType.c_str()); + handler->SetOption("CDashUploadFile", this->CDashUploadFile.c_str()); + handler->SetOption("CDashUploadType", this->CDashUploadType.c_str()); } return handler; } diff --git a/Source/CTest/cmCTestSubmitCommand.h b/Source/CTest/cmCTestSubmitCommand.h index 0caccd6..4b1bb26 100644 --- a/Source/CTest/cmCTestSubmitCommand.h +++ b/Source/CTest/cmCTestSubmitCommand.h @@ -79,7 +79,7 @@ protected: std::set<cmCTest::Part> Parts; bool FilesMentioned; bool InternalTest; - cmCTest::SetOfStrings Files; + std::set<std::string> Files; std::string RetryCount; std::string RetryDelay; bool CDashUpload; diff --git a/Source/CTest/cmCTestSubmitHandler.cxx b/Source/CTest/cmCTestSubmitHandler.cxx index 1539635..2b54365 100644 --- a/Source/CTest/cmCTestSubmitHandler.cxx +++ b/Source/CTest/cmCTestSubmitHandler.cxx @@ -259,8 +259,7 @@ bool cmCTestSubmitHandler::SubmitUsingHTTP( upload_as += ctest_curl.Escape(this->CTest->GetCurrentTag()); upload_as += "-"; upload_as += ctest_curl.Escape(this->CTest->GetTestModelString()); - cmCTestScriptHandler* ch = static_cast<cmCTestScriptHandler*>( - this->CTest->GetHandler("script")); + cmCTestScriptHandler* ch = this->CTest->GetScriptHandler(); cmake* cm = ch->GetCMake(); if (cm) { const char* subproject = @@ -558,8 +557,7 @@ int cmCTestSubmitHandler::HandleCDashUploadFile(std::string const& file, // has already been uploaded // TODO I added support for subproject. You would need to add // a "&subproject=subprojectname" to the first POST. - cmCTestScriptHandler* ch = - static_cast<cmCTestScriptHandler*>(this->CTest->GetHandler("script")); + cmCTestScriptHandler* ch = this->CTest->GetScriptHandler(); cmake* cm = ch->GetCMake(); const char* subproject = cm->GetState()->GetGlobalProperty("SubProject"); // TODO: Encode values for a URL instead of trusting caller. @@ -902,7 +900,7 @@ void cmCTestSubmitHandler::SelectParts(std::set<cmCTest::Part> const& parts) } } -void cmCTestSubmitHandler::SelectFiles(cmCTest::SetOfStrings const& files) +void cmCTestSubmitHandler::SelectFiles(std::set<std::string> const& files) { this->Files.insert(files.begin(), files.end()); } diff --git a/Source/CTest/cmCTestSubmitHandler.h b/Source/CTest/cmCTestSubmitHandler.h index 58f4f97..e0fed10 100644 --- a/Source/CTest/cmCTestSubmitHandler.h +++ b/Source/CTest/cmCTestSubmitHandler.h @@ -38,7 +38,7 @@ public: void SelectParts(std::set<cmCTest::Part> const& parts); /** Specify a set of files to submit. */ - void SelectFiles(cmCTest::SetOfStrings const& files); + void SelectFiles(std::set<std::string> const& files); // handle the cdash file upload protocol int HandleCDashUploadFile(std::string const& file, std::string const& type); @@ -74,7 +74,7 @@ private: bool SubmitPart[cmCTest::PartCount]; bool HasWarnings; bool HasErrors; - cmCTest::SetOfStrings Files; + std::set<std::string> Files; std::vector<std::string> HttpHeaders; }; diff --git a/Source/CTest/cmCTestTestCommand.cxx b/Source/CTest/cmCTestTestCommand.cxx index 895ca12..cfd5e3d 100644 --- a/Source/CTest/cmCTestTestCommand.cxx +++ b/Source/CTest/cmCTestTestCommand.cxx @@ -4,6 +4,7 @@ #include "cmCTest.h" #include "cmCTestGenericHandler.h" +#include "cmCTestTestHandler.h" #include "cmDuration.h" #include "cmMakefile.h" #include "cmSystemTools.h" @@ -140,5 +141,7 @@ cmCTestGenericHandler* cmCTestTestCommand::InitializeHandler() cmCTestGenericHandler* cmCTestTestCommand::InitializeActualHandler() { - return this->CTest->GetInitializedHandler("test"); + cmCTestTestHandler* handler = this->CTest->GetTestHandler(); + handler->Initialize(); + return handler; } diff --git a/Source/CTest/cmCTestUpdateCommand.cxx b/Source/CTest/cmCTestUpdateCommand.cxx index 3d800f8..a2f1462 100644 --- a/Source/CTest/cmCTestUpdateCommand.cxx +++ b/Source/CTest/cmCTestUpdateCommand.cxx @@ -3,7 +3,7 @@ #include "cmCTestUpdateCommand.h" #include "cmCTest.h" -#include "cmCTestGenericHandler.h" +#include "cmCTestUpdateHandler.h" #include "cmMakefile.h" #include "cmSystemTools.h" @@ -74,12 +74,8 @@ cmCTestGenericHandler* cmCTestUpdateCommand::InitializeHandler() this->CTest->SetCTestConfigurationFromCMakeVariable( this->Makefile, "P4Options", "CTEST_P4_OPTIONS", this->Quiet); - cmCTestGenericHandler* handler = - this->CTest->GetInitializedHandler("update"); - if (!handler) { - this->SetError("internal CTest error. Cannot instantiate update handler"); - return nullptr; - } + cmCTestUpdateHandler* handler = this->CTest->GetUpdateHandler(); + handler->Initialize(); handler->SetCommand(this); if (source_dir.empty()) { this->SetError("source directory not specified. Please use SOURCE tag"); diff --git a/Source/CTest/cmCTestUploadCommand.cxx b/Source/CTest/cmCTestUploadCommand.cxx index 2fe2cd3..59fbf37 100644 --- a/Source/CTest/cmCTestUploadCommand.cxx +++ b/Source/CTest/cmCTestUploadCommand.cxx @@ -6,7 +6,6 @@ #include <vector> #include "cmCTest.h" -#include "cmCTestGenericHandler.h" #include "cmCTestUploadHandler.h" #include "cmMakefile.h" #include "cmMessageType.h" @@ -14,14 +13,9 @@ cmCTestGenericHandler* cmCTestUploadCommand::InitializeHandler() { - cmCTestGenericHandler* handler = - this->CTest->GetInitializedHandler("upload"); - if (!handler) { - this->SetError("internal CTest error. Cannot instantiate upload handler"); - return nullptr; - } - static_cast<cmCTestUploadHandler*>(handler)->SetFiles(this->Files); - + cmCTestUploadHandler* handler = this->CTest->GetUploadHandler(); + handler->Initialize(); + handler->SetFiles(this->Files); handler->SetQuiet(this->Quiet); return handler; } diff --git a/Source/CTest/cmCTestUploadCommand.h b/Source/CTest/cmCTestUploadCommand.h index 61bf1cc..0d3b06e 100644 --- a/Source/CTest/cmCTestUploadCommand.h +++ b/Source/CTest/cmCTestUploadCommand.h @@ -5,9 +5,9 @@ #include "cmConfigure.h" // IWYU pragma: keep -#include "cmCTest.h" #include "cmCTestHandlerCommand.h" +#include <set> #include <string> class cmCTestGenericHandler; @@ -22,8 +22,6 @@ class cmCommand; class cmCTestUploadCommand : public cmCTestHandlerCommand { public: - cmCTestUploadCommand() {} - /** * This is a virtual constructor for the command. */ @@ -55,7 +53,7 @@ protected: ArgumentDoingLast2 }; - cmCTest::SetOfStrings Files; + std::set<std::string> Files; }; #endif diff --git a/Source/CTest/cmCTestUploadHandler.cxx b/Source/CTest/cmCTestUploadHandler.cxx index 261ecab..ee9ee91 100644 --- a/Source/CTest/cmCTestUploadHandler.cxx +++ b/Source/CTest/cmCTestUploadHandler.cxx @@ -2,6 +2,7 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmCTestUploadHandler.h" +#include "cmCTest.h" #include "cmGeneratedFileStream.h" #include "cmVersion.h" #include "cmXMLWriter.h" @@ -20,7 +21,7 @@ void cmCTestUploadHandler::Initialize() this->Files.clear(); } -void cmCTestUploadHandler::SetFiles(const cmCTest::SetOfStrings& files) +void cmCTestUploadHandler::SetFiles(std::set<std::string> const& files) { this->Files = files; } diff --git a/Source/CTest/cmCTestUploadHandler.h b/Source/CTest/cmCTestUploadHandler.h index ff50574..4d8fab4 100644 --- a/Source/CTest/cmCTestUploadHandler.h +++ b/Source/CTest/cmCTestUploadHandler.h @@ -5,9 +5,11 @@ #include "cmConfigure.h" // IWYU pragma: keep -#include "cmCTest.h" #include "cmCTestGenericHandler.h" +#include <set> +#include <string> + /** \class cmCTestUploadHandler * \brief Helper class for CTest * @@ -20,7 +22,6 @@ public: typedef cmCTestGenericHandler Superclass; cmCTestUploadHandler(); - ~cmCTestUploadHandler() override {} /* * The main entry point for this class @@ -30,10 +31,10 @@ public: void Initialize() override; /** Specify a set of files to submit. */ - void SetFiles(cmCTest::SetOfStrings const& files); + void SetFiles(std::set<std::string> const& files); private: - cmCTest::SetOfStrings Files; + std::set<std::string> Files; }; #endif diff --git a/Source/cmArchiveWrite.cxx b/Source/cmArchiveWrite.cxx index 23be603..177ba02 100644 --- a/Source/cmArchiveWrite.cxx +++ b/Source/cmArchiveWrite.cxx @@ -179,12 +179,10 @@ cmArchiveWrite::~cmArchiveWrite() bool cmArchiveWrite::Add(std::string path, size_t skip, const char* prefix, bool recursive) { - if (this->Okay()) { - if (!path.empty() && path.back() == '/') { - path.erase(path.size() - 1); - } - this->AddPath(path.c_str(), skip, prefix, recursive); + if (!path.empty() && path.back() == '/') { + path.erase(path.size() - 1); } + this->AddPath(path.c_str(), skip, prefix, recursive); return this->Okay(); } @@ -220,6 +218,7 @@ bool cmArchiveWrite::AddPath(const char* path, size_t skip, const char* prefix, bool cmArchiveWrite::AddFile(const char* file, size_t skip, const char* prefix) { + this->Error = ""; // Skip the file if we have no name for it. This may happen on a // top-level directory, which does not need to be included anyway. if (skip >= strlen(file)) { @@ -241,7 +240,7 @@ bool cmArchiveWrite::AddFile(const char* file, size_t skip, const char* prefix) cm_archive_entry_copy_pathname(e, dest); if (archive_read_disk_entry_from_file(this->Disk, e, -1, nullptr) != ARCHIVE_OK) { - this->Error = "archive_read_disk_entry_from_file '"; + this->Error = "Unable to read from file '"; this->Error += file; this->Error += "': "; this->Error += cm_archive_error_string(this->Disk); diff --git a/Source/cmCTest.cxx b/Source/cmCTest.cxx index c77bb97..709feac 100644 --- a/Source/cmCTest.cxx +++ b/Source/cmCTest.cxx @@ -43,7 +43,6 @@ #include "cmCTestTestHandler.h" #include "cmCTestUpdateHandler.h" #include "cmCTestUploadHandler.h" -#include "cmCurl.h" #include "cmDynamicLoader.h" #include "cmGeneratedFileStream.h" #include "cmGlobalGenerator.h" @@ -62,12 +61,149 @@ # include <be/kernel/OS.h> /* disable_debugger() API. */ #endif -#define DEBUGOUT \ - std::cout << __LINE__ << " "; \ - std::cout -#define DEBUGERR \ - std::cerr << __LINE__ << " "; \ - std::cerr +struct cmCTest::Private +{ + /** Representation of one part. */ + struct PartInfo + { + void SetName(const std::string& name) { this->Name = name; } + const std::string& GetName() const { return this->Name; } + + void Enable() { this->Enabled = true; } + explicit operator bool() const { return this->Enabled; } + + std::vector<std::string> SubmitFiles; + + private: + bool Enabled = false; + std::string Name; + }; + + int RepeatTests = 1; // default to run each test once + bool RepeatUntilFail = false; + std::string ConfigType; + std::string ScheduleType; + std::chrono::system_clock::time_point StopTime; + bool TestProgressOutput = false; + bool Verbose = false; + bool ExtraVerbose = false; + bool ProduceXML = false; + bool LabelSummary = true; + bool SubprojectSummary = true; + bool UseHTTP10 = false; + bool PrintLabels = false; + bool Failover = false; + + bool FlushTestProgressLine = false; + + bool ForceNewCTestProcess = false; + + bool RunConfigurationScript = false; + + // these are helper classes + cmCTestBuildHandler BuildHandler; + cmCTestBuildAndTestHandler BuildAndTestHandler; + cmCTestCoverageHandler CoverageHandler; + cmCTestScriptHandler ScriptHandler; + cmCTestTestHandler TestHandler; + cmCTestUpdateHandler UpdateHandler; + cmCTestConfigureHandler ConfigureHandler; + cmCTestMemCheckHandler MemCheckHandler; + cmCTestSubmitHandler SubmitHandler; + cmCTestUploadHandler UploadHandler; + + std::vector<cmCTestGenericHandler*> GetTestingHandlers() + { + return { &this->BuildHandler, &this->BuildAndTestHandler, + &this->CoverageHandler, &this->ScriptHandler, + &this->TestHandler, &this->UpdateHandler, + &this->ConfigureHandler, &this->MemCheckHandler, + &this->SubmitHandler, &this->UploadHandler }; + } + + std::map<std::string, cmCTestGenericHandler*> GetNamedTestingHandlers() + { + return { { "build", &this->BuildHandler }, + { "buildtest", &this->BuildAndTestHandler }, + { "coverage", &this->CoverageHandler }, + { "script", &this->ScriptHandler }, + { "test", &this->TestHandler }, + { "update", &this->UpdateHandler }, + { "configure", &this->ConfigureHandler }, + { "memcheck", &this->MemCheckHandler }, + { "submit", &this->SubmitHandler }, + { "upload", &this->UploadHandler } }; + } + + bool ShowOnly = false; + bool OutputAsJson = false; + int OutputAsJsonVersion = 1; + + // TODO: The ctest configuration should be a hierarchy of + // configuration option sources: command-line, script, ini file. + // Then the ini file can get re-loaded whenever it changes without + // affecting any higher-precedence settings. + std::map<std::string, std::string> CTestConfiguration; + std::map<std::string, std::string> CTestConfigurationOverwrites; + + PartInfo Parts[PartCount]; + std::map<std::string, Part> PartMap; + + std::string CurrentTag; + bool TomorrowTag = false; + + int TestModel = cmCTest::EXPERIMENTAL; + std::string SpecificTrack; + + cmDuration TimeOut = cmDuration::zero(); + + cmDuration GlobalTimeout = cmDuration::zero(); + + int MaxTestNameWidth = 30; + + int ParallelLevel = 1; + bool ParallelLevelSetInCli = false; + + unsigned long TestLoad = 0; + + int CompatibilityMode; + + // information for the --build-and-test options + std::string BinaryDir; + + std::string NotesFiles; + + bool InteractiveDebugMode = true; + + bool ShortDateFormat = true; + + bool CompressXMLFiles = false; + bool CompressTestOutput = true; + + // By default we write output to the process output streams. + std::ostream* StreamOut = &std::cout; + std::ostream* StreamErr = &std::cerr; + + bool SuppressUpdatingCTestConfiguration = false; + + bool Debug = false; + bool ShowLineNumbers = false; + bool Quiet = false; + + std::string BuildID; + + std::vector<std::string> InitialCommandLineArguments; + + int SubmitIndex = 0; + + cmGeneratedFileStream* OutputLogFile = nullptr; + int OutputLogFileLastTag = -1; + + bool OutputTestOutputOnTestFailure = false; + bool OutputColorCode = cmCTest::ColoredOutputSupportedByConsole(); + + std::map<std::string, std::string> Definitions; +}; struct tm* cmCTest::GetNightlyTime(std::string const& str, bool tomorrowtag) { @@ -123,6 +259,11 @@ struct tm* cmCTest::GetNightlyTime(std::string const& str, bool tomorrowtag) return lctime; } +bool cmCTest::GetTomorrowTag() const +{ + return this->Impl->TomorrowTag; +} + std::string cmCTest::CleanString(const std::string& str) { std::string::size_type spos = str.find_first_not_of(" \n\t\r\f\v"); @@ -142,7 +283,7 @@ std::string cmCTest::CurrentTime() struct tm* t = localtime(¤ttime); // return ::CleanString(ctime(¤ttime)); char current_time[1024]; - if (this->ShortDateFormat) { + if (this->Impl->ShortDateFormat) { strftime(current_time, 1000, "%b %d %H:%M %Z", t); } else { strftime(current_time, 1000, "%a %b %d %H:%M:%S %Z %Y", t); @@ -160,88 +301,6 @@ std::string cmCTest::GetCostDataFile() return fname; } -#ifdef CMAKE_BUILD_WITH_CMAKE -static size_t HTTPResponseCallback(void* ptr, size_t size, size_t nmemb, - void* data) -{ - int realsize = static_cast<int>(size * nmemb); - - std::string* response = static_cast<std::string*>(data); - const char* chPtr = static_cast<char*>(ptr); - *response += chPtr; - - return realsize; -} - -int cmCTest::HTTPRequest(std::string url, HTTPMethod method, - std::string& response, std::string const& fields, - std::string const& putFile, int timeout) -{ - CURL* curl; - FILE* file; - ::curl_global_init(CURL_GLOBAL_ALL); - curl = ::curl_easy_init(); - cmCurlSetCAInfo(curl); - - // set request options based on method - switch (method) { - case cmCTest::HTTP_POST: - ::curl_easy_setopt(curl, CURLOPT_POST, 1); - ::curl_easy_setopt(curl, CURLOPT_POSTFIELDS, fields.c_str()); - break; - case cmCTest::HTTP_PUT: - if (!cmSystemTools::FileExists(putFile)) { - response = "Error: File "; - response += putFile + " does not exist.\n"; - return -1; - } - ::curl_easy_setopt(curl, CURLOPT_PUT, 1); - file = cmsys::SystemTools::Fopen(putFile, "rb"); - ::curl_easy_setopt(curl, CURLOPT_INFILE, file); - // fall through to append GET fields - CM_FALLTHROUGH; - case cmCTest::HTTP_GET: - if (!fields.empty()) { - url += "?" + fields; - } - break; - } - - ::curl_easy_setopt(curl, CURLOPT_URL, url.c_str()); - ::curl_easy_setopt(curl, CURLOPT_TIMEOUT, timeout); - ::curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1); - - // set response options - ::curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, HTTPResponseCallback); - ::curl_easy_setopt(curl, CURLOPT_FILE, &response); - ::curl_easy_setopt(curl, CURLOPT_FAILONERROR, 1); - - CURLcode res = ::curl_easy_perform(curl); - - ::curl_easy_cleanup(curl); - ::curl_global_cleanup(); - - return static_cast<int>(res); -} -#endif - -std::string cmCTest::MakeURLSafe(const std::string& str) -{ - std::ostringstream ost; - char buffer[10]; - for (unsigned char ch : str) { - if ((ch > 126 || ch < 32 || ch == '&' || ch == '%' || ch == '+' || - ch == '=' || ch == '@') && - ch != 9) { - sprintf(buffer, "%02x;", static_cast<unsigned int>(ch)); - ost << buffer; - } else { - ost << ch; - } - } - return ost.str(); -} - std::string cmCTest::DecodeURL(const std::string& in) { std::string out; @@ -258,92 +317,39 @@ std::string cmCTest::DecodeURL(const std::string& in) } cmCTest::cmCTest() + : Impl(new Private) { - this->LabelSummary = true; - this->SubprojectSummary = true; - this->ParallelLevel = 1; - this->ParallelLevelSetInCli = false; - this->TestLoad = 0; - this->SubmitIndex = 0; - this->Failover = false; - this->ForceNewCTestProcess = false; - this->TomorrowTag = false; - this->TestProgressOutput = false; - this->FlushTestProgressLine = false; - this->Verbose = false; - - this->Debug = false; - this->ShowLineNumbers = false; - this->Quiet = false; - this->ExtraVerbose = false; - this->ProduceXML = false; - this->ShowOnly = false; - this->OutputAsJson = false; - this->OutputAsJsonVersion = 1; - this->RunConfigurationScript = false; - this->UseHTTP10 = false; - this->PrintLabels = false; - this->CompressTestOutput = true; - this->TestModel = cmCTest::EXPERIMENTAL; - this->MaxTestNameWidth = 30; - this->InteractiveDebugMode = true; - this->TimeOut = cmDuration::zero(); - this->GlobalTimeout = cmDuration::zero(); - this->CompressXMLFiles = false; - this->ScheduleType.clear(); - this->OutputLogFile = nullptr; - this->OutputLogFileLastTag = -1; - this->SuppressUpdatingCTestConfiguration = false; - this->BuildID = ""; - this->OutputTestOutputOnTestFailure = false; - this->OutputColorCode = cmCTest::ColoredOutputSupportedByConsole(); - this->RepeatTests = 1; // default to run each test once - this->RepeatUntilFail = false; - std::string envValue; if (cmSystemTools::GetEnv("CTEST_OUTPUT_ON_FAILURE", envValue)) { - this->OutputTestOutputOnTestFailure = !cmSystemTools::IsOff(envValue); + this->Impl->OutputTestOutputOnTestFailure = + !cmSystemTools::IsOff(envValue); } envValue.clear(); if (cmSystemTools::GetEnv("CTEST_PROGRESS_OUTPUT", envValue)) { - this->TestProgressOutput = !cmSystemTools::IsOff(envValue); - } - - this->InitStreams(); - - this->Parts[PartStart].SetName("Start"); - this->Parts[PartUpdate].SetName("Update"); - this->Parts[PartConfigure].SetName("Configure"); - this->Parts[PartBuild].SetName("Build"); - this->Parts[PartTest].SetName("Test"); - this->Parts[PartCoverage].SetName("Coverage"); - this->Parts[PartMemCheck].SetName("MemCheck"); - this->Parts[PartSubmit].SetName("Submit"); - this->Parts[PartNotes].SetName("Notes"); - this->Parts[PartExtraFiles].SetName("ExtraFiles"); - this->Parts[PartUpload].SetName("Upload"); - this->Parts[PartDone].SetName("Done"); + this->Impl->TestProgressOutput = !cmSystemTools::IsOff(envValue); + } + + this->Impl->Parts[PartStart].SetName("Start"); + this->Impl->Parts[PartUpdate].SetName("Update"); + this->Impl->Parts[PartConfigure].SetName("Configure"); + this->Impl->Parts[PartBuild].SetName("Build"); + this->Impl->Parts[PartTest].SetName("Test"); + this->Impl->Parts[PartCoverage].SetName("Coverage"); + this->Impl->Parts[PartMemCheck].SetName("MemCheck"); + this->Impl->Parts[PartSubmit].SetName("Submit"); + this->Impl->Parts[PartNotes].SetName("Notes"); + this->Impl->Parts[PartExtraFiles].SetName("ExtraFiles"); + this->Impl->Parts[PartUpload].SetName("Upload"); + this->Impl->Parts[PartDone].SetName("Done"); // Fill the part name-to-id map. for (Part p = PartStart; p != PartCount; p = Part(p + 1)) { - this->PartMap[cmSystemTools::LowerCase(this->Parts[p].GetName())] = p; + this->Impl + ->PartMap[cmSystemTools::LowerCase(this->Impl->Parts[p].GetName())] = p; } - this->ShortDateFormat = true; - - this->TestingHandlers["build"] = new cmCTestBuildHandler; - this->TestingHandlers["buildtest"] = new cmCTestBuildAndTestHandler; - this->TestingHandlers["coverage"] = new cmCTestCoverageHandler; - this->TestingHandlers["script"] = new cmCTestScriptHandler; - this->TestingHandlers["test"] = new cmCTestTestHandler; - this->TestingHandlers["update"] = new cmCTestUpdateHandler; - this->TestingHandlers["configure"] = new cmCTestConfigureHandler; - this->TestingHandlers["memcheck"] = new cmCTestMemCheckHandler; - this->TestingHandlers["submit"] = new cmCTestSubmitHandler; - this->TestingHandlers["upload"] = new cmCTestUploadHandler; - - for (auto& handler : this->TestingHandlers) { - handler.second->SetCTestInstance(this); + for (auto& handler : this->Impl->GetTestingHandlers()) { + handler->SetCTestInstance(this); } // Make sure we can capture the build tool output. @@ -352,31 +358,40 @@ cmCTest::cmCTest() cmCTest::~cmCTest() { - cmDeleteAll(this->TestingHandlers); - this->SetOutputLogFileName(nullptr); + delete this->Impl->OutputLogFile; +} + +int cmCTest::GetParallelLevel() const +{ + return this->Impl->ParallelLevel; } void cmCTest::SetParallelLevel(int level) { - this->ParallelLevel = level < 1 ? 1 : level; + this->Impl->ParallelLevel = level < 1 ? 1 : level; +} + +unsigned long cmCTest::GetTestLoad() const +{ + return this->Impl->TestLoad; } void cmCTest::SetTestLoad(unsigned long load) { - this->TestLoad = load; + this->Impl->TestLoad = load; } bool cmCTest::ShouldCompressTestOutput() { - return this->CompressTestOutput; + return this->Impl->CompressTestOutput; } cmCTest::Part cmCTest::GetPartFromName(const char* name) { // Look up by lower-case to make names case-insensitive. std::string lower_name = cmSystemTools::LowerCase(name); - PartMapType::const_iterator i = this->PartMap.find(lower_name); - if (i != this->PartMap.end()) { + auto const i = this->Impl->PartMap.find(lower_name); + if (i != this->Impl->PartMap.end()) { return i->second; } @@ -392,19 +407,19 @@ int cmCTest::Initialize(const char* binary_dir, cmCTestStartCommand* command) } cmCTestOptionalLog(this, DEBUG, "Here: " << __LINE__ << std::endl, quiet); - if (!this->InteractiveDebugMode) { + if (!this->Impl->InteractiveDebugMode) { this->BlockTestErrorDiagnostics(); } else { cmSystemTools::PutEnv("CTEST_INTERACTIVE_DEBUG_MODE=1"); } - this->BinaryDir = binary_dir; - cmSystemTools::ConvertToUnixSlashes(this->BinaryDir); + this->Impl->BinaryDir = binary_dir; + cmSystemTools::ConvertToUnixSlashes(this->Impl->BinaryDir); this->UpdateCTestConfiguration(); cmCTestOptionalLog(this, DEBUG, "Here: " << __LINE__ << std::endl, quiet); - if (this->ProduceXML) { + if (this->Impl->ProduceXML) { cmCTestOptionalLog(this, DEBUG, "Here: " << __LINE__ << std::endl, quiet); cmCTestOptionalLog(this, OUTPUT, " Site: " @@ -415,7 +430,7 @@ int cmCTest::Initialize(const char* binary_dir, cmCTestStartCommand* command) << std::endl, quiet); cmCTestOptionalLog(this, DEBUG, "Produce XML is on" << std::endl, quiet); - if (this->TestModel == cmCTest::NIGHTLY && + if (this->Impl->TestModel == cmCTest::NIGHTLY && this->GetCTestConfiguration("NightlyStartTime").empty()) { cmCTestOptionalLog( this, WARNING, @@ -435,17 +450,18 @@ int cmCTest::Initialize(const char* binary_dir, cmCTestStartCommand* command) cm.GetCurrentSnapshot().SetDefaultDefinitions(); cmGlobalGenerator gg(&cm); cmMakefile mf(&gg, cm.GetCurrentSnapshot()); - if (!this->ReadCustomConfigurationFileTree(this->BinaryDir.c_str(), &mf)) { + if (!this->ReadCustomConfigurationFileTree(this->Impl->BinaryDir.c_str(), + &mf)) { cmCTestOptionalLog( this, DEBUG, "Cannot find custom configuration file tree" << std::endl, quiet); return 0; } - if (this->ProduceXML) { + if (this->Impl->ProduceXML) { // Verify "Testing" directory exists: // - std::string testingDir = this->BinaryDir + "/Testing"; + std::string testingDir = this->Impl->BinaryDir + "/Testing"; if (cmSystemTools::FileExists(testingDir)) { if (!cmSystemTools::FileIsDirectory(testingDir)) { cmCTestLog(this, ERROR_MESSAGE, @@ -475,7 +491,7 @@ int cmCTest::Initialize(const char* binary_dir, cmCTestStartCommand* command) if (createNewTag) { time_t tctime = time(nullptr); - if (this->TomorrowTag) { + if (this->Impl->TomorrowTag) { tctime += (24 * 60 * 60); } struct tm* lctime = gmtime(&tctime); @@ -493,26 +509,28 @@ int cmCTest::Initialize(const char* binary_dir, cmCTestStartCommand* command) } std::string track; if (cmSystemTools::GetLineFromStream(tfin, track) && - !this->Parts[PartStart] && !command) { - this->SpecificTrack = track; + !this->Impl->Parts[PartStart] && !command) { + this->Impl->SpecificTrack = track; } std::string model; if (cmSystemTools::GetLineFromStream(tfin, model) && - !this->Parts[PartStart] && !command) { - this->TestModel = GetTestModelFromString(model.c_str()); + !this->Impl->Parts[PartStart] && !command) { + this->Impl->TestModel = GetTestModelFromString(model.c_str()); } tfin.close(); } - if (tag.empty() || (nullptr != command) || this->Parts[PartStart]) { + if (tag.empty() || (nullptr != command) || + this->Impl->Parts[PartStart]) { cmCTestOptionalLog( this, DEBUG, "TestModel: " << this->GetTestModelString() << std::endl, quiet); - cmCTestOptionalLog( - this, DEBUG, "TestModel: " << this->TestModel << std::endl, quiet); - if (this->TestModel == cmCTest::NIGHTLY) { + cmCTestOptionalLog(this, DEBUG, + "TestModel: " << this->Impl->TestModel << std::endl, + quiet); + if (this->Impl->TestModel == cmCTest::NIGHTLY) { lctime = this->GetNightlyTime( this->GetCTestConfiguration("NightlyStartTime"), - this->TomorrowTag); + this->Impl->TomorrowTag); } char datestring[100]; sprintf(datestring, "%04d%02d%02d-%02d%02d", lctime->tm_year + 1900, @@ -523,7 +541,7 @@ int cmCTest::Initialize(const char* binary_dir, cmCTestStartCommand* command) if (ofs) { ofs << tag << std::endl; ofs << this->GetTestModelString() << std::endl; - switch (this->TestModel) { + switch (this->Impl->TestModel) { case cmCTest::EXPERIMENTAL: ofs << "Experimental" << std::endl; break; @@ -565,7 +583,7 @@ int cmCTest::Initialize(const char* binary_dir, cmCTestStartCommand* command) return 0; } - if (this->TestModel == cmCTest::UNKNOWN) { + if (this->Impl->TestModel == cmCTest::UNKNOWN) { if (model == cmCTest::UNKNOWN) { cmCTestLog(this, ERROR_MESSAGE, "TAG file does not contain model and " @@ -577,8 +595,8 @@ int cmCTest::Initialize(const char* binary_dir, cmCTestStartCommand* command) this->SetTestModel(model); } - if (model != this->TestModel && model != cmCTest::UNKNOWN && - this->TestModel != cmCTest::UNKNOWN) { + if (model != this->Impl->TestModel && model != cmCTest::UNKNOWN && + this->Impl->TestModel != cmCTest::UNKNOWN) { cmCTestOptionalLog(this, WARNING, "Model given in TAG does not match " "model given in ctest_start()" @@ -586,14 +604,15 @@ int cmCTest::Initialize(const char* binary_dir, cmCTestStartCommand* command) quiet); } - if (!this->SpecificTrack.empty() && track != this->SpecificTrack) { + if (!this->Impl->SpecificTrack.empty() && + track != this->Impl->SpecificTrack) { cmCTestOptionalLog(this, WARNING, "Track given in TAG does not match " "track given in ctest_start()" << std::endl, quiet); } else { - this->SpecificTrack = track; + this->Impl->SpecificTrack = track; } cmCTestOptionalLog(this, OUTPUT, @@ -603,7 +622,7 @@ int cmCTest::Initialize(const char* binary_dir, cmCTestStartCommand* command) quiet); } - this->CurrentTag = tag; + this->Impl->CurrentTag = tag; } return 1; @@ -613,9 +632,9 @@ bool cmCTest::InitializeFromCommand(cmCTestStartCommand* command) { std::string src_dir = this->GetCTestConfiguration("SourceDirectory"); std::string bld_dir = this->GetCTestConfiguration("BuildDirectory"); - this->BuildID = ""; + this->Impl->BuildID = ""; for (Part p = PartStart; p != PartCount; p = Part(p + 1)) { - this->Parts[p].SubmitFiles.clear(); + this->Impl->Parts[p].SubmitFiles.clear(); } cmMakefile* mf = command->GetMakefile(); @@ -669,18 +688,18 @@ bool cmCTest::InitializeFromCommand(cmCTestStartCommand* command) bool cmCTest::UpdateCTestConfiguration() { - if (this->SuppressUpdatingCTestConfiguration) { + if (this->Impl->SuppressUpdatingCTestConfiguration) { return true; } - std::string fileName = this->BinaryDir + "/CTestConfiguration.ini"; + std::string fileName = this->Impl->BinaryDir + "/CTestConfiguration.ini"; if (!cmSystemTools::FileExists(fileName)) { - fileName = this->BinaryDir + "/DartConfiguration.tcl"; + fileName = this->Impl->BinaryDir + "/DartConfiguration.tcl"; } cmCTestLog(this, HANDLER_VERBOSE_OUTPUT, "UpdateCTestConfiguration from :" << fileName << "\n"); if (!cmSystemTools::FileExists(fileName)) { // No need to exit if we are not producing XML - if (this->ProduceXML) { + if (this->Impl->ProduceXML) { cmCTestLog(this, ERROR_MESSAGE, "Cannot find file: " << fileName << std::endl); return false; @@ -720,15 +739,15 @@ bool cmCTest::UpdateCTestConfiguration() } std::string key = line.substr(0, cpos); std::string value = cmCTest::CleanString(line.substr(cpos + 1)); - this->CTestConfiguration[key] = value; + this->Impl->CTestConfiguration[key] = value; } fin.close(); } if (!this->GetCTestConfiguration("BuildDirectory").empty()) { - this->BinaryDir = this->GetCTestConfiguration("BuildDirectory"); - cmSystemTools::ChangeDirectory(this->BinaryDir); + this->Impl->BinaryDir = this->GetCTestConfiguration("BuildDirectory"); + cmSystemTools::ChangeDirectory(this->Impl->BinaryDir); } - this->TimeOut = + this->Impl->TimeOut = std::chrono::seconds(atoi(this->GetCTestConfiguration("TimeOut").c_str())); std::string const& testLoad = this->GetCTestConfiguration("TestLoad"); if (!testLoad.empty()) { @@ -740,8 +759,8 @@ bool cmCTest::UpdateCTestConfiguration() "Invalid value for 'Test Load' : " << testLoad << std::endl); } } - if (this->ProduceXML) { - this->CompressXMLFiles = + if (this->Impl->ProduceXML) { + this->Impl->CompressXMLFiles = cmSystemTools::IsOn(this->GetCTestConfiguration("CompressSubmission")); } return true; @@ -760,21 +779,26 @@ void cmCTest::BlockTestErrorDiagnostics() void cmCTest::SetTestModel(int mode) { - this->InteractiveDebugMode = false; - this->TestModel = mode; + this->Impl->InteractiveDebugMode = false; + this->Impl->TestModel = mode; +} + +int cmCTest::GetTestModel() const +{ + return this->Impl->TestModel; } bool cmCTest::SetTest(const char* ttype, bool report) { if (cmSystemTools::LowerCase(ttype) == "all") { for (Part p = PartStart; p != PartCount; p = Part(p + 1)) { - this->Parts[p].Enable(); + this->Impl->Parts[p].Enable(); } return true; } Part p = this->GetPartFromName(ttype); if (p != PartCount) { - this->Parts[p].Enable(); + this->Impl->Parts[p].Enable(); return true; } if (report) { @@ -792,7 +816,7 @@ void cmCTest::Finalize() bool cmCTest::OpenOutputFile(const std::string& path, const std::string& name, cmGeneratedFileStream& stream, bool compress) { - std::string testingDir = this->BinaryDir + "/Testing"; + std::string testingDir = this->Impl->BinaryDir + "/Testing"; if (!path.empty()) { testingDir += "/" + path; } @@ -819,7 +843,7 @@ bool cmCTest::OpenOutputFile(const std::string& path, const std::string& name, return false; } if (compress) { - if (this->CompressXMLFiles) { + if (this->Impl->CompressXMLFiles) { stream.SetCompression(true); } } @@ -844,40 +868,59 @@ bool cmCTest::AddIfExists(Part part, const char* file) bool cmCTest::CTestFileExists(const std::string& filename) { - std::string testingDir = - this->BinaryDir + "/Testing/" + this->CurrentTag + "/" + filename; + std::string testingDir = this->Impl->BinaryDir + "/Testing/" + + this->Impl->CurrentTag + "/" + filename; return cmSystemTools::FileExists(testingDir); } -cmCTestGenericHandler* cmCTest::GetInitializedHandler(const char* handler) +cmCTestBuildHandler* cmCTest::GetBuildHandler() { - cmCTest::t_TestingHandlers::iterator it = - this->TestingHandlers.find(handler); - if (it == this->TestingHandlers.end()) { - return nullptr; - } - it->second->Initialize(); - return it->second; + return &this->Impl->BuildHandler; } -cmCTestGenericHandler* cmCTest::GetHandler(const char* handler) +cmCTestBuildAndTestHandler* cmCTest::GetBuildAndTestHandler() { - cmCTest::t_TestingHandlers::iterator it = - this->TestingHandlers.find(handler); - if (it == this->TestingHandlers.end()) { - return nullptr; - } - return it->second; + return &this->Impl->BuildAndTestHandler; } -int cmCTest::ExecuteHandler(const char* shandler) +cmCTestCoverageHandler* cmCTest::GetCoverageHandler() { - cmCTestGenericHandler* handler = this->GetHandler(shandler); - if (!handler) { - return -1; - } - handler->Initialize(); - return handler->ProcessHandler(); + return &this->Impl->CoverageHandler; +} + +cmCTestScriptHandler* cmCTest::GetScriptHandler() +{ + return &this->Impl->ScriptHandler; +} + +cmCTestTestHandler* cmCTest::GetTestHandler() +{ + return &this->Impl->TestHandler; +} + +cmCTestUpdateHandler* cmCTest::GetUpdateHandler() +{ + return &this->Impl->UpdateHandler; +} + +cmCTestConfigureHandler* cmCTest::GetConfigureHandler() +{ + return &this->Impl->ConfigureHandler; +} + +cmCTestMemCheckHandler* cmCTest::GetMemCheckHandler() +{ + return &this->Impl->MemCheckHandler; +} + +cmCTestSubmitHandler* cmCTest::GetSubmitHandler() +{ + return &this->Impl->SubmitHandler; +} + +cmCTestUploadHandler* cmCTest::GetUploadHandler() +{ + return &this->Impl->UploadHandler; } int cmCTest::ProcessSteps() @@ -887,11 +930,11 @@ int cmCTest::ProcessSteps() int update_count = 0; for (Part p = PartStart; notest && p != PartCount; p = Part(p + 1)) { - notest = !this->Parts[p]; + notest = !this->Impl->Parts[p]; } - if (this->Parts[PartUpdate] && + if (this->Impl->Parts[PartUpdate] && (this->GetRemainingTimeAllowed() > std::chrono::minutes(2))) { - cmCTestGenericHandler* uphandler = this->GetHandler("update"); + cmCTestUpdateHandler* uphandler = this->GetUpdateHandler(); uphandler->SetPersistentOption( "SourceDirectory", this->GetCTestConfiguration("SourceDirectory").c_str()); @@ -900,45 +943,45 @@ int cmCTest::ProcessSteps() res |= cmCTest::UPDATE_ERRORS; } } - if (this->TestModel == cmCTest::CONTINUOUS && !update_count) { + if (this->Impl->TestModel == cmCTest::CONTINUOUS && !update_count) { return 0; } - if (this->Parts[PartConfigure] && + if (this->Impl->Parts[PartConfigure] && (this->GetRemainingTimeAllowed() > std::chrono::minutes(2))) { - if (this->GetHandler("configure")->ProcessHandler() < 0) { + if (this->GetConfigureHandler()->ProcessHandler() < 0) { res |= cmCTest::CONFIGURE_ERRORS; } } - if (this->Parts[PartBuild] && + if (this->Impl->Parts[PartBuild] && (this->GetRemainingTimeAllowed() > std::chrono::minutes(2))) { this->UpdateCTestConfiguration(); - if (this->GetHandler("build")->ProcessHandler() < 0) { + if (this->GetBuildHandler()->ProcessHandler() < 0) { res |= cmCTest::BUILD_ERRORS; } } - if ((this->Parts[PartTest] || notest) && + if ((this->Impl->Parts[PartTest] || notest) && (this->GetRemainingTimeAllowed() > std::chrono::minutes(2))) { this->UpdateCTestConfiguration(); - if (this->GetHandler("test")->ProcessHandler() < 0) { + if (this->GetTestHandler()->ProcessHandler() < 0) { res |= cmCTest::TEST_ERRORS; } } - if (this->Parts[PartCoverage] && + if (this->Impl->Parts[PartCoverage] && (this->GetRemainingTimeAllowed() > std::chrono::minutes(2))) { this->UpdateCTestConfiguration(); - if (this->GetHandler("coverage")->ProcessHandler() < 0) { + if (this->GetCoverageHandler()->ProcessHandler() < 0) { res |= cmCTest::COVERAGE_ERRORS; } } - if (this->Parts[PartMemCheck] && + if (this->Impl->Parts[PartMemCheck] && (this->GetRemainingTimeAllowed() > std::chrono::minutes(2))) { this->UpdateCTestConfiguration(); - if (this->GetHandler("memcheck")->ProcessHandler() < 0) { + if (this->GetMemCheckHandler()->ProcessHandler() < 0) { res |= cmCTest::MEMORY_ERRORS; } } if (!notest) { - std::string notes_dir = this->BinaryDir + "/Testing/Notes"; + std::string notes_dir = this->Impl->BinaryDir + "/Testing/Notes"; if (cmSystemTools::FileIsDirectory(notes_dir)) { cmsys::Directory d; d.Load(notes_dir); @@ -948,24 +991,24 @@ int cmCTest::ProcessSteps() std::string fullname = notes_dir + "/" + file; if (cmSystemTools::FileExists(fullname) && !cmSystemTools::FileIsDirectory(fullname)) { - if (!this->NotesFiles.empty()) { - this->NotesFiles += ";"; + if (!this->Impl->NotesFiles.empty()) { + this->Impl->NotesFiles += ";"; } - this->NotesFiles += fullname; - this->Parts[PartNotes].Enable(); + this->Impl->NotesFiles += fullname; + this->Impl->Parts[PartNotes].Enable(); } } } } - if (this->Parts[PartNotes]) { + if (this->Impl->Parts[PartNotes]) { this->UpdateCTestConfiguration(); - if (!this->NotesFiles.empty()) { - this->GenerateNotesFile(this->NotesFiles.c_str()); + if (!this->Impl->NotesFiles.empty()) { + this->GenerateNotesFile(this->Impl->NotesFiles.c_str()); } } - if (this->Parts[PartSubmit]) { + if (this->Impl->Parts[PartSubmit]) { this->UpdateCTestConfiguration(); - if (this->GetHandler("submit")->ProcessHandler() < 0) { + if (this->GetSubmitHandler()->ProcessHandler() < 0) { res |= cmCTest::SUBMIT_ERRORS; } } @@ -977,10 +1020,10 @@ int cmCTest::ProcessSteps() std::string cmCTest::GetTestModelString() { - if (!this->SpecificTrack.empty()) { - return this->SpecificTrack; + if (!this->Impl->SpecificTrack.empty()) { + return this->Impl->SpecificTrack; } - switch (this->TestModel) { + switch (this->Impl->TestModel) { case cmCTest::NIGHTLY: return "Nightly"; case cmCTest::CONTINUOUS: @@ -1139,8 +1182,9 @@ int cmCTest::RunTest(std::vector<const char*> argv, std::string* output, if (timeout != cmCTest::MaxDuration()) { timeout -= std::chrono::minutes(2); } - if (this->TimeOut > cmDuration::zero() && this->TimeOut < timeout) { - timeout = this->TimeOut; + if (this->Impl->TimeOut > cmDuration::zero() && + this->Impl->TimeOut < timeout) { + timeout = this->Impl->TimeOut; } if (testTimeOut > cmDuration::zero() && testTimeOut < this->GetRemainingTimeAllowed()) { @@ -1158,10 +1202,10 @@ int cmCTest::RunTest(std::vector<const char*> argv, std::string* output, : std::to_string(cmDurationTo<unsigned int>(timeout))) << "\n"); if (cmSystemTools::SameFile(argv[0], cmSystemTools::GetCTestCommand()) && - !this->ForceNewCTestProcess) { + !this->Impl->ForceNewCTestProcess) { cmCTest inst; - inst.ConfigType = this->ConfigType; - inst.TimeOut = timeout; + inst.Impl->ConfigType = this->Impl->ConfigType; + inst.Impl->TimeOut = timeout; // Capture output of the child ctest. std::ostringstream oss; @@ -1267,11 +1311,11 @@ int cmCTest::RunTest(std::vector<const char*> argv, std::string* output, if (result == cmsysProcess_State_Exited) { *retVal = cmsysProcess_GetExitValue(cp); - if (*retVal != 0 && this->OutputTestOutputOnTestFailure) { + if (*retVal != 0 && this->Impl->OutputTestOutputOnTestFailure) { OutputTestErrors(tempOutput); } } else if (result == cmsysProcess_State_Exception) { - if (this->OutputTestOutputOnTestFailure) { + if (this->Impl->OutputTestOutputOnTestFailure) { OutputTestErrors(tempOutput); } *retVal = cmsysProcess_GetExitException(cp); @@ -1330,7 +1374,7 @@ std::string cmCTest::SafeBuildIdField(const std::string& value) void cmCTest::StartXML(cmXMLWriter& xml, bool append) { - if (this->CurrentTag.empty()) { + if (this->Impl->CurrentTag.empty()) { cmCTestLog(this, ERROR_MESSAGE, "Current Tag empty, this may mean" " NightlStartTime was not set correctly." @@ -1346,7 +1390,7 @@ void cmCTest::StartXML(cmXMLWriter& xml, bool append) std::string buildname = cmCTest::SafeBuildIdField(this->GetCTestConfiguration("BuildName")); - std::string stamp = cmCTest::SafeBuildIdField(this->CurrentTag + "-" + + std::string stamp = cmCTest::SafeBuildIdField(this->Impl->CurrentTag + "-" + this->GetTestModelString()); std::string site = cmCTest::SafeBuildIdField(this->GetCTestConfiguration("Site")); @@ -1394,8 +1438,7 @@ void cmCTest::StartXML(cmXMLWriter& xml, bool append) void cmCTest::AddSiteProperties(cmXMLWriter& xml) { - cmCTestScriptHandler* ch = - static_cast<cmCTestScriptHandler*>(this->GetHandler("script")); + cmCTestScriptHandler* ch = this->GetScriptHandler(); cmake* cm = ch->GetCMake(); // if no CMake then this is the old style script and props like // this will not work anyway. @@ -1465,7 +1508,7 @@ void cmCTest::EndXML(cmXMLWriter& xml) } int cmCTest::GenerateCTestNotesOutput(cmXMLWriter& xml, - const cmCTest::VectorOfStrings& files) + std::vector<std::string> const& files) { std::string buildname = cmCTest::SafeBuildIdField(this->GetCTestConfiguration("BuildName")); @@ -1477,7 +1520,7 @@ int cmCTest::GenerateCTestNotesOutput(cmXMLWriter& xml, xml.StartElement("Site"); xml.Attribute("BuildName", buildname); xml.Attribute("BuildStamp", - this->CurrentTag + "-" + this->GetTestModelString()); + this->Impl->CurrentTag + "-" + this->GetTestModelString()); xml.Attribute("Name", this->GetCTestConfiguration("Site")); xml.Attribute("Generator", std::string("ctest") + cmVersion::GetCMakeVersion()); @@ -1515,10 +1558,10 @@ int cmCTest::GenerateCTestNotesOutput(cmXMLWriter& xml, return 1; } -int cmCTest::GenerateNotesFile(const VectorOfStrings& files) +int cmCTest::GenerateNotesFile(std::vector<std::string> const& files) { cmGeneratedFileStream ofs; - if (!this->OpenOutputFile(this->CurrentTag, "Notes.xml", ofs)) { + if (!this->OpenOutputFile(this->Impl->CurrentTag, "Notes.xml", ofs)) { cmCTestLog(this, ERROR_MESSAGE, "Cannot open notes file" << std::endl); return 1; } @@ -1533,11 +1576,10 @@ int cmCTest::GenerateNotesFile(const char* cfiles) return 1; } - VectorOfStrings files; - cmCTestLog(this, OUTPUT, "Create notes file" << std::endl); - files = cmSystemTools::SplitString(cfiles, ';'); + std::vector<std::string> const files = + cmSystemTools::SplitString(cfiles, ';'); if (files.empty()) { return 1; } @@ -1548,14 +1590,14 @@ int cmCTest::GenerateNotesFile(const char* cfiles) int cmCTest::GenerateDoneFile() { cmGeneratedFileStream ofs; - if (!this->OpenOutputFile(this->CurrentTag, "Done.xml", ofs)) { + if (!this->OpenOutputFile(this->Impl->CurrentTag, "Done.xml", ofs)) { cmCTestLog(this, ERROR_MESSAGE, "Cannot open done file" << std::endl); return 1; } cmXMLWriter xml(ofs); xml.StartDocument(); xml.StartElement("Done"); - xml.Element("buildId", this->BuildID); + xml.Element("buildId", this->Impl->BuildID); xml.Element("time", std::chrono::system_clock::now()); xml.EndElement(); // Done xml.EndDocument(); @@ -1604,7 +1646,7 @@ std::string cmCTest::Base64EncodeFile(std::string const& file) return std::string(&encoded_buffer[0], rlen); } -bool cmCTest::SubmitExtraFiles(const VectorOfStrings& files) +bool cmCTest::SubmitExtraFiles(std::vector<std::string> const& files) { for (std::string const& file : files) { if (!cmSystemTools::FileExists(file)) { @@ -1624,11 +1666,10 @@ bool cmCTest::SubmitExtraFiles(const char* cfiles) return true; } - VectorOfStrings files; - cmCTestLog(this, OUTPUT, "Submit extra files" << std::endl); - files = cmSystemTools::SplitString(cfiles, ';'); + std::vector<std::string> const files = + cmSystemTools::SplitString(cfiles, ';'); if (files.empty()) { return true; } @@ -1796,17 +1837,17 @@ bool cmCTest::HandleCommandLineArguments(size_t& i, { std::string arg = args[i]; if (this->CheckArgument(arg, "-F")) { - this->Failover = true; + this->Impl->Failover = true; } if (this->CheckArgument(arg, "-j", "--parallel") && i < args.size() - 1) { i++; int plevel = atoi(args[i].c_str()); this->SetParallelLevel(plevel); - this->ParallelLevelSetInCli = true; + this->Impl->ParallelLevelSetInCli = true; } else if (arg.find("-j") == 0) { int plevel = atoi(arg.substr(2).c_str()); this->SetParallelLevel(plevel); - this->ParallelLevelSetInCli = true; + this->Impl->ParallelLevelSetInCli = true; } if (this->CheckArgument(arg, "--repeat-until-fail")) { if (i >= args.size() - 1) { @@ -1820,9 +1861,9 @@ bool cmCTest::HandleCommandLineArguments(size_t& i, "'--repeat-until-fail' given non-integer value '" + args[i] + "'"; return false; } - this->RepeatTests = static_cast<int>(repeat); + this->Impl->RepeatTests = static_cast<int>(repeat); if (repeat > 1) { - this->RepeatUntilFail = true; + this->Impl->RepeatUntilFail = true; } } @@ -1838,21 +1879,21 @@ bool cmCTest::HandleCommandLineArguments(size_t& i, } if (this->CheckArgument(arg, "--no-compress-output")) { - this->CompressTestOutput = false; + this->Impl->CompressTestOutput = false; } if (this->CheckArgument(arg, "--print-labels")) { - this->PrintLabels = true; + this->Impl->PrintLabels = true; } if (this->CheckArgument(arg, "--http1.0")) { - this->UseHTTP10 = true; + this->Impl->UseHTTP10 = true; } if (this->CheckArgument(arg, "--timeout") && i < args.size() - 1) { i++; auto timeout = cmDuration(atof(args[i].c_str())); - this->GlobalTimeout = timeout; + this->Impl->GlobalTimeout = timeout; } if (this->CheckArgument(arg, "--stop-time") && i < args.size() - 1) { @@ -1867,47 +1908,44 @@ bool cmCTest::HandleCommandLineArguments(size_t& i, } if (this->CheckArgument(arg, "--debug")) { - this->Debug = true; - this->ShowLineNumbers = true; + this->Impl->Debug = true; + this->Impl->ShowLineNumbers = true; } if (this->CheckArgument(arg, "--track") && i < args.size() - 1) { i++; - this->SpecificTrack = args[i]; + this->Impl->SpecificTrack = args[i]; } if (this->CheckArgument(arg, "--show-line-numbers")) { - this->ShowLineNumbers = true; + this->Impl->ShowLineNumbers = true; } if (this->CheckArgument(arg, "--no-label-summary")) { - this->LabelSummary = false; + this->Impl->LabelSummary = false; } if (this->CheckArgument(arg, "--no-subproject-summary")) { - this->SubprojectSummary = false; + this->Impl->SubprojectSummary = false; } if (this->CheckArgument(arg, "-Q", "--quiet")) { - this->Quiet = true; + this->Impl->Quiet = true; } if (this->CheckArgument(arg, "--progress")) { - this->TestProgressOutput = true; + this->Impl->TestProgressOutput = true; } if (this->CheckArgument(arg, "-V", "--verbose")) { - this->Verbose = true; + this->Impl->Verbose = true; } if (this->CheckArgument(arg, "-VV", "--extra-verbose")) { - this->ExtraVerbose = true; - this->Verbose = true; + this->Impl->ExtraVerbose = true; + this->Impl->Verbose = true; } if (this->CheckArgument(arg, "--output-on-failure")) { - this->OutputTestOutputOnTestFailure = true; + this->Impl->OutputTestOutputOnTestFailure = true; } if (this->CheckArgument(arg, "--test-output-size-passed") && i < args.size() - 1) { i++; long outputSize; if (cmSystemTools::StringToLong(args[i].c_str(), &outputSize)) { - if (cmCTestTestHandler* pCTestTestHandler = - static_cast<cmCTestTestHandler*>(this->TestingHandlers["test"])) { - pCTestTestHandler->SetTestOutputSizePassed(int(outputSize)); - } + this->Impl->TestHandler.SetTestOutputSizePassed(int(outputSize)); } else { cmCTestLog(this, WARNING, "Invalid value for '--test-output-size-passed': " << args[i] @@ -1919,10 +1957,7 @@ bool cmCTest::HandleCommandLineArguments(size_t& i, i++; long outputSize; if (cmSystemTools::StringToLong(args[i].c_str(), &outputSize)) { - if (cmCTestTestHandler* pCTestTestHandler = - static_cast<cmCTestTestHandler*>(this->TestingHandlers["test"])) { - pCTestTestHandler->SetTestOutputSizeFailed(int(outputSize)); - } + this->Impl->TestHandler.SetTestOutputSizeFailed(int(outputSize)); } else { cmCTestLog(this, WARNING, "Invalid value for '--test-output-size-failed': " << args[i] @@ -1930,10 +1965,10 @@ bool cmCTest::HandleCommandLineArguments(size_t& i, } } if (this->CheckArgument(arg, "-N", "--show-only")) { - this->ShowOnly = true; + this->Impl->ShowOnly = true; } if (cmSystemTools::StringStartsWith(arg.c_str(), "--show-only=")) { - this->ShowOnly = true; + this->Impl->ShowOnly = true; // Check if a specific format is requested. Defaults to human readable // text. @@ -1941,9 +1976,9 @@ bool cmCTest::HandleCommandLineArguments(size_t& i, std::string format = arg.substr(argWithFormat.length()); if (format == "json-v1") { // Force quiet mode so the only output is the json object model. - this->Quiet = true; - this->OutputAsJson = true; - this->OutputAsJsonVersion = 1; + this->Impl->Quiet = true; + this->Impl->OutputAsJson = true; + this->Impl->OutputAsJsonVersion = 1; } else if (format != "human") { errormsg = "'--show-only=' given unknown value '" + format + "'"; return false; @@ -1956,25 +1991,25 @@ bool cmCTest::HandleCommandLineArguments(size_t& i, } if (this->CheckArgument(arg, "--tomorrow-tag")) { - this->TomorrowTag = true; + this->Impl->TomorrowTag = true; } if (this->CheckArgument(arg, "--force-new-ctest-process")) { - this->ForceNewCTestProcess = true; + this->Impl->ForceNewCTestProcess = true; } if (this->CheckArgument(arg, "-W", "--max-width") && i < args.size() - 1) { i++; - this->MaxTestNameWidth = atoi(args[i].c_str()); + this->Impl->MaxTestNameWidth = atoi(args[i].c_str()); } if (this->CheckArgument(arg, "--interactive-debug-mode") && i < args.size() - 1) { i++; - this->InteractiveDebugMode = cmSystemTools::IsOn(args[i]); + this->Impl->InteractiveDebugMode = cmSystemTools::IsOn(args[i]); } if (this->CheckArgument(arg, "--submit-index") && i < args.size() - 1) { i++; - this->SubmitIndex = atoi(args[i].c_str()); - if (this->SubmitIndex < 0) { - this->SubmitIndex = 0; + this->Impl->SubmitIndex = atoi(args[i].c_str()); + if (this->Impl->SubmitIndex < 0) { + this->Impl->SubmitIndex = 0; } } @@ -1983,7 +2018,7 @@ bool cmCTest::HandleCommandLineArguments(size_t& i, this->AddCTestConfigurationOverwrite(args[i]); } if (this->CheckArgument(arg, "-A", "--add-notes") && i < args.size() - 1) { - this->ProduceXML = true; + this->Impl->ProduceXML = true; this->SetTest("Notes"); i++; this->SetNotesFiles(args[i].c_str()); @@ -1993,78 +2028,75 @@ bool cmCTest::HandleCommandLineArguments(size_t& i, if (this->CheckArgument(arg, "-I", "--tests-information") && i < args.size() - 1) { i++; - this->GetHandler("test")->SetPersistentOption("TestsToRunInformation", - args[i].c_str()); - this->GetHandler("memcheck") - ->SetPersistentOption("TestsToRunInformation", args[i].c_str()); + this->GetTestHandler()->SetPersistentOption("TestsToRunInformation", + args[i].c_str()); + this->GetMemCheckHandler()->SetPersistentOption("TestsToRunInformation", + args[i].c_str()); } if (this->CheckArgument(arg, "-U", "--union")) { - this->GetHandler("test")->SetPersistentOption("UseUnion", "true"); - this->GetHandler("memcheck")->SetPersistentOption("UseUnion", "true"); + this->GetTestHandler()->SetPersistentOption("UseUnion", "true"); + this->GetMemCheckHandler()->SetPersistentOption("UseUnion", "true"); } if (this->CheckArgument(arg, "-R", "--tests-regex") && i < args.size() - 1) { i++; - this->GetHandler("test")->SetPersistentOption("IncludeRegularExpression", - args[i].c_str()); - this->GetHandler("memcheck") - ->SetPersistentOption("IncludeRegularExpression", args[i].c_str()); + this->GetTestHandler()->SetPersistentOption("IncludeRegularExpression", + args[i].c_str()); + this->GetMemCheckHandler()->SetPersistentOption("IncludeRegularExpression", + args[i].c_str()); } if (this->CheckArgument(arg, "-L", "--label-regex") && i < args.size() - 1) { i++; - this->GetHandler("test")->SetPersistentOption("LabelRegularExpression", - args[i].c_str()); - this->GetHandler("memcheck") - ->SetPersistentOption("LabelRegularExpression", args[i].c_str()); + this->GetTestHandler()->SetPersistentOption("LabelRegularExpression", + args[i].c_str()); + this->GetMemCheckHandler()->SetPersistentOption("LabelRegularExpression", + args[i].c_str()); } if (this->CheckArgument(arg, "-LE", "--label-exclude") && i < args.size() - 1) { i++; - this->GetHandler("test")->SetPersistentOption( + this->GetTestHandler()->SetPersistentOption( + "ExcludeLabelRegularExpression", args[i].c_str()); + this->GetMemCheckHandler()->SetPersistentOption( "ExcludeLabelRegularExpression", args[i].c_str()); - this->GetHandler("memcheck") - ->SetPersistentOption("ExcludeLabelRegularExpression", args[i].c_str()); } if (this->CheckArgument(arg, "-E", "--exclude-regex") && i < args.size() - 1) { i++; - this->GetHandler("test")->SetPersistentOption("ExcludeRegularExpression", - args[i].c_str()); - this->GetHandler("memcheck") - ->SetPersistentOption("ExcludeRegularExpression", args[i].c_str()); + this->GetTestHandler()->SetPersistentOption("ExcludeRegularExpression", + args[i].c_str()); + this->GetMemCheckHandler()->SetPersistentOption("ExcludeRegularExpression", + args[i].c_str()); } if (this->CheckArgument(arg, "-FA", "--fixture-exclude-any") && i < args.size() - 1) { i++; - this->GetHandler("test")->SetPersistentOption( + this->GetTestHandler()->SetPersistentOption( + "ExcludeFixtureRegularExpression", args[i].c_str()); + this->GetMemCheckHandler()->SetPersistentOption( "ExcludeFixtureRegularExpression", args[i].c_str()); - this->GetHandler("memcheck") - ->SetPersistentOption("ExcludeFixtureRegularExpression", - args[i].c_str()); } if (this->CheckArgument(arg, "-FS", "--fixture-exclude-setup") && i < args.size() - 1) { i++; - this->GetHandler("test")->SetPersistentOption( + this->GetTestHandler()->SetPersistentOption( + "ExcludeFixtureSetupRegularExpression", args[i].c_str()); + this->GetMemCheckHandler()->SetPersistentOption( "ExcludeFixtureSetupRegularExpression", args[i].c_str()); - this->GetHandler("memcheck") - ->SetPersistentOption("ExcludeFixtureSetupRegularExpression", - args[i].c_str()); } if (this->CheckArgument(arg, "-FC", "--fixture-exclude-cleanup") && i < args.size() - 1) { i++; - this->GetHandler("test")->SetPersistentOption( + this->GetTestHandler()->SetPersistentOption( + "ExcludeFixtureCleanupRegularExpression", args[i].c_str()); + this->GetMemCheckHandler()->SetPersistentOption( "ExcludeFixtureCleanupRegularExpression", args[i].c_str()); - this->GetHandler("memcheck") - ->SetPersistentOption("ExcludeFixtureCleanupRegularExpression", - args[i].c_str()); } if (this->CheckArgument(arg, "--rerun-failed")) { - this->GetHandler("test")->SetPersistentOption("RerunFailed", "true"); - this->GetHandler("memcheck")->SetPersistentOption("RerunFailed", "true"); + this->GetTestHandler()->SetPersistentOption("RerunFailed", "true"); + this->GetMemCheckHandler()->SetPersistentOption("RerunFailed", "true"); } return true; } @@ -2111,10 +2143,9 @@ void cmCTest::HandleScriptArguments(size_t& i, std::vector<std::string>& args, std::string arg = args[i]; if (this->CheckArgument(arg, "-SP", "--script-new-process") && i < args.size() - 1) { - this->RunConfigurationScript = true; + this->Impl->RunConfigurationScript = true; i++; - cmCTestScriptHandler* ch = - static_cast<cmCTestScriptHandler*>(this->GetHandler("script")); + cmCTestScriptHandler* ch = this->GetScriptHandler(); // -SR is an internal argument, -SP should be ignored when it is passed if (!SRArgumentSpecified) { ch->AddConfigurationScript(args[i].c_str(), false); @@ -2123,18 +2154,16 @@ void cmCTest::HandleScriptArguments(size_t& i, std::vector<std::string>& args, if (this->CheckArgument(arg, "-SR", "--script-run") && i < args.size() - 1) { SRArgumentSpecified = true; - this->RunConfigurationScript = true; + this->Impl->RunConfigurationScript = true; i++; - cmCTestScriptHandler* ch = - static_cast<cmCTestScriptHandler*>(this->GetHandler("script")); + cmCTestScriptHandler* ch = this->GetScriptHandler(); ch->AddConfigurationScript(args[i].c_str(), true); } if (this->CheckArgument(arg, "-S", "--script") && i < args.size() - 1) { - this->RunConfigurationScript = true; + this->Impl->RunConfigurationScript = true; i++; - cmCTestScriptHandler* ch = - static_cast<cmCTestScriptHandler*>(this->GetHandler("script")); + cmCTestScriptHandler* ch = this->GetScriptHandler(); // -SR is an internal argument, -S should be ignored when it is passed if (!SRArgumentSpecified) { ch->AddConfigurationScript(args[i].c_str(), true); @@ -2149,7 +2178,7 @@ bool cmCTest::AddVariableDefinition(const std::string& arg) cmStateEnums::CacheEntryType type = cmStateEnums::UNINITIALIZED; if (cmake::ParseCacheEntry(arg, name, value, type)) { - this->Definitions[name] = value; + this->Impl->Definitions[name] = value; return true; } @@ -2165,8 +2194,8 @@ int cmCTest::Run(std::vector<std::string>& args, std::string* output) bool SRArgumentSpecified = false; // copy the command line - this->InitialCommandLineArguments.insert( - this->InitialCommandLineArguments.end(), args.begin(), args.end()); + this->Impl->InitialCommandLineArguments.insert( + this->Impl->InitialCommandLineArguments.end(), args.begin(), args.end()); // process the command line arguments for (size_t i = 1; i < args.size(); ++i) { @@ -2183,7 +2212,7 @@ int cmCTest::Run(std::vector<std::string>& args, std::string* output) // --dashboard: handle a request for a dashboard std::string arg = args[i]; if (this->CheckArgument(arg, "-D", "--dashboard") && i < args.size() - 1) { - this->ProduceXML = true; + this->Impl->ProduceXML = true; i++; std::string targ = args[i]; // AddTestsForDashboard parses the dashboard type and converts it @@ -2219,7 +2248,7 @@ int cmCTest::Run(std::vector<std::string>& args, std::string* output) // --extra-submit if (this->CheckArgument(arg, "--extra-submit") && i < args.size() - 1) { - this->ProduceXML = true; + this->Impl->ProduceXML = true; this->SetTest("Submit"); i++; if (!this->SubmitExtraFiles(args[i].c_str())) { @@ -2234,14 +2263,14 @@ int cmCTest::Run(std::vector<std::string>& args, std::string* output) // --schedule-random if (this->CheckArgument(arg, "--schedule-random")) { - this->ScheduleType = "Random"; + this->Impl->ScheduleType = "Random"; } // pass the argument to all the handlers as well, but i may no longer be // set to what it was originally so I'm not sure this is working as // intended - for (auto& handler : this->TestingHandlers) { - if (!handler.second->ProcessCommandLineArguments(arg, i, args)) { + for (auto& handler : this->Impl->GetTestingHandlers()) { + if (!handler->ProcessCommandLineArguments(arg, i, args)) { cmCTestLog(this, ERROR_MESSAGE, "Problem parsing command line arguments within a handler"); return 0; @@ -2250,7 +2279,7 @@ int cmCTest::Run(std::vector<std::string>& args, std::string* output) } // the close of the for argument loop // handle CTEST_PARALLEL_LEVEL environment variable - if (!this->ParallelLevelSetInCli) { + if (!this->Impl->ParallelLevelSetInCli) { std::string parallel; if (cmSystemTools::GetEnv("CTEST_PARALLEL_LEVEL", parallel)) { int plevel = atoi(parallel.c_str()); @@ -2260,10 +2289,10 @@ int cmCTest::Run(std::vector<std::string>& args, std::string* output) // TestProgressOutput only supported if console supports it and not logging // to a file - this->TestProgressOutput = this->TestProgressOutput && - !this->OutputLogFile && this->ProgressOutputSupportedByConsole(); + this->Impl->TestProgressOutput = this->Impl->TestProgressOutput && + !this->Impl->OutputLogFile && this->ProgressOutputSupportedByConsole(); #ifdef _WIN32 - if (this->TestProgressOutput) { + if (this->Impl->TestProgressOutput) { // Disable output line buffering so we can print content without // a newline. std::setvbuf(stdout, nullptr, _IONBF, 0); @@ -2290,7 +2319,7 @@ bool cmCTest::HandleTestActionArgument(const char* ctestExec, size_t& i, std::string arg = args[i]; if (this->CheckArgument(arg, "-T", "--test-action") && (i < args.size() - 1)) { - this->ProduceXML = true; + this->Impl->ProduceXML = true; i++; if (!this->SetTest(args[i].c_str(), false)) { success = false; @@ -2350,16 +2379,16 @@ int cmCTest::ExecuteTests() { int res; // call process directory - if (this->RunConfigurationScript) { - if (this->ExtraVerbose) { + if (this->Impl->RunConfigurationScript) { + if (this->Impl->ExtraVerbose) { cmCTestLog(this, OUTPUT, "* Extra verbosity turned on" << std::endl); } - for (auto& handler : this->TestingHandlers) { - handler.second->SetVerbose(this->ExtraVerbose); - handler.second->SetSubmitIndex(this->SubmitIndex); + for (auto& handler : this->Impl->GetTestingHandlers()) { + handler->SetVerbose(this->Impl->ExtraVerbose); + handler->SetSubmitIndex(this->Impl->SubmitIndex); } - this->GetHandler("script")->SetVerbose(this->Verbose); - res = this->GetHandler("script")->ProcessHandler(); + this->GetScriptHandler()->SetVerbose(this->Impl->Verbose); + res = this->GetScriptHandler()->ProcessHandler(); if (res != 0) { cmCTestLog(this, DEBUG, "running script failing returning: " << res << std::endl); @@ -2368,11 +2397,11 @@ int cmCTest::ExecuteTests() } else { // What is this? -V seems to be the same as -VV, // and Verbose is always on in this case - this->ExtraVerbose = this->Verbose; - this->Verbose = true; - for (auto& handler : this->TestingHandlers) { - handler.second->SetVerbose(this->Verbose); - handler.second->SetSubmitIndex(this->SubmitIndex); + this->Impl->ExtraVerbose = this->Impl->Verbose; + this->Impl->Verbose = true; + for (auto& handler : this->Impl->GetTestingHandlers()) { + handler->SetVerbose(this->Impl->Verbose); + handler->SetSubmitIndex(this->Impl->SubmitIndex); } std::string cwd = cmSystemTools::GetCurrentWorkingDirectory(); if (!this->Initialize(cwd.c_str(), nullptr)) { @@ -2393,9 +2422,8 @@ int cmCTest::ExecuteTests() int cmCTest::RunCMakeAndTest(std::string* output) { - this->Verbose = true; - cmCTestBuildAndTestHandler* handler = - static_cast<cmCTestBuildAndTestHandler*>(this->GetHandler("buildtest")); + this->Impl->Verbose = true; + cmCTestBuildAndTestHandler* handler = this->GetBuildAndTestHandler(); int retv = handler->ProcessHandler(); *output = handler->GetOutput(); #ifdef CMAKE_BUILD_WITH_CMAKE @@ -2413,7 +2441,12 @@ void cmCTest::SetNotesFiles(const char* notes) if (!notes) { return; } - this->NotesFiles = notes; + this->Impl->NotesFiles = notes; +} + +std::chrono::system_clock::time_point cmCTest::GetStopTime() const +{ + return this->Impl->StopTime; } void cmCTest::SetStopTime(std::string const& time_str) @@ -2443,21 +2476,29 @@ void cmCTest::SetStopTime(std::string const& time_str) time_t stop_time = curl_getdate(buf, ¤t_time); if (stop_time == -1) { - this->StopTime = std::chrono::system_clock::time_point(); + this->Impl->StopTime = std::chrono::system_clock::time_point(); return; } - this->StopTime = std::chrono::system_clock::from_time_t(stop_time); + this->Impl->StopTime = std::chrono::system_clock::from_time_t(stop_time); if (stop_time < current_time) { - this->StopTime += std::chrono::hours(24); + this->Impl->StopTime += std::chrono::hours(24); } } +std::string cmCTest::GetScheduleType() const +{ + return this->Impl->ScheduleType; +} + +void cmCTest::SetScheduleType(std::string const& type) +{ + this->Impl->ScheduleType = type; +} + int cmCTest::ReadCustomConfigurationFileTree(const char* dir, cmMakefile* mf) { bool found = false; - VectorOfStrings dirs; - VectorOfStrings ndirs; cmCTestLog(this, DEBUG, "* Read custom CTest configuration directory: " << dir << std::endl); @@ -2505,7 +2546,7 @@ int cmCTest::ReadCustomConfigurationFileTree(const char* dir, cmMakefile* mf) } if (found) { - for (auto& handler : this->TestingHandlers) { + for (auto& handler : this->Impl->GetNamedTestingHandlers()) { cmCTestLog(this, DEBUG, "* Read custom CTest configuration vectors for handler: " << handler.first << " (" << handler.second << ")" @@ -2596,16 +2637,16 @@ std::string cmCTest::GetShortPathToFile(const char* cfname) std::string cmCTest::GetCTestConfiguration(const std::string& name) { - if (this->CTestConfigurationOverwrites.find(name) != - this->CTestConfigurationOverwrites.end()) { - return this->CTestConfigurationOverwrites[name]; + if (this->Impl->CTestConfigurationOverwrites.find(name) != + this->Impl->CTestConfigurationOverwrites.end()) { + return this->Impl->CTestConfigurationOverwrites[name]; } - return this->CTestConfiguration[name]; + return this->Impl->CTestConfiguration[name]; } void cmCTest::EmptyCTestConfiguration() { - this->CTestConfiguration.clear(); + this->Impl->CTestConfiguration.clear(); } void cmCTest::SetCTestConfiguration(const char* name, const char* value, @@ -2620,10 +2661,10 @@ void cmCTest::SetCTestConfiguration(const char* name, const char* value, return; } if (!value) { - this->CTestConfiguration.erase(name); + this->Impl->CTestConfiguration.erase(name); return; } - this->CTestConfiguration[name] = value; + this->Impl->CTestConfiguration[name] = value; } std::string cmCTest::GetSubmitURL() @@ -2654,69 +2695,190 @@ std::string cmCTest::GetSubmitURL() std::string cmCTest::GetCurrentTag() { - return this->CurrentTag; + return this->Impl->CurrentTag; } std::string cmCTest::GetBinaryDir() { - return this->BinaryDir; + return this->Impl->BinaryDir; } std::string const& cmCTest::GetConfigType() { - return this->ConfigType; + return this->Impl->ConfigType; +} + +cmDuration cmCTest::GetTimeOut() const +{ + return this->Impl->TimeOut; +} + +void cmCTest::SetTimeOut(cmDuration t) +{ + this->Impl->TimeOut = t; +} + +cmDuration cmCTest::GetGlobalTimeout() const +{ + return this->Impl->GlobalTimeout; } bool cmCTest::GetShowOnly() { - return this->ShowOnly; + return this->Impl->ShowOnly; } bool cmCTest::GetOutputAsJson() { - return this->OutputAsJson; + return this->Impl->OutputAsJson; } int cmCTest::GetOutputAsJsonVersion() { - return this->OutputAsJsonVersion; + return this->Impl->OutputAsJsonVersion; +} + +bool cmCTest::ShouldUseHTTP10() const +{ + return this->Impl->UseHTTP10; +} + +bool cmCTest::ShouldPrintLabels() const +{ + return this->Impl->PrintLabels; } int cmCTest::GetMaxTestNameWidth() const { - return this->MaxTestNameWidth; + return this->Impl->MaxTestNameWidth; +} + +void cmCTest::SetMaxTestNameWidth(int w) +{ + this->Impl->MaxTestNameWidth = w; } void cmCTest::SetProduceXML(bool v) { - this->ProduceXML = v; + this->Impl->ProduceXML = v; } bool cmCTest::GetProduceXML() { - return this->ProduceXML; + return this->Impl->ProduceXML; +} + +std::vector<std::string>& cmCTest::GetInitialCommandLineArguments() +{ + return this->Impl->InitialCommandLineArguments; } const char* cmCTest::GetSpecificTrack() { - if (this->SpecificTrack.empty()) { + if (this->Impl->SpecificTrack.empty()) { return nullptr; } - return this->SpecificTrack.c_str(); + return this->Impl->SpecificTrack.c_str(); } void cmCTest::SetSpecificTrack(const char* track) { if (!track) { - this->SpecificTrack.clear(); + this->Impl->SpecificTrack.clear(); return; } - this->SpecificTrack = track; + this->Impl->SpecificTrack = track; +} + +void cmCTest::SetFailover(bool failover) +{ + this->Impl->Failover = failover; +} + +bool cmCTest::GetFailover() const +{ + return this->Impl->Failover; +} + +bool cmCTest::GetTestProgressOutput() const +{ + return this->Impl->TestProgressOutput; +} + +bool cmCTest::GetVerbose() const +{ + return this->Impl->Verbose; +} + +bool cmCTest::GetExtraVerbose() const +{ + return this->Impl->ExtraVerbose; +} + +void cmCTest::SetStreams(std::ostream* out, std::ostream* err) +{ + this->Impl->StreamOut = out; + this->Impl->StreamErr = err; +} + +bool cmCTest::GetLabelSummary() const +{ + return this->Impl->LabelSummary; +} + +bool cmCTest::GetSubprojectSummary() const +{ + return this->Impl->SubprojectSummary; +} + +bool cmCTest::GetOutputTestOutputOnTestFailure() const +{ + return this->Impl->OutputTestOutputOnTestFailure; +} + +const std::map<std::string, std::string>& cmCTest::GetDefinitions() const +{ + return this->Impl->Definitions; +} + +int cmCTest::GetTestRepeat() const +{ + return this->Impl->RepeatTests; +} + +bool cmCTest::GetRepeatUntilFail() const +{ + return this->Impl->RepeatUntilFail; +} + +void cmCTest::SetBuildID(const std::string& id) +{ + this->Impl->BuildID = id; +} + +std::string cmCTest::GetBuildID() const +{ + return this->Impl->BuildID; } void cmCTest::AddSubmitFile(Part part, const char* name) { - this->Parts[part].SubmitFiles.emplace_back(name); + this->Impl->Parts[part].SubmitFiles.emplace_back(name); +} + +std::vector<std::string> const& cmCTest::GetSubmitFiles(Part part) const +{ + return this->Impl->Parts[part].SubmitFiles; +} + +void cmCTest::ClearSubmitFiles(Part part) +{ + this->Impl->Parts[part].SubmitFiles.clear(); +} + +void cmCTest::SetSuppressUpdatingCTestConfiguration(bool val) +{ + this->Impl->SuppressUpdatingCTestConfiguration = val; } void cmCTest::AddCTestConfigurationOverwrite(const std::string& overStr) @@ -2732,14 +2894,14 @@ void cmCTest::AddCTestConfigurationOverwrite(const std::string& overStr) } std::string key = overStr.substr(0, epos); std::string value = overStr.substr(epos + 1); - this->CTestConfigurationOverwrites[key] = value; + this->Impl->CTestConfigurationOverwrites[key] = value; } void cmCTest::SetConfigType(const char* ct) { - this->ConfigType = ct ? ct : ""; - cmSystemTools::ReplaceString(this->ConfigType, ".\\", ""); - std::string confTypeEnv = "CMAKE_CONFIG_TYPE=" + this->ConfigType; + this->Impl->ConfigType = ct ? ct : ""; + cmSystemTools::ReplaceString(this->Impl->ConfigType, ".\\", ""); + std::string confTypeEnv = "CMAKE_CONFIG_TYPE=" + this->Impl->ConfigType; cmSystemTools::PutEnv(confTypeEnv); } @@ -2805,12 +2967,12 @@ bool cmCTest::RunCommand(std::vector<std::string> const& args, done = true; } if ((res == cmsysProcess_Pipe_STDOUT || res == cmsysProcess_Pipe_STDERR) && - this->ExtraVerbose) { + this->Impl->ExtraVerbose) { processOutput.DecodeText(data, length, strdata); cmSystemTools::Stdout(strdata); } } - if (this->ExtraVerbose) { + if (this->Impl->ExtraVerbose) { processOutput.DecodeText(std::string(), strdata); if (!strdata.empty()) { cmSystemTools::Stdout(strdata); @@ -2859,12 +3021,12 @@ bool cmCTest::RunCommand(std::vector<std::string> const& args, void cmCTest::SetOutputLogFileName(const char* name) { - if (this->OutputLogFile) { - delete this->OutputLogFile; - this->OutputLogFile = nullptr; + if (this->Impl->OutputLogFile) { + delete this->Impl->OutputLogFile; + this->Impl->OutputLogFile = nullptr; } if (name) { - this->OutputLogFile = new cmGeneratedFileStream(name); + this->Impl->OutputLogFile = new cmGeneratedFileStream(name); } } @@ -2880,18 +3042,11 @@ static const char* cmCTestStringLogType[] = { "DEBUG", #define cmCTestLogOutputFileLine(stream) \ do { \ - if (this->ShowLineNumbers) { \ + if (this->Impl->ShowLineNumbers) { \ (stream) << std::endl << file << ":" << line << " "; \ } \ } while (false) -void cmCTest::InitStreams() -{ - // By default we write output to the process output streams. - this->StreamOut = &std::cout; - this->StreamErr = &std::cerr; -} - void cmCTest::Log(int logType, const char* file, int line, const char* msg, bool suppress) { @@ -2902,53 +3057,53 @@ void cmCTest::Log(int logType, const char* file, int line, const char* msg, return; } if (logType == cmCTest::HANDLER_PROGRESS_OUTPUT && - (this->Debug || this->ExtraVerbose)) { + (this->Impl->Debug || this->Impl->ExtraVerbose)) { return; } - if (this->OutputLogFile) { + if (this->Impl->OutputLogFile) { bool display = true; - if (logType == cmCTest::DEBUG && !this->Debug) { + if (logType == cmCTest::DEBUG && !this->Impl->Debug) { display = false; } - if (logType == cmCTest::HANDLER_VERBOSE_OUTPUT && !this->Debug && - !this->ExtraVerbose) { + if (logType == cmCTest::HANDLER_VERBOSE_OUTPUT && !this->Impl->Debug && + !this->Impl->ExtraVerbose) { display = false; } if (display) { - cmCTestLogOutputFileLine(*this->OutputLogFile); - if (logType != this->OutputLogFileLastTag) { - *this->OutputLogFile << "["; + cmCTestLogOutputFileLine(*this->Impl->OutputLogFile); + if (logType != this->Impl->OutputLogFileLastTag) { + *this->Impl->OutputLogFile << "["; if (logType >= OTHER || logType < 0) { - *this->OutputLogFile << "OTHER"; + *this->Impl->OutputLogFile << "OTHER"; } else { - *this->OutputLogFile << cmCTestStringLogType[logType]; + *this->Impl->OutputLogFile << cmCTestStringLogType[logType]; } - *this->OutputLogFile << "] " << std::endl << std::flush; + *this->Impl->OutputLogFile << "] " << std::endl << std::flush; } - *this->OutputLogFile << msg << std::flush; - if (logType != this->OutputLogFileLastTag) { - *this->OutputLogFile << std::endl << std::flush; - this->OutputLogFileLastTag = logType; + *this->Impl->OutputLogFile << msg << std::flush; + if (logType != this->Impl->OutputLogFileLastTag) { + *this->Impl->OutputLogFile << std::endl << std::flush; + this->Impl->OutputLogFileLastTag = logType; } } } - if (!this->Quiet) { - std::ostream& out = *this->StreamOut; - std::ostream& err = *this->StreamErr; + if (!this->Impl->Quiet) { + std::ostream& out = *this->Impl->StreamOut; + std::ostream& err = *this->Impl->StreamErr; if (logType == HANDLER_TEST_PROGRESS_OUTPUT) { - if (this->TestProgressOutput) { + if (this->Impl->TestProgressOutput) { cmCTestLogOutputFileLine(out); - if (this->FlushTestProgressLine) { + if (this->Impl->FlushTestProgressLine) { printf("\r"); - this->FlushTestProgressLine = false; + this->Impl->FlushTestProgressLine = false; out.flush(); } std::string msg_str{ msg }; auto const lineBreakIt = msg_str.find('\n'); if (lineBreakIt != std::string::npos) { - this->FlushTestProgressLine = true; + this->Impl->FlushTestProgressLine = true; msg_str.erase(std::remove(msg_str.begin(), msg_str.end(), '\n'), msg_str.end()); } @@ -2965,7 +3120,7 @@ void cmCTest::Log(int logType, const char* file, int line, const char* msg, switch (logType) { case DEBUG: - if (this->Debug) { + if (this->Impl->Debug) { cmCTestLogOutputFileLine(out); out << msg; out.flush(); @@ -2973,14 +3128,14 @@ void cmCTest::Log(int logType, const char* file, int line, const char* msg, break; case OUTPUT: case HANDLER_OUTPUT: - if (this->Debug || this->Verbose) { + if (this->Impl->Debug || this->Impl->Verbose) { cmCTestLogOutputFileLine(out); out << msg; out.flush(); } break; case HANDLER_VERBOSE_OUTPUT: - if (this->Debug || this->ExtraVerbose) { + if (this->Impl->Debug || this->Impl->ExtraVerbose) { cmCTestLogOutputFileLine(out); out << msg; out.flush(); @@ -3007,7 +3162,7 @@ void cmCTest::Log(int logType, const char* file, int line, const char* msg, std::string cmCTest::GetColorCode(Color color) const { - if (this->OutputColorCode) { + if (this->Impl->OutputColorCode) { #if defined(_WIN32) // Not supported on Windows static_cast<void>(color); @@ -3021,14 +3176,7 @@ std::string cmCTest::GetColorCode(Color color) const cmDuration cmCTest::GetRemainingTimeAllowed() { - if (!this->GetHandler("script")) { - return cmCTest::MaxDuration(); - } - - cmCTestScriptHandler* ch = - static_cast<cmCTestScriptHandler*>(this->GetHandler("script")); - - return ch->GetRemainingTimeAllowed(); + return this->GetScriptHandler()->GetRemainingTimeAllowed(); } cmDuration cmCTest::MaxDuration() @@ -3038,10 +3186,7 @@ cmDuration cmCTest::MaxDuration() void cmCTest::SetRunCurrentScript(bool value) { - cmCTestScriptHandler* ch = - static_cast<cmCTestScriptHandler*>(this->GetHandler("script")); - - ch->SetRunCurrentScript(value); + this->GetScriptHandler()->SetRunCurrentScript(value); } void cmCTest::OutputTestErrors(std::vector<char> const& process_output) diff --git a/Source/cmCTest.h b/Source/cmCTest.h index a765fed..d300c33 100644 --- a/Source/cmCTest.h +++ b/Source/cmCTest.h @@ -10,13 +10,22 @@ #include <chrono> #include <map> -#include <set> +#include <memory> // IWYU pragma: keep #include <sstream> #include <string> #include <time.h> #include <vector> -class cmCTestGenericHandler; +class cmCTestBuildHandler; +class cmCTestBuildAndTestHandler; +class cmCTestCoverageHandler; +class cmCTestScriptHandler; +class cmCTestTestHandler; +class cmCTestUpdateHandler; +class cmCTestConfigureHandler; +class cmCTestMemCheckHandler; +class cmCTestSubmitHandler; +class cmCTestUploadHandler; class cmCTestStartCommand; class cmGeneratedFileStream; class cmMakefile; @@ -31,9 +40,6 @@ class cmXMLWriter; */ class cmCTest { - friend class cmCTestRunTest; - friend class cmCTestMultiProcessHandler; - public: typedef cmProcessOutput::Encoding Encoding; /** Enumerate parts of the testing and submission process. */ @@ -54,44 +60,10 @@ public: PartCount // Update names in constructor when adding a part }; - /** Representation of one part. */ - struct PartInfo - { - void SetName(const std::string& name) { this->Name = name; } - const std::string& GetName() const { return this->Name; } - - void Enable() { this->Enabled = true; } - explicit operator bool() const { return this->Enabled; } - - std::vector<std::string> SubmitFiles; - - private: - bool Enabled = false; - std::string Name; - }; -#ifdef CMAKE_BUILD_WITH_CMAKE - enum HTTPMethod - { - HTTP_GET, - HTTP_POST, - HTTP_PUT - }; - - /** - * Perform an HTTP request. - */ - static int HTTPRequest(std::string url, HTTPMethod method, - std::string& response, std::string const& fields = "", - std::string const& putFile = "", int timeout = 0); -#endif - /** Get a testing part id from its string name. Returns PartCount if the string does not name a valid part. */ Part GetPartFromName(const char* name); - typedef std::vector<std::string> VectorOfStrings; - typedef std::set<std::string> SetOfStrings; - /** Process Command line arguments */ int Run(std::vector<std::string>&, std::string* output = nullptr); @@ -128,7 +100,7 @@ public: /** * Is the tomorrow tag set? */ - bool GetTomorrowTag() { return this->TomorrowTag; } + bool GetTomorrowTag() const; /** * Try to run tests of the project @@ -137,16 +109,16 @@ public: /** what is the configuration type, e.g. Debug, Release etc. */ std::string const& GetConfigType(); - cmDuration GetTimeOut() { return this->TimeOut; } - void SetTimeOut(cmDuration t) { this->TimeOut = t; } + cmDuration GetTimeOut() const; + void SetTimeOut(cmDuration t); - cmDuration GetGlobalTimeout() { return this->GlobalTimeout; } + cmDuration GetGlobalTimeout() const; /** how many test to run at the same time */ - int GetParallelLevel() { return this->ParallelLevel; } + int GetParallelLevel() const; void SetParallelLevel(int); - unsigned long GetTestLoad() { return this->TestLoad; } + unsigned long GetTestLoad() const; void SetTestLoad(unsigned long); /** @@ -164,7 +136,7 @@ public: * Set the cmake test mode (experimental, nightly, continuous). */ void SetTestModel(int mode); - int GetTestModel() { return this->TestModel; } + int GetTestModel() const; std::string GetTestModelString(); static int GetTestModelFromString(const char* str); @@ -222,26 +194,23 @@ public: int GetOutputAsJsonVersion(); - bool ShouldUseHTTP10() { return this->UseHTTP10; } + bool ShouldUseHTTP10() const; - bool ShouldPrintLabels() { return this->PrintLabels; } + bool ShouldPrintLabels() const; bool ShouldCompressTestOutput(); bool CompressString(std::string& str); - std::chrono::system_clock::time_point GetStopTime() - { - return this->StopTime; - } + std::chrono::system_clock::time_point GetStopTime() const; void SetStopTime(std::string const& time); /** Used for parallel ctest job scheduling */ - std::string GetScheduleType() { return this->ScheduleType; } - void SetScheduleType(std::string const& type) { this->ScheduleType = type; } + std::string GetScheduleType() const; + void SetScheduleType(std::string const& type); /** The max output width */ int GetMaxTestNameWidth() const; - void SetMaxTestNameWidth(int w) { this->MaxTestNameWidth = w; } + void SetMaxTestNameWidth(int w); /** * Run a single executable command and put the stdout and stderr @@ -335,16 +304,18 @@ public: Encoding encoding = cmProcessOutput::Auto); /** - * Execute handler and return its result. If the handler fails, it returns - * negative value. - */ - int ExecuteHandler(const char* handler); - - /** * Get the handler object */ - cmCTestGenericHandler* GetHandler(const char* handler); - cmCTestGenericHandler* GetInitializedHandler(const char* handler); + cmCTestBuildHandler* GetBuildHandler(); + cmCTestBuildAndTestHandler* GetBuildAndTestHandler(); + cmCTestCoverageHandler* GetCoverageHandler(); + cmCTestScriptHandler* GetScriptHandler(); + cmCTestTestHandler* GetTestHandler(); + cmCTestUpdateHandler* GetUpdateHandler(); + cmCTestConfigureHandler* GetConfigureHandler(); + cmCTestMemCheckHandler* GetMemCheckHandler(); + cmCTestSubmitHandler* GetSubmitHandler(); + cmCTestUploadHandler* GetUploadHandler(); /** * Set the CTest variable from CMake variable @@ -354,9 +325,6 @@ public: const std::string& cmake_var, bool suppress = false); - /** Make string safe to be sent as a URL */ - static std::string MakeURLSafe(const std::string&); - /** Decode a URL to the original string. */ static std::string DecodeURL(const std::string&); @@ -364,10 +332,7 @@ public: * Should ctect configuration be updated. When using new style ctest * script, this should be true. */ - void SetSuppressUpdatingCTestConfiguration(bool val) - { - this->SuppressUpdatingCTestConfiguration = val; - } + void SetSuppressUpdatingCTestConfiguration(bool val); /** * Add overwrite to ctest configuration. @@ -377,14 +342,14 @@ public: void AddCTestConfigurationOverwrite(const std::string& encstr); /** Create XML file that contains all the notes specified */ - int GenerateNotesFile(const VectorOfStrings& files); + int GenerateNotesFile(std::vector<std::string> const& files); /** Create XML file to indicate that build is complete */ int GenerateDoneFile(); /** Submit extra files to the server */ bool SubmitExtraFiles(const char* files); - bool SubmitExtraFiles(const VectorOfStrings& files); + bool SubmitExtraFiles(std::vector<std::string> const& files); /** Set the output log file name */ void SetOutputLogFileName(const char* name); @@ -424,62 +389,52 @@ public: std::string GetColorCode(Color color) const; /** The Build ID is assigned by CDash */ - void SetBuildID(const std::string& id) { this->BuildID = id; } - std::string GetBuildID() { return this->BuildID; } + void SetBuildID(const std::string& id); + std::string GetBuildID() const; /** Add file to be submitted */ void AddSubmitFile(Part part, const char* name); - std::vector<std::string> const& GetSubmitFiles(Part part) - { - return this->Parts[part].SubmitFiles; - } - void ClearSubmitFiles(Part part) { this->Parts[part].SubmitFiles.clear(); } + std::vector<std::string> const& GetSubmitFiles(Part part) const; + void ClearSubmitFiles(Part part); /** * Read the custom configuration files and apply them to the current ctest */ int ReadCustomConfigurationFileTree(const char* dir, cmMakefile* mf); - std::vector<std::string>& GetInitialCommandLineArguments() - { - return this->InitialCommandLineArguments; - } + std::vector<std::string>& GetInitialCommandLineArguments(); /** Set the track to submit to */ void SetSpecificTrack(const char* track); const char* GetSpecificTrack(); - void SetFailover(bool failover) { this->Failover = failover; } - bool GetFailover() { return this->Failover; } + void SetFailover(bool failover); + bool GetFailover() const; - bool GetTestProgressOutput() const { return this->TestProgressOutput; } + bool GetTestProgressOutput() const; - bool GetVerbose() { return this->Verbose; } - bool GetExtraVerbose() { return this->ExtraVerbose; } + bool GetVerbose() const; + bool GetExtraVerbose() const; /** Direct process output to given streams. */ - void SetStreams(std::ostream* out, std::ostream* err) - { - this->StreamOut = out; - this->StreamErr = err; - } + void SetStreams(std::ostream* out, std::ostream* err); + void AddSiteProperties(cmXMLWriter& xml); - bool GetLabelSummary() { return this->LabelSummary; } - bool GetSubprojectSummary() { return this->SubprojectSummary; } + bool GetLabelSummary() const; + bool GetSubprojectSummary() const; std::string GetCostDataFile(); - const std::map<std::string, std::string>& GetDefinitions() - { - return this->Definitions; - } + bool GetOutputTestOutputOnTestFailure() const; + + const std::map<std::string, std::string>& GetDefinitions() const; /** Return the number of times a test should be run */ - int GetTestRepeat() { return this->RepeatTests; } + int GetTestRepeat() const; /** Return true if test should run until fail */ - bool GetRepeatUntilFail() { return this->RepeatUntilFail; } + bool GetRepeatUntilFail() const; void GenerateSubprojectsOutput(cmXMLWriter& xml); std::vector<std::string> GetLabelsForSubprojects(); @@ -487,85 +442,8 @@ public: void SetRunCurrentScript(bool value); private: - int RepeatTests; - bool RepeatUntilFail; - std::string ConfigType; - std::string ScheduleType; - std::chrono::system_clock::time_point StopTime; - bool TestProgressOutput; - bool Verbose; - bool ExtraVerbose; - bool ProduceXML; - bool LabelSummary; - bool SubprojectSummary; - bool UseHTTP10; - bool PrintLabels; - bool Failover; - - bool FlushTestProgressLine; - - bool ForceNewCTestProcess; - - bool RunConfigurationScript; - int GenerateNotesFile(const char* files); - // these are helper classes - typedef std::map<std::string, cmCTestGenericHandler*> t_TestingHandlers; - t_TestingHandlers TestingHandlers; - - bool ShowOnly; - bool OutputAsJson; - int OutputAsJsonVersion; - - /** Map of configuration properties */ - typedef std::map<std::string, std::string> CTestConfigurationMap; - - // TODO: The ctest configuration should be a hierarchy of - // configuration option sources: command-line, script, ini file. - // Then the ini file can get re-loaded whenever it changes without - // affecting any higher-precedence settings. - CTestConfigurationMap CTestConfiguration; - CTestConfigurationMap CTestConfigurationOverwrites; - PartInfo Parts[PartCount]; - typedef std::map<std::string, Part> PartMapType; - PartMapType PartMap; - - std::string CurrentTag; - bool TomorrowTag; - - int TestModel; - std::string SpecificTrack; - - cmDuration TimeOut; - - cmDuration GlobalTimeout; - - int MaxTestNameWidth; - - int ParallelLevel; - bool ParallelLevelSetInCli; - - unsigned long TestLoad; - - int CompatibilityMode; - - // information for the --build-and-test options - std::string BinaryDir; - - std::string NotesFiles; - - bool InteractiveDebugMode; - - bool ShortDateFormat; - - bool CompressXMLFiles; - bool CompressTestOutput; - - void InitStreams(); - std::ostream* StreamOut; - std::ostream* StreamErr; - void BlockTestErrorDiagnostics(); /** @@ -610,7 +488,8 @@ private: bool UpdateCTestConfiguration(); /** Create note from files. */ - int GenerateCTestNotesOutput(cmXMLWriter& xml, const VectorOfStrings& files); + int GenerateCTestNotesOutput(cmXMLWriter& xml, + std::vector<std::string> const& files); /** Check if the argument is the one specified */ bool CheckArgument(const std::string& arg, const char* varg1, @@ -630,25 +509,8 @@ private: int RunCMakeAndTest(std::string* output); int ExecuteTests(); - bool SuppressUpdatingCTestConfiguration; - - bool Debug; - bool ShowLineNumbers; - bool Quiet; - - std::string BuildID; - - std::vector<std::string> InitialCommandLineArguments; - - int SubmitIndex; - - cmGeneratedFileStream* OutputLogFile; - int OutputLogFileLastTag; - - bool OutputTestOutputOnTestFailure; - bool OutputColorCode; - - std::map<std::string, std::string> Definitions; + struct Private; + std::unique_ptr<Private> Impl; }; class cmCTestLogWrite diff --git a/Source/cmDepends.cxx b/Source/cmDepends.cxx index c128b02..efadaf1 100644 --- a/Source/cmDepends.cxx +++ b/Source/cmDepends.cxx @@ -2,7 +2,7 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmDepends.h" -#include "cmFileTimeComparison.h" +#include "cmFileTimeCache.h" #include "cmGeneratedFileStream.h" #include "cmLocalGenerator.h" #include "cmMakefile.h" @@ -177,8 +177,7 @@ bool cmDepends::CheckDependencies( if (dependerExists) { // The dependee and depender both exist. Compare file times. int result = 0; - if ((!this->FileComparison->FileTimeCompare(depender, dependee, - &result) || + if ((!this->FileTimeCache->Compare(depender, dependee, &result) || result < 0)) { // The depender is older than the dependee. regenerate = true; @@ -195,8 +194,8 @@ bool cmDepends::CheckDependencies( // The dependee exists, but the depender doesn't. Regenerate if the // internalDepends file is older than the dependee. int result = 0; - if ((!this->FileComparison->FileTimeCompare(internalDependsFileName, - dependee, &result) || + if ((!this->FileTimeCache->Compare(internalDependsFileName, dependee, + &result) || result < 0)) { // The depends-file is older than the dependee. regenerate = true; diff --git a/Source/cmDepends.h b/Source/cmDepends.h index 20c91ca..fc6571d 100644 --- a/Source/cmDepends.h +++ b/Source/cmDepends.h @@ -12,7 +12,7 @@ #include <string> #include <vector> -class cmFileTimeComparison; +class cmFileTimeCache; class cmLocalGenerator; /** \class cmDepends @@ -72,10 +72,7 @@ public: void Clear(const std::string& file); /** Set the file comparison object */ - void SetFileComparison(cmFileTimeComparison* fc) - { - this->FileComparison = fc; - } + void SetFileTimeCache(cmFileTimeCache* fc) { this->FileTimeCache = fc; } protected: // Write dependencies for the target file to the given stream. @@ -101,7 +98,7 @@ protected: // Flag for verbose output. bool Verbose = false; - cmFileTimeComparison* FileComparison = nullptr; + cmFileTimeCache* FileTimeCache = nullptr; std::string Language; diff --git a/Source/cmDependsC.cxx b/Source/cmDependsC.cxx index a85f5ee..7b78767 100644 --- a/Source/cmDependsC.cxx +++ b/Source/cmDependsC.cxx @@ -6,6 +6,7 @@ #include <utility> #include "cmAlgorithms.h" +#include "cmFileTime.h" #include "cmLocalGenerator.h" #include "cmMakefile.h" #include "cmSystemTools.h" @@ -149,7 +150,7 @@ bool cmDependsC::WriteDependencies(const std::set<std::string>& sources, // Construct the name of the file as if it were in the current // include directory. Avoid using a leading "./". std::string tmpPath = - cmSystemTools::CollapseCombinedPath(iPath, current.FileName); + cmSystemTools::CollapseFullPath(current.FileName, iPath); // Look for the file in this location. if (cmSystemTools::FileExists(tmpPath, true)) { @@ -247,6 +248,8 @@ void cmDependsC::ReadCacheFile() cmIncludeLines* cacheEntry = nullptr; bool haveFileName = false; + cmFileTime cacheFileTime; + bool const cacheFileTimeGood = cacheFileTime.Load(this->CacheFileName); while (cmSystemTools::GetLineFromStream(fin, line)) { if (line.empty()) { cacheEntry = nullptr; @@ -256,11 +259,12 @@ void cmDependsC::ReadCacheFile() // the first line after an empty line is the name of the parsed file if (!haveFileName) { haveFileName = true; - int newer = 0; - bool res = - cmSystemTools::FileTimeCompare(this->CacheFileName, line, &newer); - if (res && newer == 1) // cache is newer than the parsed file + cmFileTime fileTime; + bool const res = cacheFileTimeGood && fileTime.Load(line); + bool const newer = res && cacheFileTime.Newer(fileTime); + + if (res && newer) // cache is newer than the parsed file { cacheEntry = new cmIncludeLines; this->FileCache[line] = cacheEntry; @@ -358,7 +362,7 @@ void cmDependsC::Scan(std::istream& is, const std::string& directory, // must check for the file in the directory containing the // file we are scanning. entry.QuotedLocation = - cmSystemTools::CollapseCombinedPath(directory, entry.FileName); + cmSystemTools::CollapseFullPath(entry.FileName, directory); } // Queue the file if it has not yet been encountered and it diff --git a/Source/cmExportCommand.cxx b/Source/cmExportCommand.cxx index 722831a..c25e1f4 100644 --- a/Source/cmExportCommand.cxx +++ b/Source/cmExportCommand.cxx @@ -13,6 +13,7 @@ #include "cmGlobalGenerator.h" #include "cmMakefile.h" #include "cmMessageType.h" +#include "cmPolicies.h" #include "cmStateTypes.h" #include "cmSystemTools.h" #include "cmTarget.h" @@ -243,10 +244,23 @@ bool cmExportCommand::HandlePackage(std::vector<std::string> const& args) return false; } - // If the CMAKE_EXPORT_NO_PACKAGE_REGISTRY variable is set the command - // export(PACKAGE) does nothing. - if (this->Makefile->IsOn("CMAKE_EXPORT_NO_PACKAGE_REGISTRY")) { - return true; + // CMP0090 decides both the default and what variable changes it. + switch (this->Makefile->GetPolicyStatus(cmPolicies::CMP0090)) { + case cmPolicies::WARN: + case cmPolicies::OLD: + // Default is to export, but can be disabled. + if (this->Makefile->IsOn("CMAKE_EXPORT_NO_PACKAGE_REGISTRY")) { + return true; + } + break; + case cmPolicies::REQUIRED_IF_USED: + case cmPolicies::REQUIRED_ALWAYS: + case cmPolicies::NEW: + // Default is to not export, but can be enabled. + if (!this->Makefile->IsOn("CMAKE_EXPORT_PACKAGE_REGISTRY")) { + return true; + } + break; } // We store the current build directory in the registry as a value diff --git a/Source/cmExtraEclipseCDT4Generator.cxx b/Source/cmExtraEclipseCDT4Generator.cxx index a6ce8b7..aece3bc 100644 --- a/Source/cmExtraEclipseCDT4Generator.cxx +++ b/Source/cmExtraEclipseCDT4Generator.cxx @@ -845,6 +845,9 @@ void cmExtraEclipseCDT4Generator::CreateCProjectFile() const const std::vector<cmGeneratorTarget*>& targets = lgen->GetGeneratorTargets(); for (cmGeneratorTarget* 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); @@ -971,6 +974,8 @@ void cmExtraEclipseCDT4Generator::CreateCProjectFile() const virtDir, "", ""); } } break; + case cmStateEnums::INTERFACE_LIBRARY: + break; default: break; } diff --git a/Source/cmFileCopier.cxx b/Source/cmFileCopier.cxx index 560d893..8913e6d 100644 --- a/Source/cmFileCopier.cxx +++ b/Source/cmFileCopier.cxx @@ -532,7 +532,7 @@ bool cmFileCopier::InstallFile(const std::string& fromFile, bool copy = true; if (!this->Always) { // If both files exist with the same time do not copy. - if (!this->FileTimes.FileTimesDiffer(fromFile, toFile)) { + if (!this->FileTimes.DifferS(fromFile, toFile)) { copy = false; } } diff --git a/Source/cmFileCopier.h b/Source/cmFileCopier.h index a11c371..003b8f6 100644 --- a/Source/cmFileCopier.h +++ b/Source/cmFileCopier.h @@ -5,7 +5,7 @@ #include "cmConfigure.h" // IWYU pragma: keep -#include "cmFileTimeComparison.h" +#include "cmFileTimeCache.h" #include "cm_sys_stat.h" #include "cmsys/RegularExpression.hxx" @@ -28,7 +28,7 @@ protected: cmMakefile* Makefile; const char* Name; bool Always; - cmFileTimeComparison FileTimes; + cmFileTimeCache FileTimes; // Whether to install a file not matching any expression. bool MatchlessFiles; diff --git a/Source/cmFileTime.cxx b/Source/cmFileTime.cxx new file mode 100644 index 0000000..253457f --- /dev/null +++ b/Source/cmFileTime.cxx @@ -0,0 +1,49 @@ +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing for details. */ +#include "cmFileTime.h" + +#include <string> +#include <time.h> + +// Use a platform-specific API to get file times efficiently. +#if !defined(_WIN32) || defined(__CYGWIN__) +# include "cm_sys_stat.h" +#else +# include "cmsys/Encoding.hxx" +# include <windows.h> +#endif + +bool cmFileTime::Load(std::string const& fileName) +{ +#if !defined(_WIN32) || defined(__CYGWIN__) + // POSIX version. Use the stat function. + struct stat fst; + if (::stat(fileName.c_str(), &fst) != 0) { + return false; + } +# if CMake_STAT_HAS_ST_MTIM + // Nanosecond resolution + this->NS = fst.st_mtim.tv_sec * NsPerS + fst.st_mtim.tv_nsec; +# elif CMake_STAT_HAS_ST_MTIMESPEC + // Nanosecond resolution + this->NS = fst.st_mtimespec.tv_sec * NsPerS + fst.st_mtimespec.tv_nsec; +# else + // Second resolution + this->NS = fst.st_mtime * NsPerS; +# endif +#else + // Windows version. Get the modification time from extended file attributes. + WIN32_FILE_ATTRIBUTE_DATA fdata; + if (!GetFileAttributesExW(cmsys::Encoding::ToWide(fileName).c_str(), + GetFileExInfoStandard, &fdata)) { + return false; + } + + // Copy the file time to the output location. + this->NS = (static_cast<NSC>(fdata.ftLastWriteTime.dwHighDateTime) << 32) | + static_cast<NSC>(fdata.ftLastWriteTime.dwLowDateTime); + // The file time resolution is 100 ns. + this->NS *= 100; +#endif + return true; +} diff --git a/Source/cmFileTime.h b/Source/cmFileTime.h new file mode 100644 index 0000000..4c8e556 --- /dev/null +++ b/Source/cmFileTime.h @@ -0,0 +1,130 @@ +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing for details. */ +#ifndef cmFileTime_h +#define cmFileTime_h + +#include "cmConfigure.h" // IWYU pragma: keep + +#include <string> + +/** \class cmFileTime + * \brief Abstract file modification time with support for comparison with + * other file modification times. + */ +class cmFileTime +{ +public: + typedef long long NSC; + static constexpr NSC NsPerS = 1000000000; + + cmFileTime() = default; + ~cmFileTime() = default; + + /** + * @brief Loads the file time of fileName from the file system + * @return true on success + */ + bool Load(std::string const& fileName); + + /** + * @brief Return true if this is older than ftm + */ + bool Older(cmFileTime const& ftm) const { return (this->NS - ftm.NS) < 0; } + + /** + * @brief Return true if this is newer than ftm + */ + bool Newer(cmFileTime const& ftm) const { return (ftm.NS - this->NS) < 0; } + + /** + * @brief Return true if this is the same as ftm + */ + bool Equal(cmFileTime const& ftm) const { return this->NS == ftm.NS; } + + /** + * @brief Return true if this is not the same as ftm + */ + bool Differ(cmFileTime const& ftm) const { return this->NS != ftm.NS; } + + /** + * @brief Compare file modification times. + * @return -1, 0, +1 for this older, same, or newer than ftm. + */ + int Compare(cmFileTime const& ftm) + { + NSC const diff = this->NS - ftm.NS; + if (diff == 0) { + return 0; + } + return (diff < 0) ? -1 : 1; + } + + // -- Comparison in second resolution + + /** + * @brief Return true if this is at least a second older than ftm + */ + bool OlderS(cmFileTime const& ftm) const + { + return (ftm.NS - this->NS) >= cmFileTime::NsPerS; + } + + /** + * @brief Return true if this is at least a second newer than ftm + */ + bool NewerS(cmFileTime const& ftm) const + { + return (this->NS - ftm.NS) >= cmFileTime::NsPerS; + } + + /** + * @brief Return true if this is within the same second as ftm + */ + bool EqualS(cmFileTime const& ftm) const + { + NSC diff = this->NS - ftm.NS; + if (diff < 0) { + diff = -diff; + } + return (diff < cmFileTime::NsPerS); + } + + /** + * @brief Return true if this is older or newer than ftm by at least a second + */ + bool DifferS(cmFileTime const& ftm) const + { + NSC diff = this->NS - ftm.NS; + if (diff < 0) { + diff = -diff; + } + return (diff >= cmFileTime::NsPerS); + } + + /** + * @brief Compare file modification times. + * @return -1: this at least a second older, 0: this within the same second + * as ftm, +1: this at least a second newer than ftm. + */ + int CompareS(cmFileTime const& ftm) const + { + NSC const diff = this->NS - ftm.NS; + if (diff <= -cmFileTime::NsPerS) { + return -1; + } + if (diff >= cmFileTime::NsPerS) { + return 1; + } + return 0; + } + + /** + * @brief The file modification time in nanoseconds + */ + NSC GetNS() const { return this->NS; } + +private: + NSC NS = 0; +}; + +#endif diff --git a/Source/cmFileTimeCache.cxx b/Source/cmFileTimeCache.cxx new file mode 100644 index 0000000..1fff6a9 --- /dev/null +++ b/Source/cmFileTimeCache.cxx @@ -0,0 +1,57 @@ +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing for details. */ +#include "cmFileTimeCache.h" + +#include <string> +#include <unordered_map> +#include <utility> + +cmFileTimeCache::cmFileTimeCache() = default; + +cmFileTimeCache::~cmFileTimeCache() = default; + +bool cmFileTimeCache::Load(std::string const& fileName, cmFileTime& fileTime) +{ + // Use the stored time if available. + { + auto fit = this->FileTimes.find(fileName); + if (fit != this->FileTimes.end()) { + fileTime = fit->second; + return true; + } + } + // Read file time from OS + if (!fileTime.Load(fileName)) { + return false; + } + // Store file time in cache + this->FileTimes[fileName] = fileTime; + return true; +} + +bool cmFileTimeCache::Compare(std::string const& f1, std::string const& f2, + int* result) +{ + // Get the modification time for each file. + cmFileTime ft1, ft2; + if (this->Load(f1, ft1) && this->Load(f2, ft2)) { + // Compare the two modification times. + *result = ft1.Compare(ft2); + return true; + } + // No comparison available. Default to the same time. + *result = 0; + return false; +} + +bool cmFileTimeCache::DifferS(std::string const& f1, std::string const& f2) +{ + // Get the modification time for each file. + cmFileTime ft1, ft2; + if (this->Load(f1, ft1) && this->Load(f2, ft2)) { + // Compare the two modification times. + return ft1.DifferS(ft2); + } + // No comparison available. Default to different times. + return true; +} diff --git a/Source/cmFileTimeCache.h b/Source/cmFileTimeCache.h new file mode 100644 index 0000000..a47904c --- /dev/null +++ b/Source/cmFileTimeCache.h @@ -0,0 +1,51 @@ +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing for details. */ +#ifndef cmFileTimeCache_h +#define cmFileTimeCache_h + +#include "cmConfigure.h" // IWYU pragma: keep + +#include "cmFileTime.h" +#include <string> +#include <unordered_map> + +/** \class cmFileTimeCache + * \brief Caches file modification times in an internal map for fast lookups. + */ +class cmFileTimeCache +{ +public: + cmFileTimeCache(); + ~cmFileTimeCache(); + + cmFileTimeCache(const cmFileTimeCache&) = delete; + cmFileTimeCache& operator=(const cmFileTimeCache&) = delete; + + /** + * @brief Loads the file time from the cache or the file system. + * @return true on success + */ + bool Load(std::string const& fileName, cmFileTime& fileTime); + + /** + * @brief Compare file modification times. + * @return true for successful comparison and false for error. + * + * When true is returned, result has -1, 0, +1 for + * f1 older, same, or newer than f2. + */ + bool Compare(std::string const& f1, std::string const& f2, int* result); + + /** + * @brief Compare file modification times. + * @return true unless both files exist and have modification times less + * than 1 second apart. + */ + bool DifferS(std::string const& f1, std::string const& f2); + +private: + typedef std::unordered_map<std::string, cmFileTime> FileTimeMap; + FileTimeMap FileTimes; +}; + +#endif diff --git a/Source/cmFileTimeComparison.cxx b/Source/cmFileTimeComparison.cxx deleted file mode 100644 index 8b3911e..0000000 --- a/Source/cmFileTimeComparison.cxx +++ /dev/null @@ -1,233 +0,0 @@ -/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying - file Copyright.txt or https://cmake.org/licensing for details. */ -#include "cmFileTimeComparison.h" - -#include <string> -#include <time.h> -#include <unordered_map> -#include <utility> - -// Use a platform-specific API to get file times efficiently. -#if !defined(_WIN32) || defined(__CYGWIN__) -# include "cm_sys_stat.h" -# define cmFileTimeComparison_Type struct stat -#else -# include "cmsys/Encoding.hxx" -# include <windows.h> -# define cmFileTimeComparison_Type FILETIME -#endif - -class cmFileTimeComparisonInternal -{ -public: - // Internal comparison method. - inline bool FileTimeCompare(const std::string& f1, const std::string& f2, - int* result); - - bool FileTimesDiffer(const std::string& f1, const std::string& f2); - -private: - typedef std::unordered_map<std::string, cmFileTimeComparison_Type> - FileStatsMap; - FileStatsMap Files; - - // Internal methods to lookup and compare modification times. - inline bool Stat(const std::string& fname, cmFileTimeComparison_Type* st); - inline int Compare(cmFileTimeComparison_Type* st1, - cmFileTimeComparison_Type* st2); - inline bool TimesDiffer(cmFileTimeComparison_Type* st1, - cmFileTimeComparison_Type* st2); -}; - -bool cmFileTimeComparisonInternal::Stat(const std::string& fname, - cmFileTimeComparison_Type* st) -{ - // Use the stored time if available. - cmFileTimeComparisonInternal::FileStatsMap::iterator fit = - this->Files.find(fname); - if (fit != this->Files.end()) { - *st = fit->second; - return true; - } - -#if !defined(_WIN32) || defined(__CYGWIN__) - // POSIX version. Use the stat function. - int res = ::stat(fname.c_str(), st); - if (res != 0) { - return false; - } -#else - // Windows version. Get the modification time from extended file - // attributes. - WIN32_FILE_ATTRIBUTE_DATA fdata; - if (!GetFileAttributesExW(cmsys::Encoding::ToWide(fname).c_str(), - GetFileExInfoStandard, &fdata)) { - return false; - } - - // Copy the file time to the output location. - *st = fdata.ftLastWriteTime; -#endif - - // Store the time for future use. - this->Files[fname] = *st; - return true; -} - -cmFileTimeComparison::cmFileTimeComparison() -{ - this->Internals = new cmFileTimeComparisonInternal; -} - -cmFileTimeComparison::~cmFileTimeComparison() -{ - delete this->Internals; -} - -bool cmFileTimeComparison::FileTimeCompare(const std::string& f1, - const std::string& f2, int* result) -{ - return this->Internals->FileTimeCompare(f1, f2, result); -} - -bool cmFileTimeComparison::FileTimesDiffer(const std::string& f1, - const std::string& f2) -{ - return this->Internals->FileTimesDiffer(f1, f2); -} - -int cmFileTimeComparisonInternal::Compare(cmFileTimeComparison_Type* s1, - cmFileTimeComparison_Type* s2) -{ -#if !defined(_WIN32) || defined(__CYGWIN__) -# if CMake_STAT_HAS_ST_MTIM - // Compare using nanosecond resolution. - if (s1->st_mtim.tv_sec < s2->st_mtim.tv_sec) { - return -1; - } - if (s1->st_mtim.tv_sec > s2->st_mtim.tv_sec) { - return 1; - } - if (s1->st_mtim.tv_nsec < s2->st_mtim.tv_nsec) { - return -1; - } - if (s1->st_mtim.tv_nsec > s2->st_mtim.tv_nsec) { - return 1; - } -# elif CMake_STAT_HAS_ST_MTIMESPEC - // Compare using nanosecond resolution. - if (s1->st_mtimespec.tv_sec < s2->st_mtimespec.tv_sec) { - return -1; - } - if (s1->st_mtimespec.tv_sec > s2->st_mtimespec.tv_sec) { - return 1; - } - if (s1->st_mtimespec.tv_nsec < s2->st_mtimespec.tv_nsec) { - return -1; - } - if (s1->st_mtimespec.tv_nsec > s2->st_mtimespec.tv_nsec) { - return 1; - } -# else - // Compare using 1 second resolution. - if (s1->st_mtime < s2->st_mtime) { - return -1; - } - if (s1->st_mtime > s2->st_mtime) { - return 1; - } -# endif - // Files have the same time. - return 0; -#else - // Compare using system-provided function. - return (int)CompareFileTime(s1, s2); -#endif -} - -bool cmFileTimeComparisonInternal::TimesDiffer(cmFileTimeComparison_Type* s1, - cmFileTimeComparison_Type* s2) -{ -#if !defined(_WIN32) || defined(__CYGWIN__) -# if CMake_STAT_HAS_ST_MTIM - // Times are integers in units of 1ns. - long long bil = 1000000000; - long long t1 = s1->st_mtim.tv_sec * bil + s1->st_mtim.tv_nsec; - long long t2 = s2->st_mtim.tv_sec * bil + s2->st_mtim.tv_nsec; - if (t1 < t2) { - return (t2 - t1) >= bil; - } - if (t2 < t1) { - return (t1 - t2) >= bil; - } - return false; -# elif CMake_STAT_HAS_ST_MTIMESPEC - // Times are integers in units of 1ns. - long long bil = 1000000000; - long long t1 = s1->st_mtimespec.tv_sec * bil + s1->st_mtimespec.tv_nsec; - long long t2 = s2->st_mtimespec.tv_sec * bil + s2->st_mtimespec.tv_nsec; - if (t1 < t2) { - return (t2 - t1) >= bil; - } - if (t2 < t1) { - return (t1 - t2) >= bil; - } - return false; -# else - // Times are integers in units of 1s. - if (s1->st_mtime < s2->st_mtime) { - return (s2->st_mtime - s1->st_mtime) >= 1; - } - if (s1->st_mtime > s2->st_mtime) { - return (s1->st_mtime - s2->st_mtime) >= 1; - } - return false; -# endif -#else - // Times are integers in units of 100ns. - LARGE_INTEGER t1; - LARGE_INTEGER t2; - t1.LowPart = s1->dwLowDateTime; - t1.HighPart = s1->dwHighDateTime; - t2.LowPart = s2->dwLowDateTime; - t2.HighPart = s2->dwHighDateTime; - if (t1.QuadPart < t2.QuadPart) { - return (t2.QuadPart - t1.QuadPart) >= static_cast<LONGLONG>(10000000); - } else if (t2.QuadPart < t1.QuadPart) { - return (t1.QuadPart - t2.QuadPart) >= static_cast<LONGLONG>(10000000); - } else { - return false; - } -#endif -} - -bool cmFileTimeComparisonInternal::FileTimeCompare(const std::string& f1, - const std::string& f2, - int* result) -{ - // Get the modification time for each file. - cmFileTimeComparison_Type s1; - cmFileTimeComparison_Type s2; - if (this->Stat(f1, &s1) && this->Stat(f2, &s2)) { - // Compare the two modification times. - *result = this->Compare(&s1, &s2); - return true; - } - // No comparison available. Default to the same time. - *result = 0; - return false; -} - -bool cmFileTimeComparisonInternal::FileTimesDiffer(const std::string& f1, - const std::string& f2) -{ - // Get the modification time for each file. - cmFileTimeComparison_Type s1; - cmFileTimeComparison_Type s2; - if (this->Stat(f1, &s1) && this->Stat(f2, &s2)) { - // Compare the two modification times. - return this->TimesDiffer(&s1, &s2); - } - // No comparison available. Default to different times. - return true; -} diff --git a/Source/cmFileTimeComparison.h b/Source/cmFileTimeComparison.h deleted file mode 100644 index b4e4eb3..0000000 --- a/Source/cmFileTimeComparison.h +++ /dev/null @@ -1,45 +0,0 @@ -/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying - file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmFileTimeComparison_h -#define cmFileTimeComparison_h - -#include "cmConfigure.h" // IWYU pragma: keep - -#include <string> - -class cmFileTimeComparisonInternal; - -/** \class cmFileTimeComparison - * \brief Helper class for comparing file modification times. - * - * Compare file modification times or test if file modification times differ. - */ -class cmFileTimeComparison -{ -public: - cmFileTimeComparison(); - ~cmFileTimeComparison(); - - cmFileTimeComparison(const cmFileTimeComparison&) = delete; - cmFileTimeComparison& operator=(const cmFileTimeComparison&) = delete; - - /** - * Compare file modification times. - * Return true for successful comparison and false for error. - * When true is returned, result has -1, 0, +1 for - * f1 older, same, or newer than f2. - */ - bool FileTimeCompare(const std::string& f1, const std::string& f2, - int* result); - - /** - * Compare file modification times. Return true unless both files - * exist and have modification times less than 1 second apart. - */ - bool FileTimesDiffer(const std::string& f1, const std::string& f2); - -protected: - cmFileTimeComparisonInternal* Internals; -}; - -#endif diff --git a/Source/cmFindProgramCommand.cxx b/Source/cmFindProgramCommand.cxx index db34077..782f746 100644 --- a/Source/cmFindProgramCommand.cxx +++ b/Source/cmFindProgramCommand.cxx @@ -77,7 +77,7 @@ struct cmFindProgramHelper this->TestNameExt = name; this->TestNameExt += ext; this->TestPath = - cmSystemTools::CollapseCombinedPath(path, this->TestNameExt); + cmSystemTools::CollapseFullPath(this->TestNameExt, path); if (cmSystemTools::FileExists(this->TestPath, true)) { this->BestPath = this->TestPath; diff --git a/Source/cmGhsMultiTargetGenerator.cxx b/Source/cmGhsMultiTargetGenerator.cxx index bbe7f23..668bcbd 100644 --- a/Source/cmGhsMultiTargetGenerator.cxx +++ b/Source/cmGhsMultiTargetGenerator.cxx @@ -298,7 +298,7 @@ void cmGhsMultiTargetGenerator::WriteTargetLinkLine(std::ostream& fout, if (l.compare(0, 2, "-l") == 0) { fout << " \"" << l << "\"" << std::endl; } else { - std::string rl = cmSystemTools::CollapseCombinedPath(cbd, l); + std::string rl = cmSystemTools::CollapseFullPath(l, cbd); fout << " -l\"" << rl << "\"" << std::endl; } } diff --git a/Source/cmGlobalGenerator.cxx b/Source/cmGlobalGenerator.cxx index 6964b62..00781c3 100644 --- a/Source/cmGlobalGenerator.cxx +++ b/Source/cmGlobalGenerator.cxx @@ -1214,14 +1214,16 @@ void cmGlobalGenerator::Configure() this->ConfigureDoneCMP0026AndCMP0024 = true; // Put a copy of each global target in every directory. - std::vector<GlobalTargetInfo> globalTargets; - this->CreateDefaultGlobalTargets(globalTargets); - - for (cmMakefile* mf : this->Makefiles) { - cmTargets* targets = &(mf->GetTargets()); - for (GlobalTargetInfo const& globalTarget : globalTargets) { - targets->insert(cmTargets::value_type( - globalTarget.Name, this->CreateGlobalTarget(globalTarget, mf))); + { + std::vector<GlobalTargetInfo> globalTargets; + this->CreateDefaultGlobalTargets(globalTargets); + + for (cmMakefile* mf : this->Makefiles) { + auto& targets = mf->GetTargets(); + for (GlobalTargetInfo const& globalTarget : globalTargets) { + targets.emplace(globalTarget.Name, + this->CreateGlobalTarget(globalTarget, mf)); + } } } diff --git a/Source/cmGlobalGhsMultiGenerator.cxx b/Source/cmGlobalGhsMultiGenerator.cxx index 690398f..e6a1d78 100644 --- a/Source/cmGlobalGhsMultiGenerator.cxx +++ b/Source/cmGlobalGhsMultiGenerator.cxx @@ -194,8 +194,7 @@ void cmGlobalGhsMultiGenerator::GetToolset(cmMakefile* mf, std::string& tsd, } } else { std::string tryPath; - /* CollapseCombinedPath will check if ts is an absolute path */ - tryPath = cmSystemTools::CollapseCombinedPath(tsd, ts); + tryPath = cmSystemTools::CollapseFullPath(ts, tsd); if (!cmSystemTools::FileExists(tryPath)) { std::string msg = "GHS toolset \"" + tryPath + "\" not found."; cmSystemTools::Error(msg); diff --git a/Source/cmGlobalNinjaGenerator.cxx b/Source/cmGlobalNinjaGenerator.cxx index 841587c..e443678 100644 --- a/Source/cmGlobalNinjaGenerator.cxx +++ b/Source/cmGlobalNinjaGenerator.cxx @@ -1997,7 +1997,7 @@ int cmcmd_cmake_ninja_dyndep(std::vector<std::string>::const_iterator argBeg, std::string const dir_top_bld = tdi["dir-top-bld"].asString(); std::string const dir_top_src = tdi["dir-top-src"].asString(); std::string module_dir = tdi["module-dir"].asString(); - if (!module_dir.empty()) { + if (!module_dir.empty() && !cmHasLiteralSuffix(module_dir, "/")) { module_dir += "/"; } std::vector<std::string> linked_target_dirs; diff --git a/Source/cmGlobalVisualStudioVersionedGenerator.cxx b/Source/cmGlobalVisualStudioVersionedGenerator.cxx index 391fe69..2ba1aff 100644 --- a/Source/cmGlobalVisualStudioVersionedGenerator.cxx +++ b/Source/cmGlobalVisualStudioVersionedGenerator.cxx @@ -18,8 +18,15 @@ #elif defined(_M_IA64) # define HOST_PLATFORM_NAME "Itanium" # define HOST_TOOLS_ARCH "" +#elif defined(_WIN64) +# define HOST_PLATFORM_NAME "x64" +# define HOST_TOOLS_ARCH "x64" #else -# include "cmsys/SystemInformation.hxx" +static bool VSIsWow64() +{ + BOOL isWow64 = false; + return IsWow64Process(GetCurrentProcess(), &isWow64) && isWow64; +} #endif static std::string VSHostPlatformName() @@ -27,8 +34,7 @@ static std::string VSHostPlatformName() #ifdef HOST_PLATFORM_NAME return HOST_PLATFORM_NAME; #else - cmsys::SystemInformation info; - if (info.Is64Bits()) { + if (VSIsWow64()) { return "x64"; } else { return "Win32"; @@ -41,8 +47,7 @@ static std::string VSHostArchitecture() #ifdef HOST_TOOLS_ARCH return HOST_TOOLS_ARCH; #else - cmsys::SystemInformation info; - if (info.Is64Bits()) { + if (VSIsWow64()) { return "x64"; } else { return "x86"; diff --git a/Source/cmGlobalXCodeGenerator.cxx b/Source/cmGlobalXCodeGenerator.cxx index 53baed5..4025073 100644 --- a/Source/cmGlobalXCodeGenerator.cxx +++ b/Source/cmGlobalXCodeGenerator.cxx @@ -1022,7 +1022,7 @@ cmXCodeObject* cmGlobalXCodeGenerator::CreateXCodeFileReferenceFromPath( this->CreateString(fileType)); // Store the file path relative to the top of the source tree. - std::string path = this->RelativeToSource(fullpath.c_str()); + std::string path = this->RelativeToSource(fullpath); std::string name = cmSystemTools::GetFilenameName(path); const char* sourceTree = (cmSystemTools::FileIsFullPath(path.c_str()) ? "<absolute>" @@ -3063,7 +3063,7 @@ bool cmGlobalXCodeGenerator::CreateXCodeObjects( // Point Xcode at the top of the source tree. { std::string pdir = - this->RelativeToBinary(root->GetCurrentSourceDirectory().c_str()); + this->RelativeToBinary(root->GetCurrentSourceDirectory()); this->RootObject->AddAttribute("projectDirPath", this->CreateString(pdir)); this->RootObject->AddAttribute("projectRoot", this->CreateString("")); } @@ -3402,10 +3402,8 @@ void cmGlobalXCodeGenerator::OutputXCodeProject( } this->WriteXCodePBXProj(fout, root, generators); - if (this->IsGeneratingScheme(root)) { - this->OutputXCodeSharedSchemes(xcodeDir); - } - this->OutputXCodeWorkspaceSettings(xcodeDir, root); + bool hasGeneratedSchemes = this->OutputXCodeSharedSchemes(xcodeDir, root); + this->OutputXCodeWorkspaceSettings(xcodeDir, hasGeneratedSchemes); this->ClearXCodeObjects(); @@ -3415,17 +3413,8 @@ void cmGlobalXCodeGenerator::OutputXCodeProject( root->GetBinaryDirectory()); } -bool cmGlobalXCodeGenerator::IsGeneratingScheme(cmLocalGenerator* root) const -{ - // Since the lowest available Xcode version for testing was 6.4, - // I'm setting this as a limit then - return this->XcodeVersion >= 64 && - (root->GetMakefile()->GetCMakeInstance()->GetIsInTryCompile() || - root->GetMakefile()->IsOn("CMAKE_XCODE_GENERATE_SCHEME")); -} - -void cmGlobalXCodeGenerator::OutputXCodeSharedSchemes( - const std::string& xcProjDir) +bool cmGlobalXCodeGenerator::OutputXCodeSharedSchemes( + const std::string& xcProjDir, cmLocalGenerator* root) { // collect all tests for the targets std::map<std::string, cmXCodeScheme::TestObjects> testables; @@ -3449,21 +3438,33 @@ void cmGlobalXCodeGenerator::OutputXCodeSharedSchemes( } // generate scheme - for (auto obj : this->XCodeObjects) { - if (obj->GetType() == cmXCodeObject::OBJECT && - (obj->GetIsA() == cmXCodeObject::PBXNativeTarget || - obj->GetIsA() == cmXCodeObject::PBXAggregateTarget)) { - const std::string& targetName = obj->GetTarget()->GetName(); - cmXCodeScheme schm(obj, testables[targetName], - this->CurrentConfigurationTypes, this->XcodeVersion); - schm.WriteXCodeSharedScheme(xcProjDir, - this->RelativeToSource(xcProjDir.c_str())); + bool ret = false; + + // Since the lowest available Xcode version for testing was 6.4, + // I'm setting this as a limit then + if (this->XcodeVersion >= 64) { + for (auto obj : this->XCodeObjects) { + if (obj->GetType() == cmXCodeObject::OBJECT && + (obj->GetIsA() == cmXCodeObject::PBXNativeTarget || + obj->GetIsA() == cmXCodeObject::PBXAggregateTarget) && + (root->GetMakefile()->GetCMakeInstance()->GetIsInTryCompile() || + obj->GetTarget()->GetPropertyAsBool("XCODE_GENERATE_SCHEME"))) { + const std::string& targetName = obj->GetTarget()->GetName(); + cmXCodeScheme schm(obj, testables[targetName], + this->CurrentConfigurationTypes, + this->XcodeVersion); + schm.WriteXCodeSharedScheme(xcProjDir, + this->RelativeToSource(xcProjDir)); + ret = true; + } } } + + return ret; } void cmGlobalXCodeGenerator::OutputXCodeWorkspaceSettings( - const std::string& xcProjDir, cmLocalGenerator* root) + const std::string& xcProjDir, bool hasGeneratedSchemes) { std::string xcodeSharedDataDir = xcProjDir; xcodeSharedDataDir += "/project.xcworkspace/xcshareddata"; @@ -3489,7 +3490,7 @@ void cmGlobalXCodeGenerator::OutputXCodeWorkspaceSettings( xout.Element("key", "BuildSystemType"); xout.Element("string", "Original"); } - if (this->IsGeneratingScheme(root)) { + if (hasGeneratedSchemes) { xout.Element("key", "IDEWorkspaceSharedSettings_AutocreateContextsIfNeeded"); xout.Element("false"); @@ -3559,7 +3560,7 @@ std::string cmGlobalXCodeGenerator::ConvertToRelativeForMake( return cmSystemTools::ConvertToOutputPath(p); } -std::string cmGlobalXCodeGenerator::RelativeToSource(const char* p) +std::string cmGlobalXCodeGenerator::RelativeToSource(const std::string& p) { // We force conversion because Xcode breakpoints do not work unless // they are in a file named relative to the source tree. @@ -3567,7 +3568,7 @@ std::string cmGlobalXCodeGenerator::RelativeToSource(const char* p) cmSystemTools::JoinPath(this->ProjectSourceDirectoryComponents), p); } -std::string cmGlobalXCodeGenerator::RelativeToBinary(const char* p) +std::string cmGlobalXCodeGenerator::RelativeToBinary(const std::string& p) { return this->CurrentLocalGenerator->MaybeConvertToRelativePath( cmSystemTools::JoinPath(this->ProjectOutputDirectoryComponents), p); diff --git a/Source/cmGlobalXCodeGenerator.h b/Source/cmGlobalXCodeGenerator.h index 95db852..8daa95b 100644 --- a/Source/cmGlobalXCodeGenerator.h +++ b/Source/cmGlobalXCodeGenerator.h @@ -119,8 +119,8 @@ private: const std::string& name); bool CreateGroups(std::vector<cmLocalGenerator*>& generators); std::string XCodeEscapePath(const std::string& p); - std::string RelativeToSource(const char* p); - std::string RelativeToBinary(const char* p); + std::string RelativeToSource(const std::string& p); + std::string RelativeToBinary(const std::string& p); std::string ConvertToRelativeForMake(std::string const& p); void CreateCustomCommands(cmXCodeObject* buildPhases, cmXCodeObject* sourceBuildPhase, @@ -186,11 +186,12 @@ private: std::vector<cmLocalGenerator*>& generators); void OutputXCodeProject(cmLocalGenerator* root, std::vector<cmLocalGenerator*>& generators); - bool IsGeneratingScheme(cmLocalGenerator* root) const; // Write shared scheme files for all the native targets - void OutputXCodeSharedSchemes(const std::string& xcProjDir); + // return true if any were written + bool OutputXCodeSharedSchemes(const std::string& xcProjDir, + cmLocalGenerator* root); void OutputXCodeWorkspaceSettings(const std::string& xcProjDir, - cmLocalGenerator* root); + bool hasGeneratedSchemes); void WriteXCodePBXProj(std::ostream& fout, cmLocalGenerator* root, std::vector<cmLocalGenerator*>& generators); cmXCodeObject* CreateXCodeFileReferenceFromPath(const std::string& fullpath, diff --git a/Source/cmLocalUnixMakefileGenerator3.cxx b/Source/cmLocalUnixMakefileGenerator3.cxx index d1093be..f3d5a94 100644 --- a/Source/cmLocalUnixMakefileGenerator3.cxx +++ b/Source/cmLocalUnixMakefileGenerator3.cxx @@ -12,7 +12,7 @@ #include "cmAlgorithms.h" #include "cmCustomCommandGenerator.h" -#include "cmFileTimeComparison.h" +#include "cmFileTimeCache.h" #include "cmGeneratedFileStream.h" #include "cmGeneratorTarget.h" #include "cmGlobalGenerator.h" @@ -1273,12 +1273,11 @@ bool cmLocalUnixMakefileGenerator3::UpdateDependencies( // happen when a new source file is added and CMake regenerates the // project but no other sources were touched. bool needRescanDependInfo = false; - cmFileTimeComparison* ftc = - this->GlobalGenerator->GetCMakeInstance()->GetFileComparison(); + cmFileTimeCache* ftc = + this->GlobalGenerator->GetCMakeInstance()->GetFileTimeCache(); { int result; - if (!ftc->FileTimeCompare(internalDependFile, tgtInfo, &result) || - result < 0) { + if (!ftc->Compare(internalDependFile, tgtInfo, &result) || result < 0) { if (verbose) { std::ostringstream msg; msg << "Dependee \"" << tgtInfo << "\" is newer than depender \"" @@ -1297,7 +1296,7 @@ bool cmLocalUnixMakefileGenerator3::UpdateDependencies( dirInfoFile += "/CMakeFiles"; dirInfoFile += "/CMakeDirectoryInformation.cmake"; int result; - if (!ftc->FileTimeCompare(internalDependFile, dirInfoFile, &result) || + if (!ftc->Compare(internalDependFile, dirInfoFile, &result) || result < 0) { if (verbose) { std::ostringstream msg; @@ -1318,7 +1317,7 @@ bool cmLocalUnixMakefileGenerator3::UpdateDependencies( if (!needRescanDirInfo) { cmDependsC checker; checker.SetVerbose(verbose); - checker.SetFileComparison(ftc); + checker.SetFileTimeCache(ftc); // cmDependsC::Check() fills the vector validDependencies() with the // dependencies for those files where they are still valid, i.e. neither // the files themselves nor any files they depend on have changed. @@ -1439,8 +1438,8 @@ bool cmLocalUnixMakefileGenerator3::ScanDependencies( if (scanner) { scanner->SetLocalGenerator(this); - scanner->SetFileComparison( - this->GlobalGenerator->GetCMakeInstance()->GetFileComparison()); + scanner->SetFileTimeCache( + this->GlobalGenerator->GetCMakeInstance()->GetFileTimeCache()); scanner->SetLanguage(lang); scanner->SetTargetDirectory(targetDir); scanner->Write(ruleFileStream, internalRuleFileStream); diff --git a/Source/cmMakefile.cxx b/Source/cmMakefile.cxx index ab37774..3832427 100644 --- a/Source/cmMakefile.cxx +++ b/Source/cmMakefile.cxx @@ -2023,8 +2023,7 @@ cmTarget* cmMakefile::AddNewTarget(cmStateEnums::TargetType type, { cmTargets::iterator it = this->Targets - .insert(cmTargets::value_type( - name, cmTarget(name, type, cmTarget::VisibilityNormal, this))) + .emplace(name, cmTarget(name, type, cmTarget::VisibilityNormal, this)) .first; this->GetGlobalGenerator()->IndexTarget(&it->second); this->GetStateSnapshot().GetDirectory().AddNormalTargetName(name); diff --git a/Source/cmNinjaTargetGenerator.cxx b/Source/cmNinjaTargetGenerator.cxx index 8d11408..1ad26dd 100644 --- a/Source/cmNinjaTargetGenerator.cxx +++ b/Source/cmNinjaTargetGenerator.cxx @@ -1113,7 +1113,7 @@ void cmNinjaTargetGenerator::WriteObjectBuildStatement( // Explicit preprocessing always uses a depfile. ppVars["DEP_FILE"] = this->GetLocalGenerator()->ConvertToOutputFormat( - objectFileName + ".d", cmOutputConverter::SHELL); + objectFileName + ".pp.d", cmOutputConverter::SHELL); if (compilePP) { // The actual compilation does not need a depfile because it // depends on the already-preprocessed source. diff --git a/Source/cmPolicies.h b/Source/cmPolicies.h index 8b21166..7677186 100644 --- a/Source/cmPolicies.h +++ b/Source/cmPolicies.h @@ -264,6 +264,9 @@ class cmMakefile; 3, 14, 0, cmPolicies::WARN) \ SELECT(POLICY, CMP0089, \ "Compiler id for IBM Clang-based XL compilers is now XLClang.", 3, \ + 15, 0, cmPolicies::WARN) \ + SELECT(POLICY, CMP0090, \ + "export(PACKAGE) does not populate package registry by default.", 3, \ 15, 0, cmPolicies::WARN) #define CM_SELECT_ID(F, A1, A2, A3, A4, A5, A6) F(A1) diff --git a/Source/cmQtAutoGen.cxx b/Source/cmQtAutoGen.cxx index 022947f..87ef112 100644 --- a/Source/cmQtAutoGen.cxx +++ b/Source/cmQtAutoGen.cxx @@ -309,7 +309,7 @@ void cmQtAutoGen::RccListConvertFullPath(std::string const& qrcFileDir, std::vector<std::string>& files) { for (std::string& entry : files) { - std::string tmp = cmSystemTools::CollapseCombinedPath(qrcFileDir, entry); + std::string tmp = cmSystemTools::CollapseFullPath(entry, qrcFileDir); entry = std::move(tmp); } } diff --git a/Source/cmQtAutoGenerator.cxx b/Source/cmQtAutoGenerator.cxx index af50c1d..a1abd3f 100644 --- a/Source/cmQtAutoGenerator.cxx +++ b/Source/cmQtAutoGenerator.cxx @@ -158,11 +158,11 @@ std::string cmQtAutoGenerator::FileSystem::GetRealPath( return cmSystemTools::GetRealPath(filename); } -std::string cmQtAutoGenerator::FileSystem::CollapseCombinedPath( - std::string const& dir, std::string const& file) +std::string cmQtAutoGenerator::FileSystem::CollapseFullPath( + std::string const& file, std::string const& dir) { std::lock_guard<std::mutex> lock(Mutex_); - return cmSystemTools::CollapseCombinedPath(dir, file); + return cmSystemTools::CollapseFullPath(file, dir); } void cmQtAutoGenerator::FileSystem::SplitPath( diff --git a/Source/cmQtAutoGenerator.h b/Source/cmQtAutoGenerator.h index 6771dd8..b55bebc 100644 --- a/Source/cmQtAutoGenerator.h +++ b/Source/cmQtAutoGenerator.h @@ -77,9 +77,9 @@ public: // -- Paths /// @brief Wrapper for cmSystemTools::GetRealPath std::string GetRealPath(std::string const& filename); - /// @brief Wrapper for cmSystemTools::CollapseCombinedPath - std::string CollapseCombinedPath(std::string const& dir, - std::string const& file); + /// @brief Wrapper for cmSystemTools::CollapseFullPath + std::string CollapseFullPath(std::string const& file, + std::string const& dir); /// @brief Wrapper for cmSystemTools::SplitPath void SplitPath(const std::string& p, std::vector<std::string>& components, bool expand_home_dir = true); diff --git a/Source/cmQtAutoGeneratorMocUic.cxx b/Source/cmQtAutoGeneratorMocUic.cxx index b02cd44..cb6f7ea 100644 --- a/Source/cmQtAutoGeneratorMocUic.cxx +++ b/Source/cmQtAutoGeneratorMocUic.cxx @@ -27,7 +27,7 @@ std::string cmQtAutoGeneratorMocUic::BaseSettingsT::AbsoluteBuildPath( std::string const& relativePath) const { - return FileSys->CollapseCombinedPath(AutogenBuildDir, relativePath); + return FileSys->CollapseFullPath(relativePath, AutogenBuildDir); } /** diff --git a/Source/cmState.cxx b/Source/cmState.cxx index a08e9b8..fa7df0b 100644 --- a/Source/cmState.cxx +++ b/Source/cmState.cxx @@ -556,9 +556,28 @@ const char* cmState::GetGlobalProperty(const std::string& prop) if (prop == "CMAKE_C_KNOWN_FEATURES") { return &FOR_EACH_C_FEATURE(STRING_LIST_ELEMENT)[1]; } + if (prop == "CMAKE_C90_KNOWN_FEATURES") { + return &FOR_EACH_C90_FEATURE(STRING_LIST_ELEMENT)[1]; + } + if (prop == "CMAKE_C99_KNOWN_FEATURES") { + return &FOR_EACH_C99_FEATURE(STRING_LIST_ELEMENT)[1]; + } + if (prop == "CMAKE_C11_KNOWN_FEATURES") { + return &FOR_EACH_C11_FEATURE(STRING_LIST_ELEMENT)[1]; + } if (prop == "CMAKE_CXX_KNOWN_FEATURES") { return &FOR_EACH_CXX_FEATURE(STRING_LIST_ELEMENT)[1]; } + if (prop == "CMAKE_CXX98_KNOWN_FEATURES") { + return &FOR_EACH_CXX98_FEATURE(STRING_LIST_ELEMENT)[1]; + } + if (prop == "CMAKE_CXX11_KNOWN_FEATURES") { + return &FOR_EACH_CXX11_FEATURE(STRING_LIST_ELEMENT)[1]; + } + if (prop == "CMAKE_CXX14_KNOWN_FEATURES") { + return &FOR_EACH_CXX14_FEATURE(STRING_LIST_ELEMENT)[1]; + } + #undef STRING_LIST_ELEMENT return this->GlobalProperties.GetPropertyValue(prop); } diff --git a/Source/cmSystemTools.cxx b/Source/cmSystemTools.cxx index d762106..d201061 100644 --- a/Source/cmSystemTools.cxx +++ b/Source/cmSystemTools.cxx @@ -1510,36 +1510,6 @@ std::string cmSystemTools::ForceToRelativePath(std::string const& local_path, return relative; } -std::string cmSystemTools::CollapseCombinedPath(std::string const& dir, - std::string const& file) -{ - if (dir.empty() || dir == ".") { - return file; - } - - std::vector<std::string> dirComponents; - std::vector<std::string> fileComponents; - cmSystemTools::SplitPath(dir, dirComponents); - cmSystemTools::SplitPath(file, fileComponents); - - if (fileComponents.empty()) { - return dir; - } - if (!fileComponents[0].empty()) { - // File is not a relative path. - return file; - } - - std::vector<std::string>::iterator i = fileComponents.begin() + 1; - while (i != fileComponents.end() && *i == ".." && dirComponents.size() > 1) { - ++i; // Remove ".." file component. - dirComponents.pop_back(); // Remove last dir component. - } - - dirComponents.insert(dirComponents.end(), i, fileComponents.end()); - return cmSystemTools::JoinPath(dirComponents); -} - #ifdef CMAKE_BUILD_WITH_CMAKE bool cmSystemTools::UnsetEnv(const char* value) { @@ -1658,20 +1628,18 @@ bool cmSystemTools::CreateTar(const char* outFileName, a.SetMTime(mtime); a.SetVerbose(verbose); + bool tarCreatedSuccessfully = true; for (auto path : files) { if (cmSystemTools::FileIsFullPath(path)) { // Get the relative path to the file. path = cmSystemTools::RelativePath(cwd, path); } if (!a.Add(path)) { - break; + cmSystemTools::Error(a.GetError()); + tarCreatedSuccessfully = false; } } - if (!a) { - cmSystemTools::Error(a.GetError()); - return false; - } - return true; + return tarCreatedSuccessfully; #else (void)outFileName; (void)files; diff --git a/Source/cmSystemTools.h b/Source/cmSystemTools.h index 60e8c18..0b75025 100644 --- a/Source/cmSystemTools.h +++ b/Source/cmSystemTools.h @@ -374,12 +374,6 @@ public: static std::string ForceToRelativePath(std::string const& local_path, std::string const& remote_path); - /** Joins two paths while collapsing x/../ parts - * For example CollapseCombinedPath("a/b/c", "../../d") results in "a/d" - */ - static std::string CollapseCombinedPath(std::string const& dir, - std::string const& file); - #ifdef CMAKE_BUILD_WITH_CMAKE /** Remove an environment variable */ static bool UnsetEnv(const char* value); @@ -412,6 +406,14 @@ public: /** Setup the environment to enable VS 8 IDE output. */ static void EnableVSConsoleOutput(); + enum cmTarAction + { + TarActionCreate, + TarActionList, + TarActionExtract, + TarActionNone + }; + /** Create tar */ enum cmTarCompression { @@ -420,6 +422,7 @@ public: TarCompressXZ, TarCompressNone }; + static bool ListTar(const char* outFileName, bool verbose); static bool CreateTar(const char* outFileName, const std::vector<std::string>& files, diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx index 46f930a..c6a69be 100644 --- a/Source/cmTarget.cxx +++ b/Source/cmTarget.cxx @@ -32,6 +32,13 @@ #include "cmTargetPropertyComputer.h" #include "cmake.h" +///! Append all elements from the second container to the first container +template <class C, class R> +static inline void CApp(C& container, R const& range) +{ + container.insert(container.end(), range.begin(), range.end()); +} + template <> const char* cmTargetPropertyComputer::ComputeLocationForBuild<cmTarget>( cmTarget const* tgt) @@ -283,6 +290,7 @@ cmTarget::cmTarget(std::string const& name, cmStateEnums::TargetType type, this->SetPropertyDefault("FOLDER", nullptr); #ifdef __APPLE__ if (this->GetGlobalGenerator()->IsXcode()) { + this->SetPropertyDefault("XCODE_GENERATE_SCHEME", nullptr); this->SetPropertyDefault("XCODE_SCHEME_ADDRESS_SANITIZER", nullptr); this->SetPropertyDefault( "XCODE_SCHEME_ADDRESS_SANITIZER_USE_AFTER_RETURN", nullptr); @@ -308,10 +316,6 @@ cmTarget::cmTarget(std::string const& name, cmStateEnums::TargetType type, #endif } - // Collect the set of configuration types. - std::vector<std::string> configNames; - mf->GetConfigurations(configNames); - // Setup per-configuration property default values. if (this->GetType() != cmStateEnums::UTILITY) { static const auto configProps = { @@ -321,6 +325,9 @@ cmTarget::cmTarget(std::string const& name, cmStateEnums::TargetType type, "COMPILE_PDB_OUTPUT_DIRECTORY_", "MAP_IMPORTED_CONFIG_", "INTERPROCEDURAL_OPTIMIZATION_" }; + // Collect the set of configuration types. + std::vector<std::string> configNames; + mf->GetConfigurations(configNames); for (std::string const& configName : configNames) { std::string configUpper = cmSystemTools::UpperCase(configName); for (auto const& prop : configProps) { @@ -355,59 +362,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: - const cmStringRange parentIncludes = - this->Makefile->GetIncludeDirectoriesEntries(); - const cmBacktraceRange parentIncludesBts = - this->Makefile->GetIncludeDirectoriesBacktraces(); - - this->Internal->IncludeDirectoriesEntries.insert( - this->Internal->IncludeDirectoriesEntries.end(), parentIncludes.begin(), - parentIncludes.end()); - this->Internal->IncludeDirectoriesBacktraces.insert( - this->Internal->IncludeDirectoriesBacktraces.end(), - parentIncludesBts.begin(), parentIncludesBts.end()); - - const std::set<std::string> parentSystemIncludes = - this->Makefile->GetSystemIncludeDirectories(); - - this->SystemIncludeDirectories.insert(parentSystemIncludes.begin(), - parentSystemIncludes.end()); - - const cmStringRange parentCompileOptions = - this->Makefile->GetCompileOptionsEntries(); - const cmBacktraceRange parentCompileOptionsBts = - this->Makefile->GetCompileOptionsBacktraces(); - - this->Internal->CompileOptionsEntries.insert( - this->Internal->CompileOptionsEntries.end(), - parentCompileOptions.begin(), parentCompileOptions.end()); - this->Internal->CompileOptionsBacktraces.insert( - this->Internal->CompileOptionsBacktraces.end(), - parentCompileOptionsBts.begin(), parentCompileOptionsBts.end()); - - const cmStringRange parentLinkOptions = - this->Makefile->GetLinkOptionsEntries(); - const cmBacktraceRange parentLinkOptionsBts = - this->Makefile->GetLinkOptionsBacktraces(); - - this->Internal->LinkOptionsEntries.insert( - this->Internal->LinkOptionsEntries.end(), parentLinkOptions.begin(), - parentLinkOptions.end()); - this->Internal->LinkOptionsBacktraces.insert( - this->Internal->LinkOptionsBacktraces.end(), - parentLinkOptionsBts.begin(), parentLinkOptionsBts.end()); - - const cmStringRange parentLinkDirectories = - this->Makefile->GetLinkDirectoriesEntries(); - const cmBacktraceRange parentLinkDirectoriesBts = - this->Makefile->GetLinkDirectoriesBacktraces(); - - this->Internal->LinkDirectoriesEntries.insert( - this->Internal->LinkDirectoriesEntries.end(), - parentLinkDirectories.begin(), parentLinkDirectories.end()); - this->Internal->LinkDirectoriesBacktraces.insert( - this->Internal->LinkDirectoriesBacktraces.end(), - parentLinkDirectoriesBts.begin(), parentLinkDirectoriesBts.end()); + CApp(this->Internal->IncludeDirectoriesEntries, + this->Makefile->GetIncludeDirectoriesEntries()); + CApp(this->Internal->IncludeDirectoriesBacktraces, + this->Makefile->GetIncludeDirectoriesBacktraces()); + + { + auto const& sysInc = this->Makefile->GetSystemIncludeDirectories(); + this->SystemIncludeDirectories.insert(sysInc.begin(), sysInc.end()); + } + + CApp(this->Internal->CompileOptionsEntries, + this->Makefile->GetCompileOptionsEntries()); + CApp(this->Internal->CompileOptionsBacktraces, + this->Makefile->GetCompileOptionsBacktraces()); + + CApp(this->Internal->LinkOptionsEntries, + this->Makefile->GetLinkOptionsEntries()); + CApp(this->Internal->LinkOptionsBacktraces, + this->Makefile->GetLinkOptionsBacktraces()); + + CApp(this->Internal->LinkDirectoriesEntries, + this->Makefile->GetLinkDirectoriesEntries()); + CApp(this->Internal->LinkDirectoriesBacktraces, + this->Makefile->GetLinkDirectoriesBacktraces()); } if (this->GetType() != cmStateEnums::INTERFACE_LIBRARY && diff --git a/Source/cm_utf8.c b/Source/cm_utf8.c index 52af4a6..62e7e8c 100644 --- a/Source/cm_utf8.c +++ b/Source/cm_utf8.c @@ -2,6 +2,8 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cm_utf8.h" +#include <string.h> + /* RFC 3629 07-bit: 0xxxxxxx @@ -71,7 +73,34 @@ const char* cm_utf8_decode_character(const char* first, const char* last, return 0; } + /* UTF-16 surrogate halves. */ + if (0xD800 <= uc && uc <= 0xDFFF) { + return 0; + } + + /* Invalid codepoints. */ + if (0x10FFFF < uc) { + return 0; + } + *pc = uc; return first; } } + +int cm_utf8_is_valid(const char* s) +{ + if (!s) { + return 0; + } + + const char* last = s + strlen(s); + const char* pos = s; + unsigned int pc; + + while (pos != last && (pos = cm_utf8_decode_character(pos, last, &pc))) { + /* Nothing to do. */ + } + + return pos == last; +} diff --git a/Source/cm_utf8.h b/Source/cm_utf8.h index fcb43e0..27dc559 100644 --- a/Source/cm_utf8.h +++ b/Source/cm_utf8.h @@ -13,6 +13,10 @@ extern "C" { const char* cm_utf8_decode_character(const char* first, const char* last, unsigned int* pc); +/** Returns whether a C string is a sequence of valid UTF-8 encoded Unicode + codepoints. Returns non-zero on success. */ +int cm_utf8_is_valid(const char* s); + #ifdef __cplusplus } /* extern "C" */ #endif diff --git a/Source/cmake.cxx b/Source/cmake.cxx index 69dc26b..8c1a359 100644 --- a/Source/cmake.cxx +++ b/Source/cmake.cxx @@ -9,7 +9,7 @@ #include "cmDocumentationFormatter.h" #include "cmDuration.h" #include "cmExternalMakefileProjectGenerator.h" -#include "cmFileTimeComparison.h" +#include "cmFileTimeCache.h" #include "cmGeneratorTarget.h" #include "cmGlobalGenerator.h" #include "cmGlobalGeneratorFactory.h" @@ -141,7 +141,7 @@ cmake::cmake(Role role, cmState::Mode mode) this->DebugOutput = false; this->DebugTryCompile = false; this->ClearBuildSystem = false; - this->FileComparison = new cmFileTimeComparison; + this->FileTimeCache = new cmFileTimeCache; this->State = new cmState; this->State->SetMode(mode); @@ -225,7 +225,7 @@ cmake::~cmake() #ifdef CMAKE_BUILD_WITH_CMAKE delete this->VariableWatch; #endif - delete this->FileComparison; + delete this->FileTimeCache; } #if defined(CMAKE_BUILD_WITH_CMAKE) @@ -2144,7 +2144,7 @@ int cmake::CheckBuildSystem() std::string dep_newest = *dep++; for (; dep != depends.end(); ++dep) { int result = 0; - if (this->FileComparison->FileTimeCompare(dep_newest, *dep, &result)) { + if (this->FileTimeCache->Compare(dep_newest, *dep, &result)) { if (result < 0) { dep_newest = *dep; } @@ -2163,7 +2163,7 @@ int cmake::CheckBuildSystem() std::string out_oldest = *out++; for (; out != outputs.end(); ++out) { int result = 0; - if (this->FileComparison->FileTimeCompare(out_oldest, *out, &result)) { + if (this->FileTimeCache->Compare(out_oldest, *out, &result)) { if (result > 0) { out_oldest = *out; } @@ -2180,8 +2180,7 @@ int cmake::CheckBuildSystem() // If any output is older than any dependency then rerun. { int result = 0; - if (!this->FileComparison->FileTimeCompare(out_oldest, dep_newest, - &result) || + if (!this->FileTimeCache->Compare(out_oldest, dep_newest, &result) || result < 0) { if (verbose) { std::ostringstream msg; @@ -2436,20 +2435,22 @@ static bool cmakeCheckStampFile(const std::string& stampName) } // Compare the stamp dependencies against the dependency file itself. - cmFileTimeComparison ftc; - std::string dep; - while (cmSystemTools::GetLineFromStream(fin, dep)) { - int result; - if (!dep.empty() && dep[0] != '#' && - (!ftc.FileTimeCompare(stampDepends, dep, &result) || result < 0)) { - // The stamp depends file is older than this dependency. The - // build system is really out of date. - std::cout << "CMake is re-running because " << stampName - << " is out-of-date.\n"; - std::cout << " the file '" << dep << "'\n"; - std::cout << " is newer than '" << stampDepends << "'\n"; - std::cout << " result='" << result << "'\n"; - return false; + { + cmFileTimeCache ftc; + std::string dep; + while (cmSystemTools::GetLineFromStream(fin, dep)) { + int result; + if (!dep.empty() && dep[0] != '#' && + (!ftc.Compare(stampDepends, dep, &result) || result < 0)) { + // The stamp depends file is older than this dependency. The + // build system is really out of date. + std::cout << "CMake is re-running because " << stampName + << " is out-of-date.\n"; + std::cout << " the file '" << dep << "'\n"; + std::cout << " is newer than '" << stampDepends << "'\n"; + std::cout << " result='" << result << "'\n"; + return false; + } } } diff --git a/Source/cmake.h b/Source/cmake.h index 1ffeabc..8d22f34 100644 --- a/Source/cmake.h +++ b/Source/cmake.h @@ -26,7 +26,7 @@ class cmExternalMakefileProjectGeneratorFactory; class cmFileAPI; -class cmFileTimeComparison; +class cmFileTimeCache; class cmGlobalGenerator; class cmGlobalGeneratorFactory; class cmMakefile; @@ -329,7 +329,7 @@ public: /** * Get the file comparison class */ - cmFileTimeComparison* GetFileComparison() { return this->FileComparison; } + cmFileTimeCache* GetFileTimeCache() { return this->FileTimeCache; } // Do we want debug output during the cmake run. bool GetDebugOutput() { return this->DebugOutput; } @@ -509,7 +509,7 @@ private: std::unordered_set<std::string> HeaderFileExtensionsSet; bool ClearBuildSystem; bool DebugTryCompile; - cmFileTimeComparison* FileComparison; + cmFileTimeCache* FileTimeCache; std::string GraphVizFile; InstalledFilesMap InstalledFiles; @@ -562,40 +562,38 @@ private: "not errors." \ } +#define FOR_EACH_C90_FEATURE(F) F(c_function_prototypes) + +#define FOR_EACH_C99_FEATURE(F) \ + F(c_restrict) \ + F(c_variadic_macros) + +#define FOR_EACH_C11_FEATURE(F) F(c_static_assert) + #define FOR_EACH_C_FEATURE(F) \ F(c_std_90) \ F(c_std_99) \ F(c_std_11) \ - F(c_function_prototypes) \ - F(c_restrict) \ - F(c_static_assert) \ - F(c_variadic_macros) + FOR_EACH_C90_FEATURE(F) \ + FOR_EACH_C99_FEATURE(F) \ + FOR_EACH_C11_FEATURE(F) -#define FOR_EACH_CXX_FEATURE(F) \ - F(cxx_std_98) \ - F(cxx_std_11) \ - F(cxx_std_14) \ - F(cxx_std_17) \ - F(cxx_std_20) \ - F(cxx_aggregate_default_initializers) \ +#define FOR_EACH_CXX98_FEATURE(F) F(cxx_template_template_parameters) + +#define FOR_EACH_CXX11_FEATURE(F) \ F(cxx_alias_templates) \ F(cxx_alignas) \ F(cxx_alignof) \ F(cxx_attributes) \ - F(cxx_attribute_deprecated) \ F(cxx_auto_type) \ - F(cxx_binary_literals) \ F(cxx_constexpr) \ - F(cxx_contextual_conversions) \ F(cxx_decltype) \ - F(cxx_decltype_auto) \ F(cxx_decltype_incomplete_return_types) \ F(cxx_default_function_template_args) \ F(cxx_defaulted_functions) \ F(cxx_defaulted_move_initializers) \ F(cxx_delegating_constructors) \ F(cxx_deleted_functions) \ - F(cxx_digit_separators) \ F(cxx_enum_forward_declarations) \ F(cxx_explicit_conversions) \ F(cxx_extended_friend_declarations) \ @@ -603,11 +601,9 @@ private: F(cxx_final) \ F(cxx_func_identifier) \ F(cxx_generalized_initializers) \ - F(cxx_generic_lambdas) \ F(cxx_inheriting_constructors) \ F(cxx_inline_namespaces) \ F(cxx_lambdas) \ - F(cxx_lambda_init_captures) \ F(cxx_local_type_template_args) \ F(cxx_long_long_type) \ F(cxx_noexcept) \ @@ -617,22 +613,41 @@ private: F(cxx_range_for) \ F(cxx_raw_string_literals) \ F(cxx_reference_qualified_functions) \ - F(cxx_relaxed_constexpr) \ - F(cxx_return_type_deduction) \ F(cxx_right_angle_brackets) \ F(cxx_rvalue_references) \ F(cxx_sizeof_member) \ F(cxx_static_assert) \ F(cxx_strong_enums) \ - F(cxx_template_template_parameters) \ F(cxx_thread_local) \ F(cxx_trailing_return_types) \ F(cxx_unicode_literals) \ F(cxx_uniform_initialization) \ F(cxx_unrestricted_unions) \ F(cxx_user_literals) \ - F(cxx_variable_templates) \ F(cxx_variadic_macros) \ F(cxx_variadic_templates) +#define FOR_EACH_CXX14_FEATURE(F) \ + F(cxx_aggregate_default_initializers) \ + F(cxx_attribute_deprecated) \ + F(cxx_binary_literals) \ + F(cxx_contextual_conversions) \ + F(cxx_decltype_auto) \ + F(cxx_digit_separators) \ + F(cxx_generic_lambdas) \ + F(cxx_lambda_init_captures) \ + F(cxx_relaxed_constexpr) \ + F(cxx_return_type_deduction) \ + F(cxx_variable_templates) + +#define FOR_EACH_CXX_FEATURE(F) \ + F(cxx_std_98) \ + F(cxx_std_11) \ + F(cxx_std_14) \ + F(cxx_std_17) \ + F(cxx_std_20) \ + FOR_EACH_CXX98_FEATURE(F) \ + FOR_EACH_CXX11_FEATURE(F) \ + FOR_EACH_CXX14_FEATURE(F) + #endif diff --git a/Source/cmakemain.cxx b/Source/cmakemain.cxx index b83c744..d70c9d9 100644 --- a/Source/cmakemain.cxx +++ b/Source/cmakemain.cxx @@ -23,6 +23,7 @@ # include "cmsys/ConsoleBuf.hxx" #endif +#include <cassert> #include <ctype.h> #include <iostream> #include <string.h> @@ -72,11 +73,20 @@ static const char* cmDocumentationUsageNote[][2] = { " the build commands to be executed. \n" \ " -- = Pass remaining options to the native tool.\n" +# define CMAKE_INSTALL_OPTIONS \ + " <dir> = Project binary directory to install.\n" \ + " --config <cfg> = For multi-configuration tools, choose <cfg>.\n" \ + " --component <comp> = Component-based install. Only install <comp>.\n" \ + " --prefix <prefix> = The installation prefix CMAKE_INSTALL_PREFIX.\n" \ + " --strip = Performing install/strip.\n" \ + " -v --verbose = Enable verbose output.\n" + static const char* cmDocumentationOptions[][2] = { CMAKE_STANDARD_OPTIONS_TABLE, { "-E", "CMake command mode." }, { "-L[A][H]", "List non-advanced cached variables." }, { "--build <dir>", "Build a CMake-generated project binary tree." }, + { "--install <dir>", "Install a CMake-generated project binary tree." }, { "--open <dir>", "Open generated project in the associated application." }, { "-N", "View mode only." }, { "-P <file>", "Process script mode." }, @@ -115,6 +125,7 @@ static int do_command(int ac, char const* const* av) int do_cmake(int ac, char const* const* av); static int do_build(int ac, char const* const* av); +static int do_install(int ac, char const* const* av); static int do_open(int ac, char const* const* av); static cmMakefile* cmakemainGetMakefile(cmake* cm) @@ -189,6 +200,9 @@ int main(int ac, char const* const* av) if (strcmp(av[1], "--build") == 0) { return do_build(ac, av); } + if (strcmp(av[1], "--install") == 0) { + return do_install(ac, av); + } if (strcmp(av[1], "--open") == 0) { return do_open(ac, av); } @@ -525,6 +539,117 @@ static int do_build(int ac, char const* const* av) #endif } +static int do_install(int ac, char const* const* av) +{ +#ifndef CMAKE_BUILD_WITH_CMAKE + std::cerr << "This cmake does not support --install\n"; + return -1; +#else + assert(1 < ac); + + std::string config; + std::string component; + std::string prefix; + std::string dir; + bool strip = false; + bool verbose = cmSystemTools::HasEnv("VERBOSE"); + + enum Doing + { + DoingNone, + DoingDir, + DoingConfig, + DoingComponent, + DoingPrefix, + }; + + Doing doing = DoingDir; + + for (int i = 2; i < ac; ++i) { + if (strcmp(av[i], "--config") == 0) { + doing = DoingConfig; + } else if (strcmp(av[i], "--component") == 0) { + doing = DoingComponent; + } else if (strcmp(av[i], "--prefix") == 0) { + doing = DoingPrefix; + } else if (strcmp(av[i], "--strip") == 0) { + strip = true; + doing = DoingNone; + } else if ((strcmp(av[i], "--verbose") == 0) || + (strcmp(av[i], "-v") == 0)) { + verbose = true; + doing = DoingNone; + } else { + switch (doing) { + case DoingDir: + dir = cmSystemTools::CollapseFullPath(av[i]); + doing = DoingNone; + break; + case DoingConfig: + config = av[i]; + doing = DoingNone; + break; + case DoingComponent: + component = av[i]; + doing = DoingNone; + break; + case DoingPrefix: + prefix = av[i]; + doing = DoingNone; + break; + default: + std::cerr << "Unknown argument " << av[i] << std::endl; + dir.clear(); + break; + } + } + } + + if (dir.empty()) { + std::cerr << "Usage: cmake --install <dir> " + "[options]\nOptions:\n" CMAKE_INSTALL_OPTIONS; + return 1; + } + + cmake cm(cmake::RoleScript, cmState::Script); + + cmSystemTools::SetMessageCallback( + [&cm](const std::string& msg, const char* title) { + cmakemainMessageCallback(msg, title, &cm); + }); + cm.SetProgressCallback([&cm](const std::string& msg, float prog) { + cmakemainProgressCallback(msg, prog, &cm); + }); + cm.SetHomeDirectory(""); + cm.SetHomeOutputDirectory(""); + cm.SetDebugOutputOn(verbose); + cm.SetWorkingMode(cmake::SCRIPT_MODE); + + std::vector<std::string> args{ av[0] }; + + if (!prefix.empty()) { + args.emplace_back("-DCMAKE_INSTALL_PREFIX=" + prefix); + } + + if (!component.empty()) { + args.emplace_back("-DCMAKE_INSTALL_COMPONENT=" + component); + } + + if (strip) { + args.emplace_back("-DCMAKE_INSTALL_DO_STRIP=1"); + } + + if (!config.empty()) { + args.emplace_back("-DCMAKE_INSTALL_CONFIG_NAME=" + config); + } + + args.emplace_back("-P"); + args.emplace_back(dir + "/cmake_install.cmake"); + + return cm.Run(args) ? 1 : 0; +#endif +} + static int do_open(int ac, char const* const* av) { #ifndef CMAKE_BUILD_WITH_CMAKE diff --git a/Source/cmcmd.cxx b/Source/cmcmd.cxx index f996a3e..8d63971 100644 --- a/Source/cmcmd.cxx +++ b/Source/cmcmd.cxx @@ -1078,21 +1078,47 @@ int cmcmd::ExecuteCMakeCommand(std::vector<std::string>& args) files.push_back(arg); } } + cmSystemTools::cmTarAction action = cmSystemTools::TarActionNone; cmSystemTools::cmTarCompression compress = cmSystemTools::TarCompressNone; bool verbose = false; int nCompress = 0; - if (flags.find_first_of('j') != std::string::npos) { - compress = cmSystemTools::TarCompressBZip2; - ++nCompress; - } - if (flags.find_first_of('J') != std::string::npos) { - compress = cmSystemTools::TarCompressXZ; - ++nCompress; - } - if (flags.find_first_of('z') != std::string::npos) { - compress = cmSystemTools::TarCompressGZip; - ++nCompress; + + for (auto flag : flags) { + switch (flag) { + case '-': + case 'f': { + // Keep for backward compatibility. Ignored + } break; + case 'j': { + compress = cmSystemTools::TarCompressBZip2; + ++nCompress; + } break; + case 'J': { + compress = cmSystemTools::TarCompressXZ; + ++nCompress; + } break; + case 'z': { + compress = cmSystemTools::TarCompressGZip; + ++nCompress; + } break; + case 'v': { + verbose = true; + } break; + case 't': { + action = cmSystemTools::TarActionList; + } break; + case 'c': { + action = cmSystemTools::TarActionCreate; + } break; + case 'x': { + action = cmSystemTools::TarActionExtract; + } break; + default: { + cmSystemTools::Message( + std::string("tar: Unknown argument: ") + flag, "Warning"); + } + } } if ((format == "7zip" || format == "zip") && nCompress > 0) { cmSystemTools::Error("Can not use compression flags with format: " + @@ -1104,22 +1130,22 @@ int cmcmd::ExecuteCMakeCommand(std::vector<std::string>& args) "at most one flag of z, j, or J may be used"); return 1; } - if (flags.find_first_of('v') != std::string::npos) { - verbose = true; - } - - if (flags.find_first_of('t') != std::string::npos) { + if (action == cmSystemTools::TarActionList) { if (!cmSystemTools::ListTar(outFile.c_str(), verbose)) { cmSystemTools::Error("Problem listing tar: " + outFile); return 1; } - } else if (flags.find_first_of('c') != std::string::npos) { + } else if (action == cmSystemTools::TarActionCreate) { + if (files.empty()) { + cmSystemTools::Message("tar: No files or directories specified", + "Warning"); + } if (!cmSystemTools::CreateTar(outFile.c_str(), files, compress, verbose, mtime, format)) { cmSystemTools::Error("Problem creating tar: " + outFile); return 1; } - } else if (flags.find_first_of('x') != std::string::npos) { + } else if (action == cmSystemTools::TarActionExtract) { if (!cmSystemTools::ExtractTar(outFile.c_str(), verbose)) { cmSystemTools::Error("Problem extracting tar: " + outFile); return 1; @@ -1140,6 +1166,10 @@ int cmcmd::ExecuteCMakeCommand(std::vector<std::string>& args) cmSystemTools::Delay(delay); } #endif + } else { + cmSystemTools::Error("tar: No action specified. Please choose: 't' " + "(list), 'c' (create) or 'x' (extract)"); + return 1; } return 0; } diff --git a/Source/ctest.cxx b/Source/ctest.cxx index 4a2531a..461021b 100644 --- a/Source/ctest.cxx +++ b/Source/ctest.cxx @@ -191,8 +191,7 @@ int main(int argc, char const* const* argv) doc.addCTestStandardDocSections(); if (doc.CheckOptions(argc, argv)) { // Construct and print requested documentation. - cmCTestScriptHandler* ch = - static_cast<cmCTestScriptHandler*>(inst.GetHandler("script")); + cmCTestScriptHandler* ch = inst.GetScriptHandler(); ch->CreateCMake(); doc.SetShowGenerators(false); diff --git a/Source/kwsys/SystemTools.cxx b/Source/kwsys/SystemTools.cxx index 33a92e4..b736ed4 100644 --- a/Source/kwsys/SystemTools.cxx +++ b/Source/kwsys/SystemTools.cxx @@ -28,6 +28,7 @@ #include <iostream> #include <set> #include <sstream> +#include <utility> #include <vector> // Work-around CMake dependency scanning limitation. This must @@ -363,10 +364,6 @@ double SystemTools::GetTime(void) #endif } -class SystemToolsTranslationMap : public std::map<std::string, std::string> -{ -}; - /* Type of character storing the environment. */ #if defined(_WIN32) typedef wchar_t envchar; @@ -447,15 +444,139 @@ struct SystemToolsPathCaseCmp # endif } }; +#endif -class SystemToolsPathCaseMap - : public std::map<std::string, std::string, SystemToolsPathCaseCmp> +/** + * SystemTools static variables singleton class. + */ +class SystemToolsStatic { +public: + typedef std::map<std::string, std::string> StringMap; + /** + * Path translation table from dir to refdir + * Each time 'dir' will be found it will be replace by 'refdir' + */ + StringMap TranslationMap; +#ifdef _WIN32 + static std::string GetCasePathName(std::string const& pathIn); + static std::string GetActualCaseForPathCached(std::string const& path); + static const char* GetEnvBuffered(const char* key); + std::map<std::string, std::string, SystemToolsPathCaseCmp> PathCaseMap; + std::map<std::string, std::string> EnvMap; +#endif +#ifdef __CYGWIN__ + StringMap Cyg2Win32Map; +#endif + + /** + * Actual implementation of ReplaceString. + */ + static void ReplaceString(std::string& source, const char* replace, + size_t replaceSize, const std::string& with); + + /** + * Actual implementation of FileIsFullPath. + */ + static bool FileIsFullPath(const char*, size_t); + + /** + * Find a filename (file or directory) in the system PATH, with + * optional extra paths. + */ + static std::string FindName( + const std::string& name, + const std::vector<std::string>& path = std::vector<std::string>(), + bool no_system_path = false); }; -class SystemToolsEnvMap : public std::map<std::string, std::string> +#ifdef _WIN32 +std::string SystemToolsStatic::GetCasePathName(std::string const& pathIn) { -}; + std::string casePath; + + // First check if the file is relative. We don't fix relative paths since the + // real case depends on the root directory and the given path fragment may + // have meaning elsewhere in the project. + if (!SystemTools::FileIsFullPath(pathIn)) { + // This looks unnecessary, but it allows for the return value optimization + // since all return paths return the same local variable. + casePath = pathIn; + return casePath; + } + + std::vector<std::string> path_components; + SystemTools::SplitPath(pathIn, path_components); + + // Start with root component. + std::vector<std::string>::size_type idx = 0; + casePath = path_components[idx++]; + // make sure drive letter is always upper case + if (casePath.size() > 1 && casePath[1] == ':') { + casePath[0] = toupper(casePath[0]); + } + const char* sep = ""; + + // If network path, fill casePath with server/share so FindFirstFile + // will work after that. Maybe someday call other APIs to get + // actual case of servers and shares. + if (path_components.size() > 2 && path_components[0] == "//") { + casePath += path_components[idx++]; + casePath += "/"; + casePath += path_components[idx++]; + sep = "/"; + } + + // Convert case of all components that exist. + bool converting = true; + for (; idx < path_components.size(); idx++) { + casePath += sep; + sep = "/"; + + if (converting) { + // If path component contains wildcards, we skip matching + // because these filenames are not allowed on windows, + // and we do not want to match a different file. + if (path_components[idx].find('*') != std::string::npos || + path_components[idx].find('?') != std::string::npos) { + converting = false; + } else { + std::string test_str = casePath; + test_str += path_components[idx]; + WIN32_FIND_DATAW findData; + HANDLE hFind = + ::FindFirstFileW(Encoding::ToWide(test_str).c_str(), &findData); + if (INVALID_HANDLE_VALUE != hFind) { + path_components[idx] = Encoding::ToNarrow(findData.cFileName); + ::FindClose(hFind); + } else { + converting = false; + } + } + } + + casePath += path_components[idx]; + } + return casePath; +} + +std::string SystemToolsStatic::GetActualCaseForPathCached(std::string const& p) +{ + // Check to see if actual case has already been called + // for this path, and the result is stored in the PathCaseMap + auto& pcm = SystemTools::Statics->PathCaseMap; + { + auto itr = pcm.find(p); + if (itr != pcm.end()) { + return itr->second; + } + } + std::string casePath = SystemToolsStatic::GetCasePathName(p); + if (casePath.size() <= MAX_PATH) { + pcm[p] = casePath; + } + return casePath; +} #endif // adds the elements of the env variable path to the arg passed in @@ -496,30 +617,35 @@ void SystemTools::GetPath(std::vector<std::string>& path, const char* env) } } -const char* SystemTools::GetEnvImpl(const char* key) -{ - const char* v = KWSYS_NULLPTR; #if defined(_WIN32) +const char* SystemToolsStatic::GetEnvBuffered(const char* key) +{ std::string env; if (SystemTools::GetEnv(key, env)) { - std::string& menv = (*SystemTools::EnvMap)[key]; - menv = env; - v = menv.c_str(); + std::string& menv = SystemTools::Statics->EnvMap[key]; + menv = std::move(env); + return menv.c_str(); } -#else - v = getenv(key); -#endif - return v; + return KWSYS_NULLPTR; } +#endif const char* SystemTools::GetEnv(const char* key) { - return SystemTools::GetEnvImpl(key); +#if defined(_WIN32) + return SystemToolsStatic::GetEnvBuffered(key); +#else + return getenv(key); +#endif } const char* SystemTools::GetEnv(const std::string& key) { - return SystemTools::GetEnvImpl(key.c_str()); +#if defined(_WIN32) + return SystemToolsStatic::GetEnvBuffered(key.c_str()); +#else + return getenv(key.c_str()); +#endif } bool SystemTools::GetEnv(const char* key, std::string& result) @@ -822,7 +948,8 @@ void SystemTools::ReplaceString(std::string& source, return; } - SystemTools::ReplaceString(source, replace.c_str(), replace.size(), with); + SystemToolsStatic::ReplaceString(source, replace.c_str(), replace.size(), + with); } void SystemTools::ReplaceString(std::string& source, const char* replace, @@ -833,12 +960,13 @@ void SystemTools::ReplaceString(std::string& source, const char* replace, return; } - SystemTools::ReplaceString(source, replace, strlen(replace), - with ? with : ""); + SystemToolsStatic::ReplaceString(source, replace, strlen(replace), + with ? with : ""); } -void SystemTools::ReplaceString(std::string& source, const char* replace, - size_t replaceSize, const std::string& with) +void SystemToolsStatic::ReplaceString(std::string& source, const char* replace, + size_t replaceSize, + const std::string& with) { const char* src = source.c_str(); char* searchPos = const_cast<char*>(strstr(src, replace)); @@ -1316,18 +1444,16 @@ int SystemTools::Stat(const std::string& path, SystemTools::Stat_t* buf) #ifdef __CYGWIN__ bool SystemTools::PathCygwinToWin32(const char* path, char* win32_path) { - SystemToolsTranslationMap::iterator i = - SystemTools::Cyg2Win32Map->find(path); - - if (i != SystemTools::Cyg2Win32Map->end()) { - strncpy(win32_path, i->second.c_str(), MAX_PATH); + auto itr = SystemTools::Statics->Cyg2Win32Map.find(path); + if (itr != SystemTools::Statics->Cyg2Win32Map.end()) { + strncpy(win32_path, itr->second.c_str(), MAX_PATH); } else { if (cygwin_conv_path(CCP_POSIX_TO_WIN_A, path, win32_path, MAX_PATH) != 0) { win32_path[0] = 0; } - SystemToolsTranslationMap::value_type entry(path, win32_path); - SystemTools::Cyg2Win32Map->insert(entry); + SystemTools::Statics->Cyg2Win32Map.insert( + SystemToolsStatic::StringMap::value_type(path, win32_path)); } return win32_path[0] != 0; } @@ -2673,9 +2799,9 @@ size_t SystemTools::GetMaximumFilePathLength() * the system search path. Returns the full path to the file if it is * found. Otherwise, the empty string is returned. */ -std::string SystemTools::FindName(const std::string& name, - const std::vector<std::string>& userPaths, - bool no_system_path) +std::string SystemToolsStatic::FindName( + const std::string& name, const std::vector<std::string>& userPaths, + bool no_system_path) { // Add the system search path to our path first std::vector<std::string> path; @@ -2723,7 +2849,8 @@ std::string SystemTools::FindFile(const std::string& name, const std::vector<std::string>& userPaths, bool no_system_path) { - std::string tryPath = SystemTools::FindName(name, userPaths, no_system_path); + std::string tryPath = + SystemToolsStatic::FindName(name, userPaths, no_system_path); if (!tryPath.empty() && !SystemTools::FileIsDirectory(tryPath)) { return SystemTools::CollapseFullPath(tryPath); } @@ -2740,7 +2867,8 @@ std::string SystemTools::FindDirectory( const std::string& name, const std::vector<std::string>& userPaths, bool no_system_path) { - std::string tryPath = SystemTools::FindName(name, userPaths, no_system_path); + std::string tryPath = + SystemToolsStatic::FindName(name, userPaths, no_system_path); if (!tryPath.empty() && SystemTools::FileIsDirectory(tryPath)) { return SystemTools::CollapseFullPath(tryPath); } @@ -3244,8 +3372,9 @@ void SystemTools::AddTranslationPath(const std::string& a, path_b += '/'; } if (!(path_a == path_b)) { - SystemTools::TranslationMap->insert( - SystemToolsTranslationMap::value_type(path_a, path_b)); + SystemTools::Statics->TranslationMap.insert( + SystemToolsStatic::StringMap::value_type(std::move(path_a), + std::move(path_b))); } } } @@ -3269,21 +3398,19 @@ void SystemTools::CheckTranslationPath(std::string& path) // Always add a trailing slash before translation. It does not // matter if this adds an extra slash, but we do not want to // translate part of a directory (like the foo part of foo-dir). - path += "/"; + path += '/'; // In case a file was specified we still have to go through this: // Now convert any path found in the table back to the one desired: - std::map<std::string, std::string>::const_iterator it; - for (it = SystemTools::TranslationMap->begin(); - it != SystemTools::TranslationMap->end(); ++it) { + for (auto const& pair : SystemTools::Statics->TranslationMap) { // We need to check of the path is a substring of the other path - if (path.find(it->first) == 0) { - path = path.replace(0, it->first.size(), it->second); + if (path.find(pair.first) == 0) { + path = path.replace(0, pair.first.size(), pair.second); } } // Remove the trailing slash we added before. - path.erase(path.end() - 1, path.end()); + path.pop_back(); } static void SystemToolsAppendComponents( @@ -3371,7 +3498,7 @@ std::string SystemTools::CollapseFullPath(const std::string& in_path, SystemTools::CheckTranslationPath(newPath); #ifdef _WIN32 - newPath = SystemTools::GetActualCaseForPathCached(newPath); + newPath = SystemTools::Statics->GetActualCaseForPathCached(newPath); SystemTools::ConvertToUnixSlashes(newPath); #endif // Return the reconstructed path. @@ -3457,104 +3584,15 @@ std::string SystemTools::RelativePath(const std::string& local, return relativePath; } -#ifdef _WIN32 -static std::string GetCasePathName(std::string const& pathIn) -{ - std::string casePath; - - // First check if the file is relative. We don't fix relative paths since the - // real case depends on the root directory and the given path fragment may - // have meaning elsewhere in the project. - if (!SystemTools::FileIsFullPath(pathIn)) { - // This looks unnecessary, but it allows for the return value optimization - // since all return paths return the same local variable. - casePath = pathIn; - return casePath; - } - - std::vector<std::string> path_components; - SystemTools::SplitPath(pathIn, path_components); - - // Start with root component. - std::vector<std::string>::size_type idx = 0; - casePath = path_components[idx++]; - // make sure drive letter is always upper case - if (casePath.size() > 1 && casePath[1] == ':') { - casePath[0] = toupper(casePath[0]); - } - const char* sep = ""; - - // If network path, fill casePath with server/share so FindFirstFile - // will work after that. Maybe someday call other APIs to get - // actual case of servers and shares. - if (path_components.size() > 2 && path_components[0] == "//") { - casePath += path_components[idx++]; - casePath += "/"; - casePath += path_components[idx++]; - sep = "/"; - } - - // Convert case of all components that exist. - bool converting = true; - for (; idx < path_components.size(); idx++) { - casePath += sep; - sep = "/"; - - if (converting) { - // If path component contains wildcards, we skip matching - // because these filenames are not allowed on windows, - // and we do not want to match a different file. - if (path_components[idx].find('*') != std::string::npos || - path_components[idx].find('?') != std::string::npos) { - converting = false; - } else { - std::string test_str = casePath; - test_str += path_components[idx]; - WIN32_FIND_DATAW findData; - HANDLE hFind = - ::FindFirstFileW(Encoding::ToWide(test_str).c_str(), &findData); - if (INVALID_HANDLE_VALUE != hFind) { - path_components[idx] = Encoding::ToNarrow(findData.cFileName); - ::FindClose(hFind); - } else { - converting = false; - } - } - } - - casePath += path_components[idx]; - } - return casePath; -} -#endif - std::string SystemTools::GetActualCaseForPath(const std::string& p) { -#ifndef _WIN32 - return p; +#ifdef _WIN32 + return SystemToolsStatic::GetCasePathName(p); #else - return GetCasePathName(p); + return p; #endif } -#ifdef _WIN32 -std::string SystemTools::GetActualCaseForPathCached(std::string const& p) -{ - // Check to see if actual case has already been called - // for this path, and the result is stored in the PathCaseMap - SystemToolsPathCaseMap::iterator i = SystemTools::PathCaseMap->find(p); - if (i != SystemTools::PathCaseMap->end()) { - return i->second; - } - std::string casePath = GetCasePathName(p); - if (casePath.size() > MAX_PATH) { - return casePath; - } - (*SystemTools::PathCaseMap)[p] = casePath; - return casePath; -} -#endif - const char* SystemTools::SplitPathRootComponent(const std::string& p, std::string* root) { @@ -4047,16 +4085,16 @@ bool SystemTools::LocateFileInDir(const char* filename, const char* dir, bool SystemTools::FileIsFullPath(const std::string& in_name) { - return SystemTools::FileIsFullPath(in_name.c_str(), in_name.size()); + return SystemToolsStatic::FileIsFullPath(in_name.c_str(), in_name.size()); } bool SystemTools::FileIsFullPath(const char* in_name) { - return SystemTools::FileIsFullPath(in_name, - in_name[0] ? (in_name[1] ? 2 : 1) : 0); + return SystemToolsStatic::FileIsFullPath( + in_name, in_name[0] ? (in_name[1] ? 2 : 1) : 0); } -bool SystemTools::FileIsFullPath(const char* in_name, size_t len) +bool SystemToolsStatic::FileIsFullPath(const char* in_name, size_t len) { #if defined(_WIN32) || defined(__CYGWIN__) // On Windows, the name must be at least two characters long. @@ -4654,14 +4692,7 @@ bool SystemTools::ParseURL(const std::string& URL, std::string& protocol, // These must NOT be initialized. Default initialization to zero is // necessary. static unsigned int SystemToolsManagerCount; -SystemToolsTranslationMap* SystemTools::TranslationMap; -#ifdef _WIN32 -SystemToolsPathCaseMap* SystemTools::PathCaseMap; -SystemToolsEnvMap* SystemTools::EnvMap; -#endif -#ifdef __CYGWIN__ -SystemToolsTranslationMap* SystemTools::Cyg2Win32Map; -#endif +SystemToolsStatic* SystemTools::Statics; // SystemToolsManager manages the SystemTools singleton. // SystemToolsManager should be included in any translation unit @@ -4702,15 +4733,9 @@ void SystemTools::ClassInitialize() #ifdef __VMS SetVMSFeature("DECC$FILENAME_UNIX_ONLY", 1); #endif - // Allocate the translation map first. - SystemTools::TranslationMap = new SystemToolsTranslationMap; -#ifdef _WIN32 - SystemTools::PathCaseMap = new SystemToolsPathCaseMap; - SystemTools::EnvMap = new SystemToolsEnvMap; -#endif -#ifdef __CYGWIN__ - SystemTools::Cyg2Win32Map = new SystemToolsTranslationMap; -#endif + + // Create statics singleton instance + SystemTools::Statics = new SystemToolsStatic; // Add some special translation paths for unix. These are not added // for windows because drive letters need to be maintained. Also, @@ -4758,14 +4783,7 @@ void SystemTools::ClassInitialize() void SystemTools::ClassFinalize() { - delete SystemTools::TranslationMap; -#ifdef _WIN32 - delete SystemTools::PathCaseMap; - delete SystemTools::EnvMap; -#endif -#ifdef __CYGWIN__ - delete SystemTools::Cyg2Win32Map; -#endif + delete SystemTools::Statics; } } // namespace KWSYS_NAMESPACE diff --git a/Source/kwsys/SystemTools.hxx.in b/Source/kwsys/SystemTools.hxx.in index 33b579f..cdc9483 100644 --- a/Source/kwsys/SystemTools.hxx.in +++ b/Source/kwsys/SystemTools.hxx.in @@ -41,9 +41,7 @@ typedef @KWSYS_NAMESPACE@_VA_LIST::hack_va_list va_list; namespace @KWSYS_NAMESPACE@ { -class SystemToolsTranslationMap; -class SystemToolsPathCaseMap; -class SystemToolsEnvMap; +class SystemToolsStatic; /** \class SystemToolsManager * \brief Use to make sure SystemTools is initialized before it is used @@ -967,41 +965,8 @@ private: return &SystemToolsManagerInstance; } - /** - * Actual implementation of ReplaceString. - */ - static void ReplaceString(std::string& source, const char* replace, - size_t replaceSize, const std::string& with); - - /** - * Actual implementation of FileIsFullPath. - */ - static bool FileIsFullPath(const char*, size_t); - - /** - * Find a filename (file or directory) in the system PATH, with - * optional extra paths. - */ - static std::string FindName( - const std::string& name, - const std::vector<std::string>& path = std::vector<std::string>(), - bool no_system_path = false); - - static const char* GetEnvImpl(const char* key); - - /** - * Path translation table from dir to refdir - * Each time 'dir' will be found it will be replace by 'refdir' - */ - static SystemToolsTranslationMap* TranslationMap; -#ifdef _WIN32 - static std::string GetActualCaseForPathCached(std::string const& path); - static SystemToolsPathCaseMap* PathCaseMap; - static SystemToolsEnvMap* EnvMap; -#endif -#ifdef __CYGWIN__ - static SystemToolsTranslationMap* Cyg2Win32Map; -#endif + static SystemToolsStatic* Statics; + friend class SystemToolsStatic; friend class SystemToolsManager; }; diff --git a/Tests/CMakeLib/testRange.cxx b/Tests/CMakeLib/testRange.cxx index 5ae805f..b26b07b 100644 --- a/Tests/CMakeLib/testRange.cxx +++ b/Tests/CMakeLib/testRange.cxx @@ -11,7 +11,7 @@ do { \ if (!(x)) { \ std::cout << "ASSERT_TRUE(" #x ") failed on line " << __LINE__ << "\n"; \ - return false; \ + return -1; \ } \ } while (false) diff --git a/Tests/CMakeLib/testUTF8.cxx b/Tests/CMakeLib/testUTF8.cxx index c99c46d..a0bb5cd 100644 --- a/Tests/CMakeLib/testUTF8.cxx +++ b/Tests/CMakeLib/testUTF8.cxx @@ -13,6 +13,21 @@ static void test_utf8_char_print(test_utf8_char const c) static_cast<int>(d[3])); } +static void byte_array_print(char const* s) +{ + unsigned char const* d = reinterpret_cast<unsigned char const*>(s); + bool started = false; + printf("["); + for (; *d; ++d) { + if (started) { + printf(","); + } + started = true; + printf("0x%02X", static_cast<int>(*d)); + } + printf("]"); +} + struct test_utf8_entry { int n; @@ -21,17 +36,36 @@ struct test_utf8_entry }; static test_utf8_entry const good_entry[] = { - { 1, "\x20\x00\x00\x00", 0x0020 }, /* Space. */ - { 2, "\xC2\xA9\x00\x00", 0x00A9 }, /* Copyright. */ - { 3, "\xE2\x80\x98\x00", 0x2018 }, /* Open-single-quote. */ - { 3, "\xE2\x80\x99\x00", 0x2019 }, /* Close-single-quote. */ - { 4, "\xF0\xA3\x8E\xB4", 0x233B4 }, /* Example from RFC 3629. */ + { 1, "\x20\x00\x00\x00", 0x0020 }, /* Space. */ + { 2, "\xC2\xA9\x00\x00", 0x00A9 }, /* Copyright. */ + { 3, "\xE2\x80\x98\x00", 0x2018 }, /* Open-single-quote. */ + { 3, "\xE2\x80\x99\x00", 0x2019 }, /* Close-single-quote. */ + { 4, "\xF0\xA3\x8E\xB4", 0x233B4 }, /* Example from RFC 3629. */ + { 3, "\xED\x80\x80\x00", 0xD000 }, /* Valid 0xED prefixed codepoint. */ + { 4, "\xF4\x8F\xBF\xBF", 0x10FFFF }, /* Highest valid RFC codepoint. */ { 0, { 0, 0, 0, 0, 0 }, 0 } }; static test_utf8_char const bad_chars[] = { - "\x80\x00\x00\x00", "\xC0\x00\x00\x00", "\xE0\x00\x00\x00", - "\xE0\x80\x80\x00", "\xF0\x80\x80\x80", { 0, 0, 0, 0, 0 } + "\x80\x00\x00\x00", /* Leading continuation byte. */ + "\xC0\x80\x00\x00", /* Overlong encoding. */ + "\xC1\x80\x00\x00", /* Overlong encoding. */ + "\xC2\x00\x00\x00", /* Missing continuation byte. */ + "\xE0\x00\x00\x00", /* Missing continuation bytes. */ + "\xE0\x80\x80\x00", /* Overlong encoding. */ + "\xF0\x80\x80\x80", /* Overlong encoding. */ + "\xED\xA0\x80\x00", /* UTF-16 surrogate half. */ + "\xED\xBF\xBF\x00", /* UTF-16 surrogate half. */ + "\xF4\x90\x80\x80", /* Lowest out-of-range codepoint. */ + "\xF5\x80\x80\x80", /* Prefix forces out-of-range codepoints. */ + { 0, 0, 0, 0, 0 } +}; + +static char const* good_strings[] = { "", "ASCII", "\xC2\xA9 Kitware", 0 }; + +static char const* bad_strings[] = { + "\xC0\x80", /* Modified UTF-8 for embedded 0-byte. */ + 0 }; static void report_good(bool passed, test_utf8_char const c) @@ -87,6 +121,46 @@ static bool decode_bad(test_utf8_char const s) return true; } +static void report_valid(bool passed, char const* s) +{ + printf("%s: validity good ", passed ? "pass" : "FAIL"); + byte_array_print(s); + printf(" (%s) ", s); +} + +static void report_invalid(bool passed, char const* s) +{ + printf("%s: validity bad ", passed ? "pass" : "FAIL"); + byte_array_print(s); + printf(" "); +} + +static bool is_valid(const char* s) +{ + bool valid = cm_utf8_is_valid(s) != 0; + if (!valid) { + report_valid(false, s); + printf("expected valid, reported as invalid\n"); + return false; + } + report_valid(true, s); + printf("valid as expected\n"); + return true; +} + +static bool is_invalid(const char* s) +{ + bool valid = cm_utf8_is_valid(s) != 0; + if (valid) { + report_invalid(false, s); + printf("expected invalid, reported as valid\n"); + return false; + } + report_invalid(true, s); + printf("invalid as expected\n"); + return true; +} + int testUTF8(int /*unused*/, char* /*unused*/ []) { int result = 0; @@ -94,11 +168,27 @@ int testUTF8(int /*unused*/, char* /*unused*/ []) if (!decode_good(*e)) { result = 1; } + if (!is_valid(e->str)) { + result = 1; + } } for (test_utf8_char const* c = bad_chars; (*c)[0]; ++c) { if (!decode_bad(*c)) { result = 1; } + if (!is_invalid(*c)) { + result = 1; + } + } + for (char const** s = good_strings; *s; ++s) { + if (!is_valid(*s)) { + result = 1; + } + } + for (char const** s = bad_strings; *s; ++s) { + if (!is_invalid(*s)) { + result = 1; + } } return result; } diff --git a/Tests/CMakeLists.txt b/Tests/CMakeLists.txt index a59b6eb..3746965 100644 --- a/Tests/CMakeLists.txt +++ b/Tests/CMakeLists.txt @@ -1421,6 +1421,10 @@ ${CMake_BINARY_DIR}/bin/cmake -DDIR=dev -P ${CMake_SOURCE_DIR}/Utilities/Release add_subdirectory(FindDoxygen) endif() + if(CMake_TEST_FindEnvModules) + add_subdirectory(FindEnvModules) + endif() + if(CMake_TEST_FindEXPAT) add_subdirectory(FindEXPAT) endif() @@ -1445,6 +1449,10 @@ ${CMake_BINARY_DIR}/bin/cmake -DDIR=dev -P ${CMake_SOURCE_DIR}/Utilities/Release add_subdirectory(FindGit) endif() + if(CMake_TEST_FindGLEW) + add_subdirectory(FindGLEW) + endif() + if(CMake_TEST_FindGSL) add_subdirectory(FindGSL) endif() diff --git a/Tests/FindEnvModules/CMakeLists.txt b/Tests/FindEnvModules/CMakeLists.txt new file mode 100644 index 0000000..95b7d1d --- /dev/null +++ b/Tests/FindEnvModules/CMakeLists.txt @@ -0,0 +1,3 @@ +add_test(FindEnvModules.Test ${CMAKE_CMAKE_COMMAND} + -P ${CMAKE_CURRENT_LIST_DIR}/EnvModules.cmake +) diff --git a/Tests/FindEnvModules/EnvModules.cmake b/Tests/FindEnvModules/EnvModules.cmake new file mode 100644 index 0000000..0c81bf2 --- /dev/null +++ b/Tests/FindEnvModules/EnvModules.cmake @@ -0,0 +1,35 @@ +find_package(EnvModules REQUIRED) +message("module purge") +env_module(COMMAND purge RESULT_VARIABLE ret_var) +if(NOT ret_var EQUAL 0) + message(FATAL_ERROR "module(purge) returned ${ret_var}") +endif() + +message("module avail") +env_module_avail(avail_mods) +foreach(mod IN LISTS avail_mods) + message(" ${mod}") +endforeach() + +if(avail_mods) + list(GET avail_mods 0 mod0) + message("module load ${mod0}") + env_module(load ${mod0}) + + message("module list") + env_module_list(loaded_mods) + foreach(mod IN LISTS loaded_mods) + message(" ${mod}") + endforeach() + + list(LENGTH loaded_mods num_loaded_mods) + message("Number of modules loaded: ${num_loaded_mods}") + if(NOT num_loaded_mods EQUAL 1) + message(FATAL_ERROR "Exactly 1 module should be loaded. Found ${num_loaded_mods}") + endif() + + list(GET loaded_mods 0 mod0_actual) + if(NOT (mod0_actual MATCHES "^${mod0}")) + message(FATAL_ERROR "Loaded module does not match ${mod0}. Actual: ${mod0_actual}") + endif() +endif() diff --git a/Tests/FindGLEW/CMakeLists.txt b/Tests/FindGLEW/CMakeLists.txt new file mode 100644 index 0000000..ff42bce --- /dev/null +++ b/Tests/FindGLEW/CMakeLists.txt @@ -0,0 +1,10 @@ +add_test(NAME FindGLEW.Test COMMAND + ${CMAKE_CTEST_COMMAND} -C $<CONFIGURATION> + --build-and-test + "${CMake_SOURCE_DIR}/Tests/FindGLEW/Test" + "${CMake_BINARY_DIR}/Tests/FindGLEW/Test" + ${build_generator_args} + --build-project TestFindGLEW + --build-options ${build_options} + --test-command ${CMAKE_CTEST_COMMAND} -V -C $<CONFIGURATION> + ) diff --git a/Tests/FindGLEW/Test/CMakeLists.txt b/Tests/FindGLEW/Test/CMakeLists.txt new file mode 100644 index 0000000..954ee10 --- /dev/null +++ b/Tests/FindGLEW/Test/CMakeLists.txt @@ -0,0 +1,18 @@ +cmake_minimum_required(VERSION 3.1) +project(TestFindGLEW LANGUAGES CXX) +include(CTest) + +find_package(GLEW REQUIRED) + +add_executable(test_glew_shared_tgt main.cpp) +target_link_libraries(test_glew_shared_tgt GLEW::GLEW) +add_test(NAME test_glew_shared_tgt COMMAND test_glew_shared_tgt) + +add_executable(test_glew_generic_tgt main.cpp) +target_link_libraries(test_glew_generic_tgt GLEW::glew) +add_test(NAME test_glew_generic_tgt COMMAND test_glew_generic_tgt) + +add_executable(test_glew_var main.cpp) +target_include_directories(test_glew_var PRIVATE ${GLEW_INCLUDE_DIRS}) +target_link_libraries(test_glew_var PRIVATE ${GLEW_LIBRARIES}) +add_test(NAME test_glew_var COMMAND test_glew_var) diff --git a/Tests/FindGLEW/Test/main.cpp b/Tests/FindGLEW/Test/main.cpp new file mode 100644 index 0000000..4a108ad --- /dev/null +++ b/Tests/FindGLEW/Test/main.cpp @@ -0,0 +1,8 @@ +#include <GL/glew.h> + +int main() +{ + GLenum init_return = glewInit(); + + return (init_return == GLEW_OK); +} diff --git a/Tests/FindPackageTest/CMakeLists.txt b/Tests/FindPackageTest/CMakeLists.txt index f8b36c5..972580c 100644 --- a/Tests/FindPackageTest/CMakeLists.txt +++ b/Tests/FindPackageTest/CMakeLists.txt @@ -380,6 +380,7 @@ try_compile(EXPORTER_COMPILED ${FindPackageTest_SOURCE_DIR}/Exporter CMakeTestExportPackage dummy CMAKE_FLAGS "-UCMAKE_EXPORT_NO_PACKAGE_REGISTRY" + "-DCMAKE_POLICY_DEFAULT_CMP0090:STRING=OLD" -Dversion=${version} OUTPUT_VARIABLE output) message(STATUS "Searching for export(PACKAGE) test project") @@ -417,6 +418,25 @@ if(CMakeTestExportPackage_FOUND) message(SEND_ERROR "CMakeTestExportPackage should not be FOUND!") endif() +message(STATUS "Remove export(PACKAGE) test project") +file(REMOVE_RECURSE ${FindPackageTest_BINARY_DIR}/Exporter-build) + +message(STATUS "Preparing export(PACKAGE) test project with POLICY CMP0090=NEW") +try_compile(EXPORTER_COMPILED + ${FindPackageTest_BINARY_DIR}/Exporter-build + ${FindPackageTest_SOURCE_DIR}/Exporter + CMakeTestExportPackage dummy + CMAKE_FLAGS + "-DCMAKE_POLICY_DEFAULT_CMP0090:STRING=NEW" + -Dversion=${version} + OUTPUT_VARIABLE output) +message(STATUS "Searching for export(PACKAGE) test project") +find_package(CMakeTestExportPackage 1.${version} EXACT QUIET) +if(CMakeTestExportPackage_FOUND) + message(SEND_ERROR "CMakeTestExportPackage should not be FOUND!") +endif() + + #----------------------------------------------------------------------------- # Test configure_package_config_file(). diff --git a/Tests/RunCMake/CommandLine/RunCMakeTest.cmake b/Tests/RunCMake/CommandLine/RunCMakeTest.cmake index 5b5c5a5..3deabd0 100644 --- a/Tests/RunCMake/CommandLine/RunCMakeTest.cmake +++ b/Tests/RunCMake/CommandLine/RunCMakeTest.cmake @@ -54,6 +54,14 @@ run_cmake_command(build-bad-dir run_cmake_command(build-bad-generator ${CMAKE_COMMAND} --build ${RunCMake_SOURCE_DIR}/cache-bad-generator) +run_cmake_command(install-no-dir + ${CMAKE_COMMAND} --install) +run_cmake_command(install-bad-dir + ${CMAKE_COMMAND} --install dir-does-not-exist) +run_cmake_command(install-options-to-vars + ${CMAKE_COMMAND} --install ${RunCMake_SOURCE_DIR}/dir-install-options-to-vars + --strip --prefix /var/test --config sample --component pack) + run_cmake_command(cache-bad-entry ${CMAKE_COMMAND} --build ${RunCMake_SOURCE_DIR}/cache-bad-entry/) run_cmake_command(cache-empty-entry diff --git a/Tests/RunCMake/CommandLine/dir-install-options-to-vars/cmake_install.cmake b/Tests/RunCMake/CommandLine/dir-install-options-to-vars/cmake_install.cmake new file mode 100644 index 0000000..fd4e67d --- /dev/null +++ b/Tests/RunCMake/CommandLine/dir-install-options-to-vars/cmake_install.cmake @@ -0,0 +1,15 @@ +if(CMAKE_INSTALL_PREFIX) + message("CMAKE_INSTALL_PREFIX is ${CMAKE_INSTALL_PREFIX}") +endif() + +if(CMAKE_INSTALL_COMPONENT) + message("CMAKE_INSTALL_COMPONENT is ${CMAKE_INSTALL_COMPONENT}") +endif() + +if(CMAKE_INSTALL_CONFIG_NAME) + message("CMAKE_INSTALL_CONFIG_NAME is ${CMAKE_INSTALL_CONFIG_NAME}") +endif() + +if(CMAKE_INSTALL_DO_STRIP) + message("CMAKE_INSTALL_DO_STRIP is ${CMAKE_INSTALL_DO_STRIP}") +endif() diff --git a/Tests/RunCMake/CommandLine/install-bad-dir-result.txt b/Tests/RunCMake/CommandLine/install-bad-dir-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/CommandLine/install-bad-dir-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/CommandLine/install-bad-dir-stderr.txt b/Tests/RunCMake/CommandLine/install-bad-dir-stderr.txt new file mode 100644 index 0000000..320aecc --- /dev/null +++ b/Tests/RunCMake/CommandLine/install-bad-dir-stderr.txt @@ -0,0 +1 @@ +^CMake Error: Error processing file: diff --git a/Tests/RunCMake/CommandLine/install-no-dir-result.txt b/Tests/RunCMake/CommandLine/install-no-dir-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/CommandLine/install-no-dir-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/CommandLine/install-no-dir-stderr.txt b/Tests/RunCMake/CommandLine/install-no-dir-stderr.txt new file mode 100644 index 0000000..d64f638 --- /dev/null +++ b/Tests/RunCMake/CommandLine/install-no-dir-stderr.txt @@ -0,0 +1 @@ +^Usage: cmake --install <dir> \[options\] diff --git a/Tests/RunCMake/CommandLine/install-options-to-vars-result.txt b/Tests/RunCMake/CommandLine/install-options-to-vars-result.txt new file mode 100644 index 0000000..573541a --- /dev/null +++ b/Tests/RunCMake/CommandLine/install-options-to-vars-result.txt @@ -0,0 +1 @@ +0 diff --git a/Tests/RunCMake/CommandLine/install-options-to-vars-stderr.txt b/Tests/RunCMake/CommandLine/install-options-to-vars-stderr.txt new file mode 100644 index 0000000..f7b1583 --- /dev/null +++ b/Tests/RunCMake/CommandLine/install-options-to-vars-stderr.txt @@ -0,0 +1,4 @@ +CMAKE_INSTALL_PREFIX is /var/test +CMAKE_INSTALL_COMPONENT is pack +CMAKE_INSTALL_CONFIG_NAME is sample +CMAKE_INSTALL_DO_STRIP is 1 diff --git a/Tests/RunCMake/CommandLineTar/RunCMakeTest.cmake b/Tests/RunCMake/CommandLineTar/RunCMakeTest.cmake index 12635db..5deb110 100644 --- a/Tests/RunCMake/CommandLineTar/RunCMakeTest.cmake +++ b/Tests/RunCMake/CommandLineTar/RunCMakeTest.cmake @@ -4,19 +4,23 @@ function(external_command_test NAME) run_cmake_command(${NAME} ${CMAKE_COMMAND} -E ${ARGN}) endfunction() -external_command_test(bad-opt1 tar cvf bad.tar --bad) -external_command_test(bad-mtime1 tar cvf bad.tar --mtime=bad .) -external_command_test(bad-from1 tar cvf bad.tar --files-from=bad) -external_command_test(bad-from2 tar cvf bad.tar --files-from=.) -external_command_test(bad-from3 tar cvf bad.tar --files-from=${CMAKE_CURRENT_LIST_DIR}/bad-from3.txt) -external_command_test(bad-from4 tar cvf bad.tar --files-from=${CMAKE_CURRENT_LIST_DIR}/bad-from4.txt) -external_command_test(bad-from5 tar cvf bad.tar --files-from=${CMAKE_CURRENT_LIST_DIR}/bad-from5.txt) -external_command_test(end-opt1 tar cvf bad.tar -- --bad) -external_command_test(end-opt2 tar cvf bad.tar --) -external_command_test(mtime tar cvf bad.tar "--mtime=1970-01-01 00:00:00 UTC") -external_command_test(bad-format tar cvf bad.tar "--format=bad-format") -external_command_test(zip-bz2 tar cvjf bad.tar "--format=zip") -external_command_test(7zip-gz tar cvzf bad.tar "--format=7zip") +external_command_test(without-files tar cvf bad.tar) +external_command_test(bad-opt1 tar cvf bad.tar --bad) +external_command_test(bad-mtime1 tar cvf bad.tar --mtime=bad .) +external_command_test(bad-from1 tar cvf bad.tar --files-from=bad) +external_command_test(bad-from2 tar cvf bad.tar --files-from=.) +external_command_test(bad-from3 tar cvf bad.tar --files-from=${CMAKE_CURRENT_LIST_DIR}/bad-from3.txt) +external_command_test(bad-from4 tar cvf bad.tar --files-from=${CMAKE_CURRENT_LIST_DIR}/bad-from4.txt) +external_command_test(bad-from5 tar cvf bad.tar --files-from=${CMAKE_CURRENT_LIST_DIR}/bad-from5.txt) +external_command_test(bad-file tar cf bad.tar badfile.txt ${CMAKE_CURRENT_LIST_DIR}/test-file.txt) +external_command_test(bad-without-action tar f bad.tar ${CMAKE_CURRENT_LIST_DIR}/test-file.txt) +external_command_test(bad-wrong-flag tar cvfq bad.tar ${CMAKE_CURRENT_LIST_DIR}/test-file.txt) +external_command_test(end-opt1 tar cvf bad.tar -- --bad) +external_command_test(end-opt2 tar cvf bad.tar --) +external_command_test(mtime tar cvf bad.tar "--mtime=1970-01-01 00:00:00 UTC" ${CMAKE_CURRENT_LIST_DIR}/test-file.txt) +external_command_test(bad-format tar cvf bad.tar "--format=bad-format" ${CMAKE_CURRENT_LIST_DIR}/test-file.txt) +external_command_test(zip-bz2 tar cvjf bad.tar "--format=zip" ${CMAKE_CURRENT_LIST_DIR}/test-file.txt) +external_command_test(7zip-gz tar cvzf bad.tar "--format=7zip" ${CMAKE_CURRENT_LIST_DIR}/test-file.txt) run_cmake(7zip) run_cmake(gnutar) diff --git a/Tests/RunCMake/CommandLineTar/bad-file-result.txt b/Tests/RunCMake/CommandLineTar/bad-file-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/CommandLineTar/bad-file-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/CommandLineTar/bad-file-stderr.txt b/Tests/RunCMake/CommandLineTar/bad-file-stderr.txt new file mode 100644 index 0000000..1f9f748 --- /dev/null +++ b/Tests/RunCMake/CommandLineTar/bad-file-stderr.txt @@ -0,0 +1,2 @@ +^CMake Error: Unable to read from file 'badfile.txt': .* +CMake Error: Problem creating tar: bad.tar$ diff --git a/Tests/RunCMake/CommandLineTar/bad-from4-stderr.txt b/Tests/RunCMake/CommandLineTar/bad-from4-stderr.txt index 1417d4d..fb0702a 100644 --- a/Tests/RunCMake/CommandLineTar/bad-from4-stderr.txt +++ b/Tests/RunCMake/CommandLineTar/bad-from4-stderr.txt @@ -1,2 +1,2 @@ -^CMake Error: archive_read_disk_entry_from_file 'does-not-exist':.* +^CMake Error: Unable to read from file 'does-not-exist':.* CMake Error: Problem creating tar: bad.tar$ diff --git a/Tests/RunCMake/CommandLineTar/bad-from5-stderr.txt b/Tests/RunCMake/CommandLineTar/bad-from5-stderr.txt index 1417d4d..fb0702a 100644 --- a/Tests/RunCMake/CommandLineTar/bad-from5-stderr.txt +++ b/Tests/RunCMake/CommandLineTar/bad-from5-stderr.txt @@ -1,2 +1,2 @@ -^CMake Error: archive_read_disk_entry_from_file 'does-not-exist':.* +^CMake Error: Unable to read from file 'does-not-exist':.* CMake Error: Problem creating tar: bad.tar$ diff --git a/Tests/RunCMake/CommandLineTar/bad-without-action-result.txt b/Tests/RunCMake/CommandLineTar/bad-without-action-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/CommandLineTar/bad-without-action-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/CommandLineTar/bad-without-action-stderr.txt b/Tests/RunCMake/CommandLineTar/bad-without-action-stderr.txt new file mode 100644 index 0000000..2fec254 --- /dev/null +++ b/Tests/RunCMake/CommandLineTar/bad-without-action-stderr.txt @@ -0,0 +1 @@ +^CMake Error: tar: No action specified. Please choose: 't' \(list\), 'c' \(create\) or 'x' \(extract\)$ diff --git a/Tests/RunCMake/CommandLineTar/bad-wrong-flag-stderr.txt b/Tests/RunCMake/CommandLineTar/bad-wrong-flag-stderr.txt new file mode 100644 index 0000000..d5c1e01 --- /dev/null +++ b/Tests/RunCMake/CommandLineTar/bad-wrong-flag-stderr.txt @@ -0,0 +1 @@ +^tar: Unknown argument: q diff --git a/Tests/RunCMake/CommandLineTar/end-opt1-stderr.txt b/Tests/RunCMake/CommandLineTar/end-opt1-stderr.txt index 1fddf6d..1342dc8 100644 --- a/Tests/RunCMake/CommandLineTar/end-opt1-stderr.txt +++ b/Tests/RunCMake/CommandLineTar/end-opt1-stderr.txt @@ -1,2 +1,2 @@ -^CMake Error: archive_read_disk_entry_from_file '--bad':.* +^CMake Error: Unable to read from file '--bad':.* CMake Error: Problem creating tar: bad.tar$ diff --git a/Tests/RunCMake/CommandLineTar/end-opt2-stderr.txt b/Tests/RunCMake/CommandLineTar/end-opt2-stderr.txt new file mode 100644 index 0000000..70166f5 --- /dev/null +++ b/Tests/RunCMake/CommandLineTar/end-opt2-stderr.txt @@ -0,0 +1 @@ +^tar: No files or directories specified diff --git a/Tests/RunCMake/CommandLineTar/gnutar-gz.cmake b/Tests/RunCMake/CommandLineTar/gnutar-gz.cmake index 5f2674a..53ee961 100644 --- a/Tests/RunCMake/CommandLineTar/gnutar-gz.cmake +++ b/Tests/RunCMake/CommandLineTar/gnutar-gz.cmake @@ -1,9 +1,9 @@ set(OUTPUT_NAME "test.tar.gz") -set(COMPRESSION_FLAGS cvzf) +set(COMPRESSION_FLAGS -cvzf) set(COMPRESSION_OPTIONS --format=gnutar) -set(DECOMPRESSION_FLAGS xvzf) +set(DECOMPRESSION_FLAGS -xvzf) include(${CMAKE_CURRENT_LIST_DIR}/roundtrip.cmake) diff --git a/Tests/RunCMake/CommandLineTar/pax.cmake b/Tests/RunCMake/CommandLineTar/pax.cmake index 60ed238..77f74d1 100644 --- a/Tests/RunCMake/CommandLineTar/pax.cmake +++ b/Tests/RunCMake/CommandLineTar/pax.cmake @@ -1,9 +1,9 @@ set(OUTPUT_NAME "test.tar") -set(COMPRESSION_FLAGS cvf) +set(COMPRESSION_FLAGS -cvf) set(COMPRESSION_OPTIONS --format=pax) -set(DECOMPRESSION_FLAGS xvf) +set(DECOMPRESSION_FLAGS -xvf) include(${CMAKE_CURRENT_LIST_DIR}/roundtrip.cmake) diff --git a/Tests/RunCMake/CommandLineTar/test-file.txt b/Tests/RunCMake/CommandLineTar/test-file.txt new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/Tests/RunCMake/CommandLineTar/test-file.txt diff --git a/Tests/RunCMake/CommandLineTar/without-files-stderr.txt b/Tests/RunCMake/CommandLineTar/without-files-stderr.txt new file mode 100644 index 0000000..70166f5 --- /dev/null +++ b/Tests/RunCMake/CommandLineTar/without-files-stderr.txt @@ -0,0 +1 @@ +^tar: No files or directories specified diff --git a/Tests/RunCMake/FindPkgConfig/FindPkgConfig_IMPORTED_TARGET.cmake b/Tests/RunCMake/FindPkgConfig/FindPkgConfig_IMPORTED_TARGET.cmake index 24e7202..e82b05f 100644 --- a/Tests/RunCMake/FindPkgConfig/FindPkgConfig_IMPORTED_TARGET.cmake +++ b/Tests/RunCMake/FindPkgConfig/FindPkgConfig_IMPORTED_TARGET.cmake @@ -109,3 +109,24 @@ pkg_check_modules(FakePackage2 REQUIRED QUIET IMPORTED_TARGET cmakeinternalfakep if (NOT FakePackage2_LINK_LIBRARIES STREQUAL "${fakePkgDir}/lib/libcmakeinternalfakepackage2.a") message(FATAL_ERROR "FakePackage2_LINK_LIBRARIES has bad content on second run: ${FakePackage2_LINK_LIBRARIES}") endif() + +set(pname fakelinkoptionspackage) +file(WRITE ${fakePkgDir}/lib/pkgconfig/${pname}.pc +"Name: FakeLinkOptionsPackage +Description: Dummy package for FindPkgConfig IMPORTED_TARGET INTERFACE_LINK_OPTIONS test +Version: 1.2.3 +Libs: -e dummy_main +") + +set(expected_link_options -e dummy_main) +pkg_check_modules(FakeLinkOptionsPackage REQUIRED QUIET IMPORTED_TARGET fakelinkoptionspackage) +if (NOT TARGET PkgConfig::FakeLinkOptionsPackage) + message(FATAL_ERROR "No import target for fake link options package") +endif() +get_target_property(link_options PkgConfig::FakeLinkOptionsPackage INTERFACE_LINK_OPTIONS) +if (NOT link_options STREQUAL expected_link_options) + message(FATAL_ERROR + "Additional link options not present in INTERFACE_LINK_OPTIONS property" + "expected: \"${expected_link_options}\", but got \"${link_options}\"" + ) +endif() diff --git a/Tests/RunCMake/XcodeProject/XcodeSchemaProperty-check.cmake b/Tests/RunCMake/XcodeProject/XcodeSchemaProperty-check.cmake index f675d81..88077b3 100644 --- a/Tests/RunCMake/XcodeProject/XcodeSchemaProperty-check.cmake +++ b/Tests/RunCMake/XcodeProject/XcodeSchemaProperty-check.cmake @@ -7,6 +7,13 @@ function(check_property property matcher) endif() endfunction() +function(expect_no_schema target) + set(schema "${RunCMake_TEST_BINARY_DIR}/XcodeSchemaProperty.xcodeproj/xcshareddata/xcschemes/${target}.xcscheme") + if(EXISTS ${schema}) + message(SEND_ERROR "Found unexpected schema ${schema}") + endif() +endfunction() + check_property("ADDRESS_SANITIZER" "enableAddressSanitizer") check_property("ADDRESS_SANITIZER_USE_AFTER_RETURN" "enableASanStackUseAfterReturn") check_property("THREAD_SANITIZER" "enableThreadSanitizer") @@ -31,3 +38,5 @@ check_property("ENVIRONMENT" [=[key="FOO"]=]) check_property("ENVIRONMENT" [=[value="foo"]=]) check_property("ENVIRONMENT" [=[key="BAR"]=]) check_property("ENVIRONMENT" [=[value="bar"]=]) + +expect_no_schema("NoSchema") diff --git a/Tests/RunCMake/XcodeProject/XcodeSchemaProperty.cmake b/Tests/RunCMake/XcodeProject/XcodeSchemaProperty.cmake index 2b72a64..73ef5ca 100644 --- a/Tests/RunCMake/XcodeProject/XcodeSchemaProperty.cmake +++ b/Tests/RunCMake/XcodeProject/XcodeSchemaProperty.cmake @@ -35,3 +35,6 @@ endfunction() create_scheme_for_property(EXECUTABLE myExecutable) create_scheme_for_property(ARGUMENTS "--foo;--bar=baz") create_scheme_for_property(ENVIRONMENT "FOO=foo;BAR=bar") + +add_executable(NoSchema main.cpp) +set_target_properties(NoSchema PROPERTIES XCODE_GENERATE_SCHEME OFF) diff --git a/Utilities/Scripts/update-third-party.bash b/Utilities/Scripts/update-third-party.bash index 670946e..fcab871 100644 --- a/Utilities/Scripts/update-third-party.bash +++ b/Utilities/Scripts/update-third-party.bash @@ -71,8 +71,6 @@ warn () { readonly regex_date='20[0-9][0-9]-[0-9][0-9]-[0-9][0-9]' readonly basehash_regex="$name $regex_date ([0-9a-f]*)" -readonly basehash="$( git rev-list --author="$ownership" --grep="$basehash_regex" -n 1 HEAD )" -readonly upstream_old_short="$( git cat-file commit "$basehash" | sed -n '/'"$basehash_regex"'/ {s/.*(//;s/)//;p}' | egrep '^[0-9a-f]+$' )" ######################################################################## # Sanity checking @@ -87,6 +85,18 @@ readonly upstream_old_short="$( git cat-file commit "$basehash" | sed -n '/'"$ba die "'repo' is empty" [ -n "$tag" ] || \ die "'tag' is empty" + +# Check for an empty destination directory on disk. By checking on disk and +# not in the repo it allows a library to be freshly re-inialized in a single +# commit rather than first deleting the old copy in one commit and adding the +# new copy in a seperate commit. +if [ ! -d "$(git rev-parse --show-toplevel)/$subtree" ]; then + readonly basehash="" +else + readonly basehash="$( git rev-list --author="$ownership" --grep="$basehash_regex" -n 1 HEAD )" +fi +readonly upstream_old_short="$( git cat-file commit "$basehash" | sed -n '/'"$basehash_regex"'/ {s/.*(//;s/)//;p}' | egrep '^[0-9a-f]+$' )" + [ -n "$basehash" ] || \ warn "'basehash' is empty; performing initial import" readonly do_shortlog="${shortlog-false}" @@ -104,6 +114,8 @@ trap "rm -rf '$workdir'" EXIT git clone "$repo" "$upstreamdir" if [ -n "$basehash" ]; then + # Remove old worktrees + git worktree prune # Use the existing package's history git worktree add "$extractdir" "$basehash" # Clear out the working tree @@ -163,13 +175,17 @@ popd if [ -n "$basehash" ]; then git merge --log -s recursive "-Xsubtree=$subtree/" --no-commit "upstream-$name" else + # Note: on Windows 'git merge --help' will open a browser, and the check + # will fail, so use the flag by default. unrelated_histories_flag="" - if git merge --help | grep -q -e allow-unrelated-histories; then + if git --version | grep -q windows; then + unrelated_histories_flag="--allow-unrelated-histories " + elif git merge --help | grep -q -e allow-unrelated-histories; then unrelated_histories_flag="--allow-unrelated-histories " fi readonly unrelated_histories_flag - git fetch "$extractdir" "upstream-$name:upstream-$name" + git fetch "$extractdir" "+upstream-$name:upstream-$name" git merge --log -s ours --no-commit $unrelated_histories_flag "upstream-$name" git read-tree -u --prefix="$subtree/" "upstream-$name" fi diff --git a/Utilities/cmzstd/CMakeLists.txt b/Utilities/cmzstd/CMakeLists.txt index b1399bd..8ed04d8 100644 --- a/Utilities/cmzstd/CMakeLists.txt +++ b/Utilities/cmzstd/CMakeLists.txt @@ -41,4 +41,7 @@ add_library(cmzstd STATIC lib/dictBuilder/zdict.c ) +# BMI2 instructions are not supported in older environments. +set_property(TARGET cmzstd PROPERTY COMPILE_DEFINITIONS DYNAMIC_BMI2=0) + install(FILES LICENSE DESTINATION ${CMAKE_DOC_DIR}/cmzstd) @@ -304,7 +304,8 @@ CMAKE_CXX_SOURCES="\ cmFileCommand \ cmFileCopier \ cmFileInstaller \ - cmFileTimeComparison \ + cmFileTime \ + cmFileTimeCache \ cmFindBase \ cmFindCommon \ cmFindFileCommand \ |