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
15 #include "cmBuildOptions.h"
16 #include "cmGeneratorTarget.h"
17 #include "cmGlobalCommonGenerator.h"
18 #include "cmGlobalGeneratorFactory.h"
19 #include "cmStateSnapshot.h"
21 class cmGeneratedFileStream;
22 class cmLocalGenerator;
23 class cmLocalUnixMakefileGenerator3;
25 class cmMakefileTargetGenerator;
27 struct cmDocumentationEntry;
29 /** \class cmGlobalUnixMakefileGenerator3
30 * \brief Write a Unix makefiles.
32 * cmGlobalUnixMakefileGenerator3 manages UNIX build process for a tree
35 The basic approach of this generator is to produce Makefiles that will all
36 be run with the current working directory set to the Home Output
37 directory. The one exception to this is the subdirectory Makefiles which are
38 created as a convenience and just cd up to the Home Output directory and
39 invoke the main Makefiles.
41 The make process starts with Makefile. Makefile should only contain the
42 targets the user is likely to invoke directly from a make command line. No
43 internal targets should be in this file. Makefile2 contains the internal
44 targets that are required to make the process work.
46 Makefile2 in turn will recursively make targets in the correct order. Each
47 target has its own directory \<target\>.dir and its own makefile build.make in
48 that directory. Also in that directory is a couple makefiles per source file
49 used by the target. Typically these are named source.obj.build.make and
50 source.obj.build.depend.make. The source.obj.build.make contains the rules
51 for building, cleaning, and computing dependencies for the given source
52 file. The build.depend.make contains additional dependencies that were
53 computed during dependency scanning. An additional file called
54 source.obj.depend is used as a marker to indicate when dependencies must be
57 Rules for custom commands follow the same model as rules for source files.
61 class cmGlobalUnixMakefileGenerator3 : public cmGlobalCommonGenerator
64 cmGlobalUnixMakefileGenerator3(cmake* cm);
65 static std::unique_ptr<cmGlobalGeneratorFactory> NewFactory()
67 return std::unique_ptr<cmGlobalGeneratorFactory>(
68 new cmGlobalGeneratorSimpleFactory<cmGlobalUnixMakefileGenerator3>());
71 ~cmGlobalUnixMakefileGenerator3() override;
73 cmGlobalUnixMakefileGenerator3(const cmGlobalUnixMakefileGenerator3&) =
75 cmGlobalUnixMakefileGenerator3& operator=(
76 const cmGlobalUnixMakefileGenerator3&) = delete;
78 //! Get the name for the generator.
79 std::string GetName() const override
81 return cmGlobalUnixMakefileGenerator3::GetActualName();
83 static std::string GetActualName() { return "Unix Makefiles"; }
86 * Utilized by the generator factory to determine if this generator
89 static bool SupportsToolset() { return false; }
92 * Utilized by the generator factory to determine if this generator
95 static bool SupportsPlatform() { return false; }
98 * Utilized to determine if this generator
99 * supports DEPFILE option.
101 bool SupportsCustomCommandDepfile() const override { return true; }
103 /** Get the documentation entry for this generator. */
104 static void GetDocumentation(cmDocumentationEntry& entry);
106 std::unique_ptr<cmLocalGenerator> CreateLocalGenerator(
107 cmMakefile* mf) override;
110 * Try to determine system information such as shared library
111 * extension, pthreads, byte order etc.
113 void EnableLanguage(std::vector<std::string> const& languages, cmMakefile*,
114 bool optional) override;
116 void Configure() override;
119 * Generate the all required files for building this project/tree. This
120 * basically creates a series of LocalGenerators for each directory and
121 * requests that they Generate.
123 void Generate() override;
125 void WriteMainCMakefileLanguageRules(
126 cmGeneratedFileStream& cmakefileStream,
127 std::vector<std::unique_ptr<cmLocalGenerator>>&);
129 // write out the help rule listing the valid targets
130 void WriteHelpRule(std::ostream& ruleFileStream,
131 cmLocalUnixMakefileGenerator3*);
133 // write the top level target rules
134 void WriteConvenienceRules(std::ostream& ruleFileStream,
135 std::set<std::string>& emitted);
137 // Make tool supports dependency files generated by compiler
138 bool SupportsCompilerDependencies() const
140 return this->ToolSupportsCompilerDependencies;
143 // Make tool supports long line dependencies
144 bool SupportsLongLineDependencies() const
146 return this->ToolSupportsLongLineDependencies;
149 /** Get the command to use for a target that has no rule. This is
150 used for multiple output dependencies and for cmake_force. */
151 std::string GetEmptyRuleHackCommand() { return this->EmptyRuleHackCommand; }
153 /** Get the fake dependency to use when a rule has no real commands
155 std::string GetEmptyRuleHackDepends() { return this->EmptyRuleHackDepends; }
158 * Convert a file path to a Makefile target or dependency with
159 * escaping and quoting suitable for the generator's make tool.
161 std::string ConvertToMakefilePath(std::string const& path) const;
163 // change the build command for speed
164 std::vector<GeneratedMakeCommand> GenerateBuildCommand(
165 const std::string& makeProgram, const std::string& projectName,
166 const std::string& projectDir, std::vector<std::string> const& targetNames,
167 const std::string& config, int jobs, bool verbose,
168 const cmBuildOptions& buildOptions = cmBuildOptions(),
169 std::vector<std::string> const& makeOptions =
170 std::vector<std::string>()) override;
172 /** Record per-target progress information. */
173 void RecordTargetProgress(cmMakefileTargetGenerator* tg);
175 void AddCXXCompileCommand(const std::string& sourceFile,
176 const std::string& workingDirectory,
177 const std::string& compileCommand);
179 /** Does the make tool tolerate .NOTPARALLEL? */
180 virtual bool AllowNotParallel() const { return true; }
182 /** Does the make tool tolerate .DELETE_ON_ERROR? */
183 virtual bool AllowDeleteOnError() const { return true; }
185 /** Does the make tool interpret '\#' as '#'? */
186 virtual bool CanEscapeOctothorpe() const;
188 bool IsIPOSupported() const override { return true; }
190 void ComputeTargetObjectDirectory(cmGeneratorTarget* gt) const override;
192 std::string IncludeDirective;
193 std::string LineContinueDirective;
194 bool DefineWindowsNULL;
199 void WriteMainMakefile2();
200 void WriteMainCMakefile();
202 void WriteConvenienceRules2(std::ostream& ruleFileStream,
203 cmLocalUnixMakefileGenerator3& rootLG,
204 cmLocalUnixMakefileGenerator3& lg);
206 void WriteDirectoryRule2(std::ostream& ruleFileStream,
207 cmLocalUnixMakefileGenerator3& rootLG,
208 DirectoryTarget const& dt, const char* pass,
209 bool check_all, bool check_relink,
210 std::vector<std::string> const& commands = {});
211 void WriteDirectoryRules2(std::ostream& ruleFileStream,
212 cmLocalUnixMakefileGenerator3& rootLG,
213 DirectoryTarget const& dt);
215 void AppendGlobalTargetDepends(std::vector<std::string>& depends,
216 cmGeneratorTarget* target);
218 // Target name hooks for superclass.
219 const char* GetAllTargetName() const override { return "all"; }
220 const char* GetInstallTargetName() const override { return "install"; }
221 const char* GetInstallLocalTargetName() const override
223 return "install/local";
225 const char* GetInstallStripTargetName() const override
227 return "install/strip";
229 const char* GetPreinstallTargetName() const override { return "preinstall"; }
230 const char* GetTestTargetName() const override { return "test"; }
231 const char* GetPackageTargetName() const override { return "package"; }
232 const char* GetPackageSourceTargetName() const override
234 return "package_source";
236 const char* GetRebuildCacheTargetName() const override
238 return "rebuild_cache";
240 const char* GetCleanTargetName() const override { return "clean"; }
242 bool CheckALLOW_DUPLICATE_CUSTOM_TARGETS() const override { return true; }
244 // Specify if the make tool is able to consume dependency files
245 // generated by the compiler
246 bool ToolSupportsCompilerDependencies = true;
248 // some Make generator, such as Borland not support long line dependencies,
249 // we add SupportsLongLineDependencies to predicate.
250 bool ToolSupportsLongLineDependencies = true;
252 // Some make programs (Borland) do not keep a rule if there are no
253 // dependencies or commands. This is a problem for creating rules
254 // that might not do anything but might have other dependencies
255 // added later. If non-empty this variable holds a fake dependency
256 // that can be added.
257 std::string EmptyRuleHackDepends;
259 // Some make programs (Watcom) do not like rules with no commands.
260 // If non-empty this variable holds a bogus command that may be put
261 // in the rule to satisfy the make program.
262 std::string EmptyRuleHackCommand;
264 // Store per-target progress counters.
265 struct TargetProgress
267 unsigned long NumberOfActions = 0;
268 std::string VariableFile;
269 std::vector<unsigned long> Marks;
270 void WriteProgressVariables(unsigned long total, unsigned long& current);
272 using ProgressMapType = std::map<cmGeneratorTarget const*, TargetProgress,
273 cmGeneratorTarget::StrictTargetComparison>;
274 ProgressMapType ProgressMap;
276 size_t CountProgressMarksInTarget(
277 cmGeneratorTarget const* target,
278 std::set<cmGeneratorTarget const*>& emitted);
279 size_t CountProgressMarksInAll(const cmLocalGenerator& lg);
281 std::unique_ptr<cmGeneratedFileStream> CommandDatabase;
284 const char* GetBuildIgnoreErrorsFlag() const override { return "-i"; }
286 std::map<cmStateSnapshot, std::set<cmGeneratorTarget const*>,
287 cmStateSnapshot::StrictWeakOrder>
289 void InitializeProgressMarks() override;