Skip to content

Commit

Permalink
Pass C++ runtime lib when C++ toolchain declares it
Browse files Browse the repository at this point in the history
Currently `rules_rust` won't link against the C++ standard library in case
C++ toolchain is the `static_link_cpp_runtimes` feature (therefore when
it uses `cc_toolchain.static_runtime_lib` and `cc_toolchain.dynamic_runtime_lib`
attributes to declare which version of C++ static library should be
linked into the final binary).

This PR modifies `get_libs_for_static_executable` to also look into the
C++ toolchain and depend on C++ standard library from there.

Once we implement the support for dynamically linked rust binaries we
will likely have an equivalend `get_libs_for_dynamic_executable`, which
would then look into `cc_toolchain.dynamic_runtime_lib`.

While there, I moved the `get_cc_toolchain` function to the `utils.rs`,
to be consistent with the handling of the Rust toolchain.
  • Loading branch information
hlopko committed Feb 4, 2021
1 parent 757510f commit f88c3ce
Show file tree
Hide file tree
Showing 4 changed files with 54 additions and 37 deletions.
6 changes: 3 additions & 3 deletions cargo/cargo_build_script.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,10 @@ load("//rust:rust.bzl", "rust_binary")
load("//rust/private:rust.bzl", "name_to_crate_name")

# buildifier: disable=bzl-visibility
load("//rust/private:rustc.bzl", "BuildInfo", "DepInfo", "get_cc_toolchain", "get_compilation_mode_opts", "get_linker_and_args")
load("//rust/private:rustc.bzl", "BuildInfo", "DepInfo", "get_compilation_mode_opts", "get_linker_and_args")

# buildifier: disable=bzl-visibility
load("//rust/private:utils.bzl", "expand_locations", "find_toolchain")
load("//rust/private:utils.bzl", "expand_locations", "find_cc_toolchain", "find_toolchain")

def get_cc_compile_env(cc_toolchain, feature_configuration):
"""Gather cc environment variables from the given `cc_toolchain`
Expand Down Expand Up @@ -98,7 +98,7 @@ def _build_script_impl(ctx):

# Pull in env vars which may be required for the cc_toolchain to work (e.g. on OSX, the SDK version).
# We hope that the linker env is sufficient for the whole cc_toolchain.
cc_toolchain, feature_configuration = get_cc_toolchain(ctx)
cc_toolchain, feature_configuration = find_cc_toolchain(ctx)
_, _, linker_env = get_linker_and_args(ctx, cc_toolchain, feature_configuration, None)
env.update(**linker_env)

Expand Down
9 changes: 5 additions & 4 deletions rust/private/clippy.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,8 @@ load(
"collect_deps",
"collect_inputs",
"construct_arguments",
"get_cc_toolchain",
)
load("//rust/private:utils.bzl", "determine_output_hash", "find_toolchain")
load("//rust/private:utils.bzl", "determine_output_hash", "find_cc_toolchain", "find_toolchain")

_rust_extensions = [
"rs",
Expand All @@ -48,6 +47,7 @@ def _clippy_aspect_impl(target, ctx):
rust_srcs = _rust_sources(target, ctx.rule)

toolchain = find_toolchain(ctx)
cc_toolchain, feature_configuration = find_cc_toolchain(ctx)
crate_info = target[rust_common.crate_info]
crate_type = crate_info.type

Expand All @@ -65,13 +65,16 @@ def _clippy_aspect_impl(target, ctx):
crate_info.proc_macro_deps,
crate_info.aliases,
toolchain,
cc_toolchain,
feature_configuration,
)

compile_inputs, out_dir, build_env_file, build_flags_files = collect_inputs(
ctx,
ctx.rule.file,
ctx.rule.files,
toolchain,
cc_toolchain,
crate_info,
dep_info,
build_info,
Expand All @@ -81,8 +84,6 @@ def _clippy_aspect_impl(target, ctx):
# This file is necessary because "ctx.actions.run" mandates an output.
clippy_marker = ctx.actions.declare_file(ctx.label.name + "_clippy.ok")

cc_toolchain, feature_configuration = get_cc_toolchain(ctx)

args, env = construct_arguments(
ctx,
ctx.file,
Expand Down
55 changes: 25 additions & 30 deletions rust/private/rustc.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,11 @@ 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("//rust/private:common.bzl", "rust_common")
load(
"//rust/private:utils.bzl",
"expand_locations",
"find_cc_toolchain",
"get_lib_name",
"get_libs_for_static_executable",
"relativize",
Expand Down Expand Up @@ -113,7 +113,7 @@ def get_compilation_mode_opts(ctx, toolchain):

return toolchain.compilation_mode_opts[comp_mode]

def collect_deps(label, deps, proc_macro_deps, aliases, toolchain):
def collect_deps(label, deps, proc_macro_deps, aliases, toolchain, cc_toolchain, feature_configuration):
"""Walks through dependencies and collects the transitive dependencies.
Args:
Expand All @@ -122,6 +122,8 @@ def collect_deps(label, deps, proc_macro_deps, aliases, toolchain):
proc_macro_deps (list): The proc_macro deps from ctx.attr.proc_macro_deps.
aliases (dict): A dict mapping aliased targets to their actual Crate information.
toolchain (rust_toolchain): The current `rust_toolchain`.
cc_toolchain (CcToolchainInfo): The current `cc_toolchain`.
feature_configuration (FeatureConfiguration): The current `feature_configuration` to use with `cc_toolchain`.
Returns:
tuple: Returns a tuple (DepInfo, BuildInfo) of providers.
Expand Down Expand Up @@ -215,25 +217,6 @@ def collect_deps(label, deps, proc_macro_deps, aliases, toolchain):
build_info,
)

def get_cc_toolchain(ctx):
"""Extracts a CcToolchain from the current target's context
Args:
ctx (ctx): The current target's rule context object
Returns:
tuple: A tuple of (CcToolchain, FeatureConfiguration)
"""
cc_toolchain = find_cpp_toolchain(ctx)

feature_configuration = cc_common.configure_features(
ctx = ctx,
cc_toolchain = cc_toolchain,
requested_features = ctx.features,
unsupported_features = ctx.disabled_features,
)
return cc_toolchain, feature_configuration

def get_cc_user_link_flags(ctx):
"""Get the current target's linkopt flags
Expand Down Expand Up @@ -319,16 +302,18 @@ def collect_inputs(
file,
files,
toolchain,
cc_toolchain,
crate_info,
dep_info,
build_info):
"""Gather's the inputs and required input information for a rustc action
Args:
ctx (ctx): The rule's context object
ctx (ctx): The rule's context object.
file (struct): A struct containing files defined in label type attributes marked as `allow_single_file`.
files (list): A list of all inputs
toolchain (rust_toolchain): The current `rust_toolchain`
files (list): A list of all inputs.
toolchain (rust_toolchain): The current `rust_toolchain`.
cc_toolchain (CcToolchainInfo): The current `cc_toolchain`.
crate_info (CrateInfo): The Crate information of the crate to process build scripts for.
dep_info (DepInfo): The target Crate's dependency information.
build_info (BuildInfo): The target Crate's build settings.
Expand All @@ -338,7 +323,7 @@ def collect_inputs(
"""
linker_script = getattr(file, "linker_script") if hasattr(file, "linker_script") else None

linker_depset = find_cpp_toolchain(ctx).all_files
linker_depset = cc_toolchain.all_files

compile_inputs = depset(
crate_info.srcs +
Expand Down Expand Up @@ -510,7 +495,7 @@ def construct_arguments(
args.add("--codegen=linker=" + ld)
args.add_joined("--codegen", link_args, join_with = " ", format_joined = "link-args=%s")

add_native_link_flags(args, dep_info, crate_type)
_add_native_link_flags(args, dep_info, crate_type, cc_toolchain, feature_configuration)

# These always need to be added, even if not linking this crate.
add_crate_link_flags(args, dep_info)
Expand Down Expand Up @@ -563,26 +548,29 @@ def rustc_compile_action(
- (DepInfo): The transitive dependencies of this crate.
- (DefaultInfo): The output file for this crate, and its runfiles.
"""
cc_toolchain, feature_configuration = find_cc_toolchain(ctx)

dep_info, build_info = collect_deps(
ctx.label,
crate_info.deps,
crate_info.proc_macro_deps,
crate_info.aliases,
toolchain,
cc_toolchain,
feature_configuration,
)

compile_inputs, out_dir, build_env_file, build_flags_files = collect_inputs(
ctx,
ctx.file,
ctx.files,
toolchain,
cc_toolchain,
crate_info,
dep_info,
build_info,
)

cc_toolchain, feature_configuration = get_cc_toolchain(ctx)

args, env = construct_arguments(
ctx,
ctx.file,
Expand Down Expand Up @@ -812,13 +800,15 @@ def _get_crate_dirname(crate):
"""
return crate.output.dirname

def add_native_link_flags(args, dep_info, crate_type):
def _add_native_link_flags(args, dep_info, crate_type, cc_toolchain, feature_configuration):
"""Adds linker flags for all dependencies of the current target.
Args:
args (Args): The Args struct for a ctx.action
dep_info (DepInfo): Dependency Info provider
crate_type: Crate type of the current target
cc_toolchain (CcToolchainInfo):
feature_configuration (FeatureConfiguration):
"""
if crate_type in ["lib", "rlib"]:
Expand All @@ -829,8 +819,13 @@ def add_native_link_flags(args, dep_info, crate_type):
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")

if crate_type in ["staticlib", "dylib", "cdylib"]:
return

args.add_all(cc_toolchain.static_runtime_lib(feature_configuration = feature_configuration), map_each = get_lib_name, format_each = "-lstatic=%s")

def _get_dirname(file):
"""A helper function for `add_native_link_flags`.
"""A helper function for `_add_native_link_flags`.
Args:
file (File): The target file
Expand Down
21 changes: 21 additions & 0 deletions rust/private/utils.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@

"""Utility functions not specific to the rust toolchain."""

load("@bazel_tools//tools/cpp:toolchain_utils.bzl", find_rules_cc_toolchain = "find_cpp_toolchain")

def find_toolchain(ctx):
"""Finds the first rust toolchain that is configured.
Expand All @@ -25,6 +27,25 @@ def find_toolchain(ctx):
"""
return ctx.toolchains[Label("//rust:toolchain")]

def find_cc_toolchain(ctx):
"""Extracts a CcToolchain from the current target's context
Args:
ctx (ctx): The current target's rule context object
Returns:
tuple: A tuple of (CcToolchain, FeatureConfiguration)
"""
cc_toolchain = find_rules_cc_toolchain(ctx)

feature_configuration = cc_common.configure_features(
ctx = ctx,
cc_toolchain = cc_toolchain,
requested_features = ctx.features,
unsupported_features = ctx.disabled_features,
)
return cc_toolchain, feature_configuration

# TODO: Replace with bazel-skylib's `path.dirname`. This requires addressing some
# dependency issues or generating docs will break.
def relativize(path, start):
Expand Down

0 comments on commit f88c3ce

Please sign in to comment.