| // Copyright 2019 The Chromium Authors. All rights reserved. | |
| // Use of this source code is governed by a BSD-style license that can be | |
| // found in the LICENSE file. | |
| #include "gn/ninja_rust_binary_target_writer.h" | |
| #include "gn/config.h" | |
| #include "gn/label_ptr.h" | |
| #include "gn/pool.h" | |
| #include "gn/rust_values.h" | |
| #include "gn/scheduler.h" | |
| #include "gn/target.h" | |
| #include "gn/test_with_scheduler.h" | |
| #include "gn/test_with_scope.h" | |
| #include "util/build_config.h" | |
| #include "util/test/test.h" | |
| using NinjaRustBinaryTargetWriterTest = TestWithScheduler; | |
| TEST_F(NinjaRustBinaryTargetWriterTest, RustSourceSet) { | |
| Err err; | |
| TestWithScope setup; | |
| Target target(setup.settings(), Label(SourceDir("//foo/"), "bar")); | |
| target.set_output_type(Target::SOURCE_SET); | |
| target.visibility().SetPublic(); | |
| target.sources().push_back(SourceFile("//foo/input1.rs")); | |
| target.sources().push_back(SourceFile("//foo/main.rs")); | |
| target.source_types_used().Set(SourceFile::SOURCE_RS); | |
| target.SetToolchain(setup.toolchain()); | |
| ASSERT_FALSE(target.OnResolved(&err)); | |
| } | |
| TEST_F(NinjaRustBinaryTargetWriterTest, RustExecutable) { | |
| Err err; | |
| TestWithScope setup; | |
| Target target(setup.settings(), Label(SourceDir("//foo/"), "bar")); | |
| target.set_output_type(Target::EXECUTABLE); | |
| target.visibility().SetPublic(); | |
| SourceFile main("//foo/main.rs"); | |
| target.sources().push_back(SourceFile("//foo/input3.rs")); | |
| target.sources().push_back(main); | |
| target.source_types_used().Set(SourceFile::SOURCE_RS); | |
| target.rust_values().set_crate_root(main); | |
| target.rust_values().crate_name() = "foo_bar"; | |
| target.config_values().ldflags().push_back("-fsanitize=address"); | |
| target.SetToolchain(setup.toolchain()); | |
| ASSERT_TRUE(target.OnResolved(&err)); | |
| { | |
| std::ostringstream out; | |
| NinjaRustBinaryTargetWriter writer(&target, out); | |
| writer.Run(); | |
| const char expected[] = | |
| "crate_name = foo_bar\n" | |
| "crate_type = bin\n" | |
| "output_extension = \n" | |
| "output_dir = \n" | |
| "rustflags =\n" | |
| "rustenv =\n" | |
| "root_out_dir = .\n" | |
| "target_gen_dir = gen/foo\n" | |
| "target_out_dir = obj/foo\n" | |
| "target_output_name = bar\n" | |
| "\n" | |
| "build ./foo_bar: rust_bin ../../foo/main.rs | ../../foo/input3.rs " | |
| "../../foo/main.rs\n" | |
| " source_file_part = main.rs\n" | |
| " source_name_part = main\n" | |
| " externs =\n" | |
| " rustdeps =\n" | |
| " ldflags = -fsanitize=address\n" | |
| " sources = ../../foo/input3.rs ../../foo/main.rs\n"; | |
| std::string out_str = out.str(); | |
| EXPECT_EQ(expected, out_str); | |
| } | |
| } | |
| // Accessible dependencies appear as --extern switches for rustc, so that the | |
| // target crate can make use of them whether transitive or not. Transitive | |
| // dependencies can be accessible if they are in the public_deps of a direct | |
| // dependency, or part of a chain of public_deps from a direct dependency. Any | |
| // dependencies used by other crate dependencies also must appear, but are | |
| // pointed to by -Ldependency as they are not available for use from the target | |
| // crate. In the future they may move to `--extern priv:` when explicit private | |
| // dependencies are stabilized. | |
| TEST_F(NinjaRustBinaryTargetWriterTest, RlibDeps) { | |
| Err err; | |
| TestWithScope setup; | |
| Target private_rlib(setup.settings(), | |
| Label(SourceDir("//baz/"), "privatelib")); | |
| private_rlib.set_output_type(Target::RUST_LIBRARY); | |
| private_rlib.visibility().SetPublic(); | |
| SourceFile bazlib("//baz/lib.rs"); | |
| private_rlib.sources().push_back(SourceFile("//baz/privatelib.rs")); | |
| private_rlib.sources().push_back(bazlib); | |
| private_rlib.source_types_used().Set(SourceFile::SOURCE_RS); | |
| private_rlib.rust_values().set_crate_root(bazlib); | |
| private_rlib.rust_values().crate_name() = "privatecrate"; | |
| private_rlib.SetToolchain(setup.toolchain()); | |
| ASSERT_TRUE(private_rlib.OnResolved(&err)); | |
| { | |
| std::ostringstream out; | |
| NinjaRustBinaryTargetWriter writer(&private_rlib, out); | |
| writer.Run(); | |
| const char expected[] = | |
| "crate_name = privatecrate\n" | |
| "crate_type = rlib\n" | |
| "output_extension = .rlib\n" | |
| "output_dir = \n" | |
| "rustflags =\n" | |
| "rustenv =\n" | |
| "root_out_dir = .\n" | |
| "target_gen_dir = gen/baz\n" | |
| "target_out_dir = obj/baz\n" | |
| "target_output_name = libprivatelib\n" | |
| "\n" | |
| "build obj/baz/libprivatelib.rlib: rust_rlib ../../baz/lib.rs | " | |
| "../../baz/privatelib.rs ../../baz/lib.rs\n" | |
| " source_file_part = lib.rs\n" | |
| " source_name_part = lib\n" | |
| " externs =\n" | |
| " rustdeps =\n" | |
| " ldflags =\n" | |
| " sources = ../../baz/privatelib.rs ../../baz/lib.rs\n"; | |
| std::string out_str = out.str(); | |
| EXPECT_EQ(expected, out_str); | |
| } | |
| Target far_public_rlib(setup.settings(), | |
| Label(SourceDir("//far/"), "farlib")); | |
| far_public_rlib.set_output_type(Target::RUST_LIBRARY); | |
| far_public_rlib.visibility().SetPublic(); | |
| SourceFile farlib("//far/lib.rs"); | |
| far_public_rlib.sources().push_back(SourceFile("//far/farlib.rs")); | |
| far_public_rlib.sources().push_back(farlib); | |
| far_public_rlib.source_types_used().Set(SourceFile::SOURCE_RS); | |
| far_public_rlib.rust_values().set_crate_root(farlib); | |
| far_public_rlib.rust_values().crate_name() = "farcrate"; | |
| far_public_rlib.SetToolchain(setup.toolchain()); | |
| ASSERT_TRUE(far_public_rlib.OnResolved(&err)); | |
| { | |
| std::ostringstream out; | |
| NinjaRustBinaryTargetWriter writer(&far_public_rlib, out); | |
| writer.Run(); | |
| const char expected[] = | |
| "crate_name = farcrate\n" | |
| "crate_type = rlib\n" | |
| "output_extension = .rlib\n" | |
| "output_dir = \n" | |
| "rustflags =\n" | |
| "rustenv =\n" | |
| "root_out_dir = .\n" | |
| "target_gen_dir = gen/far\n" | |
| "target_out_dir = obj/far\n" | |
| "target_output_name = libfarlib\n" | |
| "\n" | |
| "build obj/far/libfarlib.rlib: rust_rlib ../../far/lib.rs | " | |
| "../../far/farlib.rs ../../far/lib.rs\n" | |
| " source_file_part = lib.rs\n" | |
| " source_name_part = lib\n" | |
| " externs =\n" | |
| " rustdeps =\n" | |
| " ldflags =\n" | |
| " sources = ../../far/farlib.rs ../../far/lib.rs\n"; | |
| std::string out_str = out.str(); | |
| EXPECT_EQ(expected, out_str); | |
| } | |
| Target public_rlib(setup.settings(), Label(SourceDir("//bar/"), "publiclib")); | |
| public_rlib.set_output_type(Target::RUST_LIBRARY); | |
| public_rlib.visibility().SetPublic(); | |
| SourceFile barlib("//bar/lib.rs"); | |
| public_rlib.sources().push_back(SourceFile("//bar/publiclib.rs")); | |
| public_rlib.sources().push_back(barlib); | |
| public_rlib.source_types_used().Set(SourceFile::SOURCE_RS); | |
| public_rlib.rust_values().set_crate_root(barlib); | |
| public_rlib.rust_values().crate_name() = "publiccrate"; | |
| public_rlib.public_deps().push_back(LabelTargetPair(&far_public_rlib)); | |
| public_rlib.SetToolchain(setup.toolchain()); | |
| ASSERT_TRUE(public_rlib.OnResolved(&err)); | |
| { | |
| std::ostringstream out; | |
| NinjaRustBinaryTargetWriter writer(&public_rlib, out); | |
| writer.Run(); | |
| const char expected[] = | |
| "crate_name = publiccrate\n" | |
| "crate_type = rlib\n" | |
| "output_extension = .rlib\n" | |
| "output_dir = \n" | |
| "rustflags =\n" | |
| "rustenv =\n" | |
| "root_out_dir = .\n" | |
| "target_gen_dir = gen/bar\n" | |
| "target_out_dir = obj/bar\n" | |
| "target_output_name = libpubliclib\n" | |
| "\n" | |
| "build obj/bar/libpubliclib.rlib: rust_rlib ../../bar/lib.rs | " | |
| "../../bar/publiclib.rs ../../bar/lib.rs obj/far/libfarlib.rlib\n" | |
| " source_file_part = lib.rs\n" | |
| " source_name_part = lib\n" | |
| " externs = --extern farcrate=obj/far/libfarlib.rlib\n" | |
| " rustdeps = -Ldependency=obj/far\n" | |
| " ldflags =\n" | |
| " sources = ../../bar/publiclib.rs ../../bar/lib.rs\n"; | |
| std::string out_str = out.str(); | |
| EXPECT_EQ(expected, out_str); | |
| } | |
| Target rlib(setup.settings(), Label(SourceDir("//foo/"), "direct")); | |
| rlib.set_output_type(Target::RUST_LIBRARY); | |
| rlib.visibility().SetPublic(); | |
| SourceFile lib("//foo/main.rs"); | |
| rlib.sources().push_back(SourceFile("//foo/direct.rs")); | |
| rlib.sources().push_back(lib); | |
| rlib.source_types_used().Set(SourceFile::SOURCE_RS); | |
| rlib.rust_values().set_crate_root(lib); | |
| rlib.rust_values().crate_name() = "direct"; | |
| rlib.SetToolchain(setup.toolchain()); | |
| rlib.public_deps().push_back(LabelTargetPair(&public_rlib)); | |
| rlib.private_deps().push_back(LabelTargetPair(&private_rlib)); | |
| ASSERT_TRUE(rlib.OnResolved(&err)); | |
| Target target(setup.settings(), Label(SourceDir("//main/"), "main")); | |
| target.set_output_type(Target::EXECUTABLE); | |
| target.visibility().SetPublic(); | |
| SourceFile main("//main/main.rs"); | |
| target.sources().push_back(SourceFile("//main/source.rs")); | |
| target.sources().push_back(main); | |
| target.source_types_used().Set(SourceFile::SOURCE_RS); | |
| target.rust_values().set_crate_root(main); | |
| target.rust_values().crate_name() = "main_crate"; | |
| target.private_deps().push_back(LabelTargetPair(&rlib)); | |
| target.SetToolchain(setup.toolchain()); | |
| ASSERT_TRUE(target.OnResolved(&err)); | |
| { | |
| std::ostringstream out; | |
| NinjaRustBinaryTargetWriter writer(&target, out); | |
| writer.Run(); | |
| const char expected[] = | |
| "crate_name = main_crate\n" | |
| "crate_type = bin\n" | |
| "output_extension = \n" | |
| "output_dir = \n" | |
| "rustflags =\n" | |
| "rustenv =\n" | |
| "root_out_dir = .\n" | |
| "target_gen_dir = gen/main\n" | |
| "target_out_dir = obj/main\n" | |
| "target_output_name = main\n" | |
| "\n" | |
| "build ./main_crate: rust_bin ../../main/main.rs | " | |
| "../../main/source.rs ../../main/main.rs obj/foo/libdirect.rlib " | |
| "obj/bar/libpubliclib.rlib obj/far/libfarlib.rlib " | |
| "obj/baz/libprivatelib.rlib\n" | |
| " source_file_part = main.rs\n" | |
| " source_name_part = main\n" | |
| " externs = --extern direct=obj/foo/libdirect.rlib " | |
| "--extern publiccrate=obj/bar/libpubliclib.rlib " | |
| "--extern farcrate=obj/far/libfarlib.rlib\n" | |
| " rustdeps = -Ldependency=obj/foo -Ldependency=obj/bar " | |
| "-Ldependency=obj/far -Ldependency=obj/baz\n" | |
| " ldflags =\n" | |
| " sources = ../../main/source.rs ../../main/main.rs\n"; | |
| std::string out_str = out.str(); | |
| EXPECT_EQ(expected, out_str); | |
| } | |
| } | |
| TEST_F(NinjaRustBinaryTargetWriterTest, DylibDeps) { | |
| Err err; | |
| TestWithScope setup; | |
| Target private_inside_dylib(setup.settings(), | |
| Label(SourceDir("//faz/"), "private_inside")); | |
| private_inside_dylib.set_output_type(Target::RUST_LIBRARY); | |
| private_inside_dylib.visibility().SetPublic(); | |
| SourceFile fazlib("//faz/lib.rs"); | |
| private_inside_dylib.sources().push_back( | |
| SourceFile("//faz/private_inside.rs")); | |
| private_inside_dylib.sources().push_back(fazlib); | |
| private_inside_dylib.source_types_used().Set(SourceFile::SOURCE_RS); | |
| private_inside_dylib.rust_values().set_crate_root(fazlib); | |
| private_inside_dylib.rust_values().crate_name() = "private_inside"; | |
| private_inside_dylib.SetToolchain(setup.toolchain()); | |
| ASSERT_TRUE(private_inside_dylib.OnResolved(&err)); | |
| { | |
| std::ostringstream out; | |
| NinjaRustBinaryTargetWriter writer(&private_inside_dylib, out); | |
| writer.Run(); | |
| const char expected[] = | |
| "crate_name = private_inside\n" | |
| "crate_type = rlib\n" | |
| "output_extension = .rlib\n" | |
| "output_dir = \n" | |
| "rustflags =\n" | |
| "rustenv =\n" | |
| "root_out_dir = .\n" | |
| "target_gen_dir = gen/faz\n" | |
| "target_out_dir = obj/faz\n" | |
| "target_output_name = libprivate_inside\n" | |
| "\n" | |
| "build obj/faz/libprivate_inside.rlib: rust_rlib ../../faz/lib.rs | " | |
| "../../faz/private_inside.rs ../../faz/lib.rs\n" | |
| " source_file_part = lib.rs\n" | |
| " source_name_part = lib\n" | |
| " externs =\n" | |
| " rustdeps =\n" | |
| " ldflags =\n" | |
| " sources = ../../faz/private_inside.rs ../../faz/lib.rs\n"; | |
| std::string out_str = out.str(); | |
| EXPECT_EQ(expected, out_str); | |
| } | |
| Target inside_dylib(setup.settings(), Label(SourceDir("//baz/"), "inside")); | |
| inside_dylib.set_output_type(Target::RUST_LIBRARY); | |
| inside_dylib.visibility().SetPublic(); | |
| SourceFile bazlib("//baz/lib.rs"); | |
| inside_dylib.sources().push_back(SourceFile("//baz/inside.rs")); | |
| inside_dylib.sources().push_back(bazlib); | |
| inside_dylib.source_types_used().Set(SourceFile::SOURCE_RS); | |
| inside_dylib.rust_values().set_crate_root(bazlib); | |
| inside_dylib.rust_values().crate_name() = "inside"; | |
| inside_dylib.SetToolchain(setup.toolchain()); | |
| ASSERT_TRUE(inside_dylib.OnResolved(&err)); | |
| { | |
| std::ostringstream out; | |
| NinjaRustBinaryTargetWriter writer(&inside_dylib, out); | |
| writer.Run(); | |
| const char expected[] = | |
| "crate_name = inside\n" | |
| "crate_type = rlib\n" | |
| "output_extension = .rlib\n" | |
| "output_dir = \n" | |
| "rustflags =\n" | |
| "rustenv =\n" | |
| "root_out_dir = .\n" | |
| "target_gen_dir = gen/baz\n" | |
| "target_out_dir = obj/baz\n" | |
| "target_output_name = libinside\n" | |
| "\n" | |
| "build obj/baz/libinside.rlib: rust_rlib ../../baz/lib.rs | " | |
| "../../baz/inside.rs ../../baz/lib.rs\n" | |
| " source_file_part = lib.rs\n" | |
| " source_name_part = lib\n" | |
| " externs =\n" | |
| " rustdeps =\n" | |
| " ldflags =\n" | |
| " sources = ../../baz/inside.rs ../../baz/lib.rs\n"; | |
| std::string out_str = out.str(); | |
| EXPECT_EQ(expected, out_str); | |
| } | |
| Target dylib(setup.settings(), Label(SourceDir("//bar/"), "mylib")); | |
| dylib.set_output_type(Target::SHARED_LIBRARY); | |
| dylib.visibility().SetPublic(); | |
| SourceFile barlib("//bar/lib.rs"); | |
| dylib.sources().push_back(SourceFile("//bar/mylib.rs")); | |
| dylib.sources().push_back(barlib); | |
| dylib.source_types_used().Set(SourceFile::SOURCE_RS); | |
| dylib.rust_values().set_crate_type(RustValues::CRATE_DYLIB); | |
| dylib.rust_values().set_crate_root(barlib); | |
| dylib.rust_values().crate_name() = "mylib"; | |
| dylib.public_deps().push_back(LabelTargetPair(&inside_dylib)); | |
| dylib.private_deps().push_back(LabelTargetPair(&private_inside_dylib)); | |
| dylib.SetToolchain(setup.toolchain()); | |
| ASSERT_TRUE(dylib.OnResolved(&err)); | |
| { | |
| std::ostringstream out; | |
| NinjaRustBinaryTargetWriter writer(&dylib, out); | |
| writer.Run(); | |
| const char expected[] = | |
| "crate_name = mylib\n" | |
| "crate_type = dylib\n" | |
| "output_extension = .so\n" | |
| "output_dir = \n" | |
| "rustflags =\n" | |
| "rustenv =\n" | |
| "root_out_dir = .\n" | |
| "target_gen_dir = gen/bar\n" | |
| "target_out_dir = obj/bar\n" | |
| "target_output_name = libmylib\n" | |
| "\n" | |
| "build obj/bar/libmylib.so: rust_dylib ../../bar/lib.rs | " | |
| "../../bar/mylib.rs ../../bar/lib.rs " | |
| "obj/baz/libinside.rlib obj/faz/libprivate_inside.rlib\n" | |
| " source_file_part = lib.rs\n" | |
| " source_name_part = lib\n" | |
| " externs = --extern inside=obj/baz/libinside.rlib " | |
| "--extern private_inside=obj/faz/libprivate_inside.rlib\n" | |
| " rustdeps = -Ldependency=obj/baz -Ldependency=obj/faz\n" | |
| " ldflags =\n" | |
| " sources = ../../bar/mylib.rs ../../bar/lib.rs\n"; | |
| std::string out_str = out.str(); | |
| EXPECT_EQ(expected, out_str); | |
| } | |
| Target private_dylib(setup.settings(), | |
| Label(SourceDir("//private_dylib/"), "private_dylib")); | |
| private_dylib.set_output_type(Target::SHARED_LIBRARY); | |
| private_dylib.visibility().SetPublic(); | |
| SourceFile private_dyliblib("//private_dylib/lib.rs"); | |
| private_dylib.sources().push_back(SourceFile("//private_dylib/mylib.rs")); | |
| private_dylib.sources().push_back(private_dyliblib); | |
| private_dylib.source_types_used().Set(SourceFile::SOURCE_RS); | |
| private_dylib.rust_values().set_crate_type(RustValues::CRATE_DYLIB); | |
| private_dylib.rust_values().set_crate_root(private_dyliblib); | |
| private_dylib.rust_values().crate_name() = "private_dylib"; | |
| private_dylib.SetToolchain(setup.toolchain()); | |
| ASSERT_TRUE(private_dylib.OnResolved(&err)); | |
| Target another_dylib(setup.settings(), Label(SourceDir("//foo/"), "direct")); | |
| another_dylib.set_output_type(Target::SHARED_LIBRARY); | |
| another_dylib.visibility().SetPublic(); | |
| SourceFile lib("//foo/main.rs"); | |
| another_dylib.sources().push_back(SourceFile("//foo/direct.rs")); | |
| another_dylib.sources().push_back(lib); | |
| another_dylib.source_types_used().Set(SourceFile::SOURCE_RS); | |
| another_dylib.rust_values().set_crate_type(RustValues::CRATE_DYLIB); | |
| another_dylib.rust_values().set_crate_root(lib); | |
| another_dylib.rust_values().crate_name() = "direct"; | |
| another_dylib.SetToolchain(setup.toolchain()); | |
| another_dylib.public_deps().push_back(LabelTargetPair(&dylib)); | |
| another_dylib.private_deps().push_back(LabelTargetPair(&private_dylib)); | |
| ASSERT_TRUE(another_dylib.OnResolved(&err)); | |
| Target target(setup.settings(), Label(SourceDir("//foo/"), "bar")); | |
| target.set_output_type(Target::EXECUTABLE); | |
| target.visibility().SetPublic(); | |
| SourceFile main("//foo/main.rs"); | |
| target.sources().push_back(SourceFile("//foo/source.rs")); | |
| target.sources().push_back(main); | |
| target.source_types_used().Set(SourceFile::SOURCE_RS); | |
| target.rust_values().set_crate_root(main); | |
| target.rust_values().crate_name() = "foo_bar"; | |
| target.private_deps().push_back(LabelTargetPair(&another_dylib)); | |
| target.SetToolchain(setup.toolchain()); | |
| ASSERT_TRUE(target.OnResolved(&err)); | |
| { | |
| std::ostringstream out; | |
| NinjaRustBinaryTargetWriter writer(&target, out); | |
| writer.Run(); | |
| const char expected[] = | |
| "crate_name = foo_bar\n" | |
| "crate_type = bin\n" | |
| "output_extension = \n" | |
| "output_dir = \n" | |
| "rustflags =\n" | |
| "rustenv =\n" | |
| "root_out_dir = .\n" | |
| "target_gen_dir = gen/foo\n" | |
| "target_out_dir = obj/foo\n" | |
| "target_output_name = bar\n" | |
| "\n" | |
| "build ./foo_bar: rust_bin ../../foo/main.rs | ../../foo/source.rs " | |
| "../../foo/main.rs obj/foo/libdirect.so obj/bar/libmylib.so " | |
| "obj/baz/libinside.rlib\n" | |
| " source_file_part = main.rs\n" | |
| " source_name_part = main\n" | |
| " externs = --extern direct=obj/foo/libdirect.so " | |
| "--extern mylib=obj/bar/libmylib.so " | |
| "--extern inside=obj/baz/libinside.rlib\n" | |
| " rustdeps = -Ldependency=obj/foo -Ldependency=obj/bar " | |
| "-Ldependency=obj/baz -Ldependency=obj/faz " | |
| "-Ldependency=obj/private_dylib\n" | |
| " ldflags =\n" | |
| " sources = ../../foo/source.rs ../../foo/main.rs\n"; | |
| std::string out_str = out.str(); | |
| EXPECT_EQ(expected, out_str); | |
| } | |
| } | |
| TEST_F(NinjaRustBinaryTargetWriterTest, RlibDepsAcrossGroups) { | |
| Err err; | |
| TestWithScope setup; | |
| Target procmacro(setup.settings(), Label(SourceDir("//bar/"), "mymacro")); | |
| procmacro.set_output_type(Target::RUST_PROC_MACRO); | |
| procmacro.visibility().SetPublic(); | |
| SourceFile barproc("//bar/lib.rs"); | |
| procmacro.sources().push_back(SourceFile("//bar/mylib.rs")); | |
| procmacro.sources().push_back(barproc); | |
| procmacro.source_types_used().Set(SourceFile::SOURCE_RS); | |
| procmacro.rust_values().set_crate_root(barproc); | |
| procmacro.rust_values().crate_name() = "mymacro"; | |
| procmacro.rust_values().set_crate_type(RustValues::CRATE_PROC_MACRO); | |
| procmacro.SetToolchain(setup.toolchain()); | |
| ASSERT_TRUE(procmacro.OnResolved(&err)); | |
| { | |
| std::ostringstream out; | |
| NinjaRustBinaryTargetWriter writer(&procmacro, out); | |
| writer.Run(); | |
| const char expected[] = | |
| "crate_name = mymacro\n" | |
| "crate_type = proc-macro\n" | |
| "output_extension = .so\n" | |
| "output_dir = \n" | |
| "rustflags =\n" | |
| "rustenv =\n" | |
| "root_out_dir = .\n" | |
| "target_gen_dir = gen/bar\n" | |
| "target_out_dir = obj/bar\n" | |
| "target_output_name = libmymacro\n" | |
| "\n" | |
| "build obj/bar/libmymacro.so: rust_macro ../../bar/lib.rs | " | |
| "../../bar/mylib.rs ../../bar/lib.rs\n" | |
| " source_file_part = lib.rs\n" | |
| " source_name_part = lib\n" | |
| " externs =\n" | |
| " rustdeps =\n" | |
| " ldflags =\n" | |
| " sources = ../../bar/mylib.rs ../../bar/lib.rs\n"; | |
| std::string out_str = out.str(); | |
| EXPECT_EQ(expected, out_str); | |
| } | |
| // A group produces an order-only dependency in ninja: | |
| // https://ninja-build.org/manual.html#ref_dependencies. | |
| // | |
| // If a crate D inside the group is visible to a crate C depending on the | |
| // group, the crate C needs to be rebuilt when D is changed. The group | |
| // dependency does not guarantee that it would, so we test that C has an | |
| // indirect dependency on D through this group. | |
| Target group(setup.settings(), Label(SourceDir("//baz/"), "group")); | |
| group.set_output_type(Target::GROUP); | |
| group.visibility().SetPublic(); | |
| group.public_deps().push_back(LabelTargetPair(&procmacro)); | |
| group.SetToolchain(setup.toolchain()); | |
| ASSERT_TRUE(group.OnResolved(&err)); | |
| Target rlib(setup.settings(), Label(SourceDir("//bar/"), "mylib")); | |
| rlib.set_output_type(Target::RUST_LIBRARY); | |
| rlib.visibility().SetPublic(); | |
| SourceFile barlib("//bar/lib.rs"); | |
| rlib.sources().push_back(SourceFile("//bar/mylib.rs")); | |
| rlib.sources().push_back(barlib); | |
| rlib.source_types_used().Set(SourceFile::SOURCE_RS); | |
| rlib.rust_values().set_crate_root(barlib); | |
| rlib.rust_values().crate_name() = "mylib"; | |
| rlib.SetToolchain(setup.toolchain()); | |
| rlib.public_deps().push_back(LabelTargetPair(&group)); | |
| ASSERT_TRUE(rlib.OnResolved(&err)); | |
| { | |
| std::ostringstream out; | |
| NinjaRustBinaryTargetWriter writer(&rlib, out); | |
| writer.Run(); | |
| // libmymacro.so is inside the obj/baz/group, so would be built before | |
| // libmylib.rlib. However it must also cause libmylib.rlib to be recompiled | |
| // when changed, so we expect an implicit dependency (appearing after `|` on | |
| // the build line) from libmylib.rlib to libmymacro.so. | |
| const char expected[] = | |
| "crate_name = mylib\n" | |
| "crate_type = rlib\n" | |
| "output_extension = .rlib\n" | |
| "output_dir = \n" | |
| "rustflags =\n" | |
| "rustenv =\n" | |
| "root_out_dir = .\n" | |
| "target_gen_dir = gen/bar\n" | |
| "target_out_dir = obj/bar\n" | |
| "target_output_name = libmylib\n" | |
| "\n" | |
| "build obj/bar/libmylib.rlib: rust_rlib ../../bar/lib.rs | " | |
| "../../bar/mylib.rs ../../bar/lib.rs obj/bar/libmymacro.so || " | |
| "obj/bar/libmymacro.so\n" | |
| " source_file_part = lib.rs\n" | |
| " source_name_part = lib\n" | |
| " externs = --extern mymacro=obj/bar/libmymacro.so\n" | |
| " rustdeps = -Ldependency=obj/bar\n" | |
| " ldflags =\n" | |
| " sources = ../../bar/mylib.rs ../../bar/lib.rs\n"; | |
| std::string out_str = out.str(); | |
| EXPECT_EQ(expected, out_str); | |
| } | |
| Target target(setup.settings(), Label(SourceDir("//foo/"), "bar")); | |
| target.set_output_type(Target::EXECUTABLE); | |
| target.visibility().SetPublic(); | |
| SourceFile main("//foo/main.rs"); | |
| target.sources().push_back(SourceFile("//foo/source.rs")); | |
| target.sources().push_back(main); | |
| target.source_types_used().Set(SourceFile::SOURCE_RS); | |
| target.rust_values().set_crate_root(main); | |
| target.rust_values().crate_name() = "foo_bar"; | |
| target.private_deps().push_back(LabelTargetPair(&rlib)); | |
| target.SetToolchain(setup.toolchain()); | |
| ASSERT_TRUE(target.OnResolved(&err)); | |
| { | |
| std::ostringstream out; | |
| NinjaRustBinaryTargetWriter writer(&target, out); | |
| writer.Run(); | |
| const char expected[] = | |
| "crate_name = foo_bar\n" | |
| "crate_type = bin\n" | |
| "output_extension = \n" | |
| "output_dir = \n" | |
| "rustflags =\n" | |
| "rustenv =\n" | |
| "root_out_dir = .\n" | |
| "target_gen_dir = gen/foo\n" | |
| "target_out_dir = obj/foo\n" | |
| "target_output_name = bar\n" | |
| "\n" | |
| "build ./foo_bar: rust_bin ../../foo/main.rs | " | |
| "../../foo/source.rs ../../foo/main.rs " | |
| "obj/bar/libmylib.rlib obj/bar/libmymacro.so\n" | |
| " source_file_part = main.rs\n" | |
| " source_name_part = main\n" | |
| " externs = --extern mylib=obj/bar/libmylib.rlib " | |
| "--extern mymacro=obj/bar/libmymacro.so\n" | |
| " rustdeps = -Ldependency=obj/bar\n" | |
| " ldflags =\n" | |
| " sources = ../../foo/source.rs ../../foo/main.rs\n"; | |
| std::string out_str = out.str(); | |
| EXPECT_EQ(expected, out_str); | |
| } | |
| } | |
| // Tests that order-only dependencies bypass group targets and use .linkdeps | |
| // for transitive source set dependencies in Rust targets. | |
| TEST_F(NinjaRustBinaryTargetWriterTest, GroupOrderOnlyDeps) { | |
| Err err; | |
| TestWithScope setup; | |
| Value outputs_value(nullptr, Value::LIST); | |
| outputs_value.list_value().push_back( | |
| Value(nullptr, "{{target_out_dir}}/{{source_name_part}}.dwo")); | |
| Config config(setup.settings(), Label(SourceDir("//foo/"), "split_dwarf")); | |
| config.visibility().SetPublic(); | |
| std::vector<SubstitutionPattern> patterns; | |
| for (const auto& v : outputs_value.list_value()) { | |
| SubstitutionPattern pattern; | |
| ASSERT_TRUE(pattern.Parse(v, &err)); | |
| patterns.push_back(std::move(pattern)); | |
| } | |
| config.own_values().c_additional_outputs() = std::move(patterns); | |
| ASSERT_TRUE(config.OnResolved(&err)); | |
| // Source set B (dependee, C++) | |
| Target target_b(setup.settings(), Label(SourceDir("//foo/"), "b")); | |
| target_b.set_output_type(Target::SOURCE_SET); | |
| target_b.sources().push_back(SourceFile("//foo/b.cc")); | |
| target_b.source_types_used().Set(SourceFile::SOURCE_CPP); | |
| target_b.visibility().SetPublic(); | |
| target_b.configs().push_back(LabelConfigPair(&config)); | |
| target_b.SetToolchain(setup.toolchain()); | |
| ASSERT_TRUE(target_b.OnResolved(&err)) << err.message(); | |
| // Group E (depender) | |
| Target target_e(setup.settings(), Label(SourceDir("//foo/"), "e")); | |
| target_e.set_output_type(Target::GROUP); | |
| target_e.visibility().SetPublic(); | |
| target_e.private_deps().push_back(LabelTargetPair(&target_b)); | |
| target_e.SetToolchain(setup.toolchain()); | |
| ASSERT_TRUE(target_e.OnResolved(&err)) << err.message(); | |
| // Rust Executable F (depender on group E) | |
| Target target_f(setup.settings(), Label(SourceDir("//foo/"), "f")); | |
| target_f.set_output_type(Target::EXECUTABLE); | |
| SourceFile main("//foo/main.rs"); | |
| target_f.sources().push_back(main); | |
| target_f.source_types_used().Set(SourceFile::SOURCE_RS); | |
| target_f.rust_values().set_crate_root(main); | |
| target_f.rust_values().crate_name() = "f_crate"; | |
| target_f.private_deps().push_back(LabelTargetPair(&target_e)); | |
| target_f.SetToolchain(setup.toolchain()); | |
| ASSERT_TRUE(target_f.OnResolved(&err)) << err.message(); | |
| // Verify F's output | |
| { | |
| std::ostringstream out; | |
| NinjaRustBinaryTargetWriter writer(&target_f, out); | |
| writer.Run(); | |
| const char expected[] = | |
| "crate_name = f_crate\n" | |
| "crate_type = bin\n" | |
| "output_extension = \n" | |
| "output_dir = \n" | |
| "rustflags =\n" | |
| "rustenv =\n" | |
| "root_out_dir = .\n" | |
| "target_gen_dir = gen/foo\n" | |
| "target_out_dir = obj/foo\n" | |
| "target_output_name = f\n" | |
| "\n" | |
| "build ./f_crate: rust_bin ../../foo/main.rs | ../../foo/main.rs " | |
| "obj/foo/b.b.o || phony/foo/b.linkdeps\n" | |
| " source_file_part = main.rs\n" | |
| " source_name_part = main\n" | |
| " externs =\n" | |
| " rustdeps = -Clink-arg=-Bdynamic -Clink-arg=obj/foo/b.b.o\n" | |
| " ldflags =\n" | |
| " sources = ../../foo/main.rs\n"; | |
| EXPECT_EQ(expected, out.str()); | |
| } | |
| } | |
| TEST_F(NinjaRustBinaryTargetWriterTest, RenamedDeps) { | |
| Err err; | |
| TestWithScope setup; | |
| Target transitive(setup.settings(), Label(SourceDir("//faz/"), "transitive")); | |
| transitive.set_output_type(Target::RUST_LIBRARY); | |
| transitive.visibility().SetPublic(); | |
| SourceFile transitive_lib("//faz/transitive/lib.rs"); | |
| transitive.sources().push_back(SourceFile("//faz/transitive/transitive.rs")); | |
| transitive.sources().push_back(transitive_lib); | |
| transitive.source_types_used().Set(SourceFile::SOURCE_RS); | |
| transitive.rust_values().set_crate_root(transitive_lib); | |
| transitive.rust_values().crate_name() = "transitive"; | |
| transitive.SetToolchain(setup.toolchain()); | |
| ASSERT_TRUE(transitive.OnResolved(&err)); | |
| Target rlib(setup.settings(), Label(SourceDir("//baz/"), "mylib")); | |
| rlib.set_output_type(Target::RUST_LIBRARY); | |
| rlib.visibility().SetPublic(); | |
| SourceFile barlib("//baz/bar/lib.rs"); | |
| rlib.sources().push_back(SourceFile("//baz/bar/mylib.rs")); | |
| rlib.sources().push_back(barlib); | |
| rlib.source_types_used().Set(SourceFile::SOURCE_RS); | |
| rlib.rust_values().set_crate_root(barlib); | |
| rlib.rust_values().crate_name() = "mylib"; | |
| rlib.SetToolchain(setup.toolchain()); | |
| rlib.public_deps().push_back(LabelTargetPair(&transitive)); | |
| ASSERT_TRUE(rlib.OnResolved(&err)); | |
| Target direct(setup.settings(), Label(SourceDir("//bar/"), "direct")); | |
| direct.set_output_type(Target::RUST_LIBRARY); | |
| direct.visibility().SetPublic(); | |
| SourceFile direct_lib("//bar/direct/lib.rs"); | |
| direct.sources().push_back(SourceFile("//bar/direct/direct.rs")); | |
| direct.sources().push_back(direct_lib); | |
| direct.source_types_used().Set(SourceFile::SOURCE_RS); | |
| direct.rust_values().set_crate_root(direct_lib); | |
| direct.rust_values().crate_name() = "direct"; | |
| direct.SetToolchain(setup.toolchain()); | |
| ASSERT_TRUE(direct.OnResolved(&err)); | |
| Target target(setup.settings(), Label(SourceDir("//foo/"), "bar")); | |
| target.set_output_type(Target::EXECUTABLE); | |
| target.visibility().SetPublic(); | |
| SourceFile main("//foo/main.rs"); | |
| target.sources().push_back(SourceFile("//foo/source.rs")); | |
| target.sources().push_back(main); | |
| target.source_types_used().Set(SourceFile::SOURCE_RS); | |
| target.rust_values().set_crate_root(main); | |
| target.rust_values().crate_name() = "foo_bar"; | |
| // A direct dependency is renamed. | |
| target.rust_values().aliased_deps()[direct.label()] = "direct_renamed"; | |
| // A transitive public dependency, through `rlib`, is renamed. | |
| target.rust_values().aliased_deps()[transitive.label()] = | |
| "transitive_renamed"; | |
| target.private_deps().push_back(LabelTargetPair(&direct)); | |
| target.private_deps().push_back(LabelTargetPair(&rlib)); | |
| target.SetToolchain(setup.toolchain()); | |
| ASSERT_TRUE(target.OnResolved(&err)); | |
| { | |
| std::ostringstream out; | |
| NinjaRustBinaryTargetWriter writer(&target, out); | |
| writer.Run(); | |
| const char expected[] = | |
| "crate_name = foo_bar\n" | |
| "crate_type = bin\n" | |
| "output_extension = \n" | |
| "output_dir = \n" | |
| "rustflags =\n" | |
| "rustenv =\n" | |
| "root_out_dir = .\n" | |
| "target_gen_dir = gen/foo\n" | |
| "target_out_dir = obj/foo\n" | |
| "target_output_name = bar\n" | |
| "\n" | |
| "build ./foo_bar: rust_bin ../../foo/main.rs | ../../foo/source.rs " | |
| "../../foo/main.rs obj/bar/libdirect.rlib obj/baz/libmylib.rlib " | |
| "obj/faz/libtransitive.rlib\n" | |
| " source_file_part = main.rs\n" | |
| " source_name_part = main\n" | |
| " externs = --extern direct_renamed=obj/bar/libdirect.rlib " | |
| "--extern mylib=obj/baz/libmylib.rlib " | |
| "--extern transitive_renamed=obj/faz/libtransitive.rlib\n" | |
| " rustdeps = -Ldependency=obj/bar -Ldependency=obj/baz " | |
| "-Ldependency=obj/faz\n" | |
| " ldflags =\n" | |
| " sources = ../../foo/source.rs ../../foo/main.rs\n"; | |
| std::string out_str = out.str(); | |
| EXPECT_EQ(expected, out_str); | |
| } | |
| } | |
| TEST_F(NinjaRustBinaryTargetWriterTest, NonRustDeps) { | |
| Err err; | |
| TestWithScope setup; | |
| Target staticlib(setup.settings(), Label(SourceDir("//foo/"), "static")); | |
| staticlib.set_output_type(Target::STATIC_LIBRARY); | |
| staticlib.visibility().SetPublic(); | |
| staticlib.sources().push_back(SourceFile("//foo/static.cpp")); | |
| staticlib.source_types_used().Set(SourceFile::SOURCE_CPP); | |
| staticlib.SetToolchain(setup.toolchain()); | |
| ASSERT_TRUE(staticlib.OnResolved(&err)); | |
| Target rlib(setup.settings(), Label(SourceDir("//bar/"), "mylib")); | |
| rlib.set_output_type(Target::RUST_LIBRARY); | |
| rlib.visibility().SetPublic(); | |
| SourceFile barlib("//bar/lib.rs"); | |
| rlib.sources().push_back(SourceFile("//bar/mylib.rs")); | |
| rlib.sources().push_back(barlib); | |
| rlib.source_types_used().Set(SourceFile::SOURCE_RS); | |
| rlib.rust_values().set_crate_root(barlib); | |
| rlib.rust_values().crate_name() = "mylib"; | |
| rlib.SetToolchain(setup.toolchain()); | |
| ASSERT_TRUE(rlib.OnResolved(&err)); | |
| Target sharedlib(setup.settings(), Label(SourceDir("//foo/"), "shared")); | |
| sharedlib.set_output_type(Target::SHARED_LIBRARY); | |
| sharedlib.visibility().SetPublic(); | |
| sharedlib.sources().push_back(SourceFile("//foo/static.cpp")); | |
| sharedlib.source_types_used().Set(SourceFile::SOURCE_CPP); | |
| sharedlib.SetToolchain(setup.toolchain()); | |
| ASSERT_TRUE(sharedlib.OnResolved(&err)); | |
| Target csourceset(setup.settings(), Label(SourceDir("//baz/"), "sourceset")); | |
| csourceset.set_output_type(Target::SOURCE_SET); | |
| csourceset.visibility().SetPublic(); | |
| csourceset.sources().push_back(SourceFile("//baz/csourceset.cpp")); | |
| csourceset.source_types_used().Set(SourceFile::SOURCE_CPP); | |
| csourceset.SetToolchain(setup.toolchain()); | |
| ASSERT_TRUE(csourceset.OnResolved(&err)); | |
| Toolchain toolchain_with_toc( | |
| setup.settings(), Label(SourceDir("//toolchain_with_toc/"), "with_toc")); | |
| TestWithScope::SetupToolchain(&toolchain_with_toc, true); | |
| Target sharedlib_with_toc(setup.settings(), | |
| Label(SourceDir("//foo/"), "shared_with_toc")); | |
| sharedlib_with_toc.set_output_type(Target::SHARED_LIBRARY); | |
| sharedlib_with_toc.visibility().SetPublic(); | |
| sharedlib_with_toc.sources().push_back(SourceFile("//foo/static.cpp")); | |
| sharedlib_with_toc.source_types_used().Set(SourceFile::SOURCE_CPP); | |
| sharedlib_with_toc.SetToolchain(&toolchain_with_toc); | |
| ASSERT_TRUE(sharedlib_with_toc.OnResolved(&err)); | |
| Target nonrust(setup.settings(), Label(SourceDir("//foo/"), "bar")); | |
| nonrust.set_output_type(Target::EXECUTABLE); | |
| nonrust.visibility().SetPublic(); | |
| SourceFile main("//foo/main.rs"); | |
| nonrust.sources().push_back(SourceFile("//foo/source.rs")); | |
| nonrust.sources().push_back(main); | |
| nonrust.source_types_used().Set(SourceFile::SOURCE_RS); | |
| nonrust.rust_values().set_crate_root(main); | |
| nonrust.rust_values().crate_name() = "foo_bar"; | |
| nonrust.private_deps().push_back(LabelTargetPair(&rlib)); | |
| nonrust.private_deps().push_back(LabelTargetPair(&staticlib)); | |
| nonrust.private_deps().push_back(LabelTargetPair(&sharedlib)); | |
| nonrust.private_deps().push_back(LabelTargetPair(&csourceset)); | |
| nonrust.private_deps().push_back(LabelTargetPair(&sharedlib_with_toc)); | |
| nonrust.SetToolchain(setup.toolchain()); | |
| ASSERT_TRUE(nonrust.OnResolved(&err)); | |
| { | |
| std::ostringstream out; | |
| NinjaRustBinaryTargetWriter writer(&nonrust, out); | |
| writer.Run(); | |
| const char expected[] = | |
| "crate_name = foo_bar\n" | |
| "crate_type = bin\n" | |
| "output_extension = \n" | |
| "output_dir = \n" | |
| "rustflags =\n" | |
| "rustenv =\n" | |
| "root_out_dir = .\n" | |
| "target_gen_dir = gen/foo\n" | |
| "target_out_dir = obj/foo\n" | |
| "target_output_name = bar\n" | |
| "\n" | |
| "build ./foo_bar: rust_bin ../../foo/main.rs | ../../foo/source.rs " | |
| "../../foo/main.rs obj/baz/sourceset.csourceset.o " | |
| "obj/bar/libmylib.rlib " | |
| "obj/foo/libstatic.a ./libshared.so ./libshared_with_toc.so.TOC " | |
| "|| phony/baz/sourceset.linkdeps\n" | |
| " source_file_part = main.rs\n" | |
| " source_name_part = main\n" | |
| " externs = --extern mylib=obj/bar/libmylib.rlib\n" | |
| " rustdeps = -Ldependency=obj/bar -Clink-arg=-Bdynamic " | |
| "-Clink-arg=obj/baz/sourceset.csourceset.o " | |
| "-Clink-arg=obj/foo/libstatic.a -Clink-arg=./libshared.so " | |
| "-Clink-arg=./libshared_with_toc.so\n" | |
| " ldflags =\n" | |
| " sources = ../../foo/source.rs ../../foo/main.rs\n"; | |
| std::string out_str = out.str(); | |
| EXPECT_EQ(expected, out_str); | |
| } | |
| Target nonrust_only(setup.settings(), Label(SourceDir("//foo/"), "bar")); | |
| nonrust_only.set_output_type(Target::EXECUTABLE); | |
| nonrust_only.visibility().SetPublic(); | |
| nonrust_only.sources().push_back(SourceFile("//foo/source.rs")); | |
| nonrust_only.sources().push_back(main); | |
| nonrust_only.source_types_used().Set(SourceFile::SOURCE_RS); | |
| nonrust_only.rust_values().set_crate_root(main); | |
| nonrust_only.rust_values().crate_name() = "foo_bar"; | |
| nonrust_only.private_deps().push_back(LabelTargetPair(&staticlib)); | |
| nonrust_only.SetToolchain(setup.toolchain()); | |
| ASSERT_TRUE(nonrust_only.OnResolved(&err)); | |
| { | |
| std::ostringstream out; | |
| NinjaRustBinaryTargetWriter writer(&nonrust_only, out); | |
| writer.Run(); | |
| const char expected[] = | |
| "crate_name = foo_bar\n" | |
| "crate_type = bin\n" | |
| "output_extension = \n" | |
| "output_dir = \n" | |
| "rustflags =\n" | |
| "rustenv =\n" | |
| "root_out_dir = .\n" | |
| "target_gen_dir = gen/foo\n" | |
| "target_out_dir = obj/foo\n" | |
| "target_output_name = bar\n" | |
| "\n" | |
| "build ./foo_bar: rust_bin ../../foo/main.rs | ../../foo/source.rs " | |
| "../../foo/main.rs obj/foo/libstatic.a\n" | |
| " source_file_part = main.rs\n" | |
| " source_name_part = main\n" | |
| " externs =\n" | |
| " rustdeps = -Clink-arg=-Bdynamic -Clink-arg=obj/foo/libstatic.a\n" | |
| " ldflags =\n" | |
| " sources = ../../foo/source.rs ../../foo/main.rs\n"; | |
| std::string out_str = out.str(); | |
| EXPECT_EQ(expected, out_str); | |
| } | |
| Target rstaticlib(setup.settings(), Label(SourceDir("//baz/"), "baz")); | |
| rstaticlib.set_output_type(Target::STATIC_LIBRARY); | |
| rstaticlib.visibility().SetPublic(); | |
| SourceFile bazlib("//baz/lib.rs"); | |
| rstaticlib.sources().push_back(bazlib); | |
| rstaticlib.source_types_used().Set(SourceFile::SOURCE_RS); | |
| rstaticlib.rust_values().set_crate_root(bazlib); | |
| rstaticlib.rust_values().crate_name() = "baz"; | |
| rstaticlib.private_deps().push_back(LabelTargetPair(&staticlib)); | |
| rstaticlib.SetToolchain(setup.toolchain()); | |
| ASSERT_TRUE(rstaticlib.OnResolved(&err)); | |
| { | |
| std::ostringstream out; | |
| NinjaRustBinaryTargetWriter writer(&rstaticlib, out); | |
| writer.Run(); | |
| const char expected[] = | |
| "crate_name = baz\n" | |
| "crate_type = staticlib\n" | |
| "output_extension = .a\n" | |
| "output_dir = \n" | |
| "rustflags =\n" | |
| "rustenv =\n" | |
| "root_out_dir = .\n" | |
| "target_gen_dir = gen/baz\n" | |
| "target_out_dir = obj/baz\n" | |
| "target_output_name = libbaz\n" | |
| "\n" | |
| "build obj/baz/libbaz.a: rust_staticlib ../../baz/lib.rs | " | |
| "../../baz/lib.rs " | |
| "obj/foo/libstatic.a\n" | |
| " source_file_part = lib.rs\n" | |
| " source_name_part = lib\n" | |
| " externs =\n" | |
| " rustdeps = -Clink-arg=-Balternative-dynamic " | |
| "-Clink-arg=obj/foo/libstatic.a\n" | |
| " ldflags =\n" | |
| " sources = ../../baz/lib.rs\n"; | |
| std::string out_str = out.str(); | |
| EXPECT_EQ(expected, out_str); | |
| } | |
| } | |
| TEST_F(NinjaRustBinaryTargetWriterTest, RlibInLibrary) { | |
| Err err; | |
| TestWithScope setup; | |
| Target priv_sset_in_staticlib( | |
| setup.settings(), | |
| Label(SourceDir("//priv_sset_in_staticlib/"), "priv_sset_in_staticlib")); | |
| priv_sset_in_staticlib.set_output_type(Target::SOURCE_SET); | |
| priv_sset_in_staticlib.visibility().SetPublic(); | |
| priv_sset_in_staticlib.sources().push_back( | |
| SourceFile("//priv_sset_in_staticlib/lib.cc")); | |
| priv_sset_in_staticlib.source_types_used().Set(SourceFile::SOURCE_CPP); | |
| priv_sset_in_staticlib.SetToolchain(setup.toolchain()); | |
| ASSERT_TRUE(priv_sset_in_staticlib.OnResolved(&err)); | |
| Target pub_sset_in_staticlib( | |
| setup.settings(), | |
| Label(SourceDir("//pub_sset_in_staticlib/"), "pub_sset_in_staticlib")); | |
| pub_sset_in_staticlib.set_output_type(Target::SOURCE_SET); | |
| pub_sset_in_staticlib.visibility().SetPublic(); | |
| pub_sset_in_staticlib.sources().push_back( | |
| SourceFile("//pub_sset_in_staticlib/lib.cc")); | |
| pub_sset_in_staticlib.source_types_used().Set(SourceFile::SOURCE_CPP); | |
| pub_sset_in_staticlib.SetToolchain(setup.toolchain()); | |
| ASSERT_TRUE(pub_sset_in_staticlib.OnResolved(&err)); | |
| Target priv_sset_in_dylib( | |
| setup.settings(), | |
| Label(SourceDir("//priv_sset_in_dylib/"), "priv_sset_in_dylib")); | |
| priv_sset_in_dylib.set_output_type(Target::SOURCE_SET); | |
| priv_sset_in_dylib.visibility().SetPublic(); | |
| priv_sset_in_dylib.sources().push_back( | |
| SourceFile("//priv_sset_in_dylib/lib.cc")); | |
| priv_sset_in_dylib.source_types_used().Set(SourceFile::SOURCE_CPP); | |
| priv_sset_in_dylib.SetToolchain(setup.toolchain()); | |
| ASSERT_TRUE(priv_sset_in_dylib.OnResolved(&err)); | |
| Target pub_sset_in_dylib( | |
| setup.settings(), | |
| Label(SourceDir("//pub_sset_in_dylib"), "pub_sset_in_dylib")); | |
| pub_sset_in_dylib.set_output_type(Target::SOURCE_SET); | |
| pub_sset_in_dylib.visibility().SetPublic(); | |
| pub_sset_in_dylib.sources().push_back( | |
| SourceFile("//pub_sset_in_dylib/lib.cc")); | |
| pub_sset_in_dylib.source_types_used().Set(SourceFile::SOURCE_CPP); | |
| pub_sset_in_dylib.SetToolchain(setup.toolchain()); | |
| ASSERT_TRUE(pub_sset_in_dylib.OnResolved(&err)); | |
| Target priv_in_staticlib( | |
| setup.settings(), | |
| Label(SourceDir("//priv_in_staticlib/"), "priv_in_staticlib")); | |
| priv_in_staticlib.set_output_type(Target::RUST_LIBRARY); | |
| priv_in_staticlib.visibility().SetPublic(); | |
| SourceFile priv_in_staticlib_root("//priv_in_staticlib/lib.rs"); | |
| priv_in_staticlib.sources().push_back(priv_in_staticlib_root); | |
| priv_in_staticlib.source_types_used().Set(SourceFile::SOURCE_RS); | |
| priv_in_staticlib.rust_values().set_crate_root(priv_in_staticlib_root); | |
| priv_in_staticlib.rust_values().crate_name() = "priv_in_staticlib"; | |
| priv_in_staticlib.SetToolchain(setup.toolchain()); | |
| priv_in_staticlib.private_deps().push_back( | |
| LabelTargetPair(&priv_sset_in_staticlib)); | |
| ASSERT_TRUE(priv_in_staticlib.OnResolved(&err)); | |
| Target pub_in_staticlib( | |
| setup.settings(), | |
| Label(SourceDir("//pub_in_staticlib/"), "pub_in_staticlib")); | |
| pub_in_staticlib.set_output_type(Target::RUST_LIBRARY); | |
| pub_in_staticlib.visibility().SetPublic(); | |
| SourceFile pub_in_staticlib_root("//pub_in_staticlib/lib.rs"); | |
| pub_in_staticlib.sources().push_back(pub_in_staticlib_root); | |
| pub_in_staticlib.source_types_used().Set(SourceFile::SOURCE_RS); | |
| pub_in_staticlib.rust_values().set_crate_root(pub_in_staticlib_root); | |
| pub_in_staticlib.rust_values().crate_name() = "pub_in_staticlib"; | |
| pub_in_staticlib.SetToolchain(setup.toolchain()); | |
| pub_in_staticlib.private_deps().push_back( | |
| LabelTargetPair(&pub_sset_in_staticlib)); | |
| ASSERT_TRUE(pub_in_staticlib.OnResolved(&err)); | |
| Target priv_in_dylib(setup.settings(), | |
| Label(SourceDir("//priv_in_dylib/"), "priv_in_dylib")); | |
| priv_in_dylib.set_output_type(Target::RUST_LIBRARY); | |
| priv_in_dylib.visibility().SetPublic(); | |
| SourceFile priv_in_dylib_root("//priv_in_dylib/lib.rs"); | |
| priv_in_dylib.sources().push_back(priv_in_dylib_root); | |
| priv_in_dylib.source_types_used().Set(SourceFile::SOURCE_RS); | |
| priv_in_dylib.rust_values().set_crate_root(priv_in_dylib_root); | |
| priv_in_dylib.rust_values().crate_name() = "priv_in_dylib"; | |
| priv_in_dylib.SetToolchain(setup.toolchain()); | |
| priv_in_dylib.private_deps().push_back(LabelTargetPair(&priv_sset_in_dylib)); | |
| ASSERT_TRUE(priv_in_dylib.OnResolved(&err)); | |
| Target pub_in_dylib(setup.settings(), | |
| Label(SourceDir("//pub_in_dylib/"), "pub_in_dylib")); | |
| pub_in_dylib.set_output_type(Target::RUST_LIBRARY); | |
| pub_in_dylib.visibility().SetPublic(); | |
| SourceFile pub_in_dylib_root("//pub_in_dylib/lib.rs"); | |
| pub_in_dylib.sources().push_back(pub_in_dylib_root); | |
| pub_in_dylib.source_types_used().Set(SourceFile::SOURCE_RS); | |
| pub_in_dylib.rust_values().set_crate_root(pub_in_dylib_root); | |
| pub_in_dylib.rust_values().crate_name() = "pub_in_dylib"; | |
| pub_in_dylib.SetToolchain(setup.toolchain()); | |
| pub_in_dylib.private_deps().push_back(LabelTargetPair(&pub_sset_in_dylib)); | |
| ASSERT_TRUE(pub_in_dylib.OnResolved(&err)); | |
| Target staticlib(setup.settings(), | |
| Label(SourceDir("//staticlib/"), "staticlib")); | |
| staticlib.set_output_type(Target::STATIC_LIBRARY); | |
| staticlib.visibility().SetPublic(); | |
| staticlib.sources().push_back(SourceFile("//staticlib/lib.cc")); | |
| staticlib.source_types_used().Set(SourceFile::SOURCE_CPP); | |
| staticlib.public_deps().push_back(LabelTargetPair(&pub_in_staticlib)); | |
| staticlib.private_deps().push_back(LabelTargetPair(&priv_in_staticlib)); | |
| staticlib.SetToolchain(setup.toolchain()); | |
| ASSERT_TRUE(staticlib.OnResolved(&err)); | |
| Target dylib(setup.settings(), Label(SourceDir("//dylib/"), "dylib")); | |
| dylib.set_output_type(Target::SHARED_LIBRARY); | |
| dylib.visibility().SetPublic(); | |
| SourceFile dylib_root("//dylib/lib.rs"); | |
| dylib.sources().push_back(dylib_root); | |
| dylib.source_types_used().Set(SourceFile::SOURCE_RS); | |
| dylib.rust_values().set_crate_root(dylib_root); | |
| dylib.rust_values().crate_name() = "dylib"; | |
| dylib.public_deps().push_back(LabelTargetPair(&pub_in_dylib)); | |
| dylib.private_deps().push_back(LabelTargetPair(&priv_in_dylib)); | |
| dylib.SetToolchain(setup.toolchain()); | |
| ASSERT_TRUE(dylib.OnResolved(&err)); | |
| Target target(setup.settings(), Label(SourceDir("//exe/"), "exe")); | |
| target.set_output_type(Target::EXECUTABLE); | |
| target.visibility().SetPublic(); | |
| SourceFile main("//exe/main.rs"); | |
| target.sources().push_back(main); | |
| target.source_types_used().Set(SourceFile::SOURCE_RS); | |
| target.rust_values().set_crate_root(main); | |
| target.rust_values().crate_name() = "exe"; | |
| target.private_deps().push_back(LabelTargetPair(&staticlib)); | |
| target.private_deps().push_back(LabelTargetPair(&dylib)); | |
| target.SetToolchain(setup.toolchain()); | |
| ASSERT_TRUE(target.OnResolved(&err)); | |
| std::ostringstream out; | |
| NinjaRustBinaryTargetWriter writer(&target, out); | |
| writer.Run(); | |
| const char expected[] = | |
| "crate_name = exe\n" | |
| "crate_type = bin\n" | |
| "output_extension = \n" | |
| "output_dir = \n" | |
| "rustflags =\n" | |
| "rustenv =\n" | |
| "root_out_dir = .\n" | |
| "target_gen_dir = gen/exe\n" | |
| "target_out_dir = obj/exe\n" | |
| "target_output_name = exe\n" | |
| "\n" | |
| "build ./exe: rust_bin ../../exe/main.rs | " | |
| "../../exe/main.rs " | |
| "obj/pub_sset_in_staticlib/pub_sset_in_staticlib.lib.o " | |
| "obj/priv_sset_in_staticlib/priv_sset_in_staticlib.lib.o " | |
| "obj/staticlib/libstaticlib.a " | |
| "obj/dylib/libdylib.so " | |
| "obj/pub_in_staticlib/libpub_in_staticlib.rlib " | |
| "obj/priv_in_staticlib/libpriv_in_staticlib.rlib " | |
| "obj/pub_in_dylib/libpub_in_dylib.rlib || " | |
| "phony/pub_sset_in_staticlib/pub_sset_in_staticlib.linkdeps " | |
| "phony/priv_sset_in_staticlib/priv_sset_in_staticlib.linkdeps\n" | |
| " source_file_part = main.rs\n" | |
| " source_name_part = main\n" | |
| " externs = " | |
| "--extern pub_in_staticlib=obj/pub_in_staticlib/libpub_in_staticlib.rlib " | |
| "--extern dylib=obj/dylib/libdylib.so " | |
| "--extern pub_in_dylib=obj/pub_in_dylib/libpub_in_dylib.rlib\n" | |
| " rustdeps = -Ldependency=obj/pub_in_staticlib " | |
| "-Ldependency=obj/priv_in_staticlib -Ldependency=obj/dylib " | |
| "-Ldependency=obj/pub_in_dylib -Ldependency=obj/priv_in_dylib " | |
| "-Clink-arg=-Bdynamic " | |
| "-Clink-arg=obj/pub_sset_in_staticlib/pub_sset_in_staticlib.lib.o " | |
| "-Clink-arg=obj/priv_sset_in_staticlib/priv_sset_in_staticlib.lib.o " | |
| "-Clink-arg=obj/staticlib/libstaticlib.a " | |
| "-Clink-arg=obj/priv_in_staticlib/libpriv_in_staticlib.rlib\n" | |
| " ldflags =\n" | |
| " sources = ../../exe/main.rs\n"; | |
| std::string out_str = out.str(); | |
| EXPECT_EQ(expected, out_str); | |
| } | |
| TEST_F(NinjaRustBinaryTargetWriterTest, RustOutputExtensionAndDir) { | |
| Err err; | |
| TestWithScope setup; | |
| Target target(setup.settings(), Label(SourceDir("//foo/"), "bar")); | |
| target.set_output_type(Target::EXECUTABLE); | |
| target.visibility().SetPublic(); | |
| SourceFile main("//foo/main.rs"); | |
| target.sources().push_back(SourceFile("//foo/input3.rs")); | |
| target.sources().push_back(main); | |
| target.source_types_used().Set(SourceFile::SOURCE_RS); | |
| target.set_output_extension(std::string("exe")); | |
| target.set_output_dir(SourceDir("//out/Debug/foo/")); | |
| target.rust_values().set_crate_root(main); | |
| target.rust_values().crate_name() = "foo_bar"; | |
| target.SetToolchain(setup.toolchain()); | |
| ASSERT_TRUE(target.OnResolved(&err)); | |
| { | |
| std::ostringstream out; | |
| NinjaRustBinaryTargetWriter writer(&target, out); | |
| writer.Run(); | |
| const char expected[] = | |
| "crate_name = foo_bar\n" | |
| "crate_type = bin\n" | |
| "output_extension = .exe\n" | |
| "output_dir = foo\n" | |
| "rustflags =\n" | |
| "rustenv =\n" | |
| "root_out_dir = .\n" | |
| "target_gen_dir = gen/foo\n" | |
| "target_out_dir = obj/foo\n" | |
| "target_output_name = bar\n" | |
| "\n" | |
| "build ./foo_bar.exe: rust_bin ../../foo/main.rs | ../../foo/input3.rs " | |
| "../../foo/main.rs\n" | |
| " source_file_part = main.rs\n" | |
| " source_name_part = main\n" | |
| " externs =\n" | |
| " rustdeps =\n" | |
| " ldflags =\n" | |
| " sources = ../../foo/input3.rs ../../foo/main.rs\n"; | |
| std::string out_str = out.str(); | |
| EXPECT_EQ(expected, out_str); | |
| } | |
| } | |
| TEST_F(NinjaRustBinaryTargetWriterTest, LibsAndLibDirs) { | |
| Err err; | |
| TestWithScope setup; | |
| Target rlib(setup.settings(), Label(SourceDir("//bar/"), "rlib")); | |
| rlib.set_output_type(Target::RUST_LIBRARY); | |
| rlib.visibility().SetPublic(); | |
| SourceFile barlib("//bar/lib.rs"); | |
| rlib.sources().push_back(SourceFile("//bar/rlib.rs")); | |
| rlib.sources().push_back(barlib); | |
| rlib.source_types_used().Set(SourceFile::SOURCE_RS); | |
| rlib.rust_values().set_crate_root(barlib); | |
| rlib.rust_values().crate_name() = "rlibcrate"; | |
| rlib.config_values().libs().push_back(LibFile("rliblib")); | |
| rlib.config_values().lib_dirs().push_back(SourceDir("//rliblibdir/")); | |
| rlib.config_values().framework_dirs().push_back(SourceDir("//rlibfwdir/")); | |
| rlib.SetToolchain(setup.toolchain()); | |
| ASSERT_TRUE(rlib.OnResolved(&err)); | |
| Target target(setup.settings(), Label(SourceDir("//foo/"), "bar")); | |
| target.set_output_type(Target::EXECUTABLE); | |
| target.visibility().SetPublic(); | |
| SourceFile main("//foo/main.rs"); | |
| target.sources().push_back(SourceFile("//foo/input.rs")); | |
| target.sources().push_back(main); | |
| target.source_types_used().Set(SourceFile::SOURCE_RS); | |
| target.set_output_dir(SourceDir("//out/Debug/foo/")); | |
| target.config_values().libs().push_back(LibFile(SourceFile("//dir1/ar.a"))); | |
| target.config_values().libs().push_back(LibFile("binlib")); | |
| target.config_values().lib_dirs().push_back(SourceDir("//binlibdir/")); | |
| target.config_values().framework_dirs().push_back(SourceDir("//binfwdir/")); | |
| target.public_deps().push_back(LabelTargetPair(&rlib)); | |
| target.rust_values().set_crate_root(main); | |
| target.rust_values().crate_name() = "foo_bar"; | |
| target.SetToolchain(setup.toolchain()); | |
| ASSERT_TRUE(target.OnResolved(&err)); | |
| { | |
| std::ostringstream out; | |
| NinjaRustBinaryTargetWriter writer(&target, out); | |
| writer.Run(); | |
| const char expected[] = | |
| "crate_name = foo_bar\n" | |
| "crate_type = bin\n" | |
| "output_extension = \n" | |
| "output_dir = foo\n" | |
| "rustflags =\n" | |
| "rustenv =\n" | |
| "root_out_dir = .\n" | |
| "target_gen_dir = gen/foo\n" | |
| "target_out_dir = obj/foo\n" | |
| "target_output_name = bar\n" | |
| "\n" | |
| "build ./foo_bar: rust_bin ../../foo/main.rs | ../../foo/input.rs " | |
| "../../foo/main.rs obj/bar/librlib.rlib\n" | |
| " source_file_part = main.rs\n" | |
| " source_name_part = main\n" | |
| " externs = --extern rlibcrate=obj/bar/librlib.rlib\n" | |
| " rustdeps = -Ldependency=obj/bar -Lnative=../../binlibdir " | |
| "-Lnative=../../rliblibdir -Lframework=../../binfwdir " | |
| "-Lframework=../../rlibfwdir -Clink-arg=../../dir1/ar.a -lbinlib " | |
| "-lrliblib\n" | |
| " ldflags =\n" | |
| " sources = ../../foo/input.rs ../../foo/main.rs\n"; | |
| std::string out_str = out.str(); | |
| EXPECT_EQ(expected, out_str); | |
| } | |
| } | |
| TEST_F(NinjaRustBinaryTargetWriterTest, RlibWithLibDeps) { | |
| Err err; | |
| TestWithScope setup; | |
| Target public_rlib(setup.settings(), Label(SourceDir("//bar/"), "publiclib")); | |
| public_rlib.set_output_type(Target::RUST_LIBRARY); | |
| public_rlib.visibility().SetPublic(); | |
| SourceFile barlib("//bar/lib.rs"); | |
| public_rlib.sources().push_back(SourceFile("//bar/publiclib.rs")); | |
| public_rlib.sources().push_back(barlib); | |
| public_rlib.source_types_used().Set(SourceFile::SOURCE_RS); | |
| public_rlib.rust_values().set_crate_root(barlib); | |
| public_rlib.rust_values().crate_name() = "publiccrate"; | |
| public_rlib.SetToolchain(setup.toolchain()); | |
| ASSERT_TRUE(public_rlib.OnResolved(&err)); | |
| Target staticlib(setup.settings(), Label(SourceDir("//clib/"), "static")); | |
| staticlib.set_output_type(Target::STATIC_LIBRARY); | |
| staticlib.visibility().SetPublic(); | |
| staticlib.sources().push_back(SourceFile("//foo/clib.cpp")); | |
| staticlib.source_types_used().Set(SourceFile::SOURCE_CPP); | |
| staticlib.SetToolchain(setup.toolchain()); | |
| ASSERT_TRUE(staticlib.OnResolved(&err)); | |
| Target rlib(setup.settings(), Label(SourceDir("//foo/"), "rlibcrate")); | |
| rlib.set_output_type(Target::RUST_LIBRARY); | |
| rlib.visibility().SetPublic(); | |
| SourceFile lib("//foo/input.rs"); | |
| rlib.sources().push_back(lib); | |
| rlib.source_types_used().Set(SourceFile::SOURCE_RS); | |
| rlib.rust_values().set_crate_root(lib); | |
| rlib.rust_values().crate_name() = "rlibcrate"; | |
| rlib.SetToolchain(setup.toolchain()); | |
| rlib.public_deps().push_back(LabelTargetPair(&public_rlib)); | |
| // This adds dependencies on static libraries, which are not consumed by an | |
| // rlib since it does not get linked. None of these should appear in | |
| // `rustdeps` for a `rust_rlib`, though they would for a `rust_bin` (as tested | |
| // for above). | |
| // | |
| // 1. A dependency on an archive file directly as happens with a `libs` rule, | |
| // requesting a system library. The path to that library must be specified | |
| // separately with `-L` in ldflags, the library does not appear in the | |
| // rustc compilation of an rlib. | |
| rlib.config_values().libs().push_back(LibFile(SourceFile("//dir1/ar.a"))); | |
| // 2. A dependency on a library name as happens with a `libs` rule. Libraries | |
| // need only be named when linking, they do not need to appear in an rlib | |
| // compilation. | |
| rlib.config_values().libs().push_back(LibFile("quux")); | |
| // 3. A dependency on a library path which will be used for linking, which is | |
| // separate from the dependency paths for finding Rust crates. But it may | |
| // be needed to resolve the path to a native library in a #[link] | |
| // directive. | |
| rlib.config_values().lib_dirs().push_back(SourceDir("//baz/")); | |
| // 4. A framework search directory will be used for linking frameworks, which | |
| // is also separate from finding Rust crates. Again a #[link] directive can | |
| // point to a framework, so these paths need to be present during | |
| // compilation | |
| rlib.config_values().framework_dirs().push_back(SourceDir("//fwdir/")); | |
| // 5. A dependency on a C library through a `deps` rule, which points to a | |
| // `static_library` target. GN guarantees that Rust can refer to that | |
| // library through #[link] without having to specify the path in ldflags | |
| // as well. | |
| rlib.private_deps().push_back(LabelTargetPair(&staticlib)); | |
| ASSERT_TRUE(rlib.OnResolved(&err)); | |
| { | |
| std::ostringstream out; | |
| NinjaRustBinaryTargetWriter writer(&rlib, out); | |
| writer.Run(); | |
| const char expected[] = | |
| "crate_name = rlibcrate\n" | |
| "crate_type = rlib\n" | |
| "output_extension = .rlib\n" | |
| "output_dir = \n" | |
| "rustflags =\n" | |
| "rustenv =\n" | |
| "root_out_dir = .\n" | |
| "target_gen_dir = gen/foo\n" | |
| "target_out_dir = obj/foo\n" | |
| "target_output_name = librlibcrate\n" | |
| "\n" | |
| "build obj/foo/librlibcrate.rlib: rust_rlib ../../foo/input.rs | " | |
| "../../foo/input.rs obj/bar/libpubliclib.rlib obj/clib/libstatic.a\n" | |
| " source_file_part = input.rs\n" | |
| " source_name_part = input\n" | |
| " externs = --extern publiccrate=obj/bar/libpubliclib.rlib\n" | |
| " rustdeps = -Ldependency=obj/bar -Clink-arg=-Bdynamic " | |
| "-Clink-arg=obj/clib/libstatic.a " | |
| "-Lnative=../../baz -Lframework=../../fwdir -Clink-arg=../../dir1/ar.a " | |
| "-lquux\n" | |
| " ldflags =\n" | |
| " sources = ../../foo/input.rs\n"; | |
| std::string out_str = out.str(); | |
| EXPECT_EQ(expected, out_str); | |
| } | |
| } | |
| // Test that neither public nor private rust dependencies of a proc-macro are | |
| // transitively acquired as accessible dependencies by users of the macro. But | |
| // the macro itself is listed as an accessible dependency (via --extern). | |
| TEST_F(NinjaRustBinaryTargetWriterTest, RustProcMacro) { | |
| Err err; | |
| TestWithScope setup; | |
| Target procmacropublicdep( | |
| setup.settings(), Label(SourceDir("//baz/public/"), "mymacropublicdep")); | |
| procmacropublicdep.set_output_type(Target::RUST_LIBRARY); | |
| procmacropublicdep.visibility().SetPublic(); | |
| SourceFile publicbazlib("//baz/public/lib.rs"); | |
| procmacropublicdep.sources().push_back(SourceFile("//baz/public/mylib.rs")); | |
| procmacropublicdep.sources().push_back(publicbazlib); | |
| procmacropublicdep.source_types_used().Set(SourceFile::SOURCE_RS); | |
| procmacropublicdep.rust_values().set_crate_root(publicbazlib); | |
| procmacropublicdep.rust_values().crate_name() = "publicdep"; | |
| procmacropublicdep.SetToolchain(setup.toolchain()); | |
| ASSERT_TRUE(procmacropublicdep.OnResolved(&err)); | |
| Target procmacroprivatedep( | |
| setup.settings(), | |
| Label(SourceDir("//baz/private/"), "mymacroprivatedep")); | |
| procmacroprivatedep.set_output_type(Target::RUST_LIBRARY); | |
| procmacroprivatedep.visibility().SetPublic(); | |
| SourceFile privatebazlib("//baz/private/lib.rs"); | |
| procmacroprivatedep.sources().push_back(SourceFile("//baz/private/mylib.rs")); | |
| procmacroprivatedep.sources().push_back(privatebazlib); | |
| procmacroprivatedep.source_types_used().Set(SourceFile::SOURCE_RS); | |
| procmacroprivatedep.rust_values().set_crate_root(privatebazlib); | |
| procmacroprivatedep.rust_values().crate_name() = "privatedep"; | |
| procmacroprivatedep.SetToolchain(setup.toolchain()); | |
| ASSERT_TRUE(procmacroprivatedep.OnResolved(&err)); | |
| Target procmacro(setup.settings(), Label(SourceDir("//bar/"), "mymacro")); | |
| procmacro.set_output_type(Target::RUST_PROC_MACRO); | |
| procmacro.visibility().SetPublic(); | |
| SourceFile barlib("//bar/lib.rs"); | |
| procmacro.sources().push_back(SourceFile("//bar/mylib.rs")); | |
| procmacro.sources().push_back(barlib); | |
| procmacro.source_types_used().Set(SourceFile::SOURCE_RS); | |
| procmacro.rust_values().set_crate_root(barlib); | |
| procmacro.rust_values().crate_name() = "mymacro"; | |
| procmacro.rust_values().set_crate_type(RustValues::CRATE_PROC_MACRO); | |
| // Add a dependency to the procmacro so we can be sure its output | |
| // directory is not propagated downstream beyond the proc macro. | |
| procmacro.public_deps().push_back(LabelTargetPair(&procmacropublicdep)); | |
| procmacro.private_deps().push_back(LabelTargetPair(&procmacroprivatedep)); | |
| procmacro.SetToolchain(setup.toolchain()); | |
| ASSERT_TRUE(procmacro.OnResolved(&err)); | |
| { | |
| std::ostringstream out; | |
| NinjaRustBinaryTargetWriter writer(&procmacro, out); | |
| writer.Run(); | |
| const char expected[] = | |
| "crate_name = mymacro\n" | |
| "crate_type = proc-macro\n" | |
| "output_extension = .so\n" | |
| "output_dir = \n" | |
| "rustflags =\n" | |
| "rustenv =\n" | |
| "root_out_dir = .\n" | |
| "target_gen_dir = gen/bar\n" | |
| "target_out_dir = obj/bar\n" | |
| "target_output_name = libmymacro\n" | |
| "\n" | |
| "build obj/bar/libmymacro.so: rust_macro ../../bar/lib.rs | " | |
| "../../bar/mylib.rs ../../bar/lib.rs " | |
| "obj/baz/public/libmymacropublicdep.rlib " | |
| "obj/baz/private/libmymacroprivatedep.rlib\n" | |
| " source_file_part = lib.rs\n" | |
| " source_name_part = lib\n" | |
| " externs = " | |
| "--extern publicdep=obj/baz/public/libmymacropublicdep.rlib " | |
| "--extern privatedep=obj/baz/private/libmymacroprivatedep.rlib\n" | |
| " rustdeps = -Ldependency=obj/baz/public " | |
| "-Ldependency=obj/baz/private\n" | |
| " ldflags =\n" | |
| " sources = ../../bar/mylib.rs ../../bar/lib.rs\n"; | |
| std::string out_str = out.str(); | |
| EXPECT_EQ(expected, out_str); | |
| } | |
| Target target(setup.settings(), Label(SourceDir("//foo/"), "bar")); | |
| target.set_output_type(Target::EXECUTABLE); | |
| target.visibility().SetPublic(); | |
| SourceFile main("//foo/main.rs"); | |
| target.sources().push_back(SourceFile("//foo/source.rs")); | |
| target.sources().push_back(main); | |
| target.source_types_used().Set(SourceFile::SOURCE_RS); | |
| target.rust_values().set_crate_root(main); | |
| target.rust_values().crate_name() = "foo_bar"; | |
| target.private_deps().push_back(LabelTargetPair(&procmacro)); | |
| target.SetToolchain(setup.toolchain()); | |
| ASSERT_TRUE(target.OnResolved(&err)); | |
| { | |
| std::ostringstream out; | |
| NinjaRustBinaryTargetWriter writer(&target, out); | |
| writer.Run(); | |
| const char expected[] = | |
| "crate_name = foo_bar\n" | |
| "crate_type = bin\n" | |
| "output_extension = \n" | |
| "output_dir = \n" | |
| "rustflags =\n" | |
| "rustenv =\n" | |
| "root_out_dir = .\n" | |
| "target_gen_dir = gen/foo\n" | |
| "target_out_dir = obj/foo\n" | |
| "target_output_name = bar\n" | |
| "\n" | |
| "build ./foo_bar: rust_bin ../../foo/main.rs | ../../foo/source.rs " | |
| "../../foo/main.rs obj/bar/libmymacro.so\n" | |
| " source_file_part = main.rs\n" | |
| " source_name_part = main\n" | |
| " externs = --extern mymacro=obj/bar/libmymacro.so\n" | |
| " rustdeps = -Ldependency=obj/bar\n" | |
| " ldflags =\n" | |
| " sources = ../../foo/source.rs ../../foo/main.rs\n"; | |
| std::string out_str = out.str(); | |
| EXPECT_EQ(expected, out_str); | |
| } | |
| } | |
| TEST_F(NinjaRustBinaryTargetWriterTest, GroupDeps) { | |
| Err err; | |
| TestWithScope setup; | |
| Target rlib(setup.settings(), Label(SourceDir("//bar/"), "mylib")); | |
| rlib.set_output_type(Target::RUST_LIBRARY); | |
| rlib.visibility().SetPublic(); | |
| SourceFile barlib("//bar/lib.rs"); | |
| rlib.sources().push_back(SourceFile("//bar/mylib.rs")); | |
| rlib.sources().push_back(barlib); | |
| rlib.source_types_used().Set(SourceFile::SOURCE_RS); | |
| rlib.rust_values().set_crate_root(barlib); | |
| rlib.rust_values().crate_name() = "mylib"; | |
| rlib.SetToolchain(setup.toolchain()); | |
| ASSERT_TRUE(rlib.OnResolved(&err)); | |
| { | |
| std::ostringstream out; | |
| NinjaRustBinaryTargetWriter writer(&rlib, out); | |
| writer.Run(); | |
| const char expected[] = | |
| "crate_name = mylib\n" | |
| "crate_type = rlib\n" | |
| "output_extension = .rlib\n" | |
| "output_dir = \n" | |
| "rustflags =\n" | |
| "rustenv =\n" | |
| "root_out_dir = .\n" | |
| "target_gen_dir = gen/bar\n" | |
| "target_out_dir = obj/bar\n" | |
| "target_output_name = libmylib\n" | |
| "\n" | |
| "build obj/bar/libmylib.rlib: rust_rlib ../../bar/lib.rs | " | |
| "../../bar/mylib.rs ../../bar/lib.rs\n" | |
| " source_file_part = lib.rs\n" | |
| " source_name_part = lib\n" | |
| " externs =\n" | |
| " rustdeps =\n" | |
| " ldflags =\n" | |
| " sources = ../../bar/mylib.rs ../../bar/lib.rs\n"; | |
| std::string out_str = out.str(); | |
| EXPECT_EQ(expected, out_str); | |
| } | |
| Target group(setup.settings(), Label(SourceDir("//baz/"), "group")); | |
| group.set_output_type(Target::GROUP); | |
| group.visibility().SetPublic(); | |
| group.public_deps().push_back(LabelTargetPair(&rlib)); | |
| group.SetToolchain(setup.toolchain()); | |
| ASSERT_TRUE(group.OnResolved(&err)); | |
| Target target(setup.settings(), Label(SourceDir("//foo/"), "bar")); | |
| target.set_output_type(Target::EXECUTABLE); | |
| target.visibility().SetPublic(); | |
| SourceFile main("//foo/main.rs"); | |
| target.sources().push_back(SourceFile("//foo/source.rs")); | |
| target.sources().push_back(main); | |
| target.source_types_used().Set(SourceFile::SOURCE_RS); | |
| target.rust_values().set_crate_root(main); | |
| target.rust_values().crate_name() = "foo_bar"; | |
| target.private_deps().push_back(LabelTargetPair(&group)); | |
| target.SetToolchain(setup.toolchain()); | |
| ASSERT_TRUE(target.OnResolved(&err)); | |
| { | |
| std::ostringstream out; | |
| NinjaRustBinaryTargetWriter writer(&target, out); | |
| writer.Run(); | |
| const char expected[] = | |
| "crate_name = foo_bar\n" | |
| "crate_type = bin\n" | |
| "output_extension = \n" | |
| "output_dir = \n" | |
| "rustflags =\n" | |
| "rustenv =\n" | |
| "root_out_dir = .\n" | |
| "target_gen_dir = gen/foo\n" | |
| "target_out_dir = obj/foo\n" | |
| "target_output_name = bar\n" | |
| "\n" | |
| "build ./foo_bar: rust_bin ../../foo/main.rs | " | |
| "../../foo/source.rs ../../foo/main.rs obj/bar/libmylib.rlib || " | |
| "obj/bar/libmylib.rlib\n" | |
| " source_file_part = main.rs\n" | |
| " source_name_part = main\n" | |
| " externs = --extern mylib=obj/bar/libmylib.rlib\n" | |
| " rustdeps = -Ldependency=obj/bar\n" | |
| " ldflags =\n" | |
| " sources = ../../foo/source.rs ../../foo/main.rs\n"; | |
| std::string out_str = out.str(); | |
| EXPECT_EQ(expected, out_str); | |
| } | |
| } | |
| TEST_F(NinjaRustBinaryTargetWriterTest, Externs) { | |
| Err err; | |
| TestWithScope setup; | |
| Target target(setup.settings(), Label(SourceDir("//foo/"), "bar")); | |
| target.set_output_type(Target::EXECUTABLE); | |
| target.visibility().SetPublic(); | |
| SourceFile main("//foo/main.rs"); | |
| target.sources().push_back(SourceFile("//foo/source.rs")); | |
| target.sources().push_back(main); | |
| target.source_types_used().Set(SourceFile::SOURCE_RS); | |
| target.rust_values().set_crate_root(main); | |
| target.rust_values().crate_name() = "foo_bar"; | |
| const char* lib = "lib1"; | |
| target.config_values().externs().push_back( | |
| std::pair(lib, LibFile(SourceFile("//foo/lib1.rlib")))); | |
| lib = "lib2"; | |
| target.config_values().externs().push_back( | |
| std::pair(lib, LibFile("lib2.rlib"))); | |
| target.SetToolchain(setup.toolchain()); | |
| ASSERT_TRUE(target.OnResolved(&err)); | |
| { | |
| std::ostringstream out; | |
| NinjaRustBinaryTargetWriter writer(&target, out); | |
| writer.Run(); | |
| const char expected[] = | |
| "crate_name = foo_bar\n" | |
| "crate_type = bin\n" | |
| "output_extension = \n" | |
| "output_dir = \n" | |
| "rustflags =\n" | |
| "rustenv =\n" | |
| "root_out_dir = .\n" | |
| "target_gen_dir = gen/foo\n" | |
| "target_out_dir = obj/foo\n" | |
| "target_output_name = bar\n" | |
| "\n" | |
| "build ./foo_bar: rust_bin ../../foo/main.rs | ../../foo/source.rs " | |
| "../../foo/main.rs ../../foo/lib1.rlib\n" | |
| " source_file_part = main.rs\n" | |
| " source_name_part = main\n" | |
| " externs = --extern lib1=../../foo/lib1.rlib --extern " | |
| "lib2=lib2.rlib\n" | |
| " rustdeps =\n" | |
| " ldflags =\n" | |
| " sources = ../../foo/source.rs ../../foo/main.rs\n"; | |
| std::string out_str = out.str(); | |
| EXPECT_EQ(expected, out_str); | |
| } | |
| } | |
| TEST_F(NinjaRustBinaryTargetWriterTest, Inputs) { | |
| Err err; | |
| TestWithScope setup; | |
| Target target(setup.settings(), Label(SourceDir("//foo/"), "bar")); | |
| target.set_output_type(Target::EXECUTABLE); | |
| target.visibility().SetPublic(); | |
| SourceFile main("//foo/main.rs"); | |
| target.sources().push_back(SourceFile("//foo/source.rs")); | |
| target.sources().push_back(main); | |
| target.source_types_used().Set(SourceFile::SOURCE_RS); | |
| target.rust_values().set_crate_root(main); | |
| target.rust_values().crate_name() = "foo_bar"; | |
| target.config_values().inputs().push_back(SourceFile("//foo/config.json")); | |
| target.config_values().inputs().push_back(SourceFile("//foo/template.h")); | |
| target.SetToolchain(setup.toolchain()); | |
| ASSERT_TRUE(target.OnResolved(&err)); | |
| { | |
| std::ostringstream out; | |
| NinjaRustBinaryTargetWriter writer(&target, out); | |
| writer.Run(); | |
| const char expected[] = | |
| "build phony/foo/bar.inputs: phony ../../foo/config.json " | |
| "../../foo/template.h\n" | |
| "crate_name = foo_bar\n" | |
| "crate_type = bin\n" | |
| "output_extension = \n" | |
| "output_dir = \n" | |
| "rustflags =\n" | |
| "rustenv =\n" | |
| "root_out_dir = .\n" | |
| "target_gen_dir = gen/foo\n" | |
| "target_out_dir = obj/foo\n" | |
| "target_output_name = bar\n" | |
| "\n" | |
| "build ./foo_bar: rust_bin ../../foo/main.rs | ../../foo/source.rs " | |
| "../../foo/main.rs ../../foo/config.json ../../foo/template.h " | |
| "|| phony/foo/bar.inputs\n" | |
| " source_file_part = main.rs\n" | |
| " source_name_part = main\n" | |
| " externs =\n" | |
| " rustdeps =\n" | |
| " ldflags =\n" | |
| " sources = ../../foo/source.rs ../../foo/main.rs " | |
| "../../foo/config.json ../../foo/template.h\n"; | |
| std::string out_str = out.str(); | |
| EXPECT_EQ(expected, out_str); | |
| } | |
| } | |
| TEST_F(NinjaRustBinaryTargetWriterTest, CdylibDeps) { | |
| Err err; | |
| TestWithScope setup; | |
| Target cdylib(setup.settings(), Label(SourceDir("//bar/"), "mylib")); | |
| cdylib.set_output_type(Target::SHARED_LIBRARY); | |
| cdylib.visibility().SetPublic(); | |
| SourceFile barlib("//bar/lib.rs"); | |
| cdylib.sources().push_back(barlib); | |
| cdylib.source_types_used().Set(SourceFile::SOURCE_RS); | |
| cdylib.rust_values().set_crate_type(RustValues::CRATE_CDYLIB); | |
| cdylib.rust_values().set_crate_root(barlib); | |
| cdylib.rust_values().crate_name() = "mylib"; | |
| cdylib.SetToolchain(setup.toolchain()); | |
| ASSERT_TRUE(cdylib.OnResolved(&err)); | |
| { | |
| std::ostringstream out; | |
| NinjaRustBinaryTargetWriter writer(&cdylib, out); | |
| writer.Run(); | |
| const char expected[] = | |
| "crate_name = mylib\n" | |
| "crate_type = cdylib\n" | |
| "output_extension = .so\n" | |
| "output_dir = \n" | |
| "rustflags =\n" | |
| "rustenv =\n" | |
| "root_out_dir = .\n" | |
| "target_gen_dir = gen/bar\n" | |
| "target_out_dir = obj/bar\n" | |
| "target_output_name = libmylib\n" | |
| "\n" | |
| "build obj/bar/libmylib.so: rust_cdylib ../../bar/lib.rs | " | |
| "../../bar/lib.rs\n" | |
| " source_file_part = lib.rs\n" | |
| " source_name_part = lib\n" | |
| " externs =\n" | |
| " rustdeps =\n" | |
| " ldflags =\n" | |
| " sources = ../../bar/lib.rs\n"; | |
| std::string out_str = out.str(); | |
| EXPECT_EQ(expected, out_str); | |
| } | |
| Target target(setup.settings(), Label(SourceDir("//foo/"), "bar")); | |
| target.set_output_type(Target::EXECUTABLE); | |
| target.visibility().SetPublic(); | |
| SourceFile main("//foo/main.rs"); | |
| target.sources().push_back(SourceFile("//foo/source.rs")); | |
| target.sources().push_back(main); | |
| target.source_types_used().Set(SourceFile::SOURCE_RS); | |
| target.rust_values().set_crate_root(main); | |
| target.rust_values().crate_name() = "foo_bar"; | |
| target.private_deps().push_back(LabelTargetPair(&cdylib)); | |
| target.SetToolchain(setup.toolchain()); | |
| ASSERT_TRUE(target.OnResolved(&err)); | |
| { | |
| std::ostringstream out; | |
| NinjaRustBinaryTargetWriter writer(&target, out); | |
| writer.Run(); | |
| const char expected[] = | |
| "crate_name = foo_bar\n" | |
| "crate_type = bin\n" | |
| "output_extension = \n" | |
| "output_dir = \n" | |
| "rustflags =\n" | |
| "rustenv =\n" | |
| "root_out_dir = .\n" | |
| "target_gen_dir = gen/foo\n" | |
| "target_out_dir = obj/foo\n" | |
| "target_output_name = bar\n" | |
| "\n" | |
| "build ./foo_bar: rust_bin ../../foo/main.rs | ../../foo/source.rs " | |
| "../../foo/main.rs obj/bar/libmylib.so\n" | |
| " source_file_part = main.rs\n" | |
| " source_name_part = main\n" | |
| " externs =\n" | |
| " rustdeps = -Clink-arg=-Bdynamic -Clink-arg=obj/bar/libmylib.so\n" | |
| " ldflags =\n" | |
| " sources = ../../foo/source.rs ../../foo/main.rs\n"; | |
| std::string out_str = out.str(); | |
| EXPECT_EQ(expected, out_str); | |
| } | |
| } | |
| TEST_F(NinjaRustBinaryTargetWriterTest, TransitivePublicNonRustDeps) { | |
| Err err; | |
| TestWithScope setup; | |
| // This test verifies that the Rust binary "target" links against this lib. | |
| Target implicitlib(setup.settings(), Label(SourceDir("//foo/"), "implicit")); | |
| implicitlib.set_output_type(Target::SHARED_LIBRARY); | |
| implicitlib.visibility().SetPublic(); | |
| implicitlib.sources().push_back(SourceFile("//foo/implicit.cpp")); | |
| implicitlib.source_types_used().Set(SourceFile::SOURCE_CPP); | |
| implicitlib.SetToolchain(setup.toolchain()); | |
| ASSERT_TRUE(implicitlib.OnResolved(&err)); | |
| Target sharedlib(setup.settings(), Label(SourceDir("//foo/"), "shared")); | |
| sharedlib.set_output_type(Target::SHARED_LIBRARY); | |
| sharedlib.visibility().SetPublic(); | |
| sharedlib.sources().push_back(SourceFile("//foo/shared.cpp")); | |
| sharedlib.source_types_used().Set(SourceFile::SOURCE_CPP); | |
| sharedlib.SetToolchain(setup.toolchain()); | |
| sharedlib.public_deps().push_back(LabelTargetPair(&implicitlib)); | |
| ASSERT_TRUE(sharedlib.OnResolved(&err)); | |
| Target rlib(setup.settings(), Label(SourceDir("//bar/"), "mylib")); | |
| rlib.set_output_type(Target::RUST_LIBRARY); | |
| rlib.visibility().SetPublic(); | |
| SourceFile barlib("//bar/lib.rs"); | |
| rlib.sources().push_back(SourceFile("//bar/mylib.rs")); | |
| rlib.sources().push_back(barlib); | |
| rlib.source_types_used().Set(SourceFile::SOURCE_RS); | |
| rlib.rust_values().set_crate_root(barlib); | |
| rlib.rust_values().crate_name() = "mylib"; | |
| rlib.SetToolchain(setup.toolchain()); | |
| rlib.private_deps().push_back(LabelTargetPair(&sharedlib)); | |
| ASSERT_TRUE(rlib.OnResolved(&err)); | |
| Target target(setup.settings(), Label(SourceDir("//foo/"), "bar")); | |
| target.set_output_type(Target::EXECUTABLE); | |
| target.visibility().SetPublic(); | |
| SourceFile main("//foo/main.rs"); | |
| target.sources().push_back(main); | |
| target.source_types_used().Set(SourceFile::SOURCE_RS); | |
| target.rust_values().set_crate_root(main); | |
| target.rust_values().crate_name() = "foo_bar"; | |
| target.private_deps().push_back(LabelTargetPair(&rlib)); | |
| target.SetToolchain(setup.toolchain()); | |
| ASSERT_TRUE(target.OnResolved(&err)); | |
| { | |
| std::ostringstream out; | |
| NinjaRustBinaryTargetWriter writer(&target, out); | |
| writer.Run(); | |
| const char expected[] = | |
| "crate_name = foo_bar\n" | |
| "crate_type = bin\n" | |
| "output_extension = \n" | |
| "output_dir = \n" | |
| "rustflags =\n" | |
| "rustenv =\n" | |
| "root_out_dir = .\n" | |
| "target_gen_dir = gen/foo\n" | |
| "target_out_dir = obj/foo\n" | |
| "target_output_name = bar\n" | |
| "\n" | |
| "build ./foo_bar: rust_bin ../../foo/main.rs | ../../foo/main.rs " | |
| "obj/bar/libmylib.rlib ./libshared.so ./libimplicit.so\n" | |
| " source_file_part = main.rs\n" | |
| " source_name_part = main\n" | |
| " externs = --extern mylib=obj/bar/libmylib.rlib\n" | |
| " rustdeps = -Ldependency=obj/bar -Clink-arg=-Bdynamic " | |
| "-Clink-arg=./libshared.so -Clink-arg=./libimplicit.so\n" | |
| " ldflags =\n" | |
| " sources = ../../foo/main.rs\n"; | |
| std::string out_str = out.str(); | |
| EXPECT_EQ(expected, out_str); | |
| } | |
| } | |
| TEST_F(NinjaRustBinaryTargetWriterTest, TransitiveRustDepsThroughSourceSet) { | |
| Err err; | |
| TestWithScope setup; | |
| Target rlib_pub(setup.settings(), | |
| Label(SourceDir("//public/"), "behind_sourceset_public")); | |
| rlib_pub.set_output_type(Target::RUST_LIBRARY); | |
| rlib_pub.visibility().SetPublic(); | |
| SourceFile rlib_pub_root("//public/lib.rs"); | |
| rlib_pub.sources().push_back( | |
| SourceFile("//public/behind_sourceset_public.rs")); | |
| rlib_pub.sources().push_back(rlib_pub_root); | |
| rlib_pub.source_types_used().Set(SourceFile::SOURCE_RS); | |
| rlib_pub.rust_values().set_crate_root(rlib_pub_root); | |
| rlib_pub.rust_values().crate_name() = "behind_sourceset_public"; | |
| rlib_pub.SetToolchain(setup.toolchain()); | |
| ASSERT_TRUE(rlib_pub.OnResolved(&err)); | |
| Target rlib_priv(setup.settings(), | |
| Label(SourceDir("//private/"), "behind_sourceset_private")); | |
| rlib_priv.set_output_type(Target::RUST_LIBRARY); | |
| rlib_priv.visibility().SetPublic(); | |
| SourceFile rlib_priv_root("//private/lib.rs"); | |
| rlib_priv.sources().push_back( | |
| SourceFile("//private/behind_sourceset_private.rs")); | |
| rlib_priv.sources().push_back(rlib_priv_root); | |
| rlib_priv.source_types_used().Set(SourceFile::SOURCE_RS); | |
| rlib_priv.rust_values().set_crate_root(rlib_priv_root); | |
| rlib_priv.rust_values().crate_name() = "behind_sourceset_private"; | |
| rlib_priv.SetToolchain(setup.toolchain()); | |
| ASSERT_TRUE(rlib_priv.OnResolved(&err)); | |
| Target sset(setup.settings(), Label(SourceDir("//sset/"), "bar")); | |
| sset.set_output_type(Target::SOURCE_SET); | |
| sset.visibility().SetPublic(); | |
| sset.sources().push_back(SourceFile("//sset/input1.cc")); | |
| sset.source_types_used().Set(SourceFile::SOURCE_CPP); | |
| sset.SetToolchain(setup.toolchain()); | |
| sset.public_deps().push_back(LabelTargetPair(&rlib_pub)); | |
| sset.private_deps().push_back(LabelTargetPair(&rlib_priv)); | |
| ASSERT_TRUE(sset.OnResolved(&err)); | |
| Target modules(setup.settings(), Label(SourceDir("//sset/"), "module")); | |
| modules.set_output_type(Target::SOURCE_SET); | |
| modules.visibility().SetPublic(); | |
| modules.sources().push_back(SourceFile("//sset/module.modulemap")); | |
| modules.source_types_used().Set(SourceFile::SOURCE_MODULEMAP); | |
| modules.SetToolchain(setup.toolchain()); | |
| ASSERT_TRUE(modules.OnResolved(&err)); | |
| Target target(setup.settings(), Label(SourceDir("//linked/"), "exe")); | |
| target.set_output_type(Target::EXECUTABLE); | |
| target.visibility().SetPublic(); | |
| SourceFile main("//linked/exe.rs"); | |
| target.sources().push_back(main); | |
| target.source_types_used().Set(SourceFile::SOURCE_RS); | |
| target.rust_values().set_crate_root(main); | |
| target.rust_values().crate_name() = "exe"; | |
| target.private_deps().push_back(LabelTargetPair(&sset)); | |
| target.private_deps().push_back(LabelTargetPair(&modules)); | |
| target.SetToolchain(setup.toolchain()); | |
| ASSERT_TRUE(target.OnResolved(&err)); | |
| { | |
| std::ostringstream out; | |
| NinjaRustBinaryTargetWriter writer(&target, out); | |
| writer.Run(); | |
| const char expected[] = | |
| "crate_name = exe\n" | |
| "crate_type = bin\n" | |
| "output_extension = \n" | |
| "output_dir = \n" | |
| "rustflags =\n" | |
| "rustenv =\n" | |
| "root_out_dir = .\n" | |
| "target_gen_dir = gen/linked\n" | |
| "target_out_dir = obj/linked\n" | |
| "target_output_name = exe\n" | |
| "\n" | |
| "build ./exe: rust_bin ../../linked/exe.rs | ../../linked/exe.rs " | |
| "obj/sset/bar.input1.o obj/public/libbehind_sourceset_public.rlib " | |
| "obj/private/libbehind_sourceset_private.rlib || " | |
| "phony/sset/bar.linkdeps " | |
| "phony/sset/module.linkdeps\n" | |
| " source_file_part = exe.rs\n" | |
| " source_name_part = exe\n" | |
| " externs = --extern " | |
| "behind_sourceset_public=obj/public/libbehind_sourceset_public.rlib\n" | |
| " rustdeps = -Ldependency=obj/public -Ldependency=obj/private " | |
| "-Clink-arg=-Bdynamic " | |
| "-Clink-arg=obj/sset/bar.input1.o " | |
| "-Clink-arg=obj/private/libbehind_sourceset_private.rlib\n" | |
| " ldflags =\n" | |
| " sources = ../../linked/exe.rs\n"; | |
| std::string out_str = out.str(); | |
| EXPECT_EQ(expected, out_str); | |
| } | |
| } | |
| TEST_F(NinjaRustBinaryTargetWriterTest, Pool) { | |
| Err err; | |
| TestWithScope setup; | |
| Pool pool(setup.settings(), | |
| Label(SourceDir("//foo/"), "pool", setup.toolchain()->label().dir(), | |
| setup.toolchain()->label().name())); | |
| pool.set_depth(42); | |
| Target target(setup.settings(), Label(SourceDir("//foo/"), "bar")); | |
| SourceFile main("//foo/source.rs"); | |
| target.sources().push_back(main); | |
| target.source_types_used().Set(SourceFile::SOURCE_RS); | |
| target.rust_values().set_crate_root(main); | |
| target.rust_values().crate_name() = "bar"; | |
| target.set_output_type(Target::EXECUTABLE); | |
| target.set_pool(LabelPtrPair<Pool>(&pool)); | |
| target.visibility().SetPublic(); | |
| target.SetToolchain(setup.toolchain()); | |
| ASSERT_TRUE(target.OnResolved(&err)); | |
| std::ostringstream out; | |
| NinjaBinaryTargetWriter writer(&target, out); | |
| writer.Run(); | |
| const char expected[] = | |
| "crate_name = bar\n" | |
| "crate_type = bin\n" | |
| "output_extension = \n" | |
| "output_dir = \n" | |
| "rustflags =\n" | |
| "rustenv =\n" | |
| "root_out_dir = .\n" | |
| "target_gen_dir = gen/foo\n" | |
| "target_out_dir = obj/foo\n" | |
| "target_output_name = bar\n" | |
| "\n" | |
| "build ./bar: rust_bin ../../foo/source.rs | ../../foo/source.rs\n" | |
| " source_file_part = source.rs\n" | |
| " source_name_part = source\n" | |
| " externs =\n" | |
| " rustdeps =\n" | |
| " ldflags =\n" | |
| " sources = ../../foo/source.rs\n" | |
| " pool = foo_pool\n"; | |
| std::string out_str = out.str(); | |
| EXPECT_EQ(expected, out_str); | |
| } | |
| // Tests frameworks are applied. | |
| TEST_F(NinjaRustBinaryTargetWriterTest, FrameworksAndFrameworkDirs) { | |
| Err err; | |
| TestWithScope setup; | |
| // An action for our library to depend on. | |
| Target action(setup.settings(), Label(SourceDir("//bar"), "action")); | |
| action.set_output_type(Target::ACTION_FOREACH); | |
| action.visibility().SetPublic(); | |
| action.SetToolchain(setup.toolchain()); | |
| ASSERT_TRUE(action.OnResolved(&err)); | |
| // A config that force linking with the framework. | |
| Config framework_config(setup.settings(), | |
| Label(SourceDir("//bar"), "framework_config")); | |
| framework_config.visibility().SetPublic(); | |
| framework_config.own_values().frameworks().push_back("Bar.framework"); | |
| framework_config.own_values().framework_dirs().push_back( | |
| SourceDir("//out/Debug/")); | |
| ASSERT_TRUE(framework_config.OnResolved(&err)); | |
| // A target creating a framework bundle. | |
| Target framework(setup.settings(), Label(SourceDir("//bar"), "framework")); | |
| framework.set_output_type(Target::CREATE_BUNDLE); | |
| framework.bundle_data().product_type() = "com.apple.product-type.framework"; | |
| framework.public_configs().push_back(LabelConfigPair(&framework_config)); | |
| framework.private_deps().push_back(LabelTargetPair(&action)); | |
| framework.SetToolchain(setup.toolchain()); | |
| framework.visibility().SetPublic(); | |
| ASSERT_TRUE(framework.OnResolved(&err)); | |
| Target target(setup.settings(), Label(SourceDir("//linked/"), "exe")); | |
| target.set_output_type(Target::EXECUTABLE); | |
| target.visibility().SetPublic(); | |
| SourceFile main("//linked/exe.rs"); | |
| target.sources().push_back(main); | |
| target.source_types_used().Set(SourceFile::SOURCE_RS); | |
| target.rust_values().set_crate_root(main); | |
| target.rust_values().crate_name() = "exe"; | |
| target.private_deps().push_back(LabelTargetPair(&framework)); | |
| target.config_values().frameworks().push_back("System.framework"); | |
| target.config_values().weak_frameworks().push_back("Whizbang.framework"); | |
| target.SetToolchain(setup.toolchain()); | |
| ASSERT_TRUE(target.OnResolved(&err)); | |
| std::ostringstream out; | |
| NinjaRustBinaryTargetWriter writer(&target, out); | |
| writer.Run(); | |
| const char expected[] = | |
| "crate_name = exe\n" | |
| "crate_type = bin\n" | |
| "output_extension = \n" | |
| "output_dir = \n" | |
| "rustflags =\n" | |
| "rustenv =\n" | |
| "root_out_dir = .\n" | |
| "target_gen_dir = gen/linked\n" | |
| "target_out_dir = obj/linked\n" | |
| "target_output_name = exe\n" | |
| "\n" | |
| "build ./exe: rust_bin ../../linked/exe.rs | ../../linked/exe.rs || " | |
| "phony/bar/framework\n" | |
| " source_file_part = exe.rs\n" | |
| " source_name_part = exe\n" | |
| " externs =\n" | |
| " rustdeps = -Lframework=. -lframework=System -lframework=Bar " | |
| "-lframework=Whizbang\n" | |
| " ldflags =\n" | |
| " sources = ../../linked/exe.rs\n"; | |
| const std::string out_str = out.str(); | |
| EXPECT_EQ(expected, out_str); | |
| } | |
| // Test linking of targets containing Swift modules. | |
| TEST_F(NinjaRustBinaryTargetWriterTest, SwiftModule) { | |
| Err err; | |
| TestWithScope setup; | |
| // A single Swift module. | |
| Target foo_target(setup.settings(), Label(SourceDir("//foo/"), "foo")); | |
| foo_target.set_output_type(Target::SOURCE_SET); | |
| foo_target.visibility().SetPublic(); | |
| foo_target.sources().push_back(SourceFile("//foo/file1.swift")); | |
| foo_target.sources().push_back(SourceFile("//foo/file2.swift")); | |
| foo_target.source_types_used().Set(SourceFile::SOURCE_SWIFT); | |
| foo_target.swift_values().module_name() = "Foo"; | |
| foo_target.SetToolchain(setup.toolchain()); | |
| ASSERT_TRUE(foo_target.OnResolved(&err)); | |
| // Rust target links with module. | |
| Target target(setup.settings(), Label(SourceDir("//linked/"), "exe")); | |
| target.set_output_type(Target::EXECUTABLE); | |
| target.visibility().SetPublic(); | |
| SourceFile main("//linked/exe.rs"); | |
| target.sources().push_back(main); | |
| target.source_types_used().Set(SourceFile::SOURCE_RS); | |
| target.rust_values().set_crate_root(main); | |
| target.rust_values().crate_name() = "exe"; | |
| target.private_deps().push_back(LabelTargetPair(&foo_target)); | |
| target.SetToolchain(setup.toolchain()); | |
| ASSERT_TRUE(target.OnResolved(&err)); | |
| std::ostringstream out; | |
| NinjaRustBinaryTargetWriter writer(&target, out); | |
| writer.Run(); | |
| const char expected[] = | |
| "crate_name = exe\n" | |
| "crate_type = bin\n" | |
| "output_extension = \n" | |
| "output_dir = \n" | |
| "rustflags =\n" | |
| "rustenv =\n" | |
| "root_out_dir = .\n" | |
| "target_gen_dir = gen/linked\n" | |
| "target_out_dir = obj/linked\n" | |
| "target_output_name = exe\n" | |
| "\n" | |
| "build ./exe: rust_bin ../../linked/exe.rs | ../../linked/exe.rs " | |
| "obj/foo/file1.o obj/foo/file2.o || " | |
| "phony/foo/foo obj/foo/Foo.swiftmodule phony/foo/foo.linkdeps\n" | |
| " source_file_part = exe.rs\n" | |
| " source_name_part = exe\n" | |
| " externs =\n" | |
| " rustdeps = -Clink-arg=-Bdynamic " | |
| "-Clink-arg=obj/foo/file1.o -Clink-arg=obj/foo/file2.o " | |
| "-Clink-arg=-swiftmodule=obj/foo/Foo.swiftmodule\n" | |
| " ldflags =\n" | |
| " sources = ../../linked/exe.rs\n"; | |
| const std::string out_str = out.str(); | |
| EXPECT_EQ(expected, out_str); | |
| } |