|
|
@@ -25,6 +25,7 @@
|
|
|
#include "cmAlgorithms.h"
|
|
|
#include "cmComputeLinkInformation.h"
|
|
|
#include "cmCustomCommandGenerator.h"
|
|
|
+#include "cmFileSet.h"
|
|
|
#include "cmFileTimes.h"
|
|
|
#include "cmGeneratedFileStream.h"
|
|
|
#include "cmGeneratorExpression.h"
|
|
|
@@ -41,6 +42,7 @@
|
|
|
#include "cmSourceFile.h"
|
|
|
#include "cmSourceFileLocation.h"
|
|
|
#include "cmSourceFileLocationKind.h"
|
|
|
+#include "cmSourceGroup.h"
|
|
|
#include "cmStandardLevelResolver.h"
|
|
|
#include "cmState.h"
|
|
|
#include "cmStringAlgorithms.h"
|
|
|
@@ -173,6 +175,65 @@ private:
|
|
|
BT<std::string> PropertyValue;
|
|
|
};
|
|
|
|
|
|
+class TargetPropertyEntryFileSet
|
|
|
+ : public cmGeneratorTarget::TargetPropertyEntry
|
|
|
+{
|
|
|
+public:
|
|
|
+ TargetPropertyEntryFileSet(
|
|
|
+ std::vector<std::string> dirs, bool contextSensitiveDirs,
|
|
|
+ std::unique_ptr<cmCompiledGeneratorExpression> entryCge,
|
|
|
+ const cmFileSet* fileSet, cmLinkImplItem const& item = NoLinkImplItem)
|
|
|
+ : cmGeneratorTarget::TargetPropertyEntry(item)
|
|
|
+ , BaseDirs(std::move(dirs))
|
|
|
+ , ContextSensitiveDirs(contextSensitiveDirs)
|
|
|
+ , EntryCge(std::move(entryCge))
|
|
|
+ , FileSet(fileSet)
|
|
|
+ {
|
|
|
+ }
|
|
|
+
|
|
|
+ const std::string& Evaluate(cmLocalGenerator* lg, const std::string& config,
|
|
|
+ cmGeneratorTarget const* headTarget,
|
|
|
+ cmGeneratorExpressionDAGChecker* dagChecker,
|
|
|
+ std::string const& /*lang*/) const override
|
|
|
+ {
|
|
|
+ std::map<std::string, std::vector<std::string>> filesPerDir;
|
|
|
+ this->FileSet->EvaluateFileEntry(this->BaseDirs, filesPerDir,
|
|
|
+ this->EntryCge, lg, config, headTarget,
|
|
|
+ dagChecker);
|
|
|
+
|
|
|
+ std::vector<std::string> files;
|
|
|
+ for (auto const& it : filesPerDir) {
|
|
|
+ files.insert(files.end(), it.second.begin(), it.second.end());
|
|
|
+ }
|
|
|
+
|
|
|
+ static std::string filesStr;
|
|
|
+ filesStr = cmJoin(files, ";");
|
|
|
+ return filesStr;
|
|
|
+ }
|
|
|
+
|
|
|
+ cmListFileBacktrace GetBacktrace() const override
|
|
|
+ {
|
|
|
+ return this->EntryCge->GetBacktrace();
|
|
|
+ }
|
|
|
+
|
|
|
+ std::string const& GetInput() const override
|
|
|
+ {
|
|
|
+ return this->EntryCge->GetInput();
|
|
|
+ }
|
|
|
+
|
|
|
+ bool GetHadContextSensitiveCondition() const override
|
|
|
+ {
|
|
|
+ return this->ContextSensitiveDirs ||
|
|
|
+ this->EntryCge->GetHadContextSensitiveCondition();
|
|
|
+ }
|
|
|
+
|
|
|
+private:
|
|
|
+ const std::vector<std::string> BaseDirs;
|
|
|
+ const bool ContextSensitiveDirs;
|
|
|
+ const std::unique_ptr<cmCompiledGeneratorExpression> EntryCge;
|
|
|
+ const cmFileSet* FileSet;
|
|
|
+};
|
|
|
+
|
|
|
std::unique_ptr<
|
|
|
cmGeneratorTarget::
|
|
|
TargetPropertyEntry> static CreateTargetPropertyEntry(const BT<std::
|
|
|
@@ -1594,6 +1655,80 @@ void AddObjectEntries(cmGeneratorTarget const* headTarget,
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+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()) {
|
|
|
+ TargetPropertyEntryFileSet tpe(dirs, contextSensitiveDirs,
|
|
|
+ std::move(entryCge), fileSet);
|
|
|
+ entries.Entries.emplace_back(
|
|
|
+ EvaluateTargetPropertyEntry(headTarget, config, "", dagChecker, tpe));
|
|
|
+ for (auto const& file : entries.Entries.back().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,
|
|
|
+ headTarget->GetBacktrace());
|
|
|
+ }
|
|
|
+ if (path.empty()) {
|
|
|
+ if (!e.empty()) {
|
|
|
+ cm->IssueMessage(MessageType::FATAL_ERROR, e,
|
|
|
+ headTarget->GetBacktrace());
|
|
|
+ }
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ bool found = false;
|
|
|
+ for (auto const& sg : headTarget->Makefile->GetSourceGroups()) {
|
|
|
+ if (sg.MatchesFiles(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 : cmExpandedList(entry.Value)) {
|
|
|
+ auto const* headerSet = headTarget->Target->GetFileSet(name);
|
|
|
+ addFileSetEntry(headTarget, config, dagChecker, headerSet, entries);
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
bool processSources(cmGeneratorTarget const* tgt,
|
|
|
EvaluatedTargetPropertyEntries& entries,
|
|
|
std::vector<BT<std::string>>& srcs,
|
|
|
@@ -1731,10 +1866,18 @@ std::vector<BT<std::string>> cmGeneratorTarget::GetSourceFilePaths(
|
|
|
uniqueSrcs, debugSources);
|
|
|
}
|
|
|
|
|
|
+ // Collect this target's file sets.
|
|
|
+ std::vector<std::string>::size_type numFilesBefore3 = files.size();
|
|
|
+ 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 && numFilesBefore < files.size()) &&
|
|
|
- !(contextDependentObjects && numFilesBefore2 < files.size())) {
|
|
|
+ !(contextDependentObjects && numFilesBefore2 < files.size()) &&
|
|
|
+ !(contextDependentFileSets && numFilesBefore3 < files.size())) {
|
|
|
this->SourcesAreContextDependent = Tribool::False;
|
|
|
} else {
|
|
|
this->SourcesAreContextDependent = Tribool::True;
|