From 37982c5a969b949ce80ede915a1e71e35cdf5f82 Mon Sep 17 00:00:00 2001 From: David Skidmore Date: Wed, 21 Jul 2021 23:19:02 -0700 Subject: [PATCH] Add support for passing a custom target specification. (#836) * Add support for passing a custom target specification. * Pass the target spec ias a dependency. * Created a target_flag_value toolchain info field to avoid recalculating the value. * Prevent passing both target_triple and target_json simultaneously. * Streamline checks for None. * Added unit tests for rust_toolchain rules. * Rename test target spec to avoid collisions with the builtin. * Regenerate documentation * Rename the triple used in unit tests. Co-authored-by: UebelAndre Co-authored-by: Marcel Hlopko --- cargo/cargo_build_script.bzl | 4 +- docs/flatten.md | 4 +- docs/rust_repositories.md | 4 +- rust/private/rustc.bzl | 3 +- rust/toolchain.bzl | 10 +++ test/unit/toolchain/BUILD | 3 + .../unit/toolchain/toolchain-test-triple.json | 34 ++++++++ test/unit/toolchain/toolchain_test.bzl | 80 +++++++++++++++++++ 8 files changed, 137 insertions(+), 5 deletions(-) create mode 100644 test/unit/toolchain/BUILD create mode 100644 test/unit/toolchain/toolchain-test-triple.json create mode 100644 test/unit/toolchain/toolchain_test.bzl diff --git a/cargo/cargo_build_script.bzl b/cargo/cargo_build_script.bzl index 7500920435..755ffe81a0 100644 --- a/cargo/cargo_build_script.bzl +++ b/cargo/cargo_build_script.bzl @@ -77,7 +77,7 @@ def _build_script_impl(ctx): # This isn't exactly right, but Bazel doesn't have exact views of "debug" and "release", so... "PROFILE": {"dbg": "debug", "fastbuild": "debug", "opt": "release"}.get(ctx.var["COMPILATION_MODE"], "unknown"), "RUSTC": toolchain.rustc.path, - "TARGET": toolchain.target_triple, + "TARGET": toolchain.target_flag_value, # OUT_DIR is set by the runner itself, rather than on the action. }) @@ -129,7 +129,7 @@ def _build_script_impl(ctx): script, ctx.executable._cargo_build_script_runner, toolchain.rustc, - ] + ctx.files.data, + ] + ctx.files.data + ([toolchain.target_json] if toolchain.target_json else []), transitive = toolchain_tools, ) diff --git a/docs/flatten.md b/docs/flatten.md index aca03640fe..f0466bf722 100644 --- a/docs/flatten.md +++ b/docs/flatten.md @@ -1085,7 +1085,8 @@ Run the test with `bazel build //hello_lib:hello_lib_test`.
 rust_toolchain(name, allocator_library, binary_ext, cargo, clippy_driver, debug_info,
                default_edition, dylib_ext, exec_triple, opt_level, os, rust_doc, rust_lib, rustc,
-               rustc_lib, rustc_srcs, rustfmt, staticlib_ext, stdlib_linkflags, target_triple)
+               rustc_lib, rustc_srcs, rustfmt, staticlib_ext, stdlib_linkflags, target_json,
+               target_triple)
 
Declares a Rust toolchain for use. @@ -1153,6 +1154,7 @@ See @rules_rust//rust:repositories.bzl for examples of defining the @rust_cpuX r | rustfmt | The location of the rustfmt binary. Can be a direct source or a filegroup containing one item. | Label | optional | None | | staticlib_ext | The extension for static libraries created from rustc. | String | required | | | stdlib_linkflags | Additional linker libs used when std lib is linked, see https://github.com/rust-lang/rust/blob/master/src/libstd/build.rs | List of strings | required | | +| target_json | Override the target_triple with a custom target specification. For more details see: https://doc.rust-lang.org/rustc/targets/custom.html | Label | optional | None | | target_triple | The platform triple for the toolchains target environment. For more details see: https://docs.bazel.build/versions/master/skylark/rules.html#configurations | String | optional | "" | diff --git a/docs/rust_repositories.md b/docs/rust_repositories.md index 9da7eeb0ad..5909ee4f36 100644 --- a/docs/rust_repositories.md +++ b/docs/rust_repositories.md @@ -34,7 +34,8 @@ A dedicated filegroup-like rule for Rust stdlib artifacts.
 rust_toolchain(name, allocator_library, binary_ext, cargo, clippy_driver, debug_info,
                default_edition, dylib_ext, exec_triple, opt_level, os, rust_doc, rust_lib, rustc,
-               rustc_lib, rustc_srcs, rustfmt, staticlib_ext, stdlib_linkflags, target_triple)
+               rustc_lib, rustc_srcs, rustfmt, staticlib_ext, stdlib_linkflags, target_json,
+               target_triple)
 
Declares a Rust toolchain for use. @@ -102,6 +103,7 @@ See @rules_rust//rust:repositories.bzl for examples of defining the @rust_cpuX r | rustfmt | The location of the rustfmt binary. Can be a direct source or a filegroup containing one item. | Label | optional | None | | staticlib_ext | The extension for static libraries created from rustc. | String | required | | | stdlib_linkflags | Additional linker libs used when std lib is linked, see https://github.com/rust-lang/rust/blob/master/src/libstd/build.rs | List of strings | required | | +| target_json | Override the target_triple with a custom target specification. For more details see: https://doc.rust-lang.org/rustc/targets/custom.html | Label | optional | None | | target_triple | The platform triple for the toolchains target environment. For more details see: https://docs.bazel.build/versions/master/skylark/rules.html#configurations | String | optional | "" | diff --git a/rust/private/rustc.bzl b/rust/private/rustc.bzl index aac1c20a27..b0ff72dbbb 100644 --- a/rust/private/rustc.bzl +++ b/rust/private/rustc.bzl @@ -287,6 +287,7 @@ def collect_inputs( [toolchain.rustc] + toolchain.crosstool_files + ([build_info.rustc_env, build_info.flags] if build_info else []) + + ([toolchain.target_json] if toolchain.target_json else []) + ([] if linker_script == None else [linker_script]), transitive = [ toolchain.rustc_lib.files, @@ -430,7 +431,7 @@ def construct_arguments( args.add("--emit=" + ",".join(emit_with_paths)) args.add("--color=always") - args.add("--target=" + toolchain.target_triple) + args.add("--target=" + toolchain.target_flag_value) if hasattr(attr, "crate_features"): args.add_all(getattr(attr, "crate_features"), before_each = "--cfg", format_each = 'feature="%s"') if linker_script: diff --git a/rust/toolchain.bzl b/rust/toolchain.bzl index 6ba4400c74..a8e97553a2 100644 --- a/rust/toolchain.bzl +++ b/rust/toolchain.bzl @@ -196,12 +196,17 @@ def _rust_toolchain_impl(ctx): if not k in ctx.attr.opt_level: fail("Compilation mode {} is not defined in opt_level but is defined debug_info".format(k)) + if ctx.attr.target_triple and ctx.file.target_json: + fail("Do not specify both target_triple and target_json, either use a builtin triple or provide a custom specification file.") + toolchain = platform_common.ToolchainInfo( rustc = ctx.file.rustc, rust_doc = ctx.file.rust_doc, rustfmt = ctx.file.rustfmt, cargo = ctx.file.cargo, clippy_driver = ctx.file.clippy_driver, + target_json = ctx.file.target_json, + target_flag_value = ctx.file.target_json.path if ctx.file.target_json else ctx.attr.target_triple, rustc_lib = ctx.attr.rustc_lib, rustc_srcs = ctx.attr.rustc_srcs, rust_lib = ctx.attr.rust_lib, @@ -305,6 +310,11 @@ rust_toolchain = rule( ), mandatory = True, ), + "target_json": attr.label( + doc = ("Override the target_triple with a custom target specification. " + + "For more details see: https://doc.rust-lang.org/rustc/targets/custom.html"), + allow_single_file = True, + ), "target_triple": attr.string( doc = ( "The platform triple for the toolchains target environment. " + diff --git a/test/unit/toolchain/BUILD b/test/unit/toolchain/BUILD new file mode 100644 index 0000000000..b42717221a --- /dev/null +++ b/test/unit/toolchain/BUILD @@ -0,0 +1,3 @@ +load(":toolchain_test.bzl", "toolchain_test_suite") + +toolchain_test_suite(name = "toolchain_test_suite") diff --git a/test/unit/toolchain/toolchain-test-triple.json b/test/unit/toolchain/toolchain-test-triple.json new file mode 100644 index 0000000000..1098428f40 --- /dev/null +++ b/test/unit/toolchain/toolchain-test-triple.json @@ -0,0 +1,34 @@ +{ + "arch": "x86_64", + "cpu": "x86-64", + "crt-static-respected": true, + "data-layout": "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128", + "dynamic-linking": true, + "env": "gnu", + "executables": true, + "has-elf-tls": true, + "has-rpath": true, + "llvm-target": "x86_64-unknown-linux-gnu", + "max-atomic-width": 64, + "os": "linux", + "position-independent-executables": true, + "pre-link-args": { + "gcc": [ + "-m64" + ] + }, + "relro-level": "full", + "stack-probes": { + "kind": "call" + }, + "supported-sanitizers": [ + "address", + "leak", + "memory", + "thread" + ], + "target-family": [ + "unix" + ], + "target-pointer-width": "64" +} diff --git a/test/unit/toolchain/toolchain_test.bzl b/test/unit/toolchain/toolchain_test.bzl new file mode 100644 index 0000000000..0e44df993d --- /dev/null +++ b/test/unit/toolchain/toolchain_test.bzl @@ -0,0 +1,80 @@ +"""Unit tests for rust toolchains.""" + +load("@bazel_skylib//lib:unittest.bzl", "analysistest", "asserts") +load("//rust:toolchain.bzl", "rust_stdlib_filegroup", "rust_toolchain") + +def _toolchain_specifies_target_triple_test_impl(ctx): + env = analysistest.begin(ctx) + toolchain_info = analysistest.target_under_test(env)[platform_common.ToolchainInfo] + + asserts.equals(env, None, toolchain_info.target_json) + asserts.equals(env, "toolchain-test-triple", toolchain_info.target_flag_value) + asserts.equals(env, "toolchain-test-triple", toolchain_info.target_triple) + + return analysistest.end(env) + +def _toolchain_specifies_target_json_test_impl(ctx): + env = analysistest.begin(ctx) + toolchain_info = analysistest.target_under_test(env)[platform_common.ToolchainInfo] + + asserts.equals(env, "toolchain-test-triple.json", toolchain_info.target_json.basename) + asserts.equals(env, "test/unit/toolchain/toolchain-test-triple.json", toolchain_info.target_flag_value) + asserts.equals(env, "", toolchain_info.target_triple) + + return analysistest.end(env) + +toolchain_specifies_target_triple_test = analysistest.make(_toolchain_specifies_target_triple_test_impl) +toolchain_specifies_target_json_test = analysistest.make(_toolchain_specifies_target_json_test_impl) + +def _toolchain_test(): + rust_stdlib_filegroup( + name = "std_libs", + srcs = [], + ) + + native.filegroup( + name = "target_json", + srcs = ["toolchain-test-triple.json"], + ) + + rust_toolchain( + name = "rust_triple_toolchain", + binary_ext = "", + dylib_ext = ".so", + os = "linux", + rust_lib = ":std_libs", + staticlib_ext = ".a", + stdlib_linkflags = [], + target_triple = "toolchain-test-triple", + ) + + rust_toolchain( + name = "rust_json_toolchain", + binary_ext = "", + dylib_ext = ".so", + os = "linux", + rust_lib = ":std_libs", + staticlib_ext = ".a", + stdlib_linkflags = [], + target_json = ":target_json", + ) + + toolchain_specifies_target_triple_test( + name = "toolchain_specifies_target_triple_test", + target_under_test = ":rust_triple_toolchain", + ) + toolchain_specifies_target_json_test( + name = "toolchain_specifies_target_json_test", + target_under_test = ":rust_json_toolchain", + ) + +def toolchain_test_suite(name): + _toolchain_test() + + native.test_suite( + name = name, + tests = [ + ":toolchain_specifies_target_triple_test", + ":toolchain_specifies_target_json_test", + ], + )