|
|
@@ -9115,39 +9115,83 @@ cmGeneratorTarget::Cxx20SupportLevel cmGeneratorTarget::HaveCxxModuleSupport(
|
|
|
|
|
|
void cmGeneratorTarget::CheckCxxModuleStatus(std::string const& config) const
|
|
|
{
|
|
|
+ bool haveScannableSources = false;
|
|
|
+
|
|
|
// Check for `CXX_MODULE*` file sets and a lack of support.
|
|
|
if (this->HaveCxx20ModuleSources()) {
|
|
|
- switch (this->HaveCxxModuleSupport(config)) {
|
|
|
- case cmGeneratorTarget::Cxx20SupportLevel::MissingCxx:
|
|
|
- this->Makefile->IssueMessage(
|
|
|
- MessageType::FATAL_ERROR,
|
|
|
- cmStrCat("The target named \"", this->GetName(),
|
|
|
- "\" has C++ sources that export modules but the \"CXX\" "
|
|
|
- "language has not been enabled"));
|
|
|
- break;
|
|
|
- case cmGeneratorTarget::Cxx20SupportLevel::NoCxx20: {
|
|
|
- cmStandardLevelResolver standardResolver(this->Makefile);
|
|
|
- auto effStandard =
|
|
|
- standardResolver.GetEffectiveStandard(this, "CXX", config);
|
|
|
- if (effStandard.empty()) {
|
|
|
- effStandard = "; no C++ standard found";
|
|
|
- } else {
|
|
|
- effStandard = cmStrCat("; found \"cxx_std_", effStandard, '"');
|
|
|
- }
|
|
|
- this->Makefile->IssueMessage(
|
|
|
- MessageType::FATAL_ERROR,
|
|
|
- cmStrCat(
|
|
|
- "The target named \"", this->GetName(),
|
|
|
- "\" has C++ sources that export modules but does not include "
|
|
|
- "\"cxx_std_20\" (or newer) among its `target_compile_features`",
|
|
|
- effStandard));
|
|
|
- } break;
|
|
|
- case cmGeneratorTarget::Cxx20SupportLevel::MissingRule:
|
|
|
- case cmGeneratorTarget::Cxx20SupportLevel::Supported:
|
|
|
- // All is well.
|
|
|
- break;
|
|
|
+ haveScannableSources = true;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!haveScannableSources) {
|
|
|
+ // Check to see if there are regular sources that have requested scanning.
|
|
|
+ auto sources = cmGeneratorTarget::GetSourceFiles(config);
|
|
|
+ for (auto const& source : sources) {
|
|
|
+ auto const* sf = source.Value;
|
|
|
+ auto const& lang = sf->GetLanguage();
|
|
|
+ if (lang != "CXX"_s) {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ // Ignore sources which do not need dyndep.
|
|
|
+ if (this->NeedDyndepForSource(lang, config, sf)) {
|
|
|
+ haveScannableSources = true;
|
|
|
+ }
|
|
|
}
|
|
|
}
|
|
|
+
|
|
|
+ // If there isn't anything scannable, ignore it.
|
|
|
+ if (!haveScannableSources) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ // If the generator doesn't support modules at all, error that we have
|
|
|
+ // sources that require the support.
|
|
|
+ if (!this->GetGlobalGenerator()->CheckCxxModuleSupport()) {
|
|
|
+ this->Makefile->IssueMessage(
|
|
|
+ MessageType::FATAL_ERROR,
|
|
|
+ cmStrCat(
|
|
|
+ "The target named \"", this->GetName(),
|
|
|
+ "\" contains C++ "
|
|
|
+ "sources that use modules which is not supported by the generator"));
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ switch (this->HaveCxxModuleSupport(config)) {
|
|
|
+ case cmGeneratorTarget::Cxx20SupportLevel::MissingCxx:
|
|
|
+ this->Makefile->IssueMessage(
|
|
|
+ MessageType::FATAL_ERROR,
|
|
|
+ cmStrCat("The target named \"", this->GetName(),
|
|
|
+ "\" has C++ sources that use modules but the \"CXX\" "
|
|
|
+ "language has not been enabled"));
|
|
|
+ break;
|
|
|
+ case cmGeneratorTarget::Cxx20SupportLevel::NoCxx20: {
|
|
|
+ cmStandardLevelResolver standardResolver(this->Makefile);
|
|
|
+ auto effStandard =
|
|
|
+ standardResolver.GetEffectiveStandard(this, "CXX", config);
|
|
|
+ if (effStandard.empty()) {
|
|
|
+ effStandard = "; no C++ standard found";
|
|
|
+ } else {
|
|
|
+ effStandard = cmStrCat("; found \"cxx_std_", effStandard, '"');
|
|
|
+ }
|
|
|
+ this->Makefile->IssueMessage(
|
|
|
+ MessageType::FATAL_ERROR,
|
|
|
+ cmStrCat(
|
|
|
+ "The target named \"", this->GetName(),
|
|
|
+ "\" has C++ sources that use modules but does not include "
|
|
|
+ "\"cxx_std_20\" (or newer) among its `target_compile_features`",
|
|
|
+ effStandard));
|
|
|
+ } break;
|
|
|
+ case cmGeneratorTarget::Cxx20SupportLevel::MissingRule: {
|
|
|
+ this->Makefile->IssueMessage(
|
|
|
+ MessageType::FATAL_ERROR,
|
|
|
+ cmStrCat("The target named \"", this->GetName(),
|
|
|
+ "\" has C++ sources that use modules but the compiler does "
|
|
|
+ "not provide a way to discover the import graph "
|
|
|
+ "dependencies"));
|
|
|
+ } break;
|
|
|
+ case cmGeneratorTarget::Cxx20SupportLevel::Supported:
|
|
|
+ // All is well.
|
|
|
+ break;
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
bool cmGeneratorTarget::NeedCxxModuleSupport(std::string const& lang,
|
|
|
@@ -9185,14 +9229,30 @@ bool cmGeneratorTarget::NeedDyndepForSource(std::string const& lang,
|
|
|
std::string const& config,
|
|
|
cmSourceFile const* sf) const
|
|
|
{
|
|
|
- bool const needDyndep = this->NeedDyndep(lang, config);
|
|
|
- if (!needDyndep) {
|
|
|
+ // Fortran always needs to be scanned.
|
|
|
+ if (lang == "Fortran"_s) {
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+ // Only C++ code needs scanned otherwise.
|
|
|
+ if (lang != "CXX"_s) {
|
|
|
return false;
|
|
|
}
|
|
|
+
|
|
|
+ // Any file in `CXX_MODULES` file sets need scanned (it being `CXX` is
|
|
|
+ // enforced elsewhere).
|
|
|
auto const* fs = this->GetFileSetForSource(config, sf);
|
|
|
if (fs && fs->GetType() == "CXX_MODULES"_s) {
|
|
|
return true;
|
|
|
}
|
|
|
+
|
|
|
+ switch (this->HaveCxxModuleSupport(config)) {
|
|
|
+ case Cxx20SupportLevel::MissingCxx:
|
|
|
+ case Cxx20SupportLevel::NoCxx20:
|
|
|
+ return false;
|
|
|
+ case Cxx20SupportLevel::MissingRule:
|
|
|
+ case Cxx20SupportLevel::Supported:
|
|
|
+ break;
|
|
|
+ }
|
|
|
auto const sfProp = sf->GetProperty("CXX_SCAN_FOR_MODULES");
|
|
|
if (sfProp.IsSet()) {
|
|
|
return sfProp.IsOn();
|