diff options
-rw-r--r-- | Modules/Compiler/Clang-CXX.cmake | 28 | ||||
-rw-r--r-- | Source/cmCxxModuleMapper.cxx | 8 | ||||
-rw-r--r-- | Source/cmCxxModuleMapper.h | 2 | ||||
-rw-r--r-- | Source/cmDyndepCollation.cxx | 49 | ||||
-rw-r--r-- | Source/cmGlobalNinjaGenerator.cxx | 53 | ||||
-rw-r--r-- | Source/cmGlobalNinjaGenerator.h | 1 | ||||
-rw-r--r-- | Source/cmLocalNinjaGenerator.cxx | 27 | ||||
-rw-r--r-- | Source/cmNinjaTargetGenerator.cxx | 4 |
8 files changed, 96 insertions, 76 deletions
diff --git a/Modules/Compiler/Clang-CXX.cmake b/Modules/Compiler/Clang-CXX.cmake index 33154fd..a74e90b 100644 --- a/Modules/Compiler/Clang-CXX.cmake +++ b/Modules/Compiler/Clang-CXX.cmake @@ -30,16 +30,18 @@ if("x${CMAKE_CXX_COMPILER_FRONTEND_VARIANT}" STREQUAL "xMSVC") endif() endif() -if (CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 16.0) - string(CONCAT CMAKE_EXPERIMENTAL_CXX_SCANDEP_SOURCE - "${CMAKE_CXX_COMPILER_CLANG_SCAN_DEPS}" - " -format=p1689" - " --" - " <CMAKE_CXX_COMPILER> <DEFINES> <INCLUDES> <FLAGS>" - " -x c++ <SOURCE> -c -o <OBJECT>" - " -MT <DYNDEP_FILE>" - " -MD -MF <DEP_FILE>" - " > <DYNDEP_FILE>") - set(CMAKE_EXPERIMENTAL_CXX_MODULE_MAP_FORMAT "clang") - set(CMAKE_EXPERIMENTAL_CXX_MODULE_MAP_FLAG "@<MODULE_MAP_FILE>") -endif () +if(CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 16.0) + if("x${CMAKE_CXX_COMPILER_FRONTEND_VARIANT}" STREQUAL "xGNU") + string(CONCAT CMAKE_EXPERIMENTAL_CXX_SCANDEP_SOURCE + "\"${CMAKE_CXX_COMPILER_CLANG_SCAN_DEPS}\"" + " -format=p1689" + " --" + " <CMAKE_CXX_COMPILER> <DEFINES> <INCLUDES> <FLAGS>" + " -x c++ <SOURCE> -c -o <OBJECT>" + " -MT <DYNDEP_FILE>" + " -MD -MF <DEP_FILE>" + " > <DYNDEP_FILE>") + set(CMAKE_EXPERIMENTAL_CXX_MODULE_MAP_FORMAT "clang") + set(CMAKE_EXPERIMENTAL_CXX_MODULE_MAP_FLAG "@<MODULE_MAP_FILE>") + endif() +endif() diff --git a/Source/cmCxxModuleMapper.cxx b/Source/cmCxxModuleMapper.cxx index 7952dfc..59bf4c7 100644 --- a/Source/cmCxxModuleMapper.cxx +++ b/Source/cmCxxModuleMapper.cxx @@ -21,7 +21,7 @@ cm::optional<std::string> CxxModuleLocations::BmiGeneratorPathForModule( std::string const& logical_name) const { if (auto l = this->BmiLocationForModule(logical_name)) { - return this->PathForGenerator(*l); + return this->PathForGenerator(std::move(*l)); } return {}; } @@ -239,8 +239,7 @@ std::set<std::string> CxxModuleUsageSeed( for (auto const& p : object.Provides) { if (auto bmi_loc = loc.BmiGeneratorPathForModule(p.LogicalName)) { // XXX(cxx-modules): How to support header units? - usages.AddReference(p.LogicalName, loc.PathForGenerator(*bmi_loc), - LookupMethod::ByName); + usages.AddReference(p.LogicalName, *bmi_loc, LookupMethod::ByName); } } @@ -268,8 +267,7 @@ std::set<std::string> CxxModuleUsageSeed( } if (bmi_loc) { - usages.AddReference(r.LogicalName, loc.PathForGenerator(*bmi_loc), - r.Method); + usages.AddReference(r.LogicalName, *bmi_loc, r.Method); } } } diff --git a/Source/cmCxxModuleMapper.h b/Source/cmCxxModuleMapper.h index 9271978..0f453b0 100644 --- a/Source/cmCxxModuleMapper.h +++ b/Source/cmCxxModuleMapper.h @@ -30,7 +30,7 @@ struct CxxModuleLocations std::string RootDirectory; // A function to convert a full path to a path for the generator. - std::function<std::string(std::string const&)> PathForGenerator; + std::function<std::string(std::string)> PathForGenerator; // Lookup the BMI location of a logical module name. std::function<cm::optional<std::string>(std::string const&)> diff --git a/Source/cmDyndepCollation.cxx b/Source/cmDyndepCollation.cxx index 2827659..53a262b 100644 --- a/Source/cmDyndepCollation.cxx +++ b/Source/cmDyndepCollation.cxx @@ -441,20 +441,16 @@ bool cmDyndepCollation::WriteDyndepMetadata( auto fileset_info_itr = export_info.ObjectToFileSet.find(output_path); bool const has_provides = !object.Provides.empty(); if (fileset_info_itr == export_info.ObjectToFileSet.end()) { - // If it provides anything, it should have a `CXX_MODULES` or - // `CXX_MODULE_INTERNAL_PARTITIONS` type and be present. + // If it provides anything, it should have type `CXX_MODULES` + // and be present. if (has_provides) { // Take the first module provided to provide context. auto const& provides = object.Provides[0]; - char const* ok_types = "`CXX_MODULES`"; - if (provides.LogicalName.find(':') != std::string::npos) { - ok_types = "`CXX_MODULES` (or `CXX_MODULE_INTERNAL_PARTITIONS` if " - "it is not `export`ed)"; - } - cmSystemTools::Error(cmStrCat( - "Output ", object.PrimaryOutput, " provides the `", - provides.LogicalName, - "` module but it is not found in a `FILE_SET` of type ", ok_types)); + cmSystemTools::Error( + cmStrCat("Output ", object.PrimaryOutput, " provides the `", + provides.LogicalName, + "` module but it is not found in a `FILE_SET` of type " + "`CXX_MODULES`")); result = false; } @@ -474,38 +470,15 @@ bool cmDyndepCollation::WriteDyndepMetadata( result = false; continue; } - } else if (file_set.Type == "CXX_MODULE_INTERNAL_PARTITIONS"_s) { - if (!has_provides) { - cmSystemTools::Error( - cmStrCat("Source ", file_set.SourcePath, - " is of type `CXX_MODULE_INTERNAL_PARTITIONS` but does not " - "provide a module")); - result = false; - continue; - } - auto const& provides = object.Provides[0]; - if (provides.LogicalName.find(':') == std::string::npos) { - cmSystemTools::Error( - cmStrCat("Source ", file_set.SourcePath, - " is of type `CXX_MODULE_INTERNAL_PARTITIONS` but does not " - "provide a module partition")); - result = false; - continue; - } } else if (file_set.Type == "CXX_MODULE_HEADERS"_s) { // TODO. } else { if (has_provides) { auto const& provides = object.Provides[0]; - char const* ok_types = "`CXX_MODULES`"; - if (provides.LogicalName.find(':') != std::string::npos) { - ok_types = "`CXX_MODULES` (or `CXX_MODULE_INTERNAL_PARTITIONS` if " - "it is not `export`ed)"; - } - cmSystemTools::Error( - cmStrCat("Source ", file_set.SourcePath, " provides the `", - provides.LogicalName, "` C++ module but is of type `", - file_set.Type, "` module but must be of type ", ok_types)); + cmSystemTools::Error(cmStrCat( + "Source ", file_set.SourcePath, " provides the `", + provides.LogicalName, "` C++ module but is of type `", file_set.Type, + "` module but must be of type `CXX_MODULES`")); result = false; } diff --git a/Source/cmGlobalNinjaGenerator.cxx b/Source/cmGlobalNinjaGenerator.cxx index 9db92c0..914d1c7 100644 --- a/Source/cmGlobalNinjaGenerator.cxx +++ b/Source/cmGlobalNinjaGenerator.cxx @@ -63,6 +63,19 @@ std::string const cmGlobalNinjaGenerator::SHELL_NOOP = "cd ."; std::string const cmGlobalNinjaGenerator::SHELL_NOOP = ":"; #endif +namespace { +#ifdef _WIN32 +bool DetectGCCOnWindows(cm::string_view compilerId, cm::string_view simulateId, + cm::string_view compilerFrontendVariant) +{ + return ((compilerId == "Clang"_s && compilerFrontendVariant == "GNU"_s) || + (simulateId != "MSVC"_s && + (compilerId == "GNU"_s || compilerId == "QCC"_s || + cmHasLiteralSuffix(compilerId, "Clang")))); +} +#endif +} + bool operator==( const cmGlobalNinjaGenerator::ByConfig::TargetDependsClosureKey& lhs, const cmGlobalNinjaGenerator::ByConfig::TargetDependsClosureKey& rhs) @@ -943,12 +956,8 @@ void cmGlobalNinjaGenerator::EnableLanguage( mf->GetSafeDefinition(cmStrCat("CMAKE_", l, "_SIMULATE_ID")); std::string const& compilerFrontendVariant = mf->GetSafeDefinition( cmStrCat("CMAKE_", l, "_COMPILER_FRONTEND_VARIANT")); - if ((compilerId == "Clang" && compilerFrontendVariant == "GNU") || - (simulateId != "MSVC" && - (compilerId == "GNU" || compilerId == "QCC" || - cmHasLiteralSuffix(compilerId, "Clang")))) { - this->UsingGCCOnWindows = true; - } + this->SetUsingGCCOnWindows( + DetectGCCOnWindows(compilerId, simulateId, compilerFrontendVariant)); #endif } } @@ -2629,8 +2638,14 @@ bool cmGlobalNinjaGenerator::WriteDyndepFile( { CxxModuleLocations locs; locs.RootDirectory = "."; - locs.PathForGenerator = [this](std::string const& path) -> std::string { - return this->ConvertToNinjaPath(path); + locs.PathForGenerator = [this](std::string path) -> std::string { + path = this->ConvertToNinjaPath(path); +# ifdef _WIN32 + if (this->IsGCCOnWindows()) { + std::replace(path.begin(), path.end(), '\\', '/'); + } +# endif + return path; }; locs.BmiLocationForModule = [&mod_files](std::string const& logical) -> cm::optional<std::string> { @@ -2811,6 +2826,10 @@ int cmcmd_cmake_ninja_dyndep(std::vector<std::string>::const_iterator argBeg, linked_target_dirs.push_back(tdi_linked_target_dir.asString()); } } + std::string const compilerId = tdi["compiler-id"].asString(); + std::string const simulateId = tdi["compiler-simulate-id"].asString(); + std::string const compilerFrontendVariant = + tdi["compiler-frontend-variant"].asString(); auto export_info = cmDyndepCollation::ParseExportInfo(tdi); @@ -2818,14 +2837,20 @@ int cmcmd_cmake_ninja_dyndep(std::vector<std::string>::const_iterator argBeg, cm.SetHomeDirectory(dir_top_src); cm.SetHomeOutputDirectory(dir_top_bld); auto ggd = cm.CreateGlobalGenerator("Ninja"); - if (!ggd || - !cm::static_reference_cast<cmGlobalNinjaGenerator>(ggd).WriteDyndepFile( - dir_top_src, dir_top_bld, dir_cur_src, dir_cur_bld, arg_dd, arg_ddis, - module_dir, linked_target_dirs, arg_lang, arg_modmapfmt, - *export_info)) { + if (!ggd) { return 1; } - return 0; + cmGlobalNinjaGenerator& gg = + cm::static_reference_cast<cmGlobalNinjaGenerator>(ggd); +# ifdef _WIN32 + gg.SetUsingGCCOnWindows( + DetectGCCOnWindows(compilerId, simulateId, compilerFrontendVariant)); +# endif + return gg.WriteDyndepFile(dir_top_src, dir_top_bld, dir_cur_src, dir_cur_bld, + arg_dd, arg_ddis, module_dir, linked_target_dirs, + arg_lang, arg_modmapfmt, *export_info) + ? 0 + : 1; } #endif diff --git a/Source/cmGlobalNinjaGenerator.h b/Source/cmGlobalNinjaGenerator.h index f18d63b..68b26cc 100644 --- a/Source/cmGlobalNinjaGenerator.h +++ b/Source/cmGlobalNinjaGenerator.h @@ -169,6 +169,7 @@ public: const std::string& comment = ""); bool IsGCCOnWindows() const { return this->UsingGCCOnWindows; } + void SetUsingGCCOnWindows(bool b) { this->UsingGCCOnWindows = b; } cmGlobalNinjaGenerator(cmake* cm); diff --git a/Source/cmLocalNinjaGenerator.cxx b/Source/cmLocalNinjaGenerator.cxx index 1e2ea2a..3443cd3 100644 --- a/Source/cmLocalNinjaGenerator.cxx +++ b/Source/cmLocalNinjaGenerator.cxx @@ -456,6 +456,22 @@ std::string cmLocalNinjaGenerator::WriteCommandScript( return scriptPath; } +#ifdef _WIN32 +namespace { +bool RuleNeedsCMD(std::string const& cmd) +{ + std::vector<std::string> args; + cmSystemTools::ParseWindowsCommandLine(cmd.c_str(), args); + auto it = std::find_if(args.cbegin(), args.cend(), + [](std::string const& arg) -> bool { + // FIXME: Detect more windows shell operators. + return cmHasLiteralPrefix(arg, ">"); + }); + return it != args.cend(); +} +} +#endif + std::string cmLocalNinjaGenerator::BuildCommandLine( std::vector<std::string> const& cmdLines, std::string const& outputConfig, std::string const& commandConfig, std::string const& customStep, @@ -498,12 +514,13 @@ std::string cmLocalNinjaGenerator::BuildCommandLine( } std::ostringstream cmd; - for (auto li = cmdLines.begin(); li != cmdLines.end(); ++li) #ifdef _WIN32 - { + bool const needCMD = + cmdLines.size() > 1 || (customStep.empty() && RuleNeedsCMD(cmdLines[0])); + for (auto li = cmdLines.begin(); li != cmdLines.end(); ++li) { if (li != cmdLines.begin()) { cmd << " && "; - } else if (cmdLines.size() > 1) { + } else if (needCMD) { cmd << "cmd.exe /C \""; } // Put current cmdLine in brackets if it contains "||" because it has @@ -514,11 +531,11 @@ std::string cmLocalNinjaGenerator::BuildCommandLine( cmd << *li; } } - if (cmdLines.size() > 1) { + if (needCMD) { cmd << "\""; } #else - { + for (auto li = cmdLines.begin(); li != cmdLines.end(); ++li) { if (li != cmdLines.begin()) { cmd << " && "; } diff --git a/Source/cmNinjaTargetGenerator.cxx b/Source/cmNinjaTargetGenerator.cxx index 13782b0..5abf609 100644 --- a/Source/cmNinjaTargetGenerator.cxx +++ b/Source/cmNinjaTargetGenerator.cxx @@ -1634,6 +1634,10 @@ void cmNinjaTargetGenerator::WriteTargetDependInfo(std::string const& lang, tdi["language"] = lang; tdi["compiler-id"] = this->Makefile->GetSafeDefinition( cmStrCat("CMAKE_", lang, "_COMPILER_ID")); + tdi["compiler-simulate-id"] = this->Makefile->GetSafeDefinition( + cmStrCat("CMAKE_", lang, "_SIMULATE_ID")); + tdi["compiler-frontend-variant"] = this->Makefile->GetSafeDefinition( + cmStrCat("CMAKE_", lang, "_COMPILER_FRONTEND_VARIANT")); std::string mod_dir; if (lang == "Fortran") { |