cmExtraEclipseCDT4Generator.cxx 32 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960
  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. Copyright (c) 2004 Alexander Neundorf [email protected], All rights reserved.
  9. Copyright (c) 2007 Miguel A. Figueroa-Villanueva. All rights reserved.
  10. See Copyright.txt or http://www.cmake.org/HTML/Copyright.html for details.
  11. This software is distributed WITHOUT ANY WARRANTY; without even
  12. the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
  13. PURPOSE. See the above copyright notices for more information.
  14. =========================================================================*/
  15. #include "cmExtraEclipseCDT4Generator.h"
  16. #include "cmGlobalUnixMakefileGenerator3.h"
  17. #include "cmLocalUnixMakefileGenerator3.h"
  18. #include "cmMakefile.h"
  19. #include "cmGeneratedFileStream.h"
  20. #include "cmTarget.h"
  21. #include "cmSystemTools.h"
  22. #include <stdlib.h>
  23. #include <assert.h>
  24. //----------------------------------------------------------------------------
  25. cmExtraEclipseCDT4Generator
  26. ::cmExtraEclipseCDT4Generator() : cmExternalMakefileProjectGenerator()
  27. {
  28. // TODO: Verify if __CYGWIN__ should be checked.
  29. //#if defined(_WIN32) && !defined(__CYGWIN__)
  30. #if defined(_WIN32)
  31. this->SupportedGlobalGenerators.push_back("NMake Makefiles");
  32. this->SupportedGlobalGenerators.push_back("MinGW Makefiles");
  33. // this->SupportedGlobalGenerators.push_back("MSYS Makefiles");
  34. #endif
  35. this->SupportedGlobalGenerators.push_back("Unix Makefiles");
  36. // don't create these targets in Eclipse, they are too many and
  37. // should be only rarely used directly
  38. this->TargetsToIgnore.insert("preinstall");
  39. this->TargetsToIgnore.insert("install/local");
  40. this->TargetsToIgnore.insert("ContinuousBuild");
  41. this->TargetsToIgnore.insert("ContinuousConfigure");
  42. this->TargetsToIgnore.insert("ContinuousCoverage");
  43. this->TargetsToIgnore.insert("ContinuousMemCheck");
  44. this->TargetsToIgnore.insert("ContinuousStart");
  45. this->TargetsToIgnore.insert("ContinuousSubmit");
  46. this->TargetsToIgnore.insert("ContinuousTest");
  47. this->TargetsToIgnore.insert("ContinuousUpdate");
  48. this->TargetsToIgnore.insert("ExperimentalBuild");
  49. this->TargetsToIgnore.insert("ExperimentalConfigure");
  50. this->TargetsToIgnore.insert("ExperimentalCoverage");
  51. this->TargetsToIgnore.insert("ExperimentalMemCheck");
  52. this->TargetsToIgnore.insert("ExperimentalStart");
  53. this->TargetsToIgnore.insert("ExperimentalSubmit");
  54. this->TargetsToIgnore.insert("ExperimentalTest");
  55. this->TargetsToIgnore.insert("ExperimentalUpdate");
  56. this->TargetsToIgnore.insert("NightlyBuild");
  57. this->TargetsToIgnore.insert("NightlyConfigure");
  58. this->TargetsToIgnore.insert("NightlyCoverage");
  59. this->TargetsToIgnore.insert("NightlyMemCheck");
  60. this->TargetsToIgnore.insert("NightlyMemoryCheck");
  61. this->TargetsToIgnore.insert("NightlyStart");
  62. this->TargetsToIgnore.insert("NightlySubmit");
  63. this->TargetsToIgnore.insert("NightlyTest");
  64. this->TargetsToIgnore.insert("NightlyUpdate");
  65. }
  66. //----------------------------------------------------------------------------
  67. void cmExtraEclipseCDT4Generator
  68. ::GetDocumentation(cmDocumentationEntry& entry, const char*) const
  69. {
  70. entry.Name = this->GetName();
  71. entry.Brief = "Generates Eclipse CDT 4.0 project files.";
  72. entry.Full =
  73. "Project files for Eclipse will be created in the top directory "
  74. "and will have a linked resource to every subdirectory which "
  75. "features a CMakeLists.txt file containing a PROJECT() call."
  76. "Additionally a hierarchy of makefiles is generated into the "
  77. "build tree. The appropriate make program can build the project through "
  78. "the default make target. A \"make install\" target is also provided.";
  79. }
  80. //----------------------------------------------------------------------------
  81. void cmExtraEclipseCDT4Generator
  82. ::SetGlobalGenerator(cmGlobalGenerator* generator)
  83. {
  84. cmExternalMakefileProjectGenerator::SetGlobalGenerator(generator);
  85. cmGlobalUnixMakefileGenerator3* mf
  86. = static_cast<cmGlobalUnixMakefileGenerator3*>(generator);
  87. mf->SetToolSupportsColor(true);
  88. mf->SetForceVerboseMakefiles(true);
  89. }
  90. //----------------------------------------------------------------------------
  91. void cmExtraEclipseCDT4Generator::Generate()
  92. {
  93. const cmMakefile* mf
  94. = this->GlobalGenerator->GetLocalGenerators()[0]->GetMakefile();
  95. // TODO: Decide if these are local or member variables
  96. this->HomeDirectory = mf->GetHomeDirectory();
  97. this->HomeOutputDirectory = mf->GetHomeOutputDirectory();
  98. this->IsOutOfSourceBuild = (this->HomeDirectory!=this->HomeOutputDirectory);
  99. this->GenerateSourceProject = (this->IsOutOfSourceBuild &&
  100. mf->IsOn("ECLIPSE_CDT4_GENERATE_SOURCE_PROJECT"));
  101. // NOTE: This is not good, since it pollutes the source tree. However,
  102. // Eclipse doesn't allow CVS/SVN to work when the .project is not in
  103. // the cvs/svn root directory. Hence, this is provided as an option.
  104. if (this->GenerateSourceProject)
  105. {
  106. // create .project file in the source tree
  107. this->CreateSourceProjectFile();
  108. }
  109. // create a .project file
  110. this->CreateProjectFile();
  111. // create a .cproject file
  112. this->CreateCProjectFile();
  113. }
  114. void cmExtraEclipseCDT4Generator::CreateSourceProjectFile() const
  115. {
  116. assert(this->HomeDirectory != this->HomeOutputDirectory);
  117. // set up the project name: <project>-Source@<baseSourcePathName>
  118. const cmMakefile* mf
  119. = this->GlobalGenerator->GetLocalGenerators()[0]->GetMakefile();
  120. std::string name = this->GenerateProjectName(mf->GetProjectName(), "Source",
  121. this->GetPathBasename(this->HomeDirectory));
  122. const std::string filename = this->HomeDirectory + "/.project";
  123. cmGeneratedFileStream fout(filename.c_str());
  124. if (!fout)
  125. {
  126. return;
  127. }
  128. fout <<
  129. "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
  130. "<projectDescription>\n"
  131. "\t<name>" << name << "</name>\n"
  132. "\t<comment></comment>\n"
  133. "\t<projects>\n"
  134. "\t</projects>\n"
  135. "\t<buildSpec>\n"
  136. "\t</buildSpec>\n"
  137. "\t<natures>\n"
  138. "\t</natures>\n"
  139. "</projectDescription>\n"
  140. ;
  141. }
  142. //----------------------------------------------------------------------------
  143. void cmExtraEclipseCDT4Generator::CreateProjectFile()
  144. {
  145. const cmMakefile* mf
  146. = this->GlobalGenerator->GetLocalGenerators()[0]->GetMakefile();
  147. const std::string filename = this->HomeOutputDirectory + "/.project";
  148. cmGeneratedFileStream fout(filename.c_str());
  149. if (!fout)
  150. {
  151. return;
  152. }
  153. fout <<
  154. "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
  155. "<projectDescription>\n"
  156. "\t<name>" <<
  157. this->GenerateProjectName(mf->GetProjectName(),
  158. mf->GetDefinition("CMAKE_BUILD_TYPE"),
  159. this->GetPathBasename(this->HomeOutputDirectory))
  160. << "</name>\n"
  161. "\t<comment></comment>\n"
  162. "\t<projects>\n"
  163. "\t</projects>\n"
  164. "\t<buildSpec>\n"
  165. "\t\t<buildCommand>\n"
  166. "\t\t\t<name>org.eclipse.cdt.make.core.makeBuilder</name>\n"
  167. "\t\t\t<triggers>clean,full,incremental,</triggers>\n"
  168. "\t\t\t<arguments>\n"
  169. ;
  170. // use clean target
  171. fout <<
  172. "\t\t\t\t<dictionary>\n"
  173. "\t\t\t\t\t<key>org.eclipse.cdt.make.core.cleanBuildTarget</key>\n"
  174. "\t\t\t\t\t<value>clean</value>\n"
  175. "\t\t\t\t</dictionary>\n"
  176. "\t\t\t\t<dictionary>\n"
  177. "\t\t\t\t\t<key>org.eclipse.cdt.make.core.enableCleanBuild</key>\n"
  178. "\t\t\t\t\t<value>true</value>\n"
  179. "\t\t\t\t</dictionary>\n"
  180. "\t\t\t\t<dictionary>\n"
  181. "\t\t\t\t\t<key>org.eclipse.cdt.make.core.append_environment</key>\n"
  182. "\t\t\t\t\t<value>true</value>\n"
  183. "\t\t\t\t</dictionary>\n"
  184. "\t\t\t\t<dictionary>\n"
  185. "\t\t\t\t\t<key>org.eclipse.cdt.make.core.stopOnError</key>\n"
  186. "\t\t\t\t\t<value>true</value>\n"
  187. "\t\t\t\t</dictionary>\n"
  188. ;
  189. // set the make command
  190. std::string make = mf->GetRequiredDefinition("CMAKE_MAKE_PROGRAM");
  191. fout <<
  192. "\t\t\t\t<dictionary>\n"
  193. "\t\t\t\t\t<key>org.eclipse.cdt.make.core.enabledIncrementalBuild</key>\n"
  194. "\t\t\t\t\t<value>true</value>\n"
  195. "\t\t\t\t</dictionary>\n"
  196. "\t\t\t\t<dictionary>\n"
  197. "\t\t\t\t\t<key>org.eclipse.cdt.make.core.build.command</key>\n"
  198. "\t\t\t\t\t<value>" + this->GetEclipsePath(make) + "</value>\n"
  199. "\t\t\t\t</dictionary>\n"
  200. "\t\t\t\t<dictionary>\n"
  201. "\t\t\t\t\t<key>org.eclipse.cdt.make.core.contents</key>\n"
  202. "\t\t\t\t\t<value>org.eclipse.cdt.make.core.activeConfigSettings</value>\n"
  203. "\t\t\t\t</dictionary>\n"
  204. "\t\t\t\t<dictionary>\n"
  205. "\t\t\t\t\t<key>org.eclipse.cdt.make.core.build.target.inc</key>\n"
  206. "\t\t\t\t\t<value>all</value>\n"
  207. "\t\t\t\t</dictionary>\n"
  208. "\t\t\t\t<dictionary>\n"
  209. "\t\t\t\t\t<key>org.eclipse.cdt.make.core.build.arguments</key>\n"
  210. "\t\t\t\t\t<value></value>\n"
  211. "\t\t\t\t</dictionary>\n"
  212. "\t\t\t\t<dictionary>\n"
  213. "\t\t\t\t\t<key>org.eclipse.cdt.make.core.buildLocation</key>\n"
  214. "\t\t\t\t\t<value>"
  215. << this->GetEclipsePath(this->HomeOutputDirectory) << "</value>\n"
  216. "\t\t\t\t</dictionary>\n"
  217. "\t\t\t\t<dictionary>\n"
  218. "\t\t\t\t\t<key>org.eclipse.cdt.make.core.useDefaultBuildCmd</key>\n"
  219. "\t\t\t\t\t<value>false</value>\n"
  220. "\t\t\t\t</dictionary>\n"
  221. ;
  222. // set project specific environment
  223. fout <<
  224. "\t\t\t\t<dictionary>\n"
  225. "\t\t\t\t\t<key>org.eclipse.cdt.make.core.environment</key>\n"
  226. "\t\t\t\t\t<value>"
  227. ;
  228. // set vsvars32.bat environment available at CMake time,
  229. // but not necessarily when eclipse is open
  230. if (make.find("nmake") != std::string::npos)
  231. {
  232. if (getenv("PATH"))
  233. {
  234. fout << "PATH=" << getenv("PATH") << "|";
  235. }
  236. if (getenv("INCLUDE"))
  237. {
  238. fout << "INCLUDE=" << getenv("INCLUDE") << "|";
  239. }
  240. if (getenv("LIB"))
  241. {
  242. fout << "LIB=" << getenv("LIB") << "|";
  243. }
  244. if (getenv("LIBPATH"))
  245. {
  246. fout << "LIBPATH=" << getenv("LIBPATH") << "|";
  247. }
  248. }
  249. fout <<
  250. "</value>\n"
  251. "\t\t\t\t</dictionary>\n"
  252. ;
  253. fout <<
  254. "\t\t\t\t<dictionary>\n"
  255. "\t\t\t\t\t<key>org.eclipse.cdt.make.core.enableFullBuild</key>\n"
  256. "\t\t\t\t\t<value>true</value>\n"
  257. "\t\t\t\t</dictionary>\n"
  258. "\t\t\t\t<dictionary>\n"
  259. "\t\t\t\t\t<key>org.eclipse.cdt.make.core.build.target.auto</key>\n"
  260. "\t\t\t\t\t<value>all</value>\n"
  261. "\t\t\t\t</dictionary>\n"
  262. "\t\t\t\t<dictionary>\n"
  263. "\t\t\t\t\t<key>org.eclipse.cdt.make.core.enableAutoBuild</key>\n"
  264. "\t\t\t\t\t<value>false</value>\n"
  265. "\t\t\t\t</dictionary>\n"
  266. "\t\t\t\t<dictionary>\n"
  267. "\t\t\t\t\t<key>org.eclipse.cdt.make.core.build.target.clean</key>\n"
  268. "\t\t\t\t\t<value>clean</value>\n"
  269. "\t\t\t\t</dictionary>\n"
  270. "\t\t\t\t<dictionary>\n"
  271. "\t\t\t\t\t<key>org.eclipse.cdt.make.core.fullBuildTarget</key>\n"
  272. "\t\t\t\t\t<value>all</value>\n"
  273. "\t\t\t\t</dictionary>\n"
  274. "\t\t\t\t<dictionary>\n"
  275. "\t\t\t\t\t<key>org.eclipse.cdt.make.core.buildArguments</key>\n"
  276. "\t\t\t\t\t<value></value>\n"
  277. "\t\t\t\t</dictionary>\n"
  278. "\t\t\t\t<dictionary>\n"
  279. "\t\t\t\t\t<key>org.eclipse.cdt.make.core.build.location</key>\n"
  280. "\t\t\t\t\t<value>"
  281. << this->GetEclipsePath(this->HomeOutputDirectory) << "</value>\n"
  282. "\t\t\t\t</dictionary>\n"
  283. "\t\t\t\t<dictionary>\n"
  284. "\t\t\t\t\t<key>org.eclipse.cdt.make.core.autoBuildTarget</key>\n"
  285. "\t\t\t\t\t<value>all</value>\n"
  286. "\t\t\t\t</dictionary>\n"
  287. ;
  288. // set error parsers
  289. fout <<
  290. "\t\t\t\t<dictionary>\n"
  291. "\t\t\t\t\t<key>org.eclipse.cdt.core.errorOutputParser</key>\n"
  292. "\t\t\t\t\t<value>"
  293. ;
  294. if (this->GetToolChainType(*mf) == EclipseToolchainOther)
  295. {
  296. fout << "org.eclipse.cdt.core.VCErrorParser;";
  297. }
  298. fout <<
  299. "org.eclipse.cdt.core.MakeErrorParser;"
  300. "org.eclipse.cdt.core.GCCErrorParser;"
  301. "org.eclipse.cdt.core.GASErrorParser;"
  302. "org.eclipse.cdt.core.GLDErrorParser;"
  303. "</value>\n"
  304. "\t\t\t\t</dictionary>\n"
  305. ;
  306. fout <<
  307. "\t\t\t</arguments>\n"
  308. "\t\t</buildCommand>\n"
  309. "\t\t<buildCommand>\n"
  310. "\t\t\t<name>org.eclipse.cdt.make.core.ScannerConfigBuilder</name>\n"
  311. "\t\t\t<arguments>\n"
  312. "\t\t\t</arguments>\n"
  313. "\t\t</buildCommand>\n"
  314. "\t</buildSpec>\n"
  315. ;
  316. // set natures for c/c++ projects
  317. fout <<
  318. "\t<natures>\n"
  319. // TODO: ccnature only if it is c++ ???
  320. "\t\t<nature>org.eclipse.cdt.core.ccnature</nature>\n"
  321. "\t\t<nature>org.eclipse.cdt.make.core.makeNature</nature>\n"
  322. "\t\t<nature>org.eclipse.cdt.make.core.ScannerConfigNature</nature>\n"
  323. "\t\t<nature>org.eclipse.cdt.core.cnature</nature>\n"
  324. "\t</natures>\n"
  325. ;
  326. // TODO: refactor this
  327. // create linked resources
  328. if (this->IsOutOfSourceBuild)
  329. {
  330. fout << "\t<linkedResources>\n";
  331. // for each sub project create a linked resource to the source dir
  332. // - only if it is an out-of-source build
  333. for (std::map<cmStdString, std::vector<cmLocalGenerator*> >::const_iterator
  334. it = this->GlobalGenerator->GetProjectMap().begin();
  335. it != this->GlobalGenerator->GetProjectMap().end();
  336. ++it)
  337. {
  338. std::string linkSourceDirectory = this->GetEclipsePath(
  339. it->second[0]->GetMakefile()->GetStartDirectory());
  340. // .project dir can't be subdir of a linked resource dir
  341. if (!cmSystemTools::IsSubDirectory(this->HomeOutputDirectory.c_str(),
  342. linkSourceDirectory.c_str()))
  343. {
  344. this->AppendLinkedResource(fout, it->first,
  345. this->GetEclipsePath(linkSourceDirectory));
  346. this->SrcLinkedResources.push_back(it->first);
  347. }
  348. }
  349. // for EXECUTABLE_OUTPUT_PATH when not in binary dir
  350. this->AppendOutLinkedResource(fout,
  351. mf->GetSafeDefinition("CMAKE_RUNTIME_OUTPUT_DIRECTORY"),
  352. mf->GetSafeDefinition("EXECUTABLE_OUTPUT_PATH"));
  353. // for LIBRARY_OUTPUT_PATH when not in binary dir
  354. this->AppendOutLinkedResource(fout,
  355. mf->GetSafeDefinition("CMAKE_LIBRARY_OUTPUT_DIRECTORY"),
  356. mf->GetSafeDefinition("LIBRARY_OUTPUT_PATH"));
  357. fout << "\t</linkedResources>\n";
  358. }
  359. fout << "</projectDescription>\n";
  360. }
  361. //----------------------------------------------------------------------------
  362. void cmExtraEclipseCDT4Generator::CreateCProjectFile() const
  363. {
  364. std::set<std::string> emmited;
  365. const cmMakefile* mf
  366. = this->GlobalGenerator->GetLocalGenerators()[0]->GetMakefile();
  367. const std::string filename = this->HomeOutputDirectory + "/.cproject";
  368. cmGeneratedFileStream fout(filename.c_str());
  369. if (!fout)
  370. {
  371. return;
  372. }
  373. // add header
  374. fout <<
  375. "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n"
  376. "<?fileVersion 4.0.0?>\n\n"
  377. "<cproject>\n"
  378. "<storageModule moduleId=\"org.eclipse.cdt.core.settings\">\n"
  379. ;
  380. fout << "<cconfiguration id=\"org.eclipse.cdt.core.default.config.1\">\n";
  381. // Configuration settings...
  382. fout <<
  383. "<storageModule"
  384. " buildSystemId=\"org.eclipse.cdt.core.defaultConfigDataProvider\""
  385. " id=\"org.eclipse.cdt.core.default.config.1\""
  386. " moduleId=\"org.eclipse.cdt.core.settings\" name=\"Configuration\">\n"
  387. "<externalSettings/>\n"
  388. "<extensions>\n"
  389. ;
  390. // TODO: refactor this out...
  391. switch (this->GetToolChainType(*mf))
  392. {
  393. case EclipseToolchainLinux :
  394. fout << "<extension id=\"org.eclipse.cdt.core.ELF\""
  395. " point=\"org.eclipse.cdt.core.BinaryParser\"/>\n"
  396. ;
  397. fout << "<extension id=\"org.eclipse.cdt.core.GNU_ELF\""
  398. " point=\"org.eclipse.cdt.core.BinaryParser\">\n"
  399. "<attribute key=\"addr2line\" value=\"addr2line\"/>\n"
  400. "<attribute key=\"c++filt\" value=\"c++filt\"/>\n"
  401. "</extension>\n"
  402. ;
  403. break;
  404. case EclipseToolchainCygwin :
  405. fout << "<extension id=\"org.eclipse.cdt.core.Cygwin_PE\""
  406. " point=\"org.eclipse.cdt.core.BinaryParser\">\n"
  407. "<attribute key=\"addr2line\" value=\"addr2line\"/>\n"
  408. "<attribute key=\"c++filt\" value=\"c++filt\"/>\n"
  409. "<attribute key=\"cygpath\" value=\"cygpath\"/>\n"
  410. "<attribute key=\"nm\" value=\"nm\"/>\n"
  411. "</extension>\n"
  412. ;
  413. break;
  414. case EclipseToolchainMinGW :
  415. fout << "<extension id=\"org.eclipse.cdt.core.PE\""
  416. " point=\"org.eclipse.cdt.core.BinaryParser\"/>\n"
  417. ;
  418. break;
  419. case EclipseToolchainSolaris :
  420. fout << "<extension id=\"org.eclipse.cdt.core.ELF\""
  421. " point=\"org.eclipse.cdt.core.BinaryParser\"/>\n"
  422. ;
  423. break;
  424. case EclipseToolchainMacOSX :
  425. fout << "<extension id=\"org.eclipse.cdt.core.MachO\""
  426. " point=\"org.eclipse.cdt.core.BinaryParser\">\n"
  427. "<attribute key=\"c++filt\" value=\"c++filt\"/>\n"
  428. "</extension>\n"
  429. ;
  430. break;
  431. case EclipseToolchainOther :
  432. fout << "<extension id=\"org.eclipse.cdt.core.PE\""
  433. " point=\"org.eclipse.cdt.core.BinaryParser\"/>\n"
  434. ;
  435. fout << "<extension id=\"org.eclipse.cdt.core.ELF\""
  436. " point=\"org.eclipse.cdt.core.BinaryParser\"/>\n"
  437. ;
  438. break;
  439. default :
  440. // *** Should never get here ***
  441. fout << "<error_toolchain_type/>\n";
  442. }
  443. fout << "</extensions>\n"
  444. "</storageModule>\n"
  445. ;
  446. // ???
  447. fout <<
  448. "<storageModule moduleId=\"org.eclipse.cdt.core.language.mapping\">\n"
  449. "<project-mappings/>\n"
  450. "</storageModule>\n"
  451. ;
  452. // ???
  453. fout<<"<storageModule moduleId=\"org.eclipse.cdt.core.externalSettings\"/>\n"
  454. ;
  455. // set the path entries (includes, libs, source dirs, etc.)
  456. fout << "<storageModule moduleId=\"org.eclipse.cdt.core.pathentry\">\n"
  457. ;
  458. // for each sub project with a linked resource to the source dir:
  459. // - make it type 'src'
  460. // - and exclude it from type 'out'
  461. std::string excludeFromOut;
  462. for (std::vector<std::string>::const_iterator
  463. it = this->SrcLinkedResources.begin();
  464. it != this->SrcLinkedResources.end();
  465. ++it)
  466. {
  467. fout << "<pathentry kind=\"src\" path=\"" << *it << "\"/>\n";
  468. // exlude source directory from output search path
  469. // - only if not named the same as an output directory
  470. if (!cmSystemTools::FileIsDirectory(
  471. std::string(this->HomeOutputDirectory + "/" + *it).c_str()))
  472. {
  473. excludeFromOut += *it + "/|";
  474. }
  475. }
  476. excludeFromOut += "**/CMakeFiles/";
  477. fout << "<pathentry excluding=\"" << excludeFromOut
  478. << "\" kind=\"out\" path=\"\"/>\n";
  479. // add output entry for EXECUTABLE_OUTPUT_PATH and LIBRARY_OUTPUT_PATH
  480. // - if it is a subdir of homeOutputDirectory, there is no need to add it
  481. // - if it is not then create a linked resource and add the linked name
  482. // but check it doesn't conflict with other linked resources names
  483. for (std::vector<std::string>::const_iterator
  484. it = this->OutLinkedResources.begin();
  485. it != this->OutLinkedResources.end();
  486. ++it)
  487. {
  488. fout << "<pathentry kind=\"out\" path=\"" << *it << "\"/>\n";
  489. }
  490. // add pre-processor definitions to allow eclipse to gray out sections
  491. emmited.clear();
  492. for (std::vector<cmLocalGenerator*>::const_iterator
  493. it = this->GlobalGenerator->GetLocalGenerators().begin();
  494. it != this->GlobalGenerator->GetLocalGenerators().end();
  495. ++it)
  496. {
  497. if(const char* cdefs = (*it)->GetMakefile()->GetProperty(
  498. "COMPILE_DEFINITIONS"))
  499. {
  500. // Expand the list.
  501. std::vector<std::string> defs;
  502. cmSystemTools::ExpandListArgument(cdefs, defs);
  503. for(std::vector<std::string>::const_iterator di = defs.begin();
  504. di != defs.end(); ++di)
  505. {
  506. std::string::size_type equals = di->find('=', 0);
  507. std::string::size_type enddef = di->length();
  508. std::string def;
  509. std::string val;
  510. if (equals != std::string::npos && equals < enddef)
  511. {
  512. // we have -DFOO=BAR
  513. def = di->substr(0, equals);
  514. val = di->substr(equals + 1, enddef - equals + 1);
  515. }
  516. else
  517. {
  518. // we have -DFOO
  519. def = *di;
  520. }
  521. // insert the definition if not already added.
  522. if(emmited.find(def) == emmited.end())
  523. {
  524. emmited.insert(def);
  525. fout << "<pathentry kind=\"mac\" name=\"" << def
  526. << "\" path=\"\" value=\"" << this->EscapeForXML(val)
  527. << "\"/>\n";
  528. }
  529. }
  530. }
  531. }
  532. // include dirs
  533. emmited.clear();
  534. for (std::vector<cmLocalGenerator*>::const_iterator
  535. it = this->GlobalGenerator->GetLocalGenerators().begin();
  536. it != this->GlobalGenerator->GetLocalGenerators().end();
  537. ++it)
  538. {
  539. const std::vector<std::string>& includeDirs
  540. = (*it)->GetMakefile()->GetIncludeDirectories();
  541. for(std::vector<std::string>::const_iterator inc = includeDirs.begin();
  542. inc != includeDirs.end();
  543. ++inc)
  544. {
  545. std::string dir = cmSystemTools::CollapseFullPath(inc->c_str());
  546. if(emmited.find(dir) == emmited.end())
  547. {
  548. emmited.insert(dir);
  549. fout << "<pathentry include=\"" << this->GetEclipsePath(dir)
  550. << "\" kind=\"inc\" path=\"\" system=\"true\"/>\n";
  551. }
  552. }
  553. }
  554. fout << "</storageModule>\n";
  555. // add build targets
  556. fout <<
  557. "<storageModule moduleId=\"org.eclipse.cdt.make.core.buildtargets\">\n"
  558. "<buildTargets>\n"
  559. ;
  560. emmited.clear();
  561. const std::string make = mf->GetRequiredDefinition("CMAKE_MAKE_PROGRAM");
  562. cmGlobalGenerator* generator
  563. = const_cast<cmGlobalGenerator*>(this->GlobalGenerator);
  564. if (generator->GetAllTargetName())
  565. {
  566. emmited.insert(generator->GetAllTargetName());
  567. this->AppendTarget(fout, generator->GetAllTargetName(), make);
  568. }
  569. if (generator->GetCleanTargetName())
  570. {
  571. emmited.insert(generator->GetCleanTargetName());
  572. this->AppendTarget(fout, generator->GetCleanTargetName(), make);
  573. }
  574. // add all executable and library targets and some of the GLOBAL
  575. // and UTILITY targets
  576. for (std::vector<cmLocalGenerator*>::const_iterator
  577. it = this->GlobalGenerator->GetLocalGenerators().begin();
  578. it != this->GlobalGenerator->GetLocalGenerators().end();
  579. ++it)
  580. {
  581. const cmTargets& targets = (*it)->GetMakefile()->GetTargets();
  582. for(cmTargets::const_iterator t = targets.begin(); t != targets.end(); ++t)
  583. {
  584. bool addFastTarget = false;
  585. switch(t->second.GetType())
  586. {
  587. case cmTarget::EXECUTABLE:
  588. case cmTarget::STATIC_LIBRARY:
  589. case cmTarget::SHARED_LIBRARY:
  590. case cmTarget::MODULE_LIBRARY:
  591. addFastTarget = true;
  592. // no break here
  593. case cmTarget::UTILITY:
  594. case cmTarget::GLOBAL_TARGET:
  595. {
  596. bool insertTarget = true;
  597. if(insertTarget &&
  598. (std::set<std::string>::const_iterator(
  599. this->TargetsToIgnore.find(t->first)) !=
  600. this->TargetsToIgnore.end()))
  601. {
  602. insertTarget = false;
  603. }
  604. if(insertTarget && (emmited.find(t->first) != emmited.end()))
  605. {
  606. insertTarget = false;
  607. }
  608. // add the edit_cache target only if it's not ccmake
  609. // otherwise ccmake will be executed in the log view of Eclipse,
  610. // which is no terminal, so curses don't work there, Alex
  611. if (insertTarget && (t->first=="edit_cache"))
  612. {
  613. if (strstr(mf->GetRequiredDefinition("CMAKE_EDIT_COMMAND"),
  614. "ccmake")!=NULL)
  615. {
  616. insertTarget = false;
  617. }
  618. }
  619. if (insertTarget)
  620. {
  621. emmited.insert(t->first);
  622. this->AppendTarget(fout, t->first, make);
  623. if (addFastTarget || t->first=="install")
  624. {
  625. std::string fastTarget = t->first;
  626. fastTarget = fastTarget + "/fast";
  627. this->AppendTarget(fout, fastTarget, make);
  628. }
  629. }
  630. break;
  631. }
  632. // ignore these:
  633. case cmTarget::INSTALL_FILES:
  634. case cmTarget::INSTALL_PROGRAMS:
  635. case cmTarget::INSTALL_DIRECTORY:
  636. default:
  637. break;
  638. }
  639. }
  640. }
  641. fout << "</buildTargets>\n"
  642. "</storageModule>\n"
  643. ;
  644. this->AppendStorageScanners(fout, *mf);
  645. fout << "</cconfiguration>\n"
  646. "</storageModule>\n"
  647. "<storageModule moduleId=\"cdtBuildSystem\" version=\"4.0.0\">\n"
  648. "<project id=\"" << mf->GetProjectName() << ".null.1\""
  649. " name=\"" << mf->GetProjectName() << "\"/>\n"
  650. "</storageModule>\n"
  651. "</cproject>\n"
  652. ;
  653. }
  654. //----------------------------------------------------------------------------
  655. cmExtraEclipseCDT4Generator::EclipseToolchainType
  656. cmExtraEclipseCDT4Generator::GetToolChainType(const cmMakefile& makefile)
  657. {
  658. if (makefile.IsSet("UNIX"))
  659. {
  660. if (makefile.IsSet("CYGWIN"))
  661. {
  662. return EclipseToolchainCygwin;
  663. }
  664. if (makefile.IsSet("APPLE" ))
  665. {
  666. return EclipseToolchainMacOSX;
  667. }
  668. // *** how do I determine if it is Solaris ???
  669. return EclipseToolchainLinux;
  670. }
  671. else if (makefile.IsSet("WIN32"))
  672. {
  673. if (makefile.IsSet("MINGW"))
  674. {
  675. return EclipseToolchainMinGW;
  676. }
  677. if (makefile.IsSet("MSYS" ))
  678. {
  679. return EclipseToolchainMinGW;
  680. }
  681. return EclipseToolchainOther;
  682. }
  683. else
  684. {
  685. return EclipseToolchainOther;
  686. }
  687. }
  688. std::string
  689. cmExtraEclipseCDT4Generator::GetEclipsePath(const std::string& path)
  690. {
  691. #if defined(__CYGWIN__)
  692. std::string cmd = "cygpath -m " + path;
  693. std::string out;
  694. if (!cmSystemTools::RunCommand(cmd.c_str(), out, 0, false))
  695. {
  696. return path;
  697. }
  698. else
  699. {
  700. out.erase(out.find_last_of('\n'));
  701. return out;
  702. }
  703. #else
  704. return path;
  705. #endif
  706. }
  707. std::string
  708. cmExtraEclipseCDT4Generator::GetPathBasename(const std::string& path)
  709. {
  710. std::string outputBasename = path;
  711. while (outputBasename.size() > 0 &&
  712. (outputBasename[outputBasename.size() - 1] == '/' ||
  713. outputBasename[outputBasename.size() - 1] == '\\'))
  714. {
  715. outputBasename.resize(outputBasename.size() - 1);
  716. }
  717. std::string::size_type loc = outputBasename.find_last_of("/\\");
  718. if (loc != std::string::npos)
  719. {
  720. outputBasename = outputBasename.substr(loc + 1);
  721. }
  722. return outputBasename;
  723. }
  724. std::string
  725. cmExtraEclipseCDT4Generator::GenerateProjectName(const std::string& name,
  726. const std::string& type,
  727. const std::string& path)
  728. {
  729. return name + (type.empty() ? "" : "-") + type + "@" + path;
  730. }
  731. std::string cmExtraEclipseCDT4Generator::EscapeForXML(const std::string& value)
  732. {
  733. std::string str = value;
  734. cmSystemTools::ReplaceString(str, "&", "&amp;");
  735. cmSystemTools::ReplaceString(str, "<", "&lt;");
  736. cmSystemTools::ReplaceString(str, ">", "&gt;");
  737. cmSystemTools::ReplaceString(str, "\"", "&quot;");
  738. // NOTE: This one is not necessary, since as of Eclipse CDT4 it will
  739. // automatically change this to the original value (').
  740. //cmSystemTools::ReplaceString(str, "'", "&apos;");
  741. return str;
  742. }
  743. //----------------------------------------------------------------------------
  744. // Helper functions
  745. //----------------------------------------------------------------------------
  746. void cmExtraEclipseCDT4Generator
  747. ::AppendStorageScanners(cmGeneratedFileStream& fout,
  748. const cmMakefile& makefile)
  749. {
  750. // we need the "make" and the C (or C++) compiler which are used, Alex
  751. std::string make = makefile.GetRequiredDefinition("CMAKE_MAKE_PROGRAM");
  752. std::string compiler = makefile.GetSafeDefinition("CMAKE_C_COMPILER");
  753. if (compiler.empty())
  754. {
  755. compiler = makefile.GetSafeDefinition("CMAKE_CXX_COMPILER");
  756. }
  757. if (compiler.empty()) //Hmm, what to do now ?
  758. {
  759. compiler = "gcc";
  760. }
  761. // the following right now hardcodes gcc behaviour :-/
  762. fout <<
  763. "<storageModule moduleId=\"scannerConfiguration\">\n"
  764. "<autodiscovery enabled=\"true\" problemReportingEnabled=\"true\""
  765. " selectedProfileId="
  766. "\"org.eclipse.cdt.make.core.GCCStandardMakePerProjectProfile\"/>\n"
  767. ;
  768. cmExtraEclipseCDT4Generator::AppendScannerProfile(fout,
  769. "org.eclipse.cdt.make.core.GCCStandardMakePerProjectProfile",
  770. true, "", true, "specsFile",
  771. "-E -P -v -dD ${plugin_state_location}/${specs_file}",
  772. compiler, true, true);
  773. cmExtraEclipseCDT4Generator::AppendScannerProfile(fout,
  774. "org.eclipse.cdt.make.core.GCCStandardMakePerFileProfile",
  775. true, "", true, "makefileGenerator",
  776. "-f ${project_name}_scd.mk",
  777. make, true, true);
  778. fout << "</storageModule>\n";
  779. }
  780. void cmExtraEclipseCDT4Generator::AppendTarget(cmGeneratedFileStream& fout,
  781. const std::string& target,
  782. const std::string& make)
  783. {
  784. fout <<
  785. "<target name=\"" << target << "\""
  786. " path=\"\""
  787. " targetID=\"org.eclipse.cdt.make.MakeTargetBuilder\">\n"
  788. "<buildCommand>"
  789. << cmExtraEclipseCDT4Generator::GetEclipsePath(make)
  790. << "</buildCommand>\n"
  791. "<buildArguments/>\n"
  792. "<buildTarget>" << target << "</buildTarget>\n"
  793. "<stopOnError>true</stopOnError>\n"
  794. "<useDefaultCommand>false</useDefaultCommand>\n"
  795. "</target>\n"
  796. ;
  797. }
  798. void cmExtraEclipseCDT4Generator
  799. ::AppendScannerProfile(cmGeneratedFileStream& fout,
  800. const std::string& profileID,
  801. bool openActionEnabled,
  802. const std::string& openActionFilePath,
  803. bool pParserEnabled,
  804. const std::string& scannerInfoProviderID,
  805. const std::string& runActionArguments,
  806. const std::string& runActionCommand,
  807. bool runActionUseDefault,
  808. bool sipParserEnabled)
  809. {
  810. fout <<
  811. "<profile id=\"" << profileID << "\">\n"
  812. "<buildOutputProvider>\n"
  813. "<openAction enabled=\"" << (openActionEnabled ? "true" : "false")
  814. << "\" filePath=\"" << openActionFilePath << "\"/>\n"
  815. "<parser enabled=\"" << (pParserEnabled ? "true" : "false") << "\"/>\n"
  816. "</buildOutputProvider>\n"
  817. "<scannerInfoProvider id=\"" << scannerInfoProviderID << "\">\n"
  818. "<runAction arguments=\"" << runActionArguments << "\""
  819. " command=\"" << runActionCommand
  820. << "\" useDefault=\"" << (runActionUseDefault ? "true":"false") << "\"/>\n"
  821. "<parser enabled=\"" << (sipParserEnabled ? "true" : "false") << "\"/>\n"
  822. "</scannerInfoProvider>\n"
  823. "</profile>\n"
  824. ;
  825. }
  826. void cmExtraEclipseCDT4Generator
  827. ::AppendLinkedResource (cmGeneratedFileStream& fout,
  828. const std::string& name,
  829. const std::string& path)
  830. {
  831. fout <<
  832. "\t\t<link>\n"
  833. "\t\t\t<name>" << name << "</name>\n"
  834. "\t\t\t<type>2</type>\n"
  835. "\t\t\t<location>"
  836. << path
  837. << "</location>\n"
  838. "\t\t</link>\n"
  839. ;
  840. }
  841. bool cmExtraEclipseCDT4Generator
  842. ::AppendOutLinkedResource(cmGeneratedFileStream& fout,
  843. const std::string& defname,
  844. const std::string& altdefname)
  845. {
  846. if (defname.empty() && altdefname.empty())
  847. {
  848. return false;
  849. }
  850. std::string outputPath = (defname.empty() ? altdefname : defname);
  851. if (!cmSystemTools::FileIsFullPath(outputPath.c_str()))
  852. {
  853. outputPath = this->HomeOutputDirectory + "/" + outputPath;
  854. }
  855. if (cmSystemTools::IsSubDirectory(outputPath.c_str(),
  856. this->HomeOutputDirectory.c_str()))
  857. {
  858. return false;
  859. }
  860. std::string name = this->GetPathBasename(outputPath);
  861. // make sure linked resource name is unique
  862. while (this->GlobalGenerator->GetProjectMap().find(name)
  863. != this->GlobalGenerator->GetProjectMap().end())
  864. {
  865. name += "_";
  866. }
  867. if (std::find(this->OutLinkedResources.begin(),
  868. this->OutLinkedResources.end(),
  869. name)
  870. != this->OutLinkedResources.end())
  871. {
  872. return false;
  873. }
  874. else
  875. {
  876. this->AppendLinkedResource(fout, name,
  877. this->GetEclipsePath(outputPath));
  878. this->OutLinkedResources.push_back(name);
  879. return true;
  880. }
  881. }