| /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying |
| file Copyright.txt or https://cmake.org/licensing for details. */ |
| #pragma once |
| |
| #include "cmConfigure.h" // IWYU pragma: keep |
| |
| #include <cstddef> |
| #include <iosfwd> |
| #include <map> |
| #include <memory> |
| #include <set> |
| #include <string> |
| #include <vector> |
| |
| #include "cmBuildOptions.h" |
| #include "cmGeneratorTarget.h" |
| #include "cmGlobalCommonGenerator.h" |
| #include "cmGlobalGeneratorFactory.h" |
| #include "cmStateSnapshot.h" |
| |
| class cmGeneratedFileStream; |
| class cmLocalGenerator; |
| class cmLocalUnixMakefileGenerator3; |
| class cmMakefile; |
| class cmMakefileTargetGenerator; |
| class cmake; |
| |
| /** \class cmGlobalUnixMakefileGenerator3 |
| * \brief Write a Unix makefiles. |
| * |
| * cmGlobalUnixMakefileGenerator3 manages UNIX build process for a tree |
| |
| |
| The basic approach of this generator is to produce Makefiles that will all |
| be run with the current working directory set to the Home Output |
| directory. The one exception to this is the subdirectory Makefiles which are |
| created as a convenience and just cd up to the Home Output directory and |
| invoke the main Makefiles. |
| |
| The make process starts with Makefile. Makefile should only contain the |
| targets the user is likely to invoke directly from a make command line. No |
| internal targets should be in this file. Makefile2 contains the internal |
| targets that are required to make the process work. |
| |
| Makefile2 in turn will recursively make targets in the correct order. Each |
| target has its own directory \<target\>.dir and its own makefile build.make in |
| that directory. Also in that directory is a couple makefiles per source file |
| used by the target. Typically these are named source.obj.build.make and |
| source.obj.build.depend.make. The source.obj.build.make contains the rules |
| for building, cleaning, and computing dependencies for the given source |
| file. The build.depend.make contains additional dependencies that were |
| computed during dependency scanning. An additional file called |
| source.obj.depend is used as a marker to indicate when dependencies must be |
| rescanned. |
| |
| Rules for custom commands follow the same model as rules for source files. |
| |
| */ |
| |
| class cmGlobalUnixMakefileGenerator3 : public cmGlobalCommonGenerator |
| { |
| public: |
| cmGlobalUnixMakefileGenerator3(cmake* cm); |
| static std::unique_ptr<cmGlobalGeneratorFactory> NewFactory() |
| { |
| return std::unique_ptr<cmGlobalGeneratorFactory>( |
| new cmGlobalGeneratorSimpleFactory<cmGlobalUnixMakefileGenerator3>()); |
| } |
| |
| ~cmGlobalUnixMakefileGenerator3() override; |
| |
| cmGlobalUnixMakefileGenerator3(const cmGlobalUnixMakefileGenerator3&) = |
| delete; |
| cmGlobalUnixMakefileGenerator3& operator=( |
| const cmGlobalUnixMakefileGenerator3&) = delete; |
| |
| //! Get the name for the generator. |
| std::string GetName() const override |
| { |
| return cmGlobalUnixMakefileGenerator3::GetActualName(); |
| } |
| static std::string GetActualName() { return "Unix Makefiles"; } |
| |
| /** |
| * Utilized by the generator factory to determine if this generator |
| * supports toolsets. |
| */ |
| static bool SupportsToolset() { return false; } |
| |
| /** |
| * Utilized by the generator factory to determine if this generator |
| * supports platforms. |
| */ |
| static bool SupportsPlatform() { return false; } |
| |
| /** |
| * Utilized to determine if this generator |
| * supports DEPFILE option. |
| */ |
| bool SupportsCustomCommandDepfile() const override { return true; } |
| |
| /** Get the documentation entry for this generator. */ |
| static cmDocumentationEntry GetDocumentation(); |
| |
| std::unique_ptr<cmLocalGenerator> CreateLocalGenerator( |
| cmMakefile* mf) override; |
| |
| /** |
| * Try to determine system information such as shared library |
| * extension, pthreads, byte order etc. |
| */ |
| void EnableLanguage(std::vector<std::string> const& languages, cmMakefile*, |
| bool optional) override; |
| |
| void Configure() override; |
| |
| /** |
| * Generate the all required files for building this project/tree. This |
| * basically creates a series of LocalGenerators for each directory and |
| * requests that they Generate. |
| */ |
| void Generate() override; |
| |
| void WriteMainCMakefileLanguageRules( |
| cmGeneratedFileStream& cmakefileStream, |
| std::vector<std::unique_ptr<cmLocalGenerator>>&); |
| |
| // write out the help rule listing the valid targets |
| void WriteHelpRule(std::ostream& ruleFileStream, |
| cmLocalUnixMakefileGenerator3*); |
| |
| // write the top level target rules |
| void WriteConvenienceRules(std::ostream& ruleFileStream, |
| std::set<std::string>& emitted); |
| |
| // Make tool supports dependency files generated by compiler |
| bool SupportsCompilerDependencies() const |
| { |
| return this->ToolSupportsCompilerDependencies; |
| } |
| |
| // Make tool supports long line dependencies |
| bool SupportsLongLineDependencies() const |
| { |
| return this->ToolSupportsLongLineDependencies; |
| } |
| |
| /** Get the command to use for a target that has no rule. This is |
| used for multiple output dependencies and for cmake_force. */ |
| std::string GetEmptyRuleHackCommand() { return this->EmptyRuleHackCommand; } |
| |
| /** Get the fake dependency to use when a rule has no real commands |
| or dependencies. */ |
| std::string GetEmptyRuleHackDepends() { return this->EmptyRuleHackDepends; } |
| |
| /** |
| * Convert a file path to a Makefile target or dependency with |
| * escaping and quoting suitable for the generator's make tool. |
| */ |
| std::string ConvertToMakefilePath(std::string const& path) const; |
| |
| // change the build command for speed |
| std::vector<GeneratedMakeCommand> GenerateBuildCommand( |
| const std::string& makeProgram, const std::string& projectName, |
| const std::string& projectDir, std::vector<std::string> const& targetNames, |
| const std::string& config, int jobs, bool verbose, |
| const cmBuildOptions& buildOptions = cmBuildOptions(), |
| std::vector<std::string> const& makeOptions = |
| std::vector<std::string>()) override; |
| |
| /** Record per-target progress information. */ |
| void RecordTargetProgress(cmMakefileTargetGenerator* tg); |
| |
| void AddCXXCompileCommand(const std::string& sourceFile, |
| const std::string& workingDirectory, |
| const std::string& compileCommand, |
| const std::string& objPath); |
| |
| /** Does the make tool tolerate .NOTPARALLEL? */ |
| virtual bool AllowNotParallel() const { return true; } |
| |
| /** Does the make tool tolerate .DELETE_ON_ERROR? */ |
| virtual bool AllowDeleteOnError() const { return true; } |
| |
| /** Does the make tool interpret '\#' as '#'? */ |
| virtual bool CanEscapeOctothorpe() const; |
| |
| bool IsIPOSupported() const override { return true; } |
| |
| void ComputeTargetObjectDirectory(cmGeneratorTarget* gt) const override; |
| |
| std::string IncludeDirective; |
| std::string LineContinueDirective; |
| bool DefineWindowsNULL; |
| bool PassMakeflags; |
| bool UnixCD; |
| |
| protected: |
| void WriteMainMakefile2(); |
| void WriteMainCMakefile(); |
| |
| void WriteConvenienceRules2(std::ostream& ruleFileStream, |
| cmLocalUnixMakefileGenerator3& rootLG, |
| cmLocalUnixMakefileGenerator3& lg); |
| |
| void WriteDirectoryRule2(std::ostream& ruleFileStream, |
| cmLocalUnixMakefileGenerator3& rootLG, |
| DirectoryTarget const& dt, const char* pass, |
| bool check_all, bool check_relink, |
| std::vector<std::string> const& commands = {}); |
| void WriteDirectoryRules2(std::ostream& ruleFileStream, |
| cmLocalUnixMakefileGenerator3& rootLG, |
| DirectoryTarget const& dt); |
| |
| void AppendGlobalTargetDepends(std::vector<std::string>& depends, |
| cmGeneratorTarget* target); |
| |
| // Target name hooks for superclass. |
| const char* GetAllTargetName() const override { return "all"; } |
| const char* GetInstallTargetName() const override { return "install"; } |
| const char* GetInstallLocalTargetName() const override |
| { |
| return "install/local"; |
| } |
| const char* GetInstallStripTargetName() const override |
| { |
| return "install/strip"; |
| } |
| const char* GetPreinstallTargetName() const override { return "preinstall"; } |
| const char* GetTestTargetName() const override { return "test"; } |
| const char* GetPackageTargetName() const override { return "package"; } |
| const char* GetPackageSourceTargetName() const override |
| { |
| return "package_source"; |
| } |
| const char* GetRebuildCacheTargetName() const override |
| { |
| return "rebuild_cache"; |
| } |
| const char* GetCleanTargetName() const override { return "clean"; } |
| |
| bool CheckALLOW_DUPLICATE_CUSTOM_TARGETS() const override { return true; } |
| |
| // Specify if the make tool is able to consume dependency files |
| // generated by the compiler |
| bool ToolSupportsCompilerDependencies = true; |
| |
| // some Make generator, such as Borland not support long line dependencies, |
| // we add SupportsLongLineDependencies to predicate. |
| bool ToolSupportsLongLineDependencies = true; |
| |
| // Some make programs (Borland) do not keep a rule if there are no |
| // dependencies or commands. This is a problem for creating rules |
| // that might not do anything but might have other dependencies |
| // added later. If non-empty this variable holds a fake dependency |
| // that can be added. |
| std::string EmptyRuleHackDepends; |
| |
| // Some make programs (Watcom) do not like rules with no commands. |
| // If non-empty this variable holds a bogus command that may be put |
| // in the rule to satisfy the make program. |
| std::string EmptyRuleHackCommand; |
| |
| // Store per-target progress counters. |
| struct TargetProgress |
| { |
| unsigned long NumberOfActions = 0; |
| std::string VariableFile; |
| std::vector<unsigned long> Marks; |
| void WriteProgressVariables(unsigned long total, unsigned long& current); |
| }; |
| using ProgressMapType = std::map<cmGeneratorTarget const*, TargetProgress, |
| cmGeneratorTarget::StrictTargetComparison>; |
| ProgressMapType ProgressMap; |
| |
| size_t CountProgressMarksInTarget( |
| cmGeneratorTarget const* target, |
| std::set<cmGeneratorTarget const*>& emitted); |
| size_t CountProgressMarksInAll(const cmLocalGenerator& lg); |
| |
| std::unique_ptr<cmGeneratedFileStream> CommandDatabase; |
| |
| private: |
| const char* GetBuildIgnoreErrorsFlag() const override { return "-i"; } |
| |
| std::map<cmStateSnapshot, std::set<cmGeneratorTarget const*>, |
| cmStateSnapshot::StrictWeakOrder> |
| DirectoryTargetsMap; |
| void InitializeProgressMarks() override; |
| }; |