• 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_FALSE(target.OnResolved(&err));
30 }
31 
TEST_F(NinjaRustBinaryTargetWriterTest,RustExecutable)32 TEST_F(NinjaRustBinaryTargetWriterTest, RustExecutable) {
33   Err err;
34   TestWithScope setup;
35 
36   Target target(setup.settings(), Label(SourceDir("//foo/"), "bar"));
37   target.set_output_type(Target::EXECUTABLE);
38   target.visibility().SetPublic();
39   SourceFile main("//foo/main.rs");
40   target.sources().push_back(SourceFile("//foo/input3.rs"));
41   target.sources().push_back(main);
42   target.source_types_used().Set(SourceFile::SOURCE_RS);
43   target.rust_values().set_crate_root(main);
44   target.rust_values().crate_name() = "foo_bar";
45   target.config_values().ldflags().push_back("-fsanitize=address");
46   target.SetToolchain(setup.toolchain());
47   ASSERT_TRUE(target.OnResolved(&err));
48 
49   {
50     std::ostringstream out;
51     NinjaRustBinaryTargetWriter writer(&target, out);
52     writer.Run();
53 
54     const char expected[] =
55         "crate_name = foo_bar\n"
56         "crate_type = bin\n"
57         "output_extension = \n"
58         "output_dir = \n"
59         "rustflags =\n"
60         "rustenv =\n"
61         "root_out_dir = .\n"
62         "target_out_dir = obj/foo\n"
63         "target_output_name = bar\n"
64         "\n"
65         "build ./foo_bar: rust_bin ../../foo/main.rs | ../../foo/input3.rs "
66         "../../foo/main.rs\n"
67         "  source_file_part = main.rs\n"
68         "  source_name_part = main\n"
69         "  externs =\n"
70         "  rustdeps =\n"
71         "  ldflags = -fsanitize=address\n"
72         "  sources = ../../foo/input3.rs ../../foo/main.rs\n";
73     std::string out_str = out.str();
74     EXPECT_EQ(expected, out_str) << expected << "\n" << out_str;
75   }
76 }
77 
78 // Accessible dependencies appear as --extern switches for rustc, so that the
79 // target crate can make use of them whether transitive or not. Transitive
80 // dependencies can be accessible if they are in the public_deps of a direct
81 // dependency, or part of a chain of public_deps from a direct dependency. Any
82 // dependencies used by other crate dependencies also must appear, but are
83 // pointed to by -Ldependency as they are not available for use from the target
84 // crate. In the future they may move to `--extern priv:` when explicit private
85 // dependencies are stabilized.
TEST_F(NinjaRustBinaryTargetWriterTest,RlibDeps)86 TEST_F(NinjaRustBinaryTargetWriterTest, RlibDeps) {
87   Err err;
88   TestWithScope setup;
89 
90   Target private_rlib(setup.settings(), Label(SourceDir("//baz/"), "privatelib"));
91   private_rlib.set_output_type(Target::RUST_LIBRARY);
92   private_rlib.visibility().SetPublic();
93   SourceFile bazlib("//baz/lib.rs");
94   private_rlib.sources().push_back(SourceFile("//baz/privatelib.rs"));
95   private_rlib.sources().push_back(bazlib);
96   private_rlib.source_types_used().Set(SourceFile::SOURCE_RS);
97   private_rlib.rust_values().set_crate_root(bazlib);
98   private_rlib.rust_values().crate_name() = "privatecrate";
99   private_rlib.SetToolchain(setup.toolchain());
100   ASSERT_TRUE(private_rlib.OnResolved(&err));
101 
102   {
103     std::ostringstream out;
104     NinjaRustBinaryTargetWriter writer(&private_rlib, out);
105     writer.Run();
106 
107     const char expected[] =
108         "crate_name = privatecrate\n"
109         "crate_type = rlib\n"
110         "output_extension = .rlib\n"
111         "output_dir = \n"
112         "rustflags =\n"
113         "rustenv =\n"
114         "root_out_dir = .\n"
115         "target_out_dir = obj/baz\n"
116         "target_output_name = libprivatelib\n"
117         "\n"
118         "build obj/baz/libprivatelib.rlib: rust_rlib ../../baz/lib.rs | "
119         "../../baz/privatelib.rs ../../baz/lib.rs\n"
120         "  source_file_part = lib.rs\n"
121         "  source_name_part = lib\n"
122         "  externs =\n"
123         "  rustdeps =\n"
124         "  ldflags =\n"
125         "  sources = ../../baz/privatelib.rs ../../baz/lib.rs\n";
126     std::string out_str = out.str();
127     EXPECT_EQ(expected, out_str) << expected << "\n" << out_str;
128   }
129 
130   Target far_public_rlib(setup.settings(),
131                          Label(SourceDir("//far/"), "farlib"));
132   far_public_rlib.set_output_type(Target::RUST_LIBRARY);
133   far_public_rlib.visibility().SetPublic();
134   SourceFile farlib("//far/lib.rs");
135   far_public_rlib.sources().push_back(SourceFile("//far/farlib.rs"));
136   far_public_rlib.sources().push_back(farlib);
137   far_public_rlib.source_types_used().Set(SourceFile::SOURCE_RS);
138   far_public_rlib.rust_values().set_crate_root(farlib);
139   far_public_rlib.rust_values().crate_name() = "farcrate";
140   far_public_rlib.SetToolchain(setup.toolchain());
141   ASSERT_TRUE(far_public_rlib.OnResolved(&err));
142 
143   {
144     std::ostringstream out;
145     NinjaRustBinaryTargetWriter writer(&far_public_rlib, out);
146     writer.Run();
147 
148     const char expected[] =
149         "crate_name = farcrate\n"
150         "crate_type = rlib\n"
151         "output_extension = .rlib\n"
152         "output_dir = \n"
153         "rustflags =\n"
154         "rustenv =\n"
155         "root_out_dir = .\n"
156         "target_out_dir = obj/far\n"
157         "target_output_name = libfarlib\n"
158         "\n"
159         "build obj/far/libfarlib.rlib: rust_rlib ../../far/lib.rs | "
160         "../../far/farlib.rs ../../far/lib.rs\n"
161         "  source_file_part = lib.rs\n"
162         "  source_name_part = lib\n"
163         "  externs =\n"
164         "  rustdeps =\n"
165         "  ldflags =\n"
166         "  sources = ../../far/farlib.rs ../../far/lib.rs\n";
167     std::string out_str = out.str();
168     EXPECT_EQ(expected, out_str) << expected << "\n" << out_str;
169   }
170 
171   Target public_rlib(setup.settings(), Label(SourceDir("//bar/"), "publiclib"));
172   public_rlib.set_output_type(Target::RUST_LIBRARY);
173   public_rlib.visibility().SetPublic();
174   SourceFile barlib("//bar/lib.rs");
175   public_rlib.sources().push_back(SourceFile("//bar/publiclib.rs"));
176   public_rlib.sources().push_back(barlib);
177   public_rlib.source_types_used().Set(SourceFile::SOURCE_RS);
178   public_rlib.rust_values().set_crate_root(barlib);
179   public_rlib.rust_values().crate_name() = "publiccrate";
180   public_rlib.public_deps().push_back(LabelTargetPair(&far_public_rlib));
181   public_rlib.SetToolchain(setup.toolchain());
182   ASSERT_TRUE(public_rlib.OnResolved(&err));
183 
184   {
185     std::ostringstream out;
186     NinjaRustBinaryTargetWriter writer(&public_rlib, out);
187     writer.Run();
188 
189     const char expected[] =
190         "crate_name = publiccrate\n"
191         "crate_type = rlib\n"
192         "output_extension = .rlib\n"
193         "output_dir = \n"
194         "rustflags =\n"
195         "rustenv =\n"
196         "root_out_dir = .\n"
197         "target_out_dir = obj/bar\n"
198         "target_output_name = libpubliclib\n"
199         "\n"
200         "build obj/bar/libpubliclib.rlib: rust_rlib ../../bar/lib.rs | "
201         "../../bar/publiclib.rs ../../bar/lib.rs obj/far/libfarlib.rlib\n"
202         "  source_file_part = lib.rs\n"
203         "  source_name_part = lib\n"
204         "  externs = --extern farcrate=obj/far/libfarlib.rlib\n"
205         "  rustdeps = -Ldependency=obj/far\n"
206         "  ldflags =\n"
207         "  sources = ../../bar/publiclib.rs ../../bar/lib.rs\n";
208     std::string out_str = out.str();
209     EXPECT_EQ(expected, out_str) << expected << "\n" << out_str;
210   }
211 
212   Target rlib(setup.settings(), Label(SourceDir("//foo/"), "direct"));
213   rlib.set_output_type(Target::RUST_LIBRARY);
214   rlib.visibility().SetPublic();
215   SourceFile lib("//foo/main.rs");
216   rlib.sources().push_back(SourceFile("//foo/direct.rs"));
217   rlib.sources().push_back(lib);
218   rlib.source_types_used().Set(SourceFile::SOURCE_RS);
219   rlib.rust_values().set_crate_root(lib);
220   rlib.rust_values().crate_name() = "direct";
221   rlib.SetToolchain(setup.toolchain());
222   rlib.public_deps().push_back(LabelTargetPair(&public_rlib));
223   rlib.private_deps().push_back(LabelTargetPair(&private_rlib));
224   ASSERT_TRUE(rlib.OnResolved(&err));
225 
226   Target target(setup.settings(), Label(SourceDir("//main/"), "main"));
227   target.set_output_type(Target::EXECUTABLE);
228   target.visibility().SetPublic();
229   SourceFile main("//main/main.rs");
230   target.sources().push_back(SourceFile("//main/source.rs"));
231   target.sources().push_back(main);
232   target.source_types_used().Set(SourceFile::SOURCE_RS);
233   target.rust_values().set_crate_root(main);
234   target.rust_values().crate_name() = "main_crate";
235   target.private_deps().push_back(LabelTargetPair(&rlib));
236   target.SetToolchain(setup.toolchain());
237   ASSERT_TRUE(target.OnResolved(&err));
238 
239   {
240     std::ostringstream out;
241     NinjaRustBinaryTargetWriter writer(&target, out);
242     writer.Run();
243 
244     const char expected[] =
245         "crate_name = main_crate\n"
246         "crate_type = bin\n"
247         "output_extension = \n"
248         "output_dir = \n"
249         "rustflags =\n"
250         "rustenv =\n"
251         "root_out_dir = .\n"
252         "target_out_dir = obj/main\n"
253         "target_output_name = main\n"
254         "\n"
255         "build ./main_crate: rust_bin ../../main/main.rs | "
256         "../../main/source.rs ../../main/main.rs obj/foo/libdirect.rlib "
257         "obj/bar/libpubliclib.rlib obj/far/libfarlib.rlib "
258         "obj/baz/libprivatelib.rlib\n"
259         "  source_file_part = main.rs\n"
260         "  source_name_part = main\n"
261         "  externs = --extern direct=obj/foo/libdirect.rlib "
262         "--extern publiccrate=obj/bar/libpubliclib.rlib "
263         "--extern farcrate=obj/far/libfarlib.rlib\n"
264         "  rustdeps = -Ldependency=obj/foo -Ldependency=obj/bar "
265         "-Ldependency=obj/far -Ldependency=obj/baz\n"
266         "  ldflags =\n"
267         "  sources = ../../main/source.rs ../../main/main.rs\n";
268     std::string out_str = out.str();
269     EXPECT_EQ(expected, out_str) << expected << "\n" << out_str;
270   }
271 }
272 
TEST_F(NinjaRustBinaryTargetWriterTest,DylibDeps)273 TEST_F(NinjaRustBinaryTargetWriterTest, DylibDeps) {
274   Err err;
275   TestWithScope setup;
276 
277   Target private_inside_dylib(setup.settings(), Label(SourceDir("//faz/"), "private_inside"));
278   private_inside_dylib.set_output_type(Target::RUST_LIBRARY);
279   private_inside_dylib.visibility().SetPublic();
280   SourceFile fazlib("//faz/lib.rs");
281   private_inside_dylib.sources().push_back(SourceFile("//faz/private_inside.rs"));
282   private_inside_dylib.sources().push_back(fazlib);
283   private_inside_dylib.source_types_used().Set(SourceFile::SOURCE_RS);
284   private_inside_dylib.rust_values().set_crate_root(fazlib);
285   private_inside_dylib.rust_values().crate_name() = "private_inside";
286   private_inside_dylib.SetToolchain(setup.toolchain());
287   ASSERT_TRUE(private_inside_dylib.OnResolved(&err));
288 
289   {
290     std::ostringstream out;
291     NinjaRustBinaryTargetWriter writer(&private_inside_dylib, out);
292     writer.Run();
293 
294     const char expected[] =
295         "crate_name = private_inside\n"
296         "crate_type = rlib\n"
297         "output_extension = .rlib\n"
298         "output_dir = \n"
299         "rustflags =\n"
300         "rustenv =\n"
301         "root_out_dir = .\n"
302         "target_out_dir = obj/faz\n"
303         "target_output_name = libprivate_inside\n"
304         "\n"
305         "build obj/faz/libprivate_inside.rlib: rust_rlib ../../faz/lib.rs | "
306         "../../faz/private_inside.rs ../../faz/lib.rs\n"
307         "  source_file_part = lib.rs\n"
308         "  source_name_part = lib\n"
309         "  externs =\n"
310         "  rustdeps =\n"
311         "  ldflags =\n"
312         "  sources = ../../faz/private_inside.rs ../../faz/lib.rs\n";
313     std::string out_str = out.str();
314     EXPECT_EQ(expected, out_str) << expected << "\n" << out_str;
315   }
316 
317   Target inside_dylib(setup.settings(), Label(SourceDir("//baz/"), "inside"));
318   inside_dylib.set_output_type(Target::RUST_LIBRARY);
319   inside_dylib.visibility().SetPublic();
320   SourceFile bazlib("//baz/lib.rs");
321   inside_dylib.sources().push_back(SourceFile("//baz/inside.rs"));
322   inside_dylib.sources().push_back(bazlib);
323   inside_dylib.source_types_used().Set(SourceFile::SOURCE_RS);
324   inside_dylib.rust_values().set_crate_root(bazlib);
325   inside_dylib.rust_values().crate_name() = "inside";
326   inside_dylib.SetToolchain(setup.toolchain());
327   ASSERT_TRUE(inside_dylib.OnResolved(&err));
328 
329   {
330     std::ostringstream out;
331     NinjaRustBinaryTargetWriter writer(&inside_dylib, out);
332     writer.Run();
333 
334     const char expected[] =
335         "crate_name = inside\n"
336         "crate_type = rlib\n"
337         "output_extension = .rlib\n"
338         "output_dir = \n"
339         "rustflags =\n"
340         "rustenv =\n"
341         "root_out_dir = .\n"
342         "target_out_dir = obj/baz\n"
343         "target_output_name = libinside\n"
344         "\n"
345         "build obj/baz/libinside.rlib: rust_rlib ../../baz/lib.rs | "
346         "../../baz/inside.rs ../../baz/lib.rs\n"
347         "  source_file_part = lib.rs\n"
348         "  source_name_part = lib\n"
349         "  externs =\n"
350         "  rustdeps =\n"
351         "  ldflags =\n"
352         "  sources = ../../baz/inside.rs ../../baz/lib.rs\n";
353     std::string out_str = out.str();
354     EXPECT_EQ(expected, out_str) << expected << "\n" << out_str;
355   }
356 
357   Target dylib(setup.settings(), Label(SourceDir("//bar/"), "mylib"));
358   dylib.set_output_type(Target::SHARED_LIBRARY);
359   dylib.visibility().SetPublic();
360   SourceFile barlib("//bar/lib.rs");
361   dylib.sources().push_back(SourceFile("//bar/mylib.rs"));
362   dylib.sources().push_back(barlib);
363   dylib.source_types_used().Set(SourceFile::SOURCE_RS);
364   dylib.rust_values().set_crate_type(RustValues::CRATE_DYLIB);
365   dylib.rust_values().set_crate_root(barlib);
366   dylib.rust_values().crate_name() = "mylib";
367   dylib.public_deps().push_back(LabelTargetPair(&inside_dylib));
368   dylib.private_deps().push_back(LabelTargetPair(&private_inside_dylib));
369   dylib.SetToolchain(setup.toolchain());
370   ASSERT_TRUE(dylib.OnResolved(&err));
371 
372   {
373     std::ostringstream out;
374     NinjaRustBinaryTargetWriter writer(&dylib, out);
375     writer.Run();
376 
377     const char expected[] =
378         "crate_name = mylib\n"
379         "crate_type = dylib\n"
380         "output_extension = .so\n"
381         "output_dir = \n"
382         "rustflags =\n"
383         "rustenv =\n"
384         "root_out_dir = .\n"
385         "target_out_dir = obj/bar\n"
386         "target_output_name = libmylib\n"
387         "\n"
388         "build obj/bar/libmylib.so: rust_dylib ../../bar/lib.rs | "
389         "../../bar/mylib.rs ../../bar/lib.rs "
390         "obj/baz/libinside.rlib obj/faz/libprivate_inside.rlib\n"
391         "  source_file_part = lib.rs\n"
392         "  source_name_part = lib\n"
393         "  externs = --extern inside=obj/baz/libinside.rlib "
394         "--extern private_inside=obj/faz/libprivate_inside.rlib\n"
395         "  rustdeps = -Ldependency=obj/baz -Ldependency=obj/faz\n"
396         "  ldflags =\n"
397         "  sources = ../../bar/mylib.rs ../../bar/lib.rs\n";
398     std::string out_str = out.str();
399     EXPECT_EQ(expected, out_str) << expected << "\n" << out_str;
400   }
401 
402   Target private_dylib(setup.settings(), Label(SourceDir("//private_dylib/"), "private_dylib"));
403   private_dylib.set_output_type(Target::SHARED_LIBRARY);
404   private_dylib.visibility().SetPublic();
405   SourceFile private_dyliblib("//private_dylib/lib.rs");
406   private_dylib.sources().push_back(SourceFile("//private_dylib/mylib.rs"));
407   private_dylib.sources().push_back(private_dyliblib);
408   private_dylib.source_types_used().Set(SourceFile::SOURCE_RS);
409   private_dylib.rust_values().set_crate_type(RustValues::CRATE_DYLIB);
410   private_dylib.rust_values().set_crate_root(private_dyliblib);
411   private_dylib.rust_values().crate_name() = "private_dylib";
412   private_dylib.SetToolchain(setup.toolchain());
413   ASSERT_TRUE(private_dylib.OnResolved(&err));
414 
415   Target another_dylib(setup.settings(), Label(SourceDir("//foo/"), "direct"));
416   another_dylib.set_output_type(Target::SHARED_LIBRARY);
417   another_dylib.visibility().SetPublic();
418   SourceFile lib("//foo/main.rs");
419   another_dylib.sources().push_back(SourceFile("//foo/direct.rs"));
420   another_dylib.sources().push_back(lib);
421   another_dylib.source_types_used().Set(SourceFile::SOURCE_RS);
422   another_dylib.rust_values().set_crate_type(RustValues::CRATE_DYLIB);
423   another_dylib.rust_values().set_crate_root(lib);
424   another_dylib.rust_values().crate_name() = "direct";
425   another_dylib.SetToolchain(setup.toolchain());
426   another_dylib.public_deps().push_back(LabelTargetPair(&dylib));
427   another_dylib.private_deps().push_back(LabelTargetPair(&private_dylib));
428   ASSERT_TRUE(another_dylib.OnResolved(&err));
429 
430   Target target(setup.settings(), Label(SourceDir("//foo/"), "bar"));
431   target.set_output_type(Target::EXECUTABLE);
432   target.visibility().SetPublic();
433   SourceFile main("//foo/main.rs");
434   target.sources().push_back(SourceFile("//foo/source.rs"));
435   target.sources().push_back(main);
436   target.source_types_used().Set(SourceFile::SOURCE_RS);
437   target.rust_values().set_crate_root(main);
438   target.rust_values().crate_name() = "foo_bar";
439   target.private_deps().push_back(LabelTargetPair(&another_dylib));
440   target.SetToolchain(setup.toolchain());
441   ASSERT_TRUE(target.OnResolved(&err));
442 
443   {
444     std::ostringstream out;
445     NinjaRustBinaryTargetWriter writer(&target, out);
446     writer.Run();
447 
448     const char expected[] =
449         "crate_name = foo_bar\n"
450         "crate_type = bin\n"
451         "output_extension = \n"
452         "output_dir = \n"
453         "rustflags =\n"
454         "rustenv =\n"
455         "root_out_dir = .\n"
456         "target_out_dir = obj/foo\n"
457         "target_output_name = bar\n"
458         "\n"
459         "build ./foo_bar: rust_bin ../../foo/main.rs | ../../foo/source.rs "
460         "../../foo/main.rs obj/foo/libdirect.so obj/bar/libmylib.so "
461         "obj/baz/libinside.rlib\n"
462         "  source_file_part = main.rs\n"
463         "  source_name_part = main\n"
464         "  externs = --extern direct=obj/foo/libdirect.so "
465         "--extern mylib=obj/bar/libmylib.so "
466         "--extern inside=obj/baz/libinside.rlib\n"
467         "  rustdeps = -Ldependency=obj/foo -Ldependency=obj/bar "
468         "-Ldependency=obj/baz -Ldependency=obj/faz "
469         "-Ldependency=obj/private_dylib\n"
470         "  ldflags =\n"
471         "  sources = ../../foo/source.rs ../../foo/main.rs\n";
472     std::string out_str = out.str();
473     EXPECT_EQ(expected, out_str) << expected << "\n" << out_str;
474   }
475 }
476 
TEST_F(NinjaRustBinaryTargetWriterTest,RlibDepsAcrossGroups)477 TEST_F(NinjaRustBinaryTargetWriterTest, RlibDepsAcrossGroups) {
478   Err err;
479   TestWithScope setup;
480 
481   Target procmacro(setup.settings(), Label(SourceDir("//bar/"), "mymacro"));
482   procmacro.set_output_type(Target::RUST_PROC_MACRO);
483   procmacro.visibility().SetPublic();
484   SourceFile barproc("//bar/lib.rs");
485   procmacro.sources().push_back(SourceFile("//bar/mylib.rs"));
486   procmacro.sources().push_back(barproc);
487   procmacro.source_types_used().Set(SourceFile::SOURCE_RS);
488   procmacro.rust_values().set_crate_root(barproc);
489   procmacro.rust_values().crate_name() = "mymacro";
490   procmacro.rust_values().set_crate_type(RustValues::CRATE_PROC_MACRO);
491   procmacro.SetToolchain(setup.toolchain());
492   ASSERT_TRUE(procmacro.OnResolved(&err));
493 
494   {
495     std::ostringstream out;
496     NinjaRustBinaryTargetWriter writer(&procmacro, out);
497     writer.Run();
498 
499     const char expected[] =
500         "crate_name = mymacro\n"
501         "crate_type = proc-macro\n"
502         "output_extension = .so\n"
503         "output_dir = \n"
504         "rustflags =\n"
505         "rustenv =\n"
506         "root_out_dir = .\n"
507         "target_out_dir = obj/bar\n"
508         "target_output_name = libmymacro\n"
509         "\n"
510         "build obj/bar/libmymacro.so: rust_macro ../../bar/lib.rs | "
511         "../../bar/mylib.rs ../../bar/lib.rs\n"
512         "  source_file_part = lib.rs\n"
513         "  source_name_part = lib\n"
514         "  externs =\n"
515         "  rustdeps =\n"
516         "  ldflags =\n"
517         "  sources = ../../bar/mylib.rs ../../bar/lib.rs\n";
518     std::string out_str = out.str();
519     EXPECT_EQ(expected, out_str) << expected << "\n" << out_str;
520   }
521 
522   // A group produces an order-only dependency in ninja:
523   // https://ninja-build.org/manual.html#ref_dependencies.
524   //
525   // If a crate D inside the group is visible to a crate C depending on the
526   // group, the crate C needs to be rebuilt when D is changed. The group
527   // dependency does not guarantee that it would, so we test that C has an
528   // indirect dependency on D through this group.
529   Target group(setup.settings(), Label(SourceDir("//baz/"), "group"));
530   group.set_output_type(Target::GROUP);
531   group.visibility().SetPublic();
532   group.public_deps().push_back(LabelTargetPair(&procmacro));
533   group.SetToolchain(setup.toolchain());
534   ASSERT_TRUE(group.OnResolved(&err));
535 
536   Target rlib(setup.settings(), Label(SourceDir("//bar/"), "mylib"));
537   rlib.set_output_type(Target::RUST_LIBRARY);
538   rlib.visibility().SetPublic();
539   SourceFile barlib("//bar/lib.rs");
540   rlib.sources().push_back(SourceFile("//bar/mylib.rs"));
541   rlib.sources().push_back(barlib);
542   rlib.source_types_used().Set(SourceFile::SOURCE_RS);
543   rlib.rust_values().set_crate_root(barlib);
544   rlib.rust_values().crate_name() = "mylib";
545   rlib.SetToolchain(setup.toolchain());
546   rlib.public_deps().push_back(LabelTargetPair(&group));
547   ASSERT_TRUE(rlib.OnResolved(&err));
548 
549   {
550     std::ostringstream out;
551     NinjaRustBinaryTargetWriter writer(&rlib, out);
552     writer.Run();
553 
554     // libmymacro.so is inside the obj/baz/group, so would be built before
555     // libmylib.rlib. However it must also cause libmylib.rlib to be recompiled
556     // when changed, so we expect an implicit dependency (appearing after `|` on
557     // the build line) from libmylib.rlib to libmymacro.so.
558     const char expected[] =
559         "crate_name = mylib\n"
560         "crate_type = rlib\n"
561         "output_extension = .rlib\n"
562         "output_dir = \n"
563         "rustflags =\n"
564         "rustenv =\n"
565         "root_out_dir = .\n"
566         "target_out_dir = obj/bar\n"
567         "target_output_name = libmylib\n"
568         "\n"
569         "build obj/bar/libmylib.rlib: rust_rlib ../../bar/lib.rs | "
570         "../../bar/mylib.rs ../../bar/lib.rs obj/bar/libmymacro.so || "
571         "obj/baz/group.stamp\n"
572         "  source_file_part = lib.rs\n"
573         "  source_name_part = lib\n"
574         "  externs = --extern mymacro=obj/bar/libmymacro.so\n"
575         "  rustdeps = -Ldependency=obj/bar\n"
576         "  ldflags =\n"
577         "  sources = ../../bar/mylib.rs ../../bar/lib.rs\n";
578     std::string out_str = out.str();
579     EXPECT_EQ(expected, out_str) << expected << "\n" << out_str;
580   }
581 
582   Target target(setup.settings(), Label(SourceDir("//foo/"), "bar"));
583   target.set_output_type(Target::EXECUTABLE);
584   target.visibility().SetPublic();
585   SourceFile main("//foo/main.rs");
586   target.sources().push_back(SourceFile("//foo/source.rs"));
587   target.sources().push_back(main);
588   target.source_types_used().Set(SourceFile::SOURCE_RS);
589   target.rust_values().set_crate_root(main);
590   target.rust_values().crate_name() = "foo_bar";
591   target.private_deps().push_back(LabelTargetPair(&rlib));
592   target.SetToolchain(setup.toolchain());
593   ASSERT_TRUE(target.OnResolved(&err));
594 
595   {
596     std::ostringstream out;
597     NinjaRustBinaryTargetWriter writer(&target, out);
598     writer.Run();
599 
600     const char expected[] =
601         "crate_name = foo_bar\n"
602         "crate_type = bin\n"
603         "output_extension = \n"
604         "output_dir = \n"
605         "rustflags =\n"
606         "rustenv =\n"
607         "root_out_dir = .\n"
608         "target_out_dir = obj/foo\n"
609         "target_output_name = bar\n"
610         "\n"
611         "build ./foo_bar: rust_bin ../../foo/main.rs | "
612         "../../foo/source.rs ../../foo/main.rs "
613         "obj/bar/libmylib.rlib obj/bar/libmymacro.so\n"
614         "  source_file_part = main.rs\n"
615         "  source_name_part = main\n"
616         "  externs = --extern mylib=obj/bar/libmylib.rlib "
617         "--extern mymacro=obj/bar/libmymacro.so\n"
618         "  rustdeps = -Ldependency=obj/bar\n"
619         "  ldflags =\n"
620         "  sources = ../../foo/source.rs ../../foo/main.rs\n";
621     std::string out_str = out.str();
622     EXPECT_EQ(expected, out_str) << expected << "\n" << out_str;
623   }
624 }
625 
TEST_F(NinjaRustBinaryTargetWriterTest,RenamedDeps)626 TEST_F(NinjaRustBinaryTargetWriterTest, RenamedDeps) {
627   Err err;
628   TestWithScope setup;
629 
630   Target transitive(setup.settings(), Label(SourceDir("//faz/"), "transitive"));
631   transitive.set_output_type(Target::RUST_LIBRARY);
632   transitive.visibility().SetPublic();
633   SourceFile transitive_lib("//faz/transitive/lib.rs");
634   transitive.sources().push_back(SourceFile("//faz/transitive/transitive.rs"));
635   transitive.sources().push_back(transitive_lib);
636   transitive.source_types_used().Set(SourceFile::SOURCE_RS);
637   transitive.rust_values().set_crate_root(transitive_lib);
638   transitive.rust_values().crate_name() = "transitive";
639   transitive.SetToolchain(setup.toolchain());
640   ASSERT_TRUE(transitive.OnResolved(&err));
641 
642   Target rlib(setup.settings(), Label(SourceDir("//baz/"), "mylib"));
643   rlib.set_output_type(Target::RUST_LIBRARY);
644   rlib.visibility().SetPublic();
645   SourceFile barlib("//baz/bar/lib.rs");
646   rlib.sources().push_back(SourceFile("//baz/bar/mylib.rs"));
647   rlib.sources().push_back(barlib);
648   rlib.source_types_used().Set(SourceFile::SOURCE_RS);
649   rlib.rust_values().set_crate_root(barlib);
650   rlib.rust_values().crate_name() = "mylib";
651   rlib.SetToolchain(setup.toolchain());
652   rlib.public_deps().push_back(LabelTargetPair(&transitive));
653   ASSERT_TRUE(rlib.OnResolved(&err));
654 
655   Target direct(setup.settings(), Label(SourceDir("//bar/"), "direct"));
656   direct.set_output_type(Target::RUST_LIBRARY);
657   direct.visibility().SetPublic();
658   SourceFile direct_lib("//bar/direct/lib.rs");
659   direct.sources().push_back(SourceFile("//bar/direct/direct.rs"));
660   direct.sources().push_back(direct_lib);
661   direct.source_types_used().Set(SourceFile::SOURCE_RS);
662   direct.rust_values().set_crate_root(direct_lib);
663   direct.rust_values().crate_name() = "direct";
664   direct.SetToolchain(setup.toolchain());
665   ASSERT_TRUE(direct.OnResolved(&err));
666 
667   Target target(setup.settings(), Label(SourceDir("//foo/"), "bar"));
668   target.set_output_type(Target::EXECUTABLE);
669   target.visibility().SetPublic();
670   SourceFile main("//foo/main.rs");
671   target.sources().push_back(SourceFile("//foo/source.rs"));
672   target.sources().push_back(main);
673   target.source_types_used().Set(SourceFile::SOURCE_RS);
674   target.rust_values().set_crate_root(main);
675   target.rust_values().crate_name() = "foo_bar";
676   // A direct dependency is renamed.
677   target.rust_values().aliased_deps()[direct.label()] = "direct_renamed";
678   // A transitive public dependency, through `rlib`, is renamed.
679   target.rust_values().aliased_deps()[transitive.label()] =
680       "transitive_renamed";
681   target.private_deps().push_back(LabelTargetPair(&direct));
682   target.private_deps().push_back(LabelTargetPair(&rlib));
683   target.SetToolchain(setup.toolchain());
684   ASSERT_TRUE(target.OnResolved(&err));
685 
686   {
687     std::ostringstream out;
688     NinjaRustBinaryTargetWriter writer(&target, out);
689     writer.Run();
690 
691     const char expected[] =
692         "crate_name = foo_bar\n"
693         "crate_type = bin\n"
694         "output_extension = \n"
695         "output_dir = \n"
696         "rustflags =\n"
697         "rustenv =\n"
698         "root_out_dir = .\n"
699         "target_out_dir = obj/foo\n"
700         "target_output_name = bar\n"
701         "\n"
702         "build ./foo_bar: rust_bin ../../foo/main.rs | ../../foo/source.rs "
703         "../../foo/main.rs obj/bar/libdirect.rlib obj/baz/libmylib.rlib "
704         "obj/faz/libtransitive.rlib\n"
705         "  source_file_part = main.rs\n"
706         "  source_name_part = main\n"
707         "  externs = --extern direct_renamed=obj/bar/libdirect.rlib "
708         "--extern mylib=obj/baz/libmylib.rlib "
709         "--extern transitive_renamed=obj/faz/libtransitive.rlib\n"
710         "  rustdeps = -Ldependency=obj/bar -Ldependency=obj/baz "
711         "-Ldependency=obj/faz\n"
712         "  ldflags =\n"
713         "  sources = ../../foo/source.rs ../../foo/main.rs\n";
714     std::string out_str = out.str();
715     EXPECT_EQ(expected, out_str) << expected << "\n" << out_str;
716   }
717 }
718 
TEST_F(NinjaRustBinaryTargetWriterTest,NonRustDeps)719 TEST_F(NinjaRustBinaryTargetWriterTest, NonRustDeps) {
720   Err err;
721   TestWithScope setup;
722 
723   Target staticlib(setup.settings(), Label(SourceDir("//foo/"), "static"));
724   staticlib.set_output_type(Target::STATIC_LIBRARY);
725   staticlib.visibility().SetPublic();
726   staticlib.sources().push_back(SourceFile("//foo/static.cpp"));
727   staticlib.source_types_used().Set(SourceFile::SOURCE_CPP);
728   staticlib.SetToolchain(setup.toolchain());
729   ASSERT_TRUE(staticlib.OnResolved(&err));
730 
731   Target rlib(setup.settings(), Label(SourceDir("//bar/"), "mylib"));
732   rlib.set_output_type(Target::RUST_LIBRARY);
733   rlib.visibility().SetPublic();
734   SourceFile barlib("//bar/lib.rs");
735   rlib.sources().push_back(SourceFile("//bar/mylib.rs"));
736   rlib.sources().push_back(barlib);
737   rlib.source_types_used().Set(SourceFile::SOURCE_RS);
738   rlib.rust_values().set_crate_root(barlib);
739   rlib.rust_values().crate_name() = "mylib";
740   rlib.SetToolchain(setup.toolchain());
741   ASSERT_TRUE(rlib.OnResolved(&err));
742 
743   Target sharedlib(setup.settings(), Label(SourceDir("//foo/"), "shared"));
744   sharedlib.set_output_type(Target::SHARED_LIBRARY);
745   sharedlib.visibility().SetPublic();
746   sharedlib.sources().push_back(SourceFile("//foo/static.cpp"));
747   sharedlib.source_types_used().Set(SourceFile::SOURCE_CPP);
748   sharedlib.SetToolchain(setup.toolchain());
749   ASSERT_TRUE(sharedlib.OnResolved(&err));
750 
751   Target csourceset(setup.settings(), Label(SourceDir("//baz/"), "sourceset"));
752   csourceset.set_output_type(Target::SOURCE_SET);
753   csourceset.visibility().SetPublic();
754   csourceset.sources().push_back(SourceFile("//baz/csourceset.cpp"));
755   csourceset.source_types_used().Set(SourceFile::SOURCE_CPP);
756   csourceset.SetToolchain(setup.toolchain());
757   ASSERT_TRUE(csourceset.OnResolved(&err));
758 
759   Toolchain toolchain_with_toc(
760       setup.settings(), Label(SourceDir("//toolchain_with_toc/"), "with_toc"));
761   TestWithScope::SetupToolchain(&toolchain_with_toc, true);
762   Target sharedlib_with_toc(setup.settings(),
763                             Label(SourceDir("//foo/"), "shared_with_toc"));
764   sharedlib_with_toc.set_output_type(Target::SHARED_LIBRARY);
765   sharedlib_with_toc.visibility().SetPublic();
766   sharedlib_with_toc.sources().push_back(SourceFile("//foo/static.cpp"));
767   sharedlib_with_toc.source_types_used().Set(SourceFile::SOURCE_CPP);
768   sharedlib_with_toc.SetToolchain(&toolchain_with_toc);
769   ASSERT_TRUE(sharedlib_with_toc.OnResolved(&err));
770 
771   Target nonrust(setup.settings(), Label(SourceDir("//foo/"), "bar"));
772   nonrust.set_output_type(Target::EXECUTABLE);
773   nonrust.visibility().SetPublic();
774   SourceFile main("//foo/main.rs");
775   nonrust.sources().push_back(SourceFile("//foo/source.rs"));
776   nonrust.sources().push_back(main);
777   nonrust.source_types_used().Set(SourceFile::SOURCE_RS);
778   nonrust.rust_values().set_crate_root(main);
779   nonrust.rust_values().crate_name() = "foo_bar";
780   nonrust.private_deps().push_back(LabelTargetPair(&rlib));
781   nonrust.private_deps().push_back(LabelTargetPair(&staticlib));
782   nonrust.private_deps().push_back(LabelTargetPair(&sharedlib));
783   nonrust.private_deps().push_back(LabelTargetPair(&csourceset));
784   nonrust.private_deps().push_back(LabelTargetPair(&sharedlib_with_toc));
785   nonrust.SetToolchain(setup.toolchain());
786   ASSERT_TRUE(nonrust.OnResolved(&err));
787 
788   {
789     std::ostringstream out;
790     NinjaRustBinaryTargetWriter writer(&nonrust, out);
791     writer.Run();
792 
793     const char expected[] =
794         "crate_name = foo_bar\n"
795         "crate_type = bin\n"
796         "output_extension = \n"
797         "output_dir = \n"
798         "rustflags =\n"
799         "rustenv =\n"
800         "root_out_dir = .\n"
801         "target_out_dir = obj/foo\n"
802         "target_output_name = bar\n"
803         "\n"
804         "build ./foo_bar: rust_bin ../../foo/main.rs | ../../foo/source.rs "
805         "../../foo/main.rs obj/baz/sourceset.csourceset.o "
806         "obj/bar/libmylib.rlib "
807         "obj/foo/libstatic.a ./libshared.so ./libshared_with_toc.so.TOC "
808         "|| obj/baz/sourceset.stamp\n"
809         "  source_file_part = main.rs\n"
810         "  source_name_part = main\n"
811         "  externs = --extern mylib=obj/bar/libmylib.rlib\n"
812         "  rustdeps = -Ldependency=obj/bar "
813         "-Lnative=obj/baz -Lnative=obj/foo -Lnative=. "
814         "-Clink-arg=-Bdynamic -Clink-arg=obj/baz/sourceset.csourceset.o "
815         "-Clink-arg=obj/foo/libstatic.a -Clink-arg=./libshared.so "
816         "-Clink-arg=./libshared_with_toc.so\n"
817         "  ldflags =\n"
818         "  sources = ../../foo/source.rs ../../foo/main.rs\n";
819     std::string out_str = out.str();
820     EXPECT_EQ(expected, out_str) << expected << "\n" << out_str;
821   }
822 
823   Target nonrust_only(setup.settings(), Label(SourceDir("//foo/"), "bar"));
824   nonrust_only.set_output_type(Target::EXECUTABLE);
825   nonrust_only.visibility().SetPublic();
826   nonrust_only.sources().push_back(SourceFile("//foo/source.rs"));
827   nonrust_only.sources().push_back(main);
828   nonrust_only.source_types_used().Set(SourceFile::SOURCE_RS);
829   nonrust_only.rust_values().set_crate_root(main);
830   nonrust_only.rust_values().crate_name() = "foo_bar";
831   nonrust_only.private_deps().push_back(LabelTargetPair(&staticlib));
832   nonrust_only.SetToolchain(setup.toolchain());
833   ASSERT_TRUE(nonrust_only.OnResolved(&err));
834 
835   {
836     std::ostringstream out;
837     NinjaRustBinaryTargetWriter writer(&nonrust_only, out);
838     writer.Run();
839 
840     const char expected[] =
841         "crate_name = foo_bar\n"
842         "crate_type = bin\n"
843         "output_extension = \n"
844         "output_dir = \n"
845         "rustflags =\n"
846         "rustenv =\n"
847         "root_out_dir = .\n"
848         "target_out_dir = obj/foo\n"
849         "target_output_name = bar\n"
850         "\n"
851         "build ./foo_bar: rust_bin ../../foo/main.rs | ../../foo/source.rs "
852         "../../foo/main.rs obj/foo/libstatic.a\n"
853         "  source_file_part = main.rs\n"
854         "  source_name_part = main\n"
855         "  externs =\n"
856         "  rustdeps = -Lnative=obj/foo -Clink-arg=-Bdynamic "
857         "-Clink-arg=obj/foo/libstatic.a\n"
858         "  ldflags =\n"
859         "  sources = ../../foo/source.rs ../../foo/main.rs\n";
860     std::string out_str = out.str();
861     EXPECT_EQ(expected, out_str) << expected << "\n" << out_str;
862   }
863 
864   Target rstaticlib(setup.settings(), Label(SourceDir("//baz/"), "baz"));
865   rstaticlib.set_output_type(Target::STATIC_LIBRARY);
866   rstaticlib.visibility().SetPublic();
867   SourceFile bazlib("//baz/lib.rs");
868   rstaticlib.sources().push_back(bazlib);
869   rstaticlib.source_types_used().Set(SourceFile::SOURCE_RS);
870   rstaticlib.rust_values().set_crate_root(bazlib);
871   rstaticlib.rust_values().crate_name() = "baz";
872   rstaticlib.private_deps().push_back(LabelTargetPair(&staticlib));
873   rstaticlib.SetToolchain(setup.toolchain());
874   ASSERT_TRUE(rstaticlib.OnResolved(&err));
875 
876   {
877     std::ostringstream out;
878     NinjaRustBinaryTargetWriter writer(&rstaticlib, out);
879     writer.Run();
880 
881     const char expected[] =
882         "crate_name = baz\n"
883         "crate_type = staticlib\n"
884         "output_extension = .a\n"
885         "output_dir = \n"
886         "rustflags =\n"
887         "rustenv =\n"
888         "root_out_dir = .\n"
889         "target_out_dir = obj/baz\n"
890         "target_output_name = libbaz\n"
891         "\n"
892         "build obj/baz/libbaz.a: rust_staticlib ../../baz/lib.rs | "
893         "../../baz/lib.rs "
894         "obj/foo/libstatic.a\n"
895         "  source_file_part = lib.rs\n"
896         "  source_name_part = lib\n"
897         "  externs =\n"
898         "  rustdeps = -Lnative=obj/foo -Clink-arg=-Bdynamic "
899         "-Clink-arg=obj/foo/libstatic.a\n"
900         "  ldflags =\n"
901         "  sources = ../../baz/lib.rs\n";
902     std::string out_str = out.str();
903     EXPECT_EQ(expected, out_str) << expected << "\n" << out_str;
904   }
905 }
906 
TEST_F(NinjaRustBinaryTargetWriterTest,RlibInLibrary)907 TEST_F(NinjaRustBinaryTargetWriterTest, RlibInLibrary) {
908   Err err;
909   TestWithScope setup;
910 
911   Target priv_sset_in_staticlib(
912       setup.settings(),
913       Label(SourceDir("//priv_sset_in_staticlib/"), "priv_sset_in_staticlib"));
914   priv_sset_in_staticlib.set_output_type(Target::SOURCE_SET);
915   priv_sset_in_staticlib.visibility().SetPublic();
916   priv_sset_in_staticlib.sources().push_back(
917       SourceFile("//priv_sset_in_staticlib/lib.cc"));
918   priv_sset_in_staticlib.source_types_used().Set(SourceFile::SOURCE_CPP);
919   priv_sset_in_staticlib.SetToolchain(setup.toolchain());
920   ASSERT_TRUE(priv_sset_in_staticlib.OnResolved(&err));
921 
922   Target pub_sset_in_staticlib(
923       setup.settings(),
924       Label(SourceDir("//pub_sset_in_staticlib/"), "pub_sset_in_staticlib"));
925   pub_sset_in_staticlib.set_output_type(Target::SOURCE_SET);
926   pub_sset_in_staticlib.visibility().SetPublic();
927   pub_sset_in_staticlib.sources().push_back(
928       SourceFile("//pub_sset_in_staticlib/lib.cc"));
929   pub_sset_in_staticlib.source_types_used().Set(SourceFile::SOURCE_CPP);
930   pub_sset_in_staticlib.SetToolchain(setup.toolchain());
931   ASSERT_TRUE(pub_sset_in_staticlib.OnResolved(&err));
932 
933   Target priv_sset_in_dylib(
934       setup.settings(),
935       Label(SourceDir("//priv_sset_in_dylib/"), "priv_sset_in_dylib"));
936   priv_sset_in_dylib.set_output_type(Target::SOURCE_SET);
937   priv_sset_in_dylib.visibility().SetPublic();
938   priv_sset_in_dylib.sources().push_back(
939       SourceFile("//priv_sset_in_dylib/lib.cc"));
940   priv_sset_in_dylib.source_types_used().Set(SourceFile::SOURCE_CPP);
941   priv_sset_in_dylib.SetToolchain(setup.toolchain());
942   ASSERT_TRUE(priv_sset_in_dylib.OnResolved(&err));
943 
944   Target pub_sset_in_dylib(
945       setup.settings(),
946       Label(SourceDir("//pub_sset_in_dylib"), "pub_sset_in_dylib"));
947   pub_sset_in_dylib.set_output_type(Target::SOURCE_SET);
948   pub_sset_in_dylib.visibility().SetPublic();
949   pub_sset_in_dylib.sources().push_back(
950       SourceFile("//pub_sset_in_dylib/lib.cc"));
951   pub_sset_in_dylib.source_types_used().Set(SourceFile::SOURCE_CPP);
952   pub_sset_in_dylib.SetToolchain(setup.toolchain());
953   ASSERT_TRUE(pub_sset_in_dylib.OnResolved(&err));
954 
955   Target priv_in_staticlib(
956       setup.settings(),
957       Label(SourceDir("//priv_in_staticlib/"), "priv_in_staticlib"));
958   priv_in_staticlib.set_output_type(Target::RUST_LIBRARY);
959   priv_in_staticlib.visibility().SetPublic();
960   SourceFile priv_in_staticlib_root("//priv_in_staticlib/lib.rs");
961   priv_in_staticlib.sources().push_back(priv_in_staticlib_root);
962   priv_in_staticlib.source_types_used().Set(SourceFile::SOURCE_RS);
963   priv_in_staticlib.rust_values().set_crate_root(priv_in_staticlib_root);
964   priv_in_staticlib.rust_values().crate_name() = "priv_in_staticlib";
965   priv_in_staticlib.SetToolchain(setup.toolchain());
966   priv_in_staticlib.private_deps().push_back(
967       LabelTargetPair(&priv_sset_in_staticlib));
968   ASSERT_TRUE(priv_in_staticlib.OnResolved(&err));
969 
970   Target pub_in_staticlib(
971       setup.settings(),
972       Label(SourceDir("//pub_in_staticlib/"), "pub_in_staticlib"));
973   pub_in_staticlib.set_output_type(Target::RUST_LIBRARY);
974   pub_in_staticlib.visibility().SetPublic();
975   SourceFile pub_in_staticlib_root("//pub_in_staticlib/lib.rs");
976   pub_in_staticlib.sources().push_back(pub_in_staticlib_root);
977   pub_in_staticlib.source_types_used().Set(SourceFile::SOURCE_RS);
978   pub_in_staticlib.rust_values().set_crate_root(pub_in_staticlib_root);
979   pub_in_staticlib.rust_values().crate_name() = "pub_in_staticlib";
980   pub_in_staticlib.SetToolchain(setup.toolchain());
981   pub_in_staticlib.private_deps().push_back(
982       LabelTargetPair(&pub_sset_in_staticlib));
983   ASSERT_TRUE(pub_in_staticlib.OnResolved(&err));
984 
985   Target priv_in_dylib(setup.settings(),
986                        Label(SourceDir("//priv_in_dylib/"), "priv_in_dylib"));
987   priv_in_dylib.set_output_type(Target::RUST_LIBRARY);
988   priv_in_dylib.visibility().SetPublic();
989   SourceFile priv_in_dylib_root("//priv_in_dylib/lib.rs");
990   priv_in_dylib.sources().push_back(priv_in_dylib_root);
991   priv_in_dylib.source_types_used().Set(SourceFile::SOURCE_RS);
992   priv_in_dylib.rust_values().set_crate_root(priv_in_dylib_root);
993   priv_in_dylib.rust_values().crate_name() = "priv_in_dylib";
994   priv_in_dylib.SetToolchain(setup.toolchain());
995   priv_in_dylib.private_deps().push_back(LabelTargetPair(&priv_sset_in_dylib));
996   ASSERT_TRUE(priv_in_dylib.OnResolved(&err));
997 
998   Target pub_in_dylib(setup.settings(),
999                       Label(SourceDir("//pub_in_dylib/"), "pub_in_dylib"));
1000   pub_in_dylib.set_output_type(Target::RUST_LIBRARY);
1001   pub_in_dylib.visibility().SetPublic();
1002   SourceFile pub_in_dylib_root("//pub_in_dylib/lib.rs");
1003   pub_in_dylib.sources().push_back(pub_in_dylib_root);
1004   pub_in_dylib.source_types_used().Set(SourceFile::SOURCE_RS);
1005   pub_in_dylib.rust_values().set_crate_root(pub_in_dylib_root);
1006   pub_in_dylib.rust_values().crate_name() = "pub_in_dylib";
1007   pub_in_dylib.SetToolchain(setup.toolchain());
1008   pub_in_dylib.private_deps().push_back(LabelTargetPair(&pub_sset_in_dylib));
1009   ASSERT_TRUE(pub_in_dylib.OnResolved(&err));
1010 
1011   Target staticlib(setup.settings(),
1012                    Label(SourceDir("//staticlib/"), "staticlib"));
1013   staticlib.set_output_type(Target::STATIC_LIBRARY);
1014   staticlib.visibility().SetPublic();
1015   staticlib.sources().push_back(SourceFile("//staticlib/lib.cc"));
1016   staticlib.source_types_used().Set(SourceFile::SOURCE_CPP);
1017   staticlib.public_deps().push_back(LabelTargetPair(&pub_in_staticlib));
1018   staticlib.private_deps().push_back(LabelTargetPair(&priv_in_staticlib));
1019   staticlib.SetToolchain(setup.toolchain());
1020   ASSERT_TRUE(staticlib.OnResolved(&err));
1021 
1022   Target dylib(setup.settings(), Label(SourceDir("//dylib/"), "dylib"));
1023   dylib.set_output_type(Target::SHARED_LIBRARY);
1024   dylib.visibility().SetPublic();
1025   SourceFile dylib_root("//dylib/lib.rs");
1026   dylib.sources().push_back(dylib_root);
1027   dylib.source_types_used().Set(SourceFile::SOURCE_RS);
1028   dylib.rust_values().set_crate_root(dylib_root);
1029   dylib.rust_values().crate_name() = "dylib";
1030   dylib.public_deps().push_back(LabelTargetPair(&pub_in_dylib));
1031   dylib.private_deps().push_back(LabelTargetPair(&priv_in_dylib));
1032   dylib.SetToolchain(setup.toolchain());
1033   ASSERT_TRUE(dylib.OnResolved(&err));
1034 
1035   Target target(setup.settings(), Label(SourceDir("//exe/"), "exe"));
1036   target.set_output_type(Target::EXECUTABLE);
1037   target.visibility().SetPublic();
1038   SourceFile main("//exe/main.rs");
1039   target.sources().push_back(main);
1040   target.source_types_used().Set(SourceFile::SOURCE_RS);
1041   target.rust_values().set_crate_root(main);
1042   target.rust_values().crate_name() = "exe";
1043   target.private_deps().push_back(LabelTargetPair(&staticlib));
1044   target.private_deps().push_back(LabelTargetPair(&dylib));
1045   target.SetToolchain(setup.toolchain());
1046   ASSERT_TRUE(target.OnResolved(&err));
1047 
1048 
1049   std::ostringstream out;
1050   NinjaRustBinaryTargetWriter writer(&target, out);
1051   writer.Run();
1052 
1053   const char expected[] =
1054       "crate_name = exe\n"
1055       "crate_type = bin\n"
1056       "output_extension = \n"
1057       "output_dir = \n"
1058       "rustflags =\n"
1059       "rustenv =\n"
1060       "root_out_dir = .\n"
1061       "target_out_dir = obj/exe\n"
1062       "target_output_name = exe\n"
1063       "\n"
1064       "build ./exe: rust_bin ../../exe/main.rs | "
1065       "../../exe/main.rs "
1066       "obj/pub_sset_in_staticlib/pub_sset_in_staticlib.lib.o "
1067       "obj/priv_sset_in_staticlib/priv_sset_in_staticlib.lib.o "
1068       "obj/staticlib/libstaticlib.a "
1069       "obj/dylib/libdylib.so "
1070       "obj/pub_in_staticlib/libpub_in_staticlib.rlib "
1071       "obj/priv_in_staticlib/libpriv_in_staticlib.rlib "
1072       "obj/pub_in_dylib/libpub_in_dylib.rlib || "
1073       "obj/pub_sset_in_staticlib/pub_sset_in_staticlib.stamp "
1074       "obj/priv_sset_in_staticlib/priv_sset_in_staticlib.stamp\n"
1075       "  source_file_part = main.rs\n"
1076       "  source_name_part = main\n"
1077       "  externs = "
1078       "--extern pub_in_staticlib=obj/pub_in_staticlib/libpub_in_staticlib.rlib "
1079       "--extern dylib=obj/dylib/libdylib.so "
1080       "--extern pub_in_dylib=obj/pub_in_dylib/libpub_in_dylib.rlib\n"
1081       "  rustdeps = -Ldependency=obj/pub_in_staticlib "
1082       "-Ldependency=obj/priv_in_staticlib -Ldependency=obj/dylib "
1083       "-Ldependency=obj/pub_in_dylib -Ldependency=obj/priv_in_dylib "
1084       "-Lnative=obj/pub_sset_in_staticlib "
1085       "-Lnative=obj/priv_sset_in_staticlib "
1086       "-Lnative=obj/staticlib -Clink-arg=-Bdynamic "
1087       "-Clink-arg=obj/pub_sset_in_staticlib/pub_sset_in_staticlib.lib.o "
1088       "-Clink-arg=obj/priv_sset_in_staticlib/priv_sset_in_staticlib.lib.o "
1089       "-Clink-arg=obj/staticlib/libstaticlib.a\n"
1090       "  ldflags =\n"
1091       "  sources = ../../exe/main.rs\n";
1092 
1093   std::string out_str = out.str();
1094   EXPECT_EQ(expected, out_str) << expected << "\n" << out_str;
1095 }
1096 
TEST_F(NinjaRustBinaryTargetWriterTest,RustOutputExtensionAndDir)1097 TEST_F(NinjaRustBinaryTargetWriterTest, RustOutputExtensionAndDir) {
1098   Err err;
1099   TestWithScope setup;
1100 
1101   Target target(setup.settings(), Label(SourceDir("//foo/"), "bar"));
1102   target.set_output_type(Target::EXECUTABLE);
1103   target.visibility().SetPublic();
1104   SourceFile main("//foo/main.rs");
1105   target.sources().push_back(SourceFile("//foo/input3.rs"));
1106   target.sources().push_back(main);
1107   target.source_types_used().Set(SourceFile::SOURCE_RS);
1108   target.set_output_extension(std::string("exe"));
1109   target.set_output_dir(SourceDir("//out/Debug/foo/"));
1110   target.rust_values().set_crate_root(main);
1111   target.rust_values().crate_name() = "foo_bar";
1112   target.SetToolchain(setup.toolchain());
1113   ASSERT_TRUE(target.OnResolved(&err));
1114 
1115   {
1116     std::ostringstream out;
1117     NinjaRustBinaryTargetWriter writer(&target, out);
1118     writer.Run();
1119 
1120     const char expected[] =
1121         "crate_name = foo_bar\n"
1122         "crate_type = bin\n"
1123         "output_extension = .exe\n"
1124         "output_dir = foo\n"
1125         "rustflags =\n"
1126         "rustenv =\n"
1127         "root_out_dir = .\n"
1128         "target_out_dir = obj/foo\n"
1129         "target_output_name = bar\n"
1130         "\n"
1131         "build ./foo_bar.exe: rust_bin ../../foo/main.rs | ../../foo/input3.rs "
1132         "../../foo/main.rs\n"
1133         "  source_file_part = main.rs\n"
1134         "  source_name_part = main\n"
1135         "  externs =\n"
1136         "  rustdeps =\n"
1137         "  ldflags =\n"
1138         "  sources = ../../foo/input3.rs ../../foo/main.rs\n";
1139     std::string out_str = out.str();
1140     EXPECT_EQ(expected, out_str) << expected << "\n" << out_str;
1141   }
1142 }
1143 
TEST_F(NinjaRustBinaryTargetWriterTest,LibsAndLibDirs)1144 TEST_F(NinjaRustBinaryTargetWriterTest, LibsAndLibDirs) {
1145   Err err;
1146   TestWithScope setup;
1147 
1148   Target target(setup.settings(), Label(SourceDir("//foo/"), "bar"));
1149   target.set_output_type(Target::EXECUTABLE);
1150   target.visibility().SetPublic();
1151   SourceFile main("//foo/main.rs");
1152   target.sources().push_back(SourceFile("//foo/input.rs"));
1153   target.sources().push_back(main);
1154   target.source_types_used().Set(SourceFile::SOURCE_RS);
1155   target.set_output_dir(SourceDir("//out/Debug/foo/"));
1156   target.config_values().libs().push_back(LibFile("quux"));
1157   target.config_values().lib_dirs().push_back(SourceDir("//baz/"));
1158   target.rust_values().set_crate_root(main);
1159   target.rust_values().crate_name() = "foo_bar";
1160   target.SetToolchain(setup.toolchain());
1161   ASSERT_TRUE(target.OnResolved(&err));
1162 
1163   {
1164     std::ostringstream out;
1165     NinjaRustBinaryTargetWriter writer(&target, out);
1166     writer.Run();
1167 
1168     const char expected[] =
1169         "crate_name = foo_bar\n"
1170         "crate_type = bin\n"
1171         "output_extension = \n"
1172         "output_dir = foo\n"
1173         "rustflags =\n"
1174         "rustenv =\n"
1175         "root_out_dir = .\n"
1176         "target_out_dir = obj/foo\n"
1177         "target_output_name = bar\n"
1178         "\n"
1179         "build ./foo_bar: rust_bin ../../foo/main.rs | ../../foo/input.rs "
1180         "../../foo/main.rs\n"
1181         "  source_file_part = main.rs\n"
1182         "  source_name_part = main\n"
1183         "  externs =\n"
1184         "  rustdeps = -Lnative=../../baz -lquux\n"
1185         "  ldflags =\n"
1186         "  sources = ../../foo/input.rs ../../foo/main.rs\n";
1187     std::string out_str = out.str();
1188     EXPECT_EQ(expected, out_str) << expected << "\n" << out_str;
1189   }
1190 }
1191 
1192 // Test that neither public nor private rust dependencies of a proc-macro are
1193 // transitively acquired as accessible dependencies by users of the macro. But
1194 // the macro itself is listed as an accessible dependency (via --extern).
TEST_F(NinjaRustBinaryTargetWriterTest,RustProcMacro)1195 TEST_F(NinjaRustBinaryTargetWriterTest, RustProcMacro) {
1196   Err err;
1197   TestWithScope setup;
1198 
1199   Target procmacropublicdep(
1200       setup.settings(), Label(SourceDir("//baz/public/"), "mymacropublicdep"));
1201   procmacropublicdep.set_output_type(Target::RUST_LIBRARY);
1202   procmacropublicdep.visibility().SetPublic();
1203   SourceFile publicbazlib("//baz/public/lib.rs");
1204   procmacropublicdep.sources().push_back(SourceFile("//baz/public/mylib.rs"));
1205   procmacropublicdep.sources().push_back(publicbazlib);
1206   procmacropublicdep.source_types_used().Set(SourceFile::SOURCE_RS);
1207   procmacropublicdep.rust_values().set_crate_root(publicbazlib);
1208   procmacropublicdep.rust_values().crate_name() = "publicdep";
1209   procmacropublicdep.SetToolchain(setup.toolchain());
1210   ASSERT_TRUE(procmacropublicdep.OnResolved(&err));
1211 
1212   Target procmacroprivatedep(
1213       setup.settings(),
1214       Label(SourceDir("//baz/private/"), "mymacroprivatedep"));
1215   procmacroprivatedep.set_output_type(Target::RUST_LIBRARY);
1216   procmacroprivatedep.visibility().SetPublic();
1217   SourceFile privatebazlib("//baz/private/lib.rs");
1218   procmacroprivatedep.sources().push_back(SourceFile("//baz/private/mylib.rs"));
1219   procmacroprivatedep.sources().push_back(privatebazlib);
1220   procmacroprivatedep.source_types_used().Set(SourceFile::SOURCE_RS);
1221   procmacroprivatedep.rust_values().set_crate_root(privatebazlib);
1222   procmacroprivatedep.rust_values().crate_name() = "privatedep";
1223   procmacroprivatedep.SetToolchain(setup.toolchain());
1224   ASSERT_TRUE(procmacroprivatedep.OnResolved(&err));
1225 
1226   Target procmacro(setup.settings(), Label(SourceDir("//bar/"), "mymacro"));
1227   procmacro.set_output_type(Target::RUST_PROC_MACRO);
1228   procmacro.visibility().SetPublic();
1229   SourceFile barlib("//bar/lib.rs");
1230   procmacro.sources().push_back(SourceFile("//bar/mylib.rs"));
1231   procmacro.sources().push_back(barlib);
1232   procmacro.source_types_used().Set(SourceFile::SOURCE_RS);
1233   procmacro.rust_values().set_crate_root(barlib);
1234   procmacro.rust_values().crate_name() = "mymacro";
1235   procmacro.rust_values().set_crate_type(RustValues::CRATE_PROC_MACRO);
1236   // Add a dependency to the procmacro so we can be sure its output
1237   // directory is not propagated downstream beyond the proc macro.
1238   procmacro.public_deps().push_back(LabelTargetPair(&procmacropublicdep));
1239   procmacro.private_deps().push_back(LabelTargetPair(&procmacroprivatedep));
1240   procmacro.SetToolchain(setup.toolchain());
1241   ASSERT_TRUE(procmacro.OnResolved(&err));
1242 
1243   {
1244     std::ostringstream out;
1245     NinjaRustBinaryTargetWriter writer(&procmacro, out);
1246     writer.Run();
1247 
1248     const char expected[] =
1249         "crate_name = mymacro\n"
1250         "crate_type = proc-macro\n"
1251         "output_extension = .so\n"
1252         "output_dir = \n"
1253         "rustflags =\n"
1254         "rustenv =\n"
1255         "root_out_dir = .\n"
1256         "target_out_dir = obj/bar\n"
1257         "target_output_name = libmymacro\n"
1258         "\n"
1259         "build obj/bar/libmymacro.so: rust_macro ../../bar/lib.rs | "
1260         "../../bar/mylib.rs ../../bar/lib.rs "
1261         "obj/baz/public/libmymacropublicdep.rlib "
1262         "obj/baz/private/libmymacroprivatedep.rlib\n"
1263         "  source_file_part = lib.rs\n"
1264         "  source_name_part = lib\n"
1265         "  externs = "
1266         "--extern publicdep=obj/baz/public/libmymacropublicdep.rlib "
1267         "--extern privatedep=obj/baz/private/libmymacroprivatedep.rlib\n"
1268         "  rustdeps = -Ldependency=obj/baz/public "
1269         "-Ldependency=obj/baz/private\n"
1270         "  ldflags =\n"
1271         "  sources = ../../bar/mylib.rs ../../bar/lib.rs\n";
1272     std::string out_str = out.str();
1273     EXPECT_EQ(expected, out_str) << expected << "\n" << out_str;
1274   }
1275 
1276   Target target(setup.settings(), Label(SourceDir("//foo/"), "bar"));
1277   target.set_output_type(Target::EXECUTABLE);
1278   target.visibility().SetPublic();
1279   SourceFile main("//foo/main.rs");
1280   target.sources().push_back(SourceFile("//foo/source.rs"));
1281   target.sources().push_back(main);
1282   target.source_types_used().Set(SourceFile::SOURCE_RS);
1283   target.rust_values().set_crate_root(main);
1284   target.rust_values().crate_name() = "foo_bar";
1285   target.private_deps().push_back(LabelTargetPair(&procmacro));
1286   target.SetToolchain(setup.toolchain());
1287   ASSERT_TRUE(target.OnResolved(&err));
1288 
1289   {
1290     std::ostringstream out;
1291     NinjaRustBinaryTargetWriter writer(&target, out);
1292     writer.Run();
1293 
1294     const char expected[] =
1295         "crate_name = foo_bar\n"
1296         "crate_type = bin\n"
1297         "output_extension = \n"
1298         "output_dir = \n"
1299         "rustflags =\n"
1300         "rustenv =\n"
1301         "root_out_dir = .\n"
1302         "target_out_dir = obj/foo\n"
1303         "target_output_name = bar\n"
1304         "\n"
1305         "build ./foo_bar: rust_bin ../../foo/main.rs | ../../foo/source.rs "
1306         "../../foo/main.rs obj/bar/libmymacro.so\n"
1307         "  source_file_part = main.rs\n"
1308         "  source_name_part = main\n"
1309         "  externs = --extern mymacro=obj/bar/libmymacro.so\n"
1310         "  rustdeps = -Ldependency=obj/bar\n"
1311         "  ldflags =\n"
1312         "  sources = ../../foo/source.rs ../../foo/main.rs\n";
1313     std::string out_str = out.str();
1314     EXPECT_EQ(expected, out_str) << expected << "\n" << out_str;
1315   }
1316 }
1317 
TEST_F(NinjaRustBinaryTargetWriterTest,GroupDeps)1318 TEST_F(NinjaRustBinaryTargetWriterTest, GroupDeps) {
1319   Err err;
1320   TestWithScope setup;
1321 
1322   Target rlib(setup.settings(), Label(SourceDir("//bar/"), "mylib"));
1323   rlib.set_output_type(Target::RUST_LIBRARY);
1324   rlib.visibility().SetPublic();
1325   SourceFile barlib("//bar/lib.rs");
1326   rlib.sources().push_back(SourceFile("//bar/mylib.rs"));
1327   rlib.sources().push_back(barlib);
1328   rlib.source_types_used().Set(SourceFile::SOURCE_RS);
1329   rlib.rust_values().set_crate_root(barlib);
1330   rlib.rust_values().crate_name() = "mylib";
1331   rlib.SetToolchain(setup.toolchain());
1332   ASSERT_TRUE(rlib.OnResolved(&err));
1333 
1334   {
1335     std::ostringstream out;
1336     NinjaRustBinaryTargetWriter writer(&rlib, out);
1337     writer.Run();
1338 
1339     const char expected[] =
1340         "crate_name = mylib\n"
1341         "crate_type = rlib\n"
1342         "output_extension = .rlib\n"
1343         "output_dir = \n"
1344         "rustflags =\n"
1345         "rustenv =\n"
1346         "root_out_dir = .\n"
1347         "target_out_dir = obj/bar\n"
1348         "target_output_name = libmylib\n"
1349         "\n"
1350         "build obj/bar/libmylib.rlib: rust_rlib ../../bar/lib.rs | "
1351         "../../bar/mylib.rs ../../bar/lib.rs\n"
1352         "  source_file_part = lib.rs\n"
1353         "  source_name_part = lib\n"
1354         "  externs =\n"
1355         "  rustdeps =\n"
1356         "  ldflags =\n"
1357         "  sources = ../../bar/mylib.rs ../../bar/lib.rs\n";
1358     std::string out_str = out.str();
1359     EXPECT_EQ(expected, out_str) << expected << "\n" << out_str;
1360   }
1361 
1362   Target group(setup.settings(), Label(SourceDir("//baz/"), "group"));
1363   group.set_output_type(Target::GROUP);
1364   group.visibility().SetPublic();
1365   group.public_deps().push_back(LabelTargetPair(&rlib));
1366   group.SetToolchain(setup.toolchain());
1367   ASSERT_TRUE(group.OnResolved(&err));
1368 
1369   Target target(setup.settings(), Label(SourceDir("//foo/"), "bar"));
1370   target.set_output_type(Target::EXECUTABLE);
1371   target.visibility().SetPublic();
1372   SourceFile main("//foo/main.rs");
1373   target.sources().push_back(SourceFile("//foo/source.rs"));
1374   target.sources().push_back(main);
1375   target.source_types_used().Set(SourceFile::SOURCE_RS);
1376   target.rust_values().set_crate_root(main);
1377   target.rust_values().crate_name() = "foo_bar";
1378   target.private_deps().push_back(LabelTargetPair(&group));
1379   target.SetToolchain(setup.toolchain());
1380   ASSERT_TRUE(target.OnResolved(&err));
1381 
1382   {
1383     std::ostringstream out;
1384     NinjaRustBinaryTargetWriter writer(&target, out);
1385     writer.Run();
1386 
1387     const char expected[] =
1388         "crate_name = foo_bar\n"
1389         "crate_type = bin\n"
1390         "output_extension = \n"
1391         "output_dir = \n"
1392         "rustflags =\n"
1393         "rustenv =\n"
1394         "root_out_dir = .\n"
1395         "target_out_dir = obj/foo\n"
1396         "target_output_name = bar\n"
1397         "\n"
1398         "build ./foo_bar: rust_bin ../../foo/main.rs | "
1399         "../../foo/source.rs ../../foo/main.rs obj/bar/libmylib.rlib || "
1400         "obj/baz/group.stamp\n"
1401         "  source_file_part = main.rs\n"
1402         "  source_name_part = main\n"
1403         "  externs = --extern mylib=obj/bar/libmylib.rlib\n"
1404         "  rustdeps = -Ldependency=obj/bar\n"
1405         "  ldflags =\n"
1406         "  sources = ../../foo/source.rs ../../foo/main.rs\n";
1407     std::string out_str = out.str();
1408     EXPECT_EQ(expected, out_str) << expected << "\n" << out_str;
1409   }
1410 }
1411 
TEST_F(NinjaRustBinaryTargetWriterTest,Externs)1412 TEST_F(NinjaRustBinaryTargetWriterTest, Externs) {
1413   Err err;
1414   TestWithScope setup;
1415 
1416   Target target(setup.settings(), Label(SourceDir("//foo/"), "bar"));
1417   target.set_output_type(Target::EXECUTABLE);
1418   target.visibility().SetPublic();
1419   SourceFile main("//foo/main.rs");
1420   target.sources().push_back(SourceFile("//foo/source.rs"));
1421   target.sources().push_back(main);
1422   target.source_types_used().Set(SourceFile::SOURCE_RS);
1423   target.rust_values().set_crate_root(main);
1424   target.rust_values().crate_name() = "foo_bar";
1425 
1426   const char* lib = "lib1";
1427   target.config_values().externs().push_back(
1428       std::pair(lib, LibFile(SourceFile("//foo/lib1.rlib"))));
1429   lib = "lib2";
1430   target.config_values().externs().push_back(
1431       std::pair(lib, LibFile("lib2.rlib")));
1432 
1433   target.SetToolchain(setup.toolchain());
1434   ASSERT_TRUE(target.OnResolved(&err));
1435 
1436   {
1437     std::ostringstream out;
1438     NinjaRustBinaryTargetWriter writer(&target, out);
1439     writer.Run();
1440 
1441     const char expected[] =
1442         "crate_name = foo_bar\n"
1443         "crate_type = bin\n"
1444         "output_extension = \n"
1445         "output_dir = \n"
1446         "rustflags =\n"
1447         "rustenv =\n"
1448         "root_out_dir = .\n"
1449         "target_out_dir = obj/foo\n"
1450         "target_output_name = bar\n"
1451         "\n"
1452         "build ./foo_bar: rust_bin ../../foo/main.rs | ../../foo/source.rs "
1453         "../../foo/main.rs ../../foo/lib1.rlib\n"
1454         "  source_file_part = main.rs\n"
1455         "  source_name_part = main\n"
1456         "  externs = --extern lib1=../../foo/lib1.rlib --extern "
1457         "lib2=lib2.rlib\n"
1458         "  rustdeps =\n"
1459         "  ldflags =\n"
1460         "  sources = ../../foo/source.rs ../../foo/main.rs\n";
1461     std::string out_str = out.str();
1462     EXPECT_EQ(expected, out_str) << expected << "\n" << out_str;
1463   }
1464 }
1465 
TEST_F(NinjaRustBinaryTargetWriterTest,Inputs)1466 TEST_F(NinjaRustBinaryTargetWriterTest, Inputs) {
1467   Err err;
1468   TestWithScope setup;
1469 
1470   Target target(setup.settings(), Label(SourceDir("//foo/"), "bar"));
1471   target.set_output_type(Target::EXECUTABLE);
1472   target.visibility().SetPublic();
1473   SourceFile main("//foo/main.rs");
1474   target.sources().push_back(SourceFile("//foo/source.rs"));
1475   target.sources().push_back(main);
1476   target.source_types_used().Set(SourceFile::SOURCE_RS);
1477   target.rust_values().set_crate_root(main);
1478   target.rust_values().crate_name() = "foo_bar";
1479   target.config_values().inputs().push_back(SourceFile("//foo/config.json"));
1480   target.config_values().inputs().push_back(SourceFile("//foo/template.h"));
1481   target.SetToolchain(setup.toolchain());
1482   ASSERT_TRUE(target.OnResolved(&err));
1483 
1484   {
1485     std::ostringstream out;
1486     NinjaRustBinaryTargetWriter writer(&target, out);
1487     writer.Run();
1488 
1489     const char expected[] =
1490         "build obj/foo/bar.inputs.stamp: stamp ../../foo/config.json "
1491         "../../foo/template.h\n"
1492         "crate_name = foo_bar\n"
1493         "crate_type = bin\n"
1494         "output_extension = \n"
1495         "output_dir = \n"
1496         "rustflags =\n"
1497         "rustenv =\n"
1498         "root_out_dir = .\n"
1499         "target_out_dir = obj/foo\n"
1500         "target_output_name = bar\n"
1501         "\n"
1502         "build ./foo_bar: rust_bin ../../foo/main.rs | ../../foo/source.rs "
1503         "../../foo/main.rs ../../foo/config.json ../../foo/template.h "
1504         "|| obj/foo/bar.inputs.stamp\n"
1505         "  source_file_part = main.rs\n"
1506         "  source_name_part = main\n"
1507         "  externs =\n"
1508         "  rustdeps =\n"
1509         "  ldflags =\n"
1510         "  sources = ../../foo/source.rs ../../foo/main.rs "
1511         "../../foo/config.json ../../foo/template.h\n";
1512     std::string out_str = out.str();
1513     EXPECT_EQ(expected, out_str) << expected << "\n" << out_str;
1514   }
1515 }
1516 
TEST_F(NinjaRustBinaryTargetWriterTest,CdylibDeps)1517 TEST_F(NinjaRustBinaryTargetWriterTest, CdylibDeps) {
1518   Err err;
1519   TestWithScope setup;
1520   Target cdylib(setup.settings(), Label(SourceDir("//bar/"), "mylib"));
1521   cdylib.set_output_type(Target::SHARED_LIBRARY);
1522   cdylib.visibility().SetPublic();
1523   SourceFile barlib("//bar/lib.rs");
1524   cdylib.sources().push_back(barlib);
1525   cdylib.source_types_used().Set(SourceFile::SOURCE_RS);
1526   cdylib.rust_values().set_crate_type(RustValues::CRATE_CDYLIB);
1527   cdylib.rust_values().set_crate_root(barlib);
1528   cdylib.rust_values().crate_name() = "mylib";
1529   cdylib.SetToolchain(setup.toolchain());
1530   ASSERT_TRUE(cdylib.OnResolved(&err));
1531   {
1532     std::ostringstream out;
1533     NinjaRustBinaryTargetWriter writer(&cdylib, out);
1534     writer.Run();
1535     const char expected[] =
1536         "crate_name = mylib\n"
1537         "crate_type = cdylib\n"
1538         "output_extension = .so\n"
1539         "output_dir = \n"
1540         "rustflags =\n"
1541         "rustenv =\n"
1542         "root_out_dir = .\n"
1543         "target_out_dir = obj/bar\n"
1544         "target_output_name = libmylib\n"
1545         "\n"
1546         "build obj/bar/libmylib.so: rust_cdylib ../../bar/lib.rs | "
1547         "../../bar/lib.rs\n"
1548         "  source_file_part = lib.rs\n"
1549         "  source_name_part = lib\n"
1550         "  externs =\n"
1551         "  rustdeps =\n"
1552         "  ldflags =\n"
1553         "  sources = ../../bar/lib.rs\n";
1554     std::string out_str = out.str();
1555     EXPECT_EQ(expected, out_str) << expected << "\n" << out_str;
1556   }
1557 
1558   Target target(setup.settings(), Label(SourceDir("//foo/"), "bar"));
1559   target.set_output_type(Target::EXECUTABLE);
1560   target.visibility().SetPublic();
1561   SourceFile main("//foo/main.rs");
1562   target.sources().push_back(SourceFile("//foo/source.rs"));
1563   target.sources().push_back(main);
1564   target.source_types_used().Set(SourceFile::SOURCE_RS);
1565   target.rust_values().set_crate_root(main);
1566   target.rust_values().crate_name() = "foo_bar";
1567   target.private_deps().push_back(LabelTargetPair(&cdylib));
1568   target.SetToolchain(setup.toolchain());
1569   ASSERT_TRUE(target.OnResolved(&err));
1570   {
1571     std::ostringstream out;
1572     NinjaRustBinaryTargetWriter writer(&target, out);
1573     writer.Run();
1574 
1575     const char expected[] =
1576         "crate_name = foo_bar\n"
1577         "crate_type = bin\n"
1578         "output_extension = \n"
1579         "output_dir = \n"
1580         "rustflags =\n"
1581         "rustenv =\n"
1582         "root_out_dir = .\n"
1583         "target_out_dir = obj/foo\n"
1584         "target_output_name = bar\n"
1585         "\n"
1586         "build ./foo_bar: rust_bin ../../foo/main.rs | ../../foo/source.rs "
1587         "../../foo/main.rs obj/bar/libmylib.so\n"
1588         "  source_file_part = main.rs\n"
1589         "  source_name_part = main\n"
1590         "  externs =\n"
1591         "  rustdeps = -Lnative=obj/bar -Clink-arg=-Bdynamic "
1592         "-Clink-arg=obj/bar/libmylib.so\n"
1593         "  ldflags =\n"
1594         "  sources = ../../foo/source.rs ../../foo/main.rs\n";
1595     std::string out_str = out.str();
1596     EXPECT_EQ(expected, out_str) << expected << "\n" << out_str;
1597   }
1598 }
1599 
TEST_F(NinjaRustBinaryTargetWriterTest,TransitivePublicNonRustDeps)1600 TEST_F(NinjaRustBinaryTargetWriterTest, TransitivePublicNonRustDeps) {
1601   Err err;
1602   TestWithScope setup;
1603 
1604   // This test verifies that the Rust binary "target" links against this lib.
1605   Target implicitlib(setup.settings(), Label(SourceDir("//foo/"), "implicit"));
1606   implicitlib.set_output_type(Target::SHARED_LIBRARY);
1607   implicitlib.visibility().SetPublic();
1608   implicitlib.sources().push_back(SourceFile("//foo/implicit.cpp"));
1609   implicitlib.source_types_used().Set(SourceFile::SOURCE_CPP);
1610   implicitlib.SetToolchain(setup.toolchain());
1611   ASSERT_TRUE(implicitlib.OnResolved(&err));
1612 
1613   Target sharedlib(setup.settings(), Label(SourceDir("//foo/"), "shared"));
1614   sharedlib.set_output_type(Target::SHARED_LIBRARY);
1615   sharedlib.visibility().SetPublic();
1616   sharedlib.sources().push_back(SourceFile("//foo/shared.cpp"));
1617   sharedlib.source_types_used().Set(SourceFile::SOURCE_CPP);
1618   sharedlib.SetToolchain(setup.toolchain());
1619   sharedlib.public_deps().push_back(LabelTargetPair(&implicitlib));
1620   ASSERT_TRUE(sharedlib.OnResolved(&err));
1621 
1622   Target rlib(setup.settings(), Label(SourceDir("//bar/"), "mylib"));
1623   rlib.set_output_type(Target::RUST_LIBRARY);
1624   rlib.visibility().SetPublic();
1625   SourceFile barlib("//bar/lib.rs");
1626   rlib.sources().push_back(SourceFile("//bar/mylib.rs"));
1627   rlib.sources().push_back(barlib);
1628   rlib.source_types_used().Set(SourceFile::SOURCE_RS);
1629   rlib.rust_values().set_crate_root(barlib);
1630   rlib.rust_values().crate_name() = "mylib";
1631   rlib.SetToolchain(setup.toolchain());
1632   rlib.private_deps().push_back(LabelTargetPair(&sharedlib));
1633   ASSERT_TRUE(rlib.OnResolved(&err));
1634 
1635   Target target(setup.settings(), Label(SourceDir("//foo/"), "bar"));
1636   target.set_output_type(Target::EXECUTABLE);
1637   target.visibility().SetPublic();
1638   SourceFile main("//foo/main.rs");
1639   target.sources().push_back(main);
1640   target.source_types_used().Set(SourceFile::SOURCE_RS);
1641   target.rust_values().set_crate_root(main);
1642   target.rust_values().crate_name() = "foo_bar";
1643   target.private_deps().push_back(LabelTargetPair(&rlib));
1644   target.SetToolchain(setup.toolchain());
1645   ASSERT_TRUE(target.OnResolved(&err));
1646 
1647   {
1648     std::ostringstream out;
1649     NinjaRustBinaryTargetWriter writer(&target, out);
1650     writer.Run();
1651 
1652     const char expected[] =
1653         "crate_name = foo_bar\n"
1654         "crate_type = bin\n"
1655         "output_extension = \n"
1656         "output_dir = \n"
1657         "rustflags =\n"
1658         "rustenv =\n"
1659         "root_out_dir = .\n"
1660         "target_out_dir = obj/foo\n"
1661         "target_output_name = bar\n"
1662         "\n"
1663         "build ./foo_bar: rust_bin ../../foo/main.rs | ../../foo/main.rs "
1664         "obj/bar/libmylib.rlib ./libshared.so ./libimplicit.so\n"
1665         "  source_file_part = main.rs\n"
1666         "  source_name_part = main\n"
1667         "  externs = --extern mylib=obj/bar/libmylib.rlib\n"
1668         "  rustdeps = -Ldependency=obj/bar -Lnative=. -Clink-arg=-Bdynamic "
1669         "-Clink-arg=./libshared.so -Clink-arg=./libimplicit.so\n"
1670         "  ldflags =\n"
1671         "  sources = ../../foo/main.rs\n";
1672     std::string out_str = out.str();
1673     EXPECT_EQ(expected, out_str) << expected << "\n" << out_str;
1674   }
1675 }
1676 
TEST_F(NinjaRustBinaryTargetWriterTest,TransitiveRustDepsThroughSourceSet)1677 TEST_F(NinjaRustBinaryTargetWriterTest, TransitiveRustDepsThroughSourceSet) {
1678   Err err;
1679   TestWithScope setup;
1680 
1681   Target rlib_pub(setup.settings(),
1682                   Label(SourceDir("//public/"), "behind_sourceset_public"));
1683   rlib_pub.set_output_type(Target::RUST_LIBRARY);
1684   rlib_pub.visibility().SetPublic();
1685   SourceFile rlib_pub_root("//public/lib.rs");
1686   rlib_pub.sources().push_back(
1687       SourceFile("//public/behind_sourceset_public.rs"));
1688   rlib_pub.sources().push_back(rlib_pub_root);
1689   rlib_pub.source_types_used().Set(SourceFile::SOURCE_RS);
1690   rlib_pub.rust_values().set_crate_root(rlib_pub_root);
1691   rlib_pub.rust_values().crate_name() = "behind_sourceset_public";
1692   rlib_pub.SetToolchain(setup.toolchain());
1693   ASSERT_TRUE(rlib_pub.OnResolved(&err));
1694 
1695   Target rlib_priv(setup.settings(),
1696                   Label(SourceDir("//private/"), "behind_sourceset_private"));
1697   rlib_priv.set_output_type(Target::RUST_LIBRARY);
1698   rlib_priv.visibility().SetPublic();
1699   SourceFile rlib_priv_root("//private/lib.rs");
1700   rlib_priv.sources().push_back(
1701       SourceFile("//private/behind_sourceset_private.rs"));
1702   rlib_priv.sources().push_back(rlib_priv_root);
1703   rlib_priv.source_types_used().Set(SourceFile::SOURCE_RS);
1704   rlib_priv.rust_values().set_crate_root(rlib_priv_root);
1705   rlib_priv.rust_values().crate_name() = "behind_sourceset_private";
1706   rlib_priv.SetToolchain(setup.toolchain());
1707   ASSERT_TRUE(rlib_priv.OnResolved(&err));
1708 
1709   Target sset(setup.settings(), Label(SourceDir("//sset/"), "bar"));
1710   sset.set_output_type(Target::SOURCE_SET);
1711   sset.visibility().SetPublic();
1712   sset.sources().push_back(SourceFile("//sset/input1.cc"));
1713   sset.source_types_used().Set(SourceFile::SOURCE_CPP);
1714   sset.SetToolchain(setup.toolchain());
1715   sset.public_deps().push_back(LabelTargetPair(&rlib_pub));
1716   sset.private_deps().push_back(LabelTargetPair(&rlib_priv));
1717   ASSERT_TRUE(sset.OnResolved(&err));
1718 
1719   Target target(setup.settings(), Label(SourceDir("//linked/"), "exe"));
1720   target.set_output_type(Target::EXECUTABLE);
1721   target.visibility().SetPublic();
1722   SourceFile main("//linked/exe.rs");
1723   target.sources().push_back(main);
1724   target.source_types_used().Set(SourceFile::SOURCE_RS);
1725   target.rust_values().set_crate_root(main);
1726   target.rust_values().crate_name() = "exe";
1727   target.private_deps().push_back(LabelTargetPair(&sset));
1728   target.SetToolchain(setup.toolchain());
1729   ASSERT_TRUE(target.OnResolved(&err));
1730 
1731   {
1732     std::ostringstream out;
1733     NinjaRustBinaryTargetWriter writer(&target, out);
1734     writer.Run();
1735 
1736     const char expected[] =
1737         "crate_name = exe\n"
1738         "crate_type = bin\n"
1739         "output_extension = \n"
1740         "output_dir = \n"
1741         "rustflags =\n"
1742         "rustenv =\n"
1743         "root_out_dir = .\n"
1744         "target_out_dir = obj/linked\n"
1745         "target_output_name = exe\n"
1746         "\n"
1747         "build ./exe: rust_bin ../../linked/exe.rs | ../../linked/exe.rs "
1748         "obj/sset/bar.input1.o obj/public/libbehind_sourceset_public.rlib "
1749         "obj/private/libbehind_sourceset_private.rlib || obj/sset/bar.stamp\n"
1750         "  source_file_part = exe.rs\n"
1751         "  source_name_part = exe\n"
1752         "  externs = --extern "
1753         "behind_sourceset_public=obj/public/libbehind_sourceset_public.rlib\n"
1754         "  rustdeps = -Ldependency=obj/public -Ldependency=obj/private "
1755         "-Lnative=obj/sset -Clink-arg=-Bdynamic "
1756         "-Clink-arg=obj/sset/bar.input1.o\n"
1757         "  ldflags =\n"
1758         "  sources = ../../linked/exe.rs\n";
1759     std::string out_str = out.str();
1760     EXPECT_EQ(expected, out_str) << expected << "\n" << out_str;
1761   }
1762 }
1763