Coverage Report

Created: 2026-07-14 07:09

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
23
  {
65
23
    return std::unique_ptr<cmGlobalGeneratorFactory>(
66
23
      new cmGlobalGeneratorSimpleFactory<cmGlobalUnixMakefileGenerator3>());
67
23
  }
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
  // Compute the "test_prep/<name>" build targets requested via the
230
  // CMAKE_TEST_BUILD_DEPENDS variable.  Each test's dependencies are
231
  // resolved to the build-system targets that produce them so that the
232
  // recursive Makefile graph can build them.
233
  void ComputeTestPrepTargets();
234
235
  // Write the internal "test_prep/<name>" and "test_prep/all" rules into
236
  // CMakeFiles/Makefile2.
237
  void WriteTestPrepRules(std::ostream& makefileStream,
238
                          cmLocalUnixMakefileGenerator3& rootLG);
239
240
  // Write the top-level "test_prep/<name>" convenience rules that forward
241
  // into CMakeFiles/Makefile2.
242
  void WriteTestPrepConvenienceRules(std::ostream& ruleFileStream);
243
244
  // Target name hooks for superclass.
245
0
  char const* GetAllTargetName() const override { return "all"; }
246
0
  char const* GetInstallTargetName() const override { return "install"; }
247
  char const* GetInstallLocalTargetName() const override
248
0
  {
249
0
    return "install/local";
250
0
  }
251
  char const* GetInstallStripTargetName() const override
252
0
  {
253
0
    return "install/strip";
254
0
  }
255
0
  char const* GetPreinstallTargetName() const override { return "preinstall"; }
256
0
  char const* GetTestTargetName() const override { return "test"; }
257
0
  char const* GetPackageTargetName() const override { return "package"; }
258
  char const* GetPackageSourceTargetName() const override
259
0
  {
260
0
    return "package_source";
261
0
  }
262
  char const* GetRebuildCacheTargetName() const override
263
0
  {
264
0
    return "rebuild_cache";
265
0
  }
266
0
  char const* GetCleanTargetName() const override { return "clean"; }
267
268
0
  bool CheckALLOW_DUPLICATE_CUSTOM_TARGETS() const override { return true; }
269
270
  // Specify if the make tool is able to consume dependency files
271
  // generated by the compiler
272
  bool ToolSupportsCompilerDependencies = true;
273
274
  // some Make generator, such as Borland not support long line dependencies,
275
  // we add SupportsLongLineDependencies to predicate.
276
  bool ToolSupportsLongLineDependencies = true;
277
278
  // Some make programs (Borland) do not keep a rule if there are no
279
  // dependencies or commands.  This is a problem for creating rules
280
  // that might not do anything but might have other dependencies
281
  // added later.  If non-empty this variable holds a fake dependency
282
  // that can be added.
283
  std::string EmptyRuleHackDepends;
284
285
  // Some make programs (Watcom) do not like rules with no commands.
286
  // If non-empty this variable holds a bogus command that may be put
287
  // in the rule to satisfy the make program.
288
  std::string EmptyRuleHackCommand;
289
290
  // Store per-target progress counters.
291
  struct TargetProgress
292
  {
293
    unsigned long NumberOfActions = 0;
294
    std::string VariableFile;
295
    std::vector<unsigned long> Marks;
296
    void WriteProgressVariables(unsigned long total, unsigned long& current);
297
  };
298
  using ProgressMapType = std::map<cmGeneratorTarget const*, TargetProgress,
299
                                   cmGeneratorTarget::StrictTargetComparison>;
300
  ProgressMapType ProgressMap;
301
302
  size_t CountProgressMarksInTarget(
303
    cmGeneratorTarget const* target,
304
    std::set<cmGeneratorTarget const*>& emitted);
305
  size_t CountProgressMarksInAll(cmLocalGenerator const& lg);
306
307
  std::unique_ptr<cmGeneratedFileStream> CommandDatabase;
308
309
private:
310
0
  char const* GetBuildIgnoreErrorsFlag() const override { return "-i"; }
311
312
  std::map<cmStateSnapshot, std::set<cmGeneratorTarget const*>,
313
           cmStateSnapshot::StrictWeakOrder>
314
    DirectoryTargetsMap;
315
  void InitializeProgressMarks() override;
316
317
  // Ordered map of "test_prep/<name>" -> the "<target>.dir/all" recursive
318
  // rules that must be built to prepare the named test.  Populated by
319
  // ComputeTestPrepTargets when CMAKE_TEST_BUILD_DEPENDS is enabled.
320
  std::map<std::string, std::vector<std::string>> TestPrepTargets;
321
  bool TestPrepEnabled = false;
322
};