/src/CMake/Source/cmLocalUnixMakefileGenerator3.h
Line | Count | Source |
1 | | /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying |
2 | | file LICENSE.rst or https://cmake.org/licensing for details. */ |
3 | | #pragma once |
4 | | |
5 | | #include "cmConfigure.h" // IWYU pragma: keep |
6 | | |
7 | | #include <iosfwd> |
8 | | #include <map> |
9 | | #include <set> |
10 | | #include <string> |
11 | | #include <utility> |
12 | | #include <vector> |
13 | | |
14 | | #include "cmDepends.h" |
15 | | #include "cmGeneratorOptions.h" |
16 | | #include "cmLocalCommonGenerator.h" |
17 | | #include "cmStateTypes.h" |
18 | | |
19 | | class cmCustomCommand; |
20 | | class cmCustomCommandGenerator; |
21 | | class cmGeneratorTarget; |
22 | | class cmGlobalGenerator; |
23 | | class cmMakefile; |
24 | | class cmSourceFile; |
25 | | |
26 | | /** \class cmLocalUnixMakefileGenerator3 |
27 | | * \brief Write a LocalUnix makefiles. |
28 | | * |
29 | | * cmLocalUnixMakefileGenerator3 produces a LocalUnix makefile from its |
30 | | * member Makefile. |
31 | | */ |
32 | | class cmLocalUnixMakefileGenerator3 : public cmLocalCommonGenerator |
33 | | { |
34 | | public: |
35 | | cmLocalUnixMakefileGenerator3(cmGlobalGenerator* gg, cmMakefile* mf); |
36 | | ~cmLocalUnixMakefileGenerator3() override; |
37 | | |
38 | | std::string const& GetConfigName() const; |
39 | | |
40 | | void ComputeHomeRelativeOutputPath() override; |
41 | | |
42 | | /** |
43 | | * Generate the makefile for this directory. |
44 | | */ |
45 | | void Generate() override; |
46 | | |
47 | | std::string GetObjectOutputRoot( |
48 | | cmStateEnums::IntermediateDirKind kind = |
49 | | cmStateEnums::IntermediateDirKind::ObjectFiles) const override; |
50 | | |
51 | | // this returns the relative path between the HomeOutputDirectory and this |
52 | | // local generators StartOutputDirectory |
53 | | std::string const& GetHomeRelativeOutputPath(); |
54 | | |
55 | | /** |
56 | | * Convert a file path to a Makefile target or dependency with |
57 | | * escaping and quoting suitable for the generator's make tool. |
58 | | */ |
59 | | std::string ConvertToMakefilePath(std::string const& path) const; |
60 | | |
61 | | // Write out a make rule |
62 | | void WriteMakeRule(std::ostream& os, char const* comment, |
63 | | std::string const& target, |
64 | | std::vector<std::string> const& depends, |
65 | | std::vector<std::string> const& commands, bool symbolic, |
66 | | bool in_help = false); |
67 | | |
68 | | // write the main variables used by the makefiles |
69 | | void WriteMakeVariables(std::ostream& makefileStream); |
70 | | |
71 | | /** |
72 | | * Set max makefile variable size, default is 0 which means unlimited. |
73 | | */ |
74 | 0 | void SetMakefileVariableSize(int s) { this->MakefileVariableSize = s; } |
75 | | |
76 | | /** |
77 | | * Set whether passing a make target on a command line requires an |
78 | | * extra level of escapes. |
79 | | */ |
80 | | void SetMakeCommandEscapeTargetTwice(bool b) |
81 | 0 | { |
82 | 0 | this->MakeCommandEscapeTargetTwice = b; |
83 | 0 | } |
84 | | |
85 | | /** |
86 | | * Set whether the Borland curly brace command line hack should be |
87 | | * applied. |
88 | | */ |
89 | 0 | void SetBorlandMakeCurlyHack(bool b) { this->BorlandMakeCurlyHack = b; } |
90 | | |
91 | | // used in writing out Cmake files such as WriteDirectoryInformation |
92 | | static void WriteCMakeArgument(std::ostream& os, std::string const& s); |
93 | | |
94 | | /** creates the common disclaimer text at the top of each makefile */ |
95 | | void WriteDisclaimer(std::ostream& os); |
96 | | |
97 | | // write a comment line #====... in the stream |
98 | | void WriteDivider(std::ostream& os); |
99 | | |
100 | | /** used to create a recursive make call */ |
101 | | std::string GetRecursiveMakeCall(std::string const& makefile, |
102 | | std::string const& tgt); |
103 | | |
104 | | // append flags to a string |
105 | | void AppendFlags(std::string& flags, |
106 | | std::string const& newFlags) const override; |
107 | | using cmLocalCommonGenerator::AppendFlags; |
108 | | |
109 | | // append an echo command |
110 | | enum EchoColor |
111 | | { |
112 | | EchoNormal, |
113 | | EchoDepend, |
114 | | EchoBuild, |
115 | | EchoLink, |
116 | | EchoGenerate, |
117 | | EchoGlobal |
118 | | }; |
119 | | struct EchoProgress |
120 | | { |
121 | | std::string Dir; |
122 | | std::string Arg; |
123 | | }; |
124 | | void AppendEcho(std::vector<std::string>& commands, std::string const& text, |
125 | | EchoColor color = EchoNormal, EchoProgress const* = nullptr); |
126 | | |
127 | | /** Get whether the makefile is to have color. */ |
128 | 0 | bool GetColorMakefile() const { return this->ColorMakefile; } |
129 | | |
130 | | // create a command that cds to the start dir then runs the commands |
131 | | void CreateCDCommand(std::vector<std::string>& commands, |
132 | | std::string const& targetDir, |
133 | | std::string const& relDir); |
134 | | |
135 | | static std::string ConvertToQuotedOutputPath(std::string const& p, |
136 | | bool useWatcomQuote); |
137 | | |
138 | | std::string CreateMakeVariable(std::string const& sin, |
139 | | std::string const& s2in); |
140 | | |
141 | | /** Called from command-line hook to bring dependencies up to date |
142 | | for a target. */ |
143 | | bool UpdateDependencies(std::string const& tgtInfo, |
144 | | std::string const& targetName, bool verbose, |
145 | | bool color) override; |
146 | | |
147 | | /** Called from command-line hook to clear dependencies. */ |
148 | | void ClearDependencies(cmMakefile* mf, bool verbose) override; |
149 | | |
150 | | /** write some extra rules such as make test etc */ |
151 | | void WriteSpecialTargetsTop(std::ostream& makefileStream); |
152 | | void WriteSpecialTargetsBottom(std::ostream& makefileStream); |
153 | | |
154 | | std::string GetRelativeTargetDirectory( |
155 | | cmGeneratorTarget const* target) const; |
156 | | |
157 | | // File pairs for implicit dependency scanning. The key of the map |
158 | | // is the depender and the value is the explicit dependee. |
159 | | using ImplicitDependFileMap = cmDepends::DependencyMap; |
160 | | using ImplicitDependLanguageMap = |
161 | | std::map<std::string, ImplicitDependFileMap>; |
162 | | using ImplicitDependScannerMap = |
163 | | std::map<cmDependencyScannerKind, ImplicitDependLanguageMap>; |
164 | | using ImplicitDependTargetMap = |
165 | | std::map<std::string, ImplicitDependScannerMap>; |
166 | | ImplicitDependLanguageMap const& GetImplicitDepends( |
167 | | cmGeneratorTarget const* tgt, |
168 | | cmDependencyScannerKind scanner = cmDependencyScannerKind::CMake); |
169 | | |
170 | | void AddImplicitDepends( |
171 | | cmGeneratorTarget const* tgt, std::string const& lang, |
172 | | std::string const& obj, std::string const& src, |
173 | | cmDependencyScannerKind scanner = cmDependencyScannerKind::CMake); |
174 | | |
175 | | // write the target rules for the local Makefile into the stream |
176 | | void WriteLocalAllRules(std::ostream& ruleFileStream); |
177 | | |
178 | 0 | std::vector<std::string> const& GetLocalHelp() { return this->LocalHelp; } |
179 | | |
180 | | /** Get whether to create rules to generate preprocessed and |
181 | | assembly sources. This could be converted to a variable lookup |
182 | | later. */ |
183 | | bool GetCreatePreprocessedSourceRules() const |
184 | 0 | { |
185 | 0 | return !this->SkipPreprocessedSourceRules; |
186 | 0 | } |
187 | | bool GetCreateAssemblySourceRules() const |
188 | 0 | { |
189 | 0 | return !this->SkipAssemblySourceRules; |
190 | 0 | } |
191 | | |
192 | | // Fill the vector with the target names for the object files, |
193 | | // preprocessed files and assembly files. Currently only used by the |
194 | | // Eclipse generator. |
195 | | void GetIndividualFileTargets(std::vector<std::string>& targets); |
196 | | |
197 | | std::string GetLinkDependencyFile(cmGeneratorTarget* target, |
198 | | std::string const& config) const override; |
199 | | |
200 | | protected: |
201 | | void WriteLocalMakefile(); |
202 | | |
203 | | // write the target rules for the local Makefile into the stream |
204 | | void WriteLocalMakefileTargets(std::ostream& ruleFileStream, |
205 | | std::set<std::string>& emitted); |
206 | | |
207 | | // this method Writes the Directory information files |
208 | | void WriteDirectoryInformationFile(); |
209 | | |
210 | | // write the depend info |
211 | | void WriteDependLanguageInfo(std::ostream& cmakefileStream, |
212 | | cmGeneratorTarget* tgt); |
213 | | |
214 | | // this converts a file name that is relative to the StartOutputDirectory |
215 | | // into a full path |
216 | | std::string ConvertToFullPath(std::string const& localPath); |
217 | | |
218 | | void WriteConvenienceRule(std::ostream& ruleFileStream, |
219 | | std::string const& realTarget, |
220 | | std::string const& helpTarget); |
221 | | |
222 | | void AppendRuleDepend(std::vector<std::string>& depends, |
223 | | char const* ruleFileName); |
224 | | void AppendRuleDepends(std::vector<std::string>& depends, |
225 | | std::vector<std::string> const& ruleFiles); |
226 | | void AppendCustomDepends(std::vector<std::string>& depends, |
227 | | std::vector<cmCustomCommand> const& ccs); |
228 | | void AppendCustomDepend(std::vector<std::string>& depends, |
229 | | cmCustomCommandGenerator const& cc); |
230 | | void AppendCustomCommands(std::vector<std::string>& commands, |
231 | | std::vector<cmCustomCommand> const& ccs, |
232 | | cmGeneratorTarget* target, |
233 | | std::string const& relative); |
234 | | void AppendCustomCommand(std::vector<std::string>& commands, |
235 | | cmCustomCommandGenerator const& ccg, |
236 | | cmGeneratorTarget* target, |
237 | | std::string const& relative, |
238 | | bool echo_comment = false, |
239 | | std::ostream* content = nullptr); |
240 | | void AppendCleanCommand(std::vector<std::string>& commands, |
241 | | std::set<std::string> const& files, |
242 | | cmGeneratorTarget* target, |
243 | | char const* filename = nullptr); |
244 | | void AppendDirectoryCleanCommand(std::vector<std::string>& commands); |
245 | | |
246 | | // Helper methods for dependency updates. |
247 | | bool ScanDependencies(std::string const& targetDir, |
248 | | std::string const& dependFile, |
249 | | std::string const& internalDependFile, |
250 | | cmDepends::DependencyMap& validDeps); |
251 | | void CheckMultipleOutputs(bool verbose); |
252 | | |
253 | | private: |
254 | | std::string MaybeConvertWatcomShellCommand(std::string const& cmd); |
255 | | |
256 | | friend class cmMakefileTargetGenerator; |
257 | | friend class cmMakefileExecutableTargetGenerator; |
258 | | friend class cmMakefileLibraryTargetGenerator; |
259 | | friend class cmMakefileUtilityTargetGenerator; |
260 | | friend class cmGlobalUnixMakefileGenerator3; |
261 | | |
262 | | ImplicitDependTargetMap ImplicitDepends; |
263 | | |
264 | | std::string HomeRelativeOutputPath; |
265 | | |
266 | | struct LocalObjectEntry |
267 | | { |
268 | | cmGeneratorTarget* Target = nullptr; |
269 | | std::string Language; |
270 | | LocalObjectEntry() = default; |
271 | | LocalObjectEntry(cmGeneratorTarget* t, std::string lang) |
272 | 0 | : Target(t) |
273 | 0 | , Language(std::move(lang)) |
274 | 0 | { |
275 | 0 | } |
276 | | }; |
277 | | struct LocalObjectInfo : public std::vector<LocalObjectEntry> |
278 | | { |
279 | | bool HasSourceExtension = false; |
280 | | bool HasPreprocessRule = false; |
281 | | bool HasAssembleRule = false; |
282 | | }; |
283 | | void GetLocalObjectFiles( |
284 | | std::map<std::string, LocalObjectInfo>& localObjectFiles); |
285 | | |
286 | | void WriteObjectConvenienceRule(std::ostream& ruleFileStream, |
287 | | char const* comment, |
288 | | std::string const& output, |
289 | | LocalObjectInfo const& info); |
290 | | |
291 | | std::vector<std::string> LocalHelp; |
292 | | |
293 | | /* does the work for each target */ |
294 | | std::map<std::string, std::string> MakeVariableMap; |
295 | | std::map<std::string, std::string> ShortMakeVariableMap; |
296 | | |
297 | | int MakefileVariableSize; |
298 | | bool MakeCommandEscapeTargetTwice; |
299 | | bool BorlandMakeCurlyHack; |
300 | | bool ColorMakefile; |
301 | | bool SkipPreprocessedSourceRules; |
302 | | bool SkipAssemblySourceRules; |
303 | | |
304 | | std::set<cmSourceFile const*>& GetCommandsVisited( |
305 | | cmGeneratorTarget const* target) |
306 | 0 | { |
307 | 0 | return this->CommandsVisited[target]; |
308 | 0 | } |
309 | | |
310 | | std::map<cmGeneratorTarget const*, std::set<cmSourceFile const*>> |
311 | | CommandsVisited; |
312 | | }; |