cmExtraEclipseCDT4Generator.cxx 34 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996
  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. }
  89. //----------------------------------------------------------------------------
  90. void cmExtraEclipseCDT4Generator::Generate()
  91. {
  92. const cmMakefile* mf
  93. = this->GlobalGenerator->GetLocalGenerators()[0]->GetMakefile();
  94. // TODO: Decide if these are local or member variables
  95. this->HomeDirectory = mf->GetHomeDirectory();
  96. this->HomeOutputDirectory = mf->GetHomeOutputDirectory();
  97. this->IsOutOfSourceBuild = (this->HomeDirectory!=this->HomeOutputDirectory);
  98. this->GenerateSourceProject = (this->IsOutOfSourceBuild &&
  99. mf->IsOn("ECLIPSE_CDT4_GENERATE_SOURCE_PROJECT"));
  100. // NOTE: This is not good, since it pollutes the source tree. However,
  101. // Eclipse doesn't allow CVS/SVN to work when the .project is not in
  102. // the cvs/svn root directory. Hence, this is provided as an option.
  103. if (this->GenerateSourceProject)
  104. {
  105. // create .project file in the source tree
  106. this->CreateSourceProjectFile();
  107. }
  108. // create a .project file
  109. this->CreateProjectFile();
  110. // create a .cproject file
  111. this->CreateCProjectFile();
  112. }
  113. void cmExtraEclipseCDT4Generator::CreateSourceProjectFile() const
  114. {
  115. assert(this->HomeDirectory != this->HomeOutputDirectory);
  116. // set up the project name: <project>-Source@<baseSourcePathName>
  117. const cmMakefile* mf
  118. = this->GlobalGenerator->GetLocalGenerators()[0]->GetMakefile();
  119. std::string name = this->GenerateProjectName(mf->GetProjectName(), "Source",
  120. this->GetPathBasename(this->HomeDirectory));
  121. const std::string filename = this->HomeDirectory + "/.project";
  122. cmGeneratedFileStream fout(filename.c_str());
  123. if (!fout)
  124. {
  125. return;
  126. }
  127. fout <<
  128. "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
  129. "<projectDescription>\n"
  130. "\t<name>" << name << "</name>\n"
  131. "\t<comment></comment>\n"
  132. "\t<projects>\n"
  133. "\t</projects>\n"
  134. "\t<buildSpec>\n"
  135. "\t</buildSpec>\n"
  136. "\t<natures>\n"
  137. "\t</natures>\n"
  138. "</projectDescription>\n"
  139. ;
  140. }
  141. //----------------------------------------------------------------------------
  142. void cmExtraEclipseCDT4Generator::CreateProjectFile()
  143. {
  144. const cmMakefile* mf
  145. = this->GlobalGenerator->GetLocalGenerators()[0]->GetMakefile();
  146. const std::string filename = this->HomeOutputDirectory + "/.project";
  147. cmGeneratedFileStream fout(filename.c_str());
  148. if (!fout)
  149. {
  150. return;
  151. }
  152. fout <<
  153. "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
  154. "<projectDescription>\n"
  155. "\t<name>" <<
  156. this->GenerateProjectName(mf->GetProjectName(),
  157. mf->GetDefinition("CMAKE_BUILD_TYPE"),
  158. this->GetPathBasename(this->HomeOutputDirectory))
  159. << "</name>\n"
  160. "\t<comment></comment>\n"
  161. "\t<projects>\n"
  162. "\t</projects>\n"
  163. "\t<buildSpec>\n"
  164. "\t\t<buildCommand>\n"
  165. "\t\t\t<name>org.eclipse.cdt.make.core.makeBuilder</name>\n"
  166. "\t\t\t<triggers>clean,full,incremental,</triggers>\n"
  167. "\t\t\t<arguments>\n"
  168. ;
  169. // use clean target
  170. fout <<
  171. "\t\t\t\t<dictionary>\n"
  172. "\t\t\t\t\t<key>org.eclipse.cdt.make.core.cleanBuildTarget</key>\n"
  173. "\t\t\t\t\t<value>clean</value>\n"
  174. "\t\t\t\t</dictionary>\n"
  175. "\t\t\t\t<dictionary>\n"
  176. "\t\t\t\t\t<key>org.eclipse.cdt.make.core.enableCleanBuild</key>\n"
  177. "\t\t\t\t\t<value>true</value>\n"
  178. "\t\t\t\t</dictionary>\n"
  179. "\t\t\t\t<dictionary>\n"
  180. "\t\t\t\t\t<key>org.eclipse.cdt.make.core.append_environment</key>\n"
  181. "\t\t\t\t\t<value>true</value>\n"
  182. "\t\t\t\t</dictionary>\n"
  183. "\t\t\t\t<dictionary>\n"
  184. "\t\t\t\t\t<key>org.eclipse.cdt.make.core.stopOnError</key>\n"
  185. "\t\t\t\t\t<value>true</value>\n"
  186. "\t\t\t\t</dictionary>\n"
  187. ;
  188. // set the make command
  189. std::string make = mf->GetRequiredDefinition("CMAKE_MAKE_PROGRAM");
  190. fout <<
  191. "\t\t\t\t<dictionary>\n"
  192. "\t\t\t\t\t<key>org.eclipse.cdt.make.core.enabledIncrementalBuild</key>\n"
  193. "\t\t\t\t\t<value>true</value>\n"
  194. "\t\t\t\t</dictionary>\n"
  195. "\t\t\t\t<dictionary>\n"
  196. "\t\t\t\t\t<key>org.eclipse.cdt.make.core.build.command</key>\n"
  197. "\t\t\t\t\t<value>" + this->GetEclipsePath(make) + "</value>\n"
  198. "\t\t\t\t</dictionary>\n"
  199. "\t\t\t\t<dictionary>\n"
  200. "\t\t\t\t\t<key>org.eclipse.cdt.make.core.contents</key>\n"
  201. "\t\t\t\t\t<value>org.eclipse.cdt.make.core.activeConfigSettings</value>\n"
  202. "\t\t\t\t</dictionary>\n"
  203. "\t\t\t\t<dictionary>\n"
  204. "\t\t\t\t\t<key>org.eclipse.cdt.make.core.build.target.inc</key>\n"
  205. "\t\t\t\t\t<value>all</value>\n"
  206. "\t\t\t\t</dictionary>\n"
  207. "\t\t\t\t<dictionary>\n"
  208. "\t\t\t\t\t<key>org.eclipse.cdt.make.core.build.arguments</key>\n"
  209. "\t\t\t\t\t<value></value>\n"
  210. "\t\t\t\t</dictionary>\n"
  211. "\t\t\t\t<dictionary>\n"
  212. "\t\t\t\t\t<key>org.eclipse.cdt.make.core.buildLocation</key>\n"
  213. "\t\t\t\t\t<value>"
  214. << this->GetEclipsePath(this->HomeOutputDirectory) << "</value>\n"
  215. "\t\t\t\t</dictionary>\n"
  216. "\t\t\t\t<dictionary>\n"
  217. "\t\t\t\t\t<key>org.eclipse.cdt.make.core.useDefaultBuildCmd</key>\n"
  218. "\t\t\t\t\t<value>false</value>\n"
  219. "\t\t\t\t</dictionary>\n"
  220. ;
  221. // set project specific environment
  222. fout <<
  223. "\t\t\t\t<dictionary>\n"
  224. "\t\t\t\t\t<key>org.eclipse.cdt.make.core.environment</key>\n"
  225. "\t\t\t\t\t<value>VERBOSE=1|</value>\n" // enforce VERBOSE Makefile output
  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::AppendIncludeDirectories(
  363. cmGeneratedFileStream& fout,
  364. const std::vector<std::string>& includeDirs,
  365. std::set<std::string>& emittedDirs)
  366. {
  367. for(std::vector<std::string>::const_iterator inc = includeDirs.begin();
  368. inc != includeDirs.end();
  369. ++inc)
  370. {
  371. if (!inc->empty())
  372. {
  373. std::string dir = cmSystemTools::CollapseFullPath(inc->c_str());
  374. if(emittedDirs.find(dir) == emittedDirs.end())
  375. {
  376. emittedDirs.insert(dir);
  377. fout << "<pathentry include=\""
  378. << cmExtraEclipseCDT4Generator::GetEclipsePath(dir)
  379. << "\" kind=\"inc\" path=\"\" system=\"true\"/>\n";
  380. }
  381. }
  382. }
  383. }
  384. //----------------------------------------------------------------------------
  385. void cmExtraEclipseCDT4Generator::CreateCProjectFile() const
  386. {
  387. std::set<std::string> emmited;
  388. const cmMakefile* mf
  389. = this->GlobalGenerator->GetLocalGenerators()[0]->GetMakefile();
  390. const std::string filename = this->HomeOutputDirectory + "/.cproject";
  391. cmGeneratedFileStream fout(filename.c_str());
  392. if (!fout)
  393. {
  394. return;
  395. }
  396. // add header
  397. fout <<
  398. "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n"
  399. "<?fileVersion 4.0.0?>\n\n"
  400. "<cproject>\n"
  401. "<storageModule moduleId=\"org.eclipse.cdt.core.settings\">\n"
  402. ;
  403. fout << "<cconfiguration id=\"org.eclipse.cdt.core.default.config.1\">\n";
  404. // Configuration settings...
  405. fout <<
  406. "<storageModule"
  407. " buildSystemId=\"org.eclipse.cdt.core.defaultConfigDataProvider\""
  408. " id=\"org.eclipse.cdt.core.default.config.1\""
  409. " moduleId=\"org.eclipse.cdt.core.settings\" name=\"Configuration\">\n"
  410. "<externalSettings/>\n"
  411. "<extensions>\n"
  412. ;
  413. // TODO: refactor this out...
  414. switch (this->GetToolChainType(*mf))
  415. {
  416. case EclipseToolchainLinux :
  417. fout << "<extension id=\"org.eclipse.cdt.core.ELF\""
  418. " point=\"org.eclipse.cdt.core.BinaryParser\"/>\n"
  419. ;
  420. fout << "<extension id=\"org.eclipse.cdt.core.GNU_ELF\""
  421. " point=\"org.eclipse.cdt.core.BinaryParser\">\n"
  422. "<attribute key=\"addr2line\" value=\"addr2line\"/>\n"
  423. "<attribute key=\"c++filt\" value=\"c++filt\"/>\n"
  424. "</extension>\n"
  425. ;
  426. break;
  427. case EclipseToolchainCygwin :
  428. fout << "<extension id=\"org.eclipse.cdt.core.Cygwin_PE\""
  429. " point=\"org.eclipse.cdt.core.BinaryParser\">\n"
  430. "<attribute key=\"addr2line\" value=\"addr2line\"/>\n"
  431. "<attribute key=\"c++filt\" value=\"c++filt\"/>\n"
  432. "<attribute key=\"cygpath\" value=\"cygpath\"/>\n"
  433. "<attribute key=\"nm\" value=\"nm\"/>\n"
  434. "</extension>\n"
  435. ;
  436. break;
  437. case EclipseToolchainMinGW :
  438. fout << "<extension id=\"org.eclipse.cdt.core.PE\""
  439. " point=\"org.eclipse.cdt.core.BinaryParser\"/>\n"
  440. ;
  441. break;
  442. case EclipseToolchainSolaris :
  443. fout << "<extension id=\"org.eclipse.cdt.core.ELF\""
  444. " point=\"org.eclipse.cdt.core.BinaryParser\"/>\n"
  445. ;
  446. break;
  447. case EclipseToolchainMacOSX :
  448. fout << "<extension id=\"org.eclipse.cdt.core.MachO\""
  449. " point=\"org.eclipse.cdt.core.BinaryParser\">\n"
  450. "<attribute key=\"c++filt\" value=\"c++filt\"/>\n"
  451. "</extension>\n"
  452. ;
  453. break;
  454. case EclipseToolchainOther :
  455. fout << "<extension id=\"org.eclipse.cdt.core.PE\""
  456. " point=\"org.eclipse.cdt.core.BinaryParser\"/>\n"
  457. ;
  458. fout << "<extension id=\"org.eclipse.cdt.core.ELF\""
  459. " point=\"org.eclipse.cdt.core.BinaryParser\"/>\n"
  460. ;
  461. break;
  462. default :
  463. // *** Should never get here ***
  464. fout << "<error_toolchain_type/>\n";
  465. }
  466. fout << "</extensions>\n"
  467. "</storageModule>\n"
  468. ;
  469. // ???
  470. fout <<
  471. "<storageModule moduleId=\"org.eclipse.cdt.core.language.mapping\">\n"
  472. "<project-mappings/>\n"
  473. "</storageModule>\n"
  474. ;
  475. // ???
  476. fout<<"<storageModule moduleId=\"org.eclipse.cdt.core.externalSettings\"/>\n"
  477. ;
  478. // set the path entries (includes, libs, source dirs, etc.)
  479. fout << "<storageModule moduleId=\"org.eclipse.cdt.core.pathentry\">\n"
  480. ;
  481. // for each sub project with a linked resource to the source dir:
  482. // - make it type 'src'
  483. // - and exclude it from type 'out'
  484. std::string excludeFromOut;
  485. for (std::vector<std::string>::const_iterator
  486. it = this->SrcLinkedResources.begin();
  487. it != this->SrcLinkedResources.end();
  488. ++it)
  489. {
  490. fout << "<pathentry kind=\"src\" path=\"" << *it << "\"/>\n";
  491. // exlude source directory from output search path
  492. // - only if not named the same as an output directory
  493. if (!cmSystemTools::FileIsDirectory(
  494. std::string(this->HomeOutputDirectory + "/" + *it).c_str()))
  495. {
  496. excludeFromOut += *it + "/|";
  497. }
  498. }
  499. excludeFromOut += "**/CMakeFiles/";
  500. fout << "<pathentry excluding=\"" << excludeFromOut
  501. << "\" kind=\"out\" path=\"\"/>\n";
  502. // add output entry for EXECUTABLE_OUTPUT_PATH and LIBRARY_OUTPUT_PATH
  503. // - if it is a subdir of homeOutputDirectory, there is no need to add it
  504. // - if it is not then create a linked resource and add the linked name
  505. // but check it doesn't conflict with other linked resources names
  506. for (std::vector<std::string>::const_iterator
  507. it = this->OutLinkedResources.begin();
  508. it != this->OutLinkedResources.end();
  509. ++it)
  510. {
  511. fout << "<pathentry kind=\"out\" path=\"" << *it << "\"/>\n";
  512. }
  513. // add pre-processor definitions to allow eclipse to gray out sections
  514. emmited.clear();
  515. for (std::vector<cmLocalGenerator*>::const_iterator
  516. it = this->GlobalGenerator->GetLocalGenerators().begin();
  517. it != this->GlobalGenerator->GetLocalGenerators().end();
  518. ++it)
  519. {
  520. if(const char* cdefs = (*it)->GetMakefile()->GetProperty(
  521. "COMPILE_DEFINITIONS"))
  522. {
  523. // Expand the list.
  524. std::vector<std::string> defs;
  525. cmSystemTools::ExpandListArgument(cdefs, defs);
  526. for(std::vector<std::string>::const_iterator di = defs.begin();
  527. di != defs.end(); ++di)
  528. {
  529. std::string::size_type equals = di->find('=', 0);
  530. std::string::size_type enddef = di->length();
  531. std::string def;
  532. std::string val;
  533. if (equals != std::string::npos && equals < enddef)
  534. {
  535. // we have -DFOO=BAR
  536. def = di->substr(0, equals);
  537. val = di->substr(equals + 1, enddef - equals + 1);
  538. }
  539. else
  540. {
  541. // we have -DFOO
  542. def = *di;
  543. }
  544. // insert the definition if not already added.
  545. if(emmited.find(def) == emmited.end())
  546. {
  547. emmited.insert(def);
  548. fout << "<pathentry kind=\"mac\" name=\"" << def
  549. << "\" path=\"\" value=\"" << this->EscapeForXML(val)
  550. << "\"/>\n";
  551. }
  552. }
  553. }
  554. }
  555. // include dirs
  556. emmited.clear();
  557. for (std::vector<cmLocalGenerator*>::const_iterator
  558. it = this->GlobalGenerator->GetLocalGenerators().begin();
  559. it != this->GlobalGenerator->GetLocalGenerators().end();
  560. ++it)
  561. {
  562. const std::vector<std::string>& includeDirs
  563. = (*it)->GetMakefile()->GetIncludeDirectories();
  564. this->AppendIncludeDirectories(fout, includeDirs, emmited);
  565. }
  566. // now also the system include directories, in case we found them in
  567. // CMakeSystemSpecificInformation.cmake. This makes Eclipse find the
  568. // standard headers.
  569. mf->GetDefinition("CMAKE_ECLIPSE_C_SYSTEM_INCLUDE_DIRS");
  570. std::string compiler = mf->GetSafeDefinition("CMAKE_C_COMPILER");
  571. if (!compiler.empty())
  572. {
  573. std::string systemIncludeDirs = mf->GetSafeDefinition(
  574. "CMAKE_ECLIPSE_C_SYSTEM_INCLUDE_DIRS");
  575. std::vector<std::string> dirs;
  576. cmSystemTools::ExpandListArgument(systemIncludeDirs.c_str(), dirs);
  577. this->AppendIncludeDirectories(fout, dirs, emmited);
  578. }
  579. compiler = mf->GetSafeDefinition("CMAKE_CXX_COMPILER");
  580. if (!compiler.empty())
  581. {
  582. std::string systemIncludeDirs = mf->GetSafeDefinition(
  583. "CMAKE_ECLIPSE_CXX_SYSTEM_INCLUDE_DIRS");
  584. std::vector<std::string> dirs;
  585. cmSystemTools::ExpandListArgument(systemIncludeDirs.c_str(), dirs);
  586. this->AppendIncludeDirectories(fout, dirs, emmited);
  587. }
  588. fout << "</storageModule>\n";
  589. // add build targets
  590. fout <<
  591. "<storageModule moduleId=\"org.eclipse.cdt.make.core.buildtargets\">\n"
  592. "<buildTargets>\n"
  593. ;
  594. emmited.clear();
  595. const std::string make = mf->GetRequiredDefinition("CMAKE_MAKE_PROGRAM");
  596. cmGlobalGenerator* generator
  597. = const_cast<cmGlobalGenerator*>(this->GlobalGenerator);
  598. if (generator->GetAllTargetName())
  599. {
  600. emmited.insert(generator->GetAllTargetName());
  601. this->AppendTarget(fout, generator->GetAllTargetName(), make);
  602. }
  603. if (generator->GetCleanTargetName())
  604. {
  605. emmited.insert(generator->GetCleanTargetName());
  606. this->AppendTarget(fout, generator->GetCleanTargetName(), make);
  607. }
  608. // add all executable and library targets and some of the GLOBAL
  609. // and UTILITY targets
  610. for (std::vector<cmLocalGenerator*>::const_iterator
  611. it = this->GlobalGenerator->GetLocalGenerators().begin();
  612. it != this->GlobalGenerator->GetLocalGenerators().end();
  613. ++it)
  614. {
  615. const cmTargets& targets = (*it)->GetMakefile()->GetTargets();
  616. for(cmTargets::const_iterator t = targets.begin(); t != targets.end(); ++t)
  617. {
  618. bool addFastTarget = false;
  619. switch(t->second.GetType())
  620. {
  621. case cmTarget::EXECUTABLE:
  622. case cmTarget::STATIC_LIBRARY:
  623. case cmTarget::SHARED_LIBRARY:
  624. case cmTarget::MODULE_LIBRARY:
  625. addFastTarget = true;
  626. // no break here
  627. case cmTarget::UTILITY:
  628. case cmTarget::GLOBAL_TARGET:
  629. {
  630. bool insertTarget = true;
  631. if(insertTarget &&
  632. (std::set<std::string>::const_iterator(
  633. this->TargetsToIgnore.find(t->first)) !=
  634. this->TargetsToIgnore.end()))
  635. {
  636. insertTarget = false;
  637. }
  638. if(insertTarget && (emmited.find(t->first) != emmited.end()))
  639. {
  640. insertTarget = false;
  641. }
  642. // add the edit_cache target only if it's not ccmake
  643. // otherwise ccmake will be executed in the log view of Eclipse,
  644. // which is no terminal, so curses don't work there, Alex
  645. if (insertTarget && (t->first=="edit_cache"))
  646. {
  647. if (strstr(mf->GetRequiredDefinition("CMAKE_EDIT_COMMAND"),
  648. "ccmake")!=NULL)
  649. {
  650. insertTarget = false;
  651. }
  652. }
  653. if (insertTarget)
  654. {
  655. emmited.insert(t->first);
  656. this->AppendTarget(fout, t->first, make);
  657. if (addFastTarget || t->first=="install")
  658. {
  659. std::string fastTarget = t->first;
  660. fastTarget = fastTarget + "/fast";
  661. this->AppendTarget(fout, fastTarget, make);
  662. }
  663. }
  664. break;
  665. }
  666. // ignore these:
  667. case cmTarget::INSTALL_FILES:
  668. case cmTarget::INSTALL_PROGRAMS:
  669. case cmTarget::INSTALL_DIRECTORY:
  670. default:
  671. break;
  672. }
  673. }
  674. }
  675. fout << "</buildTargets>\n"
  676. "</storageModule>\n"
  677. ;
  678. this->AppendStorageScanners(fout, *mf);
  679. fout << "</cconfiguration>\n"
  680. "</storageModule>\n"
  681. "<storageModule moduleId=\"cdtBuildSystem\" version=\"4.0.0\">\n"
  682. "<project id=\"" << mf->GetProjectName() << ".null.1\""
  683. " name=\"" << mf->GetProjectName() << "\"/>\n"
  684. "</storageModule>\n"
  685. "</cproject>\n"
  686. ;
  687. }
  688. //----------------------------------------------------------------------------
  689. cmExtraEclipseCDT4Generator::EclipseToolchainType
  690. cmExtraEclipseCDT4Generator::GetToolChainType(const cmMakefile& makefile)
  691. {
  692. if (makefile.IsSet("UNIX"))
  693. {
  694. if (makefile.IsSet("CYGWIN"))
  695. {
  696. return EclipseToolchainCygwin;
  697. }
  698. if (makefile.IsSet("APPLE" ))
  699. {
  700. return EclipseToolchainMacOSX;
  701. }
  702. // *** how do I determine if it is Solaris ???
  703. return EclipseToolchainLinux;
  704. }
  705. else if (makefile.IsSet("WIN32"))
  706. {
  707. if (makefile.IsSet("MINGW"))
  708. {
  709. return EclipseToolchainMinGW;
  710. }
  711. if (makefile.IsSet("MSYS" ))
  712. {
  713. return EclipseToolchainMinGW;
  714. }
  715. return EclipseToolchainOther;
  716. }
  717. else
  718. {
  719. return EclipseToolchainOther;
  720. }
  721. }
  722. std::string
  723. cmExtraEclipseCDT4Generator::GetEclipsePath(const std::string& path)
  724. {
  725. #if defined(__CYGWIN__)
  726. std::string cmd = "cygpath -m " + path;
  727. std::string out;
  728. if (!cmSystemTools::RunCommand(cmd.c_str(), out, 0, false))
  729. {
  730. return path;
  731. }
  732. else
  733. {
  734. out.erase(out.find_last_of('\n'));
  735. return out;
  736. }
  737. #else
  738. return path;
  739. #endif
  740. }
  741. std::string
  742. cmExtraEclipseCDT4Generator::GetPathBasename(const std::string& path)
  743. {
  744. std::string outputBasename = path;
  745. while (outputBasename.size() > 0 &&
  746. (outputBasename[outputBasename.size() - 1] == '/' ||
  747. outputBasename[outputBasename.size() - 1] == '\\'))
  748. {
  749. outputBasename.resize(outputBasename.size() - 1);
  750. }
  751. std::string::size_type loc = outputBasename.find_last_of("/\\");
  752. if (loc != std::string::npos)
  753. {
  754. outputBasename = outputBasename.substr(loc + 1);
  755. }
  756. return outputBasename;
  757. }
  758. std::string
  759. cmExtraEclipseCDT4Generator::GenerateProjectName(const std::string& name,
  760. const std::string& type,
  761. const std::string& path)
  762. {
  763. return name + (type.empty() ? "" : "-") + type + "@" + path;
  764. }
  765. std::string cmExtraEclipseCDT4Generator::EscapeForXML(const std::string& value)
  766. {
  767. std::string str = value;
  768. cmSystemTools::ReplaceString(str, "&", "&amp;");
  769. cmSystemTools::ReplaceString(str, "<", "&lt;");
  770. cmSystemTools::ReplaceString(str, ">", "&gt;");
  771. cmSystemTools::ReplaceString(str, "\"", "&quot;");
  772. // NOTE: This one is not necessary, since as of Eclipse CDT4 it will
  773. // automatically change this to the original value (').
  774. //cmSystemTools::ReplaceString(str, "'", "&apos;");
  775. return str;
  776. }
  777. //----------------------------------------------------------------------------
  778. // Helper functions
  779. //----------------------------------------------------------------------------
  780. void cmExtraEclipseCDT4Generator
  781. ::AppendStorageScanners(cmGeneratedFileStream& fout,
  782. const cmMakefile& makefile)
  783. {
  784. // we need the "make" and the C (or C++) compiler which are used, Alex
  785. std::string make = makefile.GetRequiredDefinition("CMAKE_MAKE_PROGRAM");
  786. std::string compiler = makefile.GetSafeDefinition("CMAKE_C_COMPILER");
  787. if (compiler.empty())
  788. {
  789. compiler = makefile.GetSafeDefinition("CMAKE_CXX_COMPILER");
  790. }
  791. if (compiler.empty()) //Hmm, what to do now ?
  792. {
  793. compiler = "gcc";
  794. }
  795. // the following right now hardcodes gcc behaviour :-/
  796. fout <<
  797. "<storageModule moduleId=\"scannerConfiguration\">\n"
  798. "<autodiscovery enabled=\"true\" problemReportingEnabled=\"true\""
  799. " selectedProfileId="
  800. "\"org.eclipse.cdt.make.core.GCCStandardMakePerProjectProfile\"/>\n"
  801. ;
  802. cmExtraEclipseCDT4Generator::AppendScannerProfile(fout,
  803. "org.eclipse.cdt.make.core.GCCStandardMakePerProjectProfile",
  804. true, "", true, "specsFile",
  805. "-E -P -v -dD ${plugin_state_location}/${specs_file}",
  806. compiler, true, true);
  807. cmExtraEclipseCDT4Generator::AppendScannerProfile(fout,
  808. "org.eclipse.cdt.make.core.GCCStandardMakePerFileProfile",
  809. true, "", true, "makefileGenerator",
  810. "-f ${project_name}_scd.mk",
  811. make, true, true);
  812. fout << "</storageModule>\n";
  813. }
  814. void cmExtraEclipseCDT4Generator::AppendTarget(cmGeneratedFileStream& fout,
  815. const std::string& target,
  816. const std::string& make)
  817. {
  818. fout <<
  819. "<target name=\"" << target << "\""
  820. " path=\"\""
  821. " targetID=\"org.eclipse.cdt.make.MakeTargetBuilder\">\n"
  822. "<buildCommand>"
  823. << cmExtraEclipseCDT4Generator::GetEclipsePath(make)
  824. << "</buildCommand>\n"
  825. "<buildArguments/>\n"
  826. "<buildTarget>" << target << "</buildTarget>\n"
  827. "<stopOnError>true</stopOnError>\n"
  828. "<useDefaultCommand>false</useDefaultCommand>\n"
  829. "</target>\n"
  830. ;
  831. }
  832. void cmExtraEclipseCDT4Generator
  833. ::AppendScannerProfile(cmGeneratedFileStream& fout,
  834. const std::string& profileID,
  835. bool openActionEnabled,
  836. const std::string& openActionFilePath,
  837. bool pParserEnabled,
  838. const std::string& scannerInfoProviderID,
  839. const std::string& runActionArguments,
  840. const std::string& runActionCommand,
  841. bool runActionUseDefault,
  842. bool sipParserEnabled)
  843. {
  844. fout <<
  845. "<profile id=\"" << profileID << "\">\n"
  846. "<buildOutputProvider>\n"
  847. "<openAction enabled=\"" << (openActionEnabled ? "true" : "false")
  848. << "\" filePath=\"" << openActionFilePath << "\"/>\n"
  849. "<parser enabled=\"" << (pParserEnabled ? "true" : "false") << "\"/>\n"
  850. "</buildOutputProvider>\n"
  851. "<scannerInfoProvider id=\"" << scannerInfoProviderID << "\">\n"
  852. "<runAction arguments=\"" << runActionArguments << "\""
  853. " command=\"" << runActionCommand
  854. << "\" useDefault=\"" << (runActionUseDefault ? "true":"false") << "\"/>\n"
  855. "<parser enabled=\"" << (sipParserEnabled ? "true" : "false") << "\"/>\n"
  856. "</scannerInfoProvider>\n"
  857. "</profile>\n"
  858. ;
  859. }
  860. void cmExtraEclipseCDT4Generator
  861. ::AppendLinkedResource (cmGeneratedFileStream& fout,
  862. const std::string& name,
  863. const std::string& path)
  864. {
  865. fout <<
  866. "\t\t<link>\n"
  867. "\t\t\t<name>" << name << "</name>\n"
  868. "\t\t\t<type>2</type>\n"
  869. "\t\t\t<location>"
  870. << path
  871. << "</location>\n"
  872. "\t\t</link>\n"
  873. ;
  874. }
  875. bool cmExtraEclipseCDT4Generator
  876. ::AppendOutLinkedResource(cmGeneratedFileStream& fout,
  877. const std::string& defname,
  878. const std::string& altdefname)
  879. {
  880. if (defname.empty() && altdefname.empty())
  881. {
  882. return false;
  883. }
  884. std::string outputPath = (defname.empty() ? altdefname : defname);
  885. if (!cmSystemTools::FileIsFullPath(outputPath.c_str()))
  886. {
  887. outputPath = this->HomeOutputDirectory + "/" + outputPath;
  888. }
  889. if (cmSystemTools::IsSubDirectory(outputPath.c_str(),
  890. this->HomeOutputDirectory.c_str()))
  891. {
  892. return false;
  893. }
  894. std::string name = this->GetPathBasename(outputPath);
  895. // make sure linked resource name is unique
  896. while (this->GlobalGenerator->GetProjectMap().find(name)
  897. != this->GlobalGenerator->GetProjectMap().end())
  898. {
  899. name += "_";
  900. }
  901. if (std::find(this->OutLinkedResources.begin(),
  902. this->OutLinkedResources.end(),
  903. name)
  904. != this->OutLinkedResources.end())
  905. {
  906. return false;
  907. }
  908. else
  909. {
  910. this->AppendLinkedResource(fout, name,
  911. this->GetEclipsePath(outputPath));
  912. this->OutLinkedResources.push_back(name);
  913. return true;
  914. }
  915. }