Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor rustc_compile_action to construct CrateInfo internally #2188

Merged
merged 9 commits into from
Oct 17, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion proto/prost/private/prost.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -160,7 +160,7 @@ def _compile_rust(ctx, attr, crate_name, src, deps, edition):
ctx = ctx,
attr = attr,
toolchain = toolchain,
crate_info = rust_common.create_crate_info(
crate_info_dict = dict(
name = crate_name,
type = "rlib",
root = src,
Expand Down
3 changes: 1 addition & 2 deletions proto/protobuf/proto.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ load(
_generate_proto = "rust_generate_proto",
_generated_file_stem = "generated_file_stem",
)
load("//rust:defs.bzl", "rust_common")

# buildifier: disable=bzl-visibility
load("//rust/private:rustc.bzl", "rustc_compile_action")
Expand Down Expand Up @@ -214,7 +213,7 @@ def _rust_proto_compile(protos, descriptor_sets, imports, crate_name, ctx, is_gr
ctx = ctx,
attr = ctx.attr,
toolchain = toolchain,
crate_info = rust_common.create_crate_info(
crate_info_dict = dict(
name = crate_name,
type = "rlib",
root = lib_rs,
Expand Down
56 changes: 48 additions & 8 deletions rust/private/rust.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -14,15 +14,17 @@

"""Rust rule implementations"""

load("@bazel_skylib//lib:paths.bzl", "paths")
load("//rust/private:common.bzl", "rust_common")
load("//rust/private:providers.bzl", "BuildInfo")
load("//rust/private:rustc.bzl", "rustc_compile_action")
load(
"//rust/private:utils.bzl",
"can_build_metadata",
"compute_crate_name",
"crate_root_src",
"create_crate_info_dict",
"dedent",
"determine_lib_name",
"determine_output_hash",
"expand_dict_value_locations",
"find_toolchain",
Expand All @@ -31,6 +33,7 @@ load(
"transform_deps",
"transform_sources",
)

# TODO(marco): Separate each rule into its own file.

def _assert_no_deprecated_attributes(_ctx):
Expand Down Expand Up @@ -140,10 +143,12 @@ def _rust_library_common(ctx, crate_type):

toolchain = find_toolchain(ctx)

crate_name = compute_crate_name(ctx.workspace_name, ctx.label, toolchain, ctx.attr.crate_name)

crate_root = getattr(ctx.file, "crate_root", None)
if not crate_root:
crate_root = crate_root_src(ctx.attr.name, ctx.files.srcs, crate_type)
_, crate_root = transform_sources(ctx, ctx.files.srcs, crate_root)
srcs, crate_root = transform_sources(ctx, ctx.files.srcs, crate_root)

# Determine unique hash for this rlib.
# Note that we don't include a hash for `cdylib` and `staticlib` since they are meant to be consumed externally
Expand All @@ -155,13 +160,48 @@ def _rust_library_common(ctx, crate_type):
else:
output_hash = determine_output_hash(crate_root, ctx.label)

rust_lib_name = determine_lib_name(
crate_name,
crate_type,
toolchain,
output_hash,
)
rust_lib = ctx.actions.declare_file(rust_lib_name)
rust_metadata = None
if can_build_metadata(toolchain, ctx, crate_type) and not ctx.attr.disable_pipelining:
rust_metadata = ctx.actions.declare_file(
paths.replace_extension(rust_lib_name, ".rmeta"),
sibling = rust_lib,
)

deps = transform_deps(ctx.attr.deps)
proc_macro_deps = transform_deps(ctx.attr.proc_macro_deps + get_import_macro_deps(ctx))

return rustc_compile_action(
ctx = ctx,
attr = ctx.attr,
toolchain = toolchain,
output_hash = output_hash,
crate_type = crate_type,
create_crate_info_callback = create_crate_info_dict,
crate_info_dict = dict(
name = crate_name,
type = crate_type,
root = crate_root,
srcs = depset(srcs),
deps = depset(deps),
proc_macro_deps = depset(proc_macro_deps),
aliases = ctx.attr.aliases,
output = rust_lib,
metadata = rust_metadata,
edition = get_edition(ctx.attr, toolchain, ctx.label),
rustc_env = ctx.attr.rustc_env,
rustc_env_files = ctx.files.rustc_env_files,
is_test = False,
data = depset(ctx.files.data),
compile_data = depset(ctx.files.compile_data),
compile_data_targets = depset(ctx.attr.compile_data),
owner = ctx.label,
_rustc_env_attr = ctx.attr.rustc_env,
),
)

def _rust_binary_impl(ctx):
Expand Down Expand Up @@ -191,7 +231,7 @@ def _rust_binary_impl(ctx):
ctx = ctx,
attr = ctx.attr,
toolchain = toolchain,
crate_info = rust_common.create_crate_info(
crate_info_dict = dict(
name = crate_name,
type = ctx.attr.crate_type,
root = crate_root,
Expand Down Expand Up @@ -266,7 +306,7 @@ def _rust_test_impl(ctx):
))

# Build the test binary using the dependency's srcs.
crate_info = rust_common.create_crate_info(
crate_info_dict = dict(
name = crate.name,
type = crate_type,
root = crate.root,
Expand Down Expand Up @@ -310,7 +350,7 @@ def _rust_test_impl(ctx):
)

# Target is a standalone crate. Build the test binary as its own crate.
crate_info = rust_common.create_crate_info(
crate_info_dict = dict(
name = compute_crate_name(ctx.workspace_name, ctx.label, toolchain, ctx.attr.crate_name),
type = crate_type,
root = crate_root,
Expand All @@ -333,7 +373,7 @@ def _rust_test_impl(ctx):
ctx = ctx,
attr = ctx.attr,
toolchain = toolchain,
crate_info = crate_info,
crate_info_dict = crate_info_dict,
rust_flags = ["--test"] if ctx.attr.use_libtest_harness else ["--cfg", "test"],
skip_expanding_rustc_env = True,
)
Expand Down
32 changes: 9 additions & 23 deletions rust/private/rustc.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -1085,27 +1085,21 @@ def rustc_compile_action(
attr,
toolchain,
rust_flags = [],
crate_type = None,
crate_info = None,
output_hash = None,
force_all_deps_direct = False,
# TODO: Remove create_crate_info_callback and skip_expanding_rustc_env attributes
# after all CrateInfo structs are constructed in rustc_compile_action
create_crate_info_callback = None,
crate_info_dict = None,
skip_expanding_rustc_env = False):
"""Create and run a rustc compile action based on the current rule's attributes

Args:
ctx (ctx): The rule's context object
attr (struct): Attributes to use for the rust compile action
toolchain (rust_toolchain): The current `rust_toolchain`
crate_type: TODO
crate_info (CrateInfo): The CrateInfo provider for the current target.
output_hash (str, optional): The hashed path of the crate root. Defaults to None.
rust_flags (list, optional): Additional flags to pass to rustc. Defaults to [].
force_all_deps_direct (bool, optional): Whether to pass the transitive rlibs with --extern
to the commandline as opposed to -L.
create_crate_info_callback: A callback to construct a mutable dict for constructor CrateInfo
crate_info_dict: A mutable dict used to create CrateInfo provider
skip_expanding_rustc_env (bool, optional): Whether to expand CrateInfo.rustc_env

Returns:
Expand All @@ -1114,19 +1108,11 @@ def rustc_compile_action(
- (DepInfo): The transitive dependencies of this crate.
- (DefaultInfo): The output file for this crate, and its runfiles.
"""
# TODO: Remove create_crate_info_callback after all rustc_compile_action callers migrate to
# removing CrateInfo construction before `rust_compile_action
crate_info = rust_common.create_crate_info(**crate_info_dict)

crate_info_dict = None
if create_crate_info_callback != None:
if ctx == None or toolchain == None or crate_type == None or crate_info != None:
fail("FAIL", ctx, toolchain, crate_type)
crate_info_dict = create_crate_info_callback(ctx, toolchain, crate_type)

if crate_info_dict != None:
crate_info = rust_common.create_crate_info(**crate_info_dict)

build_metadata = getattr(crate_info, "metadata", None)
build_metadata = None
if "metadata" in crate_info_dict:
build_metadata = crate_info_dict["metadata"]

cc_toolchain, feature_configuration = find_cc_toolchain(ctx)

Expand All @@ -1144,9 +1130,9 @@ def rustc_compile_action(
experimental_use_cc_common_link = toolchain._experimental_use_cc_common_link

dep_info, build_info, linkstamps = collect_deps(
deps = crate_info.deps,
proc_macro_deps = crate_info.proc_macro_deps,
aliases = crate_info.aliases,
deps = crate_info_dict["deps"],
proc_macro_deps = crate_info_dict["proc_macro_deps"],
aliases = crate_info_dict["aliases"],
are_linkstamps_supported = _are_linkstamps_supported(
feature_configuration = feature_configuration,
has_grep_includes = hasattr(ctx.attr, "_use_grep_includes"),
Expand Down
67 changes: 1 addition & 66 deletions rust/private/utils.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -727,7 +727,7 @@ def _shortest_src_with_basename(srcs, basename):
shortest = f
return shortest

def _determine_lib_name(name, crate_type, toolchain, lib_hash = None):
def determine_lib_name(name, crate_type, toolchain, lib_hash = None):
"""See https://github.com/bazelbuild/rules_rust/issues/405

Args:
Expand Down Expand Up @@ -849,68 +849,3 @@ def _symlink_for_non_generated_source(ctx, src_file, package_root):
return src_symlink
else:
return src_file

def create_crate_info_dict(ctx, toolchain, crate_type):
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The logic of this function differs significantly across the rules and aspects so it's not sharable anymore.

"""Creates a mutable dict() representing CrateInfo provider

create_crate_info_dict is a *temporary* solution until create_crate_info is completely moved into
rustc_compile_action function.

The function is currently used as a callback to support constructing CrateInfo in rustc_compile_action
to ensure `CrateInfo.rustc_env` is fully loaded with all the env vars passed to rustc.

Args:
ctx (struct): The current rule's context
toolchain (toolchain): The rust toolchain
crate_type (String): one of lib|rlib|dylib|staticlib|cdylib|proc-macro

Returns:
File: The created symlink if a non-generated file, or the file itself.
"""
crate_name = compute_crate_name(ctx.workspace_name, ctx.label, toolchain, ctx.attr.crate_name)
crate_root = getattr(ctx.file, "crate_root", None)
if not crate_root:
crate_root = crate_root_src(ctx.attr.name, ctx.files.srcs, crate_type)
srcs, crate_root = transform_sources(ctx, ctx.files.srcs, crate_root)

if crate_type in ["cdylib", "staticlib"]:
output_hash = None
else:
output_hash = determine_output_hash(crate_root, ctx.label)

deps = transform_deps(ctx.attr.deps)
proc_macro_deps = transform_deps(ctx.attr.proc_macro_deps + get_import_macro_deps(ctx))
rust_lib_name = _determine_lib_name(
crate_name,
crate_type,
toolchain,
output_hash,
)
rust_lib = ctx.actions.declare_file(rust_lib_name)
rust_metadata = None
if can_build_metadata(toolchain, ctx, crate_type) and not ctx.attr.disable_pipelining:
rust_metadata = ctx.actions.declare_file(
paths.replace_extension(rust_lib_name, ".rmeta"),
sibling = rust_lib,
)

return dict(
name = crate_name,
type = crate_type,
root = crate_root,
srcs = depset(srcs),
deps = depset(deps),
proc_macro_deps = depset(proc_macro_deps),
aliases = ctx.attr.aliases,
output = rust_lib,
metadata = rust_metadata,
edition = get_edition(ctx.attr, toolchain, ctx.label),
rustc_env = ctx.attr.rustc_env,
rustc_env_files = ctx.files.rustc_env_files,
is_test = False,
data = depset(ctx.files.data),
compile_data = depset(ctx.files.compile_data),
compile_data_targets = depset(ctx.attr.compile_data),
owner = ctx.label,
_rustc_env_attr = ctx.attr.rustc_env,
)
4 changes: 1 addition & 3 deletions test/unit/consistent_crate_name/with_modified_crate_name.bzl
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
"""A custom rule that threats all its dependencies as direct dependencies."""

load("//rust:defs.bzl", "rust_common")

# buildifier: disable=bzl-visibility
load("//rust/private:providers.bzl", "BuildInfo", "CrateInfo", "DepInfo", "DepVariantInfo")

Expand Down Expand Up @@ -35,7 +33,7 @@ def _with_modified_crate_name_impl(ctx):
ctx = ctx,
attr = ctx.attr,
toolchain = toolchain,
crate_info = rust_common.create_crate_info(
crate_info_dict = dict(
name = crate_name,
type = crate_type,
root = crate_root,
Expand Down
5 changes: 1 addition & 4 deletions test/unit/force_all_deps_direct/generator.bzl
Original file line number Diff line number Diff line change
@@ -1,8 +1,5 @@
"""A custom rule that threats all its dependencies as direct dependencies."""

# buildifier: disable=bzl-visibility
load("//rust/private:common.bzl", "rust_common")

# buildifier: disable=bzl-visibility
load("//rust/private:providers.bzl", "BuildInfo", "CrateInfo", "DepInfo", "DepVariantInfo")

Expand Down Expand Up @@ -52,7 +49,7 @@ EOF
ctx = ctx,
attr = ctx.attr,
toolchain = toolchain,
crate_info = rust_common.create_crate_info(
crate_info_dict = dict(
name = crate_name,
type = crate_type,
root = rs_file,
Expand Down
5 changes: 1 addition & 4 deletions test/unit/pipelined_compilation/wrap.bzl
Original file line number Diff line number Diff line change
@@ -1,8 +1,5 @@
"""A custom rule that wraps a crate called to_wrap."""

# buildifier: disable=bzl-visibility
load("//rust/private:common.bzl", "rust_common")

# buildifier: disable=bzl-visibility
load("//rust/private:providers.bzl", "BuildInfo", "CrateInfo", "DepInfo", "DepVariantInfo")

Expand Down Expand Up @@ -61,7 +58,7 @@ EOF
ctx = ctx,
attr = ctx.attr,
toolchain = toolchain,
crate_info = rust_common.create_crate_info(
crate_info_dict = dict(
name = crate_name,
type = crate_type,
root = rs_file,
Expand Down
Loading