Skip to content

Commit

Permalink
Make lto toolchain options public and don't link proc-macros with LTO
Browse files Browse the repository at this point in the history
Proc-macro crates can not be linked with lto and we should not emit bitcode either.
This fixes bazelbuild#3143
  • Loading branch information
havasd committed Dec 31, 2024
1 parent d3b890d commit 07dce3a
Show file tree
Hide file tree
Showing 3 changed files with 34 additions and 11 deletions.
10 changes: 6 additions & 4 deletions rust/private/lto.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ def _determine_lto_object_format(ctx, toolchain, crate_info):
if is_exec_configuration(ctx):
return "only_object"

mode = toolchain._lto.mode
mode = toolchain.lto.mode

if mode in ["off", "unspecified"]:
return "only_object"
Expand All @@ -75,9 +75,10 @@ def _determine_lto_object_format(ctx, toolchain, crate_info):
# If we're building an 'rlib' and LTO is enabled, then we can skip
# generating object files entirely.
return "only_bitcode"
elif crate_info.type == "dylib":
elif crate_info.type in ["dylib", "proc-macro"]:
# If we're a dylib and we're running LTO, then only emit object code
# because 'rustc' doesn't currently support LTO with dylibs.
# proc-macros do not benefit from LTO, and cannot be dynamically linked with LTO.
return "only_object"
else:
return "object_and_bitcode"
Expand All @@ -93,7 +94,7 @@ def construct_lto_arguments(ctx, toolchain, crate_info):
Returns:
list: A list of strings that are valid flags for 'rustc'.
"""
mode = toolchain._lto.mode
mode = toolchain.lto.mode

# The user is handling LTO on their own, don't add any arguments.
if mode == "manual":
Expand All @@ -102,7 +103,8 @@ def construct_lto_arguments(ctx, toolchain, crate_info):
format = _determine_lto_object_format(ctx, toolchain, crate_info)
args = []

if mode in ["thin", "fat", "off"] and not is_exec_configuration(ctx):
# proc-macros do not benefit from LTO, and cannot be dynamically linked with LTO.
if mode in ["thin", "fat", "off"] and not is_exec_configuration(ctx) and crate_info.type != "proc-macro":
args.append("lto={}".format(mode))

if format == "object_and_bitcode":
Expand Down
13 changes: 7 additions & 6 deletions rust/toolchain.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -521,7 +521,7 @@ def _rust_toolchain_impl(ctx):
third_party_dir = ctx.attr._third_party_dir[BuildSettingInfo].value
pipelined_compilation = ctx.attr._pipelined_compilation[BuildSettingInfo].value
no_std = ctx.attr._no_std[BuildSettingInfo].value
lto = ctx.attr._lto[RustLtoInfo]
lto = ctx.attr.lto[RustLtoInfo]

experimental_use_global_allocator = ctx.attr._experimental_use_global_allocator[BuildSettingInfo].value
if _experimental_use_cc_common_link(ctx):
Expand Down Expand Up @@ -672,6 +672,7 @@ def _rust_toolchain_impl(ctx):
nostd_and_global_allocator_cc_info = _make_libstd_and_allocator_ccinfo(ctx, rust_std, ctx.attr.global_allocator_library, "no_std_with_alloc"),
llvm_cov = ctx.file.llvm_cov,
llvm_profdata = ctx.file.llvm_profdata,
lto = lto,
make_variables = make_variable_info,
rust_doc = sysroot.rustdoc,
rust_std = sysroot.rust_std,
Expand Down Expand Up @@ -705,7 +706,6 @@ def _rust_toolchain_impl(ctx):
_toolchain_generated_sysroot = ctx.attr._toolchain_generated_sysroot[BuildSettingInfo].value,
_incompatible_do_not_include_data_in_compile_data = ctx.attr._incompatible_do_not_include_data_in_compile_data[IncompatibleFlagInfo].enabled,
_no_std = no_std,
_lto = lto,
_codegen_units = ctx.attr._codegen_units[BuildSettingInfo].value,
)
return [
Expand Down Expand Up @@ -808,6 +808,11 @@ rust_toolchain = rule(
doc = "LLVM tools that are shipped with the Rust toolchain.",
allow_files = True,
),
"lto": attr.label(
providers = [RustLtoInfo],
default = Label("//rust/settings:lto"),
doc = "Label to an LTO setting whether which can enable custom LTO settings",
),
"opt_level": attr.string_dict(
doc = "Rustc optimization levels.",
default = {
Expand Down Expand Up @@ -897,10 +902,6 @@ rust_toolchain = rule(
default = Label("//rust/settings:incompatible_do_not_include_data_in_compile_data"),
doc = "Label to a boolean build setting that controls whether to include data files in compile_data.",
),
"_lto": attr.label(
providers = [RustLtoInfo],
default = Label("//rust/settings:lto"),
),
"_no_std": attr.label(
default = Label("//rust/settings:no_std"),
),
Expand Down
22 changes: 21 additions & 1 deletion test/unit/lto/lto_test_suite.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

load("@bazel_skylib//lib:unittest.bzl", "analysistest")
load("@bazel_skylib//rules:write_file.bzl", "write_file")
load("//rust:defs.bzl", "rust_library")
load("//rust:defs.bzl", "rust_library", "rust_proc_macro")
load(
"//test/unit:common.bzl",
"assert_action_mnemonic",
Expand Down Expand Up @@ -78,6 +78,14 @@ _lto_level_fat_test = analysistest.make(
config_settings = {str(Label("//rust/settings:lto")): "fat"},
)

def _lto_proc_macro(ctx):
return _lto_test_impl(ctx, None, "no", False)

_lto_proc_macro_test = analysistest.make(
_lto_proc_macro,
config_settings = {str(Label("//rust/settings:lto")): "thin"},
)

def lto_test_suite(name):
"""Entry-point macro called from the BUILD file.
Expand All @@ -100,6 +108,12 @@ def lto_test_suite(name):
edition = "2021",
)

rust_proc_macro(
name = "proc_macro",
srcs = [":lib.rs"],
edition = "2021",
)

_lto_level_default_test(
name = "lto_level_default_test",
target_under_test = ":lib",
Expand All @@ -125,6 +139,11 @@ def lto_test_suite(name):
target_under_test = ":lib",
)

_lto_proc_macro_test(
name = "lto_proc_macro_test",
target_under_test = ":proc_macro",
)

native.test_suite(
name = name,
tests = [
Expand All @@ -133,5 +152,6 @@ def lto_test_suite(name):
":lto_level_off_test",
":lto_level_thin_test",
":lto_level_fat_test",
":lto_proc_macro_test",
],
)

0 comments on commit 07dce3a

Please sign in to comment.