Upstream version 7.36.149.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/file_template.h"
13 #include "tools/gn/ninja_action_target_writer.h"
14 #include "tools/gn/ninja_binary_target_writer.h"
15 #include "tools/gn/ninja_copy_target_writer.h"
16 #include "tools/gn/ninja_group_target_writer.h"
17 #include "tools/gn/scheduler.h"
18 #include "tools/gn/string_utils.h"
19 #include "tools/gn/target.h"
20 #include "tools/gn/trace.h"
21
22 NinjaTargetWriter::NinjaTargetWriter(const Target* target,
23                                      const Toolchain* toolchain,
24                                      std::ostream& out)
25     : settings_(target->settings()),
26       target_(target),
27       toolchain_(toolchain),
28       out_(out),
29       path_output_(settings_->build_settings()->build_dir(),
30                    ESCAPE_NINJA,
31                    false),
32       helper_(settings_->build_settings()) {
33 }
34
35 NinjaTargetWriter::~NinjaTargetWriter() {
36 }
37
38 // static
39 void NinjaTargetWriter::RunAndWriteFile(const Target* target,
40                                         const Toolchain* toolchain) {
41   const Settings* settings = target->settings();
42   NinjaHelper helper(settings->build_settings());
43
44   ScopedTrace trace(TraceItem::TRACE_FILE_WRITE,
45                     target->label().GetUserVisibleName(false));
46   trace.SetToolchain(settings->toolchain_label());
47
48   base::FilePath ninja_file(settings->build_settings()->GetFullPath(
49       helper.GetNinjaFileForTarget(target).GetSourceFile(
50           settings->build_settings())));
51
52   if (g_scheduler->verbose_logging())
53     g_scheduler->Log("Writing", FilePathToUTF8(ninja_file));
54
55   base::CreateDirectory(ninja_file.DirName());
56
57   // It's rediculously faster to write to a string and then write that to
58   // disk in one operation than to use an fstream here.
59   std::stringstream file;
60
61   // Call out to the correct sub-type of writer.
62   if (target->output_type() == Target::COPY_FILES) {
63     NinjaCopyTargetWriter writer(target, toolchain, file);
64     writer.Run();
65   } else if (target->output_type() == Target::ACTION ||
66              target->output_type() == Target::ACTION_FOREACH) {
67     NinjaActionTargetWriter writer(target, toolchain, file);
68     writer.Run();
69   } else if (target->output_type() == Target::GROUP) {
70     NinjaGroupTargetWriter writer(target, toolchain, file);
71     writer.Run();
72   } else if (target->output_type() == Target::EXECUTABLE ||
73              target->output_type() == Target::STATIC_LIBRARY ||
74              target->output_type() == Target::SHARED_LIBRARY ||
75              target->output_type() == Target::SOURCE_SET) {
76     NinjaBinaryTargetWriter writer(target, toolchain, file);
77     writer.Run();
78   } else {
79     CHECK(0);
80   }
81
82   std::string contents = file.str();
83   base::WriteFile(ninja_file, contents.c_str(),
84                   static_cast<int>(contents.size()));
85 }
86
87 std::string NinjaTargetWriter::WriteInputDepsStampAndGetDep(
88     const std::vector<const Target*>& extra_hard_deps) const {
89   // For an action (where we run a script only once) the sources are the same
90   // as the source prereqs.
91   bool list_sources_as_input_deps = target_->output_type() == Target::ACTION;
92
93   if (extra_hard_deps.empty() &&
94       target_->source_prereqs().empty() &&
95       target_->recursive_hard_deps().empty() &&
96       (!list_sources_as_input_deps || target_->sources().empty()))
97     return std::string();  // No input/hard deps.
98
99   // One potential optimization is if there are few input dependencies (or
100   // potentially few sources that depend on these) it's better to just write
101   // all hard deps on each sources line than have this intermediate stamp. We
102   // do the stamp file because duplicating all the order-only deps for each
103   // source file can really explode the ninja file but this won't be the most
104   // optimal thing in all cases.
105
106   OutputFile input_stamp_file = helper_.GetTargetOutputDir(target_);
107   input_stamp_file.value().append(target_->label().name());
108   input_stamp_file.value().append(".inputdeps.stamp");
109
110   std::ostringstream stamp_file_stream;
111   path_output_.WriteFile(stamp_file_stream, input_stamp_file);
112   std::string stamp_file_string = stamp_file_stream.str();
113
114   out_ << "build " << stamp_file_string << ": stamp";
115
116   // Input files are order-only deps.
117   const Target::FileList& prereqs = target_->source_prereqs();
118   for (size_t i = 0; i < prereqs.size(); i++) {
119     out_ << " ";
120     path_output_.WriteFile(out_, prereqs[i]);
121   }
122   if (list_sources_as_input_deps) {
123     const Target::FileList& sources = target_->sources();
124     for (size_t i = 0; i < sources.size(); i++) {
125       out_ << " ";
126       path_output_.WriteFile(out_, sources[i]);
127     }
128   }
129
130   // Add on any hard deps that are direct or indirect dependencies.
131   const std::set<const Target*>& hard_deps = target_->recursive_hard_deps();
132   for (std::set<const Target*>::const_iterator i = hard_deps.begin();
133        i != hard_deps.end(); ++i) {
134     out_ << " ";
135     path_output_.WriteFile(out_, helper_.GetTargetOutputFile(*i));
136   }
137
138   // Extra hard deps passed in.
139   for (size_t i = 0; i < extra_hard_deps.size(); i++) {
140     out_ << " ";
141     path_output_.WriteFile(out_,
142         helper_.GetTargetOutputFile(extra_hard_deps[i]));
143   }
144
145   out_ << "\n";
146   return " | " + stamp_file_string;
147 }
148
149 FileTemplate NinjaTargetWriter::GetOutputTemplate() const {
150   const Target::FileList& outputs = target_->action_values().outputs();
151   std::vector<std::string> output_template_args;
152   for (size_t i = 0; i < outputs.size(); i++) {
153     // All outputs should be in the output dir.
154     output_template_args.push_back(
155         RemovePrefix(outputs[i].value(),
156                      settings_->build_settings()->build_dir().value()));
157   }
158   return FileTemplate(output_template_args);
159 }