1 /*=========================================================================
3 Program: CMake - Cross-Platform Makefile Generator
4 Module: $RCSfile: cmGlobalXCodeGenerator.cxx,v $
6 Date: $Date: 2008-10-09 15:01:47 $
7 Version: $Revision: 1.203 $
9 Copyright (c) 2002 Kitware, Inc., Insight Consortium. All rights reserved.
10 See Copyright.txt or http://www.cmake.org/HTML/Copyright.html for details.
12 This software is distributed WITHOUT ANY WARRANTY; without even
13 the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
14 PURPOSE. See the above copyright notices for more information.
16 =========================================================================*/
17 #include "cmGlobalXCodeGenerator.h"
18 #include "cmGlobalXCode21Generator.h"
19 #include "cmLocalXCodeGenerator.h"
20 #include "cmMakefile.h"
21 #include "cmXCodeObject.h"
22 #include "cmXCode21Object.h"
24 #include "cmGeneratedFileStream.h"
25 #include "cmComputeLinkInformation.h"
26 #include "cmSourceFile.h"
28 //----------------------------------------------------------------------------
29 #if defined(CMAKE_BUILD_WITH_CMAKE)
30 #include "cmXMLParser.h"
32 // parse the xml file storing the installed version of Xcode on
34 class cmXcodeVersionParser
: public cmXMLParser
37 void StartElement(const char* , const char** )
41 void EndElement(const char* name
)
43 if(strcmp(name
, "key") == 0)
45 this->Key
= this->Data
;
47 else if(strcmp(name
, "string") == 0)
49 if(this->Key
== "CFBundleShortVersionString")
51 this->Version
= (int)(10.0 * atof(this->Data
.c_str()));
55 void CharacterDataHandler(const char* data
, int length
)
57 this->Data
.append(data
, length
);
65 //----------------------------------------------------------------------------
66 cmGlobalXCodeGenerator::cmGlobalXCodeGenerator()
68 this->FindMakeProgramFile
= "CMakeFindXCode.cmake";
70 this->MainGroupChildren
= 0;
71 this->SourcesGroupChildren
= 0;
72 this->ResourcesGroupChildren
= 0;
73 this->CurrentMakefile
= 0;
74 this->CurrentLocalGenerator
= 0;
75 this->XcodeVersion
= 15;
78 //----------------------------------------------------------------------------
79 cmGlobalGenerator
* cmGlobalXCodeGenerator::New()
81 #if defined(CMAKE_BUILD_WITH_CMAKE)
82 cmXcodeVersionParser parser
;
84 ("/Developer/Applications/Xcode.app/Contents/version.plist");
85 if(parser
.Version
== 15)
87 return new cmGlobalXCodeGenerator
;
89 else if (parser
.Version
== 20)
91 cmSystemTools::Message("Xcode 2.0 not really supported by cmake, "
92 "using Xcode 15 generator\n");
93 return new cmGlobalXCodeGenerator
;
95 cmGlobalXCodeGenerator
* ret
= new cmGlobalXCode21Generator
;
96 ret
->SetVersion(parser
.Version
);
99 std::cerr
<< "CMake should be built with cmake to use XCode, "
100 "default to Xcode 1.5\n";
101 return new cmGlobalXCodeGenerator
;
105 //----------------------------------------------------------------------------
106 void cmGlobalXCodeGenerator::EnableLanguage(std::vector
<std::string
>const&
108 cmMakefile
* mf
, bool optional
)
110 mf
->AddDefinition("XCODE","1");
111 if(this->XcodeVersion
== 15)
116 mf
->AddCacheDefinition(
117 "CMAKE_CONFIGURATION_TYPES",
118 "Debug;Release;MinSizeRel;RelWithDebInfo",
119 "Semicolon separated list of supported configuration types, "
120 "only supports Debug, Release, MinSizeRel, and RelWithDebInfo, "
121 "anything else will be ignored.",
122 cmCacheManager::STRING
);
124 mf
->AddDefinition("CMAKE_GENERATOR_CC", "gcc");
125 mf
->AddDefinition("CMAKE_GENERATOR_CXX", "g++");
126 mf
->AddDefinition("CMAKE_GENERATOR_NO_COMPILER_ENV", "1");
127 // initialize Architectures so it can be used by
128 // GetTargetObjectFileDirectories
129 this->cmGlobalGenerator::EnableLanguage(lang
, mf
, optional
);
130 const char* osxArch
=
131 mf
->GetDefinition("CMAKE_OSX_ARCHITECTURES");
132 const char* sysroot
=
133 mf
->GetDefinition("CMAKE_OSX_SYSROOT");
134 if(osxArch
&& sysroot
)
136 this->Architectures
.clear();
137 cmSystemTools::ExpandListArgument(std::string(osxArch
),
138 this->Architectures
);
142 //----------------------------------------------------------------------------
143 std::string cmGlobalXCodeGenerator
144 ::GenerateBuildCommand(const char* makeProgram
,
145 const char *projectName
,
146 const char* additionalOptions
,
147 const char *targetName
,
152 // Config is not used yet
155 // now build the test
156 if(makeProgram
== 0 || !strlen(makeProgram
))
158 cmSystemTools::Error(
159 "Generator cannot find the appropriate make command.");
162 std::string makeCommand
=
163 cmSystemTools::ConvertToOutputPath(makeProgram
);
164 std::string lowerCaseCommand
= makeCommand
;
165 cmSystemTools::LowerCase(lowerCaseCommand
);
167 makeCommand
+= " -project ";
168 makeCommand
+= projectName
;
169 makeCommand
+= ".xcode";
170 if(this->XcodeVersion
> 20)
172 makeCommand
+= "proj";
176 if ( targetName
&& strcmp(targetName
, "clean") == 0 )
179 targetName
= "ALL_BUILD";
183 makeCommand
+= " clean";
187 makeCommand
+= " build";
189 makeCommand
+= " -target ";
190 // if it is a null string for config don't use it
191 if(config
&& *config
== 0)
195 if (targetName
&& strlen(targetName
))
197 makeCommand
+= targetName
;
201 makeCommand
+= "ALL_BUILD";
203 if(this->XcodeVersion
== 15)
205 makeCommand
+= " -buildstyle Development ";
209 makeCommand
+= " -configuration ";
210 makeCommand
+= config
?config
:"Debug";
212 if ( additionalOptions
)
215 makeCommand
+= additionalOptions
;
220 //----------------------------------------------------------------------------
221 ///! Create a local generator appropriate to this Global Generator
222 cmLocalGenerator
*cmGlobalXCodeGenerator::CreateLocalGenerator()
224 cmLocalGenerator
*lg
= new cmLocalXCodeGenerator
;
225 lg
->SetGlobalGenerator(this);
229 //----------------------------------------------------------------------------
230 void cmGlobalXCodeGenerator::Generate()
232 std::map
<cmStdString
, std::vector
<cmLocalGenerator
*> >::iterator it
;
233 // make sure extra targets are added before calling
234 // the parent generate which will call trace depends
235 for(it
= this->ProjectMap
.begin(); it
!= this->ProjectMap
.end(); ++it
)
237 cmLocalGenerator
* root
= it
->second
[0];
238 this->SetGenerationRoot(root
);
239 // add ALL_BUILD, INSTALL, etc
240 this->AddExtraTargets(root
, it
->second
);
242 this->cmGlobalGenerator::Generate();
243 for(it
= this->ProjectMap
.begin(); it
!= this->ProjectMap
.end(); ++it
)
245 cmLocalGenerator
* root
= it
->second
[0];
246 this->SetGenerationRoot(root
);
247 // now create the project
248 this->OutputXCodeProject(root
, it
->second
);
252 //----------------------------------------------------------------------------
253 void cmGlobalXCodeGenerator::SetGenerationRoot(cmLocalGenerator
* root
)
255 this->CurrentProject
= root
->GetMakefile()->GetProjectName();
256 this->SetCurrentLocalGenerator(root
);
257 std::string outDir
= this->CurrentMakefile
->GetHomeOutputDirectory();
258 outDir
=cmSystemTools::CollapseFullPath(outDir
.c_str());
259 cmSystemTools::SplitPath(outDir
.c_str(),
260 this->ProjectOutputDirectoryComponents
);
262 this->CurrentXCodeHackMakefile
=
263 root
->GetMakefile()->GetCurrentOutputDirectory();
264 this->CurrentXCodeHackMakefile
+= "/CMakeScripts";
265 cmSystemTools::MakeDirectory(this->CurrentXCodeHackMakefile
.c_str());
266 this->CurrentXCodeHackMakefile
+= "/XCODE_DEPEND_HELPER.make";
269 //----------------------------------------------------------------------------
271 cmGlobalXCodeGenerator::AddExtraTargets(cmLocalGenerator
* root
,
272 std::vector
<cmLocalGenerator
*>& gens
)
274 cmMakefile
* mf
= root
->GetMakefile();
277 const char* no_working_directory
= 0;
278 std::vector
<std::string
> no_depends
;
279 mf
->AddUtilityCommand("ALL_BUILD", true, no_depends
,
280 no_working_directory
,
281 "echo", "Build all projects");
282 cmTarget
* allbuild
= mf
->FindTarget("ALL_BUILD");
284 // Refer to the main build configuration file for easy editing.
285 std::string listfile
= mf
->GetStartDirectory();
287 listfile
+= "CMakeLists.txt";
288 allbuild
->AddSource(listfile
.c_str());
290 // Add XCODE depend helper
291 std::string dir
= mf
->GetCurrentOutputDirectory();
292 cmCustomCommandLine makecommand
;
293 makecommand
.push_back("make");
294 makecommand
.push_back("-C");
295 makecommand
.push_back(dir
.c_str());
296 makecommand
.push_back("-f");
297 makecommand
.push_back(this->CurrentXCodeHackMakefile
.c_str());
298 if(this->XcodeVersion
> 20)
300 makecommand
.push_back("all.$(CONFIGURATION)");
302 cmCustomCommandLines commandLines
;
303 commandLines
.push_back(makecommand
);
304 // Add Re-Run CMake rules
305 this->CreateReRunCMakeFile(root
);
307 // now make the allbuild depend on all the non-utility targets
309 for(std::vector
<cmLocalGenerator
*>::iterator i
= gens
.begin();
310 i
!= gens
.end(); ++i
)
312 cmLocalGenerator
* lg
= *i
;
313 if(this->IsExcluded(root
, *i
))
317 cmTargets
& tgts
= lg
->GetMakefile()->GetTargets();
318 for(cmTargets::iterator l
= tgts
.begin(); l
!= tgts
.end(); l
++)
320 cmTarget
& target
= l
->second
;
321 // make all exe, shared libs and modules
322 // run the depend check makefile as a post build rule
323 // this will make sure that when the next target is built
324 // things are up-to-date
325 if((target
.GetType() == cmTarget::EXECUTABLE
||
326 target
.GetType() == cmTarget::STATIC_LIBRARY
||
327 target
.GetType() == cmTarget::SHARED_LIBRARY
||
328 target
.GetType() == cmTarget::MODULE_LIBRARY
))
330 lg
->GetMakefile()->AddCustomCommandToTarget(target
.GetName(),
333 cmTarget::POST_BUILD
,
334 "Depend check for xcode",
338 if(!target
.GetPropertyAsBool("EXCLUDE_FROM_ALL"))
340 allbuild
->AddUtility(target
.GetName());
343 // Refer to the build configuration file for easy editing.
344 listfile
= lg
->GetMakefile()->GetStartDirectory();
346 listfile
+= "CMakeLists.txt";
347 target
.AddSource(listfile
.c_str());
352 //----------------------------------------------------------------------------
353 void cmGlobalXCodeGenerator::CreateReRunCMakeFile(cmLocalGenerator
* root
)
355 cmMakefile
* mf
= root
->GetMakefile();
356 std::vector
<std::string
> lfiles
= mf
->GetListFiles();
358 std::sort(lfiles
.begin(), lfiles
.end(), std::less
<std::string
>());
359 std::vector
<std::string
>::iterator new_end
=
360 std::unique(lfiles
.begin(), lfiles
.end());
361 lfiles
.erase(new_end
, lfiles
.end());
362 std::string dir
= mf
->GetHomeOutputDirectory();
363 this->CurrentReRunCMakeMakefile
= dir
;
364 this->CurrentReRunCMakeMakefile
+= "/CMakeScripts";
365 cmSystemTools::MakeDirectory(this->CurrentReRunCMakeMakefile
.c_str());
366 this->CurrentReRunCMakeMakefile
+= "/ReRunCMake.make";
367 cmGeneratedFileStream makefileStream
368 (this->CurrentReRunCMakeMakefile
.c_str());
369 makefileStream
.SetCopyIfDifferent(true);
370 makefileStream
<< "# Generated by CMake, DO NOT EDIT\n";
371 makefileStream
<< cmake::GetCMakeFilesDirectoryPostSlash();
372 makefileStream
<< "cmake.check_cache: ";
373 for(std::vector
<std::string
>::const_iterator i
= lfiles
.begin();
374 i
!= lfiles
.end(); ++i
)
376 makefileStream
<< "\\\n" << this->ConvertToRelativeForMake(i
->c_str());
378 std::string cmake
= mf
->GetRequiredDefinition("CMAKE_COMMAND");
379 makefileStream
<< "\n\t" << this->ConvertToRelativeForMake(cmake
.c_str())
380 << " -H" << this->ConvertToRelativeForMake(
381 mf
->GetHomeDirectory())
382 << " -B" << this->ConvertToRelativeForMake(
383 mf
->GetHomeOutputDirectory()) << "\n";
386 //----------------------------------------------------------------------------
387 void cmGlobalXCodeGenerator::ClearXCodeObjects()
389 this->TargetDoneSet
.clear();
390 for(unsigned int i
= 0; i
< this->XCodeObjects
.size(); ++i
)
392 delete this->XCodeObjects
[i
];
394 this->XCodeObjects
.clear();
395 this->GroupMap
.clear();
396 this->GroupNameMap
.clear();
397 this->TargetGroup
.clear();
398 this->FileRefs
.clear();
401 //----------------------------------------------------------------------------
403 cmGlobalXCodeGenerator::CreateObject(cmXCodeObject::PBXType ptype
)
406 if(this->XcodeVersion
== 15)
408 obj
= new cmXCodeObject(ptype
, cmXCodeObject::OBJECT
);
412 obj
= new cmXCode21Object(ptype
, cmXCodeObject::OBJECT
);
414 this->XCodeObjects
.push_back(obj
);
418 //----------------------------------------------------------------------------
420 cmGlobalXCodeGenerator::CreateObject(cmXCodeObject::Type type
)
422 cmXCodeObject
* obj
= new cmXCodeObject(cmXCodeObject::None
, type
);
423 this->XCodeObjects
.push_back(obj
);
427 //----------------------------------------------------------------------------
429 cmGlobalXCodeGenerator::CreateString(const char* s
)
431 cmXCodeObject
* obj
= this->CreateObject(cmXCodeObject::STRING
);
436 //----------------------------------------------------------------------------
437 cmXCodeObject
* cmGlobalXCodeGenerator
438 ::CreateObjectReference(cmXCodeObject
* ref
)
440 cmXCodeObject
* obj
= this->CreateObject(cmXCodeObject::OBJECT_REF
);
445 //----------------------------------------------------------------------------
446 cmStdString
GetGroupMapKey(cmTarget
& cmtarget
, cmSourceFile
* sf
)
448 cmStdString
key(cmtarget
.GetName());
450 key
+= sf
->GetFullPath();
454 //----------------------------------------------------------------------------
456 cmGlobalXCodeGenerator::CreateXCodeSourceFile(cmLocalGenerator
* lg
,
460 // Add flags from target and source file properties.
462 if(cmtarget
.GetProperty("COMPILE_FLAGS"))
464 lg
->AppendFlags(flags
, cmtarget
.GetProperty("COMPILE_FLAGS"));
466 lg
->AppendFlags(flags
, sf
->GetProperty("COMPILE_FLAGS"));
468 // Add per-source definitions.
469 this->AppendDefines(flags
, sf
->GetProperty("COMPILE_DEFINITIONS"), true);
471 // Using a map and the full path guarantees that we will always get the same
472 // fileRef object for any given full path.
474 cmXCodeObject
* fileRef
= this->CreateXCodeFileReference(sf
, cmtarget
);
476 cmXCodeObject
* buildFile
= this->CreateObject(cmXCodeObject::PBXBuildFile
);
477 buildFile
->SetComment(fileRef
->GetComment());
478 buildFile
->AddAttribute("fileRef", this->CreateObjectReference(fileRef
));
480 cmXCodeObject
* settings
=
481 this->CreateObject(cmXCodeObject::ATTRIBUTE_GROUP
);
482 settings
->AddAttribute("COMPILER_FLAGS", this->CreateString(flags
.c_str()));
484 // Is this a resource file in this target? Add it to the resources group...
486 cmTarget::SourceFileFlags tsFlags
= cmtarget
.GetTargetSourceFileFlags(sf
);
487 bool isResource
= (tsFlags
.Type
== cmTarget::SourceFileTypeResource
);
489 // Is this a "private" or "public" framework header file?
490 // Set the ATTRIBUTES attribute appropriately...
492 if(cmtarget
.IsFrameworkOnApple())
494 if(tsFlags
.Type
== cmTarget::SourceFileTypePrivateHeader
)
496 cmXCodeObject
* attrs
= this->CreateObject(cmXCodeObject::OBJECT_LIST
);
497 attrs
->AddObject(this->CreateString("Private"));
498 settings
->AddAttribute("ATTRIBUTES", attrs
);
501 else if(tsFlags
.Type
== cmTarget::SourceFileTypePublicHeader
)
503 cmXCodeObject
* attrs
= this->CreateObject(cmXCodeObject::OBJECT_LIST
);
504 attrs
->AddObject(this->CreateString("Public"));
505 settings
->AddAttribute("ATTRIBUTES", attrs
);
510 // Add the fileRef to the top level Resources group/folder if it is not
513 if(isResource
&& this->ResourcesGroupChildren
&&
514 !this->ResourcesGroupChildren
->HasObject(fileRef
))
516 this->ResourcesGroupChildren
->AddObject(fileRef
);
519 buildFile
->AddAttribute("settings", settings
);
523 //----------------------------------------------------------------------------
525 cmGlobalXCodeGenerator::CreateXCodeFileReference(cmSourceFile
* sf
,
528 std::string fname
= sf
->GetFullPath();
529 cmXCodeObject
* fileRef
= this->FileRefs
[fname
];
532 fileRef
= this->CreateObject(cmXCodeObject::PBXFileReference
);
533 std::string comment
= fname
;
535 //std::string gname = group->GetObject("name")->GetString();
536 //comment += gname.substr(1, gname.size()-2);
537 fileRef
->SetComment(fname
.c_str());
538 this->FileRefs
[fname
] = fileRef
;
540 cmStdString key
= GetGroupMapKey(cmtarget
, sf
);
541 cmXCodeObject
* group
= this->GroupMap
[key
];
542 cmXCodeObject
* children
= group
->GetObject("children");
543 if (!children
->HasObject(fileRef
))
545 children
->AddObject(fileRef
);
547 fileRef
->AddAttribute("fileEncoding", this->CreateString("4"));
550 this->CurrentLocalGenerator
->GetSourceFileLanguage(*sf
);
551 std::string sourcecode
= "sourcecode";
552 std::string ext
= sf
->GetExtension();
553 ext
= cmSystemTools::LowerCase(ext
);
557 sourcecode
= "compiled.mach-o.objfile";
561 sourcecode
+= ".cpp.objcpp";
565 sourcecode
+= ".c.objc";
567 else if(ext
== "plist")
569 sourcecode
+= ".text.plist";
571 else if(ext
== "h" || ext
== "hxx" || ext
== "hpp")
573 const char* linkLanguage
= cmtarget
.GetLinkerLanguage(this);
574 if(linkLanguage
&& (std::string(linkLanguage
) == "CXX"))
576 sourcecode
+= ".cpp.h";
580 sourcecode
+= ".c.h";
583 else if(lang
&& strcmp(lang
, "CXX") == 0)
585 sourcecode
+= ".cpp.cpp";
587 else if(lang
&& strcmp(lang
, "C") == 0)
589 sourcecode
+= ".c.c";
591 else if(ext
== "txt")
593 sourcecode
+= ".text";
597 // // Already specialized above or we leave sourcecode == "sourcecode"
598 // // which is probably the most correct choice. Extensionless headers,
599 // // for example... Or file types unknown to Xcode that do not map to a
600 // // valid lastKnownFileType value.
603 fileRef
->AddAttribute("lastKnownFileType",
604 this->CreateString(sourcecode
.c_str()));
607 this->ConvertToRelativeForXCode(sf
->GetFullPath().c_str());
610 cmSystemTools::SplitProgramPath(sf
->GetFullPath().c_str(),
613 fileRef
->AddAttribute("name", this->CreateString(file
.c_str()));
614 fileRef
->AddAttribute("path", this->CreateString(path
.c_str()));
615 if(this->XcodeVersion
== 15)
617 fileRef
->AddAttribute("refType", this->CreateString("4"));
619 if(path
.size() > 1 && path
[0] == '.' && path
[1] == '.')
621 fileRef
->AddAttribute("sourceTree", this->CreateString("<group>"));
625 fileRef
->AddAttribute("sourceTree", this->CreateString("<absolute>"));
631 //----------------------------------------------------------------------------
632 bool cmGlobalXCodeGenerator::SpecialTargetEmitted(std::string
const& tname
)
634 if(tname
== "ALL_BUILD" || tname
== "XCODE_DEPEND_HELPER" ||
635 tname
== "install" || tname
== "package" || tname
== "RUN_TESTS" )
637 if(this->TargetDoneSet
.find(tname
) != this->TargetDoneSet
.end())
641 this->TargetDoneSet
.insert(tname
);
647 //----------------------------------------------------------------------------
648 void cmGlobalXCodeGenerator::SetCurrentLocalGenerator(cmLocalGenerator
* gen
)
650 this->CurrentLocalGenerator
= gen
;
651 this->CurrentMakefile
= gen
->GetMakefile();
653 cmSystemTools::CollapseFullPath(this->CurrentMakefile
->
654 GetCurrentOutputDirectory());
655 cmSystemTools::SplitPath(outdir
.c_str(),
656 this->CurrentOutputDirectoryComponents
);
658 // Select the current set of configuration types.
659 this->CurrentConfigurationTypes
.clear();
660 if(this->XcodeVersion
> 20)
662 if(const char* types
=
663 this->CurrentMakefile
->GetDefinition("CMAKE_CONFIGURATION_TYPES"))
665 cmSystemTools::ExpandListArgument(types
,
666 this->CurrentConfigurationTypes
);
669 if(this->CurrentConfigurationTypes
.empty())
671 if(const char* buildType
=
672 this->CurrentMakefile
->GetDefinition("CMAKE_BUILD_TYPE"))
674 this->CurrentConfigurationTypes
.push_back(buildType
);
678 this->CurrentConfigurationTypes
.push_back("");
683 //----------------------------------------------------------------------------
685 cmGlobalXCodeGenerator::CreateXCodeTargets(cmLocalGenerator
* gen
,
686 std::vector
<cmXCodeObject
*>&
689 this->SetCurrentLocalGenerator(gen
);
690 cmTargets
&tgts
= this->CurrentMakefile
->GetTargets();
691 for(cmTargets::iterator l
= tgts
.begin(); l
!= tgts
.end(); l
++)
693 cmTarget
& cmtarget
= l
->second
;
695 // make sure ALL_BUILD, INSTALL, etc are only done once
696 if(this->SpecialTargetEmitted(l
->first
.c_str()))
701 if(cmtarget
.GetType() == cmTarget::UTILITY
||
702 cmtarget
.GetType() == cmTarget::GLOBAL_TARGET
)
704 targets
.push_back(this->CreateUtilityTarget(cmtarget
));
708 // organize the sources
709 std::vector
<cmSourceFile
*> const &classes
= cmtarget
.GetSourceFiles();
710 std::vector
<cmXCodeObject
*> externalObjFiles
;
711 std::vector
<cmXCodeObject
*> headerFiles
;
712 std::vector
<cmXCodeObject
*> resourceFiles
;
713 std::vector
<cmXCodeObject
*> sourceFiles
;
714 for(std::vector
<cmSourceFile
*>::const_iterator i
= classes
.begin();
715 i
!= classes
.end(); ++i
)
718 this->CreateXCodeSourceFile(this->CurrentLocalGenerator
,
720 cmXCodeObject
* fr
= xsf
->GetObject("fileRef");
721 cmXCodeObject
* filetype
=
722 fr
->GetObject()->GetObject("lastKnownFileType");
724 cmTarget::SourceFileFlags tsFlags
=
725 cmtarget
.GetTargetSourceFileFlags(*i
);
727 if(strcmp(filetype
->GetString(), "compiled.mach-o.objfile") == 0)
729 externalObjFiles
.push_back(xsf
);
731 else if((*i
)->GetPropertyAsBool("HEADER_FILE_ONLY") ||
732 (tsFlags
.Type
== cmTarget::SourceFileTypePrivateHeader
) ||
733 (tsFlags
.Type
== cmTarget::SourceFileTypePublicHeader
))
735 headerFiles
.push_back(xsf
);
737 else if(tsFlags
.Type
== cmTarget::SourceFileTypeResource
)
739 resourceFiles
.push_back(xsf
);
743 // Include this file in the build if it has a known language
744 // and has not been listed as an ignored extension for this
746 if(this->CurrentLocalGenerator
->GetSourceFileLanguage(**i
) &&
747 !this->IgnoreFile((*i
)->GetExtension().c_str()))
749 sourceFiles
.push_back(xsf
);
754 // some build phases only apply to bundles and/or frameworks
755 bool isFrameworkTarget
= cmtarget
.IsFrameworkOnApple();
756 bool isBundleTarget
= cmtarget
.GetPropertyAsBool("MACOSX_BUNDLE");
758 cmXCodeObject
* buildFiles
= 0;
760 // create source build phase
761 cmXCodeObject
* sourceBuildPhase
= 0;
762 if (!sourceFiles
.empty())
765 this->CreateObject(cmXCodeObject::PBXSourcesBuildPhase
);
766 sourceBuildPhase
->SetComment("Sources");
767 sourceBuildPhase
->AddAttribute("buildActionMask",
768 this->CreateString("2147483647"));
769 buildFiles
= this->CreateObject(cmXCodeObject::OBJECT_LIST
);
770 for(std::vector
<cmXCodeObject
*>::iterator i
= sourceFiles
.begin();
771 i
!= sourceFiles
.end(); ++i
)
773 buildFiles
->AddObject(*i
);
775 sourceBuildPhase
->AddAttribute("files", buildFiles
);
776 sourceBuildPhase
->AddAttribute("runOnlyForDeploymentPostprocessing",
777 this->CreateString("0"));
780 // create header build phase - only for framework targets
781 cmXCodeObject
* headerBuildPhase
= 0;
782 if (!headerFiles
.empty() && isFrameworkTarget
)
785 this->CreateObject(cmXCodeObject::PBXHeadersBuildPhase
);
786 headerBuildPhase
->SetComment("Headers");
787 headerBuildPhase
->AddAttribute("buildActionMask",
788 this->CreateString("2147483647"));
789 buildFiles
= this->CreateObject(cmXCodeObject::OBJECT_LIST
);
790 for(std::vector
<cmXCodeObject
*>::iterator i
= headerFiles
.begin();
791 i
!= headerFiles
.end(); ++i
)
793 buildFiles
->AddObject(*i
);
795 headerBuildPhase
->AddAttribute("files", buildFiles
);
796 headerBuildPhase
->AddAttribute("runOnlyForDeploymentPostprocessing",
797 this->CreateString("0"));
800 // create resource build phase - only for framework or bundle targets
801 cmXCodeObject
* resourceBuildPhase
= 0;
802 if (!resourceFiles
.empty() && (isFrameworkTarget
|| isBundleTarget
))
805 this->CreateObject(cmXCodeObject::PBXResourcesBuildPhase
);
806 resourceBuildPhase
->SetComment("Resources");
807 resourceBuildPhase
->AddAttribute("buildActionMask",
808 this->CreateString("2147483647"));
809 buildFiles
= this->CreateObject(cmXCodeObject::OBJECT_LIST
);
810 for(std::vector
<cmXCodeObject
*>::iterator i
= resourceFiles
.begin();
811 i
!= resourceFiles
.end(); ++i
)
813 buildFiles
->AddObject(*i
);
815 resourceBuildPhase
->AddAttribute("files", buildFiles
);
816 resourceBuildPhase
->AddAttribute("runOnlyForDeploymentPostprocessing",
817 this->CreateString("0"));
820 // create vector of "non-resource content file" build phases - only for
821 // framework or bundle targets
822 std::vector
<cmXCodeObject
*> contentBuildPhases
;
823 if (isFrameworkTarget
|| isBundleTarget
)
825 typedef std::map
<cmStdString
, std::vector
<cmSourceFile
*> >
826 mapOfVectorOfSourceFiles
;
827 mapOfVectorOfSourceFiles bundleFiles
;
828 for(std::vector
<cmSourceFile
*>::const_iterator i
= classes
.begin();
829 i
!= classes
.end(); ++i
)
831 cmTarget::SourceFileFlags tsFlags
=
832 cmtarget
.GetTargetSourceFileFlags(*i
);
833 if(tsFlags
.Type
== cmTarget::SourceFileTypeMacContent
)
835 bundleFiles
[tsFlags
.MacFolder
].push_back(*i
);
838 mapOfVectorOfSourceFiles::iterator mit
;
839 for ( mit
= bundleFiles
.begin(); mit
!= bundleFiles
.end(); ++ mit
)
841 cmXCodeObject
* copyFilesBuildPhase
=
842 this->CreateObject(cmXCodeObject::PBXCopyFilesBuildPhase
);
843 copyFilesBuildPhase
->SetComment("Copy files");
844 copyFilesBuildPhase
->AddAttribute("buildActionMask",
845 this->CreateString("2147483647"));
846 copyFilesBuildPhase
->AddAttribute("dstSubfolderSpec",
847 this->CreateString("6"));
848 cmOStringStream ostr
;
849 if (cmtarget
.IsFrameworkOnApple())
851 // dstPath in frameworks is relative to Versions/<version>
854 else if ( mit
->first
!= "MacOS" )
856 // dstPath in bundles is relative to Contents/MacOS
857 ostr
<< "../" << mit
->first
.c_str();
859 copyFilesBuildPhase
->AddAttribute("dstPath",
860 this->CreateString(ostr
.str().c_str()));
861 copyFilesBuildPhase
->AddAttribute(
862 "runOnlyForDeploymentPostprocessing", this->CreateString("0"));
863 buildFiles
= this->CreateObject(cmXCodeObject::OBJECT_LIST
);
864 copyFilesBuildPhase
->AddAttribute("files", buildFiles
);
865 std::vector
<cmSourceFile
*>::iterator sfIt
;
866 for ( sfIt
= mit
->second
.begin(); sfIt
!= mit
->second
.end(); ++ sfIt
)
869 this->CreateXCodeSourceFile(this->CurrentLocalGenerator
,
871 buildFiles
->AddObject(xsf
);
873 contentBuildPhases
.push_back(copyFilesBuildPhase
);
877 // create framework build phase
878 cmXCodeObject
* frameworkBuildPhase
= 0;
879 if (!externalObjFiles
.empty())
881 frameworkBuildPhase
=
882 this->CreateObject(cmXCodeObject::PBXFrameworksBuildPhase
);
883 frameworkBuildPhase
->SetComment("Frameworks");
884 frameworkBuildPhase
->AddAttribute("buildActionMask",
885 this->CreateString("2147483647"));
886 buildFiles
= this->CreateObject(cmXCodeObject::OBJECT_LIST
);
887 frameworkBuildPhase
->AddAttribute("files", buildFiles
);
888 for(std::vector
<cmXCodeObject
*>::iterator i
= externalObjFiles
.begin();
889 i
!= externalObjFiles
.end(); ++i
)
891 buildFiles
->AddObject(*i
);
893 frameworkBuildPhase
->AddAttribute("runOnlyForDeploymentPostprocessing",
894 this->CreateString("0"));
897 // create list of build phases and create the XCode target
898 cmXCodeObject
* buildPhases
=
899 this->CreateObject(cmXCodeObject::OBJECT_LIST
);
901 this->CreateCustomCommands(buildPhases
, sourceBuildPhase
,
902 headerBuildPhase
, resourceBuildPhase
,
904 frameworkBuildPhase
, cmtarget
);
906 targets
.push_back(this->CreateXCodeTarget(cmtarget
, buildPhases
));
910 //----------------------------------------------------------------------------
912 cmGlobalXCodeGenerator::CreateBuildPhase(const char* name
,
915 const std::vector
<cmCustomCommand
>&
918 if(commands
.size() == 0 && strcmp(name
, "CMake ReRun") != 0)
922 cmXCodeObject
* buildPhase
=
923 this->CreateObject(cmXCodeObject::PBXShellScriptBuildPhase
);
924 buildPhase
->AddAttribute("buildActionMask",
925 this->CreateString("2147483647"));
926 cmXCodeObject
* buildFiles
= this->CreateObject(cmXCodeObject::OBJECT_LIST
);
927 buildPhase
->AddAttribute("files", buildFiles
);
928 buildPhase
->AddAttribute("name",
929 this->CreateString(name
));
930 buildPhase
->AddAttribute("runOnlyForDeploymentPostprocessing",
931 this->CreateString("0"));
932 buildPhase
->AddAttribute("shellPath",
933 this->CreateString("/bin/sh"));
934 this->AddCommandsToBuildPhase(buildPhase
, cmtarget
, commands
,
939 //----------------------------------------------------------------------------
940 void cmGlobalXCodeGenerator::CreateCustomCommands(cmXCodeObject
* buildPhases
,
947 std::vector
<cmXCodeObject
*>
953 std::vector
<cmCustomCommand
> const & prebuild
954 = cmtarget
.GetPreBuildCommands();
955 std::vector
<cmCustomCommand
> const & prelink
956 = cmtarget
.GetPreLinkCommands();
957 std::vector
<cmCustomCommand
> const & postbuild
958 = cmtarget
.GetPostBuildCommands();
959 std::vector
<cmSourceFile
*>const &classes
= cmtarget
.GetSourceFiles();
960 // add all the sources
961 std::vector
<cmCustomCommand
> commands
;
962 for(std::vector
<cmSourceFile
*>::const_iterator i
= classes
.begin();
963 i
!= classes
.end(); ++i
)
965 if((*i
)->GetCustomCommand())
967 commands
.push_back(*(*i
)->GetCustomCommand());
970 std::vector
<cmCustomCommand
> reruncom
;
971 cmXCodeObject
* cmakeReRunPhase
=
972 this->CreateBuildPhase("CMake ReRun", "cmakeReRunPhase",
974 buildPhases
->AddObject(cmakeReRunPhase
);
975 // create prebuild phase
976 cmXCodeObject
* cmakeRulesBuildPhase
=
977 this->CreateBuildPhase("CMake Rules",
978 "cmakeRulesBuildPhase",
980 // create prebuild phase
981 cmXCodeObject
* preBuildPhase
=
982 this->CreateBuildPhase("CMake PreBuild Rules", "preBuildCommands",
984 // create prelink phase
985 cmXCodeObject
* preLinkPhase
=
986 this->CreateBuildPhase("CMake PreLink Rules", "preLinkCommands",
988 // create postbuild phase
989 cmXCodeObject
* postBuildPhase
=
990 this->CreateBuildPhase("CMake PostBuild Rules", "postBuildPhase",
991 cmtarget
, postbuild
);
993 // The order here is the order they will be built in.
994 // The order "headers, resources, sources" mimics a native project generated
995 // from an xcode template...
999 buildPhases
->AddObject(preBuildPhase
);
1001 if(cmakeRulesBuildPhase
)
1003 buildPhases
->AddObject(cmakeRulesBuildPhase
);
1005 if(headerBuildPhase
)
1007 buildPhases
->AddObject(headerBuildPhase
);
1009 if(resourceBuildPhase
)
1011 buildPhases
->AddObject(resourceBuildPhase
);
1013 std::vector
<cmXCodeObject
*>::iterator cit
;
1014 for (cit
= contentBuildPhases
.begin(); cit
!= contentBuildPhases
.end();
1017 buildPhases
->AddObject(*cit
);
1019 if(sourceBuildPhase
)
1021 buildPhases
->AddObject(sourceBuildPhase
);
1025 buildPhases
->AddObject(preLinkPhase
);
1027 if(frameworkBuildPhase
)
1029 buildPhases
->AddObject(frameworkBuildPhase
);
1033 buildPhases
->AddObject(postBuildPhase
);
1037 //----------------------------------------------------------------------------
1038 std::string
cmGlobalXCodeGenerator::ExtractFlag(const char* flag
,
1041 std::string retFlag
;
1042 std::string::size_type pos
= flags
.find(flag
);
1043 if(pos
!= flags
.npos
&& (pos
==0 || flags
[pos
-1]==' '))
1045 while(pos
< flags
.size() && flags
[pos
] != ' ')
1047 retFlag
+= flags
[pos
];
1055 //----------------------------------------------------------------------------
1057 cmGlobalXCodeGenerator::AddCommandsToBuildPhase(cmXCodeObject
* buildphase
,
1059 std::vector
<cmCustomCommand
>
1063 if(strcmp(name
, "cmakeReRunPhase") == 0)
1065 std::string cdir
= this->CurrentMakefile
->GetHomeOutputDirectory();
1066 cdir
= this->ConvertToRelativeForMake(cdir
.c_str());
1067 std::string makecmd
= "make -C ";
1071 this->ConvertToRelativeForMake(this->CurrentReRunCMakeMakefile
.c_str());
1072 cmSystemTools::ReplaceString(makecmd
, "\\ ", "\\\\ ");
1073 buildphase
->AddAttribute("shellScript",
1074 this->CreateString(makecmd
.c_str()));
1078 // collect multiple outputs of custom commands into a set
1079 // which will be used for every configuration
1080 std::map
<cmStdString
, cmStdString
> multipleOutputPairs
;
1081 for(std::vector
<cmCustomCommand
>::const_iterator i
= commands
.begin();
1082 i
!= commands
.end(); ++i
)
1084 cmCustomCommand
const& cc
= *i
;
1085 if(!cc
.GetCommandLines().empty())
1087 const std::vector
<std::string
>& outputs
= cc
.GetOutputs();
1088 if(!outputs
.empty())
1090 // If there are more than one outputs treat the
1091 // first as the primary output and make the rest depend on it.
1092 std::vector
<std::string
>::const_iterator o
= outputs
.begin();
1093 std::string primaryOutput
= this->ConvertToRelativeForMake(o
->c_str());
1094 for(++o
; o
!= outputs
.end(); ++o
)
1096 std::string currentOutput
=this->ConvertToRelativeForMake(o
->c_str());
1097 multipleOutputPairs
[currentOutput
] = primaryOutput
;
1103 std::string dir
= this->CurrentMakefile
->GetCurrentOutputDirectory();
1104 dir
+= "/CMakeScripts";
1105 cmSystemTools::MakeDirectory(dir
.c_str());
1106 std::string makefile
= dir
;
1108 makefile
+= target
.GetName();
1111 makefile
+= ".make";
1113 for (std::vector
<std::string
>::const_iterator currentConfig
=
1114 this->CurrentConfigurationTypes
.begin();
1115 currentConfig
!=this->CurrentConfigurationTypes
.end();
1118 this->CreateCustomRulesMakefile(makefile
.c_str(),
1121 currentConfig
->c_str(),
1122 multipleOutputPairs
);
1125 std::string cdir
= this->CurrentMakefile
->GetCurrentOutputDirectory();
1126 cdir
= this->ConvertToRelativeForXCode(cdir
.c_str());
1127 std::string makecmd
= "make -C ";
1130 makecmd
+= this->ConvertToRelativeForMake(
1131 (makefile
+"$CONFIGURATION").c_str());
1132 if(!multipleOutputPairs
.empty())
1134 makecmd
+= " cmake_check_multiple_outputs";
1137 cmSystemTools::ReplaceString(makecmd
, "\\ ", "\\\\ ");
1138 buildphase
->AddAttribute("shellScript",
1139 this->CreateString(makecmd
.c_str()));
1142 //----------------------------------------------------------------------------
1143 void cmGlobalXCodeGenerator
1144 ::CreateCustomRulesMakefile(const char* makefileBasename
,
1146 std::vector
<cmCustomCommand
>
1148 const char* configName
,
1149 const std::map
<cmStdString
,
1150 cmStdString
>& multipleOutputPairs
1153 std::string makefileName
=makefileBasename
;
1154 makefileName
+=configName
;
1155 cmGeneratedFileStream
makefileStream(makefileName
.c_str());
1160 makefileStream
.SetCopyIfDifferent(true);
1161 makefileStream
<< "# Generated by CMake, DO NOT EDIT\n";
1162 makefileStream
<< "# Custom rules for " << target
.GetName() << "\n";
1164 // have all depend on all outputs
1165 makefileStream
<< "all: ";
1166 std::map
<const cmCustomCommand
*, cmStdString
> tname
;
1168 for(std::vector
<cmCustomCommand
>::const_iterator i
= commands
.begin();
1169 i
!= commands
.end(); ++i
)
1171 cmCustomCommand
const& cc
= *i
;
1172 if(!cc
.GetCommandLines().empty())
1174 const std::vector
<std::string
>& outputs
= cc
.GetOutputs();
1175 if(!outputs
.empty())
1177 for(std::vector
<std::string
>::const_iterator o
= outputs
.begin();
1178 o
!= outputs
.end(); ++o
)
1181 << "\\\n\t" << this->ConvertToRelativeForMake(o
->c_str());
1186 cmOStringStream str
;
1187 str
<< "_buildpart_" << count
++ ;
1188 tname
[&cc
] = std::string(target
.GetName()) + str
.str();
1189 makefileStream
<< "\\\n\t" << tname
[&cc
];
1193 makefileStream
<< "\n\n";
1194 for(std::vector
<cmCustomCommand
>::const_iterator i
= commands
.begin();
1195 i
!= commands
.end(); ++i
)
1197 cmCustomCommand
const& cc
= *i
;
1198 if(!cc
.GetCommandLines().empty())
1200 bool escapeOldStyle
= cc
.GetEscapeOldStyle();
1201 bool escapeAllowMakeVars
= cc
.GetEscapeAllowMakeVars();
1202 makefileStream
<< "\n";
1203 const std::vector
<std::string
>& outputs
= cc
.GetOutputs();
1204 if(!outputs
.empty())
1206 // There is at least one output, start the rule for it
1207 std::string primary_output
=
1208 this->ConvertToRelativeForMake(outputs
.begin()->c_str());
1209 makefileStream
<< primary_output
<< ": ";
1213 // There are no outputs. Use the generated force rule name.
1214 makefileStream
<< tname
[&cc
] << ": ";
1216 for(std::vector
<std::string
>::const_iterator d
=
1217 cc
.GetDepends().begin();
1218 d
!= cc
.GetDepends().end(); ++d
)
1221 this->CurrentLocalGenerator
->GetRealDependency(d
->c_str(),
1223 makefileStream
<< "\\\n" << this
1224 ->ConvertToRelativeForMake(dep
.c_str());
1226 makefileStream
<< "\n";
1228 if(const char* comment
= cc
.GetComment())
1230 std::string echo_cmd
= "echo ";
1231 echo_cmd
+= (this->CurrentLocalGenerator
->
1232 EscapeForShell(comment
, escapeAllowMakeVars
));
1233 makefileStream
<< "\t" << echo_cmd
.c_str() << "\n";
1236 // Add each command line to the set of commands.
1237 for(cmCustomCommandLines::const_iterator cl
=
1238 cc
.GetCommandLines().begin();
1239 cl
!= cc
.GetCommandLines().end(); ++cl
)
1241 // Build the command line in a single string.
1242 const cmCustomCommandLine
& commandLine
= *cl
;
1243 std::string cmd2
= this->CurrentLocalGenerator
1244 ->GetRealLocation(commandLine
[0].c_str(), configName
);
1246 cmSystemTools::ReplaceString(cmd2
, "/./", "/");
1247 cmd2
= this->ConvertToRelativeForMake(cmd2
.c_str());
1249 if(cc
.GetWorkingDirectory())
1252 cmd
+= this->ConvertToRelativeForMake(cc
.GetWorkingDirectory());
1256 for(unsigned int j
=1; j
< commandLine
.size(); ++j
)
1261 cmd
+= (this->CurrentLocalGenerator
1262 ->EscapeForShellOldStyle(commandLine
[j
].c_str()));
1266 cmd
+= (this->CurrentLocalGenerator
->
1267 EscapeForShell(commandLine
[j
].c_str(),
1268 escapeAllowMakeVars
));
1271 makefileStream
<< "\t" << cmd
.c_str() << "\n";
1276 // Add rules to deal with multiple outputs of custom commands.
1277 if(!multipleOutputPairs
.empty())
1280 "\n# Dependencies of multiple outputs to their primary outputs \n";
1282 for(std::map
<cmStdString
, cmStdString
>::const_iterator o
=
1283 multipleOutputPairs
.begin(); o
!= multipleOutputPairs
.end(); ++o
)
1285 makefileStream
<< o
->first
<< ": " << o
->second
<< "\n";
1290 "cmake_check_multiple_outputs:\n";
1291 for(std::map
<cmStdString
, cmStdString
>::const_iterator o
=
1292 multipleOutputPairs
.begin(); o
!= multipleOutputPairs
.end(); ++o
)
1294 makefileStream
<< "\t@if [ ! -f "
1295 << o
->first
<< " ]; then rm -f "
1296 << o
->second
<< "; fi\n";
1301 //----------------------------------------------------------------------------
1302 void cmGlobalXCodeGenerator::CreateBuildSettings(cmTarget
& target
,
1303 cmXCodeObject
* buildSettings
,
1304 std::string
& fileType
,
1305 std::string
& productType
,
1306 std::string
& productName
,
1307 const char* configName
)
1310 std::string defFlags
;
1311 bool shared
= ((target
.GetType() == cmTarget::SHARED_LIBRARY
) ||
1312 (target
.GetType() == cmTarget::MODULE_LIBRARY
));
1314 const char* lang
= target
.GetLinkerLanguage(this);
1318 // for c++ projects get the c flags as well
1319 if(strcmp(lang
, "CXX") == 0)
1321 this->CurrentLocalGenerator
->AddLanguageFlags(cflags
, "C", configName
);
1322 this->CurrentLocalGenerator
->AddSharedFlags(cflags
, lang
, shared
);
1325 // Add language-specific flags.
1326 this->CurrentLocalGenerator
->AddLanguageFlags(flags
, lang
, configName
);
1328 // Add shared-library flags if needed.
1329 this->CurrentLocalGenerator
->AddSharedFlags(flags
, lang
, shared
);
1333 this->CurrentLocalGenerator
->
1334 AppendFlags(defFlags
,
1335 this->CurrentMakefile
->GetDefineFlags());
1337 // Add preprocessor definitions for this target and configuration.
1339 if(this->XcodeVersion
> 15)
1341 this->AppendDefines(ppDefs
, "CMAKE_INTDIR=\"$(CONFIGURATION)\"");
1343 if(const char* exportMacro
= target
.GetExportMacro())
1345 // Add the export symbol definition for shared library objects.
1346 this->AppendDefines(ppDefs
, exportMacro
);
1349 (ppDefs
, this->CurrentMakefile
->GetProperty("COMPILE_DEFINITIONS"));
1350 this->AppendDefines(ppDefs
, target
.GetProperty("COMPILE_DEFINITIONS"));
1353 std::string defVarName
= "COMPILE_DEFINITIONS_";
1354 defVarName
+= cmSystemTools::UpperCase(configName
);
1356 (ppDefs
, this->CurrentMakefile
->GetProperty(defVarName
.c_str()));
1357 this->AppendDefines(ppDefs
, target
.GetProperty(defVarName
.c_str()));
1359 buildSettings
->AddAttribute
1360 ("GCC_PREPROCESSOR_DEFINITIONS", this->CreateString(ppDefs
.c_str()));
1362 std::string extraLinkOptions
;
1363 if(target
.GetType() == cmTarget::EXECUTABLE
)
1366 this->CurrentMakefile
->GetRequiredDefinition("CMAKE_EXE_LINKER_FLAGS");
1368 if(target
.GetType() == cmTarget::SHARED_LIBRARY
)
1370 extraLinkOptions
= this->CurrentMakefile
->
1371 GetRequiredDefinition("CMAKE_SHARED_LINKER_FLAGS");
1373 if(target
.GetType() == cmTarget::MODULE_LIBRARY
)
1375 extraLinkOptions
= this->CurrentMakefile
->
1376 GetRequiredDefinition("CMAKE_MODULE_LINKER_FLAGS");
1379 const char* targetLinkFlags
= target
.GetProperty("LINK_FLAGS");
1382 extraLinkOptions
+= " ";
1383 extraLinkOptions
+= targetLinkFlags
;
1386 // The product name is the full name of the target for this configuration.
1387 productName
= target
.GetFullName(configName
);
1389 // Get the product name components.
1390 std::string pnprefix
;
1392 std::string pnsuffix
;
1393 target
.GetFullNameComponents(pnprefix
, pnbase
, pnsuffix
, configName
);
1395 // Store the product name for all target types.
1396 buildSettings
->AddAttribute("PRODUCT_NAME",
1397 this->CreateString(pnbase
.c_str()));
1399 // Set attributes to specify the proper name for the target.
1400 if(target
.GetType() == cmTarget::STATIC_LIBRARY
||
1401 target
.GetType() == cmTarget::SHARED_LIBRARY
||
1402 target
.GetType() == cmTarget::MODULE_LIBRARY
||
1403 target
.GetType() == cmTarget::EXECUTABLE
)
1405 std::string pndir
= target
.GetDirectory();
1406 buildSettings
->AddAttribute("SYMROOT",
1407 this->CreateString(pndir
.c_str()));
1408 buildSettings
->AddAttribute("EXECUTABLE_PREFIX",
1409 this->CreateString(pnprefix
.c_str()));
1410 buildSettings
->AddAttribute("EXECUTABLE_SUFFIX",
1411 this->CreateString(pnsuffix
.c_str()));
1414 // Handle settings for each target type.
1415 switch(target
.GetType())
1417 case cmTarget::STATIC_LIBRARY
:
1419 fileType
= "archive.ar";
1420 productType
= "com.apple.product-type.library.static";
1422 buildSettings
->AddAttribute("LIBRARY_STYLE",
1423 this->CreateString("STATIC"));
1427 case cmTarget::MODULE_LIBRARY
:
1429 buildSettings
->AddAttribute("LIBRARY_STYLE",
1430 this->CreateString("BUNDLE"));
1431 if(this->XcodeVersion
>= 22)
1433 fileType
= "compiled.mach-o.executable";
1434 productType
= "com.apple.product-type.tool";
1436 buildSettings
->AddAttribute("MACH_O_TYPE",
1437 this->CreateString("mh_bundle"));
1438 buildSettings
->AddAttribute("GCC_DYNAMIC_NO_PIC",
1439 this->CreateString("NO"));
1440 // Add the flags to create an executable.
1441 std::string createFlags
=
1442 this->LookupFlags("CMAKE_", lang
, "_LINK_FLAGS", "");
1443 if(!createFlags
.empty())
1445 extraLinkOptions
+= " ";
1446 extraLinkOptions
+= createFlags
;
1451 fileType
= "compiled.mach-o.dylib";
1452 productType
= "com.apple.product-type.library.dynamic";
1454 // Add the flags to create a module.
1455 std::string createFlags
=
1456 this->LookupFlags("CMAKE_SHARED_MODULE_CREATE_", lang
, "_FLAGS",
1458 if(!createFlags
.empty())
1460 extraLinkOptions
+= " ";
1461 extraLinkOptions
+= createFlags
;
1466 case cmTarget::SHARED_LIBRARY
:
1468 if(target
.GetPropertyAsBool("FRAMEWORK"))
1470 fileType
= "wrapper.framework";
1471 productType
= "com.apple.product-type.framework";
1473 std::string version
= target
.GetFrameworkVersion();
1474 buildSettings
->AddAttribute("FRAMEWORK_VERSION",
1475 this->CreateString(version
.c_str()));
1477 std::string plist
= this->ComputeInfoPListLocation(target
);
1478 // Xcode will create the final version of Info.plist at build time,
1479 // so let it replace the framework name. This avoids creating
1480 // a per-configuration Info.plist file.
1481 this->CurrentLocalGenerator
1482 ->GenerateFrameworkInfoPList(&target
, "$(EXECUTABLE_NAME)",
1485 this->ConvertToRelativeForXCode(plist
.c_str());
1486 buildSettings
->AddAttribute("INFOPLIST_FILE",
1487 this->CreateString(path
.c_str()));
1491 fileType
= "compiled.mach-o.dylib";
1492 productType
= "com.apple.product-type.library.dynamic";
1494 // Add the flags to create a shared library.
1495 std::string createFlags
=
1496 this->LookupFlags("CMAKE_SHARED_LIBRARY_CREATE_", lang
, "_FLAGS",
1498 if(!createFlags
.empty())
1500 extraLinkOptions
+= " ";
1501 extraLinkOptions
+= createFlags
;
1505 buildSettings
->AddAttribute("LIBRARY_STYLE",
1506 this->CreateString("DYNAMIC"));
1509 case cmTarget::EXECUTABLE
:
1511 fileType
= "compiled.mach-o.executable";
1513 // Add the flags to create an executable.
1514 std::string createFlags
=
1515 this->LookupFlags("CMAKE_", lang
, "_LINK_FLAGS", "");
1516 if(!createFlags
.empty())
1518 extraLinkOptions
+= " ";
1519 extraLinkOptions
+= createFlags
;
1522 // Handle bundles and normal executables separately.
1523 if(target
.GetPropertyAsBool("MACOSX_BUNDLE"))
1525 productType
= "com.apple.product-type.application";
1526 std::string plist
= this->ComputeInfoPListLocation(target
);
1527 // Xcode will create the final version of Info.plist at build time,
1528 // so let it replace the executable name. This avoids creating
1529 // a per-configuration Info.plist file.
1530 this->CurrentLocalGenerator
1531 ->GenerateAppleInfoPList(&target
, "$(EXECUTABLE_NAME)",
1534 this->ConvertToRelativeForXCode(plist
.c_str());
1535 buildSettings
->AddAttribute("INFOPLIST_FILE",
1536 this->CreateString(path
.c_str()));
1541 productType
= "com.apple.product-type.tool";
1548 if(this->XcodeVersion
>= 22)
1550 buildSettings
->AddAttribute("PREBINDING",
1551 this->CreateString("NO"));
1554 std::vector
<std::string
> includes
;
1555 this->CurrentLocalGenerator
->GetIncludeDirectories(includes
);
1557 std::set
<cmStdString
> emitted
;
1558 emitted
.insert("/System/Library/Frameworks");
1559 for(std::vector
<std::string
>::iterator i
= includes
.begin();
1560 i
!= includes
.end(); ++i
)
1562 if(this->NameResolvesToFramework(i
->c_str()))
1564 std::string frameworkDir
= *i
;
1565 frameworkDir
+= "/../";
1566 frameworkDir
= cmSystemTools::CollapseFullPath(frameworkDir
.c_str());
1567 if(emitted
.insert(frameworkDir
).second
)
1569 fdirs
+= this->XCodeEscapePath(frameworkDir
.c_str());
1575 std::string incpath
=
1576 this->XCodeEscapePath(i
->c_str());
1577 dirs
+= incpath
+ " ";
1580 std::vector
<std::string
>& frameworks
= target
.GetFrameworks();
1581 if(frameworks
.size())
1583 for(std::vector
<std::string
>::iterator fmIt
= frameworks
.begin();
1584 fmIt
!= frameworks
.end(); ++fmIt
)
1586 if(emitted
.insert(*fmIt
).second
)
1588 fdirs
+= this->XCodeEscapePath(fmIt
->c_str());
1595 buildSettings
->AddAttribute("FRAMEWORK_SEARCH_PATHS",
1596 this->CreateString(fdirs
.c_str()));
1600 buildSettings
->AddAttribute("HEADER_SEARCH_PATHS",
1601 this->CreateString(dirs
.c_str()));
1603 std::string oflagc
= this->ExtractFlag("-O", cflags
);
1607 if(oflagc
.size() == 3)
1609 optLevel
[0] = oflagc
[2];
1611 if(oflagc
.size() == 2)
1615 std::string oflag
= this->ExtractFlag("-O", flags
);
1616 if(oflag
.size() == 3)
1618 optLevel
[0] = oflag
[2];
1620 if(oflag
.size() == 2)
1624 std::string gflagc
= this->ExtractFlag("-g", cflags
);
1625 // put back gdwarf-2 if used since there is no way
1626 // to represent it in the gui, but we still want debug yes
1627 if(gflagc
== "-gdwarf-2")
1632 std::string gflag
= this->ExtractFlag("-g", flags
);
1633 if(gflag
== "-gdwarf-2")
1638 const char* debugStr
= "YES";
1639 if(gflagc
.size() ==0 && gflag
.size() == 0)
1644 buildSettings
->AddAttribute("GCC_GENERATE_DEBUGGING_SYMBOLS",
1645 this->CreateString(debugStr
));
1646 buildSettings
->AddAttribute("GCC_OPTIMIZATION_LEVEL",
1647 this->CreateString(optLevel
));
1648 buildSettings
->AddAttribute("GCC_SYMBOLS_PRIVATE_EXTERN",
1649 this->CreateString("NO"));
1650 buildSettings
->AddAttribute("GCC_INLINES_ARE_PRIVATE_EXTERN",
1651 this->CreateString("NO"));
1652 if(lang
&& strcmp(lang
, "CXX") == 0)
1656 buildSettings
->AddAttribute("OTHER_CPLUSPLUSFLAGS",
1657 this->CreateString(flags
.c_str()));
1660 buildSettings
->AddAttribute("OTHER_CFLAGS",
1661 this->CreateString(cflags
.c_str()));
1668 buildSettings
->AddAttribute("OTHER_CFLAGS",
1669 this->CreateString(flags
.c_str()));
1672 // Create the INSTALL_PATH attribute.
1673 std::string install_name_dir
;
1674 if(target
.GetType() == cmTarget::SHARED_LIBRARY
)
1676 // Get the install_name directory for the build tree.
1677 install_name_dir
= target
.GetInstallNameDirForBuildTree(configName
, true);
1678 if(install_name_dir
.empty())
1680 // Xcode will not pass the -install_name option at all if INSTALL_PATH
1681 // is not given or is empty. We must explicitly put the flag in the
1682 // link flags to create an install_name with just the library soname.
1683 extraLinkOptions
+= " -install_name ";
1684 extraLinkOptions
+= productName
;
1688 // Convert to a path for the native build tool.
1689 cmSystemTools::ConvertToUnixSlashes(install_name_dir
);
1690 // do not escape spaces on this since it is only a single path
1693 buildSettings
->AddAttribute("INSTALL_PATH",
1694 this->CreateString(install_name_dir
.c_str()));
1696 buildSettings
->AddAttribute("OTHER_LDFLAGS",
1697 this->CreateString(extraLinkOptions
.c_str()));
1698 buildSettings
->AddAttribute("OTHER_REZFLAGS",
1699 this->CreateString(""));
1700 buildSettings
->AddAttribute("SECTORDER_FLAGS",
1701 this->CreateString(""));
1702 buildSettings
->AddAttribute("USE_HEADERMAP",
1703 this->CreateString("NO"));
1704 buildSettings
->AddAttribute("WARNING_CFLAGS",
1706 "-Wmost -Wno-four-char-constants"
1707 " -Wno-unknown-pragmas"));
1709 // Runtime version information.
1710 if(target
.GetType() == cmTarget::SHARED_LIBRARY
)
1716 // VERSION -> current_version
1717 target
.GetTargetVersion(false, major
, minor
, patch
);
1718 if(major
== 0 && minor
== 0 && patch
== 0)
1720 // Xcode always wants at least 1.0.0
1724 v
<< major
<< "." << minor
<< "." << patch
;
1725 buildSettings
->AddAttribute("DYLIB_CURRENT_VERSION",
1726 this->CreateString(v
.str().c_str()));
1728 // SOVERSION -> compatibility_version
1729 target
.GetTargetVersion(true, major
, minor
, patch
);
1730 if(major
== 0 && minor
== 0 && patch
== 0)
1732 // Xcode always wants at least 1.0.0
1735 cmOStringStream vso
;
1736 vso
<< major
<< "." << minor
<< "." << patch
;
1737 buildSettings
->AddAttribute("DYLIB_COMPATIBILITY_VERSION",
1738 this->CreateString(vso
.str().c_str()));
1740 // put this last so it can override existing settings
1741 // Convert "XCODE_ATTRIBUTE_*" properties directly.
1743 cmPropertyMap
const& props
= target
.GetProperties();
1744 for(cmPropertyMap::const_iterator i
= props
.begin();
1745 i
!= props
.end(); ++i
)
1747 if(i
->first
.find("XCODE_ATTRIBUTE_") == 0)
1749 buildSettings
->AddAttribute(i
->first
.substr(16).c_str(),
1750 this->CreateString(i
->second
.GetValue()));
1756 //----------------------------------------------------------------------------
1758 cmGlobalXCodeGenerator::CreateUtilityTarget(cmTarget
& cmtarget
)
1760 cmXCodeObject
* shellBuildPhase
=
1761 this->CreateObject(cmXCodeObject::PBXShellScriptBuildPhase
);
1762 shellBuildPhase
->AddAttribute("buildActionMask",
1763 this->CreateString("2147483647"));
1764 cmXCodeObject
* buildFiles
= this->CreateObject(cmXCodeObject::OBJECT_LIST
);
1765 shellBuildPhase
->AddAttribute("files", buildFiles
);
1766 cmXCodeObject
* inputPaths
= this->CreateObject(cmXCodeObject::OBJECT_LIST
);
1767 shellBuildPhase
->AddAttribute("inputPaths", inputPaths
);
1768 cmXCodeObject
* outputPaths
= this->CreateObject(cmXCodeObject::OBJECT_LIST
);
1769 shellBuildPhase
->AddAttribute("outputPaths", outputPaths
);
1770 shellBuildPhase
->AddAttribute("runOnlyForDeploymentPostprocessing",
1771 this->CreateString("0"));
1772 shellBuildPhase
->AddAttribute("shellPath",
1773 this->CreateString("/bin/sh"));
1774 shellBuildPhase
->AddAttribute("shellScript",
1776 "# shell script goes here\nexit 0"));
1777 cmXCodeObject
* target
=
1778 this->CreateObject(cmXCodeObject::PBXAggregateTarget
);
1779 target
->SetComment(cmtarget
.GetName());
1780 cmXCodeObject
* buildPhases
=
1781 this->CreateObject(cmXCodeObject::OBJECT_LIST
);
1782 std::vector
<cmXCodeObject
*> emptyContentVector
;
1783 this->CreateCustomCommands(buildPhases
, 0, 0, 0, emptyContentVector
, 0,
1785 target
->AddAttribute("buildPhases", buildPhases
);
1786 cmXCodeObject
* buildSettings
=
1787 this->CreateObject(cmXCodeObject::ATTRIBUTE_GROUP
);
1788 std::string fileTypeString
;
1789 std::string productTypeString
;
1790 std::string productName
;
1791 const char* globalConfig
= 0;
1792 if(this->XcodeVersion
> 20)
1794 this->AddConfigurations(target
, cmtarget
);
1798 globalConfig
= this->CurrentMakefile
->GetDefinition("CMAKE_BUILD_TYPE");
1800 this->CreateBuildSettings(cmtarget
,
1801 buildSettings
, fileTypeString
,
1802 productTypeString
, productName
, globalConfig
);
1803 target
->AddAttribute("buildSettings", buildSettings
);
1804 cmXCodeObject
* dependencies
=
1805 this->CreateObject(cmXCodeObject::OBJECT_LIST
);
1806 target
->AddAttribute("dependencies", dependencies
);
1807 target
->AddAttribute("name", this->CreateString(productName
.c_str()));
1808 target
->AddAttribute("productName",this->CreateString(productName
.c_str()));
1809 target
->SetTarget(&cmtarget
);
1811 // Add source files without build rules for editing convenience.
1812 if(cmtarget
.GetType() == cmTarget::UTILITY
)
1814 std::vector
<cmSourceFile
*> const& sources
= cmtarget
.GetSourceFiles();
1815 for(std::vector
<cmSourceFile
*>::const_iterator i
= sources
.begin();
1816 i
!= sources
.end(); ++i
)
1818 if(!(*i
)->GetPropertyAsBool("GENERATED"))
1820 this->CreateXCodeFileReference(*i
, cmtarget
);
1828 //----------------------------------------------------------------------------
1829 void cmGlobalXCodeGenerator::AddConfigurations(cmXCodeObject
* target
,
1832 std::string configTypes
=
1833 this->CurrentMakefile
->GetRequiredDefinition("CMAKE_CONFIGURATION_TYPES");
1834 std::vector
<std::string
> configVectorIn
;
1835 std::vector
<std::string
> configVector
;
1836 configVectorIn
.push_back(configTypes
);
1837 cmSystemTools::ExpandList(configVectorIn
, configVector
);
1838 cmXCodeObject
* configlist
=
1839 this->CreateObject(cmXCodeObject::XCConfigurationList
);
1840 cmXCodeObject
* buildConfigurations
=
1841 this->CreateObject(cmXCodeObject::OBJECT_LIST
);
1842 configlist
->AddAttribute("buildConfigurations", buildConfigurations
);
1843 std::string comment
= "Build configuration list for ";
1844 comment
+= cmXCodeObject::PBXTypeNames
[target
->GetIsA()];
1846 comment
+= cmtarget
.GetName();
1848 configlist
->SetComment(comment
.c_str());
1849 target
->AddAttribute("buildConfigurationList",
1850 this->CreateObjectReference(configlist
));
1851 for(unsigned int i
= 0; i
< configVector
.size(); ++i
)
1853 cmXCodeObject
* config
=
1854 this->CreateObject(cmXCodeObject::XCBuildConfiguration
);
1855 buildConfigurations
->AddObject(config
);
1856 cmXCodeObject
* buildSettings
=
1857 this->CreateObject(cmXCodeObject::ATTRIBUTE_GROUP
);
1858 std::string fileTypeString
;
1859 std::string productTypeString
;
1860 std::string productName
;
1861 this->CreateBuildSettings(cmtarget
,
1862 buildSettings
, fileTypeString
,
1863 productTypeString
, productName
,
1864 configVector
[i
].c_str());
1865 config
->AddAttribute("name", this->CreateString(configVector
[i
].c_str()));
1866 config
->SetComment(configVector
[i
].c_str());
1867 config
->AddAttribute("buildSettings", buildSettings
);
1869 if(configVector
.size())
1871 configlist
->AddAttribute("defaultConfigurationName",
1872 this->CreateString(configVector
[0].c_str()));
1873 configlist
->AddAttribute("defaultConfigurationIsVisible",
1874 this->CreateString("0"));
1878 //----------------------------------------------------------------------------
1880 cmGlobalXCodeGenerator::CreateXCodeTarget(cmTarget
& cmtarget
,
1881 cmXCodeObject
* buildPhases
)
1883 cmXCodeObject
* target
=
1884 this->CreateObject(cmXCodeObject::PBXNativeTarget
);
1885 target
->AddAttribute("buildPhases", buildPhases
);
1886 cmXCodeObject
* buildRules
= this->CreateObject(cmXCodeObject::OBJECT_LIST
);
1887 target
->AddAttribute("buildRules", buildRules
);
1888 cmXCodeObject
* buildSettings
=
1889 this->CreateObject(cmXCodeObject::ATTRIBUTE_GROUP
);
1890 std::string fileTypeString
;
1891 std::string productTypeString
;
1892 std::string productName
;
1893 const char* globalConfig
= 0;
1894 if(this->XcodeVersion
> 20)
1896 this->AddConfigurations(target
, cmtarget
);
1900 globalConfig
= this->CurrentMakefile
->GetDefinition("CMAKE_BUILD_TYPE");
1902 this->CreateBuildSettings(cmtarget
,
1903 buildSettings
, fileTypeString
,
1904 productTypeString
, productName
, globalConfig
);
1905 target
->AddAttribute("buildSettings", buildSettings
);
1906 cmXCodeObject
* dependencies
=
1907 this->CreateObject(cmXCodeObject::OBJECT_LIST
);
1908 target
->AddAttribute("dependencies", dependencies
);
1909 target
->AddAttribute("name", this->CreateString(productName
.c_str()));
1910 target
->AddAttribute("productName",this->CreateString(productName
.c_str()));
1912 cmXCodeObject
* fileRef
=
1913 this->CreateObject(cmXCodeObject::PBXFileReference
);
1914 fileRef
->AddAttribute("explicitFileType",
1915 this->CreateString(fileTypeString
.c_str()));
1916 fileRef
->AddAttribute("path", this->CreateString(productName
.c_str()));
1917 fileRef
->AddAttribute("refType", this->CreateString("0"));
1918 fileRef
->AddAttribute("sourceTree",
1919 this->CreateString("BUILT_PRODUCTS_DIR"));
1920 fileRef
->SetComment(cmtarget
.GetName());
1921 target
->AddAttribute("productReference",
1922 this->CreateObjectReference(fileRef
));
1923 target
->AddAttribute("productType",
1924 this->CreateString(productTypeString
.c_str()));
1925 target
->SetTarget(&cmtarget
);
1929 //----------------------------------------------------------------------------
1930 cmXCodeObject
* cmGlobalXCodeGenerator::FindXCodeTarget(cmTarget
* t
)
1936 for(std::vector
<cmXCodeObject
*>::iterator i
= this->XCodeObjects
.begin();
1937 i
!= this->XCodeObjects
.end(); ++i
)
1939 cmXCodeObject
* o
= *i
;
1940 if(o
->GetTarget() == t
)
1948 //----------------------------------------------------------------------------
1949 void cmGlobalXCodeGenerator::AddDependTarget(cmXCodeObject
* target
,
1950 cmXCodeObject
* dependTarget
)
1952 // make sure a target does not depend on itself
1953 if(target
== dependTarget
)
1957 // now avoid circular references if dependTarget already
1958 // depends on target then skip it. Circular references crashes
1960 cmXCodeObject
* dependTargetDepends
=
1961 dependTarget
->GetObject("dependencies");
1962 if(dependTargetDepends
)
1964 if(dependTargetDepends
->HasObject(target
->GetPBXTargetDependency()))
1970 cmXCodeObject
* targetdep
= dependTarget
->GetPBXTargetDependency();
1973 cmXCodeObject
* container
=
1974 this->CreateObject(cmXCodeObject::PBXContainerItemProxy
);
1975 container
->SetComment("PBXContainerItemProxy");
1976 container
->AddAttribute("containerPortal",
1977 this->CreateObjectReference(this->RootObject
));
1978 container
->AddAttribute("proxyType", this->CreateString("1"));
1979 container
->AddAttribute("remoteGlobalIDString",
1980 this->CreateObjectReference(dependTarget
));
1981 container
->AddAttribute("remoteInfo",
1983 dependTarget
->GetTarget()->GetName()));
1985 this->CreateObject(cmXCodeObject::PBXTargetDependency
);
1986 targetdep
->SetComment("PBXTargetDependency");
1987 targetdep
->AddAttribute("target",
1988 this->CreateObjectReference(dependTarget
));
1989 targetdep
->AddAttribute("targetProxy",
1990 this->CreateObjectReference(container
));
1991 dependTarget
->SetPBXTargetDependency(targetdep
);
1994 cmXCodeObject
* depends
= target
->GetObject("dependencies");
1998 Error("target does not have dependencies attribute error..");
2003 depends
->AddUniqueObject(targetdep
);
2007 //----------------------------------------------------------------------------
2008 void cmGlobalXCodeGenerator::AppendOrAddBuildSetting(cmXCodeObject
* settings
,
2009 const char* attribute
,
2014 cmXCodeObject
* attr
= settings
->GetObject(attribute
);
2017 settings
->AddAttribute(attribute
, this->CreateString(value
));
2021 std::string oldValue
= attr
->GetString();
2024 attr
->SetString(oldValue
.c_str());
2029 //----------------------------------------------------------------------------
2030 void cmGlobalXCodeGenerator
2031 ::AppendBuildSettingAttribute(cmXCodeObject
* target
,
2032 const char* attribute
,
2034 const char* configName
)
2036 if(this->XcodeVersion
< 21)
2038 // There is only one configuration. Add the setting to the buildSettings
2040 this->AppendOrAddBuildSetting(target
->GetObject("buildSettings"),
2045 // There are multiple configurations. Add the setting to the
2046 // buildSettings of the configuration name given.
2047 cmXCodeObject
* configurationList
=
2048 target
->GetObject("buildConfigurationList")->GetObject();
2049 cmXCodeObject
* buildConfigs
=
2050 configurationList
->GetObject("buildConfigurations");
2051 std::vector
<cmXCodeObject
*> list
= buildConfigs
->GetObjectList();
2052 // each configuration and the target itself has a buildSettings in it
2053 //list.push_back(target);
2054 for(std::vector
<cmXCodeObject
*>::iterator i
= list
.begin();
2055 i
!= list
.end(); ++i
)
2059 if(strcmp((*i
)->GetObject("name")->GetString(), configName
) == 0)
2061 cmXCodeObject
* settings
= (*i
)->GetObject("buildSettings");
2062 this->AppendOrAddBuildSetting(settings
, attribute
, value
);
2067 cmXCodeObject
* settings
= (*i
)->GetObject("buildSettings");
2068 this->AppendOrAddBuildSetting(settings
, attribute
, value
);
2074 //----------------------------------------------------------------------------
2075 void cmGlobalXCodeGenerator
2076 ::AddDependAndLinkInformation(cmXCodeObject
* target
)
2078 cmTarget
* cmtarget
= target
->GetTarget();
2081 cmSystemTools::Error("Error no target on xobject\n");
2085 // Add dependencies on other CMake targets.
2086 TargetDependSet
const& deps
= this->GetTargetDirectDepends(*cmtarget
);
2087 for(TargetDependSet::const_iterator i
= deps
.begin(); i
!= deps
.end(); ++i
)
2089 if(cmXCodeObject
* dptarget
= this->FindXCodeTarget(*i
))
2091 this->AddDependTarget(target
, dptarget
);
2095 // Skip link information for static libraries.
2096 if(cmtarget
->GetType() == cmTarget::STATIC_LIBRARY
)
2101 // Loop over configuration types and set per-configuration info.
2102 for(std::vector
<std::string
>::iterator i
=
2103 this->CurrentConfigurationTypes
.begin();
2104 i
!= this->CurrentConfigurationTypes
.end(); ++i
)
2106 // Get the current configuration name.
2107 const char* configName
= i
->c_str();
2113 // Compute the link library and directory information.
2114 cmComputeLinkInformation
* pcli
= cmtarget
->GetLinkInformation(configName
);
2119 cmComputeLinkInformation
& cli
= *pcli
;
2121 // Add dependencies directly on library files.
2123 std::vector
<std::string
> const& libDeps
= cli
.GetDepends();
2124 for(std::vector
<std::string
>::const_iterator j
= libDeps
.begin();
2125 j
!= libDeps
.end(); ++j
)
2127 target
->AddDependLibrary(configName
, j
->c_str());
2131 // add the library search paths
2133 std::vector
<std::string
> const& libDirs
= cli
.GetDirectories();
2134 std::string linkDirs
;
2135 for(std::vector
<std::string
>::const_iterator libDir
= libDirs
.begin();
2136 libDir
!= libDirs
.end(); ++libDir
)
2138 if(libDir
->size() && *libDir
!= "/usr/lib")
2140 if(this->XcodeVersion
> 15)
2142 // now add the same one but append $(CONFIGURATION) to it:
2144 linkDirs
+= this->XCodeEscapePath(
2145 (*libDir
+ "/$(CONFIGURATION)").c_str());
2148 linkDirs
+= this->XCodeEscapePath(libDir
->c_str());
2151 this->AppendBuildSettingAttribute(target
, "LIBRARY_SEARCH_PATHS",
2152 linkDirs
.c_str(), configName
);
2155 // add the framework search paths
2157 const char* sep
= "";
2159 std::vector
<std::string
> const& fwDirs
= cli
.GetFrameworkPaths();
2160 for(std::vector
<std::string
>::const_iterator fdi
= fwDirs
.begin();
2161 fdi
!= fwDirs
.end(); ++fdi
)
2165 fdirs
+= this->XCodeEscapePath(fdi
->c_str());
2169 this->AppendBuildSettingAttribute(target
, "FRAMEWORK_SEARCH_PATHS",
2170 fdirs
.c_str(), configName
);
2174 // now add the link libraries
2176 std::string linkLibs
;
2177 const char* sep
= "";
2178 typedef cmComputeLinkInformation::ItemVector ItemVector
;
2179 ItemVector
const& libNames
= cli
.GetItems();
2180 for(ItemVector::const_iterator li
= libNames
.begin();
2181 li
!= libNames
.end(); ++li
)
2187 linkLibs
+= this->XCodeEscapePath(li
->Value
.c_str());
2191 linkLibs
+= li
->Value
;
2194 this->AppendBuildSettingAttribute(target
, "OTHER_LDFLAGS",
2195 linkLibs
.c_str(), configName
);
2200 //----------------------------------------------------------------------------
2201 void cmGlobalXCodeGenerator::CreateGroups(cmLocalGenerator
* root
,
2202 std::vector
<cmLocalGenerator
*>&
2205 for(std::vector
<cmLocalGenerator
*>::iterator i
= generators
.begin();
2206 i
!= generators
.end(); ++i
)
2208 if(this->IsExcluded(root
, *i
))
2212 cmMakefile
* mf
= (*i
)->GetMakefile();
2213 std::vector
<cmSourceGroup
> sourceGroups
= mf
->GetSourceGroups();
2214 cmTargets
&tgts
= mf
->GetTargets();
2215 for(cmTargets::iterator l
= tgts
.begin(); l
!= tgts
.end(); l
++)
2217 cmTarget
& cmtarget
= l
->second
;
2219 // Same skipping logic here as in CreateXCodeTargets so that we do not
2220 // end up with (empty anyhow) ALL_BUILD and XCODE_DEPEND_HELPER source
2223 if(cmtarget
.GetType() == cmTarget::GLOBAL_TARGET
)
2228 // add the soon to be generated Info.plist file as a source for a
2229 // MACOSX_BUNDLE file
2230 if(cmtarget
.GetPropertyAsBool("MACOSX_BUNDLE"))
2232 std::string plist
= this->ComputeInfoPListLocation(cmtarget
);
2233 cmSourceFile
* sf
= mf
->GetOrCreateSource(plist
.c_str(), true);
2234 cmtarget
.AddSourceFile(sf
);
2237 std::vector
<cmSourceFile
*> classes
= cmtarget
.GetSourceFiles();
2239 for(std::vector
<cmSourceFile
*>::const_iterator s
= classes
.begin();
2240 s
!= classes
.end(); s
++)
2242 cmSourceFile
* sf
= *s
;
2243 // Add the file to the list of sources.
2244 std::string
const& source
= sf
->GetFullPath();
2245 cmSourceGroup
& sourceGroup
=
2246 mf
->FindSourceGroup(source
.c_str(), sourceGroups
);
2247 cmXCodeObject
* pbxgroup
=
2248 this->CreateOrGetPBXGroup(cmtarget
, &sourceGroup
);
2249 cmStdString key
= GetGroupMapKey(cmtarget
, sf
);
2250 this->GroupMap
[key
] = pbxgroup
;
2256 //----------------------------------------------------------------------------
2257 cmXCodeObject
* cmGlobalXCodeGenerator
2258 ::CreateOrGetPBXGroup(cmTarget
& cmtarget
, cmSourceGroup
* sg
)
2260 cmStdString s
= cmtarget
.GetName();
2263 std::map
<cmStdString
, cmXCodeObject
* >::iterator i
=
2264 this->GroupNameMap
.find(s
);
2265 if(i
!= this->GroupNameMap
.end())
2269 i
= this->TargetGroup
.find(cmtarget
.GetName());
2270 cmXCodeObject
* tgroup
= 0;
2271 if(i
!= this->TargetGroup
.end())
2277 tgroup
= this->CreateObject(cmXCodeObject::PBXGroup
);
2278 this->TargetGroup
[cmtarget
.GetName()] = tgroup
;
2279 cmXCodeObject
* tgroupChildren
=
2280 this->CreateObject(cmXCodeObject::OBJECT_LIST
);
2281 tgroup
->AddAttribute("name", this->CreateString(cmtarget
.GetName()));
2282 tgroup
->AddAttribute("children", tgroupChildren
);
2283 if(this->XcodeVersion
== 15)
2285 tgroup
->AddAttribute("refType", this->CreateString("4"));
2287 tgroup
->AddAttribute("sourceTree", this->CreateString("<group>"));
2288 this->SourcesGroupChildren
->AddObject(tgroup
);
2291 // If it's the default source group (empty name) then put the source file
2292 // directly in the tgroup...
2294 if (cmStdString(sg
->GetName()) == "")
2296 this->GroupNameMap
[s
] = tgroup
;
2300 cmXCodeObject
* tgroupChildren
= tgroup
->GetObject("children");
2301 cmXCodeObject
* group
= this->CreateObject(cmXCodeObject::PBXGroup
);
2302 cmXCodeObject
* groupChildren
=
2303 this->CreateObject(cmXCodeObject::OBJECT_LIST
);
2304 group
->AddAttribute("name", this->CreateString(sg
->GetName()));
2305 group
->AddAttribute("children", groupChildren
);
2306 if(this->XcodeVersion
== 15)
2308 group
->AddAttribute("refType", this->CreateString("4"));
2310 group
->AddAttribute("sourceTree", this->CreateString("<group>"));
2311 tgroupChildren
->AddObject(group
);
2312 this->GroupNameMap
[s
] = group
;
2316 //----------------------------------------------------------------------------
2317 void cmGlobalXCodeGenerator
2318 ::CreateXCodeObjects(cmLocalGenerator
* root
,
2319 std::vector
<cmLocalGenerator
*>&
2322 this->ClearXCodeObjects();
2323 this->RootObject
= 0;
2324 this->SourcesGroupChildren
= 0;
2325 this->ResourcesGroupChildren
= 0;
2326 this->MainGroupChildren
= 0;
2327 cmXCodeObject
* group
= this->CreateObject(cmXCodeObject::ATTRIBUTE_GROUP
);
2328 group
->AddAttribute("COPY_PHASE_STRIP", this->CreateString("NO"));
2329 cmXCodeObject
* developBuildStyle
=
2330 this->CreateObject(cmXCodeObject::PBXBuildStyle
);
2331 cmXCodeObject
* listObjs
= this->CreateObject(cmXCodeObject::OBJECT_LIST
);
2332 if(this->XcodeVersion
== 15)
2334 developBuildStyle
->AddAttribute("name",
2335 this->CreateString("Development"));
2336 developBuildStyle
->AddAttribute("buildSettings", group
);
2337 listObjs
->AddObject(developBuildStyle
);
2338 group
= this->CreateObject(cmXCodeObject::ATTRIBUTE_GROUP
);
2339 group
->AddAttribute("COPY_PHASE_STRIP", this->CreateString("YES"));
2340 cmXCodeObject
* deployBuildStyle
=
2341 this->CreateObject(cmXCodeObject::PBXBuildStyle
);
2342 deployBuildStyle
->AddAttribute("name", this->CreateString("Deployment"));
2343 deployBuildStyle
->AddAttribute("buildSettings", group
);
2344 listObjs
->AddObject(deployBuildStyle
);
2348 for(unsigned int i
= 0; i
< this->CurrentConfigurationTypes
.size(); ++i
)
2350 cmXCodeObject
* buildStyle
=
2351 this->CreateObject(cmXCodeObject::PBXBuildStyle
);
2352 const char* name
= this->CurrentConfigurationTypes
[i
].c_str();
2353 buildStyle
->AddAttribute("name", this->CreateString(name
));
2354 buildStyle
->SetComment(name
);
2355 cmXCodeObject
* sgroup
=
2356 this->CreateObject(cmXCodeObject::ATTRIBUTE_GROUP
);
2357 sgroup
->AddAttribute("COPY_PHASE_STRIP", this->CreateString("NO"));
2358 buildStyle
->AddAttribute("buildSettings", sgroup
);
2359 listObjs
->AddObject(buildStyle
);
2363 cmXCodeObject
* mainGroup
= this->CreateObject(cmXCodeObject::PBXGroup
);
2364 this->MainGroupChildren
=
2365 this->CreateObject(cmXCodeObject::OBJECT_LIST
);
2366 mainGroup
->AddAttribute("children", this->MainGroupChildren
);
2367 if(this->XcodeVersion
== 15)
2369 mainGroup
->AddAttribute("refType", this->CreateString("4"));
2371 mainGroup
->AddAttribute("sourceTree", this->CreateString("<group>"));
2373 cmXCodeObject
* sourcesGroup
= this->CreateObject(cmXCodeObject::PBXGroup
);
2374 this->SourcesGroupChildren
=
2375 this->CreateObject(cmXCodeObject::OBJECT_LIST
);
2376 sourcesGroup
->AddAttribute("name", this->CreateString("Sources"));
2377 sourcesGroup
->AddAttribute("children", this->SourcesGroupChildren
);
2378 if(this->XcodeVersion
== 15)
2380 sourcesGroup
->AddAttribute("refType", this->CreateString("4"));
2382 sourcesGroup
->AddAttribute("sourceTree", this->CreateString("<group>"));
2383 this->MainGroupChildren
->AddObject(sourcesGroup
);
2385 cmXCodeObject
* resourcesGroup
= this->CreateObject(cmXCodeObject::PBXGroup
);
2386 this->ResourcesGroupChildren
=
2387 this->CreateObject(cmXCodeObject::OBJECT_LIST
);
2388 resourcesGroup
->AddAttribute("name", this->CreateString("Resources"));
2389 resourcesGroup
->AddAttribute("children", this->ResourcesGroupChildren
);
2390 if(this->XcodeVersion
== 15)
2392 resourcesGroup
->AddAttribute("refType", this->CreateString("4"));
2394 resourcesGroup
->AddAttribute("sourceTree", this->CreateString("<group>"));
2395 this->MainGroupChildren
->AddObject(resourcesGroup
);
2397 // now create the cmake groups
2398 this->CreateGroups(root
, generators
);
2400 cmXCodeObject
* productGroup
= this->CreateObject(cmXCodeObject::PBXGroup
);
2401 productGroup
->AddAttribute("name", this->CreateString("Products"));
2402 if(this->XcodeVersion
== 15)
2404 productGroup
->AddAttribute("refType", this->CreateString("4"));
2406 productGroup
->AddAttribute("sourceTree", this->CreateString("<group>"));
2407 cmXCodeObject
* productGroupChildren
=
2408 this->CreateObject(cmXCodeObject::OBJECT_LIST
);
2409 productGroup
->AddAttribute("children", productGroupChildren
);
2410 this->MainGroupChildren
->AddObject(productGroup
);
2413 this->RootObject
= this->CreateObject(cmXCodeObject::PBXProject
);
2414 this->RootObject
->SetComment("Project object");
2415 group
= this->CreateObject(cmXCodeObject::ATTRIBUTE_GROUP
);
2416 this->RootObject
->AddAttribute("mainGroup",
2417 this->CreateObjectReference(mainGroup
));
2418 this->RootObject
->AddAttribute("buildSettings", group
);
2419 this->RootObject
->AddAttribute("buildStyles", listObjs
);
2420 this->RootObject
->AddAttribute("hasScannedForEncodings",
2421 this->CreateString("0"));
2422 // Point Xcode at the top of the source tree.
2424 std::string proot
= root
->GetMakefile()->GetCurrentDirectory();
2425 proot
= this->ConvertToRelativeForXCode(proot
.c_str());
2426 this->RootObject
->AddAttribute("projectRoot",
2427 this->CreateString(proot
.c_str()));
2429 cmXCodeObject
* configlist
=
2430 this->CreateObject(cmXCodeObject::XCConfigurationList
);
2431 cmXCodeObject
* buildConfigurations
=
2432 this->CreateObject(cmXCodeObject::OBJECT_LIST
);
2433 std::vector
<cmXCodeObject
*> configs
;
2434 if(this->XcodeVersion
== 15)
2436 cmXCodeObject
* configDebug
=
2437 this->CreateObject(cmXCodeObject::XCBuildConfiguration
);
2438 configDebug
->AddAttribute("name", this->CreateString("Debug"));
2439 configs
.push_back(configDebug
);
2440 cmXCodeObject
* configRelease
=
2441 this->CreateObject(cmXCodeObject::XCBuildConfiguration
);
2442 configRelease
->AddAttribute("name", this->CreateString("Release"));
2443 configs
.push_back(configRelease
);
2447 for(unsigned int i
= 0; i
< this->CurrentConfigurationTypes
.size(); ++i
)
2449 const char* name
= this->CurrentConfigurationTypes
[i
].c_str();
2450 cmXCodeObject
* config
=
2451 this->CreateObject(cmXCodeObject::XCBuildConfiguration
);
2452 config
->AddAttribute("name", this->CreateString(name
));
2453 configs
.push_back(config
);
2456 for(std::vector
<cmXCodeObject
*>::iterator c
= configs
.begin();
2457 c
!= configs
.end(); ++c
)
2459 buildConfigurations
->AddObject(*c
);
2461 configlist
->AddAttribute("buildConfigurations", buildConfigurations
);
2463 std::string comment
= "Build configuration list for PBXProject ";
2465 comment
+= this->CurrentProject
;
2467 configlist
->SetComment(comment
.c_str());
2468 configlist
->AddAttribute("defaultConfigurationIsVisible",
2469 this->CreateString("0"));
2470 configlist
->AddAttribute("defaultConfigurationName",
2471 this->CreateString("Debug"));
2472 cmXCodeObject
* buildSettings
=
2473 this->CreateObject(cmXCodeObject::ATTRIBUTE_GROUP
);
2474 const char* osxArch
=
2475 this->CurrentMakefile
->GetDefinition("CMAKE_OSX_ARCHITECTURES");
2476 const char* sysroot
=
2477 this->CurrentMakefile
->GetDefinition("CMAKE_OSX_SYSROOT");
2478 const char* sysrootDefault
=
2479 this->CurrentMakefile
->GetDefinition("CMAKE_OSX_SYSROOT_DEFAULT");
2480 if(osxArch
&& sysroot
)
2482 bool flagsUsed
= false;
2483 // recompute this as it may have been changed since enable language
2484 this->Architectures
.clear();
2485 cmSystemTools::ExpandListArgument(std::string(osxArch
),
2486 this->Architectures
);
2487 bool addArchFlag
= true;
2488 if(this->Architectures
.size() == 1)
2490 const char* archOrig
=
2492 CurrentMakefile
->GetSafeDefinition("CMAKE_OSX_ARCHITECTURES_DEFAULT");
2493 if(this->Architectures
[0] == archOrig
)
2495 addArchFlag
= false;
2501 buildSettings
->AddAttribute("SDKROOT",
2502 this->CreateString(sysroot
));
2503 std::string archString
;
2504 for( std::vector
<std::string
>::iterator i
=
2505 this->Architectures
.begin();
2506 i
!= this->Architectures
.end(); ++i
)
2511 buildSettings
->AddAttribute("ARCHS",
2512 this->CreateString(archString
.c_str()));
2514 if(!flagsUsed
&& sysrootDefault
&&
2515 strcmp(sysroot
, sysrootDefault
) != 0)
2517 buildSettings
->AddAttribute("SDKROOT",
2518 this->CreateString(sysroot
));
2521 for( std::vector
<cmXCodeObject
*>::iterator i
= configs
.begin();
2522 i
!= configs
.end(); ++i
)
2524 (*i
)->AddAttribute("buildSettings", buildSettings
);
2526 this->RootObject
->AddAttribute("buildConfigurationList",
2527 this->CreateObjectReference(configlist
));
2529 std::vector
<cmXCodeObject
*> targets
;
2530 for(std::vector
<cmLocalGenerator
*>::iterator i
= generators
.begin();
2531 i
!= generators
.end(); ++i
)
2533 if(!this->IsExcluded(root
, *i
))
2535 this->CreateXCodeTargets(*i
, targets
);
2538 // loop over all targets and add link and depend info
2539 for(std::vector
<cmXCodeObject
*>::iterator i
= targets
.begin();
2540 i
!= targets
.end(); ++i
)
2542 cmXCodeObject
* t
= *i
;
2543 this->AddDependAndLinkInformation(t
);
2545 // now create xcode depend hack makefile
2546 this->CreateXCodeDependHackTarget(targets
);
2547 // now add all targets to the root object
2548 cmXCodeObject
* allTargets
= this->CreateObject(cmXCodeObject::OBJECT_LIST
);
2549 for(std::vector
<cmXCodeObject
*>::iterator i
= targets
.begin();
2550 i
!= targets
.end(); ++i
)
2552 cmXCodeObject
* t
= *i
;
2553 allTargets
->AddObject(t
);
2554 cmXCodeObject
* productRef
= t
->GetObject("productReference");
2557 productGroupChildren
->AddObject(productRef
->GetObject());
2560 this->RootObject
->AddAttribute("targets", allTargets
);
2563 //----------------------------------------------------------------------------
2565 cmGlobalXCodeGenerator::CreateXCodeDependHackTarget(
2566 std::vector
<cmXCodeObject
*>& targets
)
2568 cmGeneratedFileStream
2569 makefileStream(this->CurrentXCodeHackMakefile
.c_str());
2572 cmSystemTools::Error("Could not create",
2573 this->CurrentXCodeHackMakefile
.c_str());
2576 makefileStream
.SetCopyIfDifferent(true);
2577 // one more pass for external depend information not handled
2578 // correctly by xcode
2579 makefileStream
<< "# DO NOT EDIT\n";
2580 makefileStream
<< "# This makefile makes sure all linkable targets are\n";
2581 makefileStream
<< "# up-to-date with anything they link to, avoiding a "
2582 "bug in XCode 1.5\n";
2583 for(std::vector
<std::string
>::const_iterator
2584 ct
= this->CurrentConfigurationTypes
.begin();
2585 ct
!= this->CurrentConfigurationTypes
.end(); ++ct
)
2587 if(this->XcodeVersion
< 21 || ct
->empty())
2589 makefileStream
<< "all: ";
2593 makefileStream
<< "all." << *ct
<< ": ";
2595 const char* configName
= 0;
2598 configName
= ct
->c_str();
2600 for(std::vector
<cmXCodeObject
*>::iterator i
= targets
.begin();
2601 i
!= targets
.end(); ++i
)
2603 cmXCodeObject
* target
= *i
;
2604 cmTarget
* t
=target
->GetTarget();
2605 if(t
->GetType() == cmTarget::EXECUTABLE
||
2606 t
->GetType() == cmTarget::SHARED_LIBRARY
||
2607 t
->GetType() == cmTarget::MODULE_LIBRARY
)
2609 std::string tfull
= t
->GetFullPath(configName
);
2610 if(t
->IsAppBundleOnApple())
2612 tfull
+= ".app/Contents/MacOS/";
2613 tfull
+= t
->GetFullName(configName
);
2615 makefileStream
<< "\\\n\t" <<
2616 this->ConvertToRelativeForMake(tfull
.c_str());
2619 makefileStream
<< "\n\n";
2622 << "# For each target create a dummy rule "
2623 "so the target does not have to exist\n";
2624 std::set
<cmStdString
> emitted
;
2625 for(std::vector
<cmXCodeObject
*>::iterator i
= targets
.begin();
2626 i
!= targets
.end(); ++i
)
2628 cmXCodeObject
* target
= *i
;
2629 std::map
<cmStdString
, cmXCodeObject::StringVec
> const& deplibs
=
2630 target
->GetDependLibraries();
2631 for(std::map
<cmStdString
, cmXCodeObject::StringVec
>::const_iterator ci
2632 = deplibs
.begin(); ci
!= deplibs
.end(); ++ci
)
2634 for(cmXCodeObject::StringVec::const_iterator d
= ci
->second
.begin();
2635 d
!= ci
->second
.end(); ++d
)
2637 if(emitted
.insert(*d
).second
)
2640 this->ConvertToRelativeForMake(d
->c_str()) << ":\n";
2645 makefileStream
<< "\n\n";
2647 // Write rules to help Xcode relink things at the right time.
2649 "# Rules to remove targets that are older than anything to which they\n"
2650 "# link. This forces Xcode to relink the targets from scratch. It\n"
2651 "# does not seem to check these dependencies itself.\n";
2652 for(std::vector
<std::string
>::const_iterator
2653 ct
= this->CurrentConfigurationTypes
.begin();
2654 ct
!= this->CurrentConfigurationTypes
.end(); ++ct
)
2656 const char* configName
= 0;
2659 configName
= ct
->c_str();
2661 for(std::vector
<cmXCodeObject
*>::iterator i
= targets
.begin();
2662 i
!= targets
.end(); ++i
)
2664 cmXCodeObject
* target
= *i
;
2665 cmTarget
* t
=target
->GetTarget();
2666 if(t
->GetType() == cmTarget::EXECUTABLE
||
2667 t
->GetType() == cmTarget::SHARED_LIBRARY
||
2668 t
->GetType() == cmTarget::MODULE_LIBRARY
)
2670 // Create a rule for this target.
2671 std::string tfull
= t
->GetFullPath(configName
);
2672 if(t
->IsAppBundleOnApple())
2674 tfull
+= ".app/Contents/MacOS/";
2675 tfull
+= t
->GetFullName(configName
);
2677 makefileStream
<< this->ConvertToRelativeForMake(tfull
.c_str())
2680 // List dependencies if any exist.
2681 std::map
<cmStdString
, cmXCodeObject::StringVec
>::const_iterator
2682 x
= target
->GetDependLibraries().find(*ct
);
2683 if(x
!= target
->GetDependLibraries().end())
2685 std::vector
<cmStdString
> const& deplibs
= x
->second
;
2686 for(std::vector
<cmStdString
>::const_iterator d
= deplibs
.begin();
2687 d
!= deplibs
.end(); ++d
)
2689 makefileStream
<< "\\\n\t" <<
2690 this->ConvertToRelativeForMake(d
->c_str());
2693 // Write the action to remove the target if it is out of date.
2694 makefileStream
<< "\n";
2695 makefileStream
<< "\t/bin/rm -f "
2696 << this->ConvertToRelativeForMake(tfull
.c_str())
2698 // if building for more than one architecture
2699 // then remove those exectuables as well
2700 if(this->Architectures
.size() > 1)
2702 std::string universal
= t
->GetDirectory();
2704 universal
+= this->CurrentMakefile
->GetProjectName();
2705 universal
+= ".build/";
2706 universal
+= configName
;
2708 universal
+= t
->GetName();
2709 universal
+= ".build/Objects-normal/";
2710 for( std::vector
<std::string
>::iterator arch
=
2711 this->Architectures
.begin();
2712 arch
!= this->Architectures
.end(); ++arch
)
2714 std::string universalFile
= universal
;
2715 universalFile
+= *arch
;
2716 universalFile
+= "/";
2717 universalFile
+= t
->GetName();
2718 makefileStream
<< "\t/bin/rm -f "
2720 this->ConvertToRelativeForMake(universalFile
.c_str())
2724 makefileStream
<< "\n\n";
2730 //----------------------------------------------------------------------------
2732 cmGlobalXCodeGenerator::OutputXCodeProject(cmLocalGenerator
* root
,
2733 std::vector
<cmLocalGenerator
*>&
2736 if(generators
.size() == 0)
2740 // Skip local generators that are excluded from this project.
2741 for(std::vector
<cmLocalGenerator
*>::iterator g
= generators
.begin();
2742 g
!= generators
.end(); ++g
)
2744 if(this->IsExcluded(root
, *g
))
2750 this->CreateXCodeObjects(root
,
2752 std::string xcodeDir
= root
->GetMakefile()->GetStartOutputDirectory();
2754 xcodeDir
+= root
->GetMakefile()->GetProjectName();
2755 xcodeDir
+= ".xcode";
2756 if(this->XcodeVersion
> 20)
2760 cmSystemTools::MakeDirectory(xcodeDir
.c_str());
2761 std::string xcodeProjFile
= xcodeDir
+ "/project.pbxproj";
2762 cmGeneratedFileStream
fout(xcodeProjFile
.c_str());
2763 fout
.SetCopyIfDifferent(true);
2768 this->WriteXCodePBXProj(fout
, root
, generators
);
2769 this->ClearXCodeObjects();
2772 //----------------------------------------------------------------------------
2774 cmGlobalXCodeGenerator::WriteXCodePBXProj(std::ostream
& fout
,
2776 std::vector
<cmLocalGenerator
*>& )
2778 fout
<< "// !$*UTF8*$!\n";
2780 cmXCodeObject::Indent(1, fout
);
2781 fout
<< "archiveVersion = 1;\n";
2782 cmXCodeObject::Indent(1, fout
);
2783 fout
<< "classes = {\n";
2784 cmXCodeObject::Indent(1, fout
);
2786 cmXCodeObject::Indent(1, fout
);
2787 fout
<< "objectVersion = 39;\n";
2788 cmXCodeObject::PrintList(this->XCodeObjects
, fout
);
2789 cmXCodeObject::Indent(1, fout
);
2790 fout
<< "rootObject = " << this->RootObject
->GetId() << ";\n";
2794 //----------------------------------------------------------------------------
2795 void cmGlobalXCodeGenerator::GetDocumentation(cmDocumentationEntry
& entry
)
2798 entry
.Name
= this->GetName();
2799 entry
.Brief
= "Generate XCode project files.";
2803 //----------------------------------------------------------------------------
2804 std::string
cmGlobalXCodeGenerator::ConvertToRelativeForMake(const char* p
)
2806 if ( !this->CurrentMakefile
->IsOn("CMAKE_USE_RELATIVE_PATHS") )
2808 return cmSystemTools::ConvertToOutputPath(p
);
2813 this->CurrentLocalGenerator
->
2814 ConvertToRelativePath(this->CurrentOutputDirectoryComponents
, p
);
2815 return cmSystemTools::ConvertToOutputPath(ret
.c_str());
2819 //----------------------------------------------------------------------------
2820 std::string
cmGlobalXCodeGenerator::ConvertToRelativeForXCode(const char* p
)
2822 if ( !this->CurrentMakefile
->IsOn("CMAKE_USE_RELATIVE_PATHS") )
2824 return cmSystemTools::ConvertToOutputPath(p
);
2829 this->CurrentLocalGenerator
->
2830 ConvertToRelativePath(this->ProjectOutputDirectoryComponents
, p
);
2831 return cmSystemTools::ConvertToOutputPath(ret
.c_str());
2835 //----------------------------------------------------------------------------
2836 std::string
cmGlobalXCodeGenerator::XCodeEscapePath(const char* p
)
2838 std::string ret
= p
;
2839 if(ret
.find(' ') != ret
.npos
)
2841 std::string t
= ret
;
2849 //----------------------------------------------------------------------------
2850 void cmGlobalXCodeGenerator::
2851 GetTargetObjectFileDirectories(cmTarget
* target
,
2852 std::vector
<std::string
>&
2855 std::string dir
= this->CurrentMakefile
->GetCurrentOutputDirectory();
2857 dir
+= this->CurrentMakefile
->GetProjectName();
2859 dir
+= this->GetCMakeCFGInitDirectory();
2861 if(target
->GetType() != cmTarget::EXECUTABLE
)
2865 dir
+= target
->GetName();
2866 if(target
->GetType() == cmTarget::STATIC_LIBRARY
)
2870 if(target
->GetType() == cmTarget::SHARED_LIBRARY
)
2874 if(target
->GetType() == cmTarget::MODULE_LIBRARY
)
2878 dir
+= ".build/Objects-normal/";
2879 std::string dirsave
= dir
;
2880 if(this->Architectures
.size())
2882 for(std::vector
<std::string
>::iterator i
= this->Architectures
.begin();
2883 i
!= this->Architectures
.end(); ++i
)
2886 dirs
.push_back(dir
);
2892 dirs
.push_back(dir
);
2896 //----------------------------------------------------------------------------
2898 cmGlobalXCodeGenerator
2899 ::AppendDirectoryForConfig(const char* prefix
,
2904 if(this->XcodeVersion
> 20)
2915 //----------------------------------------------------------------------------
2916 std::string
cmGlobalXCodeGenerator::LookupFlags(const char* varNamePrefix
,
2917 const char* varNameLang
,
2918 const char* varNameSuffix
,
2919 const char* default_flags
)
2923 std::string varName
= varNamePrefix
;
2924 varName
+= varNameLang
;
2925 varName
+= varNameSuffix
;
2926 if(const char* varValue
=
2927 this->CurrentMakefile
->GetDefinition(varName
.c_str()))
2935 return default_flags
;
2938 //----------------------------------------------------------------------------
2939 void cmGlobalXCodeGenerator::AppendDefines(std::string
& defs
,
2940 const char* defines_list
,
2943 // Skip this if there are no definitions.
2949 // Expand the list of definitions.
2950 std::vector
<std::string
> defines
;
2951 cmSystemTools::ExpandListArgument(defines_list
, defines
);
2953 // GCC_PREPROCESSOR_DEFINITIONS is a space-separated list of definitions.
2954 // We escape everything as follows:
2955 // - Place each definition in single quotes ''
2956 // - Escape a single quote as \\'
2957 // - Escape a backslash as \\\\ since it itself is an escape
2958 // Note that in the code below we need one more level of escapes for
2959 // C string syntax in this source file.
2960 const char* sep
= defs
.empty()? "" : " ";
2961 for(std::vector
<std::string
>::const_iterator di
= defines
.begin();
2962 di
!= defines
.end(); ++di
)
2964 // Separate from previous definition.
2968 // Open single quote.
2971 // Add -D flag if requested.
2977 // Escaped definition string.
2978 for(const char* c
= di
->c_str(); *c
; ++c
)
2994 // Close single quote.
2999 //----------------------------------------------------------------------------
3001 cmGlobalXCodeGenerator::ComputeInfoPListLocation(cmTarget
& target
)
3003 std::string plist
= target
.GetMakefile()->GetCurrentOutputDirectory();
3004 plist
+= cmake::GetCMakeFilesDirectory();
3006 plist
+= target
.GetName();
3007 plist
+= ".dir/Info.plist";