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 #330

Merged
merged 5 commits into from
Jun 13, 2020
Merged
Changes from 3 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
163 changes: 114 additions & 49 deletions rust/private/rustc.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -210,33 +210,23 @@ def _get_linker_and_args(ctx, rpaths):

return ld, link_args, link_env

def rustc_compile_action(
def _rustc_compile_inputs_add_out_dir(
ctx,
toolchain,
crate_info,
output_hash = None,
rust_flags = []):
"""
Constructs the rustc command used to build the current target.

Returns:
List[Provider]: A list of the following providers:
- CrateInfo: info for the crate we just built; same as `crate_info` parameter.
- DepInfo: The transitive dependencies of this crate.
- DefaultInfo: The output file for this crate, and its runfiles.
"""
output_dir = crate_info.output.dirname
build_info,
compile_inputs):
out_dir = _create_out_dir_action(ctx, build_info.out_dir if build_info else None)
if out_dir:
compile_inputs = depset([out_dir], transitive = [compile_inputs])
return compile_inputs, out_dir

dep_info, build_info = collect_deps(
crate_info.deps,
crate_info.aliases,
def _rustc_compile_inputs(
ctx,
toolchain,
)

crate_info,
dep_info,
build_info):
dfreese marked this conversation as resolved.
Show resolved Hide resolved
linker_script = getattr(ctx.file, "linker_script") if hasattr(ctx.file, "linker_script") else None

cc_toolchain = find_cpp_toolchain(ctx)

Comment on lines -263 to -264
Copy link
Contributor Author

Choose a reason for hiding this comment

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

This was unused, and removed.

if (len(BAZEL_VERSION) == 0 or
versions.is_at_least("0.25.0", BAZEL_VERSION)):
linker_depset = find_cpp_toolchain(ctx).all_files
Expand All @@ -257,6 +247,18 @@ def rustc_compile_action(
linker_depset,
],
)
return _rustc_compile_inputs_add_out_dir(ctx, build_info, compile_inputs)

def _rustc_compile_arguments(
ctx,
toolchain,
crate_info,
dep_info,
output_hash,
rust_flags):
output_dir = crate_info.output.dirname

linker_script = getattr(ctx.file, "linker_script") if hasattr(ctx.file, "linker_script") else None

env = _get_rustc_env(ctx, toolchain)

Expand All @@ -280,7 +282,7 @@ def rustc_compile_action(
args.add("--target=" + toolchain.target_triple)
if hasattr(ctx.attr, "crate_features"):
args.add_all(getattr(ctx.attr, "crate_features"), before_each = "--cfg", format_each = 'feature="%s"')
if hasattr(ctx.attr, "linker_script") and linker_script != None:
if linker_script:
args.add(linker_script.path, format = "--codegen=link-arg=-T%s")

# Gets the paths to the folders containing the standard library (or libcore)
Expand All @@ -305,13 +307,24 @@ def rustc_compile_action(
args.add_joined("--codegen", link_args, join_with = " ", format_joined = "link-args=%s")

add_native_link_flags(args, dep_info)

add_crate_link_flags(args, dep_info)

# We awkwardly construct this command because we cannot reference $PWD from ctx.actions.run(executable=toolchain.rustc)
out_dir = _create_out_dir_action(ctx, build_info.out_dir if build_info else None)
Comment on lines -336 to -337
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Pulled up into _rustc_compile_inputs

# Make bin crate data deps available to tests.
for data in getattr(ctx.attr, "data", []):
if CrateInfo in data:
dep_crate_info = data[CrateInfo]
if dep_crate_info.type == "bin":
env["CARGO_BIN_EXE_" + dep_crate_info.output.basename] = dep_crate_info.output.short_path

# Update environment with user provided variables.
env.update(crate_info.rustc_env)

return args, env

def _create_command_env(ctx, out_dir):
if out_dir:
compile_inputs = depset([out_dir], transitive = [compile_inputs])
# We awkwardly construct this command because we cannot reference $PWD
# from ctx.actions.run(executable=toolchain.rustc)
out_dir_env = "OUT_DIR=$(pwd)/{} ".format(out_dir.path)
else:
out_dir_env = ""
Expand All @@ -338,45 +351,97 @@ def rustc_compile_action(
package_dir = ctx.build_file_path[:ctx.build_file_path.rfind("/")]
manifest_dir_env = "CARGO_MANIFEST_DIR=$(pwd)/{} ".format(package_dir)

return out_dir_env + manifest_dir_env

def _construct_compile_command(
ctx,
command,
toolchain,
crate_info,
build_info,
out_dir):
rustc_env_expansion = ("export $(cat %s);" % build_info.rustc_env.path) if build_info else ""
command_env = _create_command_env(ctx, out_dir)
build_flags_expansion = (" $(cat '%s')" % build_info.flags.path) if build_info else ""
# Handle that the binary name and crate name may be different.
# If a target name contains a - then cargo (and rules_rust) will generate a crate name with _ instead.
# Accordingly, rustc will generate a output file (executable, or rlib, or whatever) with _ not -.
# But when cargo puts a binary in the target/${config} directory, and sets environment variables like
# `CARGO_BIN_EXE_${binary_name}` it will use the - version not the _ version.
# So we rename the rustc-generated file (with _s) to have -s if needed.
#
# If a target name contains a - then cargo (and rules_rust) will generate a
# crate name with _ instead. Accordingly, rustc will generate a output
# file (executable, or rlib, or whatever) with _ not -. But when cargo
# puts a binary in the target/${config} directory, and sets environment
# variables like `CARGO_BIN_EXE_${binary_name}` it will use the - version
# not the _ version. So we rename the rustc-generated file (with _s) to
# have -s if needed.
maybe_rename = ""
if crate_info.type == "bin":
generated_file = crate_info.name
if toolchain.target_arch == "wasm32":
generated_file = generated_file + ".wasm"
src = "/".join([output_dir, generated_file])
src = "/".join([crate_info.output.dirname, generated_file])
dst = crate_info.output.path
if src != dst:
maybe_rename = " && /bin/mv {src} {dst}".format(src=src, dst=dst)
command = '{}{}{}{} "$@" --remap-path-prefix="$(pwd)"=__bazel_redacted_pwd{}{}'.format(
("export $(cat %s);" % build_info.rustc_env.path) if build_info else "",
manifest_dir_env,
out_dir_env,

return '{}{}{} "$@" --remap-path-prefix="$(pwd)"=__bazel_redacted_pwd{}{}'.format(
rustc_env_expansion,
command_env,
toolchain.rustc.path,
(" $(cat '%s')" % build_info.flags.path) if build_info else "",
build_flags_expansion,
maybe_rename,
)

def rustc_compile_action(
ctx,
toolchain,
crate_info,
output_hash = None,
rust_flags = []):
"""
Constructs the rustc command used to build the current target.

Returns:
List[Provider]: A list of the following providers:
- CrateInfo: info for the crate we just built; same as `crate_info` parameter.
- DepInfo: The transitive dependencies of this crate.
- DefaultInfo: The output file for this crate, and its runfiles.
"""
dep_info, build_info = collect_deps(
crate_info.deps,
crate_info.aliases,
toolchain,
)

compile_inputs, out_dir = _rustc_compile_inputs(
Copy link
Collaborator

Choose a reason for hiding this comment

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

I think each of these subcommands should start w/ verbs, eg.

collect_deps
collect_inputs
construct_arguments etc

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done

ctx,
toolchain,
crate_info,
dep_info,
build_info
)

args, env = _rustc_compile_arguments(
ctx,
toolchain,
crate_info,
dep_info,
output_hash,
rust_flags
)

command = _construct_compile_command(
ctx,
toolchain.rustc.path,
toolchain,
crate_info,
build_info,
out_dir,
)

if hasattr(ctx.attr, "version") and ctx.attr.version != "0.0.0":
formatted_version = " v{}".format(ctx.attr.version)
else:
formatted_version = ""

# Make bin crate data deps available to tests.
for data in getattr(ctx.attr, "data", []):
if CrateInfo in data:
dep_crate_info = data[CrateInfo]
if dep_crate_info.type == "bin":
env["CARGO_BIN_EXE_" + dep_crate_info.output.basename] = dep_crate_info.output.short_path

# Update environment with user provided variables.
env.update(crate_info.rustc_env)
Comment on lines -395 to -403
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Pulled up into _rustc_compile_arguments


ctx.actions.run_shell(
command = command,
inputs = compile_inputs,
Expand All @@ -395,7 +460,7 @@ def rustc_compile_action(
files = dep_info.transitive_dylibs.to_list() + getattr(ctx.files, "data", []),
collect_data = True,
)

out_binary = False
if hasattr(ctx.attr, "out_binary"):
out_binary = getattr(ctx.attr, "out_binary")
Expand Down