blob: ffc4516af7b32f42e307ebe2ea2be21f09cf5561 [file] [log] [blame] [edit]
# Copyright 2023 The ChromiumOS Authors
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
_EMPTY_PORTAGE_BUILD = """
package_group(
name = "all_packages",
packages = [
"//...",
],
)
"""
def _write_portage_symlink(repo_ctx, out):
# Generate an @portage symlink in the workspace root for easy access.
args = [
"ln",
"-fs",
out,
"%s/@portage" % (repo_ctx.workspace_root),
]
st = repo_ctx.execute(args)
if st.return_code:
fail("Error running command %s:\n%s%s" % (args, st.stdout, st.stderr))
def _portage_impl(repo_ctx):
"""Repository rule to generate the board's bazel BUILD files."""
# Keep all the repo_ctx.path calls first to avoid expensive restarts
alchemist = repo_ctx.path(repo_ctx.attr.alchemist)
board = repo_ctx.read(repo_ctx.attr.board)
profile = repo_ctx.read(repo_ctx.attr.profile)
# Ensure the repo rule reruns when the digest changes.
repo_ctx.path(repo_ctx.attr.digest)
out = repo_ctx.path("")
# --source-dir needs the repo root, not just the `src` directory
root = repo_ctx.workspace_root.dirname
# If we don't have a BOARD defined, we need to clear out the repository
if board:
args = [
alchemist,
"--board",
board,
"--source-dir",
root,
]
if profile:
args += ["--profile", profile]
args += [
"generate-repo",
"--output-dir",
out,
"--output-repos-json",
repo_ctx.path("deps.json"),
]
st = repo_ctx.execute(args, quiet = False)
if st.return_code:
fail("Error running command %s" % (args,))
else:
# TODO: Consider running alchemist in this case as well. Then we don't
# need this special logic.
repo_ctx.file("deps.json", content = "{}")
repo_ctx.file(out.get_child("settings.bzl"), content = "BOARD = None")
repo_ctx.file(out.get_child("BUILD.bazel"), content = _EMPTY_PORTAGE_BUILD)
if repo_ctx.os.environ.get("ENABLE_PORTAGE_TAB_COMPLETION", "") == "1":
_write_portage_symlink(repo_ctx, out)
portage = repository_rule(
implementation = _portage_impl,
attrs = dict(
board = attr.label(allow_single_file = True),
profile = attr.label(allow_single_file = True),
digest = attr.label(
doc = "Used to trigger this rule to rerun when the overlay contents change",
allow_single_file = True,
),
alchemist = attr.label(allow_single_file = True),
),
environ = [
# This will generate an @portage symlink in the workspace_root. This
# makes it easy to find the generated BUILD files, and also allows
# tab completion to work correctly. It's guarded because it's possible
# to accidentally try and build from this repo by doing the following:
# bazel build //...
# Only enable this flag if you are aware of this edge case.
#
# Set this flag to 1 to enable the @portage symlink.
"ENABLE_PORTAGE_TAB_COMPLETION",
],
# Do not set this to true. It will force the evaluation to happen every
# bazel invocation for unknown reasons...
local = False,
)