1 /*=========================================================================
3 Program: CMake - Cross-Platform Makefile Generator
4 Module: $RCSfile: cmGlobalXCodeGenerator.cxx,v $
6 Date: $Date: 2008-01-22 14:13:03 $
7 Version: $Revision: 1.180 $
9 Copyright (c) 2002 Kitware, Inc., Insight Consortium. All rights reserved.
10 See Copyright.txt or http://www.cmake.org/HTML/Copyright.html for details.
12 This software is distributed WITHOUT ANY WARRANTY; without even
13 the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
14 PURPOSE. See the above copyright notices for more information.
16 =========================================================================*/
17 #include "cmGlobalXCodeGenerator.h"
18 #include "cmGlobalXCode21Generator.h"
19 #include "cmLocalXCodeGenerator.h"
20 #include "cmMakefile.h"
21 #include "cmXCodeObject.h"
22 #include "cmXCode21Object.h"
24 #include "cmGeneratedFileStream.h"
25 #include "cmComputeLinkInformation.h"
26 #include "cmSourceFile.h"
28 //----------------------------------------------------------------------------
29 #if defined(CMAKE_BUILD_WITH_CMAKE)
30 #include "cmXMLParser.h"
32 // parse the xml file storing the installed version of Xcode on
34 class cmXcodeVersionParser
: public cmXMLParser
37 void StartElement(const char* , const char** )
41 void EndElement(const char* name
)
43 if(strcmp(name
, "key") == 0)
45 this->Key
= this->Data
;
47 else if(strcmp(name
, "string") == 0)
49 if(this->Key
== "CFBundleShortVersionString")
51 this->Version
= (int)(10.0 * atof(this->Data
.c_str()));
55 void CharacterDataHandler(const char* data
, int length
)
57 this->Data
.append(data
, length
);
65 //----------------------------------------------------------------------------
66 cmGlobalXCodeGenerator::cmGlobalXCodeGenerator()
68 this->FindMakeProgramFile
= "CMakeFindXCode.cmake";
70 this->MainGroupChildren
= 0;
71 this->SourcesGroupChildren
= 0;
72 this->ResourcesGroupChildren
= 0;
73 this->CurrentMakefile
= 0;
74 this->CurrentLocalGenerator
= 0;
75 this->XcodeVersion
= 15;
78 //----------------------------------------------------------------------------
79 cmGlobalGenerator
* cmGlobalXCodeGenerator::New()
81 #if defined(CMAKE_BUILD_WITH_CMAKE)
82 cmXcodeVersionParser parser
;
84 ("/Developer/Applications/Xcode.app/Contents/version.plist");
85 if(parser
.Version
== 15)
87 return new cmGlobalXCodeGenerator
;
89 else if (parser
.Version
== 20)
91 cmSystemTools::Message("Xcode 2.0 not really supported by cmake, "
92 "using Xcode 15 generator\n");
93 return new cmGlobalXCodeGenerator
;
95 cmGlobalXCodeGenerator
* ret
= new cmGlobalXCode21Generator
;
96 ret
->SetVersion(parser
.Version
);
99 std::cerr
<< "CMake should be built with cmake to use XCode, "
100 "default to Xcode 1.5\n";
101 return new cmGlobalXCodeGenerator
;
105 //----------------------------------------------------------------------------
106 void cmGlobalXCodeGenerator::EnableLanguage(std::vector
<std::string
>const&
108 cmMakefile
* mf
, bool optional
)
110 mf
->AddDefinition("XCODE","1");
111 if(this->XcodeVersion
== 15)
116 mf
->AddCacheDefinition(
117 "CMAKE_CONFIGURATION_TYPES",
118 "Debug;Release;MinSizeRel;RelWithDebInfo",
119 "Semicolon separated list of supported configuration types, "
120 "only supports Debug, Release, MinSizeRel, and RelWithDebInfo, "
121 "anything else will be ignored.",
122 cmCacheManager::STRING
);
124 mf
->AddDefinition("CMAKE_GENERATOR_CC", "gcc");
125 mf
->AddDefinition("CMAKE_GENERATOR_CXX", "g++");
126 mf
->AddDefinition("CMAKE_GENERATOR_NO_COMPILER_ENV", "1");
127 // initialize Architectures so it can be used by
128 // GetTargetObjectFileDirectories
129 this->cmGlobalGenerator::EnableLanguage(lang
, mf
, optional
);
130 const char* osxArch
=
131 mf
->GetDefinition("CMAKE_OSX_ARCHITECTURES");
132 const char* sysroot
=
133 mf
->GetDefinition("CMAKE_OSX_SYSROOT");
134 if(osxArch
&& sysroot
)
136 this->Architectures
.clear();
137 cmSystemTools::ExpandListArgument(std::string(osxArch
),
138 this->Architectures
);
142 //----------------------------------------------------------------------------
143 std::string cmGlobalXCodeGenerator
144 ::GenerateBuildCommand(const char* makeProgram
,
145 const char *projectName
,
146 const char* additionalOptions
,
147 const char *targetName
,
152 // Config is not used yet
155 // now build the test
156 if(makeProgram
== 0 || !strlen(makeProgram
))
158 cmSystemTools::Error(
159 "Generator cannot find the appropriate make command.");
162 std::string makeCommand
=
163 cmSystemTools::ConvertToOutputPath(makeProgram
);
164 std::string lowerCaseCommand
= makeCommand
;
165 cmSystemTools::LowerCase(lowerCaseCommand
);
167 makeCommand
+= " -project ";
168 makeCommand
+= projectName
;
169 makeCommand
+= ".xcode";
170 if(this->XcodeVersion
> 20)
172 makeCommand
+= "proj";
176 if ( targetName
&& strcmp(targetName
, "clean") == 0 )
179 targetName
= "ALL_BUILD";
183 makeCommand
+= " clean";
187 makeCommand
+= " build";
189 makeCommand
+= " -target ";
190 // if it is a null string for config don't use it
191 if(config
&& *config
== 0)
195 if (targetName
&& strlen(targetName
))
197 makeCommand
+= targetName
;
201 makeCommand
+= "ALL_BUILD";
203 if(this->XcodeVersion
== 15)
205 makeCommand
+= " -buildstyle Development ";
209 makeCommand
+= " -configuration ";
210 makeCommand
+= config
?config
:"Debug";
212 if ( additionalOptions
)
215 makeCommand
+= additionalOptions
;
220 //----------------------------------------------------------------------------
221 ///! Create a local generator appropriate to this Global Generator
222 cmLocalGenerator
*cmGlobalXCodeGenerator::CreateLocalGenerator()
224 cmLocalGenerator
*lg
= new cmLocalXCodeGenerator
;
225 lg
->SetGlobalGenerator(this);
229 //----------------------------------------------------------------------------
230 void cmGlobalXCodeGenerator::Generate()
232 std::map
<cmStdString
, std::vector
<cmLocalGenerator
*> >::iterator it
;
233 // make sure extra targets are added before calling
234 // the parent generate which will call trace depends
235 for(it
= this->ProjectMap
.begin(); it
!= this->ProjectMap
.end(); ++it
)
237 cmLocalGenerator
* root
= it
->second
[0];
238 this->SetGenerationRoot(root
);
239 // add ALL_BUILD, INSTALL, etc
240 this->AddExtraTargets(root
, it
->second
);
242 this->cmGlobalGenerator::Generate();
243 for(it
= this->ProjectMap
.begin(); it
!= this->ProjectMap
.end(); ++it
)
245 cmLocalGenerator
* root
= it
->second
[0];
246 this->SetGenerationRoot(root
);
247 // now create the project
248 this->OutputXCodeProject(root
, it
->second
);
252 //----------------------------------------------------------------------------
253 void cmGlobalXCodeGenerator::SetGenerationRoot(cmLocalGenerator
* root
)
255 this->CurrentProject
= root
->GetMakefile()->GetProjectName();
256 this->SetCurrentLocalGenerator(root
);
257 std::string outDir
= this->CurrentMakefile
->GetHomeOutputDirectory();
258 outDir
=cmSystemTools::CollapseFullPath(outDir
.c_str());
259 cmSystemTools::SplitPath(outDir
.c_str(),
260 this->ProjectOutputDirectoryComponents
);
262 this->CurrentXCodeHackMakefile
=
263 root
->GetMakefile()->GetCurrentOutputDirectory();
264 this->CurrentXCodeHackMakefile
+= "/CMakeScripts";
265 cmSystemTools::MakeDirectory(this->CurrentXCodeHackMakefile
.c_str());
266 this->CurrentXCodeHackMakefile
+= "/XCODE_DEPEND_HELPER.make";
269 //----------------------------------------------------------------------------
271 cmGlobalXCodeGenerator::AddExtraTargets(cmLocalGenerator
* root
,
272 std::vector
<cmLocalGenerator
*>& gens
)
274 cmMakefile
* mf
= root
->GetMakefile();
277 const char* no_working_directory
= 0;
278 std::vector
<std::string
> no_depends
;
279 mf
->AddUtilityCommand("ALL_BUILD", true, no_depends
,
280 no_working_directory
,
281 "echo", "Build all projects");
282 cmTarget
* allbuild
= mf
->FindTarget("ALL_BUILD", false);
284 // Add XCODE depend helper
285 std::string dir
= mf
->GetCurrentOutputDirectory();
286 cmCustomCommandLine makecommand
;
287 makecommand
.push_back("make");
288 makecommand
.push_back("-C");
289 makecommand
.push_back(dir
.c_str());
290 makecommand
.push_back("-f");
291 makecommand
.push_back(this->CurrentXCodeHackMakefile
.c_str());
292 if(this->XcodeVersion
> 20)
294 makecommand
.push_back("all.$(CONFIGURATION)");
296 cmCustomCommandLines commandLines
;
297 commandLines
.push_back(makecommand
);
298 // Add Re-Run CMake rules
299 this->CreateReRunCMakeFile(root
);
301 // now make the allbuild depend on all the non-utility targets
303 for(std::vector
<cmLocalGenerator
*>::iterator i
= gens
.begin();
304 i
!= gens
.end(); ++i
)
306 cmLocalGenerator
* lg
= *i
;
307 if(this->IsExcluded(root
, *i
))
311 cmTargets
& tgts
= lg
->GetMakefile()->GetTargets();
312 for(cmTargets::iterator l
= tgts
.begin(); l
!= tgts
.end(); l
++)
314 cmTarget
& target
= l
->second
;
315 // make all exe, shared libs and modules
316 // run the depend check makefile as a post build rule
317 // this will make sure that when the next target is built
318 // things are up-to-date
319 if((target
.GetType() == cmTarget::EXECUTABLE
||
320 target
.GetType() == cmTarget::STATIC_LIBRARY
||
321 target
.GetType() == cmTarget::SHARED_LIBRARY
||
322 target
.GetType() == cmTarget::MODULE_LIBRARY
))
324 lg
->GetMakefile()->AddCustomCommandToTarget(target
.GetName(),
327 cmTarget::POST_BUILD
,
328 "Depend check for xcode",
332 if(!target
.GetPropertyAsBool("EXCLUDE_FROM_ALL"))
334 allbuild
->AddUtility(target
.GetName());
340 //----------------------------------------------------------------------------
341 void cmGlobalXCodeGenerator::CreateReRunCMakeFile(cmLocalGenerator
* root
)
343 cmMakefile
* mf
= root
->GetMakefile();
344 std::vector
<std::string
> lfiles
= mf
->GetListFiles();
346 std::sort(lfiles
.begin(), lfiles
.end(), std::less
<std::string
>());
347 std::vector
<std::string
>::iterator new_end
=
348 std::unique(lfiles
.begin(), lfiles
.end());
349 lfiles
.erase(new_end
, lfiles
.end());
350 std::string dir
= mf
->GetHomeOutputDirectory();
351 this->CurrentReRunCMakeMakefile
= dir
;
352 this->CurrentReRunCMakeMakefile
+= "/CMakeScripts";
353 cmSystemTools::MakeDirectory(this->CurrentReRunCMakeMakefile
.c_str());
354 this->CurrentReRunCMakeMakefile
+= "/ReRunCMake.make";
355 cmGeneratedFileStream makefileStream
356 (this->CurrentReRunCMakeMakefile
.c_str());
357 makefileStream
.SetCopyIfDifferent(true);
358 makefileStream
<< "# Generated by CMake, DO NOT EDIT\n";
359 makefileStream
<< cmake::GetCMakeFilesDirectoryPostSlash();
360 makefileStream
<< "cmake.check_cache: ";
361 for(std::vector
<std::string
>::const_iterator i
= lfiles
.begin();
362 i
!= lfiles
.end(); ++i
)
364 makefileStream
<< "\\\n" << this->ConvertToRelativeForMake(i
->c_str());
366 std::string cmake
= mf
->GetRequiredDefinition("CMAKE_COMMAND");
367 makefileStream
<< "\n\t" << this->ConvertToRelativeForMake(cmake
.c_str())
368 << " -H" << this->ConvertToRelativeForMake(
369 mf
->GetHomeDirectory())
370 << " -B" << this->ConvertToRelativeForMake(
371 mf
->GetHomeOutputDirectory()) << "\n";
374 //----------------------------------------------------------------------------
375 void cmGlobalXCodeGenerator::ClearXCodeObjects()
377 this->TargetDoneSet
.clear();
378 for(unsigned int i
= 0; i
< this->XCodeObjects
.size(); ++i
)
380 delete this->XCodeObjects
[i
];
382 this->XCodeObjects
.clear();
383 this->GroupMap
.clear();
384 this->GroupNameMap
.clear();
385 this->TargetGroup
.clear();
386 this->FileRefs
.clear();
389 //----------------------------------------------------------------------------
391 cmGlobalXCodeGenerator::CreateObject(cmXCodeObject::PBXType ptype
)
394 if(this->XcodeVersion
== 15)
396 obj
= new cmXCodeObject(ptype
, cmXCodeObject::OBJECT
);
400 obj
= new cmXCode21Object(ptype
, cmXCodeObject::OBJECT
);
402 this->XCodeObjects
.push_back(obj
);
406 //----------------------------------------------------------------------------
408 cmGlobalXCodeGenerator::CreateObject(cmXCodeObject::Type type
)
410 cmXCodeObject
* obj
= new cmXCodeObject(cmXCodeObject::None
, type
);
411 this->XCodeObjects
.push_back(obj
);
415 //----------------------------------------------------------------------------
417 cmGlobalXCodeGenerator::CreateString(const char* s
)
419 cmXCodeObject
* obj
= this->CreateObject(cmXCodeObject::STRING
);
424 //----------------------------------------------------------------------------
425 cmXCodeObject
* cmGlobalXCodeGenerator
426 ::CreateObjectReference(cmXCodeObject
* ref
)
428 cmXCodeObject
* obj
= this->CreateObject(cmXCodeObject::OBJECT_REF
);
433 //----------------------------------------------------------------------------
434 cmStdString
GetGroupMapKey(cmTarget
& cmtarget
, cmSourceFile
* sf
)
436 cmStdString
key(cmtarget
.GetName());
438 key
+= sf
->GetFullPath();
442 //----------------------------------------------------------------------------
444 cmGlobalXCodeGenerator::CreateXCodeSourceFile(cmLocalGenerator
* lg
,
448 // Add flags from target and source file properties.
450 if(cmtarget
.GetProperty("COMPILE_FLAGS"))
452 lg
->AppendFlags(flags
, cmtarget
.GetProperty("COMPILE_FLAGS"));
454 lg
->AppendFlags(flags
, sf
->GetProperty("COMPILE_FLAGS"));
455 cmSystemTools::ReplaceString(flags
, "\"", "\\\"");
457 // Add per-source definitions.
458 this->AppendDefines(flags
, sf
->GetProperty("COMPILE_DEFINITIONS"), true);
460 // Using a map and the full path guarantees that we will always get the same
461 // fileRef object for any given full path.
463 std::string fname
= sf
->GetFullPath();
464 cmXCodeObject
* fileRef
= this->FileRefs
[fname
];
467 fileRef
= this->CreateObject(cmXCodeObject::PBXFileReference
);
468 std::string comment
= fname
;
470 //std::string gname = group->GetObject("name")->GetString();
471 //comment += gname.substr(1, gname.size()-2);
472 fileRef
->SetComment(fname
.c_str());
474 this->FileRefs
[fname
] = fileRef
;
477 cmStdString key
= GetGroupMapKey(cmtarget
, sf
);
478 cmXCodeObject
* group
= this->GroupMap
[key
];
479 cmXCodeObject
* children
= group
->GetObject("children");
480 if (!children
->HasObject(fileRef
))
482 children
->AddObject(fileRef
);
485 cmXCodeObject
* buildFile
= this->CreateObject(cmXCodeObject::PBXBuildFile
);
486 buildFile
->SetComment(fileRef
->GetComment());
487 buildFile
->AddAttribute("fileRef", this->CreateObjectReference(fileRef
));
489 cmXCodeObject
* settings
=
490 this->CreateObject(cmXCodeObject::ATTRIBUTE_GROUP
);
491 settings
->AddAttribute("COMPILER_FLAGS", this->CreateString(flags
.c_str()));
493 // Is this a resource file in this target? Add it to the resources group...
495 cmTarget::SourceFileFlags tsFlags
= cmtarget
.GetTargetSourceFileFlags(sf
);
496 bool isResource
= tsFlags
.Resource
;
498 // Is this a "private" or "public" framework header file?
499 // Set the ATTRIBUTES attribute appropriately...
501 if(cmtarget
.GetType() == cmTarget::SHARED_LIBRARY
&&
502 cmtarget
.GetPropertyAsBool("FRAMEWORK"))
504 if(tsFlags
.PrivateHeader
)
506 cmXCodeObject
* attrs
= this->CreateObject(cmXCodeObject::OBJECT_LIST
);
507 attrs
->AddObject(this->CreateString("Private"));
508 settings
->AddAttribute("ATTRIBUTES", attrs
);
511 else if(tsFlags
.PublicHeader
)
513 cmXCodeObject
* attrs
= this->CreateObject(cmXCodeObject::OBJECT_LIST
);
514 attrs
->AddObject(this->CreateString("Public"));
515 settings
->AddAttribute("ATTRIBUTES", attrs
);
520 // Add the fileRef to the top level Resources group/folder if it is not
523 if(isResource
&& this->ResourcesGroupChildren
&&
524 !this->ResourcesGroupChildren
->HasObject(fileRef
))
526 this->ResourcesGroupChildren
->AddObject(fileRef
);
529 buildFile
->AddAttribute("settings", settings
);
530 fileRef
->AddAttribute("fileEncoding", this->CreateString("4"));
532 this->CurrentLocalGenerator
->GetSourceFileLanguage(*sf
);
533 std::string sourcecode
= "sourcecode";
534 std::string ext
= sf
->GetExtension();
535 ext
= cmSystemTools::LowerCase(ext
);
538 sourcecode
= "compiled.mach-o.objfile";
542 sourcecode
+= ".cpp.objcpp";
546 sourcecode
+= ".cpp.objc";
548 else if(ext
== "plist")
550 sourcecode
+= ".text.plist";
558 else if(strcmp(lang
, "C") == 0)
560 sourcecode
+= ".c.c";
562 else if(strcmp(lang
, "CXX") == 0)
564 sourcecode
+= ".cpp.cpp";
572 fileRef
->AddAttribute("lastKnownFileType",
573 this->CreateString(sourcecode
.c_str()));
575 this->ConvertToRelativeForXCode(sf
->GetFullPath().c_str());
578 cmSystemTools::SplitProgramPath(sf
->GetFullPath().c_str(),
581 fileRef
->AddAttribute("name", this->CreateString(file
.c_str()));
582 fileRef
->AddAttribute("path", this->CreateString(path
.c_str()));
583 if(this->XcodeVersion
== 15)
585 fileRef
->AddAttribute("refType", this->CreateString("4"));
587 if(path
.size() > 1 && path
[0] == '.' && path
[1] == '.')
589 fileRef
->AddAttribute("sourceTree", this->CreateString("<group>"));
593 fileRef
->AddAttribute("sourceTree", this->CreateString("<absolute>"));
598 //----------------------------------------------------------------------------
599 bool cmGlobalXCodeGenerator::SpecialTargetEmitted(std::string
const& tname
)
601 if(tname
== "ALL_BUILD" || tname
== "XCODE_DEPEND_HELPER" ||
602 tname
== "install" || tname
== "package" || tname
== "RUN_TESTS" )
604 if(this->TargetDoneSet
.find(tname
) != this->TargetDoneSet
.end())
608 this->TargetDoneSet
.insert(tname
);
614 //----------------------------------------------------------------------------
615 void cmGlobalXCodeGenerator::SetCurrentLocalGenerator(cmLocalGenerator
* gen
)
617 this->CurrentLocalGenerator
= gen
;
618 this->CurrentMakefile
= gen
->GetMakefile();
620 cmSystemTools::CollapseFullPath(this->CurrentMakefile
->
621 GetCurrentOutputDirectory());
622 cmSystemTools::SplitPath(outdir
.c_str(),
623 this->CurrentOutputDirectoryComponents
);
625 // Select the current set of configuration types.
626 this->CurrentConfigurationTypes
.clear();
627 if(this->XcodeVersion
> 20)
629 if(const char* types
=
630 this->CurrentMakefile
->GetDefinition("CMAKE_CONFIGURATION_TYPES"))
632 cmSystemTools::ExpandListArgument(types
,
633 this->CurrentConfigurationTypes
);
636 if(this->CurrentConfigurationTypes
.empty())
638 if(const char* buildType
=
639 this->CurrentMakefile
->GetDefinition("CMAKE_BUILD_TYPE"))
641 this->CurrentConfigurationTypes
.push_back(buildType
);
645 this->CurrentConfigurationTypes
.push_back("");
650 //----------------------------------------------------------------------------
652 cmGlobalXCodeGenerator::CreateXCodeTargets(cmLocalGenerator
* gen
,
653 std::vector
<cmXCodeObject
*>&
656 this->SetCurrentLocalGenerator(gen
);
657 cmTargets
&tgts
= this->CurrentMakefile
->GetTargets();
658 for(cmTargets::iterator l
= tgts
.begin(); l
!= tgts
.end(); l
++)
660 cmTarget
& cmtarget
= l
->second
;
662 // make sure ALL_BUILD, INSTALL, etc are only done once
663 if(this->SpecialTargetEmitted(l
->first
.c_str()))
668 if(cmtarget
.GetType() == cmTarget::UTILITY
||
669 cmtarget
.GetType() == cmTarget::GLOBAL_TARGET
)
671 targets
.push_back(this->CreateUtilityTarget(cmtarget
));
675 // organize the sources
676 std::vector
<cmSourceFile
*> const &classes
= cmtarget
.GetSourceFiles();
677 std::vector
<cmXCodeObject
*> externalObjFiles
;
678 std::vector
<cmXCodeObject
*> headerFiles
;
679 std::vector
<cmXCodeObject
*> resourceFiles
;
680 std::vector
<cmXCodeObject
*> sourceFiles
;
681 for(std::vector
<cmSourceFile
*>::const_iterator i
= classes
.begin();
682 i
!= classes
.end(); ++i
)
685 this->CreateXCodeSourceFile(this->CurrentLocalGenerator
,
687 cmXCodeObject
* fr
= xsf
->GetObject("fileRef");
688 cmXCodeObject
* filetype
=
689 fr
->GetObject()->GetObject("lastKnownFileType");
691 cmTarget::SourceFileFlags tsFlags
=
692 cmtarget
.GetTargetSourceFileFlags(*i
);
694 if(strcmp(filetype
->GetString(), "\"compiled.mach-o.objfile\"") == 0)
696 externalObjFiles
.push_back(xsf
);
698 else if((*i
)->GetPropertyAsBool("HEADER_FILE_ONLY"))
700 headerFiles
.push_back(xsf
);
702 else if(tsFlags
.Resource
)
704 resourceFiles
.push_back(xsf
);
708 sourceFiles
.push_back(xsf
);
712 // some build phases only apply to bundles and/or frameworks
713 bool isFrameworkTarget
= cmtarget
.GetType() == cmTarget::SHARED_LIBRARY
&&
714 cmtarget
.GetPropertyAsBool("FRAMEWORK");
715 bool isBundleTarget
= cmtarget
.GetPropertyAsBool("MACOSX_BUNDLE");
717 cmXCodeObject
* buildFiles
= 0;
719 // create source build phase
720 cmXCodeObject
* sourceBuildPhase
= 0;
721 if (!sourceFiles
.empty())
724 this->CreateObject(cmXCodeObject::PBXSourcesBuildPhase
);
725 sourceBuildPhase
->SetComment("Sources");
726 sourceBuildPhase
->AddAttribute("buildActionMask",
727 this->CreateString("2147483647"));
728 buildFiles
= this->CreateObject(cmXCodeObject::OBJECT_LIST
);
729 for(std::vector
<cmXCodeObject
*>::iterator i
= sourceFiles
.begin();
730 i
!= sourceFiles
.end(); ++i
)
732 buildFiles
->AddObject(*i
);
734 sourceBuildPhase
->AddAttribute("files", buildFiles
);
735 sourceBuildPhase
->AddAttribute("runOnlyForDeploymentPostprocessing",
736 this->CreateString("0"));
739 // create header build phase - only for framework targets
740 cmXCodeObject
* headerBuildPhase
= 0;
741 if (!headerFiles
.empty() && isFrameworkTarget
)
744 this->CreateObject(cmXCodeObject::PBXHeadersBuildPhase
);
745 headerBuildPhase
->SetComment("Headers");
746 headerBuildPhase
->AddAttribute("buildActionMask",
747 this->CreateString("2147483647"));
748 buildFiles
= this->CreateObject(cmXCodeObject::OBJECT_LIST
);
749 for(std::vector
<cmXCodeObject
*>::iterator i
= headerFiles
.begin();
750 i
!= headerFiles
.end(); ++i
)
752 buildFiles
->AddObject(*i
);
754 headerBuildPhase
->AddAttribute("files", buildFiles
);
755 headerBuildPhase
->AddAttribute("runOnlyForDeploymentPostprocessing",
756 this->CreateString("0"));
759 // create resource build phase - only for framework or bundle targets
760 cmXCodeObject
* resourceBuildPhase
= 0;
761 if (!resourceFiles
.empty() && (isFrameworkTarget
|| isBundleTarget
))
764 this->CreateObject(cmXCodeObject::PBXResourcesBuildPhase
);
765 resourceBuildPhase
->SetComment("Resources");
766 resourceBuildPhase
->AddAttribute("buildActionMask",
767 this->CreateString("2147483647"));
768 buildFiles
= this->CreateObject(cmXCodeObject::OBJECT_LIST
);
769 for(std::vector
<cmXCodeObject
*>::iterator i
= resourceFiles
.begin();
770 i
!= resourceFiles
.end(); ++i
)
772 buildFiles
->AddObject(*i
);
774 resourceBuildPhase
->AddAttribute("files", buildFiles
);
775 resourceBuildPhase
->AddAttribute("runOnlyForDeploymentPostprocessing",
776 this->CreateString("0"));
779 // create vector of "non-resource content file" build phases - only for
780 // framework or bundle targets
781 std::vector
<cmXCodeObject
*> contentBuildPhases
;
782 if (isFrameworkTarget
|| isBundleTarget
)
784 typedef std::map
<cmStdString
, std::vector
<cmSourceFile
*> >
785 mapOfVectorOfSourceFiles
;
786 mapOfVectorOfSourceFiles bundleFiles
;
787 for(std::vector
<cmSourceFile
*>::const_iterator i
= classes
.begin();
788 i
!= classes
.end(); ++i
)
790 const char* contentLoc
= (*i
)->GetProperty("MACOSX_PACKAGE_LOCATION");
791 if ( !contentLoc
|| cmStdString(contentLoc
) == "Resources" )
795 bundleFiles
[contentLoc
].push_back(*i
);
797 mapOfVectorOfSourceFiles::iterator mit
;
798 for ( mit
= bundleFiles
.begin(); mit
!= bundleFiles
.end(); ++ mit
)
800 cmXCodeObject
* copyFilesBuildPhase
=
801 this->CreateObject(cmXCodeObject::PBXCopyFilesBuildPhase
);
802 copyFilesBuildPhase
->SetComment("Copy files");
803 copyFilesBuildPhase
->AddAttribute("buildActionMask",
804 this->CreateString("2147483647"));
805 copyFilesBuildPhase
->AddAttribute("dstSubfolderSpec",
806 this->CreateString("6"));
807 cmOStringStream ostr
;
808 if ( mit
->first
!= "MacOS" )
810 ostr
<< "../" << mit
->first
.c_str();
812 copyFilesBuildPhase
->AddAttribute("dstPath",
813 this->CreateString(ostr
.str().c_str()));
814 copyFilesBuildPhase
->AddAttribute(
815 "runOnlyForDeploymentPostprocessing", this->CreateString("0"));
816 buildFiles
= this->CreateObject(cmXCodeObject::OBJECT_LIST
);
817 copyFilesBuildPhase
->AddAttribute("files", buildFiles
);
818 std::vector
<cmSourceFile
*>::iterator sfIt
;
819 for ( sfIt
= mit
->second
.begin(); sfIt
!= mit
->second
.end(); ++ sfIt
)
822 this->CreateXCodeSourceFile(this->CurrentLocalGenerator
,
824 buildFiles
->AddObject(xsf
);
826 contentBuildPhases
.push_back(copyFilesBuildPhase
);
830 // create framework build phase
831 cmXCodeObject
* frameworkBuildPhase
= 0;
832 if (!externalObjFiles
.empty())
834 frameworkBuildPhase
=
835 this->CreateObject(cmXCodeObject::PBXFrameworksBuildPhase
);
836 frameworkBuildPhase
->SetComment("Frameworks");
837 frameworkBuildPhase
->AddAttribute("buildActionMask",
838 this->CreateString("2147483647"));
839 buildFiles
= this->CreateObject(cmXCodeObject::OBJECT_LIST
);
840 frameworkBuildPhase
->AddAttribute("files", buildFiles
);
841 for(std::vector
<cmXCodeObject
*>::iterator i
= externalObjFiles
.begin();
842 i
!= externalObjFiles
.end(); ++i
)
844 buildFiles
->AddObject(*i
);
846 frameworkBuildPhase
->AddAttribute("runOnlyForDeploymentPostprocessing",
847 this->CreateString("0"));
850 // create list of build phases and create the XCode target
851 cmXCodeObject
* buildPhases
=
852 this->CreateObject(cmXCodeObject::OBJECT_LIST
);
854 this->CreateCustomCommands(buildPhases
, sourceBuildPhase
,
855 headerBuildPhase
, resourceBuildPhase
,
857 frameworkBuildPhase
, cmtarget
);
859 targets
.push_back(this->CreateXCodeTarget(cmtarget
, buildPhases
));
863 //----------------------------------------------------------------------------
865 cmGlobalXCodeGenerator::CreateBuildPhase(const char* name
,
868 const std::vector
<cmCustomCommand
>&
871 if(commands
.size() == 0 && strcmp(name
, "CMake ReRun") != 0)
875 cmXCodeObject
* buildPhase
=
876 this->CreateObject(cmXCodeObject::PBXShellScriptBuildPhase
);
877 buildPhase
->AddAttribute("buildActionMask",
878 this->CreateString("2147483647"));
879 cmXCodeObject
* buildFiles
= this->CreateObject(cmXCodeObject::OBJECT_LIST
);
880 buildPhase
->AddAttribute("files", buildFiles
);
881 buildPhase
->AddAttribute("name",
882 this->CreateString(name
));
883 buildPhase
->AddAttribute("runOnlyForDeploymentPostprocessing",
884 this->CreateString("0"));
885 buildPhase
->AddAttribute("shellPath",
886 this->CreateString("/bin/sh"));
887 this->AddCommandsToBuildPhase(buildPhase
, cmtarget
, commands
,
892 //----------------------------------------------------------------------------
893 void cmGlobalXCodeGenerator::CreateCustomCommands(cmXCodeObject
* buildPhases
,
900 std::vector
<cmXCodeObject
*>
906 std::vector
<cmCustomCommand
> const & prebuild
907 = cmtarget
.GetPreBuildCommands();
908 std::vector
<cmCustomCommand
> const & prelink
909 = cmtarget
.GetPreLinkCommands();
910 std::vector
<cmCustomCommand
> const & postbuild
911 = cmtarget
.GetPostBuildCommands();
912 std::vector
<cmSourceFile
*>const &classes
= cmtarget
.GetSourceFiles();
913 // add all the sources
914 std::vector
<cmCustomCommand
> commands
;
915 for(std::vector
<cmSourceFile
*>::const_iterator i
= classes
.begin();
916 i
!= classes
.end(); ++i
)
918 if((*i
)->GetCustomCommand())
920 commands
.push_back(*(*i
)->GetCustomCommand());
923 std::vector
<cmCustomCommand
> reruncom
;
924 cmXCodeObject
* cmakeReRunPhase
=
925 this->CreateBuildPhase("CMake ReRun", "cmakeReRunPhase",
927 buildPhases
->AddObject(cmakeReRunPhase
);
928 // create prebuild phase
929 cmXCodeObject
* cmakeRulesBuildPhase
=
930 this->CreateBuildPhase("CMake Rules",
931 "cmakeRulesBuildPhase",
933 // create prebuild phase
934 cmXCodeObject
* preBuildPhase
=
935 this->CreateBuildPhase("CMake PreBuild Rules", "preBuildCommands",
937 // create prelink phase
938 cmXCodeObject
* preLinkPhase
=
939 this->CreateBuildPhase("CMake PreLink Rules", "preLinkCommands",
941 // create postbuild phase
942 cmXCodeObject
* postBuildPhase
=
943 this->CreateBuildPhase("CMake PostBuild Rules", "postBuildPhase",
944 cmtarget
, postbuild
);
946 // The order here is the order they will be built in.
947 // The order "headers, resources, sources" mimics a native project generated
948 // from an xcode template...
952 buildPhases
->AddObject(preBuildPhase
);
954 if(cmakeRulesBuildPhase
)
956 buildPhases
->AddObject(cmakeRulesBuildPhase
);
960 buildPhases
->AddObject(headerBuildPhase
);
962 if(resourceBuildPhase
)
964 buildPhases
->AddObject(resourceBuildPhase
);
966 std::vector
<cmXCodeObject
*>::iterator cit
;
967 for (cit
= contentBuildPhases
.begin(); cit
!= contentBuildPhases
.end();
970 buildPhases
->AddObject(*cit
);
974 buildPhases
->AddObject(sourceBuildPhase
);
978 buildPhases
->AddObject(preLinkPhase
);
980 if(frameworkBuildPhase
)
982 buildPhases
->AddObject(frameworkBuildPhase
);
986 buildPhases
->AddObject(postBuildPhase
);
990 //----------------------------------------------------------------------------
991 std::string
cmGlobalXCodeGenerator::ExtractFlag(const char* flag
,
995 std::string::size_type pos
= flags
.find(flag
);
996 if(pos
!= flags
.npos
)
998 while(pos
< flags
.size() && flags
[pos
] != ' ')
1000 retFlag
+= flags
[pos
];
1008 //----------------------------------------------------------------------------
1010 cmGlobalXCodeGenerator::AddCommandsToBuildPhase(cmXCodeObject
* buildphase
,
1012 std::vector
<cmCustomCommand
>
1016 if(strcmp(name
, "cmakeReRunPhase") == 0)
1018 std::string cdir
= this->CurrentMakefile
->GetHomeOutputDirectory();
1019 cdir
= this->ConvertToRelativeForMake(cdir
.c_str());
1020 std::string makecmd
= "make -C ";
1024 this->ConvertToRelativeForMake(this->CurrentReRunCMakeMakefile
.c_str());
1025 cmSystemTools::ReplaceString(makecmd
, "\\ ", "\\\\ ");
1026 buildphase
->AddAttribute("shellScript",
1027 this->CreateString(makecmd
.c_str()));
1031 // collect multiple outputs of custom commands into a set
1032 // which will be used for every configuration
1033 std::map
<cmStdString
, cmStdString
> multipleOutputPairs
;
1034 for(std::vector
<cmCustomCommand
>::const_iterator i
= commands
.begin();
1035 i
!= commands
.end(); ++i
)
1037 cmCustomCommand
const& cc
= *i
;
1038 if(!cc
.GetCommandLines().empty())
1040 const std::vector
<std::string
>& outputs
= cc
.GetOutputs();
1041 if(!outputs
.empty())
1043 // If there are more than one outputs treat the
1044 // first as the primary output and make the rest depend on it.
1045 std::vector
<std::string
>::const_iterator o
= outputs
.begin();
1046 std::string primaryOutput
= this->ConvertToRelativeForMake(o
->c_str());
1047 for(++o
; o
!= outputs
.end(); ++o
)
1049 std::string currentOutput
=this->ConvertToRelativeForMake(o
->c_str());
1050 multipleOutputPairs
[currentOutput
] = primaryOutput
;
1056 std::string dir
= this->CurrentMakefile
->GetCurrentOutputDirectory();
1057 dir
+= "/CMakeScripts";
1058 cmSystemTools::MakeDirectory(dir
.c_str());
1059 std::string makefile
= dir
;
1061 makefile
+= target
.GetName();
1064 makefile
+= ".make";
1066 for (std::vector
<std::string
>::const_iterator currentConfig
=
1067 this->CurrentConfigurationTypes
.begin();
1068 currentConfig
!=this->CurrentConfigurationTypes
.end();
1071 this->CreateCustomRulesMakefile(makefile
.c_str(),
1074 currentConfig
->c_str(),
1075 multipleOutputPairs
);
1078 std::string cdir
= this->CurrentMakefile
->GetCurrentOutputDirectory();
1079 cdir
= this->ConvertToRelativeForXCode(cdir
.c_str());
1080 std::string makecmd
= "make -C ";
1083 makecmd
+= this->ConvertToRelativeForMake(
1084 (makefile
+"$CONFIGURATION").c_str());
1085 if(!multipleOutputPairs
.empty())
1087 makecmd
+= " cmake_check_multiple_outputs";
1090 cmSystemTools::ReplaceString(makecmd
, "\\ ", "\\\\ ");
1091 buildphase
->AddAttribute("shellScript",
1092 this->CreateString(makecmd
.c_str()));
1095 //----------------------------------------------------------------------------
1096 void cmGlobalXCodeGenerator
1097 ::CreateCustomRulesMakefile(const char* makefileBasename
,
1099 std::vector
<cmCustomCommand
>
1101 const char* configName
,
1102 const std::map
<cmStdString
,
1103 cmStdString
>& multipleOutputPairs
1106 std::string makefileName
=makefileBasename
;
1107 makefileName
+=configName
;
1108 cmGeneratedFileStream
makefileStream(makefileName
.c_str());
1113 makefileStream
.SetCopyIfDifferent(true);
1114 makefileStream
<< "# Generated by CMake, DO NOT EDIT\n";
1115 makefileStream
<< "# Custom rules for " << target
.GetName() << "\n";
1117 // have all depend on all outputs
1118 makefileStream
<< "all: ";
1119 std::map
<const cmCustomCommand
*, cmStdString
> tname
;
1121 for(std::vector
<cmCustomCommand
>::const_iterator i
= commands
.begin();
1122 i
!= commands
.end(); ++i
)
1124 cmCustomCommand
const& cc
= *i
;
1125 if(!cc
.GetCommandLines().empty())
1127 const std::vector
<std::string
>& outputs
= cc
.GetOutputs();
1128 if(!outputs
.empty())
1130 for(std::vector
<std::string
>::const_iterator o
= outputs
.begin();
1131 o
!= outputs
.end(); ++o
)
1134 << "\\\n\t" << this->ConvertToRelativeForMake(o
->c_str());
1139 cmOStringStream str
;
1140 str
<< "_buildpart_" << count
++ ;
1141 tname
[&cc
] = std::string(target
.GetName()) + str
.str();
1142 makefileStream
<< "\\\n\t" << tname
[&cc
];
1146 makefileStream
<< "\n\n";
1147 for(std::vector
<cmCustomCommand
>::const_iterator i
= commands
.begin();
1148 i
!= commands
.end(); ++i
)
1150 cmCustomCommand
const& cc
= *i
;
1151 if(!cc
.GetCommandLines().empty())
1153 bool escapeOldStyle
= cc
.GetEscapeOldStyle();
1154 bool escapeAllowMakeVars
= cc
.GetEscapeAllowMakeVars();
1155 makefileStream
<< "\n";
1156 const std::vector
<std::string
>& outputs
= cc
.GetOutputs();
1157 if(!outputs
.empty())
1159 // There is at least one output, start the rule for it
1160 std::string primary_output
=
1161 this->ConvertToRelativeForMake(outputs
.begin()->c_str());
1162 makefileStream
<< primary_output
<< ": ";
1166 // There are no outputs. Use the generated force rule name.
1167 makefileStream
<< tname
[&cc
] << ": ";
1169 for(std::vector
<std::string
>::const_iterator d
=
1170 cc
.GetDepends().begin();
1171 d
!= cc
.GetDepends().end(); ++d
)
1174 this->CurrentLocalGenerator
->GetRealDependency(d
->c_str(),
1176 makefileStream
<< "\\\n" << this
1177 ->ConvertToRelativeForMake(dep
.c_str());
1179 makefileStream
<< "\n";
1181 if(const char* comment
= cc
.GetComment())
1183 std::string echo_cmd
= "echo ";
1184 echo_cmd
+= (this->CurrentLocalGenerator
->
1185 EscapeForShell(comment
, escapeAllowMakeVars
));
1186 makefileStream
<< "\t" << echo_cmd
.c_str() << "\n";
1189 // Add each command line to the set of commands.
1190 for(cmCustomCommandLines::const_iterator cl
=
1191 cc
.GetCommandLines().begin();
1192 cl
!= cc
.GetCommandLines().end(); ++cl
)
1194 // Build the command line in a single string.
1195 const cmCustomCommandLine
& commandLine
= *cl
;
1196 std::string cmd2
= this->CurrentLocalGenerator
1197 ->GetRealLocation(commandLine
[0].c_str(), configName
);
1199 cmSystemTools::ReplaceString(cmd2
, "/./", "/");
1200 cmd2
= this->ConvertToRelativeForMake(cmd2
.c_str());
1202 if(cc
.GetWorkingDirectory())
1205 cmd
+= this->ConvertToRelativeForMake(cc
.GetWorkingDirectory());
1209 for(unsigned int j
=1; j
< commandLine
.size(); ++j
)
1214 cmd
+= (this->CurrentLocalGenerator
1215 ->EscapeForShellOldStyle(commandLine
[j
].c_str()));
1219 cmd
+= (this->CurrentLocalGenerator
->
1220 EscapeForShell(commandLine
[j
].c_str(),
1221 escapeAllowMakeVars
));
1224 makefileStream
<< "\t" << cmd
.c_str() << "\n";
1229 // Add rules to deal with multiple outputs of custom commands.
1230 if(!multipleOutputPairs
.empty())
1233 "\n# Dependencies of multiple outputs to their primary outputs \n";
1235 for(std::map
<cmStdString
, cmStdString
>::const_iterator o
=
1236 multipleOutputPairs
.begin(); o
!= multipleOutputPairs
.end(); ++o
)
1238 makefileStream
<< o
->first
<< ": " << o
->second
<< "\n";
1243 "cmake_check_multiple_outputs:\n";
1244 for(std::map
<cmStdString
, cmStdString
>::const_iterator o
=
1245 multipleOutputPairs
.begin(); o
!= multipleOutputPairs
.end(); ++o
)
1247 makefileStream
<< "\t@if [ ! -f "
1248 << o
->first
<< " ]; then rm -f "
1249 << o
->second
<< "; fi\n";
1254 //----------------------------------------------------------------------------
1255 void cmGlobalXCodeGenerator::CreateBuildSettings(cmTarget
& target
,
1256 cmXCodeObject
* buildSettings
,
1257 std::string
& fileType
,
1258 std::string
& productType
,
1259 std::string
& productName
,
1260 const char* configName
)
1263 std::string defFlags
;
1264 bool shared
= ((target
.GetType() == cmTarget::SHARED_LIBRARY
) ||
1265 (target
.GetType() == cmTarget::MODULE_LIBRARY
));
1267 const char* lang
= target
.GetLinkerLanguage(this);
1271 // for c++ projects get the c flags as well
1272 if(strcmp(lang
, "CXX") == 0)
1274 this->CurrentLocalGenerator
->AddLanguageFlags(cflags
, "C", configName
);
1275 this->CurrentLocalGenerator
->AddSharedFlags(cflags
, lang
, shared
);
1278 // Add language-specific flags.
1279 this->CurrentLocalGenerator
->AddLanguageFlags(flags
, lang
, configName
);
1281 // Add shared-library flags if needed.
1282 this->CurrentLocalGenerator
->AddSharedFlags(flags
, lang
, shared
);
1286 this->CurrentLocalGenerator
->
1287 AppendFlags(defFlags
,
1288 this->CurrentMakefile
->GetDefineFlags());
1289 cmSystemTools::ReplaceString(defFlags
, "\"", "\\\"");
1290 cmSystemTools::ReplaceString(flags
, "\"", "\\\"");
1291 cmSystemTools::ReplaceString(cflags
, "\"", "\\\"");
1293 // Add preprocessor definitions for this target and configuration.
1295 if(this->XcodeVersion
> 15)
1297 this->AppendDefines(ppDefs
, "CMAKE_INTDIR=\"$(CONFIGURATION)\"");
1299 if(const char* exportMacro
= target
.GetExportMacro())
1301 // Add the export symbol definition for shared library objects.
1302 this->AppendDefines(ppDefs
, exportMacro
);
1305 (ppDefs
, this->CurrentMakefile
->GetProperty("COMPILE_DEFINITIONS"));
1306 this->AppendDefines(ppDefs
, target
.GetProperty("COMPILE_DEFINITIONS"));
1309 std::string defVarName
= "COMPILE_DEFINITIONS_";
1310 defVarName
+= cmSystemTools::UpperCase(configName
);
1312 (ppDefs
, this->CurrentMakefile
->GetProperty(defVarName
.c_str()));
1313 this->AppendDefines(ppDefs
, target
.GetProperty(defVarName
.c_str()));
1315 buildSettings
->AddAttribute
1316 ("GCC_PREPROCESSOR_DEFINITIONS", this->CreateString(ppDefs
.c_str()));
1318 std::string extraLinkOptions
;
1319 if(target
.GetType() == cmTarget::EXECUTABLE
)
1322 this->CurrentMakefile
->GetRequiredDefinition("CMAKE_EXE_LINKER_FLAGS");
1324 if(target
.GetType() == cmTarget::SHARED_LIBRARY
)
1326 extraLinkOptions
= this->CurrentMakefile
->
1327 GetRequiredDefinition("CMAKE_SHARED_LINKER_FLAGS");
1329 if(target
.GetType() == cmTarget::MODULE_LIBRARY
)
1331 extraLinkOptions
= this->CurrentMakefile
->
1332 GetRequiredDefinition("CMAKE_MODULE_LINKER_FLAGS");
1335 const char* targetLinkFlags
= target
.GetProperty("LINK_FLAGS");
1338 extraLinkOptions
+= " ";
1339 extraLinkOptions
+= targetLinkFlags
;
1342 // The product name is the full name of the target for this configuration.
1343 productName
= target
.GetFullName(configName
);
1345 // Get the product name components.
1346 std::string pnprefix
;
1348 std::string pnsuffix
;
1349 target
.GetFullName(pnprefix
, pnbase
, pnsuffix
, configName
);
1351 // Store the product name for all target types.
1352 buildSettings
->AddAttribute("PRODUCT_NAME",
1353 this->CreateString(pnbase
.c_str()));
1355 // Set attributes to specify the proper name for the target.
1356 if(target
.GetType() == cmTarget::STATIC_LIBRARY
||
1357 target
.GetType() == cmTarget::SHARED_LIBRARY
||
1358 target
.GetType() == cmTarget::MODULE_LIBRARY
||
1359 target
.GetType() == cmTarget::EXECUTABLE
)
1361 std::string pndir
= target
.GetDirectory();
1362 if (target
.GetType() == cmTarget::SHARED_LIBRARY
&&
1363 target
.GetPropertyAsBool("FRAMEWORK"))
1366 pndir
= cmSystemTools::CollapseFullPath(pndir
.c_str());
1368 buildSettings
->AddAttribute("SYMROOT",
1369 this->CreateString(pndir
.c_str()));
1370 buildSettings
->AddAttribute("EXECUTABLE_PREFIX",
1371 this->CreateString(pnprefix
.c_str()));
1372 buildSettings
->AddAttribute("EXECUTABLE_SUFFIX",
1373 this->CreateString(pnsuffix
.c_str()));
1376 // Handle settings for each target type.
1377 switch(target
.GetType())
1379 case cmTarget::STATIC_LIBRARY
:
1381 fileType
= "archive.ar";
1382 productType
= "com.apple.product-type.library.static";
1384 buildSettings
->AddAttribute("LIBRARY_STYLE",
1385 this->CreateString("STATIC"));
1389 case cmTarget::MODULE_LIBRARY
:
1391 buildSettings
->AddAttribute("LIBRARY_STYLE",
1392 this->CreateString("BUNDLE"));
1393 if(this->XcodeVersion
>= 22)
1395 fileType
= "compiled.mach-o.executable";
1396 productType
= "com.apple.product-type.tool";
1398 buildSettings
->AddAttribute("MACH_O_TYPE",
1399 this->CreateString("mh_bundle"));
1400 buildSettings
->AddAttribute("GCC_DYNAMIC_NO_PIC",
1401 this->CreateString("NO"));
1402 // Add the flags to create an executable.
1403 std::string createFlags
=
1404 this->LookupFlags("CMAKE_", lang
, "_LINK_FLAGS", "");
1405 if(!createFlags
.empty())
1407 extraLinkOptions
+= " ";
1408 extraLinkOptions
+= createFlags
;
1413 fileType
= "compiled.mach-o.dylib";
1414 productType
= "com.apple.product-type.library.dynamic";
1416 // Add the flags to create a module.
1417 std::string createFlags
=
1418 this->LookupFlags("CMAKE_SHARED_MODULE_CREATE_", lang
, "_FLAGS",
1420 if(!createFlags
.empty())
1422 extraLinkOptions
+= " ";
1423 extraLinkOptions
+= createFlags
;
1428 case cmTarget::SHARED_LIBRARY
:
1430 if(target
.GetPropertyAsBool("FRAMEWORK"))
1432 fileType
= "wrapper.framework";
1433 productType
= "com.apple.product-type.framework";
1435 const char* version
= target
.GetProperty("FRAMEWORK_VERSION");
1438 version
= target
.GetProperty("VERSION");
1444 buildSettings
->AddAttribute("FRAMEWORK_VERSION",
1445 this->CreateString(version
));
1449 fileType
= "compiled.mach-o.dylib";
1450 productType
= "com.apple.product-type.library.dynamic";
1452 // Add the flags to create a shared library.
1453 std::string createFlags
=
1454 this->LookupFlags("CMAKE_SHARED_LIBRARY_CREATE_", lang
, "_FLAGS",
1456 if(!createFlags
.empty())
1458 extraLinkOptions
+= " ";
1459 extraLinkOptions
+= createFlags
;
1463 buildSettings
->AddAttribute("LIBRARY_STYLE",
1464 this->CreateString("DYNAMIC"));
1465 buildSettings
->AddAttribute("DYLIB_COMPATIBILITY_VERSION",
1466 this->CreateString("1"));
1467 buildSettings
->AddAttribute("DYLIB_CURRENT_VERSION",
1468 this->CreateString("1"));
1471 case cmTarget::EXECUTABLE
:
1473 fileType
= "compiled.mach-o.executable";
1475 // Add the flags to create an executable.
1476 std::string createFlags
=
1477 this->LookupFlags("CMAKE_", lang
, "_LINK_FLAGS", "");
1478 if(!createFlags
.empty())
1480 extraLinkOptions
+= " ";
1481 extraLinkOptions
+= createFlags
;
1484 // Handle bundles and normal executables separately.
1485 if(target
.GetPropertyAsBool("MACOSX_BUNDLE"))
1487 productType
= "com.apple.product-type.application";
1489 this->CurrentMakefile
->GetModulesFile("MacOSXBundleInfo.plist.in");
1490 if ( f1
.size() == 0 )
1492 cmSystemTools::Error("could not find Mac OSX bundle template file.");
1494 std::string f2
= this->CurrentMakefile
->GetCurrentOutputDirectory();
1495 f2
+= "/Info.plist";
1496 this->CurrentMakefile
->ConfigureFile(f1
.c_str(), f2
.c_str(),
1497 false, false, false);
1499 this->ConvertToRelativeForXCode(f2
.c_str());
1500 buildSettings
->AddAttribute("INFOPLIST_FILE",
1501 this->CreateString(path
.c_str()));
1506 productType
= "com.apple.product-type.tool";
1513 if(this->XcodeVersion
>= 22)
1515 buildSettings
->AddAttribute("PREBINDING",
1516 this->CreateString("NO"));
1519 std::vector
<std::string
> includes
;
1520 this->CurrentLocalGenerator
->GetIncludeDirectories(includes
);
1522 std::set
<cmStdString
> emitted
;
1523 emitted
.insert("/System/Library/Frameworks");
1524 for(std::vector
<std::string
>::iterator i
= includes
.begin();
1525 i
!= includes
.end(); ++i
)
1527 if(this->NameResolvesToFramework(i
->c_str()))
1529 std::string frameworkDir
= *i
;
1530 frameworkDir
+= "/../";
1531 frameworkDir
= cmSystemTools::CollapseFullPath(frameworkDir
.c_str());
1532 if(emitted
.insert(frameworkDir
).second
)
1534 fdirs
+= this->XCodeEscapePath(frameworkDir
.c_str());
1540 std::string incpath
=
1541 this->XCodeEscapePath(i
->c_str());
1542 dirs
+= incpath
+ " ";
1545 std::vector
<std::string
>& frameworks
= target
.GetFrameworks();
1546 if(frameworks
.size())
1548 for(std::vector
<std::string
>::iterator fmIt
= frameworks
.begin();
1549 fmIt
!= frameworks
.end(); ++fmIt
)
1551 if(emitted
.insert(*fmIt
).second
)
1553 fdirs
+= this->XCodeEscapePath(fmIt
->c_str());
1560 buildSettings
->AddAttribute("FRAMEWORK_SEARCH_PATHS",
1561 this->CreateString(fdirs
.c_str()));
1565 buildSettings
->AddAttribute("HEADER_SEARCH_PATHS",
1566 this->CreateString(dirs
.c_str()));
1568 std::string oflagc
= this->ExtractFlag("-O", cflags
);
1572 if(oflagc
.size() == 3)
1574 optLevel
[0] = oflagc
[2];
1576 if(oflagc
.size() == 2)
1580 std::string oflag
= this->ExtractFlag("-O", flags
);
1581 if(oflag
.size() == 3)
1583 optLevel
[0] = oflag
[2];
1585 if(oflag
.size() == 2)
1589 std::string gflagc
= this->ExtractFlag("-g", cflags
);
1590 // put back gdwarf-2 if used since there is no way
1591 // to represent it in the gui, but we still want debug yes
1592 if(gflagc
== "-gdwarf-2")
1597 std::string gflag
= this->ExtractFlag("-g", flags
);
1598 if(gflag
== "-gdwarf-2")
1603 const char* debugStr
= "YES";
1604 if(gflagc
.size() ==0 && gflag
.size() == 0)
1609 // Convert "XCODE_ATTRIBUTE_*" properties directly.
1611 cmPropertyMap
const& props
= target
.GetProperties();
1612 for(cmPropertyMap::const_iterator i
= props
.begin();
1613 i
!= props
.end(); ++i
)
1615 if(i
->first
.find("XCODE_ATTRIBUTE_") == 0)
1617 buildSettings
->AddAttribute(i
->first
.substr(16).c_str(),
1618 this->CreateString(i
->second
.GetValue()));
1623 buildSettings
->AddAttribute("GCC_GENERATE_DEBUGGING_SYMBOLS",
1624 this->CreateString(debugStr
));
1625 buildSettings
->AddAttribute("GCC_OPTIMIZATION_LEVEL",
1626 this->CreateString(optLevel
));
1627 buildSettings
->AddAttribute("OPTIMIZATION_CFLAGS",
1628 this->CreateString(oflagc
.c_str()));
1629 buildSettings
->AddAttribute("GCC_SYMBOLS_PRIVATE_EXTERN",
1630 this->CreateString("NO"));
1631 buildSettings
->AddAttribute("GCC_INLINES_ARE_PRIVATE_EXTERN",
1632 this->CreateString("NO"));
1633 if(lang
&& strcmp(lang
, "CXX") == 0)
1637 buildSettings
->AddAttribute("OTHER_CPLUSPLUSFLAGS",
1638 this->CreateString(flags
.c_str()));
1641 buildSettings
->AddAttribute("OTHER_CFLAGS",
1642 this->CreateString(cflags
.c_str()));
1649 buildSettings
->AddAttribute("OTHER_CFLAGS",
1650 this->CreateString(flags
.c_str()));
1653 // Create the INSTALL_PATH attribute.
1654 std::string install_name_dir
;
1655 if(target
.GetType() == cmTarget::SHARED_LIBRARY
)
1657 // Get the install_name directory for the build tree.
1658 install_name_dir
= target
.GetInstallNameDirForBuildTree(configName
);
1659 if(target
.GetPropertyAsBool("FRAMEWORK"))
1661 if(install_name_dir
.find(".framework") != install_name_dir
.npos
)
1663 install_name_dir
= install_name_dir
+ "/..";
1665 cmSystemTools::CollapseFullPath(install_name_dir
.c_str());
1666 //std::cerr << "new install name " << install_name_dir << "\n";
1670 if(install_name_dir
.empty())
1672 // Xcode will not pass the -install_name option at all if INSTALL_PATH
1673 // is not given or is empty. We must explicitly put the flag in the
1674 // link flags to create an install_name with just the library soname.
1675 extraLinkOptions
+= " -install_name ";
1676 extraLinkOptions
+= productName
;
1680 // Convert to a path for the native build tool.
1681 cmSystemTools::ConvertToUnixSlashes(install_name_dir
);
1682 // do not escape spaces on this since it is only a single path
1685 buildSettings
->AddAttribute("INSTALL_PATH",
1686 this->CreateString(install_name_dir
.c_str()));
1688 buildSettings
->AddAttribute("OTHER_LDFLAGS",
1689 this->CreateString(extraLinkOptions
.c_str()));
1690 buildSettings
->AddAttribute("OTHER_REZFLAGS",
1691 this->CreateString(""));
1692 buildSettings
->AddAttribute("SECTORDER_FLAGS",
1693 this->CreateString(""));
1694 buildSettings
->AddAttribute("USE_HEADERMAP",
1695 this->CreateString("NO"));
1696 buildSettings
->AddAttribute("WARNING_CFLAGS",
1698 "-Wmost -Wno-four-char-constants"
1699 " -Wno-unknown-pragmas"));
1702 //----------------------------------------------------------------------------
1704 cmGlobalXCodeGenerator::CreateUtilityTarget(cmTarget
& cmtarget
)
1706 cmXCodeObject
* shellBuildPhase
=
1707 this->CreateObject(cmXCodeObject::PBXShellScriptBuildPhase
);
1708 shellBuildPhase
->AddAttribute("buildActionMask",
1709 this->CreateString("2147483647"));
1710 cmXCodeObject
* buildFiles
= this->CreateObject(cmXCodeObject::OBJECT_LIST
);
1711 shellBuildPhase
->AddAttribute("files", buildFiles
);
1712 cmXCodeObject
* inputPaths
= this->CreateObject(cmXCodeObject::OBJECT_LIST
);
1713 shellBuildPhase
->AddAttribute("inputPaths", inputPaths
);
1714 cmXCodeObject
* outputPaths
= this->CreateObject(cmXCodeObject::OBJECT_LIST
);
1715 shellBuildPhase
->AddAttribute("outputPaths", outputPaths
);
1716 shellBuildPhase
->AddAttribute("runOnlyForDeploymentPostprocessing",
1717 this->CreateString("0"));
1718 shellBuildPhase
->AddAttribute("shellPath",
1719 this->CreateString("/bin/sh"));
1720 shellBuildPhase
->AddAttribute("shellScript",
1722 "# shell script goes here\nexit 0"));
1723 cmXCodeObject
* target
=
1724 this->CreateObject(cmXCodeObject::PBXAggregateTarget
);
1725 target
->SetComment(cmtarget
.GetName());
1726 cmXCodeObject
* buildPhases
=
1727 this->CreateObject(cmXCodeObject::OBJECT_LIST
);
1728 std::vector
<cmXCodeObject
*> emptyContentVector
;
1729 this->CreateCustomCommands(buildPhases
, 0, 0, 0, emptyContentVector
, 0,
1731 target
->AddAttribute("buildPhases", buildPhases
);
1732 cmXCodeObject
* buildSettings
=
1733 this->CreateObject(cmXCodeObject::ATTRIBUTE_GROUP
);
1734 std::string fileTypeString
;
1735 std::string productTypeString
;
1736 std::string productName
;
1737 const char* globalConfig
= 0;
1738 if(this->XcodeVersion
> 20)
1740 this->AddConfigurations(target
, cmtarget
);
1744 globalConfig
= this->CurrentMakefile
->GetDefinition("CMAKE_BUILD_TYPE");
1746 this->CreateBuildSettings(cmtarget
,
1747 buildSettings
, fileTypeString
,
1748 productTypeString
, productName
, globalConfig
);
1749 target
->AddAttribute("buildSettings", buildSettings
);
1750 cmXCodeObject
* dependencies
=
1751 this->CreateObject(cmXCodeObject::OBJECT_LIST
);
1752 target
->AddAttribute("dependencies", dependencies
);
1753 target
->AddAttribute("name", this->CreateString(productName
.c_str()));
1754 target
->AddAttribute("productName",this->CreateString(productName
.c_str()));
1755 target
->SetTarget(&cmtarget
);
1759 //----------------------------------------------------------------------------
1760 void cmGlobalXCodeGenerator::AddConfigurations(cmXCodeObject
* target
,
1763 std::string configTypes
=
1764 this->CurrentMakefile
->GetRequiredDefinition("CMAKE_CONFIGURATION_TYPES");
1765 std::vector
<std::string
> configVectorIn
;
1766 std::vector
<std::string
> configVector
;
1767 configVectorIn
.push_back(configTypes
);
1768 cmSystemTools::ExpandList(configVectorIn
, configVector
);
1769 cmXCodeObject
* configlist
=
1770 this->CreateObject(cmXCodeObject::XCConfigurationList
);
1771 cmXCodeObject
* buildConfigurations
=
1772 this->CreateObject(cmXCodeObject::OBJECT_LIST
);
1773 configlist
->AddAttribute("buildConfigurations", buildConfigurations
);
1774 std::string comment
= "Build configuration list for ";
1775 comment
+= cmXCodeObject::PBXTypeNames
[target
->GetIsA()];
1777 comment
+= cmtarget
.GetName();
1779 configlist
->SetComment(comment
.c_str());
1780 target
->AddAttribute("buildConfigurationList",
1781 this->CreateObjectReference(configlist
));
1782 for(unsigned int i
= 0; i
< configVector
.size(); ++i
)
1784 cmXCodeObject
* config
=
1785 this->CreateObject(cmXCodeObject::XCBuildConfiguration
);
1786 buildConfigurations
->AddObject(config
);
1787 cmXCodeObject
* buildSettings
=
1788 this->CreateObject(cmXCodeObject::ATTRIBUTE_GROUP
);
1789 std::string fileTypeString
;
1790 std::string productTypeString
;
1791 std::string productName
;
1792 this->CreateBuildSettings(cmtarget
,
1793 buildSettings
, fileTypeString
,
1794 productTypeString
, productName
,
1795 configVector
[i
].c_str());
1796 config
->AddAttribute("name", this->CreateString(configVector
[i
].c_str()));
1797 config
->SetComment(configVector
[i
].c_str());
1798 config
->AddAttribute("buildSettings", buildSettings
);
1800 if(configVector
.size())
1802 configlist
->AddAttribute("defaultConfigurationName",
1803 this->CreateString(configVector
[0].c_str()));
1804 configlist
->AddAttribute("defaultConfigurationIsVisible",
1805 this->CreateString("0"));
1809 //----------------------------------------------------------------------------
1811 cmGlobalXCodeGenerator::CreateXCodeTarget(cmTarget
& cmtarget
,
1812 cmXCodeObject
* buildPhases
)
1814 cmXCodeObject
* target
=
1815 this->CreateObject(cmXCodeObject::PBXNativeTarget
);
1816 target
->AddAttribute("buildPhases", buildPhases
);
1817 cmXCodeObject
* buildRules
= this->CreateObject(cmXCodeObject::OBJECT_LIST
);
1818 target
->AddAttribute("buildRules", buildRules
);
1819 cmXCodeObject
* buildSettings
=
1820 this->CreateObject(cmXCodeObject::ATTRIBUTE_GROUP
);
1821 std::string fileTypeString
;
1822 std::string productTypeString
;
1823 std::string productName
;
1824 const char* globalConfig
= 0;
1825 if(this->XcodeVersion
> 20)
1827 this->AddConfigurations(target
, cmtarget
);
1831 globalConfig
= this->CurrentMakefile
->GetDefinition("CMAKE_BUILD_TYPE");
1833 this->CreateBuildSettings(cmtarget
,
1834 buildSettings
, fileTypeString
,
1835 productTypeString
, productName
, globalConfig
);
1836 target
->AddAttribute("buildSettings", buildSettings
);
1837 cmXCodeObject
* dependencies
=
1838 this->CreateObject(cmXCodeObject::OBJECT_LIST
);
1839 target
->AddAttribute("dependencies", dependencies
);
1840 target
->AddAttribute("name", this->CreateString(productName
.c_str()));
1841 target
->AddAttribute("productName",this->CreateString(productName
.c_str()));
1843 cmXCodeObject
* fileRef
=
1844 this->CreateObject(cmXCodeObject::PBXFileReference
);
1845 fileRef
->AddAttribute("explicitFileType",
1846 this->CreateString(fileTypeString
.c_str()));
1847 fileRef
->AddAttribute("path", this->CreateString(productName
.c_str()));
1848 fileRef
->AddAttribute("refType", this->CreateString("0"));
1849 fileRef
->AddAttribute("sourceTree",
1850 this->CreateString("BUILT_PRODUCTS_DIR"));
1851 fileRef
->SetComment(cmtarget
.GetName());
1852 target
->AddAttribute("productReference",
1853 this->CreateObjectReference(fileRef
));
1854 target
->AddAttribute("productType",
1855 this->CreateString(productTypeString
.c_str()));
1856 target
->SetTarget(&cmtarget
);
1860 //----------------------------------------------------------------------------
1861 cmXCodeObject
* cmGlobalXCodeGenerator::FindXCodeTarget(cmTarget
* t
)
1867 for(std::vector
<cmXCodeObject
*>::iterator i
= this->XCodeObjects
.begin();
1868 i
!= this->XCodeObjects
.end(); ++i
)
1870 cmXCodeObject
* o
= *i
;
1871 if(o
->GetTarget() == t
)
1879 //----------------------------------------------------------------------------
1880 void cmGlobalXCodeGenerator::AddDependTarget(cmXCodeObject
* target
,
1881 cmXCodeObject
* dependTarget
)
1883 // make sure a target does not depend on itself
1884 if(target
== dependTarget
)
1888 // now avoid circular references if dependTarget already
1889 // depends on target then skip it. Circular references crashes
1891 cmXCodeObject
* dependTargetDepends
=
1892 dependTarget
->GetObject("dependencies");
1893 if(dependTargetDepends
)
1895 if(dependTargetDepends
->HasObject(target
->GetPBXTargetDependency()))
1901 cmXCodeObject
* targetdep
= dependTarget
->GetPBXTargetDependency();
1904 cmXCodeObject
* container
=
1905 this->CreateObject(cmXCodeObject::PBXContainerItemProxy
);
1906 container
->SetComment("PBXContainerItemProxy");
1907 container
->AddAttribute("containerPortal",
1908 this->CreateObjectReference(this->RootObject
));
1909 container
->AddAttribute("proxyType", this->CreateString("1"));
1910 container
->AddAttribute("remoteGlobalIDString",
1911 this->CreateObjectReference(dependTarget
));
1912 container
->AddAttribute("remoteInfo",
1914 dependTarget
->GetTarget()->GetName()));
1916 this->CreateObject(cmXCodeObject::PBXTargetDependency
);
1917 targetdep
->SetComment("PBXTargetDependency");
1918 targetdep
->AddAttribute("target",
1919 this->CreateObjectReference(dependTarget
));
1920 targetdep
->AddAttribute("targetProxy",
1921 this->CreateObjectReference(container
));
1922 dependTarget
->SetPBXTargetDependency(targetdep
);
1925 cmXCodeObject
* depends
= target
->GetObject("dependencies");
1929 Error("target does not have dependencies attribute error..");
1934 depends
->AddUniqueObject(targetdep
);
1938 //----------------------------------------------------------------------------
1939 void cmGlobalXCodeGenerator::AppendOrAddBuildSetting(cmXCodeObject
* settings
,
1940 const char* attribute
,
1945 cmXCodeObject
* attr
= settings
->GetObject(attribute
);
1948 settings
->AddAttribute(attribute
, this->CreateString(value
));
1952 std::string oldValue
= attr
->GetString();
1954 // unescape escaped quotes internal to the string:
1955 cmSystemTools::ReplaceString(oldValue
, "\\\"", "\"");
1957 // remove surrounding quotes, if any:
1958 std::string::size_type len
= oldValue
.length();
1959 if(oldValue
[0] == '\"' && oldValue
[len
-1] == '\"')
1961 oldValue
= oldValue
.substr(1, len
-2);
1967 // SetString automatically escapes internal quotes and then surrounds
1968 // the result with quotes if necessary...
1969 attr
->SetString(oldValue
.c_str());
1974 //----------------------------------------------------------------------------
1975 void cmGlobalXCodeGenerator
1976 ::AppendBuildSettingAttribute(cmXCodeObject
* target
,
1977 const char* attribute
,
1979 const char* configName
)
1981 if(this->XcodeVersion
< 21)
1983 // There is only one configuration. Add the setting to the buildSettings
1985 this->AppendOrAddBuildSetting(target
->GetObject("buildSettings"),
1990 // There are multiple configurations. Add the setting to the
1991 // buildSettings of the configuration name given.
1992 cmXCodeObject
* configurationList
=
1993 target
->GetObject("buildConfigurationList")->GetObject();
1994 cmXCodeObject
* buildConfigs
=
1995 configurationList
->GetObject("buildConfigurations");
1996 std::vector
<cmXCodeObject
*> list
= buildConfigs
->GetObjectList();
1997 // each configuration and the target itself has a buildSettings in it
1998 //list.push_back(target);
1999 for(std::vector
<cmXCodeObject
*>::iterator i
= list
.begin();
2000 i
!= list
.end(); ++i
)
2004 if(strcmp((*i
)->GetObject("name")->GetString(), configName
) == 0)
2006 cmXCodeObject
* settings
= (*i
)->GetObject("buildSettings");
2007 this->AppendOrAddBuildSetting(settings
, attribute
, value
);
2012 cmXCodeObject
* settings
= (*i
)->GetObject("buildSettings");
2013 this->AppendOrAddBuildSetting(settings
, attribute
, value
);
2019 //----------------------------------------------------------------------------
2020 void cmGlobalXCodeGenerator
2021 ::AddDependAndLinkInformation(cmXCodeObject
* target
)
2023 cmTarget
* cmtarget
= target
->GetTarget();
2026 cmSystemTools::Error("Error no target on xobject\n");
2030 // Add dependencies on other CMake targets.
2032 // Keep track of dependencies already listed.
2033 std::set
<cmStdString
> emitted
;
2035 // A target should not depend on itself.
2036 emitted
.insert(cmtarget
->GetName());
2038 // Loop over all library dependencies.
2039 const cmTarget::LinkLibraryVectorType
& tlibs
=
2040 cmtarget
->GetLinkLibraries();
2041 for(cmTarget::LinkLibraryVectorType::const_iterator lib
= tlibs
.begin();
2042 lib
!= tlibs
.end(); ++lib
)
2044 // Don't emit the same library twice for this target.
2045 if(emitted
.insert(lib
->first
).second
)
2047 // Add this dependency.
2048 cmTarget
* t
= this->FindTarget(this->CurrentProject
.c_str(),
2049 lib
->first
.c_str(), false);
2050 cmXCodeObject
* dptarget
= this->FindXCodeTarget(t
);
2053 this->AddDependTarget(target
, dptarget
);
2059 // write utility dependencies.
2060 for(std::set
<cmStdString
>::const_iterator i
2061 = cmtarget
->GetUtilities().begin();
2062 i
!= cmtarget
->GetUtilities().end(); ++i
)
2064 cmTarget
* t
= this->FindTarget(this->CurrentProject
.c_str(),
2066 // if the target is in this project then make target depend
2067 // on it. It may not be in this project if this is a sub
2068 // project from the top.
2071 cmXCodeObject
* dptarget
= this->FindXCodeTarget(t
);
2074 this->AddDependTarget(target
, dptarget
);
2078 std::string m
= "Error Utility: ";
2087 m
+= "Is on the target ";
2088 m
+= cmtarget
->GetName();
2090 m
+= "But it has no xcode target created yet??\n";
2091 m
+= "Current project is ";
2092 m
+= this->CurrentProject
.c_str();
2093 cmSystemTools::Error(m
.c_str());
2098 // Loop over configuration types and set per-configuration info.
2099 for(std::vector
<std::string
>::iterator i
=
2100 this->CurrentConfigurationTypes
.begin();
2101 i
!= this->CurrentConfigurationTypes
.end(); ++i
)
2103 // Get the current configuration name.
2104 const char* configName
= i
->c_str();
2110 // Compute the link library and directory information.
2111 cmComputeLinkInformation
cli(cmtarget
, configName
);
2117 // Add dependencies directly on library files.
2119 std::vector
<std::string
> const& libDeps
= cli
.GetDepends();
2120 for(std::vector
<std::string
>::const_iterator j
= libDeps
.begin();
2121 j
!= libDeps
.end(); ++j
)
2123 target
->AddDependLibrary(configName
, j
->c_str());
2127 // add the library search paths
2129 std::vector
<std::string
> const& libDirs
= cli
.GetDirectories();
2130 std::string linkDirs
;
2131 for(std::vector
<std::string
>::const_iterator libDir
= libDirs
.begin();
2132 libDir
!= libDirs
.end(); ++libDir
)
2134 if(libDir
->size() && *libDir
!= "/usr/lib")
2136 if(this->XcodeVersion
> 15)
2138 // now add the same one but append $(CONFIGURATION) to it:
2140 linkDirs
+= this->XCodeEscapePath(
2141 (*libDir
+ "/$(CONFIGURATION)").c_str());
2144 linkDirs
+= this->XCodeEscapePath(libDir
->c_str());
2147 this->AppendBuildSettingAttribute(target
, "LIBRARY_SEARCH_PATHS",
2148 linkDirs
.c_str(), configName
);
2151 // add the framework search paths
2153 const char* sep
= "";
2155 std::vector
<std::string
> const& fwDirs
= cli
.GetFrameworkPaths();
2156 for(std::vector
<std::string
>::const_iterator fdi
= fwDirs
.begin();
2157 fdi
!= fwDirs
.end(); ++fdi
)
2161 fdirs
+= this->XCodeEscapePath(fdi
->c_str());
2165 this->AppendBuildSettingAttribute(target
, "FRAMEWORK_SEARCH_PATHS",
2166 fdirs
.c_str(), configName
);
2170 // now add the link libraries
2171 if(cmtarget
->GetType() != cmTarget::STATIC_LIBRARY
)
2173 std::string linkLibs
;
2174 const char* sep
= "";
2175 typedef cmComputeLinkInformation::ItemVector ItemVector
;
2176 ItemVector
const& libNames
= cli
.GetItems();
2177 for(ItemVector::const_iterator li
= libNames
.begin();
2178 li
!= libNames
.end(); ++li
)
2184 linkLibs
+= this->XCodeEscapePath(li
->Value
.c_str());
2188 linkLibs
+= li
->Value
;
2191 this->AppendBuildSettingAttribute(target
, "OTHER_LDFLAGS",
2192 linkLibs
.c_str(), configName
);
2197 //----------------------------------------------------------------------------
2198 void cmGlobalXCodeGenerator::CreateGroups(cmLocalGenerator
* root
,
2199 std::vector
<cmLocalGenerator
*>&
2202 for(std::vector
<cmLocalGenerator
*>::iterator i
= generators
.begin();
2203 i
!= generators
.end(); ++i
)
2205 if(this->IsExcluded(root
, *i
))
2209 cmMakefile
* mf
= (*i
)->GetMakefile();
2210 std::vector
<cmSourceGroup
> sourceGroups
= mf
->GetSourceGroups();
2211 cmTargets
&tgts
= mf
->GetTargets();
2212 for(cmTargets::iterator l
= tgts
.begin(); l
!= tgts
.end(); l
++)
2214 cmTarget
& cmtarget
= l
->second
;
2216 // Same skipping logic here as in CreateXCodeTargets so that we do not
2217 // end up with (empty anyhow) ALL_BUILD and XCODE_DEPEND_HELPER source
2220 if(cmtarget
.GetType() == cmTarget::UTILITY
||
2221 cmtarget
.GetType() == cmTarget::GLOBAL_TARGET
)
2226 // add the soon to be generated Info.plist file as a source for a
2227 // MACOSX_BUNDLE file
2228 if(cmtarget
.GetPropertyAsBool("MACOSX_BUNDLE"))
2230 std::string plistFile
=
2231 this->CurrentMakefile
->GetCurrentOutputDirectory();
2232 plistFile
+= "/Info.plist";
2234 this->CurrentMakefile
->GetOrCreateSource(plistFile
.c_str(), true);
2235 cmtarget
.AddSourceFile(sf
);
2238 std::vector
<cmSourceFile
*> classes
= cmtarget
.GetSourceFiles();
2240 for(std::vector
<cmSourceFile
*>::const_iterator s
= classes
.begin();
2241 s
!= classes
.end(); s
++)
2243 cmSourceFile
* sf
= *s
;
2244 // Add the file to the list of sources.
2245 std::string
const& source
= sf
->GetFullPath();
2246 cmSourceGroup
& sourceGroup
=
2247 mf
->FindSourceGroup(source
.c_str(), sourceGroups
);
2248 cmXCodeObject
* pbxgroup
=
2249 this->CreateOrGetPBXGroup(cmtarget
, &sourceGroup
);
2250 cmStdString key
= GetGroupMapKey(cmtarget
, sf
);
2251 this->GroupMap
[key
] = pbxgroup
;
2257 //----------------------------------------------------------------------------
2258 cmXCodeObject
* cmGlobalXCodeGenerator
2259 ::CreateOrGetPBXGroup(cmTarget
& cmtarget
, cmSourceGroup
* sg
)
2261 cmStdString s
= cmtarget
.GetName();
2264 std::map
<cmStdString
, cmXCodeObject
* >::iterator i
=
2265 this->GroupNameMap
.find(s
);
2266 if(i
!= this->GroupNameMap
.end())
2270 i
= this->TargetGroup
.find(cmtarget
.GetName());
2271 cmXCodeObject
* tgroup
= 0;
2272 if(i
!= this->TargetGroup
.end())
2278 tgroup
= this->CreateObject(cmXCodeObject::PBXGroup
);
2279 this->TargetGroup
[cmtarget
.GetName()] = tgroup
;
2280 cmXCodeObject
* tgroupChildren
=
2281 this->CreateObject(cmXCodeObject::OBJECT_LIST
);
2282 tgroup
->AddAttribute("name", this->CreateString(cmtarget
.GetName()));
2283 tgroup
->AddAttribute("children", tgroupChildren
);
2284 if(this->XcodeVersion
== 15)
2286 tgroup
->AddAttribute("refType", this->CreateString("4"));
2288 tgroup
->AddAttribute("sourceTree", this->CreateString("<group>"));
2289 this->SourcesGroupChildren
->AddObject(tgroup
);
2292 // If it's the default source group (empty name) then put the source file
2293 // directly in the tgroup...
2295 if (cmStdString(sg
->GetName()) == "")
2297 this->GroupNameMap
[s
] = tgroup
;
2301 cmXCodeObject
* tgroupChildren
= tgroup
->GetObject("children");
2302 cmXCodeObject
* group
= this->CreateObject(cmXCodeObject::PBXGroup
);
2303 cmXCodeObject
* groupChildren
=
2304 this->CreateObject(cmXCodeObject::OBJECT_LIST
);
2305 group
->AddAttribute("name", this->CreateString(sg
->GetName()));
2306 group
->AddAttribute("children", groupChildren
);
2307 if(this->XcodeVersion
== 15)
2309 group
->AddAttribute("refType", this->CreateString("4"));
2311 group
->AddAttribute("sourceTree", this->CreateString("<group>"));
2312 tgroupChildren
->AddObject(group
);
2313 this->GroupNameMap
[s
] = group
;
2317 //----------------------------------------------------------------------------
2318 void cmGlobalXCodeGenerator
2319 ::CreateXCodeObjects(cmLocalGenerator
* root
,
2320 std::vector
<cmLocalGenerator
*>&
2323 this->ClearXCodeObjects();
2324 this->RootObject
= 0;
2325 this->SourcesGroupChildren
= 0;
2326 this->ResourcesGroupChildren
= 0;
2327 this->MainGroupChildren
= 0;
2328 cmXCodeObject
* group
= this->CreateObject(cmXCodeObject::ATTRIBUTE_GROUP
);
2329 group
->AddAttribute("COPY_PHASE_STRIP", this->CreateString("NO"));
2330 cmXCodeObject
* developBuildStyle
=
2331 this->CreateObject(cmXCodeObject::PBXBuildStyle
);
2332 cmXCodeObject
* listObjs
= this->CreateObject(cmXCodeObject::OBJECT_LIST
);
2333 if(this->XcodeVersion
== 15)
2335 developBuildStyle
->AddAttribute("name",
2336 this->CreateString("Development"));
2337 developBuildStyle
->AddAttribute("buildSettings", group
);
2338 listObjs
->AddObject(developBuildStyle
);
2339 group
= this->CreateObject(cmXCodeObject::ATTRIBUTE_GROUP
);
2340 group
->AddAttribute("COPY_PHASE_STRIP", this->CreateString("YES"));
2341 cmXCodeObject
* deployBuildStyle
=
2342 this->CreateObject(cmXCodeObject::PBXBuildStyle
);
2343 deployBuildStyle
->AddAttribute("name", this->CreateString("Deployment"));
2344 deployBuildStyle
->AddAttribute("buildSettings", group
);
2345 listObjs
->AddObject(deployBuildStyle
);
2349 for(unsigned int i
= 0; i
< this->CurrentConfigurationTypes
.size(); ++i
)
2351 cmXCodeObject
* buildStyle
=
2352 this->CreateObject(cmXCodeObject::PBXBuildStyle
);
2353 const char* name
= this->CurrentConfigurationTypes
[i
].c_str();
2354 buildStyle
->AddAttribute("name", this->CreateString(name
));
2355 buildStyle
->SetComment(name
);
2356 cmXCodeObject
* sgroup
=
2357 this->CreateObject(cmXCodeObject::ATTRIBUTE_GROUP
);
2358 sgroup
->AddAttribute("COPY_PHASE_STRIP", this->CreateString("NO"));
2359 buildStyle
->AddAttribute("buildSettings", sgroup
);
2360 listObjs
->AddObject(buildStyle
);
2364 cmXCodeObject
* mainGroup
= this->CreateObject(cmXCodeObject::PBXGroup
);
2365 this->MainGroupChildren
=
2366 this->CreateObject(cmXCodeObject::OBJECT_LIST
);
2367 mainGroup
->AddAttribute("children", this->MainGroupChildren
);
2368 if(this->XcodeVersion
== 15)
2370 mainGroup
->AddAttribute("refType", this->CreateString("4"));
2372 mainGroup
->AddAttribute("sourceTree", this->CreateString("<group>"));
2374 cmXCodeObject
* sourcesGroup
= this->CreateObject(cmXCodeObject::PBXGroup
);
2375 this->SourcesGroupChildren
=
2376 this->CreateObject(cmXCodeObject::OBJECT_LIST
);
2377 sourcesGroup
->AddAttribute("name", this->CreateString("Sources"));
2378 sourcesGroup
->AddAttribute("children", this->SourcesGroupChildren
);
2379 if(this->XcodeVersion
== 15)
2381 sourcesGroup
->AddAttribute("refType", this->CreateString("4"));
2383 sourcesGroup
->AddAttribute("sourceTree", this->CreateString("<group>"));
2384 this->MainGroupChildren
->AddObject(sourcesGroup
);
2386 cmXCodeObject
* resourcesGroup
= this->CreateObject(cmXCodeObject::PBXGroup
);
2387 this->ResourcesGroupChildren
=
2388 this->CreateObject(cmXCodeObject::OBJECT_LIST
);
2389 resourcesGroup
->AddAttribute("name", this->CreateString("Resources"));
2390 resourcesGroup
->AddAttribute("children", this->ResourcesGroupChildren
);
2391 if(this->XcodeVersion
== 15)
2393 resourcesGroup
->AddAttribute("refType", this->CreateString("4"));
2395 resourcesGroup
->AddAttribute("sourceTree", this->CreateString("<group>"));
2396 this->MainGroupChildren
->AddObject(resourcesGroup
);
2398 // now create the cmake groups
2399 this->CreateGroups(root
, generators
);
2401 cmXCodeObject
* productGroup
= this->CreateObject(cmXCodeObject::PBXGroup
);
2402 productGroup
->AddAttribute("name", this->CreateString("Products"));
2403 if(this->XcodeVersion
== 15)
2405 productGroup
->AddAttribute("refType", this->CreateString("4"));
2407 productGroup
->AddAttribute("sourceTree", this->CreateString("<group>"));
2408 cmXCodeObject
* productGroupChildren
=
2409 this->CreateObject(cmXCodeObject::OBJECT_LIST
);
2410 productGroup
->AddAttribute("children", productGroupChildren
);
2411 this->MainGroupChildren
->AddObject(productGroup
);
2414 this->RootObject
= this->CreateObject(cmXCodeObject::PBXProject
);
2415 this->RootObject
->SetComment("Project object");
2416 group
= this->CreateObject(cmXCodeObject::ATTRIBUTE_GROUP
);
2417 this->RootObject
->AddAttribute("mainGroup",
2418 this->CreateObjectReference(mainGroup
));
2419 this->RootObject
->AddAttribute("buildSettings", group
);
2420 this->RootObject
->AddAttribute("buildStyles", listObjs
);
2421 this->RootObject
->AddAttribute("hasScannedForEncodings",
2422 this->CreateString("0"));
2423 cmXCodeObject
* configlist
=
2424 this->CreateObject(cmXCodeObject::XCConfigurationList
);
2425 cmXCodeObject
* buildConfigurations
=
2426 this->CreateObject(cmXCodeObject::OBJECT_LIST
);
2427 std::vector
<cmXCodeObject
*> configs
;
2428 if(this->XcodeVersion
== 15)
2430 cmXCodeObject
* configDebug
=
2431 this->CreateObject(cmXCodeObject::XCBuildConfiguration
);
2432 configDebug
->AddAttribute("name", this->CreateString("Debug"));
2433 configs
.push_back(configDebug
);
2434 cmXCodeObject
* configRelease
=
2435 this->CreateObject(cmXCodeObject::XCBuildConfiguration
);
2436 configRelease
->AddAttribute("name", this->CreateString("Release"));
2437 configs
.push_back(configRelease
);
2441 for(unsigned int i
= 0; i
< this->CurrentConfigurationTypes
.size(); ++i
)
2443 const char* name
= this->CurrentConfigurationTypes
[i
].c_str();
2444 cmXCodeObject
* config
=
2445 this->CreateObject(cmXCodeObject::XCBuildConfiguration
);
2446 config
->AddAttribute("name", this->CreateString(name
));
2447 configs
.push_back(config
);
2450 for(std::vector
<cmXCodeObject
*>::iterator c
= configs
.begin();
2451 c
!= configs
.end(); ++c
)
2453 buildConfigurations
->AddObject(*c
);
2455 configlist
->AddAttribute("buildConfigurations", buildConfigurations
);
2457 std::string comment
= "Build configuration list for PBXProject ";
2459 comment
+= this->CurrentProject
;
2461 configlist
->SetComment(comment
.c_str());
2462 configlist
->AddAttribute("defaultConfigurationIsVisible",
2463 this->CreateString("0"));
2464 configlist
->AddAttribute("defaultConfigurationName",
2465 this->CreateString("Debug"));
2466 cmXCodeObject
* buildSettings
=
2467 this->CreateObject(cmXCodeObject::ATTRIBUTE_GROUP
);
2468 const char* osxArch
=
2469 this->CurrentMakefile
->GetDefinition("CMAKE_OSX_ARCHITECTURES");
2470 const char* sysroot
=
2471 this->CurrentMakefile
->GetDefinition("CMAKE_OSX_SYSROOT");
2472 if(osxArch
&& sysroot
)
2474 // recompute this as it may have been changed since enable language
2475 this->Architectures
.clear();
2476 cmSystemTools::ExpandListArgument(std::string(osxArch
),
2477 this->Architectures
);
2478 if(this->Architectures
.size() > 1)
2480 buildSettings
->AddAttribute("SDKROOT",
2481 this->CreateString(sysroot
));
2482 std::string archString
;
2483 for( std::vector
<std::string
>::iterator i
=
2484 this->Architectures
.begin();
2485 i
!= this->Architectures
.end(); ++i
)
2490 buildSettings
->AddAttribute("ARCHS",
2491 this->CreateString(archString
.c_str()));
2494 for( std::vector
<cmXCodeObject
*>::iterator i
= configs
.begin();
2495 i
!= configs
.end(); ++i
)
2497 (*i
)->AddAttribute("buildSettings", buildSettings
);
2499 this->RootObject
->AddAttribute("buildConfigurationList",
2500 this->CreateObjectReference(configlist
));
2502 std::vector
<cmXCodeObject
*> targets
;
2503 for(std::vector
<cmLocalGenerator
*>::iterator i
= generators
.begin();
2504 i
!= generators
.end(); ++i
)
2506 if(!this->IsExcluded(root
, *i
))
2508 this->CreateXCodeTargets(*i
, targets
);
2511 // loop over all targets and add link and depend info
2512 for(std::vector
<cmXCodeObject
*>::iterator i
= targets
.begin();
2513 i
!= targets
.end(); ++i
)
2515 cmXCodeObject
* t
= *i
;
2516 this->AddDependAndLinkInformation(t
);
2518 // now create xcode depend hack makefile
2519 this->CreateXCodeDependHackTarget(targets
);
2520 // now add all targets to the root object
2521 cmXCodeObject
* allTargets
= this->CreateObject(cmXCodeObject::OBJECT_LIST
);
2522 for(std::vector
<cmXCodeObject
*>::iterator i
= targets
.begin();
2523 i
!= targets
.end(); ++i
)
2525 cmXCodeObject
* t
= *i
;
2526 allTargets
->AddObject(t
);
2527 cmXCodeObject
* productRef
= t
->GetObject("productReference");
2530 productGroupChildren
->AddObject(productRef
->GetObject());
2533 this->RootObject
->AddAttribute("targets", allTargets
);
2536 //----------------------------------------------------------------------------
2538 cmGlobalXCodeGenerator::CreateXCodeDependHackTarget(
2539 std::vector
<cmXCodeObject
*>& targets
)
2541 cmGeneratedFileStream
2542 makefileStream(this->CurrentXCodeHackMakefile
.c_str());
2545 cmSystemTools::Error("Could not create",
2546 this->CurrentXCodeHackMakefile
.c_str());
2549 makefileStream
.SetCopyIfDifferent(true);
2550 // one more pass for external depend information not handled
2551 // correctly by xcode
2552 makefileStream
<< "# DO NOT EDIT\n";
2553 makefileStream
<< "# This makefile makes sure all linkable targets are\n";
2554 makefileStream
<< "# up-to-date with anything they link to, avoiding a "
2555 "bug in XCode 1.5\n";
2556 for(std::vector
<std::string
>::const_iterator
2557 ct
= this->CurrentConfigurationTypes
.begin();
2558 ct
!= this->CurrentConfigurationTypes
.end(); ++ct
)
2560 if(this->XcodeVersion
< 21 || ct
->empty())
2562 makefileStream
<< "all: ";
2566 makefileStream
<< "all." << *ct
<< ": ";
2568 const char* configName
= 0;
2571 configName
= ct
->c_str();
2573 for(std::vector
<cmXCodeObject
*>::iterator i
= targets
.begin();
2574 i
!= targets
.end(); ++i
)
2576 cmXCodeObject
* target
= *i
;
2577 cmTarget
* t
=target
->GetTarget();
2578 if(t
->GetType() == cmTarget::EXECUTABLE
||
2579 t
->GetType() == cmTarget::SHARED_LIBRARY
||
2580 t
->GetType() == cmTarget::MODULE_LIBRARY
)
2582 makefileStream
<< "\\\n\t" <<
2583 this->ConvertToRelativeForMake(
2584 t
->GetFullPath(configName
).c_str());
2587 makefileStream
<< "\n\n";
2590 << "# For each target create a dummy rule "
2591 "so the target does not have to exist\n";
2592 std::set
<cmStdString
> emitted
;
2593 for(std::vector
<cmXCodeObject
*>::iterator i
= targets
.begin();
2594 i
!= targets
.end(); ++i
)
2596 cmXCodeObject
* target
= *i
;
2597 std::map
<cmStdString
, cmXCodeObject::StringVec
> const& deplibs
=
2598 target
->GetDependLibraries();
2599 for(std::map
<cmStdString
, cmXCodeObject::StringVec
>::const_iterator ci
2600 = deplibs
.begin(); ci
!= deplibs
.end(); ++ci
)
2602 for(cmXCodeObject::StringVec::const_iterator d
= ci
->second
.begin();
2603 d
!= ci
->second
.end(); ++d
)
2605 if(emitted
.insert(*d
).second
)
2608 this->ConvertToRelativeForMake(d
->c_str()) << ":\n";
2613 makefileStream
<< "\n\n";
2615 // Write rules to help Xcode relink things at the right time.
2617 "# Rules to remove targets that are older than anything to which they\n"
2618 "# link. This forces Xcode to relink the targets from scratch. It\n"
2619 "# does not seem to check these dependencies itself.\n";
2620 for(std::vector
<std::string
>::const_iterator
2621 ct
= this->CurrentConfigurationTypes
.begin();
2622 ct
!= this->CurrentConfigurationTypes
.end(); ++ct
)
2624 const char* configName
= 0;
2627 configName
= ct
->c_str();
2629 for(std::vector
<cmXCodeObject
*>::iterator i
= targets
.begin();
2630 i
!= targets
.end(); ++i
)
2632 cmXCodeObject
* target
= *i
;
2633 cmTarget
* t
=target
->GetTarget();
2634 if(t
->GetType() == cmTarget::EXECUTABLE
||
2635 t
->GetType() == cmTarget::SHARED_LIBRARY
||
2636 t
->GetType() == cmTarget::MODULE_LIBRARY
)
2638 // Create a rule for this target.
2639 std::string tfull
= t
->GetFullPath(configName
);
2640 makefileStream
<< this->ConvertToRelativeForMake(tfull
.c_str())
2643 // List dependencies if any exist.
2644 std::map
<cmStdString
, cmXCodeObject::StringVec
>::const_iterator
2645 x
= target
->GetDependLibraries().find(*ct
);
2646 if(x
!= target
->GetDependLibraries().end())
2648 std::vector
<cmStdString
> const& deplibs
= x
->second
;
2649 for(std::vector
<cmStdString
>::const_iterator d
= deplibs
.begin();
2650 d
!= deplibs
.end(); ++d
)
2652 makefileStream
<< "\\\n\t" <<
2653 this->ConvertToRelativeForMake(d
->c_str());
2656 // Write the action to remove the target if it is out of date.
2657 makefileStream
<< "\n";
2658 makefileStream
<< "\t/bin/rm -f "
2659 << this->ConvertToRelativeForMake(tfull
.c_str())
2661 // if building for more than one architecture
2662 // then remove those exectuables as well
2663 if(this->Architectures
.size() > 1)
2665 std::string universal
= t
->GetDirectory();
2667 universal
+= this->CurrentMakefile
->GetProjectName();
2668 universal
+= ".build/";
2669 universal
+= configName
;
2671 universal
+= t
->GetName();
2672 universal
+= ".build/Objects-normal/";
2673 for( std::vector
<std::string
>::iterator arch
=
2674 this->Architectures
.begin();
2675 arch
!= this->Architectures
.end(); ++arch
)
2677 std::string universalFile
= universal
;
2678 universalFile
+= *arch
;
2679 universalFile
+= "/";
2680 universalFile
+= t
->GetName();
2681 makefileStream
<< "\t/bin/rm -f "
2683 this->ConvertToRelativeForMake(universalFile
.c_str())
2687 makefileStream
<< "\n\n";
2693 //----------------------------------------------------------------------------
2695 cmGlobalXCodeGenerator::OutputXCodeProject(cmLocalGenerator
* root
,
2696 std::vector
<cmLocalGenerator
*>&
2699 if(generators
.size() == 0)
2703 // Skip local generators that are excluded from this project.
2704 for(std::vector
<cmLocalGenerator
*>::iterator g
= generators
.begin();
2705 g
!= generators
.end(); ++g
)
2707 if(this->IsExcluded(root
, *g
))
2713 this->CreateXCodeObjects(root
,
2715 std::string xcodeDir
= root
->GetMakefile()->GetStartOutputDirectory();
2717 xcodeDir
+= root
->GetMakefile()->GetProjectName();
2718 xcodeDir
+= ".xcode";
2719 if(this->XcodeVersion
> 20)
2723 cmSystemTools::MakeDirectory(xcodeDir
.c_str());
2724 std::string xcodeProjFile
= xcodeDir
+ "/project.pbxproj";
2725 cmGeneratedFileStream
fout(xcodeProjFile
.c_str());
2726 fout
.SetCopyIfDifferent(true);
2731 this->WriteXCodePBXProj(fout
, root
, generators
);
2732 this->ClearXCodeObjects();
2735 //----------------------------------------------------------------------------
2737 cmGlobalXCodeGenerator::WriteXCodePBXProj(std::ostream
& fout
,
2739 std::vector
<cmLocalGenerator
*>& )
2741 fout
<< "// !$*UTF8*$!\n";
2743 cmXCodeObject::Indent(1, fout
);
2744 fout
<< "archiveVersion = 1;\n";
2745 cmXCodeObject::Indent(1, fout
);
2746 fout
<< "classes = {\n";
2747 cmXCodeObject::Indent(1, fout
);
2749 cmXCodeObject::Indent(1, fout
);
2750 fout
<< "objectVersion = 39;\n";
2751 cmXCodeObject::PrintList(this->XCodeObjects
, fout
);
2752 cmXCodeObject::Indent(1, fout
);
2753 fout
<< "rootObject = " << this->RootObject
->GetId() << ";\n";
2757 //----------------------------------------------------------------------------
2758 void cmGlobalXCodeGenerator::GetDocumentation(cmDocumentationEntry
& entry
)
2761 entry
.Name
= this->GetName();
2762 entry
.Brief
= "Generate XCode project files.";
2766 //----------------------------------------------------------------------------
2767 std::string
cmGlobalXCodeGenerator::ConvertToRelativeForMake(const char* p
)
2769 if ( !this->CurrentMakefile
->IsOn("CMAKE_USE_RELATIVE_PATHS") )
2771 return cmSystemTools::ConvertToOutputPath(p
);
2776 this->CurrentLocalGenerator
->
2777 ConvertToRelativePath(this->CurrentOutputDirectoryComponents
, p
);
2778 return cmSystemTools::ConvertToOutputPath(ret
.c_str());
2782 //----------------------------------------------------------------------------
2783 std::string
cmGlobalXCodeGenerator::ConvertToRelativeForXCode(const char* p
)
2785 if ( !this->CurrentMakefile
->IsOn("CMAKE_USE_RELATIVE_PATHS") )
2787 return cmSystemTools::ConvertToOutputPath(p
);
2792 this->CurrentLocalGenerator
->
2793 ConvertToRelativePath(this->ProjectOutputDirectoryComponents
, p
);
2794 return cmSystemTools::ConvertToOutputPath(ret
.c_str());
2798 //----------------------------------------------------------------------------
2799 std::string
cmGlobalXCodeGenerator::XCodeEscapePath(const char* p
)
2801 std::string ret
= p
;
2802 if(ret
.find(' ') != ret
.npos
)
2804 std::string t
= ret
;
2812 //----------------------------------------------------------------------------
2813 void cmGlobalXCodeGenerator::
2814 GetTargetObjectFileDirectories(cmTarget
* target
,
2815 std::vector
<std::string
>&
2818 std::string dir
= this->CurrentMakefile
->GetCurrentOutputDirectory();
2820 dir
+= this->CurrentMakefile
->GetProjectName();
2822 dir
+= this->GetCMakeCFGInitDirectory();
2824 if(target
->GetType() != cmTarget::EXECUTABLE
)
2828 dir
+= target
->GetName();
2829 if(target
->GetType() == cmTarget::STATIC_LIBRARY
)
2833 if(target
->GetType() == cmTarget::SHARED_LIBRARY
)
2837 if(target
->GetType() == cmTarget::MODULE_LIBRARY
)
2841 dir
+= ".build/Objects-normal/";
2842 std::string dirsave
= dir
;
2843 if(this->Architectures
.size())
2845 for(std::vector
<std::string
>::iterator i
= this->Architectures
.begin();
2846 i
!= this->Architectures
.end(); ++i
)
2849 dirs
.push_back(dir
);
2855 dirs
.push_back(dir
);
2859 //----------------------------------------------------------------------------
2861 cmGlobalXCodeGenerator
2862 ::AppendDirectoryForConfig(const char* prefix
,
2867 if(this->XcodeVersion
> 20)
2871 if(dir
.find(".framework") != dir
.npos
)
2873 // Remove trailing slashes (so that the rfind does not find the one at
2874 // the very end...!)
2876 cmSystemTools::ConvertToUnixSlashes(dir
);
2877 std::string::size_type pos
= dir
.rfind("/");
2878 std::string framework
= dir
.substr(pos
);
2879 std::string newDir
= dir
.substr(0, pos
);
2895 //----------------------------------------------------------------------------
2896 std::string
cmGlobalXCodeGenerator::LookupFlags(const char* varNamePrefix
,
2897 const char* varNameLang
,
2898 const char* varNameSuffix
,
2899 const char* default_flags
)
2903 std::string varName
= varNamePrefix
;
2904 varName
+= varNameLang
;
2905 varName
+= varNameSuffix
;
2906 if(const char* varValue
=
2907 this->CurrentMakefile
->GetDefinition(varName
.c_str()))
2915 return default_flags
;
2918 //----------------------------------------------------------------------------
2919 void cmGlobalXCodeGenerator::AppendDefines(std::string
& defs
,
2920 const char* defines_list
,
2923 // Skip this if there are no definitions.
2929 // Expand the list of definitions.
2930 std::vector
<std::string
> defines
;
2931 cmSystemTools::ExpandListArgument(defines_list
, defines
);
2933 // GCC_PREPROCESSOR_DEFINITIONS is a space-separated list of definitions.
2934 // We escape everything as follows:
2935 // - Place each definition in single quotes ''
2936 // - Escape a single quote as \\'
2937 // - Escape a backslash as \\\\ since it itself is an escape
2938 // Note that in the code below we need one more level of escapes for
2939 // C string syntax in this source file.
2940 const char* sep
= defs
.empty()? "" : " ";
2941 for(std::vector
<std::string
>::const_iterator di
= defines
.begin();
2942 di
!= defines
.end(); ++di
)
2944 // Separate from previous definition.
2948 // Open single quote.
2951 // Add -D flag if requested.
2957 // Escaped definition string.
2958 for(const char* c
= di
->c_str(); *c
; ++c
)
2974 // Close single quote.