Merge topic 'ctest-drmemory-support'
676befdf52 ctest: add support for memcheck using Dr. Memory
2db0a65f56 cmCTestMemCheckHandler.cxx: minor refactoring
Acked-by: Kitware Robot <kwrobot@kitware.com>
Merge-request: !4119
diff --git a/.clang-format b/.clang-format
index 0c7d6b0..a7f049a 100644
--- a/.clang-format
+++ b/.clang-format
@@ -22,7 +22,7 @@
IncludeCategories:
- Regex: '^[<"]cmConfigure\.h'
Priority: -1
- - Regex: '^(<|")cm/'
+ - Regex: '^(<|")cm(ext)?/'
Priority: 2
- Regex: '^(<|")windows\.h'
Priority: 3
diff --git a/CompileFlags.cmake b/CompileFlags.cmake
index 91f2adf..053259f 100644
--- a/CompileFlags.cmake
+++ b/CompileFlags.cmake
@@ -54,12 +54,20 @@
endif()
# Workaround for TOC Overflow on ppc64
+set(bigTocFlag "")
if(CMAKE_SYSTEM_NAME STREQUAL "AIX" AND
CMAKE_SYSTEM_PROCESSOR MATCHES "powerpc")
- set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,-bbigtoc")
+ set(bigTocFlag "-Wl,-bbigtoc")
elseif(CMAKE_SYSTEM_NAME STREQUAL "Linux" AND
CMAKE_SYSTEM_PROCESSOR MATCHES "ppc64")
- set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--no-multi-toc")
+ set(bigTocFlag "-Wl,--no-multi-toc")
+endif()
+if(bigTocFlag)
+ include(CheckCXXLinkerFlag)
+ check_cxx_linker_flag(${bigTocFlag} BIG_TOC_FLAG_SUPPORTED)
+ if(BIG_TOC_FLAG_SUPPORTED)
+ set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${bigTocFlag}")
+ endif()
endif()
if (CMAKE_CXX_COMPILER_ID STREQUAL SunPro AND
diff --git a/Help/command/foreach.rst b/Help/command/foreach.rst
index ecbfed3..a01a104 100644
--- a/Help/command/foreach.rst
+++ b/Help/command/foreach.rst
@@ -82,3 +82,46 @@
-- X=6
-- X=7
-- X=8
+
+
+.. code-block:: cmake
+
+ foreach(<loop_var>... IN ZIP_LISTS <lists>)
+
+In this variant, ``<lists>`` is a whitespace or semicolon
+separated list of list-valued variables. The ``foreach``
+command iterates over each list simultaneously setting the
+iteration variables as follows:
+
+- if the only ``loop_var`` given, then it sets a series of
+ ``loop_var_N`` variables to the current item from the
+ corresponding list;
+- if multiple variable names passed, their count should match
+ the lists variables count;
+- if any of the lists are shorter, the corresponding iteration
+ variable is not defined for the current iteration.
+
+.. code-block:: cmake
+
+ list(APPEND English one two three four)
+ list(APPEND Bahasa satu dua tiga)
+
+ foreach(num IN ZIP_LISTS English Bahasa)
+ message(STATUS "num_0=${num_0}, num_1=${num_1}")
+ endforeach()
+
+ foreach(en ba IN ZIP_LISTS English Bahasa)
+ message(STATUS "en=${en}, ba=${ba}")
+ endforeach()
+
+yields
+::
+
+ -- num_0=one, num_1=satu
+ -- num_0=two, num_1=dua
+ -- num_0=three, num_1=tiga
+ -- num_0=four, num_1=
+ -- en=one, ba=satu
+ -- en=two, ba=dua
+ -- en=three, ba=tiga
+ -- en=four, ba=
diff --git a/Help/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 @@
/envvar/CMAKE_GENERATOR_INSTANCE
/envvar/CMAKE_GENERATOR_PLATFORM
/envvar/CMAKE_GENERATOR_TOOLSET
+ /envvar/CMAKE_LANG_COMPILER_LAUNCHER
/envvar/CMAKE_MSVCIDE_RUN_PATH
/envvar/CMAKE_NO_VERBOSE
/envvar/CMAKE_OSX_ARCHITECTURES
diff --git a/Help/manual/cmake-policies.7.rst b/Help/manual/cmake-policies.7.rst
index eceeac7..2118031 100644
--- a/Help/manual/cmake-policies.7.rst
+++ b/Help/manual/cmake-policies.7.rst
@@ -57,6 +57,7 @@
.. toctree::
:maxdepth: 1
+ CMP0099: Link properties are transitive over private dependency on static libraries. </policy/CMP0099>
CMP0098: FindFLEX runs flex in CMAKE_CURRENT_BINARY_DIR when executing. </policy/CMP0098>
Policies Introduced by CMake 3.16
diff --git a/Help/policy/CMP0099.rst b/Help/policy/CMP0099.rst
new file mode 100644
index 0000000..c897e7b
--- /dev/null
+++ b/Help/policy/CMP0099.rst
@@ -0,0 +1,24 @@
+CMP0099
+-------
+
+Target link properties :prop_tgt:`INTERFACE_LINK_OPTIONS`,
+:prop_tgt:`INTERFACE_LINK_DIRECTORIES` and :prop_tgt:`INTERFACE_LINK_DEPENDS`
+are now transitive over private dependencies of static libraries.
+
+In CMake 3.16 and below the interface link properties attached to libraries
+are not propagated for private dependencies of static libraries.
+Only the libraries themselves are propagated to link the dependent binary.
+CMake 3.17 and later prefer to propagate all interface link properties.
+This policy provides compatibility for projects that have not been updated
+to expect the new behavior.
+
+The ``OLD`` behavior for this policy is to not propagate interface link
+properties. The ``NEW`` behavior of this policy is to propagate interface link
+properties.
+
+This policy was introduced in CMake version 3.17. Use the
+:command:`cmake_policy` command to set it to ``OLD`` or ``NEW`` explicitly.
+Unlike many policies, CMake version |release| does *not* warn
+when this policy is not set and simply uses ``OLD`` behavior.
+
+.. include:: DEPRECATED.txt
diff --git a/Help/prop_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 @@
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/Link-properties-transitive.rst b/Help/release/dev/Link-properties-transitive.rst
new file mode 100644
index 0000000..535b40c
--- /dev/null
+++ b/Help/release/dev/Link-properties-transitive.rst
@@ -0,0 +1,8 @@
+Link-properties-transitive
+--------------------------
+
+* Target link properties :prop_tgt:`INTERFACE_LINK_OPTIONS`,
+ :prop_tgt:`INTERFACE_LINK_DIRECTORIES` and
+ :prop_tgt:`INTERFACE_LINK_DEPENDS` are now transitive over private
+ dependency on static libraries.
+ See policy :policy:`CMP0099`.
diff --git a/Help/release/dev/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/ctest-configuration-type.rst b/Help/release/dev/ctest-configuration-type.rst
new file mode 100644
index 0000000..89e36c4
--- /dev/null
+++ b/Help/release/dev/ctest-configuration-type.rst
@@ -0,0 +1,5 @@
+ctest-configuration-type
+------------------------
+
+* The :variable:`CTEST_CONFIGURATION_TYPE` variable is now set from the command
+ line when :manual:`ctest(1)` is invoked with ``-C <cfg>``.
diff --git a/Help/release/dev/foreach-ZIP_LISTS.rst b/Help/release/dev/foreach-ZIP_LISTS.rst
new file mode 100644
index 0000000..d45d9b9
--- /dev/null
+++ b/Help/release/dev/foreach-ZIP_LISTS.rst
@@ -0,0 +1,5 @@
+foreach-ZIP_LISTS
+-----------------
+
+* The :command:`foreach` learned a new option ``ZIP_LISTS`` to iterate
+ over multiple lists simultaneously.
diff --git a/Help/release/dev/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/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 @@
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 @@
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 @@
This variable is used to initialize the property on each target as it is
created. This is done only when ``<LANG>`` is ``C``, ``CXX``, ``Fortran``,
or ``CUDA``.
+
+This variable is initialized to the :envvar:`CMAKE_<LANG>_COMPILER_LAUNCHER`
+environment variable if it is set.
diff --git a/Help/variable/CTEST_CONFIGURATION_TYPE.rst b/Help/variable/CTEST_CONFIGURATION_TYPE.rst
index c905480..9e277fa 100644
--- a/Help/variable/CTEST_CONFIGURATION_TYPE.rst
+++ b/Help/variable/CTEST_CONFIGURATION_TYPE.rst
@@ -3,3 +3,6 @@
Specify the CTest ``DefaultCTestConfigurationType`` setting
in a :manual:`ctest(1)` dashboard client script.
+
+If the configuration type is set via ``-C <cfg>`` from the command line
+then this variable is populated accordingly.
diff --git a/Modules/CMakeCInformation.cmake b/Modules/CMakeCInformation.cmake
index df43559..1e08bb7 100644
--- a/Modules/CMakeCInformation.cmake
+++ b/Modules/CMakeCInformation.cmake
@@ -110,6 +110,11 @@
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_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 @@
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 @@
# 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 @@
#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 @@
"<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 @@
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 @@
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 0b3664c..002fe21 100644
--- a/Modules/CMakeDetermineCompilerId.cmake
+++ b/Modules/CMakeDetermineCompilerId.cmake
@@ -246,7 +246,7 @@
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)
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 @@
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/CheckCCompilerFlag.cmake b/Modules/CheckCCompilerFlag.cmake
index a3e2da3..6d65313 100644
--- a/Modules/CheckCCompilerFlag.cmake
+++ b/Modules/CheckCCompilerFlag.cmake
@@ -36,28 +36,23 @@
include(CheckCSourceCompiles)
include(CMakeCheckCompilerFlagCommonPatterns)
-macro (CHECK_C_COMPILER_FLAG _FLAG _RESULT)
- set(SAFE_CMAKE_REQUIRED_DEFINITIONS "${CMAKE_REQUIRED_DEFINITIONS}")
- set(CMAKE_REQUIRED_DEFINITIONS "${_FLAG}")
+function(check_c_compiler_flag _flag _var)
+ set(CMAKE_REQUIRED_DEFINITIONS "${_flag}")
- # Normalize locale during test compilation.
- set(_CheckCCompilerFlag_LOCALE_VARS LC_ALL LC_MESSAGES LANG)
- foreach(v ${_CheckCCompilerFlag_LOCALE_VARS})
- set(_CheckCCompilerFlag_SAVED_${v} "$ENV{${v}}")
+ # Normalize locale during test compilation.
+ set(_locale_vars LC_ALL LC_MESSAGES LANG)
+ foreach(v IN LISTS _locale_vars)
+ set(_locale_vars_saved_${v} "$ENV{${v}}")
set(ENV{${v}} C)
endforeach()
- CHECK_COMPILER_FLAG_COMMON_PATTERNS(_CheckCCompilerFlag_COMMON_PATTERNS)
- CHECK_C_SOURCE_COMPILES("int main(void) { return 0; }" ${_RESULT}
+ check_compiler_flag_common_patterns(_common_patterns)
+ check_c_source_compiles("int main(void) { return 0; }" ${_var}
# Some compilers do not fail with a bad flag
FAIL_REGEX "command line option .* is valid for .* but not for C" # GNU
- ${_CheckCCompilerFlag_COMMON_PATTERNS}
+ ${_common_patterns}
)
- foreach(v ${_CheckCCompilerFlag_LOCALE_VARS})
- set(ENV{${v}} ${_CheckCCompilerFlag_SAVED_${v}})
- unset(_CheckCCompilerFlag_SAVED_${v})
+ foreach(v IN LISTS _locale_vars)
+ set(ENV{${v}} ${_locale_vars_saved_${v}})
endforeach()
- unset(_CheckCCompilerFlag_LOCALE_VARS)
- unset(_CheckCCompilerFlag_COMMON_PATTERNS)
-
- set (CMAKE_REQUIRED_DEFINITIONS "${SAFE_CMAKE_REQUIRED_DEFINITIONS}")
-endmacro ()
+ set(${_var} "${${_var}}" PARENT_SCOPE)
+endfunction()
diff --git a/Modules/CheckCXXCompilerFlag.cmake b/Modules/CheckCXXCompilerFlag.cmake
index 5729843..5e07c25 100644
--- a/Modules/CheckCXXCompilerFlag.cmake
+++ b/Modules/CheckCXXCompilerFlag.cmake
@@ -36,28 +36,23 @@
include(CheckCXXSourceCompiles)
include(CMakeCheckCompilerFlagCommonPatterns)
-macro (CHECK_CXX_COMPILER_FLAG _FLAG _RESULT)
- set(SAFE_CMAKE_REQUIRED_DEFINITIONS "${CMAKE_REQUIRED_DEFINITIONS}")
- set(CMAKE_REQUIRED_DEFINITIONS "${_FLAG}")
+function(check_cxx_compiler_flag _flag _var)
+ set(CMAKE_REQUIRED_DEFINITIONS "${_flag}")
# Normalize locale during test compilation.
- set(_CheckCXXCompilerFlag_LOCALE_VARS LC_ALL LC_MESSAGES LANG)
- foreach(v ${_CheckCXXCompilerFlag_LOCALE_VARS})
- set(_CheckCXXCompilerFlag_SAVED_${v} "$ENV{${v}}")
+ set(_locale_vars LC_ALL LC_MESSAGES LANG)
+ foreach(v IN LISTS _locale_vars)
+ set(_locale_vars_saved_${v} "$ENV{${v}}")
set(ENV{${v}} C)
endforeach()
- CHECK_COMPILER_FLAG_COMMON_PATTERNS(_CheckCXXCompilerFlag_COMMON_PATTERNS)
- CHECK_CXX_SOURCE_COMPILES("int main() { return 0; }" ${_RESULT}
+ check_compiler_flag_common_patterns(_common_patterns)
+ check_cxx_source_compiles("int main() { return 0; }" ${_var}
# Some compilers do not fail with a bad flag
FAIL_REGEX "command line option .* is valid for .* but not for C\\\\+\\\\+" # GNU
- ${_CheckCXXCompilerFlag_COMMON_PATTERNS}
+ ${_common_patterns}
)
- foreach(v ${_CheckCXXCompilerFlag_LOCALE_VARS})
- set(ENV{${v}} ${_CheckCXXCompilerFlag_SAVED_${v}})
- unset(_CheckCXXCompilerFlag_SAVED_${v})
+ foreach(v IN LISTS _locale_vars)
+ set(ENV{${v}} ${_locale_vars_saved_${v}})
endforeach()
- unset(_CheckCXXCompilerFlag_LOCALE_VARS)
- unset(_CheckCXXCompilerFlag_COMMON_PATTERNS)
-
- set (CMAKE_REQUIRED_DEFINITIONS "${SAFE_CMAKE_REQUIRED_DEFINITIONS}")
-endmacro ()
+ set(${_var} "${${_var}}" PARENT_SCOPE)
+endfunction()
diff --git a/Modules/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 @@
)
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 @@
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_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/FindBLAS.cmake b/Modules/FindBLAS.cmake
index 77f9d0e..165627e 100644
--- a/Modules/FindBLAS.cmake
+++ b/Modules/FindBLAS.cmake
@@ -517,7 +517,7 @@
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 @@
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 @@
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/FindPNG.cmake b/Modules/FindPNG.cmake
index bd400c7..f1fe89a 100644
--- a/Modules/FindPNG.cmake
+++ b/Modules/FindPNG.cmake
@@ -94,6 +94,10 @@
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 @@
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 @@
# 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 @@
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 @@
# 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 @@
_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 @@
# 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 4334e22..93ac51d 100644
--- a/Modules/FindwxWidgets.cmake
+++ b/Modules/FindwxWidgets.cmake
@@ -852,6 +852,8 @@
separate_arguments(wxWidgets_LIBRARIES)
string(REPLACE "-framework;" "-framework "
wxWidgets_LIBRARIES "${wxWidgets_LIBRARIES}")
+ string(REPLACE "-weak_framework;" "-weak_framework "
+ wxWidgets_LIBRARIES "${wxWidgets_LIBRARIES}")
string(REPLACE "-arch;" "-arch "
wxWidgets_LIBRARIES "${wxWidgets_LIBRARIES}")
string(REPLACE "-isysroot;" "-isysroot "
diff --git a/Modules/Internal/CPack/CPackDeb.cmake b/Modules/Internal/CPack/CPackDeb.cmake
index ad8e078..fe0fe09 100644
--- a/Modules/Internal/CPack/CPackDeb.cmake
+++ b/Modules/Internal/CPack/CPackDeb.cmake
@@ -546,8 +546,8 @@
)
# Homepage: (optional)
- if(NOT CPACK_DEBIAN_PACKAGE_HOMEPAGE AND CMAKE_PROJECT_HOMEPAGE_URL)
- set(CPACK_DEBIAN_PACKAGE_HOMEPAGE "${CMAKE_PROJECT_HOMEPAGE_URL}")
+ if(NOT CPACK_DEBIAN_PACKAGE_HOMEPAGE AND CPACK_PACKAGE_HOMEPAGE_URL)
+ set(CPACK_DEBIAN_PACKAGE_HOMEPAGE "${CPACK_PACKAGE_HOMEPAGE_URL}")
endif()
# Section: (recommended)
diff --git a/Modules/Internal/CPack/CPackFreeBSD.cmake b/Modules/Internal/CPack/CPackFreeBSD.cmake
index 16f906c..ae40532 100644
--- a/Modules/Internal/CPack/CPackFreeBSD.cmake
+++ b/Modules/Internal/CPack/CPackFreeBSD.cmake
@@ -68,7 +68,7 @@
# There's really only one homepage for a project, so
# re-use the Debian setting if it's there.
_cpack_freebsd_fallback_var("CPACK_FREEBSD_PACKAGE_WWW"
- "CMAKE_PROJECT_HOMEPAGE_URL"
+ "CPACK_PACKAGE_HOMEPAGE_URL"
"CPACK_DEBIAN_PACKAGE_HOMEPAGE"
"_cpack_freebsd_fallback_www"
)
diff --git a/Modules/Internal/CPack/CPackNuGet.cmake b/Modules/Internal/CPack/CPackNuGet.cmake
index b46a7b1..1f4bcfd 100644
--- a/Modules/Internal/CPack/CPackNuGet.cmake
+++ b/Modules/Internal/CPack/CPackNuGet.cmake
@@ -239,20 +239,13 @@
if(_ver)
_cpack_nuget_debug(" got `${_dep}` dependency version ${_ver}")
- list(APPEND _collected_deps "<dependency id=\"${_dep}\" version=\"${_ver}\" />")
+ string(CONCAT _collected_deps "${_collected_deps}" " <dependency id=\"${_dep}\" version=\"${_ver}\" />\n")
endif()
endforeach()
# Render deps into the variable
if(_collected_deps)
- set(_CPACK_NUGET_DEPENDENCIES_TAG "<dependencies>\n")
- foreach(_line IN LISTS _collected_deps)
- string(
- APPEND _CPACK_NUGET_DEPENDENCIES_TAG
- " ${_line}\n"
- )
- endforeach()
- string(APPEND _CPACK_NUGET_DEPENDENCIES_TAG " </dependencies>")
+ string(CONCAT _CPACK_NUGET_DEPENDENCIES_TAG "<dependencies>\n" "${_collected_deps}" " </dependencies>")
endif()
# Render the spec file
diff --git a/Modules/Internal/CPack/CPackRPM.cmake b/Modules/Internal/CPack/CPackRPM.cmake
index ffb24e2..3485e7d 100644
--- a/Modules/Internal/CPack/CPackRPM.cmake
+++ b/Modules/Internal/CPack/CPackRPM.cmake
@@ -844,8 +844,8 @@
endif()
endif()
- if(NOT CPACK_RPM_PACKAGE_URL AND CMAKE_PROJECT_HOMEPAGE_URL)
- set(CPACK_RPM_PACKAGE_URL "${CMAKE_PROJECT_HOMEPAGE_URL}")
+ if(NOT CPACK_RPM_PACKAGE_URL AND CPACK_PACKAGE_HOMEPAGE_URL)
+ set(CPACK_RPM_PACKAGE_URL "${CPACK_PACKAGE_HOMEPAGE_URL}")
endif()
# CPACK_RPM_PACKAGE_NAME (mandatory)
diff --git a/Modules/Platform/Windows-MSVC.cmake b/Modules/Platform/Windows-MSVC.cmake
index 34f5d03..e1d6733 100644
--- a/Modules/Platform/Windows-MSVC.cmake
+++ b/Modules/Platform/Windows-MSVC.cmake
@@ -217,7 +217,7 @@
else()
set(_PLATFORM_DEFINES "/DWIN32")
- if(_MSVC_C_ARCHITECTURE_FAMILY STREQUAL "ARM" OR _MSVC_CXX_ARCHITECTURE_FAMILY STREQUAL "ARM" OR _MSVC_C_ARCHITECTURE_FAMILY STREQUAL "ARM64" OR _MSVC_CXX_ARCHITECTURE_FAMILY STREQUAL "ARM64")
+ if(_MSVC_C_ARCHITECTURE_FAMILY STREQUAL "ARM" OR _MSVC_CXX_ARCHITECTURE_FAMILY STREQUAL "ARM")
set(CMAKE_C_STANDARD_LIBRARIES_INIT "kernel32.lib user32.lib")
elseif(MSVC_VERSION GREATER 1310)
if(CMAKE_VS_PLATFORM_TOOLSET MATCHES "v[0-9]+_clang_.*")
diff --git a/Modules/Platform/Windows-NVIDIA-CUDA.cmake b/Modules/Platform/Windows-NVIDIA-CUDA.cmake
index 94d77b9..30b5aa9 100644
--- a/Modules/Platform/Windows-NVIDIA-CUDA.cmake
+++ b/Modules/Platform/Windows-NVIDIA-CUDA.cmake
@@ -1,11 +1,11 @@
include(Platform/Windows-MSVC)
set(CMAKE_CUDA_COMPILE_PTX_COMPILATION
- "<CMAKE_CUDA_COMPILER> ${CMAKE_CUDA_HOST_FLAGS} <DEFINES> <INCLUDES> <FLAGS> -x cu -ptx <SOURCE> -o <OBJECT> -Xcompiler=-Fd<TARGET_COMPILE_PDB>,-FS")
+ "<CMAKE_CUDA_COMPILER> ${_CMAKE_CUDA_EXTRA_FLAGS} <DEFINES> <INCLUDES> <FLAGS> -x cu -ptx <SOURCE> -o <OBJECT> -Xcompiler=-Fd<TARGET_COMPILE_PDB>,-FS")
set(CMAKE_CUDA_COMPILE_SEPARABLE_COMPILATION
- "<CMAKE_CUDA_COMPILER> ${CMAKE_CUDA_HOST_FLAGS} <DEFINES> <INCLUDES> <FLAGS> -x cu -dc <SOURCE> -o <OBJECT> -Xcompiler=-Fd<TARGET_COMPILE_PDB>,-FS")
+ "<CMAKE_CUDA_COMPILER> ${_CMAKE_CUDA_EXTRA_FLAGS} <DEFINES> <INCLUDES> <FLAGS> -x cu -dc <SOURCE> -o <OBJECT> -Xcompiler=-Fd<TARGET_COMPILE_PDB>,-FS")
set(CMAKE_CUDA_COMPILE_WHOLE_COMPILATION
- "<CMAKE_CUDA_COMPILER> ${CMAKE_CUDA_HOST_FLAGS} <DEFINES> <INCLUDES> <FLAGS> -x cu -c <SOURCE> -o <OBJECT> -Xcompiler=-Fd<TARGET_COMPILE_PDB>,-FS")
+ "<CMAKE_CUDA_COMPILER> ${_CMAKE_CUDA_EXTRA_FLAGS} <DEFINES> <INCLUDES> <FLAGS> -x cu -c <SOURCE> -o <OBJECT> -Xcompiler=-Fd<TARGET_COMPILE_PDB>,-FS")
set(__IMPLICT_LINKS )
foreach(dir ${CMAKE_CUDA_HOST_IMPLICIT_LINK_DIRECTORIES})
@@ -30,11 +30,6 @@
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 @@
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/CMakeLists.txt b/Source/CMakeLists.txt
index d050fb7..ff313d6 100644
--- a/Source/CMakeLists.txt
+++ b/Source/CMakeLists.txt
@@ -693,6 +693,8 @@
cmDuration.h
cmDuration.cxx
+
+ bindexplib.cxx
)
SET_PROPERTY(SOURCE cmProcessOutput.cxx APPEND PROPERTY COMPILE_DEFINITIONS
@@ -715,7 +717,6 @@
set(SRCS ${SRCS}
cmCallVisualStudioMacro.cxx
cmCallVisualStudioMacro.h
- bindexplib.cxx
)
if(NOT UNIX)
diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake
index f337884..fe319de 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 20191203)
+set(CMake_VERSION_PATCH 20191212)
#set(CMake_VERSION_RC 0)
set(CMake_VERSION_IS_DIRTY 0)
diff --git a/Source/CTest/cmCTestScriptHandler.cxx b/Source/CTest/cmCTestScriptHandler.cxx
index 60facbd..7803e37 100644
--- a/Source/CTest/cmCTestScriptHandler.cxx
+++ b/Source/CTest/cmCTestScriptHandler.cxx
@@ -340,6 +340,13 @@
this->SetRunCurrentScript(true);
this->UpdateElapsedTime();
+ // set the CTEST_CONFIGURATION_TYPE variable to the current value of the
+ // the -C argument on the command line.
+ if (!this->CTest->GetConfigType().empty()) {
+ this->Makefile->AddDefinition("CTEST_CONFIGURATION_TYPE",
+ this->CTest->GetConfigType());
+ }
+
// add the script arg if defined
if (!script_arg.empty()) {
this->Makefile->AddDefinition("CTEST_SCRIPT_ARG", script_arg);
diff --git a/Source/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 @@
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 @@
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/Modules/CheckCXXLinkerFlag.cmake b/Source/Modules/CheckCXXLinkerFlag.cmake
new file mode 100644
index 0000000..6cb1ba3
--- /dev/null
+++ b/Source/Modules/CheckCXXLinkerFlag.cmake
@@ -0,0 +1,29 @@
+# Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+# file Copyright.txt or https://cmake.org/licensing for details.
+
+include_guard(GLOBAL)
+include(CheckCXXSourceCompiles)
+include(CMakeCheckCompilerFlagCommonPatterns)
+
+function(check_cxx_linker_flag _flag _var)
+ if(CMAKE_VERSION VERSION_LESS "3.14")
+ set(CMAKE_REQUIRED_LIBRARIES "${_flag}")
+ else()
+ set(CMAKE_REQUIRED_LINK_OPTIONS "${_flag}")
+ endif()
+
+ # Normalize locale during test compilation.
+ set(_locale_vars LC_ALL LC_MESSAGES LANG)
+ foreach(v IN LISTS _locale_vars)
+ set(_locale_vars_saved_${v} "$ENV{${v}}")
+ set(ENV{${v}} C)
+ endforeach()
+ check_compiler_flag_common_patterns(_common_patterns)
+ check_cxx_source_compiles("int main() { return 0; }" ${_var}
+ ${_common_patterns}
+ )
+ foreach(v IN LISTS _locale_vars)
+ set(ENV{${v}} ${_locale_vars_saved_${v}})
+ endforeach()
+ set(${_var} "${${_var}}" PARENT_SCOPE)
+endfunction()
diff --git a/Source/bindexplib.cxx b/Source/bindexplib.cxx
index b85cc33..0b2750d 100644
--- a/Source/bindexplib.cxx
+++ b/Source/bindexplib.cxx
@@ -64,32 +64,36 @@
*/
#include "bindexplib.h"
-#include <iostream>
+#include <cstddef>
#include <sstream>
#include <vector>
-#include <windows.h>
+#ifdef _WIN32
+# include <windows.h>
-#include "cmsys/Encoding.hxx"
+# include "cmsys/Encoding.hxx"
+#endif
+
#include "cmsys/FStream.hxx"
#include "cmSystemTools.h"
-#ifndef IMAGE_FILE_MACHINE_ARM
-# define IMAGE_FILE_MACHINE_ARM 0x01c0 // ARM Little-Endian
-#endif
+#ifdef _WIN32
+# ifndef IMAGE_FILE_MACHINE_ARM
+# define IMAGE_FILE_MACHINE_ARM 0x01c0 // ARM Little-Endian
+# endif
-#ifndef IMAGE_FILE_MACHINE_THUMB
-# define IMAGE_FILE_MACHINE_THUMB 0x01c2 // ARM Thumb/Thumb-2 Little-Endian
-#endif
+# ifndef IMAGE_FILE_MACHINE_THUMB
+# define IMAGE_FILE_MACHINE_THUMB 0x01c2 // ARM Thumb/Thumb-2 Little-Endian
+# endif
-#ifndef IMAGE_FILE_MACHINE_ARMNT
-# define IMAGE_FILE_MACHINE_ARMNT 0x01c4 // ARM Thumb-2 Little-Endian
-#endif
+# ifndef IMAGE_FILE_MACHINE_ARMNT
+# define IMAGE_FILE_MACHINE_ARMNT 0x01c4 // ARM Thumb-2 Little-Endian
+# endif
-#ifndef IMAGE_FILE_MACHINE_ARM64
-# define IMAGE_FILE_MACHINE_ARM64 0xaa64 // ARM64 Little-Endian
-#endif
+# ifndef IMAGE_FILE_MACHINE_ARM64
+# define IMAGE_FILE_MACHINE_ARM64 0xaa64 // ARM64 Little-Endian
+# endif
typedef struct cmANON_OBJECT_HEADER_BIGOBJ
{
@@ -306,6 +310,7 @@
SymbolTableType* SymbolTable;
bool IsI386;
};
+#endif
bool DumpFileWithLlvmNm(std::string const& nmPath, const char* filename,
std::set<std::string>& symbols,
@@ -315,15 +320,15 @@
// break up command line into a vector
std::vector<std::string> command;
command.push_back(nmPath);
- command.push_back("--no-weak");
- command.push_back("--defined-only");
- command.push_back("--format=posix");
- command.push_back(filename);
+ command.emplace_back("--no-weak");
+ command.emplace_back("--defined-only");
+ command.emplace_back("--format=posix");
+ command.emplace_back(filename);
// run the command
int exit_code = 0;
- cmSystemTools::RunSingleCommand(command, &output, &output, &exit_code, "",
- cmSystemTools::OUTPUT_NONE);
+ cmSystemTools::RunSingleCommand(command, &output, &output, &exit_code,
+ nullptr, cmSystemTools::OUTPUT_NONE);
if (exit_code != 0) {
fprintf(stderr, "llvm-nm returned an error: %s\n", output.c_str());
@@ -336,7 +341,7 @@
if (line.empty()) { // last line
continue;
}
- size_t sym_end = line.find(" ");
+ size_t sym_end = line.find(' ');
if (sym_end == std::string::npos) {
fprintf(stderr, "Couldn't parse llvm-nm output line: %s\n",
line.c_str());
@@ -366,6 +371,9 @@
std::set<std::string>& symbols,
std::set<std::string>& dataSymbols)
{
+#ifndef _WIN32
+ return DumpFileWithLlvmNm(nmPath, filename, symbols, dataSymbols);
+#else
HANDLE hFile;
HANDLE hFileMapping;
LPVOID lpFileBase;
@@ -446,6 +454,7 @@
CloseHandle(hFileMapping);
CloseHandle(hFile);
return true;
+#endif
}
bool bindexplib::AddObjectFile(const char* filename)
diff --git a/Source/cmAddCustomCommandCommand.cxx b/Source/cmAddCustomCommandCommand.cxx
index 6e04ce5..52fc5d5 100644
--- a/Source/cmAddCustomCommandCommand.cxx
+++ b/Source/cmAddCustomCommandCommand.cxx
@@ -343,7 +343,7 @@
// 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 @@
// 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 @@
}
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 @@
// 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 @@
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 @@
/* 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/cmCommands.cxx b/Source/cmCommands.cxx
index 563e0f1..896b6a9 100644
--- a/Source/cmCommands.cxx
+++ b/Source/cmCommands.cxx
@@ -78,6 +78,7 @@
#include "cmTargetCompileOptionsCommand.h"
#include "cmTargetIncludeDirectoriesCommand.h"
#include "cmTargetLinkLibrariesCommand.h"
+#include "cmTargetLinkOptionsCommand.h"
#include "cmTargetPrecompileHeadersCommand.h"
#include "cmTargetSourcesCommand.h"
#include "cmTryCompileCommand.h"
@@ -107,7 +108,6 @@
# include "cmSourceGroupCommand.h"
# include "cmSubdirDependsCommand.h"
# include "cmTargetLinkDirectoriesCommand.h"
-# include "cmTargetLinkOptionsCommand.h"
# include "cmUseMangledMesaCommand.h"
# include "cmUtilitySourceCommand.h"
# include "cmVariableRequiresCommand.h"
@@ -257,6 +257,7 @@
cmTargetIncludeDirectoriesCommand);
state->AddBuiltinCommand("target_link_libraries",
cmTargetLinkLibrariesCommand);
+ state->AddBuiltinCommand("target_link_options", cmTargetLinkOptionsCommand);
state->AddBuiltinCommand("target_sources", cmTargetSourcesCommand);
state->AddBuiltinCommand("try_compile",
cm::make_unique<cmTryCompileCommand>());
@@ -277,7 +278,6 @@
state->AddBuiltinCommand("install_programs", cmInstallProgramsCommand);
state->AddBuiltinCommand("add_link_options", cmAddLinkOptionsCommand);
state->AddBuiltinCommand("link_libraries", cmLinkLibrariesCommand);
- state->AddBuiltinCommand("target_link_options", cmTargetLinkOptionsCommand);
state->AddBuiltinCommand("target_link_directories",
cmTargetLinkDirectoriesCommand);
state->AddBuiltinCommand("qt_wrap_cpp", cmQTWrapCPPCommand);
diff --git a/Source/cmComputeTargetDepends.cxx b/Source/cmComputeTargetDepends.cxx
index c22cf4a..58ec53a 100644
--- a/Source/cmComputeTargetDepends.cxx
+++ b/Source/cmComputeTargetDepends.cxx
@@ -158,9 +158,8 @@
void cmComputeTargetDepends::CollectTargets()
{
// Collect all targets from all generators.
- std::vector<cmLocalGenerator*> const& lgens =
- this->GlobalGenerator->GetLocalGenerators();
- for (cmLocalGenerator* lgen : lgens) {
+ auto const& lgens = this->GlobalGenerator->GetLocalGenerators();
+ for (const auto& lgen : lgens) {
for (const auto& ti : lgen->GetGeneratorTargets()) {
int index = static_cast<int>(this->Targets.size());
this->TargetIndex[ti.get()] = index;
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 @@
{
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 @@
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/cmExtraCodeLiteGenerator.cxx b/Source/cmExtraCodeLiteGenerator.cxx
index 3557e5c..de40c77 100644
--- a/Source/cmExtraCodeLiteGenerator.cxx
+++ b/Source/cmExtraCodeLiteGenerator.cxx
@@ -117,9 +117,8 @@
{
std::vector<std::string> retval;
// for each target in the workspace create a codelite project
- const std::vector<cmLocalGenerator*>& lgs =
- this->GlobalGenerator->GetLocalGenerators();
- for (cmLocalGenerator* lg : lgs) {
+ const auto& lgs = this->GlobalGenerator->GetLocalGenerators();
+ for (const auto& lg : lgs) {
for (const auto& lt : lg->GetGeneratorTargets()) {
cmStateEnums::TargetType type = lt->GetType();
std::string const& outputDir = lg->GetCurrentBinaryDirectory();
diff --git a/Source/cmExtraEclipseCDT4Generator.cxx b/Source/cmExtraEclipseCDT4Generator.cxx
index cf79375..78cabce 100644
--- a/Source/cmExtraEclipseCDT4Generator.cxx
+++ b/Source/cmExtraEclipseCDT4Generator.cxx
@@ -99,7 +99,7 @@
void cmExtraEclipseCDT4Generator::Generate()
{
- cmLocalGenerator* lg = this->GlobalGenerator->GetLocalGenerators()[0];
+ const auto& lg = this->GlobalGenerator->GetLocalGenerators()[0];
const cmMakefile* mf = lg->GetMakefile();
std::string eclipseVersion = mf->GetSafeDefinition("CMAKE_ECLIPSE_VERSION");
@@ -176,7 +176,7 @@
void cmExtraEclipseCDT4Generator::CreateSettingsResourcePrefsFile()
{
- cmLocalGenerator* lg = this->GlobalGenerator->GetLocalGenerators()[0];
+ const auto& lg = this->GlobalGenerator->GetLocalGenerators()[0];
cmMakefile* mf = lg->GetMakefile();
const std::string filename =
@@ -199,7 +199,7 @@
assert(this->HomeDirectory != this->HomeOutputDirectory);
// set up the project name: <project>-Source@<baseSourcePathName>
- cmLocalGenerator* lg = this->GlobalGenerator->GetLocalGenerators()[0];
+ const auto& lg = this->GlobalGenerator->GetLocalGenerators()[0];
std::string name = cmExtraEclipseCDT4Generator::GenerateProjectName(
lg->GetProjectName(), "Source",
cmExtraEclipseCDT4Generator::GetPathBasename(this->HomeDirectory));
@@ -232,9 +232,9 @@
void cmExtraEclipseCDT4Generator::AddEnvVar(std::ostream& out,
const char* envVar,
- cmLocalGenerator* lg)
+ cmLocalGenerator& lg)
{
- cmMakefile* mf = lg->GetMakefile();
+ cmMakefile* mf = lg.GetMakefile();
// get the variables from the environment and from the cache and then
// figure out which one to use:
@@ -244,7 +244,7 @@
std::string cacheEntryName = cmStrCat("CMAKE_ECLIPSE_ENVVAR_", envVar);
const std::string* cacheValue =
- lg->GetState()->GetInitializedCacheValue(cacheEntryName);
+ lg.GetState()->GetInitializedCacheValue(cacheEntryName);
// now we have both, decide which one to use
std::string valueToUse;
@@ -257,7 +257,7 @@
valueToUse = envVarValue;
mf->AddCacheDefinition(cacheEntryName, valueToUse.c_str(),
cacheEntryName.c_str(), cmStateEnums::STRING, true);
- mf->GetCMakeInstance()->SaveCache(lg->GetBinaryDirectory());
+ mf->GetCMakeInstance()->SaveCache(lg.GetBinaryDirectory());
} else if (!envVarSet && cacheValue != nullptr) {
// It is already in the cache, but not in the env, so use it from the cache
valueToUse = *cacheValue;
@@ -273,7 +273,7 @@
mf->AddCacheDefinition(cacheEntryName, valueToUse.c_str(),
cacheEntryName.c_str(), cmStateEnums::STRING,
true);
- mf->GetCMakeInstance()->SaveCache(lg->GetBinaryDirectory());
+ mf->GetCMakeInstance()->SaveCache(lg.GetBinaryDirectory());
}
}
@@ -284,7 +284,7 @@
void cmExtraEclipseCDT4Generator::CreateProjectFile()
{
- cmLocalGenerator* lg = this->GlobalGenerator->GetLocalGenerators()[0];
+ const auto& lg = this->GlobalGenerator->GetLocalGenerators()[0];
cmMakefile* mf = lg->GetMakefile();
const std::string filename = this->HomeOutputDirectory + "/.project";
@@ -351,15 +351,15 @@
// set vsvars32.bat environment available at CMake time,
// but not necessarily when eclipse is open
if (compilerId == "MSVC") {
- AddEnvVar(environment, "PATH", lg);
- AddEnvVar(environment, "INCLUDE", lg);
- AddEnvVar(environment, "LIB", lg);
- AddEnvVar(environment, "LIBPATH", lg);
+ AddEnvVar(environment, "PATH", *lg);
+ AddEnvVar(environment, "INCLUDE", *lg);
+ AddEnvVar(environment, "LIB", *lg);
+ AddEnvVar(environment, "LIBPATH", *lg);
} else if (compilerId == "Intel") {
// if the env.var is set, use this one and put it in the cache
// if the env.var is not set, but the value is in the cache,
// use it from the cache:
- AddEnvVar(environment, "INTEL_LICENSE_FILE", lg);
+ AddEnvVar(environment, "INTEL_LICENSE_FILE", *lg);
}
AppendDictionary(xml, "org.eclipse.cdt.make.core.environment",
environment.str());
@@ -495,7 +495,7 @@
cmExtraEclipseCDT4Generator::AppendLinkedResource(
xml, linkName, "virtual:/virtual", VirtualFolder);
- for (cmLocalGenerator* lg : this->GlobalGenerator->GetLocalGenerators()) {
+ for (const auto& lg : this->GlobalGenerator->GetLocalGenerators()) {
cmMakefile* makefile = lg->GetMakefile();
const auto& targets = lg->GetGeneratorTargets();
@@ -606,7 +606,7 @@
{
std::set<std::string> emmited;
- cmLocalGenerator* lg = this->GlobalGenerator->GetLocalGenerators()[0];
+ const auto& lg = this->GlobalGenerator->GetLocalGenerators()[0];
const cmMakefile* mf = lg->GetMakefile();
const std::string filename = this->HomeOutputDirectory + "/.cproject";
@@ -752,7 +752,7 @@
// add pre-processor definitions to allow eclipse to gray out sections
emmited.clear();
- for (cmLocalGenerator* lgen : this->GlobalGenerator->GetLocalGenerators()) {
+ for (const auto& lgen : this->GlobalGenerator->GetLocalGenerators()) {
if (const char* cdefs =
lgen->GetMakefile()->GetProperty("COMPILE_DEFINITIONS")) {
@@ -859,7 +859,7 @@
// include dirs
emmited.clear();
- for (cmLocalGenerator* lgen : this->GlobalGenerator->GetLocalGenerators()) {
+ for (const auto& lgen : this->GlobalGenerator->GetLocalGenerators()) {
const auto& targets = lgen->GetGeneratorTargets();
for (const auto& target : targets) {
if (target->GetType() == cmStateEnums::INTERFACE_LIBRARY) {
@@ -914,7 +914,7 @@
// add all executable and library targets and some of the GLOBAL
// and UTILITY targets
- for (cmLocalGenerator* lgen : this->GlobalGenerator->GetLocalGenerators()) {
+ for (const auto& lgen : this->GlobalGenerator->GetLocalGenerators()) {
const auto& targets = lgen->GetGeneratorTargets();
std::string subdir = lgen->MaybeConvertToRelativePath(
this->HomeOutputDirectory, lgen->GetCurrentBinaryDirectory());
diff --git a/Source/cmExtraEclipseCDT4Generator.h b/Source/cmExtraEclipseCDT4Generator.h
index ff4c59e..a7aa549 100644
--- a/Source/cmExtraEclipseCDT4Generator.h
+++ b/Source/cmExtraEclipseCDT4Generator.h
@@ -86,7 +86,7 @@
std::set<std::string>& emittedDirs);
static void AddEnvVar(std::ostream& out, const char* envVar,
- cmLocalGenerator* lg);
+ cmLocalGenerator& lg);
void WriteGroups(std::vector<cmSourceGroup> const& sourceGroups,
std::string& linkName, cmXMLWriter& xml);
diff --git a/Source/cmExtraKateGenerator.cxx b/Source/cmExtraKateGenerator.cxx
index bbbc281..e463420 100644
--- a/Source/cmExtraKateGenerator.cxx
+++ b/Source/cmExtraKateGenerator.cxx
@@ -41,21 +41,21 @@
void cmExtraKateGenerator::Generate()
{
- cmLocalGenerator* lg = this->GlobalGenerator->GetLocalGenerators()[0];
+ const auto& lg = this->GlobalGenerator->GetLocalGenerators()[0];
const cmMakefile* mf = lg->GetMakefile();
this->ProjectName = this->GenerateProjectName(
lg->GetProjectName(), mf->GetSafeDefinition("CMAKE_BUILD_TYPE"),
this->GetPathBasename(lg->GetBinaryDirectory()));
this->UseNinja = (this->GlobalGenerator->GetName() == "Ninja");
- this->CreateKateProjectFile(lg);
- this->CreateDummyKateProjectFile(lg);
+ this->CreateKateProjectFile(*lg);
+ this->CreateDummyKateProjectFile(*lg);
}
void cmExtraKateGenerator::CreateKateProjectFile(
- const cmLocalGenerator* lg) const
+ const cmLocalGenerator& lg) const
{
- std::string filename = cmStrCat(lg->GetBinaryDirectory(), "/.kateproject");
+ std::string filename = cmStrCat(lg.GetBinaryDirectory(), "/.kateproject");
cmGeneratedFileStream fout(filename);
if (!fout) {
return;
@@ -65,21 +65,21 @@
fout <<
"{\n"
"\t\"name\": \"" << this->ProjectName << "\",\n"
- "\t\"directory\": \"" << lg->GetSourceDirectory() << "\",\n"
+ "\t\"directory\": \"" << lg.GetSourceDirectory() << "\",\n"
"\t\"files\": [ { " << this->GenerateFilesString(lg) << "} ],\n";
/* clang-format on */
this->WriteTargets(lg, fout);
fout << "}\n";
}
-void cmExtraKateGenerator::WriteTargets(const cmLocalGenerator* lg,
+void cmExtraKateGenerator::WriteTargets(const cmLocalGenerator& lg,
cmGeneratedFileStream& fout) const
{
- cmMakefile const* mf = lg->GetMakefile();
+ cmMakefile const* mf = lg.GetMakefile();
const std::string& make = mf->GetRequiredDefinition("CMAKE_MAKE_PROGRAM");
const std::string& makeArgs =
mf->GetSafeDefinition("CMAKE_KATE_MAKE_ARGUMENTS");
- std::string const& homeOutputDir = lg->GetBinaryDirectory();
+ std::string const& homeOutputDir = lg.GetBinaryDirectory();
/* clang-format off */
fout <<
@@ -110,8 +110,7 @@
// add all executable and library targets and some of the GLOBAL
// and UTILITY targets
- for (cmLocalGenerator* localGen :
- this->GlobalGenerator->GetLocalGenerators()) {
+ for (const auto& localGen : this->GlobalGenerator->GetLocalGenerators()) {
const auto& targets = localGen->GetGeneratorTargets();
std::string currentDir = localGen->GetCurrentBinaryDirectory();
bool topLevel = (currentDir == localGen->GetBinaryDirectory());
@@ -205,10 +204,10 @@
}
void cmExtraKateGenerator::CreateDummyKateProjectFile(
- const cmLocalGenerator* lg) const
+ const cmLocalGenerator& lg) const
{
std::string filename =
- cmStrCat(lg->GetBinaryDirectory(), '/', this->ProjectName, ".kateproject");
+ cmStrCat(lg.GetBinaryDirectory(), '/', this->ProjectName, ".kateproject");
cmGeneratedFileStream fout(filename);
if (!fout) {
return;
@@ -219,26 +218,25 @@
}
std::string cmExtraKateGenerator::GenerateFilesString(
- const cmLocalGenerator* lg) const
+ const cmLocalGenerator& lg) const
{
- std::string s = cmStrCat(lg->GetSourceDirectory(), "/.git");
+ std::string s = cmStrCat(lg.GetSourceDirectory(), "/.git");
if (cmSystemTools::FileExists(s)) {
return "\"git\": 1 ";
}
- s = cmStrCat(lg->GetSourceDirectory(), "/.svn");
+ s = cmStrCat(lg.GetSourceDirectory(), "/.svn");
if (cmSystemTools::FileExists(s)) {
return "\"svn\": 1 ";
}
- s = cmStrCat(lg->GetSourceDirectory(), '/');
+ s = cmStrCat(lg.GetSourceDirectory(), '/');
std::set<std::string> files;
std::string tmp;
- const std::vector<cmLocalGenerator*>& lgs =
- this->GlobalGenerator->GetLocalGenerators();
+ const auto& lgs = this->GlobalGenerator->GetLocalGenerators();
- for (cmLocalGenerator* lgen : lgs) {
+ for (const auto& lgen : lgs) {
cmMakefile* makefile = lgen->GetMakefile();
const std::vector<std::string>& listFiles = makefile->GetListFiles();
for (std::string const& listFile : listFiles) {
diff --git a/Source/cmExtraKateGenerator.h b/Source/cmExtraKateGenerator.h
index be1376a..1fb81b4 100644
--- a/Source/cmExtraKateGenerator.h
+++ b/Source/cmExtraKateGenerator.h
@@ -25,16 +25,16 @@
void Generate() override;
private:
- void CreateKateProjectFile(const cmLocalGenerator* lg) const;
- void CreateDummyKateProjectFile(const cmLocalGenerator* lg) const;
- void WriteTargets(const cmLocalGenerator* lg,
+ void CreateKateProjectFile(const cmLocalGenerator& lg) const;
+ void CreateDummyKateProjectFile(const cmLocalGenerator& lg) const;
+ void WriteTargets(const cmLocalGenerator& lg,
cmGeneratedFileStream& fout) const;
void AppendTarget(cmGeneratedFileStream& fout, const std::string& target,
const std::string& make, const std::string& makeArgs,
const std::string& path,
const std::string& homeOutputDir) const;
- std::string GenerateFilesString(const cmLocalGenerator* lg) const;
+ std::string GenerateFilesString(const cmLocalGenerator& lg) const;
std::string GetPathBasename(const std::string& path) const;
std::string GenerateProjectName(const std::string& name,
const std::string& type,
diff --git a/Source/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 @@
". 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 @@
std::string const varName = target + "_FLTK_UI_SRCS";
mf.AddDefinition(varName, sourceListValue);
- mf.AddFinalAction(
- [target](cmMakefile& makefile) { FinalAction(makefile, target); });
+ mf.AddGeneratorAction(
+ [target](cmLocalGenerator& lg, const cmListFileBacktrace& lfbt) {
+ FinalAction(*lg.GetMakefile(), target, lfbt);
+ });
return true;
}
diff --git a/Source/cmFileAPICMakeFiles.cxx b/Source/cmFileAPICMakeFiles.cxx
index f419997..44ba96c 100644
--- a/Source/cmFileAPICMakeFiles.cxx
+++ b/Source/cmFileAPICMakeFiles.cxx
@@ -2,6 +2,7 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmFileAPICMakeFiles.h"
+#include <memory>
#include <string>
#include <vector>
@@ -67,7 +68,7 @@
cmGlobalGenerator* gg =
this->FileAPI.GetCMakeInstance()->GetGlobalGenerator();
- for (cmLocalGenerator const* lg : gg->GetLocalGenerators()) {
+ for (const auto& lg : gg->GetLocalGenerators()) {
cmMakefile const* mf = lg->GetMakefile();
for (std::string const& file : mf->GetListFiles()) {
inputs.append(this->DumpInput(file));
diff --git a/Source/cmFileAPICodemodel.cxx b/Source/cmFileAPICodemodel.cxx
index d7993c7..d6afb77 100644
--- a/Source/cmFileAPICodemodel.cxx
+++ b/Source/cmFileAPICodemodel.cxx
@@ -469,17 +469,17 @@
{
cmGlobalGenerator* gg =
this->FileAPI.GetCMakeInstance()->GetGlobalGenerator();
- std::vector<cmLocalGenerator*> const& localGens = gg->GetLocalGenerators();
+ auto const& localGens = gg->GetLocalGenerators();
// Add directories in forward order to process parents before children.
this->Directories.reserve(localGens.size());
- for (cmLocalGenerator* lg : localGens) {
+ for (const auto& lg : localGens) {
auto directoryIndex =
static_cast<Json::ArrayIndex>(this->Directories.size());
this->Directories.emplace_back();
Directory& d = this->Directories[directoryIndex];
d.Snapshot = lg->GetStateSnapshot().GetBuildsystemDirectory();
- d.LocalGenerator = lg;
+ d.LocalGenerator = lg.get();
this->DirectoryMap[d.Snapshot] = directoryIndex;
d.ProjectIndex = this->AddProject(d.Snapshot);
@@ -554,7 +554,7 @@
std::vector<cmGeneratorTarget*> targetList;
cmGlobalGenerator* gg =
this->FileAPI.GetCMakeInstance()->GetGlobalGenerator();
- for (cmLocalGenerator const* lg : gg->GetLocalGenerators()) {
+ for (const auto& lg : gg->GetLocalGenerators()) {
cmAppend(targetList, lg->GetGeneratorTargets());
}
std::sort(targetList.begin(), targetList.end(),
diff --git a/Source/cmForEachCommand.cxx b/Source/cmForEachCommand.cxx
index 91cd4ef..ac48287 100644
--- a/Source/cmForEachCommand.cxx
+++ b/Source/cmForEachCommand.cxx
@@ -3,12 +3,15 @@
#include "cmForEachCommand.h"
#include <algorithm>
+#include <cassert>
#include <cstddef>
// NOTE The declaration of `std::abs` has moved to `cmath` since C++17
// See https://en.cppreference.com/w/cpp/numeric/math/abs
// ALERT But IWYU used to lint `#include`s do not "understand"
// conditional compilation (i.e. `#if __cplusplus >= 201703L`)
#include <cstdlib>
+#include <iterator>
+#include <map>
#include <utility>
#include <cm/memory>
@@ -29,7 +32,7 @@
class cmForEachFunctionBlocker : public cmFunctionBlocker
{
public:
- cmForEachFunctionBlocker(cmMakefile* mf);
+ explicit cmForEachFunctionBlocker(cmMakefile* mf);
~cmForEachFunctionBlocker() override;
cm::string_view StartCommandName() const override { return "foreach"_s; }
@@ -41,10 +44,33 @@
bool Replay(std::vector<cmListFileFunction> functions,
cmExecutionStatus& inStatus) override;
+ void SetIterationVarsCount(const std::size_t varsCount)
+ {
+ this->IterationVarsCount = varsCount;
+ }
+ void SetZipLists() { this->ZipLists = true; }
+
std::vector<std::string> Args;
private:
+ struct InvokeResult
+ {
+ bool Restore;
+ bool Break;
+ };
+
+ bool ReplayItems(std::vector<cmListFileFunction> const& functions,
+ cmExecutionStatus& inStatus);
+
+ bool ReplayZipLists(std::vector<cmListFileFunction> const& functions,
+ cmExecutionStatus& inStatus);
+
+ InvokeResult invoke(std::vector<cmListFileFunction> const& functions,
+ cmExecutionStatus& inStatus, cmMakefile& mf);
+
cmMakefile* Makefile;
+ std::size_t IterationVarsCount = 0u;
+ bool ZipLists = false;
};
cmForEachFunctionBlocker::cmForEachFunctionBlocker(cmMakefile* mf)
@@ -70,70 +96,240 @@
bool cmForEachFunctionBlocker::Replay(
std::vector<cmListFileFunction> functions, cmExecutionStatus& inStatus)
{
- cmMakefile& mf = inStatus.GetMakefile();
- // at end of for each execute recorded commands
+ return this->ZipLists ? this->ReplayZipLists(functions, inStatus)
+ : this->ReplayItems(functions, inStatus);
+}
+
+bool cmForEachFunctionBlocker::ReplayItems(
+ std::vector<cmListFileFunction> const& functions,
+ cmExecutionStatus& inStatus)
+{
+ assert("Unexpected number of iteration variables" &&
+ this->IterationVarsCount == 1);
+
+ auto& mf = inStatus.GetMakefile();
+
+ // At end of for each execute recorded commands
// store the old value
std::string oldDef;
if (mf.GetDefinition(this->Args.front())) {
oldDef = mf.GetDefinition(this->Args.front());
}
+ auto restore = false;
for (std::string const& arg : cmMakeRange(this->Args).advance(1)) {
- // set the variable to the loop value
+ // Set the variable to the loop value
mf.AddDefinition(this->Args.front(), arg);
// Invoke all the functions that were collected in the block.
- for (cmListFileFunction const& func : functions) {
- cmExecutionStatus status(mf);
- mf.ExecuteCommand(func, status);
- if (status.GetReturnInvoked()) {
- inStatus.SetReturnInvoked();
- // restore the variable to its prior value
- mf.AddDefinition(this->Args.front(), oldDef);
- return true;
- }
- if (status.GetBreakInvoked()) {
- // restore the variable to its prior value
- mf.AddDefinition(this->Args.front(), oldDef);
- return true;
- }
- if (status.GetContinueInvoked()) {
- break;
- }
- if (cmSystemTools::GetFatalErrorOccured()) {
- return true;
- }
+ auto r = this->invoke(functions, inStatus, mf);
+ restore = r.Restore;
+ if (r.Break) {
+ break;
}
}
- // restore the variable to its prior value
- mf.AddDefinition(this->Args.front(), oldDef);
+ if (restore) {
+ // restore the variable to its prior value
+ mf.AddDefinition(this->Args.front(), oldDef);
+ }
return true;
}
-bool HandleInMode(std::vector<std::string> const& args, cmMakefile& makefile)
+bool cmForEachFunctionBlocker::ReplayZipLists(
+ std::vector<cmListFileFunction> const& functions,
+ cmExecutionStatus& inStatus)
{
+ assert("Unexpected number of iteration variables" &&
+ this->IterationVarsCount >= 1);
+
+ auto& mf = inStatus.GetMakefile();
+
+ // Expand the list of list-variables into a list of lists of strings
+ std::vector<std::vector<std::string>> values;
+ values.reserve(this->Args.size() - this->IterationVarsCount);
+ // Also track the longest list size
+ std::size_t maxItems = 0u;
+ for (auto const& var :
+ cmMakeRange(this->Args).advance(this->IterationVarsCount)) {
+ std::vector<std::string> items;
+ auto const& value = mf.GetSafeDefinition(var);
+ if (!value.empty()) {
+ cmExpandList(value, items, true);
+ }
+ maxItems = std::max(maxItems, items.size());
+ values.emplace_back(std::move(items));
+ }
+
+ // Form the list of iteration variables
+ std::vector<std::string> iterationVars;
+ if (this->IterationVarsCount > 1) {
+ // If multiple iteration variables has given,
+ // just copy them to the `iterationVars` list.
+ iterationVars.reserve(values.size());
+ std::copy(this->Args.begin(),
+ this->Args.begin() + this->IterationVarsCount,
+ std::back_inserter(iterationVars));
+ } else {
+ // In case of the only iteration variable,
+ // generate names as `var_name_N`,
+ // where `N` is the count of lists to zip
+ iterationVars.resize(values.size());
+ const auto iter_var_prefix = this->Args.front() + "_";
+ auto i = 0u;
+ std::generate(
+ iterationVars.begin(), iterationVars.end(),
+ [&]() -> std::string { return iter_var_prefix + std::to_string(i++); });
+ }
+ assert("Sanity check" && iterationVars.size() == values.size());
+
+ // Store old values for iteration variables
+ std::map<std::string, std::string> oldDefs;
+ for (auto i = 0u; i < values.size(); ++i) {
+ if (mf.GetDefinition(iterationVars[i])) {
+ oldDefs.emplace(iterationVars[i], mf.GetDefinition(iterationVars[i]));
+ }
+ }
+
+ // Form a vector of current positions in all lists (Ok, vectors) of values
+ std::vector<decltype(values)::value_type::iterator> positions;
+ positions.reserve(values.size());
+ std::transform(
+ values.begin(), values.end(), std::back_inserter(positions),
+ // Set the initial position to the beginning of every list
+ [](decltype(values)::value_type& list) { return list.begin(); });
+ assert("Sanity check" && positions.size() == values.size());
+
+ auto restore = false;
+ // Iterate over all the lists simulateneously
+ for (auto i = 0u; i < maxItems; ++i) {
+ // Declare iteration variables
+ for (auto j = 0u; j < values.size(); ++j) {
+ // Define (or not) the iteration variable if the current position
+ // still not at the end...
+ if (positions[j] != values[j].end()) {
+ mf.AddDefinition(iterationVars[j], *positions[j]);
+ ++positions[j];
+ } else {
+ mf.RemoveDefinition(iterationVars[j]);
+ }
+ }
+ // Invoke all the functions that were collected in the block.
+ auto r = this->invoke(functions, inStatus, mf);
+ restore = r.Restore;
+ if (r.Break) {
+ break;
+ }
+ }
+
+ // Restore the variables to its prior value
+ if (restore) {
+ for (auto const& p : oldDefs) {
+ mf.AddDefinition(p.first, p.second);
+ }
+ }
+ return true;
+}
+
+auto cmForEachFunctionBlocker::invoke(
+ std::vector<cmListFileFunction> const& functions,
+ cmExecutionStatus& inStatus, cmMakefile& mf) -> InvokeResult
+{
+ InvokeResult result = { true, false };
+ // Invoke all the functions that were collected in the block.
+ for (cmListFileFunction const& func : functions) {
+ cmExecutionStatus status(mf);
+ mf.ExecuteCommand(func, status);
+ if (status.GetReturnInvoked()) {
+ inStatus.SetReturnInvoked();
+ result.Break = true;
+ break;
+ }
+ if (status.GetBreakInvoked()) {
+ result.Break = true;
+ break;
+ }
+ if (status.GetContinueInvoked()) {
+ break;
+ }
+ if (cmSystemTools::GetFatalErrorOccured()) {
+ result.Restore = false;
+ result.Break = true;
+ break;
+ }
+ }
+ return result;
+}
+
+bool HandleInMode(std::vector<std::string> const& args,
+ std::vector<std::string>::const_iterator kwInIter,
+ cmMakefile& makefile)
+{
+ assert("A valid iterator expected" && kwInIter != args.end());
+
auto fb = cm::make_unique<cmForEachFunctionBlocker>(&makefile);
- fb->Args.push_back(args.front());
+
+ // Copy iteration variable names first
+ std::copy(args.begin(), kwInIter, std::back_inserter(fb->Args));
+ // Remember the count of given iteration variable names
+ const auto varsCount = fb->Args.size();
+ fb->SetIterationVarsCount(varsCount);
enum Doing
{
DoingNone,
DoingLists,
- DoingItems
+ DoingItems,
+ DoingZipLists
};
Doing doing = DoingNone;
- for (std::string const& arg : cmMakeRange(args).advance(2)) {
+ // Iterate over arguments past the "IN" keyword
+ for (std::string const& arg : cmMakeRange(++kwInIter, args.end())) {
if (arg == "LISTS") {
+ if (doing == DoingZipLists) {
+ makefile.IssueMessage(MessageType::FATAL_ERROR,
+ "ZIP_LISTS can not be used with LISTS or ITEMS");
+ return true;
+ }
+ if (varsCount != 1u) {
+ makefile.IssueMessage(
+ MessageType::FATAL_ERROR,
+ "ITEMS or LISTS require exactly one iteration variable");
+ return true;
+ }
doing = DoingLists;
+
} else if (arg == "ITEMS") {
+ if (doing == DoingZipLists) {
+ makefile.IssueMessage(MessageType::FATAL_ERROR,
+ "ZIP_LISTS can not be used with LISTS or ITEMS");
+ return true;
+ }
+ if (varsCount != 1u) {
+ makefile.IssueMessage(
+ MessageType::FATAL_ERROR,
+ "ITEMS or LISTS require exactly one iteration variable");
+ return true;
+ }
doing = DoingItems;
+
+ } else if (arg == "ZIP_LISTS") {
+ if (doing != DoingNone) {
+ makefile.IssueMessage(MessageType::FATAL_ERROR,
+ "ZIP_LISTS can not be used with LISTS or ITEMS");
+ return true;
+ }
+ doing = DoingZipLists;
+ fb->SetZipLists();
+
} else if (doing == DoingLists) {
auto const& value = makefile.GetSafeDefinition(arg);
if (!value.empty()) {
cmExpandList(value, fb->Args, true);
}
- } else if (doing == DoingItems) {
+
+ } else if (doing == DoingItems || doing == DoingZipLists) {
fb->Args.push_back(arg);
+
} else {
makefile.IssueMessage(MessageType::FATAL_ERROR,
cmStrCat("Unknown argument:\n", " ", arg, "\n"));
@@ -141,6 +337,18 @@
}
}
+ // If `ZIP_LISTS` given and variables count more than 1,
+ // make sure the given lists count matches variables...
+ if (doing == DoingZipLists && varsCount > 1u &&
+ (2u * varsCount) != fb->Args.size()) {
+ makefile.IssueMessage(
+ MessageType::FATAL_ERROR,
+ cmStrCat("Expected ", std::to_string(varsCount),
+ " list variables, but given ",
+ std::to_string(fb->Args.size() - varsCount)));
+ return true;
+ }
+
makefile.AddFunctionBlocker(std::move(fb));
return true;
@@ -155,8 +363,9 @@
status.SetError("called with incorrect number of arguments");
return false;
}
- if (args.size() > 1 && args[1] == "IN") {
- return HandleInMode(args, status.GetMakefile());
+ auto kwInIter = std::find(args.begin(), args.end(), "IN");
+ if (kwInIter != args.end()) {
+ return HandleInMode(args, kwInIter, status.GetMakefile());
}
// create a function blocker
@@ -216,6 +425,8 @@
} else {
fb->Args = args;
}
+
+ fb->SetIterationVarsCount(1u);
status.GetMakefile().AddFunctionBlocker(std::move(fb));
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 @@
{
}
+cmCompiledGeneratorExpression::~cmCompiledGeneratorExpression() = default;
+
cmGeneratorExpression::~cmGeneratorExpression() = default;
std::unique_ptr<cmCompiledGeneratorExpression> cmGeneratorExpression::Parse(
@@ -86,7 +87,7 @@
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()
-{
- 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 @@
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() = default;
+
std::string GeneratorExpressionContent::GetOriginalExpression() const
{
return std::string(this->StartContent, this->ContentLength);
@@ -25,14 +25,13 @@
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 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 @@
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 @@
}
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 @@
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 @@
{
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 @@
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 @@
}
void cmGeneratorExpressionParser::Parse(
- std::vector<cmGeneratorExpressionEvaluator*>& result)
+ cmGeneratorExpressionEvaluatorVector& result)
{
it = this->Tokens.begin();
@@ -27,40 +30,38 @@
}
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 @@
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 @@
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 @@
// 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 @@
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 @@
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 @@
// 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 @@
{
cmGeneratorExpressionParser(std::vector<cmGeneratorExpressionToken> tokens);
- void Parse(std::vector<cmGeneratorExpressionEvaluator*>& result);
+ using cmGeneratorExpressionEvaluatorVector =
+ std::vector<std::unique_ptr<cmGeneratorExpressionEvaluator>>;
+
+ void Parse(cmGeneratorExpressionEvaluatorVector& result);
private:
- void ParseContent(std::vector<cmGeneratorExpressionEvaluator*>&);
- void ParseGeneratorExpression(std::vector<cmGeneratorExpressionEvaluator*>&);
+ void ParseContent(cmGeneratorExpressionEvaluatorVector&);
+ void ParseGeneratorExpression(cmGeneratorExpressionEvaluatorVector&);
private:
std::vector<cmGeneratorExpressionToken>::const_iterator it;
diff --git a/Source/cmGeneratorTarget.cxx b/Source/cmGeneratorTarget.cxx
index d0b5f9e..a4a074f 100644
--- a/Source/cmGeneratorTarget.cxx
+++ b/Source/cmGeneratorTarget.cxx
@@ -1116,7 +1116,8 @@
}
bool cmGeneratorTarget::MaybeHaveInterfaceProperty(
- std::string const& prop, cmGeneratorExpressionContext* context) const
+ std::string const& prop, cmGeneratorExpressionContext* context,
+ bool usage_requirements_only) const
{
std::string const key = prop + '@' + context->Config;
auto i = this->MaybeInterfacePropertyExists.find(key);
@@ -1135,7 +1136,7 @@
context->HeadTarget ? context->HeadTarget : this;
if (cmLinkInterfaceLibraries const* iface =
this->GetLinkInterfaceLibraries(context->Config, headTarget,
- true)) {
+ usage_requirements_only)) {
if (iface->HadHeadSensitiveCondition) {
// With a different head target we may get to a library with
// this interface property.
@@ -1145,7 +1146,8 @@
// head target, so we can follow them.
for (cmLinkItem const& lib : iface->Libraries) {
if (lib.Target &&
- lib.Target->MaybeHaveInterfaceProperty(prop, context)) {
+ lib.Target->MaybeHaveInterfaceProperty(
+ prop, context, usage_requirements_only)) {
maybeInterfaceProp = true;
break;
}
@@ -1159,12 +1161,14 @@
std::string cmGeneratorTarget::EvaluateInterfaceProperty(
std::string const& prop, cmGeneratorExpressionContext* context,
- cmGeneratorExpressionDAGChecker* dagCheckerParent) const
+ cmGeneratorExpressionDAGChecker* dagCheckerParent,
+ bool usage_requirements_only) const
{
std::string result;
// If the property does not appear transitively at all, we are done.
- if (!this->MaybeHaveInterfaceProperty(prop, context)) {
+ if (!this->MaybeHaveInterfaceProperty(prop, context,
+ usage_requirements_only)) {
return result;
}
@@ -1196,8 +1200,8 @@
p, context->LG, context, headTarget, &dagChecker, this);
}
- if (cmLinkInterfaceLibraries const* iface =
- this->GetLinkInterfaceLibraries(context->Config, headTarget, true)) {
+ if (cmLinkInterfaceLibraries const* iface = this->GetLinkInterfaceLibraries(
+ context->Config, headTarget, usage_requirements_only)) {
for (cmLinkItem const& lib : iface->Libraries) {
// Broken code can have a target in its own link interface.
// Don't follow such link interface entries so as not to create a
@@ -1240,7 +1244,8 @@
std::string const& config, std::string const& prop,
std::string const& lang,
cmGeneratorExpressionDAGChecker* dagChecker,
- std::vector<EvaluatedTargetPropertyEntry>& entries)
+ std::vector<EvaluatedTargetPropertyEntry>& entries,
+ bool usage_requirements_only = true)
{
if (cmLinkImplementationLibraries const* impl =
headTarget->GetLinkImplementationLibraries(config)) {
@@ -1253,9 +1258,9 @@
cmGeneratorExpressionContext context(
headTarget->GetLocalGenerator(), config, false, headTarget,
headTarget, true, lib.Backtrace, lang);
- cmExpandList(
- lib.Target->EvaluateInterfaceProperty(prop, &context, dagChecker),
- ee.Values);
+ cmExpandList(lib.Target->EvaluateInterfaceProperty(
+ prop, &context, dagChecker, usage_requirements_only),
+ ee.Values);
ee.ContextDependent = context.HadContextSensitiveCondition;
entries.emplace_back(std::move(ee));
}
@@ -2508,11 +2513,11 @@
info.WindowsExportAllSymbols =
this->Makefile->IsOn("CMAKE_SUPPORT_WINDOWS_EXPORT_ALL_SYMBOLS") &&
this->GetPropertyAsBool("WINDOWS_EXPORT_ALL_SYMBOLS");
-#if defined(_WIN32) && !defined(CMAKE_BOOTSTRAP)
+#if !defined(CMAKE_BOOTSTRAP)
info.DefFileGenerated =
info.WindowsExportAllSymbols || info.Sources.size() > 1;
#else
- // Our __create_def helper is only available on Windows.
+ // Our __create_def helper is not available during CMake bootstrap.
info.DefFileGenerated = false;
#endif
if (info.DefFileGenerated) {
@@ -3663,7 +3668,8 @@
this->LinkOptionsEntries);
AddInterfaceEntries(this, config, "INTERFACE_LINK_OPTIONS", language,
- &dagChecker, entries);
+ &dagChecker, entries,
+ this->GetPolicyStatusCMP0099() != cmPolicies::NEW);
processOptions(this, entries, result, uniqueOptions, debugOptions,
"link options", OptionsParse::Shell);
@@ -3918,7 +3924,8 @@
this->LinkDirectoriesEntries);
AddInterfaceEntries(this, config, "INTERFACE_LINK_DIRECTORIES", language,
- &dagChecker, entries);
+ &dagChecker, entries,
+ this->GetPolicyStatusCMP0099() != cmPolicies::NEW);
processLinkDirectories(this, entries, result, uniqueDirectories,
debugDirectories);
@@ -3956,7 +3963,8 @@
}
}
AddInterfaceEntries(this, config, "INTERFACE_LINK_DEPENDS", language,
- &dagChecker, entries);
+ &dagChecker, entries,
+ this->GetPolicyStatusCMP0099() != cmPolicies::NEW);
processOptions(this, entries, result, uniqueOptions, false, "link depends",
OptionsParse::None);
diff --git a/Source/cmGeneratorTarget.h b/Source/cmGeneratorTarget.h
index 336c91f..761e58a 100644
--- a/Source/cmGeneratorTarget.h
+++ b/Source/cmGeneratorTarget.h
@@ -707,7 +707,8 @@
std::string EvaluateInterfaceProperty(
std::string const& prop, cmGeneratorExpressionContext* context,
- cmGeneratorExpressionDAGChecker* dagCheckerParent) const;
+ cmGeneratorExpressionDAGChecker* dagCheckerParent,
+ bool usage_requirements_only = true) const;
bool HaveInstallTreeRPATH(const std::string& config) const;
@@ -886,7 +887,8 @@
mutable std::unordered_map<std::string, bool> MaybeInterfacePropertyExists;
bool MaybeHaveInterfaceProperty(std::string const& prop,
- cmGeneratorExpressionContext* context) const;
+ cmGeneratorExpressionContext* context,
+ bool usage_requirements_only) const;
using TargetPropertyEntryVector =
std::vector<std::unique_ptr<TargetPropertyEntry>>;
diff --git a/Source/cmGlobalBorlandMakefileGenerator.cxx b/Source/cmGlobalBorlandMakefileGenerator.cxx
index 51d681d..06943e7 100644
--- a/Source/cmGlobalBorlandMakefileGenerator.cxx
+++ b/Source/cmGlobalBorlandMakefileGenerator.cxx
@@ -2,6 +2,10 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmGlobalBorlandMakefileGenerator.h"
+#include <utility>
+
+#include <cm/memory>
+
#include "cmDocumentationEntry.h"
#include "cmLocalUnixMakefileGenerator3.h"
#include "cmMakefile.h"
@@ -35,15 +39,14 @@
}
//! Create a local generator appropriate to this Global Generator
-cmLocalGenerator* cmGlobalBorlandMakefileGenerator::CreateLocalGenerator(
- cmMakefile* mf)
+std::unique_ptr<cmLocalGenerator>
+cmGlobalBorlandMakefileGenerator::CreateLocalGenerator(cmMakefile* mf)
{
- cmLocalUnixMakefileGenerator3* lg =
- new cmLocalUnixMakefileGenerator3(this, mf);
+ auto lg = cm::make_unique<cmLocalUnixMakefileGenerator3>(this, mf);
lg->SetMakefileVariableSize(32);
lg->SetMakeCommandEscapeTargetTwice(true);
lg->SetBorlandMakeCurlyHack(true);
- return lg;
+ return std::unique_ptr<cmLocalGenerator>(std::move(lg));
}
void cmGlobalBorlandMakefileGenerator::GetDocumentation(
diff --git a/Source/cmGlobalBorlandMakefileGenerator.h b/Source/cmGlobalBorlandMakefileGenerator.h
index da04743..291220c 100644
--- a/Source/cmGlobalBorlandMakefileGenerator.h
+++ b/Source/cmGlobalBorlandMakefileGenerator.h
@@ -4,6 +4,7 @@
#define cmGlobalBorlandMakefileGenerator_h
#include <iosfwd>
+#include <memory>
#include "cmGlobalNMakeMakefileGenerator.h"
@@ -33,7 +34,8 @@
static void GetDocumentation(cmDocumentationEntry& entry);
//! Create a local generator appropriate to this Global Generator
- cmLocalGenerator* CreateLocalGenerator(cmMakefile* mf) override;
+ std::unique_ptr<cmLocalGenerator> CreateLocalGenerator(
+ cmMakefile* mf) override;
/**
* Try to determine system information such as shared library
diff --git a/Source/cmGlobalCommonGenerator.cxx b/Source/cmGlobalCommonGenerator.cxx
index d6c0a87..e04eef1 100644
--- a/Source/cmGlobalCommonGenerator.cxx
+++ b/Source/cmGlobalCommonGenerator.cxx
@@ -25,11 +25,11 @@
cmGlobalCommonGenerator::ComputeDirectoryTargets() const
{
std::map<std::string, DirectoryTarget> dirTargets;
- for (cmLocalGenerator* lg : this->LocalGenerators) {
+ for (const auto& lg : this->LocalGenerators) {
std::string const& currentBinaryDir(
lg->GetStateSnapshot().GetDirectory().GetCurrentBinary());
DirectoryTarget& dirTarget = dirTargets[currentBinaryDir];
- dirTarget.LG = lg;
+ dirTarget.LG = lg.get();
// The directory-level rule should depend on the target-level rules
// for all targets in the directory.
diff --git a/Source/cmGlobalGenerator.cxx b/Source/cmGlobalGenerator.cxx
index e38066f..9840025 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"
@@ -299,7 +300,7 @@
bool cmGlobalGenerator::CheckTargetsForMissingSources() const
{
bool failed = false;
- for (cmLocalGenerator* localGen : this->LocalGenerators) {
+ for (const auto& localGen : this->LocalGenerators) {
for (const auto& target : localGen->GetGeneratorTargets()) {
if (target->GetType() == cmStateEnums::TargetType::GLOBAL_TARGET ||
target->GetType() == cmStateEnums::TargetType::INTERFACE_LIBRARY ||
@@ -339,7 +340,7 @@
return false;
}
bool failed = false;
- for (cmLocalGenerator* generator : this->LocalGenerators) {
+ for (const auto& generator : this->LocalGenerators) {
for (const auto& target : generator->GetGeneratorTargets()) {
if (target->GetType() == cmStateEnums::EXECUTABLE &&
target->GetPropertyAsBool("WIN32_EXECUTABLE")) {
@@ -367,7 +368,7 @@
return false;
}
bool failed = false;
- for (cmLocalGenerator* generator : this->LocalGenerators) {
+ for (const auto& generator : this->LocalGenerators) {
for (const auto& target : generator->GetGeneratorTargets()) {
if (target->GetType() == cmStateEnums::TargetType::GLOBAL_TARGET ||
target->GetType() == cmStateEnums::TargetType::INTERFACE_LIBRARY ||
@@ -1203,13 +1204,12 @@
void cmGlobalGenerator::CreateLocalGenerators()
{
this->LocalGeneratorSearchIndex.clear();
- cmDeleteAll(this->LocalGenerators);
this->LocalGenerators.clear();
this->LocalGenerators.reserve(this->Makefiles.size());
for (cmMakefile* m : this->Makefiles) {
- cmLocalGenerator* lg = this->CreateLocalGenerator(m);
- this->LocalGenerators.push_back(lg);
- this->IndexLocalGenerator(lg);
+ auto lg = this->CreateLocalGenerator(m);
+ this->IndexLocalGenerator(lg.get());
+ this->LocalGenerators.push_back(std::move(lg));
}
}
@@ -1262,10 +1262,6 @@
"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 +1284,10 @@
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();
}
@@ -1299,7 +1299,7 @@
this->CreateGenerationObjects(ImportedOnly);
auto const mfit =
std::find(this->Makefiles.begin(), this->Makefiles.end(), mf);
- cmLocalGenerator* lg =
+ auto& lg =
this->LocalGenerators[std::distance(this->Makefiles.begin(), mfit)];
for (std::string const& t : targets) {
cmGeneratorTarget* gt = lg->FindGeneratorTargetToUse(t);
@@ -1352,7 +1352,7 @@
std::vector<cmExportBuildFileGenerator*> gens =
this->Makefiles[i]->GetExportBuildFileGenerators();
for (cmExportBuildFileGenerator* g : gens) {
- g->Compute(this->LocalGenerators[i]);
+ g->Compute(this->LocalGenerators[i].get());
}
}
}
@@ -1391,7 +1391,7 @@
}
// Add generator specific helper commands
- for (cmLocalGenerator* localGen : this->LocalGenerators) {
+ for (const auto& localGen : this->LocalGenerators) {
localGen->AddHelperCommands();
}
@@ -1401,16 +1401,16 @@
// on the original cmTarget instance. It accumulates features
// across all configurations. Some refactoring is needed to
// compute a per-config resulta purely during generation.
- for (cmLocalGenerator* localGen : this->LocalGenerators) {
+ for (const auto& localGen : this->LocalGenerators) {
if (!localGen->ComputeTargetCompileFeatures()) {
return false;
}
}
- for (cmLocalGenerator* localGen : this->LocalGenerators) {
+ for (const auto& localGen : this->LocalGenerators) {
cmMakefile* mf = localGen->GetMakefile();
for (cmInstallGenerator* g : mf->GetInstallGenerators()) {
- if (!g->Compute(localGen)) {
+ if (!g->Compute(localGen.get())) {
return false;
}
}
@@ -1420,7 +1420,7 @@
// Trace the dependencies, after that no custom commands should be added
// because their dependencies might not be handled correctly
- for (cmLocalGenerator* localGen : this->LocalGenerators) {
+ for (const auto& localGen : this->LocalGenerators) {
localGen->TraceDependencies();
}
@@ -1432,7 +1432,7 @@
this->ForceLinkerLanguages();
// Compute the manifest of main targets generated.
- for (cmLocalGenerator* localGen : this->LocalGenerators) {
+ for (const auto& localGen : this->LocalGenerators) {
localGen->ComputeTargetManifest();
}
@@ -1449,7 +1449,7 @@
return false;
}
- for (cmLocalGenerator* localGen : this->LocalGenerators) {
+ for (const auto& localGen : this->LocalGenerators) {
localGen->ComputeHomeRelativeOutputPath();
}
@@ -1464,6 +1464,8 @@
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 +1477,9 @@
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);
@@ -1559,16 +1562,27 @@
bool cmGlobalGenerator::AddAutomaticSources()
{
- for (cmLocalGenerator* lg : this->LocalGenerators) {
+ for (const auto& 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 (const auto& lg : this->LocalGenerators) {
+ for (const auto& gt : lg->GetGeneratorTargets()) {
+ gt->ClearSourcesCache();
+ }
+ }
return true;
}
@@ -1669,7 +1683,7 @@
for (unsigned int i = 0; i < this->Makefiles.size(); ++i) {
cmMakefile* mf = this->Makefiles[i];
for (cmTarget* ownedImpTgt : mf->GetOwnedImportedTargets()) {
- cmLocalGenerator* lg = this->LocalGenerators[i];
+ cmLocalGenerator* lg = this->LocalGenerators[i].get();
auto gt = cm::make_unique<cmGeneratorTarget>(ownedImpTgt, lg);
importedMap[ownedImpTgt] = gt.get();
lg->AddOwnedImportedGeneratorTarget(std::move(gt));
@@ -1679,7 +1693,7 @@
// Construct per-target generator information.
for (unsigned int i = 0; i < this->LocalGenerators.size(); ++i) {
this->CreateGeneratorTargets(targetTypes, this->Makefiles[i],
- this->LocalGenerators[i], importedMap);
+ this->LocalGenerators[i].get(), importedMap);
}
}
@@ -1691,7 +1705,6 @@
cmDeleteAll(this->Makefiles);
this->Makefiles.clear();
- cmDeleteAll(this->LocalGenerators);
this->LocalGenerators.clear();
this->AliasTargets.clear();
@@ -1714,12 +1727,12 @@
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 +1776,6 @@
}
}
}
- 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 +2025,10 @@
}
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);
}
@@ -2037,9 +2045,10 @@
this->InstallTargetEnabled = true;
}
-cmLocalGenerator* cmGlobalGenerator::CreateLocalGenerator(cmMakefile* mf)
+std::unique_ptr<cmLocalGenerator> cmGlobalGenerator::CreateLocalGenerator(
+ cmMakefile* mf)
{
- return new cmLocalGenerator(this, mf);
+ return cm::make_unique<cmLocalGenerator>(this, mf);
}
void cmGlobalGenerator::EnableLanguagesFromGenerator(cmGlobalGenerator* gen,
@@ -2134,7 +2143,7 @@
void cmGlobalGenerator::FillProjectMap()
{
this->ProjectMap.clear(); // make sure we start with a clean map
- for (cmLocalGenerator* localGen : this->LocalGenerators) {
+ for (const auto& localGen : this->LocalGenerators) {
// for each local generator add all projects
cmStateSnapshot snp = localGen->GetStateSnapshot();
std::string name;
@@ -2142,7 +2151,7 @@
std::string snpProjName = snp.GetProjectName();
if (name != snpProjName) {
name = snpProjName;
- this->ProjectMap[name].push_back(localGen);
+ this->ProjectMap[name].push_back(localGen.get());
}
snp = snp.GetBuildsystemDirectoryParent();
} while (snp.IsValid());
@@ -2652,8 +2661,8 @@
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()) {
@@ -2757,13 +2766,12 @@
std::back_inserter(filenames));
}
-void cmGlobalGenerator::GetTargetSets(TargetDependSet& projectTargets,
- TargetDependSet& originalTargets,
- cmLocalGenerator* root,
- GeneratorVector const& generators)
+void cmGlobalGenerator::GetTargetSets(
+ TargetDependSet& projectTargets, TargetDependSet& originalTargets,
+ cmLocalGenerator* root, std::vector<cmLocalGenerator*>& generators)
{
// loop over all local generators
- for (cmLocalGenerator* generator : generators) {
+ for (auto generator : generators) {
// check to make sure generator is not excluded
if (this->IsExcluded(root, generator)) {
continue;
@@ -2953,7 +2961,7 @@
"/CMakeFiles/TargetDirectories.txt");
cmGeneratedFileStream fout(fname);
- for (cmLocalGenerator* lg : this->LocalGenerators) {
+ for (const auto& lg : this->LocalGenerators) {
for (const auto& tgt : lg->GetGeneratorTargets()) {
if (tgt->GetType() == cmStateEnums::INTERFACE_LIBRARY) {
continue;
@@ -3103,7 +3111,7 @@
void cmGlobalGenerator::ProcessEvaluationFiles()
{
std::vector<std::string> generatedFiles;
- for (cmLocalGenerator* localGen : this->LocalGenerators) {
+ for (auto& localGen : this->LocalGenerators) {
localGen->ProcessEvaluationFiles(generatedFiles);
}
}
@@ -3119,7 +3127,7 @@
cmake::InstalledFilesMap const& installedFiles =
this->CMakeInstance->GetInstalledFiles();
- cmLocalGenerator* lg = this->LocalGenerators[0];
+ const auto& lg = this->LocalGenerators[0];
cmMakefile* mf = lg->GetMakefile();
std::vector<std::string> configs;
@@ -3138,8 +3146,8 @@
for (auto const& i : installedFiles) {
cmInstalledFile const& installedFile = i.second;
- cmCPackPropertiesGenerator cpackPropertiesGenerator(lg, installedFile,
- configs);
+ cmCPackPropertiesGenerator cpackPropertiesGenerator(
+ lg.get(), installedFile, configs);
cpackPropertiesGenerator.Generate(file, config, configs);
}
diff --git a/Source/cmGlobalGenerator.h b/Source/cmGlobalGenerator.h
index 0e87357..952b51e 100644
--- a/Source/cmGlobalGenerator.h
+++ b/Source/cmGlobalGenerator.h
@@ -90,11 +90,14 @@
class cmGlobalGenerator
{
public:
+ using LocalGeneratorVector = std::vector<std::unique_ptr<cmLocalGenerator>>;
+
//! Free any memory allocated with the GlobalGenerator
cmGlobalGenerator(cmake* cm);
virtual ~cmGlobalGenerator();
- virtual cmLocalGenerator* CreateLocalGenerator(cmMakefile* mf);
+ virtual std::unique_ptr<cmLocalGenerator> CreateLocalGenerator(
+ cmMakefile* mf);
//! Get the name for this generator
virtual std::string GetName() const { return "Generic"; }
@@ -249,7 +252,7 @@
{
return this->Makefiles;
}
- const std::vector<cmLocalGenerator*>& GetLocalGenerators() const
+ const LocalGeneratorVector& GetLocalGenerators() const
{
return this->LocalGenerators;
}
@@ -477,12 +480,11 @@
int RecursionDepth;
protected:
- using GeneratorVector = std::vector<cmLocalGenerator*>;
// for a project collect all its targets by following depend
// information, and also collect all the targets
void GetTargetSets(TargetDependSet& projectTargets,
TargetDependSet& originalTargets, cmLocalGenerator* root,
- GeneratorVector const&);
+ std::vector<cmLocalGenerator*>& generators);
bool IsRootOnlyTarget(cmGeneratorTarget* target) const;
void AddTargetDepends(const cmGeneratorTarget* target,
TargetDependSet& projectTargets);
@@ -541,7 +543,7 @@
std::string ConfiguredFilesPath;
cmake* CMakeInstance;
std::vector<cmMakefile*> Makefiles;
- std::vector<cmLocalGenerator*> LocalGenerators;
+ LocalGeneratorVector LocalGenerators;
cmMakefile* CurrentConfigureMakefile;
// map from project name to vector of local generators in that project
std::map<std::string, std::vector<cmLocalGenerator*>> ProjectMap;
diff --git a/Source/cmGlobalGhsMultiGenerator.cxx b/Source/cmGlobalGhsMultiGenerator.cxx
index 7afcd49..bb9dd37 100644
--- a/Source/cmGlobalGhsMultiGenerator.cxx
+++ b/Source/cmGlobalGhsMultiGenerator.cxx
@@ -8,6 +8,8 @@
#include <ostream>
#include <utility>
+#include <cm/memory>
+
#include "cmAlgorithms.h"
#include "cmDocumentationEntry.h"
#include "cmGeneratedFileStream.h"
@@ -40,10 +42,11 @@
cmGlobalGhsMultiGenerator::~cmGlobalGhsMultiGenerator() = default;
-cmLocalGenerator* cmGlobalGhsMultiGenerator::CreateLocalGenerator(
- cmMakefile* mf)
+std::unique_ptr<cmLocalGenerator>
+cmGlobalGhsMultiGenerator::CreateLocalGenerator(cmMakefile* mf)
{
- return new cmLocalGhsMultiGenerator(this, mf);
+ return std::unique_ptr<cmLocalGenerator>(
+ cm::make_unique<cmLocalGhsMultiGenerator>(this, mf));
}
void cmGlobalGhsMultiGenerator::GetDocumentation(cmDocumentationEntry& entry)
diff --git a/Source/cmGlobalGhsMultiGenerator.h b/Source/cmGlobalGhsMultiGenerator.h
index 7cd8c79..989b12c 100644
--- a/Source/cmGlobalGhsMultiGenerator.h
+++ b/Source/cmGlobalGhsMultiGenerator.h
@@ -4,6 +4,7 @@
#define cmGhsMultiGenerator_h
#include <iosfwd>
+#include <memory>
#include <set>
#include <string>
#include <utility>
@@ -34,7 +35,8 @@
}
//! create the correct local generator
- cmLocalGenerator* CreateLocalGenerator(cmMakefile* mf) override;
+ std::unique_ptr<cmLocalGenerator> CreateLocalGenerator(
+ cmMakefile* mf) override;
/// @return the name of this generator.
static std::string GetActualName() { return "Green Hills MULTI"; }
diff --git a/Source/cmGlobalNinjaGenerator.cxx b/Source/cmGlobalNinjaGenerator.cxx
index da21d6c..3500007 100644
--- a/Source/cmGlobalNinjaGenerator.cxx
+++ b/Source/cmGlobalNinjaGenerator.cxx
@@ -9,6 +9,7 @@
#include <sstream>
#include <cm/memory>
+#include <cmext/memory>
#include "cmsys/FStream.hxx"
@@ -429,9 +430,11 @@
// Virtual public methods.
-cmLocalGenerator* cmGlobalNinjaGenerator::CreateLocalGenerator(cmMakefile* mf)
+std::unique_ptr<cmLocalGenerator> cmGlobalNinjaGenerator::CreateLocalGenerator(
+ cmMakefile* mf)
{
- return new cmLocalNinjaGenerator(this, mf);
+ return std::unique_ptr<cmLocalGenerator>(
+ cm::make_unique<cmLocalNinjaGenerator>(this, mf));
}
codecvt::Encoding cmGlobalNinjaGenerator::GetMakefileEncoding() const
@@ -819,10 +822,10 @@
return f->second;
}
- cmLocalNinjaGenerator* ng =
- static_cast<cmLocalNinjaGenerator*>(this->LocalGenerators[0]);
- std::string const& bin_dir = ng->GetState()->GetBinaryDirectory();
- std::string convPath = ng->MaybeConvertToRelativePath(bin_dir, path);
+ const auto& ng =
+ cm::static_reference_cast<cmLocalNinjaGenerator>(this->LocalGenerators[0]);
+ std::string const& bin_dir = ng.GetState()->GetBinaryDirectory();
+ std::string convPath = ng.MaybeConvertToRelativePath(bin_dir, path);
convPath = this->NinjaOutputPath(convPath);
#ifdef _WIN32
std::replace(convPath.begin(), convPath.end(), '/', '\\');
@@ -1148,7 +1151,7 @@
// get the list of files that cmake itself has generated as a
// product of configuration.
- for (cmLocalGenerator* lg : this->LocalGenerators) {
+ for (const auto& lg : this->LocalGenerators) {
// get the vector of files created by this makefile and convert them
// to ninja paths, which are all relative in respect to the build directory
for (std::string const& file : lg->GetMakefile()->GetOutputFiles()) {
@@ -1268,7 +1271,7 @@
if (this->GlobalSettingIsOn("CMAKE_SUPPRESS_REGENERATION")) {
return;
}
- cmLocalGenerator* lg = this->LocalGenerators[0];
+ const auto& lg = this->LocalGenerators[0];
{
cmNinjaRule rule("RERUN_CMAKE");
@@ -1289,7 +1292,7 @@
reBuild.Comment = "Re-run CMake if any of its inputs changed.";
reBuild.Outputs.push_back(this->NinjaOutputPath(NINJA_BUILD_FILE));
- for (cmLocalGenerator* localGen : this->LocalGenerators) {
+ for (const auto& localGen : this->LocalGenerators) {
for (std::string const& fi : localGen->GetMakefile()->GetListFiles()) {
reBuild.ImplicitDeps.push_back(this->ConvertToNinjaPath(fi));
}
@@ -1376,14 +1379,14 @@
std::string cmGlobalNinjaGenerator::CMakeCmd() const
{
- cmLocalGenerator* lgen = this->LocalGenerators.at(0);
+ const auto& lgen = this->LocalGenerators.at(0);
return lgen->ConvertToOutputFormat(cmSystemTools::GetCMakeCommand(),
cmOutputConverter::SHELL);
}
std::string cmGlobalNinjaGenerator::NinjaCmd() const
{
- cmLocalGenerator* lgen = this->LocalGenerators[0];
+ const auto& lgen = this->LocalGenerators[0];
if (lgen != nullptr) {
return lgen->ConvertToOutputFormat(this->NinjaCommand,
cmOutputConverter::SHELL);
@@ -1413,7 +1416,7 @@
bool cmGlobalNinjaGenerator::WriteTargetCleanAdditional(std::ostream& os)
{
- cmLocalGenerator* lgr = this->LocalGenerators.at(0);
+ const auto& lgr = this->LocalGenerators.at(0);
std::string cleanScriptRel = "CMakeFiles/clean_additional.cmake";
std::string cleanScriptAbs =
cmStrCat(lgr->GetBinaryDirectory(), '/', cleanScriptRel);
@@ -1809,11 +1812,9 @@
snapshot.GetDirectory().SetRelativePathTopSource(dir_top_src.c_str());
snapshot.GetDirectory().SetRelativePathTopBinary(dir_top_bld.c_str());
auto mfd = cm::make_unique<cmMakefile>(this, snapshot);
- std::unique_ptr<cmLocalNinjaGenerator> lgd(
- static_cast<cmLocalNinjaGenerator*>(
- this->CreateLocalGenerator(mfd.get())));
+ auto lgd = this->CreateLocalGenerator(mfd.get());
this->Makefiles.push_back(mfd.release());
- this->LocalGenerators.push_back(lgd.release());
+ this->LocalGenerators.push_back(std::move(lgd));
}
std::vector<cmDyndepObjectInfo> objects;
diff --git a/Source/cmGlobalNinjaGenerator.h b/Source/cmGlobalNinjaGenerator.h
index 244e9fd..41b41ac 100644
--- a/Source/cmGlobalNinjaGenerator.h
+++ b/Source/cmGlobalNinjaGenerator.h
@@ -156,7 +156,8 @@
return new cmGlobalGeneratorSimpleFactory<cmGlobalNinjaGenerator>();
}
- cmLocalGenerator* CreateLocalGenerator(cmMakefile* mf) override;
+ std::unique_ptr<cmLocalGenerator> CreateLocalGenerator(
+ cmMakefile* mf) override;
std::string GetName() const override
{
@@ -295,11 +296,6 @@
void AppendTargetDependsClosure(cmGeneratorTarget const* target,
cmNinjaOuts& outputs, bool omit_self);
- const std::vector<cmLocalGenerator*>& GetLocalGenerators() const
- {
- return LocalGenerators;
- }
-
int GetRuleCmdLength(const std::string& name) { return RuleCmdLength[name]; }
void AddTargetAlias(const std::string& alias, cmGeneratorTarget* target);
diff --git a/Source/cmGlobalUnixMakefileGenerator3.cxx b/Source/cmGlobalUnixMakefileGenerator3.cxx
index dfc495e..fe8c3f4 100644
--- a/Source/cmGlobalUnixMakefileGenerator3.cxx
+++ b/Source/cmGlobalUnixMakefileGenerator3.cxx
@@ -8,6 +8,7 @@
#include <utility>
#include <cm/memory>
+#include <cmext/memory>
#include "cmAlgorithms.h"
#include "cmDocumentationEntry.h"
@@ -61,10 +62,11 @@
}
//! Create a local generator appropriate to this Global Generator
-cmLocalGenerator* cmGlobalUnixMakefileGenerator3::CreateLocalGenerator(
- cmMakefile* mf)
+std::unique_ptr<cmLocalGenerator>
+cmGlobalUnixMakefileGenerator3::CreateLocalGenerator(cmMakefile* mf)
{
- return new cmLocalUnixMakefileGenerator3(this, mf);
+ return std::unique_ptr<cmLocalGenerator>(
+ cm::make_unique<cmLocalUnixMakefileGenerator3>(this, mf));
}
void cmGlobalUnixMakefileGenerator3::GetDocumentation(
@@ -144,11 +146,11 @@
for (auto& pmi : this->ProgressMap) {
pmi.second.WriteProgressVariables(total, current);
}
- for (cmLocalGenerator* lg : this->LocalGenerators) {
+ for (const auto& lg : this->LocalGenerators) {
std::string markFileName =
cmStrCat(lg->GetCurrentBinaryDirectory(), "/CMakeFiles/progress.marks");
cmGeneratedFileStream markFile(markFileName);
- markFile << this->CountProgressMarksInAll(lg) << "\n";
+ markFile << this->CountProgressMarksInAll(*lg) << "\n";
}
// write the main makefile
@@ -203,11 +205,11 @@
}
// get a local generator for some useful methods
- cmLocalUnixMakefileGenerator3* lg =
- static_cast<cmLocalUnixMakefileGenerator3*>(this->LocalGenerators[0]);
+ auto& lg = cm::static_reference_cast<cmLocalUnixMakefileGenerator3>(
+ this->LocalGenerators[0]);
// Write the do not edit header.
- lg->WriteDisclaimer(makefileStream);
+ lg.WriteDisclaimer(makefileStream);
// Write the main entry point target. This must be the VERY first
// target so that make with no arguments will run it.
@@ -217,10 +219,10 @@
depends.emplace_back("all");
// Write the rule.
- lg->WriteMakeRule(makefileStream,
- "Default target executed when no arguments are "
- "given to make.",
- "default_target", depends, no_commands, true);
+ lg.WriteMakeRule(makefileStream,
+ "Default target executed when no arguments are "
+ "given to make.",
+ "default_target", depends, no_commands, true);
depends.clear();
@@ -231,7 +233,7 @@
}
// Write out the "special" stuff
- lg->WriteSpecialTargetsTop(makefileStream);
+ lg.WriteSpecialTargetsTop(makefileStream);
// Write the directory level rules.
for (auto const& it : this->ComputeDirectoryTargets()) {
@@ -239,13 +241,14 @@
}
// Write the target convenience rules
- for (cmLocalGenerator* localGen : this->LocalGenerators) {
+ for (const auto& localGen : this->LocalGenerators) {
this->WriteConvenienceRules2(
- makefileStream, static_cast<cmLocalUnixMakefileGenerator3*>(localGen));
+ makefileStream,
+ cm::static_reference_cast<cmLocalUnixMakefileGenerator3>(localGen));
}
// Write special bottom targets
- lg->WriteSpecialTargetsBottom(makefileStream);
+ lg.WriteSpecialTargetsBottom(makefileStream);
}
void cmGlobalUnixMakefileGenerator3::WriteMainCMakefile()
@@ -268,12 +271,14 @@
std::string makefileName =
cmStrCat(this->GetCMakeInstance()->GetHomeOutputDirectory(), "/Makefile");
- // get a local generator for some useful methods
- cmLocalUnixMakefileGenerator3* lg =
- static_cast<cmLocalUnixMakefileGenerator3*>(this->LocalGenerators[0]);
+ {
+ // get a local generator for some useful methods
+ auto& lg = cm::static_reference_cast<cmLocalUnixMakefileGenerator3>(
+ this->LocalGenerators[0]);
- // Write the do not edit header.
- lg->WriteDisclaimer(cmakefileStream);
+ // Write the do not edit header.
+ lg.WriteDisclaimer(cmakefileStream);
+ }
// Save the generator name
cmakefileStream << "# The generator used is:\n"
@@ -282,7 +287,7 @@
// for each cmMakefile get its list of dependencies
std::vector<std::string> lfiles;
- for (cmLocalGenerator* localGen : this->LocalGenerators) {
+ for (const auto& localGen : this->LocalGenerators) {
// Get the list of files contributing to this generation step.
cmAppend(lfiles, localGen->GetMakefile()->GetListFiles());
}
@@ -300,59 +305,61 @@
lfiles.erase(new_end, lfiles.end());
#endif
- // reset lg to the first makefile
- lg = static_cast<cmLocalUnixMakefileGenerator3*>(this->LocalGenerators[0]);
-
- std::string currentBinDir = lg->GetCurrentBinaryDirectory();
- // Save the list to the cmake file.
- cmakefileStream
- << "# The top level Makefile was generated from the following files:\n"
- << "set(CMAKE_MAKEFILE_DEPENDS\n"
- << " \"CMakeCache.txt\"\n";
- for (std::string const& f : lfiles) {
- cmakefileStream << " \""
- << lg->MaybeConvertToRelativePath(currentBinDir, f)
- << "\"\n";
- }
- cmakefileStream << " )\n\n";
-
- // Build the path to the cache check file.
- std::string check =
- cmStrCat(this->GetCMakeInstance()->GetHomeOutputDirectory(),
- "/CMakeFiles/cmake.check_cache");
-
- // Set the corresponding makefile in the cmake file.
- cmakefileStream << "# The corresponding makefile is:\n"
- << "set(CMAKE_MAKEFILE_OUTPUTS\n"
- << " \""
- << lg->MaybeConvertToRelativePath(currentBinDir,
- makefileName)
- << "\"\n"
- << " \""
- << lg->MaybeConvertToRelativePath(currentBinDir, check)
- << "\"\n";
- cmakefileStream << " )\n\n";
-
- const std::string binDir = lg->GetBinaryDirectory();
-
- // CMake must rerun if a byproduct is missing.
{
- cmakefileStream << "# Byproducts of CMake generate step:\n"
- << "set(CMAKE_MAKEFILE_PRODUCTS\n";
- for (std::string const& outfile : lg->GetMakefile()->GetOutputFiles()) {
+ // reset lg to the first makefile
+ const auto& lg = cm::static_reference_cast<cmLocalUnixMakefileGenerator3>(
+ this->LocalGenerators[0]);
+
+ const std::string& currentBinDir = lg.GetCurrentBinaryDirectory();
+ // Save the list to the cmake file.
+ cmakefileStream
+ << "# The top level Makefile was generated from the following files:\n"
+ << "set(CMAKE_MAKEFILE_DEPENDS\n"
+ << " \"CMakeCache.txt\"\n";
+ for (std::string const& f : lfiles) {
cmakefileStream << " \""
- << lg->MaybeConvertToRelativePath(binDir, outfile)
+ << lg.MaybeConvertToRelativePath(currentBinDir, f)
<< "\"\n";
}
+ cmakefileStream << " )\n\n";
+
+ // Build the path to the cache check file.
+ std::string check =
+ cmStrCat(this->GetCMakeInstance()->GetHomeOutputDirectory(),
+ "/CMakeFiles/cmake.check_cache");
+
+ // Set the corresponding makefile in the cmake file.
+ cmakefileStream << "# The corresponding makefile is:\n"
+ << "set(CMAKE_MAKEFILE_OUTPUTS\n"
+ << " \""
+ << lg.MaybeConvertToRelativePath(currentBinDir,
+ makefileName)
+ << "\"\n"
+ << " \""
+ << lg.MaybeConvertToRelativePath(currentBinDir, check)
+ << "\"\n";
+ cmakefileStream << " )\n\n";
+
+ const std::string& binDir = lg.GetBinaryDirectory();
+
+ // CMake must rerun if a byproduct is missing.
+ {
+ cmakefileStream << "# Byproducts of CMake generate step:\n"
+ << "set(CMAKE_MAKEFILE_PRODUCTS\n";
+ for (std::string const& outfile : lg.GetMakefile()->GetOutputFiles()) {
+ cmakefileStream << " \""
+ << lg.MaybeConvertToRelativePath(binDir, outfile)
+ << "\"\n";
+ }
+ }
// add in all the directory information files
std::string tmpStr;
- for (cmLocalGenerator* localGen : this->LocalGenerators) {
- lg = static_cast<cmLocalUnixMakefileGenerator3*>(localGen);
- tmpStr = cmStrCat(lg->GetCurrentBinaryDirectory(),
+ for (const auto& localGen : this->LocalGenerators) {
+ tmpStr = cmStrCat(localGen->GetCurrentBinaryDirectory(),
"/CMakeFiles/CMakeDirectoryInformation.cmake");
cmakefileStream << " \""
- << lg->MaybeConvertToRelativePath(binDir, tmpStr)
+ << localGen->MaybeConvertToRelativePath(binDir, tmpStr)
<< "\"\n";
}
cmakefileStream << " )\n\n";
@@ -364,24 +371,23 @@
void cmGlobalUnixMakefileGenerator3::WriteMainCMakefileLanguageRules(
cmGeneratedFileStream& cmakefileStream,
- std::vector<cmLocalGenerator*>& lGenerators)
+ std::vector<std::unique_ptr<cmLocalGenerator>>& lGenerators)
{
- cmLocalUnixMakefileGenerator3* lg;
-
// now list all the target info files
cmakefileStream << "# Dependency information for all targets:\n";
cmakefileStream << "set(CMAKE_DEPEND_INFO_FILES\n";
- for (cmLocalGenerator* lGenerator : lGenerators) {
- lg = static_cast<cmLocalUnixMakefileGenerator3*>(lGenerator);
+ for (const auto& lGenerator : lGenerators) {
+ const auto& lg =
+ cm::static_reference_cast<cmLocalUnixMakefileGenerator3>(lGenerator);
// for all of out targets
- for (const auto& tgt : lg->GetGeneratorTargets()) {
+ for (const auto& tgt : lg.GetGeneratorTargets()) {
if ((tgt->GetType() == cmStateEnums::EXECUTABLE) ||
(tgt->GetType() == cmStateEnums::STATIC_LIBRARY) ||
(tgt->GetType() == cmStateEnums::SHARED_LIBRARY) ||
(tgt->GetType() == cmStateEnums::MODULE_LIBRARY) ||
(tgt->GetType() == cmStateEnums::OBJECT_LIBRARY) ||
(tgt->GetType() == cmStateEnums::UTILITY)) {
- std::string tname = cmStrCat(lg->GetRelativeTargetDirectory(tgt.get()),
+ std::string tname = cmStrCat(lg.GetRelativeTargetDirectory(tgt.get()),
"/DependInfo.cmake");
cmSystemTools::ConvertToUnixSlashes(tname);
cmakefileStream << " \"" << tname << "\"\n";
@@ -544,11 +550,11 @@
}
// write the target convenience rules
- for (cmLocalGenerator* localGen : this->LocalGenerators) {
- cmLocalUnixMakefileGenerator3* lg =
- static_cast<cmLocalUnixMakefileGenerator3*>(localGen);
+ for (const auto& localGen : this->LocalGenerators) {
+ auto& lg =
+ cm::static_reference_cast<cmLocalUnixMakefileGenerator3>(localGen);
// for each target Generate the rule files for each target.
- for (const auto& gtarget : lg->GetGeneratorTargets()) {
+ for (const auto& gtarget : lg.GetGeneratorTargets()) {
// Don't emit the same rule twice (e.g. two targets with the same
// simple name)
int type = gtarget->GetType();
@@ -563,23 +569,23 @@
(type == cmStateEnums::OBJECT_LIBRARY) ||
(type == cmStateEnums::UTILITY))) {
// Add a rule to build the target by name.
- lg->WriteDivider(ruleFileStream);
+ lg.WriteDivider(ruleFileStream);
ruleFileStream << "# Target rules for targets named " << name
<< "\n\n";
// Write the rule.
commands.clear();
std::string tmp = "CMakeFiles/Makefile2";
- commands.push_back(lg->GetRecursiveMakeCall(tmp, name));
+ commands.push_back(lg.GetRecursiveMakeCall(tmp, name));
depends.clear();
if (regenerate) {
depends.emplace_back("cmake_check_build_system");
}
- lg->WriteMakeRule(ruleFileStream, "Build rule for target.", name,
- depends, commands, true);
+ lg.WriteMakeRule(ruleFileStream, "Build rule for target.", name,
+ depends, commands, true);
// Add a fast rule to build the target
- std::string localName = lg->GetRelativeTargetDirectory(gtarget.get());
+ std::string localName = lg.GetRelativeTargetDirectory(gtarget.get());
std::string makefileName;
makefileName = cmStrCat(localName, "/build.make");
depends.clear();
@@ -587,23 +593,23 @@
std::string makeTargetName = cmStrCat(localName, "/build");
localName = cmStrCat(name, "/fast");
commands.push_back(
- lg->GetRecursiveMakeCall(makefileName, makeTargetName));
- lg->WriteMakeRule(ruleFileStream, "fast build rule for target.",
- localName, depends, commands, true);
+ lg.GetRecursiveMakeCall(makefileName, makeTargetName));
+ lg.WriteMakeRule(ruleFileStream, "fast build rule for target.",
+ localName, depends, commands, true);
// Add a local name for the rule to relink the target before
// installation.
- if (gtarget->NeedRelinkBeforeInstall(lg->GetConfigName())) {
+ if (gtarget->NeedRelinkBeforeInstall(lg.GetConfigName())) {
makeTargetName = cmStrCat(
- lg->GetRelativeTargetDirectory(gtarget.get()), "/preinstall");
+ lg.GetRelativeTargetDirectory(gtarget.get()), "/preinstall");
localName = cmStrCat(name, "/preinstall");
depends.clear();
commands.clear();
commands.push_back(
- lg->GetRecursiveMakeCall(makefileName, makeTargetName));
- lg->WriteMakeRule(ruleFileStream,
- "Manual pre-install relink rule for target.",
- localName, depends, commands, true);
+ lg.GetRecursiveMakeCall(makefileName, makeTargetName));
+ lg.WriteMakeRule(ruleFileStream,
+ "Manual pre-install relink rule for target.",
+ localName, depends, commands, true);
}
}
}
@@ -611,7 +617,7 @@
}
void cmGlobalUnixMakefileGenerator3::WriteConvenienceRules2(
- std::ostream& ruleFileStream, cmLocalUnixMakefileGenerator3* lg)
+ std::ostream& ruleFileStream, cmLocalUnixMakefileGenerator3& lg)
{
std::vector<std::string> depends;
std::vector<std::string> commands;
@@ -624,7 +630,7 @@
}
// for each target Generate the rule files for each target.
- for (const auto& gtarget : lg->GetGeneratorTargets()) {
+ for (const auto& gtarget : lg.GetGeneratorTargets()) {
int type = gtarget->GetType();
std::string name = gtarget->GetName();
if (!name.empty() &&
@@ -636,27 +642,27 @@
(type == cmStateEnums::UTILITY))) {
std::string makefileName;
// Add a rule to build the target by name.
- localName = lg->GetRelativeTargetDirectory(gtarget.get());
+ localName = lg.GetRelativeTargetDirectory(gtarget.get());
makefileName = cmStrCat(localName, "/build.make");
- lg->WriteDivider(ruleFileStream);
+ lg.WriteDivider(ruleFileStream);
ruleFileStream << "# Target rules for target " << localName << "\n\n";
commands.clear();
makeTargetName = cmStrCat(localName, "/depend");
commands.push_back(
- lg->GetRecursiveMakeCall(makefileName, makeTargetName));
+ lg.GetRecursiveMakeCall(makefileName, makeTargetName));
makeTargetName = cmStrCat(localName, "/build");
commands.push_back(
- lg->GetRecursiveMakeCall(makefileName, makeTargetName));
+ lg.GetRecursiveMakeCall(makefileName, makeTargetName));
// Write the rule.
localName += "/all";
depends.clear();
cmLocalUnixMakefileGenerator3::EchoProgress progress;
- progress.Dir = cmStrCat(lg->GetBinaryDirectory(), "/CMakeFiles");
+ progress.Dir = cmStrCat(lg.GetBinaryDirectory(), "/CMakeFiles");
{
std::ostringstream progressArg;
const char* sep = "";
@@ -675,13 +681,13 @@
}
if (targetMessages) {
- lg->AppendEcho(commands, "Built target " + name,
- cmLocalUnixMakefileGenerator3::EchoNormal, &progress);
+ lg.AppendEcho(commands, "Built target " + name,
+ cmLocalUnixMakefileGenerator3::EchoNormal, &progress);
}
this->AppendGlobalTargetDepends(depends, gtarget.get());
- lg->WriteMakeRule(ruleFileStream, "All Build rule for target.",
- localName, depends, commands, true);
+ lg.WriteMakeRule(ruleFileStream, "All Build rule for target.", localName,
+ depends, commands, true);
// Write the rule.
commands.clear();
@@ -691,7 +697,7 @@
std::ostringstream progCmd;
progCmd << "$(CMAKE_COMMAND) -E cmake_progress_start ";
// # in target
- progCmd << lg->ConvertToOutputFormat(
+ progCmd << lg.ConvertToOutputFormat(
cmSystemTools::CollapseFullPath(progress.Dir),
cmOutputConverter::SHELL);
//
@@ -701,11 +707,11 @@
commands.push_back(progCmd.str());
}
std::string tmp = "CMakeFiles/Makefile2";
- commands.push_back(lg->GetRecursiveMakeCall(tmp, localName));
+ commands.push_back(lg.GetRecursiveMakeCall(tmp, localName));
{
std::ostringstream progCmd;
progCmd << "$(CMAKE_COMMAND) -E cmake_progress_start "; // # 0
- progCmd << lg->ConvertToOutputFormat(
+ progCmd << lg.ConvertToOutputFormat(
cmSystemTools::CollapseFullPath(progress.Dir),
cmOutputConverter::SHELL);
progCmd << " 0";
@@ -716,39 +722,38 @@
depends.emplace_back("cmake_check_build_system");
}
localName =
- cmStrCat(lg->GetRelativeTargetDirectory(gtarget.get()), "/rule");
- lg->WriteMakeRule(ruleFileStream,
- "Build rule for subdir invocation for target.",
- localName, depends, commands, true);
+ cmStrCat(lg.GetRelativeTargetDirectory(gtarget.get()), "/rule");
+ lg.WriteMakeRule(ruleFileStream,
+ "Build rule for subdir invocation for target.",
+ localName, depends, commands, true);
// Add a target with the canonical name (no prefix, suffix or path).
commands.clear();
depends.clear();
depends.push_back(localName);
- lg->WriteMakeRule(ruleFileStream, "Convenience name for target.", name,
- depends, commands, true);
+ lg.WriteMakeRule(ruleFileStream, "Convenience name for target.", name,
+ depends, commands, true);
// Add rules to prepare the target for installation.
- if (gtarget->NeedRelinkBeforeInstall(lg->GetConfigName())) {
- localName = cmStrCat(lg->GetRelativeTargetDirectory(gtarget.get()),
+ if (gtarget->NeedRelinkBeforeInstall(lg.GetConfigName())) {
+ localName = cmStrCat(lg.GetRelativeTargetDirectory(gtarget.get()),
"/preinstall");
depends.clear();
commands.clear();
- commands.push_back(lg->GetRecursiveMakeCall(makefileName, localName));
- lg->WriteMakeRule(ruleFileStream,
- "Pre-install relink rule for target.", localName,
- depends, commands, true);
+ commands.push_back(lg.GetRecursiveMakeCall(makefileName, localName));
+ lg.WriteMakeRule(ruleFileStream, "Pre-install relink rule for target.",
+ localName, depends, commands, true);
}
// add the clean rule
- localName = lg->GetRelativeTargetDirectory(gtarget.get());
+ localName = lg.GetRelativeTargetDirectory(gtarget.get());
makeTargetName = cmStrCat(localName, "/clean");
depends.clear();
commands.clear();
commands.push_back(
- lg->GetRecursiveMakeCall(makefileName, makeTargetName));
- lg->WriteMakeRule(ruleFileStream, "clean rule for target.",
- makeTargetName, depends, commands, true);
+ lg.GetRecursiveMakeCall(makefileName, makeTargetName));
+ lg.WriteMakeRule(ruleFileStream, "clean rule for target.",
+ makeTargetName, depends, commands, true);
commands.clear();
}
}
@@ -760,7 +765,7 @@
{
this->DirectoryTargetsMap.clear();
// Loop over all targets in all local generators.
- for (cmLocalGenerator* lg : this->LocalGenerators) {
+ for (const auto& lg : this->LocalGenerators) {
for (const auto& gt : lg->GetGeneratorTargets()) {
cmLocalGenerator* tlg = gt->GetLocalGenerator();
@@ -810,12 +815,12 @@
}
size_t cmGlobalUnixMakefileGenerator3::CountProgressMarksInAll(
- cmLocalGenerator* lg)
+ const cmLocalGenerator& lg)
{
size_t count = 0;
std::set<cmGeneratorTarget const*> emitted;
for (cmGeneratorTarget const* target :
- this->DirectoryTargetsMap[lg->GetStateSnapshot()]) {
+ this->DirectoryTargetsMap[lg.GetStateSnapshot()]) {
count += this->CountProgressMarksInTarget(target, emitted);
}
return count;
@@ -889,14 +894,14 @@
std::set<std::string> emittedTargets;
// for each local generator
- for (cmLocalGenerator* localGen : this->LocalGenerators) {
- cmLocalUnixMakefileGenerator3* lg2 =
- static_cast<cmLocalUnixMakefileGenerator3*>(localGen);
+ for (const auto& localGen : this->LocalGenerators) {
+ const auto& lg2 =
+ cm::static_reference_cast<cmLocalUnixMakefileGenerator3>(localGen);
// for the passed in makefile or if this is the top Makefile wripte out
// the targets
- if (lg2 == lg || lg->IsRootMakefile()) {
+ if (&lg2 == lg || lg->IsRootMakefile()) {
// for each target Generate the rule files for each target.
- for (const auto& target : lg2->GetGeneratorTargets()) {
+ for (const auto& target : lg2.GetGeneratorTargets()) {
cmStateEnums::TargetType type = target->GetType();
if ((type == cmStateEnums::EXECUTABLE) ||
(type == cmStateEnums::STATIC_LIBRARY) ||
diff --git a/Source/cmGlobalUnixMakefileGenerator3.h b/Source/cmGlobalUnixMakefileGenerator3.h
index 79db30e..5608baf 100644
--- a/Source/cmGlobalUnixMakefileGenerator3.h
+++ b/Source/cmGlobalUnixMakefileGenerator3.h
@@ -8,6 +8,7 @@
#include <cstddef>
#include <iosfwd>
#include <map>
+#include <memory>
#include <set>
#include <string>
#include <vector>
@@ -89,7 +90,8 @@
/** Get the documentation entry for this generator. */
static void GetDocumentation(cmDocumentationEntry& entry);
- cmLocalGenerator* CreateLocalGenerator(cmMakefile* mf) override;
+ std::unique_ptr<cmLocalGenerator> CreateLocalGenerator(
+ cmMakefile* mf) override;
/**
* Try to determine system information such as shared library
@@ -107,8 +109,9 @@
*/
void Generate() override;
- void WriteMainCMakefileLanguageRules(cmGeneratedFileStream& cmakefileStream,
- std::vector<cmLocalGenerator*>&);
+ void WriteMainCMakefileLanguageRules(
+ cmGeneratedFileStream& cmakefileStream,
+ std::vector<std::unique_ptr<cmLocalGenerator>>&);
// write out the help rule listing the valid targets
void WriteHelpRule(std::ostream& ruleFileStream,
@@ -161,7 +164,7 @@
void WriteMainCMakefile();
void WriteConvenienceRules2(std::ostream& ruleFileStream,
- cmLocalUnixMakefileGenerator3*);
+ cmLocalUnixMakefileGenerator3&);
void WriteDirectoryRule2(std::ostream& ruleFileStream,
DirectoryTarget const& dt, const char* pass,
@@ -227,7 +230,7 @@
size_t CountProgressMarksInTarget(
cmGeneratorTarget const* target,
std::set<cmGeneratorTarget const*>& emitted);
- size_t CountProgressMarksInAll(cmLocalGenerator* lg);
+ size_t CountProgressMarksInAll(const cmLocalGenerator& lg);
cmGeneratedFileStream* CommandDatabase;
diff --git a/Source/cmGlobalVisualStudio10Generator.cxx b/Source/cmGlobalVisualStudio10Generator.cxx
index 5b83e2f..bdf4cf2 100644
--- a/Source/cmGlobalVisualStudio10Generator.cxx
+++ b/Source/cmGlobalVisualStudio10Generator.cxx
@@ -4,6 +4,8 @@
#include <algorithm>
+#include <cm/memory>
+
#include "cmsys/FStream.hxx"
#include "cmsys/Glob.hxx"
#include "cmsys/RegularExpression.hxx"
@@ -574,10 +576,11 @@
}
//! Create a local generator appropriate to this Global Generator
-cmLocalGenerator* cmGlobalVisualStudio10Generator::CreateLocalGenerator(
- cmMakefile* mf)
+std::unique_ptr<cmLocalGenerator>
+cmGlobalVisualStudio10Generator::CreateLocalGenerator(cmMakefile* mf)
{
- return new cmLocalVisualStudio10Generator(this, mf);
+ return std::unique_ptr<cmLocalGenerator>(
+ cm::make_unique<cmLocalVisualStudio10Generator>(this, mf));
}
void cmGlobalVisualStudio10Generator::Generate()
diff --git a/Source/cmGlobalVisualStudio10Generator.h b/Source/cmGlobalVisualStudio10Generator.h
index 8a76047..c991c76 100644
--- a/Source/cmGlobalVisualStudio10Generator.h
+++ b/Source/cmGlobalVisualStudio10Generator.h
@@ -3,6 +3,8 @@
#ifndef cmGlobalVisualStudio10Generator_h
#define cmGlobalVisualStudio10Generator_h
+#include <memory>
+
#include "cmGlobalVisualStudio8Generator.h"
#include "cmVisualStudio10ToolsetOptions.h"
@@ -31,7 +33,8 @@
std::vector<std::string>()) override;
//! create the correct local generator
- cmLocalGenerator* CreateLocalGenerator(cmMakefile* mf) override;
+ std::unique_ptr<cmLocalGenerator> CreateLocalGenerator(
+ cmMakefile* mf) override;
/**
* Try to determine system information such as shared library
diff --git a/Source/cmGlobalVisualStudio7Generator.cxx b/Source/cmGlobalVisualStudio7Generator.cxx
index 40b214c..04ec7b3 100644
--- a/Source/cmGlobalVisualStudio7Generator.cxx
+++ b/Source/cmGlobalVisualStudio7Generator.cxx
@@ -2,8 +2,10 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmGlobalVisualStudio7Generator.h"
+#include <utility>
#include <vector>
+#include <cm/memory>
#include <cm/string_view>
#include <windows.h>
@@ -263,12 +265,11 @@
}
//! Create a local generator appropriate to this Global Generator
-cmLocalGenerator* cmGlobalVisualStudio7Generator::CreateLocalGenerator(
- cmMakefile* mf)
+std::unique_ptr<cmLocalGenerator>
+cmGlobalVisualStudio7Generator::CreateLocalGenerator(cmMakefile* mf)
{
- cmLocalVisualStudio7Generator* lg =
- new cmLocalVisualStudio7Generator(this, mf);
- return lg;
+ auto lg = cm::make_unique<cmLocalVisualStudio7Generator>(this, mf);
+ return std::unique_ptr<cmLocalGenerator>(std::move(lg));
}
#if !defined(CMAKE_BOOTSTRAP)
@@ -300,7 +301,7 @@
if (!cmSystemTools::GetErrorOccuredFlag() &&
!this->LocalGenerators.empty()) {
this->CallVisualStudioMacro(MacroReload,
- GetSLNFile(this->LocalGenerators[0]));
+ GetSLNFile(this->LocalGenerators[0].get()));
}
}
diff --git a/Source/cmGlobalVisualStudio7Generator.h b/Source/cmGlobalVisualStudio7Generator.h
index 7a9fcef..974bb1d 100644
--- a/Source/cmGlobalVisualStudio7Generator.h
+++ b/Source/cmGlobalVisualStudio7Generator.h
@@ -3,6 +3,8 @@
#ifndef cmGlobalVisualStudio7Generator_h
#define cmGlobalVisualStudio7Generator_h
+#include <memory>
+
#include "cmGlobalGeneratorFactory.h"
#include "cmGlobalVisualStudioGenerator.h"
@@ -20,7 +22,8 @@
~cmGlobalVisualStudio7Generator();
//! Create a local generator appropriate to this Global Generator
- cmLocalGenerator* CreateLocalGenerator(cmMakefile* mf) override;
+ std::unique_ptr<cmLocalGenerator> CreateLocalGenerator(
+ cmMakefile* mf) override;
#if !defined(CMAKE_BOOTSTRAP)
Json::Value GetJson() const override;
diff --git a/Source/cmGlobalVisualStudio8Generator.cxx b/Source/cmGlobalVisualStudio8Generator.cxx
index d39d42a..6e89fc4 100644
--- a/Source/cmGlobalVisualStudio8Generator.cxx
+++ b/Source/cmGlobalVisualStudio8Generator.cxx
@@ -3,6 +3,7 @@
#include "cmGlobalVisualStudio8Generator.h"
#include <cm/memory>
+#include <cmext/memory>
#include "cmCustomCommand.h"
#include "cmCustomCommandLines.h"
@@ -98,22 +99,22 @@
return false;
}
- std::vector<cmLocalGenerator*> const& generators = this->LocalGenerators;
- cmLocalVisualStudio7Generator* lg =
- static_cast<cmLocalVisualStudio7Generator*>(generators[0]);
- cmMakefile* mf = lg->GetMakefile();
+ std::vector<std::unique_ptr<cmLocalGenerator>> const& generators =
+ this->LocalGenerators;
+ auto& lg =
+ cm::static_reference_cast<cmLocalVisualStudio7Generator>(generators[0]);
const char* no_working_directory = nullptr;
std::vector<std::string> no_byproducts;
std::vector<std::string> no_depends;
cmCustomCommandLines no_commands;
- cmTarget* tgt = mf->AddUtilityCommand(
- CMAKE_CHECK_BUILD_SYSTEM_TARGET, cmCommandOrigin::Generator, false,
- no_working_directory, no_byproducts, no_depends, no_commands);
+ cmTarget* tgt = lg.AddUtilityCommand(CMAKE_CHECK_BUILD_SYSTEM_TARGET, false,
+ no_working_directory, no_byproducts,
+ no_depends, no_commands);
- auto ptr = cm::make_unique<cmGeneratorTarget>(tgt, lg);
+ auto ptr = cm::make_unique<cmGeneratorTarget>(tgt, &lg);
auto gt = ptr.get();
- lg->AddGeneratorTarget(std::move(ptr));
+ lg.AddGeneratorTarget(std::move(ptr));
// Organize in the "predefined targets" folder:
//
@@ -131,7 +132,7 @@
stampList);
std::string stampFile;
cmGeneratedFileStream fout(stampListFile.c_str());
- for (cmLocalGenerator const* gi : generators) {
+ for (const auto& gi : generators) {
stampFile = cmStrCat(gi->GetMakefile()->GetCurrentBinaryDirectory(),
"/CMakeFiles/generate.stamp");
fout << stampFile << "\n";
@@ -144,7 +145,7 @@
// Collect the input files used to generate all targets in this
// project.
std::vector<std::string> listFiles;
- for (cmLocalGenerator* gen : generators) {
+ for (const auto& gen : generators) {
cmAppend(listFiles, gen->GetMakefile()->GetListFiles());
}
@@ -156,7 +157,7 @@
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);
@@ -174,10 +175,10 @@
listFiles.erase(new_end, listFiles.end());
// Create a rule to re-run CMake.
- std::string argS = cmStrCat("-S", lg->GetSourceDirectory());
- std::string argB = cmStrCat("-B", lg->GetBinaryDirectory());
+ std::string argS = cmStrCat("-S", lg.GetSourceDirectory());
+ std::string argB = cmStrCat("-B", lg.GetBinaryDirectory());
std::string const sln =
- lg->GetBinaryDirectory() + "/" + lg->GetProjectName() + ".sln";
+ lg.GetBinaryDirectory() + "/" + lg.GetProjectName() + ".sln";
cmCustomCommandLines commandLines = cmMakeSingleCommandLine(
{ cmSystemTools::GetCMakeCommand(), argS, argB, "--check-stamp-list",
stampList, "--vs-solution-file", sln });
@@ -188,7 +189,7 @@
// (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 @@
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 @@
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..37717f4 100644
--- a/Source/cmGlobalXCodeGenerator.cxx
+++ b/Source/cmGlobalXCodeGenerator.cxx
@@ -392,9 +392,11 @@
}
//! Create a local generator appropriate to this Global Generator
-cmLocalGenerator* cmGlobalXCodeGenerator::CreateLocalGenerator(cmMakefile* mf)
+std::unique_ptr<cmLocalGenerator> cmGlobalXCodeGenerator::CreateLocalGenerator(
+ cmMakefile* mf)
{
- return new cmLocalXCodeGenerator(this, mf);
+ return std::unique_ptr<cmLocalGenerator>(
+ cm::make_unique<cmLocalXCodeGenerator>(this, mf));
}
void cmGlobalXCodeGenerator::AddExtraIDETargets()
@@ -500,16 +502,13 @@
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 +522,7 @@
// 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 +530,10 @@
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 +558,7 @@
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,
@@ -1366,7 +1365,7 @@
void cmGlobalXCodeGenerator::ForceLinkerLanguages()
{
- for (auto localGenerator : this->LocalGenerators) {
+ for (const auto& localGenerator : this->LocalGenerators) {
// All targets depend on the build-system check target.
for (const auto& tgt : localGenerator->GetGeneratorTargets()) {
// This makes sure all targets link using the proper language.
@@ -1462,12 +1461,12 @@
{ 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/cmGlobalXCodeGenerator.h b/Source/cmGlobalXCodeGenerator.h
index f60ea72..a12021d 100644
--- a/Source/cmGlobalXCodeGenerator.h
+++ b/Source/cmGlobalXCodeGenerator.h
@@ -7,6 +7,7 @@
#include <iosfwd>
#include <map>
+#include <memory>
#include <set>
#include <string>
#include <vector>
@@ -47,7 +48,8 @@
static void GetDocumentation(cmDocumentationEntry& entry);
//! Create a local generator appropriate to this Global Generator
- cmLocalGenerator* CreateLocalGenerator(cmMakefile* mf) override;
+ std::unique_ptr<cmLocalGenerator> CreateLocalGenerator(
+ cmMakefile* mf) override;
/**
* Try to determine system information such as shared library
diff --git a/Source/cmGraphVizWriter.cxx b/Source/cmGraphVizWriter.cxx
index 9c1a924..f48789a 100644
--- a/Source/cmGraphVizWriter.cxx
+++ b/Source/cmGraphVizWriter.cxx
@@ -277,7 +277,7 @@
std::set<cmGeneratorTarget const*, cmGeneratorTarget::StrictTargetComparison>
sortedGeneratorTargets;
- for (cmLocalGenerator const* lg : gg->GetLocalGenerators()) {
+ for (const auto& lg : gg->GetLocalGenerators()) {
for (const auto& gt : lg->GetGeneratorTargets()) {
// Reserved targets have inconsistent names across platforms (e.g. 'all'
// vs. 'ALL_BUILD'), which can disrupt the traversal ordering.
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 @@
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 @@
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 @@
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 a57c40b..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 @@
}
}
+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 @@
}
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 @@
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 @@
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 @@
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 @@
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) {
@@ -3430,3 +3523,245 @@
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 @@
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 @@
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/cmLocalUnixMakefileGenerator3.cxx b/Source/cmLocalUnixMakefileGenerator3.cxx
index 7b6d0f3..61cf9e9 100644
--- a/Source/cmLocalUnixMakefileGenerator3.cxx
+++ b/Source/cmLocalUnixMakefileGenerator3.cxx
@@ -1094,8 +1094,7 @@
return;
}
- cmLocalGenerator* rootLG =
- this->GetGlobalGenerator()->GetLocalGenerators().at(0);
+ const auto& rootLG = this->GetGlobalGenerator()->GetLocalGenerators().at(0);
std::string const& binaryDir = rootLG->GetCurrentBinaryDirectory();
std::string const& currentBinaryDir = this->GetCurrentBinaryDirectory();
std::string cleanfile =
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 @@
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 @@
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 @@
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 @@
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 @@
};
}
-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 @@
}
// 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 @@
}
}
+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 @@
}
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 @@
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 @@
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 @@
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 @@
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 @@
}
// Always create the byproduct sources and mark them generated.
- this->CreateGeneratedSources(byproducts);
+ this->CreateGeneratedByproducts(byproducts);
- this->CommitCustomCommandToTarget(
- t, byproducts, depends, commandLines, type, comment, workingDir,
- escapeOldStyle, uses_terminal, depfile, job_pool, command_expand_lists);
+ // 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);
+ this->CreateGeneratedOutputs(outputs);
+ this->CreateGeneratedByproducts(byproducts);
- return this->CommitCustomCommandToOutput(
- outputs, byproducts, depends, main_dependency, implicit_depends,
- commandLines, comment, workingDir, replace, escapeOldStyle, uses_terminal,
- command_expand_lists, depfile, job_pool);
-}
+ // 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);
-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);
+ // 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 @@
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 @@
// 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 @@
// 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 @@
}
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 @@
this->GetOrCreateGeneratedSource(force.Name);
// Always create the byproduct sources and mark them generated.
- this->CreateGeneratedSources(byproducts);
+ this->CreateGeneratedByproducts(byproducts);
- if (!comment) {
- // Use an empty comment to avoid generation of default comment.
- comment = "";
- }
+ // 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);
- this->CommitUtilityCommand(target, force, workingDirectory, byproducts,
- depends, commandLines, escapeOldStyle, comment,
- uses_terminal, command_expand_lists, job_pool);
+ // 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::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 @@
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::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 @@
(!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 @@
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 @@
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 @@
(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 @@
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 @@
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 cmGlobalGenerator;
class cmImplicitDependsList;
class cmInstallGenerator;
+class cmLocalGenerator;
class cmMessenger;
class cmSourceFile;
class cmState;
@@ -151,54 +152,64 @@
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();
-
- /**
- * run all FinalActions.
- */
- void FinalPass();
+ void Generate(cmLocalGenerator& lg);
/**
* Get the target for PRE_BUILD, PRE_LINK, or POST_BUILD commands.
*/
- cmTarget* GetCustomCommandTarget(
- const std::string& target, cmObjectLibraryCommands objLibCommands) const;
+ cmTarget* GetCustomCommandTarget(const std::string& target,
+ cmObjectLibraryCommands objLibCommands,
+ const cmListFileBacktrace& lfbt) const;
- /** Add a custom command to the build. */
+ /**
+ * Dispatch adding 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);
- 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 @@
/** 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 @@
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 @@
size_t ObjectLibrariesSourceGroupIndex;
#endif
- std::vector<FinalAction> FinalActions;
cmGlobalGenerator* GlobalGenerator;
bool IsFunctionBlocked(const cmListFileFunction& lff,
cmExecutionStatus& status);
@@ -1011,6 +1020,8 @@
cmListFileBacktrace Backtrace;
int RecursionDepth;
+ void DoGenerate(cmLocalGenerator& lg);
+
void ReadListFile(cmListFile const& listFile,
const std::string& filenametoread);
@@ -1080,38 +1091,15 @@
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 @@
struct SourceEntry
{
cmSourcesWithOutput Sources;
+ bool SourceMightBeOutput = false;
};
// A map for fast output to input look up.
diff --git a/Source/cmPolicies.h b/Source/cmPolicies.h
index da32204..ecf892b 100644
--- a/Source/cmPolicies.h
+++ b/Source/cmPolicies.h
@@ -293,7 +293,11 @@
3, 16, 0, cmPolicies::WARN) \
SELECT(POLICY, CMP0098, \
"FindFLEX runs flex in CMAKE_CURRENT_BINARY_DIR when executing.", 3, \
- 17, 0, cmPolicies::WARN)
+ 17, 0, cmPolicies::WARN) \
+ SELECT(POLICY, CMP0099, \
+ "Link properties are transitive over private dependency on static " \
+ "libraries.", \
+ 3, 17, 0, cmPolicies::WARN)
#define CM_SELECT_ID(F, A1, A2, A3, A4, A5, A6) F(A1)
#define CM_FOR_EACH_POLICY_ID(POLICY) \
@@ -322,7 +326,8 @@
F(CMP0076) \
F(CMP0081) \
F(CMP0083) \
- F(CMP0095)
+ F(CMP0095) \
+ F(CMP0099)
/** \class cmPolicies
* \brief Handles changes in CMake behavior and policies
diff --git a/Source/cmQtAutoGenGlobalInitializer.cxx b/Source/cmQtAutoGenGlobalInitializer.cxx
index 4792860..db5a8ba 100644
--- a/Source/cmQtAutoGenGlobalInitializer.cxx
+++ b/Source/cmQtAutoGenGlobalInitializer.cxx
@@ -7,7 +7,6 @@
#include <cm/memory>
#include "cmCustomCommandLines.h"
-#include "cmCustomCommandTypes.h"
#include "cmDuration.h"
#include "cmGeneratorTarget.h"
#include "cmLocalGenerator.h"
@@ -41,9 +40,9 @@
}
cmQtAutoGenGlobalInitializer::cmQtAutoGenGlobalInitializer(
- std::vector<cmLocalGenerator*> const& localGenerators)
+ std::vector<std::unique_ptr<cmLocalGenerator>> const& localGenerators)
{
- for (cmLocalGenerator* localGen : localGenerators) {
+ for (const auto& localGen : localGenerators) {
// Detect global autogen and autorcc target names
bool globalAutoGenTarget = false;
bool globalAutoRccTarget = false;
@@ -56,7 +55,7 @@
if (targetName.empty()) {
targetName = "autogen";
}
- GlobalAutoGenTargets_.emplace(localGen, std::move(targetName));
+ GlobalAutoGenTargets_.emplace(localGen.get(), std::move(targetName));
globalAutoGenTarget = true;
}
@@ -67,7 +66,7 @@
if (targetName.empty()) {
targetName = "autorcc";
}
- GlobalAutoRccTargets_.emplace(localGen, std::move(targetName));
+ GlobalAutoRccTargets_.emplace(localGen.get(), std::move(targetName));
globalAutoRccTarget = true;
}
}
@@ -154,12 +153,12 @@
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/cmQtAutoGenGlobalInitializer.h b/Source/cmQtAutoGenGlobalInitializer.h
index 806725a..2f6e581 100644
--- a/Source/cmQtAutoGenGlobalInitializer.h
+++ b/Source/cmQtAutoGenGlobalInitializer.h
@@ -48,7 +48,7 @@
public:
cmQtAutoGenGlobalInitializer(
- std::vector<cmLocalGenerator*> const& localGenerators);
+ std::vector<std::unique_ptr<cmLocalGenerator>> const& localGenerators);
~cmQtAutoGenGlobalInitializer();
Keywords const& kw() const { return Keywords_; };
diff --git a/Source/cmQtAutoGenInitializer.cxx b/Source/cmQtAutoGenInitializer.cxx
index 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 @@
// 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 @@
}
// 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 @@
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 @@
}
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 @@
{
}
- void operator()(cmMakefile&) const {}
+ void operator()(cmLocalGenerator&, const cmListFileBacktrace&) const {}
private:
struct Impl
@@ -145,7 +147,7 @@
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 @@
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 @@
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/Source/cmake.cxx b/Source/cmake.cxx
index b1c6e8f..c9fe963 100644
--- a/Source/cmake.cxx
+++ b/Source/cmake.cxx
@@ -538,7 +538,7 @@
std::vector<std::string> includeDirs = cmExpandedList(includes);
gg->CreateGenerationObjects();
- cmLocalGenerator* lg = gg->LocalGenerators[0];
+ const auto& lg = gg->LocalGenerators[0];
std::string includeFlags =
lg->GetIncludeFlags(includeDirs, nullptr, language);
@@ -2169,7 +2169,7 @@
if (ggd) {
cm.GetCurrentSnapshot().SetDefaultDefinitions();
cmMakefile mfd(ggd.get(), cm.GetCurrentSnapshot());
- std::unique_ptr<cmLocalGenerator> lgd(ggd->CreateLocalGenerator(&mfd));
+ auto lgd = ggd->CreateLocalGenerator(&mfd);
lgd->ClearDependencies(&mfd, verbose);
}
}
diff --git a/Source/cmcmd.cxx b/Source/cmcmd.cxx
index c2fbb43..9f4463c 100644
--- a/Source/cmcmd.cxx
+++ b/Source/cmcmd.cxx
@@ -21,16 +21,15 @@
#if !defined(CMAKE_BOOTSTRAP)
# include "cmDependsFortran.h" // For -E cmake_copy_f90_mod callback.
+# include "cmFileTime.h"
# include "cmServer.h"
# include "cmServerConnection.h"
+
+# include "bindexplib.h"
#endif
#if !defined(CMAKE_BOOTSTRAP) && defined(_WIN32)
# include "cmsys/ConsoleBuf.hxx"
-
-# include "cmFileTime.h"
-
-# include "bindexplib.h"
#endif
#if !defined(CMAKE_BOOTSTRAP) && defined(_WIN32) && !defined(__CYGWIN__)
@@ -581,11 +580,11 @@
return 0;
}
-#if defined(_WIN32) && !defined(CMAKE_BOOTSTRAP)
- else if (args[1] == "__create_def") {
+#if !defined(CMAKE_BOOTSTRAP)
+ if (args[1] == "__create_def") {
if (args.size() < 4) {
std::cerr << "__create_def Usage: -E __create_def outfile.def "
- "objlistfile [-nm=nm-path]\n";
+ "objlistfile [--nm=nm-path]\n";
return 1;
}
cmsys::ifstream fin(args[3].c_str(), std::ios::in | std::ios::binary);
@@ -612,7 +611,7 @@
return 0;
}
}
- FILE* fout = cmsys::SystemTools::Fopen(args[2].c_str(), "w+");
+ FILE* fout = cmsys::SystemTools::Fopen(args[2], "w+");
if (!fout) {
std::cerr << "could not open output .def file: " << args[2].c_str()
<< "\n";
@@ -1085,7 +1084,7 @@
snapshot.GetDirectory().SetCurrentBinary(startOutDir);
snapshot.GetDirectory().SetCurrentSource(startDir);
cmMakefile mf(ggd, snapshot);
- std::unique_ptr<cmLocalGenerator> lgd(ggd->CreateLocalGenerator(&mf));
+ auto lgd = ggd->CreateLocalGenerator(&mf);
// Actually scan dependencies.
return lgd->UpdateDependencies(depInfo, verbose, color) ? 0 : 2;
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 @@
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 @@
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/CMakeLists.txt b/Tests/CMakeLists.txt
index b45782e..0d9e43f 100644
--- a/Tests/CMakeLists.txt
+++ b/Tests/CMakeLists.txt
@@ -1405,6 +1405,7 @@
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/CMakeLists.txt b/Tests/RunCMake/CMakeLists.txt
index 1b3577f..1e0cb86 100644
--- a/Tests/RunCMake/CMakeLists.txt
+++ b/Tests/RunCMake/CMakeLists.txt
@@ -556,6 +556,7 @@
DEB.MD5SUMS
DEB.DEB_PACKAGE_VERSION_BACK_COMPATIBILITY
DEB.DEB_DESCRIPTION
+ DEB.PROJECT_META
RPM.CUSTOM_BINARY_SPEC_FILE
RPM.CUSTOM_NAMES
@@ -576,6 +577,7 @@
RPM.SUGGESTS
RPM.SYMLINKS
RPM.USER_FILELIST
+ RPM.PROJECT_META
7Z
TBZ2
diff --git a/Tests/RunCMake/CPack/RunCMakeTest.cmake b/Tests/RunCMake/CPack/RunCMakeTest.cmake
index b154c79..76d16e1 100644
--- a/Tests/RunCMake/CPack/RunCMakeTest.cmake
+++ b/Tests/RunCMake/CPack/RunCMakeTest.cmake
@@ -43,3 +43,4 @@
false
"MONOLITHIC;COMPONENT"
)
+run_cpack_test(PROJECT_META "RPM.PROJECT_META;DEB.PROJECT_META" false "MONOLITHIC;COMPONENT")
diff --git a/Tests/RunCMake/CPack/tests/PROJECT_META/ExpectedFiles.cmake b/Tests/RunCMake/CPack/tests/PROJECT_META/ExpectedFiles.cmake
new file mode 100644
index 0000000..448ed2b
--- /dev/null
+++ b/Tests/RunCMake/CPack/tests/PROJECT_META/ExpectedFiles.cmake
@@ -0,0 +1,9 @@
+if(GENERATOR_TYPE STREQUAL DEB)
+ set(EXPECTED_FILE_1 "project_meta-1.2.3*.deb")
+elseif(GENERATOR_TYPE STREQUAL RPM)
+ set(EXPECTED_FILE_1 "project_meta-1.2.3*.rpm")
+else()
+ message(FATAL_ERROR "Unexpected CPack generator")
+endif()
+set(EXPECTED_FILES_COUNT "1")
+set(EXPECTED_FILE_CONTENT_1_LIST "/foo;/foo/CMakeLists.txt")
diff --git a/Tests/RunCMake/CPack/tests/PROJECT_META/VerifyResult.cmake b/Tests/RunCMake/CPack/tests/PROJECT_META/VerifyResult.cmake
new file mode 100644
index 0000000..b3accb5
--- /dev/null
+++ b/Tests/RunCMake/CPack/tests/PROJECT_META/VerifyResult.cmake
@@ -0,0 +1,30 @@
+function(checkPackageURL FILE TAG EXPECTED_URL)
+ getPackageInfo("${FILE}" "_file_info")
+ string(REPLACE "\n" ";" _file_info "${_file_info}")
+
+ set(_seen_url FALSE)
+ foreach(_line IN LISTS _file_info)
+ if(_line MATCHES "${TAG}: (.*)")
+ set(_seen_url TRUE)
+ if(NOT CMAKE_MATCH_1 STREQUAL EXPECTED_URL)
+ message(FATAL_ERROR "Unexpected `Homepage` URL: `${CMAKE_MATCH_1}` != `${EXPECTED_URL}`")
+ endif()
+ break()
+ endif()
+ endforeach()
+ if(NOT _seen_url)
+ message(FATAL_ERROR "The packge `${FILE}` do not have URL as expected")
+ endif()
+endfunction()
+
+if(GENERATOR_TYPE STREQUAL DEB)
+ set(_tag " Homepage") # NOTE The leading space
+elseif(GENERATOR_TYPE STREQUAL RPM)
+ set(_tag "URL.*")
+else()
+ message(FATAL_ERROR "Unexpected CPack generator")
+endif()
+
+checkPackageURL("${FOUND_FILE_1}" "${_tag}" "https://meta.test.info")
+
+# kate: indent-width 2;
diff --git a/Tests/RunCMake/CPack/tests/PROJECT_META/test.cmake b/Tests/RunCMake/CPack/tests/PROJECT_META/test.cmake
new file mode 100644
index 0000000..9c5266a
--- /dev/null
+++ b/Tests/RunCMake/CPack/tests/PROJECT_META/test.cmake
@@ -0,0 +1,11 @@
+project(
+ MetaInfoTest
+ VERSION 1.2.3
+ DESCRIPTION "This is going to be a summary"
+ HOMEPAGE_URL "https://meta.test.info"
+)
+install(FILES CMakeLists.txt DESTINATION foo COMPONENT test)
+
+if(PACKAGING_TYPE STREQUAL "COMPONENT")
+ set(CPACK_COMPONENTS_ALL test)
+endif()
diff --git a/Tests/RunCMake/CTestCommandLine/CMakeLists.txt.in b/Tests/RunCMake/CTestCommandLine/CMakeLists.txt.in
new file mode 100644
index 0000000..5437800
--- /dev/null
+++ b/Tests/RunCMake/CTestCommandLine/CMakeLists.txt.in
@@ -0,0 +1,4 @@
+cmake_minimum_required(VERSION 3.1)
+project(CTestCommandLine@CASE_NAME@ NONE)
+include(CTest)
+add_test(NAME RunCMakeVersion COMMAND "${CMAKE_COMMAND}" --version)
diff --git a/Tests/RunCMake/CTestCommandLine/RunCMakeTest.cmake b/Tests/RunCMake/CTestCommandLine/RunCMakeTest.cmake
index 0953504..b2de596 100644
--- a/Tests/RunCMake/CTestCommandLine/RunCMakeTest.cmake
+++ b/Tests/RunCMake/CTestCommandLine/RunCMakeTest.cmake
@@ -1,4 +1,6 @@
include(RunCMake)
+include(RunCTest)
+
set(RunCMake_TEST_TIMEOUT 60)
unset(ENV{CTEST_PARALLEL_LEVEL})
@@ -311,3 +313,6 @@
run_cmake_command(show-only_json-v1 ${CMAKE_CTEST_COMMAND} --show-only=json-v1)
endfunction()
run_ShowOnly()
+
+# Check the configuration type variable is passed
+run_ctest(check-configuration-type)
diff --git a/Tests/RunCMake/CTestCommandLine/check-configuration-type-stderr.txt b/Tests/RunCMake/CTestCommandLine/check-configuration-type-stderr.txt
new file mode 100644
index 0000000..b2c1a45
--- /dev/null
+++ b/Tests/RunCMake/CTestCommandLine/check-configuration-type-stderr.txt
@@ -0,0 +1,2 @@
+Command line CTEST_CONFIGURATION_TYPE=Debug
+set CTEST_CONFIGURATION_TYPE=Release
diff --git a/Tests/RunCMake/CTestCommandLine/test.cmake.in b/Tests/RunCMake/CTestCommandLine/test.cmake.in
new file mode 100644
index 0000000..b82968a
--- /dev/null
+++ b/Tests/RunCMake/CTestCommandLine/test.cmake.in
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 3.1)
+
+set(CTEST_SITE "test-site")
+set(CTEST_BUILD_NAME "test-build-name")
+set(CTEST_SOURCE_DIRECTORY "@RunCMake_BINARY_DIR@/@CASE_NAME@")
+set(CTEST_BINARY_DIRECTORY "@RunCMake_BINARY_DIR@/@CASE_NAME@-build")
+set(CTEST_CMAKE_GENERATOR "@RunCMake_GENERATOR@")
+set(CTEST_CMAKE_GENERATOR_PLATFORM "@RunCMake_GENERATOR_PLATFORM@")
+set(CTEST_CMAKE_GENERATOR_TOOLSET "@RunCMake_GENERATOR_TOOLSET@")
+set(CTEST_NIGHTLY_START_TIME "01:00:00 UTC")
+set(CTEST_COMMAND "@CMAKE_CTEST_COMMAND@")
+
+if("@CASE_NAME@" MATCHES "^check-configuration-type")
+ message("Command line CTEST_CONFIGURATION_TYPE=" ${CTEST_CONFIGURATION_TYPE})
+ set(CTEST_CONFIGURATION_TYPE "Release")
+ message("set CTEST_CONFIGURATION_TYPE=" ${CTEST_CONFIGURATION_TYPE})
+
+ ctest_start(Experimental)
+endif()
diff --git a/Tests/RunCMake/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 @@
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 @@
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_cmake(PchPrologueEpilogue)
run_test(SkipPrecompileHeaders)
run_test(PchReuseFrom)
+run_test(PchReuseFromPrefixed)
run_test(PchReuseFromSubdir)
run_cmake(PchMultilanguage)
diff --git a/Tests/RunCMake/TargetPolicies/PolicyList-stderr.txt b/Tests/RunCMake/TargetPolicies/PolicyList-stderr.txt
index 6d72fac..9a1e027 100644
--- a/Tests/RunCMake/TargetPolicies/PolicyList-stderr.txt
+++ b/Tests/RunCMake/TargetPolicies/PolicyList-stderr.txt
@@ -28,6 +28,7 @@
\* CMP0081
\* CMP0083
\* CMP0095
+ \* CMP0099
Call Stack \(most recent call first\):
CMakeLists.txt:3 \(include\)
diff --git a/Tests/RunCMake/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 @@
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/Tests/RunCMake/foreach/RunCMakeTest.cmake b/Tests/RunCMake/foreach/RunCMakeTest.cmake
index 0f1fdd4..8f50203 100644
--- a/Tests/RunCMake/foreach/RunCMakeTest.cmake
+++ b/Tests/RunCMake/foreach/RunCMakeTest.cmake
@@ -2,3 +2,13 @@
run_cmake(BadRangeInFunction)
run_cmake(foreach-all-test)
+run_cmake(foreach-ITEMS-multiple-iter-vars-test)
+run_cmake(foreach-LISTS-multiple-iter-vars-test)
+run_cmake(foreach-ZIP_LISTS-test)
+run_cmake(foreach-ITEMS-with-ZIP_LISTS-mix-test)
+run_cmake(foreach-LISTS-with-ZIP_LISTS-mix-test)
+run_cmake(foreach-ZIP_LISTS-with-ITEMS-mix-test)
+run_cmake(foreach-ZIP_LISTS-with-LISTS-mix-test)
+run_cmake(foreach-ZIP_LISTS-multiple-iter-vars-test)
+run_cmake(foreach-ZIP_LISTS-iter-vars-mismatch-test-1)
+run_cmake(foreach-ZIP_LISTS-iter-vars-mismatch-test-2)
diff --git a/Tests/RunCMake/foreach/foreach-ITEMS-multiple-iter-vars-test-result.txt b/Tests/RunCMake/foreach/foreach-ITEMS-multiple-iter-vars-test-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/foreach/foreach-ITEMS-multiple-iter-vars-test-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/foreach/foreach-ITEMS-multiple-iter-vars-test-stderr.txt b/Tests/RunCMake/foreach/foreach-ITEMS-multiple-iter-vars-test-stderr.txt
new file mode 100644
index 0000000..d174bb1
--- /dev/null
+++ b/Tests/RunCMake/foreach/foreach-ITEMS-multiple-iter-vars-test-stderr.txt
@@ -0,0 +1,4 @@
+^CMake Error at foreach-ITEMS-multiple-iter-vars-test.cmake:1 \(foreach\):
+ ITEMS or LISTS require exactly one iteration variable
+Call Stack \(most recent call first\):
+ CMakeLists.txt:3 \(include\)
diff --git a/Tests/RunCMake/foreach/foreach-ITEMS-multiple-iter-vars-test.cmake b/Tests/RunCMake/foreach/foreach-ITEMS-multiple-iter-vars-test.cmake
new file mode 100644
index 0000000..55d33a8
--- /dev/null
+++ b/Tests/RunCMake/foreach/foreach-ITEMS-multiple-iter-vars-test.cmake
@@ -0,0 +1,2 @@
+foreach(one two IN ITEMS one two)
+endforeach()
diff --git a/Tests/RunCMake/foreach/foreach-ITEMS-with-ZIP_LISTS-mix-test-result.txt b/Tests/RunCMake/foreach/foreach-ITEMS-with-ZIP_LISTS-mix-test-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/foreach/foreach-ITEMS-with-ZIP_LISTS-mix-test-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/foreach/foreach-ITEMS-with-ZIP_LISTS-mix-test-stderr.txt b/Tests/RunCMake/foreach/foreach-ITEMS-with-ZIP_LISTS-mix-test-stderr.txt
new file mode 100644
index 0000000..f7d5ae7
--- /dev/null
+++ b/Tests/RunCMake/foreach/foreach-ITEMS-with-ZIP_LISTS-mix-test-stderr.txt
@@ -0,0 +1,4 @@
+^CMake Error at foreach-ITEMS-with-ZIP_LISTS-mix-test.cmake:1 \(foreach\):
+ ZIP_LISTS can not be used with LISTS or ITEMS
+Call Stack \(most recent call first\):
+ CMakeLists.txt:3 \(include\)
diff --git a/Tests/RunCMake/foreach/foreach-ITEMS-with-ZIP_LISTS-mix-test.cmake b/Tests/RunCMake/foreach/foreach-ITEMS-with-ZIP_LISTS-mix-test.cmake
new file mode 100644
index 0000000..28099a0
--- /dev/null
+++ b/Tests/RunCMake/foreach/foreach-ITEMS-with-ZIP_LISTS-mix-test.cmake
@@ -0,0 +1,2 @@
+foreach(i IN ITEMS one two three ZIP_LISTS blah)
+endforeach()
diff --git a/Tests/RunCMake/foreach/foreach-LISTS-multiple-iter-vars-test-result.txt b/Tests/RunCMake/foreach/foreach-LISTS-multiple-iter-vars-test-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/foreach/foreach-LISTS-multiple-iter-vars-test-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/foreach/foreach-LISTS-multiple-iter-vars-test-stderr.txt b/Tests/RunCMake/foreach/foreach-LISTS-multiple-iter-vars-test-stderr.txt
new file mode 100644
index 0000000..f2f83c2
--- /dev/null
+++ b/Tests/RunCMake/foreach/foreach-LISTS-multiple-iter-vars-test-stderr.txt
@@ -0,0 +1,4 @@
+^CMake Error at foreach-LISTS-multiple-iter-vars-test.cmake:1 \(foreach\):
+ ITEMS or LISTS require exactly one iteration variable
+Call Stack \(most recent call first\):
+ CMakeLists.txt:3 \(include\)
diff --git a/Tests/RunCMake/foreach/foreach-LISTS-multiple-iter-vars-test.cmake b/Tests/RunCMake/foreach/foreach-LISTS-multiple-iter-vars-test.cmake
new file mode 100644
index 0000000..78f3847
--- /dev/null
+++ b/Tests/RunCMake/foreach/foreach-LISTS-multiple-iter-vars-test.cmake
@@ -0,0 +1,2 @@
+foreach(one two IN LISTS one two)
+endforeach()
diff --git a/Tests/RunCMake/foreach/foreach-LISTS-with-ZIP_LISTS-mix-test-result.txt b/Tests/RunCMake/foreach/foreach-LISTS-with-ZIP_LISTS-mix-test-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/foreach/foreach-LISTS-with-ZIP_LISTS-mix-test-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/foreach/foreach-LISTS-with-ZIP_LISTS-mix-test-stderr.txt b/Tests/RunCMake/foreach/foreach-LISTS-with-ZIP_LISTS-mix-test-stderr.txt
new file mode 100644
index 0000000..42f8d1e
--- /dev/null
+++ b/Tests/RunCMake/foreach/foreach-LISTS-with-ZIP_LISTS-mix-test-stderr.txt
@@ -0,0 +1,4 @@
+^CMake Error at foreach-LISTS-with-ZIP_LISTS-mix-test.cmake:1 \(foreach\):
+ ZIP_LISTS can not be used with LISTS or ITEMS
+Call Stack \(most recent call first\):
+ CMakeLists.txt:3 \(include\)
diff --git a/Tests/RunCMake/foreach/foreach-LISTS-with-ZIP_LISTS-mix-test.cmake b/Tests/RunCMake/foreach/foreach-LISTS-with-ZIP_LISTS-mix-test.cmake
new file mode 100644
index 0000000..8a919dd
--- /dev/null
+++ b/Tests/RunCMake/foreach/foreach-LISTS-with-ZIP_LISTS-mix-test.cmake
@@ -0,0 +1,2 @@
+foreach(i IN LISTS one two three ZIP_LISTS blah)
+endforeach()
diff --git a/Tests/RunCMake/foreach/foreach-ZIP_LISTS-iter-vars-mismatch-test-1-result.txt b/Tests/RunCMake/foreach/foreach-ZIP_LISTS-iter-vars-mismatch-test-1-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/foreach/foreach-ZIP_LISTS-iter-vars-mismatch-test-1-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/foreach/foreach-ZIP_LISTS-iter-vars-mismatch-test-1-stderr.txt b/Tests/RunCMake/foreach/foreach-ZIP_LISTS-iter-vars-mismatch-test-1-stderr.txt
new file mode 100644
index 0000000..fa51e46
--- /dev/null
+++ b/Tests/RunCMake/foreach/foreach-ZIP_LISTS-iter-vars-mismatch-test-1-stderr.txt
@@ -0,0 +1,4 @@
+^CMake Error at foreach-ZIP_LISTS-iter-vars-mismatch-test-1.cmake:1 \(foreach\):
+ Expected 3 list variables, but given 4
+Call Stack \(most recent call first\):
+ CMakeLists.txt:3 \(include\)
diff --git a/Tests/RunCMake/foreach/foreach-ZIP_LISTS-iter-vars-mismatch-test-1.cmake b/Tests/RunCMake/foreach/foreach-ZIP_LISTS-iter-vars-mismatch-test-1.cmake
new file mode 100644
index 0000000..458b6ca
--- /dev/null
+++ b/Tests/RunCMake/foreach/foreach-ZIP_LISTS-iter-vars-mismatch-test-1.cmake
@@ -0,0 +1,2 @@
+foreach(less than lists IN ZIP_LISTS list_1 list_2 list_3 list_4)
+endforeach()
diff --git a/Tests/RunCMake/foreach/foreach-ZIP_LISTS-iter-vars-mismatch-test-2-result.txt b/Tests/RunCMake/foreach/foreach-ZIP_LISTS-iter-vars-mismatch-test-2-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/foreach/foreach-ZIP_LISTS-iter-vars-mismatch-test-2-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/foreach/foreach-ZIP_LISTS-iter-vars-mismatch-test-2-stderr.txt b/Tests/RunCMake/foreach/foreach-ZIP_LISTS-iter-vars-mismatch-test-2-stderr.txt
new file mode 100644
index 0000000..7b6b484
--- /dev/null
+++ b/Tests/RunCMake/foreach/foreach-ZIP_LISTS-iter-vars-mismatch-test-2-stderr.txt
@@ -0,0 +1,4 @@
+^CMake Error at foreach-ZIP_LISTS-iter-vars-mismatch-test-2.cmake:1 \(foreach\):
+ Expected 3 list variables, but given 2
+Call Stack \(most recent call first\):
+ CMakeLists.txt:3 \(include\)
diff --git a/Tests/RunCMake/foreach/foreach-ZIP_LISTS-iter-vars-mismatch-test-2.cmake b/Tests/RunCMake/foreach/foreach-ZIP_LISTS-iter-vars-mismatch-test-2.cmake
new file mode 100644
index 0000000..d24d99c
--- /dev/null
+++ b/Tests/RunCMake/foreach/foreach-ZIP_LISTS-iter-vars-mismatch-test-2.cmake
@@ -0,0 +1,2 @@
+foreach(greater than lists IN ZIP_LISTS list_1 list_2)
+endforeach()
diff --git a/Tests/RunCMake/foreach/foreach-ZIP_LISTS-multiple-iter-vars-test-stdout.txt b/Tests/RunCMake/foreach/foreach-ZIP_LISTS-multiple-iter-vars-test-stdout.txt
new file mode 100644
index 0000000..e009d15
--- /dev/null
+++ b/Tests/RunCMake/foreach/foreach-ZIP_LISTS-multiple-iter-vars-test-stdout.txt
@@ -0,0 +1,6 @@
+-- foreach\(\.\.\. IN ZIP_LISTS\):
+-- Begin output
+-- | one, satu, raz
+-- | two, dua, dva
+-- | three, tiga, tri
+-- End output
diff --git a/Tests/RunCMake/foreach/foreach-ZIP_LISTS-multiple-iter-vars-test.cmake b/Tests/RunCMake/foreach/foreach-ZIP_LISTS-multiple-iter-vars-test.cmake
new file mode 100644
index 0000000..9647dea
--- /dev/null
+++ b/Tests/RunCMake/foreach/foreach-ZIP_LISTS-multiple-iter-vars-test.cmake
@@ -0,0 +1,42 @@
+function(foreachTest result list_var_1 list_var_2 list_var_3)
+ set(_options MUTE)
+ set(_one_value_args)
+ set(_multi_value_args)
+ cmake_parse_arguments(PARSE_ARGV 3 _arg "${_options}" "${_one_value_args}" "${_multi_value_args}")
+
+ set(_has_any_output FALSE)
+ list(APPEND CMAKE_MESSAGE_INDENT "| ")
+ foreach(first second third IN ZIP_LISTS ${list_var_1} ${list_var_2} ${list_var_3})
+ if(NOT first)
+ set(first "[undefiend]")
+ endif()
+ if(NOT second)
+ set(second "[undefiend]")
+ endif()
+ if(NOT third)
+ set(third "[undefiend]")
+ endif()
+ if(NOT _arg_MUTE)
+ message(STATUS "${first}, ${second}, ${third}")
+ endif()
+ set(_has_any_output TRUE)
+ endforeach()
+ set(${result} ${_has_any_output} PARENT_SCOPE)
+endfunction()
+
+function(foreachTestDecorated list_var_1 list_var_2 list_var_3)
+ list(APPEND CMAKE_MESSAGE_INDENT " ")
+ message(STATUS "Begin output")
+ foreachTest(_has_any_output ${list_var_1} ${list_var_2} ${list_var_3})
+ if(NOT _has_any_output)
+ message(STATUS "--> empty-output <--")
+ endif()
+ message(STATUS "End output")
+endfunction()
+
+list(APPEND english one two three)
+list(APPEND bahasa satu dua tiga)
+list(APPEND russian raz dva tri)
+
+message(STATUS "foreach(... IN ZIP_LISTS):")
+foreachTestDecorated(english bahasa russian)
diff --git a/Tests/RunCMake/foreach/foreach-ZIP_LISTS-test-stdout.txt b/Tests/RunCMake/foreach/foreach-ZIP_LISTS-test-stdout.txt
new file mode 100644
index 0000000..25433fd
--- /dev/null
+++ b/Tests/RunCMake/foreach/foreach-ZIP_LISTS-test-stdout.txt
@@ -0,0 +1,19 @@
+-- foreach\(IN ZIP_LISTS\):
+-- <<< empty lists case >>>
+-- Begin output
+-- --> empty-output <--
+-- End output
+-- <<< same lengths lists case >>>
+-- Begin output
+-- | one, satu, raz
+-- | two, dua, dva
+-- | three, tiga, tri
+-- End output
+-- <<< different lengths lists case >>>
+-- Begin output
+-- | one, satu, raz
+-- | two, dua, dva
+-- | three, tiga, tri
+-- | \[undefiend\], empat, \[undefiend\]
+-- End output
+-- <<< test variable value restored -- PASSED >>>
diff --git a/Tests/RunCMake/foreach/foreach-ZIP_LISTS-test.cmake b/Tests/RunCMake/foreach/foreach-ZIP_LISTS-test.cmake
new file mode 100644
index 0000000..56cfe64
--- /dev/null
+++ b/Tests/RunCMake/foreach/foreach-ZIP_LISTS-test.cmake
@@ -0,0 +1,68 @@
+function(foreachTest result list_var_1 list_var_2 list_var_3)
+ set(_options MUTE)
+ set(_one_value_args)
+ set(_multi_value_args)
+ cmake_parse_arguments(PARSE_ARGV 3 _arg "${_options}" "${_one_value_args}" "${_multi_value_args}")
+
+ set(_has_any_output FALSE)
+ list(APPEND CMAKE_MESSAGE_INDENT "| ")
+ foreach(num IN ZIP_LISTS ${list_var_1} ${list_var_2} ${list_var_3})
+ foreach(i RANGE 2)
+ if(NOT num_${i})
+ set(num_${i} "[undefiend]")
+ endif()
+ endforeach()
+ if(NOT _arg_MUTE)
+ message(STATUS "${num_0}, ${num_1}, ${num_2}")
+ endif()
+ set(_has_any_output TRUE)
+ endforeach()
+ set(${result} ${_has_any_output} PARENT_SCOPE)
+endfunction()
+
+function(foreachTestDecorated list_var_1 list_var_2 list_var_3)
+ list(APPEND CMAKE_MESSAGE_INDENT " ")
+ message(STATUS "Begin output")
+ foreachTest(_has_any_output ${list_var_1} ${list_var_2} ${list_var_3})
+ if(NOT _has_any_output)
+ message(STATUS "--> empty-output <--")
+ endif()
+ message(STATUS "End output")
+endfunction()
+
+message(STATUS "foreach(IN ZIP_LISTS):")
+list(APPEND CMAKE_MESSAGE_INDENT " ")
+
+set(english)
+set(bahasa)
+set(russian)
+
+message(STATUS "<<< empty lists case >>>")
+foreachTestDecorated(english bahasa russian)
+
+list(APPEND english one two three)
+list(APPEND bahasa satu dua tiga)
+list(APPEND russian raz dva tri)
+
+message(STATUS "<<< same lengths lists case >>>")
+foreachTestDecorated(english bahasa russian)
+
+list(APPEND bahasa empat)
+
+message(STATUS "<<< different lengths lists case >>>")
+foreachTestDecorated(english bahasa russian)
+
+set(num_0 "old-0")
+set(num_1 "old-1")
+set(num_2 "old-2")
+foreachTest(_ english bahasa russian MUTE)
+set(check PASSED)
+foreach(i RANGE 2)
+ if(NOT "${num_${i}}" STREQUAL "old-${i}")
+ message(SEND_ERROR "num_${i} value is corrupted")
+ set(check FAILED)
+ endif()
+endforeach()
+message(STATUS "<<< test variable value restored -- ${check} >>>")
+
+list(POP_BACK CMAKE_MESSAGE_INDENT)
diff --git a/Tests/RunCMake/foreach/foreach-ZIP_LISTS-with-ITEMS-mix-test-result.txt b/Tests/RunCMake/foreach/foreach-ZIP_LISTS-with-ITEMS-mix-test-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/foreach/foreach-ZIP_LISTS-with-ITEMS-mix-test-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/foreach/foreach-ZIP_LISTS-with-ITEMS-mix-test-stderr.txt b/Tests/RunCMake/foreach/foreach-ZIP_LISTS-with-ITEMS-mix-test-stderr.txt
new file mode 100644
index 0000000..0dcab01
--- /dev/null
+++ b/Tests/RunCMake/foreach/foreach-ZIP_LISTS-with-ITEMS-mix-test-stderr.txt
@@ -0,0 +1,4 @@
+^CMake Error at foreach-ZIP_LISTS-with-ITEMS-mix-test.cmake:1 \(foreach\):
+ ZIP_LISTS can not be used with LISTS or ITEMS
+Call Stack \(most recent call first\):
+ CMakeLists.txt:3 \(include\)
diff --git a/Tests/RunCMake/foreach/foreach-ZIP_LISTS-with-ITEMS-mix-test.cmake b/Tests/RunCMake/foreach/foreach-ZIP_LISTS-with-ITEMS-mix-test.cmake
new file mode 100644
index 0000000..71ed842
--- /dev/null
+++ b/Tests/RunCMake/foreach/foreach-ZIP_LISTS-with-ITEMS-mix-test.cmake
@@ -0,0 +1,2 @@
+foreach(i IN ZIP_LISTS blah ITEMS blah)
+endforeach()
diff --git a/Tests/RunCMake/foreach/foreach-ZIP_LISTS-with-LISTS-mix-test-result.txt b/Tests/RunCMake/foreach/foreach-ZIP_LISTS-with-LISTS-mix-test-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/foreach/foreach-ZIP_LISTS-with-LISTS-mix-test-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/foreach/foreach-ZIP_LISTS-with-LISTS-mix-test-stderr.txt b/Tests/RunCMake/foreach/foreach-ZIP_LISTS-with-LISTS-mix-test-stderr.txt
new file mode 100644
index 0000000..a6b6e9c
--- /dev/null
+++ b/Tests/RunCMake/foreach/foreach-ZIP_LISTS-with-LISTS-mix-test-stderr.txt
@@ -0,0 +1,4 @@
+^CMake Error at foreach-ZIP_LISTS-with-LISTS-mix-test.cmake:1 \(foreach\):
+ ZIP_LISTS can not be used with LISTS or ITEMS
+Call Stack \(most recent call first\):
+ CMakeLists.txt:3 \(include\)
diff --git a/Tests/RunCMake/foreach/foreach-ZIP_LISTS-with-LISTS-mix-test.cmake b/Tests/RunCMake/foreach/foreach-ZIP_LISTS-with-LISTS-mix-test.cmake
new file mode 100644
index 0000000..11a97b2
--- /dev/null
+++ b/Tests/RunCMake/foreach/foreach-ZIP_LISTS-with-LISTS-mix-test.cmake
@@ -0,0 +1,2 @@
+foreach(i IN ZIP_LISTS blah LISTS blah)
+endforeach()
diff --git a/Tests/RunCMake/target_link_directories/CMP0099-NEW-basic-check.cmake b/Tests/RunCMake/target_link_directories/CMP0099-NEW-basic-check.cmake
new file mode 100644
index 0000000..2fffddd
--- /dev/null
+++ b/Tests/RunCMake/target_link_directories/CMP0099-NEW-basic-check.cmake
@@ -0,0 +1,4 @@
+
+if (NOT actual_stdout MATCHES "DIR_INTERFACE")
+ string (APPEND RunCMake_TEST_FAILED "\nNot found expected 'DIR_INTERFACE'.")
+endif()
diff --git a/Tests/RunCMake/target_link_directories/CMP0099-NEW-basic-result.txt b/Tests/RunCMake/target_link_directories/CMP0099-NEW-basic-result.txt
new file mode 100644
index 0000000..8d98f9d
--- /dev/null
+++ b/Tests/RunCMake/target_link_directories/CMP0099-NEW-basic-result.txt
@@ -0,0 +1 @@
+.*
diff --git a/Tests/RunCMake/target_link_directories/CMP0099-NEW.cmake b/Tests/RunCMake/target_link_directories/CMP0099-NEW.cmake
new file mode 100644
index 0000000..17dd68e
--- /dev/null
+++ b/Tests/RunCMake/target_link_directories/CMP0099-NEW.cmake
@@ -0,0 +1,4 @@
+
+cmake_policy(SET CMP0099 NEW)
+
+include(${CMAKE_CURRENT_SOURCE_DIR}/CMP0099.cmake)
diff --git a/Tests/RunCMake/target_link_directories/CMP0099-OLD-basic-check.cmake b/Tests/RunCMake/target_link_directories/CMP0099-OLD-basic-check.cmake
new file mode 100644
index 0000000..16573a7
--- /dev/null
+++ b/Tests/RunCMake/target_link_directories/CMP0099-OLD-basic-check.cmake
@@ -0,0 +1,4 @@
+
+if (actual_stdout MATCHES "DIR_INTERFACE")
+ string (APPEND RunCMake_TEST_FAILED "\nFound unexpected 'DIR_INTERFACE'.")
+endif()
diff --git a/Tests/RunCMake/target_link_directories/CMP0099-OLD-basic-result.txt b/Tests/RunCMake/target_link_directories/CMP0099-OLD-basic-result.txt
new file mode 100644
index 0000000..8d98f9d
--- /dev/null
+++ b/Tests/RunCMake/target_link_directories/CMP0099-OLD-basic-result.txt
@@ -0,0 +1 @@
+.*
diff --git a/Tests/RunCMake/target_link_directories/CMP0099-OLD.cmake b/Tests/RunCMake/target_link_directories/CMP0099-OLD.cmake
new file mode 100644
index 0000000..193a4c7
--- /dev/null
+++ b/Tests/RunCMake/target_link_directories/CMP0099-OLD.cmake
@@ -0,0 +1,4 @@
+
+cmake_policy(SET CMP0099 OLD)
+
+include(${CMAKE_CURRENT_SOURCE_DIR}/CMP0099.cmake)
diff --git a/Tests/RunCMake/target_link_directories/CMP0099.cmake b/Tests/RunCMake/target_link_directories/CMP0099.cmake
new file mode 100644
index 0000000..a2be279
--- /dev/null
+++ b/Tests/RunCMake/target_link_directories/CMP0099.cmake
@@ -0,0 +1,14 @@
+
+enable_language(C)
+
+set(CMAKE_VERBOSE_MAKEFILE TRUE)
+set(CMAKE_C_USE_RESPONSE_FILE_FOR_LIBRARIES FALSE)
+
+add_library(LinkDirs_interface INTERFACE)
+target_link_directories (LinkDirs_interface INTERFACE "/DIR_INTERFACE"})
+
+add_library(LinkDirs_static STATIC lib.c)
+target_link_libraries (LinkDirs_static PRIVATE LinkDirs_interface)
+
+add_executable(LinkDirs_exe exe.c)
+target_link_libraries (LinkDirs_exe PRIVATE LinkDirs_static)
diff --git a/Tests/RunCMake/target_link_directories/RunCMakeTest.cmake b/Tests/RunCMake/target_link_directories/RunCMakeTest.cmake
index b67c598..a74ee25 100644
--- a/Tests/RunCMake/target_link_directories/RunCMakeTest.cmake
+++ b/Tests/RunCMake/target_link_directories/RunCMakeTest.cmake
@@ -1,3 +1,33 @@
include(RunCMake)
+macro(run_cmake_target test subtest target)
+ set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/${test}-build)
+ set(RunCMake_TEST_NO_CLEAN 1)
+ run_cmake_command(${test}-${subtest} ${CMAKE_COMMAND} --build . --target ${target} ${ARGN})
+
+ unset(RunCMake_TEST_BINARY_DIR)
+ unset(RunCMake_TEST_NO_CLEAN)
+endmacro()
+
run_cmake(empty_keyword_args)
+
+if(RunCMake_GENERATOR MATCHES "(Ninja|Makefiles)" AND
+ NOT RunCMake_GENERATOR MATCHES "(NMake|Borland)")
+ set(RunCMake_TEST_OUTPUT_MERGE TRUE)
+ if (NOT RunCMake_GENERATOR_IS_MULTI_CONFIG)
+ set(RunCMake_TEST_OPTIONS -DCMAKE_BUILD_TYPE=Release)
+ endif()
+ if (RunCMake_GENERATOR MATCHES "Ninja")
+ set(VERBOSE -- -v)
+ endif()
+
+ run_cmake(CMP0099-NEW)
+ run_cmake_target(CMP0099-NEW basic LinkDirs_exe ${VERBOSE})
+
+
+ run_cmake(CMP0099-OLD)
+ run_cmake_target(CMP0099-OLD basic LinkDirs_exe ${VERBOSE})
+
+ unset(RunCMake_TEST_OPTIONS)
+ unset(RunCMake_TEST_OUTPUT_MERGE)
+endif()
diff --git a/Tests/RunCMake/target_link_directories/exe.c b/Tests/RunCMake/target_link_directories/exe.c
new file mode 100644
index 0000000..8488f4e
--- /dev/null
+++ b/Tests/RunCMake/target_link_directories/exe.c
@@ -0,0 +1,4 @@
+int main(void)
+{
+ return 0;
+}
diff --git a/Tests/RunCMake/target_link_directories/lib.c b/Tests/RunCMake/target_link_directories/lib.c
new file mode 100644
index 0000000..9bbd24c
--- /dev/null
+++ b/Tests/RunCMake/target_link_directories/lib.c
@@ -0,0 +1,7 @@
+#if defined(_WIN32)
+__declspec(dllexport)
+#endif
+ int flags_lib(void)
+{
+ return 0;
+}
diff --git a/Tests/RunCMake/target_link_options/CMP0099-NEW-basic-check.cmake b/Tests/RunCMake/target_link_options/CMP0099-NEW-basic-check.cmake
new file mode 100644
index 0000000..555bc37
--- /dev/null
+++ b/Tests/RunCMake/target_link_options/CMP0099-NEW-basic-check.cmake
@@ -0,0 +1,4 @@
+
+if (NOT actual_stdout MATCHES "BADFLAG_INTERFACE")
+ string (APPEND RunCMake_TEST_FAILED "\nNot found expected 'BADFLAG_INTERFACE'.")
+endif()
diff --git a/Tests/RunCMake/target_link_options/CMP0099-NEW-basic-result.txt b/Tests/RunCMake/target_link_options/CMP0099-NEW-basic-result.txt
new file mode 100644
index 0000000..8d98f9d
--- /dev/null
+++ b/Tests/RunCMake/target_link_options/CMP0099-NEW-basic-result.txt
@@ -0,0 +1 @@
+.*
diff --git a/Tests/RunCMake/target_link_options/CMP0099-NEW.cmake b/Tests/RunCMake/target_link_options/CMP0099-NEW.cmake
new file mode 100644
index 0000000..17dd68e
--- /dev/null
+++ b/Tests/RunCMake/target_link_options/CMP0099-NEW.cmake
@@ -0,0 +1,4 @@
+
+cmake_policy(SET CMP0099 NEW)
+
+include(${CMAKE_CURRENT_SOURCE_DIR}/CMP0099.cmake)
diff --git a/Tests/RunCMake/target_link_options/CMP0099-OLD-basic-check.cmake b/Tests/RunCMake/target_link_options/CMP0099-OLD-basic-check.cmake
new file mode 100644
index 0000000..4f159f1
--- /dev/null
+++ b/Tests/RunCMake/target_link_options/CMP0099-OLD-basic-check.cmake
@@ -0,0 +1,4 @@
+
+if (actual_stdout MATCHES "BADFLAG_INTERFACE")
+ string (APPEND RunCMake_TEST_FAILED "\nFound unexpected 'BADFLAG_INTERFACE'.")
+endif()
diff --git a/Tests/RunCMake/target_link_options/CMP0099-OLD-basic-result.txt b/Tests/RunCMake/target_link_options/CMP0099-OLD-basic-result.txt
new file mode 100644
index 0000000..8d98f9d
--- /dev/null
+++ b/Tests/RunCMake/target_link_options/CMP0099-OLD-basic-result.txt
@@ -0,0 +1 @@
+.*
diff --git a/Tests/RunCMake/target_link_options/CMP0099-OLD.cmake b/Tests/RunCMake/target_link_options/CMP0099-OLD.cmake
new file mode 100644
index 0000000..193a4c7
--- /dev/null
+++ b/Tests/RunCMake/target_link_options/CMP0099-OLD.cmake
@@ -0,0 +1,4 @@
+
+cmake_policy(SET CMP0099 OLD)
+
+include(${CMAKE_CURRENT_SOURCE_DIR}/CMP0099.cmake)
diff --git a/Tests/RunCMake/target_link_options/CMP0099.cmake b/Tests/RunCMake/target_link_options/CMP0099.cmake
new file mode 100644
index 0000000..9dee964
--- /dev/null
+++ b/Tests/RunCMake/target_link_options/CMP0099.cmake
@@ -0,0 +1,16 @@
+
+enable_language(C)
+
+set(obj "${CMAKE_C_OUTPUT_EXTENSION}")
+if(BORLAND)
+ set(pre -)
+endif()
+
+add_library(LinkOptions_interface INTERFACE)
+target_link_options (LinkOptions_interface INTERFACE ${pre}BADFLAG_INTERFACE${obj})
+
+add_library(LinkOptions_static STATIC LinkOptionsLib.c)
+target_link_libraries (LinkOptions_static PRIVATE LinkOptions_interface)
+
+add_executable(LinkOptions_exe LinkOptionsExe.c)
+target_link_libraries (LinkOptions_exe PRIVATE LinkOptions_static)
diff --git a/Tests/RunCMake/target_link_options/RunCMakeTest.cmake b/Tests/RunCMake/target_link_options/RunCMakeTest.cmake
index 1d9ef8b..cdfdd7b 100644
--- a/Tests/RunCMake/target_link_options/RunCMakeTest.cmake
+++ b/Tests/RunCMake/target_link_options/RunCMakeTest.cmake
@@ -41,3 +41,21 @@
endif()
run_cmake(empty_keyword_args)
+
+if (NOT CMAKE_C_COMPILER_ID STREQUAL "Intel")
+ # Intel compiler does not reject bad flags or objects!
+ set(RunCMake_TEST_OUTPUT_MERGE TRUE)
+ if (NOT RunCMake_GENERATOR_IS_MULTI_CONFIG)
+ set(RunCMake_TEST_OPTIONS -DCMAKE_BUILD_TYPE=Release)
+ endif()
+
+ run_cmake(CMP0099-NEW)
+ run_cmake_target(CMP0099-NEW basic LinkOptions_exe)
+
+
+ run_cmake(CMP0099-OLD)
+ run_cmake_target(CMP0099-OLD basic LinkOptions_exe)
+
+ unset(RunCMake_TEST_OPTIONS)
+ unset(RunCMake_TEST_OUTPUT_MERGE)
+endif()
diff --git a/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..6e89589 100755
--- a/bootstrap
+++ b/bootstrap
@@ -294,6 +294,7 @@
cmCreateTestSourceList \
cmCustomCommand \
cmCustomCommandGenerator \
+ cmCustomCommandLines \
cmDefinePropertyCommand \
cmDefinitions \
cmDepends \
@@ -436,6 +437,7 @@
cmTargetCompileOptionsCommand \
cmTargetIncludeDirectoriesCommand \
cmTargetLinkLibrariesCommand \
+ cmTargetLinkOptionsCommand \
cmTargetPrecompileHeadersCommand \
cmTargetPropCommandBase \
cmTargetPropertyComputer \