/src/CMake/Source/cmGlobalUnixMakefileGenerator3.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 <cstddef> |
8 | | #include <iosfwd> |
9 | | #include <map> |
10 | | #include <memory> |
11 | | #include <set> |
12 | | #include <string> |
13 | | #include <vector> |
14 | | |
15 | | #include "cmBuildOptions.h" |
16 | | #include "cmGeneratorTarget.h" |
17 | | #include "cmGlobalCommonGenerator.h" |
18 | | #include "cmGlobalGeneratorFactory.h" |
19 | | #include "cmStateSnapshot.h" |
20 | | |
21 | | class cmGeneratedFileStream; |
22 | | class cmLocalGenerator; |
23 | | class cmLocalUnixMakefileGenerator3; |
24 | | class cmMakefileTargetGenerator; |
25 | | class cmake; |
26 | | |
27 | | /** \class cmGlobalUnixMakefileGenerator3 |
28 | | * \brief Write a Unix makefiles. |
29 | | * |
30 | | * cmGlobalUnixMakefileGenerator3 manages UNIX build process for a tree |
31 | | |
32 | | |
33 | | The basic approach of this generator is to produce Makefiles that will all |
34 | | be run with the current working directory set to the Home Output |
35 | | directory. The one exception to this is the subdirectory Makefiles which are |
36 | | created as a convenience and just cd up to the Home Output directory and |
37 | | invoke the main Makefiles. |
38 | | |
39 | | The make process starts with Makefile. Makefile should only contain the |
40 | | targets the user is likely to invoke directly from a make command line. No |
41 | | internal targets should be in this file. Makefile2 contains the internal |
42 | | targets that are required to make the process work. |
43 | | |
44 | | Makefile2 in turn will recursively make targets in the correct order. Each |
45 | | target has its own directory \<target\>.dir and its own makefile build.make in |
46 | | that directory. Also in that directory is a couple makefiles per source file |
47 | | used by the target. Typically these are named source.obj.build.make and |
48 | | source.obj.build.depend.make. The source.obj.build.make contains the rules |
49 | | for building, cleaning, and computing dependencies for the given source |
50 | | file. The build.depend.make contains additional dependencies that were |
51 | | computed during dependency scanning. An additional file called |
52 | | source.obj.depend is used as a marker to indicate when dependencies must be |
53 | | rescanned. |
54 | | |
55 | | Rules for custom commands follow the same model as rules for source files. |
56 | | |
57 | | */ |
58 | | |
59 | | class cmGlobalUnixMakefileGenerator3 : public cmGlobalCommonGenerator |
60 | | { |
61 | | public: |
62 | | cmGlobalUnixMakefileGenerator3(cmake* cm); |
63 | | static std::unique_ptr<cmGlobalGeneratorFactory> NewFactory() |
64 | 35 | { |
65 | 35 | return std::unique_ptr<cmGlobalGeneratorFactory>( |
66 | 35 | new cmGlobalGeneratorSimpleFactory<cmGlobalUnixMakefileGenerator3>()); |
67 | 35 | } |
68 | | |
69 | | ~cmGlobalUnixMakefileGenerator3() override; |
70 | | |
71 | | cmGlobalUnixMakefileGenerator3(cmGlobalUnixMakefileGenerator3 const&) = |
72 | | delete; |
73 | | cmGlobalUnixMakefileGenerator3& operator=( |
74 | | cmGlobalUnixMakefileGenerator3 const&) = delete; |
75 | | |
76 | | //! Get the name for the generator. |
77 | | std::string GetName() const override |
78 | 0 | { |
79 | 0 | return cmGlobalUnixMakefileGenerator3::GetActualName(); |
80 | 0 | } |
81 | 0 | static std::string GetActualName() { return "Unix Makefiles"; } |
82 | | |
83 | | /** |
84 | | * Utilized by the generator factory to determine if this generator |
85 | | * supports toolsets. |
86 | | */ |
87 | 0 | static bool SupportsToolset() { return false; } |
88 | | |
89 | | /** |
90 | | * Utilized by the generator factory to determine if this generator |
91 | | * supports platforms. |
92 | | */ |
93 | 0 | static bool SupportsPlatform() { return false; } |
94 | | |
95 | | /** |
96 | | * Utilized to determine if this generator |
97 | | * supports DEPFILE option. |
98 | | */ |
99 | 0 | bool SupportsCustomCommandDepfile() const override { return true; } |
100 | | |
101 | | /** |
102 | | * Utilized to determine if this generator |
103 | | * supports linker dependency file. |
104 | | */ |
105 | 0 | bool SupportsLinkerDependencyFile() const override { return true; } |
106 | | |
107 | | /** Get the documentation entry for this generator. */ |
108 | | static cmDocumentationEntry GetDocumentation(); |
109 | | |
110 | | std::unique_ptr<cmLocalGenerator> CreateLocalGenerator( |
111 | | cmMakefile* mf) override; |
112 | | |
113 | | /** |
114 | | * Try to determine system information such as shared library |
115 | | * extension, pthreads, byte order etc. |
116 | | */ |
117 | | void EnableLanguage(std::vector<std::string> const& languages, cmMakefile*, |
118 | | bool optional) override; |
119 | | |
120 | | void Configure() override; |
121 | | |
122 | 0 | bool IsGNUMakeJobServerAware() const override { return true; } |
123 | | |
124 | | /** |
125 | | * Generate the all required files for building this project/tree. This |
126 | | * basically creates a series of LocalGenerators for each directory and |
127 | | * requests that they Generate. |
128 | | */ |
129 | | void Generate() override; |
130 | | |
131 | | void WriteMainCMakefileLanguageRules( |
132 | | cmGeneratedFileStream& cmakefileStream, |
133 | | std::vector<std::unique_ptr<cmLocalGenerator>>&); |
134 | | |
135 | | // write out the help rule listing the valid targets |
136 | | void WriteHelpRule(std::ostream& ruleFileStream, |
137 | | cmLocalUnixMakefileGenerator3*); |
138 | | |
139 | | // write the top level target rules |
140 | | void WriteConvenienceRules(std::ostream& ruleFileStream, |
141 | | std::set<std::string>& emitted); |
142 | | |
143 | | // Make tool supports dependency files generated by compiler |
144 | | bool SupportsCompilerDependencies() const |
145 | 0 | { |
146 | 0 | return this->ToolSupportsCompilerDependencies; |
147 | 0 | } |
148 | | |
149 | | // Make tool supports long line dependencies |
150 | | bool SupportsLongLineDependencies() const |
151 | 0 | { |
152 | 0 | return this->ToolSupportsLongLineDependencies; |
153 | 0 | } |
154 | | |
155 | | /** Get the command to use for a target that has no rule. This is |
156 | | used for multiple output dependencies and for cmake_force. */ |
157 | 0 | std::string GetEmptyRuleHackCommand() { return this->EmptyRuleHackCommand; } |
158 | | |
159 | | /** Get the fake dependency to use when a rule has no real commands |
160 | | or dependencies. */ |
161 | 0 | std::string GetEmptyRuleHackDepends() { return this->EmptyRuleHackDepends; } |
162 | | |
163 | | /** |
164 | | * Convert a file path to a Makefile target or dependency with |
165 | | * escaping and quoting suitable for the generator's make tool. |
166 | | */ |
167 | | std::string ConvertToMakefilePath(std::string const& path) const; |
168 | | |
169 | | // change the build command for speed |
170 | | std::vector<GeneratedMakeCommand> GenerateBuildCommand( |
171 | | std::string const& makeProgram, std::string const& projectName, |
172 | | std::string const& projectDir, std::vector<std::string> const& targetNames, |
173 | | std::string const& config, int jobs, bool verbose, |
174 | | cmBuildOptions buildOptions = cmBuildOptions(), |
175 | | std::vector<std::string> const& makeOptions = std::vector<std::string>(), |
176 | | BuildTryCompile isInTryCompile = BuildTryCompile::No) override; |
177 | | |
178 | | /** Record per-target progress information. */ |
179 | | void RecordTargetProgress(cmMakefileTargetGenerator* tg); |
180 | | |
181 | | void AddCXXCompileCommand(std::string const& sourceFile, |
182 | | std::string const& workingDirectory, |
183 | | std::string const& compileCommand, |
184 | | std::string const& objPath); |
185 | | |
186 | | /** Does the make tool tolerate .NOTPARALLEL? */ |
187 | 0 | virtual bool AllowNotParallel() const { return true; } |
188 | | |
189 | | /** Does the make tool tolerate .DELETE_ON_ERROR? */ |
190 | 0 | virtual bool AllowDeleteOnError() const { return true; } |
191 | | |
192 | | /** Does the make tool interpret '\#' as '#'? */ |
193 | | virtual bool CanEscapeOctothorpe() const; |
194 | | |
195 | 0 | bool IsIPOSupported() const override { return true; } |
196 | | |
197 | | bool SupportsShortObjectNames() const override; |
198 | | void ComputeTargetObjectDirectory(cmGeneratorTarget* gt) const override; |
199 | | |
200 | | std::string IncludeDirective; |
201 | | std::string LineContinueDirective; |
202 | | bool DefineWindowsNULL; |
203 | | bool PassMakeflags; |
204 | | bool UnixCD; |
205 | | |
206 | | protected: |
207 | | void WriteMainMakefile2(); |
208 | | void WriteMainCMakefile(); |
209 | | |
210 | | void WriteConvenienceRules2(std::ostream& ruleFileStream, |
211 | | cmLocalUnixMakefileGenerator3& rootLG, |
212 | | cmLocalUnixMakefileGenerator3& lg); |
213 | | |
214 | | void WriteDirectoryRule2(std::ostream& ruleFileStream, |
215 | | cmLocalUnixMakefileGenerator3& rootLG, |
216 | | DirectoryTarget const& dt, char const* pass, |
217 | | bool check_all, bool check_relink, |
218 | | std::vector<std::string> const& commands = {}); |
219 | | void WriteDirectoryRules2(std::ostream& ruleFileStream, |
220 | | cmLocalUnixMakefileGenerator3& rootLG, |
221 | | DirectoryTarget const& dt); |
222 | | |
223 | | void AppendGlobalTargetDepends(std::vector<std::string>& depends, |
224 | | cmGeneratorTarget* target); |
225 | | |
226 | | void AppendCodegenTargetDepends(std::vector<std::string>& depends, |
227 | | cmGeneratorTarget* target); |
228 | | |
229 | | // Target name hooks for superclass. |
230 | 0 | char const* GetAllTargetName() const override { return "all"; } |
231 | 0 | char const* GetInstallTargetName() const override { return "install"; } |
232 | | char const* GetInstallLocalTargetName() const override |
233 | 0 | { |
234 | 0 | return "install/local"; |
235 | 0 | } |
236 | | char const* GetInstallStripTargetName() const override |
237 | 0 | { |
238 | 0 | return "install/strip"; |
239 | 0 | } |
240 | 0 | char const* GetPreinstallTargetName() const override { return "preinstall"; } |
241 | 0 | char const* GetTestTargetName() const override { return "test"; } |
242 | 0 | char const* GetPackageTargetName() const override { return "package"; } |
243 | | char const* GetPackageSourceTargetName() const override |
244 | 0 | { |
245 | 0 | return "package_source"; |
246 | 0 | } |
247 | | char const* GetRebuildCacheTargetName() const override |
248 | 0 | { |
249 | 0 | return "rebuild_cache"; |
250 | 0 | } |
251 | 0 | char const* GetCleanTargetName() const override { return "clean"; } |
252 | | |
253 | 0 | bool CheckALLOW_DUPLICATE_CUSTOM_TARGETS() const override { return true; } |
254 | | |
255 | | // Specify if the make tool is able to consume dependency files |
256 | | // generated by the compiler |
257 | | bool ToolSupportsCompilerDependencies = true; |
258 | | |
259 | | // some Make generator, such as Borland not support long line dependencies, |
260 | | // we add SupportsLongLineDependencies to predicate. |
261 | | bool ToolSupportsLongLineDependencies = true; |
262 | | |
263 | | // Some make programs (Borland) do not keep a rule if there are no |
264 | | // dependencies or commands. This is a problem for creating rules |
265 | | // that might not do anything but might have other dependencies |
266 | | // added later. If non-empty this variable holds a fake dependency |
267 | | // that can be added. |
268 | | std::string EmptyRuleHackDepends; |
269 | | |
270 | | // Some make programs (Watcom) do not like rules with no commands. |
271 | | // If non-empty this variable holds a bogus command that may be put |
272 | | // in the rule to satisfy the make program. |
273 | | std::string EmptyRuleHackCommand; |
274 | | |
275 | | // Store per-target progress counters. |
276 | | struct TargetProgress |
277 | | { |
278 | | unsigned long NumberOfActions = 0; |
279 | | std::string VariableFile; |
280 | | std::vector<unsigned long> Marks; |
281 | | void WriteProgressVariables(unsigned long total, unsigned long& current); |
282 | | }; |
283 | | using ProgressMapType = std::map<cmGeneratorTarget const*, TargetProgress, |
284 | | cmGeneratorTarget::StrictTargetComparison>; |
285 | | ProgressMapType ProgressMap; |
286 | | |
287 | | size_t CountProgressMarksInTarget( |
288 | | cmGeneratorTarget const* target, |
289 | | std::set<cmGeneratorTarget const*>& emitted); |
290 | | size_t CountProgressMarksInAll(cmLocalGenerator const& lg); |
291 | | |
292 | | std::unique_ptr<cmGeneratedFileStream> CommandDatabase; |
293 | | |
294 | | private: |
295 | 0 | char const* GetBuildIgnoreErrorsFlag() const override { return "-i"; } |
296 | | |
297 | | std::map<cmStateSnapshot, std::set<cmGeneratorTarget const*>, |
298 | | cmStateSnapshot::StrictWeakOrder> |
299 | | DirectoryTargetsMap; |
300 | | void InitializeProgressMarks() override; |
301 | | }; |