summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Source/CMakeLists.txt1
-rw-r--r--Source/cmGeneratorTarget.cxx515
-rw-r--r--Source/cmGeneratorTarget_Sources.cxx560
-rwxr-xr-xbootstrap1
4 files changed, 562 insertions, 515 deletions
diff --git a/Source/CMakeLists.txt b/Source/CMakeLists.txt
index 5683524..8faebab 100644
--- a/Source/CMakeLists.txt
+++ b/Source/CMakeLists.txt
@@ -285,6 +285,7 @@ add_library(
cmGeneratorExpression.h
cmGeneratorTarget.cxx
cmGeneratorTarget.h
+ cmGeneratorTarget_Sources.cxx
cmGeneratorTarget_TargetPropertyEntry.cxx
cmLinkItemGraphVisitor.cxx
cmLinkItemGraphVisitor.h
diff --git a/Source/cmGeneratorTarget.cxx b/Source/cmGeneratorTarget.cxx
index 61b93be..fb921fd 100644
--- a/Source/cmGeneratorTarget.cxx
+++ b/Source/cmGeneratorTarget.cxx
@@ -23,8 +23,6 @@
#include <cmext/algorithm>
#include <cmext/string_view>
-#include "cmsys/RegularExpression.hxx"
-
#include "cmAlgorithms.h"
#include "cmComputeLinkInformation.h"
#include "cmCryptoHash.h"
@@ -49,7 +47,6 @@
#include "cmSourceFile.h"
#include "cmSourceFileLocation.h"
#include "cmSourceFileLocationKind.h"
-#include "cmSourceGroup.h"
#include "cmStandardLevel.h"
#include "cmStandardLevelResolver.h"
#include "cmState.h"
@@ -1520,519 +1517,7 @@ void AddLangSpecificImplicitIncludeDirectories(
}
}
-void AddObjectEntries(cmGeneratorTarget const* headTarget,
- std::string const& config,
- cmGeneratorExpressionDAGChecker* dagChecker,
- EvaluatedTargetPropertyEntries& entries)
-{
- if (cmLinkImplementationLibraries const* impl =
- headTarget->GetLinkImplementationLibraries(config, UseTo::Compile)) {
- entries.HadContextSensitiveCondition = impl->HadContextSensitiveCondition;
- for (cmLinkImplItem const& lib : impl->Libraries) {
- if (lib.Target &&
- lib.Target->GetType() == cmStateEnums::OBJECT_LIBRARY) {
- std::string uniqueName =
- headTarget->GetGlobalGenerator()->IndexGeneratorTargetUniquely(
- lib.Target);
- std::string genex = "$<TARGET_OBJECTS:" + std::move(uniqueName) + ">";
- cmGeneratorExpression ge(*headTarget->Makefile->GetCMakeInstance(),
- lib.Backtrace);
- std::unique_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(genex);
- cge->SetEvaluateForBuildsystem(true);
-
- EvaluatedTargetPropertyEntry ee(lib, lib.Backtrace);
- cmExpandList(cge->Evaluate(headTarget->GetLocalGenerator(), config,
- headTarget, dagChecker),
- ee.Values);
- if (cge->GetHadContextSensitiveCondition()) {
- ee.ContextDependent = true;
- }
- entries.Entries.emplace_back(std::move(ee));
- }
- }
- }
-}
-
-void addFileSetEntry(cmGeneratorTarget const* headTarget,
- std::string const& config,
- cmGeneratorExpressionDAGChecker* dagChecker,
- cmFileSet const* fileSet,
- EvaluatedTargetPropertyEntries& entries)
-{
- auto dirCges = fileSet->CompileDirectoryEntries();
- auto dirs = fileSet->EvaluateDirectoryEntries(
- dirCges, headTarget->GetLocalGenerator(), config, headTarget, dagChecker);
- bool contextSensitiveDirs = false;
- for (auto const& dirCge : dirCges) {
- if (dirCge->GetHadContextSensitiveCondition()) {
- contextSensitiveDirs = true;
- break;
- }
- }
- cmake* cm = headTarget->GetLocalGenerator()->GetCMakeInstance();
- for (auto& entryCge : fileSet->CompileFileEntries()) {
- auto tpe = cmGeneratorTarget::TargetPropertyEntry::CreateFileSet(
- dirs, contextSensitiveDirs, std::move(entryCge), fileSet);
- entries.Entries.emplace_back(
- EvaluateTargetPropertyEntry(headTarget, config, "", dagChecker, *tpe));
- EvaluatedTargetPropertyEntry const& entry = entries.Entries.back();
- for (auto const& file : entry.Values) {
- auto* sf = headTarget->Makefile->GetOrCreateSource(file);
- if (fileSet->GetType() == "HEADERS"_s) {
- sf->SetProperty("HEADER_FILE_ONLY", "TRUE");
- }
-
-#ifndef CMAKE_BOOTSTRAP
- std::string e;
- std::string w;
- auto path = sf->ResolveFullPath(&e, &w);
- if (!w.empty()) {
- cm->IssueMessage(MessageType::AUTHOR_WARNING, w, entry.Backtrace);
- }
- if (path.empty()) {
- if (!e.empty()) {
- cm->IssueMessage(MessageType::FATAL_ERROR, e, entry.Backtrace);
- }
- return;
- }
- bool found = false;
- for (auto const& sg : headTarget->Makefile->GetSourceGroups()) {
- if (sg.MatchChildrenFiles(path)) {
- found = true;
- break;
- }
- }
- if (!found) {
- if (fileSet->GetType() == "HEADERS"_s) {
- headTarget->Makefile->GetOrCreateSourceGroup("Header Files")
- ->AddGroupFile(path);
- }
- }
-#endif
- }
- }
-}
-
-void AddFileSetEntries(cmGeneratorTarget const* headTarget,
- std::string const& config,
- cmGeneratorExpressionDAGChecker* dagChecker,
- EvaluatedTargetPropertyEntries& entries)
-{
- for (auto const& entry : headTarget->Target->GetHeaderSetsEntries()) {
- for (auto const& name : cmList{ entry.Value }) {
- auto const* headerSet = headTarget->Target->GetFileSet(name);
- addFileSetEntry(headTarget, config, dagChecker, headerSet, entries);
- }
- }
- for (auto const& entry : headTarget->Target->GetCxxModuleSetsEntries()) {
- for (auto const& name : cmList{ entry.Value }) {
- auto const* cxxModuleSet = headTarget->Target->GetFileSet(name);
- addFileSetEntry(headTarget, config, dagChecker, cxxModuleSet, entries);
- }
- }
-}
-
-bool processSources(cmGeneratorTarget const* tgt,
- EvaluatedTargetPropertyEntries& entries,
- std::vector<BT<std::string>>& srcs,
- std::unordered_set<std::string>& uniqueSrcs,
- bool debugSources)
-{
- cmMakefile* mf = tgt->Target->GetMakefile();
-
- bool contextDependent = entries.HadContextSensitiveCondition;
-
- for (EvaluatedTargetPropertyEntry& entry : entries.Entries) {
- if (entry.ContextDependent) {
- contextDependent = true;
- }
-
- cmLinkImplItem const& item = entry.LinkImplItem;
- std::string const& targetName = item.AsStr();
-
- for (std::string& src : entry.Values) {
- cmSourceFile* sf = mf->GetOrCreateSource(src);
- std::string e;
- std::string w;
- std::string fullPath = sf->ResolveFullPath(&e, &w);
- cmake* cm = tgt->GetLocalGenerator()->GetCMakeInstance();
- if (!w.empty()) {
- cm->IssueMessage(MessageType::AUTHOR_WARNING, w, entry.Backtrace);
- }
- if (fullPath.empty()) {
- if (!e.empty()) {
- cm->IssueMessage(MessageType::FATAL_ERROR, e, entry.Backtrace);
- }
- return contextDependent;
- }
-
- if (!targetName.empty() && !cmSystemTools::FileIsFullPath(src)) {
- std::ostringstream err;
- if (!targetName.empty()) {
- err << "Target \"" << targetName
- << "\" contains relative path in its INTERFACE_SOURCES:\n \""
- << src << "\"";
- } else {
- err << "Found relative path while evaluating sources of \""
- << tgt->GetName() << "\":\n \"" << src << "\"\n";
- }
- tgt->GetLocalGenerator()->IssueMessage(MessageType::FATAL_ERROR,
- err.str());
- return contextDependent;
- }
- src = fullPath;
- }
- std::string usedSources;
- for (std::string const& src : entry.Values) {
- if (uniqueSrcs.insert(src).second) {
- srcs.emplace_back(src, entry.Backtrace);
- if (debugSources) {
- usedSources += " * " + src + "\n";
- }
- }
- }
- if (!usedSources.empty()) {
- tgt->GetLocalGenerator()->GetCMakeInstance()->IssueMessage(
- MessageType::LOG,
- std::string("Used sources for target ") + tgt->GetName() + ":\n" +
- usedSources,
- entry.Backtrace);
- }
- }
- return contextDependent;
-}
}
-
-std::vector<BT<std::string>> cmGeneratorTarget::GetSourceFilePaths(
- std::string const& config) const
-{
- std::vector<BT<std::string>> files;
-
- if (!this->LocalGenerator->GetGlobalGenerator()->GetConfigureDoneCMP0026()) {
- // At configure-time, this method can be called as part of getting the
- // LOCATION property or to export() a file to be include()d. However
- // there is no cmGeneratorTarget at configure-time, so search the SOURCES
- // for TARGET_OBJECTS instead for backwards compatibility with OLD
- // behavior of CMP0024 and CMP0026 only.
-
- cmBTStringRange sourceEntries = this->Target->GetSourceEntries();
- for (auto const& entry : sourceEntries) {
- cmList items{ entry.Value };
- for (auto const& item : items) {
- if (cmHasLiteralPrefix(item, "$<TARGET_OBJECTS:") &&
- item.back() == '>') {
- continue;
- }
- files.emplace_back(item);
- }
- }
- return files;
- }
-
- cmList debugProperties{ this->Makefile->GetDefinition(
- "CMAKE_DEBUG_TARGET_PROPERTIES") };
- bool debugSources =
- !this->DebugSourcesDone && cm::contains(debugProperties, "SOURCES");
-
- if (this->LocalGenerator->GetGlobalGenerator()->GetConfigureDoneCMP0026()) {
- this->DebugSourcesDone = true;
- }
-
- cmGeneratorExpressionDAGChecker dagChecker(this, "SOURCES", nullptr, nullptr,
- this->LocalGenerator);
-
- EvaluatedTargetPropertyEntries entries = EvaluateTargetPropertyEntries(
- this, config, std::string(), &dagChecker, this->SourceEntries);
-
- std::unordered_set<std::string> uniqueSrcs;
- bool contextDependentDirectSources =
- processSources(this, entries, files, uniqueSrcs, debugSources);
-
- // Collect INTERFACE_SOURCES of all direct link-dependencies.
- EvaluatedTargetPropertyEntries linkInterfaceSourcesEntries;
- AddInterfaceEntries(this, config, "INTERFACE_SOURCES", std::string(),
- &dagChecker, linkInterfaceSourcesEntries,
- IncludeRuntimeInterface::No, UseTo::Compile);
- bool contextDependentInterfaceSources = processSources(
- this, linkInterfaceSourcesEntries, files, uniqueSrcs, debugSources);
-
- // Collect TARGET_OBJECTS of direct object link-dependencies.
- bool contextDependentObjects = false;
- if (this->GetType() != cmStateEnums::OBJECT_LIBRARY) {
- EvaluatedTargetPropertyEntries linkObjectsEntries;
- AddObjectEntries(this, config, &dagChecker, linkObjectsEntries);
- contextDependentObjects = processSources(this, linkObjectsEntries, files,
- uniqueSrcs, debugSources);
- // Note that for imported targets or multi-config generators supporting
- // cross-config builds the paths to the object files must be per-config,
- // so contextDependentObjects will be true here even if object libraries
- // are specified without per-config generator expressions.
- }
-
- // Collect this target's file sets.
- EvaluatedTargetPropertyEntries fileSetEntries;
- AddFileSetEntries(this, config, &dagChecker, fileSetEntries);
- bool contextDependentFileSets =
- processSources(this, fileSetEntries, files, uniqueSrcs, debugSources);
-
- // Determine if sources are context-dependent or not.
- if (!contextDependentDirectSources && !contextDependentInterfaceSources &&
- !contextDependentObjects && !contextDependentFileSets) {
- this->SourcesAreContextDependent = Tribool::False;
- } else {
- this->SourcesAreContextDependent = Tribool::True;
- }
-
- return files;
-}
-
-void cmGeneratorTarget::GetSourceFiles(std::vector<cmSourceFile*>& files,
- const std::string& config) const
-{
- std::vector<BT<cmSourceFile*>> tmp = this->GetSourceFiles(config);
- files.reserve(tmp.size());
- for (BT<cmSourceFile*>& v : tmp) {
- files.push_back(v.Value);
- }
-}
-
-std::vector<BT<cmSourceFile*>> cmGeneratorTarget::GetSourceFiles(
- std::string const& config) const
-{
- std::vector<BT<cmSourceFile*>> files;
- if (!this->GlobalGenerator->GetConfigureDoneCMP0026()) {
- // Since we are still configuring not all sources may exist yet,
- // so we need to avoid full source classification because that
- // requires the absolute paths to all sources to be determined.
- // Since this is only for compatibility with old policies that
- // projects should not depend on anymore, just compute the files
- // without memoizing them.
- std::vector<BT<std::string>> srcs = this->GetSourceFilePaths(config);
- std::set<cmSourceFile*> emitted;
- for (BT<std::string> const& s : srcs) {
- cmSourceFile* sf = this->Makefile->GetOrCreateSource(s.Value);
- if (emitted.insert(sf).second) {
- files.emplace_back(sf, s.Backtrace);
- }
- }
- return files;
- }
-
- KindedSources const& kinded = this->GetKindedSources(config);
- files.reserve(kinded.Sources.size());
- for (SourceAndKind const& si : kinded.Sources) {
- files.push_back(si.Source);
- }
- return files;
-}
-
-void cmGeneratorTarget::GetSourceFilesWithoutObjectLibraries(
- std::vector<cmSourceFile*>& files, const std::string& config) const
-{
- std::vector<BT<cmSourceFile*>> tmp =
- this->GetSourceFilesWithoutObjectLibraries(config);
- files.reserve(tmp.size());
- for (BT<cmSourceFile*>& v : tmp) {
- files.push_back(v.Value);
- }
-}
-
-std::vector<BT<cmSourceFile*>>
-cmGeneratorTarget::GetSourceFilesWithoutObjectLibraries(
- std::string const& config) const
-{
- std::vector<BT<cmSourceFile*>> files;
- KindedSources const& kinded = this->GetKindedSources(config);
- files.reserve(kinded.Sources.size());
- for (SourceAndKind const& si : kinded.Sources) {
- if (si.Source.Value->GetObjectLibrary().empty()) {
- files.push_back(si.Source);
- }
- }
- return files;
-}
-
-cmGeneratorTarget::KindedSources const& cmGeneratorTarget::GetKindedSources(
- std::string const& config) const
-{
- // If we already processed one configuration and found no dependency
- // on configuration then always use the one result.
- if (this->SourcesAreContextDependent == Tribool::False) {
- return this->KindedSourcesMap.begin()->second;
- }
-
- // Lookup any existing link implementation for this configuration.
- std::string const key = cmSystemTools::UpperCase(config);
- auto it = this->KindedSourcesMap.find(key);
- if (it != this->KindedSourcesMap.end()) {
- if (!it->second.Initialized) {
- std::ostringstream e;
- e << "The SOURCES of \"" << this->GetName()
- << "\" use a generator expression that depends on the "
- "SOURCES themselves.";
- this->GlobalGenerator->GetCMakeInstance()->IssueMessage(
- MessageType::FATAL_ERROR, e.str(), this->GetBacktrace());
- static KindedSources empty;
- return empty;
- }
- return it->second;
- }
-
- // Add an entry to the map for this configuration.
- KindedSources& files = this->KindedSourcesMap[key];
- this->ComputeKindedSources(files, config);
- files.Initialized = true;
- return files;
-}
-
-void cmGeneratorTarget::ComputeKindedSources(KindedSources& files,
- std::string const& config) const
-{
- // Get the source file paths by string.
- std::vector<BT<std::string>> srcs = this->GetSourceFilePaths(config);
-
- cmsys::RegularExpression header_regex(CM_HEADER_REGEX);
- std::vector<cmSourceFile*> badObjLib;
-
- std::set<cmSourceFile*> emitted;
- for (BT<std::string> const& s : srcs) {
- // Create each source at most once.
- cmSourceFile* sf = this->Makefile->GetOrCreateSource(s.Value);
- if (!emitted.insert(sf).second) {
- continue;
- }
-
- // Compute the kind (classification) of this source file.
- SourceKind kind;
- std::string ext = cmSystemTools::LowerCase(sf->GetExtension());
- cmFileSet const* fs = this->GetFileSetForSource(config, sf);
- if (sf->GetCustomCommand()) {
- kind = SourceKindCustomCommand;
- } else if (!this->Target->IsNormal() && !this->Target->IsImported() &&
- fs && (fs->GetType() == "CXX_MODULES"_s)) {
- kind = SourceKindCxxModuleSource;
- } else if (this->Target->GetType() == cmStateEnums::UTILITY ||
- this->Target->GetType() == cmStateEnums::INTERFACE_LIBRARY
- // XXX(clang-tidy): https://bugs.llvm.org/show_bug.cgi?id=44165
- // NOLINTNEXTLINE(bugprone-branch-clone)
- ) {
- kind = SourceKindExtra;
- } else if (this->IsSourceFilePartOfUnityBatch(sf->ResolveFullPath())) {
- kind = SourceKindUnityBatched;
- // XXX(clang-tidy): https://bugs.llvm.org/show_bug.cgi?id=44165
- // NOLINTNEXTLINE(bugprone-branch-clone)
- } else if (sf->GetPropertyAsBool("HEADER_FILE_ONLY")) {
- kind = SourceKindHeader;
- } else if (sf->GetPropertyAsBool("EXTERNAL_OBJECT")) {
- kind = SourceKindExternalObject;
- } else if (!sf->GetOrDetermineLanguage().empty()) {
- kind = SourceKindObjectSource;
- } else if (ext == "def") {
- kind = SourceKindModuleDefinition;
- if (this->GetType() == cmStateEnums::OBJECT_LIBRARY) {
- badObjLib.push_back(sf);
- }
- } else if (ext == "idl") {
- kind = SourceKindIDL;
- if (this->GetType() == cmStateEnums::OBJECT_LIBRARY) {
- badObjLib.push_back(sf);
- }
- } else if (ext == "resx") {
- kind = SourceKindResx;
- } else if (ext == "appxmanifest") {
- kind = SourceKindAppManifest;
- } else if (ext == "manifest") {
- if (sf->GetPropertyAsBool("VS_DEPLOYMENT_CONTENT")) {
- kind = SourceKindExtra;
- } else {
- kind = SourceKindManifest;
- }
- } else if (ext == "pfx") {
- kind = SourceKindCertificate;
- } else if (ext == "xaml") {
- kind = SourceKindXaml;
- } else if (header_regex.find(sf->ResolveFullPath())) {
- kind = SourceKindHeader;
- } else {
- kind = SourceKindExtra;
- }
-
- // Save this classified source file in the result vector.
- files.Sources.push_back({ BT<cmSourceFile*>(sf, s.Backtrace), kind });
- }
-
- if (!badObjLib.empty()) {
- std::ostringstream e;
- e << "OBJECT library \"" << this->GetName() << "\" contains:\n";
- for (cmSourceFile* i : badObjLib) {
- e << " " << i->GetLocation().GetName() << "\n";
- }
- e << "but may contain only sources that compile, header files, and "
- "other files that would not affect linking of a normal library.";
- this->GlobalGenerator->GetCMakeInstance()->IssueMessage(
- MessageType::FATAL_ERROR, e.str(), this->GetBacktrace());
- }
-}
-
-std::vector<cmGeneratorTarget::AllConfigSource> const&
-cmGeneratorTarget::GetAllConfigSources() const
-{
- if (this->AllConfigSources.empty()) {
- this->ComputeAllConfigSources();
- }
- return this->AllConfigSources;
-}
-
-void cmGeneratorTarget::ComputeAllConfigSources() const
-{
- std::vector<std::string> configs =
- this->Makefile->GetGeneratorConfigs(cmMakefile::IncludeEmptyConfig);
-
- std::map<cmSourceFile const*, size_t> index;
-
- for (size_t ci = 0; ci < configs.size(); ++ci) {
- KindedSources const& sources = this->GetKindedSources(configs[ci]);
- for (SourceAndKind const& src : sources.Sources) {
- auto mi = index.find(src.Source.Value);
- if (mi == index.end()) {
- AllConfigSource acs;
- acs.Source = src.Source.Value;
- acs.Kind = src.Kind;
- this->AllConfigSources.push_back(std::move(acs));
- std::map<cmSourceFile const*, size_t>::value_type entry(
- src.Source.Value, this->AllConfigSources.size() - 1);
- mi = index.insert(entry).first;
- }
- this->AllConfigSources[mi->second].Configs.push_back(ci);
- }
- }
-}
-
-std::vector<cmGeneratorTarget::AllConfigSource>
-cmGeneratorTarget::GetAllConfigSources(SourceKind kind) const
-{
- std::vector<AllConfigSource> result;
- for (AllConfigSource const& source : this->GetAllConfigSources()) {
- if (source.Kind == kind) {
- result.push_back(source);
- }
- }
- return result;
-}
-
-std::set<std::string> cmGeneratorTarget::GetAllConfigCompileLanguages() const
-{
- std::set<std::string> languages;
- std::vector<AllConfigSource> const& sources = this->GetAllConfigSources();
- for (AllConfigSource const& si : sources) {
- std::string const& lang = si.Source->GetOrDetermineLanguage();
- if (!lang.empty()) {
- languages.emplace(lang);
- }
- }
- return languages;
-}
-
std::string cmGeneratorTarget::GetCompilePDBName(
const std::string& config) const
{
diff --git a/Source/cmGeneratorTarget_Sources.cxx b/Source/cmGeneratorTarget_Sources.cxx
new file mode 100644
index 0000000..de18df5
--- /dev/null
+++ b/Source/cmGeneratorTarget_Sources.cxx
@@ -0,0 +1,560 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+/* clang-format off */
+#include "cmGeneratorTarget.h"
+/* clang-format on */
+
+#include <cstddef>
+#include <map>
+#include <memory>
+#include <set>
+#include <sstream>
+#include <string>
+#include <type_traits>
+#include <unordered_set>
+#include <utility>
+#include <vector>
+
+#include <cm/string_view>
+#include <cmext/algorithm>
+#include <cmext/string_view>
+
+#include "cmsys/RegularExpression.hxx"
+
+#include "cmAlgorithms.h"
+#include "cmEvaluatedTargetProperty.h"
+#include "cmFileSet.h"
+#include "cmGeneratorExpression.h"
+#include "cmGeneratorExpressionDAGChecker.h"
+#include "cmGlobalGenerator.h"
+#include "cmLinkItem.h"
+#include "cmList.h"
+#include "cmListFileCache.h"
+#include "cmLocalGenerator.h"
+#include "cmMakefile.h"
+#include "cmMessageType.h"
+#include "cmSourceFile.h"
+#include "cmSourceFileLocation.h"
+#include "cmSourceGroup.h"
+#include "cmStateTypes.h"
+#include "cmStringAlgorithms.h"
+#include "cmSystemTools.h"
+#include "cmTarget.h"
+#include "cmValue.h"
+#include "cmake.h"
+
+namespace {
+using UseTo = cmGeneratorTarget::UseTo;
+
+void AddObjectEntries(cmGeneratorTarget const* headTarget,
+ std::string const& config,
+ cmGeneratorExpressionDAGChecker* dagChecker,
+ EvaluatedTargetPropertyEntries& entries)
+{
+ if (cmLinkImplementationLibraries const* impl =
+ headTarget->GetLinkImplementationLibraries(config, UseTo::Compile)) {
+ entries.HadContextSensitiveCondition = impl->HadContextSensitiveCondition;
+ for (cmLinkImplItem const& lib : impl->Libraries) {
+ if (lib.Target &&
+ lib.Target->GetType() == cmStateEnums::OBJECT_LIBRARY) {
+ std::string uniqueName =
+ headTarget->GetGlobalGenerator()->IndexGeneratorTargetUniquely(
+ lib.Target);
+ std::string genex = "$<TARGET_OBJECTS:" + std::move(uniqueName) + ">";
+ cmGeneratorExpression ge(*headTarget->Makefile->GetCMakeInstance(),
+ lib.Backtrace);
+ std::unique_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(genex);
+ cge->SetEvaluateForBuildsystem(true);
+
+ EvaluatedTargetPropertyEntry ee(lib, lib.Backtrace);
+ cmExpandList(cge->Evaluate(headTarget->GetLocalGenerator(), config,
+ headTarget, dagChecker),
+ ee.Values);
+ if (cge->GetHadContextSensitiveCondition()) {
+ ee.ContextDependent = true;
+ }
+ entries.Entries.emplace_back(std::move(ee));
+ }
+ }
+ }
+}
+
+void addFileSetEntry(cmGeneratorTarget const* headTarget,
+ std::string const& config,
+ cmGeneratorExpressionDAGChecker* dagChecker,
+ cmFileSet const* fileSet,
+ EvaluatedTargetPropertyEntries& entries)
+{
+ auto dirCges = fileSet->CompileDirectoryEntries();
+ auto dirs = fileSet->EvaluateDirectoryEntries(
+ dirCges, headTarget->GetLocalGenerator(), config, headTarget, dagChecker);
+ bool contextSensitiveDirs = false;
+ for (auto const& dirCge : dirCges) {
+ if (dirCge->GetHadContextSensitiveCondition()) {
+ contextSensitiveDirs = true;
+ break;
+ }
+ }
+ cmake* cm = headTarget->GetLocalGenerator()->GetCMakeInstance();
+ for (auto& entryCge : fileSet->CompileFileEntries()) {
+ auto tpe = cmGeneratorTarget::TargetPropertyEntry::CreateFileSet(
+ dirs, contextSensitiveDirs, std::move(entryCge), fileSet);
+ entries.Entries.emplace_back(
+ EvaluateTargetPropertyEntry(headTarget, config, "", dagChecker, *tpe));
+ EvaluatedTargetPropertyEntry const& entry = entries.Entries.back();
+ for (auto const& file : entry.Values) {
+ auto* sf = headTarget->Makefile->GetOrCreateSource(file);
+ if (fileSet->GetType() == "HEADERS"_s) {
+ sf->SetProperty("HEADER_FILE_ONLY", "TRUE");
+ }
+
+#ifndef CMAKE_BOOTSTRAP
+ std::string e;
+ std::string w;
+ auto path = sf->ResolveFullPath(&e, &w);
+ if (!w.empty()) {
+ cm->IssueMessage(MessageType::AUTHOR_WARNING, w, entry.Backtrace);
+ }
+ if (path.empty()) {
+ if (!e.empty()) {
+ cm->IssueMessage(MessageType::FATAL_ERROR, e, entry.Backtrace);
+ }
+ return;
+ }
+ bool found = false;
+ for (auto const& sg : headTarget->Makefile->GetSourceGroups()) {
+ if (sg.MatchChildrenFiles(path)) {
+ found = true;
+ break;
+ }
+ }
+ if (!found) {
+ if (fileSet->GetType() == "HEADERS"_s) {
+ headTarget->Makefile->GetOrCreateSourceGroup("Header Files")
+ ->AddGroupFile(path);
+ }
+ }
+#endif
+ }
+ }
+}
+
+void AddFileSetEntries(cmGeneratorTarget const* headTarget,
+ std::string const& config,
+ cmGeneratorExpressionDAGChecker* dagChecker,
+ EvaluatedTargetPropertyEntries& entries)
+{
+ for (auto const& entry : headTarget->Target->GetHeaderSetsEntries()) {
+ for (auto const& name : cmList{ entry.Value }) {
+ auto const* headerSet = headTarget->Target->GetFileSet(name);
+ addFileSetEntry(headTarget, config, dagChecker, headerSet, entries);
+ }
+ }
+ for (auto const& entry : headTarget->Target->GetCxxModuleSetsEntries()) {
+ for (auto const& name : cmList{ entry.Value }) {
+ auto const* cxxModuleSet = headTarget->Target->GetFileSet(name);
+ addFileSetEntry(headTarget, config, dagChecker, cxxModuleSet, entries);
+ }
+ }
+}
+
+bool processSources(cmGeneratorTarget const* tgt,
+ EvaluatedTargetPropertyEntries& entries,
+ std::vector<BT<std::string>>& srcs,
+ std::unordered_set<std::string>& uniqueSrcs,
+ bool debugSources)
+{
+ cmMakefile* mf = tgt->Target->GetMakefile();
+
+ bool contextDependent = entries.HadContextSensitiveCondition;
+
+ for (EvaluatedTargetPropertyEntry& entry : entries.Entries) {
+ if (entry.ContextDependent) {
+ contextDependent = true;
+ }
+
+ cmLinkImplItem const& item = entry.LinkImplItem;
+ std::string const& targetName = item.AsStr();
+
+ for (std::string& src : entry.Values) {
+ cmSourceFile* sf = mf->GetOrCreateSource(src);
+ std::string e;
+ std::string w;
+ std::string fullPath = sf->ResolveFullPath(&e, &w);
+ cmake* cm = tgt->GetLocalGenerator()->GetCMakeInstance();
+ if (!w.empty()) {
+ cm->IssueMessage(MessageType::AUTHOR_WARNING, w, entry.Backtrace);
+ }
+ if (fullPath.empty()) {
+ if (!e.empty()) {
+ cm->IssueMessage(MessageType::FATAL_ERROR, e, entry.Backtrace);
+ }
+ return contextDependent;
+ }
+
+ if (!targetName.empty() && !cmSystemTools::FileIsFullPath(src)) {
+ std::ostringstream err;
+ if (!targetName.empty()) {
+ err << "Target \"" << targetName
+ << "\" contains relative path in its INTERFACE_SOURCES:\n \""
+ << src << "\"";
+ } else {
+ err << "Found relative path while evaluating sources of \""
+ << tgt->GetName() << "\":\n \"" << src << "\"\n";
+ }
+ tgt->GetLocalGenerator()->IssueMessage(MessageType::FATAL_ERROR,
+ err.str());
+ return contextDependent;
+ }
+ src = fullPath;
+ }
+ std::string usedSources;
+ for (std::string const& src : entry.Values) {
+ if (uniqueSrcs.insert(src).second) {
+ srcs.emplace_back(src, entry.Backtrace);
+ if (debugSources) {
+ usedSources += " * " + src + "\n";
+ }
+ }
+ }
+ if (!usedSources.empty()) {
+ tgt->GetLocalGenerator()->GetCMakeInstance()->IssueMessage(
+ MessageType::LOG,
+ std::string("Used sources for target ") + tgt->GetName() + ":\n" +
+ usedSources,
+ entry.Backtrace);
+ }
+ }
+ return contextDependent;
+}
+}
+
+std::vector<BT<std::string>> cmGeneratorTarget::GetSourceFilePaths(
+ std::string const& config) const
+{
+ std::vector<BT<std::string>> files;
+
+ if (!this->LocalGenerator->GetGlobalGenerator()->GetConfigureDoneCMP0026()) {
+ // At configure-time, this method can be called as part of getting the
+ // LOCATION property or to export() a file to be include()d. However
+ // there is no cmGeneratorTarget at configure-time, so search the SOURCES
+ // for TARGET_OBJECTS instead for backwards compatibility with OLD
+ // behavior of CMP0024 and CMP0026 only.
+
+ cmBTStringRange sourceEntries = this->Target->GetSourceEntries();
+ for (auto const& entry : sourceEntries) {
+ cmList items{ entry.Value };
+ for (auto const& item : items) {
+ if (cmHasLiteralPrefix(item, "$<TARGET_OBJECTS:") &&
+ item.back() == '>') {
+ continue;
+ }
+ files.emplace_back(item);
+ }
+ }
+ return files;
+ }
+
+ cmList debugProperties{ this->Makefile->GetDefinition(
+ "CMAKE_DEBUG_TARGET_PROPERTIES") };
+ bool debugSources =
+ !this->DebugSourcesDone && cm::contains(debugProperties, "SOURCES");
+
+ if (this->LocalGenerator->GetGlobalGenerator()->GetConfigureDoneCMP0026()) {
+ this->DebugSourcesDone = true;
+ }
+
+ cmGeneratorExpressionDAGChecker dagChecker(this, "SOURCES", nullptr, nullptr,
+ this->LocalGenerator);
+
+ EvaluatedTargetPropertyEntries entries = EvaluateTargetPropertyEntries(
+ this, config, std::string(), &dagChecker, this->SourceEntries);
+
+ std::unordered_set<std::string> uniqueSrcs;
+ bool contextDependentDirectSources =
+ processSources(this, entries, files, uniqueSrcs, debugSources);
+
+ // Collect INTERFACE_SOURCES of all direct link-dependencies.
+ EvaluatedTargetPropertyEntries linkInterfaceSourcesEntries;
+ AddInterfaceEntries(this, config, "INTERFACE_SOURCES", std::string(),
+ &dagChecker, linkInterfaceSourcesEntries,
+ IncludeRuntimeInterface::No, UseTo::Compile);
+ bool contextDependentInterfaceSources = processSources(
+ this, linkInterfaceSourcesEntries, files, uniqueSrcs, debugSources);
+
+ // Collect TARGET_OBJECTS of direct object link-dependencies.
+ bool contextDependentObjects = false;
+ if (this->GetType() != cmStateEnums::OBJECT_LIBRARY) {
+ EvaluatedTargetPropertyEntries linkObjectsEntries;
+ AddObjectEntries(this, config, &dagChecker, linkObjectsEntries);
+ contextDependentObjects = processSources(this, linkObjectsEntries, files,
+ uniqueSrcs, debugSources);
+ // Note that for imported targets or multi-config generators supporting
+ // cross-config builds the paths to the object files must be per-config,
+ // so contextDependentObjects will be true here even if object libraries
+ // are specified without per-config generator expressions.
+ }
+
+ // Collect this target's file sets.
+ EvaluatedTargetPropertyEntries fileSetEntries;
+ AddFileSetEntries(this, config, &dagChecker, fileSetEntries);
+ bool contextDependentFileSets =
+ processSources(this, fileSetEntries, files, uniqueSrcs, debugSources);
+
+ // Determine if sources are context-dependent or not.
+ if (!contextDependentDirectSources && !contextDependentInterfaceSources &&
+ !contextDependentObjects && !contextDependentFileSets) {
+ this->SourcesAreContextDependent = Tribool::False;
+ } else {
+ this->SourcesAreContextDependent = Tribool::True;
+ }
+
+ return files;
+}
+
+void cmGeneratorTarget::GetSourceFiles(std::vector<cmSourceFile*>& files,
+ const std::string& config) const
+{
+ std::vector<BT<cmSourceFile*>> tmp = this->GetSourceFiles(config);
+ files.reserve(tmp.size());
+ for (BT<cmSourceFile*>& v : tmp) {
+ files.push_back(v.Value);
+ }
+}
+
+std::vector<BT<cmSourceFile*>> cmGeneratorTarget::GetSourceFiles(
+ std::string const& config) const
+{
+ std::vector<BT<cmSourceFile*>> files;
+ if (!this->GlobalGenerator->GetConfigureDoneCMP0026()) {
+ // Since we are still configuring not all sources may exist yet,
+ // so we need to avoid full source classification because that
+ // requires the absolute paths to all sources to be determined.
+ // Since this is only for compatibility with old policies that
+ // projects should not depend on anymore, just compute the files
+ // without memoizing them.
+ std::vector<BT<std::string>> srcs = this->GetSourceFilePaths(config);
+ std::set<cmSourceFile*> emitted;
+ for (BT<std::string> const& s : srcs) {
+ cmSourceFile* sf = this->Makefile->GetOrCreateSource(s.Value);
+ if (emitted.insert(sf).second) {
+ files.emplace_back(sf, s.Backtrace);
+ }
+ }
+ return files;
+ }
+
+ KindedSources const& kinded = this->GetKindedSources(config);
+ files.reserve(kinded.Sources.size());
+ for (SourceAndKind const& si : kinded.Sources) {
+ files.push_back(si.Source);
+ }
+ return files;
+}
+
+void cmGeneratorTarget::GetSourceFilesWithoutObjectLibraries(
+ std::vector<cmSourceFile*>& files, const std::string& config) const
+{
+ std::vector<BT<cmSourceFile*>> tmp =
+ this->GetSourceFilesWithoutObjectLibraries(config);
+ files.reserve(tmp.size());
+ for (BT<cmSourceFile*>& v : tmp) {
+ files.push_back(v.Value);
+ }
+}
+
+std::vector<BT<cmSourceFile*>>
+cmGeneratorTarget::GetSourceFilesWithoutObjectLibraries(
+ std::string const& config) const
+{
+ std::vector<BT<cmSourceFile*>> files;
+ KindedSources const& kinded = this->GetKindedSources(config);
+ files.reserve(kinded.Sources.size());
+ for (SourceAndKind const& si : kinded.Sources) {
+ if (si.Source.Value->GetObjectLibrary().empty()) {
+ files.push_back(si.Source);
+ }
+ }
+ return files;
+}
+
+cmGeneratorTarget::KindedSources const& cmGeneratorTarget::GetKindedSources(
+ std::string const& config) const
+{
+ // If we already processed one configuration and found no dependency
+ // on configuration then always use the one result.
+ if (this->SourcesAreContextDependent == Tribool::False) {
+ return this->KindedSourcesMap.begin()->second;
+ }
+
+ // Lookup any existing link implementation for this configuration.
+ std::string const key = cmSystemTools::UpperCase(config);
+ auto it = this->KindedSourcesMap.find(key);
+ if (it != this->KindedSourcesMap.end()) {
+ if (!it->second.Initialized) {
+ std::ostringstream e;
+ e << "The SOURCES of \"" << this->GetName()
+ << "\" use a generator expression that depends on the "
+ "SOURCES themselves.";
+ this->GlobalGenerator->GetCMakeInstance()->IssueMessage(
+ MessageType::FATAL_ERROR, e.str(), this->GetBacktrace());
+ static KindedSources empty;
+ return empty;
+ }
+ return it->second;
+ }
+
+ // Add an entry to the map for this configuration.
+ KindedSources& files = this->KindedSourcesMap[key];
+ this->ComputeKindedSources(files, config);
+ files.Initialized = true;
+ return files;
+}
+
+void cmGeneratorTarget::ComputeKindedSources(KindedSources& files,
+ std::string const& config) const
+{
+ // Get the source file paths by string.
+ std::vector<BT<std::string>> srcs = this->GetSourceFilePaths(config);
+
+ cmsys::RegularExpression header_regex(CM_HEADER_REGEX);
+ std::vector<cmSourceFile*> badObjLib;
+
+ std::set<cmSourceFile*> emitted;
+ for (BT<std::string> const& s : srcs) {
+ // Create each source at most once.
+ cmSourceFile* sf = this->Makefile->GetOrCreateSource(s.Value);
+ if (!emitted.insert(sf).second) {
+ continue;
+ }
+
+ // Compute the kind (classification) of this source file.
+ SourceKind kind;
+ std::string ext = cmSystemTools::LowerCase(sf->GetExtension());
+ cmFileSet const* fs = this->GetFileSetForSource(config, sf);
+ if (sf->GetCustomCommand()) {
+ kind = SourceKindCustomCommand;
+ } else if (!this->Target->IsNormal() && !this->Target->IsImported() &&
+ fs && (fs->GetType() == "CXX_MODULES"_s)) {
+ kind = SourceKindCxxModuleSource;
+ } else if (this->Target->GetType() == cmStateEnums::UTILITY ||
+ this->Target->GetType() == cmStateEnums::INTERFACE_LIBRARY
+ // XXX(clang-tidy): https://bugs.llvm.org/show_bug.cgi?id=44165
+ // NOLINTNEXTLINE(bugprone-branch-clone)
+ ) {
+ kind = SourceKindExtra;
+ } else if (this->IsSourceFilePartOfUnityBatch(sf->ResolveFullPath())) {
+ kind = SourceKindUnityBatched;
+ // XXX(clang-tidy): https://bugs.llvm.org/show_bug.cgi?id=44165
+ // NOLINTNEXTLINE(bugprone-branch-clone)
+ } else if (sf->GetPropertyAsBool("HEADER_FILE_ONLY")) {
+ kind = SourceKindHeader;
+ } else if (sf->GetPropertyAsBool("EXTERNAL_OBJECT")) {
+ kind = SourceKindExternalObject;
+ } else if (!sf->GetOrDetermineLanguage().empty()) {
+ kind = SourceKindObjectSource;
+ } else if (ext == "def") {
+ kind = SourceKindModuleDefinition;
+ if (this->GetType() == cmStateEnums::OBJECT_LIBRARY) {
+ badObjLib.push_back(sf);
+ }
+ } else if (ext == "idl") {
+ kind = SourceKindIDL;
+ if (this->GetType() == cmStateEnums::OBJECT_LIBRARY) {
+ badObjLib.push_back(sf);
+ }
+ } else if (ext == "resx") {
+ kind = SourceKindResx;
+ } else if (ext == "appxmanifest") {
+ kind = SourceKindAppManifest;
+ } else if (ext == "manifest") {
+ if (sf->GetPropertyAsBool("VS_DEPLOYMENT_CONTENT")) {
+ kind = SourceKindExtra;
+ } else {
+ kind = SourceKindManifest;
+ }
+ } else if (ext == "pfx") {
+ kind = SourceKindCertificate;
+ } else if (ext == "xaml") {
+ kind = SourceKindXaml;
+ } else if (header_regex.find(sf->ResolveFullPath())) {
+ kind = SourceKindHeader;
+ } else {
+ kind = SourceKindExtra;
+ }
+
+ // Save this classified source file in the result vector.
+ files.Sources.push_back({ BT<cmSourceFile*>(sf, s.Backtrace), kind });
+ }
+
+ if (!badObjLib.empty()) {
+ std::ostringstream e;
+ e << "OBJECT library \"" << this->GetName() << "\" contains:\n";
+ for (cmSourceFile* i : badObjLib) {
+ e << " " << i->GetLocation().GetName() << "\n";
+ }
+ e << "but may contain only sources that compile, header files, and "
+ "other files that would not affect linking of a normal library.";
+ this->GlobalGenerator->GetCMakeInstance()->IssueMessage(
+ MessageType::FATAL_ERROR, e.str(), this->GetBacktrace());
+ }
+}
+
+std::vector<cmGeneratorTarget::AllConfigSource> const&
+cmGeneratorTarget::GetAllConfigSources() const
+{
+ if (this->AllConfigSources.empty()) {
+ this->ComputeAllConfigSources();
+ }
+ return this->AllConfigSources;
+}
+
+void cmGeneratorTarget::ComputeAllConfigSources() const
+{
+ std::vector<std::string> configs =
+ this->Makefile->GetGeneratorConfigs(cmMakefile::IncludeEmptyConfig);
+
+ std::map<cmSourceFile const*, size_t> index;
+
+ for (size_t ci = 0; ci < configs.size(); ++ci) {
+ KindedSources const& sources = this->GetKindedSources(configs[ci]);
+ for (SourceAndKind const& src : sources.Sources) {
+ auto mi = index.find(src.Source.Value);
+ if (mi == index.end()) {
+ AllConfigSource acs;
+ acs.Source = src.Source.Value;
+ acs.Kind = src.Kind;
+ this->AllConfigSources.push_back(std::move(acs));
+ std::map<cmSourceFile const*, size_t>::value_type entry(
+ src.Source.Value, this->AllConfigSources.size() - 1);
+ mi = index.insert(entry).first;
+ }
+ this->AllConfigSources[mi->second].Configs.push_back(ci);
+ }
+ }
+}
+
+std::vector<cmGeneratorTarget::AllConfigSource>
+cmGeneratorTarget::GetAllConfigSources(SourceKind kind) const
+{
+ std::vector<AllConfigSource> result;
+ for (AllConfigSource const& source : this->GetAllConfigSources()) {
+ if (source.Kind == kind) {
+ result.push_back(source);
+ }
+ }
+ return result;
+}
+
+std::set<std::string> cmGeneratorTarget::GetAllConfigCompileLanguages() const
+{
+ std::set<std::string> languages;
+ std::vector<AllConfigSource> const& sources = this->GetAllConfigSources();
+ for (AllConfigSource const& si : sources) {
+ std::string const& lang = si.Source->GetOrDetermineLanguage();
+ if (!lang.empty()) {
+ languages.emplace(lang);
+ }
+ }
+ return languages;
+}
diff --git a/bootstrap b/bootstrap
index 8347894..fc77bcc 100755
--- a/bootstrap
+++ b/bootstrap
@@ -381,6 +381,7 @@ CMAKE_CXX_SOURCES="\
cmGeneratorExpressionNode \
cmGeneratorExpressionParser \
cmGeneratorTarget \
+ cmGeneratorTarget_Sources \
cmGeneratorTarget_TargetPropertyEntry \
cmGetCMakePropertyCommand \
cmGetDirectoryPropertyCommand \