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.
8 #include "testing/gtest/include/gtest/gtest.h"
9 #include "tools/gn/file_template.h"
10 #include "tools/gn/ninja_action_target_writer.h"
11 #include "tools/gn/test_with_scope.h"
13 TEST(NinjaActionTargetWriter
, WriteOutputFilesForBuildLine
) {
15 setup
.build_settings()->SetBuildDir(SourceDir("//out/Debug/"));
16 Target
target(setup
.settings(), Label(SourceDir("//foo/"), "bar"));
18 target
.action_values().outputs().push_back(
19 SourceFile("//out/Debug/gen/a b{{source_name_part}}.h"));
20 target
.action_values().outputs().push_back(
21 SourceFile("//out/Debug/gen/{{source_name_part}}.cc"));
23 std::ostringstream out
;
24 NinjaActionTargetWriter
writer(&target
, setup
.toolchain(), out
);
26 FileTemplate output_template
= writer
.GetOutputTemplate();
28 SourceFile
source("//foo/bar.in");
29 std::vector
<OutputFile
> output_files
;
30 writer
.WriteOutputFilesForBuildLine(output_template
, source
, &output_files
);
32 EXPECT_EQ(" gen/a$ bbar.h gen/bar.cc", out
.str());
35 TEST(NinjaActionTargetWriter
, WriteArgsSubstitutions
) {
37 setup
.build_settings()->SetBuildDir(SourceDir("//out/Debug/"));
38 Target
target(setup
.settings(), Label(SourceDir("//foo/"), "bar"));
40 std::ostringstream out
;
41 NinjaActionTargetWriter
writer(&target
, setup
.toolchain(), out
);
43 std::vector
<std::string
> args
;
45 args
.push_back("{{source}}");
46 args
.push_back("--out=foo bar{{source_name_part}}.o");
47 FileTemplate
args_template(setup
.settings(), args
);
49 writer
.WriteArgsSubstitutions(SourceFile("//foo/b ar.in"), args_template
);
51 EXPECT_EQ(" source = \"../../foo/b$ ar.in\"\n"
52 " source_name_part = \"b$ ar\"\n",
55 EXPECT_EQ(" source = ../../foo/b\\$ ar.in\n"
56 " source_name_part = b\\$ ar\n",
61 // Makes sure that we write sources as input dependencies for actions with
62 // both sources and inputs (ACTION_FOREACH treats the sources differently).
63 TEST(NinjaActionTargetWriter
, ActionWithSources
) {
65 setup
.build_settings()->SetBuildDir(SourceDir("//out/Debug/"));
66 Target
target(setup
.settings(), Label(SourceDir("//foo/"), "bar"));
67 target
.set_output_type(Target::ACTION
);
69 target
.action_values().set_script(SourceFile("//foo/script.py"));
71 target
.sources().push_back(SourceFile("//foo/source.txt"));
72 target
.inputs().push_back(SourceFile("//foo/included.txt"));
74 target
.action_values().outputs().push_back(
75 SourceFile("//out/Debug/foo.out"));
79 setup
.settings()->set_target_os(Settings::LINUX
);
80 setup
.build_settings()->set_python_path(base::FilePath(FILE_PATH_LITERAL(
83 std::ostringstream out
;
84 NinjaActionTargetWriter
writer(&target
, setup
.toolchain(), out
);
87 const char expected_linux
[] =
88 "rule __foo_bar___rule\n"
89 " command = /usr/bin/python ../../foo/script.py\n"
90 " description = ACTION //foo:bar()\n"
92 "build obj/foo/bar.inputdeps.stamp: stamp ../../foo/script.py "
93 "../../foo/included.txt ../../foo/source.txt\n"
95 "build foo.out: __foo_bar___rule | obj/foo/bar.inputdeps.stamp\n"
97 "build obj/foo/bar.stamp: stamp foo.out\n";
98 EXPECT_EQ(expected_linux
, out
.str());
103 // Note: we use forward slashes here so that the output will be the same on
104 // Linux and Windows.
105 setup
.build_settings()->set_python_path(base::FilePath(FILE_PATH_LITERAL(
106 "C:/python/python.exe")));
107 setup
.settings()->set_target_os(Settings::WIN
);
109 std::ostringstream out
;
110 NinjaActionTargetWriter
writer(&target
, setup
.toolchain(), out
);
113 const char expected_win
[] =
114 "rule __foo_bar___rule\n"
115 " command = C$:/python/python.exe gyp-win-tool action-wrapper environment.x86 __foo_bar___rule.$unique_name.rsp\n"
116 " description = ACTION //foo:bar()\n"
118 " rspfile = __foo_bar___rule.$unique_name.rsp\n"
119 " rspfile_content = C$:/python/python.exe ../../foo/script.py\n"
120 "build obj/foo/bar.inputdeps.stamp: stamp ../../foo/script.py "
121 "../../foo/included.txt ../../foo/source.txt\n"
123 "build foo.out: __foo_bar___rule | obj/foo/bar.inputdeps.stamp\n"
125 "build obj/foo/bar.stamp: stamp foo.out\n";
126 EXPECT_EQ(expected_win
, out
.str());
130 TEST(NinjaActionTargetWriter
, ForEach
) {
132 setup
.build_settings()->SetBuildDir(SourceDir("//out/Debug/"));
134 // Some dependencies that the action can depend on. Use actions for these
135 // so they have a nice platform-independent stamp file that can appear in the
136 // output (rather than having to worry about how the current platform names
138 Target
dep(setup
.settings(), Label(SourceDir("//foo/"), "dep"));
139 dep
.set_output_type(Target::ACTION
);
140 Target
datadep(setup
.settings(), Label(SourceDir("//foo/"), "datadep"));
141 datadep
.set_output_type(Target::ACTION
);
143 Target
target(setup
.settings(), Label(SourceDir("//foo/"), "bar"));
144 target
.set_output_type(Target::ACTION_FOREACH
);
145 target
.deps().push_back(LabelTargetPair(&dep
));
146 target
.datadeps().push_back(LabelTargetPair(&datadep
));
148 target
.sources().push_back(SourceFile("//foo/input1.txt"));
149 target
.sources().push_back(SourceFile("//foo/input2.txt"));
151 target
.action_values().set_script(SourceFile("//foo/script.py"));
153 target
.action_values().args().push_back("-i");
154 target
.action_values().args().push_back("{{source}}");
155 target
.action_values().args().push_back(
156 "--out=foo bar{{source_name_part}}.o");
158 target
.action_values().outputs().push_back(
159 SourceFile("//out/Debug/{{source_name_part}}.out"));
161 target
.inputs().push_back(SourceFile("//foo/included.txt"));
165 setup
.settings()->set_target_os(Settings::LINUX
);
166 setup
.build_settings()->set_python_path(base::FilePath(FILE_PATH_LITERAL(
167 "/usr/bin/python")));
169 std::ostringstream out
;
170 NinjaActionTargetWriter
writer(&target
, setup
.toolchain(), out
);
173 const char expected_linux
[] =
174 "rule __foo_bar___rule\n"
175 " command = /usr/bin/python ../../foo/script.py -i ${source} "
176 // Escaping is different between Windows and Posix.
178 "\"--out=foo$ bar${source_name_part}.o\"\n"
180 "--out=foo\\$ bar${source_name_part}.o\n"
182 " description = ACTION //foo:bar()\n"
184 "build obj/foo/bar.inputdeps.stamp: stamp ../../foo/script.py "
185 "../../foo/included.txt obj/foo/dep.stamp\n"
187 "build input1.out: __foo_bar___rule ../../foo/input1.txt | "
188 "obj/foo/bar.inputdeps.stamp\n"
189 " source = ../../foo/input1.txt\n"
190 " source_name_part = input1\n"
191 "build input2.out: __foo_bar___rule ../../foo/input2.txt | "
192 "obj/foo/bar.inputdeps.stamp\n"
193 " source = ../../foo/input2.txt\n"
194 " source_name_part = input2\n"
196 "build obj/foo/bar.stamp: "
197 "stamp input1.out input2.out obj/foo/datadep.stamp\n";
199 std::string out_str
= out
.str();
201 std::replace(out_str
.begin(), out_str
.end(), '\\', '/');
203 EXPECT_EQ(expected_linux
, out_str
);
208 setup
.build_settings()->set_python_path(base::FilePath(FILE_PATH_LITERAL(
209 "C:/python/python.exe")));
210 setup
.settings()->set_target_os(Settings::WIN
);
212 std::ostringstream out
;
213 NinjaActionTargetWriter
writer(&target
, setup
.toolchain(), out
);
216 const char expected_win
[] =
217 "rule __foo_bar___rule\n"
218 " command = C$:/python/python.exe gyp-win-tool action-wrapper "
219 "environment.x86 __foo_bar___rule.$unique_name.rsp\n"
220 " description = ACTION //foo:bar()\n"
222 " rspfile = __foo_bar___rule.$unique_name.rsp\n"
223 " rspfile_content = C$:/python/python.exe ../../foo/script.py -i "
225 "${source} \"--out=foo$ bar${source_name_part}.o\"\n"
227 "${source} --out=foo\\$ bar${source_name_part}.o\n"
229 "build obj/foo/bar.inputdeps.stamp: stamp ../../foo/script.py "
230 "../../foo/included.txt obj/foo/dep.stamp\n"
232 "build input1.out: __foo_bar___rule ../../foo/input1.txt | "
233 "obj/foo/bar.inputdeps.stamp\n"
235 " source = ../../foo/input1.txt\n"
236 " source_name_part = input1\n"
237 "build input2.out: __foo_bar___rule ../../foo/input2.txt | "
238 "obj/foo/bar.inputdeps.stamp\n"
240 " source = ../../foo/input2.txt\n"
241 " source_name_part = input2\n"
243 "build obj/foo/bar.stamp: "
244 "stamp input1.out input2.out obj/foo/datadep.stamp\n";
245 EXPECT_EQ(expected_win
, out
.str());
249 TEST(NinjaActionTargetWriter
, ForEachWithDepfile
) {
251 setup
.build_settings()->SetBuildDir(SourceDir("//out/Debug/"));
252 Target
target(setup
.settings(), Label(SourceDir("//foo/"), "bar"));
253 target
.set_output_type(Target::ACTION_FOREACH
);
255 target
.sources().push_back(SourceFile("//foo/input1.txt"));
256 target
.sources().push_back(SourceFile("//foo/input2.txt"));
258 target
.action_values().set_script(SourceFile("//foo/script.py"));
259 target
.action_values().set_depfile(
260 SourceFile("//out/Debug/gen/{{source_name_part}}.d"));
262 target
.action_values().args().push_back("-i");
263 target
.action_values().args().push_back("{{source}}");
264 target
.action_values().args().push_back(
265 "--out=foo bar{{source_name_part}}.o");
267 target
.action_values().outputs().push_back(
268 SourceFile("//out/Debug/{{source_name_part}}.out"));
270 target
.inputs().push_back(SourceFile("//foo/included.txt"));
274 setup
.settings()->set_target_os(Settings::LINUX
);
275 setup
.build_settings()->set_python_path(base::FilePath(FILE_PATH_LITERAL(
276 "/usr/bin/python")));
278 std::ostringstream out
;
279 NinjaActionTargetWriter
writer(&target
, setup
.toolchain(), out
);
282 const char expected_linux
[] =
283 "rule __foo_bar___rule\n"
284 " command = /usr/bin/python ../../foo/script.py -i ${source} "
286 "\"--out=foo$ bar${source_name_part}.o\"\n"
288 "--out=foo\\$ bar${source_name_part}.o\n"
290 " description = ACTION //foo:bar()\n"
292 "build obj/foo/bar.inputdeps.stamp: stamp ../../foo/script.py "
293 "../../foo/included.txt\n"
295 "build input1.out: __foo_bar___rule ../../foo/input1.txt"
296 " | obj/foo/bar.inputdeps.stamp\n"
297 " source = ../../foo/input1.txt\n"
298 " source_name_part = input1\n"
299 " depfile = gen/input1.d\n"
300 "build input2.out: __foo_bar___rule ../../foo/input2.txt"
301 " | obj/foo/bar.inputdeps.stamp\n"
302 " source = ../../foo/input2.txt\n"
303 " source_name_part = input2\n"
304 " depfile = gen/input2.d\n"
306 "build obj/foo/bar.stamp: stamp input1.out input2.out\n";
307 EXPECT_EQ(expected_linux
, out
.str());
312 setup
.build_settings()->set_python_path(base::FilePath(FILE_PATH_LITERAL(
313 "C:/python/python.exe")));
314 setup
.settings()->set_target_os(Settings::WIN
);
316 std::ostringstream out
;
317 NinjaActionTargetWriter
writer(&target
, setup
.toolchain(), out
);
320 const char expected_win
[] =
321 "rule __foo_bar___rule\n"
322 " command = C$:/python/python.exe gyp-win-tool action-wrapper "
323 "environment.x86 __foo_bar___rule.$unique_name.rsp\n"
324 " description = ACTION //foo:bar()\n"
326 " rspfile = __foo_bar___rule.$unique_name.rsp\n"
327 " rspfile_content = C$:/python/python.exe ../../foo/script.py -i "
329 "${source} \"--out=foo$ bar${source_name_part}.o\"\n"
331 "${source} --out=foo\\$ bar${source_name_part}.o\n"
333 "build obj/foo/bar.inputdeps.stamp: stamp ../../foo/script.py "
334 "../../foo/included.txt\n"
336 "build input1.out: __foo_bar___rule ../../foo/input1.txt"
337 " | obj/foo/bar.inputdeps.stamp\n"
339 " source = ../../foo/input1.txt\n"
340 " source_name_part = input1\n"
341 " depfile = gen/input1.d\n"
342 "build input2.out: __foo_bar___rule ../../foo/input2.txt"
343 " | obj/foo/bar.inputdeps.stamp\n"
345 " source = ../../foo/input2.txt\n"
346 " source_name_part = input2\n"
347 " depfile = gen/input2.d\n"
349 "build obj/foo/bar.stamp: stamp input1.out input2.out\n";
350 EXPECT_EQ(expected_win
, out
.str());