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