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

#include "cmsys/RegularExpression.hxx"

#include "cmDocumentationEntry.h"
#include "cmDuration.h"
#include "cmLocalUnixMakefileGenerator3.h"
#include "cmMakefile.h"
#include "cmState.h"
#include "cmake.h"

cmGlobalNMakeMakefileGenerator::cmGlobalNMakeMakefileGenerator(cmake* cm)
  : cmGlobalUnixMakefileGenerator3(cm)
{
  this->FindMakeProgramFile = "CMakeNMakeFindMake.cmake";
  this->ForceUnixPaths = false;
  this->ToolSupportsColor = true;
  this->UseLinkScript = false;
  cm->GetState()->SetWindowsShell(true);
  cm->GetState()->SetNMake(true);
  this->DefineWindowsNULL = true;
  this->PassMakeflags = true;
  this->UnixCD = false;
  this->MakeSilentFlag = "/nologo";
  // nmake breaks on '!' in long-line dependencies
  this->ToolSupportsLongLineDependencies = false;
}

void cmGlobalNMakeMakefileGenerator::EnableLanguage(
  std::vector<std::string> const& l, cmMakefile* mf, bool optional)
{
  // pick a default
  mf->AddDefinition("CMAKE_GENERATOR_CC", "cl");
  mf->AddDefinition("CMAKE_GENERATOR_CXX", "cl");
  this->cmGlobalUnixMakefileGenerator3::EnableLanguage(l, mf, optional);
}

bool cmGlobalNMakeMakefileGenerator::FindMakeProgram(cmMakefile* mf)
{
  if (!this->cmGlobalGenerator::FindMakeProgram(mf)) {
    return false;
  }
  if (cmProp nmakeCommand = mf->GetDefinition("CMAKE_MAKE_PROGRAM")) {
    std::vector<std::string> command{ *nmakeCommand, "-?" };
    std::string out;
    std::string err;
    if (!cmSystemTools::RunSingleCommand(command, &out, &err, nullptr, nullptr,
                                         cmSystemTools::OUTPUT_NONE,
                                         cmDuration(30))) {
      mf->IssueMessage(MessageType::FATAL_ERROR,
                       cmStrCat("Running\n '", cmJoin(command, "' '"),
                                "'\n"
                                "failed with:\n ",
                                err));
      cmSystemTools::SetFatalErrorOccured();
      return false;
    }
    cmsys::RegularExpression regex(
      "Program Maintenance Utility Version ([1-9][0-9.]+)");
    if (regex.find(err)) {
      this->NMakeVersion = regex.match(1);
      this->CheckNMakeFeatures();
    }
  }
  return true;
}

void cmGlobalNMakeMakefileGenerator::CheckNMakeFeatures()
{
  this->NMakeSupportsUTF8 = !cmSystemTools::VersionCompare(
    cmSystemTools::OP_LESS, this->NMakeVersion.c_str(), "9");
}

void cmGlobalNMakeMakefileGenerator::GetDocumentation(
  cmDocumentationEntry& entry)
{
  entry.Name = cmGlobalNMakeMakefileGenerator::GetActualName();
  entry.Brief = "Generates NMake makefiles.";
}

void cmGlobalNMakeMakefileGenerator::PrintCompilerAdvice(
  std::ostream& os, std::string const& lang, const char* envVar) const
{
  if (lang == "CXX" || lang == "C") {
    /* clang-format off */
    os <<
      "To use the NMake generator with Visual C++, cmake must be run from a "
      "shell that can use the compiler cl from the command line. This "
      "environment is unable to invoke the cl compiler. To fix this problem, "
      "run cmake from the Visual Studio Command Prompt (vcvarsall.bat).\n";
    /* clang-format on */
  }
  this->cmGlobalUnixMakefileGenerator3::PrintCompilerAdvice(os, lang, envVar);
}

std::vector<cmGlobalGenerator::GeneratedMakeCommand>
cmGlobalNMakeMakefileGenerator::GenerateBuildCommand(
  const std::string& makeProgram, const std::string& projectName,
  const std::string& projectDir, std::vector<std::string> const& targetNames,
  const std::string& config, bool fast, int /*jobs*/, bool verbose,
  std::vector<std::string> const& makeOptions)
{
  std::vector<std::string> nmakeMakeOptions;

  // Since we have full control over the invocation of nmake, let us
  // make it quiet.
  nmakeMakeOptions.push_back(this->MakeSilentFlag);
  cm::append(nmakeMakeOptions, makeOptions);

  return this->cmGlobalUnixMakefileGenerator3::GenerateBuildCommand(
    makeProgram, projectName, projectDir, targetNames, config, fast,
    cmake::NO_BUILD_PARALLEL_LEVEL, verbose, nmakeMakeOptions);
}

void cmGlobalNMakeMakefileGenerator::PrintBuildCommandAdvice(std::ostream& os,
                                                             int jobs) const
{
  if (jobs != cmake::NO_BUILD_PARALLEL_LEVEL) {
    // nmake does not support parallel build level
    // see https://msdn.microsoft.com/en-us/library/afyyse50.aspx

    /* clang-format off */
    os <<
      "Warning: NMake does not support parallel builds. "
      "Ignoring parallel build command line option.\n";
    /* clang-format on */
  }

  this->cmGlobalUnixMakefileGenerator3::PrintBuildCommandAdvice(
    os, cmake::NO_BUILD_PARALLEL_LEVEL);
}
