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

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

#include "cmComputeLinkInformation.h"
#include "cmGeneratorTarget.h"
#include "cmGlobalCommonGenerator.h"
#include "cmGlobalGenerator.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 "cmTarget.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(const std::string& feature,
                                            const std::string& config)
{
  return this->GeneratorTarget->GetFeature(feature, config);
}

void cmCommonTargetGenerator::AppendFortranFormatFlags(
  std::string& flags, cmSourceFile const& source)
{
  const std::string 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);
  }
  const char* 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)
{
  const std::string 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);
  }
  const char* 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(const std::string& l,
                                              const std::string& config,
                                              const std::string& arch)
{
  const std::string 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(const std::string& l,
                                                const std::string& 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,
                                                 const std::string& 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;
}

std::vector<std::string> cmCommonTargetGenerator::GetLinkedTargetDirectories(
  const std::string& config) const
{
  std::vector<std::string> dirs;
  std::set<cmGeneratorTarget const*> emitted;
  if (cmComputeLinkInformation* cli =
        this->GeneratorTarget->GetLinkInformation(config)) {
    cmComputeLinkInformation::ItemVector const& items = cli->GetItems();
    for (auto const& item : items) {
      cmGeneratorTarget const* linkee = item.Target;
      if (linkee &&
          !linkee->IsImported()
          // We can ignore the INTERFACE_LIBRARY items because
          // Target->GetLinkInformation already processed their
          // link interface and they don't have any output themselves.
          && linkee->GetType() != cmStateEnums::INTERFACE_LIBRARY &&
          emitted.insert(linkee).second) {
        cmLocalGenerator* lg = linkee->GetLocalGenerator();
        std::string di = cmStrCat(lg->GetCurrentBinaryDirectory(), '/',
                                  lg->GetTargetDirectory(linkee));
        if (lg->GetGlobalGenerator()->IsMultiConfig()) {
          di = cmStrCat(di, '/', config);
        }
        dirs.push_back(std::move(di));
      }
    }
  }
  return dirs;
}

std::string cmCommonTargetGenerator::ComputeTargetCompilePDB(
  const std::string& 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(const std::string& 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 const& manifestFlag =
    this->Makefile->GetDefinition("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->Target->IsAIX()) {
    if (cmValue exportAll =
          this->GeneratorTarget->GetProperty("AIX_EXPORT_ALL_SYMBOLS")) {
      if (cmIsOff(*exportAll)) {
        aixExports = "-n";
      }
    }
  }
  return aixExports;
}

void cmCommonTargetGenerator::AppendOSXVerFlag(std::string& flags,
                                               const std::string& lang,
                                               const char* 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::GetLinkerLauncher(
  const std::string& config)
{
  std::string lang = this->GeneratorTarget->GetLinkerLanguage(config);
  cmValue launcherProp =
    this->GeneratorTarget->GetProperty(lang + "_LINKER_LAUNCHER");
  if (cmNonempty(launcherProp)) {
    // Convert ;-delimited list to single string
    std::vector<std::string> args = cmExpandedList(*launcherProp, true);
    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(
  const std::vector<cmSourceFile 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](const std::string& lang) -> bool {
    const bool 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);
}
