cmExtraCodeLiteGenerator.cxx 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711
  1. /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
  2. file Copyright.txt or https://cmake.org/licensing for details. */
  3. #include "cmExtraCodeLiteGenerator.h"
  4. #include "cmGeneratedFileStream.h"
  5. #include "cmGeneratorTarget.h"
  6. #include "cmGlobalGenerator.h"
  7. #include "cmLocalGenerator.h"
  8. #include "cmMakefile.h"
  9. #include "cmSourceFile.h"
  10. #include "cmStateTypes.h"
  11. #include "cmSystemTools.h"
  12. #include "cmXMLWriter.h"
  13. #include "cmake.h"
  14. #include "cmsys/SystemInformation.hxx"
  15. #include <map>
  16. #include <set>
  17. #include <sstream>
  18. #include <string.h>
  19. #include <utility>
  20. cmExtraCodeLiteGenerator::cmExtraCodeLiteGenerator()
  21. : cmExternalMakefileProjectGenerator()
  22. , ConfigName("NoConfig")
  23. , CpuCount(2)
  24. {
  25. }
  26. cmExternalMakefileProjectGeneratorFactory*
  27. cmExtraCodeLiteGenerator::GetFactory()
  28. {
  29. static cmExternalMakefileProjectGeneratorSimpleFactory<
  30. cmExtraCodeLiteGenerator>
  31. factory("CodeLite", "Generates CodeLite project files.");
  32. if (factory.GetSupportedGlobalGenerators().empty()) {
  33. #if defined(_WIN32)
  34. factory.AddSupportedGlobalGenerator("MinGW Makefiles");
  35. factory.AddSupportedGlobalGenerator("NMake Makefiles");
  36. #endif
  37. factory.AddSupportedGlobalGenerator("Ninja");
  38. factory.AddSupportedGlobalGenerator("Unix Makefiles");
  39. }
  40. return &factory;
  41. }
  42. void cmExtraCodeLiteGenerator::Generate()
  43. {
  44. // Hold root tree information for creating the workspace
  45. std::string workspaceProjectName;
  46. std::string workspaceOutputDir;
  47. std::string workspaceFileName;
  48. std::string workspaceSourcePath;
  49. const std::map<std::string, std::vector<cmLocalGenerator*> >& projectMap =
  50. this->GlobalGenerator->GetProjectMap();
  51. // loop projects and locate the root project.
  52. // and extract the information for creating the worspace
  53. // root makefile
  54. for (std::map<std::string, std::vector<cmLocalGenerator*> >::const_iterator
  55. it = projectMap.begin();
  56. it != projectMap.end(); ++it) {
  57. const cmMakefile* mf = it->second[0]->GetMakefile();
  58. this->ConfigName = GetConfigurationName(mf);
  59. if (strcmp(it->second[0]->GetCurrentBinaryDirectory(),
  60. it->second[0]->GetBinaryDirectory()) == 0) {
  61. workspaceOutputDir = it->second[0]->GetCurrentBinaryDirectory();
  62. workspaceProjectName = it->second[0]->GetProjectName();
  63. workspaceSourcePath = it->second[0]->GetSourceDirectory();
  64. workspaceFileName = workspaceOutputDir + "/";
  65. workspaceFileName += workspaceProjectName + ".workspace";
  66. this->WorkspacePath = it->second[0]->GetCurrentBinaryDirectory();
  67. ;
  68. break;
  69. }
  70. }
  71. cmGeneratedFileStream fout(workspaceFileName.c_str());
  72. cmXMLWriter xml(fout);
  73. xml.StartDocument("utf-8");
  74. xml.StartElement("CodeLite_Workspace");
  75. xml.Attribute("Name", workspaceProjectName);
  76. bool const targetsAreProjects =
  77. this->GlobalGenerator->GlobalSettingIsOn("CMAKE_CODELITE_USE_TARGETS");
  78. std::vector<std::string> ProjectNames;
  79. if (targetsAreProjects) {
  80. ProjectNames = CreateProjectsByTarget(&xml);
  81. } else {
  82. ProjectNames = CreateProjectsByProjectMaps(&xml);
  83. }
  84. xml.StartElement("BuildMatrix");
  85. xml.StartElement("WorkspaceConfiguration");
  86. xml.Attribute("Name", this->ConfigName);
  87. xml.Attribute("Selected", "yes");
  88. for (std::vector<std::string>::iterator it(ProjectNames.begin());
  89. it != ProjectNames.end(); it++) {
  90. xml.StartElement("Project");
  91. xml.Attribute("Name", *it);
  92. xml.Attribute("ConfigName", this->ConfigName);
  93. xml.EndElement();
  94. }
  95. xml.EndElement(); // WorkspaceConfiguration
  96. xml.EndElement(); // BuildMatrix
  97. xml.EndElement(); // CodeLite_Workspace
  98. }
  99. // Create projects where targets are the projects
  100. std::vector<std::string> cmExtraCodeLiteGenerator::CreateProjectsByTarget(
  101. cmXMLWriter* xml)
  102. {
  103. std::vector<std::string> retval;
  104. // for each target in the workspace create a codelite project
  105. const std::vector<cmLocalGenerator*>& lgs =
  106. this->GlobalGenerator->GetLocalGenerators();
  107. for (std::vector<cmLocalGenerator*>::const_iterator lg(lgs.begin());
  108. lg != lgs.end(); lg++) {
  109. for (std::vector<cmGeneratorTarget*>::const_iterator lt =
  110. (*lg)->GetGeneratorTargets().begin();
  111. lt != (*lg)->GetGeneratorTargets().end(); lt++) {
  112. cmStateEnums::TargetType type = (*lt)->GetType();
  113. std::string outputDir = (*lg)->GetCurrentBinaryDirectory();
  114. std::string targetName = (*lt)->GetName();
  115. std::string filename = outputDir + "/" + targetName + ".project";
  116. retval.push_back(targetName);
  117. // Make the project file relative to the workspace
  118. std::string relafilename = cmSystemTools::RelativePath(
  119. this->WorkspacePath.c_str(), filename.c_str());
  120. std::string visualname = targetName;
  121. switch (type) {
  122. case cmStateEnums::SHARED_LIBRARY:
  123. case cmStateEnums::STATIC_LIBRARY:
  124. case cmStateEnums::MODULE_LIBRARY:
  125. visualname = "lib" + visualname;
  126. CM_FALLTHROUGH;
  127. case cmStateEnums::EXECUTABLE:
  128. xml->StartElement("Project");
  129. xml->Attribute("Name", visualname);
  130. xml->Attribute("Path", relafilename);
  131. xml->Attribute("Active", "No");
  132. xml->EndElement();
  133. CreateNewProjectFile(*lt, filename);
  134. break;
  135. default:
  136. break;
  137. }
  138. }
  139. }
  140. return retval;
  141. }
  142. // The "older way of doing it.
  143. std::vector<std::string> cmExtraCodeLiteGenerator::CreateProjectsByProjectMaps(
  144. cmXMLWriter* xml)
  145. {
  146. std::vector<std::string> retval;
  147. // for each sub project in the workspace create a codelite project
  148. for (std::map<std::string, std::vector<cmLocalGenerator*> >::const_iterator
  149. it = this->GlobalGenerator->GetProjectMap().begin();
  150. it != this->GlobalGenerator->GetProjectMap().end(); it++) {
  151. std::string outputDir = it->second[0]->GetCurrentBinaryDirectory();
  152. std::string projectName = it->second[0]->GetProjectName();
  153. retval.push_back(projectName);
  154. std::string filename = outputDir + "/" + projectName + ".project";
  155. // Make the project file relative to the workspace
  156. filename = cmSystemTools::RelativePath(this->WorkspacePath.c_str(),
  157. filename.c_str());
  158. // create a project file
  159. this->CreateProjectFile(it->second);
  160. xml->StartElement("Project");
  161. xml->Attribute("Name", projectName);
  162. xml->Attribute("Path", filename);
  163. xml->Attribute("Active", "No");
  164. xml->EndElement();
  165. }
  166. return retval;
  167. }
  168. /* create the project file */
  169. void cmExtraCodeLiteGenerator::CreateProjectFile(
  170. const std::vector<cmLocalGenerator*>& lgs)
  171. {
  172. std::string outputDir = lgs[0]->GetCurrentBinaryDirectory();
  173. std::string projectName = lgs[0]->GetProjectName();
  174. std::string filename = outputDir + "/";
  175. filename += projectName + ".project";
  176. this->CreateNewProjectFile(lgs, filename);
  177. }
  178. std::string cmExtraCodeLiteGenerator::CollectSourceFiles(
  179. const cmMakefile* makefile, const cmGeneratorTarget* gt,
  180. std::map<std::string, cmSourceFile*>& cFiles,
  181. std::set<std::string>& otherFiles)
  182. {
  183. const std::vector<std::string>& srcExts =
  184. this->GlobalGenerator->GetCMakeInstance()->GetSourceExtensions();
  185. std::string projectType;
  186. switch (gt->GetType()) {
  187. case cmStateEnums::EXECUTABLE: {
  188. projectType = "Executable";
  189. } break;
  190. case cmStateEnums::STATIC_LIBRARY: {
  191. projectType = "Static Library";
  192. } break;
  193. case cmStateEnums::SHARED_LIBRARY: {
  194. projectType = "Dynamic Library";
  195. } break;
  196. case cmStateEnums::MODULE_LIBRARY: {
  197. projectType = "Dynamic Library";
  198. } break;
  199. default: // intended fallthrough
  200. break;
  201. }
  202. switch (gt->GetType()) {
  203. case cmStateEnums::EXECUTABLE:
  204. case cmStateEnums::STATIC_LIBRARY:
  205. case cmStateEnums::SHARED_LIBRARY:
  206. case cmStateEnums::MODULE_LIBRARY: {
  207. std::vector<cmSourceFile*> sources;
  208. gt->GetSourceFiles(sources,
  209. makefile->GetSafeDefinition("CMAKE_BUILD_TYPE"));
  210. for (std::vector<cmSourceFile*>::const_iterator si = sources.begin();
  211. si != sources.end(); si++) {
  212. // check whether it is a C/C++ implementation file
  213. bool isCFile = false;
  214. std::string lang = (*si)->GetLanguage();
  215. if (lang == "C" || lang == "CXX") {
  216. std::string const& srcext = (*si)->GetExtension();
  217. for (std::vector<std::string>::const_iterator ext = srcExts.begin();
  218. ext != srcExts.end(); ++ext) {
  219. if (srcext == *ext) {
  220. isCFile = true;
  221. break;
  222. }
  223. }
  224. }
  225. // then put it accordingly into one of the two containers
  226. if (isCFile) {
  227. cFiles[(*si)->GetFullPath()] = *si;
  228. } else {
  229. otherFiles.insert((*si)->GetFullPath());
  230. }
  231. }
  232. }
  233. default: // intended fallthrough
  234. break;
  235. }
  236. return projectType;
  237. }
  238. void cmExtraCodeLiteGenerator::CreateNewProjectFile(
  239. const std::vector<cmLocalGenerator*>& lgs, const std::string& filename)
  240. {
  241. const cmMakefile* mf = lgs[0]->GetMakefile();
  242. cmGeneratedFileStream fout(filename.c_str());
  243. if (!fout) {
  244. return;
  245. }
  246. cmXMLWriter xml(fout);
  247. ////////////////////////////////////
  248. xml.StartDocument("utf-8");
  249. xml.StartElement("CodeLite_Project");
  250. xml.Attribute("Name", lgs[0]->GetProjectName());
  251. xml.Attribute("InternalType", "");
  252. std::string projectType;
  253. // Collect all used source files in the project
  254. // Sort them into two containers, one for C/C++ implementation files
  255. // which may have an acompanying header, one for all other files
  256. std::map<std::string, cmSourceFile*> cFiles;
  257. std::set<std::string> otherFiles;
  258. for (std::vector<cmLocalGenerator*>::const_iterator lg = lgs.begin();
  259. lg != lgs.end(); lg++) {
  260. cmMakefile* makefile = (*lg)->GetMakefile();
  261. const std::vector<cmGeneratorTarget*>& targets =
  262. (*lg)->GetGeneratorTargets();
  263. for (std::vector<cmGeneratorTarget*>::const_iterator ti = targets.begin();
  264. ti != targets.end(); ti++) {
  265. projectType = CollectSourceFiles(makefile, *ti, cFiles, otherFiles);
  266. }
  267. }
  268. // Get the project path ( we need it later to convert files to
  269. // their relative path)
  270. std::string projectPath = cmSystemTools::GetFilenamePath(filename);
  271. CreateProjectSourceEntries(cFiles, otherFiles, &xml, projectPath, mf,
  272. projectType, "");
  273. xml.EndElement(); // CodeLite_Project
  274. }
  275. void cmExtraCodeLiteGenerator::FindMatchingHeaderfiles(
  276. std::map<std::string, cmSourceFile*>& cFiles,
  277. std::set<std::string>& otherFiles)
  278. {
  279. const std::vector<std::string>& headerExts =
  280. this->GlobalGenerator->GetCMakeInstance()->GetHeaderExtensions();
  281. // The following loop tries to add header files matching to implementation
  282. // files to the project. It does that by iterating over all source files,
  283. // replacing the file name extension with ".h" and checks whether such a
  284. // file exists. If it does, it is inserted into the map of files.
  285. // A very similar version of that code exists also in the kdevelop
  286. // project generator.
  287. for (std::map<std::string, cmSourceFile*>::const_iterator sit =
  288. cFiles.begin();
  289. sit != cFiles.end(); ++sit) {
  290. std::string headerBasename = cmSystemTools::GetFilenamePath(sit->first);
  291. headerBasename += "/";
  292. headerBasename += cmSystemTools::GetFilenameWithoutExtension(sit->first);
  293. // check if there's a matching header around
  294. for (std::vector<std::string>::const_iterator ext = headerExts.begin();
  295. ext != headerExts.end(); ++ext) {
  296. std::string hname = headerBasename;
  297. hname += ".";
  298. hname += *ext;
  299. // if it's already in the set, don't check if it exists on disk
  300. std::set<std::string>::const_iterator headerIt = otherFiles.find(hname);
  301. if (headerIt != otherFiles.end()) {
  302. break;
  303. }
  304. if (cmSystemTools::FileExists(hname.c_str())) {
  305. otherFiles.insert(hname);
  306. break;
  307. }
  308. }
  309. }
  310. }
  311. void cmExtraCodeLiteGenerator::CreateFoldersAndFiles(
  312. std::set<std::string>& cFiles, cmXMLWriter& xml,
  313. const std::string& projectPath)
  314. {
  315. std::vector<std::string> tmp_path;
  316. std::vector<std::string> components;
  317. size_t numOfEndEl = 0;
  318. for (std::set<std::string>::const_iterator it = cFiles.begin();
  319. it != cFiles.end(); ++it) {
  320. std::string frelapath =
  321. cmSystemTools::RelativePath(projectPath.c_str(), it->c_str());
  322. cmsys::SystemTools::SplitPath(frelapath, components, false);
  323. components.pop_back(); // erase last member -> it is file, not folder
  324. components.erase(components.begin()); // erase "root"
  325. size_t sizeOfSkip = 0;
  326. for (size_t i = 0; i < components.size(); ++i) {
  327. // skip relative path
  328. if (components[i] == ".." || components[i] == ".") {
  329. sizeOfSkip++;
  330. continue;
  331. }
  332. // same folder
  333. if (tmp_path.size() > i - sizeOfSkip &&
  334. tmp_path[i - sizeOfSkip] == components[i]) {
  335. continue;
  336. }
  337. // delete "old" subfolders
  338. if (tmp_path.size() > i - sizeOfSkip) {
  339. numOfEndEl = tmp_path.size() - i + sizeOfSkip;
  340. tmp_path.erase(tmp_path.end() - numOfEndEl, tmp_path.end());
  341. for (; numOfEndEl--;) {
  342. xml.EndElement();
  343. }
  344. }
  345. // add folder
  346. xml.StartElement("VirtualDirectory");
  347. xml.Attribute("Name", components[i]);
  348. tmp_path.push_back(components[i]);
  349. }
  350. // delete "old" subfolders
  351. numOfEndEl = tmp_path.size() - components.size() + sizeOfSkip;
  352. if (numOfEndEl) {
  353. tmp_path.erase(tmp_path.end() - numOfEndEl, tmp_path.end());
  354. for (; numOfEndEl--;) {
  355. xml.EndElement();
  356. }
  357. }
  358. // add file
  359. xml.StartElement("File");
  360. xml.Attribute("Name", frelapath);
  361. xml.EndElement();
  362. }
  363. // end of folders
  364. numOfEndEl = tmp_path.size();
  365. for (; numOfEndEl--;) {
  366. xml.EndElement();
  367. }
  368. }
  369. void cmExtraCodeLiteGenerator::CreateFoldersAndFiles(
  370. std::map<std::string, cmSourceFile*>& cFiles, cmXMLWriter& xml,
  371. const std::string& projectPath)
  372. {
  373. std::set<std::string> s;
  374. for (std::map<std::string, cmSourceFile*>::const_iterator it =
  375. cFiles.begin();
  376. it != cFiles.end(); ++it) {
  377. s.insert(it->first);
  378. }
  379. this->CreateFoldersAndFiles(s, xml, projectPath);
  380. }
  381. void cmExtraCodeLiteGenerator::CreateProjectSourceEntries(
  382. std::map<std::string, cmSourceFile*>& cFiles,
  383. std::set<std::string>& otherFiles, cmXMLWriter* _xml,
  384. const std::string& projectPath, const cmMakefile* mf,
  385. const std::string& projectType, const std::string& targetName)
  386. {
  387. cmXMLWriter& xml(*_xml);
  388. FindMatchingHeaderfiles(cFiles, otherFiles);
  389. // Create 2 virtual folders: src and include
  390. // and place all the implementation files into the src
  391. // folder, the rest goes to the include folder
  392. xml.StartElement("VirtualDirectory");
  393. xml.Attribute("Name", "src");
  394. // insert all source files in the codelite project
  395. // first the C/C++ implementation files, then all others
  396. this->CreateFoldersAndFiles(cFiles, xml, projectPath);
  397. xml.EndElement(); // VirtualDirectory
  398. xml.StartElement("VirtualDirectory");
  399. xml.Attribute("Name", "include");
  400. this->CreateFoldersAndFiles(otherFiles, xml, projectPath);
  401. xml.EndElement(); // VirtualDirectory
  402. // Get the number of CPUs. We use this information for the make -jN
  403. // command
  404. cmsys::SystemInformation info;
  405. info.RunCPUCheck();
  406. this->CpuCount =
  407. info.GetNumberOfLogicalCPU() * info.GetNumberOfPhysicalCPU();
  408. std::string codeliteCompilerName = this->GetCodeLiteCompilerName(mf);
  409. xml.StartElement("Settings");
  410. xml.Attribute("Type", projectType);
  411. xml.StartElement("Configuration");
  412. xml.Attribute("Name", this->ConfigName);
  413. xml.Attribute("CompilerType", this->GetCodeLiteCompilerName(mf));
  414. xml.Attribute("DebuggerType", "GNU gdb debugger");
  415. xml.Attribute("Type", projectType);
  416. xml.Attribute("BuildCmpWithGlobalSettings", "append");
  417. xml.Attribute("BuildLnkWithGlobalSettings", "append");
  418. xml.Attribute("BuildResWithGlobalSettings", "append");
  419. xml.StartElement("Compiler");
  420. xml.Attribute("Options", "-g");
  421. xml.Attribute("Required", "yes");
  422. xml.Attribute("PreCompiledHeader", "");
  423. xml.StartElement("IncludePath");
  424. xml.Attribute("Value", ".");
  425. xml.EndElement(); // IncludePath
  426. xml.EndElement(); // Compiler
  427. xml.StartElement("Linker");
  428. xml.Attribute("Options", "");
  429. xml.Attribute("Required", "yes");
  430. xml.EndElement(); // Linker
  431. xml.StartElement("ResourceCompiler");
  432. xml.Attribute("Options", "");
  433. xml.Attribute("Required", "no");
  434. xml.EndElement(); // ResourceCompiler
  435. xml.StartElement("General");
  436. std::string outputPath = mf->GetSafeDefinition("EXECUTABLE_OUTPUT_PATH");
  437. std::string relapath;
  438. if (!outputPath.empty()) {
  439. relapath = cmSystemTools::RelativePath(this->WorkspacePath.c_str(),
  440. outputPath.c_str());
  441. xml.Attribute("OutputFile", relapath + "/$(ProjectName)");
  442. } else {
  443. xml.Attribute("OutputFile", "$(IntermediateDirectory)/$(ProjectName)");
  444. }
  445. xml.Attribute("IntermediateDirectory", "./");
  446. xml.Attribute("Command", "./$(ProjectName)");
  447. xml.Attribute("CommandArguments", "");
  448. if (!outputPath.empty()) {
  449. xml.Attribute("WorkingDirectory", relapath);
  450. } else {
  451. xml.Attribute("WorkingDirectory", "$(IntermediateDirectory)");
  452. }
  453. xml.Attribute("PauseExecWhenProcTerminates", "yes");
  454. xml.EndElement(); // General
  455. xml.StartElement("Debugger");
  456. xml.Attribute("IsRemote", "no");
  457. xml.Attribute("RemoteHostName", "");
  458. xml.Attribute("RemoteHostPort", "");
  459. xml.Attribute("DebuggerPath", "");
  460. xml.Element("PostConnectCommands");
  461. xml.Element("StartupCommands");
  462. xml.EndElement(); // Debugger
  463. xml.Element("PreBuild");
  464. xml.Element("PostBuild");
  465. xml.StartElement("CustomBuild");
  466. xml.Attribute("Enabled", "yes");
  467. xml.Element("RebuildCommand", GetRebuildCommand(mf, targetName));
  468. xml.Element("CleanCommand", GetCleanCommand(mf, targetName));
  469. xml.Element("BuildCommand", GetBuildCommand(mf, targetName));
  470. xml.Element("SingleFileCommand", GetSingleFileBuildCommand(mf));
  471. xml.Element("PreprocessFileCommand");
  472. xml.Element("WorkingDirectory", "$(WorkspacePath)");
  473. xml.EndElement(); // CustomBuild
  474. xml.StartElement("AdditionalRules");
  475. xml.Element("CustomPostBuild");
  476. xml.Element("CustomPreBuild");
  477. xml.EndElement(); // AdditionalRules
  478. xml.EndElement(); // Configuration
  479. xml.StartElement("GlobalSettings");
  480. xml.StartElement("Compiler");
  481. xml.Attribute("Options", "");
  482. xml.StartElement("IncludePath");
  483. xml.Attribute("Value", ".");
  484. xml.EndElement(); // IncludePath
  485. xml.EndElement(); // Compiler
  486. xml.StartElement("Linker");
  487. xml.Attribute("Options", "");
  488. xml.StartElement("LibraryPath");
  489. xml.Attribute("Value", ".");
  490. xml.EndElement(); // LibraryPath
  491. xml.EndElement(); // Linker
  492. xml.StartElement("ResourceCompiler");
  493. xml.Attribute("Options", "");
  494. xml.EndElement(); // ResourceCompiler
  495. xml.EndElement(); // GlobalSettings
  496. xml.EndElement(); // Settings
  497. }
  498. void cmExtraCodeLiteGenerator::CreateNewProjectFile(
  499. const cmGeneratorTarget* gt, const std::string& filename)
  500. {
  501. const cmMakefile* mf = gt->Makefile;
  502. cmGeneratedFileStream fout(filename.c_str());
  503. if (!fout) {
  504. return;
  505. }
  506. cmXMLWriter xml(fout);
  507. ////////////////////////////////////
  508. xml.StartDocument("utf-8");
  509. xml.StartElement("CodeLite_Project");
  510. std::string targetName = gt->GetName();
  511. std::string visualname = targetName;
  512. switch (gt->GetType()) {
  513. case cmStateEnums::STATIC_LIBRARY:
  514. case cmStateEnums::SHARED_LIBRARY:
  515. case cmStateEnums::MODULE_LIBRARY:
  516. visualname = "lib" + targetName;
  517. default: // intended fallthrough
  518. break;
  519. }
  520. xml.Attribute("Name", visualname);
  521. xml.Attribute("InternalType", "");
  522. // Collect all used source files in the project
  523. // Sort them into two containers, one for C/C++ implementation files
  524. // which may have an acompanying header, one for all other files
  525. std::string projectType;
  526. std::map<std::string, cmSourceFile*> cFiles;
  527. std::set<std::string> otherFiles;
  528. projectType = CollectSourceFiles(mf, gt, cFiles, otherFiles);
  529. // Get the project path ( we need it later to convert files to
  530. // their relative path)
  531. std::string projectPath = cmSystemTools::GetFilenamePath(filename);
  532. CreateProjectSourceEntries(cFiles, otherFiles, &xml, projectPath, mf,
  533. projectType, targetName);
  534. xml.EndElement(); // CodeLite_Project
  535. }
  536. std::string cmExtraCodeLiteGenerator::GetCodeLiteCompilerName(
  537. const cmMakefile* mf) const
  538. {
  539. // figure out which language to use
  540. // for now care only for C and C++
  541. std::string compilerIdVar = "CMAKE_CXX_COMPILER_ID";
  542. if (!this->GlobalGenerator->GetLanguageEnabled("CXX")) {
  543. compilerIdVar = "CMAKE_C_COMPILER_ID";
  544. }
  545. std::string compilerId = mf->GetSafeDefinition(compilerIdVar);
  546. std::string compiler = "gnu g++"; // default to g++
  547. // Since we need the compiler for parsing purposes only
  548. // it does not matter if we use clang or clang++, same as
  549. // "gnu gcc" vs "gnu g++"
  550. if (compilerId == "MSVC") {
  551. compiler = "VC++";
  552. } else if (compilerId == "Clang") {
  553. compiler = "clang++";
  554. } else if (compilerId == "GNU") {
  555. compiler = "gnu g++";
  556. }
  557. return compiler;
  558. }
  559. std::string cmExtraCodeLiteGenerator::GetConfigurationName(
  560. const cmMakefile* mf) const
  561. {
  562. std::string confName = mf->GetSafeDefinition("CMAKE_BUILD_TYPE");
  563. // Trim the configuration name from whitespaces (left and right)
  564. confName.erase(0, confName.find_first_not_of(" \t\r\v\n"));
  565. confName.erase(confName.find_last_not_of(" \t\r\v\n") + 1);
  566. if (confName.empty()) {
  567. confName = "NoConfig";
  568. }
  569. return confName;
  570. }
  571. std::string cmExtraCodeLiteGenerator::GetBuildCommand(
  572. const cmMakefile* mf, const std::string& targetName) const
  573. {
  574. std::string generator = mf->GetSafeDefinition("CMAKE_GENERATOR");
  575. std::string make = mf->GetRequiredDefinition("CMAKE_MAKE_PROGRAM");
  576. std::string buildCommand = make; // Default
  577. std::ostringstream ss;
  578. if (generator == "NMake Makefiles" || generator == "Ninja") {
  579. ss << make;
  580. } else if (generator == "MinGW Makefiles" || generator == "Unix Makefiles") {
  581. ss << make << " -j " << this->CpuCount;
  582. }
  583. if (!targetName.empty()) {
  584. ss << " " << targetName;
  585. }
  586. buildCommand = ss.str();
  587. return buildCommand;
  588. }
  589. std::string cmExtraCodeLiteGenerator::GetCleanCommand(
  590. const cmMakefile* mf, const std::string& targetName) const
  591. {
  592. std::string generator = mf->GetSafeDefinition("CMAKE_GENERATOR");
  593. std::ostringstream ss;
  594. std::string buildcommand = GetBuildCommand(mf, "");
  595. if (!targetName.empty() && generator == "Ninja") {
  596. ss << buildcommand << " -t clean " << targetName;
  597. } else {
  598. ss << buildcommand << " clean";
  599. }
  600. return ss.str();
  601. }
  602. std::string cmExtraCodeLiteGenerator::GetRebuildCommand(
  603. const cmMakefile* mf, const std::string& targetName) const
  604. {
  605. return GetCleanCommand(mf, targetName) + " && " +
  606. GetBuildCommand(mf, targetName);
  607. }
  608. std::string cmExtraCodeLiteGenerator::GetSingleFileBuildCommand(
  609. const cmMakefile* mf) const
  610. {
  611. std::string buildCommand;
  612. std::string make = mf->GetRequiredDefinition("CMAKE_MAKE_PROGRAM");
  613. std::string generator = mf->GetSafeDefinition("CMAKE_GENERATOR");
  614. if (generator == "Unix Makefiles" || generator == "MinGW Makefiles") {
  615. std::ostringstream ss;
  616. ss << make << " -f$(ProjectPath)/Makefile $(CurrentFileName).cpp.o";
  617. buildCommand = ss.str();
  618. }
  619. return buildCommand;
  620. }