1 /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
2 file Copyright.txt or https://cmake.org/licensing for details. */
10 #include <cmext/string_view>
12 #include "cmsys/RegularExpression.hxx"
14 #include "cmGeneratorExpression.h"
15 #include "cmListFileCache.h"
16 #include "cmLocalGenerator.h"
17 #include "cmMakefile.h"
18 #include "cmMessageType.h"
19 #include "cmStringAlgorithms.h"
20 #include "cmSystemTools.h"
23 cm::static_string_view cmFileSetVisibilityToName(cmFileSetVisibility vis)
26 case cmFileSetVisibility::Interface:
28 case cmFileSetVisibility::Public:
30 case cmFileSetVisibility::Private:
36 cmFileSetVisibility cmFileSetVisibilityFromName(cm::string_view name,
39 if (name == "INTERFACE"_s) {
40 return cmFileSetVisibility::Interface;
42 if (name == "PUBLIC"_s) {
43 return cmFileSetVisibility::Public;
45 if (name == "PRIVATE"_s) {
46 return cmFileSetVisibility::Private;
48 auto msg = cmStrCat("File set visibility \"", name, "\" is not valid.");
50 mf->IssueMessage(MessageType::FATAL_ERROR, msg);
52 cmSystemTools::Error(msg);
54 return cmFileSetVisibility::Private;
57 bool cmFileSetVisibilityIsForSelf(cmFileSetVisibility vis)
60 case cmFileSetVisibility::Interface:
62 case cmFileSetVisibility::Public:
63 case cmFileSetVisibility::Private:
69 bool cmFileSetVisibilityIsForInterface(cmFileSetVisibility vis)
72 case cmFileSetVisibility::Interface:
73 case cmFileSetVisibility::Public:
75 case cmFileSetVisibility::Private:
81 cmFileSet::cmFileSet(std::string name, std::string type,
82 cmFileSetVisibility visibility)
83 : Name(std::move(name))
84 , Type(std::move(type))
85 , Visibility(visibility)
89 void cmFileSet::ClearDirectoryEntries()
91 this->DirectoryEntries.clear();
94 void cmFileSet::AddDirectoryEntry(BT<std::string> directories)
96 this->DirectoryEntries.push_back(std::move(directories));
99 void cmFileSet::ClearFileEntries()
101 this->FileEntries.clear();
104 void cmFileSet::AddFileEntry(BT<std::string> files)
106 this->FileEntries.push_back(std::move(files));
109 std::vector<std::unique_ptr<cmCompiledGeneratorExpression>>
110 cmFileSet::CompileFileEntries() const
112 std::vector<std::unique_ptr<cmCompiledGeneratorExpression>> result;
114 for (auto const& entry : this->FileEntries) {
115 for (auto const& ex : cmExpandedList(entry.Value)) {
116 cmGeneratorExpression ge(entry.Backtrace);
117 auto cge = ge.Parse(ex);
118 result.push_back(std::move(cge));
125 std::vector<std::unique_ptr<cmCompiledGeneratorExpression>>
126 cmFileSet::CompileDirectoryEntries() const
128 std::vector<std::unique_ptr<cmCompiledGeneratorExpression>> result;
130 for (auto const& entry : this->DirectoryEntries) {
131 for (auto const& ex : cmExpandedList(entry.Value)) {
132 cmGeneratorExpression ge(entry.Backtrace);
133 auto cge = ge.Parse(ex);
134 result.push_back(std::move(cge));
141 std::vector<std::string> cmFileSet::EvaluateDirectoryEntries(
142 const std::vector<std::unique_ptr<cmCompiledGeneratorExpression>>& cges,
143 cmLocalGenerator* lg, const std::string& config,
144 const cmGeneratorTarget* target,
145 cmGeneratorExpressionDAGChecker* dagChecker) const
147 std::vector<std::string> result;
148 for (auto const& cge : cges) {
149 auto entry = cge->Evaluate(lg, config, target, dagChecker);
150 auto dirs = cmExpandedList(entry);
151 for (std::string dir : dirs) {
152 if (!cmSystemTools::FileIsFullPath(dir)) {
153 dir = cmStrCat(lg->GetCurrentSourceDirectory(), '/', dir);
155 auto collapsedDir = cmSystemTools::CollapseFullPath(dir);
156 for (auto const& priorDir : result) {
157 auto collapsedPriorDir = cmSystemTools::CollapseFullPath(priorDir);
158 if (!cmSystemTools::SameFile(collapsedDir, collapsedPriorDir) &&
159 (cmSystemTools::IsSubDirectory(collapsedDir, collapsedPriorDir) ||
160 cmSystemTools::IsSubDirectory(collapsedPriorDir, collapsedDir))) {
161 lg->GetCMakeInstance()->IssueMessage(
162 MessageType::FATAL_ERROR,
164 "Base directories in file set cannot be subdirectories of each "
166 priorDir, "\n ", dir),
167 cge->GetBacktrace());
171 result.push_back(dir);
177 void cmFileSet::EvaluateFileEntry(
178 const std::vector<std::string>& dirs,
179 std::map<std::string, std::vector<std::string>>& filesPerDir,
180 const std::unique_ptr<cmCompiledGeneratorExpression>& cge,
181 cmLocalGenerator* lg, const std::string& config,
182 const cmGeneratorTarget* target,
183 cmGeneratorExpressionDAGChecker* dagChecker) const
185 auto files = cge->Evaluate(lg, config, target, dagChecker);
186 for (std::string file : cmExpandedList(files)) {
187 if (!cmSystemTools::FileIsFullPath(file)) {
188 file = cmStrCat(lg->GetCurrentSourceDirectory(), '/', file);
190 auto collapsedFile = cmSystemTools::CollapseFullPath(file);
193 for (auto const& dir : dirs) {
194 auto collapsedDir = cmSystemTools::CollapseFullPath(dir);
195 if (cmSystemTools::IsSubDirectory(collapsedFile, collapsedDir)) {
197 relDir = cmSystemTools::GetParentDirectory(
198 cmSystemTools::RelativePath(collapsedDir, collapsedFile));
203 std::ostringstream e;
204 e << "File:\n " << file
205 << "\nmust be in one of the file set's base directories:";
206 for (auto const& dir : dirs) {
209 lg->GetCMakeInstance()->IssueMessage(MessageType::FATAL_ERROR, e.str(),
210 cge->GetBacktrace());
214 filesPerDir[relDir].push_back(file);
218 bool cmFileSet::IsValidName(const std::string& name)
220 static const cmsys::RegularExpression regex("^[a-z0-9][a-zA-Z0-9_]*$");
222 cmsys::RegularExpressionMatch match;
223 return regex.find(name.c_str(), match);