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

#include <ostream>
#include <string>
#include <utility>
#include <vector>

#include <cm/memory>

#include "cmGeneratedFileStream.h"
#include "cmGeneratorTarget.h"
#include "cmGlobalUnixMakefileGenerator3.h"
#include "cmLocalUnixMakefileGenerator3.h"
#include "cmMakefile.h"
#include "cmOSXBundleGenerator.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"

cmMakefileUtilityTargetGenerator::cmMakefileUtilityTargetGenerator(
  cmGeneratorTarget* target)
  : cmMakefileTargetGenerator(target)
{
  this->CustomCommandDriver = OnUtility;
  this->OSXBundleGenerator = cm::make_unique<cmOSXBundleGenerator>(target);
  this->OSXBundleGenerator->SetMacContentFolders(&this->MacContentFolders);
}

cmMakefileUtilityTargetGenerator::~cmMakefileUtilityTargetGenerator() =
  default;

void cmMakefileUtilityTargetGenerator::WriteRuleFiles()
{
  this->CreateRuleFile();

  *this->BuildFileStream << "# Utility rule file for "
                         << this->GeneratorTarget->GetName() << ".\n\n";

  char const* root = (this->Makefile->IsOn("CMAKE_MAKE_INCLUDE_FROM_ROOT")
                        ? "$(CMAKE_BINARY_DIR)/"
                        : "");

  // Include the dependencies for the target.
  std::string dependFile =
    cmStrCat(this->TargetBuildDirectoryFull, "/compiler_depend.make");
  *this->BuildFileStream
    << "# Include any custom commands dependencies for this target.\n"
    << this->GlobalGenerator->IncludeDirective << " " << root
    << cmSystemTools::ConvertToOutputPath(
         this->LocalGenerator->MaybeRelativeToTopBinDir(dependFile))
    << "\n\n";
  if (!cmSystemTools::FileExists(dependFile)) {
    // Write an empty dependency file.
    cmGeneratedFileStream depFileStream(
      dependFile, false, this->GlobalGenerator->GetMakefileEncoding());
    depFileStream << "# Empty custom commands generated dependencies file for "
                  << this->GeneratorTarget->GetName()
                  << ".\n"
                     "# This may be replaced when dependencies are built.\n";
  }

  std::string dependTimestamp =
    cmStrCat(this->TargetBuildDirectoryFull, "/compiler_depend.ts");
  if (!cmSystemTools::FileExists(dependTimestamp)) {
    // Write a dependency timestamp file.
    cmGeneratedFileStream depFileStream(
      dependTimestamp, false, this->GlobalGenerator->GetMakefileEncoding());
    depFileStream << "# CMAKE generated file: DO NOT EDIT!\n"
                     "# Timestamp file for custom commands dependencies "
                     "management for "
                  << this->GeneratorTarget->GetName() << ".\n";
  }

  if (!this->NoRuleMessages) {
    // Include the progress variables for the target.
    *this->BuildFileStream
      << "# Include the progress variables for this target.\n"
      << this->GlobalGenerator->IncludeDirective << " " << root
      << cmSystemTools::ConvertToOutputPath(
           this->LocalGenerator->MaybeRelativeToTopBinDir(
             this->ProgressFileNameFull))
      << "\n\n";
  }

  // write the custom commands for this target
  this->WriteTargetBuildRules();

  // Collect the commands and dependencies.
  std::vector<std::string> commands;
  std::vector<std::string> depends;

  // Utility targets store their rules in pre- and post-build commands.
  this->LocalGenerator->AppendCustomDepends(
    depends, this->GeneratorTarget->GetPreBuildCommands());

  this->LocalGenerator->AppendCustomDepends(
    depends, this->GeneratorTarget->GetPostBuildCommands());

  this->LocalGenerator->AppendCustomCommands(
    commands, this->GeneratorTarget->GetPreBuildCommands(),
    this->GeneratorTarget, this->LocalGenerator->GetBinaryDirectory());

  // Depend on all custom command outputs for sources
  this->DriveCustomCommands(depends);

  this->LocalGenerator->AppendCustomCommands(
    commands, this->GeneratorTarget->GetPostBuildCommands(),
    this->GeneratorTarget, this->LocalGenerator->GetBinaryDirectory());

  // Add dependencies on targets that must be built first.
  this->AppendTargetDepends(depends);

  // Add a dependency on the rule file itself.
  this->LocalGenerator->AppendRuleDepend(depends,
                                         this->BuildFileNameFull.c_str());

  // If the rule is empty add the special empty rule dependency needed
  // by some make tools.
  if (depends.empty() && commands.empty()) {
    std::string hack = this->GlobalGenerator->GetEmptyRuleHackDepends();
    if (!hack.empty()) {
      depends.push_back(std::move(hack));
    }
  }

  // Write the rule.
  this->LocalGenerator->WriteMakeRule(*this->BuildFileStream, nullptr,
                                      this->GeneratorTarget->GetName(),
                                      depends, commands, true);

  // Write the main driver rule to build everything in this target.
  this->WriteTargetDriverRule(this->GeneratorTarget->GetName(), false);

  // Write clean target
  this->WriteTargetCleanRules();

  // Write the dependency generation rule.  This must be done last so
  // that multiple output pair information is available.
  this->WriteTargetDependRules();

  // close the streams
  this->CloseFileStreams();
}
