blob: b7fe8ba085804b2c96b800f836d299c1b0f55a90 [file] [log] [blame] [edit]
# Copyright 2024 The ChromiumOS Authors
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
"""Rules for creating hermetic C++ binaries"""
load(
"//bazel/module_extensions/toolchains/hermetic_launcher:hermetic_launcher.bzl",
"create_hermetic_launcher_nontest",
"create_hermetic_launcher_test",
)
visibility("public")
# https://bazel.build/reference/be/common-definitions#common-attributes
_COMMON_BUILD_ARGS = [
"compatible_with",
"deprecation",
"distribs",
"exec_compatible_with",
"exec_properties",
"features",
"restricted_to",
"tags",
"target_compatible_with",
"testonly",
"toolchains",
"visibility",
]
# https://bazel.build/reference/be/common-definitions#common-attributes-binaries
_COMMON_BIN_ARGS = [
"args",
"env",
"output_licenses",
]
# https://bazel.build/reference/be/common-definitions#common-attributes-tests
_COMMON_TEST_ARGS = [
"args",
"env",
"env_inherit",
"size",
"timeout",
"flaky",
"shard_count",
"local",
]
def _hermetic_launcher(wrapper_rule):
"""Generates a macro that wraps a rule to ensure it runs hermetically.
Args:
wrapper_rule: rule: The rule to wrap (eg. cc_binary).
Returns:
A macro wrapping the rule with a hermetic launcher.
"""
def wrapper(name, visibility = None, features = [], hermetic_launcher = True, **kwargs):
# Shared libraries don't need a launcher.
if kwargs.get("linkshared", False) or not hermetic_launcher:
# buildifier: disable=native-cc
native.cc_binary(
name = name,
visibility = visibility,
features = features,
**kwargs
)
else:
# The hard part here is determining which kwargs should go to the
# cc_binary rule, which should go to the launcher, and which should go
# to both.
wrapper_args = {}
inner_args = {}
for k, v in kwargs.items():
if k in _COMMON_BUILD_ARGS or k in _COMMON_BIN_ARGS:
# Attributes such as testonly are relevant for both the inner
# and outer rules.
wrapper_args[k] = v
inner_args[k] = v
elif k in _COMMON_TEST_ARGS:
# If this is a non-test rule, this allows bazel itself to handle
# the error.
wrapper_args[k] = v
else:
inner_args[k] = v
real_name = "_%s_real" % name
# buildifier: disable=native-cc
native.cc_binary(
name = real_name,
visibility = ["//visibility:private"],
features = features,
**inner_args
)
wrapper_rule(
name = name,
bin = real_name,
enable = "@@//bazel/module_extensions/toolchains/cc:use_hermetic_launcher",
visibility = visibility,
**wrapper_args
)
return wrapper
cc_binary = _hermetic_launcher(create_hermetic_launcher_nontest)
cc_test = _hermetic_launcher(create_hermetic_launcher_test)