[refactor] More post-NSS WebCrypto cleanups (utility functions).
[chromium-blink-merge.git] / tools / gn / ninja_binary_target_writer_unittest.cc
blob4bb055337d31ff260d459c7c5a6492a0d5a393a2
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.
5 #include <sstream>
7 #include "testing/gtest/include/gtest/gtest.h"
8 #include "tools/gn/ninja_binary_target_writer.h"
9 #include "tools/gn/scheduler.h"
10 #include "tools/gn/target.h"
11 #include "tools/gn/test_with_scope.h"
13 TEST(NinjaBinaryTargetWriter, SourceSet) {
14 TestWithScope setup;
15 Err err;
17 setup.build_settings()->SetBuildDir(SourceDir("//out/Debug/"));
18 setup.settings()->set_target_os(Settings::WIN);
20 Target target(setup.settings(), Label(SourceDir("//foo/"), "bar"));
21 target.set_output_type(Target::SOURCE_SET);
22 target.visibility().SetPublic();
23 target.sources().push_back(SourceFile("//foo/input1.cc"));
24 target.sources().push_back(SourceFile("//foo/input2.cc"));
25 // Also test object files, which should be just passed through to the
26 // dependents to link.
27 target.sources().push_back(SourceFile("//foo/input3.o"));
28 target.sources().push_back(SourceFile("//foo/input4.obj"));
29 target.SetToolchain(setup.toolchain());
30 ASSERT_TRUE(target.OnResolved(&err));
32 // Source set itself.
34 std::ostringstream out;
35 NinjaBinaryTargetWriter writer(&target, out);
36 writer.Run();
38 const char expected[] =
39 "defines =\n"
40 "include_dirs =\n"
41 "cflags =\n"
42 "cflags_cc =\n"
43 "root_out_dir = .\n"
44 "target_out_dir = obj/foo\n"
45 "target_output_name = bar\n"
46 "\n"
47 "build obj/foo/bar.input1.o: cxx ../../foo/input1.cc\n"
48 "build obj/foo/bar.input2.o: cxx ../../foo/input2.cc\n"
49 "\n"
50 "build obj/foo/bar.stamp: stamp obj/foo/bar.input1.o "
51 "obj/foo/bar.input2.o ../../foo/input3.o ../../foo/input4.obj\n";
52 std::string out_str = out.str();
53 EXPECT_EQ(expected, out_str);
56 // A shared library that depends on the source set.
57 Target shlib_target(setup.settings(), Label(SourceDir("//foo/"), "shlib"));
58 shlib_target.set_output_type(Target::SHARED_LIBRARY);
59 shlib_target.public_deps().push_back(LabelTargetPair(&target));
60 shlib_target.SetToolchain(setup.toolchain());
61 ASSERT_TRUE(shlib_target.OnResolved(&err));
64 std::ostringstream out;
65 NinjaBinaryTargetWriter writer(&shlib_target, out);
66 writer.Run();
68 const char expected[] =
69 "defines =\n"
70 "include_dirs =\n"
71 "root_out_dir = .\n"
72 "target_out_dir = obj/foo\n"
73 "target_output_name = libshlib\n"
74 "\n"
75 "\n"
76 // Ordering of the obj files here should come out in the order
77 // specified, with the target's first, followed by the source set's, in
78 // order.
79 "build ./libshlib.so: solink obj/foo/bar.input1.o "
80 "obj/foo/bar.input2.o ../../foo/input3.o ../../foo/input4.obj "
81 "|| obj/foo/bar.stamp\n"
82 " ldflags =\n"
83 " libs =\n"
84 " output_extension = .so\n";
85 std::string out_str = out.str();
86 EXPECT_EQ(expected, out_str);
89 // A static library that depends on the source set (should not link it).
90 Target stlib_target(setup.settings(), Label(SourceDir("//foo/"), "stlib"));
91 stlib_target.set_output_type(Target::STATIC_LIBRARY);
92 stlib_target.public_deps().push_back(LabelTargetPair(&target));
93 stlib_target.SetToolchain(setup.toolchain());
94 ASSERT_TRUE(stlib_target.OnResolved(&err));
97 std::ostringstream out;
98 NinjaBinaryTargetWriter writer(&stlib_target, out);
99 writer.Run();
101 const char expected[] =
102 "defines =\n"
103 "include_dirs =\n"
104 "root_out_dir = .\n"
105 "target_out_dir = obj/foo\n"
106 "target_output_name = libstlib\n"
107 "\n"
108 "\n"
109 // There are no sources so there are no params to alink. (In practice
110 // this will probably fail in the archive tool.)
111 "build obj/foo/libstlib.a: alink || obj/foo/bar.stamp\n"
112 " ldflags =\n"
113 " libs =\n"
114 " output_extension = \n";
115 std::string out_str = out.str();
116 EXPECT_EQ(expected, out_str);
119 // Make the static library 'complete', which means it should be linked.
120 stlib_target.set_complete_static_lib(true);
122 std::ostringstream out;
123 NinjaBinaryTargetWriter writer(&stlib_target, out);
124 writer.Run();
126 const char expected[] =
127 "defines =\n"
128 "include_dirs =\n"
129 "root_out_dir = .\n"
130 "target_out_dir = obj/foo\n"
131 "target_output_name = libstlib\n"
132 "\n"
133 "\n"
134 // Ordering of the obj files here should come out in the order
135 // specified, with the target's first, followed by the source set's, in
136 // order.
137 "build obj/foo/libstlib.a: alink obj/foo/bar.input1.o "
138 "obj/foo/bar.input2.o ../../foo/input3.o ../../foo/input4.obj "
139 "|| obj/foo/bar.stamp\n"
140 " ldflags =\n"
141 " libs =\n"
142 " output_extension = \n";
143 std::string out_str = out.str();
144 EXPECT_EQ(expected, out_str);
148 // This tests that output extension overrides apply, and input dependencies
149 // are applied.
150 TEST(NinjaBinaryTargetWriter, ProductExtensionAndInputDeps) {
151 TestWithScope setup;
152 Err err;
154 setup.build_settings()->SetBuildDir(SourceDir("//out/Debug/"));
155 setup.settings()->set_target_os(Settings::LINUX);
157 // An action for our library to depend on.
158 Target action(setup.settings(), Label(SourceDir("//foo/"), "action"));
159 action.set_output_type(Target::ACTION_FOREACH);
160 action.visibility().SetPublic();
161 action.SetToolchain(setup.toolchain());
162 ASSERT_TRUE(action.OnResolved(&err));
164 // A shared library w/ the product_extension set to a custom value.
165 Target target(setup.settings(), Label(SourceDir("//foo/"), "shlib"));
166 target.set_output_type(Target::SHARED_LIBRARY);
167 target.set_output_extension(std::string("so.6"));
168 target.sources().push_back(SourceFile("//foo/input1.cc"));
169 target.sources().push_back(SourceFile("//foo/input2.cc"));
170 target.public_deps().push_back(LabelTargetPair(&action));
171 target.SetToolchain(setup.toolchain());
172 ASSERT_TRUE(target.OnResolved(&err));
174 std::ostringstream out;
175 NinjaBinaryTargetWriter writer(&target, out);
176 writer.Run();
178 const char expected[] =
179 "defines =\n"
180 "include_dirs =\n"
181 "cflags =\n"
182 "cflags_cc =\n"
183 "root_out_dir = .\n"
184 "target_out_dir = obj/foo\n"
185 "target_output_name = libshlib\n"
186 "\n"
187 "build obj/foo/shlib.inputdeps.stamp: stamp obj/foo/action.stamp\n"
188 "build obj/foo/libshlib.input1.o: cxx ../../foo/input1.cc"
189 " || obj/foo/shlib.inputdeps.stamp\n"
190 "build obj/foo/libshlib.input2.o: cxx ../../foo/input2.cc"
191 " || obj/foo/shlib.inputdeps.stamp\n"
192 "\n"
193 "build ./libshlib.so.6: solink obj/foo/libshlib.input1.o "
194 // The order-only dependency here is stricly unnecessary since the
195 // sources list this as an order-only dep. See discussion in the code
196 // that writes this.
197 "obj/foo/libshlib.input2.o || obj/foo/action.stamp\n"
198 " ldflags =\n"
199 " libs =\n"
200 " output_extension = .so.6\n";
202 std::string out_str = out.str();
203 EXPECT_EQ(expected, out_str);
206 TEST(NinjaBinaryTargetWriter, EmptyProductExtension) {
207 TestWithScope setup;
208 Err err;
210 setup.build_settings()->SetBuildDir(SourceDir("//out/Debug/"));
211 setup.settings()->set_target_os(Settings::LINUX);
213 // This test is the same as ProductExtension, except that
214 // we call set_output_extension("") and ensure that we still get the default.
215 Target target(setup.settings(), Label(SourceDir("//foo/"), "shlib"));
216 target.set_output_type(Target::SHARED_LIBRARY);
217 target.set_output_extension(std::string());
218 target.sources().push_back(SourceFile("//foo/input1.cc"));
219 target.sources().push_back(SourceFile("//foo/input2.cc"));
221 target.SetToolchain(setup.toolchain());
222 ASSERT_TRUE(target.OnResolved(&err));
224 std::ostringstream out;
225 NinjaBinaryTargetWriter writer(&target, out);
226 writer.Run();
228 const char expected[] =
229 "defines =\n"
230 "include_dirs =\n"
231 "cflags =\n"
232 "cflags_cc =\n"
233 "root_out_dir = .\n"
234 "target_out_dir = obj/foo\n"
235 "target_output_name = libshlib\n"
236 "\n"
237 "build obj/foo/libshlib.input1.o: cxx ../../foo/input1.cc\n"
238 "build obj/foo/libshlib.input2.o: cxx ../../foo/input2.cc\n"
239 "\n"
240 "build ./libshlib.so: solink obj/foo/libshlib.input1.o "
241 "obj/foo/libshlib.input2.o\n"
242 " ldflags =\n"
243 " libs =\n"
244 " output_extension = .so\n";
246 std::string out_str = out.str();
247 EXPECT_EQ(expected, out_str);
250 TEST(NinjaBinaryTargetWriter, SourceSetDataDeps) {
251 TestWithScope setup;
252 setup.build_settings()->SetBuildDir(SourceDir("//out/Debug/"));
253 setup.settings()->set_target_os(Settings::LINUX);
255 Err err;
257 // This target is a data (runtime) dependency of the intermediate target.
258 Target data(setup.settings(), Label(SourceDir("//foo/"), "data_target"));
259 data.set_output_type(Target::EXECUTABLE);
260 data.visibility().SetPublic();
261 data.SetToolchain(setup.toolchain());
262 ASSERT_TRUE(data.OnResolved(&err));
264 // Intermediate source set target.
265 Target inter(setup.settings(), Label(SourceDir("//foo/"), "inter"));
266 inter.set_output_type(Target::SOURCE_SET);
267 inter.visibility().SetPublic();
268 inter.data_deps().push_back(LabelTargetPair(&data));
269 inter.SetToolchain(setup.toolchain());
270 inter.sources().push_back(SourceFile("//foo/inter.cc"));
271 ASSERT_TRUE(inter.OnResolved(&err)) << err.message();
273 // Write out the intermediate target.
274 std::ostringstream inter_out;
275 NinjaBinaryTargetWriter inter_writer(&inter, inter_out);
276 inter_writer.Run();
278 // The intermediate source set will be a stamp file that depends on the
279 // object files, and will have an order-only dependency on its data dep and
280 // data file.
281 const char inter_expected[] =
282 "defines =\n"
283 "include_dirs =\n"
284 "cflags =\n"
285 "cflags_cc =\n"
286 "root_out_dir = .\n"
287 "target_out_dir = obj/foo\n"
288 "target_output_name = inter\n"
289 "\n"
290 "build obj/foo/inter.inter.o: cxx ../../foo/inter.cc\n"
291 "\n"
292 "build obj/foo/inter.stamp: stamp obj/foo/inter.inter.o || "
293 "./data_target\n";
294 EXPECT_EQ(inter_expected, inter_out.str());
296 // Final target.
297 Target exe(setup.settings(), Label(SourceDir("//foo/"), "exe"));
298 exe.set_output_type(Target::EXECUTABLE);
299 exe.public_deps().push_back(LabelTargetPair(&inter));
300 exe.SetToolchain(setup.toolchain());
301 exe.sources().push_back(SourceFile("//foo/final.cc"));
302 ASSERT_TRUE(exe.OnResolved(&err));
304 std::ostringstream final_out;
305 NinjaBinaryTargetWriter final_writer(&exe, final_out);
306 final_writer.Run();
308 // The final output depends on both object files (one from the final target,
309 // one from the source set) and has an order-only dependency on the source
310 // set's stamp file and the final target's data file. The source set stamp
311 // dependency will create an implicit order-only dependency on the data
312 // target.
313 const char final_expected[] =
314 "defines =\n"
315 "include_dirs =\n"
316 "cflags =\n"
317 "cflags_cc =\n"
318 "root_out_dir = .\n"
319 "target_out_dir = obj/foo\n"
320 "target_output_name = exe\n"
321 "\n"
322 "build obj/foo/exe.final.o: cxx ../../foo/final.cc\n"
323 "\n"
324 "build ./exe: link obj/foo/exe.final.o obj/foo/inter.inter.o || "
325 "obj/foo/inter.stamp\n"
326 " ldflags =\n"
327 " libs =\n"
328 " output_extension = \n";
329 EXPECT_EQ(final_expected, final_out.str());
332 TEST(NinjaBinaryTargetWriter, SharedLibraryModuleDefinitionFile) {
333 TestWithScope setup;
334 setup.build_settings()->SetBuildDir(SourceDir("//out/Debug/"));
335 setup.settings()->set_target_os(Settings::WIN);
337 Target shared_lib(setup.settings(), Label(SourceDir("//foo/"), "bar"));
338 shared_lib.set_output_type(Target::SHARED_LIBRARY);
339 shared_lib.SetToolchain(setup.toolchain());
340 shared_lib.sources().push_back(SourceFile("//foo/sources.cc"));
341 shared_lib.sources().push_back(SourceFile("//foo/bar.def"));
343 Err err;
344 ASSERT_TRUE(shared_lib.OnResolved(&err));
346 std::ostringstream out;
347 NinjaBinaryTargetWriter writer(&shared_lib, out);
348 writer.Run();
350 const char expected[] =
351 "defines =\n"
352 "include_dirs =\n"
353 "cflags =\n"
354 "cflags_cc =\n"
355 "root_out_dir = .\n"
356 "target_out_dir = obj/foo\n"
357 "target_output_name = libbar\n"
358 "\n"
359 "build obj/foo/libbar.sources.o: cxx ../../foo/sources.cc\n"
360 "\n"
361 "build ./libbar.so: solink obj/foo/libbar.sources.o | ../../foo/bar.def\n"
362 " ldflags = /DEF:../../foo/bar.def\n"
363 " libs =\n"
364 " output_extension = .so\n";
365 EXPECT_EQ(expected, out.str());
368 TEST(NinjaBinaryTargetWriter, WinPrecompiledHeaders) {
369 Err err;
371 // This setup's toolchain does not have precompiled headers defined.
372 TestWithScope setup;
374 // A precompiled header toolchain.
375 Settings pch_settings(setup.build_settings(), "withpch/");
376 Toolchain pch_toolchain(&pch_settings,
377 Label(SourceDir("//toolchain/"), "withpch"));
378 pch_settings.set_toolchain_label(pch_toolchain.label());
379 pch_settings.set_default_toolchain_label(setup.toolchain()->label());
381 // Declare a C++ compiler that supports PCH.
382 scoped_ptr<Tool> cxx_tool(new Tool);
383 TestWithScope::SetCommandForTool(
384 "c++ {{source}} {{cflags}} {{cflags_cc}} {{defines}} {{include_dirs}} "
385 "-o {{output}}",
386 cxx_tool.get());
387 cxx_tool->set_outputs(SubstitutionList::MakeForTest(
388 "{{source_out_dir}}/{{target_output_name}}.{{source_name_part}}.o"));
389 cxx_tool->set_precompiled_header_type(Tool::PCH_MSVC);
390 pch_toolchain.SetTool(Toolchain::TYPE_CXX, cxx_tool.Pass());
392 // Add a C compiler as well.
393 scoped_ptr<Tool> cc_tool(new Tool);
394 TestWithScope::SetCommandForTool(
395 "cc {{source}} {{cflags}} {{cflags_c}} {{defines}} {{include_dirs}} "
396 "-o {{output}}",
397 cc_tool.get());
398 cc_tool->set_outputs(SubstitutionList::MakeForTest(
399 "{{source_out_dir}}/{{target_output_name}}.{{source_name_part}}.o"));
400 cc_tool->set_precompiled_header_type(Tool::PCH_MSVC);
401 pch_toolchain.SetTool(Toolchain::TYPE_CC, cc_tool.Pass());
402 pch_toolchain.ToolchainSetupComplete();
404 // This target doesn't specify precompiled headers.
406 Target no_pch_target(&pch_settings,
407 Label(SourceDir("//foo/"), "no_pch_target"));
408 no_pch_target.set_output_type(Target::SOURCE_SET);
409 no_pch_target.visibility().SetPublic();
410 no_pch_target.sources().push_back(SourceFile("//foo/input1.cc"));
411 no_pch_target.sources().push_back(SourceFile("//foo/input2.c"));
412 no_pch_target.SetToolchain(&pch_toolchain);
413 ASSERT_TRUE(no_pch_target.OnResolved(&err));
415 std::ostringstream out;
416 NinjaBinaryTargetWriter writer(&no_pch_target, out);
417 writer.Run();
419 const char no_pch_expected[] =
420 "defines =\n"
421 "include_dirs =\n"
422 "cflags =\n"
423 "cflags_c =\n"
424 "cflags_cc =\n"
425 "target_output_name = no_pch_target\n"
426 "\n"
427 "build withpch/obj/foo/no_pch_target.input1.o: "
428 "withpch_cxx ../../foo/input1.cc\n"
429 "build withpch/obj/foo/no_pch_target.input2.o: "
430 "withpch_cc ../../foo/input2.c\n"
431 "\n"
432 "build withpch/obj/foo/no_pch_target.stamp: "
433 "withpch_stamp withpch/obj/foo/no_pch_target.input1.o "
434 "withpch/obj/foo/no_pch_target.input2.o\n";
435 EXPECT_EQ(no_pch_expected, out.str());
438 // This target specifies PCH.
440 Target pch_target(&pch_settings,
441 Label(SourceDir("//foo/"), "pch_target"));
442 pch_target.config_values().set_precompiled_header("build/precompile.h");
443 pch_target.config_values().set_precompiled_source(
444 SourceFile("//build/precompile.cc"));
445 pch_target.set_output_type(Target::SOURCE_SET);
446 pch_target.visibility().SetPublic();
447 pch_target.sources().push_back(SourceFile("//foo/input1.cc"));
448 pch_target.sources().push_back(SourceFile("//foo/input2.c"));
449 pch_target.SetToolchain(&pch_toolchain);
450 ASSERT_TRUE(pch_target.OnResolved(&err));
452 std::ostringstream out;
453 NinjaBinaryTargetWriter writer(&pch_target, out);
454 writer.Run();
456 const char pch_win_expected[] =
457 "defines =\n"
458 "include_dirs =\n"
459 "cflags =\n"
460 // It should output language-specific pch files.
461 "cflags_c = /Fpwithpch/obj/foo/pch_target_c.pch "
462 "/Yubuild/precompile.h\n"
463 "cflags_cc = /Fpwithpch/obj/foo/pch_target_cc.pch "
464 "/Yubuild/precompile.h\n"
465 "target_output_name = pch_target\n"
466 "\n"
467 // Compile the precompiled source files with /Yc.
468 "build withpch/obj/build/pch_target.precompile.c.o: "
469 "withpch_cc ../../build/precompile.cc\n"
470 " cflags_c = ${cflags_c} /Ycbuild/precompile.h\n"
471 "\n"
472 "build withpch/obj/build/pch_target.precompile.cc.o: "
473 "withpch_cxx ../../build/precompile.cc\n"
474 " cflags_cc = ${cflags_cc} /Ycbuild/precompile.h\n"
475 "\n"
476 "build withpch/obj/foo/pch_target.input1.o: "
477 "withpch_cxx ../../foo/input1.cc | "
478 // Explicit dependency on the PCH build step.
479 "withpch/obj/build/pch_target.precompile.cc.o\n"
480 "build withpch/obj/foo/pch_target.input2.o: "
481 "withpch_cc ../../foo/input2.c | "
482 // Explicit dependency on the PCH build step.
483 "withpch/obj/build/pch_target.precompile.c.o\n"
484 "\n"
485 "build withpch/obj/foo/pch_target.stamp: withpch_stamp "
486 "withpch/obj/foo/pch_target.input1.o "
487 "withpch/obj/foo/pch_target.input2.o "
488 // The precompiled object files were added to the outputs.
489 "withpch/obj/build/pch_target.precompile.c.o "
490 "withpch/obj/build/pch_target.precompile.cc.o\n";
491 EXPECT_EQ(pch_win_expected, out.str());
495 TEST(NinjaBinaryTargetWriter, GCCPrecompiledHeaders) {
496 Err err;
498 // This setup's toolchain does not have precompiled headers defined.
499 TestWithScope setup;
501 // A precompiled header toolchain.
502 Settings pch_settings(setup.build_settings(), "withpch/");
503 Toolchain pch_toolchain(&pch_settings,
504 Label(SourceDir("//toolchain/"), "withpch"));
505 pch_settings.set_toolchain_label(pch_toolchain.label());
506 pch_settings.set_default_toolchain_label(setup.toolchain()->label());
508 // Declare a C++ compiler that supports PCH.
509 scoped_ptr<Tool> cxx_tool(new Tool);
510 TestWithScope::SetCommandForTool(
511 "c++ {{source}} {{cflags}} {{cflags_cc}} {{defines}} {{include_dirs}} "
512 "-o {{output}}",
513 cxx_tool.get());
514 cxx_tool->set_outputs(SubstitutionList::MakeForTest(
515 "{{source_out_dir}}/{{target_output_name}}.{{source_name_part}}.o"));
516 cxx_tool->set_precompiled_header_type(Tool::PCH_GCC);
517 pch_toolchain.SetTool(Toolchain::TYPE_CXX, cxx_tool.Pass());
518 pch_toolchain.ToolchainSetupComplete();
520 // Add a C compiler as well.
521 scoped_ptr<Tool> cc_tool(new Tool);
522 TestWithScope::SetCommandForTool(
523 "cc {{source}} {{cflags}} {{cflags_c}} {{defines}} {{include_dirs}} "
524 "-o {{output}}",
525 cc_tool.get());
526 cc_tool->set_outputs(SubstitutionList::MakeForTest(
527 "{{source_out_dir}}/{{target_output_name}}.{{source_name_part}}.o"));
528 cc_tool->set_precompiled_header_type(Tool::PCH_GCC);
529 pch_toolchain.SetTool(Toolchain::TYPE_CC, cc_tool.Pass());
530 pch_toolchain.ToolchainSetupComplete();
532 // This target doesn't specify precompiled headers.
534 Target no_pch_target(&pch_settings,
535 Label(SourceDir("//foo/"), "no_pch_target"));
536 no_pch_target.set_output_type(Target::SOURCE_SET);
537 no_pch_target.visibility().SetPublic();
538 no_pch_target.sources().push_back(SourceFile("//foo/input1.cc"));
539 no_pch_target.sources().push_back(SourceFile("//foo/input2.c"));
540 no_pch_target.SetToolchain(&pch_toolchain);
541 ASSERT_TRUE(no_pch_target.OnResolved(&err));
543 std::ostringstream out;
544 NinjaBinaryTargetWriter writer(&no_pch_target, out);
545 writer.Run();
547 const char no_pch_expected[] =
548 "defines =\n"
549 "include_dirs =\n"
550 "cflags =\n"
551 "cflags_c =\n"
552 "cflags_cc =\n"
553 "target_output_name = no_pch_target\n"
554 "\n"
555 "build withpch/obj/foo/no_pch_target.input1.o: "
556 "withpch_cxx ../../foo/input1.cc\n"
557 "build withpch/obj/foo/no_pch_target.input2.o: "
558 "withpch_cc ../../foo/input2.c\n"
559 "\n"
560 "build withpch/obj/foo/no_pch_target.stamp: "
561 "withpch_stamp withpch/obj/foo/no_pch_target.input1.o "
562 "withpch/obj/foo/no_pch_target.input2.o\n";
563 EXPECT_EQ(no_pch_expected, out.str());
566 // This target specifies PCH.
568 Target pch_target(&pch_settings,
569 Label(SourceDir("//foo/"), "pch_target"));
570 pch_target.config_values().set_precompiled_header("build/precompile.h");
571 pch_target.config_values().set_precompiled_source(
572 SourceFile("//build/precompile.h"));
573 pch_target.config_values().cflags_c().push_back("-std=c99");
574 pch_target.set_output_type(Target::SOURCE_SET);
575 pch_target.visibility().SetPublic();
576 pch_target.sources().push_back(SourceFile("//foo/input1.cc"));
577 pch_target.sources().push_back(SourceFile("//foo/input2.c"));
578 pch_target.SetToolchain(&pch_toolchain);
579 ASSERT_TRUE(pch_target.OnResolved(&err));
581 std::ostringstream out;
582 NinjaBinaryTargetWriter writer(&pch_target, out);
583 writer.Run();
585 const char pch_gcc_expected[] =
586 "defines =\n"
587 "include_dirs =\n"
588 "cflags =\n"
589 "cflags_c = -std=c99 "
590 "-include withpch/obj/build/pch_target.precompile.h-c\n"
591 "cflags_cc = -include withpch/obj/build/pch_target.precompile.h-cc\n"
592 "target_output_name = pch_target\n"
593 "\n"
594 // Compile the precompiled sources with -x <lang>.
595 "build withpch/obj/build/pch_target.precompile.h-c.gch: "
596 "withpch_cc ../../build/precompile.h\n"
597 " cflags_c = -std=c99 -x c-header\n"
598 "\n"
599 "build withpch/obj/build/pch_target.precompile.h-cc.gch: "
600 "withpch_cxx ../../build/precompile.h\n"
601 " cflags_cc = -x c++-header\n"
602 "\n"
603 "build withpch/obj/foo/pch_target.input1.o: "
604 "withpch_cxx ../../foo/input1.cc | "
605 // Explicit dependency on the PCH build step.
606 "withpch/obj/build/pch_target.precompile.h-cc.gch\n"
607 "build withpch/obj/foo/pch_target.input2.o: "
608 "withpch_cc ../../foo/input2.c | "
609 // Explicit dependency on the PCH build step.
610 "withpch/obj/build/pch_target.precompile.h-c.gch\n"
611 "\n"
612 "build withpch/obj/foo/pch_target.stamp: "
613 "withpch_stamp withpch/obj/foo/pch_target.input1.o "
614 "withpch/obj/foo/pch_target.input2.o\n";
615 EXPECT_EQ(pch_gcc_expected, out.str());
619 // Should throw an error with the scheduler if a duplicate object file exists.
620 // This is dependent on the toolchain's object file mapping.
621 TEST(NinjaBinaryTargetWriter, DupeObjFileError) {
622 Scheduler scheduler;
624 TestWithScope setup;
625 TestTarget target(setup, "//foo:bar", Target::EXECUTABLE);
626 target.sources().push_back(SourceFile("//a.cc"));
627 target.sources().push_back(SourceFile("//a.cc"));
629 EXPECT_FALSE(scheduler.is_failed());
631 std::ostringstream out;
632 NinjaBinaryTargetWriter writer(&target, out);
633 writer.Run();
635 // Should have issued an error.
636 EXPECT_TRUE(scheduler.is_failed());