diff options
author | Kyle Edwards <kyle.edwards@kitware.com> | 2022-02-24 18:09:53 -0500 |
---|---|---|
committer | Kyle Edwards <kyle.edwards@kitware.com> | 2022-03-29 13:58:27 -0400 |
commit | c798744f8193e97f00f1b6e47dc5bc6fdc34b222 (patch) | |
tree | 27b2dc2cbd04d45026319bbe006acd72bb0f3dff /Source/cmGeneratorTarget.cxx | |
parent | fdbef2a2be1f070e0f0809536639ff20d80584e6 (diff) | |
download | cmake-c798744f8193e97f00f1b6e47dc5bc6fdc34b222.tar.gz |
FILE_SET: Add VERIFY_HEADER_SETS target property
Fixes: #23338
Diffstat (limited to 'Source/cmGeneratorTarget.cxx')
-rw-r--r-- | Source/cmGeneratorTarget.cxx | 173 |
1 files changed, 173 insertions, 0 deletions
diff --git a/Source/cmGeneratorTarget.cxx b/Source/cmGeneratorTarget.cxx index 1a13bdbf41..f1ab85ca91 100644 --- a/Source/cmGeneratorTarget.cxx +++ b/Source/cmGeneratorTarget.cxx @@ -8522,3 +8522,176 @@ cmGeneratorTarget::ManagedType cmGeneratorTarget::GetManagedType( // has to be set manually for C# targets. return this->IsCSharpOnly() ? ManagedType::Managed : ManagedType::Native; } + +bool cmGeneratorTarget::AddHeaderSetVerification() +{ + if (!this->GetPropertyAsBool("VERIFY_HEADER_SETS")) { + return true; + } + + if (this->GetType() != cmStateEnums::STATIC_LIBRARY && + this->GetType() != cmStateEnums::SHARED_LIBRARY && + this->GetType() != cmStateEnums::UNKNOWN_LIBRARY && + this->GetType() != cmStateEnums::OBJECT_LIBRARY && + this->GetType() != cmStateEnums::INTERFACE_LIBRARY && + !this->IsExecutableWithExports()) { + return true; + } + + cmTarget* verifyTarget = nullptr; + + auto interfaceFileSetEntries = this->Target->GetInterfaceHeaderSetsEntries(); + + std::set<cmFileSet*> fileSets; + auto const addFileSets = [&fileSets, this](const cmBTStringRange& entries) { + for (auto const& entry : entries) { + for (auto const& name : cmExpandedList(entry.Value)) { + fileSets.insert(this->Target->GetFileSet(name)); + } + } + }; + addFileSets(interfaceFileSetEntries); + + cm::optional<std::set<std::string>> languages; + for (auto* fileSet : fileSets) { + auto dirCges = fileSet->CompileDirectoryEntries(); + auto fileCges = fileSet->CompileFileEntries(); + + static auto const contextSensitive = + [](const std::unique_ptr<cmCompiledGeneratorExpression>& cge) { + return cge->GetHadContextSensitiveCondition(); + }; + bool dirCgesContextSensitive = false; + bool fileCgesContextSensitive = false; + + std::vector<std::string> dirs; + std::map<std::string, std::vector<std::string>> filesPerDir; + bool first = true; + for (auto const& config : this->Makefile->GetGeneratorConfigs( + cmMakefile::GeneratorConfigQuery::IncludeEmptyConfig)) { + if (first || dirCgesContextSensitive) { + dirs = fileSet->EvaluateDirectoryEntries(dirCges, this->LocalGenerator, + config, this); + dirCgesContextSensitive = + std::any_of(dirCges.begin(), dirCges.end(), contextSensitive); + } + if (first || fileCgesContextSensitive) { + filesPerDir.clear(); + for (auto const& fileCge : fileCges) { + fileSet->EvaluateFileEntry(dirs, filesPerDir, fileCge, + this->LocalGenerator, config, this); + if (fileCge->GetHadContextSensitiveCondition()) { + fileCgesContextSensitive = true; + } + } + } + + for (auto const& files : filesPerDir) { + for (auto const& file : files.second) { + std::string filename = this->GenerateHeaderSetVerificationFile( + *this->Makefile->GetOrCreateSource(file), files.first, languages); + if (filename.empty()) { + continue; + } + + if (!verifyTarget) { + { + cmMakefile::PolicyPushPop polScope(this->Makefile); + this->Makefile->SetPolicy(cmPolicies::CMP0119, cmPolicies::NEW); + verifyTarget = this->Makefile->AddLibrary( + cmStrCat(this->GetName(), "_verify_header_sets"), + cmStateEnums::OBJECT_LIBRARY, {}, true); + } + + verifyTarget->AddLinkLibrary( + *this->Makefile, this->GetName(), + cmTargetLinkLibraryType::GENERAL_LibraryType); + verifyTarget->SetProperty("AUTOMOC", "OFF"); + verifyTarget->SetProperty("AUTORCC", "OFF"); + verifyTarget->SetProperty("AUTOUIC", "OFF"); + verifyTarget->SetProperty("DISABLE_PRECOMPILE_HEADERS", "ON"); + verifyTarget->SetProperty("UNITY_BUILD", "OFF"); + } + + if (fileCgesContextSensitive) { + filename = cmStrCat("$<$<CONFIG:", config, ">:", filename, ">"); + } + verifyTarget->AddSource(filename); + } + } + + if (!dirCgesContextSensitive && !fileCgesContextSensitive) { + break; + } + first = false; + } + } + + if (verifyTarget) { + this->LocalGenerator->AddGeneratorTarget( + cm::make_unique<cmGeneratorTarget>(verifyTarget, this->LocalGenerator)); + } + + return true; +} + +std::string cmGeneratorTarget::GenerateHeaderSetVerificationFile( + cmSourceFile& source, const std::string& dir, + cm::optional<std::set<std::string>>& languages) const +{ + std::string extension; + std::string language = source.GetOrDetermineLanguage(); + + if (language.empty()) { + if (!languages) { + languages.emplace(); + for (auto const& tgtSource : this->GetAllConfigSources()) { + auto const& tgtSourceLanguage = + tgtSource.Source->GetOrDetermineLanguage(); + if (tgtSourceLanguage == "CXX") { + languages->insert("CXX"); + break; // C++ overrides everything else, so we don't need to keep + // checking. + } + if (tgtSourceLanguage == "C") { + languages->insert("C"); + } + } + } + + if (languages->count("CXX")) { + language = "CXX"; + } else if (languages->count("C")) { + language = "C"; + } + } + + if (language == "C") { + extension = ".c"; + } else if (language == "CXX") { + extension = ".cxx"; + } else { + return ""; + } + + std::string headerFilename = dir; + if (!headerFilename.empty()) { + headerFilename += '/'; + } + headerFilename += source.GetLocation().GetName(); + + auto filename = cmStrCat(this->LocalGenerator->GetCurrentBinaryDirectory(), + '/', this->GetName(), "_verify_header_sets/", + headerFilename, extension); + auto* verificationSource = this->Makefile->GetOrCreateSource(filename); + verificationSource->SetProperty("LANGUAGE", language); + + cmSystemTools::MakeDirectory(cmSystemTools::GetFilenamePath(filename)); + + cmGeneratedFileStream fout(filename); + fout.SetCopyIfDifferent(true); + fout << "#include <" << headerFilename << ">\n"; + fout.close(); + + return filename; +} |