From 627ef4c1d002cf642ef0ef9048c5e3fa24069516 Mon Sep 17 00:00:00 2001 From: Robert Maynard Date: Wed, 27 Apr 2022 13:54:42 -0400 Subject: Provide guidance when trying to use non-enabled language Fixes #23463 --- Source/cmCommonTargetGenerator.cxx | 30 +++++++++++++++++++++- Source/cmCommonTargetGenerator.h | 4 +++ Source/cmMakefileTargetGenerator.cxx | 14 ++++++---- Source/cmNinjaNormalTargetGenerator.cxx | 10 +++----- .../project/LanguagesUsedButNotEnabled-result.txt | 1 + .../project/LanguagesUsedButNotEnabled-stderr.txt | 4 +++ .../project/LanguagesUsedButNotEnabled.cmake | 3 +++ Tests/RunCMake/project/RunCMakeTest.cmake | 3 +++ 8 files changed, 56 insertions(+), 13 deletions(-) create mode 100644 Tests/RunCMake/project/LanguagesUsedButNotEnabled-result.txt create mode 100644 Tests/RunCMake/project/LanguagesUsedButNotEnabled-stderr.txt create mode 100644 Tests/RunCMake/project/LanguagesUsedButNotEnabled.cmake diff --git a/Source/cmCommonTargetGenerator.cxx b/Source/cmCommonTargetGenerator.cxx index 129ef4b..b172c20 100644 --- a/Source/cmCommonTargetGenerator.cxx +++ b/Source/cmCommonTargetGenerator.cxx @@ -2,7 +2,7 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmCommonTargetGenerator.h" -#include +#include #include #include @@ -13,9 +13,11 @@ #include "cmLocalCommonGenerator.h" #include "cmLocalGenerator.h" #include "cmMakefile.h" +#include "cmMessageType.h" #include "cmOutputConverter.h" #include "cmRange.h" #include "cmSourceFile.h" +#include "cmState.h" #include "cmStateTypes.h" #include "cmStringAlgorithms.h" #include "cmTarget.h" @@ -321,3 +323,29 @@ std::string cmCommonTargetGenerator::GetLinkerLauncher( } return std::string(); } + +bool cmCommonTargetGenerator::HaveRequiredLanguages( + const std::vector& sources, + std::set& languagesNeeded) const +{ + for (cmSourceFile const* sf : sources) { + languagesNeeded.insert(sf->GetLanguage()); + } + + auto* makefile = this->Makefile; + auto* state = makefile->GetState(); + auto unary = [&state, &makefile](const std::string& lang) -> bool { + const bool valid = state->GetLanguageEnabled(lang); + if (!valid) { + makefile->IssueMessage( + MessageType::FATAL_ERROR, + cmStrCat("The language ", lang, + " was requested for compilation but was not enabled." + " To enable a language it needs to be specified in a" + " 'project' or 'enable_language' command in the root" + " CMakeLists.txt")); + } + return valid; + }; + return std::all_of(languagesNeeded.cbegin(), languagesNeeded.cend(), unary); +} diff --git a/Source/cmCommonTargetGenerator.h b/Source/cmCommonTargetGenerator.h index 5aba1c6..1b804b4 100644 --- a/Source/cmCommonTargetGenerator.h +++ b/Source/cmCommonTargetGenerator.h @@ -5,6 +5,7 @@ #include "cmConfigure.h" // IWYU pragma: keep #include +#include #include #include @@ -74,6 +75,9 @@ protected: std::string GetLinkerLauncher(const std::string& config); + bool HaveRequiredLanguages(const std::vector& sources, + std::set& languagesNeeded) const; + private: using ByLanguageMap = std::map; struct ByConfig diff --git a/Source/cmMakefileTargetGenerator.cxx b/Source/cmMakefileTargetGenerator.cxx index 1c92c7f..aec6577 100644 --- a/Source/cmMakefileTargetGenerator.cxx +++ b/Source/cmMakefileTargetGenerator.cxx @@ -305,9 +305,14 @@ void cmMakefileTargetGenerator::WriteTargetBuildRules() std::vector objectSources; this->GeneratorTarget->GetObjectSources(objectSources, this->GetConfigName()); - for (cmSourceFile const* sf : objectSources) { - // Generate this object file's rule file. - this->WriteObjectRuleFiles(*sf); + + // validate that all languages requested are enabled. + std::set requiredLangs; + if (this->HaveRequiredLanguages(objectSources, requiredLangs)) { + for (cmSourceFile const* sf : objectSources) { + // Generate this object file's rule file. + this->WriteObjectRuleFiles(*sf); + } } } @@ -532,8 +537,7 @@ void cmMakefileTargetGenerator::WriteObjectRuleFiles( cmSourceFile const& source) { // Identify the language of the source file. - const std::string& lang = - this->LocalGenerator->GetSourceFileLanguage(source); + const std::string& lang = source.GetLanguage(); if (lang.empty()) { // don't know anything about this file so skip it return; diff --git a/Source/cmNinjaNormalTargetGenerator.cxx b/Source/cmNinjaNormalTargetGenerator.cxx index 1c5bac8..4f6da0e 100644 --- a/Source/cmNinjaNormalTargetGenerator.cxx +++ b/Source/cmNinjaNormalTargetGenerator.cxx @@ -126,15 +126,11 @@ void cmNinjaNormalTargetGenerator::WriteLanguagesRules( std::set languages; std::vector sourceFiles; this->GetGeneratorTarget()->GetObjectSources(sourceFiles, config); - for (cmSourceFile const* sf : sourceFiles) { - std::string const lang = sf->GetLanguage(); - if (!lang.empty()) { - languages.insert(lang); + if (this->HaveRequiredLanguages(sourceFiles, languages)) { + for (std::string const& language : languages) { + this->WriteLanguageRules(language, config); } } - for (std::string const& language : languages) { - this->WriteLanguageRules(language, config); - } } const char* cmNinjaNormalTargetGenerator::GetVisibleTypeName() const diff --git a/Tests/RunCMake/project/LanguagesUsedButNotEnabled-result.txt b/Tests/RunCMake/project/LanguagesUsedButNotEnabled-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/project/LanguagesUsedButNotEnabled-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/project/LanguagesUsedButNotEnabled-stderr.txt b/Tests/RunCMake/project/LanguagesUsedButNotEnabled-stderr.txt new file mode 100644 index 0000000..bf9157b --- /dev/null +++ b/Tests/RunCMake/project/LanguagesUsedButNotEnabled-stderr.txt @@ -0,0 +1,4 @@ +CMake Error in CMakeLists.txt: + The language CXX was requested for compilation but was not enabled. To + enable a language it needs to be specified in a 'project' or + 'enable_language' command in the root CMakeLists.txt diff --git a/Tests/RunCMake/project/LanguagesUsedButNotEnabled.cmake b/Tests/RunCMake/project/LanguagesUsedButNotEnabled.cmake new file mode 100644 index 0000000..caab687 --- /dev/null +++ b/Tests/RunCMake/project/LanguagesUsedButNotEnabled.cmake @@ -0,0 +1,3 @@ + +add_executable(UsesCXXLang empty.cxx) +set_source_files_properties(empty.cxx PROPERTIES GENERATED TRUE LANGUAGE CXX ) diff --git a/Tests/RunCMake/project/RunCMakeTest.cmake b/Tests/RunCMake/project/RunCMakeTest.cmake index 349e8ac..d7dab12 100644 --- a/Tests/RunCMake/project/RunCMakeTest.cmake +++ b/Tests/RunCMake/project/RunCMakeTest.cmake @@ -8,6 +8,9 @@ run_cmake(LanguagesEmpty) run_cmake(LanguagesNONE) run_cmake(LanguagesTwice) run_cmake(LanguagesUnordered) +if(RunCMake_GENERATOR MATCHES "Make|Ninja") + run_cmake(LanguagesUsedButNotEnabled) +endif() run_cmake(ProjectDescription) run_cmake(ProjectDescription2) run_cmake(ProjectDescriptionNoArg) -- cgit v0.12