Coverage Report

Created: 2026-02-09 06:05

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/CMake/Source/cmCommonTargetGenerator.cxx
Line
Count
Source
1
/* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
2
   file LICENSE.rst or https://cmake.org/licensing for details.  */
3
#include "cmCommonTargetGenerator.h"
4
5
#include <algorithm>
6
#include <sstream>
7
#include <utility>
8
9
#include <cm/string_view>
10
#include <cmext/string_view>
11
12
#include "cmComputeLinkInformation.h"
13
#include "cmGenExContext.h"
14
#include "cmGeneratorExpression.h"
15
#include "cmGeneratorExpressionDAGChecker.h"
16
#include "cmGeneratorTarget.h"
17
#include "cmGlobalCommonGenerator.h"
18
#include "cmGlobalGenerator.h"
19
#include "cmList.h"
20
#include "cmLocalCommonGenerator.h"
21
#include "cmLocalGenerator.h"
22
#include "cmMakefile.h"
23
#include "cmMessageType.h"
24
#include "cmOutputConverter.h"
25
#include "cmRange.h"
26
#include "cmSourceFile.h"
27
#include "cmState.h"
28
#include "cmStateTypes.h"
29
#include "cmStringAlgorithms.h"
30
#include "cmSystemTools.h"
31
#include "cmValue.h"
32
33
cmCommonTargetGenerator::cmCommonTargetGenerator(cmGeneratorTarget* gt)
34
0
  : GeneratorTarget(gt)
35
0
  , Makefile(gt->Makefile)
36
  , LocalCommonGenerator(
37
0
      static_cast<cmLocalCommonGenerator*>(gt->LocalGenerator))
38
0
  , GlobalCommonGenerator(static_cast<cmGlobalCommonGenerator*>(
39
0
      gt->LocalGenerator->GetGlobalGenerator()))
40
0
  , ConfigNames(this->LocalCommonGenerator->GetConfigNames())
41
0
{
42
0
}
43
44
0
cmCommonTargetGenerator::~cmCommonTargetGenerator() = default;
45
46
std::vector<std::string> const& cmCommonTargetGenerator::GetConfigNames() const
47
0
{
48
0
  return this->ConfigNames;
49
0
}
50
51
cmValue cmCommonTargetGenerator::GetFeature(std::string const& feature,
52
                                            std::string const& config)
53
0
{
54
0
  return this->GeneratorTarget->GetFeature(feature, config);
55
0
}
56
57
void cmCommonTargetGenerator::AppendFortranFormatFlags(
58
  std::string& flags, cmSourceFile const& source)
59
0
{
60
0
  std::string const srcfmt = source.GetSafeProperty("Fortran_FORMAT");
61
0
  cmOutputConverter::FortranFormat format =
62
0
    cmOutputConverter::GetFortranFormat(srcfmt);
63
0
  if (format == cmOutputConverter::FortranFormatNone) {
64
0
    std::string const& tgtfmt =
65
0
      this->GeneratorTarget->GetSafeProperty("Fortran_FORMAT");
66
0
    format = cmOutputConverter::GetFortranFormat(tgtfmt);
67
0
  }
68
0
  char const* var = nullptr;
69
0
  switch (format) {
70
0
    case cmOutputConverter::FortranFormatFixed:
71
0
      var = "CMAKE_Fortran_FORMAT_FIXED_FLAG";
72
0
      break;
73
0
    case cmOutputConverter::FortranFormatFree:
74
0
      var = "CMAKE_Fortran_FORMAT_FREE_FLAG";
75
0
      break;
76
0
    default:
77
0
      break;
78
0
  }
79
0
  if (var) {
80
0
    this->LocalCommonGenerator->AppendFlags(
81
0
      flags, this->Makefile->GetSafeDefinition(var));
82
0
  }
83
0
}
84
85
void cmCommonTargetGenerator::AppendFortranPreprocessFlags(
86
  std::string& flags, cmSourceFile const& source,
87
  PreprocessFlagsRequired requires_pp)
88
0
{
89
0
  std::string const srcpp = source.GetSafeProperty("Fortran_PREPROCESS");
90
0
  cmOutputConverter::FortranPreprocess preprocess =
91
0
    cmOutputConverter::GetFortranPreprocess(srcpp);
92
0
  if (preprocess == cmOutputConverter::FortranPreprocess::Unset) {
93
0
    std::string const& tgtpp =
94
0
      this->GeneratorTarget->GetSafeProperty("Fortran_PREPROCESS");
95
0
    preprocess = cmOutputConverter::GetFortranPreprocess(tgtpp);
96
0
  }
97
0
  char const* var = nullptr;
98
0
  switch (preprocess) {
99
0
    case cmOutputConverter::FortranPreprocess::Needed:
100
0
      if (requires_pp == PreprocessFlagsRequired::YES) {
101
0
        var = "CMAKE_Fortran_COMPILE_OPTIONS_PREPROCESS_ON";
102
0
      }
103
0
      break;
104
0
    case cmOutputConverter::FortranPreprocess::NotNeeded:
105
0
      var = "CMAKE_Fortran_COMPILE_OPTIONS_PREPROCESS_OFF";
106
0
      break;
107
0
    default:
108
0
      break;
109
0
  }
110
0
  if (var) {
111
0
    this->LocalCommonGenerator->AppendCompileOptions(
112
0
      flags, this->Makefile->GetSafeDefinition(var));
113
0
  }
114
0
}
115
116
std::string cmCommonTargetGenerator::GetFlags(std::string const& l,
117
                                              std::string const& config,
118
                                              std::string const& arch)
119
0
{
120
0
  std::string const key = config + arch;
121
122
0
  auto i = this->Configs[key].FlagsByLanguage.find(l);
123
0
  if (i == this->Configs[key].FlagsByLanguage.end()) {
124
0
    std::string flags;
125
126
0
    this->LocalCommonGenerator->GetTargetCompileFlags(this->GeneratorTarget,
127
0
                                                      config, l, flags, arch);
128
129
0
    ByLanguageMap::value_type entry(l, flags);
130
0
    i = this->Configs[key].FlagsByLanguage.insert(entry).first;
131
0
  }
132
0
  return i->second;
133
0
}
134
135
std::string cmCommonTargetGenerator::GetDefines(std::string const& l,
136
                                                std::string const& config)
137
0
{
138
0
  auto i = this->Configs[config].DefinesByLanguage.find(l);
139
0
  if (i == this->Configs[config].DefinesByLanguage.end()) {
140
0
    std::set<std::string> defines;
141
0
    this->LocalCommonGenerator->GetTargetDefines(this->GeneratorTarget, config,
142
0
                                                 l, defines);
143
144
0
    std::string definesString;
145
0
    this->LocalCommonGenerator->JoinDefines(defines, definesString, l);
146
147
0
    ByLanguageMap::value_type entry(l, definesString);
148
0
    i = this->Configs[config].DefinesByLanguage.insert(entry).first;
149
0
  }
150
0
  return i->second;
151
0
}
152
153
std::string cmCommonTargetGenerator::GetIncludes(std::string const& l,
154
                                                 std::string const& config)
155
0
{
156
0
  auto i = this->Configs[config].IncludesByLanguage.find(l);
157
0
  if (i == this->Configs[config].IncludesByLanguage.end()) {
158
0
    std::string includes;
159
0
    this->AddIncludeFlags(includes, l, config);
160
0
    ByLanguageMap::value_type entry(l, includes);
161
0
    i = this->Configs[config].IncludesByLanguage.insert(entry).first;
162
0
  }
163
0
  return i->second;
164
0
}
165
166
cmCommonTargetGenerator::LinkedTargetDirs
167
cmCommonTargetGenerator::GetLinkedTargetDirectories(
168
  std::string const& lang, std::string const& config) const
169
0
{
170
0
  LinkedTargetDirs dirs;
171
0
  std::set<cmGeneratorTarget const*> forward_emitted;
172
0
  std::set<cmGeneratorTarget const*> direct_emitted;
173
0
  cmGlobalCommonGenerator* const gg = this->GlobalCommonGenerator;
174
175
0
  enum class Forwarding
176
0
  {
177
0
    Yes,
178
0
    No
179
0
  };
180
181
0
  if (cmComputeLinkInformation* cli =
182
0
        this->GeneratorTarget->GetLinkInformation(config)) {
183
0
    auto addLinkedTarget =
184
0
      [this, &lang, &config, &dirs, &direct_emitted, &forward_emitted,
185
0
       gg](cmGeneratorTarget const* linkee, Forwarding forward) {
186
0
        if (linkee &&
187
0
            !linkee->IsImported()
188
            // Skip targets that build after this one in a static lib cycle.
189
0
            && gg->TargetOrderIndexLess(linkee, this->GeneratorTarget)
190
            // We can ignore the INTERFACE_LIBRARY items because
191
            // Target->GetLinkInformation already processed their
192
            // link interface and they don't have any output themselves.
193
0
            && (linkee->GetType() != cmStateEnums::INTERFACE_LIBRARY
194
                // Synthesized targets may have relevant rules.
195
0
                || linkee->IsSynthetic()) &&
196
0
            ((lang == "CXX"_s && linkee->HaveCxx20ModuleSources()) ||
197
0
             (lang == "Fortran"_s && linkee->HaveFortranSources(config)))) {
198
0
          cmLocalGenerator* lg = linkee->GetLocalGenerator();
199
0
          std::string di = linkee->GetSupportDirectory();
200
0
          if (lg->GetGlobalGenerator()->IsMultiConfig()) {
201
0
            di = cmStrCat(di, '/', config);
202
0
          }
203
0
          if (forward == Forwarding::Yes &&
204
0
              forward_emitted.insert(linkee).second) {
205
0
            dirs.Forward.push_back(di);
206
0
          }
207
0
          if (direct_emitted.insert(linkee).second) {
208
0
            dirs.Direct.emplace_back(di);
209
0
          }
210
0
        }
211
0
      };
212
0
    for (auto const& item : cli->GetItems()) {
213
0
      if (item.Target) {
214
0
        addLinkedTarget(item.Target, Forwarding::No);
215
0
      } else if (item.ObjectSource && lang == "Fortran"_s
216
                 /* Object source files do not have a language associated with
217
                    them. */
218
0
                 /* && item.ObjectSource->GetLanguage() == "Fortran"_s*/) {
219
        // Fortran modules provided by `$<TARGET_OBJECTS>` as linked items
220
        // should be collated for use in this target.
221
0
        addLinkedTarget(this->LocalCommonGenerator->FindGeneratorTargetToUse(
222
0
                          item.ObjectSource->GetObjectLibrary()),
223
0
                        Forwarding::Yes);
224
0
      }
225
0
    }
226
0
    for (cmGeneratorTarget const* target : cli->GetExternalObjectTargets()) {
227
0
      addLinkedTarget(target, Forwarding::No);
228
0
    }
229
0
    if (lang == "Fortran"_s) {
230
      // Fortran modules provided by `$<TARGET_OBJECTS>` as sources should be
231
      // collated for use in this target.
232
0
      for (cmGeneratorTarget const* target :
233
0
           this->GeneratorTarget->GetSourceObjectLibraries(config)) {
234
0
        addLinkedTarget(target, Forwarding::Yes);
235
0
      }
236
0
    }
237
0
  }
238
0
  return dirs;
239
0
}
240
241
std::string cmCommonTargetGenerator::ComputeTargetCompilePDB(
242
  std::string const& config) const
243
0
{
244
0
  std::string compilePdbPath;
245
0
  if (this->GeneratorTarget->GetType() > cmStateEnums::OBJECT_LIBRARY) {
246
0
    return compilePdbPath;
247
0
  }
248
249
0
  compilePdbPath = this->GeneratorTarget->GetCompilePDBPath(config);
250
0
  if (compilePdbPath.empty()) {
251
    // Match VS default: `$(IntDir)vc$(PlatformToolsetVersion).pdb`.
252
    // A trailing slash tells the toolchain to add its default file name.
253
0
    compilePdbPath = this->GeneratorTarget->GetSupportDirectory();
254
0
    if (this->GlobalCommonGenerator->IsMultiConfig()) {
255
0
      compilePdbPath += "/";
256
0
      compilePdbPath += config;
257
0
    }
258
0
    compilePdbPath += "/";
259
0
    if (this->GeneratorTarget->GetType() == cmStateEnums::STATIC_LIBRARY) {
260
      // Match VS default for static libs: `$(IntDir)$(ProjectName).pdb`.
261
0
      compilePdbPath += this->GeneratorTarget->GetName();
262
0
      compilePdbPath += ".pdb";
263
0
    }
264
0
  }
265
266
0
  return compilePdbPath;
267
0
}
268
269
std::string cmCommonTargetGenerator::GetManifests(std::string const& config)
270
0
{
271
0
  std::vector<cmSourceFile const*> manifest_srcs;
272
0
  this->GeneratorTarget->GetManifests(manifest_srcs, config);
273
274
0
  std::vector<std::string> manifests;
275
0
  manifests.reserve(manifest_srcs.size());
276
277
0
  std::string lang = this->GeneratorTarget->GetLinkerLanguage(config);
278
0
  std::string manifestFlag = this->Makefile->GetDefinition(
279
0
    cmStrCat("CMAKE_", lang, "_LINKER_MANIFEST_FLAG"));
280
0
  for (cmSourceFile const* manifest_src : manifest_srcs) {
281
0
    manifests.push_back(manifestFlag +
282
0
                        this->LocalCommonGenerator->ConvertToOutputFormat(
283
0
                          this->LocalCommonGenerator->MaybeRelativeToWorkDir(
284
0
                            manifest_src->GetFullPath()),
285
0
                          cmOutputConverter::SHELL));
286
0
  }
287
288
0
  return cmJoin(manifests, " ");
289
0
}
290
291
std::string cmCommonTargetGenerator::GetAIXExports(std::string const&)
292
0
{
293
0
  std::string aixExports;
294
0
  if (this->GeneratorTarget->IsAIX()) {
295
0
    if (cmValue exportAll =
296
0
          this->GeneratorTarget->GetProperty("AIX_EXPORT_ALL_SYMBOLS")) {
297
0
      if (exportAll.IsOff()) {
298
0
        aixExports = "-n";
299
0
      }
300
0
    }
301
0
  }
302
0
  return aixExports;
303
0
}
304
305
void cmCommonTargetGenerator::AppendOSXVerFlag(std::string& flags,
306
                                               std::string const& lang,
307
                                               char const* name, bool so)
308
0
{
309
  // Lookup the flag to specify the version.
310
0
  std::string fvar = cmStrCat("CMAKE_", lang, "_OSX_", name, "_VERSION_FLAG");
311
0
  cmValue flag = this->Makefile->GetDefinition(fvar);
312
313
  // Skip if no such flag.
314
0
  if (!flag) {
315
0
    return;
316
0
  }
317
318
  // Lookup the target version information.
319
0
  int major;
320
0
  int minor;
321
0
  int patch;
322
0
  std::string prop = cmStrCat("MACHO_", name, "_VERSION");
323
0
  std::string fallback_prop = so ? "SOVERSION" : "VERSION";
324
0
  this->GeneratorTarget->GetTargetVersionFallback(prop, fallback_prop, major,
325
0
                                                  minor, patch);
326
0
  if (major > 0 || minor > 0 || patch > 0) {
327
    // Append the flag since a non-zero version is specified.
328
0
    std::ostringstream vflag;
329
0
    vflag << *flag << major << "." << minor << "." << patch;
330
0
    this->LocalCommonGenerator->AppendFlags(flags, vflag.str());
331
0
  }
332
0
}
333
334
std::string cmCommonTargetGenerator::GetCompilerLauncher(
335
  std::string const& lang, std::string const& config)
336
0
{
337
0
  std::string compilerLauncher;
338
0
  if (lang == "C" || lang == "CXX" || lang == "Fortran" || lang == "CUDA" ||
339
0
      lang == "HIP" || lang == "ISPC" || lang == "OBJC" || lang == "OBJCXX") {
340
0
    std::string const clauncher_prop = cmStrCat(lang, "_COMPILER_LAUNCHER");
341
0
    cmValue clauncher = this->GeneratorTarget->GetProperty(clauncher_prop);
342
0
    std::string const evaluatedClauncher = cmGeneratorExpression::Evaluate(
343
0
      *clauncher, this->GeneratorTarget->GetLocalGenerator(), config,
344
0
      this->GeneratorTarget, nullptr, this->GeneratorTarget, lang);
345
0
    if (!evaluatedClauncher.empty()) {
346
0
      compilerLauncher = evaluatedClauncher;
347
0
    }
348
0
  }
349
0
  return compilerLauncher;
350
0
}
351
352
std::string cmCommonTargetGenerator::GenerateCodeCheckRules(
353
  cmSourceFile const& source, std::string& compilerLauncher,
354
  std::string const& cmakeCmd, std::string const& config,
355
  std::function<std::string(std::string const&)> const& pathConverter)
356
0
{
357
0
  auto const lang = source.GetLanguage();
358
0
  std::string tidy;
359
0
  std::string iwyu;
360
0
  std::string cpplint;
361
0
  std::string cppcheck;
362
0
  std::string icstat;
363
0
  std::string pvs;
364
365
0
  auto evaluateProp = [&](std::string const& prop) -> std::string {
366
0
    auto const value = this->GeneratorTarget->GetProperty(prop);
367
0
    if (!value) {
368
0
      return std::string{};
369
0
    }
370
0
    auto evaluatedProp = cmGeneratorExpression::Evaluate(
371
0
      *value, this->GeneratorTarget->GetLocalGenerator(), config,
372
0
      this->GeneratorTarget, nullptr, this->GeneratorTarget, lang);
373
0
    return evaluatedProp;
374
0
  };
375
0
  std::string const tidy_prop = cmStrCat(lang, "_CLANG_TIDY");
376
0
  tidy = evaluateProp(tidy_prop);
377
378
0
  if (lang == "C" || lang == "CXX") {
379
0
    std::string const iwyu_prop = cmStrCat(lang, "_INCLUDE_WHAT_YOU_USE");
380
0
    iwyu = evaluateProp(iwyu_prop);
381
382
0
    std::string const cpplint_prop = cmStrCat(lang, "_CPPLINT");
383
0
    cpplint = evaluateProp(cpplint_prop);
384
385
0
    std::string const cppcheck_prop = cmStrCat(lang, "_CPPCHECK");
386
0
    cppcheck = evaluateProp(cppcheck_prop);
387
388
0
    std::string const icstat_prop = cmStrCat(lang, "_ICSTAT");
389
0
    icstat = evaluateProp(icstat_prop);
390
391
0
    std::string const pvs_prop = cmStrCat(lang, "_PVS_STUDIO");
392
0
    pvs = evaluateProp(pvs_prop);
393
0
  }
394
395
0
  if (cmNonempty(iwyu) || cmNonempty(tidy) || cmNonempty(cpplint) ||
396
0
      cmNonempty(cppcheck) || cmNonempty(icstat) || cmNonempty(pvs)) {
397
0
    std::string code_check = cmakeCmd + " -E __run_co_compile";
398
0
    if (!compilerLauncher.empty()) {
399
      // In __run_co_compile case the launcher command is supplied
400
      // via --launcher=<maybe-list> and consumed
401
0
      code_check =
402
0
        cmStrCat(std::move(code_check), " --launcher=",
403
0
                 this->GeneratorTarget->GetLocalGenerator()->EscapeForShell(
404
0
                   compilerLauncher));
405
0
      compilerLauncher.clear();
406
0
    }
407
0
    if (cmNonempty(iwyu)) {
408
0
      code_check += " --iwyu=";
409
410
      // Only add --driver-mode if it is not already specified, as adding
411
      // it unconditionally might override a user-specified driver-mode
412
0
      if (iwyu.find("--driver-mode=") == std::string::npos) {
413
0
        cmValue const p = this->Makefile->GetDefinition(
414
0
          cmStrCat("CMAKE_", lang, "_INCLUDE_WHAT_YOU_USE_DRIVER_MODE"));
415
0
        std::string driverMode;
416
417
0
        if (cmNonempty(p)) {
418
0
          driverMode = *p;
419
0
        } else {
420
0
          driverMode = lang == "C" ? "gcc" : "g++";
421
0
        }
422
423
0
        code_check +=
424
0
          this->GeneratorTarget->GetLocalGenerator()->EscapeForShell(
425
0
            cmStrCat(iwyu, ";--driver-mode=", driverMode));
426
0
      } else {
427
0
        code_check +=
428
0
          this->GeneratorTarget->GetLocalGenerator()->EscapeForShell(iwyu);
429
0
      }
430
0
    }
431
0
    if (cmNonempty(tidy)) {
432
0
      code_check += " --tidy=";
433
0
      cmValue const p = this->Makefile->GetDefinition(
434
0
        cmStrCat("CMAKE_", lang, "_CLANG_TIDY_DRIVER_MODE"));
435
0
      std::string driverMode;
436
0
      if (cmNonempty(p)) {
437
0
        driverMode = *p;
438
0
      } else {
439
0
        driverMode = lang == "C" ? "gcc" : "g++";
440
0
      }
441
442
0
      auto const generatorName = this->GeneratorTarget->GetLocalGenerator()
443
0
                                   ->GetGlobalGenerator()
444
0
                                   ->GetName();
445
0
      auto const clangTidyExportFixedDir =
446
0
        this->GeneratorTarget->GetClangTidyExportFixesDirectory(lang);
447
0
      auto fixesFile = this->GetClangTidyReplacementsFilePath(
448
0
        clangTidyExportFixedDir, source, config);
449
0
      std::string exportFixes;
450
0
      if (!clangTidyExportFixedDir.empty()) {
451
0
        this->GlobalCommonGenerator->AddClangTidyExportFixesDir(
452
0
          clangTidyExportFixedDir);
453
0
      }
454
0
      if (generatorName.find("Make") != std::string::npos) {
455
0
        if (!clangTidyExportFixedDir.empty()) {
456
0
          this->GlobalCommonGenerator->AddClangTidyExportFixesFile(fixesFile);
457
0
          cmSystemTools::MakeDirectory(
458
0
            cmSystemTools::GetFilenamePath(fixesFile));
459
0
          fixesFile = this->GeneratorTarget->GetLocalGenerator()
460
0
                        ->MaybeRelativeToCurBinDir(fixesFile);
461
0
          exportFixes = cmStrCat(";--export-fixes=", fixesFile);
462
0
        }
463
0
        code_check +=
464
0
          this->GeneratorTarget->GetLocalGenerator()->EscapeForShell(
465
0
            cmStrCat(tidy, ";--extra-arg-before=--driver-mode=", driverMode,
466
0
                     exportFixes));
467
0
      } else if (generatorName.find("Ninja") != std::string::npos ||
468
0
                 generatorName.find("FASTBuild") != std::string::npos) {
469
0
        if (!clangTidyExportFixedDir.empty()) {
470
0
          this->GlobalCommonGenerator->AddClangTidyExportFixesFile(fixesFile);
471
0
          cmSystemTools::MakeDirectory(
472
0
            cmSystemTools::GetFilenamePath(fixesFile));
473
0
          if (pathConverter) {
474
0
            fixesFile = pathConverter(fixesFile);
475
0
          }
476
0
          exportFixes = cmStrCat(";--export-fixes=", fixesFile);
477
0
        }
478
0
        code_check +=
479
0
          this->GeneratorTarget->GetLocalGenerator()->EscapeForShell(
480
0
            cmStrCat(tidy, ";--extra-arg-before=--driver-mode=", driverMode,
481
0
                     exportFixes));
482
0
      }
483
0
    }
484
0
    if (cmNonempty(pvs)) {
485
0
      cmMakefile* mf =
486
0
        this->GeneratorTarget->GetLocalGenerator()->GetMakefile();
487
0
      std::string extraPvsArgs;
488
0
      if (lang == "CXX") {
489
0
        extraPvsArgs +=
490
0
          cmStrCat(";--cxx;", mf->GetDefinition("CMAKE_CXX_COMPILER"));
491
0
      } else if (lang == "C") {
492
0
        extraPvsArgs +=
493
0
          cmStrCat(";--cc;", mf->GetDefinition("CMAKE_C_COMPILER"));
494
0
      }
495
      // cocompile args
496
0
      code_check += " --pvs-studio=";
497
0
      code_check += this->GeneratorTarget->GetLocalGenerator()->EscapeForShell(
498
0
        cmStrCat(pvs, extraPvsArgs));
499
0
      code_check += " --object=";
500
0
      code_check +=
501
0
        this->GeneratorTarget->GetLocalGenerator()->ConvertToOutputFormat(
502
0
          cmSystemTools::CollapseFullPath(
503
0
            cmStrCat(this->GeneratorTarget->GetObjectDirectory(config), '/',
504
0
                     this->GeneratorTarget->GetObjectName(&source))),
505
0
          cmOutputConverter::SHELL);
506
0
    }
507
0
    if (cmNonempty(cpplint)) {
508
0
      code_check += " --cpplint=";
509
0
      code_check +=
510
0
        this->GeneratorTarget->GetLocalGenerator()->EscapeForShell(cpplint);
511
0
    }
512
0
    if (cmNonempty(cppcheck)) {
513
0
      code_check += " --cppcheck=";
514
0
      code_check +=
515
0
        this->GeneratorTarget->GetLocalGenerator()->EscapeForShell(cppcheck);
516
0
    }
517
0
    if (cmNonempty(icstat)) {
518
0
      code_check += " --icstat=";
519
0
      std::string checksParam{};
520
0
      std::string dbParam{};
521
      // Set default values for mandatory parameters
522
0
      std::string checksFile{ "cstat_sel_checks.txt" };
523
0
      std::string dbFile{ "cstat.db" };
524
      // Populate the command line with C-STAT
525
      // mandatory parameters unless specified
526
0
      if (icstat.find("--checks=") == std::string::npos) {
527
0
        checksParam = cmStrCat(";--checks=", checksFile);
528
0
      }
529
0
      if (icstat.find("--db=") == std::string::npos) {
530
0
        dbParam = cmStrCat(";--db=", dbFile);
531
0
      }
532
0
      code_check += this->GeneratorTarget->GetLocalGenerator()->EscapeForShell(
533
0
        cmStrCat(icstat, checksParam, dbParam));
534
0
    }
535
0
    if (cmNonempty(tidy) || (cmNonempty(cpplint)) || (cmNonempty(cppcheck)) ||
536
0
        cmNonempty(pvs)) {
537
0
      code_check += " --source=";
538
0
      code_check +=
539
0
        this->GeneratorTarget->GetLocalGenerator()->ConvertToOutputFormat(
540
0
          source.GetFullPath(), cmOutputConverter::SHELL);
541
0
    }
542
0
    code_check += " -- ";
543
0
    return code_check;
544
0
  }
545
0
  return "";
546
0
}
547
548
std::string cmCommonTargetGenerator::GetLinkerLauncher(
549
  std::string const& config)
550
0
{
551
0
  std::string lang = this->GeneratorTarget->GetLinkerLanguage(config);
552
0
  std::string propName = lang + "_LINKER_LAUNCHER";
553
0
  cmValue launcherProp = this->GeneratorTarget->GetProperty(propName);
554
0
  if (cmNonempty(launcherProp)) {
555
0
    cm::GenEx::Context context(this->LocalCommonGenerator, config, lang);
556
0
    cmGeneratorExpressionDAGChecker dagChecker{ this->GeneratorTarget,
557
0
                                                propName, nullptr, nullptr,
558
0
                                                context };
559
0
    std::string evaluatedLinklauncher = cmGeneratorExpression::Evaluate(
560
0
      *launcherProp, context.LG, context.Config, this->GeneratorTarget,
561
0
      &dagChecker, this->GeneratorTarget, context.Language);
562
    // Convert ;-delimited list to single string
563
0
    cmList args{ evaluatedLinklauncher, cmList::EmptyElements::Yes };
564
0
    if (!args.empty()) {
565
0
      args[0] = this->LocalCommonGenerator->ConvertToOutputFormat(
566
0
        args[0], cmOutputConverter::SHELL);
567
0
      for (std::string& i : cmMakeRange(args.begin() + 1, args.end())) {
568
0
        i = this->LocalCommonGenerator->EscapeForShell(i);
569
0
      }
570
0
      return cmJoin(args, " ");
571
0
    }
572
0
  }
573
0
  return std::string();
574
0
}
575
576
bool cmCommonTargetGenerator::HaveRequiredLanguages(
577
  std::vector<cmSourceFile const*> const& sources,
578
  std::set<std::string>& languagesNeeded) const
579
0
{
580
0
  for (cmSourceFile const* sf : sources) {
581
0
    languagesNeeded.insert(sf->GetLanguage());
582
0
  }
583
584
0
  auto* makefile = this->Makefile;
585
0
  auto* state = makefile->GetState();
586
0
  auto unary = [&state, &makefile](std::string const& lang) -> bool {
587
0
    bool const valid = state->GetLanguageEnabled(lang);
588
0
    if (!valid) {
589
0
      makefile->IssueMessage(
590
0
        MessageType::FATAL_ERROR,
591
0
        cmStrCat("The language ", lang,
592
0
                 " was requested for compilation but was not enabled."
593
0
                 " To enable a language it needs to be specified in a"
594
0
                 " 'project' or 'enable_language' command in the root"
595
0
                 " CMakeLists.txt"));
596
0
    }
597
0
    return valid;
598
0
  };
599
0
  return std::all_of(languagesNeeded.cbegin(), languagesNeeded.cend(), unary);
600
0
}