Imported Upstream version 2.8.9
[platform/upstream/cmake.git] / Source / cmGlobalXCodeGenerator.cxx
1 /*============================================================================
2   CMake - Cross Platform Makefile Generator
3   Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
4
5   Distributed under the OSI-approved BSD License (the "License");
6   see accompanying file Copyright.txt for details.
7
8   This software is distributed WITHOUT ANY WARRANTY; without even the
9   implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
10   See the License for more information.
11 ============================================================================*/
12 #include "cmGlobalXCodeGenerator.h"
13 #include "cmLocalXCodeGenerator.h"
14 #include "cmMakefile.h"
15 #include "cmXCodeObject.h"
16 #include "cmXCode21Object.h"
17 #include "cmake.h"
18 #include "cmGeneratedFileStream.h"
19 #include "cmComputeLinkInformation.h"
20 #include "cmSourceFile.h"
21 #include "cmCustomCommandGenerator.h"
22 #include "cmGeneratorTarget.h"
23
24 #include <cmsys/auto_ptr.hxx>
25
26 //----------------------------------------------------------------------------
27 #if defined(CMAKE_BUILD_WITH_CMAKE)
28 #include "cmXMLParser.h"
29
30 // parse the xml file storing the installed version of Xcode on
31 // the machine
32 class cmXcodeVersionParser : public cmXMLParser
33 {
34 public:
35   cmXcodeVersionParser(): Version("1.5") {}
36   void StartElement(const char* , const char** )
37     {
38       this->Data = "";
39     }
40   void EndElement(const char* name)
41     {
42       if(strcmp(name, "key") == 0)
43         {
44         this->Key = this->Data;
45         }
46       else if(strcmp(name, "string") == 0)
47         {
48         if(this->Key == "CFBundleShortVersionString")
49           {
50           this->Version = this->Data;
51           }
52         }
53     }
54   void CharacterDataHandler(const char* data, int length)
55     {
56       this->Data.append(data, length);
57     }
58   std::string Version;
59   std::string Key;
60   std::string Data;
61 };
62 #endif
63
64 // Builds either an object list or a space-separated string from the
65 // given inputs.
66 class cmGlobalXCodeGenerator::BuildObjectListOrString
67 {
68   cmGlobalXCodeGenerator *Generator;
69   cmXCodeObject *Group;
70   bool Empty;
71   std::string String;
72
73 public:
74   BuildObjectListOrString(cmGlobalXCodeGenerator *gen, bool buildObjectList)
75     : Generator(gen), Group(0), Empty(true)
76     {
77     if (buildObjectList)
78       {
79       this->Group = this->Generator->CreateObject(cmXCodeObject::OBJECT_LIST);
80       }
81     }
82
83   bool IsEmpty() const { return this->Empty; }
84
85   void Add(const char *newString)
86     {
87     this->Empty = false;
88
89     if (this->Group)
90       {
91       this->Group->AddObject(this->Generator->CreateString(newString));
92       }
93     else
94       {
95       this->String += newString;
96       this->String += ' ';
97       }
98     }
99
100   const std::string &GetString() const { return this->String; }
101
102   cmXCodeObject *CreateList()
103     {
104     if (this->Group)
105       {
106       return this->Group;
107       }
108     else
109       {
110       return this->Generator->CreateString(this->String.c_str());
111       }
112     }
113 };
114
115 //----------------------------------------------------------------------------
116 cmGlobalXCodeGenerator::cmGlobalXCodeGenerator(std::string const& version)
117 {
118   this->VersionString = version;
119
120   // Compute an integer form of the version number.
121   unsigned int v[2] = {0,0};
122   sscanf(this->VersionString.c_str(), "%u.%u", &v[0], &v[1]);
123   this->XcodeVersion = 10*v[0] + v[1];
124
125   this->FindMakeProgramFile = "CMakeFindXCode.cmake";
126   this->RootObject = 0;
127   this->MainGroupChildren = 0;
128   this->SourcesGroupChildren = 0;
129   this->ResourcesGroupChildren = 0;
130   this->CurrentMakefile = 0;
131   this->CurrentLocalGenerator = 0;
132 }
133
134 //----------------------------------------------------------------------------
135 cmGlobalGenerator* cmGlobalXCodeGenerator::New()
136 {
137 #if defined(CMAKE_BUILD_WITH_CMAKE)
138   cmXcodeVersionParser parser;
139   if (cmSystemTools::FileExists(
140        "/Applications/Xcode.app/Contents/version.plist"))
141     {
142     parser.ParseFile
143       ("/Applications/Xcode.app/Contents/version.plist");
144     }
145   else
146     {
147     parser.ParseFile
148       ("/Developer/Applications/Xcode.app/Contents/version.plist");
149     }
150   cmsys::auto_ptr<cmGlobalXCodeGenerator>
151     gg(new cmGlobalXCodeGenerator(parser.Version));
152   if (gg->XcodeVersion == 20)
153     {
154     cmSystemTools::Message("Xcode 2.0 not really supported by cmake, "
155                            "using Xcode 15 generator\n");
156     gg->XcodeVersion = 15;
157     }
158   return gg.release();
159 #else
160   std::cerr << "CMake should be built with cmake to use Xcode, "
161     "default to Xcode 1.5\n";
162   return new cmGlobalXCodeGenerator;
163 #endif
164 }
165
166 //----------------------------------------------------------------------------
167 void cmGlobalXCodeGenerator::EnableLanguage(std::vector<std::string>const&
168                                             lang,
169                                             cmMakefile * mf, bool optional)
170 {
171   mf->AddDefinition("XCODE","1");
172   mf->AddDefinition("XCODE_VERSION", this->VersionString.c_str());
173   if(this->XcodeVersion == 15)
174     {
175     }
176   else
177     {
178     if(!mf->GetDefinition("CMAKE_CONFIGURATION_TYPES"))
179       {
180       mf->AddCacheDefinition(
181         "CMAKE_CONFIGURATION_TYPES",
182         "Debug;Release;MinSizeRel;RelWithDebInfo",
183         "Semicolon separated list of supported configuration types, "
184         "only supports Debug, Release, MinSizeRel, and RelWithDebInfo, "
185         "anything else will be ignored.",
186         cmCacheManager::STRING);
187       }
188     }
189   mf->AddDefinition("CMAKE_GENERATOR_CC", "gcc");
190   mf->AddDefinition("CMAKE_GENERATOR_CXX", "g++");
191   mf->AddDefinition("CMAKE_GENERATOR_NO_COMPILER_ENV", "1");
192   this->cmGlobalGenerator::EnableLanguage(lang, mf, optional);
193     const char* osxArch =
194       mf->GetDefinition("CMAKE_OSX_ARCHITECTURES");
195   const char* sysroot =
196       mf->GetDefinition("CMAKE_OSX_SYSROOT");
197   if(osxArch && sysroot)
198     {
199     this->Architectures.clear();
200     cmSystemTools::ExpandListArgument(std::string(osxArch),
201                                       this->Architectures);
202     }
203 }
204
205 //----------------------------------------------------------------------------
206 std::string cmGlobalXCodeGenerator
207 ::GenerateBuildCommand(const char* makeProgram,
208                        const char *projectName,
209                        const char* additionalOptions,
210                        const char *targetName,
211                        const char* config,
212                        bool ignoreErrors,
213                        bool)
214 {
215   // Config is not used yet
216   (void) ignoreErrors;
217
218   // now build the test
219   if(makeProgram == 0 || !strlen(makeProgram))
220     {
221     cmSystemTools::Error(
222       "Generator cannot find the appropriate make command.");
223     return "";
224     }
225   std::string makeCommand =
226     cmSystemTools::ConvertToOutputPath(makeProgram);
227   std::string lowerCaseCommand = makeCommand;
228   cmSystemTools::LowerCase(lowerCaseCommand);
229
230   makeCommand += " -project ";
231   makeCommand += projectName;
232   makeCommand += ".xcode";
233   if(this->XcodeVersion > 20)
234     {
235     makeCommand += "proj";
236     }
237
238   bool clean = false;
239   if ( targetName && strcmp(targetName, "clean") == 0 )
240     {
241     clean = true;
242     targetName = "ALL_BUILD";
243     }
244   if(clean)
245     {
246     makeCommand += " clean";
247     }
248   else
249     {
250     makeCommand += " build";
251     }
252   makeCommand += " -target ";
253   // if it is a null string for config don't use it
254   if(config && *config == 0)
255     {
256     config = 0;
257     }
258   if (targetName && strlen(targetName))
259     {
260     makeCommand += targetName;
261     }
262   else
263     {
264     makeCommand += "ALL_BUILD";
265     }
266   if(this->XcodeVersion == 15)
267     {
268     makeCommand += " -buildstyle Development ";
269     }
270   else
271     {
272     makeCommand += " -configuration ";
273     makeCommand += config?config:"Debug";
274     }
275   if ( additionalOptions )
276     {
277     makeCommand += " ";
278     makeCommand += additionalOptions;
279     }
280   return makeCommand;
281 }
282
283 //----------------------------------------------------------------------------
284 ///! Create a local generator appropriate to this Global Generator
285 cmLocalGenerator *cmGlobalXCodeGenerator::CreateLocalGenerator()
286 {
287   cmLocalGenerator *lg = new cmLocalXCodeGenerator;
288   lg->SetGlobalGenerator(this);
289   return lg;
290 }
291
292 //----------------------------------------------------------------------------
293 void cmGlobalXCodeGenerator::Generate()
294 {
295   std::map<cmStdString, std::vector<cmLocalGenerator*> >::iterator it;
296   // make sure extra targets are added before calling
297   // the parent generate which will call trace depends
298   for(it = this->ProjectMap.begin(); it!= this->ProjectMap.end(); ++it)
299     {
300     cmLocalGenerator* root = it->second[0];
301     this->SetGenerationRoot(root);
302     // add ALL_BUILD, INSTALL, etc
303     this->AddExtraTargets(root, it->second);
304     }
305   this->ForceLinkerLanguages();
306   this->cmGlobalGenerator::Generate();
307   if(cmSystemTools::GetErrorOccuredFlag())
308     {
309     return;
310     }
311   for(it = this->ProjectMap.begin(); it!= this->ProjectMap.end(); ++it)
312     {
313     cmLocalGenerator* root = it->second[0];
314     this->SetGenerationRoot(root);
315     // now create the project
316     this->OutputXCodeProject(root, it->second);
317     }
318 }
319
320 //----------------------------------------------------------------------------
321 void cmGlobalXCodeGenerator::SetGenerationRoot(cmLocalGenerator* root)
322 {
323   this->CurrentProject = root->GetMakefile()->GetProjectName();
324   this->SetCurrentLocalGenerator(root);
325   cmSystemTools::SplitPath(this->CurrentMakefile->GetCurrentDirectory(),
326                            this->ProjectSourceDirectoryComponents);
327   cmSystemTools::SplitPath(this->CurrentMakefile->GetCurrentOutputDirectory(),
328                            this->ProjectOutputDirectoryComponents);
329
330   this->CurrentXCodeHackMakefile =
331     root->GetMakefile()->GetCurrentOutputDirectory();
332   this->CurrentXCodeHackMakefile += "/CMakeScripts";
333   cmSystemTools::MakeDirectory(this->CurrentXCodeHackMakefile.c_str());
334   this->CurrentXCodeHackMakefile += "/XCODE_DEPEND_HELPER.make";
335 }
336
337 //----------------------------------------------------------------------------
338 std::string
339 cmGlobalXCodeGenerator::PostBuildMakeTarget(std::string const& tName,
340                                             std::string const& configName)
341 {
342   std::string target = tName;
343   cmSystemTools::ReplaceString(target, " ", "_");
344   std::string out = "PostBuild." + target;
345   if(this->XcodeVersion > 20)
346     {
347     out += "." + configName;
348     }
349   return out;
350 }
351
352 //----------------------------------------------------------------------------
353 #define CMAKE_CHECK_BUILD_SYSTEM_TARGET "ZERO_CHECK"
354
355 //----------------------------------------------------------------------------
356 void
357 cmGlobalXCodeGenerator::AddExtraTargets(cmLocalGenerator* root,
358                                         std::vector<cmLocalGenerator*>& gens)
359 {
360   cmMakefile* mf = root->GetMakefile();
361
362   // Add ALL_BUILD
363   const char* no_working_directory = 0;
364   std::vector<std::string> no_depends;
365   mf->AddUtilityCommand("ALL_BUILD", true, no_depends,
366                         no_working_directory,
367                         "echo", "Build all projects");
368   cmTarget* allbuild = mf->FindTarget("ALL_BUILD");
369
370   // Refer to the main build configuration file for easy editing.
371   std::string listfile = mf->GetStartDirectory();
372   listfile += "/";
373   listfile += "CMakeLists.txt";
374   allbuild->AddSource(listfile.c_str());
375
376   // Add XCODE depend helper
377   std::string dir = mf->GetCurrentOutputDirectory();
378   cmCustomCommandLine makecommand;
379   makecommand.push_back("make");
380   makecommand.push_back("-C");
381   makecommand.push_back(dir.c_str());
382   makecommand.push_back("-f");
383   makecommand.push_back(this->CurrentXCodeHackMakefile.c_str());
384   makecommand.push_back(""); // placeholder, see below
385
386   // Add ZERO_CHECK
387   bool regenerate = !mf->IsOn("CMAKE_SUPPRESS_REGENERATION");
388   if (regenerate)
389     {
390     this->CreateReRunCMakeFile(root, gens);
391     std::string file = this->ConvertToRelativeForMake(
392       this->CurrentReRunCMakeMakefile.c_str());
393     cmSystemTools::ReplaceString(file, "\\ ", " ");
394     mf->AddUtilityCommand(CMAKE_CHECK_BUILD_SYSTEM_TARGET, true, no_depends,
395                           no_working_directory,
396                           "make", "-f", file.c_str());
397     }
398
399   // now make the allbuild depend on all the non-utility targets
400   // in the project
401   for(std::vector<cmLocalGenerator*>::iterator i = gens.begin();
402       i != gens.end(); ++i)
403     {
404     cmLocalGenerator* lg = *i;
405     if(this->IsExcluded(root, *i))
406       {
407       continue;
408       }
409
410     cmTargets& tgts = lg->GetMakefile()->GetTargets();
411     for(cmTargets::iterator l = tgts.begin(); l != tgts.end(); l++)
412       {
413       cmTarget& target = l->second;
414
415       if (regenerate && (l->first != CMAKE_CHECK_BUILD_SYSTEM_TARGET))
416         {
417         target.AddUtility(CMAKE_CHECK_BUILD_SYSTEM_TARGET);
418         }
419
420       // make all exe, shared libs and modules
421       // run the depend check makefile as a post build rule
422       // this will make sure that when the next target is built
423       // things are up-to-date
424       if((target.GetType() == cmTarget::EXECUTABLE ||
425 // Nope - no post-build for OBJECT_LIRBRARY
426 //          target.GetType() == cmTarget::OBJECT_LIBRARY ||
427           target.GetType() == cmTarget::STATIC_LIBRARY ||
428           target.GetType() == cmTarget::SHARED_LIBRARY ||
429           target.GetType() == cmTarget::MODULE_LIBRARY))
430         {
431         makecommand[makecommand.size()-1] =
432           this->PostBuildMakeTarget(target.GetName(), "$(CONFIGURATION)");
433         cmCustomCommandLines commandLines;
434         commandLines.push_back(makecommand);
435         lg->GetMakefile()->AddCustomCommandToTarget(target.GetName(),
436                                                     no_depends,
437                                                     commandLines,
438                                                     cmTarget::POST_BUILD,
439                                                     "Depend check for xcode",
440                                                     dir.c_str());
441         }
442
443       if(!target.GetPropertyAsBool("EXCLUDE_FROM_ALL"))
444         {
445         allbuild->AddUtility(target.GetName());
446         }
447
448       // Refer to the build configuration file for easy editing.
449       listfile = lg->GetMakefile()->GetStartDirectory();
450       listfile += "/";
451       listfile += "CMakeLists.txt";
452       target.AddSource(listfile.c_str());
453       }
454     }
455 }
456
457 //----------------------------------------------------------------------------
458 void cmGlobalXCodeGenerator::CreateReRunCMakeFile(
459   cmLocalGenerator* root, std::vector<cmLocalGenerator*> const& gens)
460 {
461   cmMakefile* mf = root->GetMakefile();
462   std::vector<std::string> lfiles;
463   for(std::vector<cmLocalGenerator*>::const_iterator gi = gens.begin();
464       gi != gens.end(); ++gi)
465     {
466     std::vector<std::string> const& lf = (*gi)->GetMakefile()->GetListFiles();
467     lfiles.insert(lfiles.end(), lf.begin(), lf.end());
468     }
469
470   // sort the array
471   std::sort(lfiles.begin(), lfiles.end(), std::less<std::string>());
472   std::vector<std::string>::iterator new_end =
473     std::unique(lfiles.begin(), lfiles.end());
474   lfiles.erase(new_end, lfiles.end());
475   this->CurrentReRunCMakeMakefile = mf->GetStartOutputDirectory();
476   this->CurrentReRunCMakeMakefile += "/CMakeScripts";
477   cmSystemTools::MakeDirectory(this->CurrentReRunCMakeMakefile.c_str());
478   this->CurrentReRunCMakeMakefile += "/ReRunCMake.make";
479   cmGeneratedFileStream makefileStream
480     (this->CurrentReRunCMakeMakefile.c_str());
481   makefileStream.SetCopyIfDifferent(true);
482   makefileStream << "# Generated by CMake, DO NOT EDIT\n";
483   makefileStream << cmake::GetCMakeFilesDirectoryPostSlash();
484   makefileStream << "cmake.check_cache: ";
485   for(std::vector<std::string>::const_iterator i = lfiles.begin();
486       i !=  lfiles.end(); ++i)
487     {
488     makefileStream << "\\\n" << this->ConvertToRelativeForMake(i->c_str());
489     }
490   std::string cmake = mf->GetRequiredDefinition("CMAKE_COMMAND");
491   makefileStream << "\n\t" << this->ConvertToRelativeForMake(cmake.c_str())
492                  << " -H" << this->ConvertToRelativeForMake(
493                    mf->GetHomeDirectory())
494                  << " -B" << this->ConvertToRelativeForMake(
495                    mf->GetHomeOutputDirectory()) << "\n";
496 }
497
498 //----------------------------------------------------------------------------
499 void cmGlobalXCodeGenerator::ClearXCodeObjects()
500 {
501   this->TargetDoneSet.clear();
502   for(unsigned int i = 0; i < this->XCodeObjects.size(); ++i)
503     {
504     delete this->XCodeObjects[i];
505     }
506   this->XCodeObjects.clear();
507   this->XCodeObjectIDs.clear();
508   this->GroupMap.clear();
509   this->GroupNameMap.clear();
510   this->TargetGroup.clear();
511   this->FileRefs.clear();
512 }
513
514 //----------------------------------------------------------------------------
515 void cmGlobalXCodeGenerator::addObject(cmXCodeObject *obj)
516 {
517   if(obj->GetType() == cmXCodeObject::OBJECT)
518     {
519     cmStdString id = obj->GetId();
520
521     // If this is a duplicate id, it's an error:
522     //
523     if(this->XCodeObjectIDs.count(id))
524       {
525       cmSystemTools::Error(
526         "Xcode generator: duplicate object ids not allowed");
527       }
528
529     this->XCodeObjectIDs.insert(id);
530     }
531
532   this->XCodeObjects.push_back(obj);
533 }
534
535 //----------------------------------------------------------------------------
536 cmXCodeObject*
537 cmGlobalXCodeGenerator::CreateObject(cmXCodeObject::PBXType ptype)
538 {
539   cmXCodeObject* obj;
540   if(this->XcodeVersion == 15)
541     {
542     obj = new cmXCodeObject(ptype, cmXCodeObject::OBJECT);
543     }
544   else
545     {
546     obj = new cmXCode21Object(ptype, cmXCodeObject::OBJECT);
547     }
548   this->addObject(obj);
549   return obj;
550 }
551
552 //----------------------------------------------------------------------------
553 cmXCodeObject*
554 cmGlobalXCodeGenerator::CreateObject(cmXCodeObject::Type type)
555 {
556   cmXCodeObject* obj = new cmXCodeObject(cmXCodeObject::None, type);
557   this->addObject(obj);
558   return obj;
559 }
560
561 //----------------------------------------------------------------------------
562 cmXCodeObject*
563 cmGlobalXCodeGenerator::CreateString(const char* s)
564 {
565   cmXCodeObject* obj = this->CreateObject(cmXCodeObject::STRING);
566   obj->SetString(s);
567   return obj;
568 }
569
570 //----------------------------------------------------------------------------
571 cmXCodeObject* cmGlobalXCodeGenerator
572 ::CreateObjectReference(cmXCodeObject* ref)
573 {
574   cmXCodeObject* obj = this->CreateObject(cmXCodeObject::OBJECT_REF);
575   obj->SetObject(ref);
576   return obj;
577 }
578
579 //----------------------------------------------------------------------------
580 cmStdString
581 GetGroupMapKeyFromPath(cmTarget& cmtarget, const std::string& fullpath)
582 {
583   cmStdString key(cmtarget.GetName());
584   key += "-";
585   key += fullpath;
586   return key;
587 }
588
589 //----------------------------------------------------------------------------
590 cmStdString
591 GetGroupMapKey(cmTarget& cmtarget, cmSourceFile* sf)
592 {
593   return GetGroupMapKeyFromPath(cmtarget, sf->GetFullPath());
594 }
595
596 //----------------------------------------------------------------------------
597 cmXCodeObject*
598 cmGlobalXCodeGenerator::CreateXCodeSourceFileFromPath(
599   const std::string &fullpath,
600   cmTarget& cmtarget,
601   const std::string &lang)
602 {
603   // Using a map and the full path guarantees that we will always get the same
604   // fileRef object for any given full path.
605   //
606   cmXCodeObject* fileRef =
607     this->CreateXCodeFileReferenceFromPath(fullpath, cmtarget, lang);
608
609   cmXCodeObject* buildFile = this->CreateObject(cmXCodeObject::PBXBuildFile);
610   buildFile->SetComment(fileRef->GetComment());
611   buildFile->AddAttribute("fileRef", this->CreateObjectReference(fileRef));
612
613   return buildFile;
614 }
615
616 //----------------------------------------------------------------------------
617 cmXCodeObject*
618 cmGlobalXCodeGenerator::CreateXCodeSourceFile(cmLocalGenerator* lg,
619                                               cmSourceFile* sf,
620                                               cmTarget& cmtarget)
621 {
622   // Add flags from target and source file properties.
623   std::string flags;
624   if(cmtarget.GetProperty("COMPILE_FLAGS"))
625     {
626     lg->AppendFlags(flags, cmtarget.GetProperty("COMPILE_FLAGS"));
627     }
628   const char* srcfmt = sf->GetProperty("Fortran_FORMAT");
629   switch(this->CurrentLocalGenerator->GetFortranFormat(srcfmt))
630     {
631     case cmLocalGenerator::FortranFormatFixed: flags="-fixed "+flags; break;
632     case cmLocalGenerator::FortranFormatFree: flags="-free "+flags; break;
633     default: break;
634     }
635   lg->AppendFlags(flags, sf->GetProperty("COMPILE_FLAGS"));
636
637   // Add per-source definitions.
638   BuildObjectListOrString flagsBuild(this, false);
639   this->AppendDefines(flagsBuild,
640                       sf->GetProperty("COMPILE_DEFINITIONS"), true);
641   if (!flagsBuild.IsEmpty())
642     {
643     if (flags.size())
644       {
645       flags += ' ';
646       }
647     flags += flagsBuild.GetString();
648     }
649
650   const char* lang =
651     this->CurrentLocalGenerator->GetSourceFileLanguage(*sf);
652   if (!lang)
653     {
654     lang = "";
655     }
656
657   cmXCodeObject* buildFile =
658     this->CreateXCodeSourceFileFromPath(sf->GetFullPath(), cmtarget, lang);
659   cmXCodeObject* fileRef = buildFile->GetObject("fileRef")->GetObject();
660
661   cmXCodeObject* settings =
662     this->CreateObject(cmXCodeObject::ATTRIBUTE_GROUP);
663   settings->AddAttribute("COMPILER_FLAGS", this->CreateString(flags.c_str()));
664
665   // Is this a resource file in this target? Add it to the resources group...
666   //
667   cmTarget::SourceFileFlags tsFlags = cmtarget.GetTargetSourceFileFlags(sf);
668   bool isResource = (tsFlags.Type == cmTarget::SourceFileTypeResource);
669
670   // Is this a "private" or "public" framework header file?
671   // Set the ATTRIBUTES attribute appropriately...
672   //
673   if(cmtarget.IsFrameworkOnApple())
674     {
675     if(tsFlags.Type == cmTarget::SourceFileTypePrivateHeader)
676       {
677       cmXCodeObject* attrs = this->CreateObject(cmXCodeObject::OBJECT_LIST);
678       attrs->AddObject(this->CreateString("Private"));
679       settings->AddAttribute("ATTRIBUTES", attrs);
680       isResource = true;
681       }
682     else if(tsFlags.Type == cmTarget::SourceFileTypePublicHeader)
683       {
684       cmXCodeObject* attrs = this->CreateObject(cmXCodeObject::OBJECT_LIST);
685       attrs->AddObject(this->CreateString("Public"));
686       settings->AddAttribute("ATTRIBUTES", attrs);
687       isResource = true;
688       }
689     }
690
691   if(cmtarget.IsCFBundleOnApple())
692     {
693     cmtarget.SetProperty("PREFIX", "");
694     cmtarget.SetProperty("SUFFIX", "");
695     }
696
697   // Add the fileRef to the top level Resources group/folder if it is not
698   // already there.
699   //
700   if(isResource && this->ResourcesGroupChildren &&
701     !this->ResourcesGroupChildren->HasObject(fileRef))
702     {
703     this->ResourcesGroupChildren->AddObject(fileRef);
704     }
705
706   buildFile->AddAttribute("settings", settings);
707   return buildFile;
708 }
709
710 //----------------------------------------------------------------------------
711 std::string
712 GetSourcecodeValueFromFileExtension(const std::string& _ext,
713                                     const std::string& lang)
714 {
715   std::string ext = cmSystemTools::LowerCase(_ext);
716   std::string sourcecode = "sourcecode";
717
718   if(ext == "o")
719     {
720     sourcecode = "compiled.mach-o.objfile";
721     }
722   else if(ext == "xib")
723     {
724     sourcecode = "file.xib";
725     }
726   else if(ext == "storyboard")
727     {
728     sourcecode = "file.storyboard";
729     }
730   else if(ext == "mm")
731     {
732     sourcecode += ".cpp.objcpp";
733     }
734   else if(ext == "m")
735     {
736     sourcecode += ".c.objc";
737     }
738   else if(ext == "xib")
739     {
740     sourcecode += ".file.xib";
741     }
742   else if(ext == "plist")
743     {
744     sourcecode += ".text.plist";
745     }
746   else if(ext == "h")
747     {
748     sourcecode += ".c.h";
749     }
750   else if(ext == "hxx" || ext == "hpp" || ext == "txx"
751     || ext == "pch" || ext == "hh")
752     {
753     sourcecode += ".cpp.h";
754     }
755   else if(ext == "png" || ext == "gif" || ext == "jpg")
756     {
757     sourcecode = "image";
758     }
759   else if(ext == "txt")
760     {
761     sourcecode += ".text";
762     }
763   else if(lang == "CXX")
764     {
765     sourcecode += ".cpp.cpp";
766     }
767   else if(lang == "C")
768     {
769     sourcecode += ".c.c";
770     }
771   else if(lang == "Fortran")
772     {
773     sourcecode += ".fortran.f90";
774     }
775   //else
776   //  {
777   //  // Already specialized above or we leave sourcecode == "sourcecode"
778   //  // which is probably the most correct choice. Extensionless headers,
779   //  // for example... Or file types unknown to Xcode that do not map to a
780   //  // valid lastKnownFileType value.
781   //  }
782
783   return sourcecode;
784 }
785
786 //----------------------------------------------------------------------------
787 cmXCodeObject*
788 cmGlobalXCodeGenerator::CreateXCodeFileReferenceFromPath(
789   const std::string &fullpath,
790   cmTarget& cmtarget,
791   const std::string &lang)
792 {
793   std::string fname = fullpath;
794   cmXCodeObject* fileRef = this->FileRefs[fname];
795   if(!fileRef)
796     {
797     fileRef = this->CreateObject(cmXCodeObject::PBXFileReference);
798     std::string comment = fname;
799     fileRef->SetComment(fname.c_str());
800     this->FileRefs[fname] = fileRef;
801     }
802   cmStdString key = GetGroupMapKeyFromPath(cmtarget, fullpath);
803   cmXCodeObject* group = this->GroupMap[key];
804   cmXCodeObject* children = group->GetObject("children");
805   if (!children->HasObject(fileRef))
806     {
807     children->AddObject(fileRef);
808     }
809   fileRef->AddAttribute("fileEncoding", this->CreateString("4"));
810
811   // Compute the extension.
812   std::string ext;
813   std::string realExt =
814     cmSystemTools::GetFilenameLastExtension(fullpath);
815   if(!realExt.empty())
816     {
817     // Extension without the leading '.'.
818     ext = realExt.substr(1);
819     }
820
821   std::string sourcecode = GetSourcecodeValueFromFileExtension(ext, lang);
822
823   fileRef->AddAttribute("lastKnownFileType",
824                         this->CreateString(sourcecode.c_str()));
825
826   // Store the file path relative to the top of the source tree.
827   std::string path = this->RelativeToSource(fullpath.c_str());
828   std::string name = cmSystemTools::GetFilenameName(path.c_str());
829   const char* sourceTree = (cmSystemTools::FileIsFullPath(path.c_str())?
830                             "<absolute>" : "SOURCE_ROOT");
831   fileRef->AddAttribute("name", this->CreateString(name.c_str()));
832   fileRef->AddAttribute("path", this->CreateString(path.c_str()));
833   fileRef->AddAttribute("sourceTree", this->CreateString(sourceTree));
834   if(this->XcodeVersion == 15)
835     {
836     fileRef->AddAttribute("refType", this->CreateString("4"));
837     }
838   return fileRef;
839 }
840
841 //----------------------------------------------------------------------------
842 cmXCodeObject*
843 cmGlobalXCodeGenerator::CreateXCodeFileReference(cmSourceFile* sf,
844                                                  cmTarget& cmtarget)
845 {
846   const char* lang =
847     this->CurrentLocalGenerator->GetSourceFileLanguage(*sf);
848   if (!lang)
849     {
850     lang = "";
851     }
852
853   return this->CreateXCodeFileReferenceFromPath(
854     sf->GetFullPath(), cmtarget, lang);
855 }
856
857 //----------------------------------------------------------------------------
858 bool cmGlobalXCodeGenerator::SpecialTargetEmitted(std::string const& tname)
859 {
860   if(tname == "ALL_BUILD" || tname == "XCODE_DEPEND_HELPER" ||
861      tname == "install" || tname == "package" || tname == "RUN_TESTS" ||
862      tname == CMAKE_CHECK_BUILD_SYSTEM_TARGET )
863     {
864     if(this->TargetDoneSet.find(tname) != this->TargetDoneSet.end())
865       {
866       return true;
867       }
868     this->TargetDoneSet.insert(tname);
869     return false;
870     }
871   return false;
872 }
873
874 //----------------------------------------------------------------------------
875 void cmGlobalXCodeGenerator::SetCurrentLocalGenerator(cmLocalGenerator* gen)
876 {
877   this->CurrentLocalGenerator = gen;
878   this->CurrentMakefile = gen->GetMakefile();
879   std::string outdir =
880     cmSystemTools::CollapseFullPath(this->CurrentMakefile->
881                                     GetCurrentOutputDirectory());
882   cmSystemTools::SplitPath(outdir.c_str(),
883                            this->CurrentOutputDirectoryComponents);
884
885   // Select the current set of configuration types.
886   this->CurrentConfigurationTypes.clear();
887   this->CurrentMakefile->GetConfigurations(this->CurrentConfigurationTypes);
888   if(this->CurrentConfigurationTypes.empty())
889     {
890     this->CurrentConfigurationTypes.push_back("");
891     }
892 }
893
894 //----------------------------------------------------------------------------
895 void
896 cmGlobalXCodeGenerator::CreateXCodeTargets(cmLocalGenerator* gen,
897                                            std::vector<cmXCodeObject*>&
898                                            targets)
899 {
900   this->SetCurrentLocalGenerator(gen);
901   cmTargets &tgts = this->CurrentMakefile->GetTargets();
902   for(cmTargets::iterator l = tgts.begin(); l != tgts.end(); l++)
903     {
904     cmTarget& cmtarget = l->second;
905
906     // make sure ALL_BUILD, INSTALL, etc are only done once
907     if(this->SpecialTargetEmitted(l->first.c_str()))
908       {
909       continue;
910       }
911
912     if(cmtarget.GetType() == cmTarget::UTILITY ||
913        cmtarget.GetType() == cmTarget::GLOBAL_TARGET)
914       {
915       targets.push_back(this->CreateUtilityTarget(cmtarget));
916       continue;
917       }
918
919     // organize the sources
920     std::vector<cmSourceFile*> const &classes = cmtarget.GetSourceFiles();
921     std::vector<cmXCodeObject*> externalObjFiles;
922     std::vector<cmXCodeObject*> headerFiles;
923     std::vector<cmXCodeObject*> resourceFiles;
924     std::vector<cmXCodeObject*> sourceFiles;
925     for(std::vector<cmSourceFile*>::const_iterator i = classes.begin();
926         i != classes.end(); ++i)
927       {
928       cmXCodeObject* xsf =
929         this->CreateXCodeSourceFile(this->CurrentLocalGenerator,
930                                     *i, cmtarget);
931       cmXCodeObject* fr = xsf->GetObject("fileRef");
932       cmXCodeObject* filetype =
933         fr->GetObject()->GetObject("lastKnownFileType");
934
935       cmTarget::SourceFileFlags tsFlags =
936         cmtarget.GetTargetSourceFileFlags(*i);
937
938       if(strcmp(filetype->GetString(), "compiled.mach-o.objfile") == 0)
939         {
940         externalObjFiles.push_back(xsf);
941         }
942       else if(this->IsHeaderFile(*i) ||
943         (tsFlags.Type == cmTarget::SourceFileTypePrivateHeader) ||
944         (tsFlags.Type == cmTarget::SourceFileTypePublicHeader))
945         {
946         headerFiles.push_back(xsf);
947         }
948       else if(tsFlags.Type == cmTarget::SourceFileTypeResource)
949         {
950         resourceFiles.push_back(xsf);
951         }
952       else if(!(*i)->GetPropertyAsBool("HEADER_FILE_ONLY"))
953         {
954         // Include this file in the build if it has a known language
955         // and has not been listed as an ignored extension for this
956         // generator.
957         if(this->CurrentLocalGenerator->GetSourceFileLanguage(**i) &&
958            !this->IgnoreFile((*i)->GetExtension().c_str()))
959           {
960           sourceFiles.push_back(xsf);
961           }
962         }
963       }
964
965     // Add object library contents as external objects. (Equivalent to
966     // the externalObjFiles above, except each one is not a cmSourceFile
967     // within the target.)
968     std::vector<std::string> objs;
969     this->GetGeneratorTarget(&cmtarget)->UseObjectLibraries(objs);
970     for(std::vector<std::string>::const_iterator
971           oi = objs.begin(); oi != objs.end(); ++oi)
972       {
973       std::string obj = *oi;
974       cmXCodeObject* xsf =
975         this->CreateXCodeSourceFileFromPath(obj, cmtarget, "");
976       externalObjFiles.push_back(xsf);
977       }
978
979     // some build phases only apply to bundles and/or frameworks
980     bool isFrameworkTarget = cmtarget.IsFrameworkOnApple();
981     bool isBundleTarget = cmtarget.GetPropertyAsBool("MACOSX_BUNDLE");
982     bool isCFBundleTarget = cmtarget.IsCFBundleOnApple();
983
984     cmXCodeObject* buildFiles = 0;
985
986     // create source build phase
987     cmXCodeObject* sourceBuildPhase = 0;
988     if (!sourceFiles.empty())
989       {
990       sourceBuildPhase =
991         this->CreateObject(cmXCodeObject::PBXSourcesBuildPhase);
992       sourceBuildPhase->SetComment("Sources");
993       sourceBuildPhase->AddAttribute("buildActionMask",
994                                      this->CreateString("2147483647"));
995       buildFiles = this->CreateObject(cmXCodeObject::OBJECT_LIST);
996       for(std::vector<cmXCodeObject*>::iterator i = sourceFiles.begin();
997           i != sourceFiles.end(); ++i)
998         {
999         buildFiles->AddObject(*i);
1000         }
1001       sourceBuildPhase->AddAttribute("files", buildFiles);
1002       sourceBuildPhase->AddAttribute("runOnlyForDeploymentPostprocessing",
1003                                      this->CreateString("0"));
1004       }
1005
1006     // create header build phase - only for framework targets
1007     cmXCodeObject* headerBuildPhase = 0;
1008     if (!headerFiles.empty() && isFrameworkTarget)
1009       {
1010       headerBuildPhase =
1011         this->CreateObject(cmXCodeObject::PBXHeadersBuildPhase);
1012       headerBuildPhase->SetComment("Headers");
1013       headerBuildPhase->AddAttribute("buildActionMask",
1014                                      this->CreateString("2147483647"));
1015       buildFiles = this->CreateObject(cmXCodeObject::OBJECT_LIST);
1016       for(std::vector<cmXCodeObject*>::iterator i = headerFiles.begin();
1017           i != headerFiles.end(); ++i)
1018         {
1019         buildFiles->AddObject(*i);
1020         }
1021       headerBuildPhase->AddAttribute("files", buildFiles);
1022       headerBuildPhase->AddAttribute("runOnlyForDeploymentPostprocessing",
1023                                      this->CreateString("0"));
1024       }
1025
1026     // create resource build phase - only for framework or bundle targets
1027     cmXCodeObject* resourceBuildPhase = 0;
1028     if (!resourceFiles.empty() &&
1029         (isFrameworkTarget || isBundleTarget || isCFBundleTarget))
1030       {
1031       resourceBuildPhase =
1032         this->CreateObject(cmXCodeObject::PBXResourcesBuildPhase);
1033       resourceBuildPhase->SetComment("Resources");
1034       resourceBuildPhase->AddAttribute("buildActionMask",
1035                                        this->CreateString("2147483647"));
1036       buildFiles = this->CreateObject(cmXCodeObject::OBJECT_LIST);
1037       for(std::vector<cmXCodeObject*>::iterator i = resourceFiles.begin();
1038           i != resourceFiles.end(); ++i)
1039         {
1040         buildFiles->AddObject(*i);
1041         }
1042       resourceBuildPhase->AddAttribute("files", buildFiles);
1043       resourceBuildPhase->AddAttribute("runOnlyForDeploymentPostprocessing",
1044                                      this->CreateString("0"));
1045       }
1046
1047     // create vector of "non-resource content file" build phases - only for
1048     // framework or bundle targets
1049     std::vector<cmXCodeObject*> contentBuildPhases;
1050     if (isFrameworkTarget || isBundleTarget || isCFBundleTarget)
1051       {
1052       typedef std::map<cmStdString, std::vector<cmSourceFile*> >
1053         mapOfVectorOfSourceFiles;
1054       mapOfVectorOfSourceFiles bundleFiles;
1055       for(std::vector<cmSourceFile*>::const_iterator i = classes.begin();
1056           i != classes.end(); ++i)
1057         {
1058         cmTarget::SourceFileFlags tsFlags =
1059           cmtarget.GetTargetSourceFileFlags(*i);
1060         if(tsFlags.Type == cmTarget::SourceFileTypeMacContent)
1061           {
1062           bundleFiles[tsFlags.MacFolder].push_back(*i);
1063           }
1064         }
1065       mapOfVectorOfSourceFiles::iterator mit;
1066       for ( mit = bundleFiles.begin(); mit != bundleFiles.end(); ++ mit )
1067         {
1068         cmXCodeObject* copyFilesBuildPhase =
1069           this->CreateObject(cmXCodeObject::PBXCopyFilesBuildPhase);
1070         copyFilesBuildPhase->SetComment("Copy files");
1071         copyFilesBuildPhase->AddAttribute("buildActionMask",
1072           this->CreateString("2147483647"));
1073         copyFilesBuildPhase->AddAttribute("dstSubfolderSpec",
1074           this->CreateString("6"));
1075         cmOStringStream ostr;
1076         if (cmtarget.IsFrameworkOnApple())
1077           {
1078           // dstPath in frameworks is relative to Versions/<version>
1079           ostr << mit->first;
1080           }
1081         else if ( mit->first != "MacOS" )
1082           {
1083           // dstPath in bundles is relative to Contents/MacOS
1084           ostr << "../" << mit->first.c_str();
1085           }
1086         copyFilesBuildPhase->AddAttribute("dstPath",
1087           this->CreateString(ostr.str().c_str()));
1088         copyFilesBuildPhase->AddAttribute(
1089           "runOnlyForDeploymentPostprocessing", this->CreateString("0"));
1090         buildFiles = this->CreateObject(cmXCodeObject::OBJECT_LIST);
1091         copyFilesBuildPhase->AddAttribute("files", buildFiles);
1092         std::vector<cmSourceFile*>::iterator sfIt;
1093         for ( sfIt = mit->second.begin(); sfIt != mit->second.end(); ++ sfIt )
1094           {
1095           cmXCodeObject* xsf =
1096             this->CreateXCodeSourceFile(this->CurrentLocalGenerator,
1097                                         *sfIt, cmtarget);
1098           buildFiles->AddObject(xsf);
1099           }
1100         contentBuildPhases.push_back(copyFilesBuildPhase);
1101         }
1102       }
1103
1104     // create framework build phase
1105     cmXCodeObject* frameworkBuildPhase = 0;
1106     if (!externalObjFiles.empty())
1107       {
1108       frameworkBuildPhase =
1109         this->CreateObject(cmXCodeObject::PBXFrameworksBuildPhase);
1110       frameworkBuildPhase->SetComment("Frameworks");
1111       frameworkBuildPhase->AddAttribute("buildActionMask",
1112                                         this->CreateString("2147483647"));
1113       buildFiles = this->CreateObject(cmXCodeObject::OBJECT_LIST);
1114       frameworkBuildPhase->AddAttribute("files", buildFiles);
1115       for(std::vector<cmXCodeObject*>::iterator i =  externalObjFiles.begin();
1116           i != externalObjFiles.end(); ++i)
1117         {
1118         buildFiles->AddObject(*i);
1119         }
1120       frameworkBuildPhase->AddAttribute("runOnlyForDeploymentPostprocessing",
1121                                         this->CreateString("0"));
1122       }
1123
1124     // create list of build phases and create the Xcode target
1125     cmXCodeObject* buildPhases =
1126       this->CreateObject(cmXCodeObject::OBJECT_LIST);
1127
1128     this->CreateCustomCommands(buildPhases, sourceBuildPhase,
1129                                headerBuildPhase, resourceBuildPhase,
1130                                contentBuildPhases,
1131                                frameworkBuildPhase, cmtarget);
1132
1133     targets.push_back(this->CreateXCodeTarget(cmtarget, buildPhases));
1134     }
1135 }
1136
1137 //----------------------------------------------------------------------------
1138 void cmGlobalXCodeGenerator::ForceLinkerLanguages()
1139 {
1140   // This makes sure all targets link using the proper language.
1141   for(std::map<cmStdString, cmTarget*>::const_iterator
1142         ti = this->TotalTargets.begin(); ti != this->TotalTargets.end(); ++ti)
1143     {
1144     this->ForceLinkerLanguage(*ti->second);
1145     }
1146 }
1147
1148 //----------------------------------------------------------------------------
1149 void cmGlobalXCodeGenerator::ForceLinkerLanguage(cmTarget& cmtarget)
1150 {
1151   // This matters only for targets that link.
1152   if(cmtarget.GetType() != cmTarget::EXECUTABLE &&
1153      cmtarget.GetType() != cmTarget::SHARED_LIBRARY &&
1154      cmtarget.GetType() != cmTarget::MODULE_LIBRARY)
1155     {
1156     return;
1157     }
1158
1159   const char* llang = cmtarget.GetLinkerLanguage("NOCONFIG");
1160   if(!llang) { return; }
1161
1162   // If the language is compiled as a source trust Xcode to link with it.
1163   cmTarget::LinkImplementation const* impl =
1164     cmtarget.GetLinkImplementation("NOCONFIG");
1165   for(std::vector<std::string>::const_iterator li = impl->Languages.begin();
1166       li != impl->Languages.end(); ++li)
1167     {
1168     if(*li == llang) { return; }
1169     }
1170
1171   // Add an empty source file to the target that compiles with the
1172   // linker language.  This should convince Xcode to choose the proper
1173   // language.
1174   cmMakefile* mf = cmtarget.GetMakefile();
1175   std::string fname = mf->GetCurrentOutputDirectory();
1176   fname += cmake::GetCMakeFilesDirectory();
1177   fname += "/";
1178   fname += cmtarget.GetName();
1179   fname += "-CMakeForceLinker";
1180   fname += ".";
1181   fname += cmSystemTools::LowerCase(llang);
1182   {
1183   cmGeneratedFileStream fout(fname.c_str());
1184   fout << "\n";
1185   }
1186   if(cmSourceFile* sf = mf->GetOrCreateSource(fname.c_str()))
1187     {
1188     sf->SetProperty("LANGUAGE", llang);
1189     cmtarget.AddSourceFile(sf);
1190     }
1191 }
1192
1193 //----------------------------------------------------------------------------
1194 bool cmGlobalXCodeGenerator::IsHeaderFile(cmSourceFile* sf)
1195 {
1196   const std::vector<std::string>& hdrExts =
1197     this->CurrentMakefile->GetHeaderExtensions();
1198   return (std::find(hdrExts.begin(), hdrExts.end(), sf->GetExtension()) !=
1199           hdrExts.end());
1200 }
1201
1202 //----------------------------------------------------------------------------
1203 cmXCodeObject*
1204 cmGlobalXCodeGenerator::CreateBuildPhase(const char* name,
1205                                          const char* name2,
1206                                          cmTarget& cmtarget,
1207                                          const std::vector<cmCustomCommand>&
1208                                          commands)
1209 {
1210   if(commands.size() == 0 && strcmp(name, "CMake ReRun") != 0)
1211     {
1212     return 0;
1213     }
1214   cmXCodeObject* buildPhase =
1215     this->CreateObject(cmXCodeObject::PBXShellScriptBuildPhase);
1216   buildPhase->AddAttribute("buildActionMask",
1217                            this->CreateString("2147483647"));
1218   cmXCodeObject* buildFiles = this->CreateObject(cmXCodeObject::OBJECT_LIST);
1219   buildPhase->AddAttribute("files", buildFiles);
1220   buildPhase->AddAttribute("name",
1221                            this->CreateString(name));
1222   buildPhase->AddAttribute("runOnlyForDeploymentPostprocessing",
1223                            this->CreateString("0"));
1224   buildPhase->AddAttribute("shellPath",
1225                            this->CreateString("/bin/sh"));
1226   this->AddCommandsToBuildPhase(buildPhase, cmtarget, commands,
1227                                 name2);
1228   return buildPhase;
1229 }
1230
1231 //----------------------------------------------------------------------------
1232 void cmGlobalXCodeGenerator::CreateCustomCommands(cmXCodeObject* buildPhases,
1233                                                   cmXCodeObject*
1234                                                   sourceBuildPhase,
1235                                                   cmXCodeObject*
1236                                                   headerBuildPhase,
1237                                                   cmXCodeObject*
1238                                                   resourceBuildPhase,
1239                                                   std::vector<cmXCodeObject*>
1240                                                   contentBuildPhases,
1241                                                   cmXCodeObject*
1242                                                   frameworkBuildPhase,
1243                                                   cmTarget& cmtarget)
1244 {
1245   std::vector<cmCustomCommand> const & prebuild
1246     = cmtarget.GetPreBuildCommands();
1247   std::vector<cmCustomCommand> const & prelink
1248     = cmtarget.GetPreLinkCommands();
1249   std::vector<cmCustomCommand> const & postbuild
1250     = cmtarget.GetPostBuildCommands();
1251   std::vector<cmSourceFile*>const &classes = cmtarget.GetSourceFiles();
1252   // add all the sources
1253   std::vector<cmCustomCommand> commands;
1254   for(std::vector<cmSourceFile*>::const_iterator i = classes.begin();
1255       i != classes.end(); ++i)
1256     {
1257     if((*i)->GetCustomCommand())
1258       {
1259       commands.push_back(*(*i)->GetCustomCommand());
1260       }
1261     }
1262   // create prebuild phase
1263   cmXCodeObject* cmakeRulesBuildPhase =
1264     this->CreateBuildPhase("CMake Rules",
1265                            "cmakeRulesBuildPhase",
1266                            cmtarget, commands);
1267   // create prebuild phase
1268   cmXCodeObject* preBuildPhase =
1269     this->CreateBuildPhase("CMake PreBuild Rules", "preBuildCommands",
1270                            cmtarget, prebuild);
1271   // create prelink phase
1272   cmXCodeObject* preLinkPhase =
1273     this->CreateBuildPhase("CMake PreLink Rules", "preLinkCommands",
1274                            cmtarget, prelink);
1275   // create postbuild phase
1276   cmXCodeObject* postBuildPhase =
1277     this->CreateBuildPhase("CMake PostBuild Rules", "postBuildPhase",
1278                            cmtarget, postbuild);
1279
1280   // The order here is the order they will be built in.
1281   // The order "headers, resources, sources" mimics a native project generated
1282   // from an xcode template...
1283   //
1284   if(preBuildPhase)
1285     {
1286     buildPhases->AddObject(preBuildPhase);
1287     }
1288   if(cmakeRulesBuildPhase)
1289     {
1290     buildPhases->AddObject(cmakeRulesBuildPhase);
1291     }
1292   if(headerBuildPhase)
1293     {
1294     buildPhases->AddObject(headerBuildPhase);
1295     }
1296   if(resourceBuildPhase)
1297     {
1298     buildPhases->AddObject(resourceBuildPhase);
1299     }
1300   std::vector<cmXCodeObject*>::iterator cit;
1301   for (cit = contentBuildPhases.begin(); cit != contentBuildPhases.end();
1302        ++cit)
1303     {
1304     buildPhases->AddObject(*cit);
1305     }
1306   if(sourceBuildPhase)
1307     {
1308     buildPhases->AddObject(sourceBuildPhase);
1309     }
1310   if(preLinkPhase)
1311     {
1312     buildPhases->AddObject(preLinkPhase);
1313     }
1314   if(frameworkBuildPhase)
1315     {
1316     buildPhases->AddObject(frameworkBuildPhase);
1317     }
1318   if(postBuildPhase)
1319     {
1320     buildPhases->AddObject(postBuildPhase);
1321     }
1322 }
1323
1324 //----------------------------------------------------------------------------
1325 // This function removes each occurence of the flag and returns the last one
1326 // (i.e., the dominant flag in GCC)
1327 std::string cmGlobalXCodeGenerator::ExtractFlag(const char* flag,
1328                                                 std::string& flags)
1329 {
1330   std::string retFlag;
1331   std::string::size_type pos = flags.rfind(flag);
1332   bool saved = false;
1333   while(pos != flags.npos)
1334     {
1335     if(pos == 0 || flags[pos-1]==' ')
1336       {
1337       while(pos < flags.size() && flags[pos] != ' ')
1338         {
1339         if(!saved)
1340           {
1341           retFlag += flags[pos];
1342           }
1343         flags[pos] = ' ';
1344         pos++;
1345         }
1346       }
1347       saved = true;
1348       pos = flags.rfind(flag);
1349     }
1350   return retFlag;
1351 }
1352
1353 //----------------------------------------------------------------------------
1354 void
1355 cmGlobalXCodeGenerator::AddCommandsToBuildPhase(cmXCodeObject* buildphase,
1356                                                 cmTarget& target,
1357                                                 std::vector<cmCustomCommand>
1358                                                 const & commands,
1359                                                 const char* name)
1360 {
1361
1362   // collect multiple outputs of custom commands into a set
1363   // which will be used for every configuration
1364   std::map<cmStdString, cmStdString> multipleOutputPairs;
1365   for(std::vector<cmCustomCommand>::const_iterator i = commands.begin();
1366       i != commands.end(); ++i)
1367     {
1368     cmCustomCommand const& cc = *i;
1369     if(!cc.GetCommandLines().empty())
1370       {
1371       const std::vector<std::string>& outputs = cc.GetOutputs();
1372       if(!outputs.empty())
1373         {
1374         // If there are more than one outputs treat the
1375         // first as the primary output and make the rest depend on it.
1376         std::vector<std::string>::const_iterator o = outputs.begin();
1377         std::string primaryOutput = this->ConvertToRelativeForMake(o->c_str());
1378         for(++o; o != outputs.end(); ++o)
1379           {
1380           std::string currentOutput=this->ConvertToRelativeForMake(o->c_str());
1381           multipleOutputPairs[currentOutput] = primaryOutput;
1382           }
1383         }
1384       }
1385     }
1386
1387   std::string dir = this->CurrentMakefile->GetCurrentOutputDirectory();
1388   dir += "/CMakeScripts";
1389   cmSystemTools::MakeDirectory(dir.c_str());
1390   std::string makefile = dir;
1391   makefile += "/";
1392   makefile += target.GetName();
1393   makefile += "_";
1394   makefile += name;
1395   makefile += ".make";
1396
1397   for (std::vector<std::string>::const_iterator currentConfig=
1398             this->CurrentConfigurationTypes.begin();
1399        currentConfig!=this->CurrentConfigurationTypes.end();
1400        currentConfig++ )
1401     {
1402     this->CreateCustomRulesMakefile(makefile.c_str(),
1403                                     target,
1404                                     commands,
1405                                     currentConfig->c_str(),
1406                                     multipleOutputPairs);
1407     }
1408
1409   std::string cdir = this->CurrentMakefile->GetCurrentOutputDirectory();
1410   cdir = this->ConvertToRelativeForXCode(cdir.c_str());
1411   std::string makecmd = "make -C ";
1412   makecmd += cdir;
1413   makecmd += " -f ";
1414   makecmd += this->ConvertToRelativeForMake(
1415                                           (makefile+"$CONFIGURATION").c_str());
1416   if(!multipleOutputPairs.empty())
1417     {
1418     makecmd += " cmake_check_multiple_outputs";
1419     }
1420   makecmd += " all";
1421   cmSystemTools::ReplaceString(makecmd, "\\ ", "\\\\ ");
1422   buildphase->AddAttribute("shellScript",
1423                            this->CreateString(makecmd.c_str()));
1424   buildphase->AddAttribute("showEnvVarsInLog",
1425                            this->CreateString("0"));
1426 }
1427
1428 //----------------------------------------------------------------------------
1429 void  cmGlobalXCodeGenerator
1430 ::CreateCustomRulesMakefile(const char* makefileBasename,
1431                             cmTarget& target,
1432                             std::vector<cmCustomCommand>
1433                             const & commands,
1434                             const char* configName,
1435                             const std::map<cmStdString,
1436                             cmStdString>& multipleOutputPairs
1437                            )
1438 {
1439   std::string makefileName=makefileBasename;
1440   if(this->XcodeVersion > 20)
1441     {
1442     makefileName+=configName;
1443     }
1444   cmGeneratedFileStream makefileStream(makefileName.c_str());
1445   if(!makefileStream)
1446     {
1447     return;
1448     }
1449   makefileStream.SetCopyIfDifferent(true);
1450   makefileStream << "# Generated by CMake, DO NOT EDIT\n";
1451   makefileStream << "# Custom rules for " << target.GetName() << "\n";
1452
1453   // disable the implicit rules
1454   makefileStream << ".SUFFIXES: " << "\n";
1455
1456   // have all depend on all outputs
1457   makefileStream << "all: ";
1458   std::map<const cmCustomCommand*, cmStdString> tname;
1459   int count = 0;
1460   for(std::vector<cmCustomCommand>::const_iterator i = commands.begin();
1461       i != commands.end(); ++i)
1462     {
1463     cmCustomCommand const& cc = *i;
1464     if(!cc.GetCommandLines().empty())
1465       {
1466       const std::vector<std::string>& outputs = cc.GetOutputs();
1467       if(!outputs.empty())
1468         {
1469         for(std::vector<std::string>::const_iterator o = outputs.begin();
1470             o != outputs.end(); ++o)
1471           {
1472           makefileStream
1473               << "\\\n\t" << this->ConvertToRelativeForMake(o->c_str());
1474           }
1475         }
1476       else
1477         {
1478         cmOStringStream str;
1479         str << "_buildpart_" << count++ ;
1480         tname[&cc] = std::string(target.GetName()) + str.str();
1481         makefileStream << "\\\n\t" << tname[&cc];
1482         }
1483       }
1484     }
1485   makefileStream << "\n\n";
1486   for(std::vector<cmCustomCommand>::const_iterator i = commands.begin();
1487       i != commands.end(); ++i)
1488     {
1489     cmCustomCommand const& cc = *i;
1490     if(!cc.GetCommandLines().empty())
1491       {
1492       cmCustomCommandGenerator ccg(cc, configName, this->CurrentMakefile);
1493       makefileStream << "\n";
1494       const std::vector<std::string>& outputs = cc.GetOutputs();
1495       if(!outputs.empty())
1496         {
1497         // There is at least one output, start the rule for it
1498         std::string primary_output =
1499             this->ConvertToRelativeForMake(outputs.begin()->c_str());
1500         makefileStream << primary_output << ": ";
1501         }
1502       else
1503         {
1504         // There are no outputs.  Use the generated force rule name.
1505         makefileStream << tname[&cc] << ": ";
1506         }
1507       for(std::vector<std::string>::const_iterator d =
1508           cc.GetDepends().begin();
1509           d != cc.GetDepends().end(); ++d)
1510         {
1511         std::string dep;
1512         if(this->CurrentLocalGenerator
1513            ->GetRealDependency(d->c_str(), configName, dep))
1514           {
1515           makefileStream << "\\\n" <<
1516             this->ConvertToRelativeForMake(dep.c_str());
1517           }
1518         }
1519       makefileStream << "\n";
1520
1521       if(const char* comment = cc.GetComment())
1522         {
1523         std::string echo_cmd = "echo ";
1524         echo_cmd += (this->CurrentLocalGenerator->
1525                      EscapeForShell(comment, cc.GetEscapeAllowMakeVars()));
1526         makefileStream << "\t" << echo_cmd.c_str() << "\n";
1527         }
1528
1529       // Add each command line to the set of commands.
1530       for(unsigned int c = 0; c < ccg.GetNumberOfCommands(); ++c)
1531         {
1532         // Build the command line in a single string.
1533         std::string cmd2 = ccg.GetCommand(c);
1534         cmSystemTools::ReplaceString(cmd2, "/./", "/");
1535         cmd2 = this->ConvertToRelativeForMake(cmd2.c_str());
1536         std::string cmd;
1537         if(cc.GetWorkingDirectory())
1538           {
1539           cmd += "cd ";
1540           cmd += this->ConvertToRelativeForMake(cc.GetWorkingDirectory());
1541           cmd += " && ";
1542           }
1543         cmd += cmd2;
1544         ccg.AppendArguments(c, cmd);
1545         makefileStream << "\t" << cmd.c_str() << "\n";
1546         }
1547       }
1548     }
1549
1550   // Add rules to deal with multiple outputs of custom commands.
1551   if(!multipleOutputPairs.empty())
1552     {
1553     makefileStream <<
1554         "\n# Dependencies of multiple outputs to their primary outputs \n";
1555
1556     for(std::map<cmStdString, cmStdString>::const_iterator o =
1557         multipleOutputPairs.begin(); o != multipleOutputPairs.end(); ++o)
1558       {
1559       makefileStream << o->first << ": " << o->second << "\n";
1560       }
1561
1562     makefileStream <<
1563         "\n"
1564         "cmake_check_multiple_outputs:\n";
1565     for(std::map<cmStdString, cmStdString>::const_iterator o =
1566         multipleOutputPairs.begin(); o != multipleOutputPairs.end(); ++o)
1567       {
1568       makefileStream << "\t@if [ ! -f "
1569           << o->first << " ]; then rm -f "
1570           << o->second << "; fi\n";
1571       }
1572     }
1573 }
1574
1575 //----------------------------------------------------------------------------
1576 void cmGlobalXCodeGenerator::CreateBuildSettings(cmTarget& target,
1577                                                  cmXCodeObject* buildSettings,
1578                                                  const char* configName)
1579 {
1580   std::string flags;
1581   std::string defFlags;
1582   bool shared = ((target.GetType() == cmTarget::SHARED_LIBRARY) ||
1583                  (target.GetType() == cmTarget::MODULE_LIBRARY));
1584   bool binary = ((target.GetType() == cmTarget::OBJECT_LIBRARY) ||
1585                  (target.GetType() == cmTarget::STATIC_LIBRARY) ||
1586                  (target.GetType() == cmTarget::EXECUTABLE) ||
1587                  shared);
1588
1589   const char* lang = target.GetLinkerLanguage(configName);
1590   std::string cflags;
1591   if(lang)
1592     {
1593     // for c++ projects get the c flags as well
1594     if(strcmp(lang, "CXX") == 0)
1595       {
1596       this->CurrentLocalGenerator->AddLanguageFlags(cflags, "C", configName);
1597       this->CurrentLocalGenerator->AddCMP0018Flags(cflags, &target, "C");
1598       }
1599
1600     // Add language-specific flags.
1601     this->CurrentLocalGenerator->AddLanguageFlags(flags, lang, configName);
1602
1603     // Add shared-library flags if needed.
1604     this->CurrentLocalGenerator->AddCMP0018Flags(flags, &target, lang);
1605     }
1606   else if(binary)
1607   {
1608     cmSystemTools::Error
1609       ("CMake can not determine linker language for target:",
1610        target.GetName());
1611     return;
1612   }
1613
1614   // Add define flags
1615   this->CurrentLocalGenerator->
1616     AppendFlags(defFlags,
1617                 this->CurrentMakefile->GetDefineFlags());
1618
1619   // Add preprocessor definitions for this target and configuration.
1620   BuildObjectListOrString ppDefs(this, this->XcodeVersion >= 30);
1621   if(this->XcodeVersion > 15)
1622     {
1623     this->AppendDefines(ppDefs,
1624       "CMAKE_INTDIR=\"$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)\"");
1625     }
1626   if(const char* exportMacro = target.GetExportMacro())
1627     {
1628     // Add the export symbol definition for shared library objects.
1629     this->AppendDefines(ppDefs, exportMacro);
1630     }
1631   this->AppendDefines
1632     (ppDefs, this->CurrentMakefile->GetProperty("COMPILE_DEFINITIONS"));
1633   this->AppendDefines(ppDefs, target.GetProperty("COMPILE_DEFINITIONS"));
1634   if(configName)
1635     {
1636     std::string defVarName = "COMPILE_DEFINITIONS_";
1637     defVarName += cmSystemTools::UpperCase(configName);
1638     this->AppendDefines
1639       (ppDefs, this->CurrentMakefile->GetProperty(defVarName.c_str()));
1640     this->AppendDefines(ppDefs, target.GetProperty(defVarName.c_str()));
1641     }
1642   buildSettings->AddAttribute
1643     ("GCC_PREPROCESSOR_DEFINITIONS", ppDefs.CreateList());
1644
1645   std::string extraLinkOptions;
1646   if(target.GetType() == cmTarget::EXECUTABLE)
1647     {
1648     extraLinkOptions =
1649       this->CurrentMakefile->GetRequiredDefinition("CMAKE_EXE_LINKER_FLAGS");
1650     std::string var = "CMAKE_EXE_LINKER_FLAGS_";
1651     var += cmSystemTools::UpperCase(configName);
1652     std::string val =
1653       this->CurrentMakefile->GetSafeDefinition(var.c_str());
1654     if(val.size())
1655       {
1656       extraLinkOptions += " ";
1657       extraLinkOptions += val;
1658       }
1659     }
1660   if(target.GetType() == cmTarget::SHARED_LIBRARY)
1661     {
1662     extraLinkOptions = this->CurrentMakefile->
1663       GetRequiredDefinition("CMAKE_SHARED_LINKER_FLAGS");
1664     }
1665   if(target.GetType() == cmTarget::MODULE_LIBRARY)
1666     {
1667     extraLinkOptions = this->CurrentMakefile->
1668       GetRequiredDefinition("CMAKE_MODULE_LINKER_FLAGS");
1669     }
1670
1671   const char* linkFlagsProp = "LINK_FLAGS";
1672   if(target.GetType() == cmTarget::OBJECT_LIBRARY ||
1673      target.GetType() == cmTarget::STATIC_LIBRARY)
1674     {
1675     linkFlagsProp = "STATIC_LIBRARY_FLAGS";
1676     }
1677   const char* targetLinkFlags = target.GetProperty(linkFlagsProp);
1678   if(targetLinkFlags)
1679     {
1680     extraLinkOptions += " ";
1681     extraLinkOptions += targetLinkFlags;
1682     }
1683   if(configName && *configName)
1684     {
1685     std::string linkFlagsVar = linkFlagsProp;
1686     linkFlagsVar += "_";
1687     linkFlagsVar += cmSystemTools::UpperCase(configName);
1688     if(const char* linkFlags = target.GetProperty(linkFlagsVar.c_str()))
1689       {
1690       extraLinkOptions += " ";
1691       extraLinkOptions += linkFlags;
1692       }
1693     }
1694
1695   // Set target-specific architectures.
1696   std::vector<std::string> archs;
1697   target.GetAppleArchs(configName, archs);
1698   if(!archs.empty())
1699     {
1700     // Enable ARCHS attribute.
1701     buildSettings->AddAttribute("ONLY_ACTIVE_ARCH",
1702                                 this->CreateString("NO"));
1703
1704     // Store ARCHS value.
1705     if(archs.size() == 1)
1706       {
1707       buildSettings->AddAttribute("ARCHS",
1708                                   this->CreateString(archs[0].c_str()));
1709       }
1710     else
1711       {
1712       cmXCodeObject* archObjects =
1713         this->CreateObject(cmXCodeObject::OBJECT_LIST);
1714       for(std::vector<std::string>::iterator i = archs.begin();
1715           i != archs.end(); i++)
1716         {
1717         archObjects->AddObject(this->CreateString((*i).c_str()));
1718         }
1719       buildSettings->AddAttribute("ARCHS", archObjects);
1720       }
1721     }
1722
1723   // Get the product name components.
1724   std::string pnprefix;
1725   std::string pnbase;
1726   std::string pnsuffix;
1727
1728   target.GetFullNameComponents(pnprefix, pnbase, pnsuffix, configName);
1729
1730   // Set attributes to specify the proper name for the target.
1731   std::string pndir = this->CurrentMakefile->GetCurrentOutputDirectory();
1732   if(target.GetType() == cmTarget::STATIC_LIBRARY ||
1733      target.GetType() == cmTarget::SHARED_LIBRARY ||
1734      target.GetType() == cmTarget::MODULE_LIBRARY ||
1735      target.GetType() == cmTarget::EXECUTABLE)
1736     {
1737     if(this->XcodeVersion >= 21)
1738       {
1739       if(!target.UsesDefaultOutputDir(configName, false))
1740         {
1741         std::string pncdir = target.GetDirectory(configName);
1742         buildSettings->AddAttribute("CONFIGURATION_BUILD_DIR",
1743                                     this->CreateString(pncdir.c_str()));
1744         }
1745       }
1746     else
1747       {
1748       buildSettings->AddAttribute("OBJROOT",
1749                                   this->CreateString(pndir.c_str()));
1750       pndir = target.GetDirectory(configName);
1751       }
1752
1753     buildSettings->AddAttribute("EXECUTABLE_PREFIX",
1754                                 this->CreateString(pnprefix.c_str()));
1755     buildSettings->AddAttribute("EXECUTABLE_SUFFIX",
1756                                 this->CreateString(pnsuffix.c_str()));
1757     }
1758   else if(target.GetType() == cmTarget::OBJECT_LIBRARY)
1759     {
1760     pnprefix = "lib";
1761     pnbase = target.GetName();
1762     pnsuffix = ".a";
1763
1764     if(this->XcodeVersion >= 21)
1765       {
1766       std::string pncdir = this->GetObjectsNormalDirectory(
1767         this->CurrentProject, configName, &target);
1768       buildSettings->AddAttribute("CONFIGURATION_BUILD_DIR",
1769                                   this->CreateString(pncdir.c_str()));
1770       }
1771     else
1772       {
1773       buildSettings->AddAttribute("OBJROOT",
1774                                   this->CreateString(pndir.c_str()));
1775       pndir = this->GetObjectsNormalDirectory(
1776         this->CurrentProject, configName, &target);
1777       }
1778     }
1779
1780   // Store the product name for all target types.
1781   buildSettings->AddAttribute("PRODUCT_NAME",
1782                               this->CreateString(pnbase.c_str()));
1783   buildSettings->AddAttribute("SYMROOT",
1784                               this->CreateString(pndir.c_str()));
1785
1786   // Handle settings for each target type.
1787   switch(target.GetType())
1788     {
1789     case cmTarget::OBJECT_LIBRARY:
1790     case cmTarget::STATIC_LIBRARY:
1791     {
1792     buildSettings->AddAttribute("LIBRARY_STYLE",
1793                                 this->CreateString("STATIC"));
1794     break;
1795     }
1796
1797     case cmTarget::MODULE_LIBRARY:
1798     {
1799     buildSettings->AddAttribute("LIBRARY_STYLE",
1800                                 this->CreateString("BUNDLE"));
1801     if (target.GetPropertyAsBool("BUNDLE"))
1802       {
1803       // It turns out that a BUNDLE is basically the same
1804       // in many ways as an application bundle, as far as
1805       // link flags go
1806       std::string createFlags =
1807         this->LookupFlags("CMAKE_SHARED_MODULE_CREATE_", lang, "_FLAGS",
1808                           "-bundle");
1809       if(!createFlags.empty())
1810         {
1811         extraLinkOptions += " ";
1812         extraLinkOptions += createFlags;
1813         }
1814       std::string plist = this->ComputeInfoPListLocation(target);
1815       // Xcode will create the final version of Info.plist at build time,
1816       // so let it replace the cfbundle name. This avoids creating
1817       // a per-configuration Info.plist file. The cfbundle plist
1818       // is very similar to the application bundle plist
1819       this->CurrentLocalGenerator
1820         ->GenerateAppleInfoPList(&target, "$(EXECUTABLE_NAME)",
1821                                  plist.c_str());
1822       std::string path =
1823         this->ConvertToRelativeForXCode(plist.c_str());
1824       buildSettings->AddAttribute("INFOPLIST_FILE",
1825                                   this->CreateString(path.c_str()));
1826       }
1827     else if(this->XcodeVersion >= 22)
1828       {
1829       buildSettings->AddAttribute("MACH_O_TYPE",
1830                                   this->CreateString("mh_bundle"));
1831       buildSettings->AddAttribute("GCC_DYNAMIC_NO_PIC",
1832                                   this->CreateString("NO"));
1833       // Add the flags to create an executable.
1834       std::string createFlags =
1835         this->LookupFlags("CMAKE_", lang, "_LINK_FLAGS", "");
1836       if(!createFlags.empty())
1837         {
1838         extraLinkOptions += " ";
1839         extraLinkOptions += createFlags;
1840         }
1841       }
1842     else
1843       {
1844       // Add the flags to create a module.
1845       std::string createFlags =
1846         this->LookupFlags("CMAKE_SHARED_MODULE_CREATE_", lang, "_FLAGS",
1847                           "-bundle");
1848       if(!createFlags.empty())
1849         {
1850         extraLinkOptions += " ";
1851         extraLinkOptions += createFlags;
1852         }
1853       }
1854     break;
1855     }
1856     case cmTarget::SHARED_LIBRARY:
1857     {
1858     if(target.GetPropertyAsBool("FRAMEWORK"))
1859       {
1860       std::string version = target.GetFrameworkVersion();
1861       buildSettings->AddAttribute("FRAMEWORK_VERSION",
1862                                   this->CreateString(version.c_str()));
1863
1864       std::string plist = this->ComputeInfoPListLocation(target);
1865       // Xcode will create the final version of Info.plist at build time,
1866       // so let it replace the framework name. This avoids creating
1867       // a per-configuration Info.plist file.
1868       this->CurrentLocalGenerator
1869         ->GenerateFrameworkInfoPList(&target, "$(EXECUTABLE_NAME)",
1870                                      plist.c_str());
1871       std::string path =
1872         this->ConvertToRelativeForXCode(plist.c_str());
1873       buildSettings->AddAttribute("INFOPLIST_FILE",
1874                                   this->CreateString(path.c_str()));
1875       }
1876     else
1877       {
1878       // Add the flags to create a shared library.
1879       std::string createFlags =
1880         this->LookupFlags("CMAKE_SHARED_LIBRARY_CREATE_", lang, "_FLAGS",
1881                           "-dynamiclib");
1882       if(!createFlags.empty())
1883         {
1884         extraLinkOptions += " ";
1885         extraLinkOptions += createFlags;
1886         }
1887       }
1888
1889     buildSettings->AddAttribute("LIBRARY_STYLE",
1890                                 this->CreateString("DYNAMIC"));
1891     break;
1892     }
1893     case cmTarget::EXECUTABLE:
1894     {
1895     // Add the flags to create an executable.
1896     std::string createFlags =
1897       this->LookupFlags("CMAKE_", lang, "_LINK_FLAGS", "");
1898     if(!createFlags.empty())
1899       {
1900       extraLinkOptions += " ";
1901       extraLinkOptions += createFlags;
1902       }
1903
1904     // Handle bundles and normal executables separately.
1905     if(target.GetPropertyAsBool("MACOSX_BUNDLE"))
1906       {
1907       std::string plist = this->ComputeInfoPListLocation(target);
1908       // Xcode will create the final version of Info.plist at build time,
1909       // so let it replace the executable name.  This avoids creating
1910       // a per-configuration Info.plist file.
1911       this->CurrentLocalGenerator
1912         ->GenerateAppleInfoPList(&target, "$(EXECUTABLE_NAME)",
1913                                  plist.c_str());
1914       std::string path =
1915         this->ConvertToRelativeForXCode(plist.c_str());
1916       buildSettings->AddAttribute("INFOPLIST_FILE",
1917                                   this->CreateString(path.c_str()));
1918
1919       }
1920     }
1921     break;
1922     default:
1923       break;
1924     }
1925   if(this->XcodeVersion >= 22 && this->XcodeVersion < 40)
1926     {
1927     buildSettings->AddAttribute("PREBINDING",
1928                                 this->CreateString("NO"));
1929     }
1930
1931   BuildObjectListOrString dirs(this, this->XcodeVersion >= 30);
1932   BuildObjectListOrString fdirs(this, this->XcodeVersion >= 30);
1933   std::vector<std::string> includes;
1934   this->CurrentLocalGenerator->GetIncludeDirectories(includes, &target);
1935   std::set<cmStdString> emitted;
1936   emitted.insert("/System/Library/Frameworks");
1937   for(std::vector<std::string>::iterator i = includes.begin();
1938       i != includes.end(); ++i)
1939     {
1940     if(this->NameResolvesToFramework(i->c_str()))
1941       {
1942       std::string frameworkDir = *i;
1943       frameworkDir += "/../";
1944       frameworkDir = cmSystemTools::CollapseFullPath(frameworkDir.c_str());
1945       if(emitted.insert(frameworkDir).second)
1946         {
1947         fdirs.Add(this->XCodeEscapePath(frameworkDir.c_str()).c_str());
1948         }
1949       }
1950     else
1951       {
1952       std::string incpath =
1953         this->XCodeEscapePath(i->c_str());
1954       dirs.Add(incpath.c_str());
1955       }
1956     }
1957   std::vector<std::string>& frameworks = target.GetFrameworks();
1958   if(frameworks.size())
1959     {
1960     for(std::vector<std::string>::iterator fmIt = frameworks.begin();
1961         fmIt != frameworks.end(); ++fmIt)
1962       {
1963       if(emitted.insert(*fmIt).second)
1964         {
1965         fdirs.Add(this->XCodeEscapePath(fmIt->c_str()).c_str());
1966         }
1967       }
1968     }
1969   if(!fdirs.IsEmpty())
1970     {
1971     buildSettings->AddAttribute("FRAMEWORK_SEARCH_PATHS",
1972                                 fdirs.CreateList());
1973     }
1974   if(!dirs.IsEmpty())
1975     {
1976     buildSettings->AddAttribute("HEADER_SEARCH_PATHS",
1977                                 dirs.CreateList());
1978     }
1979   std::string oflagc = this->ExtractFlag("-O", cflags);
1980   char optLevel[2];
1981   optLevel[0] = '0';
1982   optLevel[1] = 0;
1983   if(oflagc.size() == 3)
1984     {
1985     optLevel[0] = oflagc[2];
1986     }
1987   if(oflagc.size() == 2)
1988     {
1989     optLevel[0] = '1';
1990     }
1991   std::string oflag = this->ExtractFlag("-O", flags);
1992   if(oflag.size() == 3)
1993     {
1994     optLevel[0] = oflag[2];
1995     }
1996   if(oflag.size() == 2)
1997     {
1998     optLevel[0] = '1';
1999     }
2000   std::string gflagc = this->ExtractFlag("-g", cflags);
2001   // put back gdwarf-2 if used since there is no way
2002   // to represent it in the gui, but we still want debug yes
2003   if(gflagc == "-gdwarf-2")
2004     {
2005     cflags += " ";
2006     cflags += gflagc;
2007     }
2008   std::string gflag = this->ExtractFlag("-g", flags);
2009   if(gflag == "-gdwarf-2")
2010     {
2011     flags += " ";
2012     flags += gflag;
2013     }
2014   const char* debugStr = "YES";
2015   // We can't set the Xcode flag differently depending on the language,
2016   // so put them back in this case.
2017   if( (lang && strcmp(lang, "CXX") == 0) && gflag != gflagc )
2018     {
2019     cflags += " ";
2020     cflags += gflagc;
2021     flags += " ";
2022     flags += gflag;
2023     debugStr = "NO";
2024     }
2025   if( gflag == "-g0" || gflag.size() == 0 )
2026     {
2027     debugStr = "NO";
2028     }
2029
2030   buildSettings->AddAttribute("GCC_GENERATE_DEBUGGING_SYMBOLS",
2031                               this->CreateString(debugStr));
2032   buildSettings->AddAttribute("GCC_OPTIMIZATION_LEVEL",
2033                               this->CreateString(optLevel));
2034   buildSettings->AddAttribute("GCC_SYMBOLS_PRIVATE_EXTERN",
2035                               this->CreateString("NO"));
2036   buildSettings->AddAttribute("GCC_INLINES_ARE_PRIVATE_EXTERN",
2037                               this->CreateString("NO"));
2038   if(lang && strcmp(lang, "CXX") == 0)
2039     {
2040     flags += " ";
2041     flags += defFlags;
2042     buildSettings->AddAttribute("OTHER_CPLUSPLUSFLAGS",
2043                                 this->CreateString(flags.c_str()));
2044     cflags += " ";
2045     cflags += defFlags;
2046     buildSettings->AddAttribute("OTHER_CFLAGS",
2047                                 this->CreateString(cflags.c_str()));
2048
2049     }
2050   else
2051     {
2052     flags += " ";
2053     flags += defFlags;
2054     buildSettings->AddAttribute("OTHER_CFLAGS",
2055                                 this->CreateString(flags.c_str()));
2056     }
2057
2058   // Add Fortran source format attribute if property is set.
2059   const char* format = 0;
2060   const char* tgtfmt = target.GetProperty("Fortran_FORMAT");
2061   switch(this->CurrentLocalGenerator->GetFortranFormat(tgtfmt))
2062     {
2063     case cmLocalGenerator::FortranFormatFixed: format = "fixed"; break;
2064     case cmLocalGenerator::FortranFormatFree: format = "free"; break;
2065     default: break;
2066     }
2067   if(format)
2068     {
2069     buildSettings->AddAttribute("IFORT_LANG_SRCFMT",
2070                                 this->CreateString(format));
2071     }
2072
2073   // Create the INSTALL_PATH attribute.
2074   std::string install_name_dir;
2075   if(target.GetType() == cmTarget::SHARED_LIBRARY)
2076     {
2077     // Get the install_name directory for the build tree.
2078     install_name_dir = target.GetInstallNameDirForBuildTree(configName, true);
2079     if(install_name_dir.empty())
2080       {
2081       // Xcode will not pass the -install_name option at all if INSTALL_PATH
2082       // is not given or is empty.  We must explicitly put the flag in the
2083       // link flags to create an install_name with just the library soname.
2084       extraLinkOptions += " -install_name ";
2085       extraLinkOptions += target.GetFullName(configName);
2086       }
2087     else
2088       {
2089       // Convert to a path for the native build tool.
2090       cmSystemTools::ConvertToUnixSlashes(install_name_dir);
2091       // do not escape spaces on this since it is only a single path
2092       }
2093     }
2094   buildSettings->AddAttribute("INSTALL_PATH",
2095                               this->CreateString(install_name_dir.c_str()));
2096
2097   buildSettings->AddAttribute("OTHER_LDFLAGS",
2098                               this->CreateString(extraLinkOptions.c_str()));
2099   buildSettings->AddAttribute("OTHER_REZFLAGS",
2100                               this->CreateString(""));
2101   buildSettings->AddAttribute("SECTORDER_FLAGS",
2102                               this->CreateString(""));
2103   buildSettings->AddAttribute("USE_HEADERMAP",
2104                               this->CreateString("NO"));
2105   if (this->XcodeVersion >= 30)
2106     {
2107     cmXCodeObject *group = this->CreateObject(cmXCodeObject::OBJECT_LIST);
2108     group->AddObject(this->CreateString("-Wmost"));
2109     group->AddObject(this->CreateString("-Wno-four-char-constants"));
2110     group->AddObject(this->CreateString("-Wno-unknown-pragmas"));
2111     buildSettings->AddAttribute("WARNING_CFLAGS", group);
2112     }
2113   else
2114     {
2115     buildSettings->AddAttribute("WARNING_CFLAGS",
2116                                 this->CreateString(
2117                                   "-Wmost -Wno-four-char-constants"
2118                                   " -Wno-unknown-pragmas"));
2119     }
2120
2121   // Runtime version information.
2122   if(target.GetType() == cmTarget::SHARED_LIBRARY)
2123     {
2124     int major;
2125     int minor;
2126     int patch;
2127
2128     // VERSION -> current_version
2129     target.GetTargetVersion(false, major, minor, patch);
2130     cmOStringStream v;
2131
2132     // Xcode always wants at least 1.0.0 or nothing
2133     if(!(major == 0 && minor == 0 && patch == 0))
2134       {
2135       v << major << "." << minor << "." << patch;
2136       }
2137     buildSettings->AddAttribute("DYLIB_CURRENT_VERSION",
2138                                 this->CreateString(v.str().c_str()));
2139
2140     // SOVERSION -> compatibility_version
2141     target.GetTargetVersion(true, major, minor, patch);
2142     cmOStringStream vso;
2143
2144     // Xcode always wants at least 1.0.0 or nothing
2145     if(!(major == 0 && minor == 0 && patch == 0))
2146       {
2147       vso << major << "." << minor << "." << patch;
2148       }
2149     buildSettings->AddAttribute("DYLIB_COMPATIBILITY_VERSION",
2150                                 this->CreateString(vso.str().c_str()));
2151     }
2152   // put this last so it can override existing settings
2153   // Convert "XCODE_ATTRIBUTE_*" properties directly.
2154   {
2155   cmPropertyMap const& props = target.GetProperties();
2156   for(cmPropertyMap::const_iterator i = props.begin();
2157       i != props.end(); ++i)
2158     {
2159     if(i->first.find("XCODE_ATTRIBUTE_") == 0)
2160       {
2161       buildSettings->AddAttribute(i->first.substr(16).c_str(),
2162                                   this->CreateString(i->second.GetValue()));
2163       }
2164     }
2165   }
2166 }
2167
2168 //----------------------------------------------------------------------------
2169 cmXCodeObject*
2170 cmGlobalXCodeGenerator::CreateUtilityTarget(cmTarget& cmtarget)
2171 {
2172   cmXCodeObject* shellBuildPhase =
2173     this->CreateObject(cmXCodeObject::PBXShellScriptBuildPhase);
2174   shellBuildPhase->AddAttribute("buildActionMask",
2175                                 this->CreateString("2147483647"));
2176   cmXCodeObject* buildFiles = this->CreateObject(cmXCodeObject::OBJECT_LIST);
2177   shellBuildPhase->AddAttribute("files", buildFiles);
2178   cmXCodeObject* inputPaths = this->CreateObject(cmXCodeObject::OBJECT_LIST);
2179   shellBuildPhase->AddAttribute("inputPaths", inputPaths);
2180   cmXCodeObject* outputPaths = this->CreateObject(cmXCodeObject::OBJECT_LIST);
2181   shellBuildPhase->AddAttribute("outputPaths", outputPaths);
2182   shellBuildPhase->AddAttribute("runOnlyForDeploymentPostprocessing",
2183                                 this->CreateString("0"));
2184   shellBuildPhase->AddAttribute("shellPath",
2185                                 this->CreateString("/bin/sh"));
2186   shellBuildPhase->AddAttribute("shellScript",
2187                                 this->CreateString(
2188                                   "# shell script goes here\nexit 0"));
2189   shellBuildPhase->AddAttribute("showEnvVarsInLog",
2190                                 this->CreateString("0"));
2191
2192   cmXCodeObject* target =
2193     this->CreateObject(cmXCodeObject::PBXAggregateTarget);
2194   target->SetComment(cmtarget.GetName());
2195   cmXCodeObject* buildPhases =
2196     this->CreateObject(cmXCodeObject::OBJECT_LIST);
2197   std::vector<cmXCodeObject*> emptyContentVector;
2198   this->CreateCustomCommands(buildPhases, 0, 0, 0, emptyContentVector, 0,
2199                              cmtarget);
2200   target->AddAttribute("buildPhases", buildPhases);
2201   if(this->XcodeVersion > 20)
2202     {
2203     this->AddConfigurations(target, cmtarget);
2204     }
2205   else
2206     {
2207     const char* theConfig =
2208       this->CurrentMakefile->GetDefinition("CMAKE_BUILD_TYPE");
2209     cmXCodeObject* buildSettings =
2210       this->CreateObject(cmXCodeObject::ATTRIBUTE_GROUP);
2211     this->CreateBuildSettings(cmtarget, buildSettings, theConfig);
2212     target->AddAttribute("buildSettings", buildSettings);
2213     }
2214   cmXCodeObject* dependencies =
2215     this->CreateObject(cmXCodeObject::OBJECT_LIST);
2216   target->AddAttribute("dependencies", dependencies);
2217   target->AddAttribute("name", this->CreateString(cmtarget.GetName()));
2218   target->AddAttribute("productName",this->CreateString(cmtarget.GetName()));
2219   target->SetTarget(&cmtarget);
2220
2221   // Add source files without build rules for editing convenience.
2222   if(cmtarget.GetType() == cmTarget::UTILITY)
2223     {
2224     std::vector<cmSourceFile*> const& sources = cmtarget.GetSourceFiles();
2225     for(std::vector<cmSourceFile*>::const_iterator i = sources.begin();
2226         i != sources.end(); ++i)
2227       {
2228       if(!(*i)->GetPropertyAsBool("GENERATED"))
2229         {
2230         this->CreateXCodeFileReference(*i, cmtarget);
2231         }
2232       }
2233     }
2234
2235   target->SetId(this->GetOrCreateId(
2236     cmtarget.GetName(), target->GetId()).c_str());
2237
2238   return target;
2239 }
2240
2241 //----------------------------------------------------------------------------
2242 std::string cmGlobalXCodeGenerator::AddConfigurations(cmXCodeObject* target,
2243                                                       cmTarget& cmtarget)
2244 {
2245   std::string configTypes =
2246     this->CurrentMakefile->GetRequiredDefinition("CMAKE_CONFIGURATION_TYPES");
2247   std::vector<std::string> configVectorIn;
2248   std::vector<std::string> configVector;
2249   configVectorIn.push_back(configTypes);
2250   cmSystemTools::ExpandList(configVectorIn, configVector);
2251   cmXCodeObject* configlist =
2252     this->CreateObject(cmXCodeObject::XCConfigurationList);
2253   cmXCodeObject* buildConfigurations =
2254     this->CreateObject(cmXCodeObject::OBJECT_LIST);
2255   configlist->AddAttribute("buildConfigurations", buildConfigurations);
2256   std::string comment = "Build configuration list for ";
2257   comment += cmXCodeObject::PBXTypeNames[target->GetIsA()];
2258   comment += " \"";
2259   comment += cmtarget.GetName();
2260   comment += "\"";
2261   configlist->SetComment(comment.c_str());
2262   target->AddAttribute("buildConfigurationList",
2263                        this->CreateObjectReference(configlist));
2264   for(unsigned int i = 0; i < configVector.size(); ++i)
2265     {
2266     cmXCodeObject* config =
2267       this->CreateObject(cmXCodeObject::XCBuildConfiguration);
2268     buildConfigurations->AddObject(config);
2269     cmXCodeObject* buildSettings =
2270       this->CreateObject(cmXCodeObject::ATTRIBUTE_GROUP);
2271     this->CreateBuildSettings(cmtarget, buildSettings,
2272                               configVector[i].c_str());
2273     config->AddAttribute("name", this->CreateString(configVector[i].c_str()));
2274     config->SetComment(configVector[i].c_str());
2275     config->AddAttribute("buildSettings", buildSettings);
2276     }
2277   if(configVector.size())
2278     {
2279     configlist->AddAttribute("defaultConfigurationName",
2280                              this->CreateString(configVector[0].c_str()));
2281     configlist->AddAttribute("defaultConfigurationIsVisible",
2282                              this->CreateString("0"));
2283     return configVector[0];
2284     }
2285   return "";
2286 }
2287
2288 //----------------------------------------------------------------------------
2289 const char* cmGlobalXCodeGenerator::GetTargetFileType(cmTarget& cmtarget)
2290 {
2291   switch(cmtarget.GetType())
2292     {
2293     case cmTarget::OBJECT_LIBRARY:
2294     case cmTarget::STATIC_LIBRARY:
2295       return "archive.ar";
2296     case cmTarget::MODULE_LIBRARY:
2297       if (cmtarget.IsCFBundleOnApple())
2298         return "wrapper.plug-in";
2299       else
2300         return ((this->XcodeVersion >= 22)?
2301               "compiled.mach-o.executable" : "compiled.mach-o.dylib");
2302     case cmTarget::SHARED_LIBRARY:
2303       return (cmtarget.GetPropertyAsBool("FRAMEWORK")?
2304               "wrapper.framework" : "compiled.mach-o.dylib");
2305     case cmTarget::EXECUTABLE:
2306       return "compiled.mach-o.executable";
2307     default: break;
2308     }
2309   return 0;
2310 }
2311
2312 //----------------------------------------------------------------------------
2313 const char* cmGlobalXCodeGenerator::GetTargetProductType(cmTarget& cmtarget)
2314 {
2315   switch(cmtarget.GetType())
2316     {
2317     case cmTarget::OBJECT_LIBRARY:
2318     case cmTarget::STATIC_LIBRARY:
2319       return "com.apple.product-type.library.static";
2320     case cmTarget::MODULE_LIBRARY:
2321       if (cmtarget.IsCFBundleOnApple())
2322         return "com.apple.product-type.bundle";
2323       else
2324         return ((this->XcodeVersion >= 22)?
2325                 "com.apple.product-type.tool" :
2326                 "com.apple.product-type.library.dynamic");
2327     case cmTarget::SHARED_LIBRARY:
2328       return (cmtarget.GetPropertyAsBool("FRAMEWORK")?
2329               "com.apple.product-type.framework" :
2330               "com.apple.product-type.library.dynamic");
2331     case cmTarget::EXECUTABLE:
2332       return (cmtarget.GetPropertyAsBool("MACOSX_BUNDLE")?
2333               "com.apple.product-type.application" :
2334               "com.apple.product-type.tool");
2335     default: break;
2336     }
2337   return 0;
2338 }
2339
2340 //----------------------------------------------------------------------------
2341 cmXCodeObject*
2342 cmGlobalXCodeGenerator::CreateXCodeTarget(cmTarget& cmtarget,
2343                                           cmXCodeObject* buildPhases)
2344 {
2345   cmXCodeObject* target =
2346     this->CreateObject(cmXCodeObject::PBXNativeTarget);
2347   target->AddAttribute("buildPhases", buildPhases);
2348   cmXCodeObject* buildRules = this->CreateObject(cmXCodeObject::OBJECT_LIST);
2349   target->AddAttribute("buildRules", buildRules);
2350   std::string defConfig;
2351   if(this->XcodeVersion > 20)
2352     {
2353     defConfig = this->AddConfigurations(target, cmtarget);
2354     }
2355   else
2356     {
2357     cmXCodeObject* buildSettings =
2358       this->CreateObject(cmXCodeObject::ATTRIBUTE_GROUP);
2359     defConfig = this->CurrentMakefile->GetSafeDefinition("CMAKE_BUILD_TYPE");
2360     this->CreateBuildSettings(cmtarget, buildSettings, defConfig.c_str());
2361     target->AddAttribute("buildSettings", buildSettings);
2362     }
2363   cmXCodeObject* dependencies =
2364     this->CreateObject(cmXCodeObject::OBJECT_LIST);
2365   target->AddAttribute("dependencies", dependencies);
2366   target->AddAttribute("name", this->CreateString(cmtarget.GetName()));
2367   target->AddAttribute("productName",this->CreateString(cmtarget.GetName()));
2368
2369   cmXCodeObject* fileRef =
2370     this->CreateObject(cmXCodeObject::PBXFileReference);
2371   if(const char* fileType = this->GetTargetFileType(cmtarget))
2372     {
2373     fileRef->AddAttribute("explicitFileType", this->CreateString(fileType));
2374     }
2375   std::string fullName;
2376   if(cmtarget.GetType() == cmTarget::OBJECT_LIBRARY)
2377     {
2378     fullName = "lib";
2379     fullName += cmtarget.GetName();
2380     fullName += ".a";
2381     }
2382   else
2383     {
2384     fullName = cmtarget.GetFullName(defConfig.c_str());
2385     }
2386   fileRef->AddAttribute("path", this->CreateString(fullName.c_str()));
2387   fileRef->AddAttribute("refType", this->CreateString("0"));
2388   fileRef->AddAttribute("sourceTree",
2389                         this->CreateString("BUILT_PRODUCTS_DIR"));
2390   fileRef->SetComment(cmtarget.GetName());
2391   target->AddAttribute("productReference",
2392                        this->CreateObjectReference(fileRef));
2393   if(const char* productType = this->GetTargetProductType(cmtarget))
2394     {
2395     target->AddAttribute("productType", this->CreateString(productType));
2396     }
2397   target->SetTarget(&cmtarget);
2398   target->SetId(this->GetOrCreateId(
2399     cmtarget.GetName(), target->GetId()).c_str());
2400   return target;
2401 }
2402
2403 //----------------------------------------------------------------------------
2404 cmXCodeObject* cmGlobalXCodeGenerator::FindXCodeTarget(cmTarget* t)
2405 {
2406   if(!t)
2407     {
2408     return 0;
2409     }
2410   for(std::vector<cmXCodeObject*>::iterator i = this->XCodeObjects.begin();
2411       i != this->XCodeObjects.end(); ++i)
2412     {
2413     cmXCodeObject* o = *i;
2414     if(o->GetTarget() == t)
2415       {
2416       return o;
2417       }
2418     }
2419   return 0;
2420 }
2421
2422 //----------------------------------------------------------------------------
2423 std::string cmGlobalXCodeGenerator::GetOrCreateId(const char* name,
2424                                                   const char* id)
2425 {
2426   std::string guidStoreName = name;
2427   guidStoreName += "_GUID_CMAKE";
2428   const char* storedGUID =
2429     this->CMakeInstance->GetCacheDefinition(guidStoreName.c_str());
2430
2431   if(storedGUID)
2432     {
2433     return storedGUID;
2434     }
2435
2436   this->CMakeInstance->AddCacheEntry(guidStoreName.c_str(),
2437     id, "Stored Xcode object GUID", cmCacheManager::INTERNAL);
2438
2439   return id;
2440 }
2441
2442 //----------------------------------------------------------------------------
2443 void cmGlobalXCodeGenerator::AddDependTarget(cmXCodeObject* target,
2444                                              cmXCodeObject* dependTarget)
2445 {
2446   // make sure a target does not depend on itself
2447   if(target == dependTarget)
2448     {
2449     return;
2450     }
2451   // now avoid circular references if dependTarget already
2452   // depends on target then skip it.  Circular references crashes
2453   // xcode
2454   cmXCodeObject* dependTargetDepends =
2455     dependTarget->GetObject("dependencies");
2456   if(dependTargetDepends)
2457     {
2458     if(dependTargetDepends->HasObject(target->GetPBXTargetDependency()))
2459       {
2460       return;
2461       }
2462     }
2463
2464   cmXCodeObject* targetdep = dependTarget->GetPBXTargetDependency();
2465   if(!targetdep)
2466     {
2467     cmXCodeObject* container =
2468       this->CreateObject(cmXCodeObject::PBXContainerItemProxy);
2469     container->SetComment("PBXContainerItemProxy");
2470     container->AddAttribute("containerPortal",
2471                             this->CreateObjectReference(this->RootObject));
2472     container->AddAttribute("proxyType", this->CreateString("1"));
2473     container->AddAttribute("remoteGlobalIDString",
2474                             this->CreateObjectReference(dependTarget));
2475     container->AddAttribute("remoteInfo",
2476                             this->CreateString(
2477                               dependTarget->GetTarget()->GetName()));
2478     targetdep =
2479       this->CreateObject(cmXCodeObject::PBXTargetDependency);
2480     targetdep->SetComment("PBXTargetDependency");
2481     targetdep->AddAttribute("target",
2482                             this->CreateObjectReference(dependTarget));
2483     targetdep->AddAttribute("targetProxy",
2484                             this->CreateObjectReference(container));
2485     dependTarget->SetPBXTargetDependency(targetdep);
2486     }
2487
2488   cmXCodeObject* depends = target->GetObject("dependencies");
2489   if(!depends)
2490     {
2491     cmSystemTools::
2492       Error("target does not have dependencies attribute error..");
2493
2494     }
2495   else
2496     {
2497     depends->AddUniqueObject(targetdep);
2498     }
2499 }
2500
2501 //----------------------------------------------------------------------------
2502 void cmGlobalXCodeGenerator::AppendOrAddBuildSetting(cmXCodeObject* settings,
2503                                                      const char* attribute,
2504                                                      const char* value)
2505 {
2506   if(settings)
2507     {
2508     cmXCodeObject* attr = settings->GetObject(attribute);
2509     if(!attr)
2510       {
2511       settings->AddAttribute(attribute, this->CreateString(value));
2512       }
2513     else
2514       {
2515       std::string oldValue = attr->GetString();
2516       oldValue += " ";
2517       oldValue += value;
2518       attr->SetString(oldValue.c_str());
2519       }
2520     }
2521 }
2522
2523 //----------------------------------------------------------------------------
2524 void cmGlobalXCodeGenerator
2525 ::AppendBuildSettingAttribute(cmXCodeObject* target,
2526                               const char* attribute,
2527                               const char* value,
2528                               const char* configName)
2529 {
2530   if(this->XcodeVersion < 21)
2531     {
2532     // There is only one configuration.  Add the setting to the buildSettings
2533     // of the target.
2534     this->AppendOrAddBuildSetting(target->GetObject("buildSettings"),
2535                                   attribute, value);
2536     }
2537   else
2538     {
2539     // There are multiple configurations.  Add the setting to the
2540     // buildSettings of the configuration name given.
2541     cmXCodeObject* configurationList =
2542       target->GetObject("buildConfigurationList")->GetObject();
2543     cmXCodeObject* buildConfigs =
2544       configurationList->GetObject("buildConfigurations");
2545     std::vector<cmXCodeObject*> list = buildConfigs->GetObjectList();
2546     // each configuration and the target itself has a buildSettings in it
2547     //list.push_back(target);
2548     for(std::vector<cmXCodeObject*>::iterator i = list.begin();
2549         i != list.end(); ++i)
2550       {
2551       if(configName)
2552         {
2553         if(strcmp((*i)->GetObject("name")->GetString(), configName) == 0)
2554           {
2555           cmXCodeObject* settings = (*i)->GetObject("buildSettings");
2556           this->AppendOrAddBuildSetting(settings, attribute, value);
2557           }
2558         }
2559       else
2560         {
2561         cmXCodeObject* settings = (*i)->GetObject("buildSettings");
2562         this->AppendOrAddBuildSetting(settings, attribute, value);
2563         }
2564       }
2565     }
2566 }
2567
2568 //----------------------------------------------------------------------------
2569 void cmGlobalXCodeGenerator
2570 ::AddDependAndLinkInformation(cmXCodeObject* target)
2571 {
2572   cmTarget* cmtarget = target->GetTarget();
2573   if(!cmtarget)
2574     {
2575     cmSystemTools::Error("Error no target on xobject\n");
2576     return;
2577     }
2578
2579   // Add dependencies on other CMake targets.
2580   TargetDependSet const& deps = this->GetTargetDirectDepends(*cmtarget);
2581   for(TargetDependSet::const_iterator i = deps.begin(); i != deps.end(); ++i)
2582     {
2583     if(cmXCodeObject* dptarget = this->FindXCodeTarget(*i))
2584       {
2585       this->AddDependTarget(target, dptarget);
2586       }
2587     }
2588
2589   // Skip link information for static libraries.
2590   if(cmtarget->GetType() == cmTarget::OBJECT_LIBRARY ||
2591      cmtarget->GetType() == cmTarget::STATIC_LIBRARY)
2592     {
2593     return;
2594     }
2595
2596   // Loop over configuration types and set per-configuration info.
2597   for(std::vector<std::string>::iterator i =
2598         this->CurrentConfigurationTypes.begin();
2599       i != this->CurrentConfigurationTypes.end(); ++i)
2600     {
2601     // Get the current configuration name.
2602     const char* configName = i->c_str();
2603     if(!*configName)
2604       {
2605       configName = 0;
2606       }
2607
2608     // Compute the link library and directory information.
2609     cmComputeLinkInformation* pcli = cmtarget->GetLinkInformation(configName);
2610     if(!pcli)
2611       {
2612       continue;
2613       }
2614     cmComputeLinkInformation& cli = *pcli;
2615
2616     // Add dependencies directly on library files.
2617     {
2618     std::vector<std::string> const& libDeps = cli.GetDepends();
2619     for(std::vector<std::string>::const_iterator j = libDeps.begin();
2620         j != libDeps.end(); ++j)
2621       {
2622       target->AddDependLibrary(configName, j->c_str());
2623       }
2624     }
2625
2626     // add the library search paths
2627     {
2628     std::vector<std::string> const& libDirs = cli.GetDirectories();
2629     std::string linkDirs;
2630     for(std::vector<std::string>::const_iterator libDir = libDirs.begin();
2631         libDir != libDirs.end(); ++libDir)
2632       {
2633       if(libDir->size() && *libDir != "/usr/lib")
2634         {
2635         if(this->XcodeVersion > 15)
2636           {
2637           // Now add the same one but append
2638           // $(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) to it:
2639           linkDirs += " ";
2640           linkDirs += this->XCodeEscapePath(
2641             (*libDir + "/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)").c_str());
2642           }
2643         linkDirs += " ";
2644         linkDirs += this->XCodeEscapePath(libDir->c_str());
2645         }
2646       }
2647     this->AppendBuildSettingAttribute(target, "LIBRARY_SEARCH_PATHS",
2648                                       linkDirs.c_str(), configName);
2649     }
2650
2651     // add the framework search paths
2652     {
2653     const char* sep = "";
2654     std::string fdirs;
2655     std::vector<std::string> const& fwDirs = cli.GetFrameworkPaths();
2656     for(std::vector<std::string>::const_iterator fdi = fwDirs.begin();
2657         fdi != fwDirs.end(); ++fdi)
2658       {
2659       fdirs += sep;
2660       sep = " ";
2661       fdirs += this->XCodeEscapePath(fdi->c_str());
2662       }
2663     if(!fdirs.empty())
2664       {
2665       this->AppendBuildSettingAttribute(target, "FRAMEWORK_SEARCH_PATHS",
2666                                         fdirs.c_str(), configName);
2667       }
2668     }
2669
2670     // now add the link libraries
2671     {
2672     std::string linkLibs;
2673     const char* sep = "";
2674     typedef cmComputeLinkInformation::ItemVector ItemVector;
2675     ItemVector const& libNames = cli.GetItems();
2676     for(ItemVector::const_iterator li = libNames.begin();
2677         li != libNames.end(); ++li)
2678       {
2679       linkLibs += sep;
2680       sep = " ";
2681       if(li->IsPath)
2682         {
2683         linkLibs += this->XCodeEscapePath(li->Value.c_str());
2684         }
2685       else
2686         {
2687         linkLibs += li->Value;
2688         }
2689       if(li->Target && !li->Target->IsImported())
2690         {
2691         target->AddDependTarget(configName, li->Target->GetName());
2692         }
2693       }
2694     this->AppendBuildSettingAttribute(target, "OTHER_LDFLAGS",
2695                                       linkLibs.c_str(), configName);
2696     }
2697     }
2698 }
2699
2700 //----------------------------------------------------------------------------
2701 void cmGlobalXCodeGenerator::CreateGroups(cmLocalGenerator* root,
2702                                           std::vector<cmLocalGenerator*>&
2703                                           generators)
2704 {
2705   for(std::vector<cmLocalGenerator*>::iterator i = generators.begin();
2706       i != generators.end(); ++i)
2707     {
2708     if(this->IsExcluded(root, *i))
2709       {
2710       continue;
2711       }
2712     cmMakefile* mf = (*i)->GetMakefile();
2713     std::vector<cmSourceGroup> sourceGroups = mf->GetSourceGroups();
2714     cmTargets &tgts = mf->GetTargets();
2715     for(cmTargets::iterator l = tgts.begin(); l != tgts.end(); l++)
2716       {
2717       cmTarget& cmtarget = l->second;
2718
2719       // Same skipping logic here as in CreateXCodeTargets so that we do not
2720       // end up with (empty anyhow) ALL_BUILD and XCODE_DEPEND_HELPER source
2721       // groups:
2722       //
2723       if(cmtarget.GetType() == cmTarget::GLOBAL_TARGET)
2724         {
2725         continue;
2726         }
2727
2728       // add the soon to be generated Info.plist file as a source for a
2729       // MACOSX_BUNDLE file
2730       if(cmtarget.GetPropertyAsBool("MACOSX_BUNDLE"))
2731         {
2732         std::string plist = this->ComputeInfoPListLocation(cmtarget);
2733         cmSourceFile* sf = mf->GetOrCreateSource(plist.c_str(), true);
2734         cmtarget.AddSourceFile(sf);
2735         }
2736
2737       std::vector<cmSourceFile*>  classes = cmtarget.GetSourceFiles();
2738
2739       // Put cmSourceFile instances in proper groups:
2740       for(std::vector<cmSourceFile*>::const_iterator s = classes.begin();
2741           s != classes.end(); s++)
2742         {
2743         cmSourceFile* sf = *s;
2744         // Add the file to the list of sources.
2745         std::string const& source = sf->GetFullPath();
2746         cmSourceGroup& sourceGroup =
2747           mf->FindSourceGroup(source.c_str(), sourceGroups);
2748         cmXCodeObject* pbxgroup =
2749           this->CreateOrGetPBXGroup(cmtarget, &sourceGroup);
2750         cmStdString key = GetGroupMapKey(cmtarget, sf);
2751         this->GroupMap[key] = pbxgroup;
2752         }
2753
2754       // Put OBJECT_LIBRARY objects in proper groups:
2755       std::vector<std::string> objs;
2756       this->GetGeneratorTarget(&cmtarget)->UseObjectLibraries(objs);
2757       for(std::vector<std::string>::const_iterator
2758             oi = objs.begin(); oi != objs.end(); ++oi)
2759         {
2760         std::string const& source = *oi;
2761         cmSourceGroup& sourceGroup =
2762           mf->FindSourceGroup(source.c_str(), sourceGroups);
2763         cmXCodeObject* pbxgroup =
2764           this->CreateOrGetPBXGroup(cmtarget, &sourceGroup);
2765         cmStdString key = GetGroupMapKeyFromPath(cmtarget, source);
2766         this->GroupMap[key] = pbxgroup;
2767         }
2768       }
2769     }
2770 }
2771
2772 cmXCodeObject *cmGlobalXCodeGenerator
2773 ::CreatePBXGroup(cmXCodeObject *parent, cmStdString name)
2774 {
2775   cmXCodeObject* parentChildren = NULL;
2776   if(parent)
2777     parentChildren = parent->GetObject("children");
2778   cmXCodeObject* group = this->CreateObject(cmXCodeObject::PBXGroup);
2779   cmXCodeObject* groupChildren =
2780   this->CreateObject(cmXCodeObject::OBJECT_LIST);
2781   group->AddAttribute("name", this->CreateString(name.c_str()));
2782   group->AddAttribute("children", groupChildren);
2783   if(this->XcodeVersion == 15)
2784   {
2785     group->AddAttribute("refType", this->CreateString("4"));
2786   }
2787   group->AddAttribute("sourceTree", this->CreateString("<group>"));
2788   if(parentChildren)
2789     parentChildren->AddObject(group);
2790   return group;
2791 }
2792
2793 //----------------------------------------------------------------------------
2794 cmXCodeObject* cmGlobalXCodeGenerator
2795 ::CreateOrGetPBXGroup(cmTarget& cmtarget, cmSourceGroup* sg)
2796 {
2797   cmStdString s;
2798   cmStdString target;
2799   const char *targetFolder= cmtarget.GetProperty("FOLDER");
2800   if(targetFolder) {
2801     target = targetFolder;
2802     target += "/";
2803   }
2804   target += cmtarget.GetName();
2805   s = target + "/";
2806   s += sg->GetFullName();
2807   std::map<cmStdString, cmXCodeObject* >::iterator it =
2808     this->GroupNameMap.find(s);
2809   if(it != this->GroupNameMap.end())
2810     {
2811     return it->second;
2812     }
2813
2814   it = this->TargetGroup.find(target);
2815   cmXCodeObject* tgroup = 0;
2816   if(it != this->TargetGroup.end())
2817     {
2818     tgroup = it->second;
2819     }
2820   else
2821     {
2822     std::vector<std::string> tgt_folders =
2823       cmSystemTools::tokenize(target, "/");
2824     cmStdString curr_tgt_folder;
2825     for(std::vector<std::string>::size_type i = 0; i < tgt_folders.size();i++)
2826       {
2827       curr_tgt_folder += tgt_folders[i];
2828       it = this->TargetGroup.find(curr_tgt_folder);
2829       if(it == this->TargetGroup.end())
2830         {
2831         tgroup = this->CreatePBXGroup(tgroup,tgt_folders[i]);
2832         this->TargetGroup[curr_tgt_folder] = tgroup;
2833         }
2834       else
2835         {
2836         tgroup = it->second;
2837         continue;
2838         }
2839       if(i == 0)
2840         {
2841         this->SourcesGroupChildren->AddObject(tgroup);
2842         }
2843       curr_tgt_folder += "/";
2844       }
2845     }
2846   this->TargetGroup[target] = tgroup;
2847
2848   // If it's the default source group (empty name) then put the source file
2849   // directly in the tgroup...
2850   //
2851   if (cmStdString(sg->GetFullName()) == "")
2852     {
2853     this->GroupNameMap[s] = tgroup;
2854     return tgroup;
2855     }
2856
2857   //It's a recursive folder structure, let's find the real parent group
2858   if(std::string(sg->GetFullName()) != std::string(sg->GetName()))
2859     {
2860     std::vector<std::string> folders =
2861       cmSystemTools::tokenize(sg->GetFullName(), "\\");
2862     cmStdString curr_folder = cmtarget.GetName();
2863     curr_folder += "/";
2864     for(std::vector<std::string>::size_type i = 0; i < folders.size();i++)
2865       {
2866       curr_folder += folders[i];
2867       std::map<cmStdString, cmXCodeObject* >::iterator i_folder =
2868         this->GroupNameMap.find(curr_folder);
2869       //Create new folder
2870       if(i_folder == this->GroupNameMap.end())
2871         {
2872         cmXCodeObject *group = this->CreatePBXGroup(tgroup,folders[i]);
2873         this->GroupNameMap[curr_folder] = group;
2874         tgroup = group;
2875         }
2876       else
2877         {
2878         tgroup = i_folder->second;
2879         }
2880       curr_folder = curr_folder + "\\";
2881       }
2882     return tgroup;
2883     }
2884   cmXCodeObject *group = this->CreatePBXGroup(tgroup,sg->GetName());
2885   this->GroupNameMap[s] = group;
2886   return group;
2887 }
2888
2889 //----------------------------------------------------------------------------
2890 void cmGlobalXCodeGenerator
2891 ::CreateXCodeObjects(cmLocalGenerator* root,
2892                      std::vector<cmLocalGenerator*>&
2893                      generators)
2894 {
2895   this->ClearXCodeObjects();
2896   this->RootObject = 0;
2897   this->SourcesGroupChildren = 0;
2898   this->ResourcesGroupChildren = 0;
2899   this->MainGroupChildren = 0;
2900   cmXCodeObject* group = this->CreateObject(cmXCodeObject::ATTRIBUTE_GROUP);
2901   group->AddAttribute("COPY_PHASE_STRIP", this->CreateString("NO"));
2902   cmXCodeObject* developBuildStyle =
2903     this->CreateObject(cmXCodeObject::PBXBuildStyle);
2904   cmXCodeObject* listObjs = this->CreateObject(cmXCodeObject::OBJECT_LIST);
2905   if(this->XcodeVersion == 15)
2906     {
2907     developBuildStyle->AddAttribute("name",
2908                                     this->CreateString("Development"));
2909     developBuildStyle->AddAttribute("buildSettings", group);
2910     listObjs->AddObject(developBuildStyle);
2911     group = this->CreateObject(cmXCodeObject::ATTRIBUTE_GROUP);
2912     group->AddAttribute("COPY_PHASE_STRIP", this->CreateString("YES"));
2913     cmXCodeObject* deployBuildStyle =
2914     this->CreateObject(cmXCodeObject::PBXBuildStyle);
2915     deployBuildStyle->AddAttribute("name", this->CreateString("Deployment"));
2916     deployBuildStyle->AddAttribute("buildSettings", group);
2917     listObjs->AddObject(deployBuildStyle);
2918     }
2919   else
2920     {
2921     for(unsigned int i = 0; i < this->CurrentConfigurationTypes.size(); ++i)
2922       {
2923       cmXCodeObject* buildStyle =
2924         this->CreateObject(cmXCodeObject::PBXBuildStyle);
2925       const char* name = this->CurrentConfigurationTypes[i].c_str();
2926       buildStyle->AddAttribute("name", this->CreateString(name));
2927       buildStyle->SetComment(name);
2928       cmXCodeObject* sgroup =
2929         this->CreateObject(cmXCodeObject::ATTRIBUTE_GROUP);
2930       sgroup->AddAttribute("COPY_PHASE_STRIP", this->CreateString("NO"));
2931       buildStyle->AddAttribute("buildSettings", sgroup);
2932       listObjs->AddObject(buildStyle);
2933       }
2934     }
2935
2936   cmXCodeObject* mainGroup = this->CreateObject(cmXCodeObject::PBXGroup);
2937   this->MainGroupChildren =
2938     this->CreateObject(cmXCodeObject::OBJECT_LIST);
2939   mainGroup->AddAttribute("children", this->MainGroupChildren);
2940   if(this->XcodeVersion == 15)
2941     {
2942     mainGroup->AddAttribute("refType", this->CreateString("4"));
2943     }
2944   mainGroup->AddAttribute("sourceTree", this->CreateString("<group>"));
2945
2946   cmXCodeObject* sourcesGroup = this->CreateObject(cmXCodeObject::PBXGroup);
2947   this->SourcesGroupChildren =
2948     this->CreateObject(cmXCodeObject::OBJECT_LIST);
2949   sourcesGroup->AddAttribute("name", this->CreateString("Sources"));
2950   sourcesGroup->AddAttribute("children", this->SourcesGroupChildren);
2951   if(this->XcodeVersion == 15)
2952     {
2953     sourcesGroup->AddAttribute("refType", this->CreateString("4"));
2954     }
2955   sourcesGroup->AddAttribute("sourceTree", this->CreateString("<group>"));
2956   this->MainGroupChildren->AddObject(sourcesGroup);
2957
2958   cmXCodeObject* resourcesGroup = this->CreateObject(cmXCodeObject::PBXGroup);
2959   this->ResourcesGroupChildren =
2960     this->CreateObject(cmXCodeObject::OBJECT_LIST);
2961   resourcesGroup->AddAttribute("name", this->CreateString("Resources"));
2962   resourcesGroup->AddAttribute("children", this->ResourcesGroupChildren);
2963   if(this->XcodeVersion == 15)
2964     {
2965     resourcesGroup->AddAttribute("refType", this->CreateString("4"));
2966     }
2967   resourcesGroup->AddAttribute("sourceTree", this->CreateString("<group>"));
2968   this->MainGroupChildren->AddObject(resourcesGroup);
2969
2970   // now create the cmake groups
2971   this->CreateGroups(root, generators);
2972
2973   cmXCodeObject* productGroup = this->CreateObject(cmXCodeObject::PBXGroup);
2974   productGroup->AddAttribute("name", this->CreateString("Products"));
2975   if(this->XcodeVersion == 15)
2976     {
2977     productGroup->AddAttribute("refType", this->CreateString("4"));
2978     }
2979   productGroup->AddAttribute("sourceTree", this->CreateString("<group>"));
2980   cmXCodeObject* productGroupChildren =
2981     this->CreateObject(cmXCodeObject::OBJECT_LIST);
2982   productGroup->AddAttribute("children", productGroupChildren);
2983   this->MainGroupChildren->AddObject(productGroup);
2984
2985
2986   this->RootObject = this->CreateObject(cmXCodeObject::PBXProject);
2987   this->RootObject->SetComment("Project object");
2988
2989   std::string project_id = "PROJECT_";
2990   project_id += root->GetMakefile()->GetProjectName();
2991   this->RootObject->SetId(this->GetOrCreateId(
2992     project_id.c_str(), this->RootObject->GetId()).c_str());
2993
2994   group = this->CreateObject(cmXCodeObject::ATTRIBUTE_GROUP);
2995   this->RootObject->AddAttribute("mainGroup",
2996                              this->CreateObjectReference(mainGroup));
2997   this->RootObject->AddAttribute("buildSettings", group);
2998   this->RootObject->AddAttribute("buildStyles", listObjs);
2999   this->RootObject->AddAttribute("hasScannedForEncodings",
3000                              this->CreateString("0"));
3001   if (this->XcodeVersion >= 30)
3002     {
3003     group = this->CreateObject(cmXCodeObject::ATTRIBUTE_GROUP);
3004     group->AddAttribute("BuildIndependentTargetsInParallel",
3005                         this->CreateString("YES"));
3006     this->RootObject->AddAttribute("attributes", group);
3007     if (this->XcodeVersion >= 32)
3008       this->RootObject->AddAttribute("compatibilityVersion",
3009                                      this->CreateString("Xcode 3.2"));
3010     else if (this->XcodeVersion >= 31)
3011       this->RootObject->AddAttribute("compatibilityVersion",
3012                                      this->CreateString("Xcode 3.1"));
3013     else
3014       this->RootObject->AddAttribute("compatibilityVersion",
3015                                      this->CreateString("Xcode 3.0"));
3016     }
3017   // Point Xcode at the top of the source tree.
3018   {
3019   std::string pdir =
3020     this->RelativeToBinary(root->GetMakefile()->GetCurrentDirectory());
3021   this->RootObject->AddAttribute("projectDirPath",
3022                                  this->CreateString(pdir.c_str()));
3023   this->RootObject->AddAttribute("projectRoot", this->CreateString(""));
3024   }
3025   cmXCodeObject* configlist =
3026     this->CreateObject(cmXCodeObject::XCConfigurationList);
3027   cmXCodeObject* buildConfigurations =
3028     this->CreateObject(cmXCodeObject::OBJECT_LIST);
3029   std::vector<cmXCodeObject*> configs;
3030   const char *defaultConfigName = "Debug";
3031   if(this->XcodeVersion == 15)
3032     {
3033     cmXCodeObject* configDebug =
3034       this->CreateObject(cmXCodeObject::XCBuildConfiguration);
3035     configDebug->AddAttribute("name", this->CreateString("Debug"));
3036     configs.push_back(configDebug);
3037     cmXCodeObject* configRelease =
3038       this->CreateObject(cmXCodeObject::XCBuildConfiguration);
3039     configRelease->AddAttribute("name", this->CreateString("Release"));
3040     configs.push_back(configRelease);
3041     }
3042   else
3043     {
3044     for(unsigned int i = 0; i < this->CurrentConfigurationTypes.size(); ++i)
3045       {
3046       const char* name = this->CurrentConfigurationTypes[i].c_str();
3047       if (0 == i)
3048         {
3049         defaultConfigName = name;
3050         }
3051       cmXCodeObject* config =
3052         this->CreateObject(cmXCodeObject::XCBuildConfiguration);
3053       config->AddAttribute("name", this->CreateString(name));
3054       configs.push_back(config);
3055       }
3056     }
3057   for(std::vector<cmXCodeObject*>::iterator c = configs.begin();
3058       c != configs.end(); ++c)
3059     {
3060     buildConfigurations->AddObject(*c);
3061     }
3062   configlist->AddAttribute("buildConfigurations", buildConfigurations);
3063
3064   std::string comment = "Build configuration list for PBXProject ";
3065   comment += " \"";
3066   comment += this->CurrentProject;
3067   comment += "\"";
3068   configlist->SetComment(comment.c_str());
3069   configlist->AddAttribute("defaultConfigurationIsVisible",
3070                            this->CreateString("0"));
3071   configlist->AddAttribute("defaultConfigurationName",
3072                            this->CreateString(defaultConfigName));
3073   cmXCodeObject* buildSettings =
3074       this->CreateObject(cmXCodeObject::ATTRIBUTE_GROUP);
3075   const char* osxArch =
3076       this->CurrentMakefile->GetDefinition("CMAKE_OSX_ARCHITECTURES");
3077   if(!osxArch || strlen(osxArch) == 0)
3078     {
3079     if(this->XcodeVersion >= 32)
3080       {
3081       osxArch = "$(ARCHS_STANDARD_32_64_BIT)";
3082       }
3083     else if(this->XcodeVersion == 31)
3084       {
3085       osxArch = "$(ARCHS_STANDARD_32_BIT)";
3086       }
3087     else if(this->XcodeVersion <= 30)
3088       {
3089 #ifdef __ppc__
3090       osxArch = "ppc";
3091 #endif
3092 #ifdef __i386
3093       osxArch = "i386";
3094 #endif
3095       }
3096     buildSettings->AddAttribute("ONLY_ACTIVE_ARCH",
3097                                 this->CreateString("YES"));
3098     }
3099
3100   const char* sysroot =
3101       this->CurrentMakefile->GetDefinition("CMAKE_OSX_SYSROOT");
3102   const char* sysrootDefault =
3103     this->CurrentMakefile->GetDefinition("CMAKE_OSX_SYSROOT_DEFAULT");
3104   const char* deploymentTarget =
3105     this->CurrentMakefile->GetDefinition("CMAKE_OSX_DEPLOYMENT_TARGET");
3106   if(osxArch && sysroot)
3107     {
3108     bool flagsUsed = false;
3109     // recompute this as it may have been changed since enable language
3110     this->Architectures.clear();
3111     cmSystemTools::ExpandListArgument(std::string(osxArch),
3112                                       this->Architectures);
3113     flagsUsed = true;
3114     buildSettings->AddAttribute("SDKROOT",
3115                                 this->CreateString(sysroot));
3116     std::string archString;
3117     const char* sep = "";
3118     for( std::vector<std::string>::iterator i =
3119            this->Architectures.begin();
3120          i != this->Architectures.end(); ++i)
3121       {
3122       archString += sep;
3123       archString += *i;
3124       sep = " ";
3125       }
3126     buildSettings->AddAttribute("ARCHS",
3127                                 this->CreateString(archString.c_str()));
3128     if(!flagsUsed && sysrootDefault &&
3129        strcmp(sysroot, sysrootDefault) != 0)
3130       {
3131       buildSettings->AddAttribute("SDKROOT",
3132                                   this->CreateString(sysroot));
3133       }
3134     }
3135   if(deploymentTarget && *deploymentTarget)
3136     {
3137     buildSettings->AddAttribute("MACOSX_DEPLOYMENT_TARGET",
3138                                 this->CreateString(deploymentTarget));
3139     }
3140
3141   // Put this last so it can override existing settings
3142   // Convert "CMAKE_XCODE_ATTRIBUTE_*" variables directly.
3143   {
3144     std::vector<std::string> vars = this->CurrentMakefile->GetDefinitions();
3145     for(std::vector<std::string>::const_iterator i = vars.begin();
3146         i != vars.end(); ++i)
3147     {
3148       if(i->find("CMAKE_XCODE_ATTRIBUTE_") == 0)
3149       {
3150         buildSettings->AddAttribute(i->substr(22).c_str(),
3151           this->CreateString(
3152             this->CurrentMakefile->GetDefinition(i->c_str())));
3153       }
3154     }
3155   }
3156
3157   std::string symroot = root->GetMakefile()->GetCurrentOutputDirectory();
3158   symroot += "/build";
3159   buildSettings->AddAttribute("SYMROOT", this->CreateString(symroot.c_str()));
3160
3161   for( std::vector<cmXCodeObject*>::iterator i = configs.begin();
3162        i != configs.end(); ++i)
3163     {
3164     (*i)->AddAttribute("buildSettings", buildSettings);
3165     }
3166
3167   this->RootObject->AddAttribute("buildConfigurationList",
3168                              this->CreateObjectReference(configlist));
3169
3170   std::vector<cmXCodeObject*> targets;
3171   for(std::vector<cmLocalGenerator*>::iterator i = generators.begin();
3172       i != generators.end(); ++i)
3173     {
3174     if(!this->IsExcluded(root, *i))
3175       {
3176       this->CreateXCodeTargets(*i, targets);
3177       }
3178     }
3179   // loop over all targets and add link and depend info
3180   for(std::vector<cmXCodeObject*>::iterator i = targets.begin();
3181       i != targets.end(); ++i)
3182     {
3183     cmXCodeObject* t = *i;
3184     this->AddDependAndLinkInformation(t);
3185     }
3186   // now create xcode depend hack makefile
3187   this->CreateXCodeDependHackTarget(targets);
3188   // now add all targets to the root object
3189   cmXCodeObject* allTargets = this->CreateObject(cmXCodeObject::OBJECT_LIST);
3190   for(std::vector<cmXCodeObject*>::iterator i = targets.begin();
3191       i != targets.end(); ++i)
3192     {
3193     cmXCodeObject* t = *i;
3194     allTargets->AddObject(t);
3195     cmXCodeObject* productRef = t->GetObject("productReference");
3196     if(productRef)
3197       {
3198       productGroupChildren->AddObject(productRef->GetObject());
3199       }
3200     }
3201   this->RootObject->AddAttribute("targets", allTargets);
3202 }
3203
3204 //----------------------------------------------------------------------------
3205 std::string
3206 cmGlobalXCodeGenerator::GetObjectsNormalDirectory(
3207   const std::string &projName,
3208   const std::string &configName,
3209   const cmTarget *t) const
3210 {
3211   std::string dir =
3212     t->GetMakefile()->GetCurrentOutputDirectory();
3213   dir += "/";
3214   dir += projName;
3215   dir += ".build/";
3216   dir += configName;
3217   dir += "/";
3218   dir += t->GetName();
3219   dir += ".build/Objects-normal/";
3220
3221   return dir;
3222 }
3223
3224 //----------------------------------------------------------------------------
3225 void
3226 cmGlobalXCodeGenerator::CreateXCodeDependHackTarget(
3227   std::vector<cmXCodeObject*>& targets)
3228 {
3229   cmGeneratedFileStream
3230     makefileStream(this->CurrentXCodeHackMakefile.c_str());
3231   if(!makefileStream)
3232     {
3233     cmSystemTools::Error("Could not create",
3234                          this->CurrentXCodeHackMakefile.c_str());
3235     return;
3236     }
3237   makefileStream.SetCopyIfDifferent(true);
3238   // one more pass for external depend information not handled
3239   // correctly by xcode
3240   makefileStream << "# DO NOT EDIT\n";
3241   makefileStream << "# This makefile makes sure all linkable targets are\n";
3242   makefileStream << "# up-to-date with anything they link to\n"
3243     "default:\n"
3244     "\techo \"Do not invoke directly\"\n"
3245     "\n";
3246   makefileStream
3247     << "# For each target create a dummy rule "
3248     "so the target does not have to exist\n";
3249   std::set<cmStdString> emitted;
3250   for(std::vector<cmXCodeObject*>::iterator i = targets.begin();
3251       i != targets.end(); ++i)
3252     {
3253     cmXCodeObject* target = *i;
3254     std::map<cmStdString, cmXCodeObject::StringVec> const& deplibs =
3255       target->GetDependLibraries();
3256     for(std::map<cmStdString, cmXCodeObject::StringVec>::const_iterator ci
3257           = deplibs.begin(); ci != deplibs.end(); ++ci)
3258       {
3259       for(cmXCodeObject::StringVec::const_iterator d = ci->second.begin();
3260           d != ci->second.end(); ++d)
3261         {
3262         if(emitted.insert(*d).second)
3263           {
3264           makefileStream <<
3265             this->ConvertToRelativeForMake(d->c_str()) << ":\n";
3266           }
3267         }
3268       }
3269     }
3270   makefileStream << "\n\n";
3271
3272   // Write rules to help Xcode relink things at the right time.
3273   makefileStream <<
3274     "# Rules to remove targets that are older than anything to which they\n"
3275     "# link.  This forces Xcode to relink the targets from scratch.  It\n"
3276     "# does not seem to check these dependencies itself.\n";
3277   for(std::vector<std::string>::const_iterator
3278         ct = this->CurrentConfigurationTypes.begin();
3279       ct != this->CurrentConfigurationTypes.end(); ++ct)
3280     {
3281     const char* configName = 0;
3282     if(!ct->empty())
3283       {
3284       configName = ct->c_str();
3285       }
3286     for(std::vector<cmXCodeObject*>::iterator i = targets.begin();
3287         i != targets.end(); ++i)
3288       {
3289       cmXCodeObject* target = *i;
3290       cmTarget* t =target->GetTarget();
3291
3292       if(t->GetType() == cmTarget::EXECUTABLE ||
3293 // Nope - no post-build for OBJECT_LIRBRARY
3294 //         t->GetType() == cmTarget::OBJECT_LIBRARY ||
3295          t->GetType() == cmTarget::STATIC_LIBRARY ||
3296          t->GetType() == cmTarget::SHARED_LIBRARY ||
3297          t->GetType() == cmTarget::MODULE_LIBRARY)
3298         {
3299         // Declare an entry point for the target post-build phase.
3300         makefileStream << this->PostBuildMakeTarget(t->GetName(), *ct)
3301                        << ":\n";
3302         }
3303
3304       if(t->GetType() == cmTarget::EXECUTABLE ||
3305          t->GetType() == cmTarget::SHARED_LIBRARY ||
3306          t->GetType() == cmTarget::MODULE_LIBRARY)
3307         {
3308         std::string tfull = t->GetFullPath(configName);
3309         std::string trel = this->ConvertToRelativeForMake(tfull.c_str());
3310
3311         // Add this target to the post-build phases of its dependencies.
3312         std::map<cmStdString, cmXCodeObject::StringVec>::const_iterator
3313           y = target->GetDependTargets().find(*ct);
3314         if(y != target->GetDependTargets().end())
3315           {
3316           std::vector<cmStdString> const& deptgts = y->second;
3317           for(std::vector<cmStdString>::const_iterator d = deptgts.begin();
3318               d != deptgts.end(); ++d)
3319             {
3320             makefileStream << this->PostBuildMakeTarget(*d, *ct) << ": "
3321                            << trel << "\n";
3322             }
3323           }
3324
3325         // Create a rule for this target.
3326         makefileStream << trel << ":";
3327
3328         // List dependencies if any exist.
3329         std::map<cmStdString, cmXCodeObject::StringVec>::const_iterator
3330           x = target->GetDependLibraries().find(*ct);
3331         if(x != target->GetDependLibraries().end())
3332           {
3333           std::vector<cmStdString> const& deplibs = x->second;
3334           for(std::vector<cmStdString>::const_iterator d = deplibs.begin();
3335               d != deplibs.end(); ++d)
3336             {
3337             makefileStream << "\\\n\t" <<
3338               this->ConvertToRelativeForMake(d->c_str());
3339             }
3340           }
3341         // Write the action to remove the target if it is out of date.
3342         makefileStream << "\n";
3343         makefileStream << "\t/bin/rm -f "
3344                        << this->ConvertToRelativeForMake(tfull.c_str())
3345                        << "\n";
3346         // if building for more than one architecture
3347         // then remove those exectuables as well
3348         if(this->Architectures.size() > 1)
3349           {
3350           std::string universal = this->GetObjectsNormalDirectory(
3351             this->CurrentProject, configName, t);
3352           for( std::vector<std::string>::iterator arch =
3353                  this->Architectures.begin();
3354                arch != this->Architectures.end(); ++arch)
3355             {
3356             std::string universalFile = universal;
3357             universalFile += *arch;
3358             universalFile += "/";
3359             universalFile += t->GetFullName(configName);
3360             makefileStream << "\t/bin/rm -f "
3361                            <<
3362               this->ConvertToRelativeForMake(universalFile.c_str())
3363                            << "\n";
3364             }
3365           }
3366         makefileStream << "\n\n";
3367         }
3368       }
3369     }
3370 }
3371
3372 //----------------------------------------------------------------------------
3373 void
3374 cmGlobalXCodeGenerator::OutputXCodeProject(cmLocalGenerator* root,
3375                                            std::vector<cmLocalGenerator*>&
3376                                            generators)
3377 {
3378   if(generators.size() == 0)
3379     {
3380     return;
3381     }
3382   // Skip local generators that are excluded from this project.
3383   for(std::vector<cmLocalGenerator*>::iterator g = generators.begin();
3384       g != generators.end(); ++g)
3385     {
3386     if(this->IsExcluded(root, *g))
3387       {
3388       continue;
3389       }
3390     }
3391
3392   this->CreateXCodeObjects(root,
3393                            generators);
3394   std::string xcodeDir = root->GetMakefile()->GetStartOutputDirectory();
3395   xcodeDir += "/";
3396   xcodeDir += root->GetMakefile()->GetProjectName();
3397   xcodeDir += ".xcode";
3398   if(this->XcodeVersion > 20)
3399     {
3400     xcodeDir += "proj";
3401     }
3402   cmSystemTools::MakeDirectory(xcodeDir.c_str());
3403   std::string xcodeProjFile = xcodeDir + "/project.pbxproj";
3404   cmGeneratedFileStream fout(xcodeProjFile.c_str());
3405   fout.SetCopyIfDifferent(true);
3406   if(!fout)
3407     {
3408     return;
3409     }
3410   this->WriteXCodePBXProj(fout, root, generators);
3411   this->ClearXCodeObjects();
3412
3413   // Since this call may have created new cache entries, save the cache:
3414   //
3415   root->GetMakefile()->GetCacheManager()->SaveCache(
3416     root->GetMakefile()->GetHomeOutputDirectory());
3417 }
3418
3419 //----------------------------------------------------------------------------
3420 void
3421 cmGlobalXCodeGenerator::WriteXCodePBXProj(std::ostream& fout,
3422                                           cmLocalGenerator* ,
3423                                           std::vector<cmLocalGenerator*>& )
3424 {
3425   fout << "// !$*UTF8*$!\n";
3426   fout << "{\n";
3427   cmXCodeObject::Indent(1, fout);
3428   fout << "archiveVersion = 1;\n";
3429   cmXCodeObject::Indent(1, fout);
3430   fout << "classes = {\n";
3431   cmXCodeObject::Indent(1, fout);
3432   fout << "};\n";
3433   cmXCodeObject::Indent(1, fout);
3434   if(this->XcodeVersion >= 21)
3435     {
3436     if (this->XcodeVersion >= 32)
3437       fout << "objectVersion = 46;\n";
3438     else if (this->XcodeVersion >= 31)
3439       fout << "objectVersion = 45;\n";
3440     else if (this->XcodeVersion >= 30)
3441       fout << "objectVersion = 44;\n";
3442     else
3443       fout << "objectVersion = 42;\n";
3444     cmXCode21Object::PrintList(this->XCodeObjects, fout);
3445     }
3446   else
3447     {
3448     fout << "objectVersion = 39;\n";
3449     cmXCodeObject::PrintList(this->XCodeObjects, fout);
3450     }
3451   cmXCodeObject::Indent(1, fout);
3452   fout << "rootObject = " << this->RootObject->GetId() << ";\n";
3453   fout << "}\n";
3454 }
3455
3456 //----------------------------------------------------------------------------
3457 const char* cmGlobalXCodeGenerator::GetCMakeCFGIntDir() const
3458 {
3459   return this->XcodeVersion >= 21 ?
3460     "$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)" : ".";
3461 }
3462
3463 //----------------------------------------------------------------------------
3464 void cmGlobalXCodeGenerator::GetDocumentation(cmDocumentationEntry& entry)
3465   const
3466 {
3467   entry.Name = this->GetName();
3468   entry.Brief = "Generate Xcode project files.";
3469   entry.Full = "";
3470 }
3471
3472 //----------------------------------------------------------------------------
3473 std::string cmGlobalXCodeGenerator::ConvertToRelativeForMake(const char* p)
3474 {
3475   if ( !this->CurrentMakefile->IsOn("CMAKE_USE_RELATIVE_PATHS") )
3476     {
3477     return cmSystemTools::ConvertToOutputPath(p);
3478     }
3479   else
3480     {
3481     std::string ret =
3482       this->CurrentLocalGenerator->
3483         ConvertToRelativePath(this->CurrentOutputDirectoryComponents, p);
3484     return cmSystemTools::ConvertToOutputPath(ret.c_str());
3485     }
3486 }
3487
3488 //----------------------------------------------------------------------------
3489 std::string cmGlobalXCodeGenerator::ConvertToRelativeForXCode(const char* p)
3490 {
3491   if ( !this->CurrentMakefile->IsOn("CMAKE_USE_RELATIVE_PATHS") )
3492     {
3493     return cmSystemTools::ConvertToOutputPath(p);
3494     }
3495   else
3496     {
3497     std::string ret =
3498       this->CurrentLocalGenerator->
3499         ConvertToRelativePath(this->ProjectOutputDirectoryComponents, p);
3500     return cmSystemTools::ConvertToOutputPath(ret.c_str());
3501     }
3502 }
3503
3504 //----------------------------------------------------------------------------
3505 std::string cmGlobalXCodeGenerator::RelativeToSource(const char* p)
3506 {
3507   // We force conversion because Xcode breakpoints do not work unless
3508   // they are in a file named relative to the source tree.
3509   return this->CurrentLocalGenerator->
3510     ConvertToRelativePath(this->ProjectSourceDirectoryComponents, p, true);
3511 }
3512
3513 //----------------------------------------------------------------------------
3514 std::string cmGlobalXCodeGenerator::RelativeToBinary(const char* p)
3515 {
3516   return this->CurrentLocalGenerator->
3517     ConvertToRelativePath(this->ProjectOutputDirectoryComponents, p);
3518 }
3519
3520 //----------------------------------------------------------------------------
3521 std::string cmGlobalXCodeGenerator::XCodeEscapePath(const char* p)
3522 {
3523   std::string ret = p;
3524   if(ret.find(' ') != ret.npos)
3525     {
3526     std::string t = ret;
3527     ret = "\"";
3528     ret += t;
3529     ret += "\"";
3530     }
3531   return ret;
3532 }
3533
3534 //----------------------------------------------------------------------------
3535 void
3536 cmGlobalXCodeGenerator
3537 ::AppendDirectoryForConfig(const char* prefix,
3538                            const char* config,
3539                            const char* suffix,
3540                            std::string& dir)
3541 {
3542   if(this->XcodeVersion > 20)
3543     {
3544     if(config)
3545       {
3546       dir += prefix;
3547       dir += config;
3548       dir += suffix;
3549       }
3550     }
3551 }
3552
3553 //----------------------------------------------------------------------------
3554 std::string cmGlobalXCodeGenerator::LookupFlags(const char* varNamePrefix,
3555                                                 const char* varNameLang,
3556                                                 const char* varNameSuffix,
3557                                                 const char* default_flags)
3558 {
3559   if(varNameLang)
3560     {
3561     std::string varName = varNamePrefix;
3562     varName += varNameLang;
3563     varName += varNameSuffix;
3564     if(const char* varValue =
3565        this->CurrentMakefile->GetDefinition(varName.c_str()))
3566       {
3567       if(*varValue)
3568         {
3569         return varValue;
3570         }
3571       }
3572     }
3573   return default_flags;
3574 }
3575
3576 //----------------------------------------------------------------------------
3577 void cmGlobalXCodeGenerator::AppendDefines(BuildObjectListOrString& defs,
3578                                            const char* defines_list,
3579                                            bool dflag)
3580 {
3581   // Skip this if there are no definitions.
3582   if(!defines_list)
3583     {
3584     return;
3585     }
3586
3587   // Expand the list of definitions.
3588   std::vector<std::string> defines;
3589   cmSystemTools::ExpandListArgument(defines_list, defines);
3590
3591   // Store the definitions in the string.
3592   this->AppendDefines(defs, defines, dflag);
3593 }
3594
3595 //----------------------------------------------------------------------------
3596 void
3597 cmGlobalXCodeGenerator::AppendDefines(BuildObjectListOrString& defs,
3598                                       std::vector<std::string> const& defines,
3599                                       bool dflag)
3600 {
3601   // GCC_PREPROCESSOR_DEFINITIONS is a space-separated list of definitions.
3602   std::string def;
3603   for(std::vector<std::string>::const_iterator di = defines.begin();
3604       di != defines.end(); ++di)
3605     {
3606     // Start with -D if requested.
3607     def = dflag? "-D": "";
3608     def += *di;
3609
3610     // Append the flag with needed escapes.
3611     std::string tmp;
3612     this->AppendFlag(tmp, def);
3613     defs.Add(tmp.c_str());
3614     }
3615 }
3616
3617 //----------------------------------------------------------------------------
3618 void cmGlobalXCodeGenerator::AppendFlag(std::string& flags,
3619                                         std::string const& flag)
3620 {
3621   // Short-circuit for an empty flag.
3622   if(flag.empty())
3623     {
3624     return;
3625     }
3626
3627   // Separate from previous flags.
3628   if(!flags.empty())
3629     {
3630     flags += " ";
3631     }
3632
3633   // Check if the flag needs quoting.
3634   bool quoteFlag =
3635     flag.find_first_of("`~!@#$%^&*()+={}[]|:;\"'<>,.? ") != flag.npos;
3636
3637   // We escape a flag as follows:
3638   //   - Place each flag in single quotes ''
3639   //   - Escape a single quote as \\'
3640   //   - Escape a backslash as \\\\ since it itself is an escape
3641   // Note that in the code below we need one more level of escapes for
3642   // C string syntax in this source file.
3643   //
3644   // The final level of escaping is done when the string is stored
3645   // into the project file by cmXCodeObject::PrintString.
3646
3647   if(quoteFlag)
3648     {
3649     // Open single quote.
3650     flags += "'";
3651     }
3652
3653   // Flag value with escaped quotes and backslashes.
3654   for(const char* c = flag.c_str(); *c; ++c)
3655     {
3656     if(*c == '\'')
3657       {
3658       if (this->XcodeVersion >= 40)
3659         {
3660         flags += "'\\\\''";
3661         }
3662       else
3663         {
3664         flags += "\\\\'";
3665         }
3666       }
3667     else if(*c == '\\')
3668       {
3669       flags += "\\\\\\\\";
3670       }
3671     else
3672       {
3673       flags += *c;
3674       }
3675     }
3676
3677   if(quoteFlag)
3678     {
3679     // Close single quote.
3680     flags += "'";
3681     }
3682 }
3683
3684 //----------------------------------------------------------------------------
3685 std::string
3686 cmGlobalXCodeGenerator::ComputeInfoPListLocation(cmTarget& target)
3687 {
3688   std::string plist = target.GetMakefile()->GetCurrentOutputDirectory();
3689   plist += cmake::GetCMakeFilesDirectory();
3690   plist += "/";
3691   plist += target.GetName();
3692   plist += ".dir/Info.plist";
3693   return plist;
3694 }
3695
3696 //----------------------------------------------------------------------------
3697 // Return true if the generated build tree may contain multiple builds.
3698 // i.e. "Can I build Debug and Release in the same tree?"
3699 bool cmGlobalXCodeGenerator::IsMultiConfig()
3700 {
3701   // Old Xcode 1.5 is single config:
3702   if(this->XcodeVersion == 15)
3703     {
3704     return false;
3705     }
3706
3707   // Newer Xcode versions are multi config:
3708   return true;
3709 }
3710
3711  //----------------------------------------------------------------------------
3712 void
3713 cmGlobalXCodeGenerator
3714 ::ComputeTargetObjects(cmGeneratorTarget* gt) const
3715 {
3716   // Count the number of object files with each name. Warn about duplicate
3717   // names since Xcode names them uniquely automatically with a numeric suffix
3718   // to avoid exact duplicate file names. Note that Mac file names are not
3719   // typically case sensitive, hence the LowerCase.
3720   std::map<cmStdString, int> counts;
3721   for(std::vector<cmSourceFile*>::const_iterator
3722       si = gt->ObjectSources.begin();
3723       si != gt->ObjectSources.end(); ++si)
3724     {
3725     cmSourceFile* sf = *si;
3726     std::string objectName =
3727       cmSystemTools::GetFilenameWithoutLastExtension(sf->GetFullPath());
3728     objectName += ".o";
3729
3730     std::string objectNameLower = cmSystemTools::LowerCase(objectName);
3731     counts[objectNameLower] += 1;
3732     if (2 == counts[objectNameLower])
3733       {
3734       // TODO: emit warning about duplicate name?
3735       }
3736
3737     gt->Objects[sf] = objectName;
3738     }
3739
3740   const char* configName = this->GetCMakeCFGIntDir();
3741   std::string dir = this->GetObjectsNormalDirectory(
3742     this->CurrentProject, configName, gt->Target);
3743   if(this->XcodeVersion >= 21)
3744     {
3745     dir += "$(CURRENT_ARCH)/";
3746     }
3747   else
3748     {
3749 #ifdef __ppc__
3750     dir += "ppc/";
3751 #endif
3752 #ifdef __i386
3753     dir += "i386/";
3754 #endif
3755     }
3756   gt->ObjectDirectory = dir;
3757 }