cmExtraCodeLiteGenerator.cxx 23 KB

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