/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 | 19.9k | { |
65 | 19.9k | return std::unique_ptr<cmGlobalGeneratorFactory>( |
66 | 19.9k | new cmGlobalGeneratorSimpleFactory<cmGlobalUnixMakefileGenerator3>()); |
67 | 19.9k | } |
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 | | * Utilized to determine if the make tool matches target names |
126 | | * case-insensitively, so that generated target names may not differ |
127 | | * only in case. |
128 | | */ |
129 | 0 | virtual bool TargetNamesAreCaseInsensitive() const { return false; } |
130 | | |
131 | | /** |
132 | | * Generate the all required files for building this project/tree. This |
133 | | * basically creates a series of LocalGenerators for each directory and |
134 | | * requests that they Generate. |
135 | | */ |
136 | | void Generate() override; |
137 | | |
138 | | void WriteMainCMakefileLanguageRules( |
139 | | cmGeneratedFileStream& cmakefileStream, |
140 | | std::vector<std::unique_ptr<cmLocalGenerator>>&); |
141 | | |
142 | | // write out the help rule listing the valid targets |
143 | | void WriteHelpRule(std::ostream& ruleFileStream, |
144 | | cmLocalUnixMakefileGenerator3*); |
145 | | |
146 | | // write the top level target rules |
147 | | void WriteConvenienceRules(std::ostream& ruleFileStream, |
148 | | std::set<std::string>& emitted); |
149 | | |
150 | | // Make tool supports dependency files generated by compiler |
151 | | bool SupportsCompilerDependencies() const |
152 | 0 | { |
153 | 0 | return this->ToolSupportsCompilerDependencies; |
154 | 0 | } |
155 | | |
156 | | // Make tool supports long line dependencies |
157 | | bool SupportsLongLineDependencies() const |
158 | 0 | { |
159 | 0 | return this->ToolSupportsLongLineDependencies; |
160 | 0 | } |
161 | | |
162 | | /** Get the command to use for a target that has no rule. This is |
163 | | used for multiple output dependencies and for cmake_force. */ |
164 | 0 | std::string GetEmptyRuleHackCommand() { return this->EmptyRuleHackCommand; } |
165 | | |
166 | | /** Get the fake dependency to use when a rule has no real commands |
167 | | or dependencies. */ |
168 | 0 | std::string GetEmptyRuleHackDepends() { return this->EmptyRuleHackDepends; } |
169 | | |
170 | | /** |
171 | | * Convert a file path to a Makefile target or dependency with |
172 | | * escaping and quoting suitable for the generator's make tool. |
173 | | */ |
174 | | std::string ConvertToMakefilePath(std::string const& path) const; |
175 | | |
176 | | // change the build command for speed |
177 | | std::vector<GeneratedMakeCommand> GenerateBuildCommand( |
178 | | std::string const& makeProgram, std::string const& projectName, |
179 | | std::string const& projectDir, std::vector<std::string> const& targetNames, |
180 | | std::string const& config, int jobs, bool verbose, |
181 | | cmBuildOptions buildOptions = cmBuildOptions(), |
182 | | std::vector<std::string> const& makeOptions = std::vector<std::string>(), |
183 | | BuildTryCompile isInTryCompile = BuildTryCompile::No) override; |
184 | | |
185 | | /** Record per-target progress information. */ |
186 | | void RecordTargetProgress(cmMakefileTargetGenerator* tg); |
187 | | |
188 | | void AddCXXCompileCommand(std::string const& sourceFile, |
189 | | std::string const& workingDirectory, |
190 | | std::string const& compileCommand, |
191 | | std::string const& objPath); |
192 | | |
193 | | /** Does the make tool tolerate .NOTPARALLEL? */ |
194 | 0 | virtual bool AllowNotParallel() const { return true; } |
195 | | |
196 | | /** Does the make tool tolerate .DELETE_ON_ERROR? */ |
197 | 0 | virtual bool AllowDeleteOnError() const { return true; } |
198 | | |
199 | | /** Does the make tool interpret '\#' as '#'? */ |
200 | | virtual bool CanEscapeOctothorpe() const; |
201 | | |
202 | 0 | bool IsIPOSupported() const override { return true; } |
203 | | |
204 | | bool IsInstallPrepComponentRepresentable( |
205 | | std::string const& component) const override; |
206 | | |
207 | | bool SupportsShortObjectNames() const override; |
208 | | void ComputeTargetObjectDirectory(cmGeneratorTarget* gt) const override; |
209 | | |
210 | | std::string IncludeDirective; |
211 | | std::string LineContinueDirective; |
212 | | bool DefineWindowsNULL; |
213 | | bool PassMakeflags; |
214 | | bool UnixCD; |
215 | | |
216 | | protected: |
217 | | void WriteMainMakefile2(); |
218 | | void WriteMainCMakefile(); |
219 | | |
220 | | void WriteConvenienceRules2(std::ostream& ruleFileStream, |
221 | | cmLocalUnixMakefileGenerator3& rootLG, |
222 | | cmLocalUnixMakefileGenerator3& lg); |
223 | | |
224 | | void WriteDirectoryRule2(std::ostream& ruleFileStream, |
225 | | cmLocalUnixMakefileGenerator3& rootLG, |
226 | | DirectoryTarget const& dt, char const* pass, |
227 | | bool check_all, bool check_relink, |
228 | | std::vector<std::string> const& commands = {}); |
229 | | void WriteDirectoryRules2(std::ostream& ruleFileStream, |
230 | | cmLocalUnixMakefileGenerator3& rootLG, |
231 | | DirectoryTarget const& dt); |
232 | | |
233 | | void AppendGlobalTargetDepends(std::vector<std::string>& depends, |
234 | | cmGeneratorTarget* target); |
235 | | |
236 | | void AppendCodegenTargetDepends(std::vector<std::string>& depends, |
237 | | cmGeneratorTarget* target); |
238 | | |
239 | | // Compute the "test_prep/<name>" build targets. Each test's dependencies |
240 | | // are resolved to the build-system targets that produce them so that the |
241 | | // recursive Makefile graph can build them. |
242 | | void ComputeTestPrepTargets(); |
243 | | |
244 | | // Write the internal "test_prep/<name>" and "test_prep/all" rules into |
245 | | // CMakeFiles/Makefile2. |
246 | | void WriteTestPrepRules(std::ostream& makefileStream, |
247 | | cmLocalUnixMakefileGenerator3& rootLG); |
248 | | |
249 | | // Write the top-level "test_prep/<name>" convenience rules that forward |
250 | | // into CMakeFiles/Makefile2. |
251 | | void WriteTestPrepConvenienceRules(std::ostream& ruleFileStream); |
252 | | |
253 | | // Compute the "install_prep/<component>" build targets. Each installation |
254 | | // component's dependencies are resolved to the build-system targets that |
255 | | // produce them so that the recursive Makefile graph can build them. |
256 | | void ComputeInstallPrepTargets(); |
257 | | |
258 | | // Write the internal "install_prep/<component>" and "install_prep/all" rules |
259 | | // into CMakeFiles/Makefile2. |
260 | | void WriteInstallPrepRules(std::ostream& makefileStream, |
261 | | cmLocalUnixMakefileGenerator3& rootLG); |
262 | | |
263 | | // Write the top-level "install_prep/<component>" convenience rules that |
264 | | // forward into CMakeFiles/Makefile2. |
265 | | void WriteInstallPrepConvenienceRules(std::ostream& ruleFileStream); |
266 | | |
267 | | // Target name hooks for superclass. |
268 | 0 | char const* GetAllTargetName() const override { return "all"; } |
269 | 0 | char const* GetInstallTargetName() const override { return "install"; } |
270 | | char const* GetInstallLocalTargetName() const override |
271 | 0 | { |
272 | 0 | return "install/local"; |
273 | 0 | } |
274 | | char const* GetInstallStripTargetName() const override |
275 | 0 | { |
276 | 0 | return "install/strip"; |
277 | 0 | } |
278 | 0 | char const* GetPreinstallTargetName() const override { return "preinstall"; } |
279 | 0 | char const* GetTestTargetName() const override { return "test"; } |
280 | 0 | char const* GetPackageTargetName() const override { return "package"; } |
281 | | char const* GetPackageSourceTargetName() const override |
282 | 0 | { |
283 | 0 | return "package_source"; |
284 | 0 | } |
285 | | char const* GetRebuildCacheTargetName() const override |
286 | 0 | { |
287 | 0 | return "rebuild_cache"; |
288 | 0 | } |
289 | 0 | char const* GetCleanTargetName() const override { return "clean"; } |
290 | | |
291 | 0 | bool CheckALLOW_DUPLICATE_CUSTOM_TARGETS() const override { return true; } |
292 | | |
293 | | // Specify if the make tool is able to consume dependency files |
294 | | // generated by the compiler |
295 | | bool ToolSupportsCompilerDependencies = true; |
296 | | |
297 | | // some Make generator, such as Borland not support long line dependencies, |
298 | | // we add SupportsLongLineDependencies to predicate. |
299 | | bool ToolSupportsLongLineDependencies = true; |
300 | | |
301 | | // Some make programs (Borland) do not keep a rule if there are no |
302 | | // dependencies or commands. This is a problem for creating rules |
303 | | // that might not do anything but might have other dependencies |
304 | | // added later. If non-empty this variable holds a fake dependency |
305 | | // that can be added. |
306 | | std::string EmptyRuleHackDepends; |
307 | | |
308 | | // Some make programs (Watcom) do not like rules with no commands. |
309 | | // If non-empty this variable holds a bogus command that may be put |
310 | | // in the rule to satisfy the make program. |
311 | | std::string EmptyRuleHackCommand; |
312 | | |
313 | | // Store per-target progress counters. |
314 | | struct TargetProgress |
315 | | { |
316 | | unsigned long NumberOfActions = 0; |
317 | | std::string VariableFile; |
318 | | std::vector<unsigned long> Marks; |
319 | | void WriteProgressVariables(unsigned long total, unsigned long& current); |
320 | | }; |
321 | | using ProgressMapType = std::map<cmGeneratorTarget const*, TargetProgress, |
322 | | cmGeneratorTarget::StrictTargetComparison>; |
323 | | ProgressMapType ProgressMap; |
324 | | |
325 | | size_t CountProgressMarksInTarget( |
326 | | cmGeneratorTarget const* target, |
327 | | std::set<cmGeneratorTarget const*>& emitted); |
328 | | size_t CountProgressMarksInAll(cmLocalGenerator const& lg); |
329 | | |
330 | | std::unique_ptr<cmGeneratedFileStream> CommandDatabase; |
331 | | |
332 | | private: |
333 | 0 | char const* GetBuildIgnoreErrorsFlag() const override { return "-i"; } |
334 | | |
335 | | // Probe the make tool (once, memoized) for whether it is GNU Make 4.0 or |
336 | | // newer and thus supports grouped output via --output-sync. |
337 | | bool MakeSupportsOutputSync(std::string const& makeProgram); |
338 | | |
339 | | enum class OutputSyncSupport |
340 | | { |
341 | | Unknown, |
342 | | Yes, |
343 | | No |
344 | | }; |
345 | | OutputSyncSupport OutputSyncSupportState = OutputSyncSupport::Unknown; |
346 | | |
347 | | std::map<cmStateSnapshot, std::set<cmGeneratorTarget const*>, |
348 | | cmStateSnapshot::StrictWeakOrder> |
349 | | DirectoryTargetsMap; |
350 | | void InitializeProgressMarks() override; |
351 | | |
352 | | // A "test_prep/<name>" target and the "<target>.dir/all" recursive rules |
353 | | // that must be built to prepare the named test. |
354 | | struct TestPrepTarget |
355 | | { |
356 | | std::string Name; |
357 | | std::vector<std::string> Rules; |
358 | | }; |
359 | | |
360 | | // Ordered map of "test_prep/" target name -> its rules. Populated by |
361 | | // ComputeTestPrepTargets when test preparation targets are enabled. |
362 | | std::map<std::string, TestPrepTarget> TestPrepTargets; |
363 | | TestPrepTarget& GetTestPrepTarget(std::string const& name); |
364 | | void AddDirectoryTestPrepTargets(cmLocalGenerator* lg); |
365 | | bool TestPrepEnabled = false; |
366 | | |
367 | | // An "install_prep/<component>" target and the "<target>.dir/all" |
368 | | // recursive rules that must be built to prepare the named installation |
369 | | // component. |
370 | | struct InstallPrepTarget |
371 | | { |
372 | | std::string Name; |
373 | | std::vector<std::string> Rules; |
374 | | }; |
375 | | |
376 | | // Ordered map of "install_prep/" target name -> its rules. Populated by |
377 | | // ComputeInstallPrepTargets. |
378 | | std::map<std::string, InstallPrepTarget> InstallPrepComponentTargets; |
379 | | std::vector<std::string> InstallPrepAllTargets; |
380 | | |
381 | | struct InstallPrepOrderedTarget |
382 | | { |
383 | | std::string NormalRule; |
384 | | std::string PreinstallRule; |
385 | | }; |
386 | | std::map<std::string, InstallPrepOrderedTarget> InstallPrepOrderedTargets; |
387 | | |
388 | | bool InstallPrepEnabled = false; |
389 | | }; |