Coverage Report

Created: 2026-10-28 06:38

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/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
};