summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.clang-format2
-rw-r--r--Help/envvar/CMAKE_LANG_COMPILER_LAUNCHER.rst10
-rw-r--r--Help/manual/cmake-env-variables.7.rst1
-rw-r--r--Help/manual/ctest.1.rst26
-rw-r--r--Help/prop_test/RESOURCE_GROUPS.rst16
-rw-r--r--Help/prop_tgt/INSTALL_RPATH_USE_LINK_PATH.rst14
-rw-r--r--Help/release/dev/FindLibArchive-target.rst5
-rw-r--r--Help/release/dev/compiler-launcher-env.rst5
-rw-r--r--Help/release/dev/ninja-tool.rst7
-rw-r--r--Help/release/dev/xlf-ninja.rst5
-rw-r--r--Help/variable/CMAKE_HOST_SYSTEM_PROCESSOR.rst13
-rw-r--r--Help/variable/CMAKE_INSTALL_RPATH_USE_LINK_PATH.rst12
-rw-r--r--Help/variable/CMAKE_LANG_COMPILER_LAUNCHER.rst3
-rw-r--r--Modules/CMakeCInformation.cmake5
-rw-r--r--Modules/CMakeCUDACompiler.cmake.in5
-rw-r--r--Modules/CMakeCUDAInformation.cmake33
-rw-r--r--Modules/CMakeCXXInformation.cmake5
-rw-r--r--Modules/CMakeDetermineCompilerId.cmake12
-rw-r--r--Modules/CMakeDetermineFortranCompiler.cmake5
-rw-r--r--Modules/CMakeFortranCompiler.cmake.in1
-rw-r--r--Modules/CMakeFortranInformation.cmake5
-rw-r--r--Modules/CMakeNinjaFindMake.cmake1
-rw-r--r--Modules/CMakeParseImplicitIncludeInfo.cmake2
-rw-r--r--Modules/Compiler/Clang.cmake4
-rw-r--r--Modules/Compiler/GNU.cmake4
-rw-r--r--Modules/Compiler/NVIDIA-CUDA.cmake23
-rw-r--r--Modules/Compiler/XL-Fortran.cmake4
-rwxr-xr-xModules/Compiler/XL-Fortran/cpp29
-rw-r--r--Modules/FindBLAS.cmake2
-rw-r--r--Modules/FindLibArchive.cmake15
-rw-r--r--Modules/FindODBC.cmake2
-rw-r--r--Modules/FindPNG.cmake10
-rw-r--r--Modules/FindPkgConfig.cmake2
-rw-r--r--Modules/FindThreads.cmake8
-rw-r--r--Modules/FindwxWidgets.cmake2
-rw-r--r--Modules/Internal/CPack/CPackNuGet.cmake11
-rw-r--r--Modules/Platform/Windows-NVIDIA-CUDA.cmake17
-rw-r--r--Source/CMakeVersion.cmake2
-rw-r--r--Source/CTest/cmCTestResourceSpec.cxx26
-rw-r--r--Source/Checks/cm_cxx14_check.cmake2
-rw-r--r--Source/Checks/cm_cxx17_check.cmake2
-rw-r--r--Source/Checks/cm_cxx17_check.cpp10
-rw-r--r--Source/Checks/cm_cxx_features.cmake2
-rw-r--r--Source/cmAddCustomCommandCommand.cxx2
-rw-r--r--Source/cmAddCustomTargetCommand.cxx7
-rw-r--r--Source/cmAlgorithms.h8
-rw-r--r--Source/cmCPluginAPI.cxx6
-rw-r--r--Source/cmCPluginAPI.h4
-rw-r--r--Source/cmCustomCommand.cxx10
-rw-r--r--Source/cmCustomCommand.h8
-rw-r--r--Source/cmExportLibraryDependenciesCommand.cxx9
-rw-r--r--Source/cmFLTKWrapUICommand.cxx16
-rw-r--r--Source/cmGeneratorExpression.cxx10
-rw-r--r--Source/cmGeneratorExpression.h2
-rw-r--r--Source/cmGeneratorExpressionEvaluator.cxx21
-rw-r--r--Source/cmGeneratorExpressionEvaluator.h16
-rw-r--r--Source/cmGeneratorExpressionParser.cxx64
-rw-r--r--Source/cmGeneratorExpressionParser.h10
-rw-r--r--Source/cmGlobalGenerator.cxx52
-rw-r--r--Source/cmGlobalVisualStudio8Generator.cxx11
-rw-r--r--Source/cmGlobalVisualStudioGenerator.cxx13
-rw-r--r--Source/cmGlobalXCodeGenerator.cxx29
-rw-r--r--Source/cmInstallFilesCommand.cxx10
-rw-r--r--Source/cmInstallProgramsCommand.cxx10
-rw-r--r--Source/cmLoadCommandCommand.cxx9
-rw-r--r--Source/cmLocalGenerator.cxx404
-rw-r--r--Source/cmLocalGenerator.h91
-rw-r--r--Source/cmLocalVisualStudio7Generator.cxx12
-rw-r--r--Source/cmLocalVisualStudioGenerator.cxx4
-rw-r--r--Source/cmMakefile.cxx446
-rw-r--r--Source/cmMakefile.h101
-rw-r--r--Source/cmQtAutoGenGlobalInitializer.cxx13
-rw-r--r--Source/cmQtAutoGenInitializer.cxx19
-rw-r--r--Source/cmVariableWatchCommand.cxx6
-rw-r--r--Source/cmVisualStudio10TargetGenerator.cxx2
-rw-r--r--Templates/TestDriver.cxx.in2
-rw-r--r--Tests/CMakeLib/CMakeLists.txt1
-rw-r--r--Tests/CMakeLib/testCMExtMemory.cxx65
-rw-r--r--Tests/CMakeLib/testCTestResourceGroups.cxx3
-rw-r--r--Tests/CMakeLib/testCTestResourceSpec.cxx18
-rw-r--r--Tests/CMakeLib/testCTestResourceSpec_data/spec1.json4
-rw-r--r--Tests/CMakeLib/testCTestResourceSpec_data/spec10.json4
-rw-r--r--Tests/CMakeLib/testCTestResourceSpec_data/spec11.json4
-rw-r--r--Tests/CMakeLib/testCTestResourceSpec_data/spec14.json4
-rw-r--r--Tests/CMakeLib/testCTestResourceSpec_data/spec15.json4
-rw-r--r--Tests/CMakeLib/testCTestResourceSpec_data/spec16.json4
-rw-r--r--Tests/CMakeLib/testCTestResourceSpec_data/spec17.json4
-rw-r--r--Tests/CMakeLib/testCTestResourceSpec_data/spec18.json4
-rw-r--r--Tests/CMakeLib/testCTestResourceSpec_data/spec19.json5
-rw-r--r--Tests/CMakeLib/testCTestResourceSpec_data/spec2.json4
-rw-r--r--Tests/CMakeLib/testCTestResourceSpec_data/spec20.json8
-rw-r--r--Tests/CMakeLib/testCTestResourceSpec_data/spec21.json5
-rw-r--r--Tests/CMakeLib/testCTestResourceSpec_data/spec22.json5
-rw-r--r--Tests/CMakeLib/testCTestResourceSpec_data/spec23.json7
-rw-r--r--Tests/CMakeLib/testCTestResourceSpec_data/spec24.json7
-rw-r--r--Tests/CMakeLib/testCTestResourceSpec_data/spec25.json8
-rw-r--r--Tests/CMakeLib/testCTestResourceSpec_data/spec26.json8
-rw-r--r--Tests/CMakeLib/testCTestResourceSpec_data/spec27.json8
-rw-r--r--Tests/CMakeLib/testCTestResourceSpec_data/spec28.json8
-rw-r--r--Tests/CMakeLib/testCTestResourceSpec_data/spec29.json5
-rw-r--r--Tests/CMakeLib/testCTestResourceSpec_data/spec3.json4
-rw-r--r--Tests/CMakeLib/testCTestResourceSpec_data/spec30.json5
-rw-r--r--Tests/CMakeLib/testCTestResourceSpec_data/spec31.json5
-rw-r--r--Tests/CMakeLib/testCTestResourceSpec_data/spec32.json5
-rw-r--r--Tests/CMakeLib/testCTestResourceSpec_data/spec33.json5
-rw-r--r--Tests/CMakeLib/testCTestResourceSpec_data/spec34.json5
-rw-r--r--Tests/CMakeLib/testCTestResourceSpec_data/spec35.json5
-rw-r--r--Tests/CMakeLib/testCTestResourceSpec_data/spec36.json4
-rw-r--r--Tests/CMakeLib/testCTestResourceSpec_data/spec4.json4
-rw-r--r--Tests/CMakeLib/testCTestResourceSpec_data/spec5.json4
-rw-r--r--Tests/CMakeLib/testCTestResourceSpec_data/spec6.json4
-rw-r--r--Tests/CMakeLib/testCTestResourceSpec_data/spec7.json4
-rw-r--r--Tests/CMakeLib/testCTestResourceSpec_data/spec8.json4
-rw-r--r--Tests/CMakeLib/testCTestResourceSpec_data/spec9.json4
-rw-r--r--Tests/CMakeLists.txt1
-rw-r--r--Tests/FindLibArchive/CMakeLists.txt10
-rw-r--r--Tests/FindLibArchive/Test/CMakeLists.txt14
-rw-r--r--Tests/FindLibArchive/Test/main.c7
-rw-r--r--Tests/RunCMake/CTestResourceAllocation/RunCMakeTest.cmake2
-rw-r--r--Tests/RunCMake/CTestResourceAllocation/combine.cmake5
-rw-r--r--Tests/RunCMake/CTestResourceAllocation/notenough1.cmake2
-rw-r--r--Tests/RunCMake/CTestResourceAllocation/notenough2.cmake2
-rw-r--r--Tests/RunCMake/CTestResourceAllocation/notenough3-ctest-s-res-check.cmake3
-rw-r--r--Tests/RunCMake/CTestResourceAllocation/notenough3-ctest-s-res-result.txt1
-rw-r--r--Tests/RunCMake/CTestResourceAllocation/notenough3-ctest-s-res-stderr.txt4
-rw-r--r--Tests/RunCMake/CTestResourceAllocation/notenough3.cmake5
-rw-r--r--Tests/RunCMake/CTestResourceAllocation/resspec.json4
-rw-r--r--Tests/RunCMake/CompilerLauncher/C-common.cmake3
-rw-r--r--Tests/RunCMake/CompilerLauncher/C-env-Build-stdout.txt1
-rw-r--r--Tests/RunCMake/CompilerLauncher/C-env-launch-Build-stdout.txt1
-rw-r--r--Tests/RunCMake/CompilerLauncher/C-env.cmake1
-rw-r--r--Tests/RunCMake/CompilerLauncher/C-launch-env.cmake3
-rw-r--r--Tests/RunCMake/CompilerLauncher/C.cmake4
-rw-r--r--Tests/RunCMake/CompilerLauncher/CUDA-common.cmake3
-rw-r--r--Tests/RunCMake/CompilerLauncher/CUDA-env-Build-stdout.txt1
-rw-r--r--Tests/RunCMake/CompilerLauncher/CUDA-env-launch-Build-stdout.txt1
-rw-r--r--Tests/RunCMake/CompilerLauncher/CUDA-env.cmake1
-rw-r--r--Tests/RunCMake/CompilerLauncher/CUDA-launch-env.cmake3
-rw-r--r--Tests/RunCMake/CompilerLauncher/CUDA.cmake4
-rw-r--r--Tests/RunCMake/CompilerLauncher/CXX-common.cmake3
-rw-r--r--Tests/RunCMake/CompilerLauncher/CXX-env-Build-stdout.txt1
-rw-r--r--Tests/RunCMake/CompilerLauncher/CXX-env-launch-Build-stdout.txt1
-rw-r--r--Tests/RunCMake/CompilerLauncher/CXX-env.cmake1
-rw-r--r--Tests/RunCMake/CompilerLauncher/CXX-launch-env.cmake3
-rw-r--r--Tests/RunCMake/CompilerLauncher/CXX.cmake4
-rw-r--r--Tests/RunCMake/CompilerLauncher/Fortran-common.cmake3
-rw-r--r--Tests/RunCMake/CompilerLauncher/Fortran-env-Build-stdout.txt1
-rw-r--r--Tests/RunCMake/CompilerLauncher/Fortran-env-launch-Build-stdout.txt1
-rw-r--r--Tests/RunCMake/CompilerLauncher/Fortran-env.cmake1
-rw-r--r--Tests/RunCMake/CompilerLauncher/Fortran-launch-env.cmake3
-rw-r--r--Tests/RunCMake/CompilerLauncher/Fortran.cmake4
-rw-r--r--Tests/RunCMake/CompilerLauncher/RunCMakeTest.cmake9
-rw-r--r--Tests/RunCMake/ObjectLibrary/OwnSources-stderr.txt6
-rw-r--r--Tests/RunCMake/PrecompileHeaders/PchReuseFromPrefixed-build-stderr.txt2
-rw-r--r--Tests/RunCMake/PrecompileHeaders/PchReuseFromPrefixed.cmake29
-rw-r--r--Tests/RunCMake/PrecompileHeaders/RunCMakeTest.cmake1
-rw-r--r--Tests/RunCMake/UnityBuild/RunCMakeTest.cmake1
-rw-r--r--Tests/RunCMake/UnityBuild/unitybuild_object_library.cmake13
-rwxr-xr-xUtilities/GitSetup/setup-user8
-rw-r--r--Utilities/std/.gitattributes1
-rw-r--r--Utilities/std/cm/type_traits46
-rw-r--r--Utilities/std/cmext/memory32
-rwxr-xr-xbootstrap1
163 files changed, 1716 insertions, 601 deletions
diff --git a/.clang-format b/.clang-format
index 0c7d6b0..a7f049a 100644
--- a/.clang-format
+++ b/.clang-format
@@ -22,7 +22,7 @@ IncludeBlocks: Regroup
IncludeCategories:
- Regex: '^[<"]cmConfigure\.h'
Priority: -1
- - Regex: '^(<|")cm/'
+ - Regex: '^(<|")cm(ext)?/'
Priority: 2
- Regex: '^(<|")windows\.h'
Priority: 3
diff --git a/Help/envvar/CMAKE_LANG_COMPILER_LAUNCHER.rst b/Help/envvar/CMAKE_LANG_COMPILER_LAUNCHER.rst
new file mode 100644
index 0000000..4f91e9a
--- /dev/null
+++ b/Help/envvar/CMAKE_LANG_COMPILER_LAUNCHER.rst
@@ -0,0 +1,10 @@
+CMAKE_<LANG>_COMPILER_LAUNCHER
+------------------------------
+
+.. include:: ENV_VAR.txt
+
+Default compiler launcher to use for the specified language. Will only be used
+by CMake to initialize the variable on the first configuration. Afterwards, it
+is available through the cache setting of the variable of the same name. For
+any configuration run (including the first), the environment variable will be
+ignored if the :variable:`CMAKE_<LANG>_COMPILER_LAUNCHER` variable is defined.
diff --git a/Help/manual/cmake-env-variables.7.rst b/Help/manual/cmake-env-variables.7.rst
index c98f18f..adfc39e 100644
--- a/Help/manual/cmake-env-variables.7.rst
+++ b/Help/manual/cmake-env-variables.7.rst
@@ -28,6 +28,7 @@ Environment Variables that Control the Build
/envvar/CMAKE_GENERATOR_INSTANCE
/envvar/CMAKE_GENERATOR_PLATFORM
/envvar/CMAKE_GENERATOR_TOOLSET
+ /envvar/CMAKE_LANG_COMPILER_LAUNCHER
/envvar/CMAKE_MSVCIDE_RUN_PATH
/envvar/CMAKE_NO_VERBOSE
/envvar/CMAKE_OSX_ARCHITECTURES
diff --git a/Help/manual/ctest.1.rst b/Help/manual/ctest.1.rst
index 2a6cb48..17bddb6 100644
--- a/Help/manual/ctest.1.rst
+++ b/Help/manual/ctest.1.rst
@@ -1348,6 +1348,23 @@ the :ref:`environment variables <ctest-resource-environment-variables>` to
determine which resources have been allocated to each group. For example,
each group may correspond to a process the test will spawn when executed.
+Note that even if a test specifies a ``RESOURCE_GROUPS`` property, it is still
+possible for that to test to run without any resource allocation (and without
+the corresponding
+:ref:`environment variables <ctest-resource-environment-variables>`)
+if the user does not pass a resource specification file. Passing this file,
+either through the ``--resource-spec-file`` command-line argument or the
+``RESOURCE_SPEC_FILE`` argument to :command:`ctest_test`, is what activates the
+resource allocation feature. Tests should check the
+``CTEST_RESOURCE_GROUP_COUNT`` environment variable to find out whether or not
+resource allocation is activated. This variable will always (and only) be
+defined if resource allocation is activated. If resource allocation is not
+activated, then the ``CTEST_RESOURCE_GROUP_COUNT`` variable will not exist,
+even if it exists for the parent ``ctest`` process. If a test absolutely must
+have resource allocation, then it can return a failing exit code or use the
+:prop_test:`SKIP_RETURN_CODE` or :prop_test:`SKIP_REGULAR_EXPRESSION`
+properties to indicate a skipped test.
+
.. _`ctest-resource-specification-file`:
Resource Specification File
@@ -1362,6 +1379,10 @@ the following resource specification file:
.. code-block:: json
{
+ "version": {
+ "major": 1,
+ "minor": 0
+ },
"local": [
{
"gpus": [
@@ -1393,6 +1414,11 @@ the following resource specification file:
The members are:
+``version``
+ An object containing a ``major`` integer field and a ``minor`` integer field.
+ Currently, the only supported version is major ``1``, minor ``0``. Any other
+ value is an error.
+
``local``
A JSON array of resource sets present on the system. Currently, this array
is restricted to being of size 1.
diff --git a/Help/prop_test/RESOURCE_GROUPS.rst b/Help/prop_test/RESOURCE_GROUPS.rst
index 436451c..63c56ce 100644
--- a/Help/prop_test/RESOURCE_GROUPS.rst
+++ b/Help/prop_test/RESOURCE_GROUPS.rst
@@ -38,6 +38,22 @@ This single group requires 4 slots from a single GPU and 2 slots from a
single cryptography chip. In total, 3 resource groups are specified for this
test, each with its own unique requirements.
+Note that the number of slots following the resource type specifies slots from
+a *single* instance of the resource. If the resource group can tolerate
+receiving slots from different instances of the same resource, it can indicate
+this by splitting the specification into multiple requirements of one slot. For
+example:
+
+.. code-block:: cmake
+
+ add_test(NAME MyTest COMMAND MyExe)
+ set_property(TEST MyTest PROPERTY RESOURCE_GROUPS
+ "gpus:1,gpus:1,gpus:1,gpus:1")
+
+In this case, the single resource group indicates that it needs four GPU slots,
+all of which may come from separate GPUs (though they don't have to; CTest may
+still assign slots from the same GPU.)
+
When CTest sets the :ref:`environment variables
<ctest-resource-environment-variables>` for a test, it assigns a group number
based on the group description, starting at 0 on the left and the number of
diff --git a/Help/prop_tgt/INSTALL_RPATH_USE_LINK_PATH.rst b/Help/prop_tgt/INSTALL_RPATH_USE_LINK_PATH.rst
index d8be954..d16a7a1 100644
--- a/Help/prop_tgt/INSTALL_RPATH_USE_LINK_PATH.rst
+++ b/Help/prop_tgt/INSTALL_RPATH_USE_LINK_PATH.rst
@@ -3,8 +3,12 @@ INSTALL_RPATH_USE_LINK_PATH
Add paths to linker search and installed rpath.
-``INSTALL_RPATH_USE_LINK_PATH`` is a boolean that if set to ``True`` will
-append directories in the linker search path and outside the project
-to the :prop_tgt:`INSTALL_RPATH`. This property is initialized by the value of
-the variable ``CMAKE_INSTALL_RPATH_USE_LINK_PATH`` if it is set when a
-target is created.
+``INSTALL_RPATH_USE_LINK_PATH`` is a boolean that if set to ``True``
+will append to the runtime search path (rpath) of installed binaries
+any directories outside the project that are in the linker search path or
+contain linked library files. The directories are appended after the
+value of the :prop_tgt:`INSTALL_RPATH` target property.
+
+This property is initialized by the value of the variable
+:variable:`CMAKE_INSTALL_RPATH_USE_LINK_PATH` if it is set when a target is
+created.
diff --git a/Help/release/dev/FindLibArchive-target.rst b/Help/release/dev/FindLibArchive-target.rst
new file mode 100644
index 0000000..8998dae
--- /dev/null
+++ b/Help/release/dev/FindLibArchive-target.rst
@@ -0,0 +1,5 @@
+FindLibArchive-target
+---------------------
+
+* The :module:`FindLibArchive` module now returns an ``IMPORTED`` target
+ for libarchive.
diff --git a/Help/release/dev/compiler-launcher-env.rst b/Help/release/dev/compiler-launcher-env.rst
new file mode 100644
index 0000000..58519d9
--- /dev/null
+++ b/Help/release/dev/compiler-launcher-env.rst
@@ -0,0 +1,5 @@
+compiler-launcher-env
+---------------------
+
+* The :envvar:`CMAKE_<LANG>_COMPILER_LAUNCHER` environment variable may now be
+ used to initialize the :variable:`CMAKE_<LANG>_COMPILER_LAUNCHER` variable.
diff --git a/Help/release/dev/ninja-tool.rst b/Help/release/dev/ninja-tool.rst
new file mode 100644
index 0000000..aa0292e
--- /dev/null
+++ b/Help/release/dev/ninja-tool.rst
@@ -0,0 +1,7 @@
+ninja-tool
+----------
+
+* The :generator:`Ninja` generator now prefers the first ninja build
+ tool to appear in the ``PATH`` no matter whether it is called
+ ``ninja-build``, ``ninja``, or ``samu``. Previously the first
+ of those names to appear anywhere in the ``PATH`` would be preferred.
diff --git a/Help/release/dev/xlf-ninja.rst b/Help/release/dev/xlf-ninja.rst
new file mode 100644
index 0000000..916e713
--- /dev/null
+++ b/Help/release/dev/xlf-ninja.rst
@@ -0,0 +1,5 @@
+xlf-ninja
+---------
+
+* The IBM XL Fortran compiler is now supported by the :generator:`Ninja`
+ generator.
diff --git a/Help/variable/CMAKE_HOST_SYSTEM_PROCESSOR.rst b/Help/variable/CMAKE_HOST_SYSTEM_PROCESSOR.rst
index ba8a850..5f08728 100644
--- a/Help/variable/CMAKE_HOST_SYSTEM_PROCESSOR.rst
+++ b/Help/variable/CMAKE_HOST_SYSTEM_PROCESSOR.rst
@@ -3,6 +3,13 @@ CMAKE_HOST_SYSTEM_PROCESSOR
The name of the CPU CMake is running on.
-On systems that support ``uname``, this variable is set to the output of
-``uname -p``. On Windows it is set to the value of the environment variable
-``PROCESSOR_ARCHITECTURE``.
+On Windows, this variable is set to the value of the environment variable
+``PROCESSOR_ARCHITECTURE``. On systems that support ``uname``, this variable is
+set to the output of:
+
+- ``uname -m`` on GNU, Linux, Cygwin, Darwin, Android, or
+- ``arch`` on OpenBSD, or
+- on other systems,
+
+ * ``uname -p`` if its exit code is nonzero, or
+ * ``uname -m`` otherwise.
diff --git a/Help/variable/CMAKE_INSTALL_RPATH_USE_LINK_PATH.rst b/Help/variable/CMAKE_INSTALL_RPATH_USE_LINK_PATH.rst
index 78148d5..a99c108 100644
--- a/Help/variable/CMAKE_INSTALL_RPATH_USE_LINK_PATH.rst
+++ b/Help/variable/CMAKE_INSTALL_RPATH_USE_LINK_PATH.rst
@@ -3,7 +3,11 @@ CMAKE_INSTALL_RPATH_USE_LINK_PATH
Add paths to linker search and installed rpath.
-``CMAKE_INSTALL_RPATH_USE_LINK_PATH`` is a boolean that if set to ``true``
-will append directories in the linker search path and outside the
-project to the :prop_tgt:`INSTALL_RPATH`. This is used to initialize the
-target property :prop_tgt:`INSTALL_RPATH_USE_LINK_PATH` for all targets.
+``CMAKE_INSTALL_RPATH_USE_LINK_PATH`` is a boolean that if set to ``True``
+will append to the runtime search path (rpath) of installed binaries
+any directories outside the project that are in the linker search path or
+contain linked library files. The directories are appended after the
+value of the :prop_tgt:`INSTALL_RPATH` target property.
+
+This varibale is used to initialize the target property
+:prop_tgt:`INSTALL_RPATH_USE_LINK_PATH` for all targets.
diff --git a/Help/variable/CMAKE_LANG_COMPILER_LAUNCHER.rst b/Help/variable/CMAKE_LANG_COMPILER_LAUNCHER.rst
index e6c8bb5..e5dda60 100644
--- a/Help/variable/CMAKE_LANG_COMPILER_LAUNCHER.rst
+++ b/Help/variable/CMAKE_LANG_COMPILER_LAUNCHER.rst
@@ -5,3 +5,6 @@ Default value for :prop_tgt:`<LANG>_COMPILER_LAUNCHER` target property.
This variable is used to initialize the property on each target as it is
created. This is done only when ``<LANG>`` is ``C``, ``CXX``, ``Fortran``,
or ``CUDA``.
+
+This variable is initialized to the :envvar:`CMAKE_<LANG>_COMPILER_LAUNCHER`
+environment variable if it is set.
diff --git a/Modules/CMakeCInformation.cmake b/Modules/CMakeCInformation.cmake
index df43559..1e08bb7 100644
--- a/Modules/CMakeCInformation.cmake
+++ b/Modules/CMakeCInformation.cmake
@@ -110,6 +110,11 @@ if(CMAKE_C_STANDARD_LIBRARIES_INIT)
mark_as_advanced(CMAKE_C_STANDARD_LIBRARIES)
endif()
+if(NOT CMAKE_C_COMPILER_LAUNCHER AND DEFINED ENV{CMAKE_C_COMPILER_LAUNCHER})
+ set(CMAKE_C_COMPILER_LAUNCHER "$ENV{CMAKE_C_COMPILER_LAUNCHER}"
+ CACHE STRING "Compiler launcher for C.")
+endif()
+
include(CMakeCommonLanguageInclude)
# now define the following rule variables
diff --git a/Modules/CMakeCUDACompiler.cmake.in b/Modules/CMakeCUDACompiler.cmake.in
index 711129a..e012abf 100644
--- a/Modules/CMakeCUDACompiler.cmake.in
+++ b/Modules/CMakeCUDACompiler.cmake.in
@@ -17,6 +17,11 @@ set(CMAKE_CUDA_SOURCE_FILE_EXTENSIONS cu)
set(CMAKE_CUDA_LINKER_PREFERENCE 15)
set(CMAKE_CUDA_LINKER_PREFERENCE_PROPAGATES 1)
+set(CMAKE_CUDA_LIBRARY_ARCHITECTURE "@CMAKE_CUDA_LIBRARY_ARCHITECTURE@")
+if(CMAKE_CUDA_LIBRARY_ARCHITECTURE)
+ set(CMAKE_LIBRARY_ARCHITECTURE "@CMAKE_CUDA_LIBRARY_ARCHITECTURE@")
+endif()
+
set(CMAKE_CUDA_TOOLKIT_INCLUDE_DIRECTORIES "@CMAKE_CUDA_TOOLKIT_INCLUDE_DIRECTORIES@")
set(CMAKE_CUDA_HOST_IMPLICIT_LINK_LIBRARIES "@CMAKE_CUDA_HOST_IMPLICIT_LINK_LIBRARIES@")
diff --git a/Modules/CMakeCUDAInformation.cmake b/Modules/CMakeCUDAInformation.cmake
index b0d80d1..974f5fa 100644
--- a/Modules/CMakeCUDAInformation.cmake
+++ b/Modules/CMakeCUDAInformation.cmake
@@ -82,6 +82,11 @@ if(CMAKE_CUDA_STANDARD_LIBRARIES_INIT)
mark_as_advanced(CMAKE_CUDA_STANDARD_LIBRARIES)
endif()
+if(NOT CMAKE_CUDA_COMPILER_LAUNCHER AND DEFINED ENV{CMAKE_CUDA_COMPILER_LAUNCHER})
+ set(CMAKE_CUDA_COMPILER_LAUNCHER "$ENV{CMAKE_CUDA_COMPILER_LAUNCHER}"
+ CACHE STRING "Compiler launcher for CUDA.")
+endif()
+
include(CMakeCommonLanguageInclude)
# now define the following rules:
@@ -93,9 +98,7 @@ include(CMakeCommonLanguageInclude)
# CMAKE_CUDA_LINK_EXECUTABLE
if(CMAKE_CUDA_HOST_COMPILER)
- set(CMAKE_CUDA_HOST_FLAGS "-ccbin=<CMAKE_CUDA_HOST_COMPILER>")
-else()
- set(CMAKE_CUDA_HOST_FLAGS "")
+ string(APPEND _CMAKE_CUDA_EXTRA_FLAGS " -ccbin=<CMAKE_CUDA_HOST_COMPILER>")
endif()
set(__IMPLICT_LINKS )
@@ -135,26 +138,26 @@ endif()
#Specify how to compile when ptx has been requested
if(NOT CMAKE_CUDA_COMPILE_PTX_COMPILATION)
set(CMAKE_CUDA_COMPILE_PTX_COMPILATION
- "<CMAKE_CUDA_COMPILER> ${CMAKE_CUDA_HOST_FLAGS} <DEFINES> <INCLUDES> <FLAGS> -x cu -ptx <SOURCE> -o <OBJECT>")
+ "<CMAKE_CUDA_COMPILER> ${_CMAKE_CUDA_EXTRA_FLAGS} <DEFINES> <INCLUDES> <FLAGS> -x cu -ptx <SOURCE> -o <OBJECT>")
endif()
#Specify how to compile when separable compilation has been requested
if(NOT CMAKE_CUDA_COMPILE_SEPARABLE_COMPILATION)
set(CMAKE_CUDA_COMPILE_SEPARABLE_COMPILATION
- "<CMAKE_CUDA_COMPILER> ${CMAKE_CUDA_HOST_FLAGS} <DEFINES> <INCLUDES> <FLAGS> -x cu -dc <SOURCE> -o <OBJECT>")
+ "<CMAKE_CUDA_COMPILER> ${_CMAKE_CUDA_EXTRA_FLAGS} <DEFINES> <INCLUDES> <FLAGS> -x cu -dc <SOURCE> -o <OBJECT>")
endif()
#Specify how to compile when whole compilation has been requested
if(NOT CMAKE_CUDA_COMPILE_WHOLE_COMPILATION)
set(CMAKE_CUDA_COMPILE_WHOLE_COMPILATION
- "<CMAKE_CUDA_COMPILER> ${CMAKE_CUDA_HOST_FLAGS} <DEFINES> <INCLUDES> <FLAGS> -x cu -c <SOURCE> -o <OBJECT>")
+ "<CMAKE_CUDA_COMPILER> ${_CMAKE_CUDA_EXTRA_FLAGS} <DEFINES> <INCLUDES> <FLAGS> -x cu -c <SOURCE> -o <OBJECT>")
endif()
-if(CMAKE_GENERATOR STREQUAL "Ninja")
+if(CMAKE_GENERATOR STREQUAL "Ninja" AND NOT CMAKE_DEPFILE_FLAGS_CUDA )
set(CMAKE_CUDA_COMPILE_DEPENDENCY_DETECTION
- "<CMAKE_CUDA_COMPILER> ${CMAKE_CUDA_HOST_FLAGS} <DEFINES> <INCLUDES> <FLAGS> -x cu -M <SOURCE> -MT <OBJECT> -o $DEP_FILE")
+ "<CMAKE_CUDA_COMPILER> ${_CMAKE_CUDA_EXTRA_FLAGS} <DEFINES> <INCLUDES> <FLAGS> -x cu -M <SOURCE> -MT <OBJECT> -o $DEP_FILE")
#The Ninja generator uses the make file dependency files to determine what
- #files need to be recompiled. Unfortunately, nvcc doesn't support building
+ #files need to be recompiled. Unfortunately, nvcc < 10.2 doesn't support building
#a source file and generating the dependencies of said file in a single
#invocation. Instead we have to state that you need to chain two commands.
#
@@ -171,13 +174,6 @@ if(NOT CMAKE_CUDA_LINK_EXECUTABLE)
"<CMAKE_CUDA_HOST_LINK_LAUNCHER> <LINK_FLAGS> <OBJECTS> -o <TARGET> <LINK_LIBRARIES>${__IMPLICT_LINKS}")
endif()
-if( CMAKE_CUDA_COMPILER_ID STREQUAL "NVIDIA" AND
- CMAKE_CUDA_COMPILER_VERSION VERSION_GREATER_EQUAL "8.0.0")
- set(_CMAKE_CUDA_EXTRA_DEVICE_LINK_FLAGS "-Wno-deprecated-gpu-targets")
-else()
- set(_CMAKE_CUDA_EXTRA_DEVICE_LINK_FLAGS "")
-endif()
-
# Add implicit host link directories that contain device libraries
# to the device link line.
set(__IMPLICT_DLINK_DIRS ${CMAKE_CUDA_IMPLICIT_LINK_DIRECTORIES})
@@ -192,14 +188,15 @@ foreach(dir ${__IMPLICT_DLINK_DIRS})
endforeach()
unset(__IMPLICT_DLINK_DIRS)
+
#These are used when linking relocatable (dc) cuda code
if(NOT CMAKE_CUDA_DEVICE_LINK_LIBRARY)
set(CMAKE_CUDA_DEVICE_LINK_LIBRARY
- "<CMAKE_CUDA_COMPILER> ${CMAKE_CUDA_HOST_FLAGS} <LANGUAGE_COMPILE_FLAGS> ${CMAKE_CUDA_COMPILE_OPTIONS_PIC} ${_CMAKE_CUDA_EXTRA_DEVICE_LINK_FLAGS} -shared -dlink <OBJECTS> -o <TARGET> <LINK_LIBRARIES>${__IMPLICT_DLINK_FLAGS}")
+ "<CMAKE_CUDA_COMPILER> ${_CMAKE_CUDA_EXTRA_FLAGS} <LANGUAGE_COMPILE_FLAGS> ${CMAKE_CUDA_COMPILE_OPTIONS_PIC} ${_CMAKE_CUDA_EXTRA_DEVICE_LINK_FLAGS} -shared -dlink <OBJECTS> -o <TARGET> <LINK_LIBRARIES>${__IMPLICT_DLINK_FLAGS}")
endif()
if(NOT CMAKE_CUDA_DEVICE_LINK_EXECUTABLE)
set(CMAKE_CUDA_DEVICE_LINK_EXECUTABLE
- "<CMAKE_CUDA_COMPILER> ${CMAKE_CUDA_HOST_FLAGS} <FLAGS> ${CMAKE_CUDA_COMPILE_OPTIONS_PIC} ${_CMAKE_CUDA_EXTRA_DEVICE_LINK_FLAGS} -shared -dlink <OBJECTS> -o <TARGET> <LINK_LIBRARIES>${__IMPLICT_DLINK_FLAGS}")
+ "<CMAKE_CUDA_COMPILER> ${_CMAKE_CUDA_EXTRA_FLAGS} <FLAGS> ${CMAKE_CUDA_COMPILE_OPTIONS_PIC} ${_CMAKE_CUDA_EXTRA_DEVICE_LINK_FLAGS} -shared -dlink <OBJECTS> -o <TARGET> <LINK_LIBRARIES>${__IMPLICT_DLINK_FLAGS}")
endif()
unset(_CMAKE_CUDA_EXTRA_DEVICE_LINK_FLAGS)
diff --git a/Modules/CMakeCXXInformation.cmake b/Modules/CMakeCXXInformation.cmake
index a896b99..da7440a 100644
--- a/Modules/CMakeCXXInformation.cmake
+++ b/Modules/CMakeCXXInformation.cmake
@@ -207,6 +207,11 @@ if(CMAKE_CXX_STANDARD_LIBRARIES_INIT)
mark_as_advanced(CMAKE_CXX_STANDARD_LIBRARIES)
endif()
+if(NOT CMAKE_CXX_COMPILER_LAUNCHER AND DEFINED ENV{CMAKE_CXX_COMPILER_LAUNCHER})
+ set(CMAKE_CXX_COMPILER_LAUNCHER "$ENV{CMAKE_CXX_COMPILER_LAUNCHER}"
+ CACHE STRING "Compiler launcher for CXX.")
+endif()
+
include(CMakeCommonLanguageInclude)
# now define the following rules:
diff --git a/Modules/CMakeDetermineCompilerId.cmake b/Modules/CMakeDetermineCompilerId.cmake
index f7ef755..002fe21 100644
--- a/Modules/CMakeDetermineCompilerId.cmake
+++ b/Modules/CMakeDetermineCompilerId.cmake
@@ -182,6 +182,10 @@ function(CMAKE_DETERMINE_COMPILER_ID lang flagvar src)
message(STATUS "The ${lang} compiler identification is unknown")
endif()
+ if(lang STREQUAL "Fortran" AND CMAKE_${lang}_COMPILER_ID STREQUAL "XL")
+ set(CMAKE_${lang}_XL_CPP "${CMAKE_${lang}_COMPILER_ID_CPP}" PARENT_SCOPE)
+ endif()
+
set(CMAKE_${lang}_COMPILER_ID "${CMAKE_${lang}_COMPILER_ID}" PARENT_SCOPE)
set(CMAKE_${lang}_PLATFORM_ID "${CMAKE_${lang}_PLATFORM_ID}" PARENT_SCOPE)
set(CMAKE_${lang}_COMPILER_ARCHITECTURE_ID "${CMAKE_${lang}_COMPILER_ARCHITECTURE_ID}" PARENT_SCOPE)
@@ -242,7 +246,7 @@ Id flags: ${testflags} ${CMAKE_${lang}_COMPILER_ID_FLAGS_ALWAYS}
set(id_platform ${CMAKE_VS_PLATFORM_NAME})
set(id_lang "${lang}")
set(id_PostBuildEvent_Command "")
- if(CMAKE_VS_PLATFORM_TOOLSET MATCHES "^[Ll][Ll][Vv][Mm](_v[0-9]+(_xp)?)?$")
+ if(CMAKE_VS_PLATFORM_TOOLSET MATCHES "^([Ll][Ll][Vv][Mm](_v[0-9]+(_xp)?)?|[Cc][Ll][Aa][Nn][Gg][Cc][Ll])$")
set(id_cl_var "ClangClExecutable")
elseif(CMAKE_VS_PLATFORM_TOOLSET MATCHES "v[0-9]+_clang_.*")
set(id_cl clang.exe)
@@ -542,6 +546,12 @@ Id flags: ${testflags} ${CMAKE_${lang}_COMPILER_ID_FLAGS_ALWAYS}
ERROR_VARIABLE CMAKE_${lang}_COMPILER_ID_OUTPUT
RESULT_VARIABLE CMAKE_${lang}_COMPILER_ID_RESULT
)
+ if("${CMAKE_${lang}_COMPILER_ID_OUTPUT}" MATCHES "exec: [^\n]*\\((/[^,\n]*/cpp),CMakeFortranCompilerId.F")
+ set(_cpp "${CMAKE_MATCH_1}")
+ if(EXISTS "${_cpp}")
+ set(CMAKE_${lang}_COMPILER_ID_CPP "${_cpp}" PARENT_SCOPE)
+ endif()
+ endif()
endif()
# Check the result of compilation.
diff --git a/Modules/CMakeDetermineFortranCompiler.cmake b/Modules/CMakeDetermineFortranCompiler.cmake
index 5ddd64f..e850541 100644
--- a/Modules/CMakeDetermineFortranCompiler.cmake
+++ b/Modules/CMakeDetermineFortranCompiler.cmake
@@ -271,6 +271,11 @@ include(CMakeFindBinUtils)
include(Compiler/${CMAKE_Fortran_COMPILER_ID}-FindBinUtils OPTIONAL)
unset(_CMAKE_PROCESSING_LANGUAGE)
+if(CMAKE_Fortran_XL_CPP)
+ set(_SET_CMAKE_Fortran_XL_CPP
+ "set(CMAKE_Fortran_XL_CPP \"${CMAKE_Fortran_XL_CPP}\")")
+endif()
+
if(CMAKE_Fortran_COMPILER_ARCHITECTURE_ID)
set(_SET_CMAKE_Fortran_COMPILER_ARCHITECTURE_ID
"set(CMAKE_Fortran_COMPILER_ARCHITECTURE_ID ${CMAKE_Fortran_COMPILER_ARCHITECTURE_ID})")
diff --git a/Modules/CMakeFortranCompiler.cmake.in b/Modules/CMakeFortranCompiler.cmake.in
index ae7b73a..34f44aa 100644
--- a/Modules/CMakeFortranCompiler.cmake.in
+++ b/Modules/CMakeFortranCompiler.cmake.in
@@ -6,6 +6,7 @@ set(CMAKE_Fortran_COMPILER_WRAPPER "@CMAKE_Fortran_COMPILER_WRAPPER@")
set(CMAKE_Fortran_PLATFORM_ID "@CMAKE_Fortran_PLATFORM_ID@")
set(CMAKE_Fortran_SIMULATE_ID "@CMAKE_Fortran_SIMULATE_ID@")
set(CMAKE_Fortran_SIMULATE_VERSION "@CMAKE_Fortran_SIMULATE_VERSION@")
+@_SET_CMAKE_Fortran_XL_CPP@
@_SET_CMAKE_Fortran_COMPILER_ARCHITECTURE_ID@
@SET_MSVC_Fortran_ARCHITECTURE_ID@
set(CMAKE_AR "@CMAKE_AR@")
diff --git a/Modules/CMakeFortranInformation.cmake b/Modules/CMakeFortranInformation.cmake
index ffa6a24..e80716b 100644
--- a/Modules/CMakeFortranInformation.cmake
+++ b/Modules/CMakeFortranInformation.cmake
@@ -163,6 +163,11 @@ set(CMAKE_Fortran_FLAGS_INIT "$ENV{FFLAGS} ${CMAKE_Fortran_FLAGS_INIT}")
cmake_initialize_per_config_variable(CMAKE_Fortran_FLAGS "Flags used by the Fortran compiler")
+if(NOT CMAKE_Fortran_COMPILER_LAUNCHER AND DEFINED ENV{CMAKE_Fortran_COMPILER_LAUNCHER})
+ set(CMAKE_Fortran_COMPILER_LAUNCHER "$ENV{CMAKE_Fortran_COMPILER_LAUNCHER}"
+ CACHE STRING "Compiler launcher for Fortran.")
+endif()
+
include(CMakeCommonLanguageInclude)
# now define the following rule variables
diff --git a/Modules/CMakeNinjaFindMake.cmake b/Modules/CMakeNinjaFindMake.cmake
index 702af13..32f78da 100644
--- a/Modules/CMakeNinjaFindMake.cmake
+++ b/Modules/CMakeNinjaFindMake.cmake
@@ -4,5 +4,6 @@
find_program(CMAKE_MAKE_PROGRAM
NAMES ninja-build ninja samu
+ NAMES_PER_DIR
DOC "Program used to build from build.ninja files.")
mark_as_advanced(CMAKE_MAKE_PROGRAM)
diff --git a/Modules/CMakeParseImplicitIncludeInfo.cmake b/Modules/CMakeParseImplicitIncludeInfo.cmake
index 91d03cd..ff4c325 100644
--- a/Modules/CMakeParseImplicitIncludeInfo.cmake
+++ b/Modules/CMakeParseImplicitIncludeInfo.cmake
@@ -167,7 +167,7 @@ function(cmake_parse_implicit_include_info text lang dir_var log_var state_var)
set(log "")
# go through each line of output...
- string(REGEX REPLACE "\r?\n" ";" output_lines "${text}")
+ string(REGEX REPLACE "\r*\n" ";" output_lines "${text}")
foreach(line IN LISTS output_lines)
if(state STREQUAL start)
string(FIND "${line}" "#include \"...\" search starts here:" rv)
diff --git a/Modules/Compiler/Clang.cmake b/Modules/Compiler/Clang.cmake
index ea5a3b3..5cc9328 100644
--- a/Modules/Compiler/Clang.cmake
+++ b/Modules/Compiler/Clang.cmake
@@ -98,7 +98,9 @@ else()
)
set(CMAKE_PCH_EXTENSION .pch)
- set(CMAKE_PCH_PROLOGUE "#pragma clang system_header")
+ if (NOT CMAKE_GENERATOR MATCHES "Xcode")
+ set(CMAKE_PCH_PROLOGUE "#pragma clang system_header")
+ endif()
set(CMAKE_${lang}_COMPILE_OPTIONS_USE_PCH -Xclang -include-pch -Xclang <PCH_FILE>)
set(CMAKE_${lang}_COMPILE_OPTIONS_CREATE_PCH -Xclang -emit-pch -Xclang -include -Xclang <PCH_HEADER>)
endmacro()
diff --git a/Modules/Compiler/GNU.cmake b/Modules/Compiler/GNU.cmake
index 6960571..1c050a2 100644
--- a/Modules/Compiler/GNU.cmake
+++ b/Modules/Compiler/GNU.cmake
@@ -111,7 +111,9 @@ macro(__compiler_gnu lang)
list(APPEND CMAKE_${lang}_COMPILER_PREDEFINES_COMMAND "-dM" "-E" "-c" "${CMAKE_ROOT}/Modules/CMakeCXXCompilerABI.cpp")
set(CMAKE_PCH_EXTENSION .gch)
- set(CMAKE_PCH_PROLOGUE "#pragma GCC system_header")
+ if (NOT CMAKE_GENERATOR MATCHES "Xcode")
+ set(CMAKE_PCH_PROLOGUE "#pragma GCC system_header")
+ endif()
set(CMAKE_${lang}_COMPILE_OPTIONS_USE_PCH -Winvalid-pch -include <PCH_HEADER>)
set(CMAKE_${lang}_COMPILE_OPTIONS_CREATE_PCH -Winvalid-pch -x ${__pch_header_${lang}} -include <PCH_HEADER>)
endmacro()
diff --git a/Modules/Compiler/NVIDIA-CUDA.cmake b/Modules/Compiler/NVIDIA-CUDA.cmake
index b59deda..2b24fa5 100644
--- a/Modules/Compiler/NVIDIA-CUDA.cmake
+++ b/Modules/Compiler/NVIDIA-CUDA.cmake
@@ -2,6 +2,29 @@ set(CMAKE_CUDA_COMPILER_HAS_DEVICE_LINK_PHASE True)
set(CMAKE_CUDA_VERBOSE_FLAG "-v")
set(CMAKE_CUDA_VERBOSE_COMPILE_FLAG "-Xcompiler=-v")
+if (NOT CMAKE_CUDA_COMPILER_VERSION VERSION_LESS 10.2)
+ # The -forward-unknown-to-host-compiler flag was only
+ # added to nvcc in 10.2 so before that we had no good
+ # way to invoke the CUDA compiler and propagate unknown
+ # flags such as -pthread to the host compiler
+ set(_CMAKE_CUDA_EXTRA_FLAGS "-forward-unknown-to-host-compiler")
+else()
+ set(_CMAKE_CUDA_EXTRA_FLAGS "")
+endif()
+
+if(CMAKE_CUDA_COMPILER_VERSION VERSION_GREATER_EQUAL "8.0.0")
+ set(_CMAKE_CUDA_EXTRA_DEVICE_LINK_FLAGS "-Wno-deprecated-gpu-targets")
+else()
+ set(_CMAKE_CUDA_EXTRA_DEVICE_LINK_FLAGS "")
+endif()
+
+if (NOT CMAKE_CUDA_COMPILER_VERSION VERSION_LESS 10.2)
+ # The -MD flag was only added to nvcc in 10.2 so
+ # before that we had to invoke the compiler twice
+ # to get header dependency information
+ set(CMAKE_DEPFILE_FLAGS_CUDA "-MD -MT <OBJECT> -MF <DEPFILE>")
+endif()
+
if(NOT "x${CMAKE_CUDA_SIMULATE_ID}" STREQUAL "xMSVC")
set(CMAKE_CUDA_COMPILE_OPTIONS_PIE -Xcompiler=-fPIE)
set(CMAKE_CUDA_COMPILE_OPTIONS_PIC -Xcompiler=-fPIC)
diff --git a/Modules/Compiler/XL-Fortran.cmake b/Modules/Compiler/XL-Fortran.cmake
index c4fb097..1683dff 100644
--- a/Modules/Compiler/XL-Fortran.cmake
+++ b/Modules/Compiler/XL-Fortran.cmake
@@ -18,3 +18,7 @@ string(APPEND CMAKE_Fortran_FLAGS_INIT " -qthreaded -qhalt=e")
# xlf: 1501-214 (W) command option E reserved for future use - ignored
set(CMAKE_Fortran_CREATE_PREPROCESSED_SOURCE)
set(CMAKE_Fortran_CREATE_ASSEMBLY_SOURCE)
+
+set(CMAKE_Fortran_PREPROCESS_SOURCE
+ "<CMAKE_Fortran_COMPILER> <DEFINES> <INCLUDES> <FLAGS> -qpreprocess -qnoobject -qsuppress=1517-020 -tF -B \"${CMAKE_CURRENT_LIST_DIR}/XL-Fortran/\" -WF,--cpp,\"${CMAKE_Fortran_XL_CPP}\",--out,<PREPROCESSED_SOURCE> <SOURCE>"
+ )
diff --git a/Modules/Compiler/XL-Fortran/cpp b/Modules/Compiler/XL-Fortran/cpp
new file mode 100755
index 0000000..1fd62c2
--- /dev/null
+++ b/Modules/Compiler/XL-Fortran/cpp
@@ -0,0 +1,29 @@
+#!/usr/bin/env bash
+
+# Source file.
+src="$(printf %q "$1")"
+shift
+
+# Output file the compiler expects.
+out="$(printf %q "$1")"
+shift
+
+# Create the file the compiler expects. It will check syntax.
+>"$out"
+
+cpp='cpp'
+opts=''
+while test "$#" != 0; do
+ case "$1" in
+ # Extract the option for the path to cpp.
+ --cpp) shift; cpp="$(printf %q "$1")" ;;
+ # Extract the option for our own output file.
+ --out) shift; out="$(printf %q "$1")" ;;
+ # Collect the rest of the command line.
+ *) opts="$opts $(printf %q "$1")" ;;
+ esac
+ shift
+done
+
+# Execute the real preprocessor tool.
+eval "exec $cpp $src $out $opts"
diff --git a/Modules/FindBLAS.cmake b/Modules/FindBLAS.cmake
index 77f9d0e..165627e 100644
--- a/Modules/FindBLAS.cmake
+++ b/Modules/FindBLAS.cmake
@@ -517,7 +517,7 @@ if (BLA_VENDOR STREQUAL "ATLAS" OR BLA_VENDOR STREQUAL "All")
BLAS
dgemm
""
- "f77blas;atlas"
+ "blas;f77blas;atlas"
""
)
endif()
diff --git a/Modules/FindLibArchive.cmake b/Modules/FindLibArchive.cmake
index ef27b7d..ce3c8b8 100644
--- a/Modules/FindLibArchive.cmake
+++ b/Modules/FindLibArchive.cmake
@@ -16,18 +16,26 @@ The module defines the following variables:
LibArchive_INCLUDE_DIRS - include search path
LibArchive_LIBRARIES - libraries to link
LibArchive_VERSION - libarchive 3-component version number
+
+The module defines the following ``IMPORTED`` targets:
+
+::
+
+ LibArchive::LibArchive - target for linking against libarchive
#]=======================================================================]
find_path(LibArchive_INCLUDE_DIR
NAMES archive.h
PATHS
"[HKEY_LOCAL_MACHINE\\SOFTWARE\\GnuWin32\\LibArchive;InstallPath]/include"
+ DOC "libarchive include directory"
)
find_library(LibArchive_LIBRARY
NAMES archive libarchive
PATHS
"[HKEY_LOCAL_MACHINE\\SOFTWARE\\GnuWin32\\LibArchive;InstallPath]/lib"
+ DOC "libarchive library"
)
mark_as_advanced(LibArchive_INCLUDE_DIR LibArchive_LIBRARY)
@@ -58,4 +66,11 @@ unset(LIBARCHIVE_FOUND)
if(LibArchive_FOUND)
set(LibArchive_INCLUDE_DIRS ${LibArchive_INCLUDE_DIR})
set(LibArchive_LIBRARIES ${LibArchive_LIBRARY})
+
+ if (NOT TARGET LibArchive::LibArchive)
+ add_library(LibArchive::LibArchive UNKNOWN IMPORTED)
+ set_target_properties(LibArchive::LibArchive PROPERTIES
+ IMPORTED_LOCATION "${LibArchive_LIBRARY}"
+ INTERFACE_INCLUDE_DIRECTORIES "${LibArchive_INCLUDE_DIR}")
+ endif ()
endif()
diff --git a/Modules/FindODBC.cmake b/Modules/FindODBC.cmake
index 29d7af9..3f710db 100644
--- a/Modules/FindODBC.cmake
+++ b/Modules/FindODBC.cmake
@@ -92,6 +92,8 @@ if(WIN32)
# List names of ODBC libraries on Windows
if(NOT MINGW)
set(ODBC_LIBRARY odbc32.lib)
+ else()
+ set(ODBC_LIBRARY libodbc32.a)
endif()
set(_odbc_lib_names odbc32;)
diff --git a/Modules/FindPNG.cmake b/Modules/FindPNG.cmake
index bd400c7..f1fe89a 100644
--- a/Modules/FindPNG.cmake
+++ b/Modules/FindPNG.cmake
@@ -94,6 +94,10 @@ if(ZLIB_FOUND)
set(PNG_INCLUDE_DIRS ${PNG_PNG_INCLUDE_DIR} ${ZLIB_INCLUDE_DIR} )
set(PNG_INCLUDE_DIR ${PNG_INCLUDE_DIRS} ) # for backward compatibility
set(PNG_LIBRARIES ${PNG_LIBRARY} ${ZLIB_LIBRARY})
+ if((CMAKE_SYSTEM_NAME STREQUAL "Linux") AND
+ ("${PNG_LIBRARY}" MATCHES "\\${CMAKE_STATIC_LIBRARY_SUFFIX}$"))
+ list(APPEND PNG_LIBRARIES m)
+ endif()
if (CYGWIN)
if(BUILD_SHARED_LIBS)
@@ -110,6 +114,12 @@ if(ZLIB_FOUND)
INTERFACE_COMPILE_DEFINITIONS "${_PNG_COMPILE_DEFINITIONS}"
INTERFACE_INCLUDE_DIRECTORIES "${PNG_INCLUDE_DIRS}"
INTERFACE_LINK_LIBRARIES ZLIB::ZLIB)
+ if((CMAKE_SYSTEM_NAME STREQUAL "Linux") AND
+ ("${PNG_LIBRARY}" MATCHES "\\${CMAKE_STATIC_LIBRARY_SUFFIX}$"))
+ set_property(TARGET PNG::PNG APPEND PROPERTY
+ INTERFACE_LINK_LIBRARIES m)
+ endif()
+
if(EXISTS "${PNG_LIBRARY}")
set_target_properties(PNG::PNG PROPERTIES
IMPORTED_LINK_INTERFACE_LANGUAGES "C"
diff --git a/Modules/FindPkgConfig.cmake b/Modules/FindPkgConfig.cmake
index 5162a44..f4b6ea1 100644
--- a/Modules/FindPkgConfig.cmake
+++ b/Modules/FindPkgConfig.cmake
@@ -337,7 +337,7 @@ macro(_pkg_set_path_internal)
# remove empty values from the list
list(REMOVE_ITEM _pkgconfig_path "")
file(TO_NATIVE_PATH "${_pkgconfig_path}" _pkgconfig_path)
- if(UNIX)
+ if(CMAKE_HOST_UNIX)
string(REPLACE ";" ":" _pkgconfig_path "${_pkgconfig_path}")
string(REPLACE "\\ " " " _pkgconfig_path "${_pkgconfig_path}")
endif()
diff --git a/Modules/FindThreads.cmake b/Modules/FindThreads.cmake
index 1780511..64576eb 100644
--- a/Modules/FindThreads.cmake
+++ b/Modules/FindThreads.cmake
@@ -77,7 +77,7 @@ macro(_check_threads_lib LIBNAME FUNCNAME VARNAME)
if(NOT Threads_FOUND)
CHECK_LIBRARY_EXISTS(${LIBNAME} ${FUNCNAME} "" ${VARNAME})
if(${VARNAME})
- set(CMAKE_THREAD_LIBS_INIT "${LIBNAME}")
+ set(CMAKE_THREAD_LIBS_INIT "-l${LIBNAME}")
set(CMAKE_HAVE_THREADS_LIBRARY 1)
set(Threads_FOUND TRUE)
endif()
@@ -88,7 +88,7 @@ endmacro()
# Do NOT even think about using it outside of this file!
macro(_check_pthreads_flag)
if(NOT Threads_FOUND)
- # If we did not find a thread library look for -pthread compiler option.
+ # If we did not found -lpthread, -lpthread, or -lthread, look for -pthread
if(NOT DEFINED THREADS_HAVE_PTHREAD_ARG)
message(CHECK_START "Check if compiler accepts -pthread")
if(CMAKE_C_COMPILER_LOADED)
@@ -164,7 +164,7 @@ if(CMAKE_HAVE_PTHREAD_H)
_check_threads_lib(pthreads pthread_create CMAKE_HAVE_PTHREADS_CREATE)
_check_threads_lib(pthread pthread_create CMAKE_HAVE_PTHREAD_CREATE)
if(CMAKE_SYSTEM_NAME MATCHES "SunOS")
- # On sun also check for thread library with thr_create
+ # On sun also check for -lthread
_check_threads_lib(thread thr_create CMAKE_HAVE_THR_CREATE)
endif()
endif()
@@ -195,7 +195,7 @@ if(CMAKE_USE_PTHREADS_INIT)
# are available.
CHECK_LIBRARY_EXISTS(cma pthread_attr_create "" CMAKE_HAVE_HP_CMA)
if(CMAKE_HAVE_HP_CMA)
- set(CMAKE_THREAD_LIBS_INIT "cma")
+ set(CMAKE_THREAD_LIBS_INIT "-lcma")
set(CMAKE_HP_PTHREADS_INIT 1)
set(Threads_FOUND TRUE)
endif()
diff --git a/Modules/FindwxWidgets.cmake b/Modules/FindwxWidgets.cmake
index 798d19a..4334e22 100644
--- a/Modules/FindwxWidgets.cmake
+++ b/Modules/FindwxWidgets.cmake
@@ -649,7 +649,7 @@ if(wxWidgets_FIND_STYLE STREQUAL "win32")
# Find wxWidgets libraries.
WX_FIND_LIBS("${PF}" "${UNV}" "${UCD}" "${DBG}")
if(WX_USE_REL_AND_DBG)
- WX_FIND_LIBS("${UNV}" "${UCD}" "d")
+ WX_FIND_LIBS("${PF}" "${UNV}" "${UCD}" "d")
endif()
# Settings for requested libs (i.e., include dir, libraries, etc.).
diff --git a/Modules/Internal/CPack/CPackNuGet.cmake b/Modules/Internal/CPack/CPackNuGet.cmake
index b46a7b1..1f4bcfd 100644
--- a/Modules/Internal/CPack/CPackNuGet.cmake
+++ b/Modules/Internal/CPack/CPackNuGet.cmake
@@ -239,20 +239,13 @@ function(_cpack_nuget_render_spec)
if(_ver)
_cpack_nuget_debug(" got `${_dep}` dependency version ${_ver}")
- list(APPEND _collected_deps "<dependency id=\"${_dep}\" version=\"${_ver}\" />")
+ string(CONCAT _collected_deps "${_collected_deps}" " <dependency id=\"${_dep}\" version=\"${_ver}\" />\n")
endif()
endforeach()
# Render deps into the variable
if(_collected_deps)
- set(_CPACK_NUGET_DEPENDENCIES_TAG "<dependencies>\n")
- foreach(_line IN LISTS _collected_deps)
- string(
- APPEND _CPACK_NUGET_DEPENDENCIES_TAG
- " ${_line}\n"
- )
- endforeach()
- string(APPEND _CPACK_NUGET_DEPENDENCIES_TAG " </dependencies>")
+ string(CONCAT _CPACK_NUGET_DEPENDENCIES_TAG "<dependencies>\n" "${_collected_deps}" " </dependencies>")
endif()
# Render the spec file
diff --git a/Modules/Platform/Windows-NVIDIA-CUDA.cmake b/Modules/Platform/Windows-NVIDIA-CUDA.cmake
index 94d77b9..30b5aa9 100644
--- a/Modules/Platform/Windows-NVIDIA-CUDA.cmake
+++ b/Modules/Platform/Windows-NVIDIA-CUDA.cmake
@@ -1,11 +1,11 @@
include(Platform/Windows-MSVC)
set(CMAKE_CUDA_COMPILE_PTX_COMPILATION
- "<CMAKE_CUDA_COMPILER> ${CMAKE_CUDA_HOST_FLAGS} <DEFINES> <INCLUDES> <FLAGS> -x cu -ptx <SOURCE> -o <OBJECT> -Xcompiler=-Fd<TARGET_COMPILE_PDB>,-FS")
+ "<CMAKE_CUDA_COMPILER> ${_CMAKE_CUDA_EXTRA_FLAGS} <DEFINES> <INCLUDES> <FLAGS> -x cu -ptx <SOURCE> -o <OBJECT> -Xcompiler=-Fd<TARGET_COMPILE_PDB>,-FS")
set(CMAKE_CUDA_COMPILE_SEPARABLE_COMPILATION
- "<CMAKE_CUDA_COMPILER> ${CMAKE_CUDA_HOST_FLAGS} <DEFINES> <INCLUDES> <FLAGS> -x cu -dc <SOURCE> -o <OBJECT> -Xcompiler=-Fd<TARGET_COMPILE_PDB>,-FS")
+ "<CMAKE_CUDA_COMPILER> ${_CMAKE_CUDA_EXTRA_FLAGS} <DEFINES> <INCLUDES> <FLAGS> -x cu -dc <SOURCE> -o <OBJECT> -Xcompiler=-Fd<TARGET_COMPILE_PDB>,-FS")
set(CMAKE_CUDA_COMPILE_WHOLE_COMPILATION
- "<CMAKE_CUDA_COMPILER> ${CMAKE_CUDA_HOST_FLAGS} <DEFINES> <INCLUDES> <FLAGS> -x cu -c <SOURCE> -o <OBJECT> -Xcompiler=-Fd<TARGET_COMPILE_PDB>,-FS")
+ "<CMAKE_CUDA_COMPILER> ${_CMAKE_CUDA_EXTRA_FLAGS} <DEFINES> <INCLUDES> <FLAGS> -x cu -c <SOURCE> -o <OBJECT> -Xcompiler=-Fd<TARGET_COMPILE_PDB>,-FS")
set(__IMPLICT_LINKS )
foreach(dir ${CMAKE_CUDA_HOST_IMPLICIT_LINK_DIRECTORIES})
@@ -30,11 +30,6 @@ set(CMAKE_CUDA_LINK_EXECUTABLE
unset(_CMAKE_VS_LINK_EXE)
unset(_CMAKE_VS_LINK_EXE)
-if(CMAKE_CUDA_COMPILER_VERSION VERSION_GREATER_EQUAL "8.0.0")
- set(_CMAKE_CUDA_EXTRA_DEVICE_LINK_FLAGS "-Wno-deprecated-gpu-targets")
-else()
- set(_CMAKE_CUDA_EXTRA_DEVICE_LINK_FLAGS "")
-endif()
# Add implicit host link directories that contain device libraries
# to the device link line.
@@ -51,11 +46,9 @@ endforeach()
unset(__IMPLICT_DLINK_DIRS)
set(CMAKE_CUDA_DEVICE_LINK_LIBRARY
- "<CMAKE_CUDA_COMPILER> <LANGUAGE_COMPILE_FLAGS> ${_CMAKE_CUDA_EXTRA_DEVICE_LINK_FLAGS} -shared -dlink <OBJECTS> -o <TARGET> <LINK_LIBRARIES> -Xcompiler=-Fd<TARGET_COMPILE_PDB>,-FS${__IMPLICT_DLINK_FLAGS}")
+ "<CMAKE_CUDA_COMPILER> ${_CMAKE_CUDA_EXTRA_FLAGS} <LANGUAGE_COMPILE_FLAGS> ${_CMAKE_CUDA_EXTRA_DEVICE_LINK_FLAGS} -shared -dlink <OBJECTS> -o <TARGET> <LINK_LIBRARIES> -Xcompiler=-Fd<TARGET_COMPILE_PDB>,-FS${__IMPLICT_DLINK_FLAGS}")
set(CMAKE_CUDA_DEVICE_LINK_EXECUTABLE
- "<CMAKE_CUDA_COMPILER> <FLAGS> ${_CMAKE_CUDA_EXTRA_DEVICE_LINK_FLAGS} -shared -dlink <OBJECTS> -o <TARGET> <LINK_LIBRARIES> -Xcompiler=-Fd<TARGET_COMPILE_PDB>,-FS${__IMPLICT_DLINK_FLAGS}")
-
-unset(_CMAKE_CUDA_EXTRA_DEVICE_LINK_FLAGS)
+ "<CMAKE_CUDA_COMPILER> ${_CMAKE_CUDA_EXTRA_FLAGS} <FLAGS> ${_CMAKE_CUDA_EXTRA_DEVICE_LINK_FLAGS} -shared -dlink <OBJECTS> -o <TARGET> <LINK_LIBRARIES> -Xcompiler=-Fd<TARGET_COMPILE_PDB>,-FS${__IMPLICT_DLINK_FLAGS}")
unset(__IMPLICT_DLINK_FLAGS)
string(REPLACE "/D" "-D" _PLATFORM_DEFINES_CUDA "${_PLATFORM_DEFINES}${_PLATFORM_DEFINES_CXX}")
diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake
index 3f65c67..cdd0893 100644
--- a/Source/CMakeVersion.cmake
+++ b/Source/CMakeVersion.cmake
@@ -1,7 +1,7 @@
# CMake version number components.
set(CMake_VERSION_MAJOR 3)
set(CMake_VERSION_MINOR 16)
-set(CMake_VERSION_PATCH 20191122)
+set(CMake_VERSION_PATCH 20191209)
#set(CMake_VERSION_RC 0)
set(CMake_VERSION_IS_DIRTY 0)
diff --git a/Source/CTest/cmCTestResourceSpec.cxx b/Source/CTest/cmCTestResourceSpec.cxx
index b4a2b30..237a745 100644
--- a/Source/CTest/cmCTestResourceSpec.cxx
+++ b/Source/CTest/cmCTestResourceSpec.cxx
@@ -33,6 +33,32 @@ bool cmCTestResourceSpec::ReadFromJSONFile(const std::string& filename)
return false;
}
+ int majorVersion = 1;
+ int minorVersion = 0;
+ if (root.isMember("version")) {
+ auto const& version = root["version"];
+ if (version.isObject()) {
+ if (!version.isMember("major") || !version.isMember("minor")) {
+ return false;
+ }
+ auto const& major = version["major"];
+ auto const& minor = version["minor"];
+ if (!major.isInt() || !minor.isInt()) {
+ return false;
+ }
+ majorVersion = major.asInt();
+ minorVersion = minor.asInt();
+ } else {
+ return false;
+ }
+ } else {
+ return false;
+ }
+
+ if (majorVersion != 1 || minorVersion != 0) {
+ return false;
+ }
+
auto const& local = root["local"];
if (!local.isArray()) {
return false;
diff --git a/Source/Checks/cm_cxx14_check.cmake b/Source/Checks/cm_cxx14_check.cmake
index 8e9c2c7..e5656bf 100644
--- a/Source/Checks/cm_cxx14_check.cmake
+++ b/Source/Checks/cm_cxx14_check.cmake
@@ -1,5 +1,5 @@
set(CMake_CXX14_BROKEN 0)
-if(CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang|PGI")
+if(CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang|PGI|Intel")
if(NOT CMAKE_CXX14_STANDARD_COMPILE_OPTION)
set(CMake_CXX14_WORKS 0)
endif()
diff --git a/Source/Checks/cm_cxx17_check.cmake b/Source/Checks/cm_cxx17_check.cmake
index 9e1d9c3..dba3eaf 100644
--- a/Source/Checks/cm_cxx17_check.cmake
+++ b/Source/Checks/cm_cxx17_check.cmake
@@ -1,5 +1,5 @@
set(CMake_CXX17_BROKEN 0)
-if(CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang|PGI")
+if(CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang|PGI|Intel")
if(NOT CMAKE_CXX17_STANDARD_COMPILE_OPTION)
set(CMake_CXX17_WORKS 0)
endif()
diff --git a/Source/Checks/cm_cxx17_check.cpp b/Source/Checks/cm_cxx17_check.cpp
index 29863b1..abbe22c 100644
--- a/Source/Checks/cm_cxx17_check.cpp
+++ b/Source/Checks/cm_cxx17_check.cpp
@@ -8,6 +8,13 @@
# include <comdef.h>
#endif
+template <typename T,
+ typename std::invoke_result<decltype(&T::get), T>::type = nullptr>
+typename T::pointer get_ptr(T& item)
+{
+ return item.get();
+}
+
int main()
{
int a[] = { 0, 1, 2 };
@@ -20,6 +27,9 @@ int main()
std::unique_ptr<int> u(new int(0));
+ // Intel compiler do not handle correctly 'decltype' inside 'invoke_result'
+ get_ptr(u);
+
#ifdef _MSC_VER
// clang-cl has problems instantiating this constructor in C++17 mode
// error: indirection requires pointer operand ('const _GUID' invalid)
diff --git a/Source/Checks/cm_cxx_features.cmake b/Source/Checks/cm_cxx_features.cmake
index de8a77a..3b00dfb 100644
--- a/Source/Checks/cm_cxx_features.cmake
+++ b/Source/Checks/cm_cxx_features.cmake
@@ -30,6 +30,8 @@ function(cm_check_cxx_feature name)
string(REGEX REPLACE "[^\n]*warning:[^\n]*sprintf\\(\\) is often misused, please use snprintf[^\n]*" "" check_output "${check_output}")
# Filter out xcodebuild warnings.
string(REGEX REPLACE "[^\n]* xcodebuild\\[[0-9]*:[0-9]*\\] warning: [^\n]*" "" check_output "${check_output}")
+ # Filter out ld warnings.
+ string(REGEX REPLACE "[^\n]*ld: warning: [^\n]*" "" check_output "${check_output}")
# If using the feature causes warnings, treat it as broken/unavailable.
if(check_output MATCHES "(^|[ :])[Ww][Aa][Rr][Nn][Ii][Nn][Gg]")
set(CMake_HAVE_CXX_${FEATURE} OFF CACHE INTERNAL "TRY_COMPILE" FORCE)
diff --git a/Source/cmAddCustomCommandCommand.cxx b/Source/cmAddCustomCommandCommand.cxx
index 6e04ce5..52fc5d5 100644
--- a/Source/cmAddCustomCommandCommand.cxx
+++ b/Source/cmAddCustomCommandCommand.cxx
@@ -343,7 +343,7 @@ bool cmAddCustomCommandCommand(std::vector<std::string> const& args,
// Target is empty, use the output.
mf.AddCustomCommandToOutput(
output, byproducts, depends, main_dependency, implicit_depends,
- commandLines, comment, working.c_str(), false, escapeOldStyle,
+ commandLines, comment, working.c_str(), nullptr, false, escapeOldStyle,
uses_terminal, command_expand_lists, depfile, job_pool);
} else if (!byproducts.empty()) {
status.SetError("BYPRODUCTS may not be specified with SOURCE signatures");
diff --git a/Source/cmAddCustomTargetCommand.cxx b/Source/cmAddCustomTargetCommand.cxx
index e27b126..aa98d89 100644
--- a/Source/cmAddCustomTargetCommand.cxx
+++ b/Source/cmAddCustomTargetCommand.cxx
@@ -6,7 +6,6 @@
#include "cmCheckCustomOutputs.h"
#include "cmCustomCommandLines.h"
-#include "cmCustomCommandTypes.h"
#include "cmExecutionStatus.h"
#include "cmGeneratorExpression.h"
#include "cmGlobalGenerator.h"
@@ -215,9 +214,9 @@ bool cmAddCustomTargetCommand(std::vector<std::string> const& args,
// Add the utility target to the makefile.
bool escapeOldStyle = !verbatim;
cmTarget* target = mf.AddUtilityCommand(
- targetName, cmCommandOrigin::Project, excludeFromAll,
- working_directory.c_str(), byproducts, depends, commandLines,
- escapeOldStyle, comment, uses_terminal, command_expand_lists, job_pool);
+ targetName, excludeFromAll, working_directory.c_str(), byproducts, depends,
+ commandLines, escapeOldStyle, comment, uses_terminal, command_expand_lists,
+ job_pool);
// Add additional user-specified source files to the target.
target->AddSources(sources);
diff --git a/Source/cmAlgorithms.h b/Source/cmAlgorithms.h
index e83f160..def3ac7 100644
--- a/Source/cmAlgorithms.h
+++ b/Source/cmAlgorithms.h
@@ -146,6 +146,14 @@ void cmDeleteAll(Range const& r)
}
template <typename T>
+void cmAppend(std::vector<std::unique_ptr<T>>& v,
+ std::vector<std::unique_ptr<T>>&& r)
+{
+ std::transform(r.begin(), r.end(), std::back_inserter(v),
+ [](std::unique_ptr<T>& item) { return std::move(item); });
+}
+
+template <typename T>
void cmAppend(std::vector<T*>& v, std::vector<std::unique_ptr<T>> const& r)
{
std::transform(r.begin(), r.end(), std::back_inserter(v),
diff --git a/Source/cmCPluginAPI.cxx b/Source/cmCPluginAPI.cxx
index 177bca8..b5c7e96 100644
--- a/Source/cmCPluginAPI.cxx
+++ b/Source/cmCPluginAPI.cxx
@@ -221,10 +221,10 @@ void CCONV cmAddUtilityCommand(void* arg, const char* utilityName,
// Pass the call to the makefile instance.
std::vector<std::string> no_byproducts;
- mf->AddUtilityCommand(utilityName, cmCommandOrigin::Project,
- (all ? false : true), nullptr, no_byproducts, depends2,
- commandLines);
+ mf->AddUtilityCommand(utilityName, (all ? false : true), nullptr,
+ no_byproducts, depends2, commandLines);
}
+
void CCONV cmAddCustomCommand(void* arg, const char* source,
const char* command, int numArgs,
const char** args, int numDepends,
diff --git a/Source/cmCPluginAPI.h b/Source/cmCPluginAPI.h
index 6a95148..19626f0 100644
--- a/Source/cmCPluginAPI.h
+++ b/Source/cmCPluginAPI.h
@@ -36,7 +36,7 @@ typedef struct
of functions are utility functions that are specific to the plugin API
=========================================================================*/
/* set/Get the ClientData in the cmLoadedCommandInfo structure, this is how
- information is passed from the InitialPass to FInalPass for commands
+ information is passed from the InitialPass to FinalPass for commands
that need a FinalPass and need information from the InitialPass */
void*(CCONV* GetClientData)(void* info);
/* return the summed size in characters of all the arguments */
@@ -44,7 +44,7 @@ typedef struct
/* free all the memory associated with an argc, argv pair */
void(CCONV* FreeArguments)(int argc, char** argv);
/* set/Get the ClientData in the cmLoadedCommandInfo structure, this is how
- information is passed from the InitialPass to FInalPass for commands
+ information is passed from the InitialPass to FinalPass for commands
that need a FinalPass and need information from the InitialPass */
void(CCONV* SetClientData)(void* info, void* cd);
/* when an error occurs, call this function to set the error string */
diff --git a/Source/cmCustomCommand.cxx b/Source/cmCustomCommand.cxx
index 09d269b..7cc3c04 100644
--- a/Source/cmCustomCommand.cxx
+++ b/Source/cmCustomCommand.cxx
@@ -5,26 +5,22 @@
#include <utility>
#include "cmAlgorithms.h"
-#include "cmMakefile.h"
-cmCustomCommand::cmCustomCommand(cmMakefile const* mf,
- std::vector<std::string> outputs,
+cmCustomCommand::cmCustomCommand(std::vector<std::string> outputs,
std::vector<std::string> byproducts,
std::vector<std::string> depends,
cmCustomCommandLines commandLines,
- const char* comment,
+ cmListFileBacktrace lfbt, const char* comment,
const char* workingDirectory)
: Outputs(std::move(outputs))
, Byproducts(std::move(byproducts))
, Depends(std::move(depends))
, CommandLines(std::move(commandLines))
+ , Backtrace(std::move(lfbt))
, Comment(comment ? comment : "")
, WorkingDirectory(workingDirectory ? workingDirectory : "")
, HaveComment(comment != nullptr)
{
- if (mf) {
- this->Backtrace = mf->GetBacktrace();
- }
}
const std::vector<std::string>& cmCustomCommand::GetOutputs() const
diff --git a/Source/cmCustomCommand.h b/Source/cmCustomCommand.h
index 4689ace..d300fa5 100644
--- a/Source/cmCustomCommand.h
+++ b/Source/cmCustomCommand.h
@@ -12,8 +12,6 @@
#include "cmCustomCommandLines.h"
#include "cmListFileCache.h"
-class cmMakefile;
-
class cmImplicitDependsList
: public std::vector<std::pair<std::string, std::string>>
{
@@ -28,11 +26,11 @@ class cmCustomCommand
{
public:
/** Main constructor specifies all information for the command. */
- cmCustomCommand(cmMakefile const* mf, std::vector<std::string> outputs,
+ cmCustomCommand(std::vector<std::string> outputs,
std::vector<std::string> byproducts,
std::vector<std::string> depends,
- cmCustomCommandLines commandLines, const char* comment,
- const char* workingDirectory);
+ cmCustomCommandLines commandLines, cmListFileBacktrace lfbt,
+ const char* comment, const char* workingDirectory);
/** Get the output file produced by the command. */
const std::vector<std::string>& GetOutputs() const;
diff --git a/Source/cmExportLibraryDependenciesCommand.cxx b/Source/cmExportLibraryDependenciesCommand.cxx
index 89093e9..dfc8de5 100644
--- a/Source/cmExportLibraryDependenciesCommand.cxx
+++ b/Source/cmExportLibraryDependenciesCommand.cxx
@@ -12,6 +12,7 @@
#include "cmExecutionStatus.h"
#include "cmGeneratedFileStream.h"
#include "cmGlobalGenerator.h"
+#include "cmLocalGenerator.h"
#include "cmMakefile.h"
#include "cmStateTypes.h"
#include "cmStringAlgorithms.h"
@@ -20,6 +21,8 @@
#include "cmTargetLinkLibraryType.h"
#include "cmake.h"
+class cmListFileBacktrace;
+
static void FinalAction(cmMakefile& makefile, std::string const& filename,
bool append)
{
@@ -150,9 +153,9 @@ bool cmExportLibraryDependenciesCommand(std::vector<std::string> const& args,
std::string const& filename = args[0];
bool const append = args.size() > 1 && args[1] == "APPEND";
- status.GetMakefile().AddFinalAction(
- [filename, append](cmMakefile& makefile) {
- FinalAction(makefile, filename, append);
+ status.GetMakefile().AddGeneratorAction(
+ [filename, append](cmLocalGenerator& lg, const cmListFileBacktrace&) {
+ FinalAction(*lg.GetMakefile(), filename, append);
});
return true;
diff --git a/Source/cmFLTKWrapUICommand.cxx b/Source/cmFLTKWrapUICommand.cxx
index 11844e4..d88617a 100644
--- a/Source/cmFLTKWrapUICommand.cxx
+++ b/Source/cmFLTKWrapUICommand.cxx
@@ -6,15 +6,20 @@
#include "cmCustomCommandLines.h"
#include "cmExecutionStatus.h"
+#include "cmListFileCache.h"
+#include "cmLocalGenerator.h"
#include "cmMakefile.h"
+#include "cmMessageType.h"
#include "cmRange.h"
#include "cmSourceFile.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
+#include "cmake.h"
class cmTarget;
-static void FinalAction(cmMakefile& makefile, std::string const& name)
+static void FinalAction(cmMakefile& makefile, std::string const& name,
+ const cmListFileBacktrace& lfbt)
{
// people should add the srcs to the target themselves, but the old command
// didn't support that, so check and see if they added the files in and if
@@ -26,7 +31,8 @@ static void FinalAction(cmMakefile& makefile, std::string const& name)
". The problem was found while processing the source directory: ",
makefile.GetCurrentSourceDirectory(),
". This FLTK_WRAP_UI call will be ignored.");
- cmSystemTools::Message(msg, "Warning");
+ makefile.GetCMakeInstance()->IssueMessage(MessageType::AUTHOR_ERROR, msg,
+ lfbt);
}
}
@@ -116,7 +122,9 @@ bool cmFLTKWrapUICommand(std::vector<std::string> const& args,
std::string const varName = target + "_FLTK_UI_SRCS";
mf.AddDefinition(varName, sourceListValue);
- mf.AddFinalAction(
- [target](cmMakefile& makefile) { FinalAction(makefile, target); });
+ mf.AddGeneratorAction(
+ [target](cmLocalGenerator& lg, const cmListFileBacktrace& lfbt) {
+ FinalAction(*lg.GetMakefile(), target, lfbt);
+ });
return true;
}
diff --git a/Source/cmGeneratorExpression.cxx b/Source/cmGeneratorExpression.cxx
index de43d3e..81d1e46 100644
--- a/Source/cmGeneratorExpression.cxx
+++ b/Source/cmGeneratorExpression.cxx
@@ -8,7 +8,6 @@
#include "cmsys/RegularExpression.hxx"
-#include "cmAlgorithms.h"
#include "cmGeneratorExpressionContext.h"
#include "cmGeneratorExpressionDAGChecker.h"
#include "cmGeneratorExpressionEvaluator.h"
@@ -22,6 +21,8 @@ cmGeneratorExpression::cmGeneratorExpression(cmListFileBacktrace backtrace)
{
}
+cmCompiledGeneratorExpression::~cmCompiledGeneratorExpression() = default;
+
cmGeneratorExpression::~cmGeneratorExpression() = default;
std::unique_ptr<cmCompiledGeneratorExpression> cmGeneratorExpression::Parse(
@@ -86,7 +87,7 @@ const std::string& cmCompiledGeneratorExpression::EvaluateWithContext(
this->Output.clear();
- for (const cmGeneratorExpressionEvaluator* it : this->Evaluators) {
+ for (const auto& it : this->Evaluators) {
this->Output += it->Evaluate(&context, dagChecker);
this->SeenTargetProperties.insert(context.SeenTargetProperties.cbegin(),
@@ -129,11 +130,6 @@ cmCompiledGeneratorExpression::cmCompiledGeneratorExpression(
}
}
-cmCompiledGeneratorExpression::~cmCompiledGeneratorExpression()
-{
- cmDeleteAll(this->Evaluators);
-}
-
std::string cmGeneratorExpression::StripEmptyListElements(
const std::string& input)
{
diff --git a/Source/cmGeneratorExpression.h b/Source/cmGeneratorExpression.h
index cd35e1e..c4be3a1 100644
--- a/Source/cmGeneratorExpression.h
+++ b/Source/cmGeneratorExpression.h
@@ -163,7 +163,7 @@ private:
friend class cmGeneratorExpression;
cmListFileBacktrace Backtrace;
- std::vector<cmGeneratorExpressionEvaluator*> Evaluators;
+ std::vector<std::unique_ptr<cmGeneratorExpressionEvaluator>> Evaluators;
const std::string Input;
bool NeedsEvaluation;
bool EvaluateForBuildsystem;
diff --git a/Source/cmGeneratorExpressionEvaluator.cxx b/Source/cmGeneratorExpressionEvaluator.cxx
index e0ae170..4129a0c 100644
--- a/Source/cmGeneratorExpressionEvaluator.cxx
+++ b/Source/cmGeneratorExpressionEvaluator.cxx
@@ -2,10 +2,8 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmGeneratorExpressionEvaluator.h"
-#include <algorithm>
#include <sstream>
-#include "cmAlgorithms.h"
#include "cmGeneratorExpressionContext.h"
#include "cmGeneratorExpressionNode.h"
@@ -16,6 +14,8 @@ GeneratorExpressionContent::GeneratorExpressionContent(
{
}
+GeneratorExpressionContent::~GeneratorExpressionContent() = default;
+
std::string GeneratorExpressionContent::GetOriginalExpression() const
{
return std::string(this->StartContent, this->ContentLength);
@@ -25,14 +25,13 @@ std::string GeneratorExpressionContent::ProcessArbitraryContent(
const cmGeneratorExpressionNode* node, const std::string& identifier,
cmGeneratorExpressionContext* context,
cmGeneratorExpressionDAGChecker* dagChecker,
- std::vector<std::vector<cmGeneratorExpressionEvaluator*>>::const_iterator
- pit) const
+ std::vector<cmGeneratorExpressionEvaluatorVector>::const_iterator pit) const
{
std::string result;
const auto pend = this->ParamChildren.end();
for (; pit != pend; ++pit) {
- for (cmGeneratorExpressionEvaluator* pExprEval : *pit) {
+ for (auto& pExprEval : *pit) {
if (node->RequiresLiteralInput()) {
if (pExprEval->GetType() != cmGeneratorExpressionEvaluator::Text) {
reportError(context, this->GetOriginalExpression(),
@@ -64,8 +63,7 @@ std::string GeneratorExpressionContent::Evaluate(
{
std::string identifier;
{
- for (cmGeneratorExpressionEvaluator* pExprEval :
- this->IdentifierChildren) {
+ for (auto& pExprEval : this->IdentifierChildren) {
identifier += pExprEval->Evaluate(context, dagChecker);
if (context->HadError) {
return std::string();
@@ -126,7 +124,7 @@ std::string GeneratorExpressionContent::EvaluateParameters(
return std::string();
}
std::string parameter;
- for (cmGeneratorExpressionEvaluator* pExprEval : *pit) {
+ for (auto& pExprEval : *pit) {
parameter += pExprEval->Evaluate(context, dagChecker);
if (context->HadError) {
return std::string();
@@ -174,10 +172,3 @@ std::string GeneratorExpressionContent::EvaluateParameters(
}
return std::string();
}
-
-GeneratorExpressionContent::~GeneratorExpressionContent()
-{
- cmDeleteAll(this->IdentifierChildren);
- std::for_each(this->ParamChildren.begin(), this->ParamChildren.end(),
- cmDeleteAll<std::vector<cmGeneratorExpressionEvaluator*>>);
-}
diff --git a/Source/cmGeneratorExpressionEvaluator.h b/Source/cmGeneratorExpressionEvaluator.h
index b10bb5b..10496fd 100644
--- a/Source/cmGeneratorExpressionEvaluator.h
+++ b/Source/cmGeneratorExpressionEvaluator.h
@@ -6,6 +6,7 @@
#include "cmConfigure.h" // IWYU pragma: keep
#include <cstddef>
+#include <memory>
#include <string>
#include <utility>
#include <vector>
@@ -36,6 +37,9 @@ struct cmGeneratorExpressionEvaluator
cmGeneratorExpressionDAGChecker*) const = 0;
};
+using cmGeneratorExpressionEvaluatorVector =
+ std::vector<std::unique_ptr<cmGeneratorExpressionEvaluator>>;
+
struct TextContent : public cmGeneratorExpressionEvaluator
{
TextContent(const char* start, size_t length)
@@ -68,13 +72,13 @@ struct GeneratorExpressionContent : public cmGeneratorExpressionEvaluator
{
GeneratorExpressionContent(const char* startContent, size_t length);
- void SetIdentifier(std::vector<cmGeneratorExpressionEvaluator*> identifier)
+ void SetIdentifier(cmGeneratorExpressionEvaluatorVector&& identifier)
{
this->IdentifierChildren = std::move(identifier);
}
void SetParameters(
- std::vector<std::vector<cmGeneratorExpressionEvaluator*>> parameters)
+ std::vector<cmGeneratorExpressionEvaluatorVector>&& parameters)
{
this->ParamChildren = std::move(parameters);
}
@@ -102,12 +106,12 @@ private:
const cmGeneratorExpressionNode* node, const std::string& identifier,
cmGeneratorExpressionContext* context,
cmGeneratorExpressionDAGChecker* dagChecker,
- std::vector<std::vector<cmGeneratorExpressionEvaluator*>>::const_iterator
- pit) const;
+ std::vector<cmGeneratorExpressionEvaluatorVector>::const_iterator pit)
+ const;
private:
- std::vector<cmGeneratorExpressionEvaluator*> IdentifierChildren;
- std::vector<std::vector<cmGeneratorExpressionEvaluator*>> ParamChildren;
+ cmGeneratorExpressionEvaluatorVector IdentifierChildren;
+ std::vector<cmGeneratorExpressionEvaluatorVector> ParamChildren;
const char* StartContent;
size_t ContentLength;
};
diff --git a/Source/cmGeneratorExpressionParser.cxx b/Source/cmGeneratorExpressionParser.cxx
index d6cc6ab..4159a7b 100644
--- a/Source/cmGeneratorExpressionParser.cxx
+++ b/Source/cmGeneratorExpressionParser.cxx
@@ -6,6 +6,9 @@
#include <cstddef>
#include <utility>
+#include <cm/memory>
+#include <cmext/memory>
+
#include "cmAlgorithms.h"
#include "cmGeneratorExpressionEvaluator.h"
@@ -17,7 +20,7 @@ cmGeneratorExpressionParser::cmGeneratorExpressionParser(
}
void cmGeneratorExpressionParser::Parse(
- std::vector<cmGeneratorExpressionEvaluator*>& result)
+ cmGeneratorExpressionEvaluatorVector& result)
{
it = this->Tokens.begin();
@@ -27,40 +30,38 @@ void cmGeneratorExpressionParser::Parse(
}
static void extendText(
- std::vector<cmGeneratorExpressionEvaluator*>& result,
+ cmGeneratorExpressionEvaluatorVector& result,
std::vector<cmGeneratorExpressionToken>::const_iterator it)
{
if (!result.empty() &&
(*(result.end() - 1))->GetType() ==
cmGeneratorExpressionEvaluator::Text) {
- TextContent* textContent = static_cast<TextContent*>(*(result.end() - 1));
- textContent->Extend(it->Length);
+ cm::static_reference_cast<TextContent>(*(result.end() - 1))
+ .Extend(it->Length);
} else {
- TextContent* textContent = new TextContent(it->Content, it->Length);
- result.push_back(textContent);
+ auto textContent = cm::make_unique<TextContent>(it->Content, it->Length);
+ result.push_back(std::move(textContent));
}
}
static void extendResult(
- std::vector<cmGeneratorExpressionEvaluator*>& result,
- const std::vector<cmGeneratorExpressionEvaluator*>& contents)
+ cmGeneratorExpressionParser::cmGeneratorExpressionEvaluatorVector& result,
+ cmGeneratorExpressionParser::cmGeneratorExpressionEvaluatorVector&& contents)
{
if (!result.empty() &&
(*(result.end() - 1))->GetType() ==
cmGeneratorExpressionEvaluator::Text &&
contents.front()->GetType() == cmGeneratorExpressionEvaluator::Text) {
- TextContent* textContent = static_cast<TextContent*>(*(result.end() - 1));
- textContent->Extend(
- static_cast<TextContent*>(contents.front())->GetLength());
- delete contents.front();
- cmAppend(result, contents.begin() + 1, contents.end());
- } else {
- cmAppend(result, contents);
+ cm::static_reference_cast<TextContent>(*(result.end() - 1))
+ .Extend(
+ cm::static_reference_cast<TextContent>(contents.front()).GetLength());
+ contents.erase(contents.begin());
}
+ cmAppend(result, std::move(contents));
}
void cmGeneratorExpressionParser::ParseGeneratorExpression(
- std::vector<cmGeneratorExpressionEvaluator*>& result)
+ cmGeneratorExpressionEvaluatorVector& result)
{
assert(this->it != this->Tokens.end());
unsigned int nestedLevel = this->NestingLevel;
@@ -68,7 +69,7 @@ void cmGeneratorExpressionParser::ParseGeneratorExpression(
auto startToken = this->it - 1;
- std::vector<cmGeneratorExpressionEvaluator*> identifier;
+ cmGeneratorExpressionEvaluatorVector identifier;
while (this->it->TokenType != cmGeneratorExpressionToken::EndExpression &&
this->it->TokenType != cmGeneratorExpressionToken::ColonSeparator) {
if (this->it->TokenType == cmGeneratorExpressionToken::CommaSeparator) {
@@ -87,18 +88,18 @@ void cmGeneratorExpressionParser::ParseGeneratorExpression(
if (this->it != this->Tokens.end() &&
this->it->TokenType == cmGeneratorExpressionToken::EndExpression) {
- GeneratorExpressionContent* content = new GeneratorExpressionContent(
+ auto content = cm::make_unique<GeneratorExpressionContent>(
startToken->Content,
this->it->Content - startToken->Content + this->it->Length);
assert(this->it != this->Tokens.end());
++this->it;
--this->NestingLevel;
content->SetIdentifier(std::move(identifier));
- result.push_back(content);
+ result.push_back(std::move(content));
return;
}
- std::vector<std::vector<cmGeneratorExpressionEvaluator*>> parameters;
+ std::vector<cmGeneratorExpressionEvaluatorVector> parameters;
std::vector<std::vector<cmGeneratorExpressionToken>::const_iterator>
commaTokens;
std::vector<cmGeneratorExpressionToken>::const_iterator colonToken;
@@ -169,7 +170,7 @@ void cmGeneratorExpressionParser::ParseGeneratorExpression(
// treat the '$<' as having been plain text, along with the
// corresponding : and , tokens that might have been found.
extendText(result, startToken);
- extendResult(result, identifier);
+ extendResult(result, std::move(identifier));
if (!parameters.empty()) {
extendText(result, colonToken);
@@ -179,7 +180,7 @@ void cmGeneratorExpressionParser::ParseGeneratorExpression(
assert(parameters.size() > commaTokens.size());
for (; pit != pend; ++pit, ++commaIt) {
if (!pit->empty() && !emptyParamTermination) {
- extendResult(result, *pit);
+ extendResult(result, std::move(*pit));
}
if (commaIt != commaTokens.end()) {
extendText(result, *commaIt);
@@ -193,15 +194,15 @@ void cmGeneratorExpressionParser::ParseGeneratorExpression(
size_t contentLength =
((this->it - 1)->Content - startToken->Content) + (this->it - 1)->Length;
- GeneratorExpressionContent* content =
- new GeneratorExpressionContent(startToken->Content, contentLength);
+ auto content = cm::make_unique<GeneratorExpressionContent>(
+ startToken->Content, contentLength);
content->SetIdentifier(std::move(identifier));
content->SetParameters(std::move(parameters));
- result.push_back(content);
+ result.push_back(std::move(content));
}
void cmGeneratorExpressionParser::ParseContent(
- std::vector<cmGeneratorExpressionEvaluator*>& result)
+ cmGeneratorExpressionEvaluatorVector& result)
{
assert(this->it != this->Tokens.end());
switch (this->it->TokenType) {
@@ -213,17 +214,16 @@ void cmGeneratorExpressionParser::ParseContent(
// A comma in 'plain text' could have split text that should
// otherwise be continuous. Extend the last text content instead of
// creating a new one.
- TextContent* textContent =
- static_cast<TextContent*>(*(result.end() - 1));
- textContent->Extend(this->it->Length);
+ cm::static_reference_cast<TextContent>(*(result.end() - 1))
+ .Extend(this->it->Length);
assert(this->it != this->Tokens.end());
++this->it;
return;
}
}
- cmGeneratorExpressionEvaluator* n =
- new TextContent(this->it->Content, this->it->Length);
- result.push_back(n);
+ auto n =
+ cm::make_unique<TextContent>(this->it->Content, this->it->Length);
+ result.push_back(std::move(n));
assert(this->it != this->Tokens.end());
++this->it;
return;
diff --git a/Source/cmGeneratorExpressionParser.h b/Source/cmGeneratorExpressionParser.h
index e663496..1ba1654 100644
--- a/Source/cmGeneratorExpressionParser.h
+++ b/Source/cmGeneratorExpressionParser.h
@@ -5,6 +5,7 @@
#include "cmConfigure.h" // IWYU pragma: keep
+#include <memory>
#include <vector>
#include "cmGeneratorExpressionLexer.h"
@@ -15,11 +16,14 @@ struct cmGeneratorExpressionParser
{
cmGeneratorExpressionParser(std::vector<cmGeneratorExpressionToken> tokens);
- void Parse(std::vector<cmGeneratorExpressionEvaluator*>& result);
+ using cmGeneratorExpressionEvaluatorVector =
+ std::vector<std::unique_ptr<cmGeneratorExpressionEvaluator>>;
+
+ void Parse(cmGeneratorExpressionEvaluatorVector& result);
private:
- void ParseContent(std::vector<cmGeneratorExpressionEvaluator*>&);
- void ParseGeneratorExpression(std::vector<cmGeneratorExpressionEvaluator*>&);
+ void ParseContent(cmGeneratorExpressionEvaluatorVector&);
+ void ParseGeneratorExpression(cmGeneratorExpressionEvaluatorVector&);
private:
std::vector<cmGeneratorExpressionToken>::const_iterator it;
diff --git a/Source/cmGlobalGenerator.cxx b/Source/cmGlobalGenerator.cxx
index e38066f..0e782f2 100644
--- a/Source/cmGlobalGenerator.cxx
+++ b/Source/cmGlobalGenerator.cxx
@@ -34,6 +34,7 @@
#include "cmGeneratorTarget.h"
#include "cmInstallGenerator.h"
#include "cmLinkLineComputer.h"
+#include "cmListFileCache.h"
#include "cmLocalGenerator.h"
#include "cmMSVC60LinkLineComputer.h"
#include "cmMakefile.h"
@@ -1262,10 +1263,6 @@ void cmGlobalGenerator::Configure()
"number of local generators",
cmStateEnums::INTERNAL);
- // check for link libraries and include directories containing "NOTFOUND"
- // and for infinite loops
- this->CheckTargetProperties();
-
if (this->CMakeInstance->GetWorkingMode() == cmake::NORMAL_MODE) {
std::ostringstream msg;
if (cmSystemTools::GetErrorOccuredFlag()) {
@@ -1288,6 +1285,10 @@ void cmGlobalGenerator::Configure()
void cmGlobalGenerator::CreateGenerationObjects(TargetTypes targetTypes)
{
this->CreateLocalGenerators();
+ // Commit side effects only if we are actually generating
+ if (this->GetConfigureDoneCMP0026()) {
+ this->CheckTargetProperties();
+ }
this->CreateGeneratorTargets(targetTypes);
this->ComputeBuildFileGenerators();
}
@@ -1464,6 +1465,8 @@ void cmGlobalGenerator::Generate()
this->ProcessEvaluationFiles();
+ this->CMakeInstance->UpdateProgress("Generating", 0.1f);
+
// Generate project files
for (unsigned int i = 0; i < this->LocalGenerators.size(); ++i) {
this->SetCurrentMakefile(this->LocalGenerators[i]->GetMakefile());
@@ -1475,8 +1478,9 @@ void cmGlobalGenerator::Generate()
this->LocalGenerators[i]->GenerateTestFiles();
this->CMakeInstance->UpdateProgress(
"Generating",
- (static_cast<float>(i) + 1.0f) /
- static_cast<float>(this->LocalGenerators.size()));
+ 0.1f +
+ 0.9f * (static_cast<float>(i) + 1.0f) /
+ static_cast<float>(this->LocalGenerators.size()));
}
this->SetCurrentMakefile(nullptr);
@@ -1562,13 +1566,24 @@ bool cmGlobalGenerator::AddAutomaticSources()
for (cmLocalGenerator* lg : this->LocalGenerators) {
lg->CreateEvaluationFileOutputs();
for (const auto& gt : lg->GetGeneratorTargets()) {
- if (gt->GetType() == cmStateEnums::INTERFACE_LIBRARY) {
+ if (gt->GetType() == cmStateEnums::INTERFACE_LIBRARY ||
+ gt->GetType() == cmStateEnums::UTILITY ||
+ gt->GetType() == cmStateEnums::GLOBAL_TARGET) {
continue;
}
lg->AddUnityBuild(gt.get());
lg->AddPchDependencies(gt.get());
}
}
+ // The above transformations may have changed the classification of sources.
+ // Clear the source list and classification cache (KindedSources) of all
+ // targets so that it will be recomputed correctly by the generators later
+ // now that the above transformations are done for all targets.
+ for (cmLocalGenerator* lg : this->LocalGenerators) {
+ for (const auto& gt : lg->GetGeneratorTargets()) {
+ gt->ClearSourcesCache();
+ }
+ }
return true;
}
@@ -1714,12 +1729,12 @@ void cmGlobalGenerator::ComputeTargetObjectDirectory(
void cmGlobalGenerator::CheckTargetProperties()
{
+ // check for link libraries and include directories containing "NOTFOUND"
+ // and for infinite loops
std::map<std::string, std::string> notFoundMap;
- // std::set<std::string> notFoundMap;
- // after it is all done do a ConfigureFinalPass
cmState* state = this->GetCMakeInstance()->GetState();
for (unsigned int i = 0; i < this->Makefiles.size(); ++i) {
- this->Makefiles[i]->ConfigureFinalPass();
+ this->Makefiles[i]->Generate(*this->LocalGenerators[i]);
for (auto const& target : this->Makefiles[i]->GetTargets()) {
if (target.second.GetType() == cmStateEnums::INTERFACE_LIBRARY) {
continue;
@@ -1763,11 +1778,6 @@ void cmGlobalGenerator::CheckTargetProperties()
}
}
}
- this->CMakeInstance->UpdateProgress(
- "Configuring",
- 0.9f +
- 0.1f * (static_cast<float>(i) + 1.0f) /
- static_cast<float>(this->Makefiles.size()));
}
if (!notFoundMap.empty()) {
@@ -2017,10 +2027,10 @@ void cmGlobalGenerator::AddMakefile(cmMakefile* mf)
}
int numGen = atoi(numGenC->c_str());
- float prog = 0.9f * static_cast<float>(this->Makefiles.size()) /
- static_cast<float>(numGen);
- if (prog > 0.9f) {
- prog = 0.9f;
+ float prog =
+ static_cast<float>(this->Makefiles.size()) / static_cast<float>(numGen);
+ if (prog > 1.0f) {
+ prog = 1.0f;
}
this->CMakeInstance->UpdateProgress("Configuring", prog);
}
@@ -2652,8 +2662,8 @@ cmTarget cmGlobalGenerator::CreateGlobalTarget(GlobalTargetInfo const& gti,
std::vector<std::string> no_byproducts;
std::vector<std::string> no_depends;
// Store the custom command in the target.
- cmCustomCommand cc(nullptr, no_outputs, no_byproducts, no_depends,
- gti.CommandLines, nullptr, gti.WorkingDir.c_str());
+ cmCustomCommand cc(no_outputs, no_byproducts, no_depends, gti.CommandLines,
+ cmListFileBacktrace(), nullptr, gti.WorkingDir.c_str());
cc.SetUsesTerminal(gti.UsesTerminal);
target.AddPostBuildCommand(std::move(cc));
if (!gti.Message.empty()) {
diff --git a/Source/cmGlobalVisualStudio8Generator.cxx b/Source/cmGlobalVisualStudio8Generator.cxx
index d39d42a..ea603b0 100644
--- a/Source/cmGlobalVisualStudio8Generator.cxx
+++ b/Source/cmGlobalVisualStudio8Generator.cxx
@@ -101,15 +101,14 @@ bool cmGlobalVisualStudio8Generator::AddCheckTarget()
std::vector<cmLocalGenerator*> const& generators = this->LocalGenerators;
cmLocalVisualStudio7Generator* lg =
static_cast<cmLocalVisualStudio7Generator*>(generators[0]);
- cmMakefile* mf = lg->GetMakefile();
const char* no_working_directory = nullptr;
std::vector<std::string> no_byproducts;
std::vector<std::string> no_depends;
cmCustomCommandLines no_commands;
- cmTarget* tgt = mf->AddUtilityCommand(
- CMAKE_CHECK_BUILD_SYSTEM_TARGET, cmCommandOrigin::Generator, false,
- no_working_directory, no_byproducts, no_depends, no_commands);
+ cmTarget* tgt = lg->AddUtilityCommand(CMAKE_CHECK_BUILD_SYSTEM_TARGET, false,
+ no_working_directory, no_byproducts,
+ no_depends, no_commands);
auto ptr = cm::make_unique<cmGeneratorTarget>(tgt, lg);
auto gt = ptr.get();
@@ -156,7 +155,7 @@ bool cmGlobalVisualStudio8Generator::AddCheckTarget()
std::vector<std::string> byproducts;
byproducts.push_back(cm->GetGlobVerifyStamp());
- mf->AddCustomCommandToTarget(
+ lg->AddCustomCommandToTarget(
CMAKE_CHECK_BUILD_SYSTEM_TARGET, byproducts, no_depends,
verifyCommandLines, cmCustomCommandType::PRE_BUILD,
"Checking File Globs", no_working_directory, false);
@@ -188,7 +187,7 @@ bool cmGlobalVisualStudio8Generator::AddCheckTarget()
// (this could be avoided with per-target source files)
std::string no_main_dependency;
cmImplicitDependsList no_implicit_depends;
- if (cmSourceFile* file = mf->AddCustomCommandToOutput(
+ if (cmSourceFile* file = lg->AddCustomCommandToOutput(
stamps, no_byproducts, listFiles, no_main_dependency,
no_implicit_depends, commandLines, "Checking Build System",
no_working_directory, true, false)) {
diff --git a/Source/cmGlobalVisualStudioGenerator.cxx b/Source/cmGlobalVisualStudioGenerator.cxx
index 2181994..be5cfd4 100644
--- a/Source/cmGlobalVisualStudioGenerator.cxx
+++ b/Source/cmGlobalVisualStudioGenerator.cxx
@@ -197,9 +197,9 @@ void cmGlobalVisualStudioGenerator::AddExtraIDETargets()
if (!gen.empty()) {
// Use no actual command lines so that the target itself is not
// considered always out of date.
- cmTarget* allBuild = gen[0]->GetMakefile()->AddUtilityCommand(
- "ALL_BUILD", cmCommandOrigin::Generator, true, no_working_dir,
- no_byproducts, no_depends, no_commands, false, "Build all projects");
+ cmTarget* allBuild = gen[0]->AddUtilityCommand(
+ "ALL_BUILD", true, no_working_dir, no_byproducts, no_depends,
+ no_commands, false, "Build all projects");
gen[0]->AddGeneratorTarget(
cm::make_unique<cmGeneratorTarget>(allBuild, gen[0]));
@@ -930,9 +930,10 @@ void cmGlobalVisualStudioGenerator::AddSymbolExportCommand(
cmCustomCommandLines commandLines = cmMakeSingleCommandLine(
{ cmakeCommand, "-E", "__create_def", mdi->DefFile, objs_file });
- cmCustomCommand command(gt->Target->GetMakefile(), outputs, empty, empty,
- commandLines, "Auto build dll exports", ".");
- commands.push_back(command);
+ cmCustomCommand command(outputs, empty, empty, commandLines,
+ gt->Target->GetMakefile()->GetBacktrace(),
+ "Auto build dll exports", ".");
+ commands.push_back(std::move(command));
}
static bool OpenSolution(std::string sln)
diff --git a/Source/cmGlobalXCodeGenerator.cxx b/Source/cmGlobalXCodeGenerator.cxx
index 9e6741d..d75c489 100644
--- a/Source/cmGlobalXCodeGenerator.cxx
+++ b/Source/cmGlobalXCodeGenerator.cxx
@@ -500,16 +500,13 @@ std::string cmGlobalXCodeGenerator::PostBuildMakeTarget(
void cmGlobalXCodeGenerator::AddExtraTargets(
cmLocalGenerator* root, std::vector<cmLocalGenerator*>& gens)
{
- cmMakefile* mf = root->GetMakefile();
-
const char* no_working_directory = nullptr;
std::vector<std::string> no_byproducts;
std::vector<std::string> no_depends;
// Add ALL_BUILD
- cmTarget* allbuild = mf->AddUtilityCommand(
- "ALL_BUILD", cmCommandOrigin::Generator, true, no_working_directory,
- no_byproducts, no_depends,
+ cmTarget* allbuild = root->AddUtilityCommand(
+ "ALL_BUILD", true, no_working_directory, no_byproducts, no_depends,
cmMakeSingleCommandLine({ "echo", "Build all projects" }));
root->AddGeneratorTarget(cm::make_unique<cmGeneratorTarget>(allbuild, root));
@@ -523,7 +520,7 @@ void cmGlobalXCodeGenerator::AddExtraTargets(
// Add ZERO_CHECK
bool regenerate = !this->GlobalSettingIsOn("CMAKE_SUPPRESS_REGENERATION");
bool generateTopLevelProjectOnly =
- mf->IsOn("CMAKE_XCODE_GENERATE_TOP_LEVEL_PROJECT_ONLY");
+ root->GetMakefile()->IsOn("CMAKE_XCODE_GENERATE_TOP_LEVEL_PROJECT_ONLY");
bool isTopLevel =
!root->GetStateSnapshot().GetBuildsystemDirectoryParent().IsValid();
if (regenerate && (isTopLevel || !generateTopLevelProjectOnly)) {
@@ -531,10 +528,10 @@ void cmGlobalXCodeGenerator::AddExtraTargets(
std::string file =
this->ConvertToRelativeForMake(this->CurrentReRunCMakeMakefile);
cmSystemTools::ReplaceString(file, "\\ ", " ");
- cmTarget* check = mf->AddUtilityCommand(
- CMAKE_CHECK_BUILD_SYSTEM_TARGET, cmCommandOrigin::Generator, true,
- no_working_directory, no_byproducts, no_depends,
- cmMakeSingleCommandLine({ "make", "-f", file }));
+ cmTarget* check =
+ root->AddUtilityCommand(CMAKE_CHECK_BUILD_SYSTEM_TARGET, true,
+ no_working_directory, no_byproducts, no_depends,
+ cmMakeSingleCommandLine({ "make", "-f", file }));
root->AddGeneratorTarget(cm::make_unique<cmGeneratorTarget>(check, root));
}
@@ -559,7 +556,7 @@ void cmGlobalXCodeGenerator::AddExtraTargets(
if (target->GetType() == cmStateEnums::OBJECT_LIBRARY) {
commandLines.front().back() = // fill placeholder
this->PostBuildMakeTarget(target->GetName(), "$(CONFIGURATION)");
- gen->GetMakefile()->AddCustomCommandToTarget(
+ gen->AddCustomCommandToTarget(
target->GetName(), no_byproducts, no_depends, commandLines,
cmCustomCommandType::POST_BUILD, "Depend check for xcode",
dir.c_str(), true, false, "", "", false,
@@ -1462,12 +1459,12 @@ void cmGlobalXCodeGenerator::CreateCustomCommands(
{ cmSystemTools::GetCMakeCommand(), "-E", "cmake_symlink_library",
str_file, str_so_file, str_link_file });
- cmCustomCommand command(this->CurrentMakefile, std::vector<std::string>(),
- std::vector<std::string>(),
- std::vector<std::string>(), cmd,
- "Creating symlinks", "");
+ cmCustomCommand command(
+ std::vector<std::string>(), std::vector<std::string>(),
+ std::vector<std::string>(), cmd, this->CurrentMakefile->GetBacktrace(),
+ "Creating symlinks", "");
- postbuild.push_back(command);
+ postbuild.push_back(std::move(command));
}
std::vector<cmSourceFile*> classes;
diff --git a/Source/cmInstallFilesCommand.cxx b/Source/cmInstallFilesCommand.cxx
index d623943..efbcb98 100644
--- a/Source/cmInstallFilesCommand.cxx
+++ b/Source/cmInstallFilesCommand.cxx
@@ -7,11 +7,14 @@
#include "cmGlobalGenerator.h"
#include "cmInstallFilesGenerator.h"
#include "cmInstallGenerator.h"
+#include "cmLocalGenerator.h"
#include "cmMakefile.h"
#include "cmRange.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
+class cmListFileBacktrace;
+
static std::string FindInstallSource(cmMakefile& makefile, const char* name);
static void CreateInstallGenerator(cmMakefile& makefile,
std::string const& dest,
@@ -43,9 +46,10 @@ bool cmInstallFilesCommand(std::vector<std::string> const& args,
CreateInstallGenerator(mf, dest, files);
} else {
std::vector<std::string> finalArgs(args.begin() + 1, args.end());
- mf.AddFinalAction([dest, finalArgs](cmMakefile& makefile) {
- FinalAction(makefile, dest, finalArgs);
- });
+ mf.AddGeneratorAction(
+ [dest, finalArgs](cmLocalGenerator& lg, const cmListFileBacktrace&) {
+ FinalAction(*lg.GetMakefile(), dest, finalArgs);
+ });
}
mf.GetGlobalGenerator()->AddInstallComponent(
diff --git a/Source/cmInstallProgramsCommand.cxx b/Source/cmInstallProgramsCommand.cxx
index 6bb4409..2088eae 100644
--- a/Source/cmInstallProgramsCommand.cxx
+++ b/Source/cmInstallProgramsCommand.cxx
@@ -7,10 +7,13 @@
#include "cmGlobalGenerator.h"
#include "cmInstallFilesGenerator.h"
#include "cmInstallGenerator.h"
+#include "cmLocalGenerator.h"
#include "cmMakefile.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
+class cmListFileBacktrace;
+
static void FinalAction(cmMakefile& makefile, std::string const& dest,
std::vector<std::string> const& args);
static std::string FindInstallSource(cmMakefile& makefile, const char* name);
@@ -33,9 +36,10 @@ bool cmInstallProgramsCommand(std::vector<std::string> const& args,
std::string const& dest = args[0];
std::vector<std::string> const finalArgs(args.begin() + 1, args.end());
- mf.AddFinalAction([dest, finalArgs](cmMakefile& makefile) {
- FinalAction(makefile, dest, finalArgs);
- });
+ mf.AddGeneratorAction(
+ [dest, finalArgs](cmLocalGenerator& lg, const cmListFileBacktrace&) {
+ FinalAction(*lg.GetMakefile(), dest, finalArgs);
+ });
return true;
}
diff --git a/Source/cmLoadCommandCommand.cxx b/Source/cmLoadCommandCommand.cxx
index 23ace64..92258e2 100644
--- a/Source/cmLoadCommandCommand.cxx
+++ b/Source/cmLoadCommandCommand.cxx
@@ -14,6 +14,7 @@
#include "cmCommand.h"
#include "cmDynamicLoader.h"
#include "cmExecutionStatus.h"
+#include "cmLocalGenerator.h"
#include "cmMakefile.h"
#include "cmState.h"
#include "cmStringAlgorithms.h"
@@ -25,6 +26,8 @@
# include <malloc.h> /* for malloc/free on QNX */
#endif
+class cmListFileBacktrace;
+
namespace {
const char* LastName = nullptr;
@@ -158,8 +161,10 @@ bool cmLoadedCommand::InitialPass(std::vector<std::string> const& args,
if (result) {
if (this->Impl->FinalPass) {
auto impl = this->Impl;
- this->Makefile->AddFinalAction(
- [impl](cmMakefile& makefile) { impl->DoFinalPass(&makefile); });
+ this->Makefile->AddGeneratorAction(
+ [impl](cmLocalGenerator& lg, const cmListFileBacktrace&) {
+ impl->DoFinalPass(lg.GetMakefile());
+ });
}
return true;
}
diff --git a/Source/cmLocalGenerator.cxx b/Source/cmLocalGenerator.cxx
index c43876c..c58603f 100644
--- a/Source/cmLocalGenerator.cxx
+++ b/Source/cmLocalGenerator.cxx
@@ -14,6 +14,7 @@
#include <utility>
#include <vector>
+#include <cm/memory>
#include <cm/string_view>
#include "cmsys/RegularExpression.hxx"
@@ -988,6 +989,91 @@ void cmLocalGenerator::AddCompileOptions(std::vector<BT<std::string>>& flags,
}
}
+cmTarget* cmLocalGenerator::AddCustomCommandToTarget(
+ const std::string& target, const std::vector<std::string>& byproducts,
+ const std::vector<std::string>& depends,
+ const cmCustomCommandLines& commandLines, cmCustomCommandType type,
+ const char* comment, const char* workingDir, bool escapeOldStyle,
+ bool uses_terminal, const std::string& depfile, const std::string& job_pool,
+ bool command_expand_lists, cmObjectLibraryCommands objLibCommands)
+{
+ cmTarget* t = this->Makefile->GetCustomCommandTarget(
+ target, objLibCommands, this->DirectoryBacktrace);
+ if (!t) {
+ return nullptr;
+ }
+
+ detail::AddCustomCommandToTarget(
+ *this, this->DirectoryBacktrace, cmCommandOrigin::Generator, t, byproducts,
+ depends, commandLines, type, comment, workingDir, escapeOldStyle,
+ uses_terminal, depfile, job_pool, command_expand_lists);
+
+ return t;
+}
+
+cmSourceFile* cmLocalGenerator::AddCustomCommandToOutput(
+ const std::string& output, const std::vector<std::string>& depends,
+ const std::string& main_dependency, const cmCustomCommandLines& commandLines,
+ const char* comment, const char* workingDir, bool replace,
+ bool escapeOldStyle, bool uses_terminal, bool command_expand_lists,
+ const std::string& depfile, const std::string& job_pool)
+{
+ std::vector<std::string> no_byproducts;
+ cmImplicitDependsList no_implicit_depends;
+ return this->AddCustomCommandToOutput(
+ { output }, no_byproducts, depends, main_dependency, no_implicit_depends,
+ commandLines, comment, workingDir, replace, escapeOldStyle, uses_terminal,
+ command_expand_lists, depfile, job_pool);
+}
+
+cmSourceFile* cmLocalGenerator::AddCustomCommandToOutput(
+ const std::vector<std::string>& outputs,
+ const std::vector<std::string>& byproducts,
+ const std::vector<std::string>& depends, const std::string& main_dependency,
+ const cmImplicitDependsList& implicit_depends,
+ const cmCustomCommandLines& commandLines, const char* comment,
+ const char* workingDir, bool replace, bool escapeOldStyle,
+ bool uses_terminal, bool command_expand_lists, const std::string& depfile,
+ const std::string& job_pool)
+{
+ // Make sure there is at least one output.
+ if (outputs.empty()) {
+ cmSystemTools::Error("Attempt to add a custom rule with no output!");
+ return nullptr;
+ }
+
+ return detail::AddCustomCommandToOutput(
+ *this, this->DirectoryBacktrace, cmCommandOrigin::Generator, outputs,
+ byproducts, depends, main_dependency, implicit_depends, commandLines,
+ comment, workingDir, replace, escapeOldStyle, uses_terminal,
+ command_expand_lists, depfile, job_pool);
+}
+
+cmTarget* cmLocalGenerator::AddUtilityCommand(
+ const std::string& utilityName, bool excludeFromAll, const char* workingDir,
+ const std::vector<std::string>& byproducts,
+ const std::vector<std::string>& depends,
+ const cmCustomCommandLines& commandLines, bool escapeOldStyle,
+ const char* comment, bool uses_terminal, bool command_expand_lists,
+ const std::string& job_pool)
+{
+ cmTarget* target =
+ this->Makefile->AddNewUtilityTarget(utilityName, excludeFromAll);
+ target->SetIsGeneratorProvided(true);
+
+ if (commandLines.empty() && depends.empty()) {
+ return target;
+ }
+
+ detail::AddUtilityCommand(
+ *this, this->DirectoryBacktrace, cmCommandOrigin::Generator, target,
+ this->Makefile->GetUtilityOutput(target), workingDir, byproducts, depends,
+ commandLines, escapeOldStyle, comment, uses_terminal, command_expand_lists,
+ job_pool);
+
+ return target;
+}
+
std::vector<BT<std::string>> cmLocalGenerator::GetIncludeDirectoriesImplicit(
cmGeneratorTarget const* target, std::string const& lang,
std::string const& config, bool stripImplicitDirs,
@@ -2307,6 +2393,7 @@ void cmLocalGenerator::AddPchDependencies(cmGeneratorTarget* target)
}
const std::string buildType = cmSystemTools::UpperCase(config);
+ // FIXME: Refactor collection of sources to not evaluate object libraries.
std::vector<cmSourceFile*> sources;
target->GetSourceFiles(sources, buildType);
@@ -2381,19 +2468,31 @@ void cmLocalGenerator::AddPchDependencies(cmGeneratorTarget* target)
target->GetLocalGenerator()->GetCurrentBinaryDirectory(), "/",
target->GetName(), ".dir/${PDB_PREFIX}");
- file << "if (EXISTS \"" << from_file << "\")\n";
+ const std::string to_file =
+ cmStrCat(to_dir, pchReuseFrom, extension);
+
+ std::string dest_file = to_file;
+
+ const std::string prefix = target->GetSafeProperty("PREFIX");
+ if (!prefix.empty()) {
+ dest_file = cmStrCat(to_dir, prefix, pchReuseFrom, extension);
+ }
+
+ file << "if (EXISTS \"" << from_file << "\" AND \"" << from_file
+ << "\" IS_NEWER_THAN \"" << dest_file << "\")\n";
file << " file(COPY \"" << from_file << "\""
<< " DESTINATION \"" << to_dir << "\")\n";
+ if (!prefix.empty()) {
+ file << " file(REMOVE \"" << dest_file << "\")\n";
+ file << " file(RENAME \"" << to_file << "\" \"" << dest_file
+ << "\")\n";
+ }
file << "endif()\n";
}
- cmCustomCommandLines commandLines;
- cmCustomCommandLine currentLine;
- currentLine.push_back(cmSystemTools::GetCMakeCommand());
- currentLine.push_back(cmStrCat("-DPDB_PREFIX=", pdb_prefix));
- currentLine.push_back("-P");
- currentLine.push_back(copy_script);
- commandLines.push_back(std::move(currentLine));
+ cmCustomCommandLines commandLines = cmMakeSingleCommandLine(
+ { cmSystemTools::GetCMakeCommand(),
+ cmStrCat("-DPDB_PREFIX=", pdb_prefix), "-P", copy_script });
const std::string no_main_dependency;
const std::vector<std::string> no_deps;
@@ -2406,16 +2505,14 @@ void cmLocalGenerator::AddPchDependencies(cmGeneratorTarget* target)
pchReuseFrom, ".pdb"));
if (this->GetGlobalGenerator()->IsMultiConfig()) {
- this->Makefile->AddCustomCommandToTarget(
+ this->AddCustomCommandToTarget(
target->GetName(), outputs, no_deps, commandLines,
cmCustomCommandType::PRE_BUILD, no_message, no_current_dir);
} else {
cmImplicitDependsList no_implicit_depends;
- cmSourceFile* copy_rule =
- this->Makefile->AddCustomCommandToOutput(
- outputs, no_byproducts, no_deps, no_main_dependency,
- no_implicit_depends, commandLines, no_message,
- no_current_dir);
+ cmSourceFile* copy_rule = this->AddCustomCommandToOutput(
+ outputs, no_byproducts, no_deps, no_main_dependency,
+ no_implicit_depends, commandLines, no_message, no_current_dir);
if (copy_rule) {
target->AddSource(copy_rule->ResolveFullPath());
@@ -2469,6 +2566,7 @@ void cmLocalGenerator::AddUnityBuild(cmGeneratorTarget* target)
cmStrCat(this->GetCurrentBinaryDirectory(), "/CMakeFiles/",
target->GetName(), ".dir/Unity/");
+ // FIXME: Refactor collection of sources to not evaluate object libraries.
std::vector<cmSourceFile*> sources;
target->GetSourceFiles(sources, buildType);
@@ -2518,12 +2616,7 @@ void cmLocalGenerator::AddUnityBuild(cmGeneratorTarget* target)
for (; begin != end; ++begin) {
cmSourceFile* sf = filtered_sources[begin];
- // Only in Visual Studio generator we keep the source files
- // for explicit processing.
- if (!this->GetGlobalGenerator()->IsMultiConfig() ||
- this->GetGlobalGenerator()->IsXcode()) {
- target->AddSourceFileToUnityBatch(sf->ResolveFullPath());
- }
+ target->AddSourceFileToUnityBatch(sf->ResolveFullPath());
sf->SetProperty("UNITY_SOURCE_FILE", filename.c_str());
if (beforeInclude) {
@@ -3147,6 +3240,22 @@ std::string cmLocalGenerator::GetObjectFileNameWithoutTarget(
}
}
+ // Ensure that for the CMakeFiles/<target>.dir/generated_source_file
+ // we don't end up having:
+ // CMakeFiles/<target>.dir/CMakeFiles/<target>.dir/generated_source_file.obj
+ const char* unitySourceFile = source.GetProperty("UNITY_SOURCE_FILE");
+ const char* pchExtension = source.GetProperty("PCH_EXTENSION");
+ if (unitySourceFile || pchExtension) {
+ if (pchExtension) {
+ customOutputExtension = pchExtension;
+ }
+
+ cmsys::RegularExpression var("(CMakeFiles/[^/]+.dir/)");
+ if (var.find(objectName)) {
+ objectName.erase(var.start(), var.end() - var.start());
+ }
+ }
+
// Replace the original source file extension with the object file
// extension.
bool keptSourceExtension = true;
@@ -3163,19 +3272,6 @@ std::string cmLocalGenerator::GetObjectFileNameWithoutTarget(
}
}
- const char* pchExtension = source.GetProperty("PCH_EXTENSION");
- if (pchExtension) {
- customOutputExtension = pchExtension;
-
- // Make sure that for the CMakeFiles/<target>.dir/cmake_pch.h|xx.c|xx
- // source file, we don't end up having
- // CMakeFiles/<target>.dir/CMakeFiles/<target>.dir/cmake_pch.h|xx.pch
- cmsys::RegularExpression var("(CMakeFiles/[^/]+.dir/)");
- while (var.find(objectName)) {
- objectName.erase(var.start(), var.end() - var.start());
- }
- }
-
// Remove the source extension if it is to be replaced.
if (replaceExt || customOutputExtension) {
keptSourceExtension = false;
@@ -3427,3 +3523,245 @@ void cmLocalGenerator::GenerateFrameworkInfoPList(
cmLGInfoProp(mf, target, "MACOSX_FRAMEWORK_BUNDLE_VERSION");
mf->ConfigureFile(inFile, fname, false, false, false);
}
+
+namespace {
+void CreateGeneratedSource(cmLocalGenerator& lg, const std::string& output,
+ cmCommandOrigin origin,
+ const cmListFileBacktrace& lfbt)
+{
+ if (cmGeneratorExpression::Find(output) == std::string::npos) {
+ // Outputs without generator expressions from the project are already
+ // created and marked as generated. Do not mark them again, because
+ // other commands might have overwritten the property.
+ if (origin == cmCommandOrigin::Generator) {
+ lg.GetMakefile()->GetOrCreateGeneratedSource(output);
+ }
+ } else {
+ lg.GetCMakeInstance()->IssueMessage(
+ MessageType::FATAL_ERROR,
+ "Generator expressions in custom command outputs are not implemented!",
+ lfbt);
+ }
+}
+
+void CreateGeneratedSources(cmLocalGenerator& lg,
+ const std::vector<std::string>& outputs,
+ cmCommandOrigin origin,
+ const cmListFileBacktrace& lfbt)
+{
+ for (std::string const& o : outputs) {
+ CreateGeneratedSource(lg, o, origin, lfbt);
+ }
+}
+
+cmSourceFile* AddCustomCommand(
+ cmLocalGenerator& lg, const cmListFileBacktrace& lfbt,
+ const std::vector<std::string>& outputs,
+ const std::vector<std::string>& byproducts,
+ const std::vector<std::string>& depends, const std::string& main_dependency,
+ const cmImplicitDependsList& implicit_depends,
+ const cmCustomCommandLines& commandLines, const char* comment,
+ const char* workingDir, bool replace, bool escapeOldStyle,
+ bool uses_terminal, bool command_expand_lists, const std::string& depfile,
+ const std::string& job_pool)
+{
+ cmMakefile* mf = lg.GetMakefile();
+
+ // Choose a source file on which to store the custom command.
+ cmSourceFile* file = nullptr;
+ if (!commandLines.empty() && !main_dependency.empty()) {
+ // The main dependency was specified. Use it unless a different
+ // custom command already used it.
+ file = mf->GetSource(main_dependency);
+ if (file && file->GetCustomCommand() && !replace) {
+ // The main dependency already has a custom command.
+ if (commandLines == file->GetCustomCommand()->GetCommandLines()) {
+ // The existing custom command is identical. Silently ignore
+ // the duplicate.
+ return file;
+ }
+ // The existing custom command is different. We need to
+ // generate a rule file for this new command.
+ file = nullptr;
+ } else if (!file) {
+ file = mf->CreateSource(main_dependency);
+ }
+ }
+
+ // Generate a rule file if the main dependency is not available.
+ if (!file) {
+ cmGlobalGenerator* gg = lg.GetGlobalGenerator();
+
+ // Construct a rule file associated with the first output produced.
+ std::string outName = gg->GenerateRuleFile(outputs[0]);
+
+ // Check if the rule file already exists.
+ file = mf->GetSource(outName, cmSourceFileLocationKind::Known);
+ if (file && file->GetCustomCommand() && !replace) {
+ // The rule file already exists.
+ if (commandLines != file->GetCustomCommand()->GetCommandLines()) {
+ lg.GetCMakeInstance()->IssueMessage(
+ MessageType::FATAL_ERROR,
+ cmStrCat("Attempt to add a custom rule to output\n ", outName,
+ "\nwhich already has a custom rule."),
+ lfbt);
+ }
+ return file;
+ }
+
+ // Create a cmSourceFile for the rule file.
+ if (!file) {
+ file = mf->CreateSource(outName, true, cmSourceFileLocationKind::Known);
+ }
+ file->SetProperty("__CMAKE_RULE", "1");
+ }
+
+ // Attach the custom command to the file.
+ if (file) {
+ // Construct a complete list of dependencies.
+ std::vector<std::string> depends2(depends);
+ if (!main_dependency.empty()) {
+ depends2.push_back(main_dependency);
+ }
+
+ std::unique_ptr<cmCustomCommand> cc = cm::make_unique<cmCustomCommand>(
+ outputs, byproducts, depends2, commandLines, lfbt, comment, workingDir);
+ cc->SetEscapeOldStyle(escapeOldStyle);
+ cc->SetEscapeAllowMakeVars(true);
+ cc->SetImplicitDepends(implicit_depends);
+ cc->SetUsesTerminal(uses_terminal);
+ cc->SetCommandExpandLists(command_expand_lists);
+ cc->SetDepfile(depfile);
+ cc->SetJobPool(job_pool);
+ file->SetCustomCommand(std::move(cc));
+
+ mf->AddSourceOutputs(file, outputs, byproducts);
+ }
+ return file;
+}
+}
+
+namespace detail {
+void AddCustomCommandToTarget(cmLocalGenerator& lg,
+ const cmListFileBacktrace& lfbt,
+ cmCommandOrigin origin, cmTarget* target,
+ const std::vector<std::string>& byproducts,
+ const std::vector<std::string>& depends,
+ const cmCustomCommandLines& commandLines,
+ cmCustomCommandType type, const char* comment,
+ const char* workingDir, bool escapeOldStyle,
+ bool uses_terminal, const std::string& depfile,
+ const std::string& job_pool,
+ bool command_expand_lists)
+{
+ cmMakefile* mf = lg.GetMakefile();
+
+ // Always create the byproduct sources and mark them generated.
+ CreateGeneratedSources(lg, byproducts, origin, lfbt);
+
+ // Add the command to the appropriate build step for the target.
+ std::vector<std::string> no_output;
+ cmCustomCommand cc(no_output, byproducts, depends, commandLines, lfbt,
+ comment, workingDir);
+ cc.SetEscapeOldStyle(escapeOldStyle);
+ cc.SetEscapeAllowMakeVars(true);
+ cc.SetUsesTerminal(uses_terminal);
+ cc.SetCommandExpandLists(command_expand_lists);
+ cc.SetDepfile(depfile);
+ cc.SetJobPool(job_pool);
+ switch (type) {
+ case cmCustomCommandType::PRE_BUILD:
+ target->AddPreBuildCommand(std::move(cc));
+ break;
+ case cmCustomCommandType::PRE_LINK:
+ target->AddPreLinkCommand(std::move(cc));
+ break;
+ case cmCustomCommandType::POST_BUILD:
+ target->AddPostBuildCommand(std::move(cc));
+ break;
+ }
+
+ mf->AddTargetByproducts(target, byproducts);
+}
+
+cmSourceFile* AddCustomCommandToOutput(
+ cmLocalGenerator& lg, const cmListFileBacktrace& lfbt,
+ cmCommandOrigin origin, const std::vector<std::string>& outputs,
+ const std::vector<std::string>& byproducts,
+ const std::vector<std::string>& depends, const std::string& main_dependency,
+ const cmImplicitDependsList& implicit_depends,
+ const cmCustomCommandLines& commandLines, const char* comment,
+ const char* workingDir, bool replace, bool escapeOldStyle,
+ bool uses_terminal, bool command_expand_lists, const std::string& depfile,
+ const std::string& job_pool)
+{
+ // Always create the output sources and mark them generated.
+ CreateGeneratedSources(lg, outputs, origin, lfbt);
+ CreateGeneratedSources(lg, byproducts, origin, lfbt);
+
+ return AddCustomCommand(
+ lg, lfbt, outputs, byproducts, depends, main_dependency, implicit_depends,
+ commandLines, comment, workingDir, replace, escapeOldStyle, uses_terminal,
+ command_expand_lists, depfile, job_pool);
+}
+
+void AppendCustomCommandToOutput(cmLocalGenerator& lg,
+ const cmListFileBacktrace& lfbt,
+ const std::string& output,
+ const std::vector<std::string>& depends,
+ const cmImplicitDependsList& implicit_depends,
+ const cmCustomCommandLines& commandLines)
+{
+ // Lookup an existing command.
+ if (cmSourceFile* sf = lg.GetMakefile()->GetSourceFileWithOutput(output)) {
+ if (cmCustomCommand* cc = sf->GetCustomCommand()) {
+ cc->AppendCommands(commandLines);
+ cc->AppendDepends(depends);
+ cc->AppendImplicitDepends(implicit_depends);
+ return;
+ }
+ }
+
+ // No existing command found.
+ lg.GetCMakeInstance()->IssueMessage(
+ MessageType::FATAL_ERROR,
+ cmStrCat("Attempt to append to output\n ", output,
+ "\nwhich is not already a custom command output."),
+ lfbt);
+}
+
+void AddUtilityCommand(cmLocalGenerator& lg, const cmListFileBacktrace& lfbt,
+ cmCommandOrigin origin, cmTarget* target,
+ const cmUtilityOutput& force, const char* workingDir,
+ const std::vector<std::string>& byproducts,
+ const std::vector<std::string>& depends,
+ const cmCustomCommandLines& commandLines,
+ bool escapeOldStyle, const char* comment,
+ bool uses_terminal, bool command_expand_lists,
+ const std::string& job_pool)
+{
+ // Always create the byproduct sources and mark them generated.
+ CreateGeneratedSource(lg, force.Name, origin, lfbt);
+ CreateGeneratedSources(lg, byproducts, origin, lfbt);
+
+ // Use an empty comment to avoid generation of default comment.
+ if (!comment) {
+ comment = "";
+ }
+
+ std::string no_main_dependency;
+ cmImplicitDependsList no_implicit_depends;
+ cmSourceFile* rule = AddCustomCommand(
+ lg, lfbt, { force.Name }, byproducts, depends, no_main_dependency,
+ no_implicit_depends, commandLines, comment, workingDir, /*replace=*/false,
+ escapeOldStyle, uses_terminal, command_expand_lists, /*depfile=*/"",
+ job_pool);
+ if (rule) {
+ lg.GetMakefile()->AddTargetByproducts(target, byproducts);
+ }
+
+ if (!force.NameCMP0049.empty()) {
+ target->AddSource(force.NameCMP0049);
+ }
+}
+}
diff --git a/Source/cmLocalGenerator.h b/Source/cmLocalGenerator.h
index e5c89f9..8788c2f 100644
--- a/Source/cmLocalGenerator.h
+++ b/Source/cmLocalGenerator.h
@@ -15,6 +15,7 @@
#include "cm_kwiml.h"
+#include "cmCustomCommandTypes.h"
#include "cmListFileCache.h"
#include "cmMessageType.h"
#include "cmOutputConverter.h"
@@ -23,13 +24,16 @@
class cmComputeLinkInformation;
class cmCustomCommandGenerator;
+class cmCustomCommandLines;
class cmGeneratorTarget;
class cmGlobalGenerator;
+class cmImplicitDependsList;
class cmLinkLineComputer;
class cmMakefile;
class cmRulePlaceholderExpander;
class cmSourceFile;
class cmState;
+class cmTarget;
class cmake;
/** \class cmLocalGenerator
@@ -295,6 +299,51 @@ public:
cmGeneratorTarget* target, const std::string& lang,
const std::string& config);
+ /**
+ * Add a custom PRE_BUILD, PRE_LINK, or POST_BUILD command to a target.
+ */
+ cmTarget* AddCustomCommandToTarget(
+ const std::string& target, const std::vector<std::string>& byproducts,
+ const std::vector<std::string>& depends,
+ const cmCustomCommandLines& commandLines, cmCustomCommandType type,
+ const char* comment, const char* workingDir, bool escapeOldStyle = true,
+ bool uses_terminal = false, const std::string& depfile = "",
+ const std::string& job_pool = "", bool command_expand_lists = false,
+ cmObjectLibraryCommands objLibCommands = cmObjectLibraryCommands::Reject);
+
+ /**
+ * Add a custom command to a source file.
+ */
+ cmSourceFile* AddCustomCommandToOutput(
+ const std::string& output, const std::vector<std::string>& depends,
+ const std::string& main_dependency,
+ const cmCustomCommandLines& commandLines, const char* comment,
+ const char* workingDir, bool replace = false, bool escapeOldStyle = true,
+ bool uses_terminal = false, bool command_expand_lists = false,
+ const std::string& depfile = "", const std::string& job_pool = "");
+ cmSourceFile* AddCustomCommandToOutput(
+ const std::vector<std::string>& outputs,
+ const std::vector<std::string>& byproducts,
+ const std::vector<std::string>& depends,
+ const std::string& main_dependency,
+ const cmImplicitDependsList& implicit_depends,
+ const cmCustomCommandLines& commandLines, const char* comment,
+ const char* workingDir, bool replace = false, bool escapeOldStyle = true,
+ bool uses_terminal = false, bool command_expand_lists = false,
+ const std::string& depfile = "", const std::string& job_pool = "");
+
+ /**
+ * Add a utility to the build. A utility target is a command that is run
+ * every time the target is built.
+ */
+ cmTarget* AddUtilityCommand(
+ const std::string& utilityName, bool excludeFromAll,
+ const char* workingDir, const std::vector<std::string>& byproducts,
+ const std::vector<std::string>& depends,
+ const cmCustomCommandLines& commandLines, bool escapeOldStyle = true,
+ const char* comment = nullptr, bool uses_terminal = false,
+ bool command_expand_lists = false, const std::string& job_pool = "");
+
std::string GetProjectName() const;
/** Compute the language used to compile the given source file. */
@@ -497,4 +546,46 @@ bool cmLocalGeneratorCheckObjectName(std::string& objName,
std::string::size_type max_total_len);
#endif
+namespace detail {
+void AddCustomCommandToTarget(cmLocalGenerator& lg,
+ const cmListFileBacktrace& lfbt,
+ cmCommandOrigin origin, cmTarget* target,
+ const std::vector<std::string>& byproducts,
+ const std::vector<std::string>& depends,
+ const cmCustomCommandLines& commandLines,
+ cmCustomCommandType type, const char* comment,
+ const char* workingDir, bool escapeOldStyle,
+ bool uses_terminal, const std::string& depfile,
+ const std::string& job_pool,
+ bool command_expand_lists);
+
+cmSourceFile* AddCustomCommandToOutput(
+ cmLocalGenerator& lg, const cmListFileBacktrace& lfbt,
+ cmCommandOrigin origin, const std::vector<std::string>& outputs,
+ const std::vector<std::string>& byproducts,
+ const std::vector<std::string>& depends, const std::string& main_dependency,
+ const cmImplicitDependsList& implicit_depends,
+ const cmCustomCommandLines& commandLines, const char* comment,
+ const char* workingDir, bool replace, bool escapeOldStyle,
+ bool uses_terminal, bool command_expand_lists, const std::string& depfile,
+ const std::string& job_pool);
+
+void AppendCustomCommandToOutput(cmLocalGenerator& lg,
+ const cmListFileBacktrace& lfbt,
+ const std::string& output,
+ const std::vector<std::string>& depends,
+ const cmImplicitDependsList& implicit_depends,
+ const cmCustomCommandLines& commandLines);
+
+void AddUtilityCommand(cmLocalGenerator& lg, const cmListFileBacktrace& lfbt,
+ cmCommandOrigin origin, cmTarget* target,
+ const cmUtilityOutput& force, const char* workingDir,
+ const std::vector<std::string>& byproducts,
+ const std::vector<std::string>& depends,
+ const cmCustomCommandLines& commandLines,
+ bool escapeOldStyle, const char* comment,
+ bool uses_terminal, bool command_expand_lists,
+ const std::string& job_pool);
+}
+
#endif
diff --git a/Source/cmLocalVisualStudio7Generator.cxx b/Source/cmLocalVisualStudio7Generator.cxx
index 5354f14..0758fd4 100644
--- a/Source/cmLocalVisualStudio7Generator.cxx
+++ b/Source/cmLocalVisualStudio7Generator.cxx
@@ -102,9 +102,9 @@ void cmLocalVisualStudio7Generator::FixGlobalTargets()
this->Makefile->GetOrCreateGeneratedSource(force)) {
sf->SetProperty("SYMBOLIC", "1");
}
- if (cmSourceFile* file = this->Makefile->AddCustomCommandToOutput(
- force.c_str(), no_depends, no_main_dependency, force_commands, " ",
- 0, true)) {
+ if (cmSourceFile* file = this->AddCustomCommandToOutput(
+ force, no_depends, no_main_dependency, force_commands, " ",
+ nullptr, true)) {
l->AddSource(file->ResolveFullPath());
}
}
@@ -259,9 +259,9 @@ cmSourceFile* cmLocalVisualStudio7Generator::CreateVCProjBuildRule()
const char* no_working_directory = nullptr;
std::string fullpathStampName =
cmSystemTools::CollapseFullPath(stampName.c_str());
- this->Makefile->AddCustomCommandToOutput(
- fullpathStampName, listFiles, makefileIn, commandLines, comment.c_str(),
- no_working_directory, true, false);
+ this->AddCustomCommandToOutput(fullpathStampName, listFiles, makefileIn,
+ commandLines, comment.c_str(),
+ no_working_directory, true, false);
if (cmSourceFile* file = this->Makefile->GetSource(makefileIn.c_str())) {
// Finalize the source file path now since we're adding this after
// the generator validated all project-named sources.
diff --git a/Source/cmLocalVisualStudioGenerator.cxx b/Source/cmLocalVisualStudioGenerator.cxx
index 336e3a5..8d50898 100644
--- a/Source/cmLocalVisualStudioGenerator.cxx
+++ b/Source/cmLocalVisualStudioGenerator.cxx
@@ -104,8 +104,8 @@ cmLocalVisualStudioGenerator::MaybeCreateImplibDir(cmGeneratorTarget* target,
std::vector<std::string> no_depends;
cmCustomCommandLines commands = cmMakeSingleCommandLine(
{ cmSystemTools::GetCMakeCommand(), "-E", "make_directory", impDir });
- pcc.reset(new cmCustomCommand(0, no_output, no_byproducts, no_depends,
- commands, 0, 0));
+ pcc.reset(new cmCustomCommand(no_output, no_byproducts, no_depends, commands,
+ cmListFileBacktrace(), nullptr, nullptr));
pcc->SetEscapeOldStyle(false);
pcc->SetEscapeAllowMakeVars(true);
return pcc;
diff --git a/Source/cmMakefile.cxx b/Source/cmMakefile.cxx
index bf488b1..dc0b50f 100644
--- a/Source/cmMakefile.cxx
+++ b/Source/cmMakefile.cxx
@@ -14,7 +14,7 @@
#include <utility>
#include <cm/iterator>
-#include <cm/memory>
+#include <cm/optional>
#include "cmsys/FStream.hxx"
#include "cmsys/RegularExpression.hxx"
@@ -36,6 +36,7 @@
#include "cmInstallGenerator.h" // IWYU pragma: keep
#include "cmInstallSubdirectoryGenerator.h"
#include "cmListFileCache.h"
+#include "cmLocalGenerator.h"
#include "cmMessageType.h"
#include "cmRange.h"
#include "cmSourceFile.h"
@@ -146,7 +147,7 @@ void cmMakefile::IssueMessage(MessageType t, std::string const& text) const
this->ExecutionStatusStack.back()->SetNestedError();
}
}
- this->GetCMakeInstance()->IssueMessage(t, text, this->GetBacktrace());
+ this->GetCMakeInstance()->IssueMessage(t, text, this->Backtrace);
}
bool cmMakefile::CheckCMP0037(std::string const& targetName,
@@ -780,21 +781,25 @@ struct file_not_persistent
};
}
-void cmMakefile::AddFinalAction(FinalAction action)
+void cmMakefile::AddGeneratorAction(GeneratorAction action)
{
- this->FinalActions.push_back(std::move(action));
+ assert(!this->GeneratorActionsInvoked);
+ this->GeneratorActions.emplace_back(std::move(action), this->Backtrace);
}
-void cmMakefile::FinalPass()
+void cmMakefile::DoGenerate(cmLocalGenerator& lg)
{
// do all the variable expansions here
this->ExpandVariablesCMP0019();
// give all the commands a chance to do something
// after the file has been parsed before generation
- for (FinalAction& action : this->FinalActions) {
- action(*this);
+ for (const BT<GeneratorAction>& action : this->GeneratorActions) {
+ action.Value(lg, action.Backtrace);
}
+ this->GeneratorActionsInvoked = true;
+ this->DelayedOutputFiles.clear();
+ this->DelayedOutputFilesHaveGenex = false;
// go through all configured files and see which ones still exist.
// we don't want cmake to re-run if a configured file is created and deleted
@@ -809,9 +814,9 @@ void cmMakefile::FinalPass()
}
// Generate the output file
-void cmMakefile::ConfigureFinalPass()
+void cmMakefile::Generate(cmLocalGenerator& lg)
{
- this->FinalPass();
+ this->DoGenerate(lg);
const char* oldValue = this->GetDefinition("CMAKE_BACKWARDS_COMPATIBILITY");
if (oldValue &&
cmSystemTools::VersionCompare(cmSystemTools::OP_LESS, oldValue, "2.4")) {
@@ -825,6 +830,39 @@ void cmMakefile::ConfigureFinalPass()
}
}
+namespace {
+// There are still too many implicit backtraces through cmMakefile. As a
+// workaround we reset the backtrace temporarily.
+struct BacktraceGuard
+{
+ BacktraceGuard(cmListFileBacktrace& lfbt, cmListFileBacktrace current)
+ : Backtrace(lfbt)
+ , Previous(lfbt)
+ {
+ this->Backtrace = std::move(current);
+ }
+
+ ~BacktraceGuard() { this->Backtrace = std::move(Previous); }
+
+private:
+ cmListFileBacktrace& Backtrace;
+ cmListFileBacktrace Previous;
+};
+
+cm::optional<std::string> MakeOptionalString(const char* str)
+{
+ if (str) {
+ return str;
+ }
+ return cm::nullopt;
+}
+
+const char* GetCStrOrNull(const cm::optional<std::string>& str)
+{
+ return str ? str->c_str() : nullptr;
+}
+}
+
bool cmMakefile::ValidateCustomCommand(
const cmCustomCommandLines& commandLines) const
{
@@ -842,7 +880,8 @@ bool cmMakefile::ValidateCustomCommand(
}
cmTarget* cmMakefile::GetCustomCommandTarget(
- const std::string& target, cmObjectLibraryCommands objLibCommands) const
+ const std::string& target, cmObjectLibraryCommands objLibCommands,
+ const cmListFileBacktrace& lfbt) const
{
// Find the target to which to add the custom command.
auto ti = this->Targets.find(target);
@@ -876,7 +915,7 @@ cmTarget* cmMakefile::GetCustomCommandTarget(
e << "No TARGET '" << target
<< "' has been created in this directory.";
}
- this->IssueMessage(messageType, e.str());
+ this->GetCMakeInstance()->IssueMessage(messageType, e.str(), lfbt);
}
return nullptr;
@@ -889,7 +928,8 @@ cmTarget* cmMakefile::GetCustomCommandTarget(
e << "Target \"" << target
<< "\" is an OBJECT library "
"that may not have PRE_BUILD, PRE_LINK, or POST_BUILD commands.";
- this->IssueMessage(MessageType::FATAL_ERROR, e.str());
+ this->GetCMakeInstance()->IssueMessage(MessageType::FATAL_ERROR, e.str(),
+ lfbt);
return nullptr;
}
if (t->GetType() == cmStateEnums::INTERFACE_LIBRARY) {
@@ -897,7 +937,8 @@ cmTarget* cmMakefile::GetCustomCommandTarget(
e << "Target \"" << target
<< "\" is an INTERFACE library "
"that may not have PRE_BUILD, PRE_LINK, or POST_BUILD commands.";
- this->IssueMessage(MessageType::FATAL_ERROR, e.str());
+ this->GetCMakeInstance()->IssueMessage(MessageType::FATAL_ERROR, e.str(),
+ lfbt);
return nullptr;
}
@@ -910,9 +951,10 @@ cmTarget* cmMakefile::AddCustomCommandToTarget(
const cmCustomCommandLines& commandLines, cmCustomCommandType type,
const char* comment, const char* workingDir, bool escapeOldStyle,
bool uses_terminal, const std::string& depfile, const std::string& job_pool,
- bool command_expand_lists, cmObjectLibraryCommands objLibCommands)
+ bool command_expand_lists)
{
- cmTarget* t = this->GetCustomCommandTarget(target, objLibCommands);
+ cmTarget* t = this->GetCustomCommandTarget(
+ target, cmObjectLibraryCommands::Reject, this->Backtrace);
// Validate custom commands.
if (!t || !this->ValidateCustomCommand(commandLines)) {
@@ -920,175 +962,83 @@ cmTarget* cmMakefile::AddCustomCommandToTarget(
}
// Always create the byproduct sources and mark them generated.
- this->CreateGeneratedSources(byproducts);
-
- this->CommitCustomCommandToTarget(
- t, byproducts, depends, commandLines, type, comment, workingDir,
- escapeOldStyle, uses_terminal, depfile, job_pool, command_expand_lists);
+ this->CreateGeneratedByproducts(byproducts);
+
+ // Strings could be moved into the callback function with C++14.
+ cm::optional<std::string> commentStr = MakeOptionalString(comment);
+ cm::optional<std::string> workingStr = MakeOptionalString(workingDir);
+
+ // Dispatch command creation to allow generator expressions in outputs.
+ this->AddGeneratorAction([=](cmLocalGenerator& lg,
+ const cmListFileBacktrace& lfbt) {
+ BacktraceGuard guard(this->Backtrace, lfbt);
+ detail::AddCustomCommandToTarget(
+ lg, lfbt, cmCommandOrigin::Project, t, byproducts, depends, commandLines,
+ type, GetCStrOrNull(commentStr), GetCStrOrNull(workingStr),
+ escapeOldStyle, uses_terminal, depfile, job_pool, command_expand_lists);
+ });
return t;
}
-void cmMakefile::CommitCustomCommandToTarget(
- cmTarget* target, const std::vector<std::string>& byproducts,
- const std::vector<std::string>& depends,
- const cmCustomCommandLines& commandLines, cmCustomCommandType type,
- const char* comment, const char* workingDir, bool escapeOldStyle,
- bool uses_terminal, const std::string& depfile, const std::string& job_pool,
- bool command_expand_lists)
-{
- // Add the command to the appropriate build step for the target.
- std::vector<std::string> no_output;
- cmCustomCommand cc(this, no_output, byproducts, depends, commandLines,
- comment, workingDir);
- cc.SetEscapeOldStyle(escapeOldStyle);
- cc.SetEscapeAllowMakeVars(true);
- cc.SetUsesTerminal(uses_terminal);
- cc.SetCommandExpandLists(command_expand_lists);
- cc.SetDepfile(depfile);
- cc.SetJobPool(job_pool);
- switch (type) {
- case cmCustomCommandType::PRE_BUILD:
- target->AddPreBuildCommand(std::move(cc));
- break;
- case cmCustomCommandType::PRE_LINK:
- target->AddPreLinkCommand(std::move(cc));
- break;
- case cmCustomCommandType::POST_BUILD:
- target->AddPostBuildCommand(std::move(cc));
- break;
- }
-
- this->AddTargetByproducts(target, byproducts);
-}
-
-cmSourceFile* cmMakefile::AddCustomCommandToOutput(
+void cmMakefile::AddCustomCommandToOutput(
const std::string& output, const std::vector<std::string>& depends,
const std::string& main_dependency, const cmCustomCommandLines& commandLines,
- const char* comment, const char* workingDir, bool replace,
- bool escapeOldStyle, bool uses_terminal, bool command_expand_lists,
- const std::string& depfile, const std::string& job_pool)
+ const char* comment, const char* workingDir,
+ const CommandSourceCallback& callback, bool replace, bool escapeOldStyle,
+ bool uses_terminal, bool command_expand_lists, const std::string& depfile,
+ const std::string& job_pool)
{
- std::vector<std::string> outputs;
- outputs.push_back(output);
std::vector<std::string> no_byproducts;
cmImplicitDependsList no_implicit_depends;
- return this->AddCustomCommandToOutput(
- outputs, no_byproducts, depends, main_dependency, no_implicit_depends,
- commandLines, comment, workingDir, replace, escapeOldStyle, uses_terminal,
- command_expand_lists, depfile, job_pool);
+ this->AddCustomCommandToOutput(
+ { output }, no_byproducts, depends, main_dependency, no_implicit_depends,
+ commandLines, comment, workingDir, callback, replace, escapeOldStyle,
+ uses_terminal, command_expand_lists, depfile, job_pool);
}
-cmSourceFile* cmMakefile::AddCustomCommandToOutput(
+void cmMakefile::AddCustomCommandToOutput(
const std::vector<std::string>& outputs,
const std::vector<std::string>& byproducts,
const std::vector<std::string>& depends, const std::string& main_dependency,
const cmImplicitDependsList& implicit_depends,
const cmCustomCommandLines& commandLines, const char* comment,
- const char* workingDir, bool replace, bool escapeOldStyle,
- bool uses_terminal, bool command_expand_lists, const std::string& depfile,
- const std::string& job_pool)
+ const char* workingDir, const CommandSourceCallback& callback, bool replace,
+ bool escapeOldStyle, bool uses_terminal, bool command_expand_lists,
+ const std::string& depfile, const std::string& job_pool)
{
// Make sure there is at least one output.
if (outputs.empty()) {
cmSystemTools::Error("Attempt to add a custom rule with no output!");
- return nullptr;
+ return;
}
// Validate custom commands.
if (!this->ValidateCustomCommand(commandLines)) {
- return nullptr;
+ return;
}
// Always create the output sources and mark them generated.
- this->CreateGeneratedSources(outputs);
- this->CreateGeneratedSources(byproducts);
-
- return this->CommitCustomCommandToOutput(
- outputs, byproducts, depends, main_dependency, implicit_depends,
- commandLines, comment, workingDir, replace, escapeOldStyle, uses_terminal,
- command_expand_lists, depfile, job_pool);
-}
-
-cmSourceFile* cmMakefile::CommitCustomCommandToOutput(
- const std::vector<std::string>& outputs,
- const std::vector<std::string>& byproducts,
- const std::vector<std::string>& depends, const std::string& main_dependency,
- const cmImplicitDependsList& implicit_depends,
- const cmCustomCommandLines& commandLines, const char* comment,
- const char* workingDir, bool replace, bool escapeOldStyle,
- bool uses_terminal, bool command_expand_lists, const std::string& depfile,
- const std::string& job_pool)
-{
- // Choose a source file on which to store the custom command.
- cmSourceFile* file = nullptr;
- if (!commandLines.empty() && !main_dependency.empty()) {
- // The main dependency was specified. Use it unless a different
- // custom command already used it.
- file = this->GetSource(main_dependency);
- if (file && file->GetCustomCommand() && !replace) {
- // The main dependency already has a custom command.
- if (commandLines == file->GetCustomCommand()->GetCommandLines()) {
- // The existing custom command is identical. Silently ignore
- // the duplicate.
- return file;
- }
- // The existing custom command is different. We need to
- // generate a rule file for this new command.
- file = nullptr;
- } else if (!file) {
- file = this->CreateSource(main_dependency);
+ this->CreateGeneratedOutputs(outputs);
+ this->CreateGeneratedByproducts(byproducts);
+
+ // Strings could be moved into the callback function with C++14.
+ cm::optional<std::string> commentStr = MakeOptionalString(comment);
+ cm::optional<std::string> workingStr = MakeOptionalString(workingDir);
+
+ // Dispatch command creation to allow generator expressions in outputs.
+ this->AddGeneratorAction([=](cmLocalGenerator& lg,
+ const cmListFileBacktrace& lfbt) {
+ BacktraceGuard guard(this->Backtrace, lfbt);
+ cmSourceFile* sf = detail::AddCustomCommandToOutput(
+ lg, lfbt, cmCommandOrigin::Project, outputs, byproducts, depends,
+ main_dependency, implicit_depends, commandLines,
+ GetCStrOrNull(commentStr), GetCStrOrNull(workingStr), replace,
+ escapeOldStyle, uses_terminal, command_expand_lists, depfile, job_pool);
+ if (callback && sf) {
+ callback(sf);
}
- }
-
- // Generate a rule file if the main dependency is not available.
- if (!file) {
- cmGlobalGenerator* gg = this->GetGlobalGenerator();
-
- // Construct a rule file associated with the first output produced.
- std::string outName = gg->GenerateRuleFile(outputs[0]);
-
- // Check if the rule file already exists.
- file = this->GetSource(outName, cmSourceFileLocationKind::Known);
- if (file && file->GetCustomCommand() && !replace) {
- // The rule file already exists.
- if (commandLines != file->GetCustomCommand()->GetCommandLines()) {
- cmSystemTools::Error("Attempt to add a custom rule to output \"" +
- outName + "\" which already has a custom rule.");
- }
- return file;
- }
-
- // Create a cmSourceFile for the rule file.
- if (!file) {
- file =
- this->CreateSource(outName, true, cmSourceFileLocationKind::Known);
- }
- file->SetProperty("__CMAKE_RULE", "1");
- }
-
- // Attach the custom command to the file.
- if (file) {
- // Construct a complete list of dependencies.
- std::vector<std::string> depends2(depends);
- if (!main_dependency.empty()) {
- depends2.push_back(main_dependency);
- }
-
- std::unique_ptr<cmCustomCommand> cc = cm::make_unique<cmCustomCommand>(
- this, outputs, byproducts, depends2, commandLines, comment, workingDir);
- cc->SetEscapeOldStyle(escapeOldStyle);
- cc->SetEscapeAllowMakeVars(true);
- cc->SetImplicitDepends(implicit_depends);
- cc->SetUsesTerminal(uses_terminal);
- cc->SetCommandExpandLists(command_expand_lists);
- cc->SetDepfile(depfile);
- cc->SetJobPool(job_pool);
- file->SetCustomCommand(std::move(cc));
-
- this->AddSourceOutputs(file, outputs, byproducts);
- }
- return file;
+ });
}
void cmMakefile::AddCustomCommandOldStyle(
@@ -1136,11 +1086,8 @@ void cmMakefile::AddCustomCommandOldStyle(
if (sourceFiles.find(source)) {
// The source looks like a real file. Use it as the main dependency.
for (std::string const& output : outputs) {
- cmSourceFile* sf = this->AddCustomCommandToOutput(
- output, depends, source, commandLines, comment, nullptr);
- if (sf) {
- addRuleFileToTarget(sf);
- }
+ this->AddCustomCommandToOutput(output, depends, source, commandLines,
+ comment, nullptr, addRuleFileToTarget);
}
} else {
std::string no_main_dependency;
@@ -1149,11 +1096,9 @@ void cmMakefile::AddCustomCommandOldStyle(
// The source may not be a real file. Do not use a main dependency.
for (std::string const& output : outputs) {
- cmSourceFile* sf = this->AddCustomCommandToOutput(
- output, depends2, no_main_dependency, commandLines, comment, nullptr);
- if (sf) {
- addRuleFileToTarget(sf);
- }
+ this->AddCustomCommandToOutput(output, depends2, no_main_dependency,
+ commandLines, comment, nullptr,
+ addRuleFileToTarget);
}
}
}
@@ -1170,29 +1115,18 @@ bool cmMakefile::AppendCustomCommandToOutput(
// Validate custom commands.
if (this->ValidateCustomCommand(commandLines)) {
- // Add command factory to allow generator expressions in output.
- this->CommitAppendCustomCommandToOutput(output, depends, implicit_depends,
- commandLines);
+ // Dispatch command creation to allow generator expressions in outputs.
+ this->AddGeneratorAction(
+ [=](cmLocalGenerator& lg, const cmListFileBacktrace& lfbt) {
+ BacktraceGuard guard(this->Backtrace, lfbt);
+ detail::AppendCustomCommandToOutput(lg, lfbt, output, depends,
+ implicit_depends, commandLines);
+ });
}
return true;
}
-void cmMakefile::CommitAppendCustomCommandToOutput(
- const std::string& output, const std::vector<std::string>& depends,
- const cmImplicitDependsList& implicit_depends,
- const cmCustomCommandLines& commandLines)
-{
- // Lookup an existing command.
- if (cmSourceFile* sf = this->GetSourceFileWithOutput(output)) {
- if (cmCustomCommand* cc = sf->GetCustomCommand()) {
- cc->AppendCommands(commandLines);
- cc->AppendDepends(depends);
- cc->AppendImplicitDepends(implicit_depends);
- }
- }
-}
-
cmUtilityOutput cmMakefile::GetUtilityOutput(cmTarget* target)
{
std::string force = cmStrCat(this->GetCurrentBinaryDirectory(),
@@ -1215,15 +1149,14 @@ cmUtilityOutput cmMakefile::GetUtilityOutput(cmTarget* target)
}
cmTarget* cmMakefile::AddUtilityCommand(
- const std::string& utilityName, cmCommandOrigin origin, bool excludeFromAll,
- const char* workingDirectory, const std::vector<std::string>& byproducts,
+ const std::string& utilityName, bool excludeFromAll, const char* workingDir,
+ const std::vector<std::string>& byproducts,
const std::vector<std::string>& depends,
const cmCustomCommandLines& commandLines, bool escapeOldStyle,
const char* comment, bool uses_terminal, bool command_expand_lists,
const std::string& job_pool)
{
- cmTarget* target =
- this->AddNewUtilityTarget(utilityName, origin, excludeFromAll);
+ cmTarget* target = this->AddNewUtilityTarget(utilityName, excludeFromAll);
// Validate custom commands.
if ((commandLines.empty() && depends.empty()) ||
@@ -1236,45 +1169,26 @@ cmTarget* cmMakefile::AddUtilityCommand(
this->GetOrCreateGeneratedSource(force.Name);
// Always create the byproduct sources and mark them generated.
- this->CreateGeneratedSources(byproducts);
-
- if (!comment) {
- // Use an empty comment to avoid generation of default comment.
- comment = "";
- }
-
- this->CommitUtilityCommand(target, force, workingDirectory, byproducts,
- depends, commandLines, escapeOldStyle, comment,
- uses_terminal, command_expand_lists, job_pool);
+ this->CreateGeneratedByproducts(byproducts);
+
+ // Strings could be moved into the callback function with C++14.
+ cm::optional<std::string> commentStr = MakeOptionalString(comment);
+ cm::optional<std::string> workingStr = MakeOptionalString(workingDir);
+
+ // Dispatch command creation to allow generator expressions in outputs.
+ this->AddGeneratorAction(
+ [=](cmLocalGenerator& lg, const cmListFileBacktrace& lfbt) {
+ BacktraceGuard guard(this->Backtrace, lfbt);
+ detail::AddUtilityCommand(lg, lfbt, cmCommandOrigin::Project, target,
+ force, GetCStrOrNull(workingStr), byproducts,
+ depends, commandLines, escapeOldStyle,
+ GetCStrOrNull(commentStr), uses_terminal,
+ command_expand_lists, job_pool);
+ });
return target;
}
-void cmMakefile::CommitUtilityCommand(
- cmTarget* target, const cmUtilityOutput& force, const char* workingDirectory,
- const std::vector<std::string>& byproducts,
- const std::vector<std::string>& depends,
- const cmCustomCommandLines& commandLines, bool escapeOldStyle,
- const char* comment, bool uses_terminal, bool command_expand_lists,
- const std::string& job_pool)
-{
- std::vector<std::string> forced;
- forced.push_back(force.Name);
- std::string no_main_dependency;
- cmImplicitDependsList no_implicit_depends;
- bool no_replace = false;
- cmSourceFile* sf = this->AddCustomCommandToOutput(
- forced, byproducts, depends, no_main_dependency, no_implicit_depends,
- commandLines, comment, workingDirectory, no_replace, escapeOldStyle,
- uses_terminal, command_expand_lists, /*depfile=*/"", job_pool);
- if (!force.NameCMP0049.empty()) {
- target->AddSource(force.NameCMP0049);
- }
- if (sf) {
- this->AddTargetByproducts(target, byproducts);
- }
-}
-
static void s_AddDefineFlag(std::string const& flag, std::string& dflags)
{
// remove any \n\r
@@ -1357,13 +1271,12 @@ void cmMakefile::AddLinkOption(std::string const& option)
void cmMakefile::AddLinkDirectory(std::string const& directory, bool before)
{
- cmListFileBacktrace lfbt = this->GetBacktrace();
if (before) {
- this->StateSnapshot.GetDirectory().PrependLinkDirectoriesEntry(directory,
- lfbt);
+ this->StateSnapshot.GetDirectory().PrependLinkDirectoriesEntry(
+ directory, this->Backtrace);
} else {
- this->StateSnapshot.GetDirectory().AppendLinkDirectoriesEntry(directory,
- lfbt);
+ this->StateSnapshot.GetDirectory().AppendLinkDirectoriesEntry(
+ directory, this->Backtrace);
}
}
@@ -1820,20 +1733,19 @@ void cmMakefile::AddIncludeDirectories(const std::vector<std::string>& incs,
return;
}
- cmListFileBacktrace lfbt = this->GetBacktrace();
std::string entryString = cmJoin(incs, ";");
if (before) {
this->StateSnapshot.GetDirectory().PrependIncludeDirectoriesEntry(
- entryString, lfbt);
+ entryString, this->Backtrace);
} else {
this->StateSnapshot.GetDirectory().AppendIncludeDirectoriesEntry(
- entryString, lfbt);
+ entryString, this->Backtrace);
}
// Property on each target:
for (auto& target : this->Targets) {
cmTarget& t = target.second;
- t.InsertInclude(entryString, lfbt, before);
+ t.InsertInclude(entryString, this->Backtrace, before);
}
}
@@ -2089,11 +2001,9 @@ cmTarget* cmMakefile::AddNewTarget(cmStateEnums::TargetType type,
}
cmTarget* cmMakefile::AddNewUtilityTarget(const std::string& utilityName,
- cmCommandOrigin origin,
bool excludeFromAll)
{
cmTarget* target = this->AddNewTarget(cmStateEnums::UTILITY, utilityName);
- target->SetIsGeneratorProvided(origin == cmCommandOrigin::Generator);
if (excludeFromAll) {
target->SetProperty("EXCLUDE_FROM_ALL", "TRUE");
}
@@ -2211,8 +2121,8 @@ cmSourceFile* cmMakefile::GetSourceFileWithOutput(
(!o->second.Sources.SourceIsByproduct ||
kind == cmSourceOutputKind::OutputOrByproduct)) {
// Source file could also be null pointer for example if we found the
- // byproduct of a utility target or a PRE_BUILD, PRE_LINK, or POST_BUILD
- // command of a target.
+ // byproduct of a utility target, a PRE_BUILD, PRE_LINK, or POST_BUILD
+ // command of a target, or a not yet created custom command.
return o->second.Sources.Source;
}
return nullptr;
@@ -2220,12 +2130,20 @@ cmSourceFile* cmMakefile::GetSourceFileWithOutput(
bool cmMakefile::MightHaveCustomCommand(const std::string& name) const
{
- // This will have to be changed for delaying custom command creation, because
- // GetSourceFileWithOutput requires the command to be already created.
- if (cmSourceFile* sf = this->GetSourceFileWithOutput(name)) {
- if (sf->GetCustomCommand()) {
- return true;
- }
+ if (this->DelayedOutputFilesHaveGenex ||
+ cmGeneratorExpression::Find(name) != std::string::npos) {
+ // Could be more restrictive, but for now we assume that there could always
+ // be a match when generator expressions are involved.
+ return true;
+ }
+ // Also see LinearGetSourceFileWithOutput.
+ if (!cmSystemTools::FileIsFullPath(name)) {
+ return AnyOutputMatches(name, this->DelayedOutputFiles);
+ }
+ // Otherwise we use an efficient lookup map.
+ auto o = this->OutputToSource.find(name);
+ if (o != this->OutputToSource.end()) {
+ return o->second.SourceMightBeOutput;
}
return false;
}
@@ -2278,6 +2196,7 @@ void cmMakefile::UpdateOutputToSourceMap(std::string const& output,
SourceEntry entry;
entry.Sources.Source = source;
entry.Sources.SourceIsByproduct = byproduct;
+ entry.SourceMightBeOutput = !byproduct;
auto pr = this->OutputToSource.emplace(output, entry);
if (!pr.second) {
@@ -2287,6 +2206,7 @@ void cmMakefile::UpdateOutputToSourceMap(std::string const& output,
(current.Sources.SourceIsByproduct && !byproduct)) {
current.Sources.Source = source;
current.Sources.SourceIsByproduct = false;
+ current.SourceMightBeOutput = true;
} else {
// Multiple custom commands produce the same output but may
// be attached to a different source file (MAIN_DEPENDENCY).
@@ -3553,11 +3473,41 @@ cmSourceFile* cmMakefile::GetOrCreateGeneratedSource(
return sf;
}
-void cmMakefile::CreateGeneratedSources(
+void cmMakefile::CreateGeneratedOutputs(
const std::vector<std::string>& outputs)
{
- for (std::string const& output : outputs) {
- this->GetOrCreateGeneratedSource(output);
+ for (std::string const& o : outputs) {
+ if (cmGeneratorExpression::Find(o) == std::string::npos) {
+ this->GetOrCreateGeneratedSource(o);
+ this->AddDelayedOutput(o);
+ } else {
+ this->DelayedOutputFilesHaveGenex = true;
+ }
+ }
+}
+
+void cmMakefile::CreateGeneratedByproducts(
+ const std::vector<std::string>& byproducts)
+{
+ for (std::string const& o : byproducts) {
+ if (cmGeneratorExpression::Find(o) == std::string::npos) {
+ this->GetOrCreateGeneratedSource(o);
+ }
+ }
+}
+
+void cmMakefile::AddDelayedOutput(std::string const& output)
+{
+ // Note that this vector might contain the output names in a different order
+ // than in source file iteration order.
+ this->DelayedOutputFiles.push_back(output);
+
+ SourceEntry entry;
+ entry.SourceMightBeOutput = true;
+
+ auto pr = this->OutputToSource.emplace(output, entry);
+ if (!pr.second) {
+ pr.first->second.SourceMightBeOutput = true;
}
}
@@ -4029,16 +3979,14 @@ int cmMakefile::ConfigureFile(const std::string& infile,
void cmMakefile::SetProperty(const std::string& prop, const char* value)
{
- cmListFileBacktrace lfbt = this->GetBacktrace();
- this->StateSnapshot.GetDirectory().SetProperty(prop, value, lfbt);
+ this->StateSnapshot.GetDirectory().SetProperty(prop, value, this->Backtrace);
}
void cmMakefile::AppendProperty(const std::string& prop, const char* value,
bool asString)
{
- cmListFileBacktrace lfbt = this->GetBacktrace();
this->StateSnapshot.GetDirectory().AppendProperty(prop, value, asString,
- lfbt);
+ this->Backtrace);
}
const char* cmMakefile::GetProperty(const std::string& prop) const
diff --git a/Source/cmMakefile.h b/Source/cmMakefile.h
index 6e59494..d0dceb9 100644
--- a/Source/cmMakefile.h
+++ b/Source/cmMakefile.h
@@ -49,6 +49,7 @@ class cmGeneratorExpressionEvaluationFile;
class cmGlobalGenerator;
class cmImplicitDependsList;
class cmInstallGenerator;
+class cmLocalGenerator;
class cmMessenger;
class cmSourceFile;
class cmState;
@@ -151,54 +152,64 @@ public:
bool EnforceUniqueName(std::string const& name, std::string& msg,
bool isCustom = false) const;
- using FinalAction = std::function<void(cmMakefile&)>;
+ using GeneratorAction =
+ std::function<void(cmLocalGenerator&, const cmListFileBacktrace&)>;
/**
- * Register an action that is executed during FinalPass
+ * Register an action that is executed during Generate
*/
- void AddFinalAction(FinalAction action);
+ void AddGeneratorAction(GeneratorAction action);
/**
- * Perform FinalPass, Library dependency analysis etc before output of the
- * makefile.
+ * Perform generate actions, Library dependency analysis etc before output of
+ * the makefile.
*/
- void ConfigureFinalPass();
+ void Generate(cmLocalGenerator& lg);
/**
- * run all FinalActions.
+ * Get the target for PRE_BUILD, PRE_LINK, or POST_BUILD commands.
*/
- void FinalPass();
+ cmTarget* GetCustomCommandTarget(const std::string& target,
+ cmObjectLibraryCommands objLibCommands,
+ const cmListFileBacktrace& lfbt) const;
/**
- * Get the target for PRE_BUILD, PRE_LINK, or POST_BUILD commands.
+ * Dispatch adding a custom PRE_BUILD, PRE_LINK, or POST_BUILD command to a
+ * target.
*/
- cmTarget* GetCustomCommandTarget(
- const std::string& target, cmObjectLibraryCommands objLibCommands) const;
-
- /** Add a custom command to the build. */
cmTarget* AddCustomCommandToTarget(
const std::string& target, const std::vector<std::string>& byproducts,
const std::vector<std::string>& depends,
const cmCustomCommandLines& commandLines, cmCustomCommandType type,
const char* comment, const char* workingDir, bool escapeOldStyle = true,
bool uses_terminal = false, const std::string& depfile = "",
- const std::string& job_pool = "", bool command_expand_lists = false,
- cmObjectLibraryCommands objLibCommands = cmObjectLibraryCommands::Reject);
- cmSourceFile* AddCustomCommandToOutput(
+ const std::string& job_pool = "", bool command_expand_lists = false);
+
+ /**
+ * Called for each file with custom command.
+ */
+ using CommandSourceCallback = std::function<void(cmSourceFile*)>;
+
+ /**
+ * Dispatch adding a custom command to a source file.
+ */
+ void AddCustomCommandToOutput(
const std::string& output, const std::vector<std::string>& depends,
const std::string& main_dependency,
const cmCustomCommandLines& commandLines, const char* comment,
- const char* workingDir, bool replace = false, bool escapeOldStyle = true,
+ const char* workingDir, const CommandSourceCallback& callback = nullptr,
+ bool replace = false, bool escapeOldStyle = true,
bool uses_terminal = false, bool command_expand_lists = false,
const std::string& depfile = "", const std::string& job_pool = "");
- cmSourceFile* AddCustomCommandToOutput(
+ void AddCustomCommandToOutput(
const std::vector<std::string>& outputs,
const std::vector<std::string>& byproducts,
const std::vector<std::string>& depends,
const std::string& main_dependency,
const cmImplicitDependsList& implicit_depends,
const cmCustomCommandLines& commandLines, const char* comment,
- const char* workingDir, bool replace = false, bool escapeOldStyle = true,
+ const char* workingDir, const CommandSourceCallback& callback = nullptr,
+ bool replace = false, bool escapeOldStyle = true,
bool uses_terminal = false, bool command_expand_lists = false,
const std::string& depfile = "", const std::string& job_pool = "");
void AddCustomCommandOldStyle(const std::string& target,
@@ -244,7 +255,7 @@ public:
/** Create a target instance for the utility. */
cmTarget* AddNewUtilityTarget(const std::string& utilityName,
- cmCommandOrigin origin, bool excludeFromAll);
+ bool excludeFromAll);
/**
* Add an executable to the build.
@@ -259,13 +270,12 @@ public:
cmUtilityOutput GetUtilityOutput(cmTarget* target);
/**
- * Add a utility to the build. A utility target is a command that
- * is run every time the target is built.
+ * Dispatch adding a utility to the build. A utility target is a command
+ * that is run every time the target is built.
*/
cmTarget* AddUtilityCommand(
- const std::string& utilityName, cmCommandOrigin origin,
- bool excludeFromAll, const char* workingDirectory,
- const std::vector<std::string>& byproducts,
+ const std::string& utilityName, bool excludeFromAll,
+ const char* workingDir, const std::vector<std::string>& byproducts,
const std::vector<std::string>& depends,
const cmCustomCommandLines& commandLines, bool escapeOldStyle = true,
const char* comment = nullptr, bool uses_terminal = false,
@@ -1001,7 +1011,6 @@ protected:
size_t ObjectLibrariesSourceGroupIndex;
#endif
- std::vector<FinalAction> FinalActions;
cmGlobalGenerator* GlobalGenerator;
bool IsFunctionBlocked(const cmListFileFunction& lff,
cmExecutionStatus& status);
@@ -1011,6 +1020,8 @@ private:
cmListFileBacktrace Backtrace;
int RecursionDepth;
+ void DoGenerate(cmLocalGenerator& lg);
+
void ReadListFile(cmListFile const& listFile,
const std::string& filenametoread);
@@ -1080,38 +1091,15 @@ private:
bool ValidateCustomCommand(const cmCustomCommandLines& commandLines) const;
- void CreateGeneratedSources(const std::vector<std::string>& outputs);
+ void CreateGeneratedOutputs(const std::vector<std::string>& outputs);
+ void CreateGeneratedByproducts(const std::vector<std::string>& byproducts);
- void CommitCustomCommandToTarget(
- cmTarget* target, const std::vector<std::string>& byproducts,
- const std::vector<std::string>& depends,
- const cmCustomCommandLines& commandLines, cmCustomCommandType type,
- const char* comment, const char* workingDir, bool escapeOldStyle,
- bool uses_terminal, const std::string& depfile,
- const std::string& job_pool, bool command_expand_lists);
- cmSourceFile* CommitCustomCommandToOutput(
- const std::vector<std::string>& outputs,
- const std::vector<std::string>& byproducts,
- const std::vector<std::string>& depends,
- const std::string& main_dependency,
- const cmImplicitDependsList& implicit_depends,
- const cmCustomCommandLines& commandLines, const char* comment,
- const char* workingDir, bool replace, bool escapeOldStyle,
- bool uses_terminal, bool command_expand_lists, const std::string& depfile,
- const std::string& job_pool);
- void CommitAppendCustomCommandToOutput(
- const std::string& output, const std::vector<std::string>& depends,
- const cmImplicitDependsList& implicit_depends,
- const cmCustomCommandLines& commandLines);
+ std::vector<BT<GeneratorAction>> GeneratorActions;
+ bool GeneratorActionsInvoked = false;
+ bool DelayedOutputFilesHaveGenex = false;
+ std::vector<std::string> DelayedOutputFiles;
- void CommitUtilityCommand(cmTarget* target, const cmUtilityOutput& force,
- const char* workingDirectory,
- const std::vector<std::string>& byproducts,
- const std::vector<std::string>& depends,
- const cmCustomCommandLines& commandLines,
- bool escapeOldStyle, const char* comment,
- bool uses_terminal, bool command_expand_lists,
- const std::string& job_pool);
+ void AddDelayedOutput(std::string const& output);
/**
* See LinearGetSourceFileWithOutput for background information
@@ -1131,6 +1119,7 @@ private:
struct SourceEntry
{
cmSourcesWithOutput Sources;
+ bool SourceMightBeOutput = false;
};
// A map for fast output to input look up.
diff --git a/Source/cmQtAutoGenGlobalInitializer.cxx b/Source/cmQtAutoGenGlobalInitializer.cxx
index 4792860..ef70fce 100644
--- a/Source/cmQtAutoGenGlobalInitializer.cxx
+++ b/Source/cmQtAutoGenGlobalInitializer.cxx
@@ -7,7 +7,6 @@
#include <cm/memory>
#include "cmCustomCommandLines.h"
-#include "cmCustomCommandTypes.h"
#include "cmDuration.h"
#include "cmGeneratorTarget.h"
#include "cmLocalGenerator.h"
@@ -154,12 +153,12 @@ void cmQtAutoGenGlobalInitializer::GetOrCreateGlobalTarget(
cmMakefile* makefile = localGen->GetMakefile();
// Create utility target
- cmTarget* target = makefile->AddUtilityCommand(
- name, cmCommandOrigin::Generator, true,
- makefile->GetHomeOutputDirectory().c_str() /*work dir*/,
- std::vector<std::string>() /*output*/,
- std::vector<std::string>() /*depends*/, cmCustomCommandLines(), false,
- comment.c_str());
+ std::vector<std::string> no_byproducts;
+ std::vector<std::string> no_depends;
+ cmCustomCommandLines no_commands;
+ cmTarget* target = localGen->AddUtilityCommand(
+ name, true, makefile->GetHomeOutputDirectory().c_str(), no_byproducts,
+ no_depends, no_commands, false, comment.c_str());
localGen->AddGeneratorTarget(
cm::make_unique<cmGeneratorTarget>(target, localGen));
diff --git a/Source/cmQtAutoGenInitializer.cxx b/Source/cmQtAutoGenInitializer.cxx
index 68b7122..42979af 100644
--- a/Source/cmQtAutoGenInitializer.cxx
+++ b/Source/cmQtAutoGenInitializer.cxx
@@ -25,7 +25,6 @@
#include "cmAlgorithms.h"
#include "cmCustomCommand.h"
#include "cmCustomCommandLines.h"
-#include "cmCustomCommandTypes.h"
#include "cmGeneratedFileStream.h"
#include "cmGeneratorExpression.h"
#include "cmGeneratorTarget.h"
@@ -1082,8 +1081,8 @@ bool cmQtAutoGenInitializer::InitAutogenTarget()
// PRE_BUILD does not support file dependencies!
const std::vector<std::string> no_output;
const std::vector<std::string> no_deps;
- cmCustomCommand cc(this->Makefile, no_output, autogenProvides, no_deps,
- commandLines, autogenComment.c_str(),
+ cmCustomCommand cc(no_output, autogenProvides, no_deps, commandLines,
+ this->Makefile->GetBacktrace(), autogenComment.c_str(),
this->Dir.Work.c_str());
cc.SetEscapeOldStyle(false);
cc.SetEscapeAllowMakeVars(true);
@@ -1118,9 +1117,9 @@ bool cmQtAutoGenInitializer::InitAutogenTarget()
}
// Create autogen target
- cmTarget* autogenTarget = this->Makefile->AddUtilityCommand(
- this->AutogenTarget.Name, cmCommandOrigin::Generator, true,
- this->Dir.Work.c_str(), /*byproducts=*/autogenProvides,
+ cmTarget* autogenTarget = this->LocalGen->AddUtilityCommand(
+ this->AutogenTarget.Name, true, this->Dir.Work.c_str(),
+ /*byproducts=*/autogenProvides,
std::vector<std::string>(this->AutogenTarget.DependFiles.begin(),
this->AutogenTarget.DependFiles.end()),
commandLines, false, autogenComment.c_str());
@@ -1200,9 +1199,9 @@ bool cmQtAutoGenInitializer::InitRccTargets()
ccName += cmStrCat('_', qrc.QrcPathChecksum);
}
- cmTarget* autoRccTarget = this->Makefile->AddUtilityCommand(
- ccName, cmCommandOrigin::Generator, true, this->Dir.Work.c_str(),
- ccOutput, ccDepends, commandLines, false, ccComment.c_str());
+ cmTarget* autoRccTarget = this->LocalGen->AddUtilityCommand(
+ ccName, true, this->Dir.Work.c_str(), ccOutput, ccDepends,
+ commandLines, false, ccComment.c_str());
// Create autogen generator target
this->LocalGen->AddGeneratorTarget(
@@ -1239,7 +1238,7 @@ bool cmQtAutoGenInitializer::InitRccTargets()
}
std::string no_main_dependency;
cmImplicitDependsList no_implicit_depends;
- this->Makefile->AddCustomCommandToOutput(
+ this->LocalGen->AddCustomCommandToOutput(
ccOutput, ccByproducts, ccDepends, no_main_dependency,
no_implicit_depends, commandLines, ccComment.c_str(),
this->Dir.Work.c_str());
diff --git a/Source/cmVariableWatchCommand.cxx b/Source/cmVariableWatchCommand.cxx
index 039f1ba..35b9a1d 100644
--- a/Source/cmVariableWatchCommand.cxx
+++ b/Source/cmVariableWatchCommand.cxx
@@ -15,6 +15,8 @@
#include "cmVariableWatch.h"
#include "cmake.h"
+class cmLocalGenerator;
+
namespace {
struct cmVariableWatchCallbackData
{
@@ -91,7 +93,7 @@ public:
{
}
- void operator()(cmMakefile&) const {}
+ void operator()(cmLocalGenerator&, const cmListFileBacktrace&) const {}
private:
struct Impl
@@ -145,7 +147,7 @@ bool cmVariableWatchCommand(std::vector<std::string> const& args,
return false;
}
- status.GetMakefile().AddFinalAction(
+ status.GetMakefile().AddGeneratorAction(
FinalAction{ &status.GetMakefile(), variable });
return true;
}
diff --git a/Source/cmVisualStudio10TargetGenerator.cxx b/Source/cmVisualStudio10TargetGenerator.cxx
index 5ffa576..8fc40a79 100644
--- a/Source/cmVisualStudio10TargetGenerator.cxx
+++ b/Source/cmVisualStudio10TargetGenerator.cxx
@@ -2160,7 +2160,6 @@ void cmVisualStudio10TargetGenerator::WriteAllSources(Elem& e0)
this->WriteExtraSource(e1, si.Source);
break;
case cmGeneratorTarget::SourceKindHeader:
- case cmGeneratorTarget::SourceKindUnityBatched:
this->WriteHeaderSource(e1, si.Source);
break;
case cmGeneratorTarget::SourceKindIDL:
@@ -2172,6 +2171,7 @@ void cmVisualStudio10TargetGenerator::WriteAllSources(Elem& e0)
case cmGeneratorTarget::SourceKindModuleDefinition:
tool = "None";
break;
+ case cmGeneratorTarget::SourceKindUnityBatched:
case cmGeneratorTarget::SourceKindObjectSource: {
const std::string& lang = si.Source->GetLanguage();
if (lang == "C" || lang == "CXX") {
diff --git a/Templates/TestDriver.cxx.in b/Templates/TestDriver.cxx.in
index ad8bfb0..846a828 100644
--- a/Templates/TestDriver.cxx.in
+++ b/Templates/TestDriver.cxx.in
@@ -54,7 +54,7 @@ static char* lowercase(const char* string)
if (new_string == CM_NULL) { /* NOLINT */
return CM_NULL; /* NOLINT */
}
- strcpy(new_string, string);
+ strcpy(new_string, string); /* NOLINT */
for (p = new_string; *p != 0; ++p) {
*p = CM_CAST(char, tolower(*p));
}
diff --git a/Tests/CMakeLib/CMakeLists.txt b/Tests/CMakeLib/CMakeLists.txt
index 840afc1..976c924 100644
--- a/Tests/CMakeLib/CMakeLists.txt
+++ b/Tests/CMakeLib/CMakeLists.txt
@@ -25,6 +25,7 @@ set(CMakeLib_TESTS
testUVProcessChain.cxx
testUVRAII.cxx
testUVStreambuf.cxx
+ testCMExtMemory.cxx
)
add_executable(testUVProcessChainHelper testUVProcessChainHelper.cxx)
diff --git a/Tests/CMakeLib/testCMExtMemory.cxx b/Tests/CMakeLib/testCMExtMemory.cxx
new file mode 100644
index 0000000..6663c17
--- /dev/null
+++ b/Tests/CMakeLib/testCMExtMemory.cxx
@@ -0,0 +1,65 @@
+#include <iostream>
+#include <memory>
+
+#include <cmext/memory>
+
+namespace {
+class Base
+{
+public:
+ virtual ~Base() = default;
+};
+
+class Derived : public Base
+{
+public:
+ ~Derived() = default;
+
+ void method() {}
+};
+
+template <typename T>
+class Wrapper
+{
+public:
+ Wrapper(T* v)
+ : value(v)
+ {
+ }
+ ~Wrapper() { delete value; }
+
+ T* get() const { return value; }
+
+private:
+ T* value;
+};
+
+bool testReferenceCast()
+{
+ std::cout << "testReferenceCast()" << std::endl;
+
+ std::unique_ptr<Base> u(new Derived);
+ cm::static_reference_cast<Derived>(u).method();
+ cm::dynamic_reference_cast<Derived>(u).method();
+
+ std::shared_ptr<Base> s(new Derived);
+ cm::static_reference_cast<Derived>(s).method();
+ cm::dynamic_reference_cast<Derived>(s).method();
+
+ // can also be used with custom wrappers
+ Wrapper<Base> w(new Derived);
+ cm::static_reference_cast<Derived>(w).method();
+ cm::dynamic_reference_cast<Derived>(w).method();
+
+ return true;
+}
+}
+
+int testCMExtMemory(int /*unused*/, char* /*unused*/ [])
+{
+ if (!testReferenceCast()) {
+ return 1;
+ }
+
+ return 0;
+}
diff --git a/Tests/CMakeLib/testCTestResourceGroups.cxx b/Tests/CMakeLib/testCTestResourceGroups.cxx
index 5fd7d4a..c3532a6 100644
--- a/Tests/CMakeLib/testCTestResourceGroups.cxx
+++ b/Tests/CMakeLib/testCTestResourceGroups.cxx
@@ -74,6 +74,9 @@ static const std::vector<ExpectedParseResult> expectedResults{
{ "1,threads:1,", true, {
{ { "threads", 1, 1 } },
} },
+ { "threads:1,threads:1", true, {
+ { { "threads", 1, 1 }, { "threads", 1, 1 } },
+ } },
{ "threads:1;;threads:2", true, {
{ { "threads", 1, 1 } },
{ { "threads", 2, 1 } },
diff --git a/Tests/CMakeLib/testCTestResourceSpec.cxx b/Tests/CMakeLib/testCTestResourceSpec.cxx
index e4bc770..b69003d 100644
--- a/Tests/CMakeLib/testCTestResourceSpec.cxx
+++ b/Tests/CMakeLib/testCTestResourceSpec.cxx
@@ -39,6 +39,24 @@ static const std::vector<ExpectedSpec> expectedResourceSpecs = {
{"spec16.json", true, {{{}}}},
{"spec17.json", false, {{{}}}},
{"spec18.json", false, {{{}}}},
+ {"spec19.json", false, {{{}}}},
+ {"spec20.json", true, {{{}}}},
+ {"spec21.json", false, {{{}}}},
+ {"spec22.json", false, {{{}}}},
+ {"spec23.json", false, {{{}}}},
+ {"spec24.json", false, {{{}}}},
+ {"spec25.json", false, {{{}}}},
+ {"spec26.json", false, {{{}}}},
+ {"spec27.json", false, {{{}}}},
+ {"spec28.json", false, {{{}}}},
+ {"spec29.json", false, {{{}}}},
+ {"spec30.json", false, {{{}}}},
+ {"spec31.json", false, {{{}}}},
+ {"spec32.json", false, {{{}}}},
+ {"spec33.json", false, {{{}}}},
+ {"spec34.json", false, {{{}}}},
+ {"spec35.json", false, {{{}}}},
+ {"spec36.json", false, {{{}}}},
{"noexist.json", false, {{{}}}},
/* clang-format on */
};
diff --git a/Tests/CMakeLib/testCTestResourceSpec_data/spec1.json b/Tests/CMakeLib/testCTestResourceSpec_data/spec1.json
index ee3d0ce..b01aa6b 100644
--- a/Tests/CMakeLib/testCTestResourceSpec_data/spec1.json
+++ b/Tests/CMakeLib/testCTestResourceSpec_data/spec1.json
@@ -1,4 +1,8 @@
{
+ "version": {
+ "major": 1,
+ "minor": 0
+ },
"local": [
{
"gpus": [
diff --git a/Tests/CMakeLib/testCTestResourceSpec_data/spec10.json b/Tests/CMakeLib/testCTestResourceSpec_data/spec10.json
index 22105d7..8764907 100644
--- a/Tests/CMakeLib/testCTestResourceSpec_data/spec10.json
+++ b/Tests/CMakeLib/testCTestResourceSpec_data/spec10.json
@@ -1,4 +1,8 @@
{
+ "version": {
+ "major": 1,
+ "minor": 0
+ },
"local": [
{
"gpus": [
diff --git a/Tests/CMakeLib/testCTestResourceSpec_data/spec11.json b/Tests/CMakeLib/testCTestResourceSpec_data/spec11.json
index 1e37ef5..7551ea2 100644
--- a/Tests/CMakeLib/testCTestResourceSpec_data/spec11.json
+++ b/Tests/CMakeLib/testCTestResourceSpec_data/spec11.json
@@ -1,4 +1,8 @@
{
+ "version": {
+ "major": 1,
+ "minor": 0
+ },
"local": [
{
"gpus": [
diff --git a/Tests/CMakeLib/testCTestResourceSpec_data/spec14.json b/Tests/CMakeLib/testCTestResourceSpec_data/spec14.json
index ce708c7..83f480c 100644
--- a/Tests/CMakeLib/testCTestResourceSpec_data/spec14.json
+++ b/Tests/CMakeLib/testCTestResourceSpec_data/spec14.json
@@ -1,4 +1,8 @@
{
+ "version": {
+ "major": 1,
+ "minor": 0
+ },
"local": [
{
"0": [
diff --git a/Tests/CMakeLib/testCTestResourceSpec_data/spec15.json b/Tests/CMakeLib/testCTestResourceSpec_data/spec15.json
index 78b6990..10fe2e3 100644
--- a/Tests/CMakeLib/testCTestResourceSpec_data/spec15.json
+++ b/Tests/CMakeLib/testCTestResourceSpec_data/spec15.json
@@ -1,4 +1,8 @@
{
+ "version": {
+ "major": 1,
+ "minor": 0
+ },
"local": [
{
"-": [
diff --git a/Tests/CMakeLib/testCTestResourceSpec_data/spec16.json b/Tests/CMakeLib/testCTestResourceSpec_data/spec16.json
index 95c7d26..8546759 100644
--- a/Tests/CMakeLib/testCTestResourceSpec_data/spec16.json
+++ b/Tests/CMakeLib/testCTestResourceSpec_data/spec16.json
@@ -1,4 +1,8 @@
{
+ "version": {
+ "major": 1,
+ "minor": 0
+ },
"local": [
{
"A": [
diff --git a/Tests/CMakeLib/testCTestResourceSpec_data/spec17.json b/Tests/CMakeLib/testCTestResourceSpec_data/spec17.json
index 1b6ab4b..e4cdfc9 100644
--- a/Tests/CMakeLib/testCTestResourceSpec_data/spec17.json
+++ b/Tests/CMakeLib/testCTestResourceSpec_data/spec17.json
@@ -1,4 +1,8 @@
{
+ "version": {
+ "major": 1,
+ "minor": 0
+ },
"local": [
{
"gpus": [
diff --git a/Tests/CMakeLib/testCTestResourceSpec_data/spec18.json b/Tests/CMakeLib/testCTestResourceSpec_data/spec18.json
index 1a17df7..26a7c70 100644
--- a/Tests/CMakeLib/testCTestResourceSpec_data/spec18.json
+++ b/Tests/CMakeLib/testCTestResourceSpec_data/spec18.json
@@ -1,4 +1,8 @@
{
+ "version": {
+ "major": 1,
+ "minor": 0
+ },
"local": [
{
"gpus": [
diff --git a/Tests/CMakeLib/testCTestResourceSpec_data/spec19.json b/Tests/CMakeLib/testCTestResourceSpec_data/spec19.json
new file mode 100644
index 0000000..3067f0c
--- /dev/null
+++ b/Tests/CMakeLib/testCTestResourceSpec_data/spec19.json
@@ -0,0 +1,5 @@
+{
+ "version": 1,
+ "local": [
+ ]
+}
diff --git a/Tests/CMakeLib/testCTestResourceSpec_data/spec2.json b/Tests/CMakeLib/testCTestResourceSpec_data/spec2.json
index 6175b1a..df49390 100644
--- a/Tests/CMakeLib/testCTestResourceSpec_data/spec2.json
+++ b/Tests/CMakeLib/testCTestResourceSpec_data/spec2.json
@@ -1,4 +1,8 @@
{
+ "version": {
+ "major": 1,
+ "minor": 0
+ },
"local": [
]
}
diff --git a/Tests/CMakeLib/testCTestResourceSpec_data/spec20.json b/Tests/CMakeLib/testCTestResourceSpec_data/spec20.json
new file mode 100644
index 0000000..df49390
--- /dev/null
+++ b/Tests/CMakeLib/testCTestResourceSpec_data/spec20.json
@@ -0,0 +1,8 @@
+{
+ "version": {
+ "major": 1,
+ "minor": 0
+ },
+ "local": [
+ ]
+}
diff --git a/Tests/CMakeLib/testCTestResourceSpec_data/spec21.json b/Tests/CMakeLib/testCTestResourceSpec_data/spec21.json
new file mode 100644
index 0000000..7459ff2
--- /dev/null
+++ b/Tests/CMakeLib/testCTestResourceSpec_data/spec21.json
@@ -0,0 +1,5 @@
+{
+ "version": [1, 0],
+ "local": [
+ ]
+}
diff --git a/Tests/CMakeLib/testCTestResourceSpec_data/spec22.json b/Tests/CMakeLib/testCTestResourceSpec_data/spec22.json
new file mode 100644
index 0000000..23c57d8
--- /dev/null
+++ b/Tests/CMakeLib/testCTestResourceSpec_data/spec22.json
@@ -0,0 +1,5 @@
+{
+ "version": 2,
+ "local": [
+ ]
+}
diff --git a/Tests/CMakeLib/testCTestResourceSpec_data/spec23.json b/Tests/CMakeLib/testCTestResourceSpec_data/spec23.json
new file mode 100644
index 0000000..a3d0a27
--- /dev/null
+++ b/Tests/CMakeLib/testCTestResourceSpec_data/spec23.json
@@ -0,0 +1,7 @@
+{
+ "version": {
+ "major": 1
+ },
+ "local": [
+ ]
+}
diff --git a/Tests/CMakeLib/testCTestResourceSpec_data/spec24.json b/Tests/CMakeLib/testCTestResourceSpec_data/spec24.json
new file mode 100644
index 0000000..d5f6b08
--- /dev/null
+++ b/Tests/CMakeLib/testCTestResourceSpec_data/spec24.json
@@ -0,0 +1,7 @@
+{
+ "version": {
+ "minor": 0
+ },
+ "local": [
+ ]
+}
diff --git a/Tests/CMakeLib/testCTestResourceSpec_data/spec25.json b/Tests/CMakeLib/testCTestResourceSpec_data/spec25.json
new file mode 100644
index 0000000..914da4b
--- /dev/null
+++ b/Tests/CMakeLib/testCTestResourceSpec_data/spec25.json
@@ -0,0 +1,8 @@
+{
+ "version": {
+ "major": 1,
+ "minor": 1
+ },
+ "local": [
+ ]
+}
diff --git a/Tests/CMakeLib/testCTestResourceSpec_data/spec26.json b/Tests/CMakeLib/testCTestResourceSpec_data/spec26.json
new file mode 100644
index 0000000..c06de22
--- /dev/null
+++ b/Tests/CMakeLib/testCTestResourceSpec_data/spec26.json
@@ -0,0 +1,8 @@
+{
+ "version": {
+ "major": 2,
+ "minor": 0
+ },
+ "local": [
+ ]
+}
diff --git a/Tests/CMakeLib/testCTestResourceSpec_data/spec27.json b/Tests/CMakeLib/testCTestResourceSpec_data/spec27.json
new file mode 100644
index 0000000..9e2b6c3
--- /dev/null
+++ b/Tests/CMakeLib/testCTestResourceSpec_data/spec27.json
@@ -0,0 +1,8 @@
+{
+ "version": {
+ "major": "1",
+ "minor": 0
+ },
+ "local": [
+ ]
+}
diff --git a/Tests/CMakeLib/testCTestResourceSpec_data/spec28.json b/Tests/CMakeLib/testCTestResourceSpec_data/spec28.json
new file mode 100644
index 0000000..ce3b76a
--- /dev/null
+++ b/Tests/CMakeLib/testCTestResourceSpec_data/spec28.json
@@ -0,0 +1,8 @@
+{
+ "version": {
+ "major": 1,
+ "minor": "0"
+ },
+ "local": [
+ ]
+}
diff --git a/Tests/CMakeLib/testCTestResourceSpec_data/spec29.json b/Tests/CMakeLib/testCTestResourceSpec_data/spec29.json
new file mode 100644
index 0000000..58afd2b
--- /dev/null
+++ b/Tests/CMakeLib/testCTestResourceSpec_data/spec29.json
@@ -0,0 +1,5 @@
+{
+ "version": [1, 0, 0],
+ "local": [
+ ]
+}
diff --git a/Tests/CMakeLib/testCTestResourceSpec_data/spec3.json b/Tests/CMakeLib/testCTestResourceSpec_data/spec3.json
index 82453ec..2f1045f 100644
--- a/Tests/CMakeLib/testCTestResourceSpec_data/spec3.json
+++ b/Tests/CMakeLib/testCTestResourceSpec_data/spec3.json
@@ -1,4 +1,8 @@
{
+ "version": {
+ "major": 1,
+ "minor": 0
+ },
"local": [
{
},
diff --git a/Tests/CMakeLib/testCTestResourceSpec_data/spec30.json b/Tests/CMakeLib/testCTestResourceSpec_data/spec30.json
new file mode 100644
index 0000000..9e13ff0
--- /dev/null
+++ b/Tests/CMakeLib/testCTestResourceSpec_data/spec30.json
@@ -0,0 +1,5 @@
+{
+ "version": [1],
+ "local": [
+ ]
+}
diff --git a/Tests/CMakeLib/testCTestResourceSpec_data/spec31.json b/Tests/CMakeLib/testCTestResourceSpec_data/spec31.json
new file mode 100644
index 0000000..c0ef7f4
--- /dev/null
+++ b/Tests/CMakeLib/testCTestResourceSpec_data/spec31.json
@@ -0,0 +1,5 @@
+{
+ "version": [1, 1],
+ "local": [
+ ]
+}
diff --git a/Tests/CMakeLib/testCTestResourceSpec_data/spec32.json b/Tests/CMakeLib/testCTestResourceSpec_data/spec32.json
new file mode 100644
index 0000000..abe977e
--- /dev/null
+++ b/Tests/CMakeLib/testCTestResourceSpec_data/spec32.json
@@ -0,0 +1,5 @@
+{
+ "version": [2, 0],
+ "local": [
+ ]
+}
diff --git a/Tests/CMakeLib/testCTestResourceSpec_data/spec33.json b/Tests/CMakeLib/testCTestResourceSpec_data/spec33.json
new file mode 100644
index 0000000..c6ca749
--- /dev/null
+++ b/Tests/CMakeLib/testCTestResourceSpec_data/spec33.json
@@ -0,0 +1,5 @@
+{
+ "version": ["1", 0],
+ "local": [
+ ]
+}
diff --git a/Tests/CMakeLib/testCTestResourceSpec_data/spec34.json b/Tests/CMakeLib/testCTestResourceSpec_data/spec34.json
new file mode 100644
index 0000000..be258f1
--- /dev/null
+++ b/Tests/CMakeLib/testCTestResourceSpec_data/spec34.json
@@ -0,0 +1,5 @@
+{
+ "version": [1, "0"],
+ "local": [
+ ]
+}
diff --git a/Tests/CMakeLib/testCTestResourceSpec_data/spec35.json b/Tests/CMakeLib/testCTestResourceSpec_data/spec35.json
new file mode 100644
index 0000000..137648c
--- /dev/null
+++ b/Tests/CMakeLib/testCTestResourceSpec_data/spec35.json
@@ -0,0 +1,5 @@
+{
+ "version": "1",
+ "local": [
+ ]
+}
diff --git a/Tests/CMakeLib/testCTestResourceSpec_data/spec36.json b/Tests/CMakeLib/testCTestResourceSpec_data/spec36.json
new file mode 100644
index 0000000..6175b1a
--- /dev/null
+++ b/Tests/CMakeLib/testCTestResourceSpec_data/spec36.json
@@ -0,0 +1,4 @@
+{
+ "local": [
+ ]
+}
diff --git a/Tests/CMakeLib/testCTestResourceSpec_data/spec4.json b/Tests/CMakeLib/testCTestResourceSpec_data/spec4.json
index 05e73d7..17349bd 100644
--- a/Tests/CMakeLib/testCTestResourceSpec_data/spec4.json
+++ b/Tests/CMakeLib/testCTestResourceSpec_data/spec4.json
@@ -1,4 +1,8 @@
{
+ "version": {
+ "major": 1,
+ "minor": 0
+ },
"local": {
}
}
diff --git a/Tests/CMakeLib/testCTestResourceSpec_data/spec5.json b/Tests/CMakeLib/testCTestResourceSpec_data/spec5.json
index 2c63c08..f6e6cb4 100644
--- a/Tests/CMakeLib/testCTestResourceSpec_data/spec5.json
+++ b/Tests/CMakeLib/testCTestResourceSpec_data/spec5.json
@@ -1,2 +1,6 @@
{
+ "version": {
+ "major": 1,
+ "minor": 0
+ }
}
diff --git a/Tests/CMakeLib/testCTestResourceSpec_data/spec6.json b/Tests/CMakeLib/testCTestResourceSpec_data/spec6.json
index 93c790d..eb8b14c 100644
--- a/Tests/CMakeLib/testCTestResourceSpec_data/spec6.json
+++ b/Tests/CMakeLib/testCTestResourceSpec_data/spec6.json
@@ -1,4 +1,8 @@
{
+ "version": {
+ "major": 1,
+ "minor": 0
+ },
"local": [
[]
]
diff --git a/Tests/CMakeLib/testCTestResourceSpec_data/spec7.json b/Tests/CMakeLib/testCTestResourceSpec_data/spec7.json
index 28b6a4f..0447981 100644
--- a/Tests/CMakeLib/testCTestResourceSpec_data/spec7.json
+++ b/Tests/CMakeLib/testCTestResourceSpec_data/spec7.json
@@ -1,4 +1,8 @@
{
+ "version": {
+ "major": 1,
+ "minor": 0
+ },
"local": [
{
"gpus": {
diff --git a/Tests/CMakeLib/testCTestResourceSpec_data/spec8.json b/Tests/CMakeLib/testCTestResourceSpec_data/spec8.json
index 79bd224..ee7a9c2 100644
--- a/Tests/CMakeLib/testCTestResourceSpec_data/spec8.json
+++ b/Tests/CMakeLib/testCTestResourceSpec_data/spec8.json
@@ -1,4 +1,8 @@
{
+ "version": {
+ "major": 1,
+ "minor": 0
+ },
"local": [
{
"gpus": [
diff --git a/Tests/CMakeLib/testCTestResourceSpec_data/spec9.json b/Tests/CMakeLib/testCTestResourceSpec_data/spec9.json
index 6bb1def..ae1117b 100644
--- a/Tests/CMakeLib/testCTestResourceSpec_data/spec9.json
+++ b/Tests/CMakeLib/testCTestResourceSpec_data/spec9.json
@@ -1,4 +1,8 @@
{
+ "version": {
+ "major": 1,
+ "minor": 0
+ },
"local": [
{
"gpus": [
diff --git a/Tests/CMakeLists.txt b/Tests/CMakeLists.txt
index b45782e..0d9e43f 100644
--- a/Tests/CMakeLists.txt
+++ b/Tests/CMakeLists.txt
@@ -1405,6 +1405,7 @@ ${CMake_SOURCE_DIR}/Utilities/Release/push.bash --dir dev -- '${CMake_BUILD_NIGH
ICU
JPEG
JsonCpp
+ LibArchive
LibLZMA
LibRHash
Libinput
diff --git a/Tests/FindLibArchive/CMakeLists.txt b/Tests/FindLibArchive/CMakeLists.txt
new file mode 100644
index 0000000..f532ef2
--- /dev/null
+++ b/Tests/FindLibArchive/CMakeLists.txt
@@ -0,0 +1,10 @@
+add_test(NAME FindLibArchive.Test COMMAND
+ ${CMAKE_CTEST_COMMAND} -C $<CONFIGURATION>
+ --build-and-test
+ "${CMake_SOURCE_DIR}/Tests/FindLibArchive/Test"
+ "${CMake_BINARY_DIR}/Tests/FindLibArchive/Test"
+ ${build_generator_args}
+ --build-project TestFindLibArchive
+ --build-options ${build_options}
+ --test-command ${CMAKE_CTEST_COMMAND} -V -C $<CONFIGURATION>
+ )
diff --git a/Tests/FindLibArchive/Test/CMakeLists.txt b/Tests/FindLibArchive/Test/CMakeLists.txt
new file mode 100644
index 0000000..35843bb
--- /dev/null
+++ b/Tests/FindLibArchive/Test/CMakeLists.txt
@@ -0,0 +1,14 @@
+cmake_minimum_required(VERSION 3.12)
+project(TestFindLibArchive C)
+include(CTest)
+
+find_package(LibArchive REQUIRED)
+
+add_executable(test_libarchive_tgt main.c)
+target_link_libraries(test_libarchive_tgt LibArchive::LibArchive)
+add_test(NAME test_libarchive_tgt COMMAND test_libarchive_tgt)
+
+add_executable(test_libarchive_var main.c)
+target_include_directories(test_libarchive_var PRIVATE ${LibArchive_INCLUDE_DIRS})
+target_link_libraries(test_libarchive_var PRIVATE ${LibArchive_LIBRARIES})
+add_test(NAME test_libarchive_var COMMAND test_libarchive_var)
diff --git a/Tests/FindLibArchive/Test/main.c b/Tests/FindLibArchive/Test/main.c
new file mode 100644
index 0000000..03e7ece
--- /dev/null
+++ b/Tests/FindLibArchive/Test/main.c
@@ -0,0 +1,7 @@
+#include <archive.h>
+
+int main(void)
+{
+ archive_read_free(archive_read_new());
+ return 0;
+}
diff --git a/Tests/RunCMake/CTestResourceAllocation/RunCMakeTest.cmake b/Tests/RunCMake/CTestResourceAllocation/RunCMakeTest.cmake
index d52a63e..8584786 100644
--- a/Tests/RunCMake/CTestResourceAllocation/RunCMakeTest.cmake
+++ b/Tests/RunCMake/CTestResourceAllocation/RunCMakeTest.cmake
@@ -160,6 +160,8 @@ run_ctest_resource(checkfree1 2 0)
run_ctest_resource(checkfree2 1 0)
run_ctest_resource(notenough1 1 0)
run_ctest_resource(notenough2 1 0)
+run_ctest_resource(notenough3 1 0)
+run_ctest_resource(combine 1 0)
run_ctest_resource(ensure_parallel 2 0)
set(ENV{CTEST_RESOURCE_GROUP_COUNT} 2)
diff --git a/Tests/RunCMake/CTestResourceAllocation/combine.cmake b/Tests/RunCMake/CTestResourceAllocation/combine.cmake
new file mode 100644
index 0000000..ed5b251
--- /dev/null
+++ b/Tests/RunCMake/CTestResourceAllocation/combine.cmake
@@ -0,0 +1,5 @@
+setup_resource_tests()
+
+add_resource_test(Test1 0 "widgets:8,widgets:4")
+
+cleanup_resource_tests()
diff --git a/Tests/RunCMake/CTestResourceAllocation/notenough1.cmake b/Tests/RunCMake/CTestResourceAllocation/notenough1.cmake
index 2908812..f820c37 100644
--- a/Tests/RunCMake/CTestResourceAllocation/notenough1.cmake
+++ b/Tests/RunCMake/CTestResourceAllocation/notenough1.cmake
@@ -1,5 +1,5 @@
setup_resource_tests()
-add_resource_test(Test1 1 "fluxcapacitors:200")
+add_resource_test(Test1 0 "fluxcapacitors:200")
cleanup_resource_tests()
diff --git a/Tests/RunCMake/CTestResourceAllocation/notenough2.cmake b/Tests/RunCMake/CTestResourceAllocation/notenough2.cmake
index d7600c8..5b81776 100644
--- a/Tests/RunCMake/CTestResourceAllocation/notenough2.cmake
+++ b/Tests/RunCMake/CTestResourceAllocation/notenough2.cmake
@@ -1,5 +1,5 @@
setup_resource_tests()
-add_resource_test(Test1 1 "terminators:2")
+add_resource_test(Test1 0 "terminators:2")
cleanup_resource_tests()
diff --git a/Tests/RunCMake/CTestResourceAllocation/notenough3-ctest-s-res-check.cmake b/Tests/RunCMake/CTestResourceAllocation/notenough3-ctest-s-res-check.cmake
new file mode 100644
index 0000000..321e9a2
--- /dev/null
+++ b/Tests/RunCMake/CTestResourceAllocation/notenough3-ctest-s-res-check.cmake
@@ -0,0 +1,3 @@
+if(EXISTS "${RunCMake_TEST_BINARY_DIR}/ctresalloc.log")
+ set(RunCMake_TEST_FAILED "ctresalloc.log should not exist")
+endif()
diff --git a/Tests/RunCMake/CTestResourceAllocation/notenough3-ctest-s-res-result.txt b/Tests/RunCMake/CTestResourceAllocation/notenough3-ctest-s-res-result.txt
new file mode 100644
index 0000000..b57e2de
--- /dev/null
+++ b/Tests/RunCMake/CTestResourceAllocation/notenough3-ctest-s-res-result.txt
@@ -0,0 +1 @@
+(-1|255)
diff --git a/Tests/RunCMake/CTestResourceAllocation/notenough3-ctest-s-res-stderr.txt b/Tests/RunCMake/CTestResourceAllocation/notenough3-ctest-s-res-stderr.txt
new file mode 100644
index 0000000..82dfdef
--- /dev/null
+++ b/Tests/RunCMake/CTestResourceAllocation/notenough3-ctest-s-res-stderr.txt
@@ -0,0 +1,4 @@
+^Insufficient resources
+CMake Error at [^
+]*/Tests/RunCMake/CTestResourceAllocation/notenough3-ctest-s-res/test\.cmake:[0-9]+ \(message\):
+ Tests did not pass$
diff --git a/Tests/RunCMake/CTestResourceAllocation/notenough3.cmake b/Tests/RunCMake/CTestResourceAllocation/notenough3.cmake
new file mode 100644
index 0000000..ddf3a9c
--- /dev/null
+++ b/Tests/RunCMake/CTestResourceAllocation/notenough3.cmake
@@ -0,0 +1,5 @@
+setup_resource_tests()
+
+add_resource_test(Test1 0 "widgets:12")
+
+cleanup_resource_tests()
diff --git a/Tests/RunCMake/CTestResourceAllocation/resspec.json b/Tests/RunCMake/CTestResourceAllocation/resspec.json
index c67fcca..48321ec 100644
--- a/Tests/RunCMake/CTestResourceAllocation/resspec.json
+++ b/Tests/RunCMake/CTestResourceAllocation/resspec.json
@@ -1,4 +1,8 @@
{
+ "version": {
+ "major": 1,
+ "minor": 0
+ },
"local": [
{
"widgets": [
diff --git a/Tests/RunCMake/CompilerLauncher/C-common.cmake b/Tests/RunCMake/CompilerLauncher/C-common.cmake
new file mode 100644
index 0000000..96b004b
--- /dev/null
+++ b/Tests/RunCMake/CompilerLauncher/C-common.cmake
@@ -0,0 +1,3 @@
+enable_language(C)
+set(CMAKE_VERBOSE_MAKEFILE TRUE)
+add_executable(main main.c)
diff --git a/Tests/RunCMake/CompilerLauncher/C-env-Build-stdout.txt b/Tests/RunCMake/CompilerLauncher/C-env-Build-stdout.txt
new file mode 100644
index 0000000..3313e31
--- /dev/null
+++ b/Tests/RunCMake/CompilerLauncher/C-env-Build-stdout.txt
@@ -0,0 +1 @@
+.*-E env USED_LAUNCHER=1.*
diff --git a/Tests/RunCMake/CompilerLauncher/C-env-launch-Build-stdout.txt b/Tests/RunCMake/CompilerLauncher/C-env-launch-Build-stdout.txt
new file mode 100644
index 0000000..3313e31
--- /dev/null
+++ b/Tests/RunCMake/CompilerLauncher/C-env-launch-Build-stdout.txt
@@ -0,0 +1 @@
+.*-E env USED_LAUNCHER=1.*
diff --git a/Tests/RunCMake/CompilerLauncher/C-env.cmake b/Tests/RunCMake/CompilerLauncher/C-env.cmake
new file mode 100644
index 0000000..09b5167
--- /dev/null
+++ b/Tests/RunCMake/CompilerLauncher/C-env.cmake
@@ -0,0 +1 @@
+include(C-common.cmake)
diff --git a/Tests/RunCMake/CompilerLauncher/C-launch-env.cmake b/Tests/RunCMake/CompilerLauncher/C-launch-env.cmake
new file mode 100644
index 0000000..68abcb5
--- /dev/null
+++ b/Tests/RunCMake/CompilerLauncher/C-launch-env.cmake
@@ -0,0 +1,3 @@
+set(CTEST_USE_LAUNCHERS 1)
+include(CTestUseLaunchers)
+include(C-env.cmake)
diff --git a/Tests/RunCMake/CompilerLauncher/C.cmake b/Tests/RunCMake/CompilerLauncher/C.cmake
index 67bf7c4..481e74d 100644
--- a/Tests/RunCMake/CompilerLauncher/C.cmake
+++ b/Tests/RunCMake/CompilerLauncher/C.cmake
@@ -1,4 +1,2 @@
-enable_language(C)
set(CMAKE_C_COMPILER_LAUNCHER "${CMAKE_COMMAND};-E;env;USED_LAUNCHER=1")
-set(CMAKE_VERBOSE_MAKEFILE TRUE)
-add_executable(main main.c)
+include(C-common.cmake)
diff --git a/Tests/RunCMake/CompilerLauncher/CUDA-common.cmake b/Tests/RunCMake/CompilerLauncher/CUDA-common.cmake
new file mode 100644
index 0000000..6f7fc86
--- /dev/null
+++ b/Tests/RunCMake/CompilerLauncher/CUDA-common.cmake
@@ -0,0 +1,3 @@
+enable_language(CUDA)
+set(CMAKE_VERBOSE_MAKEFILE TRUE)
+add_executable(main main.cu)
diff --git a/Tests/RunCMake/CompilerLauncher/CUDA-env-Build-stdout.txt b/Tests/RunCMake/CompilerLauncher/CUDA-env-Build-stdout.txt
new file mode 100644
index 0000000..3313e31
--- /dev/null
+++ b/Tests/RunCMake/CompilerLauncher/CUDA-env-Build-stdout.txt
@@ -0,0 +1 @@
+.*-E env USED_LAUNCHER=1.*
diff --git a/Tests/RunCMake/CompilerLauncher/CUDA-env-launch-Build-stdout.txt b/Tests/RunCMake/CompilerLauncher/CUDA-env-launch-Build-stdout.txt
new file mode 100644
index 0000000..3313e31
--- /dev/null
+++ b/Tests/RunCMake/CompilerLauncher/CUDA-env-launch-Build-stdout.txt
@@ -0,0 +1 @@
+.*-E env USED_LAUNCHER=1.*
diff --git a/Tests/RunCMake/CompilerLauncher/CUDA-env.cmake b/Tests/RunCMake/CompilerLauncher/CUDA-env.cmake
new file mode 100644
index 0000000..cefbe9e
--- /dev/null
+++ b/Tests/RunCMake/CompilerLauncher/CUDA-env.cmake
@@ -0,0 +1 @@
+include(CUDA-common.cmake)
diff --git a/Tests/RunCMake/CompilerLauncher/CUDA-launch-env.cmake b/Tests/RunCMake/CompilerLauncher/CUDA-launch-env.cmake
new file mode 100644
index 0000000..d0d777a
--- /dev/null
+++ b/Tests/RunCMake/CompilerLauncher/CUDA-launch-env.cmake
@@ -0,0 +1,3 @@
+set(CTEST_USE_LAUNCHERS 1)
+include(CTestUseLaunchers)
+include(CUDA-env.cmake)
diff --git a/Tests/RunCMake/CompilerLauncher/CUDA.cmake b/Tests/RunCMake/CompilerLauncher/CUDA.cmake
index fe5560b..7f1652b 100644
--- a/Tests/RunCMake/CompilerLauncher/CUDA.cmake
+++ b/Tests/RunCMake/CompilerLauncher/CUDA.cmake
@@ -1,4 +1,2 @@
-enable_language(CUDA)
set(CMAKE_CUDA_COMPILER_LAUNCHER "${CMAKE_COMMAND};-E;env;USED_LAUNCHER=1")
-set(CMAKE_VERBOSE_MAKEFILE TRUE)
-add_executable(main main.cu)
+include(CUDA-common.cmake)
diff --git a/Tests/RunCMake/CompilerLauncher/CXX-common.cmake b/Tests/RunCMake/CompilerLauncher/CXX-common.cmake
new file mode 100644
index 0000000..3d2ee00
--- /dev/null
+++ b/Tests/RunCMake/CompilerLauncher/CXX-common.cmake
@@ -0,0 +1,3 @@
+enable_language(CXX)
+set(CMAKE_VERBOSE_MAKEFILE TRUE)
+add_executable(main main.cxx)
diff --git a/Tests/RunCMake/CompilerLauncher/CXX-env-Build-stdout.txt b/Tests/RunCMake/CompilerLauncher/CXX-env-Build-stdout.txt
new file mode 100644
index 0000000..3313e31
--- /dev/null
+++ b/Tests/RunCMake/CompilerLauncher/CXX-env-Build-stdout.txt
@@ -0,0 +1 @@
+.*-E env USED_LAUNCHER=1.*
diff --git a/Tests/RunCMake/CompilerLauncher/CXX-env-launch-Build-stdout.txt b/Tests/RunCMake/CompilerLauncher/CXX-env-launch-Build-stdout.txt
new file mode 100644
index 0000000..3313e31
--- /dev/null
+++ b/Tests/RunCMake/CompilerLauncher/CXX-env-launch-Build-stdout.txt
@@ -0,0 +1 @@
+.*-E env USED_LAUNCHER=1.*
diff --git a/Tests/RunCMake/CompilerLauncher/CXX-env.cmake b/Tests/RunCMake/CompilerLauncher/CXX-env.cmake
new file mode 100644
index 0000000..db36956
--- /dev/null
+++ b/Tests/RunCMake/CompilerLauncher/CXX-env.cmake
@@ -0,0 +1 @@
+include(CXX-common.cmake)
diff --git a/Tests/RunCMake/CompilerLauncher/CXX-launch-env.cmake b/Tests/RunCMake/CompilerLauncher/CXX-launch-env.cmake
new file mode 100644
index 0000000..a65cc89
--- /dev/null
+++ b/Tests/RunCMake/CompilerLauncher/CXX-launch-env.cmake
@@ -0,0 +1,3 @@
+set(CTEST_USE_LAUNCHERS 1)
+include(CTestUseLaunchers)
+include(CXX-env.cmake)
diff --git a/Tests/RunCMake/CompilerLauncher/CXX.cmake b/Tests/RunCMake/CompilerLauncher/CXX.cmake
index cdd3478..1f9a12b 100644
--- a/Tests/RunCMake/CompilerLauncher/CXX.cmake
+++ b/Tests/RunCMake/CompilerLauncher/CXX.cmake
@@ -1,4 +1,2 @@
-enable_language(CXX)
set(CMAKE_CXX_COMPILER_LAUNCHER "${CMAKE_COMMAND};-E;env;USED_LAUNCHER=1")
-set(CMAKE_VERBOSE_MAKEFILE TRUE)
-add_executable(main main.cxx)
+include(CXX-common.cmake)
diff --git a/Tests/RunCMake/CompilerLauncher/Fortran-common.cmake b/Tests/RunCMake/CompilerLauncher/Fortran-common.cmake
new file mode 100644
index 0000000..e33c2ca
--- /dev/null
+++ b/Tests/RunCMake/CompilerLauncher/Fortran-common.cmake
@@ -0,0 +1,3 @@
+enable_language(Fortran)
+set(CMAKE_VERBOSE_MAKEFILE TRUE)
+add_executable(main main.F)
diff --git a/Tests/RunCMake/CompilerLauncher/Fortran-env-Build-stdout.txt b/Tests/RunCMake/CompilerLauncher/Fortran-env-Build-stdout.txt
new file mode 100644
index 0000000..3313e31
--- /dev/null
+++ b/Tests/RunCMake/CompilerLauncher/Fortran-env-Build-stdout.txt
@@ -0,0 +1 @@
+.*-E env USED_LAUNCHER=1.*
diff --git a/Tests/RunCMake/CompilerLauncher/Fortran-env-launch-Build-stdout.txt b/Tests/RunCMake/CompilerLauncher/Fortran-env-launch-Build-stdout.txt
new file mode 100644
index 0000000..3313e31
--- /dev/null
+++ b/Tests/RunCMake/CompilerLauncher/Fortran-env-launch-Build-stdout.txt
@@ -0,0 +1 @@
+.*-E env USED_LAUNCHER=1.*
diff --git a/Tests/RunCMake/CompilerLauncher/Fortran-env.cmake b/Tests/RunCMake/CompilerLauncher/Fortran-env.cmake
new file mode 100644
index 0000000..3dc27c3
--- /dev/null
+++ b/Tests/RunCMake/CompilerLauncher/Fortran-env.cmake
@@ -0,0 +1 @@
+include(Fortran-common.cmake)
diff --git a/Tests/RunCMake/CompilerLauncher/Fortran-launch-env.cmake b/Tests/RunCMake/CompilerLauncher/Fortran-launch-env.cmake
new file mode 100644
index 0000000..30a196c
--- /dev/null
+++ b/Tests/RunCMake/CompilerLauncher/Fortran-launch-env.cmake
@@ -0,0 +1,3 @@
+set(CTEST_USE_LAUNCHERS 1)
+include(CTestUseLaunchers)
+include(Fortran-env.cmake)
diff --git a/Tests/RunCMake/CompilerLauncher/Fortran.cmake b/Tests/RunCMake/CompilerLauncher/Fortran.cmake
index 72cc03e..dc46173 100644
--- a/Tests/RunCMake/CompilerLauncher/Fortran.cmake
+++ b/Tests/RunCMake/CompilerLauncher/Fortran.cmake
@@ -1,4 +1,2 @@
-enable_language(Fortran)
set(CMAKE_Fortran_COMPILER_LAUNCHER "${CMAKE_COMMAND};-E;env;USED_LAUNCHER=1")
-set(CMAKE_VERBOSE_MAKEFILE TRUE)
-add_executable(main main.F)
+include(Fortran-common.cmake)
diff --git a/Tests/RunCMake/CompilerLauncher/RunCMakeTest.cmake b/Tests/RunCMake/CompilerLauncher/RunCMakeTest.cmake
index bb8da03..f86e8ea 100644
--- a/Tests/RunCMake/CompilerLauncher/RunCMakeTest.cmake
+++ b/Tests/RunCMake/CompilerLauncher/RunCMakeTest.cmake
@@ -15,6 +15,13 @@ function(run_compiler_launcher lang)
run_cmake_command(${lang}-Build ${CMAKE_COMMAND} --build . ${verbose_args})
endfunction()
+function(run_compiler_launcher_env lang)
+ string(REGEX REPLACE "-.*" "" core_lang "${lang}")
+ set(ENV{CMAKE_${core_lang}_COMPILER_LAUNCHER} "${CMAKE_COMMAND};-E;env;USED_LAUNCHER=1")
+ run_compiler_launcher(${lang})
+ unset(ENV{CMAKE_${core_lang}_COMPILER_LAUNCHER})
+endfunction()
+
set(langs C CXX)
if(CMake_TEST_CUDA)
list(APPEND langs CUDA)
@@ -25,7 +32,9 @@ endif()
foreach(lang ${langs})
run_compiler_launcher(${lang})
+ run_compiler_launcher_env(${lang}-env)
if (NOT RunCMake_GENERATOR STREQUAL "Watcom WMake")
run_compiler_launcher(${lang}-launch)
+ run_compiler_launcher_env(${lang}-launch-env)
endif()
endforeach()
diff --git a/Tests/RunCMake/ObjectLibrary/OwnSources-stderr.txt b/Tests/RunCMake/ObjectLibrary/OwnSources-stderr.txt
index 208f3c9..cb1a2e5 100644
--- a/Tests/RunCMake/ObjectLibrary/OwnSources-stderr.txt
+++ b/Tests/RunCMake/ObjectLibrary/OwnSources-stderr.txt
@@ -4,4 +4,10 @@
Call Stack \(most recent call first\):
CMakeLists.txt:[0-9]+ \(include\)
+
+CMake Error at OwnSources.cmake:[0-9]+ \(add_library\):
+ The SOURCES of "A" use a generator expression that depends on the SOURCES
+ themselves.
+Call Stack \(most recent call first\):
+ CMakeLists.txt:[0-9]+ \(include\)
++
CMake Generate step failed\. Build files cannot be regenerated correctly\.$
diff --git a/Tests/RunCMake/PrecompileHeaders/PchReuseFromPrefixed-build-stderr.txt b/Tests/RunCMake/PrecompileHeaders/PchReuseFromPrefixed-build-stderr.txt
new file mode 100644
index 0000000..8cdcfd9
--- /dev/null
+++ b/Tests/RunCMake/PrecompileHeaders/PchReuseFromPrefixed-build-stderr.txt
@@ -0,0 +1,2 @@
+^(|Warning #670: precompiled header file [^
+]* was not generated in this directory)$
diff --git a/Tests/RunCMake/PrecompileHeaders/PchReuseFromPrefixed.cmake b/Tests/RunCMake/PrecompileHeaders/PchReuseFromPrefixed.cmake
new file mode 100644
index 0000000..e306d8e
--- /dev/null
+++ b/Tests/RunCMake/PrecompileHeaders/PchReuseFromPrefixed.cmake
@@ -0,0 +1,29 @@
+cmake_minimum_required(VERSION 3.15)
+project(PchReuseFromPrefixed C)
+
+if(CMAKE_C_COMPILE_OPTIONS_USE_PCH)
+ add_definitions(-DHAVE_PCH_SUPPORT)
+endif()
+
+add_library(empty empty.c)
+target_precompile_headers(empty PRIVATE
+ <stdio.h>
+ <string.h>
+)
+target_include_directories(empty PUBLIC include)
+
+add_library(foo foo.c)
+target_include_directories(foo PUBLIC include)
+target_precompile_headers(foo REUSE_FROM empty)
+
+# Visual Studio 2017 and greater
+if (NOT (CMAKE_C_COMPILER_ID STREQUAL "MSVC" AND CMAKE_C_COMPILER_VERSION VERSION_LESS_EQUAL 19.10))
+ set_target_properties(foo PROPERTIES PREFIX "lib" IMPORT_PREFIX "lib")
+endif()
+
+add_executable(foobar foobar.c)
+target_link_libraries(foobar foo )
+set_target_properties(foobar PROPERTIES PRECOMPILE_HEADERS_REUSE_FROM empty)
+
+enable_testing()
+add_test(NAME foobar COMMAND foobar)
diff --git a/Tests/RunCMake/PrecompileHeaders/RunCMakeTest.cmake b/Tests/RunCMake/PrecompileHeaders/RunCMakeTest.cmake
index ec13663..8d2f4f9 100644
--- a/Tests/RunCMake/PrecompileHeaders/RunCMakeTest.cmake
+++ b/Tests/RunCMake/PrecompileHeaders/RunCMakeTest.cmake
@@ -17,5 +17,6 @@ run_test(PchInterface)
run_cmake(PchPrologueEpilogue)
run_test(SkipPrecompileHeaders)
run_test(PchReuseFrom)
+run_test(PchReuseFromPrefixed)
run_test(PchReuseFromSubdir)
run_cmake(PchMultilanguage)
diff --git a/Tests/RunCMake/UnityBuild/RunCMakeTest.cmake b/Tests/RunCMake/UnityBuild/RunCMakeTest.cmake
index 8e484d0..24daa64 100644
--- a/Tests/RunCMake/UnityBuild/RunCMakeTest.cmake
+++ b/Tests/RunCMake/UnityBuild/RunCMakeTest.cmake
@@ -21,3 +21,4 @@ function(run_test name)
endfunction()
run_test(unitybuild_runtest)
+run_test(unitybuild_object_library)
diff --git a/Tests/RunCMake/UnityBuild/unitybuild_object_library.cmake b/Tests/RunCMake/UnityBuild/unitybuild_object_library.cmake
new file mode 100644
index 0000000..b400517
--- /dev/null
+++ b/Tests/RunCMake/UnityBuild/unitybuild_object_library.cmake
@@ -0,0 +1,13 @@
+project(unitybuild_object_library C)
+
+set(CMAKE_UNITY_BUILD ON) # This tests that the variable works in addition to the property
+
+add_library(lib OBJECT func.c)
+
+add_library(other-lib STATIC func.c)
+
+add_executable(main main.c)
+target_link_libraries(main PRIVATE lib)
+
+enable_testing()
+add_test(NAME main COMMAND main)
diff --git a/Utilities/GitSetup/setup-user b/Utilities/GitSetup/setup-user
index 1af439c..0b98879 100755
--- a/Utilities/GitSetup/setup-user
+++ b/Utilities/GitSetup/setup-user
@@ -20,12 +20,12 @@
# Project configuration instructions: NONE
for (( ; ; )); do
- user_name=$(git config user.name || echo '') &&
- user_email=$(git config user.email || echo '') &&
- if test -n "$user_name" -a -n "$user_email"; then
+ ident="$(git var GIT_AUTHOR_IDENT 2>/dev/null | rev | cut -d' ' -f3- | rev)"
+
+ if test -n "$ident"; then
echo 'Your commits will record as Author:
- '"$user_name <$user_email>"'
+ '"$ident"'
' &&
read -ep 'Is the author name and email address above correct? [Y/n] ' correct &&
if test "$correct" != "n" -a "$correct" != "N"; then
diff --git a/Utilities/std/.gitattributes b/Utilities/std/.gitattributes
index cd20549..789a754 100644
--- a/Utilities/std/.gitattributes
+++ b/Utilities/std/.gitattributes
@@ -1 +1,2 @@
cm/* our-c-style
+cmext/* our-c-style
diff --git a/Utilities/std/cm/type_traits b/Utilities/std/cm/type_traits
new file mode 100644
index 0000000..6d7a2c0
--- /dev/null
+++ b/Utilities/std/cm/type_traits
@@ -0,0 +1,46 @@
+// -*-c++-*-
+// vim: set ft=cpp:
+
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#ifndef cm_type_traits
+#define cm_type_traits
+
+#include <type_traits> // IWYU pragma: export
+
+namespace cm {
+
+#if __cplusplus >= 201402L || (defined(_MSVC_LANG) && _MSVC_LANG >= 201402L)
+
+// Miscellaneous transformations
+template <bool B, typename T = void>
+using enable_if_t = std::enable_if_t<B, T>;
+
+#else
+
+// Miscellaneous transformations
+template <bool B, typename T = void>
+using enable_if_t = typename std::enable_if<B, T>::type;
+
+#endif
+
+#if __cplusplus >= 201703L || (defined(_MSVC_LANG) && _MSVC_LANG >= 201703)
+
+// Miscellaneous transformations
+using std::invoke_result;
+using std::invoke_result_t;
+
+#else
+
+// Miscellaneous transformations
+template <typename F, typename... ArgTypes>
+using invoke_result = std::result_of<F(ArgTypes...)>;
+
+template <class F, typename... ArgTypes>
+using invoke_result_t = typename invoke_result<F, ArgTypes...>::type;
+
+#endif
+
+} // namespace cm
+
+#endif
diff --git a/Utilities/std/cmext/memory b/Utilities/std/cmext/memory
new file mode 100644
index 0000000..540a3de
--- /dev/null
+++ b/Utilities/std/cmext/memory
@@ -0,0 +1,32 @@
+// -*-c++-*-
+// vim: set ft=cpp:
+
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#ifndef cmext_memory
+#define cmext_memory
+
+#include <cm/type_traits>
+
+namespace cm {
+
+template <typename T, typename O,
+ cm::enable_if_t<
+ std::is_pointer<cm::invoke_result_t<decltype(&O::get), O>>::value,
+ int> = 0>
+T& static_reference_cast(O& item)
+{
+ return *(static_cast<T*>(item.get()));
+}
+template <typename T, typename O,
+ cm::enable_if_t<
+ std::is_pointer<cm::invoke_result_t<decltype(&O::get), O>>::value,
+ int> = 0>
+T& dynamic_reference_cast(O& item)
+{
+ return *(dynamic_cast<T*>(item.get()));
+}
+
+} // namespace cm
+
+#endif
diff --git a/bootstrap b/bootstrap
index 4432d49..8606dda 100755
--- a/bootstrap
+++ b/bootstrap
@@ -294,6 +294,7 @@ CMAKE_CXX_SOURCES="\
cmCreateTestSourceList \
cmCustomCommand \
cmCustomCommandGenerator \
+ cmCustomCommandLines \
cmDefinePropertyCommand \
cmDefinitions \
cmDepends \