cmExtraCodeLiteGenerator.cxx 22 KB

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