blob: 5204758141a1b087b21a50fd771d96efca05444b [file]
# Copyright 2026 The Fuchsia Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
"""Defines the ffx_apply_version rule for applying version info to ffx binaries.
This rule solves the problem that ffx, being the largest binary in the
build, takes a long time to link. It is desirable to minimize causes of cache
invalidations for builds of this binary, so as to save build time. One of the
causes of invalidations is changes in repository version information, that
will occur for every patch in CI/CQ, even if no source files for ffx or its
dependencies change. Applying the version post-link avoids these costs, as it
is cheap compared to re-linking the binary.
This rule works with both stripped and unstripped binaries as input, but will
always produce a stripped binary. The build-id directory entry for the stripped
binary is not produced, if that's needed, it should be produced in a separate
action, and this rule used with the resultant stripped binary.
"""
load("@rules_cc//cc:find_cc_toolchain.bzl", "CC_TOOLCHAIN_ATTRS", "find_cc_toolchain", "use_cc_toolchain")
def _ffx_apply_version_impl(ctx):
cc_toolchain = find_cc_toolchain(ctx)
unversioned = ctx.file.unversioned_binary
versioned = ctx.actions.declare_file(ctx.attr.name)
args = ctx.actions.args()
# -x applies a "strip" on the output. Strip is currently performed after the link
# step in the normal toolchain rules, and uses this same flag on most platforms.
args.add("-x")
args.add("--update-section=.ffx_version=%s" % ctx.file._version_info.path)
args.add("--update-section=.ffx_build=%s" % ctx.file._build_version.path)
args.add(unversioned)
args.add(versioned)
ctx.actions.run(
executable = cc_toolchain.objcopy_executable,
arguments = [args],
inputs = [unversioned, ctx.file._version_info, ctx.file._build_version],
outputs = [versioned],
tools = cc_toolchain.all_files,
mnemonic = "FfxApplyVersion",
progress_message = "Applying version to %s" % ctx.label,
)
return [
DefaultInfo(files = depset([versioned]), executable = versioned),
]
ffx_apply_version = rule(
implementation = _ffx_apply_version_impl,
toolchains = use_cc_toolchain(),
attrs = {
"unversioned_binary": attr.label(
doc = "Unversioned binary",
mandatory = True,
allow_single_file = True,
),
"_version_info": attr.label(
doc = "Version info binary file",
default = "//src/developer/ffx/lib/version/build:version_info.bin",
allow_single_file = True,
),
"_build_version": attr.label(
doc = "Build version binary file",
default = "//src/developer/ffx/lib/version/build:build_version.bin",
allow_single_file = True,
),
} | CC_TOOLCHAIN_ATTRS, # Needed by find_cc_toolchain
executable = True,
)