resolve cyclic dependency with zstd
[platform/upstream/cmake.git] / Source / cmFileSet.cxx
1 /* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
2    file Copyright.txt or https://cmake.org/licensing for details.  */
3 #include "cmFileSet.h"
4
5 #include <sstream>
6 #include <string>
7 #include <utility>
8 #include <vector>
9
10 #include <cmext/string_view>
11
12 #include "cmsys/RegularExpression.hxx"
13
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"
21 #include "cmake.h"
22
23 cm::static_string_view cmFileSetVisibilityToName(cmFileSetVisibility vis)
24 {
25   switch (vis) {
26     case cmFileSetVisibility::Interface:
27       return "INTERFACE"_s;
28     case cmFileSetVisibility::Public:
29       return "PUBLIC"_s;
30     case cmFileSetVisibility::Private:
31       return "PRIVATE"_s;
32   }
33   return ""_s;
34 }
35
36 cmFileSetVisibility cmFileSetVisibilityFromName(cm::string_view name,
37                                                 cmMakefile* mf)
38 {
39   if (name == "INTERFACE"_s) {
40     return cmFileSetVisibility::Interface;
41   }
42   if (name == "PUBLIC"_s) {
43     return cmFileSetVisibility::Public;
44   }
45   if (name == "PRIVATE"_s) {
46     return cmFileSetVisibility::Private;
47   }
48   auto msg = cmStrCat("File set visibility \"", name, "\" is not valid.");
49   if (mf) {
50     mf->IssueMessage(MessageType::FATAL_ERROR, msg);
51   } else {
52     cmSystemTools::Error(msg);
53   }
54   return cmFileSetVisibility::Private;
55 }
56
57 bool cmFileSetVisibilityIsForSelf(cmFileSetVisibility vis)
58 {
59   switch (vis) {
60     case cmFileSetVisibility::Interface:
61       return false;
62     case cmFileSetVisibility::Public:
63     case cmFileSetVisibility::Private:
64       return true;
65   }
66   return false;
67 }
68
69 bool cmFileSetVisibilityIsForInterface(cmFileSetVisibility vis)
70 {
71   switch (vis) {
72     case cmFileSetVisibility::Interface:
73     case cmFileSetVisibility::Public:
74       return true;
75     case cmFileSetVisibility::Private:
76       return false;
77   }
78   return false;
79 }
80
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)
86 {
87 }
88
89 void cmFileSet::ClearDirectoryEntries()
90 {
91   this->DirectoryEntries.clear();
92 }
93
94 void cmFileSet::AddDirectoryEntry(BT<std::string> directories)
95 {
96   this->DirectoryEntries.push_back(std::move(directories));
97 }
98
99 void cmFileSet::ClearFileEntries()
100 {
101   this->FileEntries.clear();
102 }
103
104 void cmFileSet::AddFileEntry(BT<std::string> files)
105 {
106   this->FileEntries.push_back(std::move(files));
107 }
108
109 std::vector<std::unique_ptr<cmCompiledGeneratorExpression>>
110 cmFileSet::CompileFileEntries() const
111 {
112   std::vector<std::unique_ptr<cmCompiledGeneratorExpression>> result;
113
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));
119     }
120   }
121
122   return result;
123 }
124
125 std::vector<std::unique_ptr<cmCompiledGeneratorExpression>>
126 cmFileSet::CompileDirectoryEntries() const
127 {
128   std::vector<std::unique_ptr<cmCompiledGeneratorExpression>> result;
129
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));
135     }
136   }
137
138   return result;
139 }
140
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
146 {
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);
154       }
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,
163             cmStrCat(
164               "Base directories in file set cannot be subdirectories of each "
165               "other:\n  ",
166               priorDir, "\n  ", dir),
167             cge->GetBacktrace());
168           return {};
169         }
170       }
171       result.push_back(dir);
172     }
173   }
174   return result;
175 }
176
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
184 {
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);
189     }
190     auto collapsedFile = cmSystemTools::CollapseFullPath(file);
191     bool found = false;
192     std::string relDir;
193     for (auto const& dir : dirs) {
194       auto collapsedDir = cmSystemTools::CollapseFullPath(dir);
195       if (cmSystemTools::IsSubDirectory(collapsedFile, collapsedDir)) {
196         found = true;
197         relDir = cmSystemTools::GetParentDirectory(
198           cmSystemTools::RelativePath(collapsedDir, collapsedFile));
199         break;
200       }
201     }
202     if (!found) {
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) {
207         e << "\n  " << dir;
208       }
209       lg->GetCMakeInstance()->IssueMessage(MessageType::FATAL_ERROR, e.str(),
210                                            cge->GetBacktrace());
211       return;
212     }
213
214     filesPerDir[relDir].push_back(file);
215   }
216 }
217
218 bool cmFileSet::IsValidName(const std::string& name)
219 {
220   static const cmsys::RegularExpression regex("^[a-z0-9][a-zA-Z0-9_]*$");
221
222   cmsys::RegularExpressionMatch match;
223   return regex.find(name.c_str(), match);
224 }