1 /*=========================================================================
3 Program: CMake - Cross-Platform Makefile Generator
4 Module: $RCSfile: cmGlobalXCodeGenerator.cxx,v $
6 Date: $Date: 2009-09-22 20:18:30 $
7 Version: $Revision: 1.230 $
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 "cmLocalXCodeGenerator.h"
19 #include "cmMakefile.h"
20 #include "cmXCodeObject.h"
21 #include "cmXCode21Object.h"
23 #include "cmGeneratedFileStream.h"
24 #include "cmComputeLinkInformation.h"
25 #include "cmSourceFile.h"
27 #include <cmsys/auto_ptr.hxx>
29 //----------------------------------------------------------------------------
30 #if defined(CMAKE_BUILD_WITH_CMAKE)
31 #include "cmXMLParser.h"
33 // parse the xml file storing the installed version of Xcode on
35 class cmXcodeVersionParser
: public cmXMLParser
38 void StartElement(const char* , const char** )
42 void EndElement(const char* name
)
44 if(strcmp(name
, "key") == 0)
46 this->Key
= this->Data
;
48 else if(strcmp(name
, "string") == 0)
50 if(this->Key
== "CFBundleShortVersionString")
52 this->Version
= (int)(10.0 * atof(this->Data
.c_str()));
56 void CharacterDataHandler(const char* data
, int length
)
58 this->Data
.append(data
, length
);
66 // Builds either an object list or a space-separated string from the
68 class cmGlobalXCodeGenerator::BuildObjectListOrString
70 cmGlobalXCodeGenerator
*Generator
;
76 BuildObjectListOrString(cmGlobalXCodeGenerator
*gen
, bool buildObjectList
)
77 : Generator(gen
), Group(0), Empty(true)
81 this->Group
= this->Generator
->CreateObject(cmXCodeObject::OBJECT_LIST
);
85 bool IsEmpty() const { return this->Empty
; }
87 void Add(const char *newString
)
93 this->Group
->AddObject(this->Generator
->CreateString(newString
));
97 this->String
+= newString
;
102 const std::string
&GetString() const { return this->String
; }
104 cmXCodeObject
*CreateList()
112 return this->Generator
->CreateString(this->String
.c_str());
117 //----------------------------------------------------------------------------
118 cmGlobalXCodeGenerator::cmGlobalXCodeGenerator()
120 this->FindMakeProgramFile
= "CMakeFindXCode.cmake";
121 this->RootObject
= 0;
122 this->MainGroupChildren
= 0;
123 this->SourcesGroupChildren
= 0;
124 this->ResourcesGroupChildren
= 0;
125 this->CurrentMakefile
= 0;
126 this->CurrentLocalGenerator
= 0;
127 this->XcodeVersion
= 15;
130 //----------------------------------------------------------------------------
131 cmGlobalGenerator
* cmGlobalXCodeGenerator::New()
133 #if defined(CMAKE_BUILD_WITH_CMAKE)
134 cmXcodeVersionParser parser
;
136 ("/Developer/Applications/Xcode.app/Contents/version.plist");
137 cmsys::auto_ptr
<cmGlobalXCodeGenerator
> gg(new cmGlobalXCodeGenerator
);
138 if (parser
.Version
== 20)
140 cmSystemTools::Message("Xcode 2.0 not really supported by cmake, "
141 "using Xcode 15 generator\n");
143 gg
->SetVersion(parser
.Version
);
146 std::cerr
<< "CMake should be built with cmake to use XCode, "
147 "default to Xcode 1.5\n";
148 return new cmGlobalXCodeGenerator
;
152 //----------------------------------------------------------------------------
153 void cmGlobalXCodeGenerator::EnableLanguage(std::vector
<std::string
>const&
155 cmMakefile
* mf
, bool optional
)
157 mf
->AddDefinition("XCODE","1");
158 if(this->XcodeVersion
== 15)
163 mf
->AddCacheDefinition(
164 "CMAKE_CONFIGURATION_TYPES",
165 "Debug;Release;MinSizeRel;RelWithDebInfo",
166 "Semicolon separated list of supported configuration types, "
167 "only supports Debug, Release, MinSizeRel, and RelWithDebInfo, "
168 "anything else will be ignored.",
169 cmCacheManager::STRING
);
171 mf
->AddDefinition("CMAKE_GENERATOR_CC", "gcc");
172 mf
->AddDefinition("CMAKE_GENERATOR_CXX", "g++");
173 mf
->AddDefinition("CMAKE_GENERATOR_NO_COMPILER_ENV", "1");
174 // initialize Architectures so it can be used by
175 // GetTargetObjectFileDirectories
176 this->cmGlobalGenerator::EnableLanguage(lang
, mf
, optional
);
177 const char* osxArch
=
178 mf
->GetDefinition("CMAKE_OSX_ARCHITECTURES");
179 const char* sysroot
=
180 mf
->GetDefinition("CMAKE_OSX_SYSROOT");
181 if(osxArch
&& sysroot
)
183 this->Architectures
.clear();
184 cmSystemTools::ExpandListArgument(std::string(osxArch
),
185 this->Architectures
);
189 //----------------------------------------------------------------------------
190 std::string cmGlobalXCodeGenerator
191 ::GenerateBuildCommand(const char* makeProgram
,
192 const char *projectName
,
193 const char* additionalOptions
,
194 const char *targetName
,
199 // Config is not used yet
202 // now build the test
203 if(makeProgram
== 0 || !strlen(makeProgram
))
205 cmSystemTools::Error(
206 "Generator cannot find the appropriate make command.");
209 std::string makeCommand
=
210 cmSystemTools::ConvertToOutputPath(makeProgram
);
211 std::string lowerCaseCommand
= makeCommand
;
212 cmSystemTools::LowerCase(lowerCaseCommand
);
214 makeCommand
+= " -project ";
215 makeCommand
+= projectName
;
216 makeCommand
+= ".xcode";
217 if(this->XcodeVersion
> 20)
219 makeCommand
+= "proj";
223 if ( targetName
&& strcmp(targetName
, "clean") == 0 )
226 targetName
= "ALL_BUILD";
230 makeCommand
+= " clean";
234 makeCommand
+= " build";
236 makeCommand
+= " -target ";
237 // if it is a null string for config don't use it
238 if(config
&& *config
== 0)
242 if (targetName
&& strlen(targetName
))
244 makeCommand
+= targetName
;
248 makeCommand
+= "ALL_BUILD";
250 if(this->XcodeVersion
== 15)
252 makeCommand
+= " -buildstyle Development ";
256 makeCommand
+= " -configuration ";
257 makeCommand
+= config
?config
:"Debug";
259 if ( additionalOptions
)
262 makeCommand
+= additionalOptions
;
267 //----------------------------------------------------------------------------
268 ///! Create a local generator appropriate to this Global Generator
269 cmLocalGenerator
*cmGlobalXCodeGenerator::CreateLocalGenerator()
271 cmLocalGenerator
*lg
= new cmLocalXCodeGenerator
;
272 lg
->SetGlobalGenerator(this);
276 //----------------------------------------------------------------------------
277 void cmGlobalXCodeGenerator::Generate()
279 std::map
<cmStdString
, std::vector
<cmLocalGenerator
*> >::iterator it
;
280 // make sure extra targets are added before calling
281 // the parent generate which will call trace depends
282 for(it
= this->ProjectMap
.begin(); it
!= this->ProjectMap
.end(); ++it
)
284 cmLocalGenerator
* root
= it
->second
[0];
285 this->SetGenerationRoot(root
);
286 // add ALL_BUILD, INSTALL, etc
287 this->AddExtraTargets(root
, it
->second
);
289 this->ForceLinkerLanguages();
290 this->cmGlobalGenerator::Generate();
291 for(it
= this->ProjectMap
.begin(); it
!= this->ProjectMap
.end(); ++it
)
293 cmLocalGenerator
* root
= it
->second
[0];
294 this->SetGenerationRoot(root
);
295 // now create the project
296 this->OutputXCodeProject(root
, it
->second
);
300 //----------------------------------------------------------------------------
301 void cmGlobalXCodeGenerator::SetGenerationRoot(cmLocalGenerator
* root
)
303 this->CurrentProject
= root
->GetMakefile()->GetProjectName();
304 this->SetCurrentLocalGenerator(root
);
305 cmSystemTools::SplitPath(this->CurrentMakefile
->GetCurrentDirectory(),
306 this->ProjectSourceDirectoryComponents
);
307 cmSystemTools::SplitPath(this->CurrentMakefile
->GetCurrentOutputDirectory(),
308 this->ProjectOutputDirectoryComponents
);
310 this->CurrentXCodeHackMakefile
=
311 root
->GetMakefile()->GetCurrentOutputDirectory();
312 this->CurrentXCodeHackMakefile
+= "/CMakeScripts";
313 cmSystemTools::MakeDirectory(this->CurrentXCodeHackMakefile
.c_str());
314 this->CurrentXCodeHackMakefile
+= "/XCODE_DEPEND_HELPER.make";
317 //----------------------------------------------------------------------------
319 cmGlobalXCodeGenerator::AddExtraTargets(cmLocalGenerator
* root
,
320 std::vector
<cmLocalGenerator
*>& gens
)
322 cmMakefile
* mf
= root
->GetMakefile();
325 const char* no_working_directory
= 0;
326 std::vector
<std::string
> no_depends
;
327 mf
->AddUtilityCommand("ALL_BUILD", true, no_depends
,
328 no_working_directory
,
329 "echo", "Build all projects");
330 cmTarget
* allbuild
= mf
->FindTarget("ALL_BUILD");
332 // Refer to the main build configuration file for easy editing.
333 std::string listfile
= mf
->GetStartDirectory();
335 listfile
+= "CMakeLists.txt";
336 allbuild
->AddSource(listfile
.c_str());
338 // Add XCODE depend helper
339 std::string dir
= mf
->GetCurrentOutputDirectory();
340 cmCustomCommandLine makecommand
;
341 makecommand
.push_back("make");
342 makecommand
.push_back("-C");
343 makecommand
.push_back(dir
.c_str());
344 makecommand
.push_back("-f");
345 makecommand
.push_back(this->CurrentXCodeHackMakefile
.c_str());
346 if(this->XcodeVersion
> 20)
348 makecommand
.push_back("all.$(CONFIGURATION)");
350 cmCustomCommandLines commandLines
;
351 commandLines
.push_back(makecommand
);
352 // Add Re-Run CMake rules
353 this->CreateReRunCMakeFile(root
);
355 // now make the allbuild depend on all the non-utility targets
357 for(std::vector
<cmLocalGenerator
*>::iterator i
= gens
.begin();
358 i
!= gens
.end(); ++i
)
360 cmLocalGenerator
* lg
= *i
;
361 if(this->IsExcluded(root
, *i
))
365 cmTargets
& tgts
= lg
->GetMakefile()->GetTargets();
366 for(cmTargets::iterator l
= tgts
.begin(); l
!= tgts
.end(); l
++)
368 cmTarget
& target
= l
->second
;
369 // make all exe, shared libs and modules
370 // run the depend check makefile as a post build rule
371 // this will make sure that when the next target is built
372 // things are up-to-date
373 if((target
.GetType() == cmTarget::EXECUTABLE
||
374 target
.GetType() == cmTarget::STATIC_LIBRARY
||
375 target
.GetType() == cmTarget::SHARED_LIBRARY
||
376 target
.GetType() == cmTarget::MODULE_LIBRARY
))
378 lg
->GetMakefile()->AddCustomCommandToTarget(target
.GetName(),
381 cmTarget::POST_BUILD
,
382 "Depend check for xcode",
386 if(!target
.GetPropertyAsBool("EXCLUDE_FROM_ALL"))
388 allbuild
->AddUtility(target
.GetName());
391 // Refer to the build configuration file for easy editing.
392 listfile
= lg
->GetMakefile()->GetStartDirectory();
394 listfile
+= "CMakeLists.txt";
395 target
.AddSource(listfile
.c_str());
400 //----------------------------------------------------------------------------
401 void cmGlobalXCodeGenerator::CreateReRunCMakeFile(cmLocalGenerator
* root
)
403 cmMakefile
* mf
= root
->GetMakefile();
404 std::vector
<std::string
> lfiles
= mf
->GetListFiles();
406 std::sort(lfiles
.begin(), lfiles
.end(), std::less
<std::string
>());
407 std::vector
<std::string
>::iterator new_end
=
408 std::unique(lfiles
.begin(), lfiles
.end());
409 lfiles
.erase(new_end
, lfiles
.end());
410 std::string dir
= mf
->GetHomeOutputDirectory();
411 this->CurrentReRunCMakeMakefile
= dir
;
412 this->CurrentReRunCMakeMakefile
+= "/CMakeScripts";
413 cmSystemTools::MakeDirectory(this->CurrentReRunCMakeMakefile
.c_str());
414 this->CurrentReRunCMakeMakefile
+= "/ReRunCMake.make";
415 cmGeneratedFileStream makefileStream
416 (this->CurrentReRunCMakeMakefile
.c_str());
417 makefileStream
.SetCopyIfDifferent(true);
418 makefileStream
<< "# Generated by CMake, DO NOT EDIT\n";
419 makefileStream
<< cmake::GetCMakeFilesDirectoryPostSlash();
420 makefileStream
<< "cmake.check_cache: ";
421 for(std::vector
<std::string
>::const_iterator i
= lfiles
.begin();
422 i
!= lfiles
.end(); ++i
)
424 makefileStream
<< "\\\n" << this->ConvertToRelativeForMake(i
->c_str());
426 std::string cmake
= mf
->GetRequiredDefinition("CMAKE_COMMAND");
427 makefileStream
<< "\n\t" << this->ConvertToRelativeForMake(cmake
.c_str())
428 << " -H" << this->ConvertToRelativeForMake(
429 mf
->GetHomeDirectory())
430 << " -B" << this->ConvertToRelativeForMake(
431 mf
->GetHomeOutputDirectory()) << "\n";
434 //----------------------------------------------------------------------------
435 void cmGlobalXCodeGenerator::ClearXCodeObjects()
437 this->TargetDoneSet
.clear();
438 for(unsigned int i
= 0; i
< this->XCodeObjects
.size(); ++i
)
440 delete this->XCodeObjects
[i
];
442 this->XCodeObjects
.clear();
443 this->GroupMap
.clear();
444 this->GroupNameMap
.clear();
445 this->TargetGroup
.clear();
446 this->FileRefs
.clear();
449 //----------------------------------------------------------------------------
451 cmGlobalXCodeGenerator::CreateObject(cmXCodeObject::PBXType ptype
)
454 if(this->XcodeVersion
== 15)
456 obj
= new cmXCodeObject(ptype
, cmXCodeObject::OBJECT
);
460 obj
= new cmXCode21Object(ptype
, cmXCodeObject::OBJECT
);
462 this->XCodeObjects
.push_back(obj
);
466 //----------------------------------------------------------------------------
468 cmGlobalXCodeGenerator::CreateObject(cmXCodeObject::Type type
)
470 cmXCodeObject
* obj
= new cmXCodeObject(cmXCodeObject::None
, type
);
471 this->XCodeObjects
.push_back(obj
);
475 //----------------------------------------------------------------------------
477 cmGlobalXCodeGenerator::CreateString(const char* s
)
479 cmXCodeObject
* obj
= this->CreateObject(cmXCodeObject::STRING
);
484 //----------------------------------------------------------------------------
485 cmXCodeObject
* cmGlobalXCodeGenerator
486 ::CreateObjectReference(cmXCodeObject
* ref
)
488 cmXCodeObject
* obj
= this->CreateObject(cmXCodeObject::OBJECT_REF
);
493 //----------------------------------------------------------------------------
494 cmStdString
GetGroupMapKey(cmTarget
& cmtarget
, cmSourceFile
* sf
)
496 cmStdString
key(cmtarget
.GetName());
498 key
+= sf
->GetFullPath();
502 //----------------------------------------------------------------------------
504 cmGlobalXCodeGenerator::CreateXCodeSourceFile(cmLocalGenerator
* lg
,
508 // Add flags from target and source file properties.
510 if(cmtarget
.GetProperty("COMPILE_FLAGS"))
512 lg
->AppendFlags(flags
, cmtarget
.GetProperty("COMPILE_FLAGS"));
514 lg
->AppendFlags(flags
, sf
->GetProperty("COMPILE_FLAGS"));
516 // Add per-source definitions.
517 BuildObjectListOrString
flagsBuild(this, false);
518 this->AppendDefines(flagsBuild
,
519 sf
->GetProperty("COMPILE_DEFINITIONS"), true);
520 if (!flagsBuild
.IsEmpty())
526 flags
+= flagsBuild
.GetString();
529 // Using a map and the full path guarantees that we will always get the same
530 // fileRef object for any given full path.
532 cmXCodeObject
* fileRef
= this->CreateXCodeFileReference(sf
, cmtarget
);
534 cmXCodeObject
* buildFile
= this->CreateObject(cmXCodeObject::PBXBuildFile
);
535 buildFile
->SetComment(fileRef
->GetComment());
536 buildFile
->AddAttribute("fileRef", this->CreateObjectReference(fileRef
));
538 cmXCodeObject
* settings
=
539 this->CreateObject(cmXCodeObject::ATTRIBUTE_GROUP
);
540 settings
->AddAttribute("COMPILER_FLAGS", this->CreateString(flags
.c_str()));
542 // Is this a resource file in this target? Add it to the resources group...
544 cmTarget::SourceFileFlags tsFlags
= cmtarget
.GetTargetSourceFileFlags(sf
);
545 bool isResource
= (tsFlags
.Type
== cmTarget::SourceFileTypeResource
);
547 // Is this a "private" or "public" framework header file?
548 // Set the ATTRIBUTES attribute appropriately...
550 if(cmtarget
.IsFrameworkOnApple())
552 if(tsFlags
.Type
== cmTarget::SourceFileTypePrivateHeader
)
554 cmXCodeObject
* attrs
= this->CreateObject(cmXCodeObject::OBJECT_LIST
);
555 attrs
->AddObject(this->CreateString("Private"));
556 settings
->AddAttribute("ATTRIBUTES", attrs
);
559 else if(tsFlags
.Type
== cmTarget::SourceFileTypePublicHeader
)
561 cmXCodeObject
* attrs
= this->CreateObject(cmXCodeObject::OBJECT_LIST
);
562 attrs
->AddObject(this->CreateString("Public"));
563 settings
->AddAttribute("ATTRIBUTES", attrs
);
568 // Add the fileRef to the top level Resources group/folder if it is not
571 if(isResource
&& this->ResourcesGroupChildren
&&
572 !this->ResourcesGroupChildren
->HasObject(fileRef
))
574 this->ResourcesGroupChildren
->AddObject(fileRef
);
577 buildFile
->AddAttribute("settings", settings
);
581 //----------------------------------------------------------------------------
583 cmGlobalXCodeGenerator::CreateXCodeFileReference(cmSourceFile
* sf
,
586 std::string fname
= sf
->GetFullPath();
587 cmXCodeObject
* fileRef
= this->FileRefs
[fname
];
590 fileRef
= this->CreateObject(cmXCodeObject::PBXFileReference
);
591 std::string comment
= fname
;
593 //std::string gname = group->GetObject("name")->GetString();
594 //comment += gname.substr(1, gname.size()-2);
595 fileRef
->SetComment(fname
.c_str());
596 this->FileRefs
[fname
] = fileRef
;
598 cmStdString key
= GetGroupMapKey(cmtarget
, sf
);
599 cmXCodeObject
* group
= this->GroupMap
[key
];
600 cmXCodeObject
* children
= group
->GetObject("children");
601 if (!children
->HasObject(fileRef
))
603 children
->AddObject(fileRef
);
605 fileRef
->AddAttribute("fileEncoding", this->CreateString("4"));
608 this->CurrentLocalGenerator
->GetSourceFileLanguage(*sf
);
609 std::string sourcecode
= "sourcecode";
610 std::string ext
= sf
->GetExtension();
611 ext
= cmSystemTools::LowerCase(ext
);
615 sourcecode
= "compiled.mach-o.objfile";
617 else if(ext
== "xib")
619 sourcecode
= "file.xib";
623 sourcecode
+= ".cpp.objcpp";
627 sourcecode
+= ".c.objc";
629 else if(ext
== "xib")
631 sourcecode
+= ".file.xib";
633 else if(ext
== "plist")
635 sourcecode
+= ".text.plist";
639 sourcecode
+= ".c.h";
641 else if(ext
== "hxx" || ext
== "hpp" || ext
== "txx"
644 sourcecode
+= ".cpp.h";
646 else if(lang
&& strcmp(lang
, "CXX") == 0)
648 sourcecode
+= ".cpp.cpp";
650 else if(lang
&& strcmp(lang
, "C") == 0)
652 sourcecode
+= ".c.c";
654 else if(ext
== "png" || ext
== "gif" || ext
== "jpg")
656 sourcecode
= "image";
658 else if(ext
== "txt")
660 sourcecode
+= ".text";
664 // // Already specialized above or we leave sourcecode == "sourcecode"
665 // // which is probably the most correct choice. Extensionless headers,
666 // // for example... Or file types unknown to Xcode that do not map to a
667 // // valid lastKnownFileType value.
670 fileRef
->AddAttribute("lastKnownFileType",
671 this->CreateString(sourcecode
.c_str()));
673 // Store the file path relative to the top of the source tree.
674 std::string path
= this->RelativeToSource(sf
->GetFullPath().c_str());
675 std::string name
= cmSystemTools::GetFilenameName(path
.c_str());
676 const char* sourceTree
= (cmSystemTools::FileIsFullPath(path
.c_str())?
677 "<absolute>" : "SOURCE_ROOT");
678 fileRef
->AddAttribute("name", this->CreateString(name
.c_str()));
679 fileRef
->AddAttribute("path", this->CreateString(path
.c_str()));
680 fileRef
->AddAttribute("sourceTree", this->CreateString(sourceTree
));
681 if(this->XcodeVersion
== 15)
683 fileRef
->AddAttribute("refType", this->CreateString("4"));
688 //----------------------------------------------------------------------------
689 bool cmGlobalXCodeGenerator::SpecialTargetEmitted(std::string
const& tname
)
691 if(tname
== "ALL_BUILD" || tname
== "XCODE_DEPEND_HELPER" ||
692 tname
== "install" || tname
== "package" || tname
== "RUN_TESTS" )
694 if(this->TargetDoneSet
.find(tname
) != this->TargetDoneSet
.end())
698 this->TargetDoneSet
.insert(tname
);
704 //----------------------------------------------------------------------------
705 void cmGlobalXCodeGenerator::SetCurrentLocalGenerator(cmLocalGenerator
* gen
)
707 this->CurrentLocalGenerator
= gen
;
708 this->CurrentMakefile
= gen
->GetMakefile();
710 cmSystemTools::CollapseFullPath(this->CurrentMakefile
->
711 GetCurrentOutputDirectory());
712 cmSystemTools::SplitPath(outdir
.c_str(),
713 this->CurrentOutputDirectoryComponents
);
715 // Select the current set of configuration types.
716 this->CurrentConfigurationTypes
.clear();
717 if(this->XcodeVersion
> 20)
719 if(const char* types
=
720 this->CurrentMakefile
->GetDefinition("CMAKE_CONFIGURATION_TYPES"))
722 cmSystemTools::ExpandListArgument(types
,
723 this->CurrentConfigurationTypes
);
726 if(this->CurrentConfigurationTypes
.empty())
728 if(const char* buildType
=
729 this->CurrentMakefile
->GetDefinition("CMAKE_BUILD_TYPE"))
731 this->CurrentConfigurationTypes
.push_back(buildType
);
735 this->CurrentConfigurationTypes
.push_back("");
740 //----------------------------------------------------------------------------
742 cmGlobalXCodeGenerator::CreateXCodeTargets(cmLocalGenerator
* gen
,
743 std::vector
<cmXCodeObject
*>&
746 this->SetCurrentLocalGenerator(gen
);
747 cmTargets
&tgts
= this->CurrentMakefile
->GetTargets();
748 for(cmTargets::iterator l
= tgts
.begin(); l
!= tgts
.end(); l
++)
750 cmTarget
& cmtarget
= l
->second
;
752 // make sure ALL_BUILD, INSTALL, etc are only done once
753 if(this->SpecialTargetEmitted(l
->first
.c_str()))
758 if(cmtarget
.GetType() == cmTarget::UTILITY
||
759 cmtarget
.GetType() == cmTarget::GLOBAL_TARGET
)
761 targets
.push_back(this->CreateUtilityTarget(cmtarget
));
765 // organize the sources
766 std::vector
<cmSourceFile
*> const &classes
= cmtarget
.GetSourceFiles();
767 std::vector
<cmXCodeObject
*> externalObjFiles
;
768 std::vector
<cmXCodeObject
*> headerFiles
;
769 std::vector
<cmXCodeObject
*> resourceFiles
;
770 std::vector
<cmXCodeObject
*> sourceFiles
;
771 for(std::vector
<cmSourceFile
*>::const_iterator i
= classes
.begin();
772 i
!= classes
.end(); ++i
)
775 this->CreateXCodeSourceFile(this->CurrentLocalGenerator
,
777 cmXCodeObject
* fr
= xsf
->GetObject("fileRef");
778 cmXCodeObject
* filetype
=
779 fr
->GetObject()->GetObject("lastKnownFileType");
781 cmTarget::SourceFileFlags tsFlags
=
782 cmtarget
.GetTargetSourceFileFlags(*i
);
784 if(strcmp(filetype
->GetString(), "compiled.mach-o.objfile") == 0)
786 externalObjFiles
.push_back(xsf
);
788 else if(this->IsHeaderFile(*i
) ||
789 (tsFlags
.Type
== cmTarget::SourceFileTypePrivateHeader
) ||
790 (tsFlags
.Type
== cmTarget::SourceFileTypePublicHeader
))
792 headerFiles
.push_back(xsf
);
794 else if(tsFlags
.Type
== cmTarget::SourceFileTypeResource
)
796 resourceFiles
.push_back(xsf
);
798 else if(!(*i
)->GetPropertyAsBool("HEADER_FILE_ONLY"))
800 // Include this file in the build if it has a known language
801 // and has not been listed as an ignored extension for this
803 if(this->CurrentLocalGenerator
->GetSourceFileLanguage(**i
) &&
804 !this->IgnoreFile((*i
)->GetExtension().c_str()))
806 sourceFiles
.push_back(xsf
);
811 // some build phases only apply to bundles and/or frameworks
812 bool isFrameworkTarget
= cmtarget
.IsFrameworkOnApple();
813 bool isBundleTarget
= cmtarget
.GetPropertyAsBool("MACOSX_BUNDLE");
815 cmXCodeObject
* buildFiles
= 0;
817 // create source build phase
818 cmXCodeObject
* sourceBuildPhase
= 0;
819 if (!sourceFiles
.empty())
822 this->CreateObject(cmXCodeObject::PBXSourcesBuildPhase
);
823 sourceBuildPhase
->SetComment("Sources");
824 sourceBuildPhase
->AddAttribute("buildActionMask",
825 this->CreateString("2147483647"));
826 buildFiles
= this->CreateObject(cmXCodeObject::OBJECT_LIST
);
827 for(std::vector
<cmXCodeObject
*>::iterator i
= sourceFiles
.begin();
828 i
!= sourceFiles
.end(); ++i
)
830 buildFiles
->AddObject(*i
);
832 sourceBuildPhase
->AddAttribute("files", buildFiles
);
833 sourceBuildPhase
->AddAttribute("runOnlyForDeploymentPostprocessing",
834 this->CreateString("0"));
837 // create header build phase - only for framework targets
838 cmXCodeObject
* headerBuildPhase
= 0;
839 if (!headerFiles
.empty() && isFrameworkTarget
)
842 this->CreateObject(cmXCodeObject::PBXHeadersBuildPhase
);
843 headerBuildPhase
->SetComment("Headers");
844 headerBuildPhase
->AddAttribute("buildActionMask",
845 this->CreateString("2147483647"));
846 buildFiles
= this->CreateObject(cmXCodeObject::OBJECT_LIST
);
847 for(std::vector
<cmXCodeObject
*>::iterator i
= headerFiles
.begin();
848 i
!= headerFiles
.end(); ++i
)
850 buildFiles
->AddObject(*i
);
852 headerBuildPhase
->AddAttribute("files", buildFiles
);
853 headerBuildPhase
->AddAttribute("runOnlyForDeploymentPostprocessing",
854 this->CreateString("0"));
857 // create resource build phase - only for framework or bundle targets
858 cmXCodeObject
* resourceBuildPhase
= 0;
859 if (!resourceFiles
.empty() && (isFrameworkTarget
|| isBundleTarget
))
862 this->CreateObject(cmXCodeObject::PBXResourcesBuildPhase
);
863 resourceBuildPhase
->SetComment("Resources");
864 resourceBuildPhase
->AddAttribute("buildActionMask",
865 this->CreateString("2147483647"));
866 buildFiles
= this->CreateObject(cmXCodeObject::OBJECT_LIST
);
867 for(std::vector
<cmXCodeObject
*>::iterator i
= resourceFiles
.begin();
868 i
!= resourceFiles
.end(); ++i
)
870 buildFiles
->AddObject(*i
);
872 resourceBuildPhase
->AddAttribute("files", buildFiles
);
873 resourceBuildPhase
->AddAttribute("runOnlyForDeploymentPostprocessing",
874 this->CreateString("0"));
877 // create vector of "non-resource content file" build phases - only for
878 // framework or bundle targets
879 std::vector
<cmXCodeObject
*> contentBuildPhases
;
880 if (isFrameworkTarget
|| isBundleTarget
)
882 typedef std::map
<cmStdString
, std::vector
<cmSourceFile
*> >
883 mapOfVectorOfSourceFiles
;
884 mapOfVectorOfSourceFiles bundleFiles
;
885 for(std::vector
<cmSourceFile
*>::const_iterator i
= classes
.begin();
886 i
!= classes
.end(); ++i
)
888 cmTarget::SourceFileFlags tsFlags
=
889 cmtarget
.GetTargetSourceFileFlags(*i
);
890 if(tsFlags
.Type
== cmTarget::SourceFileTypeMacContent
)
892 bundleFiles
[tsFlags
.MacFolder
].push_back(*i
);
895 mapOfVectorOfSourceFiles::iterator mit
;
896 for ( mit
= bundleFiles
.begin(); mit
!= bundleFiles
.end(); ++ mit
)
898 cmXCodeObject
* copyFilesBuildPhase
=
899 this->CreateObject(cmXCodeObject::PBXCopyFilesBuildPhase
);
900 copyFilesBuildPhase
->SetComment("Copy files");
901 copyFilesBuildPhase
->AddAttribute("buildActionMask",
902 this->CreateString("2147483647"));
903 copyFilesBuildPhase
->AddAttribute("dstSubfolderSpec",
904 this->CreateString("6"));
905 cmOStringStream ostr
;
906 if (cmtarget
.IsFrameworkOnApple())
908 // dstPath in frameworks is relative to Versions/<version>
911 else if ( mit
->first
!= "MacOS" )
913 // dstPath in bundles is relative to Contents/MacOS
914 ostr
<< "../" << mit
->first
.c_str();
916 copyFilesBuildPhase
->AddAttribute("dstPath",
917 this->CreateString(ostr
.str().c_str()));
918 copyFilesBuildPhase
->AddAttribute(
919 "runOnlyForDeploymentPostprocessing", this->CreateString("0"));
920 buildFiles
= this->CreateObject(cmXCodeObject::OBJECT_LIST
);
921 copyFilesBuildPhase
->AddAttribute("files", buildFiles
);
922 std::vector
<cmSourceFile
*>::iterator sfIt
;
923 for ( sfIt
= mit
->second
.begin(); sfIt
!= mit
->second
.end(); ++ sfIt
)
926 this->CreateXCodeSourceFile(this->CurrentLocalGenerator
,
928 buildFiles
->AddObject(xsf
);
930 contentBuildPhases
.push_back(copyFilesBuildPhase
);
934 // create framework build phase
935 cmXCodeObject
* frameworkBuildPhase
= 0;
936 if (!externalObjFiles
.empty())
938 frameworkBuildPhase
=
939 this->CreateObject(cmXCodeObject::PBXFrameworksBuildPhase
);
940 frameworkBuildPhase
->SetComment("Frameworks");
941 frameworkBuildPhase
->AddAttribute("buildActionMask",
942 this->CreateString("2147483647"));
943 buildFiles
= this->CreateObject(cmXCodeObject::OBJECT_LIST
);
944 frameworkBuildPhase
->AddAttribute("files", buildFiles
);
945 for(std::vector
<cmXCodeObject
*>::iterator i
= externalObjFiles
.begin();
946 i
!= externalObjFiles
.end(); ++i
)
948 buildFiles
->AddObject(*i
);
950 frameworkBuildPhase
->AddAttribute("runOnlyForDeploymentPostprocessing",
951 this->CreateString("0"));
954 // create list of build phases and create the XCode target
955 cmXCodeObject
* buildPhases
=
956 this->CreateObject(cmXCodeObject::OBJECT_LIST
);
958 this->CreateCustomCommands(buildPhases
, sourceBuildPhase
,
959 headerBuildPhase
, resourceBuildPhase
,
961 frameworkBuildPhase
, cmtarget
);
963 targets
.push_back(this->CreateXCodeTarget(cmtarget
, buildPhases
));
967 //----------------------------------------------------------------------------
968 void cmGlobalXCodeGenerator::ForceLinkerLanguages()
970 // This makes sure all targets link using the proper language.
971 for(std::map
<cmStdString
, cmTarget
*>::const_iterator
972 ti
= this->TotalTargets
.begin(); ti
!= this->TotalTargets
.end(); ++ti
)
974 this->ForceLinkerLanguage(*ti
->second
);
978 //----------------------------------------------------------------------------
979 void cmGlobalXCodeGenerator::ForceLinkerLanguage(cmTarget
& cmtarget
)
981 // This matters only for targets that link.
982 if(cmtarget
.GetType() != cmTarget::EXECUTABLE
&&
983 cmtarget
.GetType() != cmTarget::SHARED_LIBRARY
&&
984 cmtarget
.GetType() != cmTarget::MODULE_LIBRARY
)
989 const char* llang
= cmtarget
.GetLinkerLanguage("NOCONFIG");
990 if(!llang
) { return; }
992 // If the language is compiled as a source trust Xcode to link with it.
993 cmTarget::LinkImplementation
const* impl
=
994 cmtarget
.GetLinkImplementation("NOCONFIG");
995 for(std::vector
<std::string
>::const_iterator li
= impl
->Languages
.begin();
996 li
!= impl
->Languages
.end(); ++li
)
998 if(*li
== llang
) { return; }
1001 // Add an empty source file to the target that compiles with the
1002 // linker language. This should convince Xcode to choose the proper
1004 cmMakefile
* mf
= cmtarget
.GetMakefile();
1005 std::string fname
= mf
->GetCurrentOutputDirectory();
1006 fname
+= cmake::GetCMakeFilesDirectory();
1008 fname
+= cmtarget
.GetName();
1009 fname
+= "-CMakeForceLinker";
1011 fname
+= cmSystemTools::LowerCase(llang
);
1013 cmGeneratedFileStream
fout(fname
.c_str());
1016 if(cmSourceFile
* sf
= mf
->GetOrCreateSource(fname
.c_str()))
1018 sf
->SetProperty("LANGUAGE", llang
);
1019 cmtarget
.AddSourceFile(sf
);
1023 //----------------------------------------------------------------------------
1024 bool cmGlobalXCodeGenerator::IsHeaderFile(cmSourceFile
* sf
)
1026 const std::vector
<std::string
>& hdrExts
=
1027 this->CurrentMakefile
->GetHeaderExtensions();
1028 return (std::find(hdrExts
.begin(), hdrExts
.end(), sf
->GetExtension()) !=
1032 //----------------------------------------------------------------------------
1034 cmGlobalXCodeGenerator::CreateBuildPhase(const char* name
,
1037 const std::vector
<cmCustomCommand
>&
1040 if(commands
.size() == 0 && strcmp(name
, "CMake ReRun") != 0)
1044 cmXCodeObject
* buildPhase
=
1045 this->CreateObject(cmXCodeObject::PBXShellScriptBuildPhase
);
1046 buildPhase
->AddAttribute("buildActionMask",
1047 this->CreateString("2147483647"));
1048 cmXCodeObject
* buildFiles
= this->CreateObject(cmXCodeObject::OBJECT_LIST
);
1049 buildPhase
->AddAttribute("files", buildFiles
);
1050 buildPhase
->AddAttribute("name",
1051 this->CreateString(name
));
1052 buildPhase
->AddAttribute("runOnlyForDeploymentPostprocessing",
1053 this->CreateString("0"));
1054 buildPhase
->AddAttribute("shellPath",
1055 this->CreateString("/bin/sh"));
1056 this->AddCommandsToBuildPhase(buildPhase
, cmtarget
, commands
,
1061 //----------------------------------------------------------------------------
1062 void cmGlobalXCodeGenerator::CreateCustomCommands(cmXCodeObject
* buildPhases
,
1069 std::vector
<cmXCodeObject
*>
1072 frameworkBuildPhase
,
1075 std::vector
<cmCustomCommand
> const & prebuild
1076 = cmtarget
.GetPreBuildCommands();
1077 std::vector
<cmCustomCommand
> const & prelink
1078 = cmtarget
.GetPreLinkCommands();
1079 std::vector
<cmCustomCommand
> const & postbuild
1080 = cmtarget
.GetPostBuildCommands();
1081 std::vector
<cmSourceFile
*>const &classes
= cmtarget
.GetSourceFiles();
1082 // add all the sources
1083 std::vector
<cmCustomCommand
> commands
;
1084 for(std::vector
<cmSourceFile
*>::const_iterator i
= classes
.begin();
1085 i
!= classes
.end(); ++i
)
1087 if((*i
)->GetCustomCommand())
1089 commands
.push_back(*(*i
)->GetCustomCommand());
1092 std::vector
<cmCustomCommand
> reruncom
;
1093 cmXCodeObject
* cmakeReRunPhase
=
1094 this->CreateBuildPhase("CMake ReRun", "cmakeReRunPhase",
1095 cmtarget
, reruncom
);
1096 buildPhases
->AddObject(cmakeReRunPhase
);
1097 // create prebuild phase
1098 cmXCodeObject
* cmakeRulesBuildPhase
=
1099 this->CreateBuildPhase("CMake Rules",
1100 "cmakeRulesBuildPhase",
1101 cmtarget
, commands
);
1102 // create prebuild phase
1103 cmXCodeObject
* preBuildPhase
=
1104 this->CreateBuildPhase("CMake PreBuild Rules", "preBuildCommands",
1105 cmtarget
, prebuild
);
1106 // create prelink phase
1107 cmXCodeObject
* preLinkPhase
=
1108 this->CreateBuildPhase("CMake PreLink Rules", "preLinkCommands",
1110 // create postbuild phase
1111 cmXCodeObject
* postBuildPhase
=
1112 this->CreateBuildPhase("CMake PostBuild Rules", "postBuildPhase",
1113 cmtarget
, postbuild
);
1115 // The order here is the order they will be built in.
1116 // The order "headers, resources, sources" mimics a native project generated
1117 // from an xcode template...
1121 buildPhases
->AddObject(preBuildPhase
);
1123 if(cmakeRulesBuildPhase
)
1125 buildPhases
->AddObject(cmakeRulesBuildPhase
);
1127 if(headerBuildPhase
)
1129 buildPhases
->AddObject(headerBuildPhase
);
1131 if(resourceBuildPhase
)
1133 buildPhases
->AddObject(resourceBuildPhase
);
1135 std::vector
<cmXCodeObject
*>::iterator cit
;
1136 for (cit
= contentBuildPhases
.begin(); cit
!= contentBuildPhases
.end();
1139 buildPhases
->AddObject(*cit
);
1141 if(sourceBuildPhase
)
1143 buildPhases
->AddObject(sourceBuildPhase
);
1147 buildPhases
->AddObject(preLinkPhase
);
1149 if(frameworkBuildPhase
)
1151 buildPhases
->AddObject(frameworkBuildPhase
);
1155 buildPhases
->AddObject(postBuildPhase
);
1159 //----------------------------------------------------------------------------
1160 std::string
cmGlobalXCodeGenerator::ExtractFlag(const char* flag
,
1163 std::string retFlag
;
1164 std::string::size_type pos
= flags
.find(flag
);
1165 if(pos
!= flags
.npos
&& (pos
==0 || flags
[pos
-1]==' '))
1167 while(pos
< flags
.size() && flags
[pos
] != ' ')
1169 retFlag
+= flags
[pos
];
1177 //----------------------------------------------------------------------------
1179 cmGlobalXCodeGenerator::AddCommandsToBuildPhase(cmXCodeObject
* buildphase
,
1181 std::vector
<cmCustomCommand
>
1185 if(strcmp(name
, "cmakeReRunPhase") == 0)
1187 std::string cdir
= this->CurrentMakefile
->GetHomeOutputDirectory();
1188 cdir
= this->ConvertToRelativeForMake(cdir
.c_str());
1189 std::string makecmd
= "make -C ";
1193 this->ConvertToRelativeForMake(this->CurrentReRunCMakeMakefile
.c_str());
1194 cmSystemTools::ReplaceString(makecmd
, "\\ ", "\\\\ ");
1195 buildphase
->AddAttribute("shellScript",
1196 this->CreateString(makecmd
.c_str()));
1200 // collect multiple outputs of custom commands into a set
1201 // which will be used for every configuration
1202 std::map
<cmStdString
, cmStdString
> multipleOutputPairs
;
1203 for(std::vector
<cmCustomCommand
>::const_iterator i
= commands
.begin();
1204 i
!= commands
.end(); ++i
)
1206 cmCustomCommand
const& cc
= *i
;
1207 if(!cc
.GetCommandLines().empty())
1209 const std::vector
<std::string
>& outputs
= cc
.GetOutputs();
1210 if(!outputs
.empty())
1212 // If there are more than one outputs treat the
1213 // first as the primary output and make the rest depend on it.
1214 std::vector
<std::string
>::const_iterator o
= outputs
.begin();
1215 std::string primaryOutput
= this->ConvertToRelativeForMake(o
->c_str());
1216 for(++o
; o
!= outputs
.end(); ++o
)
1218 std::string currentOutput
=this->ConvertToRelativeForMake(o
->c_str());
1219 multipleOutputPairs
[currentOutput
] = primaryOutput
;
1225 std::string dir
= this->CurrentMakefile
->GetCurrentOutputDirectory();
1226 dir
+= "/CMakeScripts";
1227 cmSystemTools::MakeDirectory(dir
.c_str());
1228 std::string makefile
= dir
;
1230 makefile
+= target
.GetName();
1233 makefile
+= ".make";
1235 for (std::vector
<std::string
>::const_iterator currentConfig
=
1236 this->CurrentConfigurationTypes
.begin();
1237 currentConfig
!=this->CurrentConfigurationTypes
.end();
1240 this->CreateCustomRulesMakefile(makefile
.c_str(),
1243 currentConfig
->c_str(),
1244 multipleOutputPairs
);
1247 std::string cdir
= this->CurrentMakefile
->GetCurrentOutputDirectory();
1248 cdir
= this->ConvertToRelativeForXCode(cdir
.c_str());
1249 std::string makecmd
= "make -C ";
1252 makecmd
+= this->ConvertToRelativeForMake(
1253 (makefile
+"$CONFIGURATION").c_str());
1254 if(!multipleOutputPairs
.empty())
1256 makecmd
+= " cmake_check_multiple_outputs";
1259 cmSystemTools::ReplaceString(makecmd
, "\\ ", "\\\\ ");
1260 buildphase
->AddAttribute("shellScript",
1261 this->CreateString(makecmd
.c_str()));
1264 //----------------------------------------------------------------------------
1265 void cmGlobalXCodeGenerator
1266 ::CreateCustomRulesMakefile(const char* makefileBasename
,
1268 std::vector
<cmCustomCommand
>
1270 const char* configName
,
1271 const std::map
<cmStdString
,
1272 cmStdString
>& multipleOutputPairs
1275 std::string makefileName
=makefileBasename
;
1276 makefileName
+=configName
;
1277 cmGeneratedFileStream
makefileStream(makefileName
.c_str());
1282 makefileStream
.SetCopyIfDifferent(true);
1283 makefileStream
<< "# Generated by CMake, DO NOT EDIT\n";
1284 makefileStream
<< "# Custom rules for " << target
.GetName() << "\n";
1286 // have all depend on all outputs
1287 makefileStream
<< "all: ";
1288 std::map
<const cmCustomCommand
*, cmStdString
> tname
;
1290 for(std::vector
<cmCustomCommand
>::const_iterator i
= commands
.begin();
1291 i
!= commands
.end(); ++i
)
1293 cmCustomCommand
const& cc
= *i
;
1294 if(!cc
.GetCommandLines().empty())
1296 const std::vector
<std::string
>& outputs
= cc
.GetOutputs();
1297 if(!outputs
.empty())
1299 for(std::vector
<std::string
>::const_iterator o
= outputs
.begin();
1300 o
!= outputs
.end(); ++o
)
1303 << "\\\n\t" << this->ConvertToRelativeForMake(o
->c_str());
1308 cmOStringStream str
;
1309 str
<< "_buildpart_" << count
++ ;
1310 tname
[&cc
] = std::string(target
.GetName()) + str
.str();
1311 makefileStream
<< "\\\n\t" << tname
[&cc
];
1315 makefileStream
<< "\n\n";
1316 for(std::vector
<cmCustomCommand
>::const_iterator i
= commands
.begin();
1317 i
!= commands
.end(); ++i
)
1319 cmCustomCommand
const& cc
= *i
;
1320 if(!cc
.GetCommandLines().empty())
1322 bool escapeOldStyle
= cc
.GetEscapeOldStyle();
1323 bool escapeAllowMakeVars
= cc
.GetEscapeAllowMakeVars();
1324 makefileStream
<< "\n";
1325 const std::vector
<std::string
>& outputs
= cc
.GetOutputs();
1326 if(!outputs
.empty())
1328 // There is at least one output, start the rule for it
1329 std::string primary_output
=
1330 this->ConvertToRelativeForMake(outputs
.begin()->c_str());
1331 makefileStream
<< primary_output
<< ": ";
1335 // There are no outputs. Use the generated force rule name.
1336 makefileStream
<< tname
[&cc
] << ": ";
1338 for(std::vector
<std::string
>::const_iterator d
=
1339 cc
.GetDepends().begin();
1340 d
!= cc
.GetDepends().end(); ++d
)
1343 this->CurrentLocalGenerator
->GetRealDependency(d
->c_str(),
1345 makefileStream
<< "\\\n" << this
1346 ->ConvertToRelativeForMake(dep
.c_str());
1348 makefileStream
<< "\n";
1350 if(const char* comment
= cc
.GetComment())
1352 std::string echo_cmd
= "echo ";
1353 echo_cmd
+= (this->CurrentLocalGenerator
->
1354 EscapeForShell(comment
, escapeAllowMakeVars
));
1355 makefileStream
<< "\t" << echo_cmd
.c_str() << "\n";
1358 // Add each command line to the set of commands.
1359 for(cmCustomCommandLines::const_iterator cl
=
1360 cc
.GetCommandLines().begin();
1361 cl
!= cc
.GetCommandLines().end(); ++cl
)
1363 // Build the command line in a single string.
1364 const cmCustomCommandLine
& commandLine
= *cl
;
1365 std::string cmd2
= this->CurrentLocalGenerator
1366 ->GetRealLocation(commandLine
[0].c_str(), configName
);
1368 cmSystemTools::ReplaceString(cmd2
, "/./", "/");
1369 cmd2
= this->ConvertToRelativeForMake(cmd2
.c_str());
1371 if(cc
.GetWorkingDirectory())
1374 cmd
+= this->ConvertToRelativeForMake(cc
.GetWorkingDirectory());
1378 for(unsigned int j
=1; j
< commandLine
.size(); ++j
)
1383 cmd
+= (this->CurrentLocalGenerator
1384 ->EscapeForShellOldStyle(commandLine
[j
].c_str()));
1388 cmd
+= (this->CurrentLocalGenerator
->
1389 EscapeForShell(commandLine
[j
].c_str(),
1390 escapeAllowMakeVars
));
1393 makefileStream
<< "\t" << cmd
.c_str() << "\n";
1398 // Add rules to deal with multiple outputs of custom commands.
1399 if(!multipleOutputPairs
.empty())
1402 "\n# Dependencies of multiple outputs to their primary outputs \n";
1404 for(std::map
<cmStdString
, cmStdString
>::const_iterator o
=
1405 multipleOutputPairs
.begin(); o
!= multipleOutputPairs
.end(); ++o
)
1407 makefileStream
<< o
->first
<< ": " << o
->second
<< "\n";
1412 "cmake_check_multiple_outputs:\n";
1413 for(std::map
<cmStdString
, cmStdString
>::const_iterator o
=
1414 multipleOutputPairs
.begin(); o
!= multipleOutputPairs
.end(); ++o
)
1416 makefileStream
<< "\t@if [ ! -f "
1417 << o
->first
<< " ]; then rm -f "
1418 << o
->second
<< "; fi\n";
1423 //----------------------------------------------------------------------------
1424 void cmGlobalXCodeGenerator::CreateBuildSettings(cmTarget
& target
,
1425 cmXCodeObject
* buildSettings
,
1426 const char* configName
)
1429 std::string defFlags
;
1430 bool shared
= ((target
.GetType() == cmTarget::SHARED_LIBRARY
) ||
1431 (target
.GetType() == cmTarget::MODULE_LIBRARY
));
1433 const char* lang
= target
.GetLinkerLanguage(configName
);
1437 // for c++ projects get the c flags as well
1438 if(strcmp(lang
, "CXX") == 0)
1440 this->CurrentLocalGenerator
->AddLanguageFlags(cflags
, "C", configName
);
1441 this->CurrentLocalGenerator
->AddSharedFlags(cflags
, lang
, shared
);
1444 // Add language-specific flags.
1445 this->CurrentLocalGenerator
->AddLanguageFlags(flags
, lang
, configName
);
1447 // Add shared-library flags if needed.
1448 this->CurrentLocalGenerator
->AddSharedFlags(flags
, lang
, shared
);
1452 this->CurrentLocalGenerator
->
1453 AppendFlags(defFlags
,
1454 this->CurrentMakefile
->GetDefineFlags());
1456 // Add preprocessor definitions for this target and configuration.
1457 BuildObjectListOrString
ppDefs(this, this->XcodeVersion
>= 30);
1458 if(this->XcodeVersion
> 15)
1460 this->AppendDefines(ppDefs
, "CMAKE_INTDIR=\"$(CONFIGURATION)\"");
1462 if(const char* exportMacro
= target
.GetExportMacro())
1464 // Add the export symbol definition for shared library objects.
1465 this->AppendDefines(ppDefs
, exportMacro
);
1468 (ppDefs
, this->CurrentMakefile
->GetProperty("COMPILE_DEFINITIONS"));
1469 this->AppendDefines(ppDefs
, target
.GetProperty("COMPILE_DEFINITIONS"));
1472 std::string defVarName
= "COMPILE_DEFINITIONS_";
1473 defVarName
+= cmSystemTools::UpperCase(configName
);
1475 (ppDefs
, this->CurrentMakefile
->GetProperty(defVarName
.c_str()));
1476 this->AppendDefines(ppDefs
, target
.GetProperty(defVarName
.c_str()));
1478 buildSettings
->AddAttribute
1479 ("GCC_PREPROCESSOR_DEFINITIONS", ppDefs
.CreateList());
1481 std::string extraLinkOptions
;
1482 if(target
.GetType() == cmTarget::EXECUTABLE
)
1485 this->CurrentMakefile
->GetRequiredDefinition("CMAKE_EXE_LINKER_FLAGS");
1486 std::string var
= "CMAKE_EXE_LINKER_FLAGS_";
1487 var
+= cmSystemTools::UpperCase(configName
);
1489 this->CurrentMakefile
->GetSafeDefinition(var
.c_str());
1492 extraLinkOptions
+= " ";
1493 extraLinkOptions
+= val
;
1496 if(target
.GetType() == cmTarget::SHARED_LIBRARY
)
1498 extraLinkOptions
= this->CurrentMakefile
->
1499 GetRequiredDefinition("CMAKE_SHARED_LINKER_FLAGS");
1501 if(target
.GetType() == cmTarget::MODULE_LIBRARY
)
1503 extraLinkOptions
= this->CurrentMakefile
->
1504 GetRequiredDefinition("CMAKE_MODULE_LINKER_FLAGS");
1507 const char* targetLinkFlags
= target
.GetProperty("LINK_FLAGS");
1510 extraLinkOptions
+= " ";
1511 extraLinkOptions
+= targetLinkFlags
;
1514 // Get the product name components.
1515 std::string pnprefix
;
1517 std::string pnsuffix
;
1518 target
.GetFullNameComponents(pnprefix
, pnbase
, pnsuffix
, configName
);
1520 // Store the product name for all target types.
1521 buildSettings
->AddAttribute("PRODUCT_NAME",
1522 this->CreateString(pnbase
.c_str()));
1524 // Set attributes to specify the proper name for the target.
1525 if(target
.GetType() == cmTarget::STATIC_LIBRARY
||
1526 target
.GetType() == cmTarget::SHARED_LIBRARY
||
1527 target
.GetType() == cmTarget::MODULE_LIBRARY
||
1528 target
.GetType() == cmTarget::EXECUTABLE
)
1530 std::string pndir
= target
.GetDirectory();
1531 buildSettings
->AddAttribute("SYMROOT",
1532 this->CreateString(pndir
.c_str()));
1533 buildSettings
->AddAttribute("EXECUTABLE_PREFIX",
1534 this->CreateString(pnprefix
.c_str()));
1535 buildSettings
->AddAttribute("EXECUTABLE_SUFFIX",
1536 this->CreateString(pnsuffix
.c_str()));
1539 // Handle settings for each target type.
1540 switch(target
.GetType())
1542 case cmTarget::STATIC_LIBRARY
:
1544 buildSettings
->AddAttribute("LIBRARY_STYLE",
1545 this->CreateString("STATIC"));
1549 case cmTarget::MODULE_LIBRARY
:
1551 buildSettings
->AddAttribute("LIBRARY_STYLE",
1552 this->CreateString("BUNDLE"));
1553 if(this->XcodeVersion
>= 22)
1555 buildSettings
->AddAttribute("MACH_O_TYPE",
1556 this->CreateString("mh_bundle"));
1557 buildSettings
->AddAttribute("GCC_DYNAMIC_NO_PIC",
1558 this->CreateString("NO"));
1559 // Add the flags to create an executable.
1560 std::string createFlags
=
1561 this->LookupFlags("CMAKE_", lang
, "_LINK_FLAGS", "");
1562 if(!createFlags
.empty())
1564 extraLinkOptions
+= " ";
1565 extraLinkOptions
+= createFlags
;
1570 // Add the flags to create a module.
1571 std::string createFlags
=
1572 this->LookupFlags("CMAKE_SHARED_MODULE_CREATE_", lang
, "_FLAGS",
1574 if(!createFlags
.empty())
1576 extraLinkOptions
+= " ";
1577 extraLinkOptions
+= createFlags
;
1582 case cmTarget::SHARED_LIBRARY
:
1584 if(target
.GetPropertyAsBool("FRAMEWORK"))
1586 std::string version
= target
.GetFrameworkVersion();
1587 buildSettings
->AddAttribute("FRAMEWORK_VERSION",
1588 this->CreateString(version
.c_str()));
1590 std::string plist
= this->ComputeInfoPListLocation(target
);
1591 // Xcode will create the final version of Info.plist at build time,
1592 // so let it replace the framework name. This avoids creating
1593 // a per-configuration Info.plist file.
1594 this->CurrentLocalGenerator
1595 ->GenerateFrameworkInfoPList(&target
, "$(EXECUTABLE_NAME)",
1598 this->ConvertToRelativeForXCode(plist
.c_str());
1599 buildSettings
->AddAttribute("INFOPLIST_FILE",
1600 this->CreateString(path
.c_str()));
1604 // Add the flags to create a shared library.
1605 std::string createFlags
=
1606 this->LookupFlags("CMAKE_SHARED_LIBRARY_CREATE_", lang
, "_FLAGS",
1608 if(!createFlags
.empty())
1610 extraLinkOptions
+= " ";
1611 extraLinkOptions
+= createFlags
;
1615 buildSettings
->AddAttribute("LIBRARY_STYLE",
1616 this->CreateString("DYNAMIC"));
1619 case cmTarget::EXECUTABLE
:
1621 // Add the flags to create an executable.
1622 std::string createFlags
=
1623 this->LookupFlags("CMAKE_", lang
, "_LINK_FLAGS", "");
1624 if(!createFlags
.empty())
1626 extraLinkOptions
+= " ";
1627 extraLinkOptions
+= createFlags
;
1630 // Handle bundles and normal executables separately.
1631 if(target
.GetPropertyAsBool("MACOSX_BUNDLE"))
1633 std::string plist
= this->ComputeInfoPListLocation(target
);
1634 // Xcode will create the final version of Info.plist at build time,
1635 // so let it replace the executable name. This avoids creating
1636 // a per-configuration Info.plist file.
1637 this->CurrentLocalGenerator
1638 ->GenerateAppleInfoPList(&target
, "$(EXECUTABLE_NAME)",
1641 this->ConvertToRelativeForXCode(plist
.c_str());
1642 buildSettings
->AddAttribute("INFOPLIST_FILE",
1643 this->CreateString(path
.c_str()));
1651 if(this->XcodeVersion
>= 22)
1653 buildSettings
->AddAttribute("PREBINDING",
1654 this->CreateString("NO"));
1657 BuildObjectListOrString
dirs(this, this->XcodeVersion
>= 30);
1658 BuildObjectListOrString
fdirs(this, this->XcodeVersion
>= 30);
1659 std::vector
<std::string
> includes
;
1660 this->CurrentLocalGenerator
->GetIncludeDirectories(includes
);
1661 std::set
<cmStdString
> emitted
;
1662 emitted
.insert("/System/Library/Frameworks");
1663 for(std::vector
<std::string
>::iterator i
= includes
.begin();
1664 i
!= includes
.end(); ++i
)
1666 if(this->NameResolvesToFramework(i
->c_str()))
1668 std::string frameworkDir
= *i
;
1669 frameworkDir
+= "/../";
1670 frameworkDir
= cmSystemTools::CollapseFullPath(frameworkDir
.c_str());
1671 if(emitted
.insert(frameworkDir
).second
)
1673 fdirs
.Add(this->XCodeEscapePath(frameworkDir
.c_str()).c_str());
1678 std::string incpath
=
1679 this->XCodeEscapePath(i
->c_str());
1680 dirs
.Add(incpath
.c_str());
1683 std::vector
<std::string
>& frameworks
= target
.GetFrameworks();
1684 if(frameworks
.size())
1686 for(std::vector
<std::string
>::iterator fmIt
= frameworks
.begin();
1687 fmIt
!= frameworks
.end(); ++fmIt
)
1689 if(emitted
.insert(*fmIt
).second
)
1691 fdirs
.Add(this->XCodeEscapePath(fmIt
->c_str()).c_str());
1695 if(!fdirs
.IsEmpty())
1697 buildSettings
->AddAttribute("FRAMEWORK_SEARCH_PATHS",
1698 fdirs
.CreateList());
1702 buildSettings
->AddAttribute("HEADER_SEARCH_PATHS",
1705 std::string oflagc
= this->ExtractFlag("-O", cflags
);
1709 if(oflagc
.size() == 3)
1711 optLevel
[0] = oflagc
[2];
1713 if(oflagc
.size() == 2)
1717 std::string oflag
= this->ExtractFlag("-O", flags
);
1718 if(oflag
.size() == 3)
1720 optLevel
[0] = oflag
[2];
1722 if(oflag
.size() == 2)
1726 std::string gflagc
= this->ExtractFlag("-g", cflags
);
1727 // put back gdwarf-2 if used since there is no way
1728 // to represent it in the gui, but we still want debug yes
1729 if(gflagc
== "-gdwarf-2")
1734 std::string gflag
= this->ExtractFlag("-g", flags
);
1735 if(gflag
== "-gdwarf-2")
1740 const char* debugStr
= "YES";
1741 if(gflagc
.size() ==0 && gflag
.size() == 0)
1746 buildSettings
->AddAttribute("GCC_GENERATE_DEBUGGING_SYMBOLS",
1747 this->CreateString(debugStr
));
1748 buildSettings
->AddAttribute("GCC_OPTIMIZATION_LEVEL",
1749 this->CreateString(optLevel
));
1750 buildSettings
->AddAttribute("GCC_SYMBOLS_PRIVATE_EXTERN",
1751 this->CreateString("NO"));
1752 buildSettings
->AddAttribute("GCC_INLINES_ARE_PRIVATE_EXTERN",
1753 this->CreateString("NO"));
1754 if(lang
&& strcmp(lang
, "CXX") == 0)
1758 buildSettings
->AddAttribute("OTHER_CPLUSPLUSFLAGS",
1759 this->CreateString(flags
.c_str()));
1762 buildSettings
->AddAttribute("OTHER_CFLAGS",
1763 this->CreateString(cflags
.c_str()));
1770 buildSettings
->AddAttribute("OTHER_CFLAGS",
1771 this->CreateString(flags
.c_str()));
1774 // Create the INSTALL_PATH attribute.
1775 std::string install_name_dir
;
1776 if(target
.GetType() == cmTarget::SHARED_LIBRARY
)
1778 // Get the install_name directory for the build tree.
1779 install_name_dir
= target
.GetInstallNameDirForBuildTree(configName
, true);
1780 if(install_name_dir
.empty())
1782 // Xcode will not pass the -install_name option at all if INSTALL_PATH
1783 // is not given or is empty. We must explicitly put the flag in the
1784 // link flags to create an install_name with just the library soname.
1785 extraLinkOptions
+= " -install_name ";
1786 extraLinkOptions
+= target
.GetFullName(configName
);
1790 // Convert to a path for the native build tool.
1791 cmSystemTools::ConvertToUnixSlashes(install_name_dir
);
1792 // do not escape spaces on this since it is only a single path
1795 buildSettings
->AddAttribute("INSTALL_PATH",
1796 this->CreateString(install_name_dir
.c_str()));
1798 buildSettings
->AddAttribute("OTHER_LDFLAGS",
1799 this->CreateString(extraLinkOptions
.c_str()));
1800 buildSettings
->AddAttribute("OTHER_REZFLAGS",
1801 this->CreateString(""));
1802 buildSettings
->AddAttribute("SECTORDER_FLAGS",
1803 this->CreateString(""));
1804 buildSettings
->AddAttribute("USE_HEADERMAP",
1805 this->CreateString("NO"));
1806 if (this->XcodeVersion
>= 30)
1808 cmXCodeObject
*group
= this->CreateObject(cmXCodeObject::OBJECT_LIST
);
1809 group
->AddObject(this->CreateString("-Wmost"));
1810 group
->AddObject(this->CreateString("-Wno-four-char-constants"));
1811 group
->AddObject(this->CreateString("-Wno-unknown-pragmas"));
1812 buildSettings
->AddAttribute("WARNING_CFLAGS", group
);
1816 buildSettings
->AddAttribute("WARNING_CFLAGS",
1818 "-Wmost -Wno-four-char-constants"
1819 " -Wno-unknown-pragmas"));
1822 // Runtime version information.
1823 if(target
.GetType() == cmTarget::SHARED_LIBRARY
)
1829 // VERSION -> current_version
1830 target
.GetTargetVersion(false, major
, minor
, patch
);
1831 if(major
== 0 && minor
== 0 && patch
== 0)
1833 // Xcode always wants at least 1.0.0
1837 v
<< major
<< "." << minor
<< "." << patch
;
1838 buildSettings
->AddAttribute("DYLIB_CURRENT_VERSION",
1839 this->CreateString(v
.str().c_str()));
1841 // SOVERSION -> compatibility_version
1842 target
.GetTargetVersion(true, major
, minor
, patch
);
1843 if(major
== 0 && minor
== 0 && patch
== 0)
1845 // Xcode always wants at least 1.0.0
1848 cmOStringStream vso
;
1849 vso
<< major
<< "." << minor
<< "." << patch
;
1850 buildSettings
->AddAttribute("DYLIB_COMPATIBILITY_VERSION",
1851 this->CreateString(vso
.str().c_str()));
1853 // put this last so it can override existing settings
1854 // Convert "XCODE_ATTRIBUTE_*" properties directly.
1856 cmPropertyMap
const& props
= target
.GetProperties();
1857 for(cmPropertyMap::const_iterator i
= props
.begin();
1858 i
!= props
.end(); ++i
)
1860 if(i
->first
.find("XCODE_ATTRIBUTE_") == 0)
1862 buildSettings
->AddAttribute(i
->first
.substr(16).c_str(),
1863 this->CreateString(i
->second
.GetValue()));
1869 //----------------------------------------------------------------------------
1871 cmGlobalXCodeGenerator::CreateUtilityTarget(cmTarget
& cmtarget
)
1873 cmXCodeObject
* shellBuildPhase
=
1874 this->CreateObject(cmXCodeObject::PBXShellScriptBuildPhase
);
1875 shellBuildPhase
->AddAttribute("buildActionMask",
1876 this->CreateString("2147483647"));
1877 cmXCodeObject
* buildFiles
= this->CreateObject(cmXCodeObject::OBJECT_LIST
);
1878 shellBuildPhase
->AddAttribute("files", buildFiles
);
1879 cmXCodeObject
* inputPaths
= this->CreateObject(cmXCodeObject::OBJECT_LIST
);
1880 shellBuildPhase
->AddAttribute("inputPaths", inputPaths
);
1881 cmXCodeObject
* outputPaths
= this->CreateObject(cmXCodeObject::OBJECT_LIST
);
1882 shellBuildPhase
->AddAttribute("outputPaths", outputPaths
);
1883 shellBuildPhase
->AddAttribute("runOnlyForDeploymentPostprocessing",
1884 this->CreateString("0"));
1885 shellBuildPhase
->AddAttribute("shellPath",
1886 this->CreateString("/bin/sh"));
1887 shellBuildPhase
->AddAttribute("shellScript",
1889 "# shell script goes here\nexit 0"));
1890 cmXCodeObject
* target
=
1891 this->CreateObject(cmXCodeObject::PBXAggregateTarget
);
1892 target
->SetComment(cmtarget
.GetName());
1893 cmXCodeObject
* buildPhases
=
1894 this->CreateObject(cmXCodeObject::OBJECT_LIST
);
1895 std::vector
<cmXCodeObject
*> emptyContentVector
;
1896 this->CreateCustomCommands(buildPhases
, 0, 0, 0, emptyContentVector
, 0,
1898 target
->AddAttribute("buildPhases", buildPhases
);
1899 if(this->XcodeVersion
> 20)
1901 this->AddConfigurations(target
, cmtarget
);
1905 const char* theConfig
=
1906 this->CurrentMakefile
->GetDefinition("CMAKE_BUILD_TYPE");
1907 cmXCodeObject
* buildSettings
=
1908 this->CreateObject(cmXCodeObject::ATTRIBUTE_GROUP
);
1909 this->CreateBuildSettings(cmtarget
, buildSettings
, theConfig
);
1910 target
->AddAttribute("buildSettings", buildSettings
);
1912 cmXCodeObject
* dependencies
=
1913 this->CreateObject(cmXCodeObject::OBJECT_LIST
);
1914 target
->AddAttribute("dependencies", dependencies
);
1915 target
->AddAttribute("name", this->CreateString(cmtarget
.GetName()));
1916 target
->AddAttribute("productName",this->CreateString(cmtarget
.GetName()));
1917 target
->SetTarget(&cmtarget
);
1919 // Add source files without build rules for editing convenience.
1920 if(cmtarget
.GetType() == cmTarget::UTILITY
)
1922 std::vector
<cmSourceFile
*> const& sources
= cmtarget
.GetSourceFiles();
1923 for(std::vector
<cmSourceFile
*>::const_iterator i
= sources
.begin();
1924 i
!= sources
.end(); ++i
)
1926 if(!(*i
)->GetPropertyAsBool("GENERATED"))
1928 this->CreateXCodeFileReference(*i
, cmtarget
);
1936 //----------------------------------------------------------------------------
1937 std::string
cmGlobalXCodeGenerator::AddConfigurations(cmXCodeObject
* target
,
1940 std::string configTypes
=
1941 this->CurrentMakefile
->GetRequiredDefinition("CMAKE_CONFIGURATION_TYPES");
1942 std::vector
<std::string
> configVectorIn
;
1943 std::vector
<std::string
> configVector
;
1944 configVectorIn
.push_back(configTypes
);
1945 cmSystemTools::ExpandList(configVectorIn
, configVector
);
1946 cmXCodeObject
* configlist
=
1947 this->CreateObject(cmXCodeObject::XCConfigurationList
);
1948 cmXCodeObject
* buildConfigurations
=
1949 this->CreateObject(cmXCodeObject::OBJECT_LIST
);
1950 configlist
->AddAttribute("buildConfigurations", buildConfigurations
);
1951 std::string comment
= "Build configuration list for ";
1952 comment
+= cmXCodeObject::PBXTypeNames
[target
->GetIsA()];
1954 comment
+= cmtarget
.GetName();
1956 configlist
->SetComment(comment
.c_str());
1957 target
->AddAttribute("buildConfigurationList",
1958 this->CreateObjectReference(configlist
));
1959 for(unsigned int i
= 0; i
< configVector
.size(); ++i
)
1961 cmXCodeObject
* config
=
1962 this->CreateObject(cmXCodeObject::XCBuildConfiguration
);
1963 buildConfigurations
->AddObject(config
);
1964 cmXCodeObject
* buildSettings
=
1965 this->CreateObject(cmXCodeObject::ATTRIBUTE_GROUP
);
1966 this->CreateBuildSettings(cmtarget
, buildSettings
,
1967 configVector
[i
].c_str());
1968 config
->AddAttribute("name", this->CreateString(configVector
[i
].c_str()));
1969 config
->SetComment(configVector
[i
].c_str());
1970 config
->AddAttribute("buildSettings", buildSettings
);
1972 if(configVector
.size())
1974 configlist
->AddAttribute("defaultConfigurationName",
1975 this->CreateString(configVector
[0].c_str()));
1976 configlist
->AddAttribute("defaultConfigurationIsVisible",
1977 this->CreateString("0"));
1978 return configVector
[0];
1983 //----------------------------------------------------------------------------
1984 const char* cmGlobalXCodeGenerator::GetTargetFileType(cmTarget
& cmtarget
)
1986 switch(cmtarget
.GetType())
1988 case cmTarget::STATIC_LIBRARY
:
1989 return "archive.ar";
1990 case cmTarget::MODULE_LIBRARY
:
1991 return ((this->XcodeVersion
>= 22)?
1992 "compiled.mach-o.executable" : "compiled.mach-o.dylib");
1993 case cmTarget::SHARED_LIBRARY
:
1994 return (cmtarget
.GetPropertyAsBool("FRAMEWORK")?
1995 "wrapper.framework" : "compiled.mach-o.dylib");
1996 case cmTarget::EXECUTABLE
:
1997 return "compiled.mach-o.executable";
2003 //----------------------------------------------------------------------------
2004 const char* cmGlobalXCodeGenerator::GetTargetProductType(cmTarget
& cmtarget
)
2006 switch(cmtarget
.GetType())
2008 case cmTarget::STATIC_LIBRARY
:
2009 return "com.apple.product-type.library.static";
2010 case cmTarget::MODULE_LIBRARY
:
2011 return ((this->XcodeVersion
>= 22)? "com.apple.product-type.tool" :
2012 "com.apple.product-type.library.dynamic");
2013 case cmTarget::SHARED_LIBRARY
:
2014 return (cmtarget
.GetPropertyAsBool("FRAMEWORK")?
2015 "com.apple.product-type.framework" :
2016 "com.apple.product-type.library.dynamic");
2017 case cmTarget::EXECUTABLE
:
2018 return (cmtarget
.GetPropertyAsBool("MACOSX_BUNDLE")?
2019 "com.apple.product-type.application" :
2020 "com.apple.product-type.tool");
2026 //----------------------------------------------------------------------------
2028 cmGlobalXCodeGenerator::CreateXCodeTarget(cmTarget
& cmtarget
,
2029 cmXCodeObject
* buildPhases
)
2031 cmXCodeObject
* target
=
2032 this->CreateObject(cmXCodeObject::PBXNativeTarget
);
2033 target
->AddAttribute("buildPhases", buildPhases
);
2034 cmXCodeObject
* buildRules
= this->CreateObject(cmXCodeObject::OBJECT_LIST
);
2035 target
->AddAttribute("buildRules", buildRules
);
2036 std::string defConfig
;
2037 if(this->XcodeVersion
> 20)
2039 defConfig
= this->AddConfigurations(target
, cmtarget
);
2043 cmXCodeObject
* buildSettings
=
2044 this->CreateObject(cmXCodeObject::ATTRIBUTE_GROUP
);
2045 defConfig
= this->CurrentMakefile
->GetSafeDefinition("CMAKE_BUILD_TYPE");
2046 this->CreateBuildSettings(cmtarget
, buildSettings
, defConfig
.c_str());
2047 target
->AddAttribute("buildSettings", buildSettings
);
2049 cmXCodeObject
* dependencies
=
2050 this->CreateObject(cmXCodeObject::OBJECT_LIST
);
2051 target
->AddAttribute("dependencies", dependencies
);
2052 target
->AddAttribute("name", this->CreateString(cmtarget
.GetName()));
2053 target
->AddAttribute("productName",this->CreateString(cmtarget
.GetName()));
2055 cmXCodeObject
* fileRef
=
2056 this->CreateObject(cmXCodeObject::PBXFileReference
);
2057 if(const char* fileType
= this->GetTargetFileType(cmtarget
))
2059 fileRef
->AddAttribute("explicitFileType", this->CreateString(fileType
));
2061 std::string fullName
= cmtarget
.GetFullName(defConfig
.c_str());
2062 fileRef
->AddAttribute("path", this->CreateString(fullName
.c_str()));
2063 fileRef
->AddAttribute("refType", this->CreateString("0"));
2064 fileRef
->AddAttribute("sourceTree",
2065 this->CreateString("BUILT_PRODUCTS_DIR"));
2066 fileRef
->SetComment(cmtarget
.GetName());
2067 target
->AddAttribute("productReference",
2068 this->CreateObjectReference(fileRef
));
2069 if(const char* productType
= this->GetTargetProductType(cmtarget
))
2071 target
->AddAttribute("productType", this->CreateString(productType
));
2073 target
->SetTarget(&cmtarget
);
2077 //----------------------------------------------------------------------------
2078 cmXCodeObject
* cmGlobalXCodeGenerator::FindXCodeTarget(cmTarget
* t
)
2084 for(std::vector
<cmXCodeObject
*>::iterator i
= this->XCodeObjects
.begin();
2085 i
!= this->XCodeObjects
.end(); ++i
)
2087 cmXCodeObject
* o
= *i
;
2088 if(o
->GetTarget() == t
)
2096 //----------------------------------------------------------------------------
2097 void cmGlobalXCodeGenerator::AddDependTarget(cmXCodeObject
* target
,
2098 cmXCodeObject
* dependTarget
)
2100 // make sure a target does not depend on itself
2101 if(target
== dependTarget
)
2105 // now avoid circular references if dependTarget already
2106 // depends on target then skip it. Circular references crashes
2108 cmXCodeObject
* dependTargetDepends
=
2109 dependTarget
->GetObject("dependencies");
2110 if(dependTargetDepends
)
2112 if(dependTargetDepends
->HasObject(target
->GetPBXTargetDependency()))
2118 cmXCodeObject
* targetdep
= dependTarget
->GetPBXTargetDependency();
2121 cmXCodeObject
* container
=
2122 this->CreateObject(cmXCodeObject::PBXContainerItemProxy
);
2123 container
->SetComment("PBXContainerItemProxy");
2124 container
->AddAttribute("containerPortal",
2125 this->CreateObjectReference(this->RootObject
));
2126 container
->AddAttribute("proxyType", this->CreateString("1"));
2127 container
->AddAttribute("remoteGlobalIDString",
2128 this->CreateObjectReference(dependTarget
));
2129 container
->AddAttribute("remoteInfo",
2131 dependTarget
->GetTarget()->GetName()));
2133 this->CreateObject(cmXCodeObject::PBXTargetDependency
);
2134 targetdep
->SetComment("PBXTargetDependency");
2135 targetdep
->AddAttribute("target",
2136 this->CreateObjectReference(dependTarget
));
2137 targetdep
->AddAttribute("targetProxy",
2138 this->CreateObjectReference(container
));
2139 dependTarget
->SetPBXTargetDependency(targetdep
);
2142 cmXCodeObject
* depends
= target
->GetObject("dependencies");
2146 Error("target does not have dependencies attribute error..");
2151 depends
->AddUniqueObject(targetdep
);
2155 //----------------------------------------------------------------------------
2156 void cmGlobalXCodeGenerator::AppendOrAddBuildSetting(cmXCodeObject
* settings
,
2157 const char* attribute
,
2162 cmXCodeObject
* attr
= settings
->GetObject(attribute
);
2165 settings
->AddAttribute(attribute
, this->CreateString(value
));
2169 std::string oldValue
= attr
->GetString();
2172 attr
->SetString(oldValue
.c_str());
2177 //----------------------------------------------------------------------------
2178 void cmGlobalXCodeGenerator
2179 ::AppendBuildSettingAttribute(cmXCodeObject
* target
,
2180 const char* attribute
,
2182 const char* configName
)
2184 if(this->XcodeVersion
< 21)
2186 // There is only one configuration. Add the setting to the buildSettings
2188 this->AppendOrAddBuildSetting(target
->GetObject("buildSettings"),
2193 // There are multiple configurations. Add the setting to the
2194 // buildSettings of the configuration name given.
2195 cmXCodeObject
* configurationList
=
2196 target
->GetObject("buildConfigurationList")->GetObject();
2197 cmXCodeObject
* buildConfigs
=
2198 configurationList
->GetObject("buildConfigurations");
2199 std::vector
<cmXCodeObject
*> list
= buildConfigs
->GetObjectList();
2200 // each configuration and the target itself has a buildSettings in it
2201 //list.push_back(target);
2202 for(std::vector
<cmXCodeObject
*>::iterator i
= list
.begin();
2203 i
!= list
.end(); ++i
)
2207 if(strcmp((*i
)->GetObject("name")->GetString(), configName
) == 0)
2209 cmXCodeObject
* settings
= (*i
)->GetObject("buildSettings");
2210 this->AppendOrAddBuildSetting(settings
, attribute
, value
);
2215 cmXCodeObject
* settings
= (*i
)->GetObject("buildSettings");
2216 this->AppendOrAddBuildSetting(settings
, attribute
, value
);
2222 //----------------------------------------------------------------------------
2223 void cmGlobalXCodeGenerator
2224 ::AddDependAndLinkInformation(cmXCodeObject
* target
)
2226 cmTarget
* cmtarget
= target
->GetTarget();
2229 cmSystemTools::Error("Error no target on xobject\n");
2233 // Add dependencies on other CMake targets.
2234 TargetDependSet
const& deps
= this->GetTargetDirectDepends(*cmtarget
);
2235 for(TargetDependSet::const_iterator i
= deps
.begin(); i
!= deps
.end(); ++i
)
2237 if(cmXCodeObject
* dptarget
= this->FindXCodeTarget(*i
))
2239 this->AddDependTarget(target
, dptarget
);
2243 // Skip link information for static libraries.
2244 if(cmtarget
->GetType() == cmTarget::STATIC_LIBRARY
)
2249 // Loop over configuration types and set per-configuration info.
2250 for(std::vector
<std::string
>::iterator i
=
2251 this->CurrentConfigurationTypes
.begin();
2252 i
!= this->CurrentConfigurationTypes
.end(); ++i
)
2254 // Get the current configuration name.
2255 const char* configName
= i
->c_str();
2261 // Compute the link library and directory information.
2262 cmComputeLinkInformation
* pcli
= cmtarget
->GetLinkInformation(configName
);
2267 cmComputeLinkInformation
& cli
= *pcli
;
2269 // Add dependencies directly on library files.
2271 std::vector
<std::string
> const& libDeps
= cli
.GetDepends();
2272 for(std::vector
<std::string
>::const_iterator j
= libDeps
.begin();
2273 j
!= libDeps
.end(); ++j
)
2275 target
->AddDependLibrary(configName
, j
->c_str());
2279 // add the library search paths
2281 std::vector
<std::string
> const& libDirs
= cli
.GetDirectories();
2282 std::string linkDirs
;
2283 for(std::vector
<std::string
>::const_iterator libDir
= libDirs
.begin();
2284 libDir
!= libDirs
.end(); ++libDir
)
2286 if(libDir
->size() && *libDir
!= "/usr/lib")
2288 if(this->XcodeVersion
> 15)
2290 // now add the same one but append $(CONFIGURATION) to it:
2292 linkDirs
+= this->XCodeEscapePath(
2293 (*libDir
+ "/$(CONFIGURATION)").c_str());
2296 linkDirs
+= this->XCodeEscapePath(libDir
->c_str());
2299 this->AppendBuildSettingAttribute(target
, "LIBRARY_SEARCH_PATHS",
2300 linkDirs
.c_str(), configName
);
2303 // add the framework search paths
2305 const char* sep
= "";
2307 std::vector
<std::string
> const& fwDirs
= cli
.GetFrameworkPaths();
2308 for(std::vector
<std::string
>::const_iterator fdi
= fwDirs
.begin();
2309 fdi
!= fwDirs
.end(); ++fdi
)
2313 fdirs
+= this->XCodeEscapePath(fdi
->c_str());
2317 this->AppendBuildSettingAttribute(target
, "FRAMEWORK_SEARCH_PATHS",
2318 fdirs
.c_str(), configName
);
2322 // now add the link libraries
2324 std::string linkLibs
;
2325 const char* sep
= "";
2326 typedef cmComputeLinkInformation::ItemVector ItemVector
;
2327 ItemVector
const& libNames
= cli
.GetItems();
2328 for(ItemVector::const_iterator li
= libNames
.begin();
2329 li
!= libNames
.end(); ++li
)
2335 linkLibs
+= this->XCodeEscapePath(li
->Value
.c_str());
2339 linkLibs
+= li
->Value
;
2342 this->AppendBuildSettingAttribute(target
, "OTHER_LDFLAGS",
2343 linkLibs
.c_str(), configName
);
2348 //----------------------------------------------------------------------------
2349 void cmGlobalXCodeGenerator::CreateGroups(cmLocalGenerator
* root
,
2350 std::vector
<cmLocalGenerator
*>&
2353 for(std::vector
<cmLocalGenerator
*>::iterator i
= generators
.begin();
2354 i
!= generators
.end(); ++i
)
2356 if(this->IsExcluded(root
, *i
))
2360 cmMakefile
* mf
= (*i
)->GetMakefile();
2361 std::vector
<cmSourceGroup
> sourceGroups
= mf
->GetSourceGroups();
2362 cmTargets
&tgts
= mf
->GetTargets();
2363 for(cmTargets::iterator l
= tgts
.begin(); l
!= tgts
.end(); l
++)
2365 cmTarget
& cmtarget
= l
->second
;
2367 // Same skipping logic here as in CreateXCodeTargets so that we do not
2368 // end up with (empty anyhow) ALL_BUILD and XCODE_DEPEND_HELPER source
2371 if(cmtarget
.GetType() == cmTarget::GLOBAL_TARGET
)
2376 // add the soon to be generated Info.plist file as a source for a
2377 // MACOSX_BUNDLE file
2378 if(cmtarget
.GetPropertyAsBool("MACOSX_BUNDLE"))
2380 std::string plist
= this->ComputeInfoPListLocation(cmtarget
);
2381 cmSourceFile
* sf
= mf
->GetOrCreateSource(plist
.c_str(), true);
2382 cmtarget
.AddSourceFile(sf
);
2385 std::vector
<cmSourceFile
*> classes
= cmtarget
.GetSourceFiles();
2387 for(std::vector
<cmSourceFile
*>::const_iterator s
= classes
.begin();
2388 s
!= classes
.end(); s
++)
2390 cmSourceFile
* sf
= *s
;
2391 // Add the file to the list of sources.
2392 std::string
const& source
= sf
->GetFullPath();
2393 cmSourceGroup
& sourceGroup
=
2394 mf
->FindSourceGroup(source
.c_str(), sourceGroups
);
2395 cmXCodeObject
* pbxgroup
=
2396 this->CreateOrGetPBXGroup(cmtarget
, &sourceGroup
);
2397 cmStdString key
= GetGroupMapKey(cmtarget
, sf
);
2398 this->GroupMap
[key
] = pbxgroup
;
2404 //----------------------------------------------------------------------------
2405 cmXCodeObject
* cmGlobalXCodeGenerator
2406 ::CreateOrGetPBXGroup(cmTarget
& cmtarget
, cmSourceGroup
* sg
)
2408 cmStdString s
= cmtarget
.GetName();
2411 std::map
<cmStdString
, cmXCodeObject
* >::iterator i
=
2412 this->GroupNameMap
.find(s
);
2413 if(i
!= this->GroupNameMap
.end())
2417 i
= this->TargetGroup
.find(cmtarget
.GetName());
2418 cmXCodeObject
* tgroup
= 0;
2419 if(i
!= this->TargetGroup
.end())
2425 tgroup
= this->CreateObject(cmXCodeObject::PBXGroup
);
2426 this->TargetGroup
[cmtarget
.GetName()] = tgroup
;
2427 cmXCodeObject
* tgroupChildren
=
2428 this->CreateObject(cmXCodeObject::OBJECT_LIST
);
2429 tgroup
->AddAttribute("name", this->CreateString(cmtarget
.GetName()));
2430 tgroup
->AddAttribute("children", tgroupChildren
);
2431 if(this->XcodeVersion
== 15)
2433 tgroup
->AddAttribute("refType", this->CreateString("4"));
2435 tgroup
->AddAttribute("sourceTree", this->CreateString("<group>"));
2436 this->SourcesGroupChildren
->AddObject(tgroup
);
2439 // If it's the default source group (empty name) then put the source file
2440 // directly in the tgroup...
2442 if (cmStdString(sg
->GetName()) == "")
2444 this->GroupNameMap
[s
] = tgroup
;
2448 cmXCodeObject
* tgroupChildren
= tgroup
->GetObject("children");
2449 cmXCodeObject
* group
= this->CreateObject(cmXCodeObject::PBXGroup
);
2450 cmXCodeObject
* groupChildren
=
2451 this->CreateObject(cmXCodeObject::OBJECT_LIST
);
2452 group
->AddAttribute("name", this->CreateString(sg
->GetName()));
2453 group
->AddAttribute("children", groupChildren
);
2454 if(this->XcodeVersion
== 15)
2456 group
->AddAttribute("refType", this->CreateString("4"));
2458 group
->AddAttribute("sourceTree", this->CreateString("<group>"));
2459 tgroupChildren
->AddObject(group
);
2460 this->GroupNameMap
[s
] = group
;
2464 //----------------------------------------------------------------------------
2465 void cmGlobalXCodeGenerator
2466 ::CreateXCodeObjects(cmLocalGenerator
* root
,
2467 std::vector
<cmLocalGenerator
*>&
2470 this->ClearXCodeObjects();
2471 this->RootObject
= 0;
2472 this->SourcesGroupChildren
= 0;
2473 this->ResourcesGroupChildren
= 0;
2474 this->MainGroupChildren
= 0;
2475 cmXCodeObject
* group
= this->CreateObject(cmXCodeObject::ATTRIBUTE_GROUP
);
2476 group
->AddAttribute("COPY_PHASE_STRIP", this->CreateString("NO"));
2477 cmXCodeObject
* developBuildStyle
=
2478 this->CreateObject(cmXCodeObject::PBXBuildStyle
);
2479 cmXCodeObject
* listObjs
= this->CreateObject(cmXCodeObject::OBJECT_LIST
);
2480 if(this->XcodeVersion
== 15)
2482 developBuildStyle
->AddAttribute("name",
2483 this->CreateString("Development"));
2484 developBuildStyle
->AddAttribute("buildSettings", group
);
2485 listObjs
->AddObject(developBuildStyle
);
2486 group
= this->CreateObject(cmXCodeObject::ATTRIBUTE_GROUP
);
2487 group
->AddAttribute("COPY_PHASE_STRIP", this->CreateString("YES"));
2488 cmXCodeObject
* deployBuildStyle
=
2489 this->CreateObject(cmXCodeObject::PBXBuildStyle
);
2490 deployBuildStyle
->AddAttribute("name", this->CreateString("Deployment"));
2491 deployBuildStyle
->AddAttribute("buildSettings", group
);
2492 listObjs
->AddObject(deployBuildStyle
);
2496 for(unsigned int i
= 0; i
< this->CurrentConfigurationTypes
.size(); ++i
)
2498 cmXCodeObject
* buildStyle
=
2499 this->CreateObject(cmXCodeObject::PBXBuildStyle
);
2500 const char* name
= this->CurrentConfigurationTypes
[i
].c_str();
2501 buildStyle
->AddAttribute("name", this->CreateString(name
));
2502 buildStyle
->SetComment(name
);
2503 cmXCodeObject
* sgroup
=
2504 this->CreateObject(cmXCodeObject::ATTRIBUTE_GROUP
);
2505 sgroup
->AddAttribute("COPY_PHASE_STRIP", this->CreateString("NO"));
2506 buildStyle
->AddAttribute("buildSettings", sgroup
);
2507 listObjs
->AddObject(buildStyle
);
2511 cmXCodeObject
* mainGroup
= this->CreateObject(cmXCodeObject::PBXGroup
);
2512 this->MainGroupChildren
=
2513 this->CreateObject(cmXCodeObject::OBJECT_LIST
);
2514 mainGroup
->AddAttribute("children", this->MainGroupChildren
);
2515 if(this->XcodeVersion
== 15)
2517 mainGroup
->AddAttribute("refType", this->CreateString("4"));
2519 mainGroup
->AddAttribute("sourceTree", this->CreateString("<group>"));
2521 cmXCodeObject
* sourcesGroup
= this->CreateObject(cmXCodeObject::PBXGroup
);
2522 this->SourcesGroupChildren
=
2523 this->CreateObject(cmXCodeObject::OBJECT_LIST
);
2524 sourcesGroup
->AddAttribute("name", this->CreateString("Sources"));
2525 sourcesGroup
->AddAttribute("children", this->SourcesGroupChildren
);
2526 if(this->XcodeVersion
== 15)
2528 sourcesGroup
->AddAttribute("refType", this->CreateString("4"));
2530 sourcesGroup
->AddAttribute("sourceTree", this->CreateString("<group>"));
2531 this->MainGroupChildren
->AddObject(sourcesGroup
);
2533 cmXCodeObject
* resourcesGroup
= this->CreateObject(cmXCodeObject::PBXGroup
);
2534 this->ResourcesGroupChildren
=
2535 this->CreateObject(cmXCodeObject::OBJECT_LIST
);
2536 resourcesGroup
->AddAttribute("name", this->CreateString("Resources"));
2537 resourcesGroup
->AddAttribute("children", this->ResourcesGroupChildren
);
2538 if(this->XcodeVersion
== 15)
2540 resourcesGroup
->AddAttribute("refType", this->CreateString("4"));
2542 resourcesGroup
->AddAttribute("sourceTree", this->CreateString("<group>"));
2543 this->MainGroupChildren
->AddObject(resourcesGroup
);
2545 // now create the cmake groups
2546 this->CreateGroups(root
, generators
);
2548 cmXCodeObject
* productGroup
= this->CreateObject(cmXCodeObject::PBXGroup
);
2549 productGroup
->AddAttribute("name", this->CreateString("Products"));
2550 if(this->XcodeVersion
== 15)
2552 productGroup
->AddAttribute("refType", this->CreateString("4"));
2554 productGroup
->AddAttribute("sourceTree", this->CreateString("<group>"));
2555 cmXCodeObject
* productGroupChildren
=
2556 this->CreateObject(cmXCodeObject::OBJECT_LIST
);
2557 productGroup
->AddAttribute("children", productGroupChildren
);
2558 this->MainGroupChildren
->AddObject(productGroup
);
2561 this->RootObject
= this->CreateObject(cmXCodeObject::PBXProject
);
2562 this->RootObject
->SetComment("Project object");
2563 group
= this->CreateObject(cmXCodeObject::ATTRIBUTE_GROUP
);
2564 this->RootObject
->AddAttribute("mainGroup",
2565 this->CreateObjectReference(mainGroup
));
2566 this->RootObject
->AddAttribute("buildSettings", group
);
2567 this->RootObject
->AddAttribute("buildStyles", listObjs
);
2568 this->RootObject
->AddAttribute("hasScannedForEncodings",
2569 this->CreateString("0"));
2570 if (this->XcodeVersion
>= 30)
2572 group
= this->CreateObject(cmXCodeObject::ATTRIBUTE_GROUP
);
2573 group
->AddAttribute("BuildIndependentTargetsInParallel",
2574 this->CreateString("YES"));
2575 this->RootObject
->AddAttribute("attributes", group
);
2576 if (this->XcodeVersion
>= 31)
2577 this->RootObject
->AddAttribute("compatibilityVersion",
2578 this->CreateString("Xcode 3.1"));
2580 this->RootObject
->AddAttribute("compatibilityVersion",
2581 this->CreateString("Xcode 3.0"));
2583 // Point Xcode at the top of the source tree.
2586 this->RelativeToBinary(root
->GetMakefile()->GetCurrentDirectory());
2587 this->RootObject
->AddAttribute("projectDirPath",
2588 this->CreateString(pdir
.c_str()));
2589 this->RootObject
->AddAttribute("projectRoot", this->CreateString(""));
2591 cmXCodeObject
* configlist
=
2592 this->CreateObject(cmXCodeObject::XCConfigurationList
);
2593 cmXCodeObject
* buildConfigurations
=
2594 this->CreateObject(cmXCodeObject::OBJECT_LIST
);
2595 std::vector
<cmXCodeObject
*> configs
;
2596 if(this->XcodeVersion
== 15)
2598 cmXCodeObject
* configDebug
=
2599 this->CreateObject(cmXCodeObject::XCBuildConfiguration
);
2600 configDebug
->AddAttribute("name", this->CreateString("Debug"));
2601 configs
.push_back(configDebug
);
2602 cmXCodeObject
* configRelease
=
2603 this->CreateObject(cmXCodeObject::XCBuildConfiguration
);
2604 configRelease
->AddAttribute("name", this->CreateString("Release"));
2605 configs
.push_back(configRelease
);
2609 for(unsigned int i
= 0; i
< this->CurrentConfigurationTypes
.size(); ++i
)
2611 const char* name
= this->CurrentConfigurationTypes
[i
].c_str();
2612 cmXCodeObject
* config
=
2613 this->CreateObject(cmXCodeObject::XCBuildConfiguration
);
2614 config
->AddAttribute("name", this->CreateString(name
));
2615 configs
.push_back(config
);
2618 for(std::vector
<cmXCodeObject
*>::iterator c
= configs
.begin();
2619 c
!= configs
.end(); ++c
)
2621 buildConfigurations
->AddObject(*c
);
2623 configlist
->AddAttribute("buildConfigurations", buildConfigurations
);
2625 std::string comment
= "Build configuration list for PBXProject ";
2627 comment
+= this->CurrentProject
;
2629 configlist
->SetComment(comment
.c_str());
2630 configlist
->AddAttribute("defaultConfigurationIsVisible",
2631 this->CreateString("0"));
2632 configlist
->AddAttribute("defaultConfigurationName",
2633 this->CreateString("Debug"));
2634 cmXCodeObject
* buildSettings
=
2635 this->CreateObject(cmXCodeObject::ATTRIBUTE_GROUP
);
2636 const char* osxArch
=
2637 this->CurrentMakefile
->GetDefinition("CMAKE_OSX_ARCHITECTURES");
2638 if(strlen(osxArch
) == 0)
2640 if(this->XcodeVersion
>= 32)
2642 osxArch
= "$(ARCHS_STANDARD_32_64_BIT)";
2644 else if(this->XcodeVersion
<= 25)
2655 osxArch
= "$(ARCHS_STANDARD_32_BIT)";
2657 buildSettings
->AddAttribute("ONLY_ACTIVE_ARCH",
2658 this->CreateString("YES"));
2661 const char* sysroot
=
2662 this->CurrentMakefile
->GetDefinition("CMAKE_OSX_SYSROOT");
2663 const char* sysrootDefault
=
2664 this->CurrentMakefile
->GetDefinition("CMAKE_OSX_SYSROOT_DEFAULT");
2665 const char* deploymentTarget
=
2666 this->CurrentMakefile
->GetDefinition("CMAKE_OSX_DEPLOYMENT_TARGET");
2667 if(osxArch
&& sysroot
)
2669 bool flagsUsed
= false;
2670 // recompute this as it may have been changed since enable language
2671 this->Architectures
.clear();
2672 cmSystemTools::ExpandListArgument(std::string(osxArch
),
2673 this->Architectures
);
2675 buildSettings
->AddAttribute("SDKROOT",
2676 this->CreateString(sysroot
));
2677 std::string archString
;
2678 for( std::vector
<std::string
>::iterator i
=
2679 this->Architectures
.begin();
2680 i
!= this->Architectures
.end(); ++i
)
2685 buildSettings
->AddAttribute("ARCHS",
2686 this->CreateString(archString
.c_str()));
2687 if(!flagsUsed
&& sysrootDefault
&&
2688 strcmp(sysroot
, sysrootDefault
) != 0)
2690 buildSettings
->AddAttribute("SDKROOT",
2691 this->CreateString(sysroot
));
2694 if(deploymentTarget
&& *deploymentTarget
)
2696 buildSettings
->AddAttribute("MACOSX_DEPLOYMENT_TARGET",
2697 this->CreateString(deploymentTarget
));
2700 std::string symroot
= root
->GetMakefile()->GetCurrentOutputDirectory();
2701 symroot
+= "/build";
2702 buildSettings
->AddAttribute("SYMROOT", this->CreateString(symroot
.c_str()));
2704 for( std::vector
<cmXCodeObject
*>::iterator i
= configs
.begin();
2705 i
!= configs
.end(); ++i
)
2707 (*i
)->AddAttribute("buildSettings", buildSettings
);
2710 this->RootObject
->AddAttribute("buildConfigurationList",
2711 this->CreateObjectReference(configlist
));
2713 std::vector
<cmXCodeObject
*> targets
;
2714 for(std::vector
<cmLocalGenerator
*>::iterator i
= generators
.begin();
2715 i
!= generators
.end(); ++i
)
2717 if(!this->IsExcluded(root
, *i
))
2719 this->CreateXCodeTargets(*i
, targets
);
2722 // loop over all targets and add link and depend info
2723 for(std::vector
<cmXCodeObject
*>::iterator i
= targets
.begin();
2724 i
!= targets
.end(); ++i
)
2726 cmXCodeObject
* t
= *i
;
2727 this->AddDependAndLinkInformation(t
);
2729 // now create xcode depend hack makefile
2730 this->CreateXCodeDependHackTarget(targets
);
2731 // now add all targets to the root object
2732 cmXCodeObject
* allTargets
= this->CreateObject(cmXCodeObject::OBJECT_LIST
);
2733 for(std::vector
<cmXCodeObject
*>::iterator i
= targets
.begin();
2734 i
!= targets
.end(); ++i
)
2736 cmXCodeObject
* t
= *i
;
2737 allTargets
->AddObject(t
);
2738 cmXCodeObject
* productRef
= t
->GetObject("productReference");
2741 productGroupChildren
->AddObject(productRef
->GetObject());
2744 this->RootObject
->AddAttribute("targets", allTargets
);
2747 //----------------------------------------------------------------------------
2749 cmGlobalXCodeGenerator::CreateXCodeDependHackTarget(
2750 std::vector
<cmXCodeObject
*>& targets
)
2752 cmGeneratedFileStream
2753 makefileStream(this->CurrentXCodeHackMakefile
.c_str());
2756 cmSystemTools::Error("Could not create",
2757 this->CurrentXCodeHackMakefile
.c_str());
2760 makefileStream
.SetCopyIfDifferent(true);
2761 // one more pass for external depend information not handled
2762 // correctly by xcode
2763 makefileStream
<< "# DO NOT EDIT\n";
2764 makefileStream
<< "# This makefile makes sure all linkable targets are\n";
2765 makefileStream
<< "# up-to-date with anything they link to, avoiding a "
2766 "bug in XCode 1.5\n";
2767 for(std::vector
<std::string
>::const_iterator
2768 ct
= this->CurrentConfigurationTypes
.begin();
2769 ct
!= this->CurrentConfigurationTypes
.end(); ++ct
)
2771 if(this->XcodeVersion
< 21 || ct
->empty())
2773 makefileStream
<< "all: ";
2777 makefileStream
<< "all." << *ct
<< ": ";
2779 const char* configName
= 0;
2782 configName
= ct
->c_str();
2784 for(std::vector
<cmXCodeObject
*>::iterator i
= targets
.begin();
2785 i
!= targets
.end(); ++i
)
2787 cmXCodeObject
* target
= *i
;
2788 cmTarget
* t
=target
->GetTarget();
2789 if(t
->GetType() == cmTarget::EXECUTABLE
||
2790 t
->GetType() == cmTarget::SHARED_LIBRARY
||
2791 t
->GetType() == cmTarget::MODULE_LIBRARY
)
2793 std::string tfull
= t
->GetFullPath(configName
);
2794 makefileStream
<< "\\\n\t" <<
2795 this->ConvertToRelativeForMake(tfull
.c_str());
2798 makefileStream
<< "\n\n";
2801 << "# For each target create a dummy rule "
2802 "so the target does not have to exist\n";
2803 std::set
<cmStdString
> emitted
;
2804 for(std::vector
<cmXCodeObject
*>::iterator i
= targets
.begin();
2805 i
!= targets
.end(); ++i
)
2807 cmXCodeObject
* target
= *i
;
2808 std::map
<cmStdString
, cmXCodeObject::StringVec
> const& deplibs
=
2809 target
->GetDependLibraries();
2810 for(std::map
<cmStdString
, cmXCodeObject::StringVec
>::const_iterator ci
2811 = deplibs
.begin(); ci
!= deplibs
.end(); ++ci
)
2813 for(cmXCodeObject::StringVec::const_iterator d
= ci
->second
.begin();
2814 d
!= ci
->second
.end(); ++d
)
2816 if(emitted
.insert(*d
).second
)
2819 this->ConvertToRelativeForMake(d
->c_str()) << ":\n";
2824 makefileStream
<< "\n\n";
2826 // Write rules to help Xcode relink things at the right time.
2828 "# Rules to remove targets that are older than anything to which they\n"
2829 "# link. This forces Xcode to relink the targets from scratch. It\n"
2830 "# does not seem to check these dependencies itself.\n";
2831 for(std::vector
<std::string
>::const_iterator
2832 ct
= this->CurrentConfigurationTypes
.begin();
2833 ct
!= this->CurrentConfigurationTypes
.end(); ++ct
)
2835 const char* configName
= 0;
2838 configName
= ct
->c_str();
2840 for(std::vector
<cmXCodeObject
*>::iterator i
= targets
.begin();
2841 i
!= targets
.end(); ++i
)
2843 cmXCodeObject
* target
= *i
;
2844 cmTarget
* t
=target
->GetTarget();
2845 if(t
->GetType() == cmTarget::EXECUTABLE
||
2846 t
->GetType() == cmTarget::SHARED_LIBRARY
||
2847 t
->GetType() == cmTarget::MODULE_LIBRARY
)
2849 // Create a rule for this target.
2850 std::string tfull
= t
->GetFullPath(configName
);
2851 makefileStream
<< this->ConvertToRelativeForMake(tfull
.c_str())
2854 // List dependencies if any exist.
2855 std::map
<cmStdString
, cmXCodeObject::StringVec
>::const_iterator
2856 x
= target
->GetDependLibraries().find(*ct
);
2857 if(x
!= target
->GetDependLibraries().end())
2859 std::vector
<cmStdString
> const& deplibs
= x
->second
;
2860 for(std::vector
<cmStdString
>::const_iterator d
= deplibs
.begin();
2861 d
!= deplibs
.end(); ++d
)
2863 makefileStream
<< "\\\n\t" <<
2864 this->ConvertToRelativeForMake(d
->c_str());
2867 // Write the action to remove the target if it is out of date.
2868 makefileStream
<< "\n";
2869 makefileStream
<< "\t/bin/rm -f "
2870 << this->ConvertToRelativeForMake(tfull
.c_str())
2872 // if building for more than one architecture
2873 // then remove those exectuables as well
2874 if(this->Architectures
.size() > 1)
2876 std::string universal
= t
->GetDirectory();
2878 universal
+= this->CurrentProject
;
2879 universal
+= ".build/";
2880 universal
+= configName
;
2882 universal
+= t
->GetName();
2883 universal
+= ".build/Objects-normal/";
2884 for( std::vector
<std::string
>::iterator arch
=
2885 this->Architectures
.begin();
2886 arch
!= this->Architectures
.end(); ++arch
)
2888 std::string universalFile
= universal
;
2889 universalFile
+= *arch
;
2890 universalFile
+= "/";
2891 universalFile
+= t
->GetFullName(configName
);
2892 makefileStream
<< "\t/bin/rm -f "
2894 this->ConvertToRelativeForMake(universalFile
.c_str())
2898 makefileStream
<< "\n\n";
2904 //----------------------------------------------------------------------------
2906 cmGlobalXCodeGenerator::OutputXCodeProject(cmLocalGenerator
* root
,
2907 std::vector
<cmLocalGenerator
*>&
2910 if(generators
.size() == 0)
2914 // Skip local generators that are excluded from this project.
2915 for(std::vector
<cmLocalGenerator
*>::iterator g
= generators
.begin();
2916 g
!= generators
.end(); ++g
)
2918 if(this->IsExcluded(root
, *g
))
2924 this->CreateXCodeObjects(root
,
2926 std::string xcodeDir
= root
->GetMakefile()->GetStartOutputDirectory();
2928 xcodeDir
+= root
->GetMakefile()->GetProjectName();
2929 xcodeDir
+= ".xcode";
2930 if(this->XcodeVersion
> 20)
2934 cmSystemTools::MakeDirectory(xcodeDir
.c_str());
2935 std::string xcodeProjFile
= xcodeDir
+ "/project.pbxproj";
2936 cmGeneratedFileStream
fout(xcodeProjFile
.c_str());
2937 fout
.SetCopyIfDifferent(true);
2942 this->WriteXCodePBXProj(fout
, root
, generators
);
2943 this->ClearXCodeObjects();
2946 //----------------------------------------------------------------------------
2948 cmGlobalXCodeGenerator::WriteXCodePBXProj(std::ostream
& fout
,
2950 std::vector
<cmLocalGenerator
*>& )
2952 fout
<< "// !$*UTF8*$!\n";
2954 cmXCodeObject::Indent(1, fout
);
2955 fout
<< "archiveVersion = 1;\n";
2956 cmXCodeObject::Indent(1, fout
);
2957 fout
<< "classes = {\n";
2958 cmXCodeObject::Indent(1, fout
);
2960 cmXCodeObject::Indent(1, fout
);
2961 if(this->XcodeVersion
>= 21)
2963 if (this->XcodeVersion
>= 31)
2964 fout
<< "objectVersion = 45;\n";
2965 else if (this->XcodeVersion
>= 30)
2966 fout
<< "objectVersion = 44;\n";
2968 fout
<< "objectVersion = 42;\n";
2969 cmXCode21Object::PrintList(this->XCodeObjects
, fout
);
2973 fout
<< "objectVersion = 39;\n";
2974 cmXCodeObject::PrintList(this->XCodeObjects
, fout
);
2976 cmXCodeObject::Indent(1, fout
);
2977 fout
<< "rootObject = " << this->RootObject
->GetId() << ";\n";
2981 //----------------------------------------------------------------------------
2982 const char* cmGlobalXCodeGenerator::GetCMakeCFGInitDirectory()
2984 return this->XcodeVersion
>= 21? "$(CONFIGURATION)" : ".";
2987 //----------------------------------------------------------------------------
2988 void cmGlobalXCodeGenerator::GetDocumentation(cmDocumentationEntry
& entry
)
2991 entry
.Name
= this->GetName();
2992 entry
.Brief
= "Generate XCode project files.";
2996 //----------------------------------------------------------------------------
2997 std::string
cmGlobalXCodeGenerator::ConvertToRelativeForMake(const char* p
)
2999 if ( !this->CurrentMakefile
->IsOn("CMAKE_USE_RELATIVE_PATHS") )
3001 return cmSystemTools::ConvertToOutputPath(p
);
3006 this->CurrentLocalGenerator
->
3007 ConvertToRelativePath(this->CurrentOutputDirectoryComponents
, p
);
3008 return cmSystemTools::ConvertToOutputPath(ret
.c_str());
3012 //----------------------------------------------------------------------------
3013 std::string
cmGlobalXCodeGenerator::ConvertToRelativeForXCode(const char* p
)
3015 if ( !this->CurrentMakefile
->IsOn("CMAKE_USE_RELATIVE_PATHS") )
3017 return cmSystemTools::ConvertToOutputPath(p
);
3022 this->CurrentLocalGenerator
->
3023 ConvertToRelativePath(this->ProjectOutputDirectoryComponents
, p
);
3024 return cmSystemTools::ConvertToOutputPath(ret
.c_str());
3028 //----------------------------------------------------------------------------
3029 std::string
cmGlobalXCodeGenerator::RelativeToSource(const char* p
)
3031 // We force conversion because Xcode breakpoints do not work unless
3032 // they are in a file named relative to the source tree.
3033 return this->CurrentLocalGenerator
->
3034 ConvertToRelativePath(this->ProjectSourceDirectoryComponents
, p
, true);
3037 //----------------------------------------------------------------------------
3038 std::string
cmGlobalXCodeGenerator::RelativeToBinary(const char* p
)
3040 return this->CurrentLocalGenerator
->
3041 ConvertToRelativePath(this->ProjectOutputDirectoryComponents
, p
);
3044 //----------------------------------------------------------------------------
3045 std::string
cmGlobalXCodeGenerator::XCodeEscapePath(const char* p
)
3047 std::string ret
= p
;
3048 if(ret
.find(' ') != ret
.npos
)
3050 std::string t
= ret
;
3058 //----------------------------------------------------------------------------
3059 void cmGlobalXCodeGenerator::
3060 GetTargetObjectFileDirectories(cmTarget
* target
,
3061 std::vector
<std::string
>&
3064 std::string dir
= this->CurrentMakefile
->GetCurrentOutputDirectory();
3066 dir
+= this->CurrentMakefile
->GetProjectName();
3068 dir
+= this->GetCMakeCFGInitDirectory();
3070 dir
+= target
->GetName();
3071 dir
+= ".build/Objects-normal/";
3072 std::string dirsave
= dir
;
3073 if(this->Architectures
.size())
3075 for(std::vector
<std::string
>::iterator i
= this->Architectures
.begin();
3076 i
!= this->Architectures
.end(); ++i
)
3079 dirs
.push_back(dir
);
3085 dirs
.push_back(dir
);
3089 //----------------------------------------------------------------------------
3091 cmGlobalXCodeGenerator
3092 ::AppendDirectoryForConfig(const char* prefix
,
3097 if(this->XcodeVersion
> 20)
3108 //----------------------------------------------------------------------------
3109 std::string
cmGlobalXCodeGenerator::LookupFlags(const char* varNamePrefix
,
3110 const char* varNameLang
,
3111 const char* varNameSuffix
,
3112 const char* default_flags
)
3116 std::string varName
= varNamePrefix
;
3117 varName
+= varNameLang
;
3118 varName
+= varNameSuffix
;
3119 if(const char* varValue
=
3120 this->CurrentMakefile
->GetDefinition(varName
.c_str()))
3128 return default_flags
;
3131 //----------------------------------------------------------------------------
3132 void cmGlobalXCodeGenerator::AppendDefines(BuildObjectListOrString
& defs
,
3133 const char* defines_list
,
3136 // Skip this if there are no definitions.
3142 // Expand the list of definitions.
3143 std::vector
<std::string
> defines
;
3144 cmSystemTools::ExpandListArgument(defines_list
, defines
);
3146 // Store the definitions in the string.
3147 this->AppendDefines(defs
, defines
, dflag
);
3150 //----------------------------------------------------------------------------
3152 cmGlobalXCodeGenerator::AppendDefines(BuildObjectListOrString
& defs
,
3153 std::vector
<std::string
> const& defines
,
3156 // GCC_PREPROCESSOR_DEFINITIONS is a space-separated list of definitions.
3158 for(std::vector
<std::string
>::const_iterator di
= defines
.begin();
3159 di
!= defines
.end(); ++di
)
3161 // Start with -D if requested.
3162 def
= dflag
? "-D": "";
3165 // Append the flag with needed escapes.
3167 this->AppendFlag(tmp
, def
);
3168 defs
.Add(tmp
.c_str());
3172 //----------------------------------------------------------------------------
3173 void cmGlobalXCodeGenerator::AppendFlag(std::string
& flags
,
3174 std::string
const& flag
)
3176 // Short-circuit for an empty flag.
3182 // Separate from previous flags.
3188 // Check if the flag needs quoting.
3190 flag
.find_first_of("`~!@#$%^&*()+={}[]|:;\"'<>,.? ") != flag
.npos
;
3192 // We escape a flag as follows:
3193 // - Place each flag in single quotes ''
3194 // - Escape a single quote as \\'
3195 // - Escape a backslash as \\\\ since it itself is an escape
3196 // Note that in the code below we need one more level of escapes for
3197 // C string syntax in this source file.
3199 // The final level of escaping is done when the string is stored
3200 // into the project file by cmXCodeObject::PrintString.
3204 // Open single quote.
3208 // Flag value with escaped quotes and backslashes.
3209 for(const char* c
= flag
.c_str(); *c
; ++c
)
3217 flags
+= "\\\\\\\\";
3227 // Close single quote.
3232 //----------------------------------------------------------------------------
3234 cmGlobalXCodeGenerator::ComputeInfoPListLocation(cmTarget
& target
)
3236 std::string plist
= target
.GetMakefile()->GetCurrentOutputDirectory();
3237 plist
+= cmake::GetCMakeFilesDirectory();
3239 plist
+= target
.GetName();
3240 plist
+= ".dir/Info.plist";