summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Modules/Platform/Windows-LLVMFlang-Fortran.cmake12
-rw-r--r--Source/Checks/cm_cxx_filesystem.cxx28
-rw-r--r--Source/cmComputeLinkInformation.cxx23
-rw-r--r--Source/cmCoreTryCompile.cxx12
-rw-r--r--Source/cmCxxModuleMapper.cxx13
-rw-r--r--Source/cmExportCommand.cxx12
-rw-r--r--Source/cmFileCommand.cxx11
-rw-r--r--Source/cmFileCopier.cxx44
-rw-r--r--Source/cmFileLockResult.cxx2
-rw-r--r--Source/cmFileTimes.cxx42
-rw-r--r--Source/cmFileTimes.h9
-rw-r--r--Source/cmGeneratorTarget.cxx13
-rw-r--r--Source/cmGeneratorTarget.h2
-rw-r--r--Source/cmLocalGenerator.cxx3
-rw-r--r--Source/cmNinjaTargetGenerator.cxx15
-rw-r--r--Source/cmake.cxx6
-rw-r--r--Tests/CMakeLists.txt5
-rw-r--r--Tests/MSVCDebugInformationFormat/override-Fortran.cmake8
-rw-r--r--Tests/RunCMake/CXXModules/RunCMakeTest.cmake4
-rw-r--r--Tests/RunCMake/CXXModules/examples/circular-build-stdout.txt2
-rw-r--r--Tests/RunCMake/CXXModules/examples/non-trivial-collation-order-randomized/CMakeLists.txt9
-rw-r--r--Tests/RunCMake/CXXModules/examples/non-trivial-collation-order/CMakeLists.txt132
-rw-r--r--Tests/RunCMake/CXXModules/examples/non-trivial-collation-order/main.cxx6
-rw-r--r--Tests/RunCMake/CXXModules/examples/non-trivial-collation-order/module_level/mod1.cxx7
-rw-r--r--Tests/RunCMake/CXXModules/examples/non-trivial-collation-order/module_level/mod2.cxx7
-rw-r--r--Tests/RunCMake/CXXModules/examples/non-trivial-collation-order/module_level/mod3.cxx7
-rw-r--r--Tests/RunCMake/CXXModules/examples/non-trivial-collation-order/module_level/mod4.cxx7
-rw-r--r--Tests/RunCMake/CXXModules/examples/non-trivial-collation-order/module_level/mod5.cxx7
-rw-r--r--Tests/RunCMake/CXXModules/examples/non-trivial-collation-order/module_level/mod6.cxx7
-rw-r--r--Tests/RunCMake/CXXModules/examples/non-trivial-collation-order/module_level/mod7.cxx7
-rw-r--r--Tests/RunCMake/CXXModules/examples/non-trivial-collation-order/partition_level/impl-non-partition.cxx10
-rw-r--r--Tests/RunCMake/CXXModules/examples/non-trivial-collation-order/partition_level/impl1.cxx7
-rw-r--r--Tests/RunCMake/CXXModules/examples/non-trivial-collation-order/partition_level/impl2.cxx8
-rw-r--r--Tests/RunCMake/CXXModules/examples/non-trivial-collation-order/partition_level/impl3.cxx8
-rw-r--r--Tests/RunCMake/CXXModules/examples/non-trivial-collation-order/partition_level/impl4.cxx8
-rw-r--r--Tests/RunCMake/CXXModules/examples/non-trivial-collation-order/partition_level/impl5.cxx8
-rw-r--r--Tests/RunCMake/CXXModules/examples/non-trivial-collation-order/partition_level/impl6.cxx8
-rw-r--r--Tests/RunCMake/CXXModules/examples/non-trivial-collation-order/partition_level/impl7.cxx8
-rw-r--r--Tests/RunCMake/CXXModules/examples/non-trivial-collation-order/partition_level/intf1.cxx8
-rw-r--r--Tests/RunCMake/CXXModules/examples/non-trivial-collation-order/partition_level/intf2.cxx8
-rw-r--r--Tests/RunCMake/CXXModules/examples/non-trivial-collation-order/partition_level/intf3.cxx8
-rw-r--r--Tests/RunCMake/CXXModules/examples/non-trivial-collation-order/partition_level/intf4.cxx8
-rw-r--r--Tests/RunCMake/CXXModules/examples/non-trivial-collation-order/partition_level/intf5.cxx8
-rw-r--r--Tests/RunCMake/CXXModules/examples/non-trivial-collation-order/partition_level/intf6.cxx8
-rw-r--r--Tests/RunCMake/CXXModules/examples/non-trivial-collation-order/partition_level/intf7.cxx8
-rw-r--r--Tests/RunCMake/CXXModules/examples/non-trivial-collation-order/partition_level/partition_level.cxx15
-rw-r--r--Tests/RunCMake/CXXModules/examples/non-trivial-collation-order/target_level/target1.cxx7
-rw-r--r--Tests/RunCMake/CXXModules/examples/non-trivial-collation-order/target_level/target2.cxx7
-rw-r--r--Tests/RunCMake/CXXModules/examples/non-trivial-collation-order/target_level/target3.cxx7
-rw-r--r--Tests/RunCMake/CXXModules/examples/non-trivial-collation-order/target_level/target4.cxx7
-rw-r--r--Tests/RunCMake/CXXModules/examples/non-trivial-collation-order/target_level/target5.cxx7
-rw-r--r--Tests/RunCMake/CXXModules/examples/non-trivial-collation-order/target_level/target6.cxx7
-rw-r--r--Tests/RunCMake/CXXModules/examples/non-trivial-collation-order/target_level/target7.cxx7
-rw-r--r--Tests/RunCMake/CXXModules/examples/scan-with-pch/CMakeLists.txt13
-rw-r--r--Tests/RunCMake/CXXModules/examples/scan-with-pch/main.cxx8
-rw-r--r--Tests/RunCMake/CXXModules/examples/scan-with-pch/pch.h1
-rw-r--r--Utilities/cmlibuv/src/win/process.c43
57 files changed, 604 insertions, 108 deletions
diff --git a/Modules/Platform/Windows-LLVMFlang-Fortran.cmake b/Modules/Platform/Windows-LLVMFlang-Fortran.cmake
index 3e22a6e..57e36c6 100644
--- a/Modules/Platform/Windows-LLVMFlang-Fortran.cmake
+++ b/Modules/Platform/Windows-LLVMFlang-Fortran.cmake
@@ -17,11 +17,13 @@ elseif("x${CMAKE_Fortran_SIMULATE_ID}" STREQUAL "xMSVC")
set(CMAKE_Fortran_COMPILE_OPTIONS_MSVC_RUNTIME_LIBRARY_MultiThreadedDebug "")
set(CMAKE_Fortran_COMPILE_OPTIONS_MSVC_RUNTIME_LIBRARY_MultiThreadedDebugDLL "")
- # FIXME(LLVMFlang): It does not provide all debug information format flags or predefines.
- # It should be given a flag to enable Embedded debug information like MSVC -Z7.
- #set(CMAKE_Fortran_COMPILE_OPTIONS_MSVC_DEBUG_INFORMATION_FORMAT_Embedded) # not supported by LLVMFlang
- #set(CMAKE_Fortran_COMPILE_OPTIONS_MSVC_DEBUG_INFORMATION_FORMAT_EditAndContinue) # not supported by LLVMFlang
- set(CMAKE_Fortran_COMPILE_OPTIONS_MSVC_DEBUG_INFORMATION_FORMAT_ProgramDatabase "-g")
+ # LLVMFlang, like Clang, does not provide all debug information format flags.
+ # In order to provide easy integration with C and C++ projects that use the
+ # other debug information formats, pretend to support them, and just do not
+ # actually generate any debug information for Fortran.
+ set(CMAKE_Fortran_COMPILE_OPTIONS_MSVC_DEBUG_INFORMATION_FORMAT_Embedded -g)
+ set(CMAKE_Fortran_COMPILE_OPTIONS_MSVC_DEBUG_INFORMATION_FORMAT_ProgramDatabase "") # not supported by LLVMFlang
+ set(CMAKE_Fortran_COMPILE_OPTIONS_MSVC_DEBUG_INFORMATION_FORMAT_EditAndContinue "") # not supported by LLVMFlang
set(CMAKE_Fortran_COMPILE_OBJECT "<CMAKE_Fortran_COMPILER> <DEFINES> <INCLUDES> <FLAGS> -o <OBJECT> -c <SOURCE>")
diff --git a/Source/Checks/cm_cxx_filesystem.cxx b/Source/Checks/cm_cxx_filesystem.cxx
index 732f28f..c8df589 100644
--- a/Source/Checks/cm_cxx_filesystem.cxx
+++ b/Source/Checks/cm_cxx_filesystem.cxx
@@ -1,5 +1,8 @@
#include <filesystem>
+#if defined(__GLIBCXX__)
+# include <string_view>
+#endif
int main()
{
@@ -34,5 +37,30 @@ int main()
p5.remove_filename();
#endif
+#if defined(__GLIBCXX__)
+ // RH gcc-toolset-10 has a strange bug: it selects, in some circumstances,
+ // the wrong constructor which generate error in template instantiation.
+ class my_string_view : std::string_view
+ {
+ public:
+ my_string_view(const char* p)
+ : std::string_view(p)
+ {
+ }
+ };
+ class my_path
+ {
+ public:
+ my_path(std::filesystem::path path) {}
+
+ my_path(my_string_view path) {}
+ };
+
+ my_path p{ my_string_view{ "abc" } };
+ // here is the bug: the constructor taking std::filesystem::path as argument
+ // is selected, so the compiler try to build a std::filesystem::path instance
+ // from the my_string_view argument and fails to do so.
+#endif
+
return 0;
}
diff --git a/Source/cmComputeLinkInformation.cxx b/Source/cmComputeLinkInformation.cxx
index c58dc68..1b69f6e 100644
--- a/Source/cmComputeLinkInformation.cxx
+++ b/Source/cmComputeLinkInformation.cxx
@@ -2363,20 +2363,21 @@ void cmComputeLinkInformation::AddLibraryRuntimeInfo(
if (target->GetType() != cmStateEnums::SHARED_LIBRARY) {
return;
}
- auto const* info = target->GetImportInfo(this->Config);
+
+ // Skip targets that do not have a known runtime artifact.
+ if (!target->HasKnownRuntimeArtifactLocation(this->Config)) {
+ return;
+ }
// Try to get the soname of the library. Only files with this name
// could possibly conflict.
- const char* soname =
- (!info || info->SOName.empty()) ? nullptr : info->SOName.c_str();
-
- // If this shared library has a known runtime artifact (IMPORTED_LOCATION),
- // include its location in the runtime path ordering.
- if (!info || !info->Location.empty()) {
- this->OrderRuntimeSearchPath->AddRuntimeLibrary(fullPath, soname);
- if (this->LinkWithRuntimePath) {
- this->OrderLinkerSearchPath->AddRuntimeLibrary(fullPath, soname);
- }
+ std::string soName = target->GetSOName(this->Config);
+ const char* soname = soName.empty() ? nullptr : soName.c_str();
+
+ // Include this library in the runtime path ordering.
+ this->OrderRuntimeSearchPath->AddRuntimeLibrary(fullPath, soname);
+ if (this->LinkWithRuntimePath) {
+ this->OrderLinkerSearchPath->AddRuntimeLibrary(fullPath, soname);
}
}
diff --git a/Source/cmCoreTryCompile.cxx b/Source/cmCoreTryCompile.cxx
index 7e19812..8c84ace 100644
--- a/Source/cmCoreTryCompile.cxx
+++ b/Source/cmCoreTryCompile.cxx
@@ -626,13 +626,11 @@ cm::optional<cmTryCompileResult> cmCoreTryCompile::TryCompileCode(
// now create a CMakeLists.txt file in that directory
FILE* fout = cmsys::SystemTools::Fopen(outFileName, "w");
if (!fout) {
- std::ostringstream e;
- /* clang-format off */
- e << "Failed to open\n"
- " " << outFileName << "\n"
- << cmSystemTools::GetLastSystemError();
- /* clang-format on */
- this->Makefile->IssueMessage(MessageType::FATAL_ERROR, e.str());
+ this->Makefile->IssueMessage(
+ MessageType::FATAL_ERROR,
+ cmStrCat("Failed to open\n"
+ " ",
+ outFileName, '\n', cmSystemTools::GetLastSystemError()));
return cm::nullopt;
}
diff --git a/Source/cmCxxModuleMapper.cxx b/Source/cmCxxModuleMapper.cxx
index e6c10c6..f45c011 100644
--- a/Source/cmCxxModuleMapper.cxx
+++ b/Source/cmCxxModuleMapper.cxx
@@ -346,13 +346,16 @@ std::set<std::string> CxxModuleUsageSeed(
// Add the direct usage.
this_usages.insert(r.LogicalName);
- // Add the transitive usage.
- if (transitive_usages != usages.Usage.end()) {
+ if (transitive_usages == usages.Usage.end() ||
+ internal_usages.find(r.LogicalName) != internal_usages.end()) {
+ // Mark that we need to update transitive usages later.
+ if (bmi_loc.IsKnown()) {
+ internal_usages[p.LogicalName].insert(r.LogicalName);
+ }
+ } else {
+ // Add the transitive usage.
this_usages.insert(transitive_usages->second.begin(),
transitive_usages->second.end());
- } else if (bmi_loc.IsKnown()) {
- // Mark that we need to update transitive usages later.
- internal_usages[p.LogicalName].insert(r.LogicalName);
}
}
diff --git a/Source/cmExportCommand.cxx b/Source/cmExportCommand.cxx
index e78b869..7e44210 100644
--- a/Source/cmExportCommand.cxx
+++ b/Source/cmExportCommand.cxx
@@ -385,13 +385,11 @@ static void StorePackageRegistry(cmMakefile& mf, std::string const& package,
if (entry) {
entry << content << "\n";
} else {
- std::ostringstream e;
- /* clang-format off */
- e << "Cannot create package registry file:\n"
- << " " << fname << "\n"
- << cmSystemTools::GetLastSystemError() << "\n";
- /* clang-format on */
- mf.IssueMessage(MessageType::WARNING, e.str());
+ mf.IssueMessage(MessageType::WARNING,
+ cmStrCat("Cannot create package registry file:\n"
+ " ",
+ fname, '\n',
+ cmSystemTools::GetLastSystemError(), '\n'));
}
}
}
diff --git a/Source/cmFileCommand.cxx b/Source/cmFileCommand.cxx
index 93bed9a..c65136c 100644
--- a/Source/cmFileCommand.cxx
+++ b/Source/cmFileCommand.cxx
@@ -3022,16 +3022,15 @@ bool HandleCreateLinkCommand(std::vector<std::string> const& args,
// Check if the new file already exists and remove it.
if (cmSystemTools::PathExists(newFileName) &&
!cmSystemTools::RemoveFile(newFileName)) {
- std::ostringstream e;
- e << "Failed to create link '" << newFileName
- << "' because existing path cannot be removed: "
- << cmSystemTools::GetLastSystemError() << "\n";
+ auto err = cmStrCat("Failed to create link '", newFileName,
+ "' because existing path cannot be removed: ",
+ cmSystemTools::GetLastSystemError(), '\n');
if (!arguments.Result.empty()) {
- status.GetMakefile().AddDefinition(arguments.Result, e.str());
+ status.GetMakefile().AddDefinition(arguments.Result, err);
return true;
}
- status.SetError(e.str());
+ status.SetError(err);
return false;
}
diff --git a/Source/cmFileCopier.cxx b/Source/cmFileCopier.cxx
index 663bddc..686162b 100644
--- a/Source/cmFileCopier.cxx
+++ b/Source/cmFileCopier.cxx
@@ -86,10 +86,11 @@ bool cmFileCopier::SetPermissions(const std::string& toFile,
}
#endif
- if (!cmSystemTools::SetPermissions(toFile, permissions)) {
+ auto perm_status = cmSystemTools::SetPermissions(toFile, permissions);
+ if (!perm_status) {
std::ostringstream e;
e << this->Name << " cannot set permissions on \"" << toFile
- << "\": " << cmSystemTools::GetLastSystemError() << ".";
+ << "\": " << perm_status.GetString() << ".";
this->Status.SetError(e.str());
return false;
}
@@ -118,10 +119,9 @@ std::string const& cmFileCopier::ToName(std::string const& fromName)
bool cmFileCopier::ReportMissing(const std::string& fromFile)
{
// The input file does not exist and installation is not optional.
- std::ostringstream e;
- e << this->Name << " cannot find \"" << fromFile
- << "\": " << cmSystemTools::GetLastSystemError() << ".";
- this->Status.SetError(e.str());
+ this->Status.SetError(cmStrCat(this->Name, " cannot find \"", fromFile,
+ "\": ", cmSystemTools::GetLastSystemError(),
+ '.'));
return false;
}
@@ -530,11 +530,13 @@ bool cmFileCopier::InstallSymlink(const std::string& fromFile,
{
// Read the original symlink.
std::string symlinkTarget;
- if (!cmSystemTools::ReadSymlink(fromFile, symlinkTarget)) {
+ auto read_symlink_status =
+ cmSystemTools::ReadSymlink(fromFile, symlinkTarget);
+ if (!read_symlink_status) {
std::ostringstream e;
e << this->Name << " cannot read symlink \"" << fromFile
<< "\" to duplicate at \"" << toFile
- << "\": " << cmSystemTools::GetLastSystemError() << ".";
+ << "\": " << read_symlink_status.GetString() << ".";
this->Status.SetError(e.str());
return false;
}
@@ -604,12 +606,15 @@ bool cmFileCopier::InstallFile(const std::string& fromFile,
this->ReportCopy(toFile, TypeFile, copy);
// Copy the file.
- if (copy && !cmSystemTools::CopyAFile(fromFile, toFile, true)) {
- std::ostringstream e;
- e << this->Name << " cannot copy file \"" << fromFile << "\" to \""
- << toFile << "\": " << cmSystemTools::GetLastSystemError() << ".";
- this->Status.SetError(e.str());
- return false;
+ if (copy) {
+ auto copy_status = cmSystemTools::CopyAFile(fromFile, toFile, true);
+ if (!copy_status) {
+ std::ostringstream e;
+ e << this->Name << " cannot copy file \"" << fromFile << "\" to \""
+ << toFile << "\": " << copy_status.GetString() << ".";
+ this->Status.SetError(e.str());
+ return false;
+ }
}
// Set the file modification time of the destination file.
@@ -620,10 +625,11 @@ bool cmFileCopier::InstallFile(const std::string& fromFile,
if (cmSystemTools::GetPermissions(toFile, perm)) {
cmSystemTools::SetPermissions(toFile, perm | mode_owner_write);
}
- if (!cmFileTimes::Copy(fromFile, toFile)) {
+ auto copy_status = cmFileTimes::Copy(fromFile, toFile);
+ if (!copy_status) {
std::ostringstream e;
e << this->Name << " cannot set modification time on \"" << toFile
- << "\": " << cmSystemTools::GetLastSystemError() << ".";
+ << "\": " << copy_status.GetString() << ".";
this->Status.SetError(e.str());
return false;
}
@@ -660,10 +666,12 @@ bool cmFileCopier::InstallDirectory(const std::string& source,
}
// Make sure the destination directory exists.
- if (!cmSystemTools::MakeDirectory(destination, default_dir_mode)) {
+ auto makedir_status =
+ cmSystemTools::MakeDirectory(destination, default_dir_mode);
+ if (!makedir_status) {
std::ostringstream e;
e << this->Name << " cannot make directory \"" << destination
- << "\": " << cmSystemTools::GetLastSystemError() << ".";
+ << "\": " << makedir_status.GetString() << ".";
this->Status.SetError(e.str());
return false;
}
diff --git a/Source/cmFileLockResult.cxx b/Source/cmFileLockResult.cxx
index 632c0e9..cbe4fec 100644
--- a/Source/cmFileLockResult.cxx
+++ b/Source/cmFileLockResult.cxx
@@ -6,7 +6,7 @@
#include <cstring>
#ifdef _WIN32
-# include <Windows.h>
+# include <windows.h>
#endif
cmFileLockResult cmFileLockResult::MakeOk()
diff --git a/Source/cmFileTimes.cxx b/Source/cmFileTimes.cxx
index 0aaab1d..6835e46 100644
--- a/Source/cmFileTimes.cxx
+++ b/Source/cmFileTimes.cxx
@@ -6,6 +6,8 @@
#include <cm/memory>
+#include "cmsys/Status.hxx"
+
#include "cm_sys_stat.h"
#if defined(_WIN32)
@@ -13,6 +15,8 @@
# include "cmSystemTools.h"
#else
+# include <cerrno>
+
# include <utime.h>
#endif
@@ -66,7 +70,7 @@ cmFileTimes::cmFileTimes(std::string const& fileName)
}
cmFileTimes::~cmFileTimes() = default;
-bool cmFileTimes::Load(std::string const& fileName)
+cmsys::Status cmFileTimes::Load(std::string const& fileName)
{
std::unique_ptr<Times> ptr;
if (this->IsValid()) {
@@ -82,29 +86,29 @@ bool cmFileTimes::Load(std::string const& fileName)
GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING,
FILE_FLAG_BACKUP_SEMANTICS, 0);
if (!handle) {
- return false;
+ return cmsys::Status::Windows_GetLastError();
}
if (!GetFileTime(handle, &ptr->timeCreation, &ptr->timeLastAccess,
&ptr->timeLastWrite)) {
- return false;
+ return cmsys::Status::Windows_GetLastError();
}
#else
struct stat st;
if (stat(fileName.c_str(), &st) < 0) {
- return false;
+ return cmsys::Status::POSIX_errno();
}
ptr->timeBuf.actime = st.st_atime;
ptr->timeBuf.modtime = st.st_mtime;
#endif
// Accept times
this->times = std::move(ptr);
- return true;
+ return cmsys::Status::Success();
}
-bool cmFileTimes::Store(std::string const& fileName) const
+cmsys::Status cmFileTimes::Store(std::string const& fileName) const
{
if (!this->IsValid()) {
- return false;
+ return cmsys::Status::POSIX(EINVAL);
}
#if defined(_WIN32) && !defined(__CYGWIN__)
@@ -112,18 +116,28 @@ bool cmFileTimes::Store(std::string const& fileName) const
cmSystemTools::ConvertToWindowsExtendedPath(fileName).c_str(),
FILE_WRITE_ATTRIBUTES, 0, 0, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0);
if (!handle) {
- return false;
+ return cmsys::Status::Windows_GetLastError();
+ }
+ if (SetFileTime(handle, &this->times->timeCreation,
+ &this->times->timeLastAccess,
+ &this->times->timeLastWrite) == 0) {
+ return cmsys::Status::Windows_GetLastError();
}
- return SetFileTime(handle, &this->times->timeCreation,
- &this->times->timeLastAccess,
- &this->times->timeLastWrite) != 0;
#else
- return utime(fileName.c_str(), &this->times->timeBuf) >= 0;
+ if (utime(fileName.c_str(), &this->times->timeBuf) < 0) {
+ return cmsys::Status::POSIX_errno();
+ }
#endif
+ return cmsys::Status::Success();
}
-bool cmFileTimes::Copy(std::string const& fromFile, std::string const& toFile)
+cmsys::Status cmFileTimes::Copy(std::string const& fromFile,
+ std::string const& toFile)
{
cmFileTimes fileTimes;
- return (fileTimes.Load(fromFile) && fileTimes.Store(toFile));
+ cmsys::Status load_status = fileTimes.Load(fromFile);
+ if (!load_status) {
+ return load_status;
+ }
+ return fileTimes.Store(toFile);
}
diff --git a/Source/cmFileTimes.h b/Source/cmFileTimes.h
index 50d64fd..58d24bc 100644
--- a/Source/cmFileTimes.h
+++ b/Source/cmFileTimes.h
@@ -7,6 +7,8 @@
#include <memory>
#include <string>
+#include "cmsys/Status.hxx"
+
/** \class cmFileTimes
* \brief Loads and stores file times.
*/
@@ -21,12 +23,13 @@ public:
//! @return true, if file times were loaded successfully
bool IsValid() const { return (this->times != nullptr); }
//! Try to load the file times from @a fileName and @return IsValid()
- bool Load(std::string const& fileName);
+ cmsys::Status Load(std::string const& fileName);
//! Stores the file times at @a fileName (if IsValid())
- bool Store(std::string const& fileName) const;
+ cmsys::Status Store(std::string const& fileName) const;
//! Copies the file times of @a fromFile to @a toFile
- static bool Copy(std::string const& fromFile, std::string const& toFile);
+ static cmsys::Status Copy(std::string const& fromFile,
+ std::string const& toFile);
private:
#ifdef _WIN32
diff --git a/Source/cmGeneratorTarget.cxx b/Source/cmGeneratorTarget.cxx
index 4b4d8b9..45073f7 100644
--- a/Source/cmGeneratorTarget.cxx
+++ b/Source/cmGeneratorTarget.cxx
@@ -1258,6 +1258,19 @@ bool cmGeneratorTarget::CanCompileSources() const
return this->Target->CanCompileSources();
}
+bool cmGeneratorTarget::HasKnownRuntimeArtifactLocation(
+ std::string const& config) const
+{
+ if (!this->IsRuntimeBinary()) {
+ return false;
+ }
+ if (!this->IsImported()) {
+ return true;
+ }
+ ImportInfo const* info = this->GetImportInfo(config);
+ return info && !info->Location.empty();
+}
+
const std::string& cmGeneratorTarget::GetLocationForBuild() const
{
static std::string location;
diff --git a/Source/cmGeneratorTarget.h b/Source/cmGeneratorTarget.h
index 2a301e3..c13b2f6 100644
--- a/Source/cmGeneratorTarget.h
+++ b/Source/cmGeneratorTarget.h
@@ -58,6 +58,7 @@ public:
bool IsImported() const;
bool IsImportedGloballyVisible() const;
bool CanCompileSources() const;
+ bool HasKnownRuntimeArtifactLocation(std::string const& config) const;
const std::string& GetLocation(const std::string& config) const;
/** Get the full path to the target's main artifact, if known. */
@@ -1097,7 +1098,6 @@ private:
std::string SharedDeps;
};
- friend cmComputeLinkInformation;
using ImportInfoMapType = std::map<std::string, ImportInfo>;
mutable ImportInfoMapType ImportInfoMap;
void ComputeImportInfo(std::string const& desired_config,
diff --git a/Source/cmLocalGenerator.cxx b/Source/cmLocalGenerator.cxx
index fe8d502..caac535 100644
--- a/Source/cmLocalGenerator.cxx
+++ b/Source/cmLocalGenerator.cxx
@@ -2706,6 +2706,9 @@ void cmLocalGenerator::AddPchDependencies(cmGeneratorTarget* target)
auto* pch_sf = this->Makefile->GetOrCreateSource(
pchSource, false, cmSourceFileLocationKind::Known);
+ // PCH sources should never be scanned as they cannot contain C++
+ // module references.
+ pch_sf->SetProperty("CXX_SCAN_FOR_MODULES", "0");
if (!this->GetGlobalGenerator()->IsXcode()) {
if (!ReuseFrom) {
diff --git a/Source/cmNinjaTargetGenerator.cxx b/Source/cmNinjaTargetGenerator.cxx
index 2283923..4025918 100644
--- a/Source/cmNinjaTargetGenerator.cxx
+++ b/Source/cmNinjaTargetGenerator.cxx
@@ -1367,7 +1367,10 @@ void cmNinjaTargetGenerator::WriteObjectBuildStatement(
!(language == "RC" || (language == "CUDA" && !flag));
int const commandLineLengthLimit =
((lang_supports_response && this->ForceResponseFile())) ? -1 : 0;
- bool const needDyndep =
+ cmValue pchExtension =
+ this->GetMakefile()->GetDefinition("CMAKE_PCH_EXTENSION");
+ bool const isPch = cmHasSuffix(objectFileName, pchExtension);
+ bool const needDyndep = !isPch &&
this->GeneratorTarget->NeedDyndepForSource(language, config, source);
cmNinjaBuild objBuild(this->LanguageCompilerRule(
@@ -1435,13 +1438,9 @@ void cmNinjaTargetGenerator::WriteObjectBuildStatement(
}
objBuild.Outputs.push_back(objectFileName);
- if (firstForConfig) {
- cmValue pchExtension =
- this->GetMakefile()->GetDefinition("CMAKE_PCH_EXTENSION");
- if (!cmHasSuffix(objectFileName, pchExtension)) {
- // Add this object to the list of object files.
- this->Configs[config].Objects.push_back(objectFileName);
- }
+ if (firstForConfig && !isPch) {
+ // Add this object to the list of object files.
+ this->Configs[config].Objects.push_back(objectFileName);
}
objBuild.ExplicitDeps.push_back(sourceFilePath);
diff --git a/Source/cmake.cxx b/Source/cmake.cxx
index 942c59b..f54196b 100644
--- a/Source/cmake.cxx
+++ b/Source/cmake.cxx
@@ -1707,10 +1707,8 @@ void cmake::SetTraceFile(const std::string& file)
this->TraceFile.close();
this->TraceFile.open(file.c_str());
if (!this->TraceFile) {
- std::stringstream ss;
- ss << "Error opening trace file " << file << ": "
- << cmSystemTools::GetLastSystemError();
- cmSystemTools::Error(ss.str());
+ cmSystemTools::Error(cmStrCat("Error opening trace file ", file, ": ",
+ cmSystemTools::GetLastSystemError()));
return;
}
std::cout << "Trace will be written to " << file << '\n';
diff --git a/Tests/CMakeLists.txt b/Tests/CMakeLists.txt
index 4c61eab..a1619ec 100644
--- a/Tests/CMakeLists.txt
+++ b/Tests/CMakeLists.txt
@@ -2154,10 +2154,7 @@ if(BUILD_TESTING)
endif()
set(MSVCDebugInformationFormat_BUILD_OPTIONS -DCMake_TEST_CUDA=${CMake_TEST_CUDA})
- if(CMAKE_Fortran_COMPILER
- # FIXME(LLVMFlang): It does not provide debug information format flags or predefines.
- AND NOT CMAKE_Fortran_COMPILER_ID STREQUAL "LLVMFlang"
- )
+ if(CMAKE_Fortran_COMPILER)
list(APPEND MSVCDebugInformationFormat_BUILD_OPTIONS -DCMake_TEST_Fortran=1)
endif()
ADD_TEST_MACRO(MSVCDebugInformationFormat)
diff --git a/Tests/MSVCDebugInformationFormat/override-Fortran.cmake b/Tests/MSVCDebugInformationFormat/override-Fortran.cmake
index 5d2db58..8bc2067 100644
--- a/Tests/MSVCDebugInformationFormat/override-Fortran.cmake
+++ b/Tests/MSVCDebugInformationFormat/override-Fortran.cmake
@@ -2,3 +2,11 @@ set(var "CMAKE_Fortran_COMPILE_OPTIONS_MSVC_DEBUG_INFORMATION_FORMAT_Embedded")
string(REPLACE "-Z7" "-Z7;-DTEST_Z7" "${var}" "${${var}}")
set(var "CMAKE_Fortran_COMPILE_OPTIONS_MSVC_DEBUG_INFORMATION_FORMAT_ProgramDatabase")
string(REPLACE "-Zi" "-Zi;-DTEST_Zi" "${var}" "${${var}}")
+
+if(CMAKE_Fortran_COMPILER_ID STREQUAL "LLVMFlang")
+ set(var "CMAKE_Fortran_COMPILE_OPTIONS_MSVC_DEBUG_INFORMATION_FORMAT_Embedded")
+ string(REPLACE "-g" "-g;-DTEST_Z7" "${var}" "${${var}}")
+ # LLVMFlang does not actually support these, but Windows-LLVMFlang-Fortran pretends it does.
+ set(CMAKE_Fortran_COMPILE_OPTIONS_MSVC_DEBUG_INFORMATION_FORMAT_ProgramDatabase "-DTEST_Zi")
+ set(CMAKE_Fortran_COMPILE_OPTIONS_MSVC_DEBUG_INFORMATION_FORMAT_EditAndContinue "-DTEST_ZI")
+endif()
diff --git a/Tests/RunCMake/CXXModules/RunCMakeTest.cmake b/Tests/RunCMake/CXXModules/RunCMakeTest.cmake
index 781c708..fcfa60a 100644
--- a/Tests/RunCMake/CXXModules/RunCMakeTest.cmake
+++ b/Tests/RunCMake/CXXModules/RunCMakeTest.cmake
@@ -165,6 +165,8 @@ if (RunCMake_GENERATOR MATCHES "Ninja")
run_cxx_module_test_target(ninja-cmp0154 "${ninja_cmp0154_target}")
endif ()
+run_cxx_module_test(scan-with-pch)
+
# Tests which use named modules.
if ("named" IN_LIST CMake_TEST_MODULE_COMPILATION)
run_cxx_module_test(simple)
@@ -172,6 +174,8 @@ if ("named" IN_LIST CMake_TEST_MODULE_COMPILATION)
run_cxx_module_test(object-library)
run_cxx_module_test(generated)
run_cxx_module_test(deep-chain)
+ run_cxx_module_test(non-trivial-collation-order)
+ run_cxx_module_test(non-trivial-collation-order-randomized)
run_cxx_module_test(duplicate)
set(RunCMake_CXXModules_NO_TEST 1)
run_cxx_module_test(circular)
diff --git a/Tests/RunCMake/CXXModules/examples/circular-build-stdout.txt b/Tests/RunCMake/CXXModules/examples/circular-build-stdout.txt
index ac80356..f6f5e5f 100644
--- a/Tests/RunCMake/CXXModules/examples/circular-build-stdout.txt
+++ b/Tests/RunCMake/CXXModules/examples/circular-build-stdout.txt
@@ -1 +1 @@
-((Ninja generators)?(build stopped: dependency cycle:)|(Visual Studio generators)?(error : Cannot build the following source files because there is a cyclic dependency between them))
+((Ninja generators)?(CMake Error: Circular dependency detected in the C\+\+ module import graph. See modules named: "a", "b")|(Visual Studio generators)?(error : Cannot build the following source files because there is a cyclic dependency between them))
diff --git a/Tests/RunCMake/CXXModules/examples/non-trivial-collation-order-randomized/CMakeLists.txt b/Tests/RunCMake/CXXModules/examples/non-trivial-collation-order-randomized/CMakeLists.txt
new file mode 100644
index 0000000..4e1e7af
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/examples/non-trivial-collation-order-randomized/CMakeLists.txt
@@ -0,0 +1,9 @@
+cmake_minimum_required(VERSION 3.24...3.28)
+project(cxx_modules_non_trivial_collation_order_randomized CXX)
+
+include("${CMAKE_SOURCE_DIR}/../cxx-modules-rules.cmake")
+
+set(non_trivial_collation_order_randomized TRUE)
+
+add_subdirectory("${CMAKE_CURRENT_SOURCE_DIR}/../non-trivial-collation-order/"
+ "${CMAKE_CURRENT_BINARY_DIR}/non-trivial-collation-order")
diff --git a/Tests/RunCMake/CXXModules/examples/non-trivial-collation-order/CMakeLists.txt b/Tests/RunCMake/CXXModules/examples/non-trivial-collation-order/CMakeLists.txt
new file mode 100644
index 0000000..218b45f
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/examples/non-trivial-collation-order/CMakeLists.txt
@@ -0,0 +1,132 @@
+cmake_minimum_required(VERSION 3.24...3.28)
+project(cxx_modules_non_trivial_collation_order CXX)
+
+include("${CMAKE_SOURCE_DIR}/../cxx-modules-rules.cmake")
+
+if (CMAKE_CXX_COMPILER_ID MATCHES "Clang")
+ include(CheckCompilerFlag)
+ check_compiler_flag(CXX "-Wread-modules-implicitly" have_implicit_module_warning)
+ if (have_implicit_module_warning)
+ add_compile_options(-Werror=read-modules-implicitly)
+ endif ()
+endif ()
+
+# Returns an random integer from range [0,length)
+function(get_random_index result length)
+ # math(EXPR) parses and evaluates as 64-bit signed integer.
+ string(RANDOM LENGTH 18 ALPHABET "0123456789" value)
+ # Modulo is not uniformly distributed, but we doesn't need that here.
+ math(EXPR ${result} "${value} % ${length}")
+ return(PROPAGATE ${result})
+endfunction()
+
+# Shuffle list_var randomly
+function(shuffle_list list_var)
+ set(result)
+ set(length 0)
+ foreach(item IN LISTS "${list_var}")
+ math(EXPR length "${length} + 1")
+ get_random_index(index ${length})
+ list(INSERT result ${index} "${item}")
+ endforeach()
+ set("${list_var}" "${result}" PARENT_SCOPE)
+endfunction()
+
+# The import chain is:
+# impl-non-partition --(implicitly)--> partition_level(primary interface unit)
+# --> :intf7 --> :intf6 --> :intf5 --> :intf4 --> :intf3 --> :intf2 --> :intf1
+# --> :impl7 --> :impl6 --> :impl5 --> :impl4 --> :impl3 --> :impl2 --> :impl1
+set(partition_level_srcs
+ partition_level/partition_level.cxx
+ partition_level/intf1.cxx
+ partition_level/intf3.cxx
+ partition_level/intf4.cxx
+ partition_level/intf2.cxx # intentional order
+ partition_level/intf5.cxx
+ partition_level/intf6.cxx
+ partition_level/intf7.cxx
+ partition_level/impl1.cxx
+ partition_level/impl3.cxx
+ partition_level/impl4.cxx
+ partition_level/impl2.cxx # intentional order
+ partition_level/impl5.cxx
+ partition_level/impl6.cxx
+ partition_level/impl7.cxx
+)
+
+# The import chain is:
+# mod7 --> mod6 --> mod5 --> mod4 --> mod3 --> mod2 --> mod1 --> partition_level
+set(module_level_srcs
+ ${partition_level_srcs}
+ module_level/mod1.cxx
+ module_level/mod3.cxx
+ module_level/mod4.cxx
+ module_level/mod2.cxx # intentional order
+ module_level/mod5.cxx
+ module_level/mod6.cxx
+ module_level/mod7.cxx
+)
+
+# The import chain is:
+# target7 --> target6 --> target5 --> target4 -->
+# target3 --> target2 --> target1 --> target_module_level
+set(targets
+ target_module_level
+ target1
+ target3
+ target4
+ target2 # intentional order
+ target5
+ target6
+ target7
+)
+
+if(non_trivial_collation_order_randomized)
+ shuffle_list(module_level_srcs)
+ shuffle_list(targets)
+endif()
+
+message(STATUS "module_level_srcs: ${module_level_srcs}")
+message(STATUS "targets: ${targets}")
+
+foreach(tgt IN LISTS targets)
+ if (tgt STREQUAL "target_module_level")
+
+ add_library(target_module_level STATIC)
+ target_sources(target_module_level
+ PUBLIC
+ FILE_SET CXX_MODULES
+ BASE_DIRS "${CMAKE_CURRENT_SOURCE_DIR}"
+ FILES ${module_level_srcs}
+ PRIVATE
+ partition_level/impl-non-partition.cxx
+ )
+ target_compile_features(target_module_level PUBLIC cxx_std_20)
+
+ else()
+
+ add_library(${tgt} STATIC)
+ target_sources(${tgt}
+ PUBLIC
+ FILE_SET CXX_MODULES
+ BASE_DIRS "${CMAKE_CURRENT_SOURCE_DIR}"
+ FILES target_level/${tgt}.cxx
+ )
+ target_compile_features(${tgt} PUBLIC cxx_std_20)
+ if (tgt MATCHES "^target([2-9])$")
+ math(EXPR dep_number "${CMAKE_MATCH_1} - 1")
+ target_link_libraries(${tgt} PRIVATE "target${dep_number}")
+ else()
+ target_link_libraries(${tgt} PRIVATE target_module_level)
+ endif()
+
+ endif()
+endforeach()
+
+add_executable(exe)
+target_link_libraries(exe PRIVATE target7)
+target_sources(exe
+ PRIVATE
+ main.cxx)
+
+add_test(NAME exe COMMAND exe)
diff --git a/Tests/RunCMake/CXXModules/examples/non-trivial-collation-order/main.cxx b/Tests/RunCMake/CXXModules/examples/non-trivial-collation-order/main.cxx
new file mode 100644
index 0000000..6496776
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/examples/non-trivial-collation-order/main.cxx
@@ -0,0 +1,6 @@
+import target7;
+
+int main()
+{
+ return target7();
+}
diff --git a/Tests/RunCMake/CXXModules/examples/non-trivial-collation-order/module_level/mod1.cxx b/Tests/RunCMake/CXXModules/examples/non-trivial-collation-order/module_level/mod1.cxx
new file mode 100644
index 0000000..1999688
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/examples/non-trivial-collation-order/module_level/mod1.cxx
@@ -0,0 +1,7 @@
+export module mod1;
+import partition_level;
+
+export int mod1()
+{
+ return partition_level::get();
+}
diff --git a/Tests/RunCMake/CXXModules/examples/non-trivial-collation-order/module_level/mod2.cxx b/Tests/RunCMake/CXXModules/examples/non-trivial-collation-order/module_level/mod2.cxx
new file mode 100644
index 0000000..454899f
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/examples/non-trivial-collation-order/module_level/mod2.cxx
@@ -0,0 +1,7 @@
+export module mod2;
+import mod1;
+
+export int mod2()
+{
+ return mod1();
+}
diff --git a/Tests/RunCMake/CXXModules/examples/non-trivial-collation-order/module_level/mod3.cxx b/Tests/RunCMake/CXXModules/examples/non-trivial-collation-order/module_level/mod3.cxx
new file mode 100644
index 0000000..85dea1e
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/examples/non-trivial-collation-order/module_level/mod3.cxx
@@ -0,0 +1,7 @@
+export module mod3;
+import mod2;
+
+export int mod3()
+{
+ return mod2();
+}
diff --git a/Tests/RunCMake/CXXModules/examples/non-trivial-collation-order/module_level/mod4.cxx b/Tests/RunCMake/CXXModules/examples/non-trivial-collation-order/module_level/mod4.cxx
new file mode 100644
index 0000000..e6143d7
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/examples/non-trivial-collation-order/module_level/mod4.cxx
@@ -0,0 +1,7 @@
+export module mod4;
+import mod3;
+
+export int mod4()
+{
+ return mod3();
+}
diff --git a/Tests/RunCMake/CXXModules/examples/non-trivial-collation-order/module_level/mod5.cxx b/Tests/RunCMake/CXXModules/examples/non-trivial-collation-order/module_level/mod5.cxx
new file mode 100644
index 0000000..94355a9
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/examples/non-trivial-collation-order/module_level/mod5.cxx
@@ -0,0 +1,7 @@
+export module mod5;
+import mod4;
+
+export int mod5()
+{
+ return mod4();
+}
diff --git a/Tests/RunCMake/CXXModules/examples/non-trivial-collation-order/module_level/mod6.cxx b/Tests/RunCMake/CXXModules/examples/non-trivial-collation-order/module_level/mod6.cxx
new file mode 100644
index 0000000..998ed8b
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/examples/non-trivial-collation-order/module_level/mod6.cxx
@@ -0,0 +1,7 @@
+export module mod6;
+import mod5;
+
+export int mod6()
+{
+ return mod5();
+}
diff --git a/Tests/RunCMake/CXXModules/examples/non-trivial-collation-order/module_level/mod7.cxx b/Tests/RunCMake/CXXModules/examples/non-trivial-collation-order/module_level/mod7.cxx
new file mode 100644
index 0000000..15c52b0
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/examples/non-trivial-collation-order/module_level/mod7.cxx
@@ -0,0 +1,7 @@
+export module mod7;
+import mod6;
+
+export int mod7()
+{
+ return mod6();
+}
diff --git a/Tests/RunCMake/CXXModules/examples/non-trivial-collation-order/partition_level/impl-non-partition.cxx b/Tests/RunCMake/CXXModules/examples/non-trivial-collation-order/partition_level/impl-non-partition.cxx
new file mode 100644
index 0000000..0cf184f
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/examples/non-trivial-collation-order/partition_level/impl-non-partition.cxx
@@ -0,0 +1,10 @@
+module partition_level;
+
+namespace partition_level {
+int non_partition()
+{
+ return primary() + intf1() + intf2() + intf3() + intf4() + intf5() +
+ intf6() + intf7() + impl1() + impl2() + impl3() + impl4() + impl5() +
+ impl6() + impl7();
+}
+}
diff --git a/Tests/RunCMake/CXXModules/examples/non-trivial-collation-order/partition_level/impl1.cxx b/Tests/RunCMake/CXXModules/examples/non-trivial-collation-order/partition_level/impl1.cxx
new file mode 100644
index 0000000..86c27c6
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/examples/non-trivial-collation-order/partition_level/impl1.cxx
@@ -0,0 +1,7 @@
+module partition_level:impl1;
+namespace partition_level {
+int impl1()
+{
+ return 0;
+}
+}
diff --git a/Tests/RunCMake/CXXModules/examples/non-trivial-collation-order/partition_level/impl2.cxx b/Tests/RunCMake/CXXModules/examples/non-trivial-collation-order/partition_level/impl2.cxx
new file mode 100644
index 0000000..49d10e3
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/examples/non-trivial-collation-order/partition_level/impl2.cxx
@@ -0,0 +1,8 @@
+module partition_level:impl2;
+import :impl1;
+namespace partition_level {
+int impl2()
+{
+ return impl1();
+}
+}
diff --git a/Tests/RunCMake/CXXModules/examples/non-trivial-collation-order/partition_level/impl3.cxx b/Tests/RunCMake/CXXModules/examples/non-trivial-collation-order/partition_level/impl3.cxx
new file mode 100644
index 0000000..cbd183b
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/examples/non-trivial-collation-order/partition_level/impl3.cxx
@@ -0,0 +1,8 @@
+module partition_level:impl3;
+import :impl2;
+namespace partition_level {
+int impl3()
+{
+ return impl2();
+}
+}
diff --git a/Tests/RunCMake/CXXModules/examples/non-trivial-collation-order/partition_level/impl4.cxx b/Tests/RunCMake/CXXModules/examples/non-trivial-collation-order/partition_level/impl4.cxx
new file mode 100644
index 0000000..7ce9390
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/examples/non-trivial-collation-order/partition_level/impl4.cxx
@@ -0,0 +1,8 @@
+module partition_level:impl4;
+import :impl3;
+namespace partition_level {
+int impl4()
+{
+ return impl3();
+}
+}
diff --git a/Tests/RunCMake/CXXModules/examples/non-trivial-collation-order/partition_level/impl5.cxx b/Tests/RunCMake/CXXModules/examples/non-trivial-collation-order/partition_level/impl5.cxx
new file mode 100644
index 0000000..901eda9
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/examples/non-trivial-collation-order/partition_level/impl5.cxx
@@ -0,0 +1,8 @@
+module partition_level:impl5;
+import :impl4;
+namespace partition_level {
+int impl5()
+{
+ return impl4();
+}
+}
diff --git a/Tests/RunCMake/CXXModules/examples/non-trivial-collation-order/partition_level/impl6.cxx b/Tests/RunCMake/CXXModules/examples/non-trivial-collation-order/partition_level/impl6.cxx
new file mode 100644
index 0000000..38130c7
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/examples/non-trivial-collation-order/partition_level/impl6.cxx
@@ -0,0 +1,8 @@
+module partition_level:impl6;
+import :impl5;
+namespace partition_level {
+int impl6()
+{
+ return impl5();
+}
+}
diff --git a/Tests/RunCMake/CXXModules/examples/non-trivial-collation-order/partition_level/impl7.cxx b/Tests/RunCMake/CXXModules/examples/non-trivial-collation-order/partition_level/impl7.cxx
new file mode 100644
index 0000000..c3b1322
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/examples/non-trivial-collation-order/partition_level/impl7.cxx
@@ -0,0 +1,8 @@
+module partition_level:impl7;
+import :impl6;
+namespace partition_level {
+int impl7()
+{
+ return impl6();
+}
+}
diff --git a/Tests/RunCMake/CXXModules/examples/non-trivial-collation-order/partition_level/intf1.cxx b/Tests/RunCMake/CXXModules/examples/non-trivial-collation-order/partition_level/intf1.cxx
new file mode 100644
index 0000000..5d8500d
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/examples/non-trivial-collation-order/partition_level/intf1.cxx
@@ -0,0 +1,8 @@
+export module partition_level:intf1;
+import :impl7;
+namespace partition_level {
+int intf1()
+{
+ return impl7();
+}
+}
diff --git a/Tests/RunCMake/CXXModules/examples/non-trivial-collation-order/partition_level/intf2.cxx b/Tests/RunCMake/CXXModules/examples/non-trivial-collation-order/partition_level/intf2.cxx
new file mode 100644
index 0000000..76c6eed
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/examples/non-trivial-collation-order/partition_level/intf2.cxx
@@ -0,0 +1,8 @@
+export module partition_level:intf2;
+export import :intf1;
+namespace partition_level {
+int intf2()
+{
+ return intf1();
+}
+}
diff --git a/Tests/RunCMake/CXXModules/examples/non-trivial-collation-order/partition_level/intf3.cxx b/Tests/RunCMake/CXXModules/examples/non-trivial-collation-order/partition_level/intf3.cxx
new file mode 100644
index 0000000..3b16053
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/examples/non-trivial-collation-order/partition_level/intf3.cxx
@@ -0,0 +1,8 @@
+export module partition_level:intf3;
+export import :intf2;
+namespace partition_level {
+int intf3()
+{
+ return intf2();
+}
+}
diff --git a/Tests/RunCMake/CXXModules/examples/non-trivial-collation-order/partition_level/intf4.cxx b/Tests/RunCMake/CXXModules/examples/non-trivial-collation-order/partition_level/intf4.cxx
new file mode 100644
index 0000000..2826717
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/examples/non-trivial-collation-order/partition_level/intf4.cxx
@@ -0,0 +1,8 @@
+export module partition_level:intf4;
+export import :intf3;
+namespace partition_level {
+int intf4()
+{
+ return intf3();
+}
+}
diff --git a/Tests/RunCMake/CXXModules/examples/non-trivial-collation-order/partition_level/intf5.cxx b/Tests/RunCMake/CXXModules/examples/non-trivial-collation-order/partition_level/intf5.cxx
new file mode 100644
index 0000000..ede117e
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/examples/non-trivial-collation-order/partition_level/intf5.cxx
@@ -0,0 +1,8 @@
+export module partition_level:intf5;
+export import :intf4;
+namespace partition_level {
+int intf5()
+{
+ return intf4();
+}
+}
diff --git a/Tests/RunCMake/CXXModules/examples/non-trivial-collation-order/partition_level/intf6.cxx b/Tests/RunCMake/CXXModules/examples/non-trivial-collation-order/partition_level/intf6.cxx
new file mode 100644
index 0000000..c89a554
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/examples/non-trivial-collation-order/partition_level/intf6.cxx
@@ -0,0 +1,8 @@
+export module partition_level:intf6;
+export import :intf5;
+namespace partition_level {
+int intf6()
+{
+ return intf5();
+}
+}
diff --git a/Tests/RunCMake/CXXModules/examples/non-trivial-collation-order/partition_level/intf7.cxx b/Tests/RunCMake/CXXModules/examples/non-trivial-collation-order/partition_level/intf7.cxx
new file mode 100644
index 0000000..ee0b250
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/examples/non-trivial-collation-order/partition_level/intf7.cxx
@@ -0,0 +1,8 @@
+export module partition_level:intf7;
+export import :intf6;
+namespace partition_level {
+int intf7()
+{
+ return intf6();
+}
+}
diff --git a/Tests/RunCMake/CXXModules/examples/non-trivial-collation-order/partition_level/partition_level.cxx b/Tests/RunCMake/CXXModules/examples/non-trivial-collation-order/partition_level/partition_level.cxx
new file mode 100644
index 0000000..7f3ddb2
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/examples/non-trivial-collation-order/partition_level/partition_level.cxx
@@ -0,0 +1,15 @@
+export module partition_level;
+export import :intf7;
+namespace partition_level {
+int primary()
+{
+ return intf7();
+}
+
+int non_partition();
+
+export int get()
+{
+ return non_partition();
+}
+}
diff --git a/Tests/RunCMake/CXXModules/examples/non-trivial-collation-order/target_level/target1.cxx b/Tests/RunCMake/CXXModules/examples/non-trivial-collation-order/target_level/target1.cxx
new file mode 100644
index 0000000..5487e21
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/examples/non-trivial-collation-order/target_level/target1.cxx
@@ -0,0 +1,7 @@
+export module target1;
+import mod7;
+
+export int target1()
+{
+ return mod7();
+}
diff --git a/Tests/RunCMake/CXXModules/examples/non-trivial-collation-order/target_level/target2.cxx b/Tests/RunCMake/CXXModules/examples/non-trivial-collation-order/target_level/target2.cxx
new file mode 100644
index 0000000..52c87dc
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/examples/non-trivial-collation-order/target_level/target2.cxx
@@ -0,0 +1,7 @@
+export module target2;
+import target1;
+
+export int target2()
+{
+ return target1();
+}
diff --git a/Tests/RunCMake/CXXModules/examples/non-trivial-collation-order/target_level/target3.cxx b/Tests/RunCMake/CXXModules/examples/non-trivial-collation-order/target_level/target3.cxx
new file mode 100644
index 0000000..4a1a3c0
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/examples/non-trivial-collation-order/target_level/target3.cxx
@@ -0,0 +1,7 @@
+export module target3;
+import target2;
+
+export int target3()
+{
+ return target2();
+}
diff --git a/Tests/RunCMake/CXXModules/examples/non-trivial-collation-order/target_level/target4.cxx b/Tests/RunCMake/CXXModules/examples/non-trivial-collation-order/target_level/target4.cxx
new file mode 100644
index 0000000..da1bf9d
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/examples/non-trivial-collation-order/target_level/target4.cxx
@@ -0,0 +1,7 @@
+export module target4;
+import target3;
+
+export int target4()
+{
+ return target3();
+}
diff --git a/Tests/RunCMake/CXXModules/examples/non-trivial-collation-order/target_level/target5.cxx b/Tests/RunCMake/CXXModules/examples/non-trivial-collation-order/target_level/target5.cxx
new file mode 100644
index 0000000..f18df7a
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/examples/non-trivial-collation-order/target_level/target5.cxx
@@ -0,0 +1,7 @@
+export module target5;
+import target4;
+
+export int target5()
+{
+ return target4();
+}
diff --git a/Tests/RunCMake/CXXModules/examples/non-trivial-collation-order/target_level/target6.cxx b/Tests/RunCMake/CXXModules/examples/non-trivial-collation-order/target_level/target6.cxx
new file mode 100644
index 0000000..a598df8
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/examples/non-trivial-collation-order/target_level/target6.cxx
@@ -0,0 +1,7 @@
+export module target6;
+import target5;
+
+export int target6()
+{
+ return target5();
+}
diff --git a/Tests/RunCMake/CXXModules/examples/non-trivial-collation-order/target_level/target7.cxx b/Tests/RunCMake/CXXModules/examples/non-trivial-collation-order/target_level/target7.cxx
new file mode 100644
index 0000000..641cfbc
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/examples/non-trivial-collation-order/target_level/target7.cxx
@@ -0,0 +1,7 @@
+export module target7;
+import target6;
+
+export int target7()
+{
+ return target6();
+}
diff --git a/Tests/RunCMake/CXXModules/examples/scan-with-pch/CMakeLists.txt b/Tests/RunCMake/CXXModules/examples/scan-with-pch/CMakeLists.txt
new file mode 100644
index 0000000..e3e7561
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/examples/scan-with-pch/CMakeLists.txt
@@ -0,0 +1,13 @@
+cmake_minimum_required(VERSION 3.28)
+project(cxx_modules_scan_with_pch CXX)
+
+include("${CMAKE_SOURCE_DIR}/../cxx-modules-rules.cmake")
+
+add_executable(simple)
+target_sources(simple
+ PRIVATE
+ main.cxx)
+target_compile_features(simple PUBLIC cxx_std_20)
+target_precompile_headers(simple PRIVATE pch.h)
+
+add_test(NAME simple COMMAND simple)
diff --git a/Tests/RunCMake/CXXModules/examples/scan-with-pch/main.cxx b/Tests/RunCMake/CXXModules/examples/scan-with-pch/main.cxx
new file mode 100644
index 0000000..33bd41e
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/examples/scan-with-pch/main.cxx
@@ -0,0 +1,8 @@
+#ifndef from_pch
+# error "pch not present"
+#endif
+
+int main(int argc, char* argv[])
+{
+ return 0;
+}
diff --git a/Tests/RunCMake/CXXModules/examples/scan-with-pch/pch.h b/Tests/RunCMake/CXXModules/examples/scan-with-pch/pch.h
new file mode 100644
index 0000000..2841ee9
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/examples/scan-with-pch/pch.h
@@ -0,0 +1 @@
+#define from_pch
diff --git a/Utilities/cmlibuv/src/win/process.c b/Utilities/cmlibuv/src/win/process.c
index 02b6c26..7df3540 100644
--- a/Utilities/cmlibuv/src/win/process.c
+++ b/Utilities/cmlibuv/src/win/process.c
@@ -274,16 +274,19 @@ static WCHAR* path_search_walk_ext(const WCHAR *dir,
const WCHAR *name,
size_t name_len,
WCHAR *cwd,
- size_t cwd_len) {
+ size_t cwd_len,
+ int name_has_ext) {
WCHAR* result;
- /* Try the name itself first */
- result = search_path_join_test(dir, dir_len,
- name, name_len,
- L"", 0,
- cwd, cwd_len);
- if (result != NULL) {
- return result;
+ /* If the name itself has a nonempty extension, try this extension first */
+ if (name_has_ext) {
+ result = search_path_join_test(dir, dir_len,
+ name, name_len,
+ L"", 0,
+ cwd, cwd_len);
+ if (result != NULL) {
+ return result;
+ }
}
/* Try .com extension */
@@ -326,7 +329,10 @@ static WCHAR* path_search_walk_ext(const WCHAR *dir,
* - If there's really only a filename, check the current directory for file,
* then search all path directories.
*
- * - Search for the file exactly as specified first.
+ * - If a full path is specified, search for the exact filename first.
+ *
+ * - If filename specified has *any* extension, search for the file with the
+ * specified extension first.
*
* - If the literal filename is not found in a directory, try *appending*
* (not replacing) .com first and then .exe.
@@ -356,8 +362,10 @@ static WCHAR* search_path(const WCHAR *file,
int file_has_dir;
WCHAR* result = NULL;
WCHAR *file_name_start;
+ WCHAR *dot;
const WCHAR *dir_start, *dir_end, *dir_path;
size_t dir_len;
+ int name_has_ext;
size_t file_len = wcslen(file);
size_t cwd_len = wcslen(cwd);
@@ -381,12 +389,19 @@ static WCHAR* search_path(const WCHAR *file,
file_has_dir = file_name_start != file;
+ /* Check if the filename includes an extension */
+ dot = wcschr(file_name_start, L'.');
+ name_has_ext = (dot != NULL && dot[1] != L'\0');
+
if (file_has_dir) {
- /* The file has a path inside, don't use path */
+ /* The file has a path inside, don't use path
+ * Try the exact filename first, and then try standard extensions
+ */
result = path_search_walk_ext(
file, file_name_start - file,
file_name_start, file_len - (file_name_start - file),
- cwd, cwd_len);
+ cwd, cwd_len,
+ 1);
} else {
dir_end = path;
@@ -395,7 +410,8 @@ static WCHAR* search_path(const WCHAR *file,
/* The file is really only a name; look in cwd first, then scan path */
result = path_search_walk_ext(L"", 0,
file, file_len,
- cwd, cwd_len);
+ cwd, cwd_len,
+ name_has_ext);
}
while (result == NULL) {
@@ -444,7 +460,8 @@ static WCHAR* search_path(const WCHAR *file,
result = path_search_walk_ext(dir_path, dir_len,
file, file_len,
- cwd, cwd_len);
+ cwd, cwd_len,
+ name_has_ext);
}
}