blob: b5bde5f65ff257fa311ca43b8dee328f56c217aa [file]
"""Macro to build the files for a release and list where they are."""
load("//python/private:common_labels.bzl", "labels") # buildifier: disable=bzl-visibility
_FEATURES = "//command_line_option:features"
_RUSTC_FLAGS = "@rules_rust//rust/settings:extra_rustc_flags"
def _release_transition_impl(settings, attr):
features = []
rustc_flags = []
if attr.target_os == "linux":
# Rust links glibc dynamically, so the files would require at least
# the build machine's glibc version. Link it statically so they run on
# older distros too. Rust links musl statically for most CPUs, but not
# all, e.g. riscv64.
rustc_flags = ["-Ctarget-feature=+crt-static"]
if attr.target_libc != "musl":
# The gold linker can't link static glibc, so use bfd.
rustc_flags.append("-Clink-arg=-fuse-ld=bfd")
elif attr.target_os == "windows":
# Statically link the C runtime so that the VC++ redistributable isn't
# required.
features = ["static_link_msvcrt"]
rustc_flags = ["-Ctarget-feature=+crt-static"]
return {
"//command_line_option:compilation_mode": "opt",
# Only affects macOS. Without it, the minimum OS version is the build
# machine's SDK version.
"//command_line_option:macos_minimum_os": "11.0",
_FEATURES: settings[_FEATURES] + features,
_RUSTC_FLAGS: settings[_RUSTC_FLAGS] + rustc_flags,
}
_release_transition = transition(
implementation = _release_transition_impl,
inputs = [_FEATURES, _RUSTC_FLAGS],
outputs = [
"//command_line_option:compilation_mode",
"//command_line_option:macos_minimum_os",
_FEATURES,
_RUSTC_FLAGS,
],
)
def _release_files_impl(ctx):
manifest = ctx.actions.declare_file(ctx.label.name + ".txt")
ctx.actions.write(
output = manifest,
# End every line with "\n", including the last: `while read` loops skip
# an unterminated last line, and build.sh adds a line after the paths.
content = "".join([file.path + "\n" for file in ctx.files.srcs]),
)
return [DefaultInfo(files = depset([manifest] + ctx.files.srcs))]
_release_files = rule(
implementation = _release_files_impl,
attrs = {
"srcs": attr.label_list(
allow_files = True,
cfg = _release_transition,
doc = "The files to build and list.",
),
"target_libc": attr.string(
doc = "The libc that the files are built for. Set by the macro.",
),
"target_os": attr.string(
doc = "The OS that the files are built for. Set by the macro.",
),
},
)
def release_files(name, srcs, **kwargs):
"""Builds files for a release and writes their paths to `<name>.txt`.
The files are built for the target platform (`--platforms`), with release
settings for its OS and libc: optimized, and linked so that they run on
older OS versions than the build machine's, without extra runtime
libraries.
The paths, one per line, are relative to the execroot, e.g.
`bazel-out/k8-opt-ST-1234/bin/foo/foo`. Paths of generated files also
resolve from the workspace root through the `bazel-out` convenience
symlink. This lets scripts find the files without running `bazel cquery`,
which re-analyzes the build.
Args:
name: The target name.
srcs: The files to build and list.
**kwargs: Additional attributes for the rule.
"""
_release_files(
name = name,
srcs = srcs,
target_libc = select({
"//dev/platforms:musl": "musl",
"//conditions:default": "",
}),
target_os = select({
Label("@platforms//os:linux"): "linux",
labels.PLATFORMS_OS_WINDOWS: "windows",
"//conditions:default": "",
}),
**kwargs
)