Upstream version 10.39.225.0
[platform/framework/web/crosswalk.git] / src / tools / gn / ninja_target_writer.cc
index ade81a0..870cbb6 100644 (file)
@@ -7,44 +7,43 @@
 #include <fstream>
 #include <sstream>
 
-#include "base/file_util.h"
+#include "base/files/file_util.h"
+#include "base/strings/string_util.h"
 #include "tools/gn/err.h"
+#include "tools/gn/filesystem_utils.h"
 #include "tools/gn/ninja_action_target_writer.h"
 #include "tools/gn/ninja_binary_target_writer.h"
 #include "tools/gn/ninja_copy_target_writer.h"
 #include "tools/gn/ninja_group_target_writer.h"
+#include "tools/gn/ninja_utils.h"
+#include "tools/gn/output_file.h"
 #include "tools/gn/scheduler.h"
 #include "tools/gn/string_utils.h"
+#include "tools/gn/substitution_writer.h"
 #include "tools/gn/target.h"
 #include "tools/gn/trace.h"
 
 NinjaTargetWriter::NinjaTargetWriter(const Target* target,
-                                     const Toolchain* toolchain,
                                      std::ostream& out)
     : settings_(target->settings()),
       target_(target),
-      toolchain_(toolchain),
       out_(out),
-      path_output_(settings_->build_settings()->build_dir(), ESCAPE_NINJA),
-      helper_(settings_->build_settings()) {
+      path_output_(settings_->build_settings()->build_dir(), ESCAPE_NINJA) {
 }
 
 NinjaTargetWriter::~NinjaTargetWriter() {
 }
 
 // static
-void NinjaTargetWriter::RunAndWriteFile(const Target* target,
-                                        const Toolchain* toolchain) {
+void NinjaTargetWriter::RunAndWriteFile(const Target* target) {
   const Settings* settings = target->settings();
-  NinjaHelper helper(settings->build_settings());
 
   ScopedTrace trace(TraceItem::TRACE_FILE_WRITE,
                     target->label().GetUserVisibleName(false));
   trace.SetToolchain(settings->toolchain_label());
 
   base::FilePath ninja_file(settings->build_settings()->GetFullPath(
-      helper.GetNinjaFileForTarget(target).GetSourceFile(
-          settings->build_settings())));
+      GetNinjaFileForTarget(target)));
 
   if (g_scheduler->verbose_logging())
     g_scheduler->Log("Writing", FilePathToUTF8(ninja_file));
@@ -57,20 +56,20 @@ void NinjaTargetWriter::RunAndWriteFile(const Target* target,
 
   // Call out to the correct sub-type of writer.
   if (target->output_type() == Target::COPY_FILES) {
-    NinjaCopyTargetWriter writer(target, toolchain, file);
+    NinjaCopyTargetWriter writer(target, file);
     writer.Run();
   } else if (target->output_type() == Target::ACTION ||
              target->output_type() == Target::ACTION_FOREACH) {
-    NinjaActionTargetWriter writer(target, toolchain, file);
+    NinjaActionTargetWriter writer(target, file);
     writer.Run();
   } else if (target->output_type() == Target::GROUP) {
-    NinjaGroupTargetWriter writer(target, toolchain, file);
+    NinjaGroupTargetWriter writer(target, file);
     writer.Run();
   } else if (target->output_type() == Target::EXECUTABLE ||
              target->output_type() == Target::STATIC_LIBRARY ||
              target->output_type() == Target::SHARED_LIBRARY ||
              target->output_type() == Target::SOURCE_SET) {
-    NinjaBinaryTargetWriter writer(target, toolchain, file);
+    NinjaBinaryTargetWriter writer(target, file);
     writer.Run();
   } else {
     CHECK(0);
@@ -81,8 +80,75 @@ void NinjaTargetWriter::RunAndWriteFile(const Target* target,
                   static_cast<int>(contents.size()));
 }
 
-std::string NinjaTargetWriter::WriteInputDepsStampAndGetDep(
+void NinjaTargetWriter::WriteSharedVars(const SubstitutionBits& bits) {
+  bool written_anything = false;
+
+  // Target label.
+  if (bits.used[SUBSTITUTION_LABEL]) {
+    out_ << kSubstitutionNinjaNames[SUBSTITUTION_LABEL] << " = "
+         << SubstitutionWriter::GetTargetSubstitution(
+                target_, SUBSTITUTION_LABEL)
+         << std::endl;
+    written_anything = true;
+  }
+
+  // Root gen dir.
+  if (bits.used[SUBSTITUTION_ROOT_GEN_DIR]) {
+    out_ << kSubstitutionNinjaNames[SUBSTITUTION_ROOT_GEN_DIR] << " = "
+         << SubstitutionWriter::GetTargetSubstitution(
+                target_, SUBSTITUTION_ROOT_GEN_DIR)
+         << std::endl;
+    written_anything = true;
+  }
+
+  // Root out dir.
+  if (bits.used[SUBSTITUTION_ROOT_OUT_DIR]) {
+    out_ << kSubstitutionNinjaNames[SUBSTITUTION_ROOT_OUT_DIR] << " = "
+         << SubstitutionWriter::GetTargetSubstitution(
+                target_, SUBSTITUTION_ROOT_OUT_DIR)
+         << std::endl;
+    written_anything = true;
+  }
+
+  // Target gen dir.
+  if (bits.used[SUBSTITUTION_TARGET_GEN_DIR]) {
+    out_ << kSubstitutionNinjaNames[SUBSTITUTION_TARGET_GEN_DIR] << " = "
+         << SubstitutionWriter::GetTargetSubstitution(
+                target_, SUBSTITUTION_TARGET_GEN_DIR)
+         << std::endl;
+    written_anything = true;
+  }
+
+  // Target out dir.
+  if (bits.used[SUBSTITUTION_TARGET_OUT_DIR]) {
+    out_ << kSubstitutionNinjaNames[SUBSTITUTION_TARGET_OUT_DIR] << " = "
+         << SubstitutionWriter::GetTargetSubstitution(
+                target_, SUBSTITUTION_TARGET_OUT_DIR)
+         << std::endl;
+    written_anything = true;
+  }
+
+  // Target output name.
+  if (bits.used[SUBSTITUTION_TARGET_OUTPUT_NAME]) {
+    out_ << kSubstitutionNinjaNames[SUBSTITUTION_TARGET_OUTPUT_NAME] << " = "
+         << SubstitutionWriter::GetTargetSubstitution(
+                target_, SUBSTITUTION_TARGET_OUTPUT_NAME)
+         << std::endl;
+    written_anything = true;
+  }
+
+  // If we wrote any vars, separate them from the rest of the file that follows
+  // with a blank line.
+  if (written_anything)
+    out_ << std::endl;
+}
+
+OutputFile NinjaTargetWriter::WriteInputDepsStampAndGetDep(
     const std::vector<const Target*>& extra_hard_deps) const {
+  CHECK(target_->toolchain())
+      << "Toolchain not set on target "
+      << target_->label().GetUserVisibleName(true);
+
   // For an action (where we run a script only once) the sources are the same
   // as the source prereqs.
   bool list_sources_as_input_deps = (target_->output_type() == Target::ACTION);
@@ -97,8 +163,8 @@ std::string NinjaTargetWriter::WriteInputDepsStampAndGetDep(
       target_->inputs().empty() &&
       target_->recursive_hard_deps().empty() &&
       (!list_sources_as_input_deps || target_->sources().empty()) &&
-      toolchain_->deps().empty())
-    return std::string();  // No input/hard deps.
+      target_->toolchain()->deps().empty())
+    return OutputFile();  // No input/hard deps.
 
   // One potential optimization is if there are few input dependencies (or
   // potentially few sources that depend on these) it's better to just write
@@ -107,16 +173,17 @@ std::string NinjaTargetWriter::WriteInputDepsStampAndGetDep(
   // source file can really explode the ninja file but this won't be the most
   // optimal thing in all cases.
 
-  OutputFile input_stamp_file = helper_.GetTargetOutputDir(target_);
+  OutputFile input_stamp_file(
+      RebaseSourceAbsolutePath(GetTargetOutputDir(target_).value(),
+                               settings_->build_settings()->build_dir()));
   input_stamp_file.value().append(target_->label().name());
   input_stamp_file.value().append(".inputdeps.stamp");
 
-  std::ostringstream stamp_file_stream;
-  path_output_.WriteFile(stamp_file_stream, input_stamp_file);
-  std::string stamp_file_string = stamp_file_stream.str();
-
-  out_ << "build " << stamp_file_string << ": " +
-      helper_.GetRulePrefix(settings_) + "stamp";
+  out_ << "build ";
+  path_output_.WriteFile(out_, input_stamp_file);
+  out_ << ": "
+       << GetNinjaRulePrefixForToolchain(settings_)
+       << Toolchain::ToolTypeToName(Toolchain::TYPE_STAMP);
 
   // Script file (if applicable).
   if (add_script_source_as_dep) {
@@ -138,32 +205,61 @@ std::string NinjaTargetWriter::WriteInputDepsStampAndGetDep(
     }
   }
 
-  // Add on any hard deps that are direct or indirect dependencies.
+  // The different souces of input deps may duplicate some targets, so uniquify
+  // them (ordering doesn't matter for this case).
+  std::set<const Target*> unique_deps;
+
+  // Hard dependencies that are direct or indirect dependencies.
   const std::set<const Target*>& hard_deps = target_->recursive_hard_deps();
   for (std::set<const Target*>::const_iterator i = hard_deps.begin();
        i != hard_deps.end(); ++i) {
-    out_ << " ";
-    path_output_.WriteFile(out_, helper_.GetTargetOutputFile(*i));
+    unique_deps.insert(*i);
   }
 
+  // Extra hard dependencies passed in.
+  unique_deps.insert(extra_hard_deps.begin(), extra_hard_deps.end());
+
   // Toolchain dependencies. These must be resolved before doing anything.
   // This just writs all toolchain deps for simplicity. If we find that
   // toolchains often have more than one dependency, we could consider writing
   // a toolchain-specific stamp file and only include the stamp here.
-  const LabelTargetVector& toolchain_deps = toolchain_->deps();
-  for (size_t i = 0; i < toolchain_deps.size(); i++) {
-    out_ << " ";
-    path_output_.WriteFile(out_,
-                           helper_.GetTargetOutputFile(toolchain_deps[i].ptr));
-  }
+  const LabelTargetVector& toolchain_deps = target_->toolchain()->deps();
+  for (size_t i = 0; i < toolchain_deps.size(); i++)
+    unique_deps.insert(toolchain_deps[i].ptr);
 
-  // Extra hard deps passed in.
-  for (size_t i = 0; i < extra_hard_deps.size(); i++) {
+  for (std::set<const Target*>::const_iterator i = unique_deps.begin();
+       i != unique_deps.end(); ++i) {
+    DCHECK(!(*i)->dependency_output_file().value().empty());
     out_ << " ";
-    path_output_.WriteFile(out_,
-        helper_.GetTargetOutputFile(extra_hard_deps[i]));
+    path_output_.WriteFile(out_, (*i)->dependency_output_file());
   }
 
   out_ << "\n";
-  return " | " + stamp_file_string;
+  return input_stamp_file;
+}
+
+void NinjaTargetWriter::WriteStampForTarget(
+    const std::vector<OutputFile>& files,
+    const std::vector<OutputFile>& order_only_deps) {
+  const OutputFile& stamp_file = target_->dependency_output_file();
+
+  // First validate that the target's dependency is a stamp file. Otherwise,
+  // we shouldn't have gotten here!
+  CHECK(EndsWith(stamp_file.value(), ".stamp", false))
+      << "Output should end in \".stamp\" for stamp file output. Instead got: "
+      << "\"" << stamp_file.value() << "\"";
+
+  out_ << "build ";
+  path_output_.WriteFile(out_, stamp_file);
+
+  out_ << ": "
+       << GetNinjaRulePrefixForToolchain(settings_)
+       << Toolchain::ToolTypeToName(Toolchain::TYPE_STAMP);
+  path_output_.WriteFiles(out_, files);
+
+  if (!order_only_deps.empty()) {
+    out_ << " ||";
+    path_output_.WriteFiles(out_, order_only_deps);
+  }
+  out_ << std::endl;
 }