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