diff --git a/WORKSPACE b/WORKSPACE index cd69e6f7f6..8e259c56c5 100644 --- a/WORKSPACE +++ b/WORKSPACE @@ -59,3 +59,13 @@ http_archive( "https://github.com/bazelbuild/bazel-toolchains/archive/cdea5b8675914d0a354d89f108de5d28e54e0edc.tar.gz", ], ) + +http_archive( + name = "bazel_skylib", + url = "https://github.com/bazelbuild/bazel-skylib/archive/0.5.0.tar.gz", + sha256 = "b5f6abe419da897b7901f90cbab08af958b97a8f3575b0d3dd062ac7ce78541f", + strip_prefix = "bazel-skylib-0.5.0" +) + +load(":workspace.bzl", "bazel_version") +bazel_version(name = "bazel_version") diff --git a/rust/private/rust.bzl b/rust/private/rust.bzl index e05f105c02..952b67ec01 100644 --- a/rust/private/rust.bzl +++ b/rust/private/rust.bzl @@ -192,6 +192,7 @@ _rust_common_attrs = { ], single_file = True, ), + "_cc_toolchain": attr.label(default = "@bazel_tools//tools/cpp:current_cc_toolchain"), } _rust_library_attrs = { @@ -202,6 +203,7 @@ rust_library = rule( _rust_library_impl, attrs = dict(_rust_common_attrs.items() + _rust_library_attrs.items()), + fragments = ["cpp"], host_fragments = ["cpp"], toolchains = ["@io_bazel_rules_rust//rust:toolchain"], ) @@ -318,6 +320,7 @@ rust_binary = rule( _rust_binary_impl, attrs = _rust_common_attrs, executable = True, + fragments = ["cpp"], host_fragments = ["cpp"], toolchains = ["@io_bazel_rules_rust//rust:toolchain"], ) @@ -449,6 +452,7 @@ rust_test = rule( _rust_test_impl, attrs = _rust_common_attrs, executable = True, + fragments = ["cpp"], host_fragments = ["cpp"], test = True, toolchains = ["@io_bazel_rules_rust//rust:toolchain"], @@ -618,6 +622,7 @@ rust_benchmark = rule( _rust_benchmark_impl, attrs = _rust_common_attrs, executable = True, + fragments = ["cpp"], host_fragments = ["cpp"], toolchains = ["@io_bazel_rules_rust//rust:toolchain"], ) diff --git a/rust/private/rustc.bzl b/rust/private/rustc.bzl index 80acea5c5e..0bd7c445f3 100644 --- a/rust/private/rustc.bzl +++ b/rust/private/rustc.bzl @@ -13,6 +13,16 @@ # limitations under the License. load(":private/utils.bzl", "find_toolchain", "relative_path") +load( + "@bazel_tools//tools/build_defs/cc:action_names.bzl", + "CPP_LINK_EXECUTABLE_ACTION_NAME", +) +load( + "@bazel_tools//tools/cpp:toolchain_utils.bzl", + "find_cpp_toolchain", +) +load("@bazel_skylib//lib:versions.bzl", "versions") +load("@bazel_version//:def.bzl", "BAZEL_VERSION") CrateInfo = provider( fields = { @@ -178,20 +188,37 @@ def rustc_compile_action( if ctx.file.out_dir_tar: compile_inputs.append(ctx.file.out_dir_tar) - # Paths to cc (for linker) and ar - cpp_fragment = ctx.host_fragments.cpp - cc = cpp_fragment.compiler_executable - ar = cpp_fragment.ar_executable + rpaths = _compute_rpaths(toolchain, output_dir, depinfo) - # Currently, the CROSSTOOL config for darwin sets ar to "libtool". Because - # rust uses ar-specific flags, use /usr/bin/ar in this case. - # TODO(dzc): This is not ideal. Remove this workaround once ar_executable - # always points to an ar binary. - ar_str = "%s" % ar - if ar_str.find("libtool", 0) != -1: - ar = "/usr/bin/ar" + if versions.is_at_least("0.18.0", BAZEL_VERSION): + user_link_flags = ctx.fragments.cpp.linkopts + else: + user_link_flags = depset(ctx.fragments.cpp.linkopts) - rpaths = _compute_rpaths(toolchain, output_dir, depinfo) + # Paths to cc (for linker) and ar + cpp_fragment = ctx.host_fragments.cpp + cc_toolchain = find_cpp_toolchain(ctx) + feature_configuration = cc_common.configure_features( + cc_toolchain = cc_toolchain, + requested_features = ctx.features, + unsupported_features = ctx.disabled_features, + ) + ld = cc_common.get_tool_for_action( + feature_configuration = feature_configuration, + action_name = CPP_LINK_EXECUTABLE_ACTION_NAME, + ) + link_variables = cc_common.create_link_variables( + feature_configuration = feature_configuration, + cc_toolchain = cc_toolchain, + is_linking_dynamic_library = False, + runtime_library_search_directories = rpaths, + user_link_flags = user_link_flags, + ) + link_options = cc_common.get_memory_inefficient_command_line( + feature_configuration = feature_configuration, + action_name = CPP_LINK_EXECUTABLE_ACTION_NAME, + variables = link_variables, + ) # Construct features flags features_flags = _get_features_flags(ctx.attr.crate_features) @@ -222,9 +249,8 @@ def rustc_compile_action( # Mangle symbols to disambiguate crates with the same name "--codegen metadata=%s" % extra_filename, "--codegen extra-filename='%s'" % extra_filename, - "--codegen ar=%s" % ar, - "--codegen linker=%s" % cc, - "--codegen link-args='%s'" % " ".join(cpp_fragment.link_options), + "--codegen linker=%s" % ld, + "--codegen link-args='%s'" % " ".join(link_options), "--remap-path-prefix {}={}".format("$(pwd)", "__bazel_redacted_pwd"), "--out-dir", output_dir, @@ -232,7 +258,6 @@ def rustc_compile_action( "--color always", "--target=" + toolchain.target_triple, ] + - ["--codegen link-arg='-Wl,-rpath={}'".format(rpath) for rpath in rpaths] + features_flags + rust_flags + depinfo.link_search_flags + @@ -268,7 +293,7 @@ def _compute_rpaths(toolchain, output_dir, depinfo): for runtime linking of shared libraries. """ if not depinfo.transitive_dylibs: - return [] + return depset([]) if toolchain.os != "linux": fail("Runtime linking is not supported on {}, but found {}".format( toolchain.os, @@ -276,10 +301,10 @@ def _compute_rpaths(toolchain, output_dir, depinfo): )) # Multiple dylibs can be present in the same directory, so deduplicate them. - return [ - "$ORIGIN/" + relative_path(output_dir, lib_dir) + return depset([ + relative_path(output_dir, lib_dir) for lib_dir in _get_dir_names(depinfo.transitive_dylibs) - ] + ]) def _get_features_flags(features): """ diff --git a/workspace.bzl b/workspace.bzl new file mode 100644 index 0000000000..773a41dc6e --- /dev/null +++ b/workspace.bzl @@ -0,0 +1,12 @@ +load("@bazel_skylib//lib:versions.bzl", "versions") + +def _store_bazel_version(repository_ctx): + bazel_version = versions.get(); + if versions.is_at_most("0.17.0", bazel_version): + fail("Bazel %s is too old to use with rules_rust, please use at least Bazel 0.17.1, preferably newer." % bazel_version) + repository_ctx.file("BUILD", "exports_files(['def.bzl'])") + repository_ctx.file("def.bzl", "BAZEL_VERSION='" + bazel_version + "'") + +bazel_version = repository_rule( + implementation = _store_bazel_version, +)