cmGlobalKdevelopGenerator.cxx 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415
  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. See Copyright.txt or http://www.cmake.org/HTML/Copyright.html for details.
  10. This software is distributed WITHOUT ANY WARRANTY; without even
  11. the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
  12. PURPOSE. See the above copyright notices for more information.
  13. =========================================================================*/
  14. #include "cmGlobalKdevelopGenerator.h"
  15. #include "cmLocalKdevelopGenerator.h"
  16. #include "cmMakefile.h"
  17. #include "cmake.h"
  18. #include "cmSourceFile.h"
  19. #include "cmGeneratedFileStream.h"
  20. cmGlobalKdevelopGenerator::cmGlobalKdevelopGenerator()
  21. {
  22. // This type of makefile always requires unix style paths
  23. m_ForceUnixPaths = true;
  24. m_FindMakeProgramFile = "CMakeUnixFindMake.cmake";
  25. }
  26. ///! Create a local generator appropriate to this Global Generator
  27. cmLocalGenerator *cmGlobalKdevelopGenerator::CreateLocalGenerator()
  28. {
  29. cmLocalGenerator *lg = new cmLocalKdevelopGenerator;
  30. lg->SetGlobalGenerator(this);
  31. return lg;
  32. }
  33. //----------------------------------------------------------------------------
  34. void cmGlobalKdevelopGenerator::GetDocumentation(cmDocumentationEntry& entry) const
  35. {
  36. entry.name = this->GetName();
  37. entry.brief = "Generates KDevelop 3 project files.";
  38. entry.full =
  39. "Project files for KDevelop 3 will be created in the top directory and in every subdirectory "
  40. "which features a CMakeLists.txt file containing a PROJECT() call. "
  41. "If you change the settings using KDevelop cmake will try its best "
  42. "to keep your changes when regenerating the project files. "
  43. "Additionally a hierarchy of UNIX makefiles is generated into the build tree. Any "
  44. "standard UNIX-style make program can build the project through the "
  45. "default make target. A \"make install\" target is also provided.";
  46. }
  47. void cmGlobalKdevelopGenerator::Generate()
  48. {
  49. this->cmGlobalGenerator::Generate();
  50. // for each sub project in the project create
  51. // a kdevelop project
  52. std::map<cmStdString, std::vector<cmLocalGenerator*> >::iterator it;
  53. for(it = m_ProjectMap.begin(); it!= m_ProjectMap.end(); ++it)
  54. {
  55. cmMakefile* mf = it->second[0]->GetMakefile();
  56. std::string outputDir=mf->GetStartOutputDirectory();
  57. std::string projectDir=mf->GetHomeDirectory();
  58. std::string projectName=mf->GetProjectName();
  59. std::string cmakeFilePattern("CMakeLists.txt;*.cmake;");
  60. // create the project.kdevelop.filelist file
  61. if(!this->CreateFilelistFile(it->second[0], it->second,
  62. outputDir, projectDir,
  63. projectName, cmakeFilePattern))
  64. {
  65. cmSystemTools::Error("Can not create filelist file");
  66. return;
  67. }
  68. //try to find the name of an executable so we have something to
  69. //run from kdevelop for now just pick the first executable found
  70. std::string executable;
  71. cmTargets& targets=mf->GetTargets();
  72. for (cmTargets::const_iterator ti = targets.begin();
  73. ti != targets.end(); ti++)
  74. {
  75. if (ti->second.GetType()==cmTarget::EXECUTABLE)
  76. {
  77. executable=ti->first;
  78. break;
  79. }
  80. }
  81. // now create a project file
  82. this->CreateProjectFile(outputDir, projectDir, projectName,
  83. executable, cmakeFilePattern);
  84. }
  85. }
  86. bool cmGlobalKdevelopGenerator
  87. ::CreateFilelistFile(cmLocalGenerator* lg,
  88. std::vector<cmLocalGenerator*>& lgs,
  89. const std::string& outputDir,
  90. const std::string& projectDirIn,
  91. const std::string& projectname,
  92. std::string& cmakeFilePattern)
  93. {
  94. cmMakefile* mf =lg->GetMakefile();
  95. std::string projectDir = projectDirIn + "/";
  96. std::string filename = outputDir+"/" + std::string(mf->GetProjectName())
  97. +".kdevelop.filelist";
  98. std::set<cmStdString> files;
  99. std::string tmp;
  100. for (std::vector<cmLocalGenerator*>::const_iterator it=lgs.begin();
  101. it!=lgs.end(); it++)
  102. {
  103. cmMakefile* makefile=(*it)->GetMakefile();
  104. const std::vector<std::string>& listFiles=makefile->GetListFiles();
  105. for (std::vector<std::string>::const_iterator lt=listFiles.begin();
  106. lt!=listFiles.end(); lt++)
  107. {
  108. tmp=*lt;
  109. cmSystemTools::ReplaceString(tmp, projectDir.c_str(), "");
  110. // make sure the file is part of this source tree
  111. if (tmp[0]!='/')
  112. {
  113. files.insert(tmp);
  114. tmp=cmSystemTools::GetFilenameName(tmp);
  115. //add all files which dont match the default
  116. // */CMakeLists.txt;*cmake; to the file pattern
  117. if ((tmp!="CMakeLists.txt")
  118. && (strstr(tmp.c_str(), ".cmake")==0))
  119. {
  120. cmakeFilePattern+=tmp+";";
  121. }
  122. }
  123. }
  124. //get all sources
  125. cmTargets& targets=makefile->GetTargets();
  126. for (cmTargets::const_iterator ti = targets.begin();
  127. ti != targets.end(); ti++)
  128. {
  129. const std::vector<cmSourceFile*>& sources=ti->second.GetSourceFiles();
  130. for (std::vector<cmSourceFile*>::const_iterator si=sources.begin();
  131. si!=sources.end(); si++)
  132. {
  133. tmp=(*si)->GetFullPath();
  134. cmSystemTools::ReplaceString(tmp, projectDir.c_str(), "");
  135. if (tmp[0]!='/')
  136. {
  137. files.insert(tmp);
  138. }
  139. }
  140. for (std::vector<std::string>::const_iterator lt=listFiles.begin();
  141. lt!=listFiles.end(); lt++)
  142. {
  143. tmp=*lt;
  144. cmSystemTools::ReplaceString(tmp, projectDir.c_str(), "");
  145. if (tmp[0]!='/')
  146. {
  147. files.insert(tmp.c_str());
  148. }
  149. }
  150. }
  151. }
  152. //check if the output file already exists and read it
  153. //insert all files which exist into the set of files
  154. std::ifstream oldFilelist(filename.c_str());
  155. if (oldFilelist)
  156. {
  157. while (cmSystemTools::GetLineFromStream(oldFilelist, tmp))
  158. {
  159. if (tmp[0]=='/')
  160. {
  161. continue;
  162. }
  163. std::string completePath=projectDir+tmp;
  164. if (cmSystemTools::FileExists(completePath.c_str()))
  165. {
  166. files.insert(tmp);
  167. }
  168. }
  169. oldFilelist.close();
  170. }
  171. //now write the new filename
  172. cmGeneratedFileStream fout(filename.c_str());
  173. if(!fout)
  174. {
  175. return false;
  176. }
  177. for (std::set<cmStdString>::const_iterator it=files.begin();
  178. it!=files.end(); it++)
  179. {
  180. // get the full path to the file
  181. tmp=cmSystemTools::CollapseFullPath(it->c_str(), projectDir.c_str());
  182. // make it relative to the project dir
  183. cmSystemTools::ReplaceString(tmp, projectDir.c_str(), "");
  184. // only put relative paths
  185. if (tmp.size() && tmp[0] != '/')
  186. {
  187. fout << tmp.c_str() <<"\n";
  188. }
  189. }
  190. return true;
  191. }
  192. /* create the project file, if it already exists, merge it with the
  193. existing one, otherwise create a new one */
  194. void
  195. cmGlobalKdevelopGenerator::CreateProjectFile(const std::string& outputDir,
  196. const std::string& projectDir,
  197. const std::string& projectname,
  198. const std::string& executable,
  199. const std::string& cmakeFilePattern)
  200. {
  201. std::string filename=outputDir+"/";
  202. filename+=projectname+".kdevelop";
  203. if (cmSystemTools::FileExists(filename.c_str()))
  204. {
  205. this->MergeProjectFiles(outputDir, projectDir, filename,
  206. executable, cmakeFilePattern);
  207. }
  208. else
  209. {
  210. this->CreateNewProjectFile(outputDir, projectDir, filename,
  211. executable, cmakeFilePattern);
  212. }
  213. }
  214. void
  215. cmGlobalKdevelopGenerator::MergeProjectFiles(const std::string& outputDir,
  216. const std::string& projectDir,
  217. const std::string& filename,
  218. const std::string& executable,
  219. const std::string& cmakeFilePattern)
  220. {
  221. std::ifstream oldProjectFile(filename.c_str());
  222. if (!oldProjectFile)
  223. {
  224. this->CreateNewProjectFile(outputDir, projectDir, filename, executable, cmakeFilePattern);
  225. return;
  226. }
  227. /* Read the existing project file (line by line), copy all lines
  228. into the new project file, except the ones which can be reliably
  229. set from contents of the CMakeLists.txt */
  230. std::string tmp;
  231. std::vector<std::string> lines;
  232. while (cmSystemTools::GetLineFromStream(oldProjectFile, tmp))
  233. {
  234. lines.push_back(tmp);
  235. }
  236. oldProjectFile.close();
  237. cmGeneratedFileStream fout(filename.c_str());
  238. if(!fout)
  239. {
  240. return;
  241. }
  242. for (std::vector<std::string>::const_iterator it=lines.begin();
  243. it!=lines.end(); it++)
  244. {
  245. const char* line=(*it).c_str();
  246. // skip these tags as they are always replaced
  247. if ((strstr(line, "<projectdirectory>")!=0)
  248. || (strstr(line, "<projectmanagement>")!=0)
  249. || (strstr(line, "<absoluteprojectpath>")!=0)
  250. || (strstr(line, "<filelistdirectory>")!=0)
  251. || (strstr(line, "<buildtool>")!=0)
  252. || (strstr(line, "<builddir>")!=0))
  253. {
  254. continue;
  255. }
  256. // output the line from the file if it is not one of the above tags
  257. fout<<*it<<"\n";
  258. // if this is the <general> tag output the stuff that goes in the general tag
  259. if (strstr(line, "<general>"))
  260. {
  261. fout<<" <projectmanagement>KDevCustomProject</projectmanagement>\n";
  262. fout<<" <projectdirectory>"<<projectDir.c_str()<<"</projectdirectory>\n"; //this one is important
  263. fout<<" <absoluteprojectpath>true</absoluteprojectpath>\n"; //and this one
  264. }
  265. // inside kdevcustomproject the <filelistdirectory> must be put
  266. if (strstr(line, "<kdevcustomproject>"))
  267. {
  268. fout<<" <filelistdirectory>"<<outputDir.c_str()
  269. <<"</filelistdirectory>\n";
  270. }
  271. // buildtool and builddir go inside <build>
  272. if (strstr(line, "<build>"))
  273. {
  274. fout<<" <buildtool>make</buildtool>\n";
  275. fout<<" <builddir>"<<outputDir.c_str()<<"</builddir>\n";
  276. }
  277. }
  278. }
  279. void
  280. cmGlobalKdevelopGenerator::CreateNewProjectFile(const std::string& outputDir,
  281. const std::string& projectDir,
  282. const std::string& filename,
  283. const std::string& executable,
  284. const std::string& cmakeFilePattern)
  285. {
  286. cmGeneratedFileStream fout(filename.c_str());
  287. if(!fout)
  288. {
  289. return;
  290. }
  291. fout<<"<?xml version = '1.0'?>\n";
  292. fout<<"<kdevelop>\n";
  293. fout<<" <general>\n";
  294. fout<<" <author></author>\n";
  295. fout<<" <email></email>\n";
  296. fout<<" <version>$VERSION$</version>\n";
  297. fout<<" <projectmanagement>KDevCustomProject</projectmanagement>\n";
  298. fout<<" <primarylanguage>C++</primarylanguage>\n";
  299. fout<<" <ignoreparts/>\n";
  300. fout<<" <projectdirectory>"<<projectDir.c_str()<<"</projectdirectory>\n"; //this one is important
  301. fout<<" <absoluteprojectpath>true</absoluteprojectpath>\n"; //and this one
  302. fout<<" <secondaryLanguages>\n";
  303. fout<<" <language>C</language>\n";
  304. fout<<" </secondaryLanguages>\n";
  305. fout<<" </general>\n";
  306. fout<<" <kdevcustomproject>\n";
  307. fout<<" <filelistdirectory>"<<outputDir.c_str()<<"</filelistdirectory>\n";
  308. fout<<" <run>\n";
  309. fout<<" <mainprogram>"<<outputDir.c_str()<<"/"<<executable.c_str()<<"</mainprogram>\n";
  310. fout<<" <directoryradio>custom</directoryradio>\n";
  311. fout<<" <customdirectory>/</customdirectory>\n";
  312. fout<<" <programargs></programargs>\n";
  313. fout<<" <terminal>false</terminal>\n";
  314. fout<<" <autocompile>true</autocompile>\n";
  315. fout<<" <envvars/>\n";
  316. fout<<" </run>\n";
  317. fout<<" <build>\n";
  318. fout<<" <buildtool>make</buildtool>\n"; //this one is important
  319. fout<<" <builddir>"<<outputDir.c_str()<<"</builddir>\n"; //and this one
  320. fout<<" </build>\n";
  321. fout<<" <make>\n";
  322. fout<<" <abortonerror>false</abortonerror>\n";
  323. fout<<" <numberofjobs>1</numberofjobs>\n";
  324. fout<<" <dontact>false</dontact>\n";
  325. fout<<" <makebin></makebin>\n";
  326. fout<<" <selectedenvironment>default</selectedenvironment>\n";
  327. fout<<" <environments>\n";
  328. fout<<" <default/>\n";
  329. fout<<" </environments>\n";
  330. fout<<" </make>\n";
  331. fout<<" </kdevcustomproject>\n";
  332. fout<<" <kdevfilecreate>\n";
  333. fout<<" <filetypes/>\n";
  334. fout<<" <useglobaltypes>\n";
  335. fout<<" <type ext=\"ui\" />\n";
  336. fout<<" <type ext=\"cpp\" />\n";
  337. fout<<" <type ext=\"h\" />\n";
  338. fout<<" </useglobaltypes>\n";
  339. fout<<" </kdevfilecreate>\n";
  340. fout<<" <kdevdoctreeview>\n";
  341. fout<<" <projectdoc>\n";
  342. fout<<" <userdocDir>html/</userdocDir>\n";
  343. fout<<" <apidocDir>html/</apidocDir>\n";
  344. fout<<" </projectdoc>\n";
  345. fout<<" <ignoreqt_xml/>\n";
  346. fout<<" <ignoredoxygen/>\n";
  347. fout<<" <ignorekdocs/>\n";
  348. fout<<" <ignoretocs/>\n";
  349. fout<<" <ignoredevhelp/>\n";
  350. fout<<" </kdevdoctreeview>\n";
  351. fout<<" <cppsupportpart>\n";
  352. fout<<" <filetemplates>\n";
  353. fout<<" <interfacesuffix>.h</interfacesuffix>\n";
  354. fout<<" <implementationsuffix>.cpp</implementationsuffix>\n";
  355. fout<<" </filetemplates>\n";
  356. fout<<" </cppsupportpart>\n";
  357. fout<<" <kdevcppsupport>\n";
  358. fout<<" <codecompletion>\n";
  359. fout<<" <includeGlobalFunctions>true</includeGlobalFunctions>\n";
  360. fout<<" <includeTypes>true</includeTypes>\n";
  361. fout<<" <includeEnums>true</includeEnums>\n";
  362. fout<<" <includeTypedefs>false</includeTypedefs>\n";
  363. fout<<" <automaticCodeCompletion>true</automaticCodeCompletion>\n";
  364. fout<<" <automaticArgumentsHint>true</automaticArgumentsHint>\n";
  365. fout<<" <automaticHeaderCompletion>true</automaticHeaderCompletion>\n";
  366. fout<<" <codeCompletionDelay>250</codeCompletionDelay>\n";
  367. fout<<" <argumentsHintDelay>400</argumentsHintDelay>\n";
  368. fout<<" <headerCompletionDelay>250</headerCompletionDelay>\n";
  369. fout<<" </codecompletion>\n";
  370. fout<<" <references/>\n";
  371. fout<<" </kdevcppsupport>\n";
  372. fout<<" <kdevfileview>\n";
  373. fout<<" <groups>\n";
  374. fout<<" <group pattern=\""<<cmakeFilePattern.c_str()<<"\" name=\"CMake\" />\n";
  375. fout<<" <group pattern=\"*.h;*.hxx\" name=\"Header\" />\n";
  376. fout<<" <group pattern=\"*.cpp;*.c;*.C;*.cxx\" name=\"Sources\" />\n";
  377. fout<<" <group pattern=\"*.ui\" name=\"Qt Designer files\" />\n";
  378. fout<<" <hidenonprojectfiles>true</hidenonprojectfiles>\n";
  379. fout<<" </groups>\n";
  380. fout<<" <tree>\n";
  381. fout<<" <hidepatterns>*.o,*.lo,CVS,*~,cmake*</hidepatterns>\n";
  382. fout<<" <hidenonprojectfiles>true</hidenonprojectfiles>\n";
  383. fout<<" </tree>\n";
  384. fout<<" </kdevfileview>\n";
  385. fout<<"</kdevelop>\n";
  386. }