Coverage Report

Created: 2026-02-09 06:05

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
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
};