summaryrefslogtreecommitdiffstats
path: root/Source
diff options
context:
space:
mode:
authorBrad King <brad.king@kitware.com>2023-03-21 12:58:16 (GMT)
committerKitware Robot <kwrobot@kitware.com>2023-03-21 12:58:43 (GMT)
commitca8c171021369f535fa18013796cc0b8f9cbd4fc (patch)
treefe86b75fd9f168720d40c29d0763af751ddba1ab /Source
parent5f8929f721966f7560d18811126d74553af3df5f (diff)
parent1b7c26da49e7e1a337f66951424bda8d3f4067fc (diff)
downloadCMake-ca8c171021369f535fa18013796cc0b8f9cbd4fc.zip
CMake-ca8c171021369f535fa18013796cc0b8f9cbd4fc.tar.gz
CMake-ca8c171021369f535fa18013796cc0b8f9cbd4fc.tar.bz2
Merge topic 'clang-windows-cxx-modules'
1b7c26da49 Ninja: Wrap rules using '>' shell redirection with 'cmd /C' on Windows ffd8537acf Clang: Record Clang 16.0 C++ modules flags only for GNU-like front-end 6013227230 cmGlobalNinjaGenerator: Use forward slashes in clang modmap format on Windows d9d74b5e8a cmDyndepCollation: Drop outdated mentions of CXX_MODULE_INTERNAL_PARTITIONS edab56d29a cmLocalNinjaGenerator: De-duplicate condition for using 'cmd /C' on Windows 8ebe3f92b3 cmGlobalNinjaGenerator: Detect GNU-like command-line for dyndep collator f3ca199c9b cmGlobalNinjaGenerator: Factor out GNU-like command-line detection on Windows f79817fcf0 cmCxxModuleMapper: Use value semantics in path conversion callback ... Acked-by: Kitware Robot <kwrobot@kitware.com> Merge-request: !8346
Diffstat (limited to 'Source')
-rw-r--r--Source/cmCxxModuleMapper.cxx8
-rw-r--r--Source/cmCxxModuleMapper.h2
-rw-r--r--Source/cmDyndepCollation.cxx49
-rw-r--r--Source/cmGlobalNinjaGenerator.cxx53
-rw-r--r--Source/cmGlobalNinjaGenerator.h1
-rw-r--r--Source/cmLocalNinjaGenerator.cxx27
-rw-r--r--Source/cmNinjaTargetGenerator.cxx4
7 files changed, 81 insertions, 63 deletions
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 650d0aa..37856d9 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)
@@ -936,12 +949,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 c08bb46..12c6698 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 f8027c0..305dab3 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 8719364..4c0f935 100644
--- a/Source/cmNinjaTargetGenerator.cxx
+++ b/Source/cmNinjaTargetGenerator.cxx
@@ -1651,6 +1651,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") {