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 */ SetMakefileVariableSize(int s)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 */ SetMakeCommandEscapeTargetTwice(bool b)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 */ SetBorlandMakeCurlyHack(bool b)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. */ GetColorMakefile()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 GetLocalHelp()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. */ GetCreatePreprocessedSourceRules()180 bool GetCreatePreprocessedSourceRules() const 181 { 182 return !this->SkipPreprocessedSourceRules; 183 } GetCreateAssemblySourceRules()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; LocalObjectEntryLocalObjectEntry265 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 GetCommandsVisited(cmGeneratorTarget const * target)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 }; 307