Merge topic 'ctest-num-width'

6d28884617 cmCTestRunTest: Avoid float/int conversions in number width logic

Acked-by: Kitware Robot <kwrobot@kitware.com>
Merge-request: !2433
diff --git a/Help/command/install.rst b/Help/command/install.rst
index 3a2b4da..08c5718 100644
--- a/Help/command/install.rst
+++ b/Help/command/install.rst
@@ -89,6 +89,13 @@
 installation.  Use the :variable:`CMAKE_INSTALL_MESSAGE` variable
 to control which messages are printed.
 
+Many of the ``install()`` variants implicitly create the directories
+containing the installed files. If
+:variable:`CMAKE_INSTALL_DEFAULT_DIRECTORY_PERMISSIONS` is set, these
+directories will be created with the permissions specified. Otherwise,
+they will be created according to the uname rules on Unix-like platforms.
+Windows platforms are unaffected.
+
 Installing Targets
 ^^^^^^^^^^^^^^^^^^
 
diff --git a/Help/release/dev/byproducts_make_clean.rst b/Help/release/dev/byproducts_make_clean.rst
new file mode 100644
index 0000000..54df77d
--- /dev/null
+++ b/Help/release/dev/byproducts_make_clean.rst
@@ -0,0 +1,5 @@
+byproducts_make_clean
+---------------------
+
+* The :ref:`Makefile Generators` learned to remove custom command and
+  custom target byproducts during ``make clean``.
diff --git a/Modules/FindJNI.cmake b/Modules/FindJNI.cmake
index 4913e05..fdddcc7 100644
--- a/Modules/FindJNI.cmake
+++ b/Modules/FindJNI.cmake
@@ -1,29 +1,49 @@
 # Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
 # file Copyright.txt or https://cmake.org/licensing for details.
 
-#.rst:
-# FindJNI
-# -------
-#
-# Find JNI java libraries.
-#
-# This module finds if Java is installed and determines where the
-# include files and libraries are.  It also determines what the name of
-# the library is.  The caller may set variable JAVA_HOME to specify a
-# Java installation prefix explicitly.
-#
-# This module sets the following result variables:
-#
-# ::
-#
-#   JNI_INCLUDE_DIRS      = the include dirs to use
-#   JNI_LIBRARIES         = the libraries to use
-#   JNI_FOUND             = TRUE if JNI headers and libraries were found.
-#   JAVA_AWT_LIBRARY      = the path to the jawt library
-#   JAVA_JVM_LIBRARY      = the path to the jvm library
-#   JAVA_INCLUDE_PATH     = the include path to jni.h
-#   JAVA_INCLUDE_PATH2    = the include path to jni_md.h
-#   JAVA_AWT_INCLUDE_PATH = the include path to jawt.h
+#[=======================================================================[.rst:
+FindJNI
+-------
+
+Find Java Native Interface (JNI) libraries.
+
+JNI enables Java code running in a Java Virtual Machine (JVM) to call
+and be called by native applications and libraries written in other
+languages such as C, C++.
+
+This module finds if Java is installed and determines where the
+include files and libraries are.  It also determines what the name of
+the library is.  The caller may set variable ``JAVA_HOME`` to specify a
+Java installation prefix explicitly.
+
+Result Variables
+^^^^^^^^^^^^^^^^
+
+This module sets the following result variables:
+
+``JNI_INCLUDE_DIRS``
+  the include dirs to use
+``JNI_LIBRARIES``
+  the libraries to use (JAWT and JVM)
+``JNI_FOUND``
+  TRUE if JNI headers and libraries were found.
+
+Cache Variables
+^^^^^^^^^^^^^^^
+
+The following cache variables are also available to set or use:
+
+``JAVA_AWT_LIBRARY``
+  the path to the Java AWT Native Interface (JAWT) library
+``JAVA_JVM_LIBRARY``
+  the path to the Java Virtual Machine (JVM) library
+``JAVA_INCLUDE_PATH``
+  the include path to jni.h
+``JAVA_INCLUDE_PATH2``
+  the include path to jni_md.h and jniport.h
+``JAVA_AWT_INCLUDE_PATH``
+  the include path to jawt.h
+#]=======================================================================]
 
 # Expand {libarch} occurrences to java_libarch subdirectory(-ies) and set ${_var}
 macro(java_append_library_directories _var)
@@ -187,6 +207,7 @@
   /usr/lib/jvm/default/jre/lib/{libarch}
   /usr/lib/jvm/default/lib/{libarch}
   # Ubuntu specific paths for default JVM
+  /usr/lib/jvm/java-11-openjdk-{libarch}/jre/lib/{libarch}    # Ubuntu 18.04 LTS
   /usr/lib/jvm/java-8-openjdk-{libarch}/jre/lib/{libarch}     # Ubuntu 15.10
   /usr/lib/jvm/java-7-openjdk-{libarch}/jre/lib/{libarch}     # Ubuntu 15.10
   /usr/lib/jvm/java-6-openjdk-{libarch}/jre/lib/{libarch}     # Ubuntu 15.10
diff --git a/Modules/FindJava.cmake b/Modules/FindJava.cmake
index cddc5d2..bcdf166 100644
--- a/Modules/FindJava.cmake
+++ b/Modules/FindJava.cmake
@@ -8,19 +8,19 @@
 # Find Java
 #
 # This module finds if Java is installed and determines where the
-# include files and libraries are.  The caller may set variable JAVA_HOME
+# include files and libraries are.  The caller may set variable ``JAVA_HOME``
 # to specify a Java installation prefix explicitly.
 #
-# See also the :module:`FindJNI` module to find Java development tools.
+# See also the :module:`FindJNI` module to find Java Native Interface (JNI).
 #
 # Specify one or more of the following components as you call this find module. See example below.
 #
 # ::
 #
-#   Runtime     = User just want to execute some Java byte-compiled
+#   Runtime     = Java Runtime Environment used to execute Java byte-compiled applications
 #   Development = Development tools (java, javac, javah, jar and javadoc), includes Runtime component
-#   IdlJ        = idl compiler for Java
-#   JarSigner   = signer tool for jar
+#   IdlJ        = Interface Description Language (IDL) to Java compiler
+#   JarSigner   = Signer and verifier tool for Java Archive (JAR) files
 #
 #
 # This module sets the following result variables:
@@ -44,14 +44,18 @@
 #
 #
 # The minimum required version of Java can be specified using the
-# standard CMake syntax, e.g.  find_package(Java 1.5)
+# :command:`find_package` syntax, e.g.
 #
-# NOTE: ${Java_VERSION} and ${Java_VERSION_STRING} are not guaranteed to
+# .. code-block:: cmake
+#
+#   find_package(Java 1.8)
+#
+# NOTE: ``${Java_VERSION}`` and ``${Java_VERSION_STRING}`` are not guaranteed to
 # be identical.  For example some java version may return:
-# Java_VERSION_STRING = 1.5.0_17 and Java_VERSION = 1.5.0.17
+# ``Java_VERSION_STRING = 1.8.0_17`` and ``Java_VERSION = 1.8.0.17``
 #
-# another example is the Java OEM, with: Java_VERSION_STRING = 1.6.0-oem
-# and Java_VERSION = 1.6.0
+# another example is the Java OEM, with: ``Java_VERSION_STRING = 1.8.0-oem``
+# and ``Java_VERSION = 1.8.0``
 #
 # For these components the following variables are set:
 #
@@ -67,6 +71,7 @@
 # ::
 #
 #   find_package(Java)
+#   find_package(Java 1.8 REQUIRED)
 #   find_package(Java COMPONENTS Runtime)
 #   find_package(Java COMPONENTS Development)
 
diff --git a/Modules/FindPython.cmake b/Modules/FindPython.cmake
index 0bf0b4f..8645a0d 100644
--- a/Modules/FindPython.cmake
+++ b/Modules/FindPython.cmake
@@ -135,6 +135,12 @@
 
     Value ``ONLY`` is not supported so ``FIRST`` will be used instead.
 
+.. note::
+
+  If a Python virtual environment is configured, set variable
+  ``Python_FIND_REGISTRY`` (Windows) or ``CMAKE_FIND_FRAMEWORK`` (macOS) with
+  value ``LAST`` or ``NEVER`` to select it preferably.
+
 Commands
 ^^^^^^^^
 
diff --git a/Modules/FindPython/Support.cmake b/Modules/FindPython/Support.cmake
index 1834591..a8a73a7 100644
--- a/Modules/FindPython/Support.cmake
+++ b/Modules/FindPython/Support.cmake
@@ -355,20 +355,23 @@
                         ${_${_PYTHON_PREFIX}_IRON_PYTHON_NAMES}
                   NAMES_PER_DIR
                   HINTS ${_${_PYTHON_PREFIX}_HINTS}
-                  PATH_SUFFIXES bin
+                  PATH_SUFFIXES bin ${_${_PYTHON_PREFIX}_IRON_PYTHON_PATH_SUFFIXES}
                   NO_SYSTEM_ENVIRONMENT_PATH
                   NO_CMAKE_SYSTEM_PATH)
     # try using standard paths.
-    # NAMES_PER_DIR is not defined on purpose to have a chance to find
-    # expected version.
-    # For example, typical systems have 'python' for version 2.* and 'python3'
-    # for version 3.*. So looking for names per dir will find, potentially,
-    # systematically 'python' (i.e. version 2) even if version 3 is searched.
-    find_program (${_PYTHON_PREFIX}_EXECUTABLE
-                  NAMES python${_${_PYTHON_PREFIX}_VERSION}
-                        python${_${_PYTHON_PREFIX}_REQUIRED_VERSION_MAJOR}
-                        python
-                        ${_${_PYTHON_PREFIX}_IRON_PYTHON_NAMES})
+    if (WIN32)
+      find_program (${_PYTHON_PREFIX}_EXECUTABLE
+                    NAMES python${_${_PYTHON_PREFIX}_VERSION}
+                          python${_${_PYTHON_PREFIX}_REQUIRED_VERSION_MAJOR}
+                          python
+                          ${_${_PYTHON_PREFIX}_IRON_PYTHON_NAMES}
+                    NAMES_PER_DIR)
+    else()
+      find_program (${_PYTHON_PREFIX}_EXECUTABLE
+                    NAMES python${_${_PYTHON_PREFIX}_VERSION}
+                          python${_${_PYTHON_PREFIX}_REQUIRED_VERSION_MAJOR}
+                    NAMES_PER_DIR)
+    endif()
 
     # Apple frameworks handling
     if (APPLE AND _${_PYTHON_PREFIX}_FIND_FRAMEWORK STREQUAL "LAST")
@@ -413,6 +416,7 @@
                   NAMES python${_${_PYTHON_PREFIX}_REQUIRED_VERSION_MAJOR}
                         python
                         ${_${_PYTHON_PREFIX}_IRON_PYTHON_NAMES}
+                  NAMES_PER_DIR
                   HINTS ${_${_PYTHON_PREFIX}_HINTS}
                   PATH_SUFFIXES bin ${_${_PYTHON_PREFIX}_IRON_PYTHON_PATH_SUFFIXES}
                   NO_SYSTEM_ENVIRONMENT_PATH
diff --git a/Modules/FindPython2.cmake b/Modules/FindPython2.cmake
index 2735a25..998e992 100644
--- a/Modules/FindPython2.cmake
+++ b/Modules/FindPython2.cmake
@@ -136,6 +136,12 @@
 
     Value ``ONLY`` is not supported so ``FIRST`` will be used instead.
 
+.. note::
+
+  If a Python virtual environment is configured, set variable
+  ``Python_FIND_REGISTRY`` (Windows) or ``CMAKE_FIND_FRAMEWORK`` (macOS) with
+  value ``LAST`` or ``NEVER`` to select it preferably.
+
 Commands
 ^^^^^^^^
 
diff --git a/Modules/FindPython3.cmake b/Modules/FindPython3.cmake
index ed7e1a3..2176f3f 100644
--- a/Modules/FindPython3.cmake
+++ b/Modules/FindPython3.cmake
@@ -136,6 +136,12 @@
 
     Value ``ONLY`` is not supported so ``FIRST`` will be used instead.
 
+.. note::
+
+  If a Python virtual environment is configured, set variable
+  ``Python_FIND_REGISTRY`` (Windows) or ``CMAKE_FIND_FRAMEWORK`` (macOS) with
+  value ``LAST`` or ``NEVER`` to select it preferably.
+
 Commands
 ^^^^^^^^
 
diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake
index 408cc7d..129c6fb 100644
--- a/Source/CMakeVersion.cmake
+++ b/Source/CMakeVersion.cmake
@@ -1,5 +1,5 @@
 # CMake version number components.
 set(CMake_VERSION_MAJOR 3)
 set(CMake_VERSION_MINOR 12)
-set(CMake_VERSION_PATCH 20181001)
+set(CMake_VERSION_PATCH 20181003)
 #set(CMake_VERSION_RC 1)
diff --git a/Source/CTest/cmCTestSubmitHandler.cxx b/Source/CTest/cmCTestSubmitHandler.cxx
index c7f3f39..ecf309a 100644
--- a/Source/CTest/cmCTestSubmitHandler.cxx
+++ b/Source/CTest/cmCTestSubmitHandler.cxx
@@ -392,8 +392,12 @@
       ::curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
 
       std::string local_file = file;
+      bool initialize_cdash_buildid = false;
       if (!cmSystemTools::FileExists(local_file)) {
         local_file = localprefix + "/" + file;
+        // If this file exists within the local Testing directory we assume
+        // that it will be associated with the current build in CDash.
+        initialize_cdash_buildid = true;
       }
       std::string remote_file =
         remoteprefix + cmSystemTools::GetFilenameName(file);
@@ -425,26 +429,30 @@
         ((url.find('?') == std::string::npos) ? '?' : '&') +
         "FileName=" + ofile;
 
-      cmCTestCurl ctest_curl(this->CTest);
-      upload_as += "&build=";
-      upload_as +=
-        ctest_curl.Escape(this->CTest->GetCTestConfiguration("BuildName"));
-      upload_as += "&site=";
-      upload_as +=
-        ctest_curl.Escape(this->CTest->GetCTestConfiguration("Site"));
-      upload_as += "&stamp=";
-      upload_as += ctest_curl.Escape(this->CTest->GetCurrentTag());
-      upload_as += "-";
-      upload_as += ctest_curl.Escape(this->CTest->GetTestModelString());
-      cmCTestScriptHandler* ch =
-        static_cast<cmCTestScriptHandler*>(this->CTest->GetHandler("script"));
-      cmake* cm = ch->GetCMake();
-      if (cm) {
-        const char* subproject =
-          cm->GetState()->GetGlobalProperty("SubProject");
-        if (subproject) {
-          upload_as += "&subproject=";
-          upload_as += ctest_curl.Escape(subproject);
+      if (initialize_cdash_buildid) {
+        // Provide extra arguments to CDash so that it can initialize and
+        // return a buildid.
+        cmCTestCurl ctest_curl(this->CTest);
+        upload_as += "&build=";
+        upload_as +=
+          ctest_curl.Escape(this->CTest->GetCTestConfiguration("BuildName"));
+        upload_as += "&site=";
+        upload_as +=
+          ctest_curl.Escape(this->CTest->GetCTestConfiguration("Site"));
+        upload_as += "&stamp=";
+        upload_as += ctest_curl.Escape(this->CTest->GetCurrentTag());
+        upload_as += "-";
+        upload_as += ctest_curl.Escape(this->CTest->GetTestModelString());
+        cmCTestScriptHandler* ch = static_cast<cmCTestScriptHandler*>(
+          this->CTest->GetHandler("script"));
+        cmake* cm = ch->GetCMake();
+        if (cm) {
+          const char* subproject =
+            cm->GetState()->GetGlobalProperty("SubProject");
+          if (subproject) {
+            upload_as += "&subproject=";
+            upload_as += ctest_curl.Escape(subproject);
+          }
         }
       }
 
diff --git a/Source/cmFileCommand.cxx b/Source/cmFileCommand.cxx
index 54af2f4..1f76703 100644
--- a/Source/cmFileCommand.cxx
+++ b/Source/cmFileCommand.cxx
@@ -1275,6 +1275,33 @@
     this->DirPermissions |= mode_world_read;
     this->DirPermissions |= mode_world_execute;
   }
+
+  bool GetDefaultDirectoryPermissions(mode_t** mode)
+  {
+    // check if default dir creation permissions were set
+    const char* default_dir_install_permissions =
+      this->Makefile->GetDefinition(
+        "CMAKE_INSTALL_DEFAULT_DIRECTORY_PERMISSIONS");
+    if (default_dir_install_permissions && *default_dir_install_permissions) {
+      std::vector<std::string> items;
+      cmSystemTools::ExpandListArgument(default_dir_install_permissions,
+                                        items);
+      for (const auto& arg : items) {
+        if (!this->CheckPermissions(arg, **mode)) {
+          std::ostringstream e;
+          e << this->FileCommand->GetError()
+            << " Set with CMAKE_INSTALL_DEFAULT_DIRECTORY_PERMISSIONS "
+               "variable.";
+          this->FileCommand->SetError(e.str());
+          return false;
+        }
+      }
+    } else {
+      *mode = nullptr;
+    }
+
+    return true;
+  }
 };
 
 bool cmFileCopier::Parse(std::vector<std::string> const& args)
@@ -1668,8 +1695,15 @@
   this->ReportCopy(destination, TypeDir,
                    !cmSystemTools::FileIsDirectory(destination));
 
+  // check if default dir creation permissions were set
+  mode_t default_dir_mode_v = 0;
+  mode_t* default_dir_mode = &default_dir_mode_v;
+  if (!this->GetDefaultDirectoryPermissions(&default_dir_mode)) {
+    return false;
+  }
+
   // Make sure the destination directory exists.
-  if (!cmSystemTools::MakeDirectory(destination)) {
+  if (!cmSystemTools::MakeDirectory(destination, default_dir_mode)) {
     std::ostringstream e;
     e << this->Name << " cannot make directory \"" << destination
       << "\": " << cmSystemTools::GetLastSystemError();
@@ -2073,23 +2107,9 @@
 
   // check if default dir creation permissions were set
   mode_t default_dir_mode_v = 0;
-  mode_t* default_dir_mode = nullptr;
-  const char* default_dir_install_permissions = this->Makefile->GetDefinition(
-    "CMAKE_INSTALL_DEFAULT_DIRECTORY_PERMISSIONS");
-  if (default_dir_install_permissions && *default_dir_install_permissions) {
-    std::vector<std::string> items;
-    cmSystemTools::ExpandListArgument(default_dir_install_permissions, items);
-    for (const auto& arg : items) {
-      if (!this->CheckPermissions(arg, default_dir_mode_v)) {
-        std::ostringstream e;
-        e << this->FileCommand->GetError()
-          << " Set with CMAKE_INSTALL_DEFAULT_DIRECTORY_PERMISSIONS variable.";
-        this->FileCommand->SetError(e.str());
-        return false;
-      }
-    }
-
-    default_dir_mode = &default_dir_mode_v;
+  mode_t* default_dir_mode = &default_dir_mode_v;
+  if (!this->GetDefaultDirectoryPermissions(&default_dir_mode)) {
+    return false;
   }
 
   if (this->InstallType != cmInstallType_DIRECTORY) {
diff --git a/Source/cmGeneratorTarget.cxx b/Source/cmGeneratorTarget.cxx
index 29c6058..80fb621 100644
--- a/Source/cmGeneratorTarget.cxx
+++ b/Source/cmGeneratorTarget.cxx
@@ -5600,10 +5600,14 @@
 {
   std::set<std::string> languages;
   this->GetLanguages(languages, config);
+  // The "exclusive" check applies only to source files and not
+  // the linker language which may be affected by dependencies.
+  if (exclusive && languages.size() > 1) {
+    return false;
+  }
   // add linker language (if it is different from compiler languages)
   languages.insert(this->GetLinkerLanguage(config));
-  return (languages.size() == 1 || !exclusive) &&
-    languages.count(language) > 0;
+  return languages.count(language) > 0;
 }
 
 void cmGeneratorTarget::ComputeLinkImplementationLanguages(
diff --git a/Source/cmGeneratorTarget.h b/Source/cmGeneratorTarget.h
index bfd95ac..b1daa53 100644
--- a/Source/cmGeneratorTarget.h
+++ b/Source/cmGeneratorTarget.h
@@ -374,7 +374,7 @@
 
   // Evaluate if the target uses the given language for compilation
   // and/or linking. If 'exclusive' is true, 'language' is expected
-  // to be the only language used for the target.
+  // to be the only language used in source files for the target.
   bool HasLanguage(std::string const& language, std::string const& config,
                    bool exclusive = true) const;
 
diff --git a/Source/cmMakefileTargetGenerator.cxx b/Source/cmMakefileTargetGenerator.cxx
index c8dc392..f423560 100644
--- a/Source/cmMakefileTargetGenerator.cxx
+++ b/Source/cmMakefileTargetGenerator.cxx
@@ -181,6 +181,36 @@
           this->LocalGenerator->MaybeConvertToRelativePath(currentBinDir,
                                                            output));
       }
+      const std::vector<std::string>& byproducts = ccg.GetByproducts();
+      for (std::string const& byproduct : byproducts) {
+        this->CleanFiles.push_back(
+          this->LocalGenerator->MaybeConvertToRelativePath(currentBinDir,
+                                                           byproduct));
+      }
+    }
+  }
+
+  // Add byproducts from build events to the clean rules
+  if (clean) {
+    std::vector<cmCustomCommand> buildEventCommands =
+      this->GeneratorTarget->GetPreBuildCommands();
+
+    buildEventCommands.insert(
+      buildEventCommands.end(),
+      this->GeneratorTarget->GetPreLinkCommands().begin(),
+      this->GeneratorTarget->GetPreLinkCommands().end());
+    buildEventCommands.insert(
+      buildEventCommands.end(),
+      this->GeneratorTarget->GetPostBuildCommands().begin(),
+      this->GeneratorTarget->GetPostBuildCommands().end());
+
+    for (const auto& be : buildEventCommands) {
+      const std::vector<std::string>& byproducts = be.GetByproducts();
+      for (std::string const& byproduct : byproducts) {
+        this->CleanFiles.push_back(
+          this->LocalGenerator->MaybeConvertToRelativePath(currentBinDir,
+                                                           byproduct));
+      }
     }
   }
   std::vector<cmSourceFile const*> headerSources;
diff --git a/Source/cmVS141CSharpFlagTable.h b/Source/cmVS141CSharpFlagTable.h
index 5de9bf3..66c61bd 100644
--- a/Source/cmVS141CSharpFlagTable.h
+++ b/Source/cmVS141CSharpFlagTable.h
@@ -76,7 +76,12 @@
   { "LangVersion", "langversion:4", "", "4", 0 },
   { "LangVersion", "langversion:5", "", "5", 0 },
   { "LangVersion", "langversion:6", "", "6", 0 },
+  { "LangVersion", "langversion:7.0", "", "7.0", 0 },
+  { "LangVersion", "langversion:7.1", "", "7.1", 0 },
+  { "LangVersion", "langversion:7.2", "", "7.2", 0 },
+  { "LangVersion", "langversion:7.3", "", "7.3", 0 },
   { "LangVersion", "langversion:default", "", "default", 0 },
+  { "LangVersion", "langversion:latest", "", "latest", 0 },
 
   { "DelaySign", "delaysign", "", "true", 0 },
   { "DelaySign", "delaysign-", "", "false", 0 },
diff --git a/Source/cmVisualStudio10TargetGenerator.cxx b/Source/cmVisualStudio10TargetGenerator.cxx
index c79b071..16eca96 100644
--- a/Source/cmVisualStudio10TargetGenerator.cxx
+++ b/Source/cmVisualStudio10TargetGenerator.cxx
@@ -2452,10 +2452,12 @@
   }
 
   // Choose a language whose flags to use for ClCompile.
-  static const char* clLangs[] = { "CXX", "C", "Fortran", "CSharp" };
+  static const char* clLangs[] = { "CXX", "C", "Fortran" };
   std::string langForClCompile;
-  if (std::find(cm::cbegin(clLangs), cm::cend(clLangs), linkLanguage) !=
-      cm::cend(clLangs)) {
+  if (this->ProjectType == csproj) {
+    langForClCompile = "CSharp";
+  } else if (std::find(cm::cbegin(clLangs), cm::cend(clLangs), linkLanguage) !=
+             cm::cend(clLangs)) {
     langForClCompile = linkLanguage;
   } else {
     std::set<std::string> languages;
diff --git a/Source/kwsys/Terminal.c b/Source/kwsys/Terminal.c
index 1bcfd0c..4dd2461 100644
--- a/Source/kwsys/Terminal.c
+++ b/Source/kwsys/Terminal.c
@@ -103,6 +103,8 @@
 
 /* List of terminal names known to support VT100 color escape sequences.  */
 static const char* kwsysTerminalVT100Names[] = { "Eterm",
+                                                 "alacritty",
+                                                 "alacritty-direct",
                                                  "ansi",
                                                  "color-xterm",
                                                  "con132x25",
diff --git a/Tests/CSharpLinkToCxx/CMakeLists.txt b/Tests/CSharpLinkToCxx/CMakeLists.txt
index 153c57c..a3067af 100644
--- a/Tests/CSharpLinkToCxx/CMakeLists.txt
+++ b/Tests/CSharpLinkToCxx/CMakeLists.txt
@@ -21,3 +21,9 @@
 # because it is unmanaged
 add_library(CppNativeApp SHARED cpp_native.hpp cpp_native.cpp)
 target_link_libraries(CSharpLinkToCxx CppNativeApp)
+
+# Link a static C++ library into the CSharp executable.
+# We do not actually use any symbols but this helps cover
+# link language selection.
+add_library(CppStaticLib STATIC cpp_static.cpp)
+target_link_libraries(CSharpLinkToCxx CppStaticLib)
diff --git a/Tests/CSharpLinkToCxx/cpp_static.cpp b/Tests/CSharpLinkToCxx/cpp_static.cpp
new file mode 100644
index 0000000..9af2b6e
--- /dev/null
+++ b/Tests/CSharpLinkToCxx/cpp_static.cpp
@@ -0,0 +1,3 @@
+void cpp_static()
+{
+}
diff --git a/Tests/CustomCommandWorkingDirectory/CMakeLists.txt b/Tests/CustomCommandWorkingDirectory/CMakeLists.txt
index 5495a9b..2e12a78 100644
--- a/Tests/CustomCommandWorkingDirectory/CMakeLists.txt
+++ b/Tests/CustomCommandWorkingDirectory/CMakeLists.txt
@@ -9,17 +9,17 @@
 )
 
 set_source_files_properties(
-  "${TestWorkingDir_BINARY_DIR}/customTarget.c"
+  "${TestWorkingDir_BINARY_DIR}/customTarget1.c"
   "${TestWorkingDir_BINARY_DIR}/customTarget2.c"
   PROPERTIES GENERATED 1)
 
 add_executable(working "${TestWorkingDir_BINARY_DIR}/working.c"
-  "${TestWorkingDir_BINARY_DIR}/customTarget.c")
+  "${TestWorkingDir_BINARY_DIR}/customTarget1.c")
 
 add_custom_target(
   Custom ALL
-  COMMAND "${CMAKE_COMMAND}" -E copy_if_different ./customTarget.c "${TestWorkingDir_BINARY_DIR}/customTarget.c"
-  BYPRODUCTS "${TestWorkingDir_BINARY_DIR}/customTarget.c"
+  COMMAND "${CMAKE_COMMAND}" -E copy_if_different ./customTarget.c "${TestWorkingDir_BINARY_DIR}/customTarget1.c"
+  BYPRODUCTS "${TestWorkingDir_BINARY_DIR}/customTarget1.c"
   WORKING_DIRECTORY  "${TestWorkingDir_SOURCE_DIR}"
 )
 
diff --git a/Tests/RunCMake/Byproducts/CMakeLists.txt b/Tests/RunCMake/Byproducts/CMakeLists.txt
new file mode 100644
index 0000000..bf2ef15
--- /dev/null
+++ b/Tests/RunCMake/Byproducts/CMakeLists.txt
@@ -0,0 +1,3 @@
+cmake_minimum_required(VERSION 3.10)
+project(${RunCMake_TEST} NONE)
+include(${RunCMake_TEST}.cmake)
diff --git a/Tests/RunCMake/Byproducts/CleanByproducts.cmake b/Tests/RunCMake/Byproducts/CleanByproducts.cmake
new file mode 100644
index 0000000..85d9582
--- /dev/null
+++ b/Tests/RunCMake/Byproducts/CleanByproducts.cmake
@@ -0,0 +1,93 @@
+cmake_minimum_required(VERSION 3.10)
+project(CleanByproducts)
+
+# Configurable parameters
+set(TEST_CLEAN_NO_CUSTOM FALSE CACHE BOOL "Value for the CLEAN_NO_CUSTOM PROPERTY")
+set(TEST_BUILD_EVENTS TRUE CACHE BOOL "Create byproducts with build events")
+set(TEST_CUSTOM_TARGET TRUE CACHE BOOL "Create a byproduct with a custom target")
+set(TEST_CUSTOM_COMMAND TRUE CACHE BOOL "Create a byproduct with a custom command")
+
+set_property(DIRECTORY PROPERTY CLEAN_NO_CUSTOM ${TEST_CLEAN_NO_CUSTOM})
+
+macro(add_build_event)
+  set(oneValueArgs EVENT)
+
+  cmake_parse_Arguments(ABE "" "${oneValueArgs}" "" ${ARGN})
+
+  # Create two byproducts and only declare one
+  add_custom_command(TARGET foo
+    ${ABE_EVENT}
+    COMMAND ${CMAKE_COMMAND} -E touch foo.${ABE_EVENT}
+    COMMAND ${CMAKE_COMMAND} -E touch foo.${ABE_EVENT}.notdeclared
+    COMMENT "Creating byproducts with ${ABE_EVENT}"
+    BYPRODUCTS foo.${ABE_EVENT}
+  )
+
+  # The nondeclared byproduct should always be present
+  list(APPEND EXPECTED_PRESENT foo.${ABE_EVENT}.notdeclared)
+
+  # If CLEAN_NO_CUSTOM is set, the declared byproduct should be present
+  if(TEST_CLEAN_NO_CUSTOM)
+    list(APPEND EXPECTED_PRESENT foo.${ABE_EVENT})
+  else()
+    list(APPEND EXPECTED_DELETED foo.${ABE_EVENT})
+  endif()
+endmacro()
+
+add_executable(foo foo.cpp)
+
+# Test build events
+if(TEST_BUILD_EVENTS)
+  add_build_event(EVENT "PRE_BUILD" ENABLE ${TEST_PRE_BUILD})
+  add_build_event(EVENT "PRE_LINK" ENABLE ${TEST_PRE_LINK})
+  add_build_event(EVENT "POST_BUILD" ENABLE ${TEST_POST_BUILD})
+endif()
+
+# Custom command that generates byproducts
+if(TEST_CUSTOM_COMMAND)
+  file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/bar.cpp.in "void bar() {}\n")
+  add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/bar.cpp
+    COMMAND ${CMAKE_COMMAND} -E touch foo.customcommand
+    COMMAND ${CMAKE_COMMAND} -E touch foo.customcommand.notdeclared
+    COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_BINARY_DIR}/bar.cpp.in ${CMAKE_CURRENT_BINARY_DIR}/bar.cpp
+    BYPRODUCTS foo.customcommand
+    COMMENT "Creating byproducts with a custom command"
+  )
+
+  # The nondeclared byproduct should always be present
+  list(APPEND EXPECTED_PRESENT "foo.customcommand.notdeclared")
+
+  # If CLEAN_NO_CUSTOM is set, both the output and byproduct should be present
+  if(TEST_CLEAN_NO_CUSTOM)
+    list(APPEND EXPECTED_PRESENT "bar.cpp")
+    list(APPEND EXPECTED_PRESENT "foo.customcommand")
+  else()
+    list(APPEND EXPECTED_DELETED "bar.cpp")
+    list(APPEND EXPECTED_DELETED "foo.customcommand")
+  endif()
+
+  target_sources(foo PUBLIC "${CMAKE_CURRENT_BINARY_DIR}/bar.cpp")
+endif()
+
+# Custom target that generates byproducts
+if(TEST_CUSTOM_TARGET)
+  add_custom_target(foo_file ALL
+    DEPENDS foo
+    COMMAND ${CMAKE_COMMAND} -E touch foo.customtarget
+    COMMAND ${CMAKE_COMMAND} -E touch foo.customtarget.notdeclared
+    BYPRODUCTS foo.customtarget
+    COMMENT "Creating byproducts with a custom target"
+  )
+
+  # The nondeclared byproduct should always be present
+  list(APPEND EXPECTED_PRESENT "foo.customtarget.notdeclared")
+
+  # If CLEAN_NO_CUSTOM is set, the declared byproduct should be present
+  if(TEST_CLEAN_NO_CUSTOM)
+    list(APPEND EXPECTED_PRESENT "foo.customtarget")
+  else()
+    list(APPEND EXPECTED_DELETED "foo.customtarget")
+  endif()
+endif()
+
+configure_file(files.cmake.in files.cmake)
diff --git a/Tests/RunCMake/Byproducts/RunCMakeTest.cmake b/Tests/RunCMake/Byproducts/RunCMakeTest.cmake
new file mode 100644
index 0000000..a7584ee
--- /dev/null
+++ b/Tests/RunCMake/Byproducts/RunCMakeTest.cmake
@@ -0,0 +1,58 @@
+include(RunCMake)
+
+function(run_CleanByproducts case)
+  set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/CleanByproducts-${case}-build)
+  set(RunCMake_TEST_OPTIONS "${ARGN}")
+
+  run_cmake(CleanByproducts)
+  set(RunCMake_TEST_NO_CLEAN 1)
+
+  run_cmake_command(CleanByProducts-build ${CMAKE_COMMAND} --build .)
+  include("${RunCMake_TEST_BINARY_DIR}/files.cmake")
+
+  message("Checking that all expected files are present")
+  check_files(EXPECTED_PRESENT "${RunCMake_TEST_BINARY_DIR}" TRUE)
+  check_files(EXPECTED_DELETED "${RunCMake_TEST_BINARY_DIR}" TRUE)
+
+  run_cmake_command(CleanByProducts-clean ${CMAKE_COMMAND} --build . --target clean)
+
+  message("Checking that only the expected files are present after cleaning")
+  check_files(EXPECTED_PRESENT "${RunCMake_TEST_BINARY_DIR}" TRUE)
+  check_files(EXPECTED_DELETED "${RunCMake_TEST_BINARY_DIR}" FALSE)
+endfunction()
+
+function(check_files list path has_to_exist)
+  foreach(file IN LISTS ${list})
+    message("Checking ${file}")
+    set(file_exists FALSE)
+    if(EXISTS "${path}/${file}")
+      set(file_exists TRUE)
+    endif()
+
+    if(file_exists AND NOT has_to_exist)
+      message(FATAL_ERROR "${file} should have been deleted")
+    elseif(NOT file_exists AND has_to_exist)
+      message(FATAL_ERROR "${file} does not exist")
+    elseif(file_exists AND has_to_exist)
+      message("${file} found as expected")
+    elseif(NOT file_exists AND NOT has_to_exist)
+      message("${file} deleted as expected")
+    endif()
+
+  endforeach()
+endfunction()
+
+
+# Iterate through all possible test values
+set(counter 0)
+foreach(test_clean_no_custom TRUE FALSE)
+  foreach(test_build_events TRUE FALSE)
+    foreach(test_custom_command TRUE FALSE)
+      foreach(test_custom_target TRUE FALSE)
+        math(EXPR counter "${counter} + 1")
+        message("Test ${counter} - CLEAN_NO_CUSTOM: ${test_clean_no_custom}, Build events: ${test_build_events}, Custom command: ${test_custom_command}, Custom target: ${test_custom_target}")
+        run_CleanByproducts("buildevents${counter}" -DCLEAN_NO_CUSTOM=${test_clean_no_custom} -DTEST_BUILD_EVENTS=${test_build_events} -DTEST_CUSTOM_COMMAND=${test_custom_command} -DTEST_CUSTOM_TARGET=${test_custom_target})
+      endforeach()
+    endforeach()
+  endforeach()
+endforeach()
diff --git a/Tests/RunCMake/Byproducts/files.cmake.in b/Tests/RunCMake/Byproducts/files.cmake.in
new file mode 100644
index 0000000..a7d4831
--- /dev/null
+++ b/Tests/RunCMake/Byproducts/files.cmake.in
@@ -0,0 +1,2 @@
+set(EXPECTED_PRESENT "@EXPECTED_PRESENT@")
+set(EXPECTED_DELETED "@EXPECTED_DELETED@")
diff --git a/Tests/RunCMake/Byproducts/foo.cpp b/Tests/RunCMake/Byproducts/foo.cpp
new file mode 100644
index 0000000..d47cb91
--- /dev/null
+++ b/Tests/RunCMake/Byproducts/foo.cpp
@@ -0,0 +1,14 @@
+int bar(int y)
+{
+  return y * 6;
+}
+
+int foo(int x)
+{
+  return x * bar(x);
+}
+
+int main()
+{
+  return foo(4);
+}
diff --git a/Tests/RunCMake/CMakeLists.txt b/Tests/RunCMake/CMakeLists.txt
index 080d0d0..90681b9 100644
--- a/Tests/RunCMake/CMakeLists.txt
+++ b/Tests/RunCMake/CMakeLists.txt
@@ -144,6 +144,9 @@
 add_RunCMake_test(AndroidTestUtilities)
 add_RunCMake_test(BuildDepends)
 if(UNIX AND "${CMAKE_GENERATOR}" MATCHES "Unix Makefiles|Ninja")
+  add_RunCMake_test(Byproducts)
+endif()
+if(UNIX AND "${CMAKE_GENERATOR}" MATCHES "Unix Makefiles|Ninja")
   add_RunCMake_test(CompilerChange)
 endif()
 add_RunCMake_test(CompilerNotFound)
diff --git a/Tests/RunCMake/ctest_submit/FILESNoBuildId-result.txt b/Tests/RunCMake/ctest_submit/FILESNoBuildId-result.txt
new file mode 100644
index 0000000..b57e2de
--- /dev/null
+++ b/Tests/RunCMake/ctest_submit/FILESNoBuildId-result.txt
@@ -0,0 +1 @@
+(-1|255)
diff --git a/Tests/RunCMake/ctest_submit/FILESNoBuildId-stderr.txt b/Tests/RunCMake/ctest_submit/FILESNoBuildId-stderr.txt
new file mode 100644
index 0000000..a8f10b5
--- /dev/null
+++ b/Tests/RunCMake/ctest_submit/FILESNoBuildId-stderr.txt
@@ -0,0 +1 @@
+ *Error message was: ([Cc]ould *n.t resolve host:? '?-no-site-'?.*|The requested URL returned error:.*)
diff --git a/Tests/RunCMake/ctest_submit/FILESNoBuildId-stdout.txt b/Tests/RunCMake/ctest_submit/FILESNoBuildId-stdout.txt
new file mode 100644
index 0000000..929b254
--- /dev/null
+++ b/Tests/RunCMake/ctest_submit/FILESNoBuildId-stdout.txt
@@ -0,0 +1 @@
+Upload file: .* to http:\/\/-no-site-\?FileName=test-site___test-build-name___.*-Experimental___XML___RunCMakeTest.cmake&MD5=.* Size: .*
diff --git a/Tests/RunCMake/ctest_submit/RunCMakeTest.cmake b/Tests/RunCMake/ctest_submit/RunCMakeTest.cmake
index 7661383..952368d 100644
--- a/Tests/RunCMake/ctest_submit/RunCMakeTest.cmake
+++ b/Tests/RunCMake/ctest_submit/RunCMakeTest.cmake
@@ -31,6 +31,7 @@
 run_ctest_submit(CDashUploadRetry CDASH_UPLOAD ${CMAKE_CURRENT_LIST_FILE} CDASH_UPLOAD_TYPE foo RETRY_COUNT 2 RETRY_DELAY 1 INTERNAL_TEST_CHECKSUM)
 run_ctest_submit(CDashSubmitQuiet QUIET)
 run_ctest_submit_debug(CDashSubmitVerbose)
+run_ctest_submit_debug(FILESNoBuildId FILES ${CMAKE_CURRENT_LIST_FILE})
 run_ctest_submit_debug(CDashSubmitHeaders HTTPHEADER "Authorization: Bearer asdf")
 run_ctest_submit_debug(CDashUploadHeaders CDASH_UPLOAD ${CMAKE_CURRENT_LIST_FILE} CDASH_UPLOAD_TYPE foo HTTPHEADER "Authorization: Bearer asdf")
 
diff --git a/Utilities/cmlibuv/src/unix/fs.c b/Utilities/cmlibuv/src/unix/fs.c
index 4545168..a6cc6db 100644
--- a/Utilities/cmlibuv/src/unix/fs.c
+++ b/Utilities/cmlibuv/src/unix/fs.c
@@ -425,19 +425,22 @@
   return n;
 }
 
+#if defined(_POSIX_PATH_MAX)
+# define UV__FS_PATH_MAX _POSIX_PATH_MAX
+#elif defined(PATH_MAX)
+# define UV__FS_PATH_MAX PATH_MAX
+#else
+# define UV__FS_PATH_MAX_FALLBACK 8192
+# define UV__FS_PATH_MAX UV__FS_PATH_MAX_FALLBACK
+#endif
 
 static ssize_t uv__fs_pathmax_size(const char* path) {
   ssize_t pathmax;
 
   pathmax = pathconf(path, _PC_PATH_MAX);
 
-  if (pathmax == -1) {
-#if defined(PATH_MAX)
-    return PATH_MAX;
-#else
-#error "PATH_MAX undefined in the current platform"
-#endif
-  }
+  if (pathmax == -1)
+    pathmax = UV__FS_PATH_MAX;
 
   return pathmax;
 }
@@ -446,7 +449,28 @@
   ssize_t len;
   char* buf;
 
+#if defined(UV__FS_PATH_MAX_FALLBACK)
+  /* We may not have a real PATH_MAX.  Read size of link.  */
+  struct stat st;
+  int ret;
+  ret = lstat(req->path, &st);
+  if (ret != 0)
+    return -1;
+  if (!S_ISLNK(st.st_mode)) {
+    errno = EINVAL;
+    return -1;
+  }
+
+  len = st.st_size;
+
+  /* According to readlink(2) lstat can report st_size == 0
+     for some symlinks, such as those in /proc or /sys.  */
+  if (len == 0)
+    len = uv__fs_pathmax_size(req->path);
+#else
   len = uv__fs_pathmax_size(req->path);
+#endif
+
   buf = uv__malloc(len + 1);
 
   if (buf == NULL) {
@@ -473,9 +497,15 @@
 }
 
 static ssize_t uv__fs_realpath(uv_fs_t* req) {
-  ssize_t len;
   char* buf;
 
+#if defined(_POSIX_VERSION) && _POSIX_VERSION >= 200809L
+  buf = realpath(req->path, NULL);
+  if (buf == NULL)
+    return -1;
+#else
+  ssize_t len;
+
   len = uv__fs_pathmax_size(req->path);
   buf = uv__malloc(len + 1);
 
@@ -488,6 +518,7 @@
     uv__free(buf);
     return -1;
   }
+#endif
 
   req->ptr = buf;