1 /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
2 file Copyright.txt or https://cmake.org/licensing for details. */
5 #include "cmConfigure.h" // IWYU pragma: keep
14 #include "cmDepends.h"
15 #include "cmLocalCommonGenerator.h"
16 #include "cmLocalGenerator.h"
18 class cmCustomCommand;
19 class cmCustomCommandGenerator;
20 class cmGeneratorTarget;
21 class cmGlobalGenerator;
25 /** \class cmLocalUnixMakefileGenerator3
26 * \brief Write a LocalUnix makefiles.
28 * cmLocalUnixMakefileGenerator3 produces a LocalUnix makefile from its
31 class cmLocalUnixMakefileGenerator3 : public cmLocalCommonGenerator
34 cmLocalUnixMakefileGenerator3(cmGlobalGenerator* gg, cmMakefile* mf);
35 ~cmLocalUnixMakefileGenerator3() override;
37 std::string GetConfigName() const;
39 void ComputeHomeRelativeOutputPath() override;
42 * Generate the makefile for this directory.
44 void Generate() override;
46 // this returns the relative path between the HomeOutputDirectory and this
47 // local generators StartOutputDirectory
48 const std::string& GetHomeRelativeOutputPath();
51 * Convert a file path to a Makefile target or dependency with
52 * escaping and quoting suitable for the generator's make tool.
54 std::string ConvertToMakefilePath(std::string const& path) const;
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);
63 // write the main variables used by the makefiles
64 void WriteMakeVariables(std::ostream& makefileStream);
67 * Set max makefile variable size, default is 0 which means unlimited.
69 void SetMakefileVariableSize(int s) { this->MakefileVariableSize = s; }
72 * Set whether passing a make target on a command line requires an
73 * extra level of escapes.
75 void SetMakeCommandEscapeTargetTwice(bool b)
77 this->MakeCommandEscapeTargetTwice = b;
81 * Set whether the Borland curly brace command line hack should be
84 void SetBorlandMakeCurlyHack(bool b) { this->BorlandMakeCurlyHack = b; }
86 // used in writing out Cmake files such as WriteDirectoryInformation
87 static void WriteCMakeArgument(std::ostream& os, const std::string& s);
89 /** creates the common disclaimer text at the top of each makefile */
90 void WriteDisclaimer(std::ostream& os);
92 // write a comment line #====... in the stream
93 void WriteDivider(std::ostream& os);
95 /** used to create a recursive make call */
96 std::string GetRecursiveMakeCall(const std::string& makefile,
97 const std::string& tgt);
99 // append flags to a string
100 void AppendFlags(std::string& flags,
101 const std::string& newFlags) const override;
102 using cmLocalCommonGenerator::AppendFlags;
104 // append an echo command
119 void AppendEcho(std::vector<std::string>& commands, std::string const& text,
120 EchoColor color = EchoNormal, EchoProgress const* = nullptr);
122 /** Get whether the makefile is to have color. */
123 bool GetColorMakefile() const { return this->ColorMakefile; }
125 std::string GetTargetDirectory(
126 cmGeneratorTarget const* target) const override;
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);
133 static std::string ConvertToQuotedOutputPath(const std::string& p,
134 bool useWatcomQuote);
136 std::string CreateMakeVariable(const std::string& sin,
137 const std::string& s2in);
139 /** Called from command-line hook to bring dependencies up to date
141 bool UpdateDependencies(const std::string& tgtInfo, bool verbose,
142 bool color) override;
144 /** Called from command-line hook to clear dependencies. */
145 void ClearDependencies(cmMakefile* mf, bool verbose) override;
147 /** write some extra rules such as make test etc */
148 void WriteSpecialTargetsTop(std::ostream& makefileStream);
149 void WriteSpecialTargetsBottom(std::ostream& makefileStream);
151 std::string GetRelativeTargetDirectory(
152 cmGeneratorTarget const* target) const;
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);
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);
172 // write the target rules for the local Makefile into the stream
173 void WriteLocalAllRules(std::ostream& ruleFileStream);
175 std::vector<std::string> const& GetLocalHelp() { return this->LocalHelp; }
177 /** Get whether to create rules to generate preprocessed and
178 assembly sources. This could be converted to a variable lookup
180 bool GetCreatePreprocessedSourceRules() const
182 return !this->SkipPreprocessedSourceRules;
184 bool GetCreateAssemblySourceRules() const
186 return !this->SkipAssemblySourceRules;
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);
195 void WriteLocalMakefile();
197 // write the target rules for the local Makefile into the stream
198 void WriteLocalMakefileTargets(std::ostream& ruleFileStream,
199 std::set<std::string>& emitted);
201 // this method Writes the Directory information files
202 void WriteDirectoryInformationFile();
204 // write the depend info
205 void WriteDependLanguageInfo(std::ostream& cmakefileStream,
206 cmGeneratorTarget* tgt);
208 // this converts a file name that is relative to the StartOuputDirectory
210 std::string ConvertToFullPath(const std::string& localPath);
212 void WriteConvenienceRule(std::ostream& ruleFileStream,
213 const std::string& realTarget,
214 const std::string& helpTarget);
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);
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);
248 std::string MaybeConvertWatcomShellCommand(std::string const& cmd);
250 friend class cmMakefileTargetGenerator;
251 friend class cmMakefileExecutableTargetGenerator;
252 friend class cmMakefileLibraryTargetGenerator;
253 friend class cmMakefileUtilityTargetGenerator;
254 friend class cmGlobalUnixMakefileGenerator3;
256 ImplicitDependTargetMap ImplicitDepends;
258 std::string HomeRelativeOutputPath;
260 struct LocalObjectEntry
262 cmGeneratorTarget* Target = nullptr;
263 std::string Language;
264 LocalObjectEntry() = default;
265 LocalObjectEntry(cmGeneratorTarget* t, std::string lang)
267 , Language(std::move(lang))
271 struct LocalObjectInfo : public std::vector<LocalObjectEntry>
273 bool HasSourceExtension = false;
274 bool HasPreprocessRule = false;
275 bool HasAssembleRule = false;
277 void GetLocalObjectFiles(
278 std::map<std::string, LocalObjectInfo>& localObjectFiles);
280 void WriteObjectConvenienceRule(std::ostream& ruleFileStream,
282 const std::string& output,
283 LocalObjectInfo const& info);
285 std::vector<std::string> LocalHelp;
287 /* does the work for each target */
288 std::map<std::string, std::string> MakeVariableMap;
289 std::map<std::string, std::string> ShortMakeVariableMap;
291 int MakefileVariableSize;
292 bool MakeCommandEscapeTargetTwice;
293 bool BorlandMakeCurlyHack;
295 bool SkipPreprocessedSourceRules;
296 bool SkipAssemblySourceRules;
298 std::set<cmSourceFile const*>& GetCommandsVisited(
299 cmGeneratorTarget const* target)
301 return this->CommandsVisited[target];
304 std::map<cmGeneratorTarget const*, std::set<cmSourceFile const*>>