1 /*=========================================================================
3 Program: CMake - Cross-Platform Makefile Generator
4 Module: $RCSfile: cmGlobalXCodeGenerator.cxx,v $
6 Date: $Date: 2009-09-21 17:18:45 $
7 Version: $Revision: 1.229 $
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 std::string outDir
= this->CurrentMakefile
->GetHomeOutputDirectory();
306 outDir
=cmSystemTools::CollapseFullPath(outDir
.c_str());
307 cmSystemTools::SplitPath(outDir
.c_str(),
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()));
674 this->ConvertToRelativeForXCode(sf
->GetFullPath().c_str());
677 cmSystemTools::SplitProgramPath(sf
->GetFullPath().c_str(),
680 // Try to make the path relative to the project root.
681 bool Absolute
= true;
682 if (this->XcodeVersion
>= 30)
684 std::string relative
=
685 this->CurrentLocalGenerator
->Convert(sf
->GetFullPath().c_str(),
686 cmLocalGenerator::HOME
,
687 cmLocalGenerator::MAKEFILE
,
689 relative
= cmSystemTools::ConvertToOutputPath(relative
.c_str());
690 if (!relative
.empty() && relative
[0] != '/')
697 fileRef
->AddAttribute("name", this->CreateString(file
.c_str()));
698 fileRef
->AddAttribute("path", this->CreateString(path
.c_str()));
699 if(this->XcodeVersion
== 15)
701 fileRef
->AddAttribute("refType", this->CreateString("4"));
703 if(path
.size() > 1 && path
[0] == '.' && path
[1] == '.')
705 fileRef
->AddAttribute("sourceTree", this->CreateString("<group>"));
709 fileRef
->AddAttribute("sourceTree", this->CreateString("<absolute>"));
713 fileRef
->AddAttribute("sourceTree", this->CreateString("SOURCE_ROOT"));
719 //----------------------------------------------------------------------------
720 bool cmGlobalXCodeGenerator::SpecialTargetEmitted(std::string
const& tname
)
722 if(tname
== "ALL_BUILD" || tname
== "XCODE_DEPEND_HELPER" ||
723 tname
== "install" || tname
== "package" || tname
== "RUN_TESTS" )
725 if(this->TargetDoneSet
.find(tname
) != this->TargetDoneSet
.end())
729 this->TargetDoneSet
.insert(tname
);
735 //----------------------------------------------------------------------------
736 void cmGlobalXCodeGenerator::SetCurrentLocalGenerator(cmLocalGenerator
* gen
)
738 this->CurrentLocalGenerator
= gen
;
739 this->CurrentMakefile
= gen
->GetMakefile();
741 cmSystemTools::CollapseFullPath(this->CurrentMakefile
->
742 GetCurrentOutputDirectory());
743 cmSystemTools::SplitPath(outdir
.c_str(),
744 this->CurrentOutputDirectoryComponents
);
746 // Select the current set of configuration types.
747 this->CurrentConfigurationTypes
.clear();
748 if(this->XcodeVersion
> 20)
750 if(const char* types
=
751 this->CurrentMakefile
->GetDefinition("CMAKE_CONFIGURATION_TYPES"))
753 cmSystemTools::ExpandListArgument(types
,
754 this->CurrentConfigurationTypes
);
757 if(this->CurrentConfigurationTypes
.empty())
759 if(const char* buildType
=
760 this->CurrentMakefile
->GetDefinition("CMAKE_BUILD_TYPE"))
762 this->CurrentConfigurationTypes
.push_back(buildType
);
766 this->CurrentConfigurationTypes
.push_back("");
771 //----------------------------------------------------------------------------
773 cmGlobalXCodeGenerator::CreateXCodeTargets(cmLocalGenerator
* gen
,
774 std::vector
<cmXCodeObject
*>&
777 this->SetCurrentLocalGenerator(gen
);
778 cmTargets
&tgts
= this->CurrentMakefile
->GetTargets();
779 for(cmTargets::iterator l
= tgts
.begin(); l
!= tgts
.end(); l
++)
781 cmTarget
& cmtarget
= l
->second
;
783 // make sure ALL_BUILD, INSTALL, etc are only done once
784 if(this->SpecialTargetEmitted(l
->first
.c_str()))
789 if(cmtarget
.GetType() == cmTarget::UTILITY
||
790 cmtarget
.GetType() == cmTarget::GLOBAL_TARGET
)
792 targets
.push_back(this->CreateUtilityTarget(cmtarget
));
796 // organize the sources
797 std::vector
<cmSourceFile
*> const &classes
= cmtarget
.GetSourceFiles();
798 std::vector
<cmXCodeObject
*> externalObjFiles
;
799 std::vector
<cmXCodeObject
*> headerFiles
;
800 std::vector
<cmXCodeObject
*> resourceFiles
;
801 std::vector
<cmXCodeObject
*> sourceFiles
;
802 for(std::vector
<cmSourceFile
*>::const_iterator i
= classes
.begin();
803 i
!= classes
.end(); ++i
)
806 this->CreateXCodeSourceFile(this->CurrentLocalGenerator
,
808 cmXCodeObject
* fr
= xsf
->GetObject("fileRef");
809 cmXCodeObject
* filetype
=
810 fr
->GetObject()->GetObject("lastKnownFileType");
812 cmTarget::SourceFileFlags tsFlags
=
813 cmtarget
.GetTargetSourceFileFlags(*i
);
815 if(strcmp(filetype
->GetString(), "compiled.mach-o.objfile") == 0)
817 externalObjFiles
.push_back(xsf
);
819 else if(this->IsHeaderFile(*i
) ||
820 (tsFlags
.Type
== cmTarget::SourceFileTypePrivateHeader
) ||
821 (tsFlags
.Type
== cmTarget::SourceFileTypePublicHeader
))
823 headerFiles
.push_back(xsf
);
825 else if(tsFlags
.Type
== cmTarget::SourceFileTypeResource
)
827 resourceFiles
.push_back(xsf
);
829 else if(!(*i
)->GetPropertyAsBool("HEADER_FILE_ONLY"))
831 // Include this file in the build if it has a known language
832 // and has not been listed as an ignored extension for this
834 if(this->CurrentLocalGenerator
->GetSourceFileLanguage(**i
) &&
835 !this->IgnoreFile((*i
)->GetExtension().c_str()))
837 sourceFiles
.push_back(xsf
);
842 // some build phases only apply to bundles and/or frameworks
843 bool isFrameworkTarget
= cmtarget
.IsFrameworkOnApple();
844 bool isBundleTarget
= cmtarget
.GetPropertyAsBool("MACOSX_BUNDLE");
846 cmXCodeObject
* buildFiles
= 0;
848 // create source build phase
849 cmXCodeObject
* sourceBuildPhase
= 0;
850 if (!sourceFiles
.empty())
853 this->CreateObject(cmXCodeObject::PBXSourcesBuildPhase
);
854 sourceBuildPhase
->SetComment("Sources");
855 sourceBuildPhase
->AddAttribute("buildActionMask",
856 this->CreateString("2147483647"));
857 buildFiles
= this->CreateObject(cmXCodeObject::OBJECT_LIST
);
858 for(std::vector
<cmXCodeObject
*>::iterator i
= sourceFiles
.begin();
859 i
!= sourceFiles
.end(); ++i
)
861 buildFiles
->AddObject(*i
);
863 sourceBuildPhase
->AddAttribute("files", buildFiles
);
864 sourceBuildPhase
->AddAttribute("runOnlyForDeploymentPostprocessing",
865 this->CreateString("0"));
868 // create header build phase - only for framework targets
869 cmXCodeObject
* headerBuildPhase
= 0;
870 if (!headerFiles
.empty() && isFrameworkTarget
)
873 this->CreateObject(cmXCodeObject::PBXHeadersBuildPhase
);
874 headerBuildPhase
->SetComment("Headers");
875 headerBuildPhase
->AddAttribute("buildActionMask",
876 this->CreateString("2147483647"));
877 buildFiles
= this->CreateObject(cmXCodeObject::OBJECT_LIST
);
878 for(std::vector
<cmXCodeObject
*>::iterator i
= headerFiles
.begin();
879 i
!= headerFiles
.end(); ++i
)
881 buildFiles
->AddObject(*i
);
883 headerBuildPhase
->AddAttribute("files", buildFiles
);
884 headerBuildPhase
->AddAttribute("runOnlyForDeploymentPostprocessing",
885 this->CreateString("0"));
888 // create resource build phase - only for framework or bundle targets
889 cmXCodeObject
* resourceBuildPhase
= 0;
890 if (!resourceFiles
.empty() && (isFrameworkTarget
|| isBundleTarget
))
893 this->CreateObject(cmXCodeObject::PBXResourcesBuildPhase
);
894 resourceBuildPhase
->SetComment("Resources");
895 resourceBuildPhase
->AddAttribute("buildActionMask",
896 this->CreateString("2147483647"));
897 buildFiles
= this->CreateObject(cmXCodeObject::OBJECT_LIST
);
898 for(std::vector
<cmXCodeObject
*>::iterator i
= resourceFiles
.begin();
899 i
!= resourceFiles
.end(); ++i
)
901 buildFiles
->AddObject(*i
);
903 resourceBuildPhase
->AddAttribute("files", buildFiles
);
904 resourceBuildPhase
->AddAttribute("runOnlyForDeploymentPostprocessing",
905 this->CreateString("0"));
908 // create vector of "non-resource content file" build phases - only for
909 // framework or bundle targets
910 std::vector
<cmXCodeObject
*> contentBuildPhases
;
911 if (isFrameworkTarget
|| isBundleTarget
)
913 typedef std::map
<cmStdString
, std::vector
<cmSourceFile
*> >
914 mapOfVectorOfSourceFiles
;
915 mapOfVectorOfSourceFiles bundleFiles
;
916 for(std::vector
<cmSourceFile
*>::const_iterator i
= classes
.begin();
917 i
!= classes
.end(); ++i
)
919 cmTarget::SourceFileFlags tsFlags
=
920 cmtarget
.GetTargetSourceFileFlags(*i
);
921 if(tsFlags
.Type
== cmTarget::SourceFileTypeMacContent
)
923 bundleFiles
[tsFlags
.MacFolder
].push_back(*i
);
926 mapOfVectorOfSourceFiles::iterator mit
;
927 for ( mit
= bundleFiles
.begin(); mit
!= bundleFiles
.end(); ++ mit
)
929 cmXCodeObject
* copyFilesBuildPhase
=
930 this->CreateObject(cmXCodeObject::PBXCopyFilesBuildPhase
);
931 copyFilesBuildPhase
->SetComment("Copy files");
932 copyFilesBuildPhase
->AddAttribute("buildActionMask",
933 this->CreateString("2147483647"));
934 copyFilesBuildPhase
->AddAttribute("dstSubfolderSpec",
935 this->CreateString("6"));
936 cmOStringStream ostr
;
937 if (cmtarget
.IsFrameworkOnApple())
939 // dstPath in frameworks is relative to Versions/<version>
942 else if ( mit
->first
!= "MacOS" )
944 // dstPath in bundles is relative to Contents/MacOS
945 ostr
<< "../" << mit
->first
.c_str();
947 copyFilesBuildPhase
->AddAttribute("dstPath",
948 this->CreateString(ostr
.str().c_str()));
949 copyFilesBuildPhase
->AddAttribute(
950 "runOnlyForDeploymentPostprocessing", this->CreateString("0"));
951 buildFiles
= this->CreateObject(cmXCodeObject::OBJECT_LIST
);
952 copyFilesBuildPhase
->AddAttribute("files", buildFiles
);
953 std::vector
<cmSourceFile
*>::iterator sfIt
;
954 for ( sfIt
= mit
->second
.begin(); sfIt
!= mit
->second
.end(); ++ sfIt
)
957 this->CreateXCodeSourceFile(this->CurrentLocalGenerator
,
959 buildFiles
->AddObject(xsf
);
961 contentBuildPhases
.push_back(copyFilesBuildPhase
);
965 // create framework build phase
966 cmXCodeObject
* frameworkBuildPhase
= 0;
967 if (!externalObjFiles
.empty())
969 frameworkBuildPhase
=
970 this->CreateObject(cmXCodeObject::PBXFrameworksBuildPhase
);
971 frameworkBuildPhase
->SetComment("Frameworks");
972 frameworkBuildPhase
->AddAttribute("buildActionMask",
973 this->CreateString("2147483647"));
974 buildFiles
= this->CreateObject(cmXCodeObject::OBJECT_LIST
);
975 frameworkBuildPhase
->AddAttribute("files", buildFiles
);
976 for(std::vector
<cmXCodeObject
*>::iterator i
= externalObjFiles
.begin();
977 i
!= externalObjFiles
.end(); ++i
)
979 buildFiles
->AddObject(*i
);
981 frameworkBuildPhase
->AddAttribute("runOnlyForDeploymentPostprocessing",
982 this->CreateString("0"));
985 // create list of build phases and create the XCode target
986 cmXCodeObject
* buildPhases
=
987 this->CreateObject(cmXCodeObject::OBJECT_LIST
);
989 this->CreateCustomCommands(buildPhases
, sourceBuildPhase
,
990 headerBuildPhase
, resourceBuildPhase
,
992 frameworkBuildPhase
, cmtarget
);
994 targets
.push_back(this->CreateXCodeTarget(cmtarget
, buildPhases
));
998 //----------------------------------------------------------------------------
999 void cmGlobalXCodeGenerator::ForceLinkerLanguages()
1001 // This makes sure all targets link using the proper language.
1002 for(std::map
<cmStdString
, cmTarget
*>::const_iterator
1003 ti
= this->TotalTargets
.begin(); ti
!= this->TotalTargets
.end(); ++ti
)
1005 this->ForceLinkerLanguage(*ti
->second
);
1009 //----------------------------------------------------------------------------
1010 void cmGlobalXCodeGenerator::ForceLinkerLanguage(cmTarget
& cmtarget
)
1012 // This matters only for targets that link.
1013 if(cmtarget
.GetType() != cmTarget::EXECUTABLE
&&
1014 cmtarget
.GetType() != cmTarget::SHARED_LIBRARY
&&
1015 cmtarget
.GetType() != cmTarget::MODULE_LIBRARY
)
1020 const char* llang
= cmtarget
.GetLinkerLanguage("NOCONFIG");
1021 if(!llang
) { return; }
1023 // If the language is compiled as a source trust Xcode to link with it.
1024 cmTarget::LinkImplementation
const* impl
=
1025 cmtarget
.GetLinkImplementation("NOCONFIG");
1026 for(std::vector
<std::string
>::const_iterator li
= impl
->Languages
.begin();
1027 li
!= impl
->Languages
.end(); ++li
)
1029 if(*li
== llang
) { return; }
1032 // Add an empty source file to the target that compiles with the
1033 // linker language. This should convince Xcode to choose the proper
1035 cmMakefile
* mf
= cmtarget
.GetMakefile();
1036 std::string fname
= mf
->GetCurrentOutputDirectory();
1037 fname
+= cmake::GetCMakeFilesDirectory();
1039 fname
+= cmtarget
.GetName();
1040 fname
+= "-CMakeForceLinker";
1042 fname
+= cmSystemTools::LowerCase(llang
);
1044 cmGeneratedFileStream
fout(fname
.c_str());
1047 if(cmSourceFile
* sf
= mf
->GetOrCreateSource(fname
.c_str()))
1049 sf
->SetProperty("LANGUAGE", llang
);
1050 cmtarget
.AddSourceFile(sf
);
1054 //----------------------------------------------------------------------------
1055 bool cmGlobalXCodeGenerator::IsHeaderFile(cmSourceFile
* sf
)
1057 const std::vector
<std::string
>& hdrExts
=
1058 this->CurrentMakefile
->GetHeaderExtensions();
1059 return (std::find(hdrExts
.begin(), hdrExts
.end(), sf
->GetExtension()) !=
1063 //----------------------------------------------------------------------------
1065 cmGlobalXCodeGenerator::CreateBuildPhase(const char* name
,
1068 const std::vector
<cmCustomCommand
>&
1071 if(commands
.size() == 0 && strcmp(name
, "CMake ReRun") != 0)
1075 cmXCodeObject
* buildPhase
=
1076 this->CreateObject(cmXCodeObject::PBXShellScriptBuildPhase
);
1077 buildPhase
->AddAttribute("buildActionMask",
1078 this->CreateString("2147483647"));
1079 cmXCodeObject
* buildFiles
= this->CreateObject(cmXCodeObject::OBJECT_LIST
);
1080 buildPhase
->AddAttribute("files", buildFiles
);
1081 buildPhase
->AddAttribute("name",
1082 this->CreateString(name
));
1083 buildPhase
->AddAttribute("runOnlyForDeploymentPostprocessing",
1084 this->CreateString("0"));
1085 buildPhase
->AddAttribute("shellPath",
1086 this->CreateString("/bin/sh"));
1087 this->AddCommandsToBuildPhase(buildPhase
, cmtarget
, commands
,
1092 //----------------------------------------------------------------------------
1093 void cmGlobalXCodeGenerator::CreateCustomCommands(cmXCodeObject
* buildPhases
,
1100 std::vector
<cmXCodeObject
*>
1103 frameworkBuildPhase
,
1106 std::vector
<cmCustomCommand
> const & prebuild
1107 = cmtarget
.GetPreBuildCommands();
1108 std::vector
<cmCustomCommand
> const & prelink
1109 = cmtarget
.GetPreLinkCommands();
1110 std::vector
<cmCustomCommand
> const & postbuild
1111 = cmtarget
.GetPostBuildCommands();
1112 std::vector
<cmSourceFile
*>const &classes
= cmtarget
.GetSourceFiles();
1113 // add all the sources
1114 std::vector
<cmCustomCommand
> commands
;
1115 for(std::vector
<cmSourceFile
*>::const_iterator i
= classes
.begin();
1116 i
!= classes
.end(); ++i
)
1118 if((*i
)->GetCustomCommand())
1120 commands
.push_back(*(*i
)->GetCustomCommand());
1123 std::vector
<cmCustomCommand
> reruncom
;
1124 cmXCodeObject
* cmakeReRunPhase
=
1125 this->CreateBuildPhase("CMake ReRun", "cmakeReRunPhase",
1126 cmtarget
, reruncom
);
1127 buildPhases
->AddObject(cmakeReRunPhase
);
1128 // create prebuild phase
1129 cmXCodeObject
* cmakeRulesBuildPhase
=
1130 this->CreateBuildPhase("CMake Rules",
1131 "cmakeRulesBuildPhase",
1132 cmtarget
, commands
);
1133 // create prebuild phase
1134 cmXCodeObject
* preBuildPhase
=
1135 this->CreateBuildPhase("CMake PreBuild Rules", "preBuildCommands",
1136 cmtarget
, prebuild
);
1137 // create prelink phase
1138 cmXCodeObject
* preLinkPhase
=
1139 this->CreateBuildPhase("CMake PreLink Rules", "preLinkCommands",
1141 // create postbuild phase
1142 cmXCodeObject
* postBuildPhase
=
1143 this->CreateBuildPhase("CMake PostBuild Rules", "postBuildPhase",
1144 cmtarget
, postbuild
);
1146 // The order here is the order they will be built in.
1147 // The order "headers, resources, sources" mimics a native project generated
1148 // from an xcode template...
1152 buildPhases
->AddObject(preBuildPhase
);
1154 if(cmakeRulesBuildPhase
)
1156 buildPhases
->AddObject(cmakeRulesBuildPhase
);
1158 if(headerBuildPhase
)
1160 buildPhases
->AddObject(headerBuildPhase
);
1162 if(resourceBuildPhase
)
1164 buildPhases
->AddObject(resourceBuildPhase
);
1166 std::vector
<cmXCodeObject
*>::iterator cit
;
1167 for (cit
= contentBuildPhases
.begin(); cit
!= contentBuildPhases
.end();
1170 buildPhases
->AddObject(*cit
);
1172 if(sourceBuildPhase
)
1174 buildPhases
->AddObject(sourceBuildPhase
);
1178 buildPhases
->AddObject(preLinkPhase
);
1180 if(frameworkBuildPhase
)
1182 buildPhases
->AddObject(frameworkBuildPhase
);
1186 buildPhases
->AddObject(postBuildPhase
);
1190 //----------------------------------------------------------------------------
1191 std::string
cmGlobalXCodeGenerator::ExtractFlag(const char* flag
,
1194 std::string retFlag
;
1195 std::string::size_type pos
= flags
.find(flag
);
1196 if(pos
!= flags
.npos
&& (pos
==0 || flags
[pos
-1]==' '))
1198 while(pos
< flags
.size() && flags
[pos
] != ' ')
1200 retFlag
+= flags
[pos
];
1208 //----------------------------------------------------------------------------
1210 cmGlobalXCodeGenerator::AddCommandsToBuildPhase(cmXCodeObject
* buildphase
,
1212 std::vector
<cmCustomCommand
>
1216 if(strcmp(name
, "cmakeReRunPhase") == 0)
1218 std::string cdir
= this->CurrentMakefile
->GetHomeOutputDirectory();
1219 cdir
= this->ConvertToRelativeForMake(cdir
.c_str());
1220 std::string makecmd
= "make -C ";
1224 this->ConvertToRelativeForMake(this->CurrentReRunCMakeMakefile
.c_str());
1225 cmSystemTools::ReplaceString(makecmd
, "\\ ", "\\\\ ");
1226 buildphase
->AddAttribute("shellScript",
1227 this->CreateString(makecmd
.c_str()));
1231 // collect multiple outputs of custom commands into a set
1232 // which will be used for every configuration
1233 std::map
<cmStdString
, cmStdString
> multipleOutputPairs
;
1234 for(std::vector
<cmCustomCommand
>::const_iterator i
= commands
.begin();
1235 i
!= commands
.end(); ++i
)
1237 cmCustomCommand
const& cc
= *i
;
1238 if(!cc
.GetCommandLines().empty())
1240 const std::vector
<std::string
>& outputs
= cc
.GetOutputs();
1241 if(!outputs
.empty())
1243 // If there are more than one outputs treat the
1244 // first as the primary output and make the rest depend on it.
1245 std::vector
<std::string
>::const_iterator o
= outputs
.begin();
1246 std::string primaryOutput
= this->ConvertToRelativeForMake(o
->c_str());
1247 for(++o
; o
!= outputs
.end(); ++o
)
1249 std::string currentOutput
=this->ConvertToRelativeForMake(o
->c_str());
1250 multipleOutputPairs
[currentOutput
] = primaryOutput
;
1256 std::string dir
= this->CurrentMakefile
->GetCurrentOutputDirectory();
1257 dir
+= "/CMakeScripts";
1258 cmSystemTools::MakeDirectory(dir
.c_str());
1259 std::string makefile
= dir
;
1261 makefile
+= target
.GetName();
1264 makefile
+= ".make";
1266 for (std::vector
<std::string
>::const_iterator currentConfig
=
1267 this->CurrentConfigurationTypes
.begin();
1268 currentConfig
!=this->CurrentConfigurationTypes
.end();
1271 this->CreateCustomRulesMakefile(makefile
.c_str(),
1274 currentConfig
->c_str(),
1275 multipleOutputPairs
);
1278 std::string cdir
= this->CurrentMakefile
->GetCurrentOutputDirectory();
1279 cdir
= this->ConvertToRelativeForXCode(cdir
.c_str());
1280 std::string makecmd
= "make -C ";
1283 makecmd
+= this->ConvertToRelativeForMake(
1284 (makefile
+"$CONFIGURATION").c_str());
1285 if(!multipleOutputPairs
.empty())
1287 makecmd
+= " cmake_check_multiple_outputs";
1290 cmSystemTools::ReplaceString(makecmd
, "\\ ", "\\\\ ");
1291 buildphase
->AddAttribute("shellScript",
1292 this->CreateString(makecmd
.c_str()));
1295 //----------------------------------------------------------------------------
1296 void cmGlobalXCodeGenerator
1297 ::CreateCustomRulesMakefile(const char* makefileBasename
,
1299 std::vector
<cmCustomCommand
>
1301 const char* configName
,
1302 const std::map
<cmStdString
,
1303 cmStdString
>& multipleOutputPairs
1306 std::string makefileName
=makefileBasename
;
1307 makefileName
+=configName
;
1308 cmGeneratedFileStream
makefileStream(makefileName
.c_str());
1313 makefileStream
.SetCopyIfDifferent(true);
1314 makefileStream
<< "# Generated by CMake, DO NOT EDIT\n";
1315 makefileStream
<< "# Custom rules for " << target
.GetName() << "\n";
1317 // have all depend on all outputs
1318 makefileStream
<< "all: ";
1319 std::map
<const cmCustomCommand
*, cmStdString
> tname
;
1321 for(std::vector
<cmCustomCommand
>::const_iterator i
= commands
.begin();
1322 i
!= commands
.end(); ++i
)
1324 cmCustomCommand
const& cc
= *i
;
1325 if(!cc
.GetCommandLines().empty())
1327 const std::vector
<std::string
>& outputs
= cc
.GetOutputs();
1328 if(!outputs
.empty())
1330 for(std::vector
<std::string
>::const_iterator o
= outputs
.begin();
1331 o
!= outputs
.end(); ++o
)
1334 << "\\\n\t" << this->ConvertToRelativeForMake(o
->c_str());
1339 cmOStringStream str
;
1340 str
<< "_buildpart_" << count
++ ;
1341 tname
[&cc
] = std::string(target
.GetName()) + str
.str();
1342 makefileStream
<< "\\\n\t" << tname
[&cc
];
1346 makefileStream
<< "\n\n";
1347 for(std::vector
<cmCustomCommand
>::const_iterator i
= commands
.begin();
1348 i
!= commands
.end(); ++i
)
1350 cmCustomCommand
const& cc
= *i
;
1351 if(!cc
.GetCommandLines().empty())
1353 bool escapeOldStyle
= cc
.GetEscapeOldStyle();
1354 bool escapeAllowMakeVars
= cc
.GetEscapeAllowMakeVars();
1355 makefileStream
<< "\n";
1356 const std::vector
<std::string
>& outputs
= cc
.GetOutputs();
1357 if(!outputs
.empty())
1359 // There is at least one output, start the rule for it
1360 std::string primary_output
=
1361 this->ConvertToRelativeForMake(outputs
.begin()->c_str());
1362 makefileStream
<< primary_output
<< ": ";
1366 // There are no outputs. Use the generated force rule name.
1367 makefileStream
<< tname
[&cc
] << ": ";
1369 for(std::vector
<std::string
>::const_iterator d
=
1370 cc
.GetDepends().begin();
1371 d
!= cc
.GetDepends().end(); ++d
)
1374 this->CurrentLocalGenerator
->GetRealDependency(d
->c_str(),
1376 makefileStream
<< "\\\n" << this
1377 ->ConvertToRelativeForMake(dep
.c_str());
1379 makefileStream
<< "\n";
1381 if(const char* comment
= cc
.GetComment())
1383 std::string echo_cmd
= "echo ";
1384 echo_cmd
+= (this->CurrentLocalGenerator
->
1385 EscapeForShell(comment
, escapeAllowMakeVars
));
1386 makefileStream
<< "\t" << echo_cmd
.c_str() << "\n";
1389 // Add each command line to the set of commands.
1390 for(cmCustomCommandLines::const_iterator cl
=
1391 cc
.GetCommandLines().begin();
1392 cl
!= cc
.GetCommandLines().end(); ++cl
)
1394 // Build the command line in a single string.
1395 const cmCustomCommandLine
& commandLine
= *cl
;
1396 std::string cmd2
= this->CurrentLocalGenerator
1397 ->GetRealLocation(commandLine
[0].c_str(), configName
);
1399 cmSystemTools::ReplaceString(cmd2
, "/./", "/");
1400 cmd2
= this->ConvertToRelativeForMake(cmd2
.c_str());
1402 if(cc
.GetWorkingDirectory())
1405 cmd
+= this->ConvertToRelativeForMake(cc
.GetWorkingDirectory());
1409 for(unsigned int j
=1; j
< commandLine
.size(); ++j
)
1414 cmd
+= (this->CurrentLocalGenerator
1415 ->EscapeForShellOldStyle(commandLine
[j
].c_str()));
1419 cmd
+= (this->CurrentLocalGenerator
->
1420 EscapeForShell(commandLine
[j
].c_str(),
1421 escapeAllowMakeVars
));
1424 makefileStream
<< "\t" << cmd
.c_str() << "\n";
1429 // Add rules to deal with multiple outputs of custom commands.
1430 if(!multipleOutputPairs
.empty())
1433 "\n# Dependencies of multiple outputs to their primary outputs \n";
1435 for(std::map
<cmStdString
, cmStdString
>::const_iterator o
=
1436 multipleOutputPairs
.begin(); o
!= multipleOutputPairs
.end(); ++o
)
1438 makefileStream
<< o
->first
<< ": " << o
->second
<< "\n";
1443 "cmake_check_multiple_outputs:\n";
1444 for(std::map
<cmStdString
, cmStdString
>::const_iterator o
=
1445 multipleOutputPairs
.begin(); o
!= multipleOutputPairs
.end(); ++o
)
1447 makefileStream
<< "\t@if [ ! -f "
1448 << o
->first
<< " ]; then rm -f "
1449 << o
->second
<< "; fi\n";
1454 //----------------------------------------------------------------------------
1455 void cmGlobalXCodeGenerator::CreateBuildSettings(cmTarget
& target
,
1456 cmXCodeObject
* buildSettings
,
1457 const char* configName
)
1460 std::string defFlags
;
1461 bool shared
= ((target
.GetType() == cmTarget::SHARED_LIBRARY
) ||
1462 (target
.GetType() == cmTarget::MODULE_LIBRARY
));
1464 const char* lang
= target
.GetLinkerLanguage(configName
);
1468 // for c++ projects get the c flags as well
1469 if(strcmp(lang
, "CXX") == 0)
1471 this->CurrentLocalGenerator
->AddLanguageFlags(cflags
, "C", configName
);
1472 this->CurrentLocalGenerator
->AddSharedFlags(cflags
, lang
, shared
);
1475 // Add language-specific flags.
1476 this->CurrentLocalGenerator
->AddLanguageFlags(flags
, lang
, configName
);
1478 // Add shared-library flags if needed.
1479 this->CurrentLocalGenerator
->AddSharedFlags(flags
, lang
, shared
);
1483 this->CurrentLocalGenerator
->
1484 AppendFlags(defFlags
,
1485 this->CurrentMakefile
->GetDefineFlags());
1487 // Add preprocessor definitions for this target and configuration.
1488 BuildObjectListOrString
ppDefs(this, this->XcodeVersion
>= 30);
1489 if(this->XcodeVersion
> 15)
1491 this->AppendDefines(ppDefs
, "CMAKE_INTDIR=\"$(CONFIGURATION)\"");
1493 if(const char* exportMacro
= target
.GetExportMacro())
1495 // Add the export symbol definition for shared library objects.
1496 this->AppendDefines(ppDefs
, exportMacro
);
1499 (ppDefs
, this->CurrentMakefile
->GetProperty("COMPILE_DEFINITIONS"));
1500 this->AppendDefines(ppDefs
, target
.GetProperty("COMPILE_DEFINITIONS"));
1503 std::string defVarName
= "COMPILE_DEFINITIONS_";
1504 defVarName
+= cmSystemTools::UpperCase(configName
);
1506 (ppDefs
, this->CurrentMakefile
->GetProperty(defVarName
.c_str()));
1507 this->AppendDefines(ppDefs
, target
.GetProperty(defVarName
.c_str()));
1509 buildSettings
->AddAttribute
1510 ("GCC_PREPROCESSOR_DEFINITIONS", ppDefs
.CreateList());
1512 std::string extraLinkOptions
;
1513 if(target
.GetType() == cmTarget::EXECUTABLE
)
1516 this->CurrentMakefile
->GetRequiredDefinition("CMAKE_EXE_LINKER_FLAGS");
1517 std::string var
= "CMAKE_EXE_LINKER_FLAGS_";
1518 var
+= cmSystemTools::UpperCase(configName
);
1520 this->CurrentMakefile
->GetSafeDefinition(var
.c_str());
1523 extraLinkOptions
+= " ";
1524 extraLinkOptions
+= val
;
1527 if(target
.GetType() == cmTarget::SHARED_LIBRARY
)
1529 extraLinkOptions
= this->CurrentMakefile
->
1530 GetRequiredDefinition("CMAKE_SHARED_LINKER_FLAGS");
1532 if(target
.GetType() == cmTarget::MODULE_LIBRARY
)
1534 extraLinkOptions
= this->CurrentMakefile
->
1535 GetRequiredDefinition("CMAKE_MODULE_LINKER_FLAGS");
1538 const char* targetLinkFlags
= target
.GetProperty("LINK_FLAGS");
1541 extraLinkOptions
+= " ";
1542 extraLinkOptions
+= targetLinkFlags
;
1545 // Get the product name components.
1546 std::string pnprefix
;
1548 std::string pnsuffix
;
1549 target
.GetFullNameComponents(pnprefix
, pnbase
, pnsuffix
, configName
);
1551 // Store the product name for all target types.
1552 buildSettings
->AddAttribute("PRODUCT_NAME",
1553 this->CreateString(pnbase
.c_str()));
1555 // Set attributes to specify the proper name for the target.
1556 if(target
.GetType() == cmTarget::STATIC_LIBRARY
||
1557 target
.GetType() == cmTarget::SHARED_LIBRARY
||
1558 target
.GetType() == cmTarget::MODULE_LIBRARY
||
1559 target
.GetType() == cmTarget::EXECUTABLE
)
1561 std::string pndir
= target
.GetDirectory();
1562 buildSettings
->AddAttribute("SYMROOT",
1563 this->CreateString(pndir
.c_str()));
1564 buildSettings
->AddAttribute("EXECUTABLE_PREFIX",
1565 this->CreateString(pnprefix
.c_str()));
1566 buildSettings
->AddAttribute("EXECUTABLE_SUFFIX",
1567 this->CreateString(pnsuffix
.c_str()));
1570 // Handle settings for each target type.
1571 switch(target
.GetType())
1573 case cmTarget::STATIC_LIBRARY
:
1575 buildSettings
->AddAttribute("LIBRARY_STYLE",
1576 this->CreateString("STATIC"));
1580 case cmTarget::MODULE_LIBRARY
:
1582 buildSettings
->AddAttribute("LIBRARY_STYLE",
1583 this->CreateString("BUNDLE"));
1584 if(this->XcodeVersion
>= 22)
1586 buildSettings
->AddAttribute("MACH_O_TYPE",
1587 this->CreateString("mh_bundle"));
1588 buildSettings
->AddAttribute("GCC_DYNAMIC_NO_PIC",
1589 this->CreateString("NO"));
1590 // Add the flags to create an executable.
1591 std::string createFlags
=
1592 this->LookupFlags("CMAKE_", lang
, "_LINK_FLAGS", "");
1593 if(!createFlags
.empty())
1595 extraLinkOptions
+= " ";
1596 extraLinkOptions
+= createFlags
;
1601 // Add the flags to create a module.
1602 std::string createFlags
=
1603 this->LookupFlags("CMAKE_SHARED_MODULE_CREATE_", lang
, "_FLAGS",
1605 if(!createFlags
.empty())
1607 extraLinkOptions
+= " ";
1608 extraLinkOptions
+= createFlags
;
1613 case cmTarget::SHARED_LIBRARY
:
1615 if(target
.GetPropertyAsBool("FRAMEWORK"))
1617 std::string version
= target
.GetFrameworkVersion();
1618 buildSettings
->AddAttribute("FRAMEWORK_VERSION",
1619 this->CreateString(version
.c_str()));
1621 std::string plist
= this->ComputeInfoPListLocation(target
);
1622 // Xcode will create the final version of Info.plist at build time,
1623 // so let it replace the framework name. This avoids creating
1624 // a per-configuration Info.plist file.
1625 this->CurrentLocalGenerator
1626 ->GenerateFrameworkInfoPList(&target
, "$(EXECUTABLE_NAME)",
1629 this->ConvertToRelativeForXCode(plist
.c_str());
1630 buildSettings
->AddAttribute("INFOPLIST_FILE",
1631 this->CreateString(path
.c_str()));
1635 // Add the flags to create a shared library.
1636 std::string createFlags
=
1637 this->LookupFlags("CMAKE_SHARED_LIBRARY_CREATE_", lang
, "_FLAGS",
1639 if(!createFlags
.empty())
1641 extraLinkOptions
+= " ";
1642 extraLinkOptions
+= createFlags
;
1646 buildSettings
->AddAttribute("LIBRARY_STYLE",
1647 this->CreateString("DYNAMIC"));
1650 case cmTarget::EXECUTABLE
:
1652 // Add the flags to create an executable.
1653 std::string createFlags
=
1654 this->LookupFlags("CMAKE_", lang
, "_LINK_FLAGS", "");
1655 if(!createFlags
.empty())
1657 extraLinkOptions
+= " ";
1658 extraLinkOptions
+= createFlags
;
1661 // Handle bundles and normal executables separately.
1662 if(target
.GetPropertyAsBool("MACOSX_BUNDLE"))
1664 std::string plist
= this->ComputeInfoPListLocation(target
);
1665 // Xcode will create the final version of Info.plist at build time,
1666 // so let it replace the executable name. This avoids creating
1667 // a per-configuration Info.plist file.
1668 this->CurrentLocalGenerator
1669 ->GenerateAppleInfoPList(&target
, "$(EXECUTABLE_NAME)",
1672 this->ConvertToRelativeForXCode(plist
.c_str());
1673 buildSettings
->AddAttribute("INFOPLIST_FILE",
1674 this->CreateString(path
.c_str()));
1682 if(this->XcodeVersion
>= 22)
1684 buildSettings
->AddAttribute("PREBINDING",
1685 this->CreateString("NO"));
1688 BuildObjectListOrString
dirs(this, this->XcodeVersion
>= 30);
1689 BuildObjectListOrString
fdirs(this, this->XcodeVersion
>= 30);
1690 std::vector
<std::string
> includes
;
1691 this->CurrentLocalGenerator
->GetIncludeDirectories(includes
);
1692 std::set
<cmStdString
> emitted
;
1693 emitted
.insert("/System/Library/Frameworks");
1694 for(std::vector
<std::string
>::iterator i
= includes
.begin();
1695 i
!= includes
.end(); ++i
)
1697 if(this->NameResolvesToFramework(i
->c_str()))
1699 std::string frameworkDir
= *i
;
1700 frameworkDir
+= "/../";
1701 frameworkDir
= cmSystemTools::CollapseFullPath(frameworkDir
.c_str());
1702 if(emitted
.insert(frameworkDir
).second
)
1704 fdirs
.Add(this->XCodeEscapePath(frameworkDir
.c_str()).c_str());
1709 std::string incpath
=
1710 this->XCodeEscapePath(i
->c_str());
1711 dirs
.Add(incpath
.c_str());
1714 std::vector
<std::string
>& frameworks
= target
.GetFrameworks();
1715 if(frameworks
.size())
1717 for(std::vector
<std::string
>::iterator fmIt
= frameworks
.begin();
1718 fmIt
!= frameworks
.end(); ++fmIt
)
1720 if(emitted
.insert(*fmIt
).second
)
1722 fdirs
.Add(this->XCodeEscapePath(fmIt
->c_str()).c_str());
1726 if(!fdirs
.IsEmpty())
1728 buildSettings
->AddAttribute("FRAMEWORK_SEARCH_PATHS",
1729 fdirs
.CreateList());
1733 buildSettings
->AddAttribute("HEADER_SEARCH_PATHS",
1736 std::string oflagc
= this->ExtractFlag("-O", cflags
);
1740 if(oflagc
.size() == 3)
1742 optLevel
[0] = oflagc
[2];
1744 if(oflagc
.size() == 2)
1748 std::string oflag
= this->ExtractFlag("-O", flags
);
1749 if(oflag
.size() == 3)
1751 optLevel
[0] = oflag
[2];
1753 if(oflag
.size() == 2)
1757 std::string gflagc
= this->ExtractFlag("-g", cflags
);
1758 // put back gdwarf-2 if used since there is no way
1759 // to represent it in the gui, but we still want debug yes
1760 if(gflagc
== "-gdwarf-2")
1765 std::string gflag
= this->ExtractFlag("-g", flags
);
1766 if(gflag
== "-gdwarf-2")
1771 const char* debugStr
= "YES";
1772 if(gflagc
.size() ==0 && gflag
.size() == 0)
1777 buildSettings
->AddAttribute("GCC_GENERATE_DEBUGGING_SYMBOLS",
1778 this->CreateString(debugStr
));
1779 buildSettings
->AddAttribute("GCC_OPTIMIZATION_LEVEL",
1780 this->CreateString(optLevel
));
1781 buildSettings
->AddAttribute("GCC_SYMBOLS_PRIVATE_EXTERN",
1782 this->CreateString("NO"));
1783 buildSettings
->AddAttribute("GCC_INLINES_ARE_PRIVATE_EXTERN",
1784 this->CreateString("NO"));
1785 if(lang
&& strcmp(lang
, "CXX") == 0)
1789 buildSettings
->AddAttribute("OTHER_CPLUSPLUSFLAGS",
1790 this->CreateString(flags
.c_str()));
1793 buildSettings
->AddAttribute("OTHER_CFLAGS",
1794 this->CreateString(cflags
.c_str()));
1801 buildSettings
->AddAttribute("OTHER_CFLAGS",
1802 this->CreateString(flags
.c_str()));
1805 // Create the INSTALL_PATH attribute.
1806 std::string install_name_dir
;
1807 if(target
.GetType() == cmTarget::SHARED_LIBRARY
)
1809 // Get the install_name directory for the build tree.
1810 install_name_dir
= target
.GetInstallNameDirForBuildTree(configName
, true);
1811 if(install_name_dir
.empty())
1813 // Xcode will not pass the -install_name option at all if INSTALL_PATH
1814 // is not given or is empty. We must explicitly put the flag in the
1815 // link flags to create an install_name with just the library soname.
1816 extraLinkOptions
+= " -install_name ";
1817 extraLinkOptions
+= target
.GetFullName(configName
);
1821 // Convert to a path for the native build tool.
1822 cmSystemTools::ConvertToUnixSlashes(install_name_dir
);
1823 // do not escape spaces on this since it is only a single path
1826 buildSettings
->AddAttribute("INSTALL_PATH",
1827 this->CreateString(install_name_dir
.c_str()));
1829 buildSettings
->AddAttribute("OTHER_LDFLAGS",
1830 this->CreateString(extraLinkOptions
.c_str()));
1831 buildSettings
->AddAttribute("OTHER_REZFLAGS",
1832 this->CreateString(""));
1833 buildSettings
->AddAttribute("SECTORDER_FLAGS",
1834 this->CreateString(""));
1835 buildSettings
->AddAttribute("USE_HEADERMAP",
1836 this->CreateString("NO"));
1837 if (this->XcodeVersion
>= 30)
1839 cmXCodeObject
*group
= this->CreateObject(cmXCodeObject::OBJECT_LIST
);
1840 group
->AddObject(this->CreateString("-Wmost"));
1841 group
->AddObject(this->CreateString("-Wno-four-char-constants"));
1842 group
->AddObject(this->CreateString("-Wno-unknown-pragmas"));
1843 buildSettings
->AddAttribute("WARNING_CFLAGS", group
);
1847 buildSettings
->AddAttribute("WARNING_CFLAGS",
1849 "-Wmost -Wno-four-char-constants"
1850 " -Wno-unknown-pragmas"));
1853 // Runtime version information.
1854 if(target
.GetType() == cmTarget::SHARED_LIBRARY
)
1860 // VERSION -> current_version
1861 target
.GetTargetVersion(false, major
, minor
, patch
);
1862 if(major
== 0 && minor
== 0 && patch
== 0)
1864 // Xcode always wants at least 1.0.0
1868 v
<< major
<< "." << minor
<< "." << patch
;
1869 buildSettings
->AddAttribute("DYLIB_CURRENT_VERSION",
1870 this->CreateString(v
.str().c_str()));
1872 // SOVERSION -> compatibility_version
1873 target
.GetTargetVersion(true, major
, minor
, patch
);
1874 if(major
== 0 && minor
== 0 && patch
== 0)
1876 // Xcode always wants at least 1.0.0
1879 cmOStringStream vso
;
1880 vso
<< major
<< "." << minor
<< "." << patch
;
1881 buildSettings
->AddAttribute("DYLIB_COMPATIBILITY_VERSION",
1882 this->CreateString(vso
.str().c_str()));
1884 // put this last so it can override existing settings
1885 // Convert "XCODE_ATTRIBUTE_*" properties directly.
1887 cmPropertyMap
const& props
= target
.GetProperties();
1888 for(cmPropertyMap::const_iterator i
= props
.begin();
1889 i
!= props
.end(); ++i
)
1891 if(i
->first
.find("XCODE_ATTRIBUTE_") == 0)
1893 buildSettings
->AddAttribute(i
->first
.substr(16).c_str(),
1894 this->CreateString(i
->second
.GetValue()));
1900 //----------------------------------------------------------------------------
1902 cmGlobalXCodeGenerator::CreateUtilityTarget(cmTarget
& cmtarget
)
1904 cmXCodeObject
* shellBuildPhase
=
1905 this->CreateObject(cmXCodeObject::PBXShellScriptBuildPhase
);
1906 shellBuildPhase
->AddAttribute("buildActionMask",
1907 this->CreateString("2147483647"));
1908 cmXCodeObject
* buildFiles
= this->CreateObject(cmXCodeObject::OBJECT_LIST
);
1909 shellBuildPhase
->AddAttribute("files", buildFiles
);
1910 cmXCodeObject
* inputPaths
= this->CreateObject(cmXCodeObject::OBJECT_LIST
);
1911 shellBuildPhase
->AddAttribute("inputPaths", inputPaths
);
1912 cmXCodeObject
* outputPaths
= this->CreateObject(cmXCodeObject::OBJECT_LIST
);
1913 shellBuildPhase
->AddAttribute("outputPaths", outputPaths
);
1914 shellBuildPhase
->AddAttribute("runOnlyForDeploymentPostprocessing",
1915 this->CreateString("0"));
1916 shellBuildPhase
->AddAttribute("shellPath",
1917 this->CreateString("/bin/sh"));
1918 shellBuildPhase
->AddAttribute("shellScript",
1920 "# shell script goes here\nexit 0"));
1921 cmXCodeObject
* target
=
1922 this->CreateObject(cmXCodeObject::PBXAggregateTarget
);
1923 target
->SetComment(cmtarget
.GetName());
1924 cmXCodeObject
* buildPhases
=
1925 this->CreateObject(cmXCodeObject::OBJECT_LIST
);
1926 std::vector
<cmXCodeObject
*> emptyContentVector
;
1927 this->CreateCustomCommands(buildPhases
, 0, 0, 0, emptyContentVector
, 0,
1929 target
->AddAttribute("buildPhases", buildPhases
);
1930 if(this->XcodeVersion
> 20)
1932 this->AddConfigurations(target
, cmtarget
);
1936 const char* theConfig
=
1937 this->CurrentMakefile
->GetDefinition("CMAKE_BUILD_TYPE");
1938 cmXCodeObject
* buildSettings
=
1939 this->CreateObject(cmXCodeObject::ATTRIBUTE_GROUP
);
1940 this->CreateBuildSettings(cmtarget
, buildSettings
, theConfig
);
1941 target
->AddAttribute("buildSettings", buildSettings
);
1943 cmXCodeObject
* dependencies
=
1944 this->CreateObject(cmXCodeObject::OBJECT_LIST
);
1945 target
->AddAttribute("dependencies", dependencies
);
1946 target
->AddAttribute("name", this->CreateString(cmtarget
.GetName()));
1947 target
->AddAttribute("productName",this->CreateString(cmtarget
.GetName()));
1948 target
->SetTarget(&cmtarget
);
1950 // Add source files without build rules for editing convenience.
1951 if(cmtarget
.GetType() == cmTarget::UTILITY
)
1953 std::vector
<cmSourceFile
*> const& sources
= cmtarget
.GetSourceFiles();
1954 for(std::vector
<cmSourceFile
*>::const_iterator i
= sources
.begin();
1955 i
!= sources
.end(); ++i
)
1957 if(!(*i
)->GetPropertyAsBool("GENERATED"))
1959 this->CreateXCodeFileReference(*i
, cmtarget
);
1967 //----------------------------------------------------------------------------
1968 std::string
cmGlobalXCodeGenerator::AddConfigurations(cmXCodeObject
* target
,
1971 std::string configTypes
=
1972 this->CurrentMakefile
->GetRequiredDefinition("CMAKE_CONFIGURATION_TYPES");
1973 std::vector
<std::string
> configVectorIn
;
1974 std::vector
<std::string
> configVector
;
1975 configVectorIn
.push_back(configTypes
);
1976 cmSystemTools::ExpandList(configVectorIn
, configVector
);
1977 cmXCodeObject
* configlist
=
1978 this->CreateObject(cmXCodeObject::XCConfigurationList
);
1979 cmXCodeObject
* buildConfigurations
=
1980 this->CreateObject(cmXCodeObject::OBJECT_LIST
);
1981 configlist
->AddAttribute("buildConfigurations", buildConfigurations
);
1982 std::string comment
= "Build configuration list for ";
1983 comment
+= cmXCodeObject::PBXTypeNames
[target
->GetIsA()];
1985 comment
+= cmtarget
.GetName();
1987 configlist
->SetComment(comment
.c_str());
1988 target
->AddAttribute("buildConfigurationList",
1989 this->CreateObjectReference(configlist
));
1990 for(unsigned int i
= 0; i
< configVector
.size(); ++i
)
1992 cmXCodeObject
* config
=
1993 this->CreateObject(cmXCodeObject::XCBuildConfiguration
);
1994 buildConfigurations
->AddObject(config
);
1995 cmXCodeObject
* buildSettings
=
1996 this->CreateObject(cmXCodeObject::ATTRIBUTE_GROUP
);
1997 this->CreateBuildSettings(cmtarget
, buildSettings
,
1998 configVector
[i
].c_str());
1999 config
->AddAttribute("name", this->CreateString(configVector
[i
].c_str()));
2000 config
->SetComment(configVector
[i
].c_str());
2001 config
->AddAttribute("buildSettings", buildSettings
);
2003 if(configVector
.size())
2005 configlist
->AddAttribute("defaultConfigurationName",
2006 this->CreateString(configVector
[0].c_str()));
2007 configlist
->AddAttribute("defaultConfigurationIsVisible",
2008 this->CreateString("0"));
2009 return configVector
[0];
2014 //----------------------------------------------------------------------------
2015 const char* cmGlobalXCodeGenerator::GetTargetFileType(cmTarget
& cmtarget
)
2017 switch(cmtarget
.GetType())
2019 case cmTarget::STATIC_LIBRARY
:
2020 return "archive.ar";
2021 case cmTarget::MODULE_LIBRARY
:
2022 return ((this->XcodeVersion
>= 22)?
2023 "compiled.mach-o.executable" : "compiled.mach-o.dylib");
2024 case cmTarget::SHARED_LIBRARY
:
2025 return (cmtarget
.GetPropertyAsBool("FRAMEWORK")?
2026 "wrapper.framework" : "compiled.mach-o.dylib");
2027 case cmTarget::EXECUTABLE
:
2028 return "compiled.mach-o.executable";
2034 //----------------------------------------------------------------------------
2035 const char* cmGlobalXCodeGenerator::GetTargetProductType(cmTarget
& cmtarget
)
2037 switch(cmtarget
.GetType())
2039 case cmTarget::STATIC_LIBRARY
:
2040 return "com.apple.product-type.library.static";
2041 case cmTarget::MODULE_LIBRARY
:
2042 return ((this->XcodeVersion
>= 22)? "com.apple.product-type.tool" :
2043 "com.apple.product-type.library.dynamic");
2044 case cmTarget::SHARED_LIBRARY
:
2045 return (cmtarget
.GetPropertyAsBool("FRAMEWORK")?
2046 "com.apple.product-type.framework" :
2047 "com.apple.product-type.library.dynamic");
2048 case cmTarget::EXECUTABLE
:
2049 return (cmtarget
.GetPropertyAsBool("MACOSX_BUNDLE")?
2050 "com.apple.product-type.application" :
2051 "com.apple.product-type.tool");
2057 //----------------------------------------------------------------------------
2059 cmGlobalXCodeGenerator::CreateXCodeTarget(cmTarget
& cmtarget
,
2060 cmXCodeObject
* buildPhases
)
2062 cmXCodeObject
* target
=
2063 this->CreateObject(cmXCodeObject::PBXNativeTarget
);
2064 target
->AddAttribute("buildPhases", buildPhases
);
2065 cmXCodeObject
* buildRules
= this->CreateObject(cmXCodeObject::OBJECT_LIST
);
2066 target
->AddAttribute("buildRules", buildRules
);
2067 std::string defConfig
;
2068 if(this->XcodeVersion
> 20)
2070 defConfig
= this->AddConfigurations(target
, cmtarget
);
2074 cmXCodeObject
* buildSettings
=
2075 this->CreateObject(cmXCodeObject::ATTRIBUTE_GROUP
);
2076 defConfig
= this->CurrentMakefile
->GetSafeDefinition("CMAKE_BUILD_TYPE");
2077 this->CreateBuildSettings(cmtarget
, buildSettings
, defConfig
.c_str());
2078 target
->AddAttribute("buildSettings", buildSettings
);
2080 cmXCodeObject
* dependencies
=
2081 this->CreateObject(cmXCodeObject::OBJECT_LIST
);
2082 target
->AddAttribute("dependencies", dependencies
);
2083 target
->AddAttribute("name", this->CreateString(cmtarget
.GetName()));
2084 target
->AddAttribute("productName",this->CreateString(cmtarget
.GetName()));
2086 cmXCodeObject
* fileRef
=
2087 this->CreateObject(cmXCodeObject::PBXFileReference
);
2088 if(const char* fileType
= this->GetTargetFileType(cmtarget
))
2090 fileRef
->AddAttribute("explicitFileType", this->CreateString(fileType
));
2092 std::string fullName
= cmtarget
.GetFullName(defConfig
.c_str());
2093 fileRef
->AddAttribute("path", this->CreateString(fullName
.c_str()));
2094 fileRef
->AddAttribute("refType", this->CreateString("0"));
2095 fileRef
->AddAttribute("sourceTree",
2096 this->CreateString("BUILT_PRODUCTS_DIR"));
2097 fileRef
->SetComment(cmtarget
.GetName());
2098 target
->AddAttribute("productReference",
2099 this->CreateObjectReference(fileRef
));
2100 if(const char* productType
= this->GetTargetProductType(cmtarget
))
2102 target
->AddAttribute("productType", this->CreateString(productType
));
2104 target
->SetTarget(&cmtarget
);
2108 //----------------------------------------------------------------------------
2109 cmXCodeObject
* cmGlobalXCodeGenerator::FindXCodeTarget(cmTarget
* t
)
2115 for(std::vector
<cmXCodeObject
*>::iterator i
= this->XCodeObjects
.begin();
2116 i
!= this->XCodeObjects
.end(); ++i
)
2118 cmXCodeObject
* o
= *i
;
2119 if(o
->GetTarget() == t
)
2127 //----------------------------------------------------------------------------
2128 void cmGlobalXCodeGenerator::AddDependTarget(cmXCodeObject
* target
,
2129 cmXCodeObject
* dependTarget
)
2131 // make sure a target does not depend on itself
2132 if(target
== dependTarget
)
2136 // now avoid circular references if dependTarget already
2137 // depends on target then skip it. Circular references crashes
2139 cmXCodeObject
* dependTargetDepends
=
2140 dependTarget
->GetObject("dependencies");
2141 if(dependTargetDepends
)
2143 if(dependTargetDepends
->HasObject(target
->GetPBXTargetDependency()))
2149 cmXCodeObject
* targetdep
= dependTarget
->GetPBXTargetDependency();
2152 cmXCodeObject
* container
=
2153 this->CreateObject(cmXCodeObject::PBXContainerItemProxy
);
2154 container
->SetComment("PBXContainerItemProxy");
2155 container
->AddAttribute("containerPortal",
2156 this->CreateObjectReference(this->RootObject
));
2157 container
->AddAttribute("proxyType", this->CreateString("1"));
2158 container
->AddAttribute("remoteGlobalIDString",
2159 this->CreateObjectReference(dependTarget
));
2160 container
->AddAttribute("remoteInfo",
2162 dependTarget
->GetTarget()->GetName()));
2164 this->CreateObject(cmXCodeObject::PBXTargetDependency
);
2165 targetdep
->SetComment("PBXTargetDependency");
2166 targetdep
->AddAttribute("target",
2167 this->CreateObjectReference(dependTarget
));
2168 targetdep
->AddAttribute("targetProxy",
2169 this->CreateObjectReference(container
));
2170 dependTarget
->SetPBXTargetDependency(targetdep
);
2173 cmXCodeObject
* depends
= target
->GetObject("dependencies");
2177 Error("target does not have dependencies attribute error..");
2182 depends
->AddUniqueObject(targetdep
);
2186 //----------------------------------------------------------------------------
2187 void cmGlobalXCodeGenerator::AppendOrAddBuildSetting(cmXCodeObject
* settings
,
2188 const char* attribute
,
2193 cmXCodeObject
* attr
= settings
->GetObject(attribute
);
2196 settings
->AddAttribute(attribute
, this->CreateString(value
));
2200 std::string oldValue
= attr
->GetString();
2203 attr
->SetString(oldValue
.c_str());
2208 //----------------------------------------------------------------------------
2209 void cmGlobalXCodeGenerator
2210 ::AppendBuildSettingAttribute(cmXCodeObject
* target
,
2211 const char* attribute
,
2213 const char* configName
)
2215 if(this->XcodeVersion
< 21)
2217 // There is only one configuration. Add the setting to the buildSettings
2219 this->AppendOrAddBuildSetting(target
->GetObject("buildSettings"),
2224 // There are multiple configurations. Add the setting to the
2225 // buildSettings of the configuration name given.
2226 cmXCodeObject
* configurationList
=
2227 target
->GetObject("buildConfigurationList")->GetObject();
2228 cmXCodeObject
* buildConfigs
=
2229 configurationList
->GetObject("buildConfigurations");
2230 std::vector
<cmXCodeObject
*> list
= buildConfigs
->GetObjectList();
2231 // each configuration and the target itself has a buildSettings in it
2232 //list.push_back(target);
2233 for(std::vector
<cmXCodeObject
*>::iterator i
= list
.begin();
2234 i
!= list
.end(); ++i
)
2238 if(strcmp((*i
)->GetObject("name")->GetString(), configName
) == 0)
2240 cmXCodeObject
* settings
= (*i
)->GetObject("buildSettings");
2241 this->AppendOrAddBuildSetting(settings
, attribute
, value
);
2246 cmXCodeObject
* settings
= (*i
)->GetObject("buildSettings");
2247 this->AppendOrAddBuildSetting(settings
, attribute
, value
);
2253 //----------------------------------------------------------------------------
2254 void cmGlobalXCodeGenerator
2255 ::AddDependAndLinkInformation(cmXCodeObject
* target
)
2257 cmTarget
* cmtarget
= target
->GetTarget();
2260 cmSystemTools::Error("Error no target on xobject\n");
2264 // Add dependencies on other CMake targets.
2265 TargetDependSet
const& deps
= this->GetTargetDirectDepends(*cmtarget
);
2266 for(TargetDependSet::const_iterator i
= deps
.begin(); i
!= deps
.end(); ++i
)
2268 if(cmXCodeObject
* dptarget
= this->FindXCodeTarget(*i
))
2270 this->AddDependTarget(target
, dptarget
);
2274 // Skip link information for static libraries.
2275 if(cmtarget
->GetType() == cmTarget::STATIC_LIBRARY
)
2280 // Loop over configuration types and set per-configuration info.
2281 for(std::vector
<std::string
>::iterator i
=
2282 this->CurrentConfigurationTypes
.begin();
2283 i
!= this->CurrentConfigurationTypes
.end(); ++i
)
2285 // Get the current configuration name.
2286 const char* configName
= i
->c_str();
2292 // Compute the link library and directory information.
2293 cmComputeLinkInformation
* pcli
= cmtarget
->GetLinkInformation(configName
);
2298 cmComputeLinkInformation
& cli
= *pcli
;
2300 // Add dependencies directly on library files.
2302 std::vector
<std::string
> const& libDeps
= cli
.GetDepends();
2303 for(std::vector
<std::string
>::const_iterator j
= libDeps
.begin();
2304 j
!= libDeps
.end(); ++j
)
2306 target
->AddDependLibrary(configName
, j
->c_str());
2310 // add the library search paths
2312 std::vector
<std::string
> const& libDirs
= cli
.GetDirectories();
2313 std::string linkDirs
;
2314 for(std::vector
<std::string
>::const_iterator libDir
= libDirs
.begin();
2315 libDir
!= libDirs
.end(); ++libDir
)
2317 if(libDir
->size() && *libDir
!= "/usr/lib")
2319 if(this->XcodeVersion
> 15)
2321 // now add the same one but append $(CONFIGURATION) to it:
2323 linkDirs
+= this->XCodeEscapePath(
2324 (*libDir
+ "/$(CONFIGURATION)").c_str());
2327 linkDirs
+= this->XCodeEscapePath(libDir
->c_str());
2330 this->AppendBuildSettingAttribute(target
, "LIBRARY_SEARCH_PATHS",
2331 linkDirs
.c_str(), configName
);
2334 // add the framework search paths
2336 const char* sep
= "";
2338 std::vector
<std::string
> const& fwDirs
= cli
.GetFrameworkPaths();
2339 for(std::vector
<std::string
>::const_iterator fdi
= fwDirs
.begin();
2340 fdi
!= fwDirs
.end(); ++fdi
)
2344 fdirs
+= this->XCodeEscapePath(fdi
->c_str());
2348 this->AppendBuildSettingAttribute(target
, "FRAMEWORK_SEARCH_PATHS",
2349 fdirs
.c_str(), configName
);
2353 // now add the link libraries
2355 std::string linkLibs
;
2356 const char* sep
= "";
2357 typedef cmComputeLinkInformation::ItemVector ItemVector
;
2358 ItemVector
const& libNames
= cli
.GetItems();
2359 for(ItemVector::const_iterator li
= libNames
.begin();
2360 li
!= libNames
.end(); ++li
)
2366 linkLibs
+= this->XCodeEscapePath(li
->Value
.c_str());
2370 linkLibs
+= li
->Value
;
2373 this->AppendBuildSettingAttribute(target
, "OTHER_LDFLAGS",
2374 linkLibs
.c_str(), configName
);
2379 //----------------------------------------------------------------------------
2380 void cmGlobalXCodeGenerator::CreateGroups(cmLocalGenerator
* root
,
2381 std::vector
<cmLocalGenerator
*>&
2384 for(std::vector
<cmLocalGenerator
*>::iterator i
= generators
.begin();
2385 i
!= generators
.end(); ++i
)
2387 if(this->IsExcluded(root
, *i
))
2391 cmMakefile
* mf
= (*i
)->GetMakefile();
2392 std::vector
<cmSourceGroup
> sourceGroups
= mf
->GetSourceGroups();
2393 cmTargets
&tgts
= mf
->GetTargets();
2394 for(cmTargets::iterator l
= tgts
.begin(); l
!= tgts
.end(); l
++)
2396 cmTarget
& cmtarget
= l
->second
;
2398 // Same skipping logic here as in CreateXCodeTargets so that we do not
2399 // end up with (empty anyhow) ALL_BUILD and XCODE_DEPEND_HELPER source
2402 if(cmtarget
.GetType() == cmTarget::GLOBAL_TARGET
)
2407 // add the soon to be generated Info.plist file as a source for a
2408 // MACOSX_BUNDLE file
2409 if(cmtarget
.GetPropertyAsBool("MACOSX_BUNDLE"))
2411 std::string plist
= this->ComputeInfoPListLocation(cmtarget
);
2412 cmSourceFile
* sf
= mf
->GetOrCreateSource(plist
.c_str(), true);
2413 cmtarget
.AddSourceFile(sf
);
2416 std::vector
<cmSourceFile
*> classes
= cmtarget
.GetSourceFiles();
2418 for(std::vector
<cmSourceFile
*>::const_iterator s
= classes
.begin();
2419 s
!= classes
.end(); s
++)
2421 cmSourceFile
* sf
= *s
;
2422 // Add the file to the list of sources.
2423 std::string
const& source
= sf
->GetFullPath();
2424 cmSourceGroup
& sourceGroup
=
2425 mf
->FindSourceGroup(source
.c_str(), sourceGroups
);
2426 cmXCodeObject
* pbxgroup
=
2427 this->CreateOrGetPBXGroup(cmtarget
, &sourceGroup
);
2428 cmStdString key
= GetGroupMapKey(cmtarget
, sf
);
2429 this->GroupMap
[key
] = pbxgroup
;
2435 //----------------------------------------------------------------------------
2436 cmXCodeObject
* cmGlobalXCodeGenerator
2437 ::CreateOrGetPBXGroup(cmTarget
& cmtarget
, cmSourceGroup
* sg
)
2439 cmStdString s
= cmtarget
.GetName();
2442 std::map
<cmStdString
, cmXCodeObject
* >::iterator i
=
2443 this->GroupNameMap
.find(s
);
2444 if(i
!= this->GroupNameMap
.end())
2448 i
= this->TargetGroup
.find(cmtarget
.GetName());
2449 cmXCodeObject
* tgroup
= 0;
2450 if(i
!= this->TargetGroup
.end())
2456 tgroup
= this->CreateObject(cmXCodeObject::PBXGroup
);
2457 this->TargetGroup
[cmtarget
.GetName()] = tgroup
;
2458 cmXCodeObject
* tgroupChildren
=
2459 this->CreateObject(cmXCodeObject::OBJECT_LIST
);
2460 tgroup
->AddAttribute("name", this->CreateString(cmtarget
.GetName()));
2461 tgroup
->AddAttribute("children", tgroupChildren
);
2462 if(this->XcodeVersion
== 15)
2464 tgroup
->AddAttribute("refType", this->CreateString("4"));
2466 tgroup
->AddAttribute("sourceTree", this->CreateString("<group>"));
2467 this->SourcesGroupChildren
->AddObject(tgroup
);
2470 // If it's the default source group (empty name) then put the source file
2471 // directly in the tgroup...
2473 if (cmStdString(sg
->GetName()) == "")
2475 this->GroupNameMap
[s
] = tgroup
;
2479 cmXCodeObject
* tgroupChildren
= tgroup
->GetObject("children");
2480 cmXCodeObject
* group
= this->CreateObject(cmXCodeObject::PBXGroup
);
2481 cmXCodeObject
* groupChildren
=
2482 this->CreateObject(cmXCodeObject::OBJECT_LIST
);
2483 group
->AddAttribute("name", this->CreateString(sg
->GetName()));
2484 group
->AddAttribute("children", groupChildren
);
2485 if(this->XcodeVersion
== 15)
2487 group
->AddAttribute("refType", this->CreateString("4"));
2489 group
->AddAttribute("sourceTree", this->CreateString("<group>"));
2490 tgroupChildren
->AddObject(group
);
2491 this->GroupNameMap
[s
] = group
;
2495 //----------------------------------------------------------------------------
2496 void cmGlobalXCodeGenerator
2497 ::CreateXCodeObjects(cmLocalGenerator
* root
,
2498 std::vector
<cmLocalGenerator
*>&
2501 this->ClearXCodeObjects();
2502 this->RootObject
= 0;
2503 this->SourcesGroupChildren
= 0;
2504 this->ResourcesGroupChildren
= 0;
2505 this->MainGroupChildren
= 0;
2506 cmXCodeObject
* group
= this->CreateObject(cmXCodeObject::ATTRIBUTE_GROUP
);
2507 group
->AddAttribute("COPY_PHASE_STRIP", this->CreateString("NO"));
2508 cmXCodeObject
* developBuildStyle
=
2509 this->CreateObject(cmXCodeObject::PBXBuildStyle
);
2510 cmXCodeObject
* listObjs
= this->CreateObject(cmXCodeObject::OBJECT_LIST
);
2511 if(this->XcodeVersion
== 15)
2513 developBuildStyle
->AddAttribute("name",
2514 this->CreateString("Development"));
2515 developBuildStyle
->AddAttribute("buildSettings", group
);
2516 listObjs
->AddObject(developBuildStyle
);
2517 group
= this->CreateObject(cmXCodeObject::ATTRIBUTE_GROUP
);
2518 group
->AddAttribute("COPY_PHASE_STRIP", this->CreateString("YES"));
2519 cmXCodeObject
* deployBuildStyle
=
2520 this->CreateObject(cmXCodeObject::PBXBuildStyle
);
2521 deployBuildStyle
->AddAttribute("name", this->CreateString("Deployment"));
2522 deployBuildStyle
->AddAttribute("buildSettings", group
);
2523 listObjs
->AddObject(deployBuildStyle
);
2527 for(unsigned int i
= 0; i
< this->CurrentConfigurationTypes
.size(); ++i
)
2529 cmXCodeObject
* buildStyle
=
2530 this->CreateObject(cmXCodeObject::PBXBuildStyle
);
2531 const char* name
= this->CurrentConfigurationTypes
[i
].c_str();
2532 buildStyle
->AddAttribute("name", this->CreateString(name
));
2533 buildStyle
->SetComment(name
);
2534 cmXCodeObject
* sgroup
=
2535 this->CreateObject(cmXCodeObject::ATTRIBUTE_GROUP
);
2536 sgroup
->AddAttribute("COPY_PHASE_STRIP", this->CreateString("NO"));
2537 buildStyle
->AddAttribute("buildSettings", sgroup
);
2538 listObjs
->AddObject(buildStyle
);
2542 cmXCodeObject
* mainGroup
= this->CreateObject(cmXCodeObject::PBXGroup
);
2543 this->MainGroupChildren
=
2544 this->CreateObject(cmXCodeObject::OBJECT_LIST
);
2545 mainGroup
->AddAttribute("children", this->MainGroupChildren
);
2546 if(this->XcodeVersion
== 15)
2548 mainGroup
->AddAttribute("refType", this->CreateString("4"));
2550 mainGroup
->AddAttribute("sourceTree", this->CreateString("<group>"));
2552 cmXCodeObject
* sourcesGroup
= this->CreateObject(cmXCodeObject::PBXGroup
);
2553 this->SourcesGroupChildren
=
2554 this->CreateObject(cmXCodeObject::OBJECT_LIST
);
2555 sourcesGroup
->AddAttribute("name", this->CreateString("Sources"));
2556 sourcesGroup
->AddAttribute("children", this->SourcesGroupChildren
);
2557 if(this->XcodeVersion
== 15)
2559 sourcesGroup
->AddAttribute("refType", this->CreateString("4"));
2561 sourcesGroup
->AddAttribute("sourceTree", this->CreateString("<group>"));
2562 this->MainGroupChildren
->AddObject(sourcesGroup
);
2564 cmXCodeObject
* resourcesGroup
= this->CreateObject(cmXCodeObject::PBXGroup
);
2565 this->ResourcesGroupChildren
=
2566 this->CreateObject(cmXCodeObject::OBJECT_LIST
);
2567 resourcesGroup
->AddAttribute("name", this->CreateString("Resources"));
2568 resourcesGroup
->AddAttribute("children", this->ResourcesGroupChildren
);
2569 if(this->XcodeVersion
== 15)
2571 resourcesGroup
->AddAttribute("refType", this->CreateString("4"));
2573 resourcesGroup
->AddAttribute("sourceTree", this->CreateString("<group>"));
2574 this->MainGroupChildren
->AddObject(resourcesGroup
);
2576 // now create the cmake groups
2577 this->CreateGroups(root
, generators
);
2579 cmXCodeObject
* productGroup
= this->CreateObject(cmXCodeObject::PBXGroup
);
2580 productGroup
->AddAttribute("name", this->CreateString("Products"));
2581 if(this->XcodeVersion
== 15)
2583 productGroup
->AddAttribute("refType", this->CreateString("4"));
2585 productGroup
->AddAttribute("sourceTree", this->CreateString("<group>"));
2586 cmXCodeObject
* productGroupChildren
=
2587 this->CreateObject(cmXCodeObject::OBJECT_LIST
);
2588 productGroup
->AddAttribute("children", productGroupChildren
);
2589 this->MainGroupChildren
->AddObject(productGroup
);
2592 this->RootObject
= this->CreateObject(cmXCodeObject::PBXProject
);
2593 this->RootObject
->SetComment("Project object");
2594 group
= this->CreateObject(cmXCodeObject::ATTRIBUTE_GROUP
);
2595 this->RootObject
->AddAttribute("mainGroup",
2596 this->CreateObjectReference(mainGroup
));
2597 this->RootObject
->AddAttribute("buildSettings", group
);
2598 this->RootObject
->AddAttribute("buildStyles", listObjs
);
2599 this->RootObject
->AddAttribute("hasScannedForEncodings",
2600 this->CreateString("0"));
2601 if (this->XcodeVersion
>= 30)
2603 group
= this->CreateObject(cmXCodeObject::ATTRIBUTE_GROUP
);
2604 group
->AddAttribute("BuildIndependentTargetsInParallel",
2605 this->CreateString("YES"));
2606 this->RootObject
->AddAttribute("attributes", group
);
2607 if (this->XcodeVersion
>= 31)
2608 this->RootObject
->AddAttribute("compatibilityVersion",
2609 this->CreateString("Xcode 3.1"));
2611 this->RootObject
->AddAttribute("compatibilityVersion",
2612 this->CreateString("Xcode 3.0"));
2613 this->RootObject
->AddAttribute("projectDirPath", this->CreateString(""));
2615 // Point Xcode at the top of the source tree.
2617 std::string proot
= root
->GetMakefile()->GetCurrentDirectory();
2618 proot
= this->ConvertToRelativeForXCode(proot
.c_str());
2619 if (this->XcodeVersion
>= 30)
2621 this->RootObject
->AddAttribute("projectRoot",
2622 this->CreateString(""));
2623 this->RootObject
->AddAttribute("projectDirPath",
2624 this->CreateString(proot
.c_str()));
2628 this->RootObject
->AddAttribute("projectRoot",
2629 this->CreateString(proot
.c_str()));
2632 cmXCodeObject
* configlist
=
2633 this->CreateObject(cmXCodeObject::XCConfigurationList
);
2634 cmXCodeObject
* buildConfigurations
=
2635 this->CreateObject(cmXCodeObject::OBJECT_LIST
);
2636 std::vector
<cmXCodeObject
*> configs
;
2637 if(this->XcodeVersion
== 15)
2639 cmXCodeObject
* configDebug
=
2640 this->CreateObject(cmXCodeObject::XCBuildConfiguration
);
2641 configDebug
->AddAttribute("name", this->CreateString("Debug"));
2642 configs
.push_back(configDebug
);
2643 cmXCodeObject
* configRelease
=
2644 this->CreateObject(cmXCodeObject::XCBuildConfiguration
);
2645 configRelease
->AddAttribute("name", this->CreateString("Release"));
2646 configs
.push_back(configRelease
);
2650 for(unsigned int i
= 0; i
< this->CurrentConfigurationTypes
.size(); ++i
)
2652 const char* name
= this->CurrentConfigurationTypes
[i
].c_str();
2653 cmXCodeObject
* config
=
2654 this->CreateObject(cmXCodeObject::XCBuildConfiguration
);
2655 config
->AddAttribute("name", this->CreateString(name
));
2656 configs
.push_back(config
);
2659 for(std::vector
<cmXCodeObject
*>::iterator c
= configs
.begin();
2660 c
!= configs
.end(); ++c
)
2662 buildConfigurations
->AddObject(*c
);
2664 configlist
->AddAttribute("buildConfigurations", buildConfigurations
);
2666 std::string comment
= "Build configuration list for PBXProject ";
2668 comment
+= this->CurrentProject
;
2670 configlist
->SetComment(comment
.c_str());
2671 configlist
->AddAttribute("defaultConfigurationIsVisible",
2672 this->CreateString("0"));
2673 configlist
->AddAttribute("defaultConfigurationName",
2674 this->CreateString("Debug"));
2675 cmXCodeObject
* buildSettings
=
2676 this->CreateObject(cmXCodeObject::ATTRIBUTE_GROUP
);
2677 const char* osxArch
=
2678 this->CurrentMakefile
->GetDefinition("CMAKE_OSX_ARCHITECTURES");
2679 if(strlen(osxArch
) == 0)
2681 if(this->XcodeVersion
>= 32)
2683 osxArch
= "$(ARCHS_STANDARD_32_64_BIT)";
2685 else if(this->XcodeVersion
<= 25)
2696 osxArch
= "$(ARCHS_STANDARD_32_BIT)";
2698 buildSettings
->AddAttribute("ONLY_ACTIVE_ARCH",
2699 this->CreateString("YES"));
2702 const char* sysroot
=
2703 this->CurrentMakefile
->GetDefinition("CMAKE_OSX_SYSROOT");
2704 const char* sysrootDefault
=
2705 this->CurrentMakefile
->GetDefinition("CMAKE_OSX_SYSROOT_DEFAULT");
2706 const char* deploymentTarget
=
2707 this->CurrentMakefile
->GetDefinition("CMAKE_OSX_DEPLOYMENT_TARGET");
2708 if(osxArch
&& sysroot
)
2710 bool flagsUsed
= false;
2711 // recompute this as it may have been changed since enable language
2712 this->Architectures
.clear();
2713 cmSystemTools::ExpandListArgument(std::string(osxArch
),
2714 this->Architectures
);
2716 buildSettings
->AddAttribute("SDKROOT",
2717 this->CreateString(sysroot
));
2718 std::string archString
;
2719 for( std::vector
<std::string
>::iterator i
=
2720 this->Architectures
.begin();
2721 i
!= this->Architectures
.end(); ++i
)
2726 buildSettings
->AddAttribute("ARCHS",
2727 this->CreateString(archString
.c_str()));
2728 if(!flagsUsed
&& sysrootDefault
&&
2729 strcmp(sysroot
, sysrootDefault
) != 0)
2731 buildSettings
->AddAttribute("SDKROOT",
2732 this->CreateString(sysroot
));
2735 if(deploymentTarget
&& *deploymentTarget
)
2737 buildSettings
->AddAttribute("MACOSX_DEPLOYMENT_TARGET",
2738 this->CreateString(deploymentTarget
));
2741 std::string symroot
= root
->GetMakefile()->GetCurrentOutputDirectory();
2742 symroot
+= "/build";
2743 buildSettings
->AddAttribute("SYMROOT", this->CreateString(symroot
.c_str()));
2745 for( std::vector
<cmXCodeObject
*>::iterator i
= configs
.begin();
2746 i
!= configs
.end(); ++i
)
2748 (*i
)->AddAttribute("buildSettings", buildSettings
);
2751 this->RootObject
->AddAttribute("buildConfigurationList",
2752 this->CreateObjectReference(configlist
));
2754 std::vector
<cmXCodeObject
*> targets
;
2755 for(std::vector
<cmLocalGenerator
*>::iterator i
= generators
.begin();
2756 i
!= generators
.end(); ++i
)
2758 if(!this->IsExcluded(root
, *i
))
2760 this->CreateXCodeTargets(*i
, targets
);
2763 // loop over all targets and add link and depend info
2764 for(std::vector
<cmXCodeObject
*>::iterator i
= targets
.begin();
2765 i
!= targets
.end(); ++i
)
2767 cmXCodeObject
* t
= *i
;
2768 this->AddDependAndLinkInformation(t
);
2770 // now create xcode depend hack makefile
2771 this->CreateXCodeDependHackTarget(targets
);
2772 // now add all targets to the root object
2773 cmXCodeObject
* allTargets
= this->CreateObject(cmXCodeObject::OBJECT_LIST
);
2774 for(std::vector
<cmXCodeObject
*>::iterator i
= targets
.begin();
2775 i
!= targets
.end(); ++i
)
2777 cmXCodeObject
* t
= *i
;
2778 allTargets
->AddObject(t
);
2779 cmXCodeObject
* productRef
= t
->GetObject("productReference");
2782 productGroupChildren
->AddObject(productRef
->GetObject());
2785 this->RootObject
->AddAttribute("targets", allTargets
);
2788 //----------------------------------------------------------------------------
2790 cmGlobalXCodeGenerator::CreateXCodeDependHackTarget(
2791 std::vector
<cmXCodeObject
*>& targets
)
2793 cmGeneratedFileStream
2794 makefileStream(this->CurrentXCodeHackMakefile
.c_str());
2797 cmSystemTools::Error("Could not create",
2798 this->CurrentXCodeHackMakefile
.c_str());
2801 makefileStream
.SetCopyIfDifferent(true);
2802 // one more pass for external depend information not handled
2803 // correctly by xcode
2804 makefileStream
<< "# DO NOT EDIT\n";
2805 makefileStream
<< "# This makefile makes sure all linkable targets are\n";
2806 makefileStream
<< "# up-to-date with anything they link to, avoiding a "
2807 "bug in XCode 1.5\n";
2808 for(std::vector
<std::string
>::const_iterator
2809 ct
= this->CurrentConfigurationTypes
.begin();
2810 ct
!= this->CurrentConfigurationTypes
.end(); ++ct
)
2812 if(this->XcodeVersion
< 21 || ct
->empty())
2814 makefileStream
<< "all: ";
2818 makefileStream
<< "all." << *ct
<< ": ";
2820 const char* configName
= 0;
2823 configName
= ct
->c_str();
2825 for(std::vector
<cmXCodeObject
*>::iterator i
= targets
.begin();
2826 i
!= targets
.end(); ++i
)
2828 cmXCodeObject
* target
= *i
;
2829 cmTarget
* t
=target
->GetTarget();
2830 if(t
->GetType() == cmTarget::EXECUTABLE
||
2831 t
->GetType() == cmTarget::SHARED_LIBRARY
||
2832 t
->GetType() == cmTarget::MODULE_LIBRARY
)
2834 std::string tfull
= t
->GetFullPath(configName
);
2835 makefileStream
<< "\\\n\t" <<
2836 this->ConvertToRelativeForMake(tfull
.c_str());
2839 makefileStream
<< "\n\n";
2842 << "# For each target create a dummy rule "
2843 "so the target does not have to exist\n";
2844 std::set
<cmStdString
> emitted
;
2845 for(std::vector
<cmXCodeObject
*>::iterator i
= targets
.begin();
2846 i
!= targets
.end(); ++i
)
2848 cmXCodeObject
* target
= *i
;
2849 std::map
<cmStdString
, cmXCodeObject::StringVec
> const& deplibs
=
2850 target
->GetDependLibraries();
2851 for(std::map
<cmStdString
, cmXCodeObject::StringVec
>::const_iterator ci
2852 = deplibs
.begin(); ci
!= deplibs
.end(); ++ci
)
2854 for(cmXCodeObject::StringVec::const_iterator d
= ci
->second
.begin();
2855 d
!= ci
->second
.end(); ++d
)
2857 if(emitted
.insert(*d
).second
)
2860 this->ConvertToRelativeForMake(d
->c_str()) << ":\n";
2865 makefileStream
<< "\n\n";
2867 // Write rules to help Xcode relink things at the right time.
2869 "# Rules to remove targets that are older than anything to which they\n"
2870 "# link. This forces Xcode to relink the targets from scratch. It\n"
2871 "# does not seem to check these dependencies itself.\n";
2872 for(std::vector
<std::string
>::const_iterator
2873 ct
= this->CurrentConfigurationTypes
.begin();
2874 ct
!= this->CurrentConfigurationTypes
.end(); ++ct
)
2876 const char* configName
= 0;
2879 configName
= ct
->c_str();
2881 for(std::vector
<cmXCodeObject
*>::iterator i
= targets
.begin();
2882 i
!= targets
.end(); ++i
)
2884 cmXCodeObject
* target
= *i
;
2885 cmTarget
* t
=target
->GetTarget();
2886 if(t
->GetType() == cmTarget::EXECUTABLE
||
2887 t
->GetType() == cmTarget::SHARED_LIBRARY
||
2888 t
->GetType() == cmTarget::MODULE_LIBRARY
)
2890 // Create a rule for this target.
2891 std::string tfull
= t
->GetFullPath(configName
);
2892 makefileStream
<< this->ConvertToRelativeForMake(tfull
.c_str())
2895 // List dependencies if any exist.
2896 std::map
<cmStdString
, cmXCodeObject::StringVec
>::const_iterator
2897 x
= target
->GetDependLibraries().find(*ct
);
2898 if(x
!= target
->GetDependLibraries().end())
2900 std::vector
<cmStdString
> const& deplibs
= x
->second
;
2901 for(std::vector
<cmStdString
>::const_iterator d
= deplibs
.begin();
2902 d
!= deplibs
.end(); ++d
)
2904 makefileStream
<< "\\\n\t" <<
2905 this->ConvertToRelativeForMake(d
->c_str());
2908 // Write the action to remove the target if it is out of date.
2909 makefileStream
<< "\n";
2910 makefileStream
<< "\t/bin/rm -f "
2911 << this->ConvertToRelativeForMake(tfull
.c_str())
2913 // if building for more than one architecture
2914 // then remove those exectuables as well
2915 if(this->Architectures
.size() > 1)
2917 std::string universal
= t
->GetDirectory();
2919 universal
+= this->CurrentProject
;
2920 universal
+= ".build/";
2921 universal
+= configName
;
2923 universal
+= t
->GetName();
2924 universal
+= ".build/Objects-normal/";
2925 for( std::vector
<std::string
>::iterator arch
=
2926 this->Architectures
.begin();
2927 arch
!= this->Architectures
.end(); ++arch
)
2929 std::string universalFile
= universal
;
2930 universalFile
+= *arch
;
2931 universalFile
+= "/";
2932 universalFile
+= t
->GetFullName(configName
);
2933 makefileStream
<< "\t/bin/rm -f "
2935 this->ConvertToRelativeForMake(universalFile
.c_str())
2939 makefileStream
<< "\n\n";
2945 //----------------------------------------------------------------------------
2947 cmGlobalXCodeGenerator::OutputXCodeProject(cmLocalGenerator
* root
,
2948 std::vector
<cmLocalGenerator
*>&
2951 if(generators
.size() == 0)
2955 // Skip local generators that are excluded from this project.
2956 for(std::vector
<cmLocalGenerator
*>::iterator g
= generators
.begin();
2957 g
!= generators
.end(); ++g
)
2959 if(this->IsExcluded(root
, *g
))
2965 this->CreateXCodeObjects(root
,
2967 std::string xcodeDir
= root
->GetMakefile()->GetStartOutputDirectory();
2969 xcodeDir
+= root
->GetMakefile()->GetProjectName();
2970 xcodeDir
+= ".xcode";
2971 if(this->XcodeVersion
> 20)
2975 cmSystemTools::MakeDirectory(xcodeDir
.c_str());
2976 std::string xcodeProjFile
= xcodeDir
+ "/project.pbxproj";
2977 cmGeneratedFileStream
fout(xcodeProjFile
.c_str());
2978 fout
.SetCopyIfDifferent(true);
2983 this->WriteXCodePBXProj(fout
, root
, generators
);
2984 this->ClearXCodeObjects();
2987 //----------------------------------------------------------------------------
2989 cmGlobalXCodeGenerator::WriteXCodePBXProj(std::ostream
& fout
,
2991 std::vector
<cmLocalGenerator
*>& )
2993 fout
<< "// !$*UTF8*$!\n";
2995 cmXCodeObject::Indent(1, fout
);
2996 fout
<< "archiveVersion = 1;\n";
2997 cmXCodeObject::Indent(1, fout
);
2998 fout
<< "classes = {\n";
2999 cmXCodeObject::Indent(1, fout
);
3001 cmXCodeObject::Indent(1, fout
);
3002 if(this->XcodeVersion
>= 21)
3004 if (this->XcodeVersion
>= 31)
3005 fout
<< "objectVersion = 45;\n";
3006 else if (this->XcodeVersion
>= 30)
3007 fout
<< "objectVersion = 44;\n";
3009 fout
<< "objectVersion = 42;\n";
3010 cmXCode21Object::PrintList(this->XCodeObjects
, fout
);
3014 fout
<< "objectVersion = 39;\n";
3015 cmXCodeObject::PrintList(this->XCodeObjects
, fout
);
3017 cmXCodeObject::Indent(1, fout
);
3018 fout
<< "rootObject = " << this->RootObject
->GetId() << ";\n";
3022 //----------------------------------------------------------------------------
3023 const char* cmGlobalXCodeGenerator::GetCMakeCFGInitDirectory()
3025 return this->XcodeVersion
>= 21? "$(CONFIGURATION)" : ".";
3028 //----------------------------------------------------------------------------
3029 void cmGlobalXCodeGenerator::GetDocumentation(cmDocumentationEntry
& entry
)
3032 entry
.Name
= this->GetName();
3033 entry
.Brief
= "Generate XCode project files.";
3037 //----------------------------------------------------------------------------
3038 std::string
cmGlobalXCodeGenerator::ConvertToRelativeForMake(const char* p
)
3040 if ( !this->CurrentMakefile
->IsOn("CMAKE_USE_RELATIVE_PATHS") )
3042 return cmSystemTools::ConvertToOutputPath(p
);
3047 this->CurrentLocalGenerator
->
3048 ConvertToRelativePath(this->CurrentOutputDirectoryComponents
, p
);
3049 return cmSystemTools::ConvertToOutputPath(ret
.c_str());
3053 //----------------------------------------------------------------------------
3054 std::string
cmGlobalXCodeGenerator::ConvertToRelativeForXCode(const char* p
)
3056 if ( !this->CurrentMakefile
->IsOn("CMAKE_USE_RELATIVE_PATHS") )
3058 return cmSystemTools::ConvertToOutputPath(p
);
3063 this->CurrentLocalGenerator
->
3064 ConvertToRelativePath(this->ProjectOutputDirectoryComponents
, p
);
3065 return cmSystemTools::ConvertToOutputPath(ret
.c_str());
3069 //----------------------------------------------------------------------------
3070 std::string
cmGlobalXCodeGenerator::XCodeEscapePath(const char* p
)
3072 std::string ret
= p
;
3073 if(ret
.find(' ') != ret
.npos
)
3075 std::string t
= ret
;
3083 //----------------------------------------------------------------------------
3084 void cmGlobalXCodeGenerator::
3085 GetTargetObjectFileDirectories(cmTarget
* target
,
3086 std::vector
<std::string
>&
3089 std::string dir
= this->CurrentMakefile
->GetCurrentOutputDirectory();
3091 dir
+= this->CurrentMakefile
->GetProjectName();
3093 dir
+= this->GetCMakeCFGInitDirectory();
3095 dir
+= target
->GetName();
3096 dir
+= ".build/Objects-normal/";
3097 std::string dirsave
= dir
;
3098 if(this->Architectures
.size())
3100 for(std::vector
<std::string
>::iterator i
= this->Architectures
.begin();
3101 i
!= this->Architectures
.end(); ++i
)
3104 dirs
.push_back(dir
);
3110 dirs
.push_back(dir
);
3114 //----------------------------------------------------------------------------
3116 cmGlobalXCodeGenerator
3117 ::AppendDirectoryForConfig(const char* prefix
,
3122 if(this->XcodeVersion
> 20)
3133 //----------------------------------------------------------------------------
3134 std::string
cmGlobalXCodeGenerator::LookupFlags(const char* varNamePrefix
,
3135 const char* varNameLang
,
3136 const char* varNameSuffix
,
3137 const char* default_flags
)
3141 std::string varName
= varNamePrefix
;
3142 varName
+= varNameLang
;
3143 varName
+= varNameSuffix
;
3144 if(const char* varValue
=
3145 this->CurrentMakefile
->GetDefinition(varName
.c_str()))
3153 return default_flags
;
3156 //----------------------------------------------------------------------------
3157 void cmGlobalXCodeGenerator::AppendDefines(BuildObjectListOrString
& defs
,
3158 const char* defines_list
,
3161 // Skip this if there are no definitions.
3167 // Expand the list of definitions.
3168 std::vector
<std::string
> defines
;
3169 cmSystemTools::ExpandListArgument(defines_list
, defines
);
3171 // Store the definitions in the string.
3172 this->AppendDefines(defs
, defines
, dflag
);
3175 //----------------------------------------------------------------------------
3177 cmGlobalXCodeGenerator::AppendDefines(BuildObjectListOrString
& defs
,
3178 std::vector
<std::string
> const& defines
,
3181 // GCC_PREPROCESSOR_DEFINITIONS is a space-separated list of definitions.
3183 for(std::vector
<std::string
>::const_iterator di
= defines
.begin();
3184 di
!= defines
.end(); ++di
)
3186 // Start with -D if requested.
3187 def
= dflag
? "-D": "";
3190 // Append the flag with needed escapes.
3192 this->AppendFlag(tmp
, def
);
3193 defs
.Add(tmp
.c_str());
3197 //----------------------------------------------------------------------------
3198 void cmGlobalXCodeGenerator::AppendFlag(std::string
& flags
,
3199 std::string
const& flag
)
3201 // Short-circuit for an empty flag.
3207 // Separate from previous flags.
3213 // Check if the flag needs quoting.
3215 flag
.find_first_of("`~!@#$%^&*()+={}[]|:;\"'<>,.? ") != flag
.npos
;
3217 // We escape a flag as follows:
3218 // - Place each flag in single quotes ''
3219 // - Escape a single quote as \\'
3220 // - Escape a backslash as \\\\ since it itself is an escape
3221 // Note that in the code below we need one more level of escapes for
3222 // C string syntax in this source file.
3224 // The final level of escaping is done when the string is stored
3225 // into the project file by cmXCodeObject::PrintString.
3229 // Open single quote.
3233 // Flag value with escaped quotes and backslashes.
3234 for(const char* c
= flag
.c_str(); *c
; ++c
)
3242 flags
+= "\\\\\\\\";
3252 // Close single quote.
3257 //----------------------------------------------------------------------------
3259 cmGlobalXCodeGenerator::ComputeInfoPListLocation(cmTarget
& target
)
3261 std::string plist
= target
.GetMakefile()->GetCurrentOutputDirectory();
3262 plist
+= cmake::GetCMakeFilesDirectory();
3264 plist
+= target
.GetName();
3265 plist
+= ".dir/Info.plist";