cmExtraCodeLiteGenerator.cxx 21.7 KB
Newer Older
1
2
/* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
   file Copyright.txt or https://cmake.org/licensing for details.  */
3
#include "cmExtraCodeLiteGenerator.h"
Brad King's avatar
Brad King committed
4

5
#include "cmGeneratedFileStream.h"
6
7
8
#include "cmGeneratorTarget.h"
#include "cmGlobalGenerator.h"
#include "cmLocalGenerator.h"
9
10
#include "cmMakefile.h"
#include "cmSourceFile.h"
11
#include "cmStateTypes.h"
12
#include "cmSystemTools.h"
13
#include "cmXMLWriter.h"
14
#include "cmake.h"
15

16
#include "cmsys/SystemInformation.hxx"
17
18
19
20
21
#include <map>
#include <set>
#include <sstream>
#include <string.h>
#include <utility>
22
23

cmExtraCodeLiteGenerator::cmExtraCodeLiteGenerator()
24
  : ConfigName("NoConfig")
25
{
26
27
28
29
30
31
32
33
34
35
}

cmExternalMakefileProjectGeneratorFactory*
cmExtraCodeLiteGenerator::GetFactory()
{
  static cmExternalMakefileProjectGeneratorSimpleFactory<
    cmExtraCodeLiteGenerator>
    factory("CodeLite", "Generates CodeLite project files.");

  if (factory.GetSupportedGlobalGenerators().empty()) {
36
#if defined(_WIN32)
37
38
    factory.AddSupportedGlobalGenerator("MinGW Makefiles");
    factory.AddSupportedGlobalGenerator("NMake Makefiles");
39
#endif
40
41
42
43
44
    factory.AddSupportedGlobalGenerator("Ninja");
    factory.AddSupportedGlobalGenerator("Unix Makefiles");
  }

  return &factory;
45
46
47
48
49
50
51
52
53
54
}

void cmExtraCodeLiteGenerator::Generate()
{
  // Hold root tree information for creating the workspace
  std::string workspaceProjectName;
  std::string workspaceOutputDir;
  std::string workspaceFileName;
  std::string workspaceSourcePath;

55
  const std::map<std::string, std::vector<cmLocalGenerator*>>& projectMap =
56
    this->GlobalGenerator->GetProjectMap();
57
58
59

  // loop projects and locate the root project.
  // and extract the information for creating the worspace
60
  // root makefile
61
  for (auto const& it : projectMap) {
62
63
    cmLocalGenerator* lg = it.second[0];
    const cmMakefile* mf = lg->GetMakefile();
64
    this->ConfigName = GetConfigurationName(mf);
65

66
67
68
69
    if (lg->GetCurrentBinaryDirectory() == lg->GetBinaryDirectory()) {
      workspaceOutputDir = lg->GetCurrentBinaryDirectory();
      workspaceProjectName = lg->GetProjectName();
      workspaceSourcePath = lg->GetSourceDirectory();
70
71
      workspaceFileName = workspaceOutputDir + "/";
      workspaceFileName += workspaceProjectName + ".workspace";
72
      this->WorkspacePath = lg->GetCurrentBinaryDirectory();
73
      break;
74
    }
75
  }
76

77
  cmGeneratedFileStream fout(workspaceFileName);
78
79
80
81
82
83
  cmXMLWriter xml(fout);

  xml.StartDocument("utf-8");
  xml.StartElement("CodeLite_Workspace");
  xml.Attribute("Name", workspaceProjectName);

84
  bool const targetsAreProjects =
85
    this->GlobalGenerator->GlobalSettingIsOn("CMAKE_CODELITE_USE_TARGETS");
86

87
88
89
90
91
  std::vector<std::string> ProjectNames;
  if (targetsAreProjects) {
    ProjectNames = CreateProjectsByTarget(&xml);
  } else {
    ProjectNames = CreateProjectsByProjectMaps(&xml);
92
  }
93
94
95
96
97
98

  xml.StartElement("BuildMatrix");
  xml.StartElement("WorkspaceConfiguration");
  xml.Attribute("Name", this->ConfigName);
  xml.Attribute("Selected", "yes");

99
  for (std::string const& it : ProjectNames) {
100
    xml.StartElement("Project");
101
    xml.Attribute("Name", it);
102
103
    xml.Attribute("ConfigName", this->ConfigName);
    xml.EndElement();
104
  }
105

106
107
108
  xml.EndElement(); // WorkspaceConfiguration
  xml.EndElement(); // BuildMatrix
  xml.EndElement(); // CodeLite_Workspace
109
110
}

111
112
113
114
115
116
117
118
// Create projects where targets are the projects
std::vector<std::string> cmExtraCodeLiteGenerator::CreateProjectsByTarget(
  cmXMLWriter* xml)
{
  std::vector<std::string> retval;
  // for each target in the workspace create a codelite project
  const std::vector<cmLocalGenerator*>& lgs =
    this->GlobalGenerator->GetLocalGenerators();
119
120
121
  for (cmLocalGenerator* lg : lgs) {
    for (cmGeneratorTarget* lt : lg->GetGeneratorTargets()) {
      cmStateEnums::TargetType type = lt->GetType();
122
      std::string const& outputDir = lg->GetCurrentBinaryDirectory();
123
      std::string targetName = lt->GetName();
124
125
      std::string filename = outputDir + "/" + targetName + ".project";
      retval.push_back(targetName);
126
      // Make the project file relative to the workspace
127
128
      std::string relafilename =
        cmSystemTools::RelativePath(this->WorkspacePath, filename);
129
      std::string visualname = targetName;
130
      switch (type) {
131
132
133
        case cmStateEnums::SHARED_LIBRARY:
        case cmStateEnums::STATIC_LIBRARY:
        case cmStateEnums::MODULE_LIBRARY:
134
          visualname = "lib" + visualname;
135
          CM_FALLTHROUGH;
136
        case cmStateEnums::EXECUTABLE:
137
138
139
140
141
142
          xml->StartElement("Project");
          xml->Attribute("Name", visualname);
          xml->Attribute("Path", relafilename);
          xml->Attribute("Active", "No");
          xml->EndElement();

143
          CreateNewProjectFile(lt, filename);
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
          break;
        default:
          break;
      }
    }
  }
  return retval;
}

// The "older way of doing it.
std::vector<std::string> cmExtraCodeLiteGenerator::CreateProjectsByProjectMaps(
  cmXMLWriter* xml)
{
  std::vector<std::string> retval;
  // for each sub project in the workspace create a codelite project
159
  for (auto const& it : this->GlobalGenerator->GetProjectMap()) {
160

161
    std::string const& outputDir = it.second[0]->GetCurrentBinaryDirectory();
162
    std::string projectName = it.second[0]->GetProjectName();
163
164
165
166
    retval.push_back(projectName);
    std::string filename = outputDir + "/" + projectName + ".project";

    // Make the project file relative to the workspace
167
    filename = cmSystemTools::RelativePath(this->WorkspacePath, filename);
168
169

    // create a project file
170
    this->CreateProjectFile(it.second);
171
172
173
174
175
176
177
178
179
    xml->StartElement("Project");
    xml->Attribute("Name", projectName);
    xml->Attribute("Path", filename);
    xml->Attribute("Active", "No");
    xml->EndElement();
  }
  return retval;
}

180
181
182
183
/* create the project file */
void cmExtraCodeLiteGenerator::CreateProjectFile(
  const std::vector<cmLocalGenerator*>& lgs)
{
184
  std::string const& outputDir = lgs[0]->GetCurrentBinaryDirectory();
185
  std::string projectName = lgs[0]->GetProjectName();
186
  std::string filename = outputDir + "/";
187
188
189
190
191

  filename += projectName + ".project";
  this->CreateNewProjectFile(lgs, filename);
}

192
193
194
195
196
197
198
std::string cmExtraCodeLiteGenerator::CollectSourceFiles(
  const cmMakefile* makefile, const cmGeneratorTarget* gt,
  std::map<std::string, cmSourceFile*>& cFiles,
  std::set<std::string>& otherFiles)
{
  std::string projectType;
  switch (gt->GetType()) {
199
    case cmStateEnums::EXECUTABLE: {
200
201
      projectType = "Executable";
    } break;
202
    case cmStateEnums::STATIC_LIBRARY: {
203
204
      projectType = "Static Library";
    } break;
205
    case cmStateEnums::SHARED_LIBRARY: {
206
207
      projectType = "Dynamic Library";
    } break;
208
    case cmStateEnums::MODULE_LIBRARY: {
209
210
211
212
213
214
215
      projectType = "Dynamic Library";
    } break;
    default: // intended fallthrough
      break;
  }

  switch (gt->GetType()) {
216
217
218
219
    case cmStateEnums::EXECUTABLE:
    case cmStateEnums::STATIC_LIBRARY:
    case cmStateEnums::SHARED_LIBRARY:
    case cmStateEnums::MODULE_LIBRARY: {
220
221
222
      std::vector<cmSourceFile*> sources;
      gt->GetSourceFiles(sources,
                         makefile->GetSafeDefinition("CMAKE_BUILD_TYPE"));
223
      for (cmSourceFile* s : sources) {
224
        // check whether it is a source or a include file
225
        // then put it accordingly into one of the two containers
226
        switch (cmSystemTools::GetFileFormat(s->GetExtension())) {
227
228
229
230
231
232
233
234
235
          case cmSystemTools::C_FILE_FORMAT:
          case cmSystemTools::CXX_FILE_FORMAT:
          case cmSystemTools::CUDA_FILE_FORMAT:
          case cmSystemTools::FORTRAN_FILE_FORMAT: {
            cFiles[s->GetFullPath()] = s;
          } break;
          default: {
            otherFiles.insert(s->GetFullPath());
          }
236
237
238
239
240
241
242
243
244
        }
      }
    }
    default: // intended fallthrough
      break;
  }
  return projectType;
}

245
246
void cmExtraCodeLiteGenerator::CreateNewProjectFile(
  const std::vector<cmLocalGenerator*>& lgs, const std::string& filename)
247
{
248
  const cmMakefile* mf = lgs[0]->GetMakefile();
249
  cmGeneratedFileStream fout(filename);
250
  if (!fout) {
251
    return;
252
  }
253
  cmXMLWriter xml(fout);
254
255

  ////////////////////////////////////
256
257
258
259
  xml.StartDocument("utf-8");
  xml.StartElement("CodeLite_Project");
  xml.Attribute("Name", lgs[0]->GetProjectName());
  xml.Attribute("InternalType", "");
260

261
262
  std::string projectType;

263
264
  // Collect all used source files in the project
  // Sort them into two containers, one for C/C++ implementation files
luz.paz's avatar
luz.paz committed
265
  // which may have an accompanying header, one for all other files
266
267
  std::map<std::string, cmSourceFile*> cFiles;
  std::set<std::string> otherFiles;
268

269
270
271
272
273
  for (cmLocalGenerator* lg : lgs) {
    cmMakefile* makefile = lg->GetMakefile();
    const std::vector<cmGeneratorTarget*>& targets = lg->GetGeneratorTargets();
    for (cmGeneratorTarget* target : targets) {
      projectType = CollectSourceFiles(makefile, target, cFiles, otherFiles);
274
275
    }
  }
276

277
278
279
  // Get the project path ( we need it later to convert files to
  // their relative path)
  std::string projectPath = cmSystemTools::GetFilenamePath(filename);
280

281
  CreateProjectSourceEntries(cFiles, otherFiles, &xml, projectPath, mf,
282
                             projectType, "");
283

284
285
286
287
288
289
290
291
292
293
  xml.EndElement(); // CodeLite_Project
}

void cmExtraCodeLiteGenerator::FindMatchingHeaderfiles(
  std::map<std::string, cmSourceFile*>& cFiles,
  std::set<std::string>& otherFiles)
{

  const std::vector<std::string>& headerExts =
    this->GlobalGenerator->GetCMakeInstance()->GetHeaderExtensions();
294
295
296
297
298

  // The following loop tries to add header files matching to implementation
  // files to the project. It does that by iterating over all source files,
  // replacing the file name extension with ".h" and checks whether such a
  // file exists. If it does, it is inserted into the map of files.
299
  // A very similar version of that code exists also in the CodeBlocks
300
  // project generator.
301
302
  for (auto const& sit : cFiles) {
    std::string headerBasename = cmSystemTools::GetFilenamePath(sit.first);
303
    headerBasename += "/";
304
    headerBasename += cmSystemTools::GetFilenameWithoutExtension(sit.first);
305
306

    // check if there's a matching header around
307
    for (std::string const& ext : headerExts) {
308
      std::string hname = headerBasename;
309
      hname += ".";
310
      hname += ext;
311
      // if it's already in the set, don't check if it exists on disk
312
313
      std::set<std::string>::const_iterator headerIt = otherFiles.find(hname);
      if (headerIt != otherFiles.end()) {
314
        break;
315
      }
316

317
      if (cmSystemTools::FileExists(hname)) {
318
319
320
321
        otherFiles.insert(hname);
        break;
      }
    }
322
  }
323
}
324

325
326
327
328
329
330
331
332
void cmExtraCodeLiteGenerator::CreateFoldersAndFiles(
  std::set<std::string>& cFiles, cmXMLWriter& xml,
  const std::string& projectPath)
{
  std::vector<std::string> tmp_path;
  std::vector<std::string> components;
  size_t numOfEndEl = 0;

333
  for (std::string const& cFile : cFiles) {
334
    std::string frelapath = cmSystemTools::RelativePath(projectPath, cFile);
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
    cmsys::SystemTools::SplitPath(frelapath, components, false);
    components.pop_back(); // erase last member -> it is file, not folder
    components.erase(components.begin()); // erase "root"

    size_t sizeOfSkip = 0;

    for (size_t i = 0; i < components.size(); ++i) {
      // skip relative path
      if (components[i] == ".." || components[i] == ".") {
        sizeOfSkip++;
        continue;
      }

      // same folder
      if (tmp_path.size() > i - sizeOfSkip &&
          tmp_path[i - sizeOfSkip] == components[i]) {
        continue;
      }

      // delete "old" subfolders
      if (tmp_path.size() > i - sizeOfSkip) {
        numOfEndEl = tmp_path.size() - i + sizeOfSkip;
        tmp_path.erase(tmp_path.end() - numOfEndEl, tmp_path.end());
        for (; numOfEndEl--;) {
          xml.EndElement();
        }
      }

      // add folder
      xml.StartElement("VirtualDirectory");
      xml.Attribute("Name", components[i]);
      tmp_path.push_back(components[i]);
    }

    // delete "old" subfolders
    numOfEndEl = tmp_path.size() - components.size() + sizeOfSkip;
    if (numOfEndEl) {
      tmp_path.erase(tmp_path.end() - numOfEndEl, tmp_path.end());
      for (; numOfEndEl--;) {
        xml.EndElement();
      }
    }

    // add file
    xml.StartElement("File");
    xml.Attribute("Name", frelapath);
    xml.EndElement();
  }

  // end of folders
  numOfEndEl = tmp_path.size();
  for (; numOfEndEl--;) {
    xml.EndElement();
  }
}

void cmExtraCodeLiteGenerator::CreateFoldersAndFiles(
  std::map<std::string, cmSourceFile*>& cFiles, cmXMLWriter& xml,
  const std::string& projectPath)
{
  std::set<std::string> s;
396
397
  for (auto const& it : cFiles) {
    s.insert(it.first);
398
399
400
401
  }
  this->CreateFoldersAndFiles(s, xml, projectPath);
}

402
403
404
405
void cmExtraCodeLiteGenerator::CreateProjectSourceEntries(
  std::map<std::string, cmSourceFile*>& cFiles,
  std::set<std::string>& otherFiles, cmXMLWriter* _xml,
  const std::string& projectPath, const cmMakefile* mf,
406
  const std::string& projectType, const std::string& targetName)
407
408
409
{
  cmXMLWriter& xml(*_xml);
  FindMatchingHeaderfiles(cFiles, otherFiles);
410
411
412
  // Create 2 virtual folders: src and include
  // and place all the implementation files into the src
  // folder, the rest goes to the include folder
413
414
  xml.StartElement("VirtualDirectory");
  xml.Attribute("Name", "src");
415
416
417

  // insert all source files in the codelite project
  // first the C/C++ implementation files, then all others
418
  this->CreateFoldersAndFiles(cFiles, xml, projectPath);
419
  xml.EndElement(); // VirtualDirectory
420

421
422
  xml.StartElement("VirtualDirectory");
  xml.Attribute("Name", "include");
423
  this->CreateFoldersAndFiles(otherFiles, xml, projectPath);
424
  xml.EndElement(); // VirtualDirectory
425
426
427
428
429
430

  // Get the number of CPUs. We use this information for the make -jN
  // command
  cmsys::SystemInformation info;
  info.RunCPUCheck();

431
432
  this->CpuCount =
    info.GetNumberOfLogicalCPU() * info.GetNumberOfPhysicalCPU();
433
434
435

  std::string codeliteCompilerName = this->GetCodeLiteCompilerName(mf);

436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
  xml.StartElement("Settings");
  xml.Attribute("Type", projectType);

  xml.StartElement("Configuration");
  xml.Attribute("Name", this->ConfigName);
  xml.Attribute("CompilerType", this->GetCodeLiteCompilerName(mf));
  xml.Attribute("DebuggerType", "GNU gdb debugger");
  xml.Attribute("Type", projectType);
  xml.Attribute("BuildCmpWithGlobalSettings", "append");
  xml.Attribute("BuildLnkWithGlobalSettings", "append");
  xml.Attribute("BuildResWithGlobalSettings", "append");

  xml.StartElement("Compiler");
  xml.Attribute("Options", "-g");
  xml.Attribute("Required", "yes");
  xml.Attribute("PreCompiledHeader", "");
  xml.StartElement("IncludePath");
  xml.Attribute("Value", ".");
  xml.EndElement(); // IncludePath
  xml.EndElement(); // Compiler

  xml.StartElement("Linker");
  xml.Attribute("Options", "");
  xml.Attribute("Required", "yes");
  xml.EndElement(); // Linker

  xml.StartElement("ResourceCompiler");
  xml.Attribute("Options", "");
  xml.Attribute("Required", "no");
  xml.EndElement(); // ResourceCompiler

  xml.StartElement("General");
468
469
470
471
472
  std::string outputPath =
    mf->GetSafeDefinition("CMAKE_RUNTIME_OUTPUT_DIRECTORY");
  if (outputPath.empty()) {
    outputPath = mf->GetSafeDefinition("EXECUTABLE_OUTPUT_PATH");
  }
473
  std::string relapath;
474
  if (!outputPath.empty()) {
475
    relapath = cmSystemTools::RelativePath(projectPath, outputPath);
476
    xml.Attribute("OutputFile", relapath + "/$(ProjectName)");
477
  } else {
478
    xml.Attribute("OutputFile", "$(IntermediateDirectory)/$(ProjectName)");
479
  }
480
481
482
  xml.Attribute("IntermediateDirectory", "./");
  xml.Attribute("Command", "./$(ProjectName)");
  xml.Attribute("CommandArguments", "");
483
  if (!outputPath.empty()) {
484
    xml.Attribute("WorkingDirectory", relapath);
485
  } else {
486
    xml.Attribute("WorkingDirectory", "$(IntermediateDirectory)");
487
  }
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
  xml.Attribute("PauseExecWhenProcTerminates", "yes");
  xml.EndElement(); // General

  xml.StartElement("Debugger");
  xml.Attribute("IsRemote", "no");
  xml.Attribute("RemoteHostName", "");
  xml.Attribute("RemoteHostPort", "");
  xml.Attribute("DebuggerPath", "");
  xml.Element("PostConnectCommands");
  xml.Element("StartupCommands");
  xml.EndElement(); // Debugger

  xml.Element("PreBuild");
  xml.Element("PostBuild");

  xml.StartElement("CustomBuild");
  xml.Attribute("Enabled", "yes");
505
506
507
  xml.Element("RebuildCommand", GetRebuildCommand(mf, targetName));
  xml.Element("CleanCommand", GetCleanCommand(mf, targetName));
  xml.Element("BuildCommand", GetBuildCommand(mf, targetName));
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
  xml.Element("SingleFileCommand", GetSingleFileBuildCommand(mf));
  xml.Element("PreprocessFileCommand");
  xml.Element("WorkingDirectory", "$(WorkspacePath)");
  xml.EndElement(); // CustomBuild

  xml.StartElement("AdditionalRules");
  xml.Element("CustomPostBuild");
  xml.Element("CustomPreBuild");
  xml.EndElement(); // AdditionalRules

  xml.EndElement(); // Configuration
  xml.StartElement("GlobalSettings");

  xml.StartElement("Compiler");
  xml.Attribute("Options", "");
  xml.StartElement("IncludePath");
  xml.Attribute("Value", ".");
  xml.EndElement(); // IncludePath
  xml.EndElement(); // Compiler

  xml.StartElement("Linker");
  xml.Attribute("Options", "");
  xml.StartElement("LibraryPath");
  xml.Attribute("Value", ".");
  xml.EndElement(); // LibraryPath
  xml.EndElement(); // Linker

  xml.StartElement("ResourceCompiler");
  xml.Attribute("Options", "");
  xml.EndElement(); // ResourceCompiler

  xml.EndElement(); // GlobalSettings
  xml.EndElement(); // Settings
541
542
543
544
545
546
}

void cmExtraCodeLiteGenerator::CreateNewProjectFile(
  const cmGeneratorTarget* gt, const std::string& filename)
{
  const cmMakefile* mf = gt->Makefile;
547
  cmGeneratedFileStream fout(filename);
548
549
550
551
552
553
554
555
  if (!fout) {
    return;
  }
  cmXMLWriter xml(fout);

  ////////////////////////////////////
  xml.StartDocument("utf-8");
  xml.StartElement("CodeLite_Project");
556
557
  std::string targetName = gt->GetName();
  std::string visualname = targetName;
558
  switch (gt->GetType()) {
559
560
561
    case cmStateEnums::STATIC_LIBRARY:
    case cmStateEnums::SHARED_LIBRARY:
    case cmStateEnums::MODULE_LIBRARY:
562
      visualname = "lib" + targetName;
563
564
565
566
567
568
569
570
    default: // intended fallthrough
      break;
  }
  xml.Attribute("Name", visualname);
  xml.Attribute("InternalType", "");

  // Collect all used source files in the project
  // Sort them into two containers, one for C/C++ implementation files
luz.paz's avatar
luz.paz committed
571
  // which may have an accompanying header, one for all other files
572
573
574
575
576
577
578
579
580
581
582
583
  std::string projectType;

  std::map<std::string, cmSourceFile*> cFiles;
  std::set<std::string> otherFiles;

  projectType = CollectSourceFiles(mf, gt, cFiles, otherFiles);

  // Get the project path ( we need it later to convert files to
  // their relative path)
  std::string projectPath = cmSystemTools::GetFilenamePath(filename);

  CreateProjectSourceEntries(cFiles, otherFiles, &xml, projectPath, mf,
584
                             projectType, targetName);
585

586
  xml.EndElement(); // CodeLite_Project
587
588
}

589
590
std::string cmExtraCodeLiteGenerator::GetCodeLiteCompilerName(
  const cmMakefile* mf) const
591
592
593
594
{
  // figure out which language to use
  // for now care only for C and C++
  std::string compilerIdVar = "CMAKE_CXX_COMPILER_ID";
Daniel Pfeifer's avatar
Daniel Pfeifer committed
595
  if (!this->GlobalGenerator->GetLanguageEnabled("CXX")) {
596
    compilerIdVar = "CMAKE_C_COMPILER_ID";
597
  }
598

599
  std::string const& compilerId = mf->GetSafeDefinition(compilerIdVar);
600
601
602
603
604
  std::string compiler = "gnu g++"; // default to g++

  // Since we need the compiler for parsing purposes only
  // it does not matter if we use clang or clang++, same as
  // "gnu gcc" vs "gnu g++"
605
  if (compilerId == "MSVC") {
606
    compiler = "VC++";
607
  } else if (compilerId == "Clang") {
608
    compiler = "clang++";
609
  } else if (compilerId == "GNU") {
610
    compiler = "gnu g++";
611
  }
612
613
614
  return compiler;
}

615
616
std::string cmExtraCodeLiteGenerator::GetConfigurationName(
  const cmMakefile* mf) const
617
618
619
620
{
  std::string confName = mf->GetSafeDefinition("CMAKE_BUILD_TYPE");
  // Trim the configuration name from whitespaces (left and right)
  confName.erase(0, confName.find_first_not_of(" \t\r\v\n"));
621
622
  confName.erase(confName.find_last_not_of(" \t\r\v\n") + 1);
  if (confName.empty()) {
623
    confName = "NoConfig";
624
  }
625
626
627
  return confName;
}

628
std::string cmExtraCodeLiteGenerator::GetBuildCommand(
629
  const cmMakefile* mf, const std::string& targetName) const
630
631
632
633
{
  std::string generator = mf->GetSafeDefinition("CMAKE_GENERATOR");
  std::string make = mf->GetRequiredDefinition("CMAKE_MAKE_PROGRAM");
  std::string buildCommand = make; // Default
634
  std::ostringstream ss;
635
  if (generator == "NMake Makefiles" || generator == "Ninja") {
636
    ss << make;
637
  } else if (generator == "MinGW Makefiles" || generator == "Unix Makefiles") {
638
    ss << make << " -f$(ProjectPath)/Makefile -j " << this->CpuCount;
639
  }
640
641
642
643
  if (!targetName.empty()) {
    ss << " " << targetName;
  }
  buildCommand = ss.str();
644
  return buildCommand;
645
646
}

647
std::string cmExtraCodeLiteGenerator::GetCleanCommand(
648
  const cmMakefile* mf, const std::string& targetName) const
649
{
650
651
652
653
654
655
656
657
658
  std::string generator = mf->GetSafeDefinition("CMAKE_GENERATOR");
  std::ostringstream ss;
  std::string buildcommand = GetBuildCommand(mf, "");
  if (!targetName.empty() && generator == "Ninja") {
    ss << buildcommand << " -t clean " << targetName;
  } else {
    ss << buildcommand << " clean";
  }
  return ss.str();
659
660
}

661
std::string cmExtraCodeLiteGenerator::GetRebuildCommand(
662
  const cmMakefile* mf, const std::string& targetName) const
663
{
664
665
  return GetCleanCommand(mf, targetName) + " && " +
    GetBuildCommand(mf, targetName);
666
667
}

668
669
std::string cmExtraCodeLiteGenerator::GetSingleFileBuildCommand(
  const cmMakefile* mf) const
670
671
672
673
{
  std::string buildCommand;
  std::string make = mf->GetRequiredDefinition("CMAKE_MAKE_PROGRAM");
  std::string generator = mf->GetSafeDefinition("CMAKE_GENERATOR");
674
  if (generator == "Unix Makefiles" || generator == "MinGW Makefiles") {
675
    std::ostringstream ss;
676
677
678
679
680
#if defined(_WIN32)
    ss << make << " -f$(ProjectPath)/Makefile -B $(CurrentFileFullName).obj";
#else
    ss << make << " -f$(ProjectPath)/Makefile -B $(CurrentFileFullName).o";
#endif
681
    buildCommand = ss.str();
682
  }
683
684
  return buildCommand;
}