cmMakefile: Dedupe languages when enabling them

cmMakefile::EnableLanguage() now deduplicates the languages argument and
emits an author warning listing the languages that were defined multiple
times in a single call.

Fixes: #23596
This commit is contained in:
friendlyanon
2022-06-30 20:51:18 +02:00
parent 66bfe14309
commit b4fd385c9b
4 changed files with 50 additions and 2 deletions

View File

@@ -3491,13 +3491,35 @@ void cmMakefile::EnableLanguage(std::vector<std::string> const& languages,
if (const char* def = this->GetGlobalGenerator()->GetCMakeCFGIntDir()) {
this->AddDefinition("CMAKE_CFG_INTDIR", def);
}
std::vector<std::string> unique_languages;
{
std::vector<std::string> duplicate_languages;
for (std::string const& language : languages) {
if (!cm::contains(unique_languages, language)) {
unique_languages.push_back(language);
} else if (!cm::contains(duplicate_languages, language)) {
duplicate_languages.push_back(language);
}
}
if (!duplicate_languages.empty()) {
auto quantity = duplicate_languages.size() == 1 ? std::string(" has")
: std::string("s have");
this->IssueMessage(MessageType::AUTHOR_WARNING,
"Languages to be enabled may not be specified more "
"than once at the same time. The following language" +
quantity + " been specified multiple times: " +
cmJoin(duplicate_languages, ", "));
}
}
// If RC is explicitly listed we need to do it after other languages.
// On some platforms we enable RC implicitly while enabling others.
// Do not let that look like recursive enable_language(RC).
std::vector<std::string> languages_without_RC;
std::vector<std::string> languages_for_RC;
languages_without_RC.reserve(languages.size());
for (std::string const& language : languages) {
languages_without_RC.reserve(unique_languages.size());
for (std::string const& language : unique_languages) {
if (language == "RC") {
languages_for_RC.push_back(language);
} else {

View File

@@ -0,0 +1,10 @@
if(NOT actual_stderr MATCHES "The following language has been specified multiple times: C\n")
set(RunCMake_TEST_FAILED "'LANGUAGES C C C' should report only 'C' and only once.")
endif()
if(NOT actual_stderr MATCHES "The following languages have been specified multiple times: C, CXX\n")
if(RunCMake_TEST_FAILED)
string(APPEND RunCMake_TEST_FAILED "\n")
endif()
string(APPEND RunCMake_TEST_FAILED "'LANGUAGES C C CXX CXX' should report 'C' and 'CXX'.")
endif()

View File

@@ -0,0 +1,11 @@
cmake_policy(SET CMP0057 NEW)
project(ProjectA C C C)
project(ProjectB C C CXX CXX)
get_property(langs GLOBAL PROPERTY ENABLED_LANGUAGES)
foreach(lang C CXX)
if(NOT lang IN_LIST langs)
message(FATAL_ERROR "Expected language '${lang}' to be enabled.")
endif()
endforeach()

View File

@@ -12,6 +12,11 @@ run_cmake_with_options(CodeInjection
if(CMake_TEST_RESOURCES)
run_cmake(ExplicitRC)
endif()
set(RunCMake_DEFAULT_stderr .)
run_cmake(LanguagesDuplicate)
unset(RunCMake_DEFAULT_stderr)
run_cmake(LanguagesImplicit)
run_cmake(LanguagesEmpty)
run_cmake(LanguagesNONE)