1 /*=========================================================================
3 Program: CMake - Cross-Platform Makefile Generator
4 Module: $RCSfile: cmGlobalXCodeGenerator.cxx,v $
6 Date: $Date: 2009-03-16 18:30:24 $
7 Version: $Revision: 1.210 $
9 Copyright (c) 2002 Kitware, Inc., Insight Consortium. All rights reserved.
10 See Copyright.txt or http://www.cmake.org/HTML/Copyright.html for details.
12 This software is distributed WITHOUT ANY WARRANTY; without even
13 the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
14 PURPOSE. See the above copyright notices for more information.
16 =========================================================================*/
17 #include "cmGlobalXCodeGenerator.h"
18 #include "cmGlobalXCode21Generator.h"
19 #include "cmLocalXCodeGenerator.h"
20 #include "cmMakefile.h"
21 #include "cmXCodeObject.h"
22 #include "cmXCode21Object.h"
24 #include "cmGeneratedFileStream.h"
25 #include "cmComputeLinkInformation.h"
26 #include "cmSourceFile.h"
28 //----------------------------------------------------------------------------
29 #if defined(CMAKE_BUILD_WITH_CMAKE)
30 #include "cmXMLParser.h"
32 // parse the xml file storing the installed version of Xcode on
34 class cmXcodeVersionParser
: public cmXMLParser
37 void StartElement(const char* , const char** )
41 void EndElement(const char* name
)
43 if(strcmp(name
, "key") == 0)
45 this->Key
= this->Data
;
47 else if(strcmp(name
, "string") == 0)
49 if(this->Key
== "CFBundleShortVersionString")
51 this->Version
= (int)(10.0 * atof(this->Data
.c_str()));
55 void CharacterDataHandler(const char* data
, int length
)
57 this->Data
.append(data
, length
);
65 //----------------------------------------------------------------------------
66 cmGlobalXCodeGenerator::cmGlobalXCodeGenerator()
68 this->FindMakeProgramFile
= "CMakeFindXCode.cmake";
70 this->MainGroupChildren
= 0;
71 this->SourcesGroupChildren
= 0;
72 this->ResourcesGroupChildren
= 0;
73 this->CurrentMakefile
= 0;
74 this->CurrentLocalGenerator
= 0;
75 this->XcodeVersion
= 15;
78 //----------------------------------------------------------------------------
79 cmGlobalGenerator
* cmGlobalXCodeGenerator::New()
81 #if defined(CMAKE_BUILD_WITH_CMAKE)
82 cmXcodeVersionParser parser
;
84 ("/Developer/Applications/Xcode.app/Contents/version.plist");
85 if(parser
.Version
== 15)
87 return new cmGlobalXCodeGenerator
;
89 else if (parser
.Version
== 20)
91 cmSystemTools::Message("Xcode 2.0 not really supported by cmake, "
92 "using Xcode 15 generator\n");
93 return new cmGlobalXCodeGenerator
;
95 cmGlobalXCodeGenerator
* ret
= new cmGlobalXCode21Generator
;
96 ret
->SetVersion(parser
.Version
);
99 std::cerr
<< "CMake should be built with cmake to use XCode, "
100 "default to Xcode 1.5\n";
101 return new cmGlobalXCodeGenerator
;
105 //----------------------------------------------------------------------------
106 void cmGlobalXCodeGenerator::EnableLanguage(std::vector
<std::string
>const&
108 cmMakefile
* mf
, bool optional
)
110 mf
->AddDefinition("XCODE","1");
111 if(this->XcodeVersion
== 15)
116 mf
->AddCacheDefinition(
117 "CMAKE_CONFIGURATION_TYPES",
118 "Debug;Release;MinSizeRel;RelWithDebInfo",
119 "Semicolon separated list of supported configuration types, "
120 "only supports Debug, Release, MinSizeRel, and RelWithDebInfo, "
121 "anything else will be ignored.",
122 cmCacheManager::STRING
);
124 mf
->AddDefinition("CMAKE_GENERATOR_CC", "gcc");
125 mf
->AddDefinition("CMAKE_GENERATOR_CXX", "g++");
126 mf
->AddDefinition("CMAKE_GENERATOR_NO_COMPILER_ENV", "1");
127 // initialize Architectures so it can be used by
128 // GetTargetObjectFileDirectories
129 this->cmGlobalGenerator::EnableLanguage(lang
, mf
, optional
);
130 const char* osxArch
=
131 mf
->GetDefinition("CMAKE_OSX_ARCHITECTURES");
132 const char* sysroot
=
133 mf
->GetDefinition("CMAKE_OSX_SYSROOT");
134 if(osxArch
&& sysroot
)
136 this->Architectures
.clear();
137 cmSystemTools::ExpandListArgument(std::string(osxArch
),
138 this->Architectures
);
142 //----------------------------------------------------------------------------
143 std::string cmGlobalXCodeGenerator
144 ::GenerateBuildCommand(const char* makeProgram
,
145 const char *projectName
,
146 const char* additionalOptions
,
147 const char *targetName
,
152 // Config is not used yet
155 // now build the test
156 if(makeProgram
== 0 || !strlen(makeProgram
))
158 cmSystemTools::Error(
159 "Generator cannot find the appropriate make command.");
162 std::string makeCommand
=
163 cmSystemTools::ConvertToOutputPath(makeProgram
);
164 std::string lowerCaseCommand
= makeCommand
;
165 cmSystemTools::LowerCase(lowerCaseCommand
);
167 makeCommand
+= " -project ";
168 makeCommand
+= projectName
;
169 makeCommand
+= ".xcode";
170 if(this->XcodeVersion
> 20)
172 makeCommand
+= "proj";
176 if ( targetName
&& strcmp(targetName
, "clean") == 0 )
179 targetName
= "ALL_BUILD";
183 makeCommand
+= " clean";
187 makeCommand
+= " build";
189 makeCommand
+= " -target ";
190 // if it is a null string for config don't use it
191 if(config
&& *config
== 0)
195 if (targetName
&& strlen(targetName
))
197 makeCommand
+= targetName
;
201 makeCommand
+= "ALL_BUILD";
203 if(this->XcodeVersion
== 15)
205 makeCommand
+= " -buildstyle Development ";
209 makeCommand
+= " -configuration ";
210 makeCommand
+= config
?config
:"Debug";
212 if ( additionalOptions
)
215 makeCommand
+= additionalOptions
;
220 //----------------------------------------------------------------------------
221 ///! Create a local generator appropriate to this Global Generator
222 cmLocalGenerator
*cmGlobalXCodeGenerator::CreateLocalGenerator()
224 cmLocalGenerator
*lg
= new cmLocalXCodeGenerator
;
225 lg
->SetGlobalGenerator(this);
229 //----------------------------------------------------------------------------
230 void cmGlobalXCodeGenerator::Generate()
232 std::map
<cmStdString
, std::vector
<cmLocalGenerator
*> >::iterator it
;
233 // make sure extra targets are added before calling
234 // the parent generate which will call trace depends
235 for(it
= this->ProjectMap
.begin(); it
!= this->ProjectMap
.end(); ++it
)
237 cmLocalGenerator
* root
= it
->second
[0];
238 this->SetGenerationRoot(root
);
239 // add ALL_BUILD, INSTALL, etc
240 this->AddExtraTargets(root
, it
->second
);
242 this->cmGlobalGenerator::Generate();
243 for(it
= this->ProjectMap
.begin(); it
!= this->ProjectMap
.end(); ++it
)
245 cmLocalGenerator
* root
= it
->second
[0];
246 this->SetGenerationRoot(root
);
247 // now create the project
248 this->OutputXCodeProject(root
, it
->second
);
252 //----------------------------------------------------------------------------
253 void cmGlobalXCodeGenerator::SetGenerationRoot(cmLocalGenerator
* root
)
255 this->CurrentProject
= root
->GetMakefile()->GetProjectName();
256 this->SetCurrentLocalGenerator(root
);
257 std::string outDir
= this->CurrentMakefile
->GetHomeOutputDirectory();
258 outDir
=cmSystemTools::CollapseFullPath(outDir
.c_str());
259 cmSystemTools::SplitPath(outDir
.c_str(),
260 this->ProjectOutputDirectoryComponents
);
262 this->CurrentXCodeHackMakefile
=
263 root
->GetMakefile()->GetCurrentOutputDirectory();
264 this->CurrentXCodeHackMakefile
+= "/CMakeScripts";
265 cmSystemTools::MakeDirectory(this->CurrentXCodeHackMakefile
.c_str());
266 this->CurrentXCodeHackMakefile
+= "/XCODE_DEPEND_HELPER.make";
269 //----------------------------------------------------------------------------
271 cmGlobalXCodeGenerator::AddExtraTargets(cmLocalGenerator
* root
,
272 std::vector
<cmLocalGenerator
*>& gens
)
274 cmMakefile
* mf
= root
->GetMakefile();
277 const char* no_working_directory
= 0;
278 std::vector
<std::string
> no_depends
;
279 mf
->AddUtilityCommand("ALL_BUILD", true, no_depends
,
280 no_working_directory
,
281 "echo", "Build all projects");
282 cmTarget
* allbuild
= mf
->FindTarget("ALL_BUILD");
284 // Refer to the main build configuration file for easy editing.
285 std::string listfile
= mf
->GetStartDirectory();
287 listfile
+= "CMakeLists.txt";
288 allbuild
->AddSource(listfile
.c_str());
290 // Add XCODE depend helper
291 std::string dir
= mf
->GetCurrentOutputDirectory();
292 cmCustomCommandLine makecommand
;
293 makecommand
.push_back("make");
294 makecommand
.push_back("-C");
295 makecommand
.push_back(dir
.c_str());
296 makecommand
.push_back("-f");
297 makecommand
.push_back(this->CurrentXCodeHackMakefile
.c_str());
298 if(this->XcodeVersion
> 20)
300 makecommand
.push_back("all.$(CONFIGURATION)");
302 cmCustomCommandLines commandLines
;
303 commandLines
.push_back(makecommand
);
304 // Add Re-Run CMake rules
305 this->CreateReRunCMakeFile(root
);
307 // now make the allbuild depend on all the non-utility targets
309 for(std::vector
<cmLocalGenerator
*>::iterator i
= gens
.begin();
310 i
!= gens
.end(); ++i
)
312 cmLocalGenerator
* lg
= *i
;
313 if(this->IsExcluded(root
, *i
))
317 cmTargets
& tgts
= lg
->GetMakefile()->GetTargets();
318 for(cmTargets::iterator l
= tgts
.begin(); l
!= tgts
.end(); l
++)
320 cmTarget
& target
= l
->second
;
321 // make all exe, shared libs and modules
322 // run the depend check makefile as a post build rule
323 // this will make sure that when the next target is built
324 // things are up-to-date
325 if((target
.GetType() == cmTarget::EXECUTABLE
||
326 target
.GetType() == cmTarget::STATIC_LIBRARY
||
327 target
.GetType() == cmTarget::SHARED_LIBRARY
||
328 target
.GetType() == cmTarget::MODULE_LIBRARY
))
330 lg
->GetMakefile()->AddCustomCommandToTarget(target
.GetName(),
333 cmTarget::POST_BUILD
,
334 "Depend check for xcode",
338 if(!target
.GetPropertyAsBool("EXCLUDE_FROM_ALL"))
340 allbuild
->AddUtility(target
.GetName());
343 // Refer to the build configuration file for easy editing.
344 listfile
= lg
->GetMakefile()->GetStartDirectory();
346 listfile
+= "CMakeLists.txt";
347 target
.AddSource(listfile
.c_str());
352 //----------------------------------------------------------------------------
353 void cmGlobalXCodeGenerator::CreateReRunCMakeFile(cmLocalGenerator
* root
)
355 cmMakefile
* mf
= root
->GetMakefile();
356 std::vector
<std::string
> lfiles
= mf
->GetListFiles();
358 std::sort(lfiles
.begin(), lfiles
.end(), std::less
<std::string
>());
359 std::vector
<std::string
>::iterator new_end
=
360 std::unique(lfiles
.begin(), lfiles
.end());
361 lfiles
.erase(new_end
, lfiles
.end());
362 std::string dir
= mf
->GetHomeOutputDirectory();
363 this->CurrentReRunCMakeMakefile
= dir
;
364 this->CurrentReRunCMakeMakefile
+= "/CMakeScripts";
365 cmSystemTools::MakeDirectory(this->CurrentReRunCMakeMakefile
.c_str());
366 this->CurrentReRunCMakeMakefile
+= "/ReRunCMake.make";
367 cmGeneratedFileStream makefileStream
368 (this->CurrentReRunCMakeMakefile
.c_str());
369 makefileStream
.SetCopyIfDifferent(true);
370 makefileStream
<< "# Generated by CMake, DO NOT EDIT\n";
371 makefileStream
<< cmake::GetCMakeFilesDirectoryPostSlash();
372 makefileStream
<< "cmake.check_cache: ";
373 for(std::vector
<std::string
>::const_iterator i
= lfiles
.begin();
374 i
!= lfiles
.end(); ++i
)
376 makefileStream
<< "\\\n" << this->ConvertToRelativeForMake(i
->c_str());
378 std::string cmake
= mf
->GetRequiredDefinition("CMAKE_COMMAND");
379 makefileStream
<< "\n\t" << this->ConvertToRelativeForMake(cmake
.c_str())
380 << " -H" << this->ConvertToRelativeForMake(
381 mf
->GetHomeDirectory())
382 << " -B" << this->ConvertToRelativeForMake(
383 mf
->GetHomeOutputDirectory()) << "\n";
386 //----------------------------------------------------------------------------
387 void cmGlobalXCodeGenerator::ClearXCodeObjects()
389 this->TargetDoneSet
.clear();
390 for(unsigned int i
= 0; i
< this->XCodeObjects
.size(); ++i
)
392 delete this->XCodeObjects
[i
];
394 this->XCodeObjects
.clear();
395 this->GroupMap
.clear();
396 this->GroupNameMap
.clear();
397 this->TargetGroup
.clear();
398 this->FileRefs
.clear();
401 //----------------------------------------------------------------------------
403 cmGlobalXCodeGenerator::CreateObject(cmXCodeObject::PBXType ptype
)
406 if(this->XcodeVersion
== 15)
408 obj
= new cmXCodeObject(ptype
, cmXCodeObject::OBJECT
);
412 obj
= new cmXCode21Object(ptype
, cmXCodeObject::OBJECT
);
414 this->XCodeObjects
.push_back(obj
);
418 //----------------------------------------------------------------------------
420 cmGlobalXCodeGenerator::CreateObject(cmXCodeObject::Type type
)
422 cmXCodeObject
* obj
= new cmXCodeObject(cmXCodeObject::None
, type
);
423 this->XCodeObjects
.push_back(obj
);
427 //----------------------------------------------------------------------------
429 cmGlobalXCodeGenerator::CreateString(const char* s
)
431 cmXCodeObject
* obj
= this->CreateObject(cmXCodeObject::STRING
);
436 //----------------------------------------------------------------------------
437 cmXCodeObject
* cmGlobalXCodeGenerator
438 ::CreateObjectReference(cmXCodeObject
* ref
)
440 cmXCodeObject
* obj
= this->CreateObject(cmXCodeObject::OBJECT_REF
);
445 //----------------------------------------------------------------------------
446 cmStdString
GetGroupMapKey(cmTarget
& cmtarget
, cmSourceFile
* sf
)
448 cmStdString
key(cmtarget
.GetName());
450 key
+= sf
->GetFullPath();
454 //----------------------------------------------------------------------------
456 cmGlobalXCodeGenerator::CreateXCodeSourceFile(cmLocalGenerator
* lg
,
460 // Add flags from target and source file properties.
462 if(cmtarget
.GetProperty("COMPILE_FLAGS"))
464 lg
->AppendFlags(flags
, cmtarget
.GetProperty("COMPILE_FLAGS"));
466 lg
->AppendFlags(flags
, sf
->GetProperty("COMPILE_FLAGS"));
468 // Add per-source definitions.
469 this->AppendDefines(flags
, sf
->GetProperty("COMPILE_DEFINITIONS"), true);
471 // Using a map and the full path guarantees that we will always get the same
472 // fileRef object for any given full path.
474 cmXCodeObject
* fileRef
= this->CreateXCodeFileReference(sf
, cmtarget
);
476 cmXCodeObject
* buildFile
= this->CreateObject(cmXCodeObject::PBXBuildFile
);
477 buildFile
->SetComment(fileRef
->GetComment());
478 buildFile
->AddAttribute("fileRef", this->CreateObjectReference(fileRef
));
480 cmXCodeObject
* settings
=
481 this->CreateObject(cmXCodeObject::ATTRIBUTE_GROUP
);
482 settings
->AddAttribute("COMPILER_FLAGS", this->CreateString(flags
.c_str()));
484 // Is this a resource file in this target? Add it to the resources group...
486 cmTarget::SourceFileFlags tsFlags
= cmtarget
.GetTargetSourceFileFlags(sf
);
487 bool isResource
= (tsFlags
.Type
== cmTarget::SourceFileTypeResource
);
489 // Is this a "private" or "public" framework header file?
490 // Set the ATTRIBUTES attribute appropriately...
492 if(cmtarget
.IsFrameworkOnApple())
494 if(tsFlags
.Type
== cmTarget::SourceFileTypePrivateHeader
)
496 cmXCodeObject
* attrs
= this->CreateObject(cmXCodeObject::OBJECT_LIST
);
497 attrs
->AddObject(this->CreateString("Private"));
498 settings
->AddAttribute("ATTRIBUTES", attrs
);
501 else if(tsFlags
.Type
== cmTarget::SourceFileTypePublicHeader
)
503 cmXCodeObject
* attrs
= this->CreateObject(cmXCodeObject::OBJECT_LIST
);
504 attrs
->AddObject(this->CreateString("Public"));
505 settings
->AddAttribute("ATTRIBUTES", attrs
);
510 // Add the fileRef to the top level Resources group/folder if it is not
513 if(isResource
&& this->ResourcesGroupChildren
&&
514 !this->ResourcesGroupChildren
->HasObject(fileRef
))
516 this->ResourcesGroupChildren
->AddObject(fileRef
);
519 buildFile
->AddAttribute("settings", settings
);
523 //----------------------------------------------------------------------------
525 cmGlobalXCodeGenerator::CreateXCodeFileReference(cmSourceFile
* sf
,
528 std::string fname
= sf
->GetFullPath();
529 cmXCodeObject
* fileRef
= this->FileRefs
[fname
];
532 fileRef
= this->CreateObject(cmXCodeObject::PBXFileReference
);
533 std::string comment
= fname
;
535 //std::string gname = group->GetObject("name")->GetString();
536 //comment += gname.substr(1, gname.size()-2);
537 fileRef
->SetComment(fname
.c_str());
538 this->FileRefs
[fname
] = fileRef
;
540 cmStdString key
= GetGroupMapKey(cmtarget
, sf
);
541 cmXCodeObject
* group
= this->GroupMap
[key
];
542 cmXCodeObject
* children
= group
->GetObject("children");
543 if (!children
->HasObject(fileRef
))
545 children
->AddObject(fileRef
);
547 fileRef
->AddAttribute("fileEncoding", this->CreateString("4"));
550 this->CurrentLocalGenerator
->GetSourceFileLanguage(*sf
);
551 std::string sourcecode
= "sourcecode";
552 std::string ext
= sf
->GetExtension();
553 ext
= cmSystemTools::LowerCase(ext
);
557 sourcecode
= "compiled.mach-o.objfile";
559 else if(ext
== "xib")
561 sourcecode
= "file.xib";
565 sourcecode
+= ".cpp.objcpp";
569 sourcecode
+= ".c.objc";
571 else if(ext
== "plist")
573 sourcecode
+= ".text.plist";
575 else if(ext
== "h" || ext
== "hxx" || ext
== "hpp")
577 const char* linkLanguage
= cmtarget
.GetLinkerLanguage(this);
578 if(linkLanguage
&& (std::string(linkLanguage
) == "CXX"))
580 sourcecode
+= ".cpp.h";
584 sourcecode
+= ".c.h";
587 else if(lang
&& strcmp(lang
, "CXX") == 0)
589 sourcecode
+= ".cpp.cpp";
591 else if(lang
&& strcmp(lang
, "C") == 0)
593 sourcecode
+= ".c.c";
595 else if(ext
== "txt")
597 sourcecode
+= ".text";
601 // // Already specialized above or we leave sourcecode == "sourcecode"
602 // // which is probably the most correct choice. Extensionless headers,
603 // // for example... Or file types unknown to Xcode that do not map to a
604 // // valid lastKnownFileType value.
607 fileRef
->AddAttribute("lastKnownFileType",
608 this->CreateString(sourcecode
.c_str()));
611 this->ConvertToRelativeForXCode(sf
->GetFullPath().c_str());
614 cmSystemTools::SplitProgramPath(sf
->GetFullPath().c_str(),
617 fileRef
->AddAttribute("name", this->CreateString(file
.c_str()));
618 fileRef
->AddAttribute("path", this->CreateString(path
.c_str()));
619 if(this->XcodeVersion
== 15)
621 fileRef
->AddAttribute("refType", this->CreateString("4"));
623 if(path
.size() > 1 && path
[0] == '.' && path
[1] == '.')
625 fileRef
->AddAttribute("sourceTree", this->CreateString("<group>"));
629 fileRef
->AddAttribute("sourceTree", this->CreateString("<absolute>"));
635 //----------------------------------------------------------------------------
636 bool cmGlobalXCodeGenerator::SpecialTargetEmitted(std::string
const& tname
)
638 if(tname
== "ALL_BUILD" || tname
== "XCODE_DEPEND_HELPER" ||
639 tname
== "install" || tname
== "package" || tname
== "RUN_TESTS" )
641 if(this->TargetDoneSet
.find(tname
) != this->TargetDoneSet
.end())
645 this->TargetDoneSet
.insert(tname
);
651 //----------------------------------------------------------------------------
652 void cmGlobalXCodeGenerator::SetCurrentLocalGenerator(cmLocalGenerator
* gen
)
654 this->CurrentLocalGenerator
= gen
;
655 this->CurrentMakefile
= gen
->GetMakefile();
657 cmSystemTools::CollapseFullPath(this->CurrentMakefile
->
658 GetCurrentOutputDirectory());
659 cmSystemTools::SplitPath(outdir
.c_str(),
660 this->CurrentOutputDirectoryComponents
);
662 // Select the current set of configuration types.
663 this->CurrentConfigurationTypes
.clear();
664 if(this->XcodeVersion
> 20)
666 if(const char* types
=
667 this->CurrentMakefile
->GetDefinition("CMAKE_CONFIGURATION_TYPES"))
669 cmSystemTools::ExpandListArgument(types
,
670 this->CurrentConfigurationTypes
);
673 if(this->CurrentConfigurationTypes
.empty())
675 if(const char* buildType
=
676 this->CurrentMakefile
->GetDefinition("CMAKE_BUILD_TYPE"))
678 this->CurrentConfigurationTypes
.push_back(buildType
);
682 this->CurrentConfigurationTypes
.push_back("");
687 //----------------------------------------------------------------------------
689 cmGlobalXCodeGenerator::CreateXCodeTargets(cmLocalGenerator
* gen
,
690 std::vector
<cmXCodeObject
*>&
693 this->SetCurrentLocalGenerator(gen
);
694 cmTargets
&tgts
= this->CurrentMakefile
->GetTargets();
695 for(cmTargets::iterator l
= tgts
.begin(); l
!= tgts
.end(); l
++)
697 cmTarget
& cmtarget
= l
->second
;
699 // make sure ALL_BUILD, INSTALL, etc are only done once
700 if(this->SpecialTargetEmitted(l
->first
.c_str()))
705 if(cmtarget
.GetType() == cmTarget::UTILITY
||
706 cmtarget
.GetType() == cmTarget::GLOBAL_TARGET
)
708 targets
.push_back(this->CreateUtilityTarget(cmtarget
));
712 // organize the sources
713 std::vector
<cmSourceFile
*> const &classes
= cmtarget
.GetSourceFiles();
714 std::vector
<cmXCodeObject
*> externalObjFiles
;
715 std::vector
<cmXCodeObject
*> headerFiles
;
716 std::vector
<cmXCodeObject
*> resourceFiles
;
717 std::vector
<cmXCodeObject
*> sourceFiles
;
718 for(std::vector
<cmSourceFile
*>::const_iterator i
= classes
.begin();
719 i
!= classes
.end(); ++i
)
722 this->CreateXCodeSourceFile(this->CurrentLocalGenerator
,
724 cmXCodeObject
* fr
= xsf
->GetObject("fileRef");
725 cmXCodeObject
* filetype
=
726 fr
->GetObject()->GetObject("lastKnownFileType");
728 cmTarget::SourceFileFlags tsFlags
=
729 cmtarget
.GetTargetSourceFileFlags(*i
);
731 if(strcmp(filetype
->GetString(), "compiled.mach-o.objfile") == 0)
733 externalObjFiles
.push_back(xsf
);
735 else if(this->IsHeaderFile(*i
) ||
736 (tsFlags
.Type
== cmTarget::SourceFileTypePrivateHeader
) ||
737 (tsFlags
.Type
== cmTarget::SourceFileTypePublicHeader
))
739 headerFiles
.push_back(xsf
);
741 else if(tsFlags
.Type
== cmTarget::SourceFileTypeResource
)
743 resourceFiles
.push_back(xsf
);
745 else if(!(*i
)->GetPropertyAsBool("HEADER_FILE_ONLY"))
747 // Include this file in the build if it has a known language
748 // and has not been listed as an ignored extension for this
750 if(this->CurrentLocalGenerator
->GetSourceFileLanguage(**i
) &&
751 !this->IgnoreFile((*i
)->GetExtension().c_str()))
753 sourceFiles
.push_back(xsf
);
758 // some build phases only apply to bundles and/or frameworks
759 bool isFrameworkTarget
= cmtarget
.IsFrameworkOnApple();
760 bool isBundleTarget
= cmtarget
.GetPropertyAsBool("MACOSX_BUNDLE");
762 cmXCodeObject
* buildFiles
= 0;
764 // create source build phase
765 cmXCodeObject
* sourceBuildPhase
= 0;
766 if (!sourceFiles
.empty())
769 this->CreateObject(cmXCodeObject::PBXSourcesBuildPhase
);
770 sourceBuildPhase
->SetComment("Sources");
771 sourceBuildPhase
->AddAttribute("buildActionMask",
772 this->CreateString("2147483647"));
773 buildFiles
= this->CreateObject(cmXCodeObject::OBJECT_LIST
);
774 for(std::vector
<cmXCodeObject
*>::iterator i
= sourceFiles
.begin();
775 i
!= sourceFiles
.end(); ++i
)
777 buildFiles
->AddObject(*i
);
779 sourceBuildPhase
->AddAttribute("files", buildFiles
);
780 sourceBuildPhase
->AddAttribute("runOnlyForDeploymentPostprocessing",
781 this->CreateString("0"));
784 // create header build phase - only for framework targets
785 cmXCodeObject
* headerBuildPhase
= 0;
786 if (!headerFiles
.empty() && isFrameworkTarget
)
789 this->CreateObject(cmXCodeObject::PBXHeadersBuildPhase
);
790 headerBuildPhase
->SetComment("Headers");
791 headerBuildPhase
->AddAttribute("buildActionMask",
792 this->CreateString("2147483647"));
793 buildFiles
= this->CreateObject(cmXCodeObject::OBJECT_LIST
);
794 for(std::vector
<cmXCodeObject
*>::iterator i
= headerFiles
.begin();
795 i
!= headerFiles
.end(); ++i
)
797 buildFiles
->AddObject(*i
);
799 headerBuildPhase
->AddAttribute("files", buildFiles
);
800 headerBuildPhase
->AddAttribute("runOnlyForDeploymentPostprocessing",
801 this->CreateString("0"));
804 // create resource build phase - only for framework or bundle targets
805 cmXCodeObject
* resourceBuildPhase
= 0;
806 if (!resourceFiles
.empty() && (isFrameworkTarget
|| isBundleTarget
))
809 this->CreateObject(cmXCodeObject::PBXResourcesBuildPhase
);
810 resourceBuildPhase
->SetComment("Resources");
811 resourceBuildPhase
->AddAttribute("buildActionMask",
812 this->CreateString("2147483647"));
813 buildFiles
= this->CreateObject(cmXCodeObject::OBJECT_LIST
);
814 for(std::vector
<cmXCodeObject
*>::iterator i
= resourceFiles
.begin();
815 i
!= resourceFiles
.end(); ++i
)
817 buildFiles
->AddObject(*i
);
819 resourceBuildPhase
->AddAttribute("files", buildFiles
);
820 resourceBuildPhase
->AddAttribute("runOnlyForDeploymentPostprocessing",
821 this->CreateString("0"));
824 // create vector of "non-resource content file" build phases - only for
825 // framework or bundle targets
826 std::vector
<cmXCodeObject
*> contentBuildPhases
;
827 if (isFrameworkTarget
|| isBundleTarget
)
829 typedef std::map
<cmStdString
, std::vector
<cmSourceFile
*> >
830 mapOfVectorOfSourceFiles
;
831 mapOfVectorOfSourceFiles bundleFiles
;
832 for(std::vector
<cmSourceFile
*>::const_iterator i
= classes
.begin();
833 i
!= classes
.end(); ++i
)
835 cmTarget::SourceFileFlags tsFlags
=
836 cmtarget
.GetTargetSourceFileFlags(*i
);
837 if(tsFlags
.Type
== cmTarget::SourceFileTypeMacContent
)
839 bundleFiles
[tsFlags
.MacFolder
].push_back(*i
);
842 mapOfVectorOfSourceFiles::iterator mit
;
843 for ( mit
= bundleFiles
.begin(); mit
!= bundleFiles
.end(); ++ mit
)
845 cmXCodeObject
* copyFilesBuildPhase
=
846 this->CreateObject(cmXCodeObject::PBXCopyFilesBuildPhase
);
847 copyFilesBuildPhase
->SetComment("Copy files");
848 copyFilesBuildPhase
->AddAttribute("buildActionMask",
849 this->CreateString("2147483647"));
850 copyFilesBuildPhase
->AddAttribute("dstSubfolderSpec",
851 this->CreateString("6"));
852 cmOStringStream ostr
;
853 if (cmtarget
.IsFrameworkOnApple())
855 // dstPath in frameworks is relative to Versions/<version>
858 else if ( mit
->first
!= "MacOS" )
860 // dstPath in bundles is relative to Contents/MacOS
861 ostr
<< "../" << mit
->first
.c_str();
863 copyFilesBuildPhase
->AddAttribute("dstPath",
864 this->CreateString(ostr
.str().c_str()));
865 copyFilesBuildPhase
->AddAttribute(
866 "runOnlyForDeploymentPostprocessing", this->CreateString("0"));
867 buildFiles
= this->CreateObject(cmXCodeObject::OBJECT_LIST
);
868 copyFilesBuildPhase
->AddAttribute("files", buildFiles
);
869 std::vector
<cmSourceFile
*>::iterator sfIt
;
870 for ( sfIt
= mit
->second
.begin(); sfIt
!= mit
->second
.end(); ++ sfIt
)
873 this->CreateXCodeSourceFile(this->CurrentLocalGenerator
,
875 buildFiles
->AddObject(xsf
);
877 contentBuildPhases
.push_back(copyFilesBuildPhase
);
881 // create framework build phase
882 cmXCodeObject
* frameworkBuildPhase
= 0;
883 if (!externalObjFiles
.empty())
885 frameworkBuildPhase
=
886 this->CreateObject(cmXCodeObject::PBXFrameworksBuildPhase
);
887 frameworkBuildPhase
->SetComment("Frameworks");
888 frameworkBuildPhase
->AddAttribute("buildActionMask",
889 this->CreateString("2147483647"));
890 buildFiles
= this->CreateObject(cmXCodeObject::OBJECT_LIST
);
891 frameworkBuildPhase
->AddAttribute("files", buildFiles
);
892 for(std::vector
<cmXCodeObject
*>::iterator i
= externalObjFiles
.begin();
893 i
!= externalObjFiles
.end(); ++i
)
895 buildFiles
->AddObject(*i
);
897 frameworkBuildPhase
->AddAttribute("runOnlyForDeploymentPostprocessing",
898 this->CreateString("0"));
901 // create list of build phases and create the XCode target
902 cmXCodeObject
* buildPhases
=
903 this->CreateObject(cmXCodeObject::OBJECT_LIST
);
905 this->CreateCustomCommands(buildPhases
, sourceBuildPhase
,
906 headerBuildPhase
, resourceBuildPhase
,
908 frameworkBuildPhase
, cmtarget
);
910 targets
.push_back(this->CreateXCodeTarget(cmtarget
, buildPhases
));
914 //----------------------------------------------------------------------------
915 bool cmGlobalXCodeGenerator::IsHeaderFile(cmSourceFile
* sf
)
917 const std::vector
<std::string
>& hdrExts
=
918 this->CurrentMakefile
->GetHeaderExtensions();
919 return (std::find(hdrExts
.begin(), hdrExts
.end(), sf
->GetExtension()) !=
923 //----------------------------------------------------------------------------
925 cmGlobalXCodeGenerator::CreateBuildPhase(const char* name
,
928 const std::vector
<cmCustomCommand
>&
931 if(commands
.size() == 0 && strcmp(name
, "CMake ReRun") != 0)
935 cmXCodeObject
* buildPhase
=
936 this->CreateObject(cmXCodeObject::PBXShellScriptBuildPhase
);
937 buildPhase
->AddAttribute("buildActionMask",
938 this->CreateString("2147483647"));
939 cmXCodeObject
* buildFiles
= this->CreateObject(cmXCodeObject::OBJECT_LIST
);
940 buildPhase
->AddAttribute("files", buildFiles
);
941 buildPhase
->AddAttribute("name",
942 this->CreateString(name
));
943 buildPhase
->AddAttribute("runOnlyForDeploymentPostprocessing",
944 this->CreateString("0"));
945 buildPhase
->AddAttribute("shellPath",
946 this->CreateString("/bin/sh"));
947 this->AddCommandsToBuildPhase(buildPhase
, cmtarget
, commands
,
952 //----------------------------------------------------------------------------
953 void cmGlobalXCodeGenerator::CreateCustomCommands(cmXCodeObject
* buildPhases
,
960 std::vector
<cmXCodeObject
*>
966 std::vector
<cmCustomCommand
> const & prebuild
967 = cmtarget
.GetPreBuildCommands();
968 std::vector
<cmCustomCommand
> const & prelink
969 = cmtarget
.GetPreLinkCommands();
970 std::vector
<cmCustomCommand
> const & postbuild
971 = cmtarget
.GetPostBuildCommands();
972 std::vector
<cmSourceFile
*>const &classes
= cmtarget
.GetSourceFiles();
973 // add all the sources
974 std::vector
<cmCustomCommand
> commands
;
975 for(std::vector
<cmSourceFile
*>::const_iterator i
= classes
.begin();
976 i
!= classes
.end(); ++i
)
978 if((*i
)->GetCustomCommand())
980 commands
.push_back(*(*i
)->GetCustomCommand());
983 std::vector
<cmCustomCommand
> reruncom
;
984 cmXCodeObject
* cmakeReRunPhase
=
985 this->CreateBuildPhase("CMake ReRun", "cmakeReRunPhase",
987 buildPhases
->AddObject(cmakeReRunPhase
);
988 // create prebuild phase
989 cmXCodeObject
* cmakeRulesBuildPhase
=
990 this->CreateBuildPhase("CMake Rules",
991 "cmakeRulesBuildPhase",
993 // create prebuild phase
994 cmXCodeObject
* preBuildPhase
=
995 this->CreateBuildPhase("CMake PreBuild Rules", "preBuildCommands",
997 // create prelink phase
998 cmXCodeObject
* preLinkPhase
=
999 this->CreateBuildPhase("CMake PreLink Rules", "preLinkCommands",
1001 // create postbuild phase
1002 cmXCodeObject
* postBuildPhase
=
1003 this->CreateBuildPhase("CMake PostBuild Rules", "postBuildPhase",
1004 cmtarget
, postbuild
);
1006 // The order here is the order they will be built in.
1007 // The order "headers, resources, sources" mimics a native project generated
1008 // from an xcode template...
1012 buildPhases
->AddObject(preBuildPhase
);
1014 if(cmakeRulesBuildPhase
)
1016 buildPhases
->AddObject(cmakeRulesBuildPhase
);
1018 if(headerBuildPhase
)
1020 buildPhases
->AddObject(headerBuildPhase
);
1022 if(resourceBuildPhase
)
1024 buildPhases
->AddObject(resourceBuildPhase
);
1026 std::vector
<cmXCodeObject
*>::iterator cit
;
1027 for (cit
= contentBuildPhases
.begin(); cit
!= contentBuildPhases
.end();
1030 buildPhases
->AddObject(*cit
);
1032 if(sourceBuildPhase
)
1034 buildPhases
->AddObject(sourceBuildPhase
);
1038 buildPhases
->AddObject(preLinkPhase
);
1040 if(frameworkBuildPhase
)
1042 buildPhases
->AddObject(frameworkBuildPhase
);
1046 buildPhases
->AddObject(postBuildPhase
);
1050 //----------------------------------------------------------------------------
1051 std::string
cmGlobalXCodeGenerator::ExtractFlag(const char* flag
,
1054 std::string retFlag
;
1055 std::string::size_type pos
= flags
.find(flag
);
1056 if(pos
!= flags
.npos
&& (pos
==0 || flags
[pos
-1]==' '))
1058 while(pos
< flags
.size() && flags
[pos
] != ' ')
1060 retFlag
+= flags
[pos
];
1068 //----------------------------------------------------------------------------
1070 cmGlobalXCodeGenerator::AddCommandsToBuildPhase(cmXCodeObject
* buildphase
,
1072 std::vector
<cmCustomCommand
>
1076 if(strcmp(name
, "cmakeReRunPhase") == 0)
1078 std::string cdir
= this->CurrentMakefile
->GetHomeOutputDirectory();
1079 cdir
= this->ConvertToRelativeForMake(cdir
.c_str());
1080 std::string makecmd
= "make -C ";
1084 this->ConvertToRelativeForMake(this->CurrentReRunCMakeMakefile
.c_str());
1085 cmSystemTools::ReplaceString(makecmd
, "\\ ", "\\\\ ");
1086 buildphase
->AddAttribute("shellScript",
1087 this->CreateString(makecmd
.c_str()));
1091 // collect multiple outputs of custom commands into a set
1092 // which will be used for every configuration
1093 std::map
<cmStdString
, cmStdString
> multipleOutputPairs
;
1094 for(std::vector
<cmCustomCommand
>::const_iterator i
= commands
.begin();
1095 i
!= commands
.end(); ++i
)
1097 cmCustomCommand
const& cc
= *i
;
1098 if(!cc
.GetCommandLines().empty())
1100 const std::vector
<std::string
>& outputs
= cc
.GetOutputs();
1101 if(!outputs
.empty())
1103 // If there are more than one outputs treat the
1104 // first as the primary output and make the rest depend on it.
1105 std::vector
<std::string
>::const_iterator o
= outputs
.begin();
1106 std::string primaryOutput
= this->ConvertToRelativeForMake(o
->c_str());
1107 for(++o
; o
!= outputs
.end(); ++o
)
1109 std::string currentOutput
=this->ConvertToRelativeForMake(o
->c_str());
1110 multipleOutputPairs
[currentOutput
] = primaryOutput
;
1116 std::string dir
= this->CurrentMakefile
->GetCurrentOutputDirectory();
1117 dir
+= "/CMakeScripts";
1118 cmSystemTools::MakeDirectory(dir
.c_str());
1119 std::string makefile
= dir
;
1121 makefile
+= target
.GetName();
1124 makefile
+= ".make";
1126 for (std::vector
<std::string
>::const_iterator currentConfig
=
1127 this->CurrentConfigurationTypes
.begin();
1128 currentConfig
!=this->CurrentConfigurationTypes
.end();
1131 this->CreateCustomRulesMakefile(makefile
.c_str(),
1134 currentConfig
->c_str(),
1135 multipleOutputPairs
);
1138 std::string cdir
= this->CurrentMakefile
->GetCurrentOutputDirectory();
1139 cdir
= this->ConvertToRelativeForXCode(cdir
.c_str());
1140 std::string makecmd
= "make -C ";
1143 makecmd
+= this->ConvertToRelativeForMake(
1144 (makefile
+"$CONFIGURATION").c_str());
1145 if(!multipleOutputPairs
.empty())
1147 makecmd
+= " cmake_check_multiple_outputs";
1150 cmSystemTools::ReplaceString(makecmd
, "\\ ", "\\\\ ");
1151 buildphase
->AddAttribute("shellScript",
1152 this->CreateString(makecmd
.c_str()));
1155 //----------------------------------------------------------------------------
1156 void cmGlobalXCodeGenerator
1157 ::CreateCustomRulesMakefile(const char* makefileBasename
,
1159 std::vector
<cmCustomCommand
>
1161 const char* configName
,
1162 const std::map
<cmStdString
,
1163 cmStdString
>& multipleOutputPairs
1166 std::string makefileName
=makefileBasename
;
1167 makefileName
+=configName
;
1168 cmGeneratedFileStream
makefileStream(makefileName
.c_str());
1173 makefileStream
.SetCopyIfDifferent(true);
1174 makefileStream
<< "# Generated by CMake, DO NOT EDIT\n";
1175 makefileStream
<< "# Custom rules for " << target
.GetName() << "\n";
1177 // have all depend on all outputs
1178 makefileStream
<< "all: ";
1179 std::map
<const cmCustomCommand
*, cmStdString
> tname
;
1181 for(std::vector
<cmCustomCommand
>::const_iterator i
= commands
.begin();
1182 i
!= commands
.end(); ++i
)
1184 cmCustomCommand
const& cc
= *i
;
1185 if(!cc
.GetCommandLines().empty())
1187 const std::vector
<std::string
>& outputs
= cc
.GetOutputs();
1188 if(!outputs
.empty())
1190 for(std::vector
<std::string
>::const_iterator o
= outputs
.begin();
1191 o
!= outputs
.end(); ++o
)
1194 << "\\\n\t" << this->ConvertToRelativeForMake(o
->c_str());
1199 cmOStringStream str
;
1200 str
<< "_buildpart_" << count
++ ;
1201 tname
[&cc
] = std::string(target
.GetName()) + str
.str();
1202 makefileStream
<< "\\\n\t" << tname
[&cc
];
1206 makefileStream
<< "\n\n";
1207 for(std::vector
<cmCustomCommand
>::const_iterator i
= commands
.begin();
1208 i
!= commands
.end(); ++i
)
1210 cmCustomCommand
const& cc
= *i
;
1211 if(!cc
.GetCommandLines().empty())
1213 bool escapeOldStyle
= cc
.GetEscapeOldStyle();
1214 bool escapeAllowMakeVars
= cc
.GetEscapeAllowMakeVars();
1215 makefileStream
<< "\n";
1216 const std::vector
<std::string
>& outputs
= cc
.GetOutputs();
1217 if(!outputs
.empty())
1219 // There is at least one output, start the rule for it
1220 std::string primary_output
=
1221 this->ConvertToRelativeForMake(outputs
.begin()->c_str());
1222 makefileStream
<< primary_output
<< ": ";
1226 // There are no outputs. Use the generated force rule name.
1227 makefileStream
<< tname
[&cc
] << ": ";
1229 for(std::vector
<std::string
>::const_iterator d
=
1230 cc
.GetDepends().begin();
1231 d
!= cc
.GetDepends().end(); ++d
)
1234 this->CurrentLocalGenerator
->GetRealDependency(d
->c_str(),
1236 makefileStream
<< "\\\n" << this
1237 ->ConvertToRelativeForMake(dep
.c_str());
1239 makefileStream
<< "\n";
1241 if(const char* comment
= cc
.GetComment())
1243 std::string echo_cmd
= "echo ";
1244 echo_cmd
+= (this->CurrentLocalGenerator
->
1245 EscapeForShell(comment
, escapeAllowMakeVars
));
1246 makefileStream
<< "\t" << echo_cmd
.c_str() << "\n";
1249 // Add each command line to the set of commands.
1250 for(cmCustomCommandLines::const_iterator cl
=
1251 cc
.GetCommandLines().begin();
1252 cl
!= cc
.GetCommandLines().end(); ++cl
)
1254 // Build the command line in a single string.
1255 const cmCustomCommandLine
& commandLine
= *cl
;
1256 std::string cmd2
= this->CurrentLocalGenerator
1257 ->GetRealLocation(commandLine
[0].c_str(), configName
);
1259 cmSystemTools::ReplaceString(cmd2
, "/./", "/");
1260 cmd2
= this->ConvertToRelativeForMake(cmd2
.c_str());
1262 if(cc
.GetWorkingDirectory())
1265 cmd
+= this->ConvertToRelativeForMake(cc
.GetWorkingDirectory());
1269 for(unsigned int j
=1; j
< commandLine
.size(); ++j
)
1274 cmd
+= (this->CurrentLocalGenerator
1275 ->EscapeForShellOldStyle(commandLine
[j
].c_str()));
1279 cmd
+= (this->CurrentLocalGenerator
->
1280 EscapeForShell(commandLine
[j
].c_str(),
1281 escapeAllowMakeVars
));
1284 makefileStream
<< "\t" << cmd
.c_str() << "\n";
1289 // Add rules to deal with multiple outputs of custom commands.
1290 if(!multipleOutputPairs
.empty())
1293 "\n# Dependencies of multiple outputs to their primary outputs \n";
1295 for(std::map
<cmStdString
, cmStdString
>::const_iterator o
=
1296 multipleOutputPairs
.begin(); o
!= multipleOutputPairs
.end(); ++o
)
1298 makefileStream
<< o
->first
<< ": " << o
->second
<< "\n";
1303 "cmake_check_multiple_outputs:\n";
1304 for(std::map
<cmStdString
, cmStdString
>::const_iterator o
=
1305 multipleOutputPairs
.begin(); o
!= multipleOutputPairs
.end(); ++o
)
1307 makefileStream
<< "\t@if [ ! -f "
1308 << o
->first
<< " ]; then rm -f "
1309 << o
->second
<< "; fi\n";
1314 //----------------------------------------------------------------------------
1315 void cmGlobalXCodeGenerator::CreateBuildSettings(cmTarget
& target
,
1316 cmXCodeObject
* buildSettings
,
1317 std::string
& fileType
,
1318 std::string
& productType
,
1319 std::string
& productName
,
1320 const char* configName
)
1323 std::string defFlags
;
1324 bool shared
= ((target
.GetType() == cmTarget::SHARED_LIBRARY
) ||
1325 (target
.GetType() == cmTarget::MODULE_LIBRARY
));
1327 const char* lang
= target
.GetLinkerLanguage(this);
1331 // for c++ projects get the c flags as well
1332 if(strcmp(lang
, "CXX") == 0)
1334 this->CurrentLocalGenerator
->AddLanguageFlags(cflags
, "C", configName
);
1335 this->CurrentLocalGenerator
->AddSharedFlags(cflags
, lang
, shared
);
1338 // Add language-specific flags.
1339 this->CurrentLocalGenerator
->AddLanguageFlags(flags
, lang
, configName
);
1341 // Add shared-library flags if needed.
1342 this->CurrentLocalGenerator
->AddSharedFlags(flags
, lang
, shared
);
1346 this->CurrentLocalGenerator
->
1347 AppendFlags(defFlags
,
1348 this->CurrentMakefile
->GetDefineFlags());
1350 // Add preprocessor definitions for this target and configuration.
1352 if(this->XcodeVersion
> 15)
1354 this->AppendDefines(ppDefs
, "CMAKE_INTDIR=\"$(CONFIGURATION)\"");
1356 if(const char* exportMacro
= target
.GetExportMacro())
1358 // Add the export symbol definition for shared library objects.
1359 this->AppendDefines(ppDefs
, exportMacro
);
1362 (ppDefs
, this->CurrentMakefile
->GetProperty("COMPILE_DEFINITIONS"));
1363 this->AppendDefines(ppDefs
, target
.GetProperty("COMPILE_DEFINITIONS"));
1366 std::string defVarName
= "COMPILE_DEFINITIONS_";
1367 defVarName
+= cmSystemTools::UpperCase(configName
);
1369 (ppDefs
, this->CurrentMakefile
->GetProperty(defVarName
.c_str()));
1370 this->AppendDefines(ppDefs
, target
.GetProperty(defVarName
.c_str()));
1372 buildSettings
->AddAttribute
1373 ("GCC_PREPROCESSOR_DEFINITIONS", this->CreateString(ppDefs
.c_str()));
1375 std::string extraLinkOptions
;
1376 if(target
.GetType() == cmTarget::EXECUTABLE
)
1379 this->CurrentMakefile
->GetRequiredDefinition("CMAKE_EXE_LINKER_FLAGS");
1381 if(target
.GetType() == cmTarget::SHARED_LIBRARY
)
1383 extraLinkOptions
= this->CurrentMakefile
->
1384 GetRequiredDefinition("CMAKE_SHARED_LINKER_FLAGS");
1386 if(target
.GetType() == cmTarget::MODULE_LIBRARY
)
1388 extraLinkOptions
= this->CurrentMakefile
->
1389 GetRequiredDefinition("CMAKE_MODULE_LINKER_FLAGS");
1392 const char* targetLinkFlags
= target
.GetProperty("LINK_FLAGS");
1395 extraLinkOptions
+= " ";
1396 extraLinkOptions
+= targetLinkFlags
;
1399 // The product name is the full name of the target for this configuration.
1400 productName
= target
.GetFullName(configName
);
1402 // Get the product name components.
1403 std::string pnprefix
;
1405 std::string pnsuffix
;
1406 target
.GetFullNameComponents(pnprefix
, pnbase
, pnsuffix
, configName
);
1408 // Store the product name for all target types.
1409 buildSettings
->AddAttribute("PRODUCT_NAME",
1410 this->CreateString(pnbase
.c_str()));
1412 // Set attributes to specify the proper name for the target.
1413 if(target
.GetType() == cmTarget::STATIC_LIBRARY
||
1414 target
.GetType() == cmTarget::SHARED_LIBRARY
||
1415 target
.GetType() == cmTarget::MODULE_LIBRARY
||
1416 target
.GetType() == cmTarget::EXECUTABLE
)
1418 std::string pndir
= target
.GetDirectory();
1419 buildSettings
->AddAttribute("SYMROOT",
1420 this->CreateString(pndir
.c_str()));
1421 buildSettings
->AddAttribute("EXECUTABLE_PREFIX",
1422 this->CreateString(pnprefix
.c_str()));
1423 buildSettings
->AddAttribute("EXECUTABLE_SUFFIX",
1424 this->CreateString(pnsuffix
.c_str()));
1427 // Handle settings for each target type.
1428 switch(target
.GetType())
1430 case cmTarget::STATIC_LIBRARY
:
1432 fileType
= "archive.ar";
1433 productType
= "com.apple.product-type.library.static";
1435 buildSettings
->AddAttribute("LIBRARY_STYLE",
1436 this->CreateString("STATIC"));
1440 case cmTarget::MODULE_LIBRARY
:
1442 buildSettings
->AddAttribute("LIBRARY_STYLE",
1443 this->CreateString("BUNDLE"));
1444 if(this->XcodeVersion
>= 22)
1446 fileType
= "compiled.mach-o.executable";
1447 productType
= "com.apple.product-type.tool";
1449 buildSettings
->AddAttribute("MACH_O_TYPE",
1450 this->CreateString("mh_bundle"));
1451 buildSettings
->AddAttribute("GCC_DYNAMIC_NO_PIC",
1452 this->CreateString("NO"));
1453 // Add the flags to create an executable.
1454 std::string createFlags
=
1455 this->LookupFlags("CMAKE_", lang
, "_LINK_FLAGS", "");
1456 if(!createFlags
.empty())
1458 extraLinkOptions
+= " ";
1459 extraLinkOptions
+= createFlags
;
1464 fileType
= "compiled.mach-o.dylib";
1465 productType
= "com.apple.product-type.library.dynamic";
1467 // Add the flags to create a module.
1468 std::string createFlags
=
1469 this->LookupFlags("CMAKE_SHARED_MODULE_CREATE_", lang
, "_FLAGS",
1471 if(!createFlags
.empty())
1473 extraLinkOptions
+= " ";
1474 extraLinkOptions
+= createFlags
;
1479 case cmTarget::SHARED_LIBRARY
:
1481 if(target
.GetPropertyAsBool("FRAMEWORK"))
1483 fileType
= "wrapper.framework";
1484 productType
= "com.apple.product-type.framework";
1486 std::string version
= target
.GetFrameworkVersion();
1487 buildSettings
->AddAttribute("FRAMEWORK_VERSION",
1488 this->CreateString(version
.c_str()));
1490 std::string plist
= this->ComputeInfoPListLocation(target
);
1491 // Xcode will create the final version of Info.plist at build time,
1492 // so let it replace the framework name. This avoids creating
1493 // a per-configuration Info.plist file.
1494 this->CurrentLocalGenerator
1495 ->GenerateFrameworkInfoPList(&target
, "$(EXECUTABLE_NAME)",
1498 this->ConvertToRelativeForXCode(plist
.c_str());
1499 buildSettings
->AddAttribute("INFOPLIST_FILE",
1500 this->CreateString(path
.c_str()));
1504 fileType
= "compiled.mach-o.dylib";
1505 productType
= "com.apple.product-type.library.dynamic";
1507 // Add the flags to create a shared library.
1508 std::string createFlags
=
1509 this->LookupFlags("CMAKE_SHARED_LIBRARY_CREATE_", lang
, "_FLAGS",
1511 if(!createFlags
.empty())
1513 extraLinkOptions
+= " ";
1514 extraLinkOptions
+= createFlags
;
1518 buildSettings
->AddAttribute("LIBRARY_STYLE",
1519 this->CreateString("DYNAMIC"));
1522 case cmTarget::EXECUTABLE
:
1524 fileType
= "compiled.mach-o.executable";
1526 // Add the flags to create an executable.
1527 std::string createFlags
=
1528 this->LookupFlags("CMAKE_", lang
, "_LINK_FLAGS", "");
1529 if(!createFlags
.empty())
1531 extraLinkOptions
+= " ";
1532 extraLinkOptions
+= createFlags
;
1535 // Handle bundles and normal executables separately.
1536 if(target
.GetPropertyAsBool("MACOSX_BUNDLE"))
1538 productType
= "com.apple.product-type.application";
1539 std::string plist
= this->ComputeInfoPListLocation(target
);
1540 // Xcode will create the final version of Info.plist at build time,
1541 // so let it replace the executable name. This avoids creating
1542 // a per-configuration Info.plist file.
1543 this->CurrentLocalGenerator
1544 ->GenerateAppleInfoPList(&target
, "$(EXECUTABLE_NAME)",
1547 this->ConvertToRelativeForXCode(plist
.c_str());
1548 buildSettings
->AddAttribute("INFOPLIST_FILE",
1549 this->CreateString(path
.c_str()));
1554 productType
= "com.apple.product-type.tool";
1561 if(this->XcodeVersion
>= 22)
1563 buildSettings
->AddAttribute("PREBINDING",
1564 this->CreateString("NO"));
1567 std::vector
<std::string
> includes
;
1568 this->CurrentLocalGenerator
->GetIncludeDirectories(includes
);
1570 std::set
<cmStdString
> emitted
;
1571 emitted
.insert("/System/Library/Frameworks");
1572 for(std::vector
<std::string
>::iterator i
= includes
.begin();
1573 i
!= includes
.end(); ++i
)
1575 if(this->NameResolvesToFramework(i
->c_str()))
1577 std::string frameworkDir
= *i
;
1578 frameworkDir
+= "/../";
1579 frameworkDir
= cmSystemTools::CollapseFullPath(frameworkDir
.c_str());
1580 if(emitted
.insert(frameworkDir
).second
)
1582 fdirs
+= this->XCodeEscapePath(frameworkDir
.c_str());
1588 std::string incpath
=
1589 this->XCodeEscapePath(i
->c_str());
1590 dirs
+= incpath
+ " ";
1593 std::vector
<std::string
>& frameworks
= target
.GetFrameworks();
1594 if(frameworks
.size())
1596 for(std::vector
<std::string
>::iterator fmIt
= frameworks
.begin();
1597 fmIt
!= frameworks
.end(); ++fmIt
)
1599 if(emitted
.insert(*fmIt
).second
)
1601 fdirs
+= this->XCodeEscapePath(fmIt
->c_str());
1608 buildSettings
->AddAttribute("FRAMEWORK_SEARCH_PATHS",
1609 this->CreateString(fdirs
.c_str()));
1613 buildSettings
->AddAttribute("HEADER_SEARCH_PATHS",
1614 this->CreateString(dirs
.c_str()));
1616 std::string oflagc
= this->ExtractFlag("-O", cflags
);
1620 if(oflagc
.size() == 3)
1622 optLevel
[0] = oflagc
[2];
1624 if(oflagc
.size() == 2)
1628 std::string oflag
= this->ExtractFlag("-O", flags
);
1629 if(oflag
.size() == 3)
1631 optLevel
[0] = oflag
[2];
1633 if(oflag
.size() == 2)
1637 std::string gflagc
= this->ExtractFlag("-g", cflags
);
1638 // put back gdwarf-2 if used since there is no way
1639 // to represent it in the gui, but we still want debug yes
1640 if(gflagc
== "-gdwarf-2")
1645 std::string gflag
= this->ExtractFlag("-g", flags
);
1646 if(gflag
== "-gdwarf-2")
1651 const char* debugStr
= "YES";
1652 if(gflagc
.size() ==0 && gflag
.size() == 0)
1657 buildSettings
->AddAttribute("GCC_GENERATE_DEBUGGING_SYMBOLS",
1658 this->CreateString(debugStr
));
1659 buildSettings
->AddAttribute("GCC_OPTIMIZATION_LEVEL",
1660 this->CreateString(optLevel
));
1661 buildSettings
->AddAttribute("GCC_SYMBOLS_PRIVATE_EXTERN",
1662 this->CreateString("NO"));
1663 buildSettings
->AddAttribute("GCC_INLINES_ARE_PRIVATE_EXTERN",
1664 this->CreateString("NO"));
1665 if(lang
&& strcmp(lang
, "CXX") == 0)
1669 buildSettings
->AddAttribute("OTHER_CPLUSPLUSFLAGS",
1670 this->CreateString(flags
.c_str()));
1673 buildSettings
->AddAttribute("OTHER_CFLAGS",
1674 this->CreateString(cflags
.c_str()));
1681 buildSettings
->AddAttribute("OTHER_CFLAGS",
1682 this->CreateString(flags
.c_str()));
1685 // Create the INSTALL_PATH attribute.
1686 std::string install_name_dir
;
1687 if(target
.GetType() == cmTarget::SHARED_LIBRARY
)
1689 // Get the install_name directory for the build tree.
1690 install_name_dir
= target
.GetInstallNameDirForBuildTree(configName
, true);
1691 if(install_name_dir
.empty())
1693 // Xcode will not pass the -install_name option at all if INSTALL_PATH
1694 // is not given or is empty. We must explicitly put the flag in the
1695 // link flags to create an install_name with just the library soname.
1696 extraLinkOptions
+= " -install_name ";
1697 extraLinkOptions
+= productName
;
1701 // Convert to a path for the native build tool.
1702 cmSystemTools::ConvertToUnixSlashes(install_name_dir
);
1703 // do not escape spaces on this since it is only a single path
1706 buildSettings
->AddAttribute("INSTALL_PATH",
1707 this->CreateString(install_name_dir
.c_str()));
1709 buildSettings
->AddAttribute("OTHER_LDFLAGS",
1710 this->CreateString(extraLinkOptions
.c_str()));
1711 buildSettings
->AddAttribute("OTHER_REZFLAGS",
1712 this->CreateString(""));
1713 buildSettings
->AddAttribute("SECTORDER_FLAGS",
1714 this->CreateString(""));
1715 buildSettings
->AddAttribute("USE_HEADERMAP",
1716 this->CreateString("NO"));
1717 buildSettings
->AddAttribute("WARNING_CFLAGS",
1719 "-Wmost -Wno-four-char-constants"
1720 " -Wno-unknown-pragmas"));
1722 // Runtime version information.
1723 if(target
.GetType() == cmTarget::SHARED_LIBRARY
)
1729 // VERSION -> current_version
1730 target
.GetTargetVersion(false, major
, minor
, patch
);
1731 if(major
== 0 && minor
== 0 && patch
== 0)
1733 // Xcode always wants at least 1.0.0
1737 v
<< major
<< "." << minor
<< "." << patch
;
1738 buildSettings
->AddAttribute("DYLIB_CURRENT_VERSION",
1739 this->CreateString(v
.str().c_str()));
1741 // SOVERSION -> compatibility_version
1742 target
.GetTargetVersion(true, major
, minor
, patch
);
1743 if(major
== 0 && minor
== 0 && patch
== 0)
1745 // Xcode always wants at least 1.0.0
1748 cmOStringStream vso
;
1749 vso
<< major
<< "." << minor
<< "." << patch
;
1750 buildSettings
->AddAttribute("DYLIB_COMPATIBILITY_VERSION",
1751 this->CreateString(vso
.str().c_str()));
1753 // put this last so it can override existing settings
1754 // Convert "XCODE_ATTRIBUTE_*" properties directly.
1756 cmPropertyMap
const& props
= target
.GetProperties();
1757 for(cmPropertyMap::const_iterator i
= props
.begin();
1758 i
!= props
.end(); ++i
)
1760 if(i
->first
.find("XCODE_ATTRIBUTE_") == 0)
1762 buildSettings
->AddAttribute(i
->first
.substr(16).c_str(),
1763 this->CreateString(i
->second
.GetValue()));
1769 //----------------------------------------------------------------------------
1771 cmGlobalXCodeGenerator::CreateUtilityTarget(cmTarget
& cmtarget
)
1773 cmXCodeObject
* shellBuildPhase
=
1774 this->CreateObject(cmXCodeObject::PBXShellScriptBuildPhase
);
1775 shellBuildPhase
->AddAttribute("buildActionMask",
1776 this->CreateString("2147483647"));
1777 cmXCodeObject
* buildFiles
= this->CreateObject(cmXCodeObject::OBJECT_LIST
);
1778 shellBuildPhase
->AddAttribute("files", buildFiles
);
1779 cmXCodeObject
* inputPaths
= this->CreateObject(cmXCodeObject::OBJECT_LIST
);
1780 shellBuildPhase
->AddAttribute("inputPaths", inputPaths
);
1781 cmXCodeObject
* outputPaths
= this->CreateObject(cmXCodeObject::OBJECT_LIST
);
1782 shellBuildPhase
->AddAttribute("outputPaths", outputPaths
);
1783 shellBuildPhase
->AddAttribute("runOnlyForDeploymentPostprocessing",
1784 this->CreateString("0"));
1785 shellBuildPhase
->AddAttribute("shellPath",
1786 this->CreateString("/bin/sh"));
1787 shellBuildPhase
->AddAttribute("shellScript",
1789 "# shell script goes here\nexit 0"));
1790 cmXCodeObject
* target
=
1791 this->CreateObject(cmXCodeObject::PBXAggregateTarget
);
1792 target
->SetComment(cmtarget
.GetName());
1793 cmXCodeObject
* buildPhases
=
1794 this->CreateObject(cmXCodeObject::OBJECT_LIST
);
1795 std::vector
<cmXCodeObject
*> emptyContentVector
;
1796 this->CreateCustomCommands(buildPhases
, 0, 0, 0, emptyContentVector
, 0,
1798 target
->AddAttribute("buildPhases", buildPhases
);
1799 cmXCodeObject
* buildSettings
=
1800 this->CreateObject(cmXCodeObject::ATTRIBUTE_GROUP
);
1801 std::string fileTypeString
;
1802 std::string productTypeString
;
1803 std::string productName
;
1804 const char* globalConfig
= 0;
1805 if(this->XcodeVersion
> 20)
1807 this->AddConfigurations(target
, cmtarget
);
1811 globalConfig
= this->CurrentMakefile
->GetDefinition("CMAKE_BUILD_TYPE");
1813 this->CreateBuildSettings(cmtarget
,
1814 buildSettings
, fileTypeString
,
1815 productTypeString
, productName
, globalConfig
);
1816 target
->AddAttribute("buildSettings", buildSettings
);
1817 cmXCodeObject
* dependencies
=
1818 this->CreateObject(cmXCodeObject::OBJECT_LIST
);
1819 target
->AddAttribute("dependencies", dependencies
);
1820 target
->AddAttribute("name", this->CreateString(productName
.c_str()));
1821 target
->AddAttribute("productName",this->CreateString(productName
.c_str()));
1822 target
->SetTarget(&cmtarget
);
1824 // Add source files without build rules for editing convenience.
1825 if(cmtarget
.GetType() == cmTarget::UTILITY
)
1827 std::vector
<cmSourceFile
*> const& sources
= cmtarget
.GetSourceFiles();
1828 for(std::vector
<cmSourceFile
*>::const_iterator i
= sources
.begin();
1829 i
!= sources
.end(); ++i
)
1831 if(!(*i
)->GetPropertyAsBool("GENERATED"))
1833 this->CreateXCodeFileReference(*i
, cmtarget
);
1841 //----------------------------------------------------------------------------
1842 void cmGlobalXCodeGenerator::AddConfigurations(cmXCodeObject
* target
,
1845 std::string configTypes
=
1846 this->CurrentMakefile
->GetRequiredDefinition("CMAKE_CONFIGURATION_TYPES");
1847 std::vector
<std::string
> configVectorIn
;
1848 std::vector
<std::string
> configVector
;
1849 configVectorIn
.push_back(configTypes
);
1850 cmSystemTools::ExpandList(configVectorIn
, configVector
);
1851 cmXCodeObject
* configlist
=
1852 this->CreateObject(cmXCodeObject::XCConfigurationList
);
1853 cmXCodeObject
* buildConfigurations
=
1854 this->CreateObject(cmXCodeObject::OBJECT_LIST
);
1855 configlist
->AddAttribute("buildConfigurations", buildConfigurations
);
1856 std::string comment
= "Build configuration list for ";
1857 comment
+= cmXCodeObject::PBXTypeNames
[target
->GetIsA()];
1859 comment
+= cmtarget
.GetName();
1861 configlist
->SetComment(comment
.c_str());
1862 target
->AddAttribute("buildConfigurationList",
1863 this->CreateObjectReference(configlist
));
1864 for(unsigned int i
= 0; i
< configVector
.size(); ++i
)
1866 cmXCodeObject
* config
=
1867 this->CreateObject(cmXCodeObject::XCBuildConfiguration
);
1868 buildConfigurations
->AddObject(config
);
1869 cmXCodeObject
* buildSettings
=
1870 this->CreateObject(cmXCodeObject::ATTRIBUTE_GROUP
);
1871 std::string fileTypeString
;
1872 std::string productTypeString
;
1873 std::string productName
;
1874 this->CreateBuildSettings(cmtarget
,
1875 buildSettings
, fileTypeString
,
1876 productTypeString
, productName
,
1877 configVector
[i
].c_str());
1878 config
->AddAttribute("name", this->CreateString(configVector
[i
].c_str()));
1879 config
->SetComment(configVector
[i
].c_str());
1880 config
->AddAttribute("buildSettings", buildSettings
);
1882 if(configVector
.size())
1884 configlist
->AddAttribute("defaultConfigurationName",
1885 this->CreateString(configVector
[0].c_str()));
1886 configlist
->AddAttribute("defaultConfigurationIsVisible",
1887 this->CreateString("0"));
1891 //----------------------------------------------------------------------------
1893 cmGlobalXCodeGenerator::CreateXCodeTarget(cmTarget
& cmtarget
,
1894 cmXCodeObject
* buildPhases
)
1896 cmXCodeObject
* target
=
1897 this->CreateObject(cmXCodeObject::PBXNativeTarget
);
1898 target
->AddAttribute("buildPhases", buildPhases
);
1899 cmXCodeObject
* buildRules
= this->CreateObject(cmXCodeObject::OBJECT_LIST
);
1900 target
->AddAttribute("buildRules", buildRules
);
1901 cmXCodeObject
* buildSettings
=
1902 this->CreateObject(cmXCodeObject::ATTRIBUTE_GROUP
);
1903 std::string fileTypeString
;
1904 std::string productTypeString
;
1905 std::string productName
;
1906 const char* globalConfig
= 0;
1907 if(this->XcodeVersion
> 20)
1909 this->AddConfigurations(target
, cmtarget
);
1913 globalConfig
= this->CurrentMakefile
->GetDefinition("CMAKE_BUILD_TYPE");
1915 this->CreateBuildSettings(cmtarget
,
1916 buildSettings
, fileTypeString
,
1917 productTypeString
, productName
, globalConfig
);
1918 target
->AddAttribute("buildSettings", buildSettings
);
1919 cmXCodeObject
* dependencies
=
1920 this->CreateObject(cmXCodeObject::OBJECT_LIST
);
1921 target
->AddAttribute("dependencies", dependencies
);
1922 target
->AddAttribute("name", this->CreateString(productName
.c_str()));
1923 target
->AddAttribute("productName",this->CreateString(productName
.c_str()));
1925 cmXCodeObject
* fileRef
=
1926 this->CreateObject(cmXCodeObject::PBXFileReference
);
1927 fileRef
->AddAttribute("explicitFileType",
1928 this->CreateString(fileTypeString
.c_str()));
1929 fileRef
->AddAttribute("path", this->CreateString(productName
.c_str()));
1930 fileRef
->AddAttribute("refType", this->CreateString("0"));
1931 fileRef
->AddAttribute("sourceTree",
1932 this->CreateString("BUILT_PRODUCTS_DIR"));
1933 fileRef
->SetComment(cmtarget
.GetName());
1934 target
->AddAttribute("productReference",
1935 this->CreateObjectReference(fileRef
));
1936 target
->AddAttribute("productType",
1937 this->CreateString(productTypeString
.c_str()));
1938 target
->SetTarget(&cmtarget
);
1942 //----------------------------------------------------------------------------
1943 cmXCodeObject
* cmGlobalXCodeGenerator::FindXCodeTarget(cmTarget
* t
)
1949 for(std::vector
<cmXCodeObject
*>::iterator i
= this->XCodeObjects
.begin();
1950 i
!= this->XCodeObjects
.end(); ++i
)
1952 cmXCodeObject
* o
= *i
;
1953 if(o
->GetTarget() == t
)
1961 //----------------------------------------------------------------------------
1962 void cmGlobalXCodeGenerator::AddDependTarget(cmXCodeObject
* target
,
1963 cmXCodeObject
* dependTarget
)
1965 // make sure a target does not depend on itself
1966 if(target
== dependTarget
)
1970 // now avoid circular references if dependTarget already
1971 // depends on target then skip it. Circular references crashes
1973 cmXCodeObject
* dependTargetDepends
=
1974 dependTarget
->GetObject("dependencies");
1975 if(dependTargetDepends
)
1977 if(dependTargetDepends
->HasObject(target
->GetPBXTargetDependency()))
1983 cmXCodeObject
* targetdep
= dependTarget
->GetPBXTargetDependency();
1986 cmXCodeObject
* container
=
1987 this->CreateObject(cmXCodeObject::PBXContainerItemProxy
);
1988 container
->SetComment("PBXContainerItemProxy");
1989 container
->AddAttribute("containerPortal",
1990 this->CreateObjectReference(this->RootObject
));
1991 container
->AddAttribute("proxyType", this->CreateString("1"));
1992 container
->AddAttribute("remoteGlobalIDString",
1993 this->CreateObjectReference(dependTarget
));
1994 container
->AddAttribute("remoteInfo",
1996 dependTarget
->GetTarget()->GetName()));
1998 this->CreateObject(cmXCodeObject::PBXTargetDependency
);
1999 targetdep
->SetComment("PBXTargetDependency");
2000 targetdep
->AddAttribute("target",
2001 this->CreateObjectReference(dependTarget
));
2002 targetdep
->AddAttribute("targetProxy",
2003 this->CreateObjectReference(container
));
2004 dependTarget
->SetPBXTargetDependency(targetdep
);
2007 cmXCodeObject
* depends
= target
->GetObject("dependencies");
2011 Error("target does not have dependencies attribute error..");
2016 depends
->AddUniqueObject(targetdep
);
2020 //----------------------------------------------------------------------------
2021 void cmGlobalXCodeGenerator::AppendOrAddBuildSetting(cmXCodeObject
* settings
,
2022 const char* attribute
,
2027 cmXCodeObject
* attr
= settings
->GetObject(attribute
);
2030 settings
->AddAttribute(attribute
, this->CreateString(value
));
2034 std::string oldValue
= attr
->GetString();
2037 attr
->SetString(oldValue
.c_str());
2042 //----------------------------------------------------------------------------
2043 void cmGlobalXCodeGenerator
2044 ::AppendBuildSettingAttribute(cmXCodeObject
* target
,
2045 const char* attribute
,
2047 const char* configName
)
2049 if(this->XcodeVersion
< 21)
2051 // There is only one configuration. Add the setting to the buildSettings
2053 this->AppendOrAddBuildSetting(target
->GetObject("buildSettings"),
2058 // There are multiple configurations. Add the setting to the
2059 // buildSettings of the configuration name given.
2060 cmXCodeObject
* configurationList
=
2061 target
->GetObject("buildConfigurationList")->GetObject();
2062 cmXCodeObject
* buildConfigs
=
2063 configurationList
->GetObject("buildConfigurations");
2064 std::vector
<cmXCodeObject
*> list
= buildConfigs
->GetObjectList();
2065 // each configuration and the target itself has a buildSettings in it
2066 //list.push_back(target);
2067 for(std::vector
<cmXCodeObject
*>::iterator i
= list
.begin();
2068 i
!= list
.end(); ++i
)
2072 if(strcmp((*i
)->GetObject("name")->GetString(), configName
) == 0)
2074 cmXCodeObject
* settings
= (*i
)->GetObject("buildSettings");
2075 this->AppendOrAddBuildSetting(settings
, attribute
, value
);
2080 cmXCodeObject
* settings
= (*i
)->GetObject("buildSettings");
2081 this->AppendOrAddBuildSetting(settings
, attribute
, value
);
2087 //----------------------------------------------------------------------------
2088 void cmGlobalXCodeGenerator
2089 ::AddDependAndLinkInformation(cmXCodeObject
* target
)
2091 cmTarget
* cmtarget
= target
->GetTarget();
2094 cmSystemTools::Error("Error no target on xobject\n");
2098 // Add dependencies on other CMake targets.
2099 TargetDependSet
const& deps
= this->GetTargetDirectDepends(*cmtarget
);
2100 for(TargetDependSet::const_iterator i
= deps
.begin(); i
!= deps
.end(); ++i
)
2102 if(cmXCodeObject
* dptarget
= this->FindXCodeTarget(*i
))
2104 this->AddDependTarget(target
, dptarget
);
2108 // Skip link information for static libraries.
2109 if(cmtarget
->GetType() == cmTarget::STATIC_LIBRARY
)
2114 // Loop over configuration types and set per-configuration info.
2115 for(std::vector
<std::string
>::iterator i
=
2116 this->CurrentConfigurationTypes
.begin();
2117 i
!= this->CurrentConfigurationTypes
.end(); ++i
)
2119 // Get the current configuration name.
2120 const char* configName
= i
->c_str();
2126 // Compute the link library and directory information.
2127 cmComputeLinkInformation
* pcli
= cmtarget
->GetLinkInformation(configName
);
2132 cmComputeLinkInformation
& cli
= *pcli
;
2134 // Add dependencies directly on library files.
2136 std::vector
<std::string
> const& libDeps
= cli
.GetDepends();
2137 for(std::vector
<std::string
>::const_iterator j
= libDeps
.begin();
2138 j
!= libDeps
.end(); ++j
)
2140 target
->AddDependLibrary(configName
, j
->c_str());
2144 // add the library search paths
2146 std::vector
<std::string
> const& libDirs
= cli
.GetDirectories();
2147 std::string linkDirs
;
2148 for(std::vector
<std::string
>::const_iterator libDir
= libDirs
.begin();
2149 libDir
!= libDirs
.end(); ++libDir
)
2151 if(libDir
->size() && *libDir
!= "/usr/lib")
2153 if(this->XcodeVersion
> 15)
2155 // now add the same one but append $(CONFIGURATION) to it:
2157 linkDirs
+= this->XCodeEscapePath(
2158 (*libDir
+ "/$(CONFIGURATION)").c_str());
2161 linkDirs
+= this->XCodeEscapePath(libDir
->c_str());
2164 this->AppendBuildSettingAttribute(target
, "LIBRARY_SEARCH_PATHS",
2165 linkDirs
.c_str(), configName
);
2168 // add the framework search paths
2170 const char* sep
= "";
2172 std::vector
<std::string
> const& fwDirs
= cli
.GetFrameworkPaths();
2173 for(std::vector
<std::string
>::const_iterator fdi
= fwDirs
.begin();
2174 fdi
!= fwDirs
.end(); ++fdi
)
2178 fdirs
+= this->XCodeEscapePath(fdi
->c_str());
2182 this->AppendBuildSettingAttribute(target
, "FRAMEWORK_SEARCH_PATHS",
2183 fdirs
.c_str(), configName
);
2187 // now add the link libraries
2189 std::string linkLibs
;
2190 const char* sep
= "";
2191 typedef cmComputeLinkInformation::ItemVector ItemVector
;
2192 ItemVector
const& libNames
= cli
.GetItems();
2193 for(ItemVector::const_iterator li
= libNames
.begin();
2194 li
!= libNames
.end(); ++li
)
2200 linkLibs
+= this->XCodeEscapePath(li
->Value
.c_str());
2204 linkLibs
+= li
->Value
;
2207 this->AppendBuildSettingAttribute(target
, "OTHER_LDFLAGS",
2208 linkLibs
.c_str(), configName
);
2213 //----------------------------------------------------------------------------
2214 void cmGlobalXCodeGenerator::CreateGroups(cmLocalGenerator
* root
,
2215 std::vector
<cmLocalGenerator
*>&
2218 for(std::vector
<cmLocalGenerator
*>::iterator i
= generators
.begin();
2219 i
!= generators
.end(); ++i
)
2221 if(this->IsExcluded(root
, *i
))
2225 cmMakefile
* mf
= (*i
)->GetMakefile();
2226 std::vector
<cmSourceGroup
> sourceGroups
= mf
->GetSourceGroups();
2227 cmTargets
&tgts
= mf
->GetTargets();
2228 for(cmTargets::iterator l
= tgts
.begin(); l
!= tgts
.end(); l
++)
2230 cmTarget
& cmtarget
= l
->second
;
2232 // Same skipping logic here as in CreateXCodeTargets so that we do not
2233 // end up with (empty anyhow) ALL_BUILD and XCODE_DEPEND_HELPER source
2236 if(cmtarget
.GetType() == cmTarget::GLOBAL_TARGET
)
2241 // add the soon to be generated Info.plist file as a source for a
2242 // MACOSX_BUNDLE file
2243 if(cmtarget
.GetPropertyAsBool("MACOSX_BUNDLE"))
2245 std::string plist
= this->ComputeInfoPListLocation(cmtarget
);
2246 cmSourceFile
* sf
= mf
->GetOrCreateSource(plist
.c_str(), true);
2247 cmtarget
.AddSourceFile(sf
);
2250 std::vector
<cmSourceFile
*> classes
= cmtarget
.GetSourceFiles();
2252 for(std::vector
<cmSourceFile
*>::const_iterator s
= classes
.begin();
2253 s
!= classes
.end(); s
++)
2255 cmSourceFile
* sf
= *s
;
2256 // Add the file to the list of sources.
2257 std::string
const& source
= sf
->GetFullPath();
2258 cmSourceGroup
& sourceGroup
=
2259 mf
->FindSourceGroup(source
.c_str(), sourceGroups
);
2260 cmXCodeObject
* pbxgroup
=
2261 this->CreateOrGetPBXGroup(cmtarget
, &sourceGroup
);
2262 cmStdString key
= GetGroupMapKey(cmtarget
, sf
);
2263 this->GroupMap
[key
] = pbxgroup
;
2269 //----------------------------------------------------------------------------
2270 cmXCodeObject
* cmGlobalXCodeGenerator
2271 ::CreateOrGetPBXGroup(cmTarget
& cmtarget
, cmSourceGroup
* sg
)
2273 cmStdString s
= cmtarget
.GetName();
2276 std::map
<cmStdString
, cmXCodeObject
* >::iterator i
=
2277 this->GroupNameMap
.find(s
);
2278 if(i
!= this->GroupNameMap
.end())
2282 i
= this->TargetGroup
.find(cmtarget
.GetName());
2283 cmXCodeObject
* tgroup
= 0;
2284 if(i
!= this->TargetGroup
.end())
2290 tgroup
= this->CreateObject(cmXCodeObject::PBXGroup
);
2291 this->TargetGroup
[cmtarget
.GetName()] = tgroup
;
2292 cmXCodeObject
* tgroupChildren
=
2293 this->CreateObject(cmXCodeObject::OBJECT_LIST
);
2294 tgroup
->AddAttribute("name", this->CreateString(cmtarget
.GetName()));
2295 tgroup
->AddAttribute("children", tgroupChildren
);
2296 if(this->XcodeVersion
== 15)
2298 tgroup
->AddAttribute("refType", this->CreateString("4"));
2300 tgroup
->AddAttribute("sourceTree", this->CreateString("<group>"));
2301 this->SourcesGroupChildren
->AddObject(tgroup
);
2304 // If it's the default source group (empty name) then put the source file
2305 // directly in the tgroup...
2307 if (cmStdString(sg
->GetName()) == "")
2309 this->GroupNameMap
[s
] = tgroup
;
2313 cmXCodeObject
* tgroupChildren
= tgroup
->GetObject("children");
2314 cmXCodeObject
* group
= this->CreateObject(cmXCodeObject::PBXGroup
);
2315 cmXCodeObject
* groupChildren
=
2316 this->CreateObject(cmXCodeObject::OBJECT_LIST
);
2317 group
->AddAttribute("name", this->CreateString(sg
->GetName()));
2318 group
->AddAttribute("children", groupChildren
);
2319 if(this->XcodeVersion
== 15)
2321 group
->AddAttribute("refType", this->CreateString("4"));
2323 group
->AddAttribute("sourceTree", this->CreateString("<group>"));
2324 tgroupChildren
->AddObject(group
);
2325 this->GroupNameMap
[s
] = group
;
2329 //----------------------------------------------------------------------------
2330 void cmGlobalXCodeGenerator
2331 ::CreateXCodeObjects(cmLocalGenerator
* root
,
2332 std::vector
<cmLocalGenerator
*>&
2335 this->ClearXCodeObjects();
2336 this->RootObject
= 0;
2337 this->SourcesGroupChildren
= 0;
2338 this->ResourcesGroupChildren
= 0;
2339 this->MainGroupChildren
= 0;
2340 cmXCodeObject
* group
= this->CreateObject(cmXCodeObject::ATTRIBUTE_GROUP
);
2341 group
->AddAttribute("COPY_PHASE_STRIP", this->CreateString("NO"));
2342 cmXCodeObject
* developBuildStyle
=
2343 this->CreateObject(cmXCodeObject::PBXBuildStyle
);
2344 cmXCodeObject
* listObjs
= this->CreateObject(cmXCodeObject::OBJECT_LIST
);
2345 if(this->XcodeVersion
== 15)
2347 developBuildStyle
->AddAttribute("name",
2348 this->CreateString("Development"));
2349 developBuildStyle
->AddAttribute("buildSettings", group
);
2350 listObjs
->AddObject(developBuildStyle
);
2351 group
= this->CreateObject(cmXCodeObject::ATTRIBUTE_GROUP
);
2352 group
->AddAttribute("COPY_PHASE_STRIP", this->CreateString("YES"));
2353 cmXCodeObject
* deployBuildStyle
=
2354 this->CreateObject(cmXCodeObject::PBXBuildStyle
);
2355 deployBuildStyle
->AddAttribute("name", this->CreateString("Deployment"));
2356 deployBuildStyle
->AddAttribute("buildSettings", group
);
2357 listObjs
->AddObject(deployBuildStyle
);
2361 for(unsigned int i
= 0; i
< this->CurrentConfigurationTypes
.size(); ++i
)
2363 cmXCodeObject
* buildStyle
=
2364 this->CreateObject(cmXCodeObject::PBXBuildStyle
);
2365 const char* name
= this->CurrentConfigurationTypes
[i
].c_str();
2366 buildStyle
->AddAttribute("name", this->CreateString(name
));
2367 buildStyle
->SetComment(name
);
2368 cmXCodeObject
* sgroup
=
2369 this->CreateObject(cmXCodeObject::ATTRIBUTE_GROUP
);
2370 sgroup
->AddAttribute("COPY_PHASE_STRIP", this->CreateString("NO"));
2371 buildStyle
->AddAttribute("buildSettings", sgroup
);
2372 listObjs
->AddObject(buildStyle
);
2376 cmXCodeObject
* mainGroup
= this->CreateObject(cmXCodeObject::PBXGroup
);
2377 this->MainGroupChildren
=
2378 this->CreateObject(cmXCodeObject::OBJECT_LIST
);
2379 mainGroup
->AddAttribute("children", this->MainGroupChildren
);
2380 if(this->XcodeVersion
== 15)
2382 mainGroup
->AddAttribute("refType", this->CreateString("4"));
2384 mainGroup
->AddAttribute("sourceTree", this->CreateString("<group>"));
2386 cmXCodeObject
* sourcesGroup
= this->CreateObject(cmXCodeObject::PBXGroup
);
2387 this->SourcesGroupChildren
=
2388 this->CreateObject(cmXCodeObject::OBJECT_LIST
);
2389 sourcesGroup
->AddAttribute("name", this->CreateString("Sources"));
2390 sourcesGroup
->AddAttribute("children", this->SourcesGroupChildren
);
2391 if(this->XcodeVersion
== 15)
2393 sourcesGroup
->AddAttribute("refType", this->CreateString("4"));
2395 sourcesGroup
->AddAttribute("sourceTree", this->CreateString("<group>"));
2396 this->MainGroupChildren
->AddObject(sourcesGroup
);
2398 cmXCodeObject
* resourcesGroup
= this->CreateObject(cmXCodeObject::PBXGroup
);
2399 this->ResourcesGroupChildren
=
2400 this->CreateObject(cmXCodeObject::OBJECT_LIST
);
2401 resourcesGroup
->AddAttribute("name", this->CreateString("Resources"));
2402 resourcesGroup
->AddAttribute("children", this->ResourcesGroupChildren
);
2403 if(this->XcodeVersion
== 15)
2405 resourcesGroup
->AddAttribute("refType", this->CreateString("4"));
2407 resourcesGroup
->AddAttribute("sourceTree", this->CreateString("<group>"));
2408 this->MainGroupChildren
->AddObject(resourcesGroup
);
2410 // now create the cmake groups
2411 this->CreateGroups(root
, generators
);
2413 cmXCodeObject
* productGroup
= this->CreateObject(cmXCodeObject::PBXGroup
);
2414 productGroup
->AddAttribute("name", this->CreateString("Products"));
2415 if(this->XcodeVersion
== 15)
2417 productGroup
->AddAttribute("refType", this->CreateString("4"));
2419 productGroup
->AddAttribute("sourceTree", this->CreateString("<group>"));
2420 cmXCodeObject
* productGroupChildren
=
2421 this->CreateObject(cmXCodeObject::OBJECT_LIST
);
2422 productGroup
->AddAttribute("children", productGroupChildren
);
2423 this->MainGroupChildren
->AddObject(productGroup
);
2426 this->RootObject
= this->CreateObject(cmXCodeObject::PBXProject
);
2427 this->RootObject
->SetComment("Project object");
2428 group
= this->CreateObject(cmXCodeObject::ATTRIBUTE_GROUP
);
2429 this->RootObject
->AddAttribute("mainGroup",
2430 this->CreateObjectReference(mainGroup
));
2431 this->RootObject
->AddAttribute("buildSettings", group
);
2432 this->RootObject
->AddAttribute("buildStyles", listObjs
);
2433 this->RootObject
->AddAttribute("hasScannedForEncodings",
2434 this->CreateString("0"));
2435 // Point Xcode at the top of the source tree.
2437 std::string proot
= root
->GetMakefile()->GetCurrentDirectory();
2438 proot
= this->ConvertToRelativeForXCode(proot
.c_str());
2439 this->RootObject
->AddAttribute("projectRoot",
2440 this->CreateString(proot
.c_str()));
2442 cmXCodeObject
* configlist
=
2443 this->CreateObject(cmXCodeObject::XCConfigurationList
);
2444 cmXCodeObject
* buildConfigurations
=
2445 this->CreateObject(cmXCodeObject::OBJECT_LIST
);
2446 std::vector
<cmXCodeObject
*> configs
;
2447 if(this->XcodeVersion
== 15)
2449 cmXCodeObject
* configDebug
=
2450 this->CreateObject(cmXCodeObject::XCBuildConfiguration
);
2451 configDebug
->AddAttribute("name", this->CreateString("Debug"));
2452 configs
.push_back(configDebug
);
2453 cmXCodeObject
* configRelease
=
2454 this->CreateObject(cmXCodeObject::XCBuildConfiguration
);
2455 configRelease
->AddAttribute("name", this->CreateString("Release"));
2456 configs
.push_back(configRelease
);
2460 for(unsigned int i
= 0; i
< this->CurrentConfigurationTypes
.size(); ++i
)
2462 const char* name
= this->CurrentConfigurationTypes
[i
].c_str();
2463 cmXCodeObject
* config
=
2464 this->CreateObject(cmXCodeObject::XCBuildConfiguration
);
2465 config
->AddAttribute("name", this->CreateString(name
));
2466 configs
.push_back(config
);
2469 for(std::vector
<cmXCodeObject
*>::iterator c
= configs
.begin();
2470 c
!= configs
.end(); ++c
)
2472 buildConfigurations
->AddObject(*c
);
2474 configlist
->AddAttribute("buildConfigurations", buildConfigurations
);
2476 std::string comment
= "Build configuration list for PBXProject ";
2478 comment
+= this->CurrentProject
;
2480 configlist
->SetComment(comment
.c_str());
2481 configlist
->AddAttribute("defaultConfigurationIsVisible",
2482 this->CreateString("0"));
2483 configlist
->AddAttribute("defaultConfigurationName",
2484 this->CreateString("Debug"));
2485 cmXCodeObject
* buildSettings
=
2486 this->CreateObject(cmXCodeObject::ATTRIBUTE_GROUP
);
2487 const char* osxArch
=
2488 this->CurrentMakefile
->GetDefinition("CMAKE_OSX_ARCHITECTURES");
2489 const char* sysroot
=
2490 this->CurrentMakefile
->GetDefinition("CMAKE_OSX_SYSROOT");
2491 const char* sysrootDefault
=
2492 this->CurrentMakefile
->GetDefinition("CMAKE_OSX_SYSROOT_DEFAULT");
2493 const char* deploymentTarget
=
2494 this->CurrentMakefile
->GetDefinition("CMAKE_OSX_DEPLOYMENT_TARGET");
2495 if(osxArch
&& sysroot
)
2497 bool flagsUsed
= false;
2498 // recompute this as it may have been changed since enable language
2499 this->Architectures
.clear();
2500 cmSystemTools::ExpandListArgument(std::string(osxArch
),
2501 this->Architectures
);
2502 bool addArchFlag
= true;
2503 if(this->Architectures
.size() == 1)
2505 const char* archOrig
=
2507 CurrentMakefile
->GetSafeDefinition("CMAKE_OSX_ARCHITECTURES_DEFAULT");
2508 if(this->Architectures
[0] == archOrig
)
2510 addArchFlag
= false;
2516 buildSettings
->AddAttribute("SDKROOT",
2517 this->CreateString(sysroot
));
2518 std::string archString
;
2519 for( std::vector
<std::string
>::iterator i
=
2520 this->Architectures
.begin();
2521 i
!= this->Architectures
.end(); ++i
)
2526 buildSettings
->AddAttribute("ARCHS",
2527 this->CreateString(archString
.c_str()));
2529 if(!flagsUsed
&& sysrootDefault
&&
2530 strcmp(sysroot
, sysrootDefault
) != 0)
2532 buildSettings
->AddAttribute("SDKROOT",
2533 this->CreateString(sysroot
));
2536 if(deploymentTarget
&& *deploymentTarget
)
2538 buildSettings
->AddAttribute("MACOSX_DEPLOYMENT_TARGET",
2539 this->CreateString(deploymentTarget
));
2541 for( std::vector
<cmXCodeObject
*>::iterator i
= configs
.begin();
2542 i
!= configs
.end(); ++i
)
2544 (*i
)->AddAttribute("buildSettings", buildSettings
);
2546 this->RootObject
->AddAttribute("buildConfigurationList",
2547 this->CreateObjectReference(configlist
));
2549 std::vector
<cmXCodeObject
*> targets
;
2550 for(std::vector
<cmLocalGenerator
*>::iterator i
= generators
.begin();
2551 i
!= generators
.end(); ++i
)
2553 if(!this->IsExcluded(root
, *i
))
2555 this->CreateXCodeTargets(*i
, targets
);
2558 // loop over all targets and add link and depend info
2559 for(std::vector
<cmXCodeObject
*>::iterator i
= targets
.begin();
2560 i
!= targets
.end(); ++i
)
2562 cmXCodeObject
* t
= *i
;
2563 this->AddDependAndLinkInformation(t
);
2565 // now create xcode depend hack makefile
2566 this->CreateXCodeDependHackTarget(targets
);
2567 // now add all targets to the root object
2568 cmXCodeObject
* allTargets
= this->CreateObject(cmXCodeObject::OBJECT_LIST
);
2569 for(std::vector
<cmXCodeObject
*>::iterator i
= targets
.begin();
2570 i
!= targets
.end(); ++i
)
2572 cmXCodeObject
* t
= *i
;
2573 allTargets
->AddObject(t
);
2574 cmXCodeObject
* productRef
= t
->GetObject("productReference");
2577 productGroupChildren
->AddObject(productRef
->GetObject());
2580 this->RootObject
->AddAttribute("targets", allTargets
);
2583 //----------------------------------------------------------------------------
2585 cmGlobalXCodeGenerator::CreateXCodeDependHackTarget(
2586 std::vector
<cmXCodeObject
*>& targets
)
2588 cmGeneratedFileStream
2589 makefileStream(this->CurrentXCodeHackMakefile
.c_str());
2592 cmSystemTools::Error("Could not create",
2593 this->CurrentXCodeHackMakefile
.c_str());
2596 makefileStream
.SetCopyIfDifferent(true);
2597 // one more pass for external depend information not handled
2598 // correctly by xcode
2599 makefileStream
<< "# DO NOT EDIT\n";
2600 makefileStream
<< "# This makefile makes sure all linkable targets are\n";
2601 makefileStream
<< "# up-to-date with anything they link to, avoiding a "
2602 "bug in XCode 1.5\n";
2603 for(std::vector
<std::string
>::const_iterator
2604 ct
= this->CurrentConfigurationTypes
.begin();
2605 ct
!= this->CurrentConfigurationTypes
.end(); ++ct
)
2607 if(this->XcodeVersion
< 21 || ct
->empty())
2609 makefileStream
<< "all: ";
2613 makefileStream
<< "all." << *ct
<< ": ";
2615 const char* configName
= 0;
2618 configName
= ct
->c_str();
2620 for(std::vector
<cmXCodeObject
*>::iterator i
= targets
.begin();
2621 i
!= targets
.end(); ++i
)
2623 cmXCodeObject
* target
= *i
;
2624 cmTarget
* t
=target
->GetTarget();
2625 if(t
->GetType() == cmTarget::EXECUTABLE
||
2626 t
->GetType() == cmTarget::SHARED_LIBRARY
||
2627 t
->GetType() == cmTarget::MODULE_LIBRARY
)
2629 std::string tfull
= t
->GetFullPath(configName
);
2630 makefileStream
<< "\\\n\t" <<
2631 this->ConvertToRelativeForMake(tfull
.c_str());
2634 makefileStream
<< "\n\n";
2637 << "# For each target create a dummy rule "
2638 "so the target does not have to exist\n";
2639 std::set
<cmStdString
> emitted
;
2640 for(std::vector
<cmXCodeObject
*>::iterator i
= targets
.begin();
2641 i
!= targets
.end(); ++i
)
2643 cmXCodeObject
* target
= *i
;
2644 std::map
<cmStdString
, cmXCodeObject::StringVec
> const& deplibs
=
2645 target
->GetDependLibraries();
2646 for(std::map
<cmStdString
, cmXCodeObject::StringVec
>::const_iterator ci
2647 = deplibs
.begin(); ci
!= deplibs
.end(); ++ci
)
2649 for(cmXCodeObject::StringVec::const_iterator d
= ci
->second
.begin();
2650 d
!= ci
->second
.end(); ++d
)
2652 if(emitted
.insert(*d
).second
)
2655 this->ConvertToRelativeForMake(d
->c_str()) << ":\n";
2660 makefileStream
<< "\n\n";
2662 // Write rules to help Xcode relink things at the right time.
2664 "# Rules to remove targets that are older than anything to which they\n"
2665 "# link. This forces Xcode to relink the targets from scratch. It\n"
2666 "# does not seem to check these dependencies itself.\n";
2667 for(std::vector
<std::string
>::const_iterator
2668 ct
= this->CurrentConfigurationTypes
.begin();
2669 ct
!= this->CurrentConfigurationTypes
.end(); ++ct
)
2671 const char* configName
= 0;
2674 configName
= ct
->c_str();
2676 for(std::vector
<cmXCodeObject
*>::iterator i
= targets
.begin();
2677 i
!= targets
.end(); ++i
)
2679 cmXCodeObject
* target
= *i
;
2680 cmTarget
* t
=target
->GetTarget();
2681 if(t
->GetType() == cmTarget::EXECUTABLE
||
2682 t
->GetType() == cmTarget::SHARED_LIBRARY
||
2683 t
->GetType() == cmTarget::MODULE_LIBRARY
)
2685 // Create a rule for this target.
2686 std::string tfull
= t
->GetFullPath(configName
);
2687 makefileStream
<< this->ConvertToRelativeForMake(tfull
.c_str())
2690 // List dependencies if any exist.
2691 std::map
<cmStdString
, cmXCodeObject::StringVec
>::const_iterator
2692 x
= target
->GetDependLibraries().find(*ct
);
2693 if(x
!= target
->GetDependLibraries().end())
2695 std::vector
<cmStdString
> const& deplibs
= x
->second
;
2696 for(std::vector
<cmStdString
>::const_iterator d
= deplibs
.begin();
2697 d
!= deplibs
.end(); ++d
)
2699 makefileStream
<< "\\\n\t" <<
2700 this->ConvertToRelativeForMake(d
->c_str());
2703 // Write the action to remove the target if it is out of date.
2704 makefileStream
<< "\n";
2705 makefileStream
<< "\t/bin/rm -f "
2706 << this->ConvertToRelativeForMake(tfull
.c_str())
2708 // if building for more than one architecture
2709 // then remove those exectuables as well
2710 if(this->Architectures
.size() > 1)
2712 std::string universal
= t
->GetDirectory();
2714 universal
+= this->CurrentProject
;
2715 universal
+= ".build/";
2716 universal
+= configName
;
2718 universal
+= t
->GetFullName(configName
);
2719 universal
+= ".build/Objects-normal/";
2720 for( std::vector
<std::string
>::iterator arch
=
2721 this->Architectures
.begin();
2722 arch
!= this->Architectures
.end(); ++arch
)
2724 std::string universalFile
= universal
;
2725 universalFile
+= *arch
;
2726 universalFile
+= "/";
2727 universalFile
+= t
->GetFullName(configName
);
2728 makefileStream
<< "\t/bin/rm -f "
2730 this->ConvertToRelativeForMake(universalFile
.c_str())
2734 makefileStream
<< "\n\n";
2740 //----------------------------------------------------------------------------
2742 cmGlobalXCodeGenerator::OutputXCodeProject(cmLocalGenerator
* root
,
2743 std::vector
<cmLocalGenerator
*>&
2746 if(generators
.size() == 0)
2750 // Skip local generators that are excluded from this project.
2751 for(std::vector
<cmLocalGenerator
*>::iterator g
= generators
.begin();
2752 g
!= generators
.end(); ++g
)
2754 if(this->IsExcluded(root
, *g
))
2760 this->CreateXCodeObjects(root
,
2762 std::string xcodeDir
= root
->GetMakefile()->GetStartOutputDirectory();
2764 xcodeDir
+= root
->GetMakefile()->GetProjectName();
2765 xcodeDir
+= ".xcode";
2766 if(this->XcodeVersion
> 20)
2770 cmSystemTools::MakeDirectory(xcodeDir
.c_str());
2771 std::string xcodeProjFile
= xcodeDir
+ "/project.pbxproj";
2772 cmGeneratedFileStream
fout(xcodeProjFile
.c_str());
2773 fout
.SetCopyIfDifferent(true);
2778 this->WriteXCodePBXProj(fout
, root
, generators
);
2779 this->ClearXCodeObjects();
2782 //----------------------------------------------------------------------------
2784 cmGlobalXCodeGenerator::WriteXCodePBXProj(std::ostream
& fout
,
2786 std::vector
<cmLocalGenerator
*>& )
2788 fout
<< "// !$*UTF8*$!\n";
2790 cmXCodeObject::Indent(1, fout
);
2791 fout
<< "archiveVersion = 1;\n";
2792 cmXCodeObject::Indent(1, fout
);
2793 fout
<< "classes = {\n";
2794 cmXCodeObject::Indent(1, fout
);
2796 cmXCodeObject::Indent(1, fout
);
2797 fout
<< "objectVersion = 39;\n";
2798 cmXCodeObject::PrintList(this->XCodeObjects
, fout
);
2799 cmXCodeObject::Indent(1, fout
);
2800 fout
<< "rootObject = " << this->RootObject
->GetId() << ";\n";
2804 //----------------------------------------------------------------------------
2805 void cmGlobalXCodeGenerator::GetDocumentation(cmDocumentationEntry
& entry
)
2808 entry
.Name
= this->GetName();
2809 entry
.Brief
= "Generate XCode project files.";
2813 //----------------------------------------------------------------------------
2814 std::string
cmGlobalXCodeGenerator::ConvertToRelativeForMake(const char* p
)
2816 if ( !this->CurrentMakefile
->IsOn("CMAKE_USE_RELATIVE_PATHS") )
2818 return cmSystemTools::ConvertToOutputPath(p
);
2823 this->CurrentLocalGenerator
->
2824 ConvertToRelativePath(this->CurrentOutputDirectoryComponents
, p
);
2825 return cmSystemTools::ConvertToOutputPath(ret
.c_str());
2829 //----------------------------------------------------------------------------
2830 std::string
cmGlobalXCodeGenerator::ConvertToRelativeForXCode(const char* p
)
2832 if ( !this->CurrentMakefile
->IsOn("CMAKE_USE_RELATIVE_PATHS") )
2834 return cmSystemTools::ConvertToOutputPath(p
);
2839 this->CurrentLocalGenerator
->
2840 ConvertToRelativePath(this->ProjectOutputDirectoryComponents
, p
);
2841 return cmSystemTools::ConvertToOutputPath(ret
.c_str());
2845 //----------------------------------------------------------------------------
2846 std::string
cmGlobalXCodeGenerator::XCodeEscapePath(const char* p
)
2848 std::string ret
= p
;
2849 if(ret
.find(' ') != ret
.npos
)
2851 std::string t
= ret
;
2859 //----------------------------------------------------------------------------
2860 void cmGlobalXCodeGenerator::
2861 GetTargetObjectFileDirectories(cmTarget
* target
,
2862 std::vector
<std::string
>&
2865 std::string dir
= this->CurrentMakefile
->GetCurrentOutputDirectory();
2867 dir
+= this->CurrentMakefile
->GetProjectName();
2869 dir
+= this->GetCMakeCFGInitDirectory();
2871 if(target
->GetType() != cmTarget::EXECUTABLE
)
2875 dir
+= target
->GetName();
2876 if(target
->GetType() == cmTarget::STATIC_LIBRARY
)
2880 if(target
->GetType() == cmTarget::SHARED_LIBRARY
)
2884 if(target
->GetType() == cmTarget::MODULE_LIBRARY
)
2888 dir
+= ".build/Objects-normal/";
2889 std::string dirsave
= dir
;
2890 if(this->Architectures
.size())
2892 for(std::vector
<std::string
>::iterator i
= this->Architectures
.begin();
2893 i
!= this->Architectures
.end(); ++i
)
2896 dirs
.push_back(dir
);
2902 dirs
.push_back(dir
);
2906 //----------------------------------------------------------------------------
2908 cmGlobalXCodeGenerator
2909 ::AppendDirectoryForConfig(const char* prefix
,
2914 if(this->XcodeVersion
> 20)
2925 //----------------------------------------------------------------------------
2926 std::string
cmGlobalXCodeGenerator::LookupFlags(const char* varNamePrefix
,
2927 const char* varNameLang
,
2928 const char* varNameSuffix
,
2929 const char* default_flags
)
2933 std::string varName
= varNamePrefix
;
2934 varName
+= varNameLang
;
2935 varName
+= varNameSuffix
;
2936 if(const char* varValue
=
2937 this->CurrentMakefile
->GetDefinition(varName
.c_str()))
2945 return default_flags
;
2948 //----------------------------------------------------------------------------
2949 void cmGlobalXCodeGenerator::AppendDefines(std::string
& defs
,
2950 const char* defines_list
,
2953 // Skip this if there are no definitions.
2959 // Expand the list of definitions.
2960 std::vector
<std::string
> defines
;
2961 cmSystemTools::ExpandListArgument(defines_list
, defines
);
2963 // GCC_PREPROCESSOR_DEFINITIONS is a space-separated list of definitions.
2964 // We escape everything as follows:
2965 // - Place each definition in single quotes ''
2966 // - Escape a single quote as \\'
2967 // - Escape a backslash as \\\\ since it itself is an escape
2968 // Note that in the code below we need one more level of escapes for
2969 // C string syntax in this source file.
2970 const char* sep
= defs
.empty()? "" : " ";
2971 for(std::vector
<std::string
>::const_iterator di
= defines
.begin();
2972 di
!= defines
.end(); ++di
)
2974 // Separate from previous definition.
2978 // Open single quote.
2981 // Add -D flag if requested.
2987 // Escaped definition string.
2988 for(const char* c
= di
->c_str(); *c
; ++c
)
3004 // Close single quote.
3009 //----------------------------------------------------------------------------
3011 cmGlobalXCodeGenerator::ComputeInfoPListLocation(cmTarget
& target
)
3013 std::string plist
= target
.GetMakefile()->GetCurrentOutputDirectory();
3014 plist
+= cmake::GetCMakeFilesDirectory();
3016 plist
+= target
.GetName();
3017 plist
+= ".dir/Info.plist";