Coverage Report

Created: 2026-02-09 06:05

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/CMake/Source/cmLocalUnixMakefileGenerator3.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 <iosfwd>
8
#include <map>
9
#include <set>
10
#include <string>
11
#include <utility>
12
#include <vector>
13
14
#include "cmDepends.h"
15
#include "cmGeneratorOptions.h"
16
#include "cmLocalCommonGenerator.h"
17
#include "cmStateTypes.h"
18
19
class cmCustomCommand;
20
class cmCustomCommandGenerator;
21
class cmGeneratorTarget;
22
class cmGlobalGenerator;
23
class cmMakefile;
24
class cmSourceFile;
25
26
/** \class cmLocalUnixMakefileGenerator3
27
 * \brief Write a LocalUnix makefiles.
28
 *
29
 * cmLocalUnixMakefileGenerator3 produces a LocalUnix makefile from its
30
 * member Makefile.
31
 */
32
class cmLocalUnixMakefileGenerator3 : public cmLocalCommonGenerator
33
{
34
public:
35
  cmLocalUnixMakefileGenerator3(cmGlobalGenerator* gg, cmMakefile* mf);
36
  ~cmLocalUnixMakefileGenerator3() override;
37
38
  std::string const& GetConfigName() const;
39
40
  void ComputeHomeRelativeOutputPath() override;
41
42
  /**
43
   * Generate the makefile for this directory.
44
   */
45
  void Generate() override;
46
47
  std::string GetObjectOutputRoot(
48
    cmStateEnums::IntermediateDirKind kind =
49
      cmStateEnums::IntermediateDirKind::ObjectFiles) const override;
50
51
  // this returns the relative path between the HomeOutputDirectory and this
52
  // local generators StartOutputDirectory
53
  std::string const& GetHomeRelativeOutputPath();
54
55
  /**
56
   * Convert a file path to a Makefile target or dependency with
57
   * escaping and quoting suitable for the generator's make tool.
58
   */
59
  std::string ConvertToMakefilePath(std::string const& path) const;
60
61
  // Write out a make rule
62
  void WriteMakeRule(std::ostream& os, char const* comment,
63
                     std::string const& target,
64
                     std::vector<std::string> const& depends,
65
                     std::vector<std::string> const& commands, bool symbolic,
66
                     bool in_help = false);
67
68
  // write the main variables used by the makefiles
69
  void WriteMakeVariables(std::ostream& makefileStream);
70
71
  /**
72
   * Set max makefile variable size, default is 0 which means unlimited.
73
   */
74
0
  void SetMakefileVariableSize(int s) { this->MakefileVariableSize = s; }
75
76
  /**
77
   * Set whether passing a make target on a command line requires an
78
   * extra level of escapes.
79
   */
80
  void SetMakeCommandEscapeTargetTwice(bool b)
81
0
  {
82
0
    this->MakeCommandEscapeTargetTwice = b;
83
0
  }
84
85
  /**
86
   * Set whether the Borland curly brace command line hack should be
87
   * applied.
88
   */
89
0
  void SetBorlandMakeCurlyHack(bool b) { this->BorlandMakeCurlyHack = b; }
90
91
  // used in writing out Cmake files such as WriteDirectoryInformation
92
  static void WriteCMakeArgument(std::ostream& os, std::string const& s);
93
94
  /** creates the common disclaimer text at the top of each makefile */
95
  void WriteDisclaimer(std::ostream& os);
96
97
  // write a  comment line #====... in the stream
98
  void WriteDivider(std::ostream& os);
99
100
  /** used to create a recursive make call */
101
  std::string GetRecursiveMakeCall(std::string const& makefile,
102
                                   std::string const& tgt);
103
104
  // append flags to a string
105
  void AppendFlags(std::string& flags,
106
                   std::string const& newFlags) const override;
107
  using cmLocalCommonGenerator::AppendFlags;
108
109
  // append an echo command
110
  enum EchoColor
111
  {
112
    EchoNormal,
113
    EchoDepend,
114
    EchoBuild,
115
    EchoLink,
116
    EchoGenerate,
117
    EchoGlobal
118
  };
119
  struct EchoProgress
120
  {
121
    std::string Dir;
122
    std::string Arg;
123
  };
124
  void AppendEcho(std::vector<std::string>& commands, std::string const& text,
125
                  EchoColor color = EchoNormal, EchoProgress const* = nullptr);
126
127
  /** Get whether the makefile is to have color.  */
128
0
  bool GetColorMakefile() const { return this->ColorMakefile; }
129
130
  // create a command that cds to the start dir then runs the commands
131
  void CreateCDCommand(std::vector<std::string>& commands,
132
                       std::string const& targetDir,
133
                       std::string const& relDir);
134
135
  static std::string ConvertToQuotedOutputPath(std::string const& p,
136
                                               bool useWatcomQuote);
137
138
  std::string CreateMakeVariable(std::string const& sin,
139
                                 std::string const& s2in);
140
141
  /** Called from command-line hook to bring dependencies up to date
142
      for a target.  */
143
  bool UpdateDependencies(std::string const& tgtInfo,
144
                          std::string const& targetName, bool verbose,
145
                          bool color) override;
146
147
  /** Called from command-line hook to clear dependencies.  */
148
  void ClearDependencies(cmMakefile* mf, bool verbose) override;
149
150
  /** write some extra rules such as make test etc */
151
  void WriteSpecialTargetsTop(std::ostream& makefileStream);
152
  void WriteSpecialTargetsBottom(std::ostream& makefileStream);
153
154
  std::string GetRelativeTargetDirectory(
155
    cmGeneratorTarget const* target) const;
156
157
  // File pairs for implicit dependency scanning.  The key of the map
158
  // is the depender and the value is the explicit dependee.
159
  using ImplicitDependFileMap = cmDepends::DependencyMap;
160
  using ImplicitDependLanguageMap =
161
    std::map<std::string, ImplicitDependFileMap>;
162
  using ImplicitDependScannerMap =
163
    std::map<cmDependencyScannerKind, ImplicitDependLanguageMap>;
164
  using ImplicitDependTargetMap =
165
    std::map<std::string, ImplicitDependScannerMap>;
166
  ImplicitDependLanguageMap const& GetImplicitDepends(
167
    cmGeneratorTarget const* tgt,
168
    cmDependencyScannerKind scanner = cmDependencyScannerKind::CMake);
169
170
  void AddImplicitDepends(
171
    cmGeneratorTarget const* tgt, std::string const& lang,
172
    std::string const& obj, std::string const& src,
173
    cmDependencyScannerKind scanner = cmDependencyScannerKind::CMake);
174
175
  // write the target rules for the local Makefile into the stream
176
  void WriteLocalAllRules(std::ostream& ruleFileStream);
177
178
0
  std::vector<std::string> const& GetLocalHelp() { return this->LocalHelp; }
179
180
  /** Get whether to create rules to generate preprocessed and
181
      assembly sources.  This could be converted to a variable lookup
182
      later.  */
183
  bool GetCreatePreprocessedSourceRules() const
184
0
  {
185
0
    return !this->SkipPreprocessedSourceRules;
186
0
  }
187
  bool GetCreateAssemblySourceRules() const
188
0
  {
189
0
    return !this->SkipAssemblySourceRules;
190
0
  }
191
192
  // Fill the vector with the target names for the object files,
193
  // preprocessed files and assembly files. Currently only used by the
194
  // Eclipse generator.
195
  void GetIndividualFileTargets(std::vector<std::string>& targets);
196
197
  std::string GetLinkDependencyFile(cmGeneratorTarget* target,
198
                                    std::string const& config) const override;
199
200
protected:
201
  void WriteLocalMakefile();
202
203
  // write the target rules for the local Makefile into the stream
204
  void WriteLocalMakefileTargets(std::ostream& ruleFileStream,
205
                                 std::set<std::string>& emitted);
206
207
  // this method Writes the Directory information files
208
  void WriteDirectoryInformationFile();
209
210
  // write the depend info
211
  void WriteDependLanguageInfo(std::ostream& cmakefileStream,
212
                               cmGeneratorTarget* tgt);
213
214
  // this converts a file name that is relative to the StartOutputDirectory
215
  // into a full path
216
  std::string ConvertToFullPath(std::string const& localPath);
217
218
  void WriteConvenienceRule(std::ostream& ruleFileStream,
219
                            std::string const& realTarget,
220
                            std::string const& helpTarget);
221
222
  void AppendRuleDepend(std::vector<std::string>& depends,
223
                        char const* ruleFileName);
224
  void AppendRuleDepends(std::vector<std::string>& depends,
225
                         std::vector<std::string> const& ruleFiles);
226
  void AppendCustomDepends(std::vector<std::string>& depends,
227
                           std::vector<cmCustomCommand> const& ccs);
228
  void AppendCustomDepend(std::vector<std::string>& depends,
229
                          cmCustomCommandGenerator const& cc);
230
  void AppendCustomCommands(std::vector<std::string>& commands,
231
                            std::vector<cmCustomCommand> const& ccs,
232
                            cmGeneratorTarget* target,
233
                            std::string const& relative);
234
  void AppendCustomCommand(std::vector<std::string>& commands,
235
                           cmCustomCommandGenerator const& ccg,
236
                           cmGeneratorTarget* target,
237
                           std::string const& relative,
238
                           bool echo_comment = false,
239
                           std::ostream* content = nullptr);
240
  void AppendCleanCommand(std::vector<std::string>& commands,
241
                          std::set<std::string> const& files,
242
                          cmGeneratorTarget* target,
243
                          char const* filename = nullptr);
244
  void AppendDirectoryCleanCommand(std::vector<std::string>& commands);
245
246
  // Helper methods for dependency updates.
247
  bool ScanDependencies(std::string const& targetDir,
248
                        std::string const& dependFile,
249
                        std::string const& internalDependFile,
250
                        cmDepends::DependencyMap& validDeps);
251
  void CheckMultipleOutputs(bool verbose);
252
253
private:
254
  std::string MaybeConvertWatcomShellCommand(std::string const& cmd);
255
256
  friend class cmMakefileTargetGenerator;
257
  friend class cmMakefileExecutableTargetGenerator;
258
  friend class cmMakefileLibraryTargetGenerator;
259
  friend class cmMakefileUtilityTargetGenerator;
260
  friend class cmGlobalUnixMakefileGenerator3;
261
262
  ImplicitDependTargetMap ImplicitDepends;
263
264
  std::string HomeRelativeOutputPath;
265
266
  struct LocalObjectEntry
267
  {
268
    cmGeneratorTarget* Target = nullptr;
269
    std::string Language;
270
    LocalObjectEntry() = default;
271
    LocalObjectEntry(cmGeneratorTarget* t, std::string lang)
272
0
      : Target(t)
273
0
      , Language(std::move(lang))
274
0
    {
275
0
    }
276
  };
277
  struct LocalObjectInfo : public std::vector<LocalObjectEntry>
278
  {
279
    bool HasSourceExtension = false;
280
    bool HasPreprocessRule = false;
281
    bool HasAssembleRule = false;
282
  };
283
  void GetLocalObjectFiles(
284
    std::map<std::string, LocalObjectInfo>& localObjectFiles);
285
286
  void WriteObjectConvenienceRule(std::ostream& ruleFileStream,
287
                                  char const* comment,
288
                                  std::string const& output,
289
                                  LocalObjectInfo const& info);
290
291
  std::vector<std::string> LocalHelp;
292
293
  /* does the work for each target */
294
  std::map<std::string, std::string> MakeVariableMap;
295
  std::map<std::string, std::string> ShortMakeVariableMap;
296
297
  int MakefileVariableSize;
298
  bool MakeCommandEscapeTargetTwice;
299
  bool BorlandMakeCurlyHack;
300
  bool ColorMakefile;
301
  bool SkipPreprocessedSourceRules;
302
  bool SkipAssemblySourceRules;
303
304
  std::set<cmSourceFile const*>& GetCommandsVisited(
305
    cmGeneratorTarget const* target)
306
0
  {
307
0
    return this->CommandsVisited[target];
308
0
  }
309
310
  std::map<cmGeneratorTarget const*, std::set<cmSourceFile const*>>
311
    CommandsVisited;
312
};