From 1eae40f048f619a7cc53267fae1716877041e6d1 Mon Sep 17 00:00:00 2001 From: Marcel Hlopko Date: Sun, 3 Nov 2019 21:49:10 +0100 Subject: [PATCH] Propagate linkopts --- WORKSPACE | 10 ++++--- rust/private/rustc.bzl | 14 ++++++++++ test/analysis/BUILD | 3 +++ test/analysis/native_deps_test.bzl | 42 ++++++++++++++++++++++++++++++ 4 files changed, 66 insertions(+), 3 deletions(-) create mode 100644 test/analysis/BUILD create mode 100644 test/analysis/native_deps_test.bzl diff --git a/WORKSPACE b/WORKSPACE index c97ce18878..59e3dafc7a 100644 --- a/WORKSPACE +++ b/WORKSPACE @@ -19,10 +19,14 @@ local_repository( http_archive( name = "bazel_skylib", - sha256 = "eb5c57e4c12e68c0c20bc774bfbc60a568e800d025557bc4ea022c6479acc867", - strip_prefix = "bazel-skylib-0.6.0", - url = "https://github.com/bazelbuild/bazel-skylib/archive/0.6.0.tar.gz", + urls = [ + "https://mirror.bazel.build/github.com/bazelbuild/bazel-skylib/releases/download/1.0.2/bazel-skylib-1.0.2.tar.gz", + "https://github.com/bazelbuild/bazel-skylib/releases/download/1.0.2/bazel-skylib-1.0.2.tar.gz", + ], + sha256 = "97e70364e9249702246c0e9444bccdc4b847bed1eb03c5a3ece4f83dfe6abc44", ) +load("@bazel_skylib//:workspace.bzl", "bazel_skylib_workspace") +bazel_skylib_workspace() # TODO: Move this to examples/WORKSPACE when recursive repositories are enabled. load("@io_bazel_rules_rust//rust:repositories.bzl", "rust_repositories") diff --git a/rust/private/rustc.bzl b/rust/private/rustc.bzl index 0839ae407a..8c3472e7fb 100644 --- a/rust/private/rustc.bzl +++ b/rust/private/rustc.bzl @@ -44,6 +44,7 @@ DepInfo = provider( "transitive_dylibs": "depset[File]", "transitive_staticlibs": "depset[File]", "transitive_libs": "List[File]: All transitive dependencies, not filtered by type.", + "linkopts": "list[string]", }, ) @@ -101,6 +102,7 @@ def collect_deps(deps, toolchain): transitive_crates = depset() transitive_dylibs = depset(order = "topological") # dylib link flag ordering matters. transitive_staticlibs = depset() + linkopts = [] for dep in deps: if CrateInfo in dep: # This dependency is a rust_library @@ -114,10 +116,20 @@ def collect_deps(deps, toolchain): # TODO: We could let the user choose how to link, instead of always preferring to link static libraries. libs = get_libs_for_static_executable(dep) + # TODO: This is changing the order of linker inputs, it shouldn't. + # In more sophisticated scenarios we need to retain the relative + # order of static/shared libraries. Imagine following libs: + # libs = [ liba.a, libb.so, libc.a ] + # Ideally this will get converted into the following linker command + # line: + # -la -lb -lc + # But the current implementation produces: + # -la -lc -b dylibs = [l for l in libs.to_list() if l.basename.endswith(toolchain.dylib_ext)] staticlibs = [l for l in libs.to_list() if l.basename.endswith(toolchain.staticlib_ext)] transitive_dylibs = depset(transitive = [transitive_dylibs, depset(dylibs)]) transitive_staticlibs = depset(transitive = [transitive_staticlibs, depset(staticlibs)]) + linkopts.extend(dep[CcInfo].linking_context.user_link_flags) else: fail("rust targets can only depend on rust_library, rust_*_library or cc_library targets." + str(dep), "deps") @@ -132,6 +144,7 @@ def collect_deps(deps, toolchain): transitive_dylibs = transitive_dylibs, transitive_staticlibs = transitive_staticlibs, transitive_libs = transitive_libs.to_list(), + linkopts = linkopts, ) def _get_linker_and_args(ctx, rpaths): @@ -399,6 +412,7 @@ def add_native_link_flags(args, dep_info): args.add_all(native_libs, map_each = _get_dirname, uniquify = True, format_each = "-Lnative=%s") args.add_all(dep_info.transitive_dylibs, map_each = get_lib_name, format_each = "-ldylib=%s") args.add_all(dep_info.transitive_staticlibs, map_each = get_lib_name, format_each = "-lstatic=%s") + args.add_all(dep_info.linkopts, uniquify = False) def _get_dirname(file): return file.dirname diff --git a/test/analysis/BUILD b/test/analysis/BUILD new file mode 100644 index 0000000000..ba430fadec --- /dev/null +++ b/test/analysis/BUILD @@ -0,0 +1,3 @@ +load(":native_deps_test.bzl", "native_deps_test_suite") + +native_deps_test_suite(name = "native_deps_test_suite") diff --git a/test/analysis/native_deps_test.bzl b/test/analysis/native_deps_test.bzl new file mode 100644 index 0000000000..458f90ae3b --- /dev/null +++ b/test/analysis/native_deps_test.bzl @@ -0,0 +1,42 @@ +load("@rules_cc//cc:defs.bzl", "cc_library") +load("@bazel_skylib//lib:unittest.bzl", "analysistest", "asserts") +load("//rust:rust.bzl", "rust_binary") + +def _linkopts_test_impl(ctx): + env = analysistest.begin(ctx) + + subject = analysistest.target_under_test(env) + actions = analysistest.target_actions(env) + + asserts.true(env, "-lsystem_lib" in actions[0].argv) + + return analysistest.end(env) + +linkopts_test = analysistest.make(_linkopts_test_impl) + +def _linkopts_test(): + cc_library( + name = "native", + linkopts = ["-lsystem_lib"], + tags = ["manual"], + ) + rust_binary( + name = "main", + deps = [":native"], + srcs = ["main.rs"], + tags = ["manual"], + ) + linkopts_test( + name = "linkopts_test", + target_under_test = ":main", + ) + +def native_deps_test_suite(name): + _linkopts_test() + + native.test_suite( + name = name, + tests = [ + ":linkopts_test", + ], + )