/* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
   file LICENSE.rst or https://cmake.org/licensing for details.  */
#include "cmCommonTargetGenerator.h"

#include <algorithm>
#include <sstream>
#include <utility>

#include <cm/string_view>
#include <cmext/string_view>

#include "cmComputeLinkInformation.h"
#include "cmGenExContext.h"
#include "cmGeneratorExpression.h"
#include "cmGeneratorExpressionDAGChecker.h"
#include "cmGeneratorTarget.h"
#include "cmGlobalCommonGenerator.h"
#include "cmGlobalGenerator.h"
#include "cmList.h"
#include "cmLocalCommonGenerator.h"
#include "cmLocalGenerator.h"
#include "cmMakefile.h"
#include "cmMessageType.h"
#include "cmOutputConverter.h"
#include "cmRange.h"
#include "cmSourceFile.h"
#include "cmState.h"
#include "cmStateTypes.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
#include "cmValue.h"

cmCommonTargetGenerator::cmCommonTargetGenerator(cmGeneratorTarget* gt)
  : GeneratorTarget(gt)
  , Makefile(gt->Makefile)
  , LocalCommonGenerator(
      static_cast<cmLocalCommonGenerator*>(gt->LocalGenerator))
  , GlobalCommonGenerator(static_cast<cmGlobalCommonGenerator*>(
      gt->LocalGenerator->GetGlobalGenerator()))
  , ConfigNames(this->LocalCommonGenerator->GetConfigNames())
{
}

cmCommonTargetGenerator::~cmCommonTargetGenerator() = default;

std::vector<std::string> const& cmCommonTargetGenerator::GetConfigNames() const
{
  return this->ConfigNames;
}

cmValue cmCommonTargetGenerator::GetFeature(std::string const& feature,
                                            std::string const& config)
{
  return this->GeneratorTarget->GetFeature(feature, config);
}

void cmCommonTargetGenerator::AppendFortranFormatFlags(
  std::string& flags, cmSourceFile const& source)
{
  std::string const srcfmt = source.GetSafeProperty("Fortran_FORMAT");
  cmOutputConverter::FortranFormat format =
    cmOutputConverter::GetFortranFormat(srcfmt);
  if (format == cmOutputConverter::FortranFormatNone) {
    std::string const& tgtfmt =
      this->GeneratorTarget->GetSafeProperty("Fortran_FORMAT");
    format = cmOutputConverter::GetFortranFormat(tgtfmt);
  }
  char const* var = nullptr;
  switch (format) {
    case cmOutputConverter::FortranFormatFixed:
      var = "CMAKE_Fortran_FORMAT_FIXED_FLAG";
      break;
    case cmOutputConverter::FortranFormatFree:
      var = "CMAKE_Fortran_FORMAT_FREE_FLAG";
      break;
    default:
      break;
  }
  if (var) {
    this->LocalCommonGenerator->AppendFlags(
      flags, this->Makefile->GetSafeDefinition(var));
  }
}

void cmCommonTargetGenerator::AppendFortranPreprocessFlags(
  std::string& flags, cmSourceFile const& source,
  PreprocessFlagsRequired requires_pp)
{
  std::string const srcpp = source.GetSafeProperty("Fortran_PREPROCESS");
  cmOutputConverter::FortranPreprocess preprocess =
    cmOutputConverter::GetFortranPreprocess(srcpp);
  if (preprocess == cmOutputConverter::FortranPreprocess::Unset) {
    std::string const& tgtpp =
      this->GeneratorTarget->GetSafeProperty("Fortran_PREPROCESS");
    preprocess = cmOutputConverter::GetFortranPreprocess(tgtpp);
  }
  char const* var = nullptr;
  switch (preprocess) {
    case cmOutputConverter::FortranPreprocess::Needed:
      if (requires_pp == PreprocessFlagsRequired::YES) {
        var = "CMAKE_Fortran_COMPILE_OPTIONS_PREPROCESS_ON";
      }
      break;
    case cmOutputConverter::FortranPreprocess::NotNeeded:
      var = "CMAKE_Fortran_COMPILE_OPTIONS_PREPROCESS_OFF";
      break;
    default:
      break;
  }
  if (var) {
    this->LocalCommonGenerator->AppendCompileOptions(
      flags, this->Makefile->GetSafeDefinition(var));
  }
}

std::string cmCommonTargetGenerator::GetFlags(std::string const& l,
                                              std::string const& config,
                                              std::string const& arch)
{
  std::string const key = config + arch;

  auto i = this->Configs[key].FlagsByLanguage.find(l);
  if (i == this->Configs[key].FlagsByLanguage.end()) {
    std::string flags;

    this->LocalCommonGenerator->GetTargetCompileFlags(this->GeneratorTarget,
                                                      config, l, flags, arch);

    ByLanguageMap::value_type entry(l, flags);
    i = this->Configs[key].FlagsByLanguage.insert(entry).first;
  }
  return i->second;
}

std::string cmCommonTargetGenerator::GetDefines(std::string const& l,
                                                std::string const& config)
{
  auto i = this->Configs[config].DefinesByLanguage.find(l);
  if (i == this->Configs[config].DefinesByLanguage.end()) {
    std::set<std::string> defines;
    this->LocalCommonGenerator->GetTargetDefines(this->GeneratorTarget, config,
                                                 l, defines);

    std::string definesString;
    this->LocalCommonGenerator->JoinDefines(defines, definesString, l);

    ByLanguageMap::value_type entry(l, definesString);
    i = this->Configs[config].DefinesByLanguage.insert(entry).first;
  }
  return i->second;
}

std::string cmCommonTargetGenerator::GetIncludes(std::string const& l,
                                                 std::string const& config)
{
  auto i = this->Configs[config].IncludesByLanguage.find(l);
  if (i == this->Configs[config].IncludesByLanguage.end()) {
    std::string includes;
    this->AddIncludeFlags(includes, l, config);
    ByLanguageMap::value_type entry(l, includes);
    i = this->Configs[config].IncludesByLanguage.insert(entry).first;
  }
  return i->second;
}

cmCommonTargetGenerator::LinkedTargetDirs
cmCommonTargetGenerator::GetLinkedTargetDirectories(
  std::string const& lang, std::string const& config) const
{
  LinkedTargetDirs dirs;
  std::set<cmGeneratorTarget const*> forward_emitted;
  std::set<cmGeneratorTarget const*> direct_emitted;
  cmGlobalCommonGenerator* const gg = this->GlobalCommonGenerator;

  enum class Forwarding
  {
    Yes,
    No
  };

  if (cmComputeLinkInformation* cli =
        this->GeneratorTarget->GetLinkInformation(config)) {

    auto findSyntheticTarget =
      [this,
       &config](cmGeneratorTarget const* linkee) -> cmGeneratorTarget const* {
      if (!linkee) {
        return nullptr;
      }

      // Check the map of direct synthetic dependencies for a substitute
      auto const& synthDeps = this->GeneratorTarget->GetSyntheticDeps(config);
      auto it = synthDeps.find(linkee);
      if (it != synthDeps.end() && !it->second.empty()) {
        return it->second.front();
      }

      // Check linked targets to finding synthetic targets for transitive deps
      std::vector<cmGeneratorTarget const*> pending;
      std::set<cmGeneratorTarget const*> visited;
      for (auto const& dep : synthDeps) {
        for (auto const* synth : dep.second) {
          if (synth && visited.insert(synth).second) {
            pending.push_back(synth);
          }
        }
      }

      while (!pending.empty()) {
        auto const* current = pending.back();
        pending.pop_back();
        auto const& transitiveSynthDeps = current->GetSyntheticDeps(config);
        auto itLinkeeSynth = transitiveSynthDeps.find(linkee);
        if (itLinkeeSynth != transitiveSynthDeps.end() &&
            !itLinkeeSynth->second.empty()) {
          return itLinkeeSynth->second.front();
        }
        for (auto const& entry : transitiveSynthDeps) {
          for (auto const* synth : entry.second) {
            if (synth && visited.insert(synth).second) {
              pending.push_back(synth);
            }
          }
        }
      }

      return nullptr;
    };

    auto addLinkedTarget = [this, &lang, &config, &dirs, &direct_emitted,
                            &forward_emitted, &findSyntheticTarget,
                            gg](cmGeneratorTarget const* linkee,
                                Forwarding forward) {
      // Check if the linkee has a synthetic target to use for importing
      cmGeneratorTarget const* mappedLinkee = linkee;
      if (auto const* synth = findSyntheticTarget(linkee)) {
        mappedLinkee = synth;
      }

      if (mappedLinkee &&
          !mappedLinkee->IsImported()
          // Skip targets that build after this one in a static lib cycle.
          && gg->TargetOrderIndexLess(mappedLinkee, this->GeneratorTarget)
          // We can ignore the INTERFACE_LIBRARY items because
          // Target->GetLinkInformation already processed their
          // link interface and they don't have any output themselves.
          && (mappedLinkee->GetType() != cmStateEnums::INTERFACE_LIBRARY
              // Synthesized targets may have relevant rules.
              || mappedLinkee->IsSynthetic()) &&
          ((lang == "CXX"_s && mappedLinkee->HaveCxx20ModuleSources()) ||
           (lang == "Fortran"_s &&
            mappedLinkee->HaveFortranSources(config)))) {
        cmLocalGenerator* lg = mappedLinkee->GetLocalGenerator();
        std::string di = mappedLinkee->GetSupportDirectory();
        if (lg->GetGlobalGenerator()->IsMultiConfig()) {
          di = cmStrCat(di, '/', config);
        }
        if (forward == Forwarding::Yes &&
            forward_emitted.insert(mappedLinkee).second) {
          dirs.Forward.push_back(di);
        }
        if (direct_emitted.insert(mappedLinkee).second) {
          dirs.Direct.emplace_back(di);
        }
      }
    };
    for (auto const& item : cli->GetItems()) {
      if (item.Target) {
        addLinkedTarget(item.Target, Forwarding::No);
      } else if (item.ObjectSource && lang == "Fortran"_s
                 /* Object source files do not have a language associated with
                    them. */
                 /* && item.ObjectSource->GetLanguage() == "Fortran"_s*/) {
        // Fortran modules provided by `$<TARGET_OBJECTS>` as linked items
        // should be collated for use in this target.
        addLinkedTarget(this->LocalCommonGenerator->FindGeneratorTargetToUse(
                          item.ObjectSource->GetObjectLibrary()),
                        Forwarding::Yes);
      }
    }
    for (cmGeneratorTarget const* target : cli->GetExternalObjectTargets()) {
      addLinkedTarget(target, Forwarding::No);
    }
    if (lang == "Fortran"_s) {
      // Fortran modules provided by `$<TARGET_OBJECTS>` as sources should be
      // collated for use in this target.
      for (cmGeneratorTarget const* target :
           this->GeneratorTarget->GetSourceObjectLibraries(config)) {
        addLinkedTarget(target, Forwarding::Yes);
      }
    }
  }
  return dirs;
}

std::string cmCommonTargetGenerator::ComputeTargetCompilePDB(
  std::string const& config) const
{
  std::string compilePdbPath;
  if (this->GeneratorTarget->GetType() > cmStateEnums::OBJECT_LIBRARY) {
    return compilePdbPath;
  }

  compilePdbPath = this->GeneratorTarget->GetCompilePDBPath(config);
  if (compilePdbPath.empty()) {
    // Match VS default: `$(IntDir)vc$(PlatformToolsetVersion).pdb`.
    // A trailing slash tells the toolchain to add its default file name.
    compilePdbPath = this->GeneratorTarget->GetSupportDirectory();
    if (this->GlobalCommonGenerator->IsMultiConfig()) {
      compilePdbPath += "/";
      compilePdbPath += config;
    }
    compilePdbPath += "/";
    if (this->GeneratorTarget->GetType() == cmStateEnums::STATIC_LIBRARY) {
      // Match VS default for static libs: `$(IntDir)$(ProjectName).pdb`.
      compilePdbPath += this->GeneratorTarget->GetName();
      compilePdbPath += ".pdb";
    }
  }

  return compilePdbPath;
}

std::string cmCommonTargetGenerator::GetManifests(std::string const& config)
{
  std::vector<cmSourceFile const*> manifest_srcs;
  this->GeneratorTarget->GetManifests(manifest_srcs, config);

  std::vector<std::string> manifests;
  manifests.reserve(manifest_srcs.size());

  std::string lang = this->GeneratorTarget->GetLinkerLanguage(config);
  std::string manifestFlag = this->Makefile->GetDefinition(
    cmStrCat("CMAKE_", lang, "_LINKER_MANIFEST_FLAG"));
  for (cmSourceFile const* manifest_src : manifest_srcs) {
    manifests.push_back(manifestFlag +
                        this->LocalCommonGenerator->ConvertToOutputFormat(
                          this->LocalCommonGenerator->MaybeRelativeToWorkDir(
                            manifest_src->GetFullPath()),
                          cmOutputConverter::SHELL));
  }

  return cmJoin(manifests, " ");
}

std::string cmCommonTargetGenerator::GetAIXExports(std::string const&)
{
  std::string aixExports;
  if (this->GeneratorTarget->IsAIX()) {
    if (cmValue exportAll =
          this->GeneratorTarget->GetProperty("AIX_EXPORT_ALL_SYMBOLS")) {
      if (exportAll.IsOff()) {
        aixExports = "-n";
      }
    }
  }
  return aixExports;
}

void cmCommonTargetGenerator::AppendOSXVerFlag(std::string& flags,
                                               std::string const& lang,
                                               char const* name, bool so)
{
  // Lookup the flag to specify the version.
  std::string fvar = cmStrCat("CMAKE_", lang, "_OSX_", name, "_VERSION_FLAG");
  cmValue flag = this->Makefile->GetDefinition(fvar);

  // Skip if no such flag.
  if (!flag) {
    return;
  }

  // Lookup the target version information.
  int major;
  int minor;
  int patch;
  std::string prop = cmStrCat("MACHO_", name, "_VERSION");
  std::string fallback_prop = so ? "SOVERSION" : "VERSION";
  this->GeneratorTarget->GetTargetVersionFallback(prop, fallback_prop, major,
                                                  minor, patch);
  if (major > 0 || minor > 0 || patch > 0) {
    // Append the flag since a non-zero version is specified.
    std::ostringstream vflag;
    vflag << *flag << major << "." << minor << "." << patch;
    this->LocalCommonGenerator->AppendFlags(flags, vflag.str());
  }
}

std::string cmCommonTargetGenerator::GetCompilerLauncher(
  std::string const& lang, std::string const& config)
{
  std::string compilerLauncher;
  if (lang == "C" || lang == "CXX" || lang == "Fortran" || lang == "CUDA" ||
      lang == "HIP" || lang == "ISPC" || lang == "OBJC" || lang == "OBJCXX") {
    std::string const clauncher_prop = cmStrCat(lang, "_COMPILER_LAUNCHER");
    cmValue clauncher = this->GeneratorTarget->GetProperty(clauncher_prop);
    std::string const evaluatedClauncher = cmGeneratorExpression::Evaluate(
      *clauncher, this->GeneratorTarget->GetLocalGenerator(), config,
      this->GeneratorTarget, nullptr, this->GeneratorTarget, lang);
    if (!evaluatedClauncher.empty()) {
      compilerLauncher = evaluatedClauncher;
    }
  }
  return compilerLauncher;
}

std::string cmCommonTargetGenerator::GenerateCodeCheckRules(
  cmSourceFile const& source, std::string& compilerLauncher,
  std::string const& cmakeCmd, std::string const& config,
  std::function<std::string(std::string const&)> const& pathConverter)
{
  auto const lang = source.GetLanguage();
  std::string tidy;
  std::string iwyu;
  std::string cpplint;
  std::string cppcheck;
  std::string icstat;
  std::string pvs;

  auto evaluateProp = [&](std::string const& prop) -> std::string {
    auto const value = this->GeneratorTarget->GetProperty(prop);
    if (!value) {
      return std::string{};
    }
    auto evaluatedProp = cmGeneratorExpression::Evaluate(
      *value, this->GeneratorTarget->GetLocalGenerator(), config,
      this->GeneratorTarget, nullptr, this->GeneratorTarget, lang);
    return evaluatedProp;
  };
  std::string const tidy_prop = cmStrCat(lang, "_CLANG_TIDY");
  tidy = evaluateProp(tidy_prop);

  if (lang == "C" || lang == "CXX") {
    std::string const iwyu_prop = cmStrCat(lang, "_INCLUDE_WHAT_YOU_USE");
    iwyu = evaluateProp(iwyu_prop);

    std::string const cpplint_prop = cmStrCat(lang, "_CPPLINT");
    cpplint = evaluateProp(cpplint_prop);

    std::string const cppcheck_prop = cmStrCat(lang, "_CPPCHECK");
    cppcheck = evaluateProp(cppcheck_prop);

    std::string const icstat_prop = cmStrCat(lang, "_ICSTAT");
    icstat = evaluateProp(icstat_prop);

    std::string const pvs_prop = cmStrCat(lang, "_PVS_STUDIO");
    pvs = evaluateProp(pvs_prop);
  }

  if (cmNonempty(iwyu) || cmNonempty(tidy) || cmNonempty(cpplint) ||
      cmNonempty(cppcheck) || cmNonempty(icstat) || cmNonempty(pvs)) {
    std::string code_check = cmakeCmd + " -E __run_co_compile";
    if (!compilerLauncher.empty()) {
      // In __run_co_compile case the launcher command is supplied
      // via --launcher=<maybe-list> and consumed
      code_check =
        cmStrCat(std::move(code_check), " --launcher=",
                 this->GeneratorTarget->GetLocalGenerator()->EscapeForShell(
                   compilerLauncher));
      compilerLauncher.clear();
    }
    if (cmNonempty(iwyu)) {
      code_check += " --iwyu=";

      // Only add --driver-mode if it is not already specified, as adding
      // it unconditionally might override a user-specified driver-mode
      if (iwyu.find("--driver-mode=") == std::string::npos) {
        cmValue const p = this->Makefile->GetDefinition(
          cmStrCat("CMAKE_", lang, "_INCLUDE_WHAT_YOU_USE_DRIVER_MODE"));
        std::string driverMode;

        if (cmNonempty(p)) {
          driverMode = *p;
        } else {
          driverMode = lang == "C" ? "gcc" : "g++";
        }

        code_check +=
          this->GeneratorTarget->GetLocalGenerator()->EscapeForShell(
            cmStrCat(iwyu, ";--driver-mode=", driverMode));
      } else {
        code_check +=
          this->GeneratorTarget->GetLocalGenerator()->EscapeForShell(iwyu);
      }
    }
    if (cmNonempty(tidy)) {
      code_check += " --tidy=";
      cmValue const p = this->Makefile->GetDefinition(
        cmStrCat("CMAKE_", lang, "_CLANG_TIDY_DRIVER_MODE"));
      std::string driverMode;
      if (cmNonempty(p)) {
        driverMode = *p;
      } else {
        driverMode = lang == "C" ? "gcc" : "g++";
      }

      auto const generatorName = this->GeneratorTarget->GetLocalGenerator()
                                   ->GetGlobalGenerator()
                                   ->GetName();
      auto const clangTidyExportFixedDir =
        this->GeneratorTarget->GetClangTidyExportFixesDirectory(lang);
      auto fixesFile = this->GetClangTidyReplacementsFilePath(
        clangTidyExportFixedDir, source, config);
      std::string exportFixes;
      if (!clangTidyExportFixedDir.empty()) {
        this->GlobalCommonGenerator->AddClangTidyExportFixesDir(
          clangTidyExportFixedDir);
      }
      if (generatorName.find("Make") != std::string::npos) {
        if (!clangTidyExportFixedDir.empty()) {
          this->GlobalCommonGenerator->AddClangTidyExportFixesFile(fixesFile);
          cmSystemTools::MakeDirectory(
            cmSystemTools::GetFilenamePath(fixesFile));
          fixesFile = this->GeneratorTarget->GetLocalGenerator()
                        ->MaybeRelativeToCurBinDir(fixesFile);
          exportFixes = cmStrCat(";--export-fixes=", fixesFile);
        }
        code_check +=
          this->GeneratorTarget->GetLocalGenerator()->EscapeForShell(
            cmStrCat(tidy, ";--extra-arg-before=--driver-mode=", driverMode,
                     exportFixes));
      } else if (generatorName.find("Ninja") != std::string::npos ||
                 generatorName.find("FASTBuild") != std::string::npos) {
        if (!clangTidyExportFixedDir.empty()) {
          this->GlobalCommonGenerator->AddClangTidyExportFixesFile(fixesFile);
          cmSystemTools::MakeDirectory(
            cmSystemTools::GetFilenamePath(fixesFile));
          if (pathConverter) {
            fixesFile = pathConverter(fixesFile);
          }
          exportFixes = cmStrCat(";--export-fixes=", fixesFile);
        }
        code_check +=
          this->GeneratorTarget->GetLocalGenerator()->EscapeForShell(
            cmStrCat(tidy, ";--extra-arg-before=--driver-mode=", driverMode,
                     exportFixes));
      }
    }
    if (cmNonempty(pvs)) {
      cmMakefile* mf =
        this->GeneratorTarget->GetLocalGenerator()->GetMakefile();
      std::string extraPvsArgs;
      if (lang == "CXX") {
        extraPvsArgs +=
          cmStrCat(";--cxx;", mf->GetDefinition("CMAKE_CXX_COMPILER"));
      } else if (lang == "C") {
        extraPvsArgs +=
          cmStrCat(";--cc;", mf->GetDefinition("CMAKE_C_COMPILER"));
      }
      // cocompile args
      code_check += " --pvs-studio=";
      code_check += this->GeneratorTarget->GetLocalGenerator()->EscapeForShell(
        cmStrCat(pvs, extraPvsArgs));
      code_check += " --object=";
      code_check +=
        this->GeneratorTarget->GetLocalGenerator()->ConvertToOutputFormat(
          cmSystemTools::CollapseFullPath(
            cmStrCat(this->GeneratorTarget->GetObjectDirectory(config), '/',
                     this->GeneratorTarget->GetObjectName(&source))),
          cmOutputConverter::SHELL);
    }
    if (cmNonempty(cpplint)) {
      code_check += " --cpplint=";
      code_check +=
        this->GeneratorTarget->GetLocalGenerator()->EscapeForShell(cpplint);
    }
    if (cmNonempty(cppcheck)) {
      code_check += " --cppcheck=";
      code_check +=
        this->GeneratorTarget->GetLocalGenerator()->EscapeForShell(cppcheck);
    }
    if (cmNonempty(icstat)) {
      code_check += " --icstat=";
      std::string checksParam{};
      std::string dbParam{};
      // Set default values for mandatory parameters
      std::string checksFile{ "cstat_sel_checks.txt" };
      std::string dbFile{ "cstat.db" };
      // Populate the command line with C-STAT
      // mandatory parameters unless specified
      if (icstat.find("--checks=") == std::string::npos) {
        checksParam = cmStrCat(";--checks=", checksFile);
      }
      if (icstat.find("--db=") == std::string::npos) {
        dbParam = cmStrCat(";--db=", dbFile);
      }
      code_check += this->GeneratorTarget->GetLocalGenerator()->EscapeForShell(
        cmStrCat(icstat, checksParam, dbParam));
    }
    if (cmNonempty(tidy) || (cmNonempty(cpplint)) || (cmNonempty(cppcheck)) ||
        cmNonempty(pvs)) {
      code_check += " --source=";
      code_check +=
        this->GeneratorTarget->GetLocalGenerator()->ConvertToOutputFormat(
          source.GetFullPath(), cmOutputConverter::SHELL);
    }
    code_check += " -- ";
    return code_check;
  }
  return "";
}

std::string cmCommonTargetGenerator::GetLinkerLauncher(
  std::string const& config)
{
  std::string lang = this->GeneratorTarget->GetLinkerLanguage(config);
  std::string propName = lang + "_LINKER_LAUNCHER";
  cmValue launcherProp = this->GeneratorTarget->GetProperty(propName);
  if (cmNonempty(launcherProp)) {
    cm::GenEx::Context context(this->LocalCommonGenerator, config, lang);
    cmGeneratorExpressionDAGChecker dagChecker{ this->GeneratorTarget,
                                                propName, nullptr, nullptr,
                                                context };
    std::string evaluatedLinklauncher = cmGeneratorExpression::Evaluate(
      *launcherProp, context.LG, context.Config, this->GeneratorTarget,
      &dagChecker, this->GeneratorTarget, context.Language);
    // Convert ;-delimited list to single string
    cmList args{ evaluatedLinklauncher, cmList::EmptyElements::Yes };
    if (!args.empty()) {
      args[0] = this->LocalCommonGenerator->ConvertToOutputFormat(
        args[0], cmOutputConverter::SHELL);
      for (std::string& i : cmMakeRange(args.begin() + 1, args.end())) {
        i = this->LocalCommonGenerator->EscapeForShell(i);
      }
      return cmJoin(args, " ");
    }
  }
  return std::string();
}

bool cmCommonTargetGenerator::HaveRequiredLanguages(
  std::vector<cmSourceFile const*> const& sources,
  std::set<std::string>& languagesNeeded) const
{
  for (cmSourceFile const* sf : sources) {
    languagesNeeded.insert(sf->GetLanguage());
  }

  auto* makefile = this->Makefile;
  auto* state = makefile->GetState();
  auto unary = [&state, &makefile](std::string const& lang) -> bool {
    bool const valid = state->GetLanguageEnabled(lang);
    if (!valid) {
      makefile->IssueMessage(
        MessageType::FATAL_ERROR,
        cmStrCat("The language ", lang,
                 " was requested for compilation but was not enabled."
                 " To enable a language it needs to be specified in a"
                 " 'project' or 'enable_language' command in the root"
                 " CMakeLists.txt"));
    }
    return valid;
  };
  return std::all_of(languagesNeeded.cbegin(), languagesNeeded.cend(), unary);
}
