blob: 2b793543995ffb4dbf731ac06813d6c3a577e233 [file] [log] [blame] [edit]
# Copyright lowRISC contributors.
# Licensed under the Apache License, Version 2.0, see LICENSE for details.
# SPDX-License-Identifier: Apache-2.0
load("@python3//:defs.bzl", "interpreter")
load("@ot_python_deps//:requirements.bzl", "all_requirements")
def _make_pythonpath(rctx):
# Create a PYTHONPATH with all the pip deps from requirements.txt
directories = [
rctx.path(Label(pip_req + ":BUILD.bazel")).dirname
for pip_req in all_requirements
]
pythonpath = ":".join([str(directory) for directory in directories])
return pythonpath
def _bitstreams_repo_impl(rctx):
# First, check if an existing pre-built bitstream cache repo exists, and if
# so, use it instead of building one.
cache_path = rctx.os.environ.get(
"BAZEL_BITSTREAMS_CACHE",
rctx.attr.cache,
)
result = rctx.execute(
[
rctx.path(rctx.attr.python_interpreter),
rctx.attr._cache_manager,
"--build-file=BUILD.bazel",
"--bucket-url={}".format(rctx.attr.bucket_url),
"--cache={}".format(cache_path),
"--refresh-time={}".format(rctx.attr.refresh_time),
],
environment = {
"PYTHONPATH": _make_pythonpath(rctx),
},
quiet = False,
)
if result.return_code != 0:
fail("Bitstream cache not initialized properly.")
# The bitstream repo should be evaluated with `bazel sync --configure` after
# every Git checkout. Once the cache is initialized, a typical invocation will
# find the latest cached artifacts and map them to Bazel targets.
#
# The `refresh_time` sets the interval at which the cache manager will
# check for new bitstreams.
#
# By default, the cache manager will configure the latest available bitstream
# as the default bitstream. It will refresh every 18 hours.
#
# The behavior of the cache manager can be controlled via the BITSTREAM
# environment variable. The environment variable can be any command line
# arguments accepted by the cache manager script.
#
# For example, to force a refresh of the cache:
# BITSTREAM=--refresh bazel build @bitstreams//...
#
# To use an exact bitstream in a test:
# BITSTREAM=3732655dbd225b5c1ae94a79b54cc9dc8cd8e391 bazel test <label>
#
# You can use any valid git commit identifier to select a bitstream:
# BITSTREAM=HEAD~1 bazel test <label>
#
# If you ask for a bitstream that does not exist in the GCP bucket, the
# next oldest bitstream will be chosen.
bitstreams_repo = repository_rule(
implementation = _bitstreams_repo_impl,
attrs = {
"bucket_url": attr.string(
doc = "Location of the GCP bitstream bucket.",
default = "https://storage.googleapis.com/opentitan-bitstreams/",
),
"cache": attr.string(
doc = "Location of bitstreams cache.",
default = "~/.cache/opentitan-bitstreams",
),
"refresh_time": attr.int(
doc = "How often to check for new bitstreams (seconds).",
default = 18 * 3600, # Refresh every 18h
),
"python_interpreter": attr.label(
default = interpreter,
allow_single_file = True,
doc = "Python interpreter to use.",
),
"_cache_manager": attr.label(
default = Label("//rules/scripts:bitstreams_workspace.py"),
allow_files = True,
),
},
environ = ["BAZEL_BITSTREAMS_CACHE", "BITSTREAM"],
# This rule depends on the Git repository, but there's no ergonomic way to
# encode the dependency in Bazel. Instead, indicate that the rule depends on
# something outside of Bazel's dependency graph and rely on the user calling
# `bazel sync --configure` when checking out new revisions. For historical
# context, see <https://github.com/lowRISC/opentitan/issues/16832>.
configure = True,
)