diff options
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); } } |