Upstream version 9.38.198.0
[platform/framework/web/crosswalk.git] / src / tools / gn / ninja_target_writer.cc
1 // Copyright (c) 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "tools/gn/ninja_target_writer.h"
6
7 #include <fstream>
8 #include <sstream>
9
10 #include "base/file_util.h"
11 #include "tools/gn/err.h"
12 #include "tools/gn/ninja_action_target_writer.h"
13 #include "tools/gn/ninja_binary_target_writer.h"
14 #include "tools/gn/ninja_copy_target_writer.h"
15 #include "tools/gn/ninja_group_target_writer.h"
16 #include "tools/gn/scheduler.h"
17 #include "tools/gn/string_utils.h"
18 #include "tools/gn/target.h"
19 #include "tools/gn/trace.h"
20
21 NinjaTargetWriter::NinjaTargetWriter(const Target* target,
22                                      const Toolchain* toolchain,
23                                      std::ostream& out)
24     : settings_(target->settings()),
25       target_(target),
26       toolchain_(toolchain),
27       out_(out),
28       path_output_(settings_->build_settings()->build_dir(), ESCAPE_NINJA),
29       helper_(settings_->build_settings()) {
30 }
31
32 NinjaTargetWriter::~NinjaTargetWriter() {
33 }
34
35 // static
36 void NinjaTargetWriter::RunAndWriteFile(const Target* target,
37                                         const Toolchain* toolchain) {
38   const Settings* settings = target->settings();
39   NinjaHelper helper(settings->build_settings());
40
41   ScopedTrace trace(TraceItem::TRACE_FILE_WRITE,
42                     target->label().GetUserVisibleName(false));
43   trace.SetToolchain(settings->toolchain_label());
44
45   base::FilePath ninja_file(settings->build_settings()->GetFullPath(
46       helper.GetNinjaFileForTarget(target).GetSourceFile(
47           settings->build_settings())));
48
49   if (g_scheduler->verbose_logging())
50     g_scheduler->Log("Writing", FilePathToUTF8(ninja_file));
51
52   base::CreateDirectory(ninja_file.DirName());
53
54   // It's rediculously faster to write to a string and then write that to
55   // disk in one operation than to use an fstream here.
56   std::stringstream file;
57
58   // Call out to the correct sub-type of writer.
59   if (target->output_type() == Target::COPY_FILES) {
60     NinjaCopyTargetWriter writer(target, toolchain, file);
61     writer.Run();
62   } else if (target->output_type() == Target::ACTION ||
63              target->output_type() == Target::ACTION_FOREACH) {
64     NinjaActionTargetWriter writer(target, toolchain, file);
65     writer.Run();
66   } else if (target->output_type() == Target::GROUP) {
67     NinjaGroupTargetWriter writer(target, toolchain, file);
68     writer.Run();
69   } else if (target->output_type() == Target::EXECUTABLE ||
70              target->output_type() == Target::STATIC_LIBRARY ||
71              target->output_type() == Target::SHARED_LIBRARY ||
72              target->output_type() == Target::SOURCE_SET) {
73     NinjaBinaryTargetWriter writer(target, toolchain, file);
74     writer.Run();
75   } else {
76     CHECK(0);
77   }
78
79   std::string contents = file.str();
80   base::WriteFile(ninja_file, contents.c_str(),
81                   static_cast<int>(contents.size()));
82 }
83
84 std::string NinjaTargetWriter::WriteInputDepsStampAndGetDep(
85     const std::vector<const Target*>& extra_hard_deps) const {
86   // For an action (where we run a script only once) the sources are the same
87   // as the source prereqs.
88   bool list_sources_as_input_deps = (target_->output_type() == Target::ACTION);
89
90   // Actions get implicit dependencies on the script itself.
91   bool add_script_source_as_dep =
92       (target_->output_type() == Target::ACTION) ||
93       (target_->output_type() == Target::ACTION_FOREACH);
94
95   if (!add_script_source_as_dep &&
96       extra_hard_deps.empty() &&
97       target_->inputs().empty() &&
98       target_->recursive_hard_deps().empty() &&
99       (!list_sources_as_input_deps || target_->sources().empty()) &&
100       toolchain_->deps().empty())
101     return std::string();  // No input/hard deps.
102
103   // One potential optimization is if there are few input dependencies (or
104   // potentially few sources that depend on these) it's better to just write
105   // all hard deps on each sources line than have this intermediate stamp. We
106   // do the stamp file because duplicating all the order-only deps for each
107   // source file can really explode the ninja file but this won't be the most
108   // optimal thing in all cases.
109
110   OutputFile input_stamp_file = helper_.GetTargetOutputDir(target_);
111   input_stamp_file.value().append(target_->label().name());
112   input_stamp_file.value().append(".inputdeps.stamp");
113
114   std::ostringstream stamp_file_stream;
115   path_output_.WriteFile(stamp_file_stream, input_stamp_file);
116   std::string stamp_file_string = stamp_file_stream.str();
117
118   out_ << "build " << stamp_file_string << ": " +
119       helper_.GetRulePrefix(settings_) + "stamp";
120
121   // Script file (if applicable).
122   if (add_script_source_as_dep) {
123     out_ << " ";
124     path_output_.WriteFile(out_, target_->action_values().script());
125   }
126
127   // Input files are order-only deps.
128   const Target::FileList& prereqs = target_->inputs();
129   for (size_t i = 0; i < prereqs.size(); i++) {
130     out_ << " ";
131     path_output_.WriteFile(out_, prereqs[i]);
132   }
133   if (list_sources_as_input_deps) {
134     const Target::FileList& sources = target_->sources();
135     for (size_t i = 0; i < sources.size(); i++) {
136       out_ << " ";
137       path_output_.WriteFile(out_, sources[i]);
138     }
139   }
140
141   // Add on any hard deps that are direct or indirect dependencies.
142   const std::set<const Target*>& hard_deps = target_->recursive_hard_deps();
143   for (std::set<const Target*>::const_iterator i = hard_deps.begin();
144        i != hard_deps.end(); ++i) {
145     out_ << " ";
146     path_output_.WriteFile(out_, helper_.GetTargetOutputFile(*i));
147   }
148
149   // Toolchain dependencies. These must be resolved before doing anything.
150   // This just writs all toolchain deps for simplicity. If we find that
151   // toolchains often have more than one dependency, we could consider writing
152   // a toolchain-specific stamp file and only include the stamp here.
153   const LabelTargetVector& toolchain_deps = toolchain_->deps();
154   for (size_t i = 0; i < toolchain_deps.size(); i++) {
155     out_ << " ";
156     path_output_.WriteFile(out_,
157                            helper_.GetTargetOutputFile(toolchain_deps[i].ptr));
158   }
159
160   // Extra hard deps passed in.
161   for (size_t i = 0; i < extra_hard_deps.size(); i++) {
162     out_ << " ";
163     path_output_.WriteFile(out_,
164         helper_.GetTargetOutputFile(extra_hard_deps[i]));
165   }
166
167   out_ << "\n";
168   return " | " + stamp_file_string;
169 }