cmGlobalXCodeGenerator.cxx 59 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666
  1. /*=========================================================================
  2. Program: CMake - Cross-Platform Makefile Generator
  3. Module: $RCSfile$
  4. Language: C++
  5. Date: $Date$
  6. Version: $Revision$
  7. Copyright (c) 2002 Kitware, Inc., Insight Consortium. All rights reserved.
  8. See Copyright.txt or http://www.cmake.org/HTML/Copyright.html for details.
  9. This software is distributed WITHOUT ANY WARRANTY; without even
  10. the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
  11. PURPOSE. See the above copyright notices for more information.
  12. =========================================================================*/
  13. #include "cmGlobalXCodeGenerator.h"
  14. #include "cmLocalXCodeGenerator.h"
  15. #include "cmMakefile.h"
  16. #include "cmXCodeObject.h"
  17. #include "cmake.h"
  18. #include "cmGeneratedFileStream.h"
  19. #include "cmSourceFile.h"
  20. #include "cmOrderLinkDirectories.h"
  21. //TODO
  22. // add OSX application stuff
  23. //----------------------------------------------------------------------------
  24. cmGlobalXCodeGenerator::cmGlobalXCodeGenerator()
  25. {
  26. m_FindMakeProgramFile = "CMakeFindXCode.cmake";
  27. m_RootObject = 0;
  28. m_MainGroupChildren = 0;
  29. m_SourcesGroupChildren = 0;
  30. m_CurrentMakefile = 0;
  31. m_CurrentLocalGenerator = 0;
  32. }
  33. //----------------------------------------------------------------------------
  34. void cmGlobalXCodeGenerator::EnableLanguage(std::vector<std::string>const&
  35. lang,
  36. cmMakefile * mf)
  37. {
  38. mf->AddDefinition("XCODE","1");
  39. mf->AddDefinition("CMAKE_CFG_INTDIR",".");
  40. mf->AddDefinition("CMAKE_GENERATOR_CC", "gcc");
  41. mf->AddDefinition("CMAKE_GENERATOR_CXX", "g++");
  42. mf->AddDefinition("CMAKE_GENERATOR_NO_COMPILER_ENV", "1");
  43. this->cmGlobalGenerator::EnableLanguage(lang, mf);
  44. }
  45. //----------------------------------------------------------------------------
  46. std::string cmGlobalXCodeGenerator::GenerateBuildCommand(const char* makeProgram,
  47. const char *projectName, const char *targetName, const char* config,
  48. bool ignoreErrors)
  49. {
  50. // Config is not used yet
  51. (void) config;
  52. // now build the test
  53. if(makeProgram == 0 || !strlen(makeProgram))
  54. {
  55. cmSystemTools::Error(
  56. "Generator cannot find the appropriate make command.");
  57. return "";
  58. }
  59. std::string makeCommand =
  60. cmSystemTools::ConvertToOutputPath(makeProgram);
  61. std::string lowerCaseCommand = makeCommand;
  62. cmSystemTools::LowerCase(lowerCaseCommand);
  63. makeCommand += " -project ";
  64. makeCommand += projectName;
  65. makeCommand += ".xcode";
  66. bool clean = false;
  67. if ( targetName && strcmp(targetName, "clean") == 0 )
  68. {
  69. clean = true;
  70. targetName = "ALL_BUILD";
  71. }
  72. if(clean)
  73. {
  74. makeCommand += " clean";
  75. }
  76. else
  77. {
  78. makeCommand += " build";
  79. }
  80. makeCommand += " -target ";
  81. if (targetName && strlen(targetName))
  82. {
  83. makeCommand += targetName;
  84. }
  85. else
  86. {
  87. makeCommand += "ALL_BUILD";
  88. }
  89. makeCommand += " -buildstyle Development ";
  90. return makeCommand;
  91. }
  92. //----------------------------------------------------------------------------
  93. void cmGlobalXCodeGenerator::ConfigureOutputPaths()
  94. {
  95. // Format the library and executable output paths.
  96. m_LibraryOutputPath =
  97. m_CurrentMakefile->GetSafeDefinition("LIBRARY_OUTPUT_PATH");
  98. if(m_LibraryOutputPath.size() == 0)
  99. {
  100. m_LibraryOutputPath = m_CurrentMakefile->GetCurrentOutputDirectory();
  101. }
  102. // make sure there is a trailing slash
  103. if(m_LibraryOutputPath.size() &&
  104. m_LibraryOutputPath[m_LibraryOutputPath.size()-1] != '/')
  105. {
  106. m_LibraryOutputPath += "/";
  107. if(!cmSystemTools::MakeDirectory(m_LibraryOutputPath.c_str()))
  108. {
  109. cmSystemTools::Error("Error creating directory ",
  110. m_LibraryOutputPath.c_str());
  111. }
  112. }
  113. m_CurrentMakefile->AddLinkDirectory(m_LibraryOutputPath.c_str());
  114. m_ExecutableOutputPath =
  115. m_CurrentMakefile->GetSafeDefinition("EXECUTABLE_OUTPUT_PATH");
  116. if(m_ExecutableOutputPath.size() == 0)
  117. {
  118. m_ExecutableOutputPath = m_CurrentMakefile->GetCurrentOutputDirectory();
  119. }
  120. // make sure there is a trailing slash
  121. if(m_ExecutableOutputPath.size() &&
  122. m_ExecutableOutputPath[m_ExecutableOutputPath.size()-1] != '/')
  123. {
  124. m_ExecutableOutputPath += "/";
  125. if(!cmSystemTools::MakeDirectory(m_ExecutableOutputPath.c_str()))
  126. {
  127. cmSystemTools::Error("Error creating directory ",
  128. m_ExecutableOutputPath.c_str());
  129. }
  130. }
  131. }
  132. //----------------------------------------------------------------------------
  133. ///! Create a local generator appropriate to this Global Generator
  134. cmLocalGenerator *cmGlobalXCodeGenerator::CreateLocalGenerator()
  135. {
  136. cmLocalGenerator *lg = new cmLocalXCodeGenerator;
  137. lg->SetGlobalGenerator(this);
  138. return lg;
  139. }
  140. //----------------------------------------------------------------------------
  141. void cmGlobalXCodeGenerator::Generate()
  142. {
  143. this->cmGlobalGenerator::Generate();
  144. std::map<cmStdString, std::vector<cmLocalGenerator*> >::iterator it;
  145. for(it = m_ProjectMap.begin(); it!= m_ProjectMap.end(); ++it)
  146. {
  147. cmLocalGenerator* root = it->second[0];
  148. m_CurrentProject = root->GetMakefile()->GetProjectName();
  149. this->SetCurrentLocalGenerator(root);
  150. m_OutputDir = m_CurrentMakefile->GetHomeOutputDirectory();
  151. m_OutputDir = cmSystemTools::CollapseFullPath(m_OutputDir.c_str());
  152. cmSystemTools::SplitPath(m_OutputDir.c_str(),
  153. m_ProjectOutputDirectoryComponents);
  154. m_CurrentLocalGenerator = root;
  155. // add ALL_BUILD, INSTALL, etc
  156. this->AddExtraTargets(root, it->second);
  157. // now create the project
  158. this->OutputXCodeProject(root, it->second);
  159. }
  160. }
  161. //----------------------------------------------------------------------------
  162. void
  163. cmGlobalXCodeGenerator::AddExtraTargets(cmLocalGenerator* root,
  164. std::vector<cmLocalGenerator*>& gens)
  165. {
  166. cmMakefile* mf = root->GetMakefile();
  167. // Add ALL_BUILD
  168. const char* no_output = 0;
  169. std::vector<std::string> no_depends;
  170. mf->AddUtilityCommand("ALL_BUILD", false, no_output, no_depends,
  171. "echo", "Build all projects");
  172. cmTarget* allbuild = mf->FindTarget("ALL_BUILD");
  173. // ADD install
  174. std::string cmake_command = mf->GetRequiredDefinition("CMAKE_COMMAND");
  175. mf->AddUtilityCommand("install", false, no_output, no_depends,
  176. cmake_command.c_str(),
  177. "-P", "cmake_install.cmake");
  178. const char* noall =
  179. mf->GetDefinition("CMAKE_SKIP_INSTALL_ALL_DEPENDENCY");
  180. if(!noall || cmSystemTools::IsOff(noall))
  181. {
  182. cmTarget* install = mf->FindTarget("install");
  183. install->AddUtility("ALL_BUILD");
  184. }
  185. // Add RUN_TESTS target if testing has been enabled
  186. std::string fname;
  187. fname = mf->GetStartOutputDirectory();
  188. fname += "/";
  189. fname += "DartTestfile.txt";
  190. if (cmSystemTools::FileExists(fname.c_str()))
  191. {
  192. std::string ctest_command =
  193. mf->GetRequiredDefinition("CMAKE_CTEST_COMMAND");
  194. mf->AddUtilityCommand("RUN_TESTS", false, no_output, no_depends,
  195. ctest_command.c_str());
  196. }
  197. // Add XCODE depend helper
  198. std::string dir = mf->GetCurrentOutputDirectory();
  199. m_CurrentXCodeHackMakefile = dir;
  200. m_CurrentXCodeHackMakefile += "/CMakeScripts";
  201. cmSystemTools::MakeDirectory(m_CurrentXCodeHackMakefile.c_str());
  202. m_CurrentXCodeHackMakefile += "/XCODE_DEPEND_HELPER.make";
  203. cmCustomCommandLine makecommand;
  204. makecommand.push_back("make");
  205. makecommand.push_back("-C");
  206. makecommand.push_back(dir.c_str());
  207. makecommand.push_back("-f");
  208. makecommand.push_back(m_CurrentXCodeHackMakefile.c_str());
  209. cmCustomCommandLines commandLines;
  210. commandLines.push_back(makecommand);
  211. mf->AddUtilityCommand("XCODE_DEPEND_HELPER", false, no_output, no_depends,
  212. commandLines);
  213. // Add Re-Run CMake rules
  214. this->CreateReRunCMakeFile(root);
  215. // now make the allbuild depend on all the non-utility targets
  216. // in the project
  217. for(std::vector<cmLocalGenerator*>::iterator i = gens.begin();
  218. i != gens.end(); ++i)
  219. {
  220. cmLocalGenerator* lg = *i;
  221. if(this->IsExcluded(root, *i))
  222. {
  223. continue;
  224. }
  225. cmTargets& tgts = lg->GetMakefile()->GetTargets();
  226. for(cmTargets::iterator l = tgts.begin(); l != tgts.end(); l++)
  227. {
  228. cmTarget& target = l->second;
  229. // make all exe, shared libs and modules depend
  230. // on the XCODE_DEPEND_HELPER target
  231. if((target.GetType() == cmTarget::EXECUTABLE ||
  232. target.GetType() == cmTarget::SHARED_LIBRARY ||
  233. target.GetType() == cmTarget::MODULE_LIBRARY))
  234. {
  235. target.AddUtility("XCODE_DEPEND_HELPER");
  236. }
  237. if(target.IsInAll())
  238. {
  239. allbuild->AddUtility(target.GetName());
  240. }
  241. }
  242. }
  243. }
  244. //----------------------------------------------------------------------------
  245. void cmGlobalXCodeGenerator::CreateReRunCMakeFile(cmLocalGenerator* root)
  246. {
  247. cmMakefile* mf = root->GetMakefile();
  248. std::vector<std::string> lfiles = mf->GetListFiles();
  249. // sort the array
  250. std::sort(lfiles.begin(), lfiles.end(), std::less<std::string>());
  251. std::vector<std::string>::iterator new_end =
  252. std::unique(lfiles.begin(), lfiles.end());
  253. lfiles.erase(new_end, lfiles.end());
  254. std::string dir = mf->GetHomeOutputDirectory();
  255. m_CurrentReRunCMakeMakefile = dir;
  256. m_CurrentReRunCMakeMakefile += "/CMakeScripts";
  257. cmSystemTools::MakeDirectory(m_CurrentReRunCMakeMakefile.c_str());
  258. m_CurrentReRunCMakeMakefile += "/ReRunCMake.make";
  259. cmGeneratedFileStream makefileStream(m_CurrentReRunCMakeMakefile.c_str());
  260. makefileStream << "# Generated by CMake, DO NOT EDIT\n";
  261. makefileStream << "cmake.check_cache: ";
  262. for(std::vector<std::string>::const_iterator i = lfiles.begin();
  263. i != lfiles.end(); ++i)
  264. {
  265. makefileStream << "\\\n" << this->ConvertToRelativeForMake(i->c_str());
  266. }
  267. std::string cmake = mf->GetRequiredDefinition("CMAKE_COMMAND");
  268. makefileStream << "\n\t" << this->ConvertToRelativeForMake(cmake.c_str())
  269. << " -H" << this->ConvertToRelativeForMake(
  270. mf->GetHomeDirectory())
  271. << " -B" << this->ConvertToRelativeForMake(
  272. mf->GetHomeOutputDirectory()) << "\n";
  273. }
  274. //----------------------------------------------------------------------------
  275. void cmGlobalXCodeGenerator::ClearXCodeObjects()
  276. {
  277. m_TargetDoneSet.clear();
  278. for(unsigned int i = 0; i < m_XCodeObjects.size(); ++i)
  279. {
  280. delete m_XCodeObjects[i];
  281. }
  282. m_XCodeObjects.clear();
  283. m_GroupMap.clear();
  284. m_GroupNameMap.clear();
  285. m_TargetGroup.clear();
  286. }
  287. //----------------------------------------------------------------------------
  288. cmXCodeObject*
  289. cmGlobalXCodeGenerator::CreateObject(cmXCodeObject::PBXType ptype)
  290. {
  291. cmXCodeObject* obj = new cmXCodeObject(ptype, cmXCodeObject::OBJECT);
  292. m_XCodeObjects.push_back(obj);
  293. return obj;
  294. }
  295. //----------------------------------------------------------------------------
  296. cmXCodeObject*
  297. cmGlobalXCodeGenerator::CreateObject(cmXCodeObject::Type type)
  298. {
  299. cmXCodeObject* obj = new cmXCodeObject(cmXCodeObject::None, type);
  300. m_XCodeObjects.push_back(obj);
  301. return obj;
  302. }
  303. //----------------------------------------------------------------------------
  304. cmXCodeObject*
  305. cmGlobalXCodeGenerator::CreateString(const char* s)
  306. {
  307. cmXCodeObject* obj = this->CreateObject(cmXCodeObject::STRING);
  308. obj->SetString(s);
  309. return obj;
  310. }
  311. //----------------------------------------------------------------------------
  312. cmXCodeObject* cmGlobalXCodeGenerator::CreateObjectReference(cmXCodeObject* ref)
  313. {
  314. cmXCodeObject* obj = this->CreateObject(cmXCodeObject::OBJECT_REF);
  315. obj->SetObject(ref);
  316. return obj;
  317. }
  318. //----------------------------------------------------------------------------
  319. cmXCodeObject*
  320. cmGlobalXCodeGenerator::CreateXCodeSourceFile(cmLocalGenerator* lg,
  321. cmSourceFile* sf)
  322. {
  323. std::string flags;
  324. // Add flags from source file properties.
  325. lg->AppendFlags(flags, sf->GetProperty("COMPILE_FLAGS"));
  326. cmXCodeObject* fileRef = this->CreateObject(cmXCodeObject::PBXFileReference);
  327. cmXCodeObject* group = m_GroupMap[sf];
  328. cmXCodeObject* children = group->GetObject("children");
  329. children->AddObject(fileRef);
  330. // m_SourcesGroupChildren->AddObject(fileRef);
  331. cmXCodeObject* buildFile = this->CreateObject(cmXCodeObject::PBXBuildFile);
  332. buildFile->AddAttribute("fileRef", this->CreateObjectReference(fileRef));
  333. cmXCodeObject* settings = this->CreateObject(cmXCodeObject::ATTRIBUTE_GROUP);
  334. settings->AddAttribute("COMPILER_FLAGS", this->CreateString(flags.c_str()));
  335. buildFile->AddAttribute("settings", settings);
  336. fileRef->AddAttribute("fileEncoding", this->CreateString("4"));
  337. const char* lang =
  338. this->GetLanguageFromExtension(sf->GetSourceExtension().c_str());
  339. std::string sourcecode = "sourcecode";
  340. std::string ext = sf->GetSourceExtension();
  341. ext = cmSystemTools::LowerCase(ext);
  342. if(ext == "o")
  343. {
  344. sourcecode = "compiled.mach-o.objfile";
  345. }
  346. else if(ext == "mm")
  347. {
  348. sourcecode += ".cpp.objcpp";
  349. }
  350. else if(ext == "m")
  351. {
  352. sourcecode += ".cpp.objc";
  353. }
  354. else if(!lang)
  355. {
  356. sourcecode += ext;
  357. sourcecode += ".";
  358. sourcecode += ext;
  359. }
  360. else if(strcmp(lang, "C") == 0)
  361. {
  362. sourcecode += ".c.c";
  363. }
  364. else
  365. {
  366. sourcecode += ".cpp.cpp";
  367. }
  368. fileRef->AddAttribute("lastKnownFileType",
  369. this->CreateString(sourcecode.c_str()));
  370. std::string path =
  371. this->ConvertToRelativeForXCode(sf->GetFullPath().c_str());
  372. // std::string file =
  373. // cmSystemTools::RelativePath(m_CurrentMakefile->GetHomeDirectory(),
  374. // sf->GetFullPath().c_str());
  375. std::string dir;
  376. std::string file;
  377. cmSystemTools::SplitProgramPath(sf->GetFullPath().c_str(),
  378. dir, file);
  379. fileRef->AddAttribute("name", this->CreateString(file.c_str()));
  380. fileRef->AddAttribute("path", this->CreateString(path.c_str()));
  381. fileRef->AddAttribute("refType", this->CreateString("4"));
  382. if(path.size() > 1 && path[0] == '.' && path[1] == '.')
  383. {
  384. fileRef->AddAttribute("sourceTree", this->CreateString("<group>"));
  385. }
  386. else
  387. {
  388. fileRef->AddAttribute("sourceTree", this->CreateString("<absolute>"));
  389. }
  390. return buildFile;
  391. }
  392. //----------------------------------------------------------------------------
  393. bool cmGlobalXCodeGenerator::SpecialTargetEmitted(std::string const& tname)
  394. {
  395. if(tname == "ALL_BUILD" || tname == "XCODE_DEPEND_HELPER" ||
  396. tname == "install" || tname == "RUN_TESTS" )
  397. {
  398. if(m_TargetDoneSet.find(tname) != m_TargetDoneSet.end())
  399. {
  400. return true;
  401. }
  402. m_TargetDoneSet.insert(tname);
  403. return false;
  404. }
  405. return false;
  406. }
  407. void cmGlobalXCodeGenerator::SetCurrentLocalGenerator(cmLocalGenerator* gen)
  408. {
  409. m_CurrentLocalGenerator = gen;
  410. m_CurrentMakefile = gen->GetMakefile();
  411. std::string outdir =
  412. cmSystemTools::CollapseFullPath(m_CurrentMakefile->
  413. GetCurrentOutputDirectory());
  414. cmSystemTools::SplitPath(outdir.c_str(), m_CurrentOutputDirectoryComponents);
  415. }
  416. //----------------------------------------------------------------------------
  417. void
  418. cmGlobalXCodeGenerator::CreateXCodeTargets(cmLocalGenerator* gen,
  419. std::vector<cmXCodeObject*>&
  420. targets)
  421. {
  422. this->SetCurrentLocalGenerator(gen);
  423. cmTargets &tgts = gen->GetMakefile()->GetTargets();
  424. for(cmTargets::iterator l = tgts.begin(); l != tgts.end(); l++)
  425. {
  426. cmTarget& cmtarget = l->second;
  427. // make sure ALL_BUILD, INSTALL, etc are only done once
  428. if(this->SpecialTargetEmitted(l->first.c_str()))
  429. {
  430. continue;
  431. }
  432. if(cmtarget.GetType() == cmTarget::UTILITY ||
  433. cmtarget.GetType() == cmTarget::INSTALL_FILES ||
  434. cmtarget.GetType() == cmTarget::INSTALL_PROGRAMS)
  435. {
  436. if(cmtarget.GetType() == cmTarget::UTILITY)
  437. {
  438. targets.push_back(this->CreateUtilityTarget(cmtarget));
  439. }
  440. continue;
  441. }
  442. // create source build phase
  443. cmXCodeObject* sourceBuildPhase =
  444. this->CreateObject(cmXCodeObject::PBXSourcesBuildPhase);
  445. sourceBuildPhase->AddAttribute("buildActionMask",
  446. this->CreateString("2147483647"));
  447. cmXCodeObject* buildFiles = this->CreateObject(cmXCodeObject::OBJECT_LIST);
  448. sourceBuildPhase->AddAttribute("files", buildFiles);
  449. sourceBuildPhase->AddAttribute("runOnlyForDeploymentPostprocessing",
  450. this->CreateString("0"));
  451. std::vector<cmSourceFile*> &classes = l->second.GetSourceFiles();
  452. // add all the sources
  453. std::vector<cmXCodeObject*> externalObjFiles;
  454. std::vector<cmXCodeObject*> headerFiles;
  455. for(std::vector<cmSourceFile*>::iterator i = classes.begin();
  456. i != classes.end(); ++i)
  457. {
  458. cmXCodeObject* xsf = this->CreateXCodeSourceFile(gen, *i);
  459. cmXCodeObject* fr = xsf->GetObject("fileRef");
  460. cmXCodeObject* filetype =
  461. fr->GetObject()->GetObject("lastKnownFileType");
  462. if(strcmp(filetype->GetString(), "\"compiled.mach-o.objfile\"") == 0)
  463. {
  464. externalObjFiles.push_back(xsf);
  465. }
  466. else if((*i)->GetPropertyAsBool("HEADER_FILE_ONLY"))
  467. {
  468. headerFiles.push_back(xsf);
  469. }
  470. else
  471. {
  472. buildFiles->AddObject(xsf);
  473. }
  474. }
  475. // create header build phase
  476. cmXCodeObject* headerBuildPhase =
  477. this->CreateObject(cmXCodeObject::PBXHeadersBuildPhase);
  478. headerBuildPhase->AddAttribute("buildActionMask",
  479. this->CreateString("2147483647"));
  480. buildFiles = this->CreateObject(cmXCodeObject::OBJECT_LIST);
  481. for(std::vector<cmXCodeObject*>::iterator i = headerFiles.begin();
  482. i != headerFiles.end(); ++i)
  483. {
  484. buildFiles->AddObject(*i);
  485. }
  486. headerBuildPhase->AddAttribute("files", buildFiles);
  487. headerBuildPhase->AddAttribute("runOnlyForDeploymentPostprocessing",
  488. this->CreateString("0"));
  489. // create framework build phase
  490. cmXCodeObject* frameworkBuildPhase =
  491. this->CreateObject(cmXCodeObject::PBXFrameworksBuildPhase);
  492. frameworkBuildPhase->AddAttribute("buildActionMask",
  493. this->CreateString("2147483647"));
  494. buildFiles = this->CreateObject(cmXCodeObject::OBJECT_LIST);
  495. frameworkBuildPhase->AddAttribute("files", buildFiles);
  496. for(std::vector<cmXCodeObject*>::iterator i = externalObjFiles.begin();
  497. i != externalObjFiles.end(); ++i)
  498. {
  499. buildFiles->AddObject(*i);
  500. }
  501. frameworkBuildPhase->AddAttribute("runOnlyForDeploymentPostprocessing",
  502. this->CreateString("0"));
  503. cmXCodeObject* buildPhases =
  504. this->CreateObject(cmXCodeObject::OBJECT_LIST);
  505. this->CreateCustomCommands(buildPhases, sourceBuildPhase,
  506. headerBuildPhase, frameworkBuildPhase,
  507. cmtarget);
  508. targets.push_back(this->CreateXCodeTarget(l->second, buildPhases));
  509. }
  510. }
  511. //----------------------------------------------------------------------------
  512. cmXCodeObject*
  513. cmGlobalXCodeGenerator::CreateBuildPhase(const char* name,
  514. const char* name2,
  515. cmTarget& cmtarget,
  516. const std::vector<cmCustomCommand>&
  517. commands)
  518. {
  519. if(commands.size() == 0 && strcmp(name, "CMake ReRun") != 0)
  520. {
  521. return 0;
  522. }
  523. cmXCodeObject* buildPhase =
  524. this->CreateObject(cmXCodeObject::PBXShellScriptBuildPhase);
  525. buildPhase->AddAttribute("buildActionMask",
  526. this->CreateString("2147483647"));
  527. cmXCodeObject* buildFiles = this->CreateObject(cmXCodeObject::OBJECT_LIST);
  528. buildPhase->AddAttribute("files", buildFiles);
  529. buildPhase->AddAttribute("name",
  530. this->CreateString(name));
  531. buildPhase->AddAttribute("runOnlyForDeploymentPostprocessing",
  532. this->CreateString("0"));
  533. buildPhase->AddAttribute("shellPath",
  534. this->CreateString("/bin/sh"));
  535. this->AddCommandsToBuildPhase(buildPhase, cmtarget, commands,
  536. name2);
  537. return buildPhase;
  538. }
  539. //----------------------------------------------------------------------------
  540. void cmGlobalXCodeGenerator::CreateCustomCommands(cmXCodeObject* buildPhases,
  541. cmXCodeObject*
  542. sourceBuildPhase,
  543. cmXCodeObject*
  544. headerBuildPhase,
  545. cmXCodeObject*
  546. frameworkBuildPhase,
  547. cmTarget& cmtarget)
  548. {
  549. std::vector<cmCustomCommand> const & prebuild
  550. = cmtarget.GetPreBuildCommands();
  551. std::vector<cmCustomCommand> const & prelink
  552. = cmtarget.GetPreLinkCommands();
  553. std::vector<cmCustomCommand> const & postbuild
  554. = cmtarget.GetPostBuildCommands();
  555. cmtarget.TraceVSDependencies(cmtarget.GetName(), m_CurrentMakefile);
  556. std::vector<cmSourceFile*> &classes = cmtarget.GetSourceFiles();
  557. // add all the sources
  558. std::vector<cmCustomCommand> commands;
  559. for(std::vector<cmSourceFile*>::iterator i = classes.begin();
  560. i != classes.end(); ++i)
  561. {
  562. if((*i)->GetCustomCommand())
  563. {
  564. commands.push_back(*(*i)->GetCustomCommand());
  565. }
  566. }
  567. std::vector<cmCustomCommand> reruncom;
  568. cmXCodeObject* cmakeReRunPhase = this->CreateBuildPhase("CMake ReRun",
  569. "cmakeReRunPhase",
  570. cmtarget, reruncom);
  571. buildPhases->AddObject(cmakeReRunPhase);
  572. // create prebuild phase
  573. cmXCodeObject* cmakeRulesBuildPhase =
  574. this->CreateBuildPhase("CMake Rules",
  575. "cmakeRulesBuildPhase",
  576. cmtarget, commands);
  577. // create prebuild phase
  578. cmXCodeObject* preBuildPhase = this->CreateBuildPhase("CMake PreBuild Rules",
  579. "preBuildCommands",
  580. cmtarget, prebuild);
  581. // create prebuild phase
  582. cmXCodeObject* preLinkPhase = this->CreateBuildPhase("CMake PreLink Rules",
  583. "preLinkCommands",
  584. cmtarget, prelink);
  585. // create prebuild phase
  586. cmXCodeObject* postBuildPhase =
  587. this->CreateBuildPhase("CMake PostBuild Rules",
  588. "postBuildPhase",
  589. cmtarget, postbuild);
  590. // the order here is the order they will be built in
  591. if(preBuildPhase)
  592. {
  593. buildPhases->AddObject(preBuildPhase);
  594. }
  595. if(cmakeRulesBuildPhase)
  596. {
  597. buildPhases->AddObject(cmakeRulesBuildPhase);
  598. }
  599. if(sourceBuildPhase)
  600. {
  601. buildPhases->AddObject(sourceBuildPhase);
  602. }
  603. if(headerBuildPhase)
  604. {
  605. buildPhases->AddObject(headerBuildPhase);
  606. }
  607. if(preLinkPhase)
  608. {
  609. buildPhases->AddObject(preLinkPhase);
  610. }
  611. if(frameworkBuildPhase)
  612. {
  613. buildPhases->AddObject(frameworkBuildPhase);
  614. }
  615. if(postBuildPhase)
  616. {
  617. buildPhases->AddObject(postBuildPhase);
  618. }
  619. }
  620. //----------------------------------------------------------------------------
  621. void
  622. cmGlobalXCodeGenerator::AddCommandsToBuildPhase(cmXCodeObject* buildphase,
  623. cmTarget& target,
  624. std::vector<cmCustomCommand>
  625. const & commands,
  626. const char* name)
  627. {
  628. if(strcmp(name, "cmakeReRunPhase") == 0)
  629. {
  630. std::string cdir = m_CurrentMakefile->GetHomeOutputDirectory();
  631. cdir = this->ConvertToRelativeForMake(cdir.c_str());
  632. std::string makecmd = "make -C ";
  633. makecmd += cdir;
  634. makecmd += " -f ";
  635. makecmd +=
  636. this->ConvertToRelativeForMake(m_CurrentReRunCMakeMakefile.c_str());
  637. cmSystemTools::ReplaceString(makecmd, "\\ ", "\\\\ ");
  638. buildphase->AddAttribute("shellScript",
  639. this->CreateString(makecmd.c_str()));
  640. return;
  641. }
  642. std::string dir = m_CurrentMakefile->GetCurrentOutputDirectory();
  643. dir += "/CMakeScripts";
  644. cmSystemTools::MakeDirectory(dir.c_str());
  645. std::string makefile = dir;
  646. makefile += "/";
  647. makefile += target.GetName();
  648. makefile += "_";
  649. makefile += name;
  650. makefile += ".make";
  651. cmGeneratedFileStream makefileStream(makefile.c_str());
  652. if(!makefileStream)
  653. {
  654. return;
  655. }
  656. makefileStream << "# Generated by CMake, DO NOT EDIT\n";
  657. makefileStream << "# Custom rules for " << target.GetName() << "\n";
  658. // have all depend on all outputs
  659. makefileStream << "all: ";
  660. std::map<const cmCustomCommand*, cmStdString> tname;
  661. int count = 0;
  662. for(std::vector<cmCustomCommand>::const_iterator i = commands.begin();
  663. i != commands.end(); ++i)
  664. {
  665. cmCustomCommand const& cc = *i;
  666. if(!cc.GetCommandLines().empty())
  667. {
  668. if(cc.GetOutput()[0])
  669. {
  670. makefileStream << "\\\n\t" << this->
  671. ConvertToRelativeForMake(cc.GetOutput());
  672. }
  673. else
  674. {
  675. char c = '1' + count++;
  676. tname[&cc] = std::string(target.GetName()) + c;
  677. makefileStream << "\\\n\t" << tname[&cc];
  678. }
  679. }
  680. }
  681. makefileStream << "\n\n";
  682. for(std::vector<cmCustomCommand>::const_iterator i = commands.begin();
  683. i != commands.end(); ++i)
  684. {
  685. cmCustomCommand const& cc = *i;
  686. if(!cc.GetCommandLines().empty())
  687. {
  688. makefileStream << "\n#" << "Custom command rule: " <<
  689. cc.GetComment() << "\n";
  690. if(cc.GetOutput()[0])
  691. {
  692. makefileStream << this
  693. ->ConvertToRelativeForMake(cc.GetOutput()) << ": ";
  694. }
  695. else
  696. {
  697. makefileStream << tname[&cc] << ": ";
  698. }
  699. for(std::vector<std::string>::const_iterator d = cc.GetDepends().begin();
  700. d != cc.GetDepends().end(); ++d)
  701. {
  702. if(!this->FindTarget(m_CurrentProject.c_str(),
  703. d->c_str()))
  704. {
  705. makefileStream << "\\\n" << this
  706. ->ConvertToRelativeForMake(d->c_str());
  707. }
  708. else
  709. {
  710. // if the depend is a target then make
  711. // the target with the source that is a custom command
  712. // depend on the that target via a AddUtility call
  713. std::cerr << "AddUtility " << target.GetName() << " " << *d << "\n";
  714. target.AddUtility(d->c_str());
  715. }
  716. }
  717. makefileStream << "\n";
  718. // Add each command line to the set of commands.
  719. for(cmCustomCommandLines::const_iterator cl =
  720. cc.GetCommandLines().begin();
  721. cl != cc.GetCommandLines().end(); ++cl)
  722. {
  723. // Build the command line in a single string.
  724. const cmCustomCommandLine& commandLine = *cl;
  725. std::string cmd = commandLine[0];
  726. cmSystemTools::ReplaceString(cmd, "/./", "/");
  727. cmd = this->ConvertToRelativeForMake(cmd.c_str());
  728. for(unsigned int j=1; j < commandLine.size(); ++j)
  729. {
  730. cmd += " ";
  731. cmd += cmSystemTools::EscapeSpaces(commandLine[j].c_str());
  732. }
  733. makefileStream << "\t" << cmd.c_str() << "\n";
  734. }
  735. }
  736. }
  737. std::string cdir = m_CurrentMakefile->GetCurrentOutputDirectory();
  738. cdir = this->ConvertToRelativeForXCode(cdir.c_str());
  739. std::string makecmd = "make -C ";
  740. makecmd += cdir;
  741. makecmd += " -f ";
  742. makecmd += this->ConvertToRelativeForMake(makefile.c_str());
  743. cmSystemTools::ReplaceString(makecmd, "\\ ", "\\\\ ");
  744. buildphase->AddAttribute("shellScript", this->CreateString(makecmd.c_str()));
  745. }
  746. //----------------------------------------------------------------------------
  747. void cmGlobalXCodeGenerator::CreateBuildSettings(cmTarget& target,
  748. cmXCodeObject* buildSettings,
  749. std::string& fileType,
  750. std::string& productType,
  751. std::string& productName)
  752. {
  753. this->ConfigureOutputPaths();
  754. std::string flags;
  755. bool shared = ((target.GetType() == cmTarget::SHARED_LIBRARY) ||
  756. (target.GetType() == cmTarget::MODULE_LIBRARY));
  757. if(shared)
  758. {
  759. flags += "-D";
  760. if(const char* custom_export_name = target.GetProperty("DEFINE_SYMBOL"))
  761. {
  762. flags += custom_export_name;
  763. }
  764. else
  765. {
  766. std::string in = target.GetName();
  767. in += "_EXPORTS";
  768. flags += cmSystemTools::MakeCindentifier(in.c_str());
  769. }
  770. }
  771. const char* lang = target.GetLinkerLanguage(this);
  772. if(lang)
  773. {
  774. // Add language-specific flags.
  775. m_CurrentLocalGenerator->AddLanguageFlags(flags, lang);
  776. // Add shared-library flags if needed.
  777. m_CurrentLocalGenerator->AddSharedFlags(flags, lang, shared);
  778. }
  779. // Add define flags
  780. m_CurrentLocalGenerator->AppendFlags(flags,
  781. m_CurrentMakefile->GetDefineFlags());
  782. cmSystemTools::ReplaceString(flags, "\"", "\\\"");
  783. productName = target.GetName();
  784. switch(target.GetType())
  785. {
  786. case cmTarget::STATIC_LIBRARY:
  787. {
  788. if(m_LibraryOutputPath.size())
  789. {
  790. buildSettings->AddAttribute("SYMROOT",
  791. this->CreateString
  792. (m_LibraryOutputPath.c_str()));
  793. }
  794. productName += ".a";
  795. std::string t = "lib";
  796. t += productName;
  797. productName = t;
  798. productType = "com.apple.product-type.library.static";
  799. fileType = "archive.ar";
  800. buildSettings->AddAttribute("LIBRARY_STYLE",
  801. this->CreateString("STATIC"));
  802. break;
  803. }
  804. case cmTarget::MODULE_LIBRARY:
  805. {
  806. if(m_LibraryOutputPath.size())
  807. {
  808. buildSettings->AddAttribute("SYMROOT",
  809. this->CreateString
  810. (m_LibraryOutputPath.c_str()));
  811. }
  812. buildSettings->AddAttribute("EXECUTABLE_PREFIX",
  813. this->CreateString("lib"));
  814. buildSettings->AddAttribute("EXECUTABLE_EXTENSION",
  815. this->CreateString("so"));
  816. buildSettings->AddAttribute("LIBRARY_STYLE",
  817. this->CreateString("BUNDLE"));
  818. productName += ".so";
  819. std::string t = "lib";
  820. t += productName;
  821. productName = t;
  822. buildSettings->AddAttribute("OTHER_LDFLAGS",
  823. this->CreateString("-bundle"));
  824. productType = "com.apple.product-type.library.dynamic";
  825. fileType = "compiled.mach-o.dylib";
  826. break;
  827. }
  828. case cmTarget::SHARED_LIBRARY:
  829. {
  830. if(m_LibraryOutputPath.size())
  831. {
  832. buildSettings->AddAttribute("SYMROOT",
  833. this->CreateString
  834. (m_LibraryOutputPath.c_str()));
  835. }
  836. buildSettings->AddAttribute("LIBRARY_STYLE",
  837. this->CreateString("DYNAMIC"));
  838. productName += ".dylib";
  839. std::string t = "lib";
  840. t += productName;
  841. productName = t;
  842. buildSettings->AddAttribute("DYLIB_COMPATIBILITY_VERSION",
  843. this->CreateString("1"));
  844. buildSettings->AddAttribute("DYLIB_CURRENT_VERSION",
  845. this->CreateString("1"));
  846. buildSettings->AddAttribute("OTHER_LDFLAGS",
  847. this->CreateString("-dynamiclib"));
  848. productType = "com.apple.product-type.library.dynamic";
  849. fileType = "compiled.mach-o.dylib";
  850. break;
  851. }
  852. case cmTarget::EXECUTABLE:
  853. if(m_ExecutableOutputPath.size())
  854. {
  855. buildSettings->AddAttribute("SYMROOT",
  856. this->CreateString
  857. (m_ExecutableOutputPath.c_str()));
  858. }
  859. fileType = "compiled.mach-o.executable";
  860. productType = "com.apple.product-type.tool";
  861. break;
  862. case cmTarget::UTILITY:
  863. break;
  864. case cmTarget::INSTALL_FILES:
  865. break;
  866. case cmTarget::INSTALL_PROGRAMS:
  867. break;
  868. }
  869. std::string dirs;
  870. std::vector<std::string>& includes =
  871. m_CurrentMakefile->GetIncludeDirectories();
  872. std::vector<std::string>::iterator i = includes.begin();
  873. for(;i != includes.end(); ++i)
  874. {
  875. std::string incpath =
  876. this->XCodeEscapePath(i->c_str());
  877. dirs += incpath + " ";
  878. }
  879. if(dirs.size())
  880. {
  881. buildSettings->AddAttribute("HEADER_SEARCH_PATHS",
  882. this->CreateString(dirs.c_str()));
  883. }
  884. buildSettings->AddAttribute("GCC_OPTIMIZATION_LEVEL",
  885. this->CreateString("0"));
  886. buildSettings->AddAttribute("INSTALL_PATH",
  887. this->CreateString(""));
  888. buildSettings->AddAttribute("OPTIMIZATION_CFLAGS",
  889. this->CreateString(""));
  890. buildSettings->AddAttribute("OTHER_CFLAGS",
  891. this->CreateString(flags.c_str()));
  892. buildSettings->AddAttribute("OTHER_LDFLAGS",
  893. this->CreateString(""));
  894. buildSettings->AddAttribute("OTHER_REZFLAGS",
  895. this->CreateString(""));
  896. buildSettings->AddAttribute("SECTORDER_FLAGS",
  897. this->CreateString(""));
  898. buildSettings->AddAttribute("USE_HEADERMAP",
  899. this->CreateString("NO"));
  900. buildSettings->AddAttribute("WARNING_CFLAGS",
  901. this->CreateString(
  902. "-Wmost -Wno-four-char-constants"
  903. " -Wno-unknown-pragmas"));
  904. std::string pname;
  905. if(target.GetType() == cmTarget::SHARED_LIBRARY)
  906. {
  907. pname = "lib";
  908. }
  909. pname += target.GetName();
  910. buildSettings->AddAttribute("PRODUCT_NAME",
  911. this->CreateString(pname.c_str()));
  912. }
  913. //----------------------------------------------------------------------------
  914. cmXCodeObject*
  915. cmGlobalXCodeGenerator::CreateUtilityTarget(cmTarget& cmtarget)
  916. {
  917. cmXCodeObject* shellBuildPhase =
  918. this->CreateObject(cmXCodeObject::PBXShellScriptBuildPhase);
  919. shellBuildPhase->AddAttribute("buildActionMask",
  920. this->CreateString("2147483647"));
  921. cmXCodeObject* buildFiles = this->CreateObject(cmXCodeObject::OBJECT_LIST);
  922. shellBuildPhase->AddAttribute("files", buildFiles);
  923. cmXCodeObject* inputPaths = this->CreateObject(cmXCodeObject::OBJECT_LIST);
  924. shellBuildPhase->AddAttribute("inputPaths", inputPaths);
  925. cmXCodeObject* outputPaths = this->CreateObject(cmXCodeObject::OBJECT_LIST);
  926. shellBuildPhase->AddAttribute("outputPaths", outputPaths);
  927. shellBuildPhase->AddAttribute("runOnlyForDeploymentPostprocessing",
  928. this->CreateString("0"));
  929. shellBuildPhase->AddAttribute("shellPath",
  930. this->CreateString("/bin/sh"));
  931. shellBuildPhase->AddAttribute("shellScript",
  932. this->CreateString(
  933. "# shell script goes here\nexit 0"));
  934. cmXCodeObject* target =
  935. this->CreateObject(cmXCodeObject::PBXAggregateTarget);
  936. cmXCodeObject* buildPhases =
  937. this->CreateObject(cmXCodeObject::OBJECT_LIST);
  938. this->CreateCustomCommands(buildPhases, 0, 0, 0, cmtarget);
  939. target->AddAttribute("buildPhases", buildPhases);
  940. cmXCodeObject* buildSettings =
  941. this->CreateObject(cmXCodeObject::ATTRIBUTE_GROUP);
  942. std::string fileTypeString;
  943. std::string productTypeString;
  944. std::string productName;
  945. this->CreateBuildSettings(cmtarget,
  946. buildSettings, fileTypeString,
  947. productTypeString, productName);
  948. target->AddAttribute("buildSettings", buildSettings);
  949. cmXCodeObject* dependencies = this->CreateObject(cmXCodeObject::OBJECT_LIST);
  950. target->AddAttribute("dependencies", dependencies);
  951. target->AddAttribute("name", this->CreateString(cmtarget.GetName()));
  952. target->AddAttribute("productName",this->CreateString(cmtarget.GetName()));
  953. target->SetcmTarget(&cmtarget);
  954. return target;
  955. }
  956. //----------------------------------------------------------------------------
  957. cmXCodeObject*
  958. cmGlobalXCodeGenerator::CreateXCodeTarget(cmTarget& cmtarget,
  959. cmXCodeObject* buildPhases)
  960. {
  961. cmXCodeObject* target =
  962. this->CreateObject(cmXCodeObject::PBXNativeTarget);
  963. target->AddAttribute("buildPhases", buildPhases);
  964. cmXCodeObject* buildRules = this->CreateObject(cmXCodeObject::OBJECT_LIST);
  965. target->AddAttribute("buildRules", buildRules);
  966. cmXCodeObject* buildSettings =
  967. this->CreateObject(cmXCodeObject::ATTRIBUTE_GROUP);
  968. std::string fileTypeString;
  969. std::string productTypeString;
  970. std::string productName;
  971. this->CreateBuildSettings(cmtarget,
  972. buildSettings, fileTypeString,
  973. productTypeString, productName);
  974. target->AddAttribute("buildSettings", buildSettings);
  975. cmXCodeObject* dependencies = this->CreateObject(cmXCodeObject::OBJECT_LIST);
  976. target->AddAttribute("dependencies", dependencies);
  977. target->AddAttribute("name", this->CreateString(cmtarget.GetName()));
  978. target->AddAttribute("productName",this->CreateString(cmtarget.GetName()));
  979. cmXCodeObject* fileRef = this->CreateObject(cmXCodeObject::PBXFileReference);
  980. fileRef->AddAttribute("explicitFileType",
  981. this->CreateString(fileTypeString.c_str()));
  982. fileRef->AddAttribute("path", this->CreateString(productName.c_str()));
  983. fileRef->AddAttribute("refType", this->CreateString("0"));
  984. fileRef->AddAttribute("sourceTree",
  985. this->CreateString("BUILT_PRODUCTS_DIR"));
  986. target->AddAttribute("productReference",
  987. this->CreateObjectReference(fileRef));
  988. target->AddAttribute("productType",
  989. this->CreateString(productTypeString.c_str()));
  990. target->SetcmTarget(&cmtarget);
  991. return target;
  992. }
  993. //----------------------------------------------------------------------------
  994. cmXCodeObject* cmGlobalXCodeGenerator::FindXCodeTarget(cmTarget* t)
  995. {
  996. if(!t)
  997. {
  998. return 0;
  999. }
  1000. for(std::vector<cmXCodeObject*>::iterator i = m_XCodeObjects.begin();
  1001. i != m_XCodeObjects.end(); ++i)
  1002. {
  1003. cmXCodeObject* o = *i;
  1004. if(o->GetcmTarget() == t)
  1005. {
  1006. return o;
  1007. }
  1008. }
  1009. return 0;
  1010. }
  1011. //----------------------------------------------------------------------------
  1012. void cmGlobalXCodeGenerator::AddDependTarget(cmXCodeObject* target,
  1013. cmXCodeObject* dependTarget)
  1014. {
  1015. // make sure a target does not depend on itself
  1016. if(target == dependTarget)
  1017. {
  1018. return;
  1019. }
  1020. // now avoid circular references if dependTarget already
  1021. // depends on target then skip it. Circular references crashes
  1022. // xcode
  1023. cmXCodeObject* dependTargetDepends = dependTarget->GetObject("dependencies");
  1024. if(dependTargetDepends)
  1025. {
  1026. if(dependTargetDepends->HasObject(target->GetPBXTargetDependency()))
  1027. {
  1028. return;
  1029. }
  1030. }
  1031. cmXCodeObject* targetdep = dependTarget->GetPBXTargetDependency();
  1032. if(!targetdep)
  1033. {
  1034. cmXCodeObject* container =
  1035. this->CreateObject(cmXCodeObject::PBXContainerItemProxy);
  1036. container->AddAttribute("containerPortal",
  1037. this->CreateObjectReference(m_RootObject));
  1038. container->AddAttribute("proxyType", this->CreateString("1"));
  1039. container->AddAttribute("remoteGlobalIDString",
  1040. this->CreateObjectReference(dependTarget));
  1041. container->AddAttribute("remoteInfo",
  1042. this->CreateString(
  1043. dependTarget->GetcmTarget()->GetName()));
  1044. targetdep =
  1045. this->CreateObject(cmXCodeObject::PBXTargetDependency);
  1046. targetdep->AddAttribute("target",
  1047. this->CreateObjectReference(dependTarget));
  1048. targetdep->AddAttribute("targetProxy",
  1049. this->CreateObjectReference(container));
  1050. dependTarget->SetPBXTargetDependency(targetdep);
  1051. }
  1052. cmXCodeObject* depends = target->GetObject("dependencies");
  1053. if(!depends)
  1054. {
  1055. cmSystemTools::
  1056. Error("target does not have dependencies attribute error..");
  1057. }
  1058. else
  1059. {
  1060. depends->AddUniqueObject(targetdep);
  1061. }
  1062. }
  1063. //----------------------------------------------------------------------------
  1064. void cmGlobalXCodeGenerator::AddLinkLibrary(cmXCodeObject* target,
  1065. const char* library,
  1066. cmTarget* dtarget)
  1067. {
  1068. if(dtarget)
  1069. {
  1070. target->AddDependLibrary(this->GetTargetFullPath(dtarget).c_str());
  1071. }
  1072. // if the library is not a full path then add it with a -l flag
  1073. // to the settings of the target
  1074. cmXCodeObject* settings = target->GetObject("buildSettings");
  1075. cmXCodeObject* ldflags = settings->GetObject("OTHER_LDFLAGS");
  1076. std::string link = ldflags->GetString();
  1077. cmSystemTools::ReplaceString(link, "\"", "");
  1078. cmsys::RegularExpression reg("^([ \t]*\\-[lWRB])|([ \t]*\\-framework)|(\\${)|([ \t]*\\-pthread)|([ \t]*`)");
  1079. // if the library is not already in the form required by the compiler
  1080. // add a -l infront of the name
  1081. link += " ";
  1082. if(!reg.find(library))
  1083. {
  1084. link += "-l";
  1085. }
  1086. link += library;
  1087. ldflags->SetString(link.c_str());
  1088. }
  1089. //----------------------------------------------------------------------------
  1090. std::string cmGlobalXCodeGenerator::GetTargetFullPath(cmTarget* target)
  1091. {
  1092. std::string libPath;
  1093. cmXCodeObject* xtarget = this->FindXCodeTarget(target);
  1094. cmXCodeObject* bset = xtarget->GetObject("buildSettings");
  1095. cmXCodeObject* spath = bset->GetObject("SYMROOT");
  1096. libPath = spath->GetString();
  1097. libPath = libPath.substr(1, libPath.size()-2);
  1098. if(target->GetType() == cmTarget::STATIC_LIBRARY)
  1099. {
  1100. libPath += "lib";
  1101. libPath += target->GetName();
  1102. libPath += ".a";
  1103. }
  1104. else if(target->GetType() == cmTarget::SHARED_LIBRARY)
  1105. {
  1106. libPath += "lib";
  1107. libPath += target->GetName();
  1108. libPath += ".dylib";
  1109. }
  1110. else
  1111. {
  1112. libPath += target->GetName();
  1113. }
  1114. return libPath;
  1115. }
  1116. //----------------------------------------------------------------------------
  1117. void cmGlobalXCodeGenerator::AddDependAndLinkInformation(cmXCodeObject* target)
  1118. {
  1119. cmTarget* cmtarget = target->GetcmTarget();
  1120. if(!cmtarget)
  1121. {
  1122. cmSystemTools::Error("Error no target on xobject\n");
  1123. return;
  1124. }
  1125. // compute the correct order for link libraries
  1126. cmOrderLinkDirectories orderLibs;
  1127. std::string ext =
  1128. m_CurrentMakefile->GetSafeDefinition("CMAKE_STATIC_LIBRARY_SUFFIX");
  1129. if(ext.size())
  1130. {
  1131. orderLibs.AddLinkExtension(ext.c_str());
  1132. }
  1133. ext =
  1134. m_CurrentMakefile->GetSafeDefinition("CMAKE_SHARED_LIBRARY_SUFFIX");
  1135. if(ext.size())
  1136. {
  1137. orderLibs.AddLinkExtension(ext.c_str());
  1138. }
  1139. ext =
  1140. m_CurrentMakefile->GetSafeDefinition("CMAKE_LINK_LIBRARY_SUFFIX");
  1141. if(ext.size())
  1142. {
  1143. orderLibs.AddLinkExtension(ext.c_str());
  1144. }
  1145. const char* targetLibrary = cmtarget->GetName();
  1146. if(cmtarget->GetType() == cmTarget::EXECUTABLE)
  1147. {
  1148. targetLibrary = 0;
  1149. }
  1150. orderLibs.SetLinkInformation(*cmtarget, cmTarget::GENERAL, targetLibrary);
  1151. orderLibs.DetermineLibraryPathOrder();
  1152. std::vector<cmStdString> libdirs;
  1153. std::vector<cmStdString> linkItems;
  1154. orderLibs.GetLinkerInformation(libdirs, linkItems);
  1155. std::string linkDirs;
  1156. // add the library search paths
  1157. for(std::vector<cmStdString>::const_iterator libDir = libdirs.begin();
  1158. libDir != libdirs.end(); ++libDir)
  1159. {
  1160. if(libDir->size() && *libDir != "/usr/lib")
  1161. {
  1162. linkDirs += " ";
  1163. linkDirs += this->XCodeEscapePath(libDir->c_str());
  1164. }
  1165. }
  1166. cmXCodeObject* bset = target->GetObject("buildSettings");
  1167. if(bset)
  1168. {
  1169. bset->AddAttribute("LIBRARY_SEARCH_PATHS",
  1170. this->CreateString(linkDirs.c_str()));
  1171. }
  1172. // now add the link libraries
  1173. for(std::vector<cmStdString>::iterator lib = linkItems.begin();
  1174. lib != linkItems.end(); ++lib)
  1175. {
  1176. cmTarget* t = this->FindTarget(m_CurrentProject.c_str(),
  1177. lib->c_str());
  1178. cmXCodeObject* dptarget = this->FindXCodeTarget(t);
  1179. if(dptarget)
  1180. {
  1181. this->AddDependTarget(target, dptarget);
  1182. if(cmtarget->GetType() != cmTarget::STATIC_LIBRARY)
  1183. {
  1184. this->AddLinkLibrary(target, t->GetName(), t);
  1185. }
  1186. }
  1187. else
  1188. {
  1189. if(cmtarget->GetType() != cmTarget::STATIC_LIBRARY)
  1190. {
  1191. this->AddLinkLibrary(target, lib->c_str());
  1192. }
  1193. }
  1194. }
  1195. // write utility dependencies.
  1196. for(std::set<cmStdString>::const_iterator i
  1197. = cmtarget->GetUtilities().begin();
  1198. i != cmtarget->GetUtilities().end(); ++i)
  1199. {
  1200. cmTarget* t = this->FindTarget(m_CurrentProject.c_str(),
  1201. i->c_str());
  1202. // if the target is in this project then make target depend
  1203. // on it. It may not be in this project if this is a sub
  1204. // project from the top.
  1205. if(t)
  1206. {
  1207. cmXCodeObject* dptarget = this->FindXCodeTarget(t);
  1208. if(dptarget)
  1209. {
  1210. this->AddDependTarget(target, dptarget);
  1211. }
  1212. else
  1213. {
  1214. std::string m = "Error Utility: ";
  1215. m += i->c_str();
  1216. m += "\n";
  1217. m += "cmtarget ";
  1218. if(t)
  1219. {
  1220. m += t->GetName();
  1221. }
  1222. m += "\n";
  1223. m += "Is on the target ";
  1224. m += cmtarget->GetName();
  1225. m += "\n";
  1226. m += "But it has no xcode target created yet??\n";
  1227. m += "Current project is ";
  1228. m += m_CurrentProject.c_str();
  1229. cmSystemTools::Error(m.c_str());
  1230. }
  1231. }
  1232. }
  1233. std::vector<cmStdString> fullPathLibs;
  1234. orderLibs.GetFullPathLibraries(fullPathLibs);
  1235. for(std::vector<cmStdString>::iterator i = fullPathLibs.begin();
  1236. i != fullPathLibs.end(); ++i)
  1237. {
  1238. target->AddDependLibrary(i->c_str());
  1239. }
  1240. }
  1241. //----------------------------------------------------------------------------
  1242. void cmGlobalXCodeGenerator::CreateGroups(cmLocalGenerator* root,
  1243. std::vector<cmLocalGenerator*>&
  1244. generators)
  1245. {
  1246. for(std::vector<cmLocalGenerator*>::iterator i = generators.begin();
  1247. i != generators.end(); ++i)
  1248. {
  1249. if(this->IsExcluded(root, *i))
  1250. {
  1251. continue;
  1252. }
  1253. cmMakefile* mf = (*i)->GetMakefile();
  1254. std::vector<cmSourceGroup> sourceGroups = mf->GetSourceGroups();
  1255. cmTargets &tgts = mf->GetTargets();
  1256. for(cmTargets::iterator l = tgts.begin(); l != tgts.end(); l++)
  1257. {
  1258. cmTarget& cmtarget = l->second;
  1259. std::vector<cmSourceFile*> & classes = cmtarget.GetSourceFiles();
  1260. for(std::vector<cmSourceFile*>::const_iterator s = classes.begin();
  1261. s != classes.end(); s++)
  1262. {
  1263. cmSourceFile* sf = *s;
  1264. // Add the file to the list of sources.
  1265. std::string const& source = sf->GetFullPath();
  1266. cmSourceGroup& sourceGroup =
  1267. mf->FindSourceGroup(source.c_str(), sourceGroups);
  1268. cmXCodeObject* pbxgroup = this->CreateOrGetPBXGroup(cmtarget, &sourceGroup);
  1269. m_GroupMap[sf] = pbxgroup;
  1270. }
  1271. }
  1272. }
  1273. }
  1274. //----------------------------------------------------------------------------
  1275. cmXCodeObject* cmGlobalXCodeGenerator::CreateOrGetPBXGroup(cmTarget& cmtarget,
  1276. cmSourceGroup* sg)
  1277. {
  1278. cmStdString s = cmtarget.GetName();
  1279. s += "/";
  1280. s += sg->GetName();
  1281. std::map<cmStdString, cmXCodeObject* >::iterator i = m_GroupNameMap.find(s);
  1282. if(i != m_GroupNameMap.end())
  1283. {
  1284. return i->second;
  1285. }
  1286. i = m_TargetGroup.find(cmtarget.GetName());
  1287. cmXCodeObject* tgroup = 0;
  1288. if(i != m_TargetGroup.end())
  1289. {
  1290. tgroup = i->second;
  1291. }
  1292. else
  1293. {
  1294. tgroup = this->CreateObject(cmXCodeObject::PBXGroup);
  1295. m_TargetGroup[cmtarget.GetName()] = tgroup;
  1296. cmXCodeObject* tgroupChildren =
  1297. this->CreateObject(cmXCodeObject::OBJECT_LIST);
  1298. tgroup->AddAttribute("name", this->CreateString(cmtarget.GetName()));
  1299. tgroup->AddAttribute("children", tgroupChildren);
  1300. tgroup->AddAttribute("refType", this->CreateString("4"));
  1301. tgroup->AddAttribute("sourceTree", this->CreateString("<group>"));
  1302. m_SourcesGroupChildren->AddObject(tgroup);
  1303. }
  1304. cmXCodeObject* tgroupChildren = tgroup->GetObject("children");
  1305. cmXCodeObject* group = this->CreateObject(cmXCodeObject::PBXGroup);
  1306. cmXCodeObject* groupChildren =
  1307. this->CreateObject(cmXCodeObject::OBJECT_LIST);
  1308. group->AddAttribute("name", this->CreateString(sg->GetName()));
  1309. group->AddAttribute("children", groupChildren);
  1310. group->AddAttribute("refType", this->CreateString("4"));
  1311. group->AddAttribute("sourceTree", this->CreateString("<group>"));
  1312. tgroupChildren->AddObject(group);
  1313. m_GroupNameMap[s] = group;
  1314. return group;
  1315. }
  1316. //----------------------------------------------------------------------------
  1317. void cmGlobalXCodeGenerator::CreateXCodeObjects(cmLocalGenerator* root,
  1318. std::vector<cmLocalGenerator*>&
  1319. generators
  1320. )
  1321. {
  1322. this->ClearXCodeObjects();
  1323. m_RootObject = 0;
  1324. m_SourcesGroupChildren = 0;
  1325. m_MainGroupChildren = 0;
  1326. cmXCodeObject* group = this->CreateObject(cmXCodeObject::ATTRIBUTE_GROUP);
  1327. group->AddAttribute("COPY_PHASE_STRIP", this->CreateString("NO"));
  1328. cmXCodeObject* developBuildStyle =
  1329. this->CreateObject(cmXCodeObject::PBXBuildStyle);
  1330. developBuildStyle->AddAttribute("name", this->CreateString("Development"));
  1331. developBuildStyle->AddAttribute("buildSettings", group);
  1332. group = this->CreateObject(cmXCodeObject::ATTRIBUTE_GROUP);
  1333. group->AddAttribute("COPY_PHASE_STRIP", this->CreateString("YES"));
  1334. cmXCodeObject* deployBuildStyle =
  1335. this->CreateObject(cmXCodeObject::PBXBuildStyle);
  1336. deployBuildStyle->AddAttribute("name", this->CreateString("Deployment"));
  1337. deployBuildStyle->AddAttribute("buildSettings", group);
  1338. cmXCodeObject* listObjs = this->CreateObject(cmXCodeObject::OBJECT_LIST);
  1339. listObjs->AddObject(developBuildStyle);
  1340. listObjs->AddObject(deployBuildStyle);
  1341. cmXCodeObject* mainGroup = this->CreateObject(cmXCodeObject::PBXGroup);
  1342. m_MainGroupChildren =
  1343. this->CreateObject(cmXCodeObject::OBJECT_LIST);
  1344. mainGroup->AddAttribute("children", m_MainGroupChildren);
  1345. mainGroup->AddAttribute("refType", this->CreateString("4"));
  1346. mainGroup->AddAttribute("sourceTree", this->CreateString("<group>"));
  1347. cmXCodeObject* sourcesGroup = this->CreateObject(cmXCodeObject::PBXGroup);
  1348. m_SourcesGroupChildren =
  1349. this->CreateObject(cmXCodeObject::OBJECT_LIST);
  1350. sourcesGroup->AddAttribute("name", this->CreateString("Sources"));
  1351. sourcesGroup->AddAttribute("children", m_SourcesGroupChildren);
  1352. sourcesGroup->AddAttribute("refType", this->CreateString("4"));
  1353. sourcesGroup->AddAttribute("sourceTree", this->CreateString("<group>"));
  1354. m_MainGroupChildren->AddObject(sourcesGroup);
  1355. // now create the cmake groups
  1356. this->CreateGroups(root, generators);
  1357. cmXCodeObject* productGroup = this->CreateObject(cmXCodeObject::PBXGroup);
  1358. productGroup->AddAttribute("name", this->CreateString("Products"));
  1359. productGroup->AddAttribute("refType", this->CreateString("4"));
  1360. productGroup->AddAttribute("sourceTree", this->CreateString("<group>"));
  1361. cmXCodeObject* productGroupChildren =
  1362. this->CreateObject(cmXCodeObject::OBJECT_LIST);
  1363. productGroup->AddAttribute("children", productGroupChildren);
  1364. m_MainGroupChildren->AddObject(productGroup);
  1365. m_RootObject = this->CreateObject(cmXCodeObject::PBXProject);
  1366. group = this->CreateObject(cmXCodeObject::ATTRIBUTE_GROUP);
  1367. m_RootObject->AddAttribute("mainGroup",
  1368. this->CreateObjectReference(mainGroup));
  1369. m_RootObject->AddAttribute("buildSettings", group);
  1370. m_RootObject->AddAttribute("buildSyles", listObjs);
  1371. m_RootObject->AddAttribute("hasScannedForEncodings",
  1372. this->CreateString("0"));
  1373. std::vector<cmXCodeObject*> targets;
  1374. for(std::vector<cmLocalGenerator*>::iterator i = generators.begin();
  1375. i != generators.end(); ++i)
  1376. {
  1377. if(!this->IsExcluded(root, *i))
  1378. {
  1379. this->CreateXCodeTargets(*i, targets);
  1380. }
  1381. }
  1382. // loop over all targets and add link and depend info
  1383. for(std::vector<cmXCodeObject*>::iterator i = targets.begin();
  1384. i != targets.end(); ++i)
  1385. {
  1386. cmXCodeObject* t = *i;
  1387. this->AddDependAndLinkInformation(t);
  1388. }
  1389. // now create xcode depend hack makefile
  1390. this->CreateXCodeDependHackTarget(targets);
  1391. // now add all targets to the root object
  1392. cmXCodeObject* allTargets = this->CreateObject(cmXCodeObject::OBJECT_LIST);
  1393. for(std::vector<cmXCodeObject*>::iterator i = targets.begin();
  1394. i != targets.end(); ++i)
  1395. {
  1396. cmXCodeObject* t = *i;
  1397. allTargets->AddObject(t);
  1398. cmXCodeObject* productRef = t->GetObject("productReference");
  1399. if(productRef)
  1400. {
  1401. productGroupChildren->AddObject(productRef->GetObject());
  1402. }
  1403. }
  1404. m_RootObject->AddAttribute("targets", allTargets);
  1405. }
  1406. //----------------------------------------------------------------------------
  1407. void
  1408. cmGlobalXCodeGenerator::CreateXCodeDependHackTarget(
  1409. std::vector<cmXCodeObject*>& targets)
  1410. {
  1411. cmGeneratedFileStream makefileStream(m_CurrentXCodeHackMakefile.c_str());
  1412. if(!makefileStream)
  1413. {
  1414. cmSystemTools::Error("Could not create",
  1415. m_CurrentXCodeHackMakefile.c_str());
  1416. return;
  1417. }
  1418. // one more pass for external depend information not handled
  1419. // correctly by xcode
  1420. makefileStream << "# DO NOT EDIT\n";
  1421. makefileStream << "# This makefile makes sure all linkable targets are \n";
  1422. makefileStream
  1423. << "# up-to-date with anything they link to,avoiding a bug in XCode 1.5\n";
  1424. makefileStream << "all: ";
  1425. for(std::vector<cmXCodeObject*>::iterator i = targets.begin();
  1426. i != targets.end(); ++i)
  1427. {
  1428. cmXCodeObject* target = *i;
  1429. cmTarget* t =target->GetcmTarget();
  1430. if(t->GetType() == cmTarget::EXECUTABLE ||
  1431. t->GetType() == cmTarget::SHARED_LIBRARY ||
  1432. t->GetType() == cmTarget::MODULE_LIBRARY)
  1433. {
  1434. makefileStream << "\\\n\t"
  1435. << this->
  1436. ConvertToRelativeForMake(this->GetTargetFullPath(target->GetcmTarget()).c_str());
  1437. }
  1438. }
  1439. makefileStream << "\n\n";
  1440. makefileStream
  1441. << "# For each target create a dummy rule "
  1442. "so the target does not have to exist\n";
  1443. std::set<cmStdString> emitted;
  1444. for(std::vector<cmXCodeObject*>::iterator i = targets.begin();
  1445. i != targets.end(); ++i)
  1446. {
  1447. cmXCodeObject* target = *i;
  1448. std::vector<cmStdString> const& deplibs = target->GetDependLibraries();
  1449. for(std::vector<cmStdString>::const_iterator d = deplibs.begin();
  1450. d != deplibs.end(); ++d)
  1451. {
  1452. if(emitted.insert(*d).second)
  1453. {
  1454. makefileStream << this->ConvertToRelativeForMake(d->c_str()) << ":\n";
  1455. }
  1456. }
  1457. }
  1458. makefileStream << "\n\n";
  1459. makefileStream <<
  1460. "# Each linkable target depends on everything it links to.\n";
  1461. makefileStream
  1462. << "#And the target is removed if it is older than what it linkes to\n";
  1463. for(std::vector<cmXCodeObject*>::iterator i = targets.begin();
  1464. i != targets.end(); ++i)
  1465. {
  1466. cmXCodeObject* target = *i;
  1467. cmTarget* t =target->GetcmTarget();
  1468. if(t->GetType() == cmTarget::EXECUTABLE ||
  1469. t->GetType() == cmTarget::SHARED_LIBRARY ||
  1470. t->GetType() == cmTarget::MODULE_LIBRARY)
  1471. {
  1472. std::vector<cmStdString> const& deplibs = target->GetDependLibraries();
  1473. std::string tfull = this->GetTargetFullPath(target->GetcmTarget());
  1474. makefileStream << this->ConvertToRelativeForMake(tfull.c_str()) << ": ";
  1475. for(std::vector<cmStdString>::const_iterator d = deplibs.begin();
  1476. d != deplibs.end(); ++d)
  1477. {
  1478. makefileStream << "\\\n\t" << this->ConvertToRelativeForMake(d->c_str());
  1479. }
  1480. makefileStream << "\n";
  1481. makefileStream << "\t/bin/rm -f "
  1482. << this->ConvertToRelativeForMake(tfull.c_str()) << "\n";
  1483. makefileStream << "\n\n";
  1484. }
  1485. }
  1486. }
  1487. //----------------------------------------------------------------------------
  1488. void
  1489. cmGlobalXCodeGenerator::OutputXCodeProject(cmLocalGenerator* root,
  1490. std::vector<cmLocalGenerator*>&
  1491. generators)
  1492. {
  1493. if(generators.size() == 0)
  1494. {
  1495. return;
  1496. }
  1497. this->CreateXCodeObjects(root,
  1498. generators);
  1499. std::string xcodeDir = root->GetMakefile()->GetStartOutputDirectory();
  1500. xcodeDir += "/";
  1501. xcodeDir += root->GetMakefile()->GetProjectName();
  1502. xcodeDir += ".xcode";
  1503. cmSystemTools::MakeDirectory(xcodeDir.c_str());
  1504. xcodeDir += "/project.pbxproj";
  1505. cmGeneratedFileStream fout(xcodeDir.c_str());
  1506. fout.SetCopyIfDifferent(true);
  1507. if(!fout)
  1508. {
  1509. return;
  1510. }
  1511. this->WriteXCodePBXProj(fout, root, generators);
  1512. this->ClearXCodeObjects();
  1513. }
  1514. //----------------------------------------------------------------------------
  1515. void
  1516. cmGlobalXCodeGenerator::WriteXCodePBXProj(std::ostream& fout,
  1517. cmLocalGenerator* ,
  1518. std::vector<cmLocalGenerator*>& )
  1519. {
  1520. fout << "// !$*UTF8*$!\n";
  1521. fout << "{\n";
  1522. cmXCodeObject::Indent(1, fout);
  1523. fout << "archiveVersion = 1;\n";
  1524. cmXCodeObject::Indent(1, fout);
  1525. fout << "classes = {\n";
  1526. cmXCodeObject::Indent(1, fout);
  1527. fout << "};\n";
  1528. cmXCodeObject::Indent(1, fout);
  1529. fout << "objectVersion = 39;\n";
  1530. cmXCodeObject::PrintList(m_XCodeObjects, fout);
  1531. cmXCodeObject::Indent(1, fout);
  1532. fout << "rootObject = " << m_RootObject->GetId() << ";\n";
  1533. fout << "}\n";
  1534. }
  1535. //----------------------------------------------------------------------------
  1536. void cmGlobalXCodeGenerator::GetDocumentation(cmDocumentationEntry& entry)
  1537. const
  1538. {
  1539. entry.name = this->GetName();
  1540. entry.brief = "Generate XCode project files.";
  1541. entry.full = "";
  1542. }
  1543. //----------------------------------------------------------------------------
  1544. std::string cmGlobalXCodeGenerator::ConvertToRelativeForMake(const char* p)
  1545. {
  1546. if ( !m_CurrentMakefile->IsOn("CMAKE_USE_RELATIVE_PATHS") )
  1547. {
  1548. return cmSystemTools::ConvertToOutputPath(p);
  1549. }
  1550. else
  1551. {
  1552. std::string ret = this->ConvertToRelativePath(m_CurrentOutputDirectoryComponents, p);
  1553. return cmSystemTools::ConvertToOutputPath(ret.c_str());
  1554. }
  1555. }
  1556. //----------------------------------------------------------------------------
  1557. std::string cmGlobalXCodeGenerator::ConvertToRelativeForXCode(const char* p)
  1558. {
  1559. if ( !m_CurrentMakefile->IsOn("CMAKE_USE_RELATIVE_PATHS") )
  1560. {
  1561. return cmSystemTools::ConvertToOutputPath(p);
  1562. }
  1563. else
  1564. {
  1565. std::string ret = this->ConvertToRelativePath(m_ProjectOutputDirectoryComponents, p);
  1566. return cmSystemTools::ConvertToOutputPath(ret.c_str());
  1567. }
  1568. }
  1569. std::string cmGlobalXCodeGenerator::XCodeEscapePath(const char* p)
  1570. {
  1571. std::string ret = p;
  1572. if(ret.find(' ') != ret.npos)
  1573. {
  1574. std::string t = ret;
  1575. ret = "\\\"";
  1576. ret += t;
  1577. ret += "\\\"";
  1578. }
  1579. return ret;
  1580. }