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 <cm/optional>
15 #include <cm/string_view>
17 #include "cmGlobalGenerator.h"
18 #include "cmTransformDepfile.h"
20 #include "cmXCodeObject.h"
22 class cmCustomCommand;
23 class cmCustomCommandGenerator;
24 class cmGeneratorTarget;
25 class cmGlobalGeneratorFactory;
26 class cmLocalGenerator;
31 struct cmDocumentationEntry;
33 /** \class cmGlobalXCodeGenerator
34 * \brief Write a Unix makefiles.
36 * cmGlobalXCodeGenerator manages Xcode build process for a tree
38 class cmGlobalXCodeGenerator : public cmGlobalGenerator
41 cmGlobalXCodeGenerator(cmake* cm, std::string const& version_string,
42 unsigned int version_number);
43 static std::unique_ptr<cmGlobalGeneratorFactory> NewFactory();
45 cmGlobalXCodeGenerator(const cmGlobalXCodeGenerator&) = delete;
46 const cmGlobalXCodeGenerator& operator=(const cmGlobalXCodeGenerator&) =
49 //! Get the name for the generator.
50 std::string GetName() const override
52 return cmGlobalXCodeGenerator::GetActualName();
54 static std::string GetActualName() { return "Xcode"; }
56 /** Get the documentation entry for this generator. */
57 static void GetDocumentation(cmDocumentationEntry& entry);
59 //! Create a local generator appropriate to this Global Generator
60 std::unique_ptr<cmLocalGenerator> CreateLocalGenerator(
61 cmMakefile* mf) override;
64 * Try to determine system information such as shared library
65 * extension, pthreads, byte order etc.
67 void EnableLanguage(std::vector<std::string> const& languages, cmMakefile*,
68 bool optional) override;
71 * Open a generated IDE project given the following information.
73 bool Open(const std::string& bindir, const std::string& projectName,
74 bool dryRun) override;
77 * Try running cmake and building a file. This is used for dynalically
78 * loaded commands, not as part of the usual build process.
80 std::vector<GeneratedMakeCommand> GenerateBuildCommand(
81 const std::string& makeProgram, const std::string& projectName,
82 const std::string& projectDir, std::vector<std::string> const& targetNames,
83 const std::string& config, int jobs, bool verbose,
84 const cmBuildOptions& buildOptions = cmBuildOptions(),
85 std::vector<std::string> const& makeOptions =
86 std::vector<std::string>()) override;
88 /** Append the subdirectory for the given configuration. */
89 void AppendDirectoryForConfig(const std::string& prefix,
90 const std::string& config,
91 const std::string& suffix,
92 std::string& dir) override;
94 bool FindMakeProgram(cmMakefile*) override;
96 //! What is the configurations directory variable called?
97 const char* GetCMakeCFGIntDir() const override;
99 std::string ExpandCFGIntDir(const std::string& str,
100 const std::string& config) const override;
102 void SetCurrentLocalGenerator(cmLocalGenerator*);
104 /** Return true if the generated build tree may contain multiple builds.
105 i.e. "Can I build Debug and Release in the same tree?" */
106 bool IsMultiConfig() const override;
108 bool IsXcode() const override { return true; }
110 bool HasKnownObjectFileLocation(cmTarget const&,
111 std::string* reason) const override;
113 bool IsIPOSupported() const override { return true; }
115 bool UseEffectivePlatformName(cmMakefile* mf) const override;
117 bool ShouldStripResourcePath(cmMakefile*) const override;
120 * Used to determine if this generator supports DEPFILE option.
122 bool SupportsCustomCommandDepfile() const override { return true; }
123 virtual cm::optional<cmDepfileFormat> DepfileFormat() const override
125 return this->XcodeBuildSystem == BuildSystem::One
126 ? cmDepfileFormat::MakeDepfile
127 : cmDepfileFormat::GccDepfile;
130 bool SetSystemName(std::string const& s, cmMakefile* mf) override;
131 bool SetGeneratorToolset(std::string const& ts, bool build,
132 cmMakefile* mf) override;
133 void AppendFlag(std::string& flags, std::string const& flag) const;
135 enum class BuildSystem
142 void AddExtraIDETargets() override;
143 void Generate() override;
146 enum EmbedActionFlags
148 NoActionOnCopyByDefault = 0,
149 CodeSignOnCopyByDefault = 1,
150 RemoveHeadersOnCopyByDefault = 2,
153 bool ParseGeneratorToolset(std::string const& ts, cmMakefile* mf);
154 bool ProcessGeneratorToolsetField(std::string const& key,
155 std::string const& value, cmMakefile* mf);
157 cmXCodeObject* CreateOrGetPBXGroup(cmGeneratorTarget* gtgt,
159 cmXCodeObject* CreatePBXGroup(cmXCodeObject* parent,
160 const std::string& name);
161 bool CreateGroups(std::vector<cmLocalGenerator*>& generators);
162 std::string XCodeEscapePath(const std::string& p);
163 std::string RelativeToSource(const std::string& p);
164 std::string RelativeToBinary(const std::string& p);
165 std::string ConvertToRelativeForMake(std::string const& p);
166 void CreateCustomCommands(
167 cmXCodeObject* buildPhases, cmXCodeObject* sourceBuildPhase,
168 cmXCodeObject* headerBuildPhase, cmXCodeObject* resourceBuildPhase,
169 std::vector<cmXCodeObject*> const& contentBuildPhases,
170 cmXCodeObject* frameworkBuildPhase, cmGeneratorTarget* gtgt);
172 std::string ComputeInfoPListLocation(cmGeneratorTarget* target);
174 void AddCommandsToBuildPhase(cmXCodeObject* buildphase,
175 cmGeneratorTarget* target,
176 std::vector<cmCustomCommand> const& commands,
177 const char* commandFileName);
179 void CreateCustomRulesMakefile(const char* makefileBasename,
180 cmGeneratorTarget* target,
181 std::vector<cmCustomCommand> const& commands,
182 const std::string& configName);
184 cmXCodeObject* FindXCodeTarget(const cmGeneratorTarget*);
185 std::string GetObjectId(cmXCodeObject::PBXType ptype, cm::string_view key);
186 std::string GetOrCreateId(const std::string& name, const std::string& id);
188 // create cmXCodeObject from these functions so that memory can be managed
189 // correctly. All objects created are stored in this->XCodeObjects.
190 cmXCodeObject* CreateObject(cmXCodeObject::PBXType ptype,
191 cm::string_view key = {});
192 cmXCodeObject* CreateObject(cmXCodeObject::Type type);
193 cmXCodeObject* CreateString(const std::string& s);
194 cmXCodeObject* CreateObjectReference(cmXCodeObject*);
195 cmXCodeObject* CreateFlatClone(cmXCodeObject*);
196 cmXCodeObject* CreateXCodeTarget(cmGeneratorTarget* gtgt,
197 cmXCodeObject* buildPhases);
198 void ForceLinkerLanguages() override;
199 void ForceLinkerLanguage(cmGeneratorTarget* gtgt);
200 const char* GetTargetLinkFlagsVar(const cmGeneratorTarget* target) const;
201 const char* GetTargetFileType(cmGeneratorTarget* target);
202 const char* GetTargetProductType(cmGeneratorTarget* target);
203 std::string AddConfigurations(cmXCodeObject* target,
204 cmGeneratorTarget* gtgt);
205 void AppendOrAddBuildSetting(cmXCodeObject* settings, const char* attr,
206 cmXCodeObject* value);
207 void AppendBuildSettingAttribute(cmXCodeObject* settings,
208 const char* attribute, cmXCodeObject* attr,
209 cmXCodeObject* value);
210 void AppendBuildSettingAttribute(cmXCodeObject* target, const char* attr,
211 cmXCodeObject* value,
212 const std::string& configName);
213 void InheritBuildSettingAttribute(cmXCodeObject* target,
214 const char* attribute);
215 cmXCodeObject* CreateUtilityTarget(cmGeneratorTarget* gtgt);
216 void AddDependAndLinkInformation(cmXCodeObject* target);
217 void AddEmbeddedObjects(cmXCodeObject* target,
218 const std::string& copyFilesBuildPhaseName,
219 const std::string& embedPropertyName,
220 const std::string& dstSubfolderSpec,
221 int actionsOnByDefault);
222 void AddEmbeddedFrameworks(cmXCodeObject* target);
223 void AddEmbeddedPlugIns(cmXCodeObject* target);
224 void AddEmbeddedAppExtensions(cmXCodeObject* target);
225 void AddPositionIndependentLinkAttribute(cmGeneratorTarget* target,
226 cmXCodeObject* buildSettings,
227 const std::string& configName);
228 void CreateGlobalXCConfigSettings(cmLocalGenerator* root,
229 cmXCodeObject* config,
230 const std::string& configName);
231 void CreateTargetXCConfigSettings(cmGeneratorTarget* target,
232 cmXCodeObject* config,
233 const std::string& configName);
234 void CreateBuildSettings(cmGeneratorTarget* gtgt,
235 cmXCodeObject* buildSettings,
236 const std::string& buildType);
237 std::string ExtractFlag(const char* flag, std::string& flags);
238 std::string ExtractFlagRegex(const char* exp, int matchIndex,
240 void FilterConfigurationAttribute(std::string const& configName,
241 std::string& attribute);
242 void SortXCodeObjects();
243 // delete all objects in the this->XCodeObjects vector.
244 void ClearXCodeObjects();
245 bool CreateXCodeObjects(cmLocalGenerator* root,
246 std::vector<cmLocalGenerator*>& generators);
247 void OutputXCodeProject(cmLocalGenerator* root,
248 std::vector<cmLocalGenerator*>& generators);
249 // Write shared scheme files for all the native targets
250 // return true if any were written
251 bool OutputXCodeSharedSchemes(const std::string& xcProjDir,
252 cmLocalGenerator* root);
253 void OutputXCodeWorkspaceSettings(const std::string& xcProjDir,
254 bool hasGeneratedSchemes);
255 void WriteXCodePBXProj(std::ostream& fout, cmLocalGenerator* root,
256 std::vector<cmLocalGenerator*>& generators);
257 cmXCodeObject* CreateXCodeFileReferenceFromPath(const std::string& fullpath,
258 cmGeneratorTarget* target,
259 const std::string& lang,
261 cmXCodeObject* CreateXCodeBuildFileFromPath(const std::string& fullpath,
262 cmGeneratorTarget* target,
263 const std::string& lang,
265 cmXCodeObject* CreateXCodeFileReference(cmSourceFile* sf,
266 cmGeneratorTarget* target);
267 cmXCodeObject* CreateXCodeSourceFile(cmLocalGenerator* gen, cmSourceFile* sf,
268 cmGeneratorTarget* gtgt);
269 void AddXCodeProjBuildRule(cmGeneratorTarget* target,
270 std::vector<cmSourceFile*>& sources) const;
271 bool CreateXCodeTargets(cmLocalGenerator* gen, std::vector<cmXCodeObject*>&);
272 bool CreateXCodeTarget(cmGeneratorTarget* gtgt,
273 std::vector<cmXCodeObject*>&);
274 bool IsHeaderFile(cmSourceFile*);
275 void AddDependTarget(cmXCodeObject* target, cmXCodeObject* dependTarget);
276 void CreateXCodeDependHackMakefile(std::vector<cmXCodeObject*>& targets);
277 bool SpecialTargetEmitted(std::string const& tname);
278 void SetGenerationRoot(cmLocalGenerator* root);
279 void AddExtraTargets(cmLocalGenerator* root,
280 std::vector<cmLocalGenerator*>& gens);
281 cmXCodeObject* CreateLegacyRunScriptBuildPhase(
282 const char* name, const char* name2, cmGeneratorTarget* target,
283 const std::vector<cmCustomCommand>&);
284 void CreateRunScriptBuildPhases(cmXCodeObject* buildPhases,
285 cmGeneratorTarget const* gt);
286 void CreateRunScriptBuildPhases(cmXCodeObject* buildPhases,
287 cmSourceFile const* sf,
288 cmGeneratorTarget const* gt,
289 std::set<cmSourceFile const*>& visited);
290 cmXCodeObject* CreateRunScriptBuildPhase(cmSourceFile const* sf,
291 cmGeneratorTarget const* gt,
292 cmCustomCommand const& cc);
293 cmXCodeObject* CreateRunScriptBuildPhase(
294 std::string const& name, cmGeneratorTarget const* gt,
295 std::vector<cmCustomCommand> const& commands);
296 std::string ConstructScript(cmCustomCommandGenerator const& ccg);
297 void CreateReRunCMakeFile(cmLocalGenerator* root,
298 std::vector<cmLocalGenerator*> const& gens);
300 std::string LookupFlags(const std::string& varNamePrefix,
301 const std::string& varNameLang,
302 const std::string& varNameSuffix,
303 const std::string& default_flags);
306 class BuildObjectListOrString;
307 friend class BuildObjectListOrString;
309 void AppendDefines(BuildObjectListOrString& defs, const char* defines_list,
311 void AppendDefines(BuildObjectListOrString& defs,
312 std::vector<std::string> const& defines,
315 void ComputeTargetObjectDirectory(cmGeneratorTarget* gt) const override;
318 const char* GetInstallTargetName() const override { return "install"; }
319 const char* GetPackageTargetName() const override { return "package"; }
321 unsigned int XcodeVersion;
322 std::string VersionString;
323 std::set<std::string> XCodeObjectIDs;
324 std::vector<std::unique_ptr<cmXCodeObject>> XCodeObjects;
325 cmXCodeObject* RootObject;
327 BuildSystem XcodeBuildSystem = BuildSystem::One;
330 std::string const& GetXcodeBuildCommand();
331 std::string FindXcodeBuildCommand();
332 std::string XcodeBuildCommand;
333 bool XcodeBuildCommandInitialized;
335 void PrintCompilerAdvice(std::ostream&, std::string const&,
336 cmValue) const override
340 std::string GetLibraryOrFrameworkPath(const std::string& path) const;
342 std::string GetSymrootDir() const;
343 std::string GetTargetTempDir(cmGeneratorTarget const* gt,
344 std::string const& configName) const;
346 static std::string GetDeploymentPlatform(const cmMakefile* mf);
348 void ComputeArchitectures(cmMakefile* mf);
349 void ComputeObjectDirArch(cmMakefile* mf);
351 void addObject(std::unique_ptr<cmXCodeObject> obj);
352 std::string PostBuildMakeTarget(std::string const& tName,
353 std::string const& configName);
354 cmXCodeObject* MainGroupChildren;
355 cmXCodeObject* FrameworkGroup;
356 cmMakefile* CurrentMakefile;
357 cmLocalGenerator* CurrentLocalGenerator;
358 cmLocalGenerator* CurrentRootGenerator = nullptr;
359 std::vector<std::string> CurrentConfigurationTypes;
360 std::string CurrentReRunCMakeMakefile;
361 std::string CurrentXCodeHackMakefile;
362 std::string CurrentProject;
363 std::set<std::string> TargetDoneSet;
364 std::map<std::string, cmXCodeObject*> GroupMap;
365 std::map<std::string, cmXCodeObject*> GroupNameMap;
366 std::map<std::string, cmXCodeObject*> TargetGroup;
367 std::map<std::string, cmXCodeObject*> FileRefs;
368 std::map<std::string, cmXCodeObject*> ExternalLibRefs;
369 std::map<std::string, cmXCodeObject*> EmbeddedLibRefs;
370 std::map<cmGeneratorTarget const*, cmXCodeObject*> XCodeObjectMap;
371 std::map<cmXCodeObject*, cmXCodeObject*> FileRefToBuildFileMap;
372 std::map<cmXCodeObject*, cmXCodeObject*> FileRefToEmbedBuildFileMap;
373 std::vector<std::string> Architectures;
374 std::string ObjectDirArchDefault;
375 std::string ObjectDirArch;
376 std::string SystemName;
377 std::string GeneratorToolset;
378 std::vector<std::string> EnabledLangs;
379 std::map<cmGeneratorTarget const*, std::set<cmSourceFile const*>>
381 std::map<cmSourceFile const*, std::set<cmGeneratorTarget const*>>