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