Merge topic 'ghs_generator_bashism_fix'

172475b2c5 GHS: Remove bashism from custom command shell scripts

Acked-by: Kitware Robot <kwrobot@kitware.com>
Merge-request: !6409
diff --git a/Help/cpack_gen/dmg.rst b/Help/cpack_gen/dmg.rst
index 64e9769..1f05618 100644
--- a/Help/cpack_gen/dmg.rst
+++ b/Help/cpack_gen/dmg.rst
@@ -105,6 +105,8 @@
 
 .. variable:: CPACK_DMG_FILESYSTEM
 
+ .. versionadded:: 3.21
+
  The filesystem format. Common values are ``APFS`` and ``HFS+``.
  See ``man hdiutil`` for a full list of supported formats.
  Defaults to ``HFS+``.
diff --git a/Help/manual/cmake-presets.7.rst b/Help/manual/cmake-presets.7.rst
index db26b5a..74e9fae 100644
--- a/Help/manual/cmake-presets.7.rst
+++ b/Help/manual/cmake-presets.7.rst
@@ -187,8 +187,9 @@
   An optional string representing the path to the toolchain file.
   This field supports `macro expansion`_. If a relative path is specified,
   it is calculated relative to the build directory, and if not found,
-  relative to the source directory. Takes precedence over any `CMAKE_TOOLCHAIN_FILE`
-  value. This is allowed in preset files specifying version ``3`` or above.
+  relative to the source directory. This field takes precedence over any
+  :variable:`CMAKE_TOOLCHAIN_FILE` value. It is allowed in preset files
+  specifying version ``3`` or above.
 
 ``binaryDir``
 
diff --git a/Help/release/3.21.rst b/Help/release/3.21.rst
index 3e70552..fc5d6ac 100644
--- a/Help/release/3.21.rst
+++ b/Help/release/3.21.rst
@@ -304,3 +304,9 @@
 
 * The :generator:`Visual Studio 17 2022` generator is now based on
   "Visual Studio 2022 Preview 2".  Previously it was based on "Preview 1.1".
+
+3.21.2
+------
+
+* ``CUDA`` targets with :prop_tgt:`CUDA_SEPARABLE_COMPILATION` enabled are now
+  correctly generated in non-root directories.
diff --git a/Modules/Compiler/NVHPC-C.cmake b/Modules/Compiler/NVHPC-C.cmake
index a734edf..72c2656 100644
--- a/Modules/Compiler/NVHPC-C.cmake
+++ b/Modules/Compiler/NVHPC-C.cmake
@@ -4,9 +4,4 @@
 # Needed so that we support `LANGUAGE` property correctly
 set(CMAKE_C_COMPILE_OPTIONS_EXPLICIT_LANGUAGE -x c)
 
-# Required since as of NVHPC 21.03 the `-MD` flag implicitly
-# implies `-E` and therefore compilation and dependency generation
-# can't occur in the same invocation
-set(CMAKE_C_DEPENDS_EXTRA_COMMANDS "<CMAKE_C_COMPILER> <DEFINES> <INCLUDES> <FLAGS> -x c -M <SOURCE> -MT <OBJECT> -MD<DEP_FILE>")
-
 __compiler_nvhpc(C)
diff --git a/Modules/Compiler/NVHPC-CXX.cmake b/Modules/Compiler/NVHPC-CXX.cmake
index 98d0022..ac75b53 100644
--- a/Modules/Compiler/NVHPC-CXX.cmake
+++ b/Modules/Compiler/NVHPC-CXX.cmake
@@ -4,9 +4,4 @@
 # Needed so that we support `LANGUAGE` property correctly
 set(CMAKE_CXX_COMPILE_OPTIONS_EXPLICIT_LANGUAGE -x c++)
 
-# Required since as of NVHPC 21.03 the `-MD` flag implicitly
-# implies `-E` and therefore compilation and dependency generation
-# can't occur in the same invocation
-set(CMAKE_CXX_DEPENDS_EXTRA_COMMANDS "<CMAKE_CXX_COMPILER> <DEFINES> <INCLUDES> <FLAGS> -x c++ -M <SOURCE> -MT <OBJECT> -MD<DEP_FILE>")
-
 __compiler_nvhpc(CXX)
diff --git a/Modules/Compiler/NVHPC.cmake b/Modules/Compiler/NVHPC.cmake
index 7048670..a85df71 100644
--- a/Modules/Compiler/NVHPC.cmake
+++ b/Modules/Compiler/NVHPC.cmake
@@ -12,4 +12,16 @@
 
 macro(__compiler_nvhpc lang)
   # Logic specific to NVHPC.
+
+  if(CMAKE_${lang}_COMPILER_VERSION VERSION_GREATER_EQUAL 21.07)
+    set(CMAKE_DEPFILE_FLAGS_${lang} "-MD -MT <DEP_TARGET> -MF <DEP_FILE>")
+    set(CMAKE_${lang}_DEPFILE_FORMAT gcc)
+    set(CMAKE_${lang}_DEPENDS_USE_COMPILER TRUE)
+  else()
+    # Before NVHPC 21.07 the `-MD` flag implicitly
+    # implies `-E` and therefore compilation and dependency generation
+    # can't occur in the same invocation
+    set(CMAKE_${lang}_DEPENDS_EXTRA_COMMANDS "<CMAKE_${lang}_COMPILER> <DEFINES> <INCLUDES> <FLAGS> ${CMAKE_${lang}_COMPILE_OPTIONS_EXPLICIT_LANGUAGE} -M <SOURCE> -MT <OBJECT> -MD<DEP_FILE>")
+  endif()
+
 endmacro()
diff --git a/Modules/FindBLAS.cmake b/Modules/FindBLAS.cmake
index 799d179..a44af4d 100644
--- a/Modules/FindBLAS.cmake
+++ b/Modules/FindBLAS.cmake
@@ -109,7 +109,8 @@
 ``Goto``
   GotoBLAS
 
-``IBMESSL``
+``IBMESSL``, ``IBMESSL_SMP``
+
   IBM Engineering and Scientific Subroutine Library
 
 ``Intel``
@@ -150,7 +151,7 @@
 ``PhiPACK``
   Portable High Performance ANSI C (PHiPAC)
 
-``SCSL``
+``SCSL``, ``SCSL_mp``
   Scientific Computing Software Library
 
 ``SGIMATH``
@@ -862,19 +863,27 @@
 endif()
 
 # BLAS in SCSL library?  (SGI/Cray Scientific Library)
-if(BLA_VENDOR STREQUAL "SCSL" OR BLA_VENDOR STREQUAL "All")
+if(BLA_VENDOR MATCHES "SCSL" OR BLA_VENDOR STREQUAL "All")
+  set(_blas_scsl_lib "scs")
+
+  if(BLA_VENDOR MATCHES "_mp")
+    set(_blas_scsl_lib "${_blas_scsl_lib}_mp")
+  endif()
+
   if(NOT BLAS_LIBRARIES)
     check_blas_libraries(
       BLAS_LIBRARIES
       BLAS
       sgemm
       ""
-      "scsl"
+      "${_blas_scsl_lib}"
       ""
       ""
       ""
       )
   endif()
+
+  unset(_blas_scsl_lib)
 endif()
 
 # BLAS in SGIMATH library?
@@ -893,20 +902,27 @@
   endif()
 endif()
 
-# BLAS in IBM ESSL library? (requires generic BLAS lib, too)
-if(BLA_VENDOR STREQUAL "IBMESSL" OR BLA_VENDOR STREQUAL "All")
+# BLAS in IBM ESSL library?
+if(BLA_VENDOR MATCHES "IBMESSL" OR BLA_VENDOR STREQUAL "All")
+  set(_blas_essl_lib "essl")
+
+  if(BLA_VENDOR MATCHES "_SMP")
+    set(_blas_essl_lib "${_blas_essl_lib}smp")
+  endif()
   if(NOT BLAS_LIBRARIES)
     check_blas_libraries(
       BLAS_LIBRARIES
       BLAS
       sgemm
       ""
-      "essl;blas"
+      "${_blas_essl_lib}"
       ""
       ""
       ""
       )
   endif()
+
+  unset(_blas_essl_lib)
 endif()
 
 # BLAS in acml library?
diff --git a/Modules/FindLAPACK.cmake b/Modules/FindLAPACK.cmake
index aa5423a..f36acfd 100644
--- a/Modules/FindLAPACK.cmake
+++ b/Modules/FindLAPACK.cmake
@@ -491,6 +491,30 @@
     )
   endif()
 
+  # LAPACK in SCSL library? (SGI/Cray Scientific Library)
+  if(NOT LAPACK_LIBRARIES
+      AND (BLA_VENDOR MATCHES "SCSL" OR BLA_VENDOR STREQUAL "All"))
+    set(_lapack_scsl_lib "scs")
+
+    # Check for OpenMP support, VIA BLA_VENDOR of scs_mp
+    if(BLA_VENDOR MATCHES "_mp")
+      set(_lapack_scsl_lib "${_lapack_scsl_lib}_mp")
+    endif()
+
+    check_lapack_libraries(
+      LAPACK_LIBRARIES
+      LAPACK
+      cheev
+      ""
+      "${_lapack_scsl_lib}"
+      ""
+      ""
+      ""
+      "${BLAS_LIBRARIES}"
+    )
+    unset(_lapack_scsl_lib)
+  endif()
+
   # BLAS in acml library?
   if(BLA_VENDOR MATCHES "ACML" OR BLA_VENDOR STREQUAL "All")
     if(BLAS_LIBRARIES MATCHES ".+acml.+")
@@ -586,6 +610,30 @@
     unset(_ssl2_suffix)
   endif()
 
+  # LAPACK in IBM ESSL library?
+  if(NOT LAPACK_LIBRARIES
+      AND (BLA_VENDOR MATCHES "IBMESSL" OR BLA_VENDOR STREQUAL "All"))
+    set(_lapack_essl_lib "essl")
+
+    # Check for OpenMP support, VIA BLA_VENDOR of esslsmp
+    if(BLA_VENDOR MATCHES "_SMP")
+      set(_lapack_essl_lib "${_lapack_essl_lib}smp")
+    endif()
+
+    check_lapack_libraries(
+      LAPACK_LIBRARIES
+      LAPACK
+      cheev
+      ""
+      "${_lapack_essl_lib}"
+      ""
+      ""
+      ""
+      "${BLAS_LIBRARIES}"
+    )
+    unset(_lapack_essl_lib)
+  endif()
+
   # NVHPC Library?
   if(NOT LAPACK_LIBRARIES
       AND (BLA_VENDOR MATCHES "NVHPC" OR BLA_VENDOR STREQUAL "All"))
diff --git a/Modules/Platform/Haiku.cmake b/Modules/Platform/Haiku.cmake
index 7e0af61..b8e3ba6 100644
--- a/Modules/Platform/Haiku.cmake
+++ b/Modules/Platform/Haiku.cmake
@@ -1,8 +1,3 @@
-# process only once
-if(HAIKU)
-  return()
-endif()
-
 set(HAIKU 1)
 set(UNIX 1)
 
diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake
index 3a96d7e..2b24fba 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 21)
-set(CMake_VERSION_PATCH 20210728)
+set(CMake_VERSION_PATCH 20210802)
 #set(CMake_VERSION_RC 0)
 set(CMake_VERSION_IS_DIRTY 0)
 
diff --git a/Source/CTest/cmCTestGenericHandler.cxx b/Source/CTest/cmCTestGenericHandler.cxx
index cc756d7..48cc0e4 100644
--- a/Source/CTest/cmCTestGenericHandler.cxx
+++ b/Source/CTest/cmCTestGenericHandler.cxx
@@ -68,10 +68,8 @@
 {
   this->AppendXML = false;
   this->TestLoad = 0;
-  this->Options.clear();
-  for (auto const& po : this->PersistentOptions) {
-    this->Options[po.first] = po.second;
-  }
+  this->Options = this->PersistentOptions;
+  this->MultiOptions = this->PersistentMultiOptions;
 }
 
 const char* cmCTestGenericHandler::GetOption(const std::string& op)
diff --git a/Source/cmMakefileTargetGenerator.cxx b/Source/cmMakefileTargetGenerator.cxx
index d6145f8..6af2684 100644
--- a/Source/cmMakefileTargetGenerator.cxx
+++ b/Source/cmMakefileTargetGenerator.cxx
@@ -1491,14 +1491,18 @@
   }
 
   std::vector<std::string> architectures = cmExpandedList(architecturesStr);
+  std::string const& relPath =
+    this->LocalGenerator->GetHomeRelativeOutputPath();
 
   // Ensure there are no duplicates.
   const std::vector<std::string> linkDeps = [&]() -> std::vector<std::string> {
     std::vector<std::string> deps;
     this->AppendTargetDepends(deps, true);
     this->GeneratorTarget->GetLinkDepends(deps, this->GetConfigName(), "CUDA");
-    std::copy(this->Objects.begin(), this->Objects.end(),
-              std::back_inserter(deps));
+
+    for (std::string const& obj : this->Objects) {
+      deps.emplace_back(cmStrCat(relPath, obj));
+    }
 
     std::unordered_set<std::string> depsSet(deps.begin(), deps.end());
     deps.clear();
@@ -1517,33 +1521,34 @@
 
   std::string profiles;
   std::vector<std::string> fatbinaryDepends;
-  std::string registerFile = cmStrCat(objectDir, "cmake_cuda_register.h");
+  std::string const registerFile =
+    cmStrCat(objectDir, "cmake_cuda_register.h");
 
   // Link device code for each architecture.
   for (const std::string& architectureKind : architectures) {
-    // Clang always generates real code, so strip the specifier.
-    const std::string architecture =
-      architectureKind.substr(0, architectureKind.find('-'));
-    const std::string cubin =
-      cmStrCat(relObjectDir, "sm_", architecture, ".cubin");
-
-    profiles += cmStrCat(" -im=profile=sm_", architecture, ",file=", cubin);
-    fatbinaryDepends.emplace_back(cubin);
-
     std::string registerFileCmd;
 
     // The generated register file contains macros that when expanded
     // register the device routines. Because the routines are the same for
     // all architectures the register file will be the same too. Thus
     // generate it only on the first invocation to reduce overhead.
-    if (fatbinaryDepends.size() == 1) {
-      std::string registerFileRel =
-        this->LocalGenerator->MaybeRelativeToCurBinDir(registerFile);
+    if (fatbinaryDepends.empty()) {
+      std::string const registerFileRel =
+        cmStrCat(relPath, relObjectDir, "cmake_cuda_register.h");
       registerFileCmd =
         cmStrCat(" --register-link-binaries=", registerFileRel);
       cleanFiles.push_back(registerFileRel);
     }
 
+    // Clang always generates real code, so strip the specifier.
+    const std::string architecture =
+      architectureKind.substr(0, architectureKind.find('-'));
+    const std::string cubin =
+      cmStrCat(objectDir, "sm_", architecture, ".cubin");
+
+    profiles += cmStrCat(" -im=profile=sm_", architecture, ",file=", cubin);
+    fatbinaryDepends.emplace_back(cubin);
+
     std::string command = cmStrCat(
       this->Makefile->GetRequiredDefinition("CMAKE_CUDA_DEVICE_LINKER"),
       " -arch=sm_", architecture, registerFileCmd, " -o=$@ ",
@@ -1562,7 +1567,7 @@
   const std::string fatbinaryOutput =
     cmStrCat(objectDir, "cmake_cuda_fatbin.h");
   const std::string fatbinaryOutputRel =
-    this->LocalGenerator->MaybeRelativeToCurBinDir(fatbinaryOutput);
+    cmStrCat(relPath, relObjectDir, "cmake_cuda_fatbin.h");
 
   this->LocalGenerator->WriteMakeRule(*this->BuildFileStream, nullptr,
                                       fatbinaryOutputRel, fatbinaryDepends,
@@ -1590,9 +1595,8 @@
                                                compileCmd, vars);
 
   commands.emplace_back(compileCmd);
-  this->LocalGenerator->WriteMakeRule(
-    *this->BuildFileStream, nullptr, output,
-    { cmStrCat(relObjectDir, "cmake_cuda_fatbin.h") }, commands, false);
+  this->LocalGenerator->WriteMakeRule(*this->BuildFileStream, nullptr, output,
+                                      { fatbinaryOutputRel }, commands, false);
 
   // Clean all the possible executable names and symlinks.
   this->CleanFiles.insert(cleanFiles.begin(), cleanFiles.end());
diff --git a/Source/cmNinjaNormalTargetGenerator.cxx b/Source/cmNinjaNormalTargetGenerator.cxx
index 93a54c2..96e9142 100644
--- a/Source/cmNinjaNormalTargetGenerator.cxx
+++ b/Source/cmNinjaNormalTargetGenerator.cxx
@@ -759,10 +759,6 @@
     const std::string cubin =
       cmStrCat(ninjaOutputDir, "/sm_", architecture, ".cubin");
 
-    fatbinary.Variables["PROFILES"] +=
-      cmStrCat(" -im=profile=sm_", architecture, ",file=", cubin);
-    fatbinary.ExplicitDeps.emplace_back(cubin);
-
     cmNinjaBuild dlink(this->LanguageLinkerCudaDeviceRule(config));
     dlink.ExplicitDeps = explicitDeps;
     dlink.Outputs = { cubin };
@@ -772,11 +768,15 @@
     // the device routines. Because the routines are the same for all
     // architectures the register file will be the same too. Thus generate it
     // only on the first invocation to reduce overhead.
-    if (fatbinary.ExplicitDeps.size() == 1) {
+    if (fatbinary.ExplicitDeps.empty()) {
       dlink.Variables["REGISTER"] = cmStrCat(
         "--register-link-binaries=", ninjaOutputDir, "/cmake_cuda_register.h");
     }
 
+    fatbinary.Variables["PROFILES"] +=
+      cmStrCat(" -im=profile=sm_", architecture, ",file=", cubin);
+    fatbinary.ExplicitDeps.emplace_back(cubin);
+
     this->GetGlobalGenerator()->WriteBuild(this->GetCommonFileStream(), dlink);
   }
 
diff --git a/Source/cmStandardLevelResolver.cxx b/Source/cmStandardLevelResolver.cxx
index 74b9d6f..da36ed6 100644
--- a/Source/cmStandardLevelResolver.cxx
+++ b/Source/cmStandardLevelResolver.cxx
@@ -57,10 +57,10 @@
   return -1;
 }
 
-struct StanardLevelComputer
+struct StandardLevelComputer
 {
-  explicit StanardLevelComputer(std::string lang, std::vector<int> levels,
-                                std::vector<std::string> levelsStr)
+  explicit StandardLevelComputer(std::string lang, std::vector<int> levels,
+                                 std::vector<std::string> levelsStr)
     : Language(std::move(lang))
     , Levels(std::move(levels))
     , LevelsAsStrings(std::move(levelsStr))
@@ -308,31 +308,33 @@
   std::vector<std::string> LevelsAsStrings;
 };
 
-std::unordered_map<std::string, StanardLevelComputer> StandardComputerMapping =
-  { { "C",
-      StanardLevelComputer{
+std::unordered_map<std::string, StandardLevelComputer>
+  StandardComputerMapping = {
+    { "C",
+      StandardLevelComputer{
         "C", std::vector<int>{ 90, 99, 11, 17, 23 },
         std::vector<std::string>{ "90", "99", "11", "17", "23" } } },
     { "CXX",
-      StanardLevelComputer{
+      StandardLevelComputer{
         "CXX", std::vector<int>{ 98, 11, 14, 17, 20, 23 },
         std::vector<std::string>{ "98", "11", "14", "17", "20", "23" } } },
     { "CUDA",
-      StanardLevelComputer{
+      StandardLevelComputer{
         "CUDA", std::vector<int>{ 03, 11, 14, 17, 20, 23 },
         std::vector<std::string>{ "03", "11", "14", "17", "20", "23" } } },
     { "OBJC",
-      StanardLevelComputer{
+      StandardLevelComputer{
         "OBJC", std::vector<int>{ 90, 99, 11, 17, 23 },
         std::vector<std::string>{ "90", "99", "11", "17", "23" } } },
     { "OBJCXX",
-      StanardLevelComputer{
+      StandardLevelComputer{
         "OBJCXX", std::vector<int>{ 98, 11, 14, 17, 20, 23 },
         std::vector<std::string>{ "98", "11", "14", "17", "20", "23" } } },
     { "HIP",
-      StanardLevelComputer{
+      StandardLevelComputer{
         "HIP", std::vector<int>{ 98, 11, 14, 17, 20, 23 },
-        std::vector<std::string>{ "98", "11", "14", "17", "20", "23" } } } };
+        std::vector<std::string>{ "98", "11", "14", "17", "20", "23" } } }
+  };
 }
 
 std::string cmStandardLevelResolver::GetCompileOptionDef(
diff --git a/Source/cmVisualStudio10TargetGenerator.cxx b/Source/cmVisualStudio10TargetGenerator.cxx
index 82880a9..065601b 100644
--- a/Source/cmVisualStudio10TargetGenerator.cxx
+++ b/Source/cmVisualStudio10TargetGenerator.cxx
@@ -4091,6 +4091,9 @@
   if (this->ProjectType == csproj) {
     return;
   }
+  if (this->GeneratorTarget->GetType() > cmStateEnums::UTILITY) {
+    return;
+  }
 
   // This processes *any* of the .idl files specified in the project's file
   // list (and passed as the item metadata %(Filename) expressing the rule
diff --git a/Tests/CudaOnly/CMakeLists.txt b/Tests/CudaOnly/CMakeLists.txt
index fdb7a6e..a3fb409 100644
--- a/Tests/CudaOnly/CMakeLists.txt
+++ b/Tests/CudaOnly/CMakeLists.txt
@@ -15,7 +15,7 @@
 add_cuda_test_macro(CudaOnly.WithDefs CudaOnlyWithDefs)
 add_cuda_test_macro(CudaOnly.CircularLinkLine CudaOnlyCircularLinkLine)
 add_cuda_test_macro(CudaOnly.ResolveDeviceSymbols CudaOnlyResolveDeviceSymbols)
-add_cuda_test_macro(CudaOnly.SeparateCompilation CudaOnlySeparateCompilation)
+add_cuda_test_macro(CudaOnly.SeparateCompilation main/CudaOnlySeparateCompilation)
 
 if(CMake_TEST_CUDA AND NOT CMake_TEST_CUDA STREQUAL "Clang")
   # Clang doesn't have flags for selecting the runtime.
diff --git a/Tests/CudaOnly/SeparateCompilation/CMakeLists.txt b/Tests/CudaOnly/SeparateCompilation/CMakeLists.txt
index 864ecbf..17069e3 100644
--- a/Tests/CudaOnly/SeparateCompilation/CMakeLists.txt
+++ b/Tests/CudaOnly/SeparateCompilation/CMakeLists.txt
@@ -34,26 +34,9 @@
 target_compile_features(CUDASeparateLibB PRIVATE cuda_std_11)
 target_link_libraries(CUDASeparateLibB PRIVATE CUDASeparateLibA)
 
-add_executable(CudaOnlySeparateCompilation main.cu)
-target_link_libraries(CudaOnlySeparateCompilation
-                      PRIVATE CUDASeparateLibB)
-set_target_properties(CudaOnlySeparateCompilation PROPERTIES CUDA_STANDARD 11)
-set_target_properties(CudaOnlySeparateCompilation PROPERTIES CUDA_STANDARD_REQUIRED TRUE)
-
 set_target_properties(CUDASeparateLibA
                       CUDASeparateLibB
                       PROPERTIES CUDA_SEPARABLE_COMPILATION ON
                       POSITION_INDEPENDENT_CODE ON)
 
-if (CMAKE_GENERATOR MATCHES "^Visual Studio")
-  #Visual Studio CUDA integration will not perform device linking
-  #on a target that itself does not have GenerateRelocatableDeviceCode
-  #enabled.
-  set_target_properties(CudaOnlySeparateCompilation
-                        PROPERTIES CUDA_SEPARABLE_COMPILATION ON)
-endif()
-
-if(APPLE)
-  # Help the static cuda runtime find the driver (libcuda.dyllib) at runtime.
-  set_property(TARGET CudaOnlySeparateCompilation PROPERTY BUILD_RPATH ${CMAKE_CUDA_IMPLICIT_LINK_DIRECTORIES})
-endif()
+add_subdirectory(main)
diff --git a/Tests/CudaOnly/SeparateCompilation/main/CMakeLists.txt b/Tests/CudaOnly/SeparateCompilation/main/CMakeLists.txt
new file mode 100644
index 0000000..c181078
--- /dev/null
+++ b/Tests/CudaOnly/SeparateCompilation/main/CMakeLists.txt
@@ -0,0 +1,18 @@
+add_executable(CudaOnlySeparateCompilation main.cu)
+target_link_libraries(CudaOnlySeparateCompilation PRIVATE CUDASeparateLibB)
+set_target_properties(CudaOnlySeparateCompilation PROPERTIES
+  CUDA_STANDARD 11
+  CUDA_STANDARD_REQUIRED TRUE
+)
+
+if(CMAKE_GENERATOR MATCHES "^Visual Studio")
+  # Visual Studio CUDA integration will not perform device linking
+  # on a target that itself does not have GenerateRelocatableDeviceCode
+  # enabled.
+  set_property(TARGET CudaOnlySeparateCompilation PROPERTY CUDA_SEPARABLE_COMPILATION ON)
+endif()
+
+if(APPLE)
+  # Help the static cuda runtime find the driver (libcuda.dyllib) at runtime.
+  set_property(TARGET CudaOnlySeparateCompilation PROPERTY BUILD_RPATH ${CMAKE_CUDA_IMPLICIT_LINK_DIRECTORIES})
+endif()
diff --git a/Tests/CudaOnly/SeparateCompilation/main.cu b/Tests/CudaOnly/SeparateCompilation/main/main.cu
similarity index 96%
rename from Tests/CudaOnly/SeparateCompilation/main.cu
rename to Tests/CudaOnly/SeparateCompilation/main/main.cu
index 40dbe5d..2b6e8f4 100644
--- a/Tests/CudaOnly/SeparateCompilation/main.cu
+++ b/Tests/CudaOnly/SeparateCompilation/main/main.cu
@@ -1,8 +1,8 @@
 
 #include <iostream>
 
-#include "file1.h"
-#include "file2.h"
+#include "../file1.h"
+#include "../file2.h"
 
 int file4_launch_kernel(int x);
 int file5_launch_kernel(int x);
diff --git a/Tests/QtAutogen/RerunUicOnFileChange/CMakeLists.txt b/Tests/QtAutogen/RerunUicOnFileChange/CMakeLists.txt
index a9ccece..a3ba9fb 100644
--- a/Tests/QtAutogen/RerunUicOnFileChange/CMakeLists.txt
+++ b/Tests/QtAutogen/RerunUicOnFileChange/CMakeLists.txt
@@ -26,6 +26,7 @@
 endmacro()
 
 configure_file("${testProjectTemplateDir}/mocwidget.h" "${testProjectSrc}/mocwidget.h" COPYONLY)
+configure_file("${testProjectTemplateDir}/mainwindow.h" "${testProjectSrc}/mainwindow.h" COPYONLY)
 configure_file("${testProjectTemplateDir}/main.cpp" "${testProjectSrc}/main.cpp" COPYONLY)
 configure_file("${testProjectTemplateDir}/subdir/subdircheck.cpp" "${testProjectSrc}/subdir/subdircheck.cpp" COPYONLY)
 configure_file("${testProjectTemplateDir}/CMakeLists.txt.in" "${testProjectSrc}/CMakeLists.txt" @ONLY)
@@ -103,3 +104,15 @@
 if(NOT result EQUAL "0")
   message(FATAL_ERROR "Rebuild of UicOnFileChange test result is: ${result}")
 endif()
+
+# Check if the generated ui_mainwindow.h rules introduce circular dependency between the generated
+# ui_mainwinow.h and timestamp.
+#
+# The first rebuild updates a timestamp dependency file after "touching" mainwindow.h.
+sleep()
+execute_process(COMMAND ${CMAKE_COMMAND} -E touch "${testProjectSrc}/mainwindow.h")
+rebuild(3)
+
+# The second rebuild detects if cycling dependency is introduced by deps file.
+sleep()
+rebuild(4)
diff --git a/Tests/QtAutogen/RerunUicOnFileChange/UicOnFileChange/CMakeLists.txt.in b/Tests/QtAutogen/RerunUicOnFileChange/UicOnFileChange/CMakeLists.txt.in
index 2a1998d..c77075c 100644
--- a/Tests/QtAutogen/RerunUicOnFileChange/UicOnFileChange/CMakeLists.txt.in
+++ b/Tests/QtAutogen/RerunUicOnFileChange/UicOnFileChange/CMakeLists.txt.in
@@ -5,9 +5,13 @@
 
 # Enable CMAKE_AUTOUIC for all targets
 set(CMAKE_AUTOUIC ON)
+set(CMAKE_AUTOMOC ON)
 
-add_executable(UicOnFileChange main.cpp mainwindow.ui
+add_executable(UicOnFileChange main.cpp mainwindow.ui mainwindow.h
     subdir/subdircheck.cpp subdir/mainwindowsubdir.ui
 )
-target_include_directories(UicOnFileChange PRIVATE ${CMAKE_CURRENT_SOURCE_DIR})
+target_include_directories(UicOnFileChange PRIVATE
+    "${CMAKE_CURRENT_SOURCE_DIR}"
+    "${CMAKE_CURRENT_BINARY_DIR}/UicOnFileChange_autogen/include"
+)
 target_link_libraries(UicOnFileChange ${QT_QTCORE_TARGET} ${QT_LIBRARIES})
diff --git a/Tests/QtAutogen/RerunUicOnFileChange/UicOnFileChange/main.cpp b/Tests/QtAutogen/RerunUicOnFileChange/UicOnFileChange/main.cpp
index 3981268..99de13d 100644
--- a/Tests/QtAutogen/RerunUicOnFileChange/UicOnFileChange/main.cpp
+++ b/Tests/QtAutogen/RerunUicOnFileChange/UicOnFileChange/main.cpp
@@ -1,3 +1,4 @@
+#include "mainwindow.h"
 #include "ui_mainwindow.h"
 
 extern bool subdircheck();
diff --git a/Tests/QtAutogen/RerunUicOnFileChange/UicOnFileChange/mainwindow.h b/Tests/QtAutogen/RerunUicOnFileChange/UicOnFileChange/mainwindow.h
new file mode 100644
index 0000000..24621ff
--- /dev/null
+++ b/Tests/QtAutogen/RerunUicOnFileChange/UicOnFileChange/mainwindow.h
@@ -0,0 +1,13 @@
+#include <QObject>
+
+#include "ui_mainwindow.h"
+
+class MainWindow : public QObject
+{
+  Q_OBJECT
+public:
+  MainWindow() { mwUi.setupUi(&mw); }
+
+  MocWidget mw;
+  Ui::Widget mwUi;
+};
diff --git a/Tests/RunCMake/InterfaceLibrary/IncludeDirectories.cmake b/Tests/RunCMake/InterfaceLibrary/IncludeDirectories.cmake
new file mode 100644
index 0000000..b94eac0
--- /dev/null
+++ b/Tests/RunCMake/InterfaceLibrary/IncludeDirectories.cmake
@@ -0,0 +1,7 @@
+cmake_policy(SET CMP0076 NEW)
+include_directories(Inc1 Inc2)
+add_library(iface INTERFACE)
+target_sources(iface PRIVATE iface.c)
+# Ensure the INCLUDE_DIRECTORIES property is populated.
+# Since interface libraries do not actually compile anything, this should be ignored.
+set_property(TARGET iface APPEND PROPERTY INCLUDE_DIRECTORIES ${CMAKE_CURRENT_SOURCE_DIR}/Inc3 ${CMAKE_CURRENT_SOURCE_DIR}/Inc4)
diff --git a/Tests/RunCMake/InterfaceLibrary/RunCMakeTest.cmake b/Tests/RunCMake/InterfaceLibrary/RunCMakeTest.cmake
index 834b3c8..10a2d51 100644
--- a/Tests/RunCMake/InterfaceLibrary/RunCMakeTest.cmake
+++ b/Tests/RunCMake/InterfaceLibrary/RunCMakeTest.cmake
@@ -34,3 +34,4 @@
 run_WithSources(EmptySources "build1:iface" "build2:iface2,merge")
 run_WithSources(ExcludeFromAll "build1" "build2:iface" "build3:iface2,merge")
 run_WithSources(PublicSources "build1" "build2:iface" "build3:iface2,merge")
+run_WithSources(IncludeDirectories "build1:iface")
diff --git a/Tests/RunCMake/ctest_test/RunCMakeTest.cmake b/Tests/RunCMake/ctest_test/RunCMakeTest.cmake
index a211c66..de81049 100644
--- a/Tests/RunCMake/ctest_test/RunCMakeTest.cmake
+++ b/Tests/RunCMake/ctest_test/RunCMakeTest.cmake
@@ -194,6 +194,19 @@
 endfunction()
 run_completion_status()
 
+# Verify that running ctest_test() multiple times with different label arguments
+# doesn't break.
+function(run_changing_labels)
+  set(CASE_CMAKELISTS_SUFFIX_CODE [[
+add_test(NAME a COMMAND ${CMAKE_COMMAND} -E true)
+set_property(TEST a PROPERTY LABELS a)
+add_test(NAME b COMMAND ${CMAKE_COMMAND} -E true)
+set_property(TEST b PROPERTY LABELS b)
+  ]])
+  run_ctest(TestChangingLabels)
+endfunction()
+run_changing_labels()
+
 # Verify that test output can add additional labels
 function(run_extra_labels)
   set(CASE_CMAKELISTS_SUFFIX_CODE [[
diff --git a/Tests/RunCMake/ctest_test/test.cmake.in b/Tests/RunCMake/ctest_test/test.cmake.in
index 50b936d..36b1dbd 100644
--- a/Tests/RunCMake/ctest_test/test.cmake.in
+++ b/Tests/RunCMake/ctest_test/test.cmake.in
@@ -15,4 +15,9 @@
 ctest_start(Experimental)
 ctest_configure()
 ctest_build()
-ctest_test(${ctest_test_args})
+if("@CASE_NAME@" STREQUAL "TestChangingLabels")
+  ctest_test(${ctest_test_args} INCLUDE_LABEL "^a$")
+  ctest_test(${ctest_test_args} INCLUDE_LABEL "^b$")
+else()
+  ctest_test(${ctest_test_args})
+endif()