Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(756)

Side by Side Diff: tools/gn/ninja_helper.cc

Issue 440333002: Support more configurability in GN toolchains (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: unsigned check Created 6 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « tools/gn/ninja_helper.h ('k') | tools/gn/ninja_helper_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
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_helper.h"
6
7 #include "base/logging.h"
8 #include "base/strings/string_util.h"
9 #include "tools/gn/filesystem_utils.h"
10 #include "tools/gn/string_utils.h"
11 #include "tools/gn/target.h"
12
13 namespace {
14
15 const char kObjectDirNoSlash[] = "obj";
16
17 } // namespace
18
19 NinjaHelper::NinjaHelper(const BuildSettings* build_settings)
20 : build_settings_(build_settings) {
21 build_to_src_no_last_slash_ = build_settings->build_to_source_dir_string();
22 if (!build_to_src_no_last_slash_.empty() &&
23 build_to_src_no_last_slash_[build_to_src_no_last_slash_.size() - 1] ==
24 '/')
25 build_to_src_no_last_slash_.resize(build_to_src_no_last_slash_.size() - 1);
26
27 build_to_src_system_no_last_slash_ = build_to_src_no_last_slash_;
28 }
29
30 NinjaHelper::~NinjaHelper() {
31 }
32
33 std::string NinjaHelper::GetTopleveOutputDir() const {
34 return kObjectDirNoSlash;
35 }
36
37 OutputFile NinjaHelper::GetTargetOutputDir(const Target* target) const {
38 OutputFile ret(target->settings()->toolchain_output_subdir());
39 ret.value().append(kObjectDirNoSlash);
40 AppendStringPiece(&ret.value(),
41 target->label().dir().SourceAbsoluteWithOneSlash());
42 return ret;
43 }
44
45 OutputFile NinjaHelper::GetNinjaFileForTarget(const Target* target) const {
46 OutputFile ret = GetTargetOutputDir(target);
47 ret.value().append(target->label().name());
48 ret.value().append(".ninja");
49 return ret;
50 }
51
52 OutputFile NinjaHelper::GetNinjaFileForToolchain(
53 const Settings* settings) const {
54 OutputFile ret;
55 ret.value().append(settings->toolchain_output_subdir().value());
56 ret.value().append("toolchain.ninja");
57 return ret;
58 }
59
60 // In Python, GypPathToUniqueOutput does the qualification. The only case where
61 // the Python version doesn't qualify the name is for target outputs, which we
62 // handle in a separate function.
63 OutputFile NinjaHelper::GetOutputFileForSource(
64 const Target* target,
65 const SourceFile& source,
66 SourceFileType type) const {
67 // Extract the filename and remove the extension (keep the dot).
68 base::StringPiece filename = FindFilename(&source.value());
69 std::string name(filename.data(), filename.size());
70 size_t extension_offset = FindExtensionOffset(name);
71 CHECK(extension_offset != std::string::npos);
72 name.resize(extension_offset);
73
74 // Append the new extension.
75 switch (type) {
76 case SOURCE_ASM:
77 case SOURCE_C:
78 case SOURCE_CC:
79 case SOURCE_M:
80 case SOURCE_MM:
81 case SOURCE_S:
82 name.append(target->settings()->IsWin() ? "obj" : "o");
83 break;
84
85 case SOURCE_RC:
86 name.append("res");
87 break;
88
89 // Pass .o/.obj files through unchanged.
90 case SOURCE_O: {
91 // System-absolute file names get preserved (they don't need to be
92 // rebased relative to the build dir).
93 if (source.is_system_absolute())
94 return OutputFile(source.value());
95
96 // Files that are already inside the build dir should not be made
97 // relative to the source tree. Doing so will insert an unnecessary
98 // "../.." into the path which won't match the corresponding target
99 // name in ninja.
100 CHECK(build_settings_->build_dir().is_source_absolute());
101 CHECK(source.is_source_absolute());
102 if (StartsWithASCII(source.value(),
103 build_settings_->build_dir().value(),
104 true)) {
105 return OutputFile(
106 source.value().substr(
107 build_settings_->build_dir().value().size()));
108 }
109
110 // Construct the relative location of the file from the build dir.
111 OutputFile ret(build_to_src_no_last_slash());
112 source.SourceAbsoluteWithOneSlash().AppendToString(&ret.value());
113 return ret;
114 }
115
116 case SOURCE_H:
117 case SOURCE_UNKNOWN:
118 NOTREACHED();
119 return OutputFile();
120 }
121
122 // Use the scheme <path>/<target>.<name>.<extension> so that all output
123 // names are unique to different targets.
124
125 // This will look like "obj" or "toolchain_name/obj".
126 OutputFile ret(target->settings()->toolchain_output_subdir());
127 ret.value().append(kObjectDirNoSlash);
128
129 // Find the directory, assume it starts with two slashes, and trim to one.
130 base::StringPiece dir = FindDir(&source.value());
131 CHECK(dir.size() >= 2 && dir[0] == '/' && dir[1] == '/')
132 << "Source file isn't in the source repo: " << dir;
133 AppendStringPiece(&ret.value(), dir.substr(1));
134
135 ret.value().append(target->label().name());
136 ret.value().append(".");
137 ret.value().append(name);
138 return ret;
139 }
140
141 OutputFile NinjaHelper::GetTargetOutputFile(const Target* target) const {
142 OutputFile ret;
143
144 // Use the output name if given, fall back to target name if not.
145 const std::string& name = target->output_name().empty() ?
146 target->label().name() : target->output_name();
147
148 // This is prepended to the output file name. Some platforms get "lib"
149 // prepended to library names. but be careful not to make a duplicate (e.g.
150 // some targets like "libxml" already have the "lib" in the name).
151 const char* prefix;
152 if (!target->settings()->IsWin() &&
153 (target->output_type() == Target::SHARED_LIBRARY ||
154 target->output_type() == Target::STATIC_LIBRARY) &&
155 name.compare(0, 3, "lib") != 0)
156 prefix = "lib";
157 else
158 prefix = "";
159
160 const char* extension;
161 if (target->output_extension().empty()) {
162 if (target->output_type() == Target::GROUP ||
163 target->output_type() == Target::SOURCE_SET ||
164 target->output_type() == Target::COPY_FILES ||
165 target->output_type() == Target::ACTION ||
166 target->output_type() == Target::ACTION_FOREACH) {
167 extension = "stamp";
168 } else {
169 extension = GetExtensionForOutputType(target->output_type(),
170 target->settings()->target_os());
171 }
172 } else {
173 extension = target->output_extension().c_str();
174 }
175
176 // Everything goes into the toolchain directory (which will be empty for the
177 // default toolchain, and will end in a slash otherwise).
178 ret.value().append(target->settings()->toolchain_output_subdir().value());
179
180 // Binaries and shared libraries go into the toolchain root.
181 if (target->output_type() == Target::EXECUTABLE ||
182 target->output_type() == Target::SHARED_LIBRARY) {
183 // Generate a name like "<toolchain>/<prefix><name>.<extension>".
184 ret.value().append(prefix);
185 ret.value().append(name);
186 if (extension[0]) {
187 ret.value().push_back('.');
188 ret.value().append(extension);
189 }
190 return ret;
191 }
192
193 // Everything else goes next to the target's .ninja file like
194 // "<toolchain>/obj/<path>/<name>.<extension>".
195 ret.value().append(kObjectDirNoSlash);
196 AppendStringPiece(&ret.value(),
197 target->label().dir().SourceAbsoluteWithOneSlash());
198 ret.value().append(prefix);
199 ret.value().append(name);
200 if (extension[0]) {
201 ret.value().push_back('.');
202 ret.value().append(extension);
203 }
204 return ret;
205 }
206
207 std::string NinjaHelper::GetRulePrefix(const Settings* settings) const {
208 // Don't prefix the default toolchain so it looks prettier, prefix everything
209 // else.
210 if (settings->is_default())
211 return std::string(); // Default toolchain has no prefix.
212 return settings->toolchain_label().name() + "_";
213 }
214
215 std::string NinjaHelper::GetRuleForSourceType(const Settings* settings,
216 SourceFileType type) const {
217 // This function may be hot since it will be called for every source file
218 // in the tree. We could cache the results to avoid making a string for
219 // every invocation.
220 std::string prefix = GetRulePrefix(settings);
221
222 if (type == SOURCE_C)
223 return prefix + "cc";
224 if (type == SOURCE_CC)
225 return prefix + "cxx";
226 if (type == SOURCE_M)
227 return prefix + "objc";
228 if (type == SOURCE_MM)
229 return prefix + "objcxx";
230 if (type == SOURCE_RC)
231 return prefix + "rc";
232 if (type == SOURCE_S)
233 return prefix + "cc"; // Assembly files just get compiled by CC.
234
235 // TODO(brettw) asm files.
236
237 // .obj files have no rules to make them (they're already built) so we return
238 // the enpty string for SOURCE_O.
239 return std::string();
240 }
OLDNEW
« no previous file with comments | « tools/gn/ninja_helper.h ('k') | tools/gn/ninja_helper_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698