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 <memory>
10 #include <set>
11 #include <string>
12 #include <vector>
13 
14 #include "cmCommonTargetGenerator.h"
15 #include "cmGeneratorTarget.h"
16 #include "cmLocalUnixMakefileGenerator3.h"
17 #include "cmOSXBundleGenerator.h"
18 
19 class cmCustomCommandGenerator;
20 class cmGeneratedFileStream;
21 class cmGlobalUnixMakefileGenerator3;
22 class cmLinkLineComputer;
23 class cmOutputConverter;
24 class cmSourceFile;
25 class cmStateDirectory;
26 
27 /** \class cmMakefileTargetGenerator
28  * \brief Support Routines for writing makefiles
29  *
30  */
31 class cmMakefileTargetGenerator : public cmCommonTargetGenerator
32 {
33 public:
34   // constructor to set the ivars
35   cmMakefileTargetGenerator(cmGeneratorTarget* target);
36   cmMakefileTargetGenerator(const cmMakefileTargetGenerator&) = delete;
37   ~cmMakefileTargetGenerator() override;
38 
39   cmMakefileTargetGenerator& operator=(const cmMakefileTargetGenerator&) =
40     delete;
41 
42   // construct using this factory call
43   static std::unique_ptr<cmMakefileTargetGenerator> New(
44     cmGeneratorTarget* tgt);
45 
46   /* the main entry point for this class. Writes the Makefiles associated
47      with this target */
48   virtual void WriteRuleFiles() = 0;
49 
50   /* return the number of actions that have progress reporting on them */
GetNumberOfProgressActions()51   virtual unsigned long GetNumberOfProgressActions()
52   {
53     return this->NumberOfProgressActions;
54   }
GetProgressFileNameFull()55   std::string GetProgressFileNameFull() { return this->ProgressFileNameFull; }
56 
GetGeneratorTarget()57   cmGeneratorTarget* GetGeneratorTarget() { return this->GeneratorTarget; }
58 
59   std::string GetConfigName();
60 
61 protected:
62   void GetDeviceLinkFlags(std::string& linkFlags,
63                           const std::string& linkLanguage);
64   void GetTargetLinkFlags(std::string& flags, const std::string& linkLanguage);
65 
66   // create the file and directory etc
67   void CreateRuleFile();
68 
69   // outputs the rules for object files and custom commands used by
70   // this target
71   void WriteTargetBuildRules();
72 
73   // write some common code at the top of build.make
74   void WriteCommonCodeRules();
75   void WriteTargetLanguageFlags();
76 
77   // write the clean rules for this target
78   void WriteTargetCleanRules();
79 
80   // write the depend rules for this target
81   void WriteTargetDependRules();
82 
83   // write rules for macOS Application Bundle content.
84   struct MacOSXContentGeneratorType
85     : cmOSXBundleGenerator::MacOSXContentGeneratorType
86   {
MacOSXContentGeneratorTypeMacOSXContentGeneratorType87     MacOSXContentGeneratorType(cmMakefileTargetGenerator* gen)
88       : Generator(gen)
89     {
90     }
91 
92     void operator()(cmSourceFile const& source, const char* pkgloc,
93                     const std::string& config) override;
94 
95   private:
96     cmMakefileTargetGenerator* Generator;
97   };
98   friend struct MacOSXContentGeneratorType;
99 
100   // write the rules for an object
101   void WriteObjectRuleFiles(cmSourceFile const& source);
102 
103   // write the depend.make file for an object
104   void WriteObjectDependRules(cmSourceFile const& source,
105                               std::vector<std::string>& depends);
106 
107   // CUDA device linking.
108   void WriteDeviceLinkRule(std::vector<std::string>& commands,
109                            const std::string& output);
110 
111   // write the build rule for a custom command
112   void GenerateCustomRuleFile(cmCustomCommandGenerator const& ccg);
113 
114   // write a rule to drive building of more than one output from
115   // another rule
116   void GenerateExtraOutput(const char* out, const char* in,
117                            bool symbolic = false);
118 
119   void MakeEchoProgress(cmLocalUnixMakefileGenerator3::EchoProgress&) const;
120 
121   // write out the variable that lists the objects for this target
122   void WriteObjectsVariable(std::string& variableName,
123                             std::string& variableNameExternal,
124                             bool useWatcomQuote);
125   void WriteObjectsStrings(std::vector<std::string>& objStrings,
126                            std::string::size_type limit = std::string::npos);
127 
128   // write the driver rule to build target outputs
129   void WriteTargetDriverRule(const std::string& main_output, bool relink);
130 
131   void DriveCustomCommands(std::vector<std::string>& depends);
132 
133   // append intertarget dependencies
134   void AppendTargetDepends(std::vector<std::string>& depends,
135                            bool ignoreType = false);
136 
137   // Append object file dependencies.
138   void AppendObjectDepends(std::vector<std::string>& depends);
139 
140   // Append link rule dependencies (objects, etc.).
141   void AppendLinkDepends(std::vector<std::string>& depends,
142                          const std::string& linkLanguage);
143 
144   // Lookup the link rule for this target.
145   std::string GetLinkRule(const std::string& linkRuleVar);
146 
147   /** Create a script to hold link rules and a command to invoke the
148       script at build time.  */
149   void CreateLinkScript(const char* name,
150                         std::vector<std::string> const& link_commands,
151                         std::vector<std::string>& makefile_commands,
152                         std::vector<std::string>& makefile_depends);
153 
154   std::unique_ptr<cmLinkLineComputer> CreateLinkLineComputer(
155     cmOutputConverter* outputConverter, cmStateDirectory const& stateDir);
156 
157   /** Create a response file with the given set of options.  Returns
158       the relative path from the target build working directory to the
159       response file name.  */
160   std::string CreateResponseFile(const char* name, std::string const& options,
161                                  std::vector<std::string>& makefile_depends);
162 
163   bool CheckUseResponseFileForObjects(std::string const& l) const;
164   bool CheckUseResponseFileForLibraries(std::string const& l) const;
165 
166   /** Create list of flags for link libraries. */
167   void CreateLinkLibs(cmLinkLineComputer* linkLineComputer,
168                       std::string& linkLibs, bool useResponseFile,
169                       std::vector<std::string>& makefile_depends);
170 
171   /** Create lists of object files for linking and cleaning.  */
172   void CreateObjectLists(bool useLinkScript, bool useArchiveRules,
173                          bool useResponseFile, std::string& buildObjs,
174                          std::vector<std::string>& makefile_depends,
175                          bool useWatcomQuote);
176 
177   /** Add commands for generate def files */
178   void GenDefFile(std::vector<std::string>& real_link_commands);
179 
180   void AddIncludeFlags(std::string& flags, const std::string& lang,
181                        const std::string& config) override;
182 
183   virtual void CloseFileStreams();
184   cmLocalUnixMakefileGenerator3* LocalGenerator;
185   cmGlobalUnixMakefileGenerator3* GlobalGenerator;
186 
187   enum CustomCommandDriveType
188   {
189     OnBuild,
190     OnDepends,
191     OnUtility
192   };
193   CustomCommandDriveType CustomCommandDriver;
194 
195   // the full path to the build file
196   std::string BuildFileName;
197   std::string BuildFileNameFull;
198 
199   // the full path to the progress file
200   std::string ProgressFileNameFull;
201   unsigned long NumberOfProgressActions;
202   bool NoRuleMessages;
203 
204   bool CMP0113New = false;
205 
206   // the path to the directory the build file is in
207   std::string TargetBuildDirectory;
208   std::string TargetBuildDirectoryFull;
209 
210   // the stream for the build file
211   std::unique_ptr<cmGeneratedFileStream> BuildFileStream;
212 
213   // the stream for the flag file
214   std::string FlagFileNameFull;
215   std::unique_ptr<cmGeneratedFileStream> FlagFileStream;
216   class StringList : public std::vector<std::string>
217   {
218   };
219   std::map<std::string, StringList> FlagFileDepends;
220 
221   // the stream for the info file
222   std::string InfoFileNameFull;
223   std::unique_ptr<cmGeneratedFileStream> InfoFileStream;
224 
225   // files to clean
226   std::set<std::string> CleanFiles;
227 
228   // objects used by this target
229   std::vector<std::string> Objects;
230   std::vector<std::string> ExternalObjects;
231 
232   // Set of object file names that will be built in this directory.
233   std::set<std::string> ObjectFiles;
234 
235   // Set of extra output files to be driven by the build.
236   std::set<std::string> ExtraFiles;
237 
238   // Set of custom command output files to be driven by the build.
239   std::set<std::string> CustomCommandOutputs;
240 
241   using MultipleOutputPairsType = std::map<std::string, std::string>;
242   MultipleOutputPairsType MultipleOutputPairs;
243   bool WriteMakeRule(std::ostream& os, const char* comment,
244                      const std::vector<std::string>& outputs,
245                      const std::vector<std::string>& depends,
246                      const std::vector<std::string>& commands,
247                      bool in_help = false);
248 
249   // Target name info.
250   cmGeneratorTarget::Names TargetNames;
251 
252   // macOS content info.
253   std::set<std::string> MacContentFolders;
254   std::unique_ptr<cmOSXBundleGenerator> OSXBundleGenerator;
255   std::unique_ptr<MacOSXContentGeneratorType> MacOSXContentGenerator;
256 };
257