Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,4 +21,4 @@ jobs:
steps:
- uses: actions/checkout@v4
- run: bazel build //...
- run: cd example && bazel test //...
- run: cd example && bazel test //... ${{ matrix.bazel_version == '7.x' && '--incompatible_use_plus_in_repo_names' || '' }}
129 changes: 99 additions & 30 deletions README.md

Large diffs are not rendered by default.

26 changes: 26 additions & 0 deletions example/MODULE.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ local_starlark_repository = use_repo_rule("//producer/repository_rules:local_sta

local_starlark_repository(
name = "std",
copy_files = {"@sha256.bzl//:sha256.star": "sha256/sha256.star"},
repo_file = "//producer:stdlib_repo/REPO.bazel",
)

Expand All @@ -29,6 +30,31 @@ local_starlark_repository(
repo_file = "//:third_party/stringutil/REPO.bazel",
)

local_starlark_repository(
name = "mathlib",
repo_file = "//:third_party/mathlib/REPO.bazel",
)

local_starlark_repository(
name = "templates",
repo_file = "//:third_party/templates/REPO.bazel",
)

local_starlark_repository(
name = "colors",
repo_file = "//:third_party/colors/REPO.bazel",
)

local_starlark_repository(
name = "units",
repo_file = "//:third_party/units/REPO.bazel",
)

local_starlark_repository(
name = "limits",
repo_file = "//:third_party/limits/REPO.bazel",
)

http_file = use_repo_rule("@bazel_tools//tools/build_defs/repo:http.bzl", "http_file")

http_file(
Expand Down
38 changes: 17 additions & 21 deletions example/consumer/rules/fake_package.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ load("@rules_runfiles_group//runfiles_group:lib.bzl", "lib")
load(
"@rules_runfiles_group//runfiles_group:providers.bzl",
"RunfilesGroupInfo",
"RunfilesGroupSelectionInfo",
"RunfilesGroupMetadataInfo",
"RunfilesGroupTransformInfo",
)

Expand All @@ -16,32 +16,28 @@ _FakePackageGroupsInfo = provider(
)

def _fake_package_aspect_impl(target, ctx):
# 1. Obtain RunfilesGroupInfo: from target, overridden by last aspect_hint.
rgi = None
if RunfilesGroupInfo in target:
rgi = target[RunfilesGroupInfo]
for hint in ctx.rule.attr.aspect_hints:
if RunfilesGroupInfo in hint:
rgi = hint[RunfilesGroupInfo]

if rgi == None:
# 1. Obtain RunfilesGroupInfo from the target.
if RunfilesGroupInfo not in target:
return []
rgi = target[RunfilesGroupInfo]

# 2. Apply all transforms from aspect_hints.
# 2. Accumulate metadata via dict merge (binary + all hints, last-wins per key).
metadata = None
if RunfilesGroupMetadataInfo in target:
metadata = target[RunfilesGroupMetadataInfo]
for hint in ctx.rule.attr.aspect_hints:
if RunfilesGroupTransformInfo in hint:
rgi = lib.transform_groups(rgi, hint[RunfilesGroupTransformInfo])
if RunfilesGroupMetadataInfo in hint:
metadata = lib.merge_metadata(metadata, hint[RunfilesGroupMetadataInfo])

# 3. Find the last selection from [target, ...aspect_hints].
selection = None
if RunfilesGroupSelectionInfo in target:
selection = target[RunfilesGroupSelectionInfo]
# 3. Apply all transforms (new signature: (rgi, metadata) -> struct).
for hint in ctx.rule.attr.aspect_hints:
if RunfilesGroupSelectionInfo in hint:
selection = hint[RunfilesGroupSelectionInfo]
if RunfilesGroupTransformInfo in hint:
result = lib.transform_groups(rgi, metadata, hint[RunfilesGroupTransformInfo])
rgi = result.runfiles_group_info
metadata = result.runfiles_group_metadata_info

# 4. Apply ordering.
ordered = lib.ordered_groups(rgi, selection)
# 4. Apply ordering by rank.
ordered = lib.ordered_groups(rgi, metadata)

return [_FakePackageGroupsInfo(ordered_groups = ordered)]

Expand Down
120 changes: 114 additions & 6 deletions example/producer/repository_rules/local_starlark_repository.bzl
Original file line number Diff line number Diff line change
@@ -1,13 +1,121 @@
def _local_starlark_repository_impl(rctx):
rctx.watch(rctx.attr.repo_file)
repo_root = rctx.path(rctx.attr.repo_file).dirname
rctx.watch(repo_root)
rctx.symlink(repo_root, ".")

simple_name = rctx.name.split("~")[-1].split("+")[-1]
main_module = rctx.attr.main_module

# Find all .star files under repo_root.
result = rctx.execute(
["find", str(repo_root), "-name", "*.star", "-type", "f"],
quiet = True,
)
star_files = [f for f in result.stdout.strip().split("\n") if f]

# packages: map from package path (relative to repo root, "" for root) to list of (filename, byte_size).
packages = {}
root_str = str(repo_root)
for abs_path in star_files:
rel = abs_path[len(root_str) + 1:]
idx = rel.rfind("/")
if idx < 0:
pkg = ""
filename = rel
else:
pkg = rel[:idx]
filename = rel[idx + 1:]
if pkg not in packages:
packages[pkg] = []
size = len(rctx.read(abs_path))
packages[pkg].append((filename, size))
dest = rel if pkg else filename
rctx.symlink(abs_path, dest)

# Copy external files.
for label, dest in rctx.attr.copy_files.items():
src_path = rctx.path(label)
size = len(rctx.read(src_path))
rctx.symlink(src_path, dest)
idx = dest.rfind("/")
if idx < 0:
pkg = ""
filename = dest
else:
pkg = dest[:idx]
filename = dest[idx + 1:]
if pkg not in packages:
packages[pkg] = []
packages[pkg].append((filename, size))

# Generate BUILD files.
sub_packages = sorted([pkg for pkg in packages if pkg != ""])

for pkg, files in packages.items():
total_weight = 0
for _, size in files:
total_weight += size
target_name = pkg.rsplit("/", 1)[-1] if pkg else simple_name
srcs = sorted([f for f, _ in files])
path = "{}/BUILD.bazel".format(pkg) if pkg else "BUILD.bazel"
_write_build_file(rctx, path, target_name, srcs, simple_name, total_weight, [], main_module)

# Root umbrella target: if there are sub-packages, ensure a root target exists that deps on them all.
root_deps = ["//" + pkg + ":" + pkg.rsplit("/", 1)[-1] for pkg in sub_packages]
if "" in packages:
root_files = packages[""]
total_weight = 0
for _, size in root_files:
total_weight += size
srcs = sorted([f for f, _ in root_files])
_write_build_file(rctx, "BUILD.bazel", simple_name, srcs, simple_name, total_weight, root_deps, main_module)
else:
_write_build_file(rctx, "BUILD.bazel", simple_name, [], simple_name, 0, root_deps, main_module)

rctx.file("REPO.bazel", "")

def _write_build_file(rctx, path, target_name, srcs, repository, weight, deps, main_module):
lines = []
lines.append('load("@{}//producer/rules:starlark_library.bzl", "starlark_library")'.format(main_module))
lines.append("")
lines.append("starlark_library(")
lines.append(' name = "{}",'.format(target_name))
if srcs:
if len(srcs) == 1:
lines.append(' srcs = ["{}"],'.format(srcs[0]))
else:
lines.append(" srcs = [")
for src in srcs:
lines.append(' "{}",'.format(src))
lines.append(" ],")
lines.append(' repository = "{}",'.format(repository))
if weight > 0:
lines.append(" runfiles_weight = {},".format(weight))
lines.append(' visibility = ["//visibility:public"],')
if deps:
if len(deps) == 1:
lines.append(' deps = ["{}"],'.format(deps[0]))
else:
lines.append(" deps = [")
for dep in sorted(deps):
lines.append(' "{}",'.format(dep))
lines.append(" ],")
lines.append(")")
lines.append("")
rctx.file(path, "\n".join(lines))

local_starlark_repository = repository_rule(
implementation = _local_starlark_repository_impl,
attrs = {"repo_file": attr.label(
mandatory = True,
doc = "REPO.bazel of the local starlark repository",
)},
attrs = {
"repo_file": attr.label(
mandatory = True,
doc = "REPO.bazel of the local starlark repository. .star files are discovered relative to this file's directory.",
),
"copy_files": attr.label_keyed_string_dict(
doc = "Map of source labels to destination paths within the repo. Use for files that live outside the source directory (e.g., '@sha256.bzl//:sha256.star': 'sha256/sha256.star').",
),
"main_module": attr.string(
default = "rules_runfiles_group_example",
doc = "Name of the main module that provides starlark_library.",
),
},
)
24 changes: 20 additions & 4 deletions example/producer/rules/skip_interpreter.bzl
Original file line number Diff line number Diff line change
@@ -1,12 +1,28 @@
load("@rules_runfiles_group//runfiles_group:providers.bzl", "RunfilesGroupInfo", "RunfilesGroupTransformInfo")
load("@rules_runfiles_group//runfiles_group:lib.bzl", "lib")
load(
"@rules_runfiles_group//runfiles_group:providers.bzl",
"RunfilesGroupInfo",
"RunfilesGroupMetadataInfo",
"RunfilesGroupTransformInfo",
)

def _skip_interpreter_transform(runfiles_group_info):
def _skip_interpreter_transform(runfiles_group_info, runfiles_group_metadata_info):
new_groups = {}
for group_name in dir(runfiles_group_info):
for group_name in lib.group_names(runfiles_group_info):
if group_name == "interpreter":
continue
new_groups[group_name] = getattr(runfiles_group_info, group_name)
return RunfilesGroupInfo(**new_groups)

new_metadata = None
if runfiles_group_metadata_info != None:
new_meta_groups = {k: v for k, v in runfiles_group_metadata_info.groups.items() if k != "interpreter"}
if new_meta_groups:
new_metadata = RunfilesGroupMetadataInfo(groups = new_meta_groups)

return struct(
runfiles_group_info = RunfilesGroupInfo(**new_groups),
runfiles_group_metadata_info = new_metadata,
)

def _skip_interpreter_impl(ctx):
return [
Expand Down
Loading
Loading