diff --git a/misc/bazel/rust.bzl b/misc/bazel/rust.bzl index 97afee4ba1c1..7f83f09bc085 100644 --- a/misc/bazel/rust.bzl +++ b/misc/bazel/rust.bzl @@ -1,17 +1,44 @@ load("@rules_rust//rust:defs.bzl", "rust_binary") load("@semmle_code//buildutils-internal:glibc_symbols_check.bzl", "glibc_symbols_check") load("@semmle_code//buildutils-internal:lipo.bzl", "universal_binary") +load("//misc/bazel:transitions.bzl", "forward_binary_from_transition", "get_transition_attrs") + +def _full_lto_transition_impl(_settings, _attr): + return {"@rules_rust//rust/settings:lto": "fat"} + +_full_lto_transition = transition( + implementation = _full_lto_transition_impl, + inputs = [], + outputs = ["@rules_rust//rust/settings:lto"], +) + +_full_lto_binary = rule( + implementation = forward_binary_from_transition, + attrs = get_transition_attrs(_full_lto_transition), +) def codeql_rust_binary( name, + full_lto = False, target_compatible_with = None, visibility = None, symbols_test = True, **kwargs): rust_label_name = "single_arch/" + name + binary_dep = ":" + rust_label_name + if full_lto: + # rustc must consume the LLVM bitcode because the C++ linker may use an + # incompatible LLVM version. + kwargs["experimental_use_cc_common_link"] = 0 + lto_label_name = "full_lto/" + name + _full_lto_binary( + name = lto_label_name, + dep = binary_dep, + ) + binary_dep = ":" + lto_label_name universal_binary( name = name, - dep = ":" + rust_label_name, + dep = binary_dep, target_compatible_with = target_compatible_with, visibility = visibility, ) diff --git a/misc/bazel/transitions.bzl b/misc/bazel/transitions.bzl new file mode 100644 index 000000000000..bc94ccdf4a03 --- /dev/null +++ b/misc/bazel/transitions.bzl @@ -0,0 +1,47 @@ +load("@bazel_skylib//lib:paths.bzl", "paths") + +def forward_binary_from_transition(ctx): + binary = ctx.attr.dep[0] + default_info = binary[DefaultInfo] + original_executable = default_info.files_to_run.executable + if not original_executable: + fail("Cannot transition a target that is not executable") + + (_, extension) = paths.split_extension(original_executable.basename) + new_executable = ctx.actions.declare_file(ctx.label.name + extension) + inputs = [original_executable] + command = "cp %s %s" % (original_executable.path, new_executable.path) + + providers = [] + if OutputGroupInfo in binary: + pdb_file = getattr(binary[OutputGroupInfo], "pdb_file", None) + if pdb_file: + (pdb_file,) = pdb_file.to_list() + linked_pdb_file = ctx.actions.declare_file(ctx.label.name + ".pdb") + ctx.actions.symlink(target_file = pdb_file, output = linked_pdb_file) + inputs.append(linked_pdb_file) + providers.append(binary[OutputGroupInfo]) + + ctx.actions.run_shell( + inputs = inputs, + outputs = [new_executable], + command = command, + ) + files = depset(direct = [new_executable]) + runfiles = default_info.default_runfiles.merge(ctx.runfiles([new_executable])) + providers.append( + DefaultInfo( + files = files, + runfiles = runfiles, + executable = new_executable, + ), + ) + return providers + +def get_transition_attrs(transition_rule): + return { + "_allowlist_function_transition": attr.label( + default = "@bazel_tools//tools/allowlists/function_transition_allowlist", + ), + "dep": attr.label(mandatory = True, cfg = transition_rule), + } diff --git a/rust/extractor/BUILD.bazel b/rust/extractor/BUILD.bazel index 52b551f6335d..d3ae10fe39e8 100644 --- a/rust/extractor/BUILD.bazel +++ b/rust/extractor/BUILD.bazel @@ -11,6 +11,7 @@ codeql_rust_binary( "src/qltest_cargo.mustache", "src/nightly-toolchain/rust-toolchain.toml", ], + full_lto = True, proc_macro_deps = all_crate_deps( proc_macro = True, ) + [