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

toolchain: Add config settings for debug info and opt level #1925

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
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
36 changes: 35 additions & 1 deletion rust/settings/BUILD.bazel
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
load("@bazel_skylib//:bzl_library.bzl", "bzl_library")
load("@bazel_skylib//rules:common_settings.bzl", "bool_flag", "string_flag")
load("@bazel_skylib//rules:common_settings.bzl", "bool_flag", "string_flag", "string_list_flag")

package(default_visibility = ["//visibility:public"])

Expand Down Expand Up @@ -48,3 +48,37 @@ bzl_library(
name = "bzl_lib",
srcs = glob(["**/*.bzl"]),
)

# Specifies the optimization level, provided to rustc in the command-line
# argument `--codegen=opt-level=x`.
#
# If no arguments are specified, use the default values from
# //rust/toolchain.bzl.
#
# If one argument is specified, use that value for all compilation modes (dbg,
# fastbuild, and opt).
#
# If three arguments are specified (separated by commas on the Bazel command
# line), use each value in sequence for each compilation mode (dbg, fastbuild,
# and opt).
string_list_flag(
name = "opt_level",
build_setting_default = [],
)

# Specifies the optimization level (provided to rustc in the command-line
# argument `--codegen=debuginfo=x`)
#
# If no arguments are specified, use the default values from
# //rust/toolchain.bzl.
#
# If one argument is specified, use that value for all compilation modes (dbg,
# fastbuild, and opt).
#
# If three arguments are specified (separated by commas on the Bazel command
# line), use each value in sequence for each compilation mode (dbg, fastbuild,
# and opt).
string_list_flag(
name = "debug_info",
build_setting_default = [],
)
53 changes: 48 additions & 5 deletions rust/toolchain.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -428,12 +428,49 @@ def _rust_toolchain_impl(ctx):
list: A list containing the target's toolchain Provider info
"""
compilation_mode_opts = {}
for k, v in ctx.attr.opt_level.items():
if not k in ctx.attr.debug_info:

opt_level = ctx.attr.opt_level
opt_level_override = ctx.attr._opt_level_cmdline[BuildSettingInfo].value
if opt_level_override:
if len(opt_level_override) == 1:
opt_level = {
"dbg": opt_level_override[0],
"fastbuild": opt_level_override[0],
"opt": opt_level_override[0],
}
elif len(opt_level_override) == 3:
opt_level = {
"dbg": opt_level_override[0],
"fastbuild": opt_level_override[1],
"opt": opt_level_override[2],
}
else:
fail("Wrong number of elements in //rust/settings:opt_level")

debug_info = ctx.attr.debug_info
debug_info_override = ctx.attr._debug_info_cmdline[BuildSettingInfo].value
if debug_info_override:
if len(debug_info_override) == 1:
debug_info = {
"dbg": debug_info_override[0],
"fastbuild": debug_info_override[0],
"opt": debug_info_override[0],
}
elif len(debug_info_override) == 3:
debug_info = {
"dbg": debug_info_override[0],
"fastbuild": debug_info_override[1],
"opt": debug_info_override[2],
}
else:
fail("Wrong number of elements in //rust/settings:debug_info")

for k, v in opt_level.items():
if not k in debug_info:
fail("Compilation mode {} is not defined in debug_info but is defined opt_level".format(k))
compilation_mode_opts[k] = struct(debug_info = ctx.attr.debug_info[k], opt_level = v)
for k, v in ctx.attr.debug_info.items():
if not k in ctx.attr.opt_level:
compilation_mode_opts[k] = struct(debug_info = debug_info[k], opt_level = v)
for k, v in debug_info.items():
if not k in opt_level:
fail("Compilation mode {} is not defined in opt_level but is defined debug_info".format(k))

rename_first_party_crates = ctx.attr._rename_first_party_crates[BuildSettingInfo].value
Expand Down Expand Up @@ -733,6 +770,12 @@ rust_toolchain = rule(
"_cc_toolchain": attr.label(
default = Label("@bazel_tools//tools/cpp:current_cc_toolchain"),
),
"_debug_info_cmdline": attr.label(
default = Label("//rust/settings:debug_info"),
),
"_opt_level_cmdline": attr.label(
default = Label("//rust/settings:opt_level"),
),
"_pipelined_compilation": attr.label(
default = Label("//rust/settings:pipelined_compilation"),
),
Expand Down
5 changes: 5 additions & 0 deletions test/unit/rustc_opt_level/BUILD.bazel
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
load(":rustc_opt_level_test.bzl", "rustc_opt_level_test_suite")

rustc_opt_level_test_suite(
name = "rustc_opt_level_test_suite",
)
1 change: 1 addition & 0 deletions test/unit/rustc_opt_level/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
pub fn call() {}
228 changes: 228 additions & 0 deletions test/unit/rustc_opt_level/rustc_opt_level_test.bzl
Original file line number Diff line number Diff line change
@@ -0,0 +1,228 @@
"""Unit test to verify rustc optimization and debug flags"""

load("@bazel_skylib//lib:unittest.bzl", "analysistest", "asserts")
load("//rust:defs.bzl", "rust_library")
load("//test/unit:common.bzl", "assert_argv_contains")

def _rustc_opt_level_test(ctx):
env = analysistest.begin(ctx)
target = analysistest.target_under_test(env)

action = target.actions[0]
asserts.equals(env, "Rustc", action.mnemonic)

assert_argv_contains(
env = env,
action = action,
flag = "--codegen=debuginfo=" + ctx.attr._expect_debuginfo,
)

assert_argv_contains(
env = env,
action = action,
flag = "--codegen=opt-level=" + ctx.attr._expect_opt_level,
)

return analysistest.end(env)

#
# Test cases verifying the default behavior of the debug info and opt level
# flags
#

rustc_opt_level_default_dbg_test = analysistest.make(
_rustc_opt_level_test,
attrs = {
"_expect_debuginfo": attr.string(default = "2"),
"_expect_opt_level": attr.string(default = "0"),
},
config_settings = {
"//command_line_option:compilation_mode": "dbg",
},
)

rustc_opt_level_default_fastbuild_test = analysistest.make(
_rustc_opt_level_test,
attrs = {
"_expect_debuginfo": attr.string(default = "0"),
"_expect_opt_level": attr.string(default = "0"),
},
config_settings = {
"//command_line_option:compilation_mode": "fastbuild",
},
)

rustc_opt_level_default_opt_test = analysistest.make(
_rustc_opt_level_test,
attrs = {
"_expect_debuginfo": attr.string(default = "0"),
"_expect_opt_level": attr.string(default = "3"),
},
config_settings = {
"//command_line_option:compilation_mode": "opt",
},
)

#
# Tests verifying that a single config setting will change all of the debug
# info and opt level (for each compilation mode)
#

rustc_opt_level_override_single_dbg_test = analysistest.make(
_rustc_opt_level_test,
attrs = {
"_expect_debuginfo": attr.string(default = "1"),
"_expect_opt_level": attr.string(default = "s"),
},
config_settings = {
"//command_line_option:compilation_mode": "dbg",
"@//rust/settings:debug_info": ["1"],
"@//rust/settings:opt_level": ["s"],
},
)

rustc_opt_level_override_single_fastbuild_test = analysistest.make(
_rustc_opt_level_test,
attrs = {
"_expect_debuginfo": attr.string(default = "1"),
"_expect_opt_level": attr.string(default = "s"),
},
config_settings = {
"//command_line_option:compilation_mode": "fastbuild",
"@//rust/settings:debug_info": ["1"],
"@//rust/settings:opt_level": ["s"],
},
)

rustc_opt_level_override_single_opt_test = analysistest.make(
_rustc_opt_level_test,
attrs = {
"_expect_debuginfo": attr.string(default = "1"),
"_expect_opt_level": attr.string(default = "s"),
},
config_settings = {
"//command_line_option:compilation_mode": "opt",
"@//rust/settings:debug_info": ["1"],
"@//rust/settings:opt_level": ["s"],
},
)

#
# Tests verifying that a multiple config settings will change each of the debug
# info and opt level (for each compilation mode)
#

rustc_opt_level_override_multi_dbg_test = analysistest.make(
_rustc_opt_level_test,
attrs = {
"_expect_debuginfo": attr.string(default = "2"),
"_expect_opt_level": attr.string(default = "0"),
},
config_settings = {
"//command_line_option:compilation_mode": "dbg",
"@//rust/settings:debug_info": ["2", "1", "1"],
"@//rust/settings:opt_level": ["0", "1", "s"],
},
)

rustc_opt_level_override_multi_fastbuild_test = analysistest.make(
_rustc_opt_level_test,
attrs = {
"_expect_debuginfo": attr.string(default = "1"),
"_expect_opt_level": attr.string(default = "1"),
},
config_settings = {
"//command_line_option:compilation_mode": "fastbuild",
"@//rust/settings:debug_info": ["2", "1", "1"],
"@//rust/settings:opt_level": ["0", "1", "s"],
},
)

rustc_opt_level_override_multi_opt_test = analysistest.make(
_rustc_opt_level_test,
attrs = {
"_expect_debuginfo": attr.string(default = "1"),
"_expect_opt_level": attr.string(default = "s"),
},
config_settings = {
"//command_line_option:compilation_mode": "opt",
"@//rust/settings:debug_info": ["2", "1", "1"],
"@//rust/settings:opt_level": ["0", "1", "s"],
},
)

def _define_test_targets():
rust_library(
name = "lib",
srcs = ["lib.rs"],
edition = "2018",
)

def rustc_opt_level_test_suite(name):
"""Entry-point macro called from the BUILD file.

Args:
name (str): Name of the macro.
"""

_define_test_targets()

rustc_opt_level_default_dbg_test(
name = "rustc_opt_level_default_dbg_test",
target_under_test = ":lib",
)

rustc_opt_level_default_fastbuild_test(
name = "rustc_opt_level_default_fastbuild_test",
target_under_test = ":lib",
)

rustc_opt_level_default_opt_test(
name = "rustc_opt_level_default_opt_test",
target_under_test = ":lib",
)

rustc_opt_level_override_single_dbg_test(
name = "rustc_opt_level_override_single_dbg_test",
target_under_test = ":lib",
)

rustc_opt_level_override_single_fastbuild_test(
name = "rustc_opt_level_override_single_fastbuild_test",
target_under_test = ":lib",
)

rustc_opt_level_override_single_opt_test(
name = "rustc_opt_level_override_single_opt_test",
target_under_test = ":lib",
)

rustc_opt_level_override_multi_dbg_test(
name = "rustc_opt_level_override_multi_dbg_test",
target_under_test = ":lib",
)

rustc_opt_level_override_multi_fastbuild_test(
name = "rustc_opt_level_override_multi_fastbuild_test",
target_under_test = ":lib",
)

rustc_opt_level_override_multi_opt_test(
name = "rustc_opt_level_override_multi_opt_test",
target_under_test = ":lib",
)

native.test_suite(
name = name,
tests = [
":rustc_opt_level_default_dbg_test",
":rustc_opt_level_default_fastbuild_test",
":rustc_opt_level_default_opt_test",
":rustc_opt_level_override_single_dbg_test",
":rustc_opt_level_override_single_fastbuild_test",
":rustc_opt_level_override_single_opt_test",
":rustc_opt_level_override_multi_dbg_test",
":rustc_opt_level_override_multi_fastbuild_test",
":rustc_opt_level_override_multi_opt_test",
],
)