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