• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2019 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 "gn/ninja_rust_binary_target_writer.h"
6 
7 #include "gn/config.h"
8 #include "gn/rust_values.h"
9 #include "gn/scheduler.h"
10 #include "gn/target.h"
11 #include "gn/test_with_scheduler.h"
12 #include "gn/test_with_scope.h"
13 #include "util/build_config.h"
14 #include "util/test/test.h"
15 
16 using NinjaRustBinaryTargetWriterTest = TestWithScheduler;
17 
TEST_F(NinjaRustBinaryTargetWriterTest,RustSourceSet)18 TEST_F(NinjaRustBinaryTargetWriterTest, RustSourceSet) {
19   Err err;
20   TestWithScope setup;
21 
22   Target target(setup.settings(), Label(SourceDir("//foo/"), "bar"));
23   target.set_output_type(Target::SOURCE_SET);
24   target.visibility().SetPublic();
25   target.sources().push_back(SourceFile("//foo/input1.rs"));
26   target.sources().push_back(SourceFile("//foo/main.rs"));
27   target.source_types_used().Set(SourceFile::SOURCE_RS);
28   target.SetToolchain(setup.toolchain());
29   ASSERT_TRUE(target.OnResolved(&err));
30 
31   // Source set itself.
32   {
33     std::ostringstream out;
34     NinjaRustBinaryTargetWriter writer(&target, out);
35     writer.Run();
36 
37     const char expected[] =
38         "root_out_dir = .\n"
39         "target_out_dir = obj/foo\n"
40         "target_output_name = bar\n"
41         "\n"
42         "build obj/foo/bar.stamp: stamp ../../foo/input1.rs "
43         "../../foo/main.rs\n";
44     std::string out_str = out.str();
45     EXPECT_EQ(expected, out_str) << out_str;
46   }
47 }
48 
TEST_F(NinjaRustBinaryTargetWriterTest,RustExecutable)49 TEST_F(NinjaRustBinaryTargetWriterTest, RustExecutable) {
50   Err err;
51   TestWithScope setup;
52 
53   Target source_set(setup.settings(), Label(SourceDir("//foo/"), "sources"));
54   source_set.set_output_type(Target::SOURCE_SET);
55   source_set.visibility().SetPublic();
56   source_set.sources().push_back(SourceFile("//foo/input1.rs"));
57   source_set.sources().push_back(SourceFile("//foo/input2.rs"));
58   source_set.source_types_used().Set(SourceFile::SOURCE_RS);
59   source_set.SetToolchain(setup.toolchain());
60   ASSERT_TRUE(source_set.OnResolved(&err));
61 
62   Target target(setup.settings(), Label(SourceDir("//foo/"), "bar"));
63   target.set_output_type(Target::EXECUTABLE);
64   target.visibility().SetPublic();
65   SourceFile main("//foo/main.rs");
66   target.sources().push_back(SourceFile("//foo/input3.rs"));
67   target.sources().push_back(main);
68   target.source_types_used().Set(SourceFile::SOURCE_RS);
69   target.rust_values().set_crate_root(main);
70   target.rust_values().crate_name() = "foo_bar";
71   target.private_deps().push_back(LabelTargetPair(&source_set));
72   target.SetToolchain(setup.toolchain());
73   ASSERT_TRUE(target.OnResolved(&err));
74 
75   {
76     std::ostringstream out;
77     NinjaRustBinaryTargetWriter writer(&target, out);
78     writer.Run();
79 
80     const char expected[] =
81         "crate_name = foo_bar\n"
82         "crate_type = bin\n"
83         "output_extension = \n"
84         "output_dir = \n"
85         "rustflags =\n"
86         "rustenv =\n"
87         "root_out_dir = .\n"
88         "target_out_dir = obj/foo\n"
89         "target_output_name = bar\n"
90         "\n"
91         "build ./foo_bar: rust_bin ../../foo/main.rs | ../../foo/input3.rs "
92         "../../foo/main.rs ../../foo/input1.rs ../../foo/input2.rs || "
93         "obj/foo/sources.stamp\n"
94         "  externs =\n"
95         "  rustdeps =\n";
96     std::string out_str = out.str();
97     EXPECT_EQ(expected, out_str) << expected << "\n" << out_str;
98   }
99 }
100 
TEST_F(NinjaRustBinaryTargetWriterTest,RlibDeps)101 TEST_F(NinjaRustBinaryTargetWriterTest, RlibDeps) {
102   Err err;
103   TestWithScope setup;
104 
105   Target rlib(setup.settings(), Label(SourceDir("//bar/"), "mylib"));
106   rlib.set_output_type(Target::RUST_LIBRARY);
107   rlib.visibility().SetPublic();
108   SourceFile barlib("//bar/lib.rs");
109   rlib.sources().push_back(SourceFile("//bar/mylib.rs"));
110   rlib.sources().push_back(barlib);
111   rlib.source_types_used().Set(SourceFile::SOURCE_RS);
112   rlib.rust_values().set_crate_root(barlib);
113   rlib.rust_values().crate_name() = "mylib";
114   rlib.SetToolchain(setup.toolchain());
115   ASSERT_TRUE(rlib.OnResolved(&err));
116 
117   {
118     std::ostringstream out;
119     NinjaRustBinaryTargetWriter writer(&rlib, out);
120     writer.Run();
121 
122     const char expected[] =
123         "crate_name = mylib\n"
124         "crate_type = rlib\n"
125         "output_extension = .rlib\n"
126         "output_dir = \n"
127         "rustflags =\n"
128         "rustenv =\n"
129         "root_out_dir = .\n"
130         "target_out_dir = obj/bar\n"
131         "target_output_name = libmylib\n"
132         "\n"
133         "build obj/bar/libmylib.rlib: rust_rlib ../../bar/lib.rs | "
134         "../../bar/mylib.rs ../../bar/lib.rs\n"
135         "  externs =\n"
136         "  rustdeps =\n";
137     std::string out_str = out.str();
138     EXPECT_EQ(expected, out_str) << expected << "\n" << out_str;
139   }
140 
141   Target another_rlib(setup.settings(), Label(SourceDir("//foo/"), "direct"));
142   another_rlib.set_output_type(Target::RUST_LIBRARY);
143   another_rlib.visibility().SetPublic();
144   SourceFile lib("//foo/main.rs");
145   another_rlib.sources().push_back(SourceFile("//foo/direct.rs"));
146   another_rlib.sources().push_back(lib);
147   another_rlib.source_types_used().Set(SourceFile::SOURCE_RS);
148   another_rlib.rust_values().set_crate_root(lib);
149   another_rlib.rust_values().crate_name() = "direct";
150   another_rlib.SetToolchain(setup.toolchain());
151   another_rlib.public_deps().push_back(LabelTargetPair(&rlib));
152   ASSERT_TRUE(another_rlib.OnResolved(&err));
153 
154   Target target(setup.settings(), Label(SourceDir("//foo/"), "bar"));
155   target.set_output_type(Target::EXECUTABLE);
156   target.visibility().SetPublic();
157   SourceFile main("//foo/main.rs");
158   target.sources().push_back(SourceFile("//foo/source.rs"));
159   target.sources().push_back(main);
160   target.source_types_used().Set(SourceFile::SOURCE_RS);
161   target.rust_values().set_crate_root(main);
162   target.rust_values().crate_name() = "foo_bar";
163   target.private_deps().push_back(LabelTargetPair(&another_rlib));
164   target.SetToolchain(setup.toolchain());
165   ASSERT_TRUE(target.OnResolved(&err));
166 
167   {
168     std::ostringstream out;
169     NinjaRustBinaryTargetWriter writer(&target, out);
170     writer.Run();
171 
172     const char expected[] =
173         "crate_name = foo_bar\n"
174         "crate_type = bin\n"
175         "output_extension = \n"
176         "output_dir = \n"
177         "rustflags =\n"
178         "rustenv =\n"
179         "root_out_dir = .\n"
180         "target_out_dir = obj/foo\n"
181         "target_output_name = bar\n"
182         "\n"
183         "build ./foo_bar: rust_bin ../../foo/main.rs | ../../foo/source.rs "
184         "../../foo/main.rs obj/foo/libdirect.rlib obj/bar/libmylib.rlib\n"
185         "  externs = --extern direct=obj/foo/libdirect.rlib --extern "
186         "mylib=obj/bar/libmylib.rlib\n"
187         "  rustdeps = -Ldependency=obj/foo -Ldependency=obj/bar\n";
188     std::string out_str = out.str();
189     EXPECT_EQ(expected, out_str) << expected << "\n" << out_str;
190   }
191 }
192 
TEST_F(NinjaRustBinaryTargetWriterTest,RenamedDeps)193 TEST_F(NinjaRustBinaryTargetWriterTest, RenamedDeps) {
194   Err err;
195   TestWithScope setup;
196 
197   Target another_rlib(setup.settings(), Label(SourceDir("//foo/"), "direct"));
198   another_rlib.set_output_type(Target::RUST_LIBRARY);
199   another_rlib.visibility().SetPublic();
200   SourceFile lib("//foo/lib.rs");
201   another_rlib.sources().push_back(SourceFile("//foo/direct.rs"));
202   another_rlib.sources().push_back(lib);
203   another_rlib.source_types_used().Set(SourceFile::SOURCE_RS);
204   another_rlib.rust_values().set_crate_root(lib);
205   another_rlib.rust_values().crate_name() = "direct";
206   another_rlib.SetToolchain(setup.toolchain());
207   ASSERT_TRUE(another_rlib.OnResolved(&err));
208 
209   Target target(setup.settings(), Label(SourceDir("//foo/"), "bar"));
210   target.set_output_type(Target::EXECUTABLE);
211   target.visibility().SetPublic();
212   SourceFile main("//foo/main.rs");
213   target.sources().push_back(SourceFile("//foo/source.rs"));
214   target.sources().push_back(main);
215   target.source_types_used().Set(SourceFile::SOURCE_RS);
216   target.rust_values().set_crate_root(main);
217   target.rust_values().crate_name() = "foo_bar";
218   target.rust_values().aliased_deps()[another_rlib.label()] = "direct_renamed";
219   target.private_deps().push_back(LabelTargetPair(&another_rlib));
220   target.SetToolchain(setup.toolchain());
221   ASSERT_TRUE(target.OnResolved(&err));
222 
223   {
224     std::ostringstream out;
225     NinjaRustBinaryTargetWriter writer(&target, out);
226     writer.Run();
227 
228     const char expected[] =
229         "crate_name = foo_bar\n"
230         "crate_type = bin\n"
231         "output_extension = \n"
232         "output_dir = \n"
233         "rustflags =\n"
234         "rustenv =\n"
235         "root_out_dir = .\n"
236         "target_out_dir = obj/foo\n"
237         "target_output_name = bar\n"
238         "\n"
239         "build ./foo_bar: rust_bin ../../foo/main.rs | ../../foo/source.rs "
240         "../../foo/main.rs obj/foo/libdirect.rlib\n"
241         "  externs = --extern direct_renamed=obj/foo/libdirect.rlib\n"
242         "  rustdeps = -Ldependency=obj/foo\n";
243     std::string out_str = out.str();
244     EXPECT_EQ(expected, out_str) << expected << "\n" << out_str;
245   }
246 }
247 
TEST_F(NinjaRustBinaryTargetWriterTest,NonRustDeps)248 TEST_F(NinjaRustBinaryTargetWriterTest, NonRustDeps) {
249   Err err;
250   TestWithScope setup;
251 
252   Target rlib(setup.settings(), Label(SourceDir("//bar/"), "mylib"));
253   rlib.set_output_type(Target::RUST_LIBRARY);
254   rlib.visibility().SetPublic();
255   SourceFile barlib("//bar/lib.rs");
256   rlib.sources().push_back(SourceFile("//bar/mylib.rs"));
257   rlib.sources().push_back(barlib);
258   rlib.source_types_used().Set(SourceFile::SOURCE_RS);
259   rlib.rust_values().set_crate_root(barlib);
260   rlib.rust_values().crate_name() = "mylib";
261   rlib.SetToolchain(setup.toolchain());
262   ASSERT_TRUE(rlib.OnResolved(&err));
263 
264   Target staticlib(setup.settings(), Label(SourceDir("//foo/"), "static"));
265   staticlib.set_output_type(Target::STATIC_LIBRARY);
266   staticlib.visibility().SetPublic();
267   staticlib.sources().push_back(SourceFile("//foo/static.cpp"));
268   staticlib.source_types_used().Set(SourceFile::SOURCE_CPP);
269   staticlib.SetToolchain(setup.toolchain());
270   ASSERT_TRUE(staticlib.OnResolved(&err));
271 
272   Target sharedlib(setup.settings(), Label(SourceDir("//foo/"), "shared"));
273   sharedlib.set_output_type(Target::SHARED_LIBRARY);
274   sharedlib.visibility().SetPublic();
275   sharedlib.sources().push_back(SourceFile("//foo/static.cpp"));
276   sharedlib.source_types_used().Set(SourceFile::SOURCE_CPP);
277   sharedlib.SetToolchain(setup.toolchain());
278   ASSERT_TRUE(sharedlib.OnResolved(&err));
279 
280   Toolchain toolchain_with_toc(
281       setup.settings(), Label(SourceDir("//toolchain_with_toc/"), "with_toc"));
282   TestWithScope::SetupToolchain(&toolchain_with_toc, true);
283   Target sharedlib_with_toc(setup.settings(),
284                             Label(SourceDir("//foo/"), "shared_with_toc"));
285   sharedlib_with_toc.set_output_type(Target::SHARED_LIBRARY);
286   sharedlib_with_toc.visibility().SetPublic();
287   sharedlib_with_toc.sources().push_back(SourceFile("//foo/static.cpp"));
288   sharedlib_with_toc.source_types_used().Set(SourceFile::SOURCE_CPP);
289   sharedlib_with_toc.SetToolchain(&toolchain_with_toc);
290   ASSERT_TRUE(sharedlib_with_toc.OnResolved(&err));
291 
292   Target nonrust(setup.settings(), Label(SourceDir("//foo/"), "bar"));
293   nonrust.set_output_type(Target::EXECUTABLE);
294   nonrust.visibility().SetPublic();
295   SourceFile main("//foo/main.rs");
296   nonrust.sources().push_back(SourceFile("//foo/source.rs"));
297   nonrust.sources().push_back(main);
298   nonrust.source_types_used().Set(SourceFile::SOURCE_RS);
299   nonrust.rust_values().set_crate_root(main);
300   nonrust.rust_values().crate_name() = "foo_bar";
301   nonrust.private_deps().push_back(LabelTargetPair(&rlib));
302   nonrust.private_deps().push_back(LabelTargetPair(&staticlib));
303   nonrust.private_deps().push_back(LabelTargetPair(&sharedlib));
304   nonrust.private_deps().push_back(LabelTargetPair(&sharedlib_with_toc));
305   nonrust.SetToolchain(setup.toolchain());
306   ASSERT_TRUE(nonrust.OnResolved(&err));
307 
308   {
309     std::ostringstream out;
310     NinjaRustBinaryTargetWriter writer(&nonrust, out);
311     writer.Run();
312 
313     const char expected[] =
314         "crate_name = foo_bar\n"
315         "crate_type = bin\n"
316         "output_extension = \n"
317         "output_dir = \n"
318         "rustflags =\n"
319         "rustenv =\n"
320         "root_out_dir = .\n"
321         "target_out_dir = obj/foo\n"
322         "target_output_name = bar\n"
323         "\n"
324         "build ./foo_bar: rust_bin ../../foo/main.rs | ../../foo/source.rs "
325         "../../foo/main.rs obj/bar/libmylib.rlib obj/foo/libstatic.a "
326         "./libshared.so ./libshared_with_toc.so.TOC\n"
327         "  externs = --extern mylib=obj/bar/libmylib.rlib\n"
328         "  rustdeps = -Ldependency=obj/bar -Lnative=obj/foo -lstatic "
329         "-Lnative=. -lshared -Lnative=. -lshared_with_toc\n";
330     std::string out_str = out.str();
331     EXPECT_EQ(expected, out_str) << expected << "\n" << out_str;
332   }
333 
334   Target nonrust_only(setup.settings(), Label(SourceDir("//foo/"), "bar"));
335   nonrust_only.set_output_type(Target::EXECUTABLE);
336   nonrust_only.visibility().SetPublic();
337   nonrust_only.sources().push_back(SourceFile("//foo/source.rs"));
338   nonrust_only.sources().push_back(main);
339   nonrust_only.source_types_used().Set(SourceFile::SOURCE_RS);
340   nonrust_only.rust_values().set_crate_root(main);
341   nonrust_only.rust_values().crate_name() = "foo_bar";
342   nonrust_only.private_deps().push_back(LabelTargetPair(&staticlib));
343   nonrust_only.SetToolchain(setup.toolchain());
344   ASSERT_TRUE(nonrust_only.OnResolved(&err));
345 
346   {
347     std::ostringstream out;
348     NinjaRustBinaryTargetWriter writer(&nonrust_only, out);
349     writer.Run();
350 
351     const char expected[] =
352         "crate_name = foo_bar\n"
353         "crate_type = bin\n"
354         "output_extension = \n"
355         "output_dir = \n"
356         "rustflags =\n"
357         "rustenv =\n"
358         "root_out_dir = .\n"
359         "target_out_dir = obj/foo\n"
360         "target_output_name = bar\n"
361         "\n"
362         "build ./foo_bar: rust_bin ../../foo/main.rs | ../../foo/source.rs "
363         "../../foo/main.rs obj/foo/libstatic.a\n"
364         "  externs =\n"
365         "  rustdeps = -Lnative=obj/foo -lstatic\n";
366     std::string out_str = out.str();
367     EXPECT_EQ(expected, out_str) << expected << "\n" << out_str;
368   }
369 }
370 
TEST_F(NinjaRustBinaryTargetWriterTest,RustOutputExtensionAndDir)371 TEST_F(NinjaRustBinaryTargetWriterTest, RustOutputExtensionAndDir) {
372   Err err;
373   TestWithScope setup;
374 
375   Target source_set(setup.settings(), Label(SourceDir("//foo/"), "sources"));
376   source_set.set_output_type(Target::SOURCE_SET);
377   source_set.visibility().SetPublic();
378   source_set.sources().push_back(SourceFile("//foo/input1.rs"));
379   source_set.sources().push_back(SourceFile("//foo/input2.rs"));
380   source_set.source_types_used().Set(SourceFile::SOURCE_RS);
381   source_set.SetToolchain(setup.toolchain());
382   ASSERT_TRUE(source_set.OnResolved(&err));
383 
384   Target target(setup.settings(), Label(SourceDir("//foo/"), "bar"));
385   target.set_output_type(Target::EXECUTABLE);
386   target.visibility().SetPublic();
387   SourceFile main("//foo/main.rs");
388   target.sources().push_back(SourceFile("//foo/input3.rs"));
389   target.sources().push_back(main);
390   target.source_types_used().Set(SourceFile::SOURCE_RS);
391   target.set_output_extension(std::string("exe"));
392   target.set_output_dir(SourceDir("//out/Debug/foo/"));
393   target.rust_values().set_crate_root(main);
394   target.rust_values().crate_name() = "foo_bar";
395   target.private_deps().push_back(LabelTargetPair(&source_set));
396   target.SetToolchain(setup.toolchain());
397   ASSERT_TRUE(target.OnResolved(&err));
398 
399   {
400     std::ostringstream out;
401     NinjaRustBinaryTargetWriter writer(&target, out);
402     writer.Run();
403 
404     const char expected[] =
405         "crate_name = foo_bar\n"
406         "crate_type = bin\n"
407         "output_extension = .exe\n"
408         "output_dir = foo\n"
409         "rustflags =\n"
410         "rustenv =\n"
411         "root_out_dir = .\n"
412         "target_out_dir = obj/foo\n"
413         "target_output_name = bar\n"
414         "\n"
415         "build ./foo_bar.exe: rust_bin ../../foo/main.rs | ../../foo/input3.rs "
416         "../../foo/main.rs ../../foo/input1.rs ../../foo/input2.rs || "
417         "obj/foo/sources.stamp\n"
418         "  externs =\n"
419         "  rustdeps =\n";
420     std::string out_str = out.str();
421     EXPECT_EQ(expected, out_str) << expected << "\n" << out_str;
422   }
423 }
424 
TEST_F(NinjaRustBinaryTargetWriterTest,LibsAndLibDirs)425 TEST_F(NinjaRustBinaryTargetWriterTest, LibsAndLibDirs) {
426   Err err;
427   TestWithScope setup;
428 
429   Target target(setup.settings(), Label(SourceDir("//foo/"), "bar"));
430   target.set_output_type(Target::EXECUTABLE);
431   target.visibility().SetPublic();
432   SourceFile main("//foo/main.rs");
433   target.sources().push_back(SourceFile("//foo/input.rs"));
434   target.sources().push_back(main);
435   target.source_types_used().Set(SourceFile::SOURCE_RS);
436   target.set_output_dir(SourceDir("//out/Debug/foo/"));
437   target.config_values().libs().push_back(LibFile("quux"));
438   target.config_values().lib_dirs().push_back(SourceDir("//baz/"));
439   target.rust_values().set_crate_root(main);
440   target.rust_values().crate_name() = "foo_bar";
441   target.SetToolchain(setup.toolchain());
442   ASSERT_TRUE(target.OnResolved(&err));
443 
444   {
445     std::ostringstream out;
446     NinjaRustBinaryTargetWriter writer(&target, out);
447     writer.Run();
448 
449     const char expected[] =
450         "crate_name = foo_bar\n"
451         "crate_type = bin\n"
452         "output_extension = \n"
453         "output_dir = foo\n"
454         "rustflags =\n"
455         "rustenv =\n"
456         "root_out_dir = .\n"
457         "target_out_dir = obj/foo\n"
458         "target_output_name = bar\n"
459         "\n"
460         "build ./foo_bar: rust_bin ../../foo/main.rs | ../../foo/input.rs "
461         "../../foo/main.rs\n"
462         "  externs =\n"
463         "  rustdeps = -Lnative=../../baz -lquux\n";
464     std::string out_str = out.str();
465     EXPECT_EQ(expected, out_str) << expected << "\n" << out_str;
466   }
467 }
468 
TEST_F(NinjaRustBinaryTargetWriterTest,RustProcMacro)469 TEST_F(NinjaRustBinaryTargetWriterTest, RustProcMacro) {
470   Err err;
471   TestWithScope setup;
472 
473   Target procmacro(setup.settings(), Label(SourceDir("//bar/"), "mymacro"));
474   procmacro.set_output_type(Target::RUST_PROC_MACRO);
475   procmacro.visibility().SetPublic();
476   SourceFile barlib("//bar/lib.rs");
477   procmacro.sources().push_back(SourceFile("//bar/mylib.rs"));
478   procmacro.sources().push_back(barlib);
479   procmacro.source_types_used().Set(SourceFile::SOURCE_RS);
480   procmacro.rust_values().set_crate_root(barlib);
481   procmacro.rust_values().crate_name() = "mymacro";
482   procmacro.rust_values().set_crate_type(RustValues::CRATE_PROC_MACRO);
483   procmacro.SetToolchain(setup.toolchain());
484   ASSERT_TRUE(procmacro.OnResolved(&err));
485 
486   {
487     std::ostringstream out;
488     NinjaRustBinaryTargetWriter writer(&procmacro, out);
489     writer.Run();
490 
491     const char expected[] =
492         "crate_name = mymacro\n"
493         "crate_type = proc-macro\n"
494         "output_extension = .so\n"
495         "output_dir = \n"
496         "rustflags =\n"
497         "rustenv =\n"
498         "root_out_dir = .\n"
499         "target_out_dir = obj/bar\n"
500         "target_output_name = libmymacro\n"
501         "\n"
502         "build obj/bar/libmymacro.so: rust_macro ../../bar/lib.rs | "
503         "../../bar/mylib.rs ../../bar/lib.rs\n"
504         "  externs =\n"
505         "  rustdeps =\n";
506     std::string out_str = out.str();
507     EXPECT_EQ(expected, out_str) << expected << "\n" << out_str;
508   }
509 
510   Target target(setup.settings(), Label(SourceDir("//foo/"), "bar"));
511   target.set_output_type(Target::EXECUTABLE);
512   target.visibility().SetPublic();
513   SourceFile main("//foo/main.rs");
514   target.sources().push_back(SourceFile("//foo/source.rs"));
515   target.sources().push_back(main);
516   target.source_types_used().Set(SourceFile::SOURCE_RS);
517   target.rust_values().set_crate_root(main);
518   target.rust_values().crate_name() = "foo_bar";
519   target.private_deps().push_back(LabelTargetPair(&procmacro));
520   target.SetToolchain(setup.toolchain());
521   ASSERT_TRUE(target.OnResolved(&err));
522 
523   {
524     std::ostringstream out;
525     NinjaRustBinaryTargetWriter writer(&target, out);
526     writer.Run();
527 
528     const char expected[] =
529         "crate_name = foo_bar\n"
530         "crate_type = bin\n"
531         "output_extension = \n"
532         "output_dir = \n"
533         "rustflags =\n"
534         "rustenv =\n"
535         "root_out_dir = .\n"
536         "target_out_dir = obj/foo\n"
537         "target_output_name = bar\n"
538         "\n"
539         "build ./foo_bar: rust_bin ../../foo/main.rs | ../../foo/source.rs "
540         "../../foo/main.rs obj/bar/libmymacro.so\n"
541         "  externs = --extern mymacro=obj/bar/libmymacro.so\n"
542         "  rustdeps = -Ldependency=obj/bar\n";
543     std::string out_str = out.str();
544     EXPECT_EQ(expected, out_str) << expected << "\n" << out_str;
545   }
546 }
547 
TEST_F(NinjaRustBinaryTargetWriterTest,GroupDeps)548 TEST_F(NinjaRustBinaryTargetWriterTest, GroupDeps) {
549   Err err;
550   TestWithScope setup;
551 
552   Target rlib(setup.settings(), Label(SourceDir("//bar/"), "mylib"));
553   rlib.set_output_type(Target::RUST_LIBRARY);
554   rlib.visibility().SetPublic();
555   SourceFile barlib("//bar/lib.rs");
556   rlib.sources().push_back(SourceFile("//bar/mylib.rs"));
557   rlib.sources().push_back(barlib);
558   rlib.source_types_used().Set(SourceFile::SOURCE_RS);
559   rlib.rust_values().set_crate_root(barlib);
560   rlib.rust_values().crate_name() = "mylib";
561   rlib.SetToolchain(setup.toolchain());
562   ASSERT_TRUE(rlib.OnResolved(&err));
563 
564   {
565     std::ostringstream out;
566     NinjaRustBinaryTargetWriter writer(&rlib, out);
567     writer.Run();
568 
569     const char expected[] =
570         "crate_name = mylib\n"
571         "crate_type = rlib\n"
572         "output_extension = .rlib\n"
573         "output_dir = \n"
574         "rustflags =\n"
575         "rustenv =\n"
576         "root_out_dir = .\n"
577         "target_out_dir = obj/bar\n"
578         "target_output_name = libmylib\n"
579         "\n"
580         "build obj/bar/libmylib.rlib: rust_rlib ../../bar/lib.rs | "
581         "../../bar/mylib.rs ../../bar/lib.rs\n"
582         "  externs =\n"
583         "  rustdeps =\n";
584     std::string out_str = out.str();
585     EXPECT_EQ(expected, out_str) << expected << "\n" << out_str;
586   }
587 
588   Target group(setup.settings(), Label(SourceDir("//baz/"), "group"));
589   group.set_output_type(Target::GROUP);
590   group.visibility().SetPublic();
591   group.public_deps().push_back(LabelTargetPair(&rlib));
592   group.SetToolchain(setup.toolchain());
593   ASSERT_TRUE(group.OnResolved(&err));
594 
595   Target target(setup.settings(), Label(SourceDir("//foo/"), "bar"));
596   target.set_output_type(Target::EXECUTABLE);
597   target.visibility().SetPublic();
598   SourceFile main("//foo/main.rs");
599   target.sources().push_back(SourceFile("//foo/source.rs"));
600   target.sources().push_back(main);
601   target.source_types_used().Set(SourceFile::SOURCE_RS);
602   target.rust_values().set_crate_root(main);
603   target.rust_values().crate_name() = "foo_bar";
604   target.private_deps().push_back(LabelTargetPair(&group));
605   target.SetToolchain(setup.toolchain());
606   ASSERT_TRUE(target.OnResolved(&err));
607 
608   {
609     std::ostringstream out;
610     NinjaRustBinaryTargetWriter writer(&target, out);
611     writer.Run();
612 
613     const char expected[] =
614         "crate_name = foo_bar\n"
615         "crate_type = bin\n"
616         "output_extension = \n"
617         "output_dir = \n"
618         "rustflags =\n"
619         "rustenv =\n"
620         "root_out_dir = .\n"
621         "target_out_dir = obj/foo\n"
622         "target_output_name = bar\n"
623         "\n"
624         "build ./foo_bar: rust_bin ../../foo/main.rs | ../../foo/source.rs "
625         "../../foo/main.rs obj/bar/libmylib.rlib || obj/baz/group.stamp\n"
626         "  externs = --extern mylib=obj/bar/libmylib.rlib\n"
627         "  rustdeps = -Ldependency=obj/bar\n";
628     std::string out_str = out.str();
629     EXPECT_EQ(expected, out_str) << expected << "\n" << out_str;
630   }
631 }
632 
TEST_F(NinjaRustBinaryTargetWriterTest,Externs)633 TEST_F(NinjaRustBinaryTargetWriterTest, Externs) {
634   Err err;
635   TestWithScope setup;
636 
637   Target target(setup.settings(), Label(SourceDir("//foo/"), "bar"));
638   target.set_output_type(Target::EXECUTABLE);
639   target.visibility().SetPublic();
640   SourceFile main("//foo/main.rs");
641   target.sources().push_back(SourceFile("//foo/source.rs"));
642   target.sources().push_back(main);
643   target.source_types_used().Set(SourceFile::SOURCE_RS);
644   target.rust_values().set_crate_root(main);
645   target.rust_values().crate_name() = "foo_bar";
646   target.config_values().externs().push_back(
647     std::pair("lib1", LibFile(SourceFile("//foo/lib1.rlib"))));
648   target.config_values().externs().push_back(
649     std::pair("lib2", LibFile("lib2.rlib")));
650   target.SetToolchain(setup.toolchain());
651   ASSERT_TRUE(target.OnResolved(&err));
652 
653   {
654     std::ostringstream out;
655     NinjaRustBinaryTargetWriter writer(&target, out);
656     writer.Run();
657 
658     const char expected[] =
659         "crate_name = foo_bar\n"
660         "crate_type = bin\n"
661         "output_extension = \n"
662         "output_dir = \n"
663         "rustflags =\n"
664         "rustenv =\n"
665         "root_out_dir = .\n"
666         "target_out_dir = obj/foo\n"
667         "target_output_name = bar\n"
668         "\n"
669         "build ./foo_bar: rust_bin ../../foo/main.rs | ../../foo/source.rs "
670         "../../foo/main.rs ../../foo/lib1.rlib\n"
671         "  externs = --extern lib1=../../foo/lib1.rlib --extern lib2=lib2.rlib\n"
672         "  rustdeps =\n";
673     std::string out_str = out.str();
674     EXPECT_EQ(expected, out_str) << expected << "\n" << out_str;
675   }
676 }
677