diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index f79fa1d..c5147fc 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -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' || '' }} diff --git a/README.md b/README.md index fe40508..06799ab 100644 --- a/README.md +++ b/README.md @@ -1,34 +1,49 @@ # rules_runfiles_group -A Bazel module that enables `*_binary` rules to split their runfiles into named groups and packaging rules to consume those groups as ordered layers. When a binary rule supports `RunfilesGroupInfo`, packaging rules can produce more efficient artifacts: for example, container images with shared base layers or archive formats that separate interpreter, standard library, and application code. +A Bazel module that enables `*_binary` rules to split their runfiles into named groups and packaging rules to consume those groups as (partially) ordered layers. When a binary rule supports `RunfilesGroupInfo`, packaging rules can produce more efficient artifacts: for example, container images with shared base layers or archive formats that separate interpreter, standard library, and application code. ```starlark # BUILD.bazel load("@rules_foo//foo:defs.bzl", "foo_binary") -load("@rules_acme_pkg//pkg:defs.bzl", "pkg_tar") +load("@rules_acme_pkg//pkg:defs.bzl", "pkg_creator") foo_binary( name = "app", # This binary produces RunfilesGroupInfo with groups like - # "interpreter", "stdlib", "app_code", "third_party". + # "interpreter", "stdlib", "third_party", "app_code" + # --- + # it could also produce one group per third-party dep: + # "interpreter", "stdlib", "libfoo", "libbar", "libbaz", "app_code" ... ) -pkg_tar( +pkg_creator( name = "app_tar", binary = ":app", - # The packaging rule reads RunfilesGroupInfo, applies ordering, - # and creates one tar file per group. + # The packaging rule reads RunfilesGroupInfo, + # optionally merges groups (see below), + # applies partial ordering, + # and creates one package per group. ) ``` ## Table of contents +- [Providers at a glance](#providers-at-a-glance) - [Guidance for users](#guidance-for-users) - [Guidance for *_binary rule authors](#guidance-for-binary-rule-authors) - [Guidance for package rule authors](#guidance-for-package-rule-authors) - [Compatibility](#compatibility) +## Providers at a glance + +| Provider | `*_binary` rule | `aspect_hints` | Required | Purpose | +|----------|:-:|:-:|:-:|---------| +| `DefaultInfo` | **must** return | — | yes | Defines the executable and runfiles tree. Used as fallback when `RunfilesGroupInfo` is missing or the consumer doesn't support it. | +| `RunfilesGroupInfo` | may return | — | no | Splits `DefaultInfo.default_runfiles.files` into named groups. | +| `RunfilesGroupMetadataInfo` | may return | may add | no | Per-group metadata (rank, do_not_merge, weight) controlling ordering and merge behavior. | +| `RunfilesGroupTransformInfo` | — | may add | no | Transforms groups and metadata (e.g., exclude a group, remap names). | + > **Full worked example:** The [`example/`](example/) directory contains a complete end-to-end demo. Look at [`example/producer/`](example/producer/) for `*_binary` rule implementation, [`example/consumer/`](example/consumer/) for packaging rule implementation, and [`example/src/`](example/src/) for user-facing `BUILD` files. ## Guidance for users @@ -39,7 +54,7 @@ You can package any `*_binary` rule. If the rule doesn't support `RunfilesGroupI ### Customizing group behavior with `aspect_hints` -Some rulesets offer `aspect_hints` targets as mixins that let you tweak how groups are merged or ordered. For example, a ruleset might provide a target that excludes the interpreter group (because it's already present in the base image): +Some rulesets offer `aspect_hints` targets as mixins that let you tweak how groups are transformed or what metadata is attached. For example, a ruleset might provide a target that excludes the interpreter group (because it's already present in the base image): ```starlark load("@rules_foo//foo:hints.bzl", "skip_interpreter") @@ -53,11 +68,11 @@ foo_binary( ) ``` -These mixins work by attaching `RunfilesGroupTransformInfo` or `RunfilesGroupSelectionInfo` providers that packaging rules pick up through aspects. You can combine multiple hints on the same target. +These mixins work by attaching `RunfilesGroupTransformInfo` or `RunfilesGroupMetadataInfo` providers that packaging rules pick up through aspects. You can combine multiple hints on the same target. ### Advanced: custom aspects -It's also possible to implement custom rules that apply aspects to binary targets to construct `RunfilesGroupInfo` yourself. You could do this to enforce organization-specific layering policies. See the [package rule authors](#for-package-rule-authors) section for the resolution protocol. +It's also possible to implement custom rules that apply aspects to binary targets to create your own `RunfilesGroupInfo`. You could do this to enforce organization-specific layering policies. See the [package rule authors](#guidance-for-package-rule-authors) section for the resolution protocol. --- @@ -65,15 +80,41 @@ It's also possible to implement custom rules that apply aspects to binary target ### When to implement -If splitting runfiles into groups is not a concern for your rule — for example, the binary is a single statically linked executable — you don't have to do anything. Packaging rules will fall back to `DefaultInfo.default_runfiles`. +If splitting runfiles into groups is not a concern for your rule — for example, the binary is a single statically linked executable — you don't have to do anything. Packaging rules will fall back to `DefaultInfo.default_runfiles.files`. If your binary does have meaningful groups (interpreter, standard library, first-party code, third-party dependencies, debug symbols, etc.), return `RunfilesGroupInfo` alongside `DefaultInfo` from your rule. -### Ordering with `RunfilesGroupSelectionInfo` +### Metadata with `RunfilesGroupMetadataInfo` + +Return `RunfilesGroupMetadataInfo` alongside `RunfilesGroupInfo` to declare per-group metadata that controls ordering, merge eligibility, and merge priority. + +Each group can have: + +| Field | Type | Default | Description | +|-------|------|---------|-------------| +| `rank` | int | 0 | Partial ordering key. Lower rank = earlier in the output. Groups at different ranks are never merged together. | +| `do_not_merge` | bool | False | If True, packaging rules must not merge this group with others. | +| `weight` | int >= 0 or None | None | Hint for merge priority. Lighter groups are merged first when reducing group count. If None, the packager may apply its own default. | -If ordering doesn't matter, you don't need to return `RunfilesGroupSelectionInfo`. Packaging rules will default to lexicographic ordering (or no ordering). +Groups not listed in the metadata dict get default values for all fields (the same applies if `RunfilesGroupMetadataInfo` is missing). -If you do return a selection, good ordering defaults put foundational or shared content first: +Use the `lib.group_metadata()` helper to create validated metadata entries: + +```starlark +load("@rules_runfiles_group//runfiles_group:lib.bzl", "lib") +load("@rules_runfiles_group//runfiles_group:providers.bzl", + "RunfilesGroupInfo", "RunfilesGroupMetadataInfo") + +providers.append(RunfilesGroupInfo(**groups)) +providers.append(RunfilesGroupMetadataInfo(groups = { + "interpreter": lib.group_metadata(rank = -2, do_not_merge = True), + "std": lib.group_metadata(rank = -1), + "app_code": lib.group_metadata(rank = 0, weight = 100), +})) +``` + +Good rank defaults put foundational or shared content at lower ranks (negative rank numbers are supported). Note that groups with no ranking will have the default rank `0`, so you are able to place important groups relative to that. +The following types of content should typically use a negative rank: 1. Interpreter / runtime 2. Standard library @@ -82,29 +123,31 @@ If you do return a selection, good ordering defaults put foundational or shared This ordering maximizes cache reuse in layered formats — base layers change less frequently than application code. +Within the same rank, the packager is free to order or merge groups as it sees fit. The partial ordering only guarantees that groups with lower rank appear before groups with higher rank. + ### Creating groups -There may be different preferences for splitting things into groups. A good way to support this is to create fine-grained groups in `*_library` rules and merge them in `*_binary` rules. Two recommended approaches: +There may be different preferences for splitting files into groups. A good way to support this is to create fine-grained groups in `*_library` rules (and optionally merge them in `*_binary` rules). Two recommended approaches: **Bottom-up propagation.** In every `*_library` rule, propagate groups from `deps` and add the current target's files to its own group. The `*_binary` rule collects all groups from deps, optionally merging them (e.g., by repository). **Aspect-based collection.** Apply an aspect to `deps` in the `*_binary` rule that walks the dependency graph and collects files into groups. This avoids modifying `*_library` rules but requires an aspect implementation. -> **There is no single best grouping.** Different users have different deployment targets. What works for one packaging ruleset or consumer may not work well for others. Prefer producing fine-grained groups by default and let users merge them via `aspect_hints` with `RunfilesGroupTransformInfo`. This way, you provide the raw material and users shape it to their needs. Consider also exposing information about group weights (e.g., file counts or byte sizes) so that packaging rules can implement custom weight-based merging strategies. See [Group count limits](#group-count-limits) below for details. +> **There is no single best grouping.** Different users have different deployment targets. What works for one packaging ruleset or consumer may not work well for others. Prefer producing fine-grained groups by default and let users merge them via `aspect_hints` with `RunfilesGroupTransformInfo`. This way, you provide the raw material and users shape it to their needs. Set `weight` on groups to help packaging rules make informed merge decisions. > [!CAUTION] > Merging groups by merging their `depset`s is cheap. Calling `.to_list()` on a depset is expensive and should be avoided during analysis. Build group hierarchies purely through `depset(transitive = [...])`. ### Group count limits -Packaging rules may enforce a maximum group count. For example, container image runtimes may limit the total number of layers an image can have. It can make sense to let users specify a maximum group count and merge groups when the limit is exceeded. +Packaging rules may enforce a maximum group count via `lib.merge_to_limit()`. For example, container image runtimes may limit the total number of layers an image can have. The merge algorithm respects `rank` (only merges within the same rank), `do_not_merge` (never merges protected groups), and `weight` (merges lightest groups first). -To decide which groups to merge, calculate the "weight" of each group. Two recommended approaches: +Useful weight hints may be language-specific. Good examples include: - **File count proxy.** Use an aspect to count the number of files in each group. This is cheap and works well in practice. - **Actual file sizes.** In a repository rule, inspect files of third-party repos and annotate `*_library` targets with the actual byte sizes they contribute to their group. -Groups with large weight should be left unmerged. They benefit most from being cached as separate entities. Lightweight groups should be merged first, as combining them has minimal impact on cache efficiency. +Groups with large weight are more likely to be left unmerged. They benefit most from being cached as separate entities. Lightweight groups are merged first, as combining them has minimal impact on cache efficiency. ### Testing your implementation @@ -139,33 +182,59 @@ runfiles_group_analysis_test( When resolving runfiles groups from a binary target, follow this well-defined order: -1. **Obtain `RunfilesGroupInfo`:** Extract it from the binary target if present. If any `aspect_hints` target on the binary also provides `RunfilesGroupInfo`, use the last one (it overrides the binary's). +1. **Obtain `RunfilesGroupInfo`:** Extract it from the binary target if present. Note: in case `RunfilesGroupInfo` is missing, skip the rest of this protocol and package `DefaultInfo.default_runfiles.files` as a single group instead. + +2. **Accumulate metadata:** Start with the binary's `RunfilesGroupMetadataInfo` (if present). Then iterate `aspect_hints` — for each hint providing `RunfilesGroupMetadataInfo`, dict-merge it into the accumulated metadata using `lib.merge_metadata()`. This is per-key last-wins: hints can override metadata for specific groups without affecting others. -2. **Apply transforms:** Iterate through the binary's `aspect_hints` in order. For each hint that provides `RunfilesGroupTransformInfo`, apply it to the current `RunfilesGroupInfo` using `lib.transform_groups()`. +3. **Apply transforms:** Iterate through the binary's `aspect_hints` in order. For each hint that provides `RunfilesGroupTransformInfo`, apply it using `lib.transform_groups()`. The transform receives both the current `RunfilesGroupInfo` and `RunfilesGroupMetadataInfo` and returns updated versions of both. -3. **Determine selection:** Start with the binary's `RunfilesGroupSelectionInfo` (if present). Then iterate `aspect_hints` — the last hint providing `RunfilesGroupSelectionInfo` wins. +4. **Optionally merge:** If you need to enforce a maximum group count, call `lib.merge_to_limit(runfiles_group_info, metadata_info, max_groups = N)` before ordering. This merges the lightest same-rank groups until the count fits within the limit. Note: packagers may wish to implement their own group merging strategies instead of `lib.merge_to_limit`. -4. **Apply ordering:** Call `lib.ordered_groups(runfiles_group_info, selection_info)` to get the final ordered list of `(group_name, depset[File])` tuples. +5. **Apply ordering:** Call `lib.ordered_groups(runfiles_group_info, metadata_info)` to get the final ordered list of `(group_name, depset[File])` tuples, sorted by rank. ### Using the library ```starlark load("@rules_runfiles_group//runfiles_group:lib.bzl", "lib") load("@rules_runfiles_group//runfiles_group:providers.bzl", - "RunfilesGroupInfo", "RunfilesGroupSelectionInfo", "RunfilesGroupTransformInfo") + "RunfilesGroupInfo", "RunfilesGroupMetadataInfo", "RunfilesGroupTransformInfo") # In your aspect implementation: -ordered = lib.ordered_groups(runfiles_group_info, selection_info) +rgi = target[RunfilesGroupInfo] # always from the target, never from aspect_hints + +# Accumulate metadata from binary + hints +metadata = target[RunfilesGroupMetadataInfo] if RunfilesGroupMetadataInfo in target else None +for hint in ctx.rule.attr.aspect_hints: + if RunfilesGroupMetadataInfo in hint: + metadata = lib.merge_metadata(metadata, hint[RunfilesGroupMetadataInfo]) + +# Apply transforms +for hint in ctx.rule.attr.aspect_hints: + if RunfilesGroupTransformInfo in hint: + result = lib.transform_groups(rgi, metadata, hint[RunfilesGroupTransformInfo]) + rgi = result.runfiles_group_info + metadata = result.runfiles_group_metadata_info + +# Order by rank +ordered = lib.ordered_groups(rgi, metadata) for group_name, files_depset in ordered: # Create a layer / archive entry / etc. ... + +# Or merge first if you have a group limit +result = lib.merge_to_limit(rgi, metadata, max_groups = 5) +ordered = lib.ordered_groups(result.runfiles_group_info, result.runfiles_group_metadata_info) ``` ### Respecting `aspect_hints` Apply an aspect to the `binary` attribute. Inside the aspect, read `ctx.rule.attr.aspect_hints` to access the hint targets and their providers. This is the mechanism through which users customize group behavior without modifying the binary rule. -Note that ordering may not matter for some kinds of packages. In that case, it's advised to still perform the selection step `lib.ordered_groups(rgi)`, but ignore ordering of the output. +Note that ordering may not matter for some kinds of packages. In that case, it's advised to still perform the ordering step `lib.ordered_groups(rgi, metadata)`, but treat the intra-rank order as arbitrary. + +### Packaging the executable file itself along with other supporting files + +`RunfilesGroupInfo` only covers the files inside `DefaultInfo.default_runfiles.files`. A well-behaved packager should also handle the remaining pieces of the executable: the binary file itself, the runfiles symlinks, the repo mapping manifest, etc. These are not part of any runfiles group. It is up to the packager to decide where they go — they could be added to an existing group, placed in a dedicated group, or handled out of band entirely. --- @@ -173,14 +242,14 @@ Note that ordering may not matter for some kinds of packages. In that case, it's ### Rulesets producing `RunfilesGroupInfo` (*_binary rules) -| Ruleset | Grouping | Ordering | Weight-based merging | -|---------|----------|----------|---------------------| +| Ruleset | Grouping | Metadata | Weight hints | +|---------|----------|----------|-------------| | *Your ruleset here* | | | | ### Rulesets consuming `RunfilesGroupInfo` (packaging rules) -| Ruleset | Ordering | `aspect_hints` support | -|---------|----------|----------------------| -| *Your ruleset here* | | | +| Ruleset | Ordering | Merge-to-limit | `aspect_hints` support | +|---------|----------|----------------|----------------------| +| *Your ruleset here* | | | | > To add your ruleset to these tables, open a pull request. diff --git a/example/MODULE.bazel b/example/MODULE.bazel index 7e759ce..addad9f 100644 --- a/example/MODULE.bazel +++ b/example/MODULE.bazel @@ -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", ) @@ -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( diff --git a/example/consumer/rules/fake_package.bzl b/example/consumer/rules/fake_package.bzl index de2d064..9bb186b 100644 --- a/example/consumer/rules/fake_package.bzl +++ b/example/consumer/rules/fake_package.bzl @@ -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", ) @@ -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)] diff --git a/example/producer/repository_rules/local_starlark_repository.bzl b/example/producer/repository_rules/local_starlark_repository.bzl index 6185271..4dac60e 100644 --- a/example/producer/repository_rules/local_starlark_repository.bzl +++ b/example/producer/repository_rules/local_starlark_repository.bzl @@ -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.", + ), + }, ) diff --git a/example/producer/rules/skip_interpreter.bzl b/example/producer/rules/skip_interpreter.bzl index 975bed6..b0250cd 100644 --- a/example/producer/rules/skip_interpreter.bzl +++ b/example/producer/rules/skip_interpreter.bzl @@ -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 [ diff --git a/example/producer/rules/starlark_binary.bzl b/example/producer/rules/starlark_binary.bzl index 29c6d02..e937da8 100644 --- a/example/producer/rules/starlark_binary.bzl +++ b/example/producer/rules/starlark_binary.bzl @@ -2,7 +2,7 @@ load("@hermetic_launcher//launcher:lib.bzl", "launcher") load("@rules_runfiles_group//runfiles_group:lib.bzl", "lib") -load("@rules_runfiles_group//runfiles_group:providers.bzl", "RunfilesGroupInfo", "RunfilesGroupSelectionInfo") +load("@rules_runfiles_group//runfiles_group:providers.bzl", "RunfilesGroupInfo", "RunfilesGroupMetadataInfo") load("//producer/providers:providers.bzl", "StarlarkInfo") def _canonical_repo_name(ctx): @@ -119,36 +119,47 @@ def _starlark_binary_impl(ctx): if ctx.attr.runfiles_grouping != "disabled": groups = {} - ranks = {"interpreter": 0, "std": 1} + + # Collect metadata from deps (carries weight from starlark_library). + dep_metadata = None + for dep in ctx.attr.deps: + if RunfilesGroupMetadataInfo in dep: + dep_metadata = lib.merge_metadata(dep_metadata, dep[RunfilesGroupMetadataInfo]) + + metadata = {} + own_repo = ctx.attr.repository # Special group: interpreter groups["interpreter"] = depset( [interpreter_exe], transitive = [interpreter_info.default_runfiles.files], ) + metadata["interpreter"] = lib.group_metadata(rank = -2, do_not_merge = True) # Special group: std groups["std"] = stdlib[DefaultInfo].default_runfiles.files + metadata["std"] = lib.group_metadata(rank = -1) entrypoint_files = depset([output, entrypoint, loadmap, properties] + ctx.files.data) # Dep groups if ctx.attr.runfiles_grouping == "by_target": - # Keep a separate entrypoint group in by_target mode. groups["entrypoint"] = entrypoint_files - ranks["entrypoint"] = 3 + metadata["entrypoint"] = lib.group_metadata(rank = 2) for dep in ctx.attr.deps: if RunfilesGroupInfo in dep: for name in lib.group_names(dep[RunfilesGroupInfo]): groups[name] = getattr(dep[RunfilesGroupInfo], name) - if _extract_repo(name) == current_repo: - ranks[name] = 3 + dep_weight = _get_dep_weight(dep_metadata, name) + if _extract_repo(name) == own_repo: + metadata[name] = lib.group_metadata(rank = 1, weight = dep_weight) + elif dep_weight != None: + metadata[name] = lib.group_metadata(weight = dep_weight) elif ctx.attr.runfiles_grouping == "by_repo": - # Merge entrypoint into the current repo group. repo_depsets = {} - repo_depsets[current_repo] = [entrypoint_files] - ranks[current_repo] = 3 + repo_weights = {} + repo_depsets[own_repo] = [entrypoint_files] for dep in ctx.attr.deps: if RunfilesGroupInfo in dep: for name in lib.group_names(dep[RunfilesGroupInfo]): @@ -156,43 +167,44 @@ def _starlark_binary_impl(ctx): if repo not in repo_depsets: repo_depsets[repo] = [] repo_depsets[repo].append(getattr(dep[RunfilesGroupInfo], name)) + w = _get_dep_weight(dep_metadata, name) + if w != None: + repo_weights[repo] = repo_weights.get(repo, 0) + w for repo, ds in repo_depsets.items(): - groups[repo] = depset(transitive = ds) - if repo == current_repo: - ranks[repo] = 3 + groups[repo or "_main"] = depset(transitive = ds) + if repo == own_repo: + metadata[repo or "_main"] = lib.group_metadata(rank = 1, weight = repo_weights.get(repo, None)) + elif repo in repo_weights: + metadata[repo or "_main"] = lib.group_metadata(weight = repo_weights[repo]) providers.append(RunfilesGroupInfo(**groups)) - providers.append(RunfilesGroupSelectionInfo( - predicate = _predicate_all, - compare = lambda left, right: _compare_starlark_binary_order(ranks, left, right), - )) + providers.append(RunfilesGroupMetadataInfo(groups = metadata)) return providers -def _extract_repo(label_str): - idx = label_str.find("//") - if idx <= 0: - return "_main" - repo = label_str[:idx] - if repo.startswith("@@"): - repo = repo[2:] - elif repo.startswith("@"): - repo = repo[1:] - return repo if repo else "_main" +def _extract_repo(group_name): + """Extracts the friendly repo name from a loadpath-based group name. -def _format_repo(repo_tuple): - return repo_tuple[0] + "\0" + repo_tuple[1] + "@fizzbuzz//:fizzbuzz" -> "fizzbuzz" + "//src:lib_a" -> "" + """ + if not group_name.startswith("@"): + return "" + idx = group_name.find("//") + if idx < 0: + return "" + return group_name[1:idx] -def _predicate_all(_): - return True +def _get_dep_weight(dep_metadata, name): + if dep_metadata == None: + return None + entry = dep_metadata.groups.get(name, None) + if entry == None: + return None + return entry.weight -# Rank: 0 = interpreter, 1 = std, 2 = third-party deps, 3 = current repo -def _compare_starlark_binary_order(ranks, left, right): - left_rank = ranks.get(left, 2) - right_rank = ranks.get(right, 2) - if left_rank != right_rank: - return left_rank < right_rank - return left < right +def _format_repo(repo_tuple): + return repo_tuple[0] + "\0" + repo_tuple[1] starlark_binary = rule( implementation = _starlark_binary_impl, diff --git a/example/producer/rules/starlark_library.bzl b/example/producer/rules/starlark_library.bzl index d844589..e8305e9 100644 --- a/example/producer/rules/starlark_library.bzl +++ b/example/producer/rules/starlark_library.bzl @@ -1,7 +1,7 @@ """Implementation of the starlark_library rule.""" load("@rules_runfiles_group//runfiles_group:lib.bzl", "lib") -load("@rules_runfiles_group//runfiles_group:providers.bzl", "RunfilesGroupInfo") +load("@rules_runfiles_group//runfiles_group:providers.bzl", "RunfilesGroupInfo", "RunfilesGroupMetadataInfo") load("//producer/providers:providers.bzl", "StarlarkInfo") def _canonical_repo_name(ctx): @@ -28,13 +28,26 @@ def _starlark_library_impl(ctx): for dep in ctx.attr.data: runfiles = runfiles.merge(dep[DefaultInfo].default_runfiles) + group_name = loadpath + ":" + ctx.label.name + groups = {} for dep in ctx.attr.deps: if RunfilesGroupInfo in dep: for name in lib.group_names(dep[RunfilesGroupInfo]): groups[name] = getattr(dep[RunfilesGroupInfo], name) - groups[str(ctx.label)] = depset(direct_srcs + ctx.files.data) + groups[group_name] = depset(direct_srcs + ctx.files.data) + + metadata = None + for dep in ctx.attr.deps: + if RunfilesGroupMetadataInfo in dep: + metadata = lib.merge_metadata(metadata, dep[RunfilesGroupMetadataInfo]) + + own_weight = ctx.attr.runfiles_weight if ctx.attr.runfiles_weight > 0 else None + own_metadata = RunfilesGroupMetadataInfo(groups = { + group_name: lib.group_metadata(weight = own_weight), + }) + metadata = lib.merge_metadata(metadata, own_metadata) return [ DefaultInfo( @@ -47,6 +60,7 @@ def _starlark_library_impl(ctx): repos = repos, ), RunfilesGroupInfo(**groups), + RunfilesGroupMetadataInfo(groups = metadata.groups), ] starlark_library = rule( @@ -68,5 +82,9 @@ starlark_library = rule( default = "", doc = "Repository name for the load path. If empty, loadpath is '//package'. If set, loadpath is '@repository//package'.", ), + "runfiles_weight": attr.int( + default = 0, + doc = "Weight hint for this library's runfiles group. If > 0, set as the weight in RunfilesGroupMetadataInfo.", + ), }, ) diff --git a/example/producer/stdlib_repo/BUILD.bazel b/example/producer/stdlib_repo/BUILD.bazel deleted file mode 100644 index 13a4458..0000000 --- a/example/producer/stdlib_repo/BUILD.bazel +++ /dev/null @@ -1,8 +0,0 @@ -load("@rules_runfiles_group_example//producer/rules:starlark_library.bzl", "starlark_library") - -starlark_library( - name = "std", - repository = "std", - visibility = ["//visibility:public"], - deps = ["//sha256"], -) diff --git a/example/producer/stdlib_repo/MODULE.bazel b/example/producer/stdlib_repo/MODULE.bazel deleted file mode 100644 index 00bb183..0000000 --- a/example/producer/stdlib_repo/MODULE.bazel +++ /dev/null @@ -1,6 +0,0 @@ -############################################################################### -# Bazel now uses Bzlmod by default to manage external dependencies. -# Please consider migrating your external dependencies from WORKSPACE to MODULE.bazel. -# -# For more details, please check https://github.com/bazelbuild/bazel/issues/18958 -############################################################################### diff --git a/example/producer/stdlib_repo/MODULE.bazel.lock b/example/producer/stdlib_repo/MODULE.bazel.lock deleted file mode 100644 index 23f8dcf..0000000 --- a/example/producer/stdlib_repo/MODULE.bazel.lock +++ /dev/null @@ -1,192 +0,0 @@ -{ - "lockFileVersion": 26, - "registryFileHashes": { - "https://bcr.bazel.build/bazel_registry.json": "8a28e4aff06ee60aed2a8c281907fb8bcbf3b753c91fb5a5c57da3215d5b3497", - "https://bcr.bazel.build/modules/abseil-cpp/20210324.2/MODULE.bazel": "7cd0312e064fde87c8d1cd79ba06c876bd23630c83466e9500321be55c96ace2", - "https://bcr.bazel.build/modules/abseil-cpp/20211102.0/MODULE.bazel": "70390338f7a5106231d20620712f7cccb659cd0e9d073d1991c038eb9fc57589", - "https://bcr.bazel.build/modules/abseil-cpp/20230125.1/MODULE.bazel": "89047429cb0207707b2dface14ba7f8df85273d484c2572755be4bab7ce9c3a0", - "https://bcr.bazel.build/modules/abseil-cpp/20230802.0.bcr.1/MODULE.bazel": "1c8cec495288dccd14fdae6e3f95f772c1c91857047a098fad772034264cc8cb", - "https://bcr.bazel.build/modules/abseil-cpp/20230802.0/MODULE.bazel": "d253ae36a8bd9ee3c5955384096ccb6baf16a1b1e93e858370da0a3b94f77c16", - "https://bcr.bazel.build/modules/abseil-cpp/20230802.1/MODULE.bazel": "fa92e2eb41a04df73cdabeec37107316f7e5272650f81d6cc096418fe647b915", - "https://bcr.bazel.build/modules/abseil-cpp/20240116.1/MODULE.bazel": "37bcdb4440fbb61df6a1c296ae01b327f19e9bb521f9b8e26ec854b6f97309ed", - "https://bcr.bazel.build/modules/abseil-cpp/20240116.2/MODULE.bazel": "73939767a4686cd9a520d16af5ab440071ed75cec1a876bf2fcfaf1f71987a16", - "https://bcr.bazel.build/modules/abseil-cpp/20250127.1/MODULE.bazel": "c4a89e7ceb9bf1e25cf84a9f830ff6b817b72874088bf5141b314726e46a57c1", - "https://bcr.bazel.build/modules/abseil-cpp/20250512.1/MODULE.bazel": "d209fdb6f36ffaf61c509fcc81b19e81b411a999a934a032e10cd009a0226215", - "https://bcr.bazel.build/modules/abseil-cpp/20250814.1/MODULE.bazel": "51f2312901470cdab0dbdf3b88c40cd21c62a7ed58a3de45b365ddc5b11bcab2", - "https://bcr.bazel.build/modules/abseil-cpp/20250814.1/source.json": "cea3901d7e299da7320700abbaafe57a65d039f10d0d7ea601c4a66938ea4b0c", - "https://bcr.bazel.build/modules/apple_support/1.11.1/MODULE.bazel": "1843d7cd8a58369a444fc6000e7304425fba600ff641592161d9f15b179fb896", - "https://bcr.bazel.build/modules/apple_support/1.15.1/MODULE.bazel": "a0556fefca0b1bb2de8567b8827518f94db6a6e7e7d632b4c48dc5f865bc7c85", - "https://bcr.bazel.build/modules/apple_support/1.21.0/MODULE.bazel": "ac1824ed5edf17dee2fdd4927ada30c9f8c3b520be1b5fd02a5da15bc10bff3e", - "https://bcr.bazel.build/modules/apple_support/1.21.1/MODULE.bazel": "5809fa3efab15d1f3c3c635af6974044bac8a4919c62238cce06acee8a8c11f1", - "https://bcr.bazel.build/modules/apple_support/1.24.2/MODULE.bazel": "0e62471818affb9f0b26f128831d5c40b074d32e6dda5a0d3852847215a41ca4", - "https://bcr.bazel.build/modules/apple_support/1.24.2/source.json": "2c22c9827093250406c5568da6c54e6fdf0ef06238def3d99c71b12feb057a8d", - "https://bcr.bazel.build/modules/bazel_features/1.1.1/MODULE.bazel": "27b8c79ef57efe08efccbd9dd6ef70d61b4798320b8d3c134fd571f78963dbcd", - "https://bcr.bazel.build/modules/bazel_features/1.10.0/MODULE.bazel": "f75e8807570484a99be90abcd52b5e1f390362c258bcb73106f4544957a48101", - "https://bcr.bazel.build/modules/bazel_features/1.11.0/MODULE.bazel": "f9382337dd5a474c3b7d334c2f83e50b6eaedc284253334cf823044a26de03e8", - "https://bcr.bazel.build/modules/bazel_features/1.15.0/MODULE.bazel": "d38ff6e517149dc509406aca0db3ad1efdd890a85e049585b7234d04238e2a4d", - "https://bcr.bazel.build/modules/bazel_features/1.17.0/MODULE.bazel": "039de32d21b816b47bd42c778e0454217e9c9caac4a3cf8e15c7231ee3ddee4d", - "https://bcr.bazel.build/modules/bazel_features/1.18.0/MODULE.bazel": "1be0ae2557ab3a72a57aeb31b29be347bcdc5d2b1eb1e70f39e3851a7e97041a", - "https://bcr.bazel.build/modules/bazel_features/1.19.0/MODULE.bazel": "59adcdf28230d220f0067b1f435b8537dd033bfff8db21335ef9217919c7fb58", - "https://bcr.bazel.build/modules/bazel_features/1.21.0/MODULE.bazel": "675642261665d8eea09989aa3b8afb5c37627f1be178382c320d1b46afba5e3b", - "https://bcr.bazel.build/modules/bazel_features/1.23.0/MODULE.bazel": "fd1ac84bc4e97a5a0816b7fd7d4d4f6d837b0047cf4cbd81652d616af3a6591a", - "https://bcr.bazel.build/modules/bazel_features/1.27.0/MODULE.bazel": "621eeee06c4458a9121d1f104efb80f39d34deff4984e778359c60eaf1a8cb65", - "https://bcr.bazel.build/modules/bazel_features/1.28.0/MODULE.bazel": "4b4200e6cbf8fa335b2c3f43e1d6ef3e240319c33d43d60cc0fbd4b87ece299d", - "https://bcr.bazel.build/modules/bazel_features/1.3.0/MODULE.bazel": "cdcafe83ec318cda34e02948e81d790aab8df7a929cec6f6969f13a489ccecd9", - "https://bcr.bazel.build/modules/bazel_features/1.30.0/MODULE.bazel": "a14b62d05969a293b80257e72e597c2da7f717e1e69fa8b339703ed6731bec87", - "https://bcr.bazel.build/modules/bazel_features/1.33.0/MODULE.bazel": "8b8dc9d2a4c88609409c3191165bccec0e4cb044cd7a72ccbe826583303459f6", - "https://bcr.bazel.build/modules/bazel_features/1.4.1/MODULE.bazel": "e45b6bb2350aff3e442ae1111c555e27eac1d915e77775f6fdc4b351b758b5d7", - "https://bcr.bazel.build/modules/bazel_features/1.42.1/MODULE.bazel": "275a59b5406ff18c01739860aa70ad7ccb3cfb474579411decca11c93b951080", - "https://bcr.bazel.build/modules/bazel_features/1.42.1/source.json": "fcd4396b2df85f64f2b3bb436ad870793ecf39180f1d796f913cc9276d355309", - "https://bcr.bazel.build/modules/bazel_features/1.9.1/MODULE.bazel": "8f679097876a9b609ad1f60249c49d68bfab783dd9be012faf9d82547b14815a", - "https://bcr.bazel.build/modules/bazel_skylib/1.0.3/MODULE.bazel": "bcb0fd896384802d1ad283b4e4eb4d718eebd8cb820b0a2c3a347fb971afd9d8", - "https://bcr.bazel.build/modules/bazel_skylib/1.1.1/MODULE.bazel": "1add3e7d93ff2e6998f9e118022c84d163917d912f5afafb3058e3d2f1545b5e", - "https://bcr.bazel.build/modules/bazel_skylib/1.2.0/MODULE.bazel": "44fe84260e454ed94ad326352a698422dbe372b21a1ac9f3eab76eb531223686", - "https://bcr.bazel.build/modules/bazel_skylib/1.2.1/MODULE.bazel": "f35baf9da0efe45fa3da1696ae906eea3d615ad41e2e3def4aeb4e8bc0ef9a7a", - "https://bcr.bazel.build/modules/bazel_skylib/1.3.0/MODULE.bazel": "20228b92868bf5cfc41bda7afc8a8ba2a543201851de39d990ec957b513579c5", - "https://bcr.bazel.build/modules/bazel_skylib/1.4.1/MODULE.bazel": "a0dcb779424be33100dcae821e9e27e4f2901d9dfd5333efe5ac6a8d7ab75e1d", - "https://bcr.bazel.build/modules/bazel_skylib/1.4.2/MODULE.bazel": "3bd40978e7a1fac911d5989e6b09d8f64921865a45822d8b09e815eaa726a651", - "https://bcr.bazel.build/modules/bazel_skylib/1.5.0/MODULE.bazel": "32880f5e2945ce6a03d1fbd588e9198c0a959bb42297b2cfaf1685b7bc32e138", - "https://bcr.bazel.build/modules/bazel_skylib/1.6.1/MODULE.bazel": "8fdee2dbaace6c252131c00e1de4b165dc65af02ea278476187765e1a617b917", - "https://bcr.bazel.build/modules/bazel_skylib/1.7.0/MODULE.bazel": "0db596f4563de7938de764cc8deeabec291f55e8ec15299718b93c4423e9796d", - "https://bcr.bazel.build/modules/bazel_skylib/1.7.1/MODULE.bazel": "3120d80c5861aa616222ec015332e5f8d3171e062e3e804a2a0253e1be26e59b", - "https://bcr.bazel.build/modules/bazel_skylib/1.8.1/MODULE.bazel": "88ade7293becda963e0e3ea33e7d54d3425127e0a326e0d17da085a5f1f03ff6", - "https://bcr.bazel.build/modules/bazel_skylib/1.8.2/MODULE.bazel": "69ad6927098316848b34a9142bcc975e018ba27f08c4ff403f50c1b6e646ca67", - "https://bcr.bazel.build/modules/bazel_skylib/1.8.2/source.json": "34a3c8bcf233b835eb74be9d628899bb32999d3e0eadef1947a0a562a2b16ffb", - "https://bcr.bazel.build/modules/buildozer/8.5.1/MODULE.bazel": "a35d9561b3fc5b18797c330793e99e3b834a473d5fbd3d7d7634aafc9bdb6f8f", - "https://bcr.bazel.build/modules/buildozer/8.5.1/source.json": "e3386e6ff4529f2442800dee47ad28d3e6487f36a1f75ae39ae56c70f0cd2fbd", - "https://bcr.bazel.build/modules/google_benchmark/1.8.2/MODULE.bazel": "a70cf1bba851000ba93b58ae2f6d76490a9feb74192e57ab8e8ff13c34ec50cb", - "https://bcr.bazel.build/modules/googletest/1.11.0/MODULE.bazel": "3a83f095183f66345ca86aa13c58b59f9f94a2f81999c093d4eeaa2d262d12f4", - "https://bcr.bazel.build/modules/googletest/1.14.0.bcr.1/MODULE.bazel": "22c31a561553727960057361aa33bf20fb2e98584bc4fec007906e27053f80c6", - "https://bcr.bazel.build/modules/googletest/1.14.0/MODULE.bazel": "cfbcbf3e6eac06ef9d85900f64424708cc08687d1b527f0ef65aa7517af8118f", - "https://bcr.bazel.build/modules/googletest/1.15.2/MODULE.bazel": "6de1edc1d26cafb0ea1a6ab3f4d4192d91a312fd2d360b63adaa213cd00b2108", - "https://bcr.bazel.build/modules/googletest/1.17.0/MODULE.bazel": "dbec758171594a705933a29fcf69293d2468c49ec1f2ebca65c36f504d72df46", - "https://bcr.bazel.build/modules/googletest/1.17.0/source.json": "38e4454b25fc30f15439c0378e57909ab1fd0a443158aa35aec685da727cd713", - "https://bcr.bazel.build/modules/jsoncpp/1.9.5/MODULE.bazel": "31271aedc59e815656f5736f282bb7509a97c7ecb43e927ac1a37966e0578075", - "https://bcr.bazel.build/modules/jsoncpp/1.9.6/MODULE.bazel": "2f8d20d3b7d54143213c4dfc3d98225c42de7d666011528dc8fe91591e2e17b0", - "https://bcr.bazel.build/modules/jsoncpp/1.9.6/source.json": "a04756d367a2126c3541682864ecec52f92cdee80a35735a3cb249ce015ca000", - "https://bcr.bazel.build/modules/libpfm/4.11.0/MODULE.bazel": "45061ff025b301940f1e30d2c16bea596c25b176c8b6b3087e92615adbd52902", - "https://bcr.bazel.build/modules/nlohmann_json/3.6.1/MODULE.bazel": "6f7b417dcc794d9add9e556673ad25cb3ba835224290f4f848f8e2db1e1fca74", - "https://bcr.bazel.build/modules/nlohmann_json/3.6.1/source.json": "f448c6e8963fdfa7eb831457df83ad63d3d6355018f6574fb017e8169deb43a9", - "https://bcr.bazel.build/modules/platforms/0.0.10/MODULE.bazel": "8cb8efaf200bdeb2150d93e162c40f388529a25852b332cec879373771e48ed5", - "https://bcr.bazel.build/modules/platforms/0.0.11/MODULE.bazel": "0daefc49732e227caa8bfa834d65dc52e8cc18a2faf80df25e8caea151a9413f", - "https://bcr.bazel.build/modules/platforms/0.0.4/MODULE.bazel": "9b328e31ee156f53f3c416a64f8491f7eb731742655a47c9eec4703a71644aee", - "https://bcr.bazel.build/modules/platforms/0.0.5/MODULE.bazel": "5733b54ea419d5eaf7997054bb55f6a1d0b5ff8aedf0176fef9eea44f3acda37", - "https://bcr.bazel.build/modules/platforms/0.0.6/MODULE.bazel": "ad6eeef431dc52aefd2d77ed20a4b353f8ebf0f4ecdd26a807d2da5aa8cd0615", - "https://bcr.bazel.build/modules/platforms/0.0.7/MODULE.bazel": "72fd4a0ede9ee5c021f6a8dd92b503e089f46c227ba2813ff183b71616034814", - "https://bcr.bazel.build/modules/platforms/0.0.8/MODULE.bazel": "9f142c03e348f6d263719f5074b21ef3adf0b139ee4c5133e2aa35664da9eb2d", - "https://bcr.bazel.build/modules/platforms/0.0.9/MODULE.bazel": "4a87a60c927b56ddd67db50c89acaa62f4ce2a1d2149ccb63ffd871d5ce29ebc", - "https://bcr.bazel.build/modules/platforms/1.0.0/MODULE.bazel": "f05feb42b48f1b3c225e4ccf351f367be0371411a803198ec34a389fb22aa580", - "https://bcr.bazel.build/modules/platforms/1.0.0/source.json": "f4ff1fd412e0246fd38c82328eb209130ead81d62dcd5a9e40910f867f733d96", - "https://bcr.bazel.build/modules/protobuf/21.7/MODULE.bazel": "a5a29bb89544f9b97edce05642fac225a808b5b7be74038ea3640fae2f8e66a7", - "https://bcr.bazel.build/modules/protobuf/27.0/MODULE.bazel": "7873b60be88844a0a1d8f80b9d5d20cfbd8495a689b8763e76c6372998d3f64c", - "https://bcr.bazel.build/modules/protobuf/29.0-rc2/MODULE.bazel": "6241d35983510143049943fc0d57937937122baf1b287862f9dc8590fc4c37df", - "https://bcr.bazel.build/modules/protobuf/29.0-rc3/MODULE.bazel": "33c2dfa286578573afc55a7acaea3cada4122b9631007c594bf0729f41c8de92", - "https://bcr.bazel.build/modules/protobuf/29.1/MODULE.bazel": "557c3457560ff49e122ed76c0bc3397a64af9574691cb8201b4e46d4ab2ecb95", - "https://bcr.bazel.build/modules/protobuf/3.19.0/MODULE.bazel": "6b5fbb433f760a99a22b18b6850ed5784ef0e9928a72668b66e4d7ccd47db9b0", - "https://bcr.bazel.build/modules/protobuf/32.1/MODULE.bazel": "89cd2866a9cb07fee9ff74c41ceace11554f32e0d849de4e23ac55515cfada4d", - "https://bcr.bazel.build/modules/protobuf/33.4/MODULE.bazel": "114775b816b38b6d0ca620450d6b02550c60ceedfdc8d9a229833b34a223dc42", - "https://bcr.bazel.build/modules/protobuf/33.4/source.json": "555f8686b4c7d6b5ba731fbea13bf656b4bfd9a7ff629c1d9d3f6e1d6155de79", - "https://bcr.bazel.build/modules/pybind11_bazel/2.11.1/MODULE.bazel": "88af1c246226d87e65be78ed49ecd1e6f5e98648558c14ce99176da041dc378e", - "https://bcr.bazel.build/modules/pybind11_bazel/2.12.0/MODULE.bazel": "e6f4c20442eaa7c90d7190d8dc539d0ab422f95c65a57cc59562170c58ae3d34", - "https://bcr.bazel.build/modules/pybind11_bazel/2.12.0/source.json": "6900fdc8a9e95866b8c0d4ad4aba4d4236317b5c1cd04c502df3f0d33afed680", - "https://bcr.bazel.build/modules/re2/2023-09-01/MODULE.bazel": "cb3d511531b16cfc78a225a9e2136007a48cf8a677e4264baeab57fe78a80206", - "https://bcr.bazel.build/modules/re2/2024-07-02.bcr.1/MODULE.bazel": "b4963dda9b31080be1905ef085ecd7dd6cd47c05c79b9cdf83ade83ab2ab271a", - "https://bcr.bazel.build/modules/re2/2024-07-02.bcr.1/source.json": "2ff292be6ef3340325ce8a045ecc326e92cbfab47c7cbab4bd85d28971b97ac4", - "https://bcr.bazel.build/modules/re2/2024-07-02/MODULE.bazel": "0eadc4395959969297cbcf31a249ff457f2f1d456228c67719480205aa306daa", - "https://bcr.bazel.build/modules/rules_android/0.1.1/MODULE.bazel": "48809ab0091b07ad0182defb787c4c5328bd3a278938415c00a7b69b50c4d3a8", - "https://bcr.bazel.build/modules/rules_android/0.1.1/source.json": "e6986b41626ee10bdc864937ffb6d6bf275bb5b9c65120e6137d56e6331f089e", - "https://bcr.bazel.build/modules/rules_apple/3.16.0/MODULE.bazel": "0d1caf0b8375942ce98ea944be754a18874041e4e0459401d925577624d3a54a", - "https://bcr.bazel.build/modules/rules_apple/4.1.0/MODULE.bazel": "76e10fd4a48038d3fc7c5dc6e63b7063bbf5304a2e3bd42edda6ec660eebea68", - "https://bcr.bazel.build/modules/rules_apple/4.1.0/source.json": "8ee81e1708756f81b343a5eb2b2f0b953f1d25c4ab3d4a68dc02754872e80715", - "https://bcr.bazel.build/modules/rules_cc/0.0.1/MODULE.bazel": "cb2aa0747f84c6c3a78dad4e2049c154f08ab9d166b1273835a8174940365647", - "https://bcr.bazel.build/modules/rules_cc/0.0.10/MODULE.bazel": "ec1705118f7eaedd6e118508d3d26deba2a4e76476ada7e0e3965211be012002", - "https://bcr.bazel.build/modules/rules_cc/0.0.13/MODULE.bazel": "0e8529ed7b323dad0775ff924d2ae5af7640b23553dfcd4d34344c7e7a867191", - "https://bcr.bazel.build/modules/rules_cc/0.0.15/MODULE.bazel": "6704c35f7b4a72502ee81f61bf88706b54f06b3cbe5558ac17e2e14666cd5dcc", - "https://bcr.bazel.build/modules/rules_cc/0.0.16/MODULE.bazel": "7661303b8fc1b4d7f532e54e9d6565771fea666fbdf839e0a86affcd02defe87", - "https://bcr.bazel.build/modules/rules_cc/0.0.17/MODULE.bazel": "2ae1d8f4238ec67d7185d8861cb0a2cdf4bc608697c331b95bf990e69b62e64a", - "https://bcr.bazel.build/modules/rules_cc/0.0.2/MODULE.bazel": "6915987c90970493ab97393024c156ea8fb9f3bea953b2f3ec05c34f19b5695c", - "https://bcr.bazel.build/modules/rules_cc/0.0.6/MODULE.bazel": "abf360251023dfe3efcef65ab9d56beefa8394d4176dd29529750e1c57eaa33f", - "https://bcr.bazel.build/modules/rules_cc/0.0.8/MODULE.bazel": "964c85c82cfeb6f3855e6a07054fdb159aced38e99a5eecf7bce9d53990afa3e", - "https://bcr.bazel.build/modules/rules_cc/0.0.9/MODULE.bazel": "836e76439f354b89afe6a911a7adf59a6b2518fafb174483ad78a2a2fde7b1c5", - "https://bcr.bazel.build/modules/rules_cc/0.1.1/MODULE.bazel": "2f0222a6f229f0bf44cd711dc13c858dad98c62d52bd51d8fc3a764a83125513", - "https://bcr.bazel.build/modules/rules_cc/0.1.2/MODULE.bazel": "557ddc3a96858ec0d465a87c0a931054d7dcfd6583af2c7ed3baf494407fd8d0", - "https://bcr.bazel.build/modules/rules_cc/0.1.5/MODULE.bazel": "88dfc9361e8b5ae1008ac38f7cdfd45ad738e4fa676a3ad67d19204f045a1fd8", - "https://bcr.bazel.build/modules/rules_cc/0.2.0/MODULE.bazel": "b5c17f90458caae90d2ccd114c81970062946f49f355610ed89bebf954f5783c", - "https://bcr.bazel.build/modules/rules_cc/0.2.13/MODULE.bazel": "eecdd666eda6be16a8d9dc15e44b5c75133405e820f620a234acc4b1fdc5aa37", - "https://bcr.bazel.build/modules/rules_cc/0.2.17/MODULE.bazel": "1849602c86cb60da8613d2de887f9566a6d354a6df6d7009f9d04a14402f9a84", - "https://bcr.bazel.build/modules/rules_cc/0.2.17/source.json": "3832f45d145354049137c0090df04629d9c2b5493dc5c2bf46f1834040133a07", - "https://bcr.bazel.build/modules/rules_cc/0.2.8/MODULE.bazel": "f1df20f0bf22c28192a794f29b501ee2018fa37a3862a1a2132ae2940a23a642", - "https://bcr.bazel.build/modules/rules_foreign_cc/0.9.0/MODULE.bazel": "c9e8c682bf75b0e7c704166d79b599f93b72cfca5ad7477df596947891feeef6", - "https://bcr.bazel.build/modules/rules_fuzzing/0.5.2/MODULE.bazel": "40c97d1144356f52905566c55811f13b299453a14ac7769dfba2ac38192337a8", - "https://bcr.bazel.build/modules/rules_java/4.0.0/MODULE.bazel": "5a78a7ae82cd1a33cef56dc578c7d2a46ed0dca12643ee45edbb8417899e6f74", - "https://bcr.bazel.build/modules/rules_java/5.3.5/MODULE.bazel": "a4ec4f2db570171e3e5eb753276ee4b389bae16b96207e9d3230895c99644b86", - "https://bcr.bazel.build/modules/rules_java/6.5.2/MODULE.bazel": "1d440d262d0e08453fa0c4d8f699ba81609ed0e9a9a0f02cd10b3e7942e61e31", - "https://bcr.bazel.build/modules/rules_java/7.10.0/MODULE.bazel": "530c3beb3067e870561739f1144329a21c851ff771cd752a49e06e3dc9c2e71a", - "https://bcr.bazel.build/modules/rules_java/7.12.2/MODULE.bazel": "579c505165ee757a4280ef83cda0150eea193eed3bef50b1004ba88b99da6de6", - "https://bcr.bazel.build/modules/rules_java/7.2.0/MODULE.bazel": "06c0334c9be61e6cef2c8c84a7800cef502063269a5af25ceb100b192453d4ab", - "https://bcr.bazel.build/modules/rules_java/7.6.1/MODULE.bazel": "2f14b7e8a1aa2f67ae92bc69d1ec0fa8d9f827c4e17ff5e5f02e91caa3b2d0fe", - "https://bcr.bazel.build/modules/rules_java/8.3.2/MODULE.bazel": "7336d5511ad5af0b8615fdc7477535a2e4e723a357b6713af439fe8cf0195017", - "https://bcr.bazel.build/modules/rules_java/8.5.1/MODULE.bazel": "d8a9e38cc5228881f7055a6079f6f7821a073df3744d441978e7a43e20226939", - "https://bcr.bazel.build/modules/rules_java/8.6.1/MODULE.bazel": "f4808e2ab5b0197f094cabce9f4b006a27766beb6a9975931da07099560ca9c2", - "https://bcr.bazel.build/modules/rules_java/9.1.0/MODULE.bazel": "ee63f27e36a3fada80342869361182f120a9819c74320e8e65b1e04ba0cd7a9d", - "https://bcr.bazel.build/modules/rules_java/9.1.0/source.json": "da589573c1dee2c9ac4a568b301269a2e8191110ff0345c1a959fa7ea6c4dfd6", - "https://bcr.bazel.build/modules/rules_jvm_external/4.4.2/MODULE.bazel": "a56b85e418c83eb1839819f0b515c431010160383306d13ec21959ac412d2fe7", - "https://bcr.bazel.build/modules/rules_jvm_external/5.1/MODULE.bazel": "33f6f999e03183f7d088c9be518a63467dfd0be94a11d0055fe2d210f89aa909", - "https://bcr.bazel.build/modules/rules_jvm_external/5.2/MODULE.bazel": "d9351ba35217ad0de03816ef3ed63f89d411349353077348a45348b096615036", - "https://bcr.bazel.build/modules/rules_jvm_external/6.3/MODULE.bazel": "c998e060b85f71e00de5ec552019347c8bca255062c990ac02d051bb80a38df0", - "https://bcr.bazel.build/modules/rules_jvm_external/6.7/MODULE.bazel": "e717beabc4d091ecb2c803c2d341b88590e9116b8bf7947915eeb33aab4f96dd", - "https://bcr.bazel.build/modules/rules_jvm_external/6.7/source.json": "5426f412d0a7fc6b611643376c7e4a82dec991491b9ce5cb1cfdd25fe2e92be4", - "https://bcr.bazel.build/modules/rules_kotlin/1.9.6/MODULE.bazel": "d269a01a18ee74d0335450b10f62c9ed81f2321d7958a2934e44272fe82dcef3", - "https://bcr.bazel.build/modules/rules_kotlin/1.9.6/source.json": "2faa4794364282db7c06600b7e5e34867a564ae91bda7cae7c29c64e9466b7d5", - "https://bcr.bazel.build/modules/rules_license/0.0.3/MODULE.bazel": "627e9ab0247f7d1e05736b59dbb1b6871373de5ad31c3011880b4133cafd4bd0", - "https://bcr.bazel.build/modules/rules_license/0.0.7/MODULE.bazel": "088fbeb0b6a419005b89cf93fe62d9517c0a2b8bb56af3244af65ecfe37e7d5d", - "https://bcr.bazel.build/modules/rules_license/1.0.0/MODULE.bazel": "a7fda60eefdf3d8c827262ba499957e4df06f659330bbe6cdbdb975b768bb65c", - "https://bcr.bazel.build/modules/rules_license/1.0.0/source.json": "a52c89e54cc311196e478f8382df91c15f7a2bfdf4c6cd0e2675cc2ff0b56efb", - "https://bcr.bazel.build/modules/rules_pkg/0.7.0/MODULE.bazel": "df99f03fc7934a4737122518bb87e667e62d780b610910f0447665a7e2be62dc", - "https://bcr.bazel.build/modules/rules_pkg/1.0.1/MODULE.bazel": "5b1df97dbc29623bccdf2b0dcd0f5cb08e2f2c9050aab1092fd39a41e82686ff", - "https://bcr.bazel.build/modules/rules_pkg/1.0.1/source.json": "bd82e5d7b9ce2d31e380dd9f50c111d678c3bdaca190cb76b0e1c71b05e1ba8a", - "https://bcr.bazel.build/modules/rules_proto/4.0.0/MODULE.bazel": "a7a7b6ce9bee418c1a760b3d84f83a299ad6952f9903c67f19e4edd964894e06", - "https://bcr.bazel.build/modules/rules_proto/5.3.0-21.7/MODULE.bazel": "e8dff86b0971688790ae75528fe1813f71809b5afd57facb44dad9e8eca631b7", - "https://bcr.bazel.build/modules/rules_proto/6.0.0-rc1/MODULE.bazel": "1e5b502e2e1a9e825eef74476a5a1ee524a92297085015a052510b09a1a09483", - "https://bcr.bazel.build/modules/rules_proto/6.0.2/MODULE.bazel": "ce916b775a62b90b61888052a416ccdda405212b6aaeb39522f7dc53431a5e73", - "https://bcr.bazel.build/modules/rules_proto/7.1.0/MODULE.bazel": "002d62d9108f75bb807cd56245d45648f38275cb3a99dcd45dfb864c5d74cb96", - "https://bcr.bazel.build/modules/rules_proto/7.1.0/source.json": "39f89066c12c24097854e8f57ab8558929f9c8d474d34b2c00ac04630ad8940e", - "https://bcr.bazel.build/modules/rules_python/0.10.2/MODULE.bazel": "cc82bc96f2997baa545ab3ce73f196d040ffb8756fd2d66125a530031cd90e5f", - "https://bcr.bazel.build/modules/rules_python/0.23.1/MODULE.bazel": "49ffccf0511cb8414de28321f5fcf2a31312b47c40cc21577144b7447f2bf300", - "https://bcr.bazel.build/modules/rules_python/0.25.0/MODULE.bazel": "72f1506841c920a1afec76975b35312410eea3aa7b63267436bfb1dd91d2d382", - "https://bcr.bazel.build/modules/rules_python/0.28.0/MODULE.bazel": "cba2573d870babc976664a912539b320cbaa7114cd3e8f053c720171cde331ed", - "https://bcr.bazel.build/modules/rules_python/0.31.0/MODULE.bazel": "93a43dc47ee570e6ec9f5779b2e64c1476a6ce921c48cc9a1678a91dd5f8fd58", - "https://bcr.bazel.build/modules/rules_python/0.33.2/MODULE.bazel": "3e036c4ad8d804a4dad897d333d8dce200d943df4827cb849840055be8d2e937", - "https://bcr.bazel.build/modules/rules_python/0.4.0/MODULE.bazel": "9208ee05fd48bf09ac60ed269791cf17fb343db56c8226a720fbb1cdf467166c", - "https://bcr.bazel.build/modules/rules_python/1.3.0/MODULE.bazel": "8361d57eafb67c09b75bf4bbe6be360e1b8f4f18118ab48037f2bd50aa2ccb13", - "https://bcr.bazel.build/modules/rules_python/1.4.1/MODULE.bazel": "8991ad45bdc25018301d6b7e1d3626afc3c8af8aaf4bc04f23d0b99c938b73a6", - "https://bcr.bazel.build/modules/rules_python/1.6.0/MODULE.bazel": "7e04ad8f8d5bea40451cf80b1bd8262552aa73f841415d20db96b7241bd027d8", - "https://bcr.bazel.build/modules/rules_python/1.7.0/MODULE.bazel": "d01f995ecd137abf30238ad9ce97f8fc3ac57289c8b24bd0bf53324d937a14f8", - "https://bcr.bazel.build/modules/rules_python/1.7.0/source.json": "028a084b65dcf8f4dc4f82f8778dbe65df133f234b316828a82e060d81bdce32", - "https://bcr.bazel.build/modules/rules_shell/0.2.0/MODULE.bazel": "fda8a652ab3c7d8fee214de05e7a9916d8b28082234e8d2c0094505c5268ed3c", - "https://bcr.bazel.build/modules/rules_shell/0.3.0/MODULE.bazel": "de4402cd12f4cc8fda2354fce179fdb068c0b9ca1ec2d2b17b3e21b24c1a937b", - "https://bcr.bazel.build/modules/rules_shell/0.6.1/MODULE.bazel": "72e76b0eea4e81611ef5452aa82b3da34caca0c8b7b5c0c9584338aa93bae26b", - "https://bcr.bazel.build/modules/rules_shell/0.6.1/source.json": "20ec05cd5e592055e214b2da8ccb283c7f2a421ea0dc2acbf1aa792e11c03d0c", - "https://bcr.bazel.build/modules/rules_swift/1.16.0/MODULE.bazel": "4a09f199545a60d09895e8281362b1ff3bb08bbde69c6fc87aff5b92fcc916ca", - "https://bcr.bazel.build/modules/rules_swift/2.1.1/MODULE.bazel": "494900a80f944fc7aa61500c2073d9729dff0b764f0e89b824eb746959bc1046", - "https://bcr.bazel.build/modules/rules_swift/2.4.0/MODULE.bazel": "1639617eb1ede28d774d967a738b4a68b0accb40650beadb57c21846beab5efd", - "https://bcr.bazel.build/modules/rules_swift/3.1.2/MODULE.bazel": "72c8f5cf9d26427cee6c76c8e3853eb46ce6b0412a081b2b6db6e8ad56267400", - "https://bcr.bazel.build/modules/rules_swift/3.1.2/source.json": "e85761f3098a6faf40b8187695e3de6d97944e98abd0d8ce579cb2daf6319a66", - "https://bcr.bazel.build/modules/stardoc/0.5.1/MODULE.bazel": "1a05d92974d0c122f5ccf09291442580317cdd859f07a8655f1db9a60374f9f8", - "https://bcr.bazel.build/modules/stardoc/0.5.3/MODULE.bazel": "c7f6948dae6999bf0db32c1858ae345f112cacf98f174c7a8bb707e41b974f1c", - "https://bcr.bazel.build/modules/stardoc/0.7.0/MODULE.bazel": "05e3d6d30c099b6770e97da986c53bd31844d7f13d41412480ea265ac9e8079c", - "https://bcr.bazel.build/modules/stardoc/0.7.2/MODULE.bazel": "fc152419aa2ea0f51c29583fab1e8c99ddefd5b3778421845606ee628629e0e5", - "https://bcr.bazel.build/modules/stardoc/0.7.2/source.json": "58b029e5e901d6802967754adf0a9056747e8176f017cfe3607c0851f4d42216", - "https://bcr.bazel.build/modules/swift_argument_parser/1.3.1.1/MODULE.bazel": "5e463fbfba7b1701d957555ed45097d7f984211330106ccd1352c6e0af0dcf91", - "https://bcr.bazel.build/modules/swift_argument_parser/1.3.1.2/MODULE.bazel": "75aab2373a4bbe2a1260b9bf2a1ebbdbf872d3bd36f80bff058dccd82e89422f", - "https://bcr.bazel.build/modules/swift_argument_parser/1.3.1.2/source.json": "5fba48bbe0ba48761f9e9f75f92876cafb5d07c0ce059cc7a8027416de94a05b", - "https://bcr.bazel.build/modules/upb/0.0.0-20220923-a547704/MODULE.bazel": "7298990c00040a0e2f121f6c32544bab27d4452f80d9ce51349b1a28f3005c43", - "https://bcr.bazel.build/modules/zlib/1.2.11/MODULE.bazel": "07b389abc85fdbca459b69e2ec656ae5622873af3f845e1c9d80fe179f3effa0", - "https://bcr.bazel.build/modules/zlib/1.3.1.bcr.5/MODULE.bazel": "eec517b5bbe5492629466e11dae908d043364302283de25581e3eb944326c4ca", - "https://bcr.bazel.build/modules/zlib/1.3.1.bcr.5/source.json": "22bc55c47af97246cfc093d0acf683a7869377de362b5d1c552c2c2e16b7a806", - "https://bcr.bazel.build/modules/zlib/1.3.1/MODULE.bazel": "751c9940dcfe869f5f7274e1295422a34623555916eb98c174c1e945594bf198" - }, - "selectedYankedVersions": {}, - "moduleExtensions": {}, - "facts": {} -} diff --git a/example/producer/stdlib_repo/collections/collections.star b/example/producer/stdlib_repo/collections/collections.star new file mode 100644 index 0000000..55ec699 --- /dev/null +++ b/example/producer/stdlib_repo/collections/collections.star @@ -0,0 +1,60 @@ +def sorted_list(items, reverse = False): + result = list(items) + for i in range(len(result)): + for j in range(i + 1, len(result)): + swap = result[i] > result[j] if not reverse else result[i] < result[j] + if swap: + result[i], result[j] = result[j], result[i] + return result + +def unique(items): + seen = {} + result = [] + for item in items: + key = str(item) + if key not in seen: + seen[key] = True + result.append(item) + return result + +def group_by(items, key_fn): + groups = {} + for item in items: + key = key_fn(item) + if key not in groups: + groups[key] = [] + groups[key].append(item) + return groups + +def flatten(nested): + result = [] + for item in nested: + if type(item) == "list": + result.extend(flatten(item)) + else: + result.append(item) + return result + +def chunk(items, size): + result = [] + current = [] + for item in items: + current.append(item) + if len(current) == size: + result.append(current) + current = [] + if current: + result.append(current) + return result + +def zip_lists(a, b): + result = [] + for i in range(min(len(a), len(b))): + result.append((a[i], b[i])) + return result + +def take(items, n): + return items[:n] + +def drop(items, n): + return items[n:] diff --git a/example/producer/stdlib_repo/sha256/BUILD.bazel b/example/producer/stdlib_repo/sha256/BUILD.bazel deleted file mode 100644 index 1ec8f05..0000000 --- a/example/producer/stdlib_repo/sha256/BUILD.bazel +++ /dev/null @@ -1,15 +0,0 @@ -load("@bazel_skylib//rules:copy_file.bzl", "copy_file") -load("@rules_runfiles_group_example//producer/rules:starlark_library.bzl", "starlark_library") - -copy_file( - name = "implementation_src", - src = "@sha256.bzl//:sha256.star", - out = "sha256.star", -) - -starlark_library( - name = "sha256", - srcs = ["sha256.star"], - repository = "std", - visibility = ["//visibility:public"], -) diff --git a/example/producer/stdlib_repo/strings/strings.star b/example/producer/stdlib_repo/strings/strings.star new file mode 100644 index 0000000..e1cd89e --- /dev/null +++ b/example/producer/stdlib_repo/strings/strings.star @@ -0,0 +1,58 @@ +def join(separator, items): + result = "" + for i, item in enumerate(items): + if i > 0: + result += separator + result += str(item) + return result + +def split(s, separator): + parts = [] + sep_len = len(separator) + start = 0 + for i in range(len(s)): + if i < start: + continue + if s[i:i + sep_len] == separator: + parts.append(s[start:i]) + start = i + sep_len + parts.append(s[start:]) + return parts + +def trim(s): + start = 0 + end = len(s) + for i in range(len(s)): + if s[i] != " " and s[i] != "\t" and s[i] != "\n": + start = i + break + for i in range(len(s) - 1, -1, -1): + if s[i] != " " and s[i] != "\t" and s[i] != "\n": + end = i + 1 + break + return s[start:end] + +def repeat(s, n): + result = "" + for _ in range(n): + result += s + return result + +def pad_left(s, width, fill = " "): + if len(s) < width: + s = repeat(fill, width - len(s)) + s + return s + +def pad_right(s, width, fill = " "): + if len(s) < width: + s = s + repeat(fill, width - len(s)) + return s + +def contains(s, substr): + return s.find(substr) >= 0 + +def starts_with(s, prefix): + return s[:len(prefix)] == prefix + +def ends_with(s, suffix): + return s[len(s) - len(suffix):] == suffix diff --git a/example/src/BUILD.bazel b/example/src/BUILD.bazel index 911d48f..34da65e 100644 --- a/example/src/BUILD.bazel +++ b/example/src/BUILD.bazel @@ -81,6 +81,18 @@ starlark_binary( ], ) +starlark_binary( + name = "merge_demo", + src = "merge_demo.star", + deps = [ + "@colors", + "@limits", + "@mathlib", + "@templates", + "@units", + ], +) + fake_package( name = "adder_pkg", binary = ":adder", @@ -108,5 +120,178 @@ runfiles_group_analysis_test( ":adder_without_interpreter", ":hasher", ":3p_deps_demo", + ":merge_demo", + ], +) + +# Per-binary tests: ordering without group limits + +runfiles_group_analysis_test( + name = "test_adder_groups", + binaries = [":adder"], + expected_group_names = [ + "interpreter", + "std", + "//src:lib_a", + "//src:lib_b", + "entrypoint", + ], + overlapping_group_behavior = "error", +) + +runfiles_group_analysis_test( + name = "test_hasher_groups", + binaries = [":hasher"], + expected_group_names = [ + "interpreter", + "std", + "_main", + ], + overlapping_group_behavior = "error", +) + +runfiles_group_analysis_test( + name = "test_3p_deps_demo_groups", + binaries = [":3p_deps_demo"], + expected_group_names = [ + "interpreter", + "std", + "fizzbuzz", + "stringutil", + "_main", + ], + overlapping_group_behavior = "error", +) + +# Per-binary tests: ordering with group limits + +runfiles_group_analysis_test( + name = "test_adder_groups_merged", + binaries = [":adder"], + expected_group_names = [ + "interpreter", + "std", + "//src:lib_a+//src:lib_b", + "entrypoint", + ], + max_groups = 4, + overlapping_group_behavior = "error", +) + +runfiles_group_analysis_test( + name = "test_hasher_groups_merged", + binaries = [":hasher"], + # All groups are alone in their rank or do_not_merge, + # so merging cannot reduce below 3. + expected_group_count = 3, + expected_group_names = [ + "interpreter", + "std", + "_main", + ], + max_groups = 2, + overlapping_group_behavior = "error", +) + +runfiles_group_analysis_test( + name = "test_3p_deps_demo_groups_merged", + binaries = [":3p_deps_demo"], + # fizzbuzz and stringutil (both rank 0) merge into fizzbuzz+stringutil. + expected_group_names = [ + "interpreter", + "std", + "fizzbuzz+stringutil", + "_main", + ], + max_groups = 4, + overlapping_group_behavior = "error", +) + +# merge_demo tests: 8 groups total +# rank -2: interpreter (do_not_merge) +# rank -1: std +# rank 0: colors(42), limits(43), units(40), mathlib(2296), templates(7092) +# rank 1: _main + +fake_package( + name = "merge_demo_pkg", + binary = ":merge_demo", +) + +runfiles_group_analysis_test( + name = "test_merge_demo_groups", + binaries = [":merge_demo"], + expected_group_names = [ + "interpreter", + "std", + "colors", + "limits", + "mathlib", + "templates", + "units", + "_main", + ], + overlapping_group_behavior = "error", +) + +# max_groups=6: merge the 3 tiny constant libs +# units(40)+colors(42) -> "units+colors"(82), then limits(43)+"units+colors"(82) -> "limits+units+colors"(125) +runfiles_group_analysis_test( + name = "test_merge_demo_max6", + binaries = [":merge_demo"], + expected_group_names = [ + "interpreter", + "std", + "limits+units+colors", + "mathlib", + "templates", + "_main", + ], + max_groups = 6, + overlapping_group_behavior = "error", +) + +# max_groups=5: also merges "limits+units+colors"(125) into mathlib(2296) +runfiles_group_analysis_test( + name = "test_merge_demo_max5", + binaries = [":merge_demo"], + expected_group_names = [ + "interpreter", + "std", + "limits+units+colors+mathlib", + "templates", + "_main", + ], + max_groups = 5, + overlapping_group_behavior = "error", +) + +# max_groups=4: also merges into templates, leaving one rank-0 group +runfiles_group_analysis_test( + name = "test_merge_demo_max4", + binaries = [":merge_demo"], + expected_group_names = [ + "interpreter", + "std", + "limits+units+colors+mathlib+templates", + "_main", + ], + max_groups = 4, + overlapping_group_behavior = "error", +) + +# max_groups=3: cannot reduce further (interpreter is do_not_merge, +# remaining groups are each alone in their rank) +runfiles_group_analysis_test( + name = "test_merge_demo_max3", + binaries = [":merge_demo"], + expected_group_count = 4, + expected_group_names = [ + "interpreter", + "std", + "limits+units+colors+mathlib+templates", + "_main", ], + max_groups = 3, + overlapping_group_behavior = "error", ) diff --git a/example/src/merge_demo.star b/example/src/merge_demo.star new file mode 100644 index 0000000..9825618 --- /dev/null +++ b/example/src/merge_demo.star @@ -0,0 +1,46 @@ +load("@colors//:colors.star", "BLUE", "GREEN", "RED") +load("@limits//:limits.star", "MAX_INT", "MIN_INT") +load("@mathlib//:constants.star", "E", "PI") +load("@mathlib//arithmetic:add.star", "sum_list") +load("@mathlib//arithmetic:multiply.star", "factorial", "power") +load("@mathlib//geometry:circle.star", "circle_area", "circle_circumference") +load("@mathlib//geometry/shapes:rectangle.star", "rectangle_area", "rectangle_perimeter") +load("@templates//:css.star", "color", "reset_css") +load("@templates//:html.star", "document", "heading", "list_items", "paragraph", "table") +load("@units//:units.star", "CM_PER_INCH", "KG_PER_LB") + +print("=== Math Demo ===") +print("PI = %s, E = %s" % (PI, E)) +print("sum([1,2,3,4,5]) = %d" % sum_list([1, 2, 3, 4, 5])) +print("5! = %d" % factorial(5)) +print("2^10 = %d" % power(2, 10)) +print("circle area (r=5) = %s" % circle_area(5)) +print("circle circumference (r=5) = %s" % circle_circumference(5)) +print("rectangle area (3x4) = %d" % rectangle_area(3, 4)) +print("rectangle perimeter (3x4) = %d" % rectangle_perimeter(3, 4)) + +print("\n=== Constants ===") +print("Colors: %s, %s, %s" % (RED, GREEN, BLUE)) +print("1 inch = %s cm" % CM_PER_INCH) +print("1 lb = %s kg" % KG_PER_LB) +print("int range: [%d, %d]" % (MIN_INT, MAX_INT)) + +print("\n=== Template Demo ===") +print(reset_css()) +print(color("coral")) +html = document("Demo", "\n".join([ + heading(1, "Merge Test"), + paragraph("Testing runfiles group merging with many deps."), + list_items(["mathlib", "templates", "colors", "units", "limits"]), + table( + ["Library", "Type"], + [ + ["mathlib", "large nested"], + ["templates", "large flat"], + ["colors", "tiny constants"], + ["units", "tiny constants"], + ["limits", "tiny constants"], + ], + ), +])) +print(html) diff --git a/example/third_party/colors/REPO.bazel b/example/third_party/colors/REPO.bazel new file mode 100644 index 0000000..60a7d8e --- /dev/null +++ b/example/third_party/colors/REPO.bazel @@ -0,0 +1 @@ +# This is the root of the "@colors" repo. diff --git a/example/third_party/colors/colors.star b/example/third_party/colors/colors.star new file mode 100644 index 0000000..2a7c23f --- /dev/null +++ b/example/third_party/colors/colors.star @@ -0,0 +1,3 @@ +RED = "red" +GREEN = "green" +BLUE = "blue" diff --git a/example/third_party/fizzbuzz/BUILD.bazel b/example/third_party/fizzbuzz/BUILD.bazel deleted file mode 100644 index db01e76..0000000 --- a/example/third_party/fizzbuzz/BUILD.bazel +++ /dev/null @@ -1,8 +0,0 @@ -load("@rules_runfiles_group_example//producer/rules:starlark_library.bzl", "starlark_library") - -starlark_library( - name = "fizzbuzz", - srcs = ["fizzbuzz.star"], - repository = "fizzbuzz", - visibility = ["//visibility:public"], -) diff --git a/example/third_party/fizzbuzz/MODULE.bazel b/example/third_party/fizzbuzz/MODULE.bazel deleted file mode 100644 index 00bb183..0000000 --- a/example/third_party/fizzbuzz/MODULE.bazel +++ /dev/null @@ -1,6 +0,0 @@ -############################################################################### -# Bazel now uses Bzlmod by default to manage external dependencies. -# Please consider migrating your external dependencies from WORKSPACE to MODULE.bazel. -# -# For more details, please check https://github.com/bazelbuild/bazel/issues/18958 -############################################################################### diff --git a/example/third_party/fizzbuzz/MODULE.bazel.lock b/example/third_party/fizzbuzz/MODULE.bazel.lock deleted file mode 100644 index 23f8dcf..0000000 --- a/example/third_party/fizzbuzz/MODULE.bazel.lock +++ /dev/null @@ -1,192 +0,0 @@ -{ - "lockFileVersion": 26, - "registryFileHashes": { - "https://bcr.bazel.build/bazel_registry.json": "8a28e4aff06ee60aed2a8c281907fb8bcbf3b753c91fb5a5c57da3215d5b3497", - "https://bcr.bazel.build/modules/abseil-cpp/20210324.2/MODULE.bazel": "7cd0312e064fde87c8d1cd79ba06c876bd23630c83466e9500321be55c96ace2", - "https://bcr.bazel.build/modules/abseil-cpp/20211102.0/MODULE.bazel": "70390338f7a5106231d20620712f7cccb659cd0e9d073d1991c038eb9fc57589", - "https://bcr.bazel.build/modules/abseil-cpp/20230125.1/MODULE.bazel": "89047429cb0207707b2dface14ba7f8df85273d484c2572755be4bab7ce9c3a0", - "https://bcr.bazel.build/modules/abseil-cpp/20230802.0.bcr.1/MODULE.bazel": "1c8cec495288dccd14fdae6e3f95f772c1c91857047a098fad772034264cc8cb", - "https://bcr.bazel.build/modules/abseil-cpp/20230802.0/MODULE.bazel": "d253ae36a8bd9ee3c5955384096ccb6baf16a1b1e93e858370da0a3b94f77c16", - "https://bcr.bazel.build/modules/abseil-cpp/20230802.1/MODULE.bazel": "fa92e2eb41a04df73cdabeec37107316f7e5272650f81d6cc096418fe647b915", - "https://bcr.bazel.build/modules/abseil-cpp/20240116.1/MODULE.bazel": "37bcdb4440fbb61df6a1c296ae01b327f19e9bb521f9b8e26ec854b6f97309ed", - "https://bcr.bazel.build/modules/abseil-cpp/20240116.2/MODULE.bazel": "73939767a4686cd9a520d16af5ab440071ed75cec1a876bf2fcfaf1f71987a16", - "https://bcr.bazel.build/modules/abseil-cpp/20250127.1/MODULE.bazel": "c4a89e7ceb9bf1e25cf84a9f830ff6b817b72874088bf5141b314726e46a57c1", - "https://bcr.bazel.build/modules/abseil-cpp/20250512.1/MODULE.bazel": "d209fdb6f36ffaf61c509fcc81b19e81b411a999a934a032e10cd009a0226215", - "https://bcr.bazel.build/modules/abseil-cpp/20250814.1/MODULE.bazel": "51f2312901470cdab0dbdf3b88c40cd21c62a7ed58a3de45b365ddc5b11bcab2", - "https://bcr.bazel.build/modules/abseil-cpp/20250814.1/source.json": "cea3901d7e299da7320700abbaafe57a65d039f10d0d7ea601c4a66938ea4b0c", - "https://bcr.bazel.build/modules/apple_support/1.11.1/MODULE.bazel": "1843d7cd8a58369a444fc6000e7304425fba600ff641592161d9f15b179fb896", - "https://bcr.bazel.build/modules/apple_support/1.15.1/MODULE.bazel": "a0556fefca0b1bb2de8567b8827518f94db6a6e7e7d632b4c48dc5f865bc7c85", - "https://bcr.bazel.build/modules/apple_support/1.21.0/MODULE.bazel": "ac1824ed5edf17dee2fdd4927ada30c9f8c3b520be1b5fd02a5da15bc10bff3e", - "https://bcr.bazel.build/modules/apple_support/1.21.1/MODULE.bazel": "5809fa3efab15d1f3c3c635af6974044bac8a4919c62238cce06acee8a8c11f1", - "https://bcr.bazel.build/modules/apple_support/1.24.2/MODULE.bazel": "0e62471818affb9f0b26f128831d5c40b074d32e6dda5a0d3852847215a41ca4", - "https://bcr.bazel.build/modules/apple_support/1.24.2/source.json": "2c22c9827093250406c5568da6c54e6fdf0ef06238def3d99c71b12feb057a8d", - "https://bcr.bazel.build/modules/bazel_features/1.1.1/MODULE.bazel": "27b8c79ef57efe08efccbd9dd6ef70d61b4798320b8d3c134fd571f78963dbcd", - "https://bcr.bazel.build/modules/bazel_features/1.10.0/MODULE.bazel": "f75e8807570484a99be90abcd52b5e1f390362c258bcb73106f4544957a48101", - "https://bcr.bazel.build/modules/bazel_features/1.11.0/MODULE.bazel": "f9382337dd5a474c3b7d334c2f83e50b6eaedc284253334cf823044a26de03e8", - "https://bcr.bazel.build/modules/bazel_features/1.15.0/MODULE.bazel": "d38ff6e517149dc509406aca0db3ad1efdd890a85e049585b7234d04238e2a4d", - "https://bcr.bazel.build/modules/bazel_features/1.17.0/MODULE.bazel": "039de32d21b816b47bd42c778e0454217e9c9caac4a3cf8e15c7231ee3ddee4d", - "https://bcr.bazel.build/modules/bazel_features/1.18.0/MODULE.bazel": "1be0ae2557ab3a72a57aeb31b29be347bcdc5d2b1eb1e70f39e3851a7e97041a", - "https://bcr.bazel.build/modules/bazel_features/1.19.0/MODULE.bazel": "59adcdf28230d220f0067b1f435b8537dd033bfff8db21335ef9217919c7fb58", - "https://bcr.bazel.build/modules/bazel_features/1.21.0/MODULE.bazel": "675642261665d8eea09989aa3b8afb5c37627f1be178382c320d1b46afba5e3b", - "https://bcr.bazel.build/modules/bazel_features/1.23.0/MODULE.bazel": "fd1ac84bc4e97a5a0816b7fd7d4d4f6d837b0047cf4cbd81652d616af3a6591a", - "https://bcr.bazel.build/modules/bazel_features/1.27.0/MODULE.bazel": "621eeee06c4458a9121d1f104efb80f39d34deff4984e778359c60eaf1a8cb65", - "https://bcr.bazel.build/modules/bazel_features/1.28.0/MODULE.bazel": "4b4200e6cbf8fa335b2c3f43e1d6ef3e240319c33d43d60cc0fbd4b87ece299d", - "https://bcr.bazel.build/modules/bazel_features/1.3.0/MODULE.bazel": "cdcafe83ec318cda34e02948e81d790aab8df7a929cec6f6969f13a489ccecd9", - "https://bcr.bazel.build/modules/bazel_features/1.30.0/MODULE.bazel": "a14b62d05969a293b80257e72e597c2da7f717e1e69fa8b339703ed6731bec87", - "https://bcr.bazel.build/modules/bazel_features/1.33.0/MODULE.bazel": "8b8dc9d2a4c88609409c3191165bccec0e4cb044cd7a72ccbe826583303459f6", - "https://bcr.bazel.build/modules/bazel_features/1.4.1/MODULE.bazel": "e45b6bb2350aff3e442ae1111c555e27eac1d915e77775f6fdc4b351b758b5d7", - "https://bcr.bazel.build/modules/bazel_features/1.42.1/MODULE.bazel": "275a59b5406ff18c01739860aa70ad7ccb3cfb474579411decca11c93b951080", - "https://bcr.bazel.build/modules/bazel_features/1.42.1/source.json": "fcd4396b2df85f64f2b3bb436ad870793ecf39180f1d796f913cc9276d355309", - "https://bcr.bazel.build/modules/bazel_features/1.9.1/MODULE.bazel": "8f679097876a9b609ad1f60249c49d68bfab783dd9be012faf9d82547b14815a", - "https://bcr.bazel.build/modules/bazel_skylib/1.0.3/MODULE.bazel": "bcb0fd896384802d1ad283b4e4eb4d718eebd8cb820b0a2c3a347fb971afd9d8", - "https://bcr.bazel.build/modules/bazel_skylib/1.1.1/MODULE.bazel": "1add3e7d93ff2e6998f9e118022c84d163917d912f5afafb3058e3d2f1545b5e", - "https://bcr.bazel.build/modules/bazel_skylib/1.2.0/MODULE.bazel": "44fe84260e454ed94ad326352a698422dbe372b21a1ac9f3eab76eb531223686", - "https://bcr.bazel.build/modules/bazel_skylib/1.2.1/MODULE.bazel": "f35baf9da0efe45fa3da1696ae906eea3d615ad41e2e3def4aeb4e8bc0ef9a7a", - "https://bcr.bazel.build/modules/bazel_skylib/1.3.0/MODULE.bazel": "20228b92868bf5cfc41bda7afc8a8ba2a543201851de39d990ec957b513579c5", - "https://bcr.bazel.build/modules/bazel_skylib/1.4.1/MODULE.bazel": "a0dcb779424be33100dcae821e9e27e4f2901d9dfd5333efe5ac6a8d7ab75e1d", - "https://bcr.bazel.build/modules/bazel_skylib/1.4.2/MODULE.bazel": "3bd40978e7a1fac911d5989e6b09d8f64921865a45822d8b09e815eaa726a651", - "https://bcr.bazel.build/modules/bazel_skylib/1.5.0/MODULE.bazel": "32880f5e2945ce6a03d1fbd588e9198c0a959bb42297b2cfaf1685b7bc32e138", - "https://bcr.bazel.build/modules/bazel_skylib/1.6.1/MODULE.bazel": "8fdee2dbaace6c252131c00e1de4b165dc65af02ea278476187765e1a617b917", - "https://bcr.bazel.build/modules/bazel_skylib/1.7.0/MODULE.bazel": "0db596f4563de7938de764cc8deeabec291f55e8ec15299718b93c4423e9796d", - "https://bcr.bazel.build/modules/bazel_skylib/1.7.1/MODULE.bazel": "3120d80c5861aa616222ec015332e5f8d3171e062e3e804a2a0253e1be26e59b", - "https://bcr.bazel.build/modules/bazel_skylib/1.8.1/MODULE.bazel": "88ade7293becda963e0e3ea33e7d54d3425127e0a326e0d17da085a5f1f03ff6", - "https://bcr.bazel.build/modules/bazel_skylib/1.8.2/MODULE.bazel": "69ad6927098316848b34a9142bcc975e018ba27f08c4ff403f50c1b6e646ca67", - "https://bcr.bazel.build/modules/bazel_skylib/1.8.2/source.json": "34a3c8bcf233b835eb74be9d628899bb32999d3e0eadef1947a0a562a2b16ffb", - "https://bcr.bazel.build/modules/buildozer/8.5.1/MODULE.bazel": "a35d9561b3fc5b18797c330793e99e3b834a473d5fbd3d7d7634aafc9bdb6f8f", - "https://bcr.bazel.build/modules/buildozer/8.5.1/source.json": "e3386e6ff4529f2442800dee47ad28d3e6487f36a1f75ae39ae56c70f0cd2fbd", - "https://bcr.bazel.build/modules/google_benchmark/1.8.2/MODULE.bazel": "a70cf1bba851000ba93b58ae2f6d76490a9feb74192e57ab8e8ff13c34ec50cb", - "https://bcr.bazel.build/modules/googletest/1.11.0/MODULE.bazel": "3a83f095183f66345ca86aa13c58b59f9f94a2f81999c093d4eeaa2d262d12f4", - "https://bcr.bazel.build/modules/googletest/1.14.0.bcr.1/MODULE.bazel": "22c31a561553727960057361aa33bf20fb2e98584bc4fec007906e27053f80c6", - "https://bcr.bazel.build/modules/googletest/1.14.0/MODULE.bazel": "cfbcbf3e6eac06ef9d85900f64424708cc08687d1b527f0ef65aa7517af8118f", - "https://bcr.bazel.build/modules/googletest/1.15.2/MODULE.bazel": "6de1edc1d26cafb0ea1a6ab3f4d4192d91a312fd2d360b63adaa213cd00b2108", - "https://bcr.bazel.build/modules/googletest/1.17.0/MODULE.bazel": "dbec758171594a705933a29fcf69293d2468c49ec1f2ebca65c36f504d72df46", - "https://bcr.bazel.build/modules/googletest/1.17.0/source.json": "38e4454b25fc30f15439c0378e57909ab1fd0a443158aa35aec685da727cd713", - "https://bcr.bazel.build/modules/jsoncpp/1.9.5/MODULE.bazel": "31271aedc59e815656f5736f282bb7509a97c7ecb43e927ac1a37966e0578075", - "https://bcr.bazel.build/modules/jsoncpp/1.9.6/MODULE.bazel": "2f8d20d3b7d54143213c4dfc3d98225c42de7d666011528dc8fe91591e2e17b0", - "https://bcr.bazel.build/modules/jsoncpp/1.9.6/source.json": "a04756d367a2126c3541682864ecec52f92cdee80a35735a3cb249ce015ca000", - "https://bcr.bazel.build/modules/libpfm/4.11.0/MODULE.bazel": "45061ff025b301940f1e30d2c16bea596c25b176c8b6b3087e92615adbd52902", - "https://bcr.bazel.build/modules/nlohmann_json/3.6.1/MODULE.bazel": "6f7b417dcc794d9add9e556673ad25cb3ba835224290f4f848f8e2db1e1fca74", - "https://bcr.bazel.build/modules/nlohmann_json/3.6.1/source.json": "f448c6e8963fdfa7eb831457df83ad63d3d6355018f6574fb017e8169deb43a9", - "https://bcr.bazel.build/modules/platforms/0.0.10/MODULE.bazel": "8cb8efaf200bdeb2150d93e162c40f388529a25852b332cec879373771e48ed5", - "https://bcr.bazel.build/modules/platforms/0.0.11/MODULE.bazel": "0daefc49732e227caa8bfa834d65dc52e8cc18a2faf80df25e8caea151a9413f", - "https://bcr.bazel.build/modules/platforms/0.0.4/MODULE.bazel": "9b328e31ee156f53f3c416a64f8491f7eb731742655a47c9eec4703a71644aee", - "https://bcr.bazel.build/modules/platforms/0.0.5/MODULE.bazel": "5733b54ea419d5eaf7997054bb55f6a1d0b5ff8aedf0176fef9eea44f3acda37", - "https://bcr.bazel.build/modules/platforms/0.0.6/MODULE.bazel": "ad6eeef431dc52aefd2d77ed20a4b353f8ebf0f4ecdd26a807d2da5aa8cd0615", - "https://bcr.bazel.build/modules/platforms/0.0.7/MODULE.bazel": "72fd4a0ede9ee5c021f6a8dd92b503e089f46c227ba2813ff183b71616034814", - "https://bcr.bazel.build/modules/platforms/0.0.8/MODULE.bazel": "9f142c03e348f6d263719f5074b21ef3adf0b139ee4c5133e2aa35664da9eb2d", - "https://bcr.bazel.build/modules/platforms/0.0.9/MODULE.bazel": "4a87a60c927b56ddd67db50c89acaa62f4ce2a1d2149ccb63ffd871d5ce29ebc", - "https://bcr.bazel.build/modules/platforms/1.0.0/MODULE.bazel": "f05feb42b48f1b3c225e4ccf351f367be0371411a803198ec34a389fb22aa580", - "https://bcr.bazel.build/modules/platforms/1.0.0/source.json": "f4ff1fd412e0246fd38c82328eb209130ead81d62dcd5a9e40910f867f733d96", - "https://bcr.bazel.build/modules/protobuf/21.7/MODULE.bazel": "a5a29bb89544f9b97edce05642fac225a808b5b7be74038ea3640fae2f8e66a7", - "https://bcr.bazel.build/modules/protobuf/27.0/MODULE.bazel": "7873b60be88844a0a1d8f80b9d5d20cfbd8495a689b8763e76c6372998d3f64c", - "https://bcr.bazel.build/modules/protobuf/29.0-rc2/MODULE.bazel": "6241d35983510143049943fc0d57937937122baf1b287862f9dc8590fc4c37df", - "https://bcr.bazel.build/modules/protobuf/29.0-rc3/MODULE.bazel": "33c2dfa286578573afc55a7acaea3cada4122b9631007c594bf0729f41c8de92", - "https://bcr.bazel.build/modules/protobuf/29.1/MODULE.bazel": "557c3457560ff49e122ed76c0bc3397a64af9574691cb8201b4e46d4ab2ecb95", - "https://bcr.bazel.build/modules/protobuf/3.19.0/MODULE.bazel": "6b5fbb433f760a99a22b18b6850ed5784ef0e9928a72668b66e4d7ccd47db9b0", - "https://bcr.bazel.build/modules/protobuf/32.1/MODULE.bazel": "89cd2866a9cb07fee9ff74c41ceace11554f32e0d849de4e23ac55515cfada4d", - "https://bcr.bazel.build/modules/protobuf/33.4/MODULE.bazel": "114775b816b38b6d0ca620450d6b02550c60ceedfdc8d9a229833b34a223dc42", - "https://bcr.bazel.build/modules/protobuf/33.4/source.json": "555f8686b4c7d6b5ba731fbea13bf656b4bfd9a7ff629c1d9d3f6e1d6155de79", - "https://bcr.bazel.build/modules/pybind11_bazel/2.11.1/MODULE.bazel": "88af1c246226d87e65be78ed49ecd1e6f5e98648558c14ce99176da041dc378e", - "https://bcr.bazel.build/modules/pybind11_bazel/2.12.0/MODULE.bazel": "e6f4c20442eaa7c90d7190d8dc539d0ab422f95c65a57cc59562170c58ae3d34", - "https://bcr.bazel.build/modules/pybind11_bazel/2.12.0/source.json": "6900fdc8a9e95866b8c0d4ad4aba4d4236317b5c1cd04c502df3f0d33afed680", - "https://bcr.bazel.build/modules/re2/2023-09-01/MODULE.bazel": "cb3d511531b16cfc78a225a9e2136007a48cf8a677e4264baeab57fe78a80206", - "https://bcr.bazel.build/modules/re2/2024-07-02.bcr.1/MODULE.bazel": "b4963dda9b31080be1905ef085ecd7dd6cd47c05c79b9cdf83ade83ab2ab271a", - "https://bcr.bazel.build/modules/re2/2024-07-02.bcr.1/source.json": "2ff292be6ef3340325ce8a045ecc326e92cbfab47c7cbab4bd85d28971b97ac4", - "https://bcr.bazel.build/modules/re2/2024-07-02/MODULE.bazel": "0eadc4395959969297cbcf31a249ff457f2f1d456228c67719480205aa306daa", - "https://bcr.bazel.build/modules/rules_android/0.1.1/MODULE.bazel": "48809ab0091b07ad0182defb787c4c5328bd3a278938415c00a7b69b50c4d3a8", - "https://bcr.bazel.build/modules/rules_android/0.1.1/source.json": "e6986b41626ee10bdc864937ffb6d6bf275bb5b9c65120e6137d56e6331f089e", - "https://bcr.bazel.build/modules/rules_apple/3.16.0/MODULE.bazel": "0d1caf0b8375942ce98ea944be754a18874041e4e0459401d925577624d3a54a", - "https://bcr.bazel.build/modules/rules_apple/4.1.0/MODULE.bazel": "76e10fd4a48038d3fc7c5dc6e63b7063bbf5304a2e3bd42edda6ec660eebea68", - "https://bcr.bazel.build/modules/rules_apple/4.1.0/source.json": "8ee81e1708756f81b343a5eb2b2f0b953f1d25c4ab3d4a68dc02754872e80715", - "https://bcr.bazel.build/modules/rules_cc/0.0.1/MODULE.bazel": "cb2aa0747f84c6c3a78dad4e2049c154f08ab9d166b1273835a8174940365647", - "https://bcr.bazel.build/modules/rules_cc/0.0.10/MODULE.bazel": "ec1705118f7eaedd6e118508d3d26deba2a4e76476ada7e0e3965211be012002", - "https://bcr.bazel.build/modules/rules_cc/0.0.13/MODULE.bazel": "0e8529ed7b323dad0775ff924d2ae5af7640b23553dfcd4d34344c7e7a867191", - "https://bcr.bazel.build/modules/rules_cc/0.0.15/MODULE.bazel": "6704c35f7b4a72502ee81f61bf88706b54f06b3cbe5558ac17e2e14666cd5dcc", - "https://bcr.bazel.build/modules/rules_cc/0.0.16/MODULE.bazel": "7661303b8fc1b4d7f532e54e9d6565771fea666fbdf839e0a86affcd02defe87", - "https://bcr.bazel.build/modules/rules_cc/0.0.17/MODULE.bazel": "2ae1d8f4238ec67d7185d8861cb0a2cdf4bc608697c331b95bf990e69b62e64a", - "https://bcr.bazel.build/modules/rules_cc/0.0.2/MODULE.bazel": "6915987c90970493ab97393024c156ea8fb9f3bea953b2f3ec05c34f19b5695c", - "https://bcr.bazel.build/modules/rules_cc/0.0.6/MODULE.bazel": "abf360251023dfe3efcef65ab9d56beefa8394d4176dd29529750e1c57eaa33f", - "https://bcr.bazel.build/modules/rules_cc/0.0.8/MODULE.bazel": "964c85c82cfeb6f3855e6a07054fdb159aced38e99a5eecf7bce9d53990afa3e", - "https://bcr.bazel.build/modules/rules_cc/0.0.9/MODULE.bazel": "836e76439f354b89afe6a911a7adf59a6b2518fafb174483ad78a2a2fde7b1c5", - "https://bcr.bazel.build/modules/rules_cc/0.1.1/MODULE.bazel": "2f0222a6f229f0bf44cd711dc13c858dad98c62d52bd51d8fc3a764a83125513", - "https://bcr.bazel.build/modules/rules_cc/0.1.2/MODULE.bazel": "557ddc3a96858ec0d465a87c0a931054d7dcfd6583af2c7ed3baf494407fd8d0", - "https://bcr.bazel.build/modules/rules_cc/0.1.5/MODULE.bazel": "88dfc9361e8b5ae1008ac38f7cdfd45ad738e4fa676a3ad67d19204f045a1fd8", - "https://bcr.bazel.build/modules/rules_cc/0.2.0/MODULE.bazel": "b5c17f90458caae90d2ccd114c81970062946f49f355610ed89bebf954f5783c", - "https://bcr.bazel.build/modules/rules_cc/0.2.13/MODULE.bazel": "eecdd666eda6be16a8d9dc15e44b5c75133405e820f620a234acc4b1fdc5aa37", - "https://bcr.bazel.build/modules/rules_cc/0.2.17/MODULE.bazel": "1849602c86cb60da8613d2de887f9566a6d354a6df6d7009f9d04a14402f9a84", - "https://bcr.bazel.build/modules/rules_cc/0.2.17/source.json": "3832f45d145354049137c0090df04629d9c2b5493dc5c2bf46f1834040133a07", - "https://bcr.bazel.build/modules/rules_cc/0.2.8/MODULE.bazel": "f1df20f0bf22c28192a794f29b501ee2018fa37a3862a1a2132ae2940a23a642", - "https://bcr.bazel.build/modules/rules_foreign_cc/0.9.0/MODULE.bazel": "c9e8c682bf75b0e7c704166d79b599f93b72cfca5ad7477df596947891feeef6", - "https://bcr.bazel.build/modules/rules_fuzzing/0.5.2/MODULE.bazel": "40c97d1144356f52905566c55811f13b299453a14ac7769dfba2ac38192337a8", - "https://bcr.bazel.build/modules/rules_java/4.0.0/MODULE.bazel": "5a78a7ae82cd1a33cef56dc578c7d2a46ed0dca12643ee45edbb8417899e6f74", - "https://bcr.bazel.build/modules/rules_java/5.3.5/MODULE.bazel": "a4ec4f2db570171e3e5eb753276ee4b389bae16b96207e9d3230895c99644b86", - "https://bcr.bazel.build/modules/rules_java/6.5.2/MODULE.bazel": "1d440d262d0e08453fa0c4d8f699ba81609ed0e9a9a0f02cd10b3e7942e61e31", - "https://bcr.bazel.build/modules/rules_java/7.10.0/MODULE.bazel": "530c3beb3067e870561739f1144329a21c851ff771cd752a49e06e3dc9c2e71a", - "https://bcr.bazel.build/modules/rules_java/7.12.2/MODULE.bazel": "579c505165ee757a4280ef83cda0150eea193eed3bef50b1004ba88b99da6de6", - "https://bcr.bazel.build/modules/rules_java/7.2.0/MODULE.bazel": "06c0334c9be61e6cef2c8c84a7800cef502063269a5af25ceb100b192453d4ab", - "https://bcr.bazel.build/modules/rules_java/7.6.1/MODULE.bazel": "2f14b7e8a1aa2f67ae92bc69d1ec0fa8d9f827c4e17ff5e5f02e91caa3b2d0fe", - "https://bcr.bazel.build/modules/rules_java/8.3.2/MODULE.bazel": "7336d5511ad5af0b8615fdc7477535a2e4e723a357b6713af439fe8cf0195017", - "https://bcr.bazel.build/modules/rules_java/8.5.1/MODULE.bazel": "d8a9e38cc5228881f7055a6079f6f7821a073df3744d441978e7a43e20226939", - "https://bcr.bazel.build/modules/rules_java/8.6.1/MODULE.bazel": "f4808e2ab5b0197f094cabce9f4b006a27766beb6a9975931da07099560ca9c2", - "https://bcr.bazel.build/modules/rules_java/9.1.0/MODULE.bazel": "ee63f27e36a3fada80342869361182f120a9819c74320e8e65b1e04ba0cd7a9d", - "https://bcr.bazel.build/modules/rules_java/9.1.0/source.json": "da589573c1dee2c9ac4a568b301269a2e8191110ff0345c1a959fa7ea6c4dfd6", - "https://bcr.bazel.build/modules/rules_jvm_external/4.4.2/MODULE.bazel": "a56b85e418c83eb1839819f0b515c431010160383306d13ec21959ac412d2fe7", - "https://bcr.bazel.build/modules/rules_jvm_external/5.1/MODULE.bazel": "33f6f999e03183f7d088c9be518a63467dfd0be94a11d0055fe2d210f89aa909", - "https://bcr.bazel.build/modules/rules_jvm_external/5.2/MODULE.bazel": "d9351ba35217ad0de03816ef3ed63f89d411349353077348a45348b096615036", - "https://bcr.bazel.build/modules/rules_jvm_external/6.3/MODULE.bazel": "c998e060b85f71e00de5ec552019347c8bca255062c990ac02d051bb80a38df0", - "https://bcr.bazel.build/modules/rules_jvm_external/6.7/MODULE.bazel": "e717beabc4d091ecb2c803c2d341b88590e9116b8bf7947915eeb33aab4f96dd", - "https://bcr.bazel.build/modules/rules_jvm_external/6.7/source.json": "5426f412d0a7fc6b611643376c7e4a82dec991491b9ce5cb1cfdd25fe2e92be4", - "https://bcr.bazel.build/modules/rules_kotlin/1.9.6/MODULE.bazel": "d269a01a18ee74d0335450b10f62c9ed81f2321d7958a2934e44272fe82dcef3", - "https://bcr.bazel.build/modules/rules_kotlin/1.9.6/source.json": "2faa4794364282db7c06600b7e5e34867a564ae91bda7cae7c29c64e9466b7d5", - "https://bcr.bazel.build/modules/rules_license/0.0.3/MODULE.bazel": "627e9ab0247f7d1e05736b59dbb1b6871373de5ad31c3011880b4133cafd4bd0", - "https://bcr.bazel.build/modules/rules_license/0.0.7/MODULE.bazel": "088fbeb0b6a419005b89cf93fe62d9517c0a2b8bb56af3244af65ecfe37e7d5d", - "https://bcr.bazel.build/modules/rules_license/1.0.0/MODULE.bazel": "a7fda60eefdf3d8c827262ba499957e4df06f659330bbe6cdbdb975b768bb65c", - "https://bcr.bazel.build/modules/rules_license/1.0.0/source.json": "a52c89e54cc311196e478f8382df91c15f7a2bfdf4c6cd0e2675cc2ff0b56efb", - "https://bcr.bazel.build/modules/rules_pkg/0.7.0/MODULE.bazel": "df99f03fc7934a4737122518bb87e667e62d780b610910f0447665a7e2be62dc", - "https://bcr.bazel.build/modules/rules_pkg/1.0.1/MODULE.bazel": "5b1df97dbc29623bccdf2b0dcd0f5cb08e2f2c9050aab1092fd39a41e82686ff", - "https://bcr.bazel.build/modules/rules_pkg/1.0.1/source.json": "bd82e5d7b9ce2d31e380dd9f50c111d678c3bdaca190cb76b0e1c71b05e1ba8a", - "https://bcr.bazel.build/modules/rules_proto/4.0.0/MODULE.bazel": "a7a7b6ce9bee418c1a760b3d84f83a299ad6952f9903c67f19e4edd964894e06", - "https://bcr.bazel.build/modules/rules_proto/5.3.0-21.7/MODULE.bazel": "e8dff86b0971688790ae75528fe1813f71809b5afd57facb44dad9e8eca631b7", - "https://bcr.bazel.build/modules/rules_proto/6.0.0-rc1/MODULE.bazel": "1e5b502e2e1a9e825eef74476a5a1ee524a92297085015a052510b09a1a09483", - "https://bcr.bazel.build/modules/rules_proto/6.0.2/MODULE.bazel": "ce916b775a62b90b61888052a416ccdda405212b6aaeb39522f7dc53431a5e73", - "https://bcr.bazel.build/modules/rules_proto/7.1.0/MODULE.bazel": "002d62d9108f75bb807cd56245d45648f38275cb3a99dcd45dfb864c5d74cb96", - "https://bcr.bazel.build/modules/rules_proto/7.1.0/source.json": "39f89066c12c24097854e8f57ab8558929f9c8d474d34b2c00ac04630ad8940e", - "https://bcr.bazel.build/modules/rules_python/0.10.2/MODULE.bazel": "cc82bc96f2997baa545ab3ce73f196d040ffb8756fd2d66125a530031cd90e5f", - "https://bcr.bazel.build/modules/rules_python/0.23.1/MODULE.bazel": "49ffccf0511cb8414de28321f5fcf2a31312b47c40cc21577144b7447f2bf300", - "https://bcr.bazel.build/modules/rules_python/0.25.0/MODULE.bazel": "72f1506841c920a1afec76975b35312410eea3aa7b63267436bfb1dd91d2d382", - "https://bcr.bazel.build/modules/rules_python/0.28.0/MODULE.bazel": "cba2573d870babc976664a912539b320cbaa7114cd3e8f053c720171cde331ed", - "https://bcr.bazel.build/modules/rules_python/0.31.0/MODULE.bazel": "93a43dc47ee570e6ec9f5779b2e64c1476a6ce921c48cc9a1678a91dd5f8fd58", - "https://bcr.bazel.build/modules/rules_python/0.33.2/MODULE.bazel": "3e036c4ad8d804a4dad897d333d8dce200d943df4827cb849840055be8d2e937", - "https://bcr.bazel.build/modules/rules_python/0.4.0/MODULE.bazel": "9208ee05fd48bf09ac60ed269791cf17fb343db56c8226a720fbb1cdf467166c", - "https://bcr.bazel.build/modules/rules_python/1.3.0/MODULE.bazel": "8361d57eafb67c09b75bf4bbe6be360e1b8f4f18118ab48037f2bd50aa2ccb13", - "https://bcr.bazel.build/modules/rules_python/1.4.1/MODULE.bazel": "8991ad45bdc25018301d6b7e1d3626afc3c8af8aaf4bc04f23d0b99c938b73a6", - "https://bcr.bazel.build/modules/rules_python/1.6.0/MODULE.bazel": "7e04ad8f8d5bea40451cf80b1bd8262552aa73f841415d20db96b7241bd027d8", - "https://bcr.bazel.build/modules/rules_python/1.7.0/MODULE.bazel": "d01f995ecd137abf30238ad9ce97f8fc3ac57289c8b24bd0bf53324d937a14f8", - "https://bcr.bazel.build/modules/rules_python/1.7.0/source.json": "028a084b65dcf8f4dc4f82f8778dbe65df133f234b316828a82e060d81bdce32", - "https://bcr.bazel.build/modules/rules_shell/0.2.0/MODULE.bazel": "fda8a652ab3c7d8fee214de05e7a9916d8b28082234e8d2c0094505c5268ed3c", - "https://bcr.bazel.build/modules/rules_shell/0.3.0/MODULE.bazel": "de4402cd12f4cc8fda2354fce179fdb068c0b9ca1ec2d2b17b3e21b24c1a937b", - "https://bcr.bazel.build/modules/rules_shell/0.6.1/MODULE.bazel": "72e76b0eea4e81611ef5452aa82b3da34caca0c8b7b5c0c9584338aa93bae26b", - "https://bcr.bazel.build/modules/rules_shell/0.6.1/source.json": "20ec05cd5e592055e214b2da8ccb283c7f2a421ea0dc2acbf1aa792e11c03d0c", - "https://bcr.bazel.build/modules/rules_swift/1.16.0/MODULE.bazel": "4a09f199545a60d09895e8281362b1ff3bb08bbde69c6fc87aff5b92fcc916ca", - "https://bcr.bazel.build/modules/rules_swift/2.1.1/MODULE.bazel": "494900a80f944fc7aa61500c2073d9729dff0b764f0e89b824eb746959bc1046", - "https://bcr.bazel.build/modules/rules_swift/2.4.0/MODULE.bazel": "1639617eb1ede28d774d967a738b4a68b0accb40650beadb57c21846beab5efd", - "https://bcr.bazel.build/modules/rules_swift/3.1.2/MODULE.bazel": "72c8f5cf9d26427cee6c76c8e3853eb46ce6b0412a081b2b6db6e8ad56267400", - "https://bcr.bazel.build/modules/rules_swift/3.1.2/source.json": "e85761f3098a6faf40b8187695e3de6d97944e98abd0d8ce579cb2daf6319a66", - "https://bcr.bazel.build/modules/stardoc/0.5.1/MODULE.bazel": "1a05d92974d0c122f5ccf09291442580317cdd859f07a8655f1db9a60374f9f8", - "https://bcr.bazel.build/modules/stardoc/0.5.3/MODULE.bazel": "c7f6948dae6999bf0db32c1858ae345f112cacf98f174c7a8bb707e41b974f1c", - "https://bcr.bazel.build/modules/stardoc/0.7.0/MODULE.bazel": "05e3d6d30c099b6770e97da986c53bd31844d7f13d41412480ea265ac9e8079c", - "https://bcr.bazel.build/modules/stardoc/0.7.2/MODULE.bazel": "fc152419aa2ea0f51c29583fab1e8c99ddefd5b3778421845606ee628629e0e5", - "https://bcr.bazel.build/modules/stardoc/0.7.2/source.json": "58b029e5e901d6802967754adf0a9056747e8176f017cfe3607c0851f4d42216", - "https://bcr.bazel.build/modules/swift_argument_parser/1.3.1.1/MODULE.bazel": "5e463fbfba7b1701d957555ed45097d7f984211330106ccd1352c6e0af0dcf91", - "https://bcr.bazel.build/modules/swift_argument_parser/1.3.1.2/MODULE.bazel": "75aab2373a4bbe2a1260b9bf2a1ebbdbf872d3bd36f80bff058dccd82e89422f", - "https://bcr.bazel.build/modules/swift_argument_parser/1.3.1.2/source.json": "5fba48bbe0ba48761f9e9f75f92876cafb5d07c0ce059cc7a8027416de94a05b", - "https://bcr.bazel.build/modules/upb/0.0.0-20220923-a547704/MODULE.bazel": "7298990c00040a0e2f121f6c32544bab27d4452f80d9ce51349b1a28f3005c43", - "https://bcr.bazel.build/modules/zlib/1.2.11/MODULE.bazel": "07b389abc85fdbca459b69e2ec656ae5622873af3f845e1c9d80fe179f3effa0", - "https://bcr.bazel.build/modules/zlib/1.3.1.bcr.5/MODULE.bazel": "eec517b5bbe5492629466e11dae908d043364302283de25581e3eb944326c4ca", - "https://bcr.bazel.build/modules/zlib/1.3.1.bcr.5/source.json": "22bc55c47af97246cfc093d0acf683a7869377de362b5d1c552c2c2e16b7a806", - "https://bcr.bazel.build/modules/zlib/1.3.1/MODULE.bazel": "751c9940dcfe869f5f7274e1295422a34623555916eb98c174c1e945594bf198" - }, - "selectedYankedVersions": {}, - "moduleExtensions": {}, - "facts": {} -} diff --git a/example/third_party/limits/REPO.bazel b/example/third_party/limits/REPO.bazel new file mode 100644 index 0000000..7b604fd --- /dev/null +++ b/example/third_party/limits/REPO.bazel @@ -0,0 +1 @@ +# This is the root of the "@limits" repo. diff --git a/example/third_party/limits/limits.star b/example/third_party/limits/limits.star new file mode 100644 index 0000000..5c0fc1b --- /dev/null +++ b/example/third_party/limits/limits.star @@ -0,0 +1,2 @@ +MAX_INT = 2147483647 +MIN_INT = -2147483648 diff --git a/example/third_party/mathlib/REPO.bazel b/example/third_party/mathlib/REPO.bazel new file mode 100644 index 0000000..7ea98c9 --- /dev/null +++ b/example/third_party/mathlib/REPO.bazel @@ -0,0 +1 @@ +# This is the root of the "@mathlib" repo. diff --git a/example/third_party/mathlib/arithmetic/add.star b/example/third_party/mathlib/arithmetic/add.star new file mode 100644 index 0000000..e6cf3e6 --- /dev/null +++ b/example/third_party/mathlib/arithmetic/add.star @@ -0,0 +1,22 @@ +def add(a, b): + return a + b + +def subtract(a, b): + return a - b + +def negate(a): + return -a + +def sum_list(items): + result = 0 + for item in items: + result = result + item + return result + +def running_sum(items): + result = [] + total = 0 + for item in items: + total = total + item + result.append(total) + return result diff --git a/example/third_party/mathlib/arithmetic/multiply.star b/example/third_party/mathlib/arithmetic/multiply.star new file mode 100644 index 0000000..9b0a597 --- /dev/null +++ b/example/third_party/mathlib/arithmetic/multiply.star @@ -0,0 +1,27 @@ +def multiply(a, b): + return a * b + +def divide(a, b): + if b == 0: + fail("division by zero") + return a / b + +def power(base, exp): + result = 1 + for _ in range(exp): + result = result * base + return result + +def factorial(n): + if n < 0: + fail("factorial of negative number") + result = 1 + for i in range(1, n + 1): + result = result * i + return result + +def product_list(items): + result = 1 + for item in items: + result = result * item + return result diff --git a/example/third_party/mathlib/constants.star b/example/third_party/mathlib/constants.star new file mode 100644 index 0000000..0c1744e --- /dev/null +++ b/example/third_party/mathlib/constants.star @@ -0,0 +1,14 @@ +PI = 3.14159265358979323846 +E = 2.71828182845904523536 +TAU = 6.28318530717958647692 +GOLDEN_RATIO = 1.61803398874989484820 + +def clamp(value, low, high): + if value < low: + return low + if value > high: + return high + return value + +def lerp(a, b, t): + return a + (b - a) * t diff --git a/example/third_party/mathlib/geometry/circle.star b/example/third_party/mathlib/geometry/circle.star new file mode 100644 index 0000000..77453e2 --- /dev/null +++ b/example/third_party/mathlib/geometry/circle.star @@ -0,0 +1,12 @@ +load("@mathlib//:math_utils.star", "sqrt") + +def circle_area(radius): + return 3.14159265358979 * radius * radius + +def circle_circumference(radius): + return 2 * 3.14159265358979 * radius + +def point_distance(x1, y1, x2, y2): + dx = x2 - x1 + dy = y2 - y1 + return sqrt(dx * dx + dy * dy) diff --git a/example/third_party/mathlib/geometry/shapes/rectangle.star b/example/third_party/mathlib/geometry/shapes/rectangle.star new file mode 100644 index 0000000..288fc30 --- /dev/null +++ b/example/third_party/mathlib/geometry/shapes/rectangle.star @@ -0,0 +1,22 @@ +load("@mathlib//:math_utils.star", "sqrt") + +def rectangle_area(width, height): + return width * height + +def rectangle_perimeter(width, height): + return 2 * (width + height) + +def square_area(side): + return side * side + +def square_perimeter(side): + return 4 * side + +def is_square(width, height): + return width == height + +def scale_rectangle(width, height, factor): + return (width * factor, height * factor) + +def rectangle_diagonal(width, height): + return sqrt(width * width + height * height) diff --git a/example/third_party/mathlib/math_utils.star b/example/third_party/mathlib/math_utils.star new file mode 100644 index 0000000..9b0ba73 --- /dev/null +++ b/example/third_party/mathlib/math_utils.star @@ -0,0 +1,9 @@ +def sqrt(x): + if x < 0: + fail("sqrt of negative number") + if x == 0: + return 0 + guess = x / 2 + for _ in range(50): + guess = (guess + x / guess) / 2 + return guess diff --git a/example/third_party/stringutil/BUILD.bazel b/example/third_party/stringutil/BUILD.bazel deleted file mode 100644 index fa7a6b3..0000000 --- a/example/third_party/stringutil/BUILD.bazel +++ /dev/null @@ -1,8 +0,0 @@ -load("@rules_runfiles_group_example//producer/rules:starlark_library.bzl", "starlark_library") - -starlark_library( - name = "stringutil", - srcs = ["stringutil.star"], - repository = "stringutil", - visibility = ["//visibility:public"], -) diff --git a/example/third_party/stringutil/MODULE.bazel b/example/third_party/stringutil/MODULE.bazel deleted file mode 100644 index 00bb183..0000000 --- a/example/third_party/stringutil/MODULE.bazel +++ /dev/null @@ -1,6 +0,0 @@ -############################################################################### -# Bazel now uses Bzlmod by default to manage external dependencies. -# Please consider migrating your external dependencies from WORKSPACE to MODULE.bazel. -# -# For more details, please check https://github.com/bazelbuild/bazel/issues/18958 -############################################################################### diff --git a/example/third_party/stringutil/MODULE.bazel.lock b/example/third_party/stringutil/MODULE.bazel.lock deleted file mode 100644 index 23f8dcf..0000000 --- a/example/third_party/stringutil/MODULE.bazel.lock +++ /dev/null @@ -1,192 +0,0 @@ -{ - "lockFileVersion": 26, - "registryFileHashes": { - "https://bcr.bazel.build/bazel_registry.json": "8a28e4aff06ee60aed2a8c281907fb8bcbf3b753c91fb5a5c57da3215d5b3497", - "https://bcr.bazel.build/modules/abseil-cpp/20210324.2/MODULE.bazel": "7cd0312e064fde87c8d1cd79ba06c876bd23630c83466e9500321be55c96ace2", - "https://bcr.bazel.build/modules/abseil-cpp/20211102.0/MODULE.bazel": "70390338f7a5106231d20620712f7cccb659cd0e9d073d1991c038eb9fc57589", - "https://bcr.bazel.build/modules/abseil-cpp/20230125.1/MODULE.bazel": "89047429cb0207707b2dface14ba7f8df85273d484c2572755be4bab7ce9c3a0", - "https://bcr.bazel.build/modules/abseil-cpp/20230802.0.bcr.1/MODULE.bazel": "1c8cec495288dccd14fdae6e3f95f772c1c91857047a098fad772034264cc8cb", - "https://bcr.bazel.build/modules/abseil-cpp/20230802.0/MODULE.bazel": "d253ae36a8bd9ee3c5955384096ccb6baf16a1b1e93e858370da0a3b94f77c16", - "https://bcr.bazel.build/modules/abseil-cpp/20230802.1/MODULE.bazel": "fa92e2eb41a04df73cdabeec37107316f7e5272650f81d6cc096418fe647b915", - "https://bcr.bazel.build/modules/abseil-cpp/20240116.1/MODULE.bazel": "37bcdb4440fbb61df6a1c296ae01b327f19e9bb521f9b8e26ec854b6f97309ed", - "https://bcr.bazel.build/modules/abseil-cpp/20240116.2/MODULE.bazel": "73939767a4686cd9a520d16af5ab440071ed75cec1a876bf2fcfaf1f71987a16", - "https://bcr.bazel.build/modules/abseil-cpp/20250127.1/MODULE.bazel": "c4a89e7ceb9bf1e25cf84a9f830ff6b817b72874088bf5141b314726e46a57c1", - "https://bcr.bazel.build/modules/abseil-cpp/20250512.1/MODULE.bazel": "d209fdb6f36ffaf61c509fcc81b19e81b411a999a934a032e10cd009a0226215", - "https://bcr.bazel.build/modules/abseil-cpp/20250814.1/MODULE.bazel": "51f2312901470cdab0dbdf3b88c40cd21c62a7ed58a3de45b365ddc5b11bcab2", - "https://bcr.bazel.build/modules/abseil-cpp/20250814.1/source.json": "cea3901d7e299da7320700abbaafe57a65d039f10d0d7ea601c4a66938ea4b0c", - "https://bcr.bazel.build/modules/apple_support/1.11.1/MODULE.bazel": "1843d7cd8a58369a444fc6000e7304425fba600ff641592161d9f15b179fb896", - "https://bcr.bazel.build/modules/apple_support/1.15.1/MODULE.bazel": "a0556fefca0b1bb2de8567b8827518f94db6a6e7e7d632b4c48dc5f865bc7c85", - "https://bcr.bazel.build/modules/apple_support/1.21.0/MODULE.bazel": "ac1824ed5edf17dee2fdd4927ada30c9f8c3b520be1b5fd02a5da15bc10bff3e", - "https://bcr.bazel.build/modules/apple_support/1.21.1/MODULE.bazel": "5809fa3efab15d1f3c3c635af6974044bac8a4919c62238cce06acee8a8c11f1", - "https://bcr.bazel.build/modules/apple_support/1.24.2/MODULE.bazel": "0e62471818affb9f0b26f128831d5c40b074d32e6dda5a0d3852847215a41ca4", - "https://bcr.bazel.build/modules/apple_support/1.24.2/source.json": "2c22c9827093250406c5568da6c54e6fdf0ef06238def3d99c71b12feb057a8d", - "https://bcr.bazel.build/modules/bazel_features/1.1.1/MODULE.bazel": "27b8c79ef57efe08efccbd9dd6ef70d61b4798320b8d3c134fd571f78963dbcd", - "https://bcr.bazel.build/modules/bazel_features/1.10.0/MODULE.bazel": "f75e8807570484a99be90abcd52b5e1f390362c258bcb73106f4544957a48101", - "https://bcr.bazel.build/modules/bazel_features/1.11.0/MODULE.bazel": "f9382337dd5a474c3b7d334c2f83e50b6eaedc284253334cf823044a26de03e8", - "https://bcr.bazel.build/modules/bazel_features/1.15.0/MODULE.bazel": "d38ff6e517149dc509406aca0db3ad1efdd890a85e049585b7234d04238e2a4d", - "https://bcr.bazel.build/modules/bazel_features/1.17.0/MODULE.bazel": "039de32d21b816b47bd42c778e0454217e9c9caac4a3cf8e15c7231ee3ddee4d", - "https://bcr.bazel.build/modules/bazel_features/1.18.0/MODULE.bazel": "1be0ae2557ab3a72a57aeb31b29be347bcdc5d2b1eb1e70f39e3851a7e97041a", - "https://bcr.bazel.build/modules/bazel_features/1.19.0/MODULE.bazel": "59adcdf28230d220f0067b1f435b8537dd033bfff8db21335ef9217919c7fb58", - "https://bcr.bazel.build/modules/bazel_features/1.21.0/MODULE.bazel": "675642261665d8eea09989aa3b8afb5c37627f1be178382c320d1b46afba5e3b", - "https://bcr.bazel.build/modules/bazel_features/1.23.0/MODULE.bazel": "fd1ac84bc4e97a5a0816b7fd7d4d4f6d837b0047cf4cbd81652d616af3a6591a", - "https://bcr.bazel.build/modules/bazel_features/1.27.0/MODULE.bazel": "621eeee06c4458a9121d1f104efb80f39d34deff4984e778359c60eaf1a8cb65", - "https://bcr.bazel.build/modules/bazel_features/1.28.0/MODULE.bazel": "4b4200e6cbf8fa335b2c3f43e1d6ef3e240319c33d43d60cc0fbd4b87ece299d", - "https://bcr.bazel.build/modules/bazel_features/1.3.0/MODULE.bazel": "cdcafe83ec318cda34e02948e81d790aab8df7a929cec6f6969f13a489ccecd9", - "https://bcr.bazel.build/modules/bazel_features/1.30.0/MODULE.bazel": "a14b62d05969a293b80257e72e597c2da7f717e1e69fa8b339703ed6731bec87", - "https://bcr.bazel.build/modules/bazel_features/1.33.0/MODULE.bazel": "8b8dc9d2a4c88609409c3191165bccec0e4cb044cd7a72ccbe826583303459f6", - "https://bcr.bazel.build/modules/bazel_features/1.4.1/MODULE.bazel": "e45b6bb2350aff3e442ae1111c555e27eac1d915e77775f6fdc4b351b758b5d7", - "https://bcr.bazel.build/modules/bazel_features/1.42.1/MODULE.bazel": "275a59b5406ff18c01739860aa70ad7ccb3cfb474579411decca11c93b951080", - "https://bcr.bazel.build/modules/bazel_features/1.42.1/source.json": "fcd4396b2df85f64f2b3bb436ad870793ecf39180f1d796f913cc9276d355309", - "https://bcr.bazel.build/modules/bazel_features/1.9.1/MODULE.bazel": "8f679097876a9b609ad1f60249c49d68bfab783dd9be012faf9d82547b14815a", - "https://bcr.bazel.build/modules/bazel_skylib/1.0.3/MODULE.bazel": "bcb0fd896384802d1ad283b4e4eb4d718eebd8cb820b0a2c3a347fb971afd9d8", - "https://bcr.bazel.build/modules/bazel_skylib/1.1.1/MODULE.bazel": "1add3e7d93ff2e6998f9e118022c84d163917d912f5afafb3058e3d2f1545b5e", - "https://bcr.bazel.build/modules/bazel_skylib/1.2.0/MODULE.bazel": "44fe84260e454ed94ad326352a698422dbe372b21a1ac9f3eab76eb531223686", - "https://bcr.bazel.build/modules/bazel_skylib/1.2.1/MODULE.bazel": "f35baf9da0efe45fa3da1696ae906eea3d615ad41e2e3def4aeb4e8bc0ef9a7a", - "https://bcr.bazel.build/modules/bazel_skylib/1.3.0/MODULE.bazel": "20228b92868bf5cfc41bda7afc8a8ba2a543201851de39d990ec957b513579c5", - "https://bcr.bazel.build/modules/bazel_skylib/1.4.1/MODULE.bazel": "a0dcb779424be33100dcae821e9e27e4f2901d9dfd5333efe5ac6a8d7ab75e1d", - "https://bcr.bazel.build/modules/bazel_skylib/1.4.2/MODULE.bazel": "3bd40978e7a1fac911d5989e6b09d8f64921865a45822d8b09e815eaa726a651", - "https://bcr.bazel.build/modules/bazel_skylib/1.5.0/MODULE.bazel": "32880f5e2945ce6a03d1fbd588e9198c0a959bb42297b2cfaf1685b7bc32e138", - "https://bcr.bazel.build/modules/bazel_skylib/1.6.1/MODULE.bazel": "8fdee2dbaace6c252131c00e1de4b165dc65af02ea278476187765e1a617b917", - "https://bcr.bazel.build/modules/bazel_skylib/1.7.0/MODULE.bazel": "0db596f4563de7938de764cc8deeabec291f55e8ec15299718b93c4423e9796d", - "https://bcr.bazel.build/modules/bazel_skylib/1.7.1/MODULE.bazel": "3120d80c5861aa616222ec015332e5f8d3171e062e3e804a2a0253e1be26e59b", - "https://bcr.bazel.build/modules/bazel_skylib/1.8.1/MODULE.bazel": "88ade7293becda963e0e3ea33e7d54d3425127e0a326e0d17da085a5f1f03ff6", - "https://bcr.bazel.build/modules/bazel_skylib/1.8.2/MODULE.bazel": "69ad6927098316848b34a9142bcc975e018ba27f08c4ff403f50c1b6e646ca67", - "https://bcr.bazel.build/modules/bazel_skylib/1.8.2/source.json": "34a3c8bcf233b835eb74be9d628899bb32999d3e0eadef1947a0a562a2b16ffb", - "https://bcr.bazel.build/modules/buildozer/8.5.1/MODULE.bazel": "a35d9561b3fc5b18797c330793e99e3b834a473d5fbd3d7d7634aafc9bdb6f8f", - "https://bcr.bazel.build/modules/buildozer/8.5.1/source.json": "e3386e6ff4529f2442800dee47ad28d3e6487f36a1f75ae39ae56c70f0cd2fbd", - "https://bcr.bazel.build/modules/google_benchmark/1.8.2/MODULE.bazel": "a70cf1bba851000ba93b58ae2f6d76490a9feb74192e57ab8e8ff13c34ec50cb", - "https://bcr.bazel.build/modules/googletest/1.11.0/MODULE.bazel": "3a83f095183f66345ca86aa13c58b59f9f94a2f81999c093d4eeaa2d262d12f4", - "https://bcr.bazel.build/modules/googletest/1.14.0.bcr.1/MODULE.bazel": "22c31a561553727960057361aa33bf20fb2e98584bc4fec007906e27053f80c6", - "https://bcr.bazel.build/modules/googletest/1.14.0/MODULE.bazel": "cfbcbf3e6eac06ef9d85900f64424708cc08687d1b527f0ef65aa7517af8118f", - "https://bcr.bazel.build/modules/googletest/1.15.2/MODULE.bazel": "6de1edc1d26cafb0ea1a6ab3f4d4192d91a312fd2d360b63adaa213cd00b2108", - "https://bcr.bazel.build/modules/googletest/1.17.0/MODULE.bazel": "dbec758171594a705933a29fcf69293d2468c49ec1f2ebca65c36f504d72df46", - "https://bcr.bazel.build/modules/googletest/1.17.0/source.json": "38e4454b25fc30f15439c0378e57909ab1fd0a443158aa35aec685da727cd713", - "https://bcr.bazel.build/modules/jsoncpp/1.9.5/MODULE.bazel": "31271aedc59e815656f5736f282bb7509a97c7ecb43e927ac1a37966e0578075", - "https://bcr.bazel.build/modules/jsoncpp/1.9.6/MODULE.bazel": "2f8d20d3b7d54143213c4dfc3d98225c42de7d666011528dc8fe91591e2e17b0", - "https://bcr.bazel.build/modules/jsoncpp/1.9.6/source.json": "a04756d367a2126c3541682864ecec52f92cdee80a35735a3cb249ce015ca000", - "https://bcr.bazel.build/modules/libpfm/4.11.0/MODULE.bazel": "45061ff025b301940f1e30d2c16bea596c25b176c8b6b3087e92615adbd52902", - "https://bcr.bazel.build/modules/nlohmann_json/3.6.1/MODULE.bazel": "6f7b417dcc794d9add9e556673ad25cb3ba835224290f4f848f8e2db1e1fca74", - "https://bcr.bazel.build/modules/nlohmann_json/3.6.1/source.json": "f448c6e8963fdfa7eb831457df83ad63d3d6355018f6574fb017e8169deb43a9", - "https://bcr.bazel.build/modules/platforms/0.0.10/MODULE.bazel": "8cb8efaf200bdeb2150d93e162c40f388529a25852b332cec879373771e48ed5", - "https://bcr.bazel.build/modules/platforms/0.0.11/MODULE.bazel": "0daefc49732e227caa8bfa834d65dc52e8cc18a2faf80df25e8caea151a9413f", - "https://bcr.bazel.build/modules/platforms/0.0.4/MODULE.bazel": "9b328e31ee156f53f3c416a64f8491f7eb731742655a47c9eec4703a71644aee", - "https://bcr.bazel.build/modules/platforms/0.0.5/MODULE.bazel": "5733b54ea419d5eaf7997054bb55f6a1d0b5ff8aedf0176fef9eea44f3acda37", - "https://bcr.bazel.build/modules/platforms/0.0.6/MODULE.bazel": "ad6eeef431dc52aefd2d77ed20a4b353f8ebf0f4ecdd26a807d2da5aa8cd0615", - "https://bcr.bazel.build/modules/platforms/0.0.7/MODULE.bazel": "72fd4a0ede9ee5c021f6a8dd92b503e089f46c227ba2813ff183b71616034814", - "https://bcr.bazel.build/modules/platforms/0.0.8/MODULE.bazel": "9f142c03e348f6d263719f5074b21ef3adf0b139ee4c5133e2aa35664da9eb2d", - "https://bcr.bazel.build/modules/platforms/0.0.9/MODULE.bazel": "4a87a60c927b56ddd67db50c89acaa62f4ce2a1d2149ccb63ffd871d5ce29ebc", - "https://bcr.bazel.build/modules/platforms/1.0.0/MODULE.bazel": "f05feb42b48f1b3c225e4ccf351f367be0371411a803198ec34a389fb22aa580", - "https://bcr.bazel.build/modules/platforms/1.0.0/source.json": "f4ff1fd412e0246fd38c82328eb209130ead81d62dcd5a9e40910f867f733d96", - "https://bcr.bazel.build/modules/protobuf/21.7/MODULE.bazel": "a5a29bb89544f9b97edce05642fac225a808b5b7be74038ea3640fae2f8e66a7", - "https://bcr.bazel.build/modules/protobuf/27.0/MODULE.bazel": "7873b60be88844a0a1d8f80b9d5d20cfbd8495a689b8763e76c6372998d3f64c", - "https://bcr.bazel.build/modules/protobuf/29.0-rc2/MODULE.bazel": "6241d35983510143049943fc0d57937937122baf1b287862f9dc8590fc4c37df", - "https://bcr.bazel.build/modules/protobuf/29.0-rc3/MODULE.bazel": "33c2dfa286578573afc55a7acaea3cada4122b9631007c594bf0729f41c8de92", - "https://bcr.bazel.build/modules/protobuf/29.1/MODULE.bazel": "557c3457560ff49e122ed76c0bc3397a64af9574691cb8201b4e46d4ab2ecb95", - "https://bcr.bazel.build/modules/protobuf/3.19.0/MODULE.bazel": "6b5fbb433f760a99a22b18b6850ed5784ef0e9928a72668b66e4d7ccd47db9b0", - "https://bcr.bazel.build/modules/protobuf/32.1/MODULE.bazel": "89cd2866a9cb07fee9ff74c41ceace11554f32e0d849de4e23ac55515cfada4d", - "https://bcr.bazel.build/modules/protobuf/33.4/MODULE.bazel": "114775b816b38b6d0ca620450d6b02550c60ceedfdc8d9a229833b34a223dc42", - "https://bcr.bazel.build/modules/protobuf/33.4/source.json": "555f8686b4c7d6b5ba731fbea13bf656b4bfd9a7ff629c1d9d3f6e1d6155de79", - "https://bcr.bazel.build/modules/pybind11_bazel/2.11.1/MODULE.bazel": "88af1c246226d87e65be78ed49ecd1e6f5e98648558c14ce99176da041dc378e", - "https://bcr.bazel.build/modules/pybind11_bazel/2.12.0/MODULE.bazel": "e6f4c20442eaa7c90d7190d8dc539d0ab422f95c65a57cc59562170c58ae3d34", - "https://bcr.bazel.build/modules/pybind11_bazel/2.12.0/source.json": "6900fdc8a9e95866b8c0d4ad4aba4d4236317b5c1cd04c502df3f0d33afed680", - "https://bcr.bazel.build/modules/re2/2023-09-01/MODULE.bazel": "cb3d511531b16cfc78a225a9e2136007a48cf8a677e4264baeab57fe78a80206", - "https://bcr.bazel.build/modules/re2/2024-07-02.bcr.1/MODULE.bazel": "b4963dda9b31080be1905ef085ecd7dd6cd47c05c79b9cdf83ade83ab2ab271a", - "https://bcr.bazel.build/modules/re2/2024-07-02.bcr.1/source.json": "2ff292be6ef3340325ce8a045ecc326e92cbfab47c7cbab4bd85d28971b97ac4", - "https://bcr.bazel.build/modules/re2/2024-07-02/MODULE.bazel": "0eadc4395959969297cbcf31a249ff457f2f1d456228c67719480205aa306daa", - "https://bcr.bazel.build/modules/rules_android/0.1.1/MODULE.bazel": "48809ab0091b07ad0182defb787c4c5328bd3a278938415c00a7b69b50c4d3a8", - "https://bcr.bazel.build/modules/rules_android/0.1.1/source.json": "e6986b41626ee10bdc864937ffb6d6bf275bb5b9c65120e6137d56e6331f089e", - "https://bcr.bazel.build/modules/rules_apple/3.16.0/MODULE.bazel": "0d1caf0b8375942ce98ea944be754a18874041e4e0459401d925577624d3a54a", - "https://bcr.bazel.build/modules/rules_apple/4.1.0/MODULE.bazel": "76e10fd4a48038d3fc7c5dc6e63b7063bbf5304a2e3bd42edda6ec660eebea68", - "https://bcr.bazel.build/modules/rules_apple/4.1.0/source.json": "8ee81e1708756f81b343a5eb2b2f0b953f1d25c4ab3d4a68dc02754872e80715", - "https://bcr.bazel.build/modules/rules_cc/0.0.1/MODULE.bazel": "cb2aa0747f84c6c3a78dad4e2049c154f08ab9d166b1273835a8174940365647", - "https://bcr.bazel.build/modules/rules_cc/0.0.10/MODULE.bazel": "ec1705118f7eaedd6e118508d3d26deba2a4e76476ada7e0e3965211be012002", - "https://bcr.bazel.build/modules/rules_cc/0.0.13/MODULE.bazel": "0e8529ed7b323dad0775ff924d2ae5af7640b23553dfcd4d34344c7e7a867191", - "https://bcr.bazel.build/modules/rules_cc/0.0.15/MODULE.bazel": "6704c35f7b4a72502ee81f61bf88706b54f06b3cbe5558ac17e2e14666cd5dcc", - "https://bcr.bazel.build/modules/rules_cc/0.0.16/MODULE.bazel": "7661303b8fc1b4d7f532e54e9d6565771fea666fbdf839e0a86affcd02defe87", - "https://bcr.bazel.build/modules/rules_cc/0.0.17/MODULE.bazel": "2ae1d8f4238ec67d7185d8861cb0a2cdf4bc608697c331b95bf990e69b62e64a", - "https://bcr.bazel.build/modules/rules_cc/0.0.2/MODULE.bazel": "6915987c90970493ab97393024c156ea8fb9f3bea953b2f3ec05c34f19b5695c", - "https://bcr.bazel.build/modules/rules_cc/0.0.6/MODULE.bazel": "abf360251023dfe3efcef65ab9d56beefa8394d4176dd29529750e1c57eaa33f", - "https://bcr.bazel.build/modules/rules_cc/0.0.8/MODULE.bazel": "964c85c82cfeb6f3855e6a07054fdb159aced38e99a5eecf7bce9d53990afa3e", - "https://bcr.bazel.build/modules/rules_cc/0.0.9/MODULE.bazel": "836e76439f354b89afe6a911a7adf59a6b2518fafb174483ad78a2a2fde7b1c5", - "https://bcr.bazel.build/modules/rules_cc/0.1.1/MODULE.bazel": "2f0222a6f229f0bf44cd711dc13c858dad98c62d52bd51d8fc3a764a83125513", - "https://bcr.bazel.build/modules/rules_cc/0.1.2/MODULE.bazel": "557ddc3a96858ec0d465a87c0a931054d7dcfd6583af2c7ed3baf494407fd8d0", - "https://bcr.bazel.build/modules/rules_cc/0.1.5/MODULE.bazel": "88dfc9361e8b5ae1008ac38f7cdfd45ad738e4fa676a3ad67d19204f045a1fd8", - "https://bcr.bazel.build/modules/rules_cc/0.2.0/MODULE.bazel": "b5c17f90458caae90d2ccd114c81970062946f49f355610ed89bebf954f5783c", - "https://bcr.bazel.build/modules/rules_cc/0.2.13/MODULE.bazel": "eecdd666eda6be16a8d9dc15e44b5c75133405e820f620a234acc4b1fdc5aa37", - "https://bcr.bazel.build/modules/rules_cc/0.2.17/MODULE.bazel": "1849602c86cb60da8613d2de887f9566a6d354a6df6d7009f9d04a14402f9a84", - "https://bcr.bazel.build/modules/rules_cc/0.2.17/source.json": "3832f45d145354049137c0090df04629d9c2b5493dc5c2bf46f1834040133a07", - "https://bcr.bazel.build/modules/rules_cc/0.2.8/MODULE.bazel": "f1df20f0bf22c28192a794f29b501ee2018fa37a3862a1a2132ae2940a23a642", - "https://bcr.bazel.build/modules/rules_foreign_cc/0.9.0/MODULE.bazel": "c9e8c682bf75b0e7c704166d79b599f93b72cfca5ad7477df596947891feeef6", - "https://bcr.bazel.build/modules/rules_fuzzing/0.5.2/MODULE.bazel": "40c97d1144356f52905566c55811f13b299453a14ac7769dfba2ac38192337a8", - "https://bcr.bazel.build/modules/rules_java/4.0.0/MODULE.bazel": "5a78a7ae82cd1a33cef56dc578c7d2a46ed0dca12643ee45edbb8417899e6f74", - "https://bcr.bazel.build/modules/rules_java/5.3.5/MODULE.bazel": "a4ec4f2db570171e3e5eb753276ee4b389bae16b96207e9d3230895c99644b86", - "https://bcr.bazel.build/modules/rules_java/6.5.2/MODULE.bazel": "1d440d262d0e08453fa0c4d8f699ba81609ed0e9a9a0f02cd10b3e7942e61e31", - "https://bcr.bazel.build/modules/rules_java/7.10.0/MODULE.bazel": "530c3beb3067e870561739f1144329a21c851ff771cd752a49e06e3dc9c2e71a", - "https://bcr.bazel.build/modules/rules_java/7.12.2/MODULE.bazel": "579c505165ee757a4280ef83cda0150eea193eed3bef50b1004ba88b99da6de6", - "https://bcr.bazel.build/modules/rules_java/7.2.0/MODULE.bazel": "06c0334c9be61e6cef2c8c84a7800cef502063269a5af25ceb100b192453d4ab", - "https://bcr.bazel.build/modules/rules_java/7.6.1/MODULE.bazel": "2f14b7e8a1aa2f67ae92bc69d1ec0fa8d9f827c4e17ff5e5f02e91caa3b2d0fe", - "https://bcr.bazel.build/modules/rules_java/8.3.2/MODULE.bazel": "7336d5511ad5af0b8615fdc7477535a2e4e723a357b6713af439fe8cf0195017", - "https://bcr.bazel.build/modules/rules_java/8.5.1/MODULE.bazel": "d8a9e38cc5228881f7055a6079f6f7821a073df3744d441978e7a43e20226939", - "https://bcr.bazel.build/modules/rules_java/8.6.1/MODULE.bazel": "f4808e2ab5b0197f094cabce9f4b006a27766beb6a9975931da07099560ca9c2", - "https://bcr.bazel.build/modules/rules_java/9.1.0/MODULE.bazel": "ee63f27e36a3fada80342869361182f120a9819c74320e8e65b1e04ba0cd7a9d", - "https://bcr.bazel.build/modules/rules_java/9.1.0/source.json": "da589573c1dee2c9ac4a568b301269a2e8191110ff0345c1a959fa7ea6c4dfd6", - "https://bcr.bazel.build/modules/rules_jvm_external/4.4.2/MODULE.bazel": "a56b85e418c83eb1839819f0b515c431010160383306d13ec21959ac412d2fe7", - "https://bcr.bazel.build/modules/rules_jvm_external/5.1/MODULE.bazel": "33f6f999e03183f7d088c9be518a63467dfd0be94a11d0055fe2d210f89aa909", - "https://bcr.bazel.build/modules/rules_jvm_external/5.2/MODULE.bazel": "d9351ba35217ad0de03816ef3ed63f89d411349353077348a45348b096615036", - "https://bcr.bazel.build/modules/rules_jvm_external/6.3/MODULE.bazel": "c998e060b85f71e00de5ec552019347c8bca255062c990ac02d051bb80a38df0", - "https://bcr.bazel.build/modules/rules_jvm_external/6.7/MODULE.bazel": "e717beabc4d091ecb2c803c2d341b88590e9116b8bf7947915eeb33aab4f96dd", - "https://bcr.bazel.build/modules/rules_jvm_external/6.7/source.json": "5426f412d0a7fc6b611643376c7e4a82dec991491b9ce5cb1cfdd25fe2e92be4", - "https://bcr.bazel.build/modules/rules_kotlin/1.9.6/MODULE.bazel": "d269a01a18ee74d0335450b10f62c9ed81f2321d7958a2934e44272fe82dcef3", - "https://bcr.bazel.build/modules/rules_kotlin/1.9.6/source.json": "2faa4794364282db7c06600b7e5e34867a564ae91bda7cae7c29c64e9466b7d5", - "https://bcr.bazel.build/modules/rules_license/0.0.3/MODULE.bazel": "627e9ab0247f7d1e05736b59dbb1b6871373de5ad31c3011880b4133cafd4bd0", - "https://bcr.bazel.build/modules/rules_license/0.0.7/MODULE.bazel": "088fbeb0b6a419005b89cf93fe62d9517c0a2b8bb56af3244af65ecfe37e7d5d", - "https://bcr.bazel.build/modules/rules_license/1.0.0/MODULE.bazel": "a7fda60eefdf3d8c827262ba499957e4df06f659330bbe6cdbdb975b768bb65c", - "https://bcr.bazel.build/modules/rules_license/1.0.0/source.json": "a52c89e54cc311196e478f8382df91c15f7a2bfdf4c6cd0e2675cc2ff0b56efb", - "https://bcr.bazel.build/modules/rules_pkg/0.7.0/MODULE.bazel": "df99f03fc7934a4737122518bb87e667e62d780b610910f0447665a7e2be62dc", - "https://bcr.bazel.build/modules/rules_pkg/1.0.1/MODULE.bazel": "5b1df97dbc29623bccdf2b0dcd0f5cb08e2f2c9050aab1092fd39a41e82686ff", - "https://bcr.bazel.build/modules/rules_pkg/1.0.1/source.json": "bd82e5d7b9ce2d31e380dd9f50c111d678c3bdaca190cb76b0e1c71b05e1ba8a", - "https://bcr.bazel.build/modules/rules_proto/4.0.0/MODULE.bazel": "a7a7b6ce9bee418c1a760b3d84f83a299ad6952f9903c67f19e4edd964894e06", - "https://bcr.bazel.build/modules/rules_proto/5.3.0-21.7/MODULE.bazel": "e8dff86b0971688790ae75528fe1813f71809b5afd57facb44dad9e8eca631b7", - "https://bcr.bazel.build/modules/rules_proto/6.0.0-rc1/MODULE.bazel": "1e5b502e2e1a9e825eef74476a5a1ee524a92297085015a052510b09a1a09483", - "https://bcr.bazel.build/modules/rules_proto/6.0.2/MODULE.bazel": "ce916b775a62b90b61888052a416ccdda405212b6aaeb39522f7dc53431a5e73", - "https://bcr.bazel.build/modules/rules_proto/7.1.0/MODULE.bazel": "002d62d9108f75bb807cd56245d45648f38275cb3a99dcd45dfb864c5d74cb96", - "https://bcr.bazel.build/modules/rules_proto/7.1.0/source.json": "39f89066c12c24097854e8f57ab8558929f9c8d474d34b2c00ac04630ad8940e", - "https://bcr.bazel.build/modules/rules_python/0.10.2/MODULE.bazel": "cc82bc96f2997baa545ab3ce73f196d040ffb8756fd2d66125a530031cd90e5f", - "https://bcr.bazel.build/modules/rules_python/0.23.1/MODULE.bazel": "49ffccf0511cb8414de28321f5fcf2a31312b47c40cc21577144b7447f2bf300", - "https://bcr.bazel.build/modules/rules_python/0.25.0/MODULE.bazel": "72f1506841c920a1afec76975b35312410eea3aa7b63267436bfb1dd91d2d382", - "https://bcr.bazel.build/modules/rules_python/0.28.0/MODULE.bazel": "cba2573d870babc976664a912539b320cbaa7114cd3e8f053c720171cde331ed", - "https://bcr.bazel.build/modules/rules_python/0.31.0/MODULE.bazel": "93a43dc47ee570e6ec9f5779b2e64c1476a6ce921c48cc9a1678a91dd5f8fd58", - "https://bcr.bazel.build/modules/rules_python/0.33.2/MODULE.bazel": "3e036c4ad8d804a4dad897d333d8dce200d943df4827cb849840055be8d2e937", - "https://bcr.bazel.build/modules/rules_python/0.4.0/MODULE.bazel": "9208ee05fd48bf09ac60ed269791cf17fb343db56c8226a720fbb1cdf467166c", - "https://bcr.bazel.build/modules/rules_python/1.3.0/MODULE.bazel": "8361d57eafb67c09b75bf4bbe6be360e1b8f4f18118ab48037f2bd50aa2ccb13", - "https://bcr.bazel.build/modules/rules_python/1.4.1/MODULE.bazel": "8991ad45bdc25018301d6b7e1d3626afc3c8af8aaf4bc04f23d0b99c938b73a6", - "https://bcr.bazel.build/modules/rules_python/1.6.0/MODULE.bazel": "7e04ad8f8d5bea40451cf80b1bd8262552aa73f841415d20db96b7241bd027d8", - "https://bcr.bazel.build/modules/rules_python/1.7.0/MODULE.bazel": "d01f995ecd137abf30238ad9ce97f8fc3ac57289c8b24bd0bf53324d937a14f8", - "https://bcr.bazel.build/modules/rules_python/1.7.0/source.json": "028a084b65dcf8f4dc4f82f8778dbe65df133f234b316828a82e060d81bdce32", - "https://bcr.bazel.build/modules/rules_shell/0.2.0/MODULE.bazel": "fda8a652ab3c7d8fee214de05e7a9916d8b28082234e8d2c0094505c5268ed3c", - "https://bcr.bazel.build/modules/rules_shell/0.3.0/MODULE.bazel": "de4402cd12f4cc8fda2354fce179fdb068c0b9ca1ec2d2b17b3e21b24c1a937b", - "https://bcr.bazel.build/modules/rules_shell/0.6.1/MODULE.bazel": "72e76b0eea4e81611ef5452aa82b3da34caca0c8b7b5c0c9584338aa93bae26b", - "https://bcr.bazel.build/modules/rules_shell/0.6.1/source.json": "20ec05cd5e592055e214b2da8ccb283c7f2a421ea0dc2acbf1aa792e11c03d0c", - "https://bcr.bazel.build/modules/rules_swift/1.16.0/MODULE.bazel": "4a09f199545a60d09895e8281362b1ff3bb08bbde69c6fc87aff5b92fcc916ca", - "https://bcr.bazel.build/modules/rules_swift/2.1.1/MODULE.bazel": "494900a80f944fc7aa61500c2073d9729dff0b764f0e89b824eb746959bc1046", - "https://bcr.bazel.build/modules/rules_swift/2.4.0/MODULE.bazel": "1639617eb1ede28d774d967a738b4a68b0accb40650beadb57c21846beab5efd", - "https://bcr.bazel.build/modules/rules_swift/3.1.2/MODULE.bazel": "72c8f5cf9d26427cee6c76c8e3853eb46ce6b0412a081b2b6db6e8ad56267400", - "https://bcr.bazel.build/modules/rules_swift/3.1.2/source.json": "e85761f3098a6faf40b8187695e3de6d97944e98abd0d8ce579cb2daf6319a66", - "https://bcr.bazel.build/modules/stardoc/0.5.1/MODULE.bazel": "1a05d92974d0c122f5ccf09291442580317cdd859f07a8655f1db9a60374f9f8", - "https://bcr.bazel.build/modules/stardoc/0.5.3/MODULE.bazel": "c7f6948dae6999bf0db32c1858ae345f112cacf98f174c7a8bb707e41b974f1c", - "https://bcr.bazel.build/modules/stardoc/0.7.0/MODULE.bazel": "05e3d6d30c099b6770e97da986c53bd31844d7f13d41412480ea265ac9e8079c", - "https://bcr.bazel.build/modules/stardoc/0.7.2/MODULE.bazel": "fc152419aa2ea0f51c29583fab1e8c99ddefd5b3778421845606ee628629e0e5", - "https://bcr.bazel.build/modules/stardoc/0.7.2/source.json": "58b029e5e901d6802967754adf0a9056747e8176f017cfe3607c0851f4d42216", - "https://bcr.bazel.build/modules/swift_argument_parser/1.3.1.1/MODULE.bazel": "5e463fbfba7b1701d957555ed45097d7f984211330106ccd1352c6e0af0dcf91", - "https://bcr.bazel.build/modules/swift_argument_parser/1.3.1.2/MODULE.bazel": "75aab2373a4bbe2a1260b9bf2a1ebbdbf872d3bd36f80bff058dccd82e89422f", - "https://bcr.bazel.build/modules/swift_argument_parser/1.3.1.2/source.json": "5fba48bbe0ba48761f9e9f75f92876cafb5d07c0ce059cc7a8027416de94a05b", - "https://bcr.bazel.build/modules/upb/0.0.0-20220923-a547704/MODULE.bazel": "7298990c00040a0e2f121f6c32544bab27d4452f80d9ce51349b1a28f3005c43", - "https://bcr.bazel.build/modules/zlib/1.2.11/MODULE.bazel": "07b389abc85fdbca459b69e2ec656ae5622873af3f845e1c9d80fe179f3effa0", - "https://bcr.bazel.build/modules/zlib/1.3.1.bcr.5/MODULE.bazel": "eec517b5bbe5492629466e11dae908d043364302283de25581e3eb944326c4ca", - "https://bcr.bazel.build/modules/zlib/1.3.1.bcr.5/source.json": "22bc55c47af97246cfc093d0acf683a7869377de362b5d1c552c2c2e16b7a806", - "https://bcr.bazel.build/modules/zlib/1.3.1/MODULE.bazel": "751c9940dcfe869f5f7274e1295422a34623555916eb98c174c1e945594bf198" - }, - "selectedYankedVersions": {}, - "moduleExtensions": {}, - "facts": {} -} diff --git a/example/third_party/templates/REPO.bazel b/example/third_party/templates/REPO.bazel new file mode 100644 index 0000000..cd4d7ae --- /dev/null +++ b/example/third_party/templates/REPO.bazel @@ -0,0 +1 @@ +# This is the root of the "@templates" repo. diff --git a/example/third_party/templates/css.star b/example/third_party/templates/css.star new file mode 100644 index 0000000..671b534 --- /dev/null +++ b/example/third_party/templates/css.star @@ -0,0 +1,112 @@ +_COLORS = { + "black": "#000000", + "white": "#ffffff", + "red": "#ff0000", + "green": "#00ff00", + "blue": "#0000ff", + "yellow": "#ffff00", + "cyan": "#00ffff", + "magenta": "#ff00ff", + "gray": "#808080", + "silver": "#c0c0c0", + "maroon": "#800000", + "olive": "#808000", + "navy": "#000080", + "teal": "#008080", + "purple": "#800080", + "orange": "#ffa500", + "coral": "#ff7f50", + "salmon": "#fa8072", + "tomato": "#ff6347", + "gold": "#ffd700", + "khaki": "#f0e68c", + "plum": "#dda0dd", + "orchid": "#da70d6", + "violet": "#ee82ee", + "indigo": "#4b0082", + "turquoise": "#40e0d0", + "sienna": "#a0522d", + "chocolate": "#d2691e", + "crimson": "#dc143c", + "aquamarine": "#7fffd4", +} + +_FONT_SIZES = { + "xs": "0.75rem", + "sm": "0.875rem", + "base": "1rem", + "lg": "1.125rem", + "xl": "1.25rem", + "2xl": "1.5rem", + "3xl": "1.875rem", + "4xl": "2.25rem", +} + +_SPACING = { + "0": "0", + "1": "0.25rem", + "2": "0.5rem", + "3": "0.75rem", + "4": "1rem", + "5": "1.25rem", + "6": "1.5rem", + "8": "2rem", + "10": "2.5rem", + "12": "3rem", + "16": "4rem", + "20": "5rem", +} + +def _rule(selector, **properties): + props = [] + for key, value in properties.items(): + css_key = key.replace("_", "-") + props.append(" {}: {};".format(css_key, value)) + return selector + " {\n" + "\n".join(props) + "\n}" + +def stylesheet(rules): + return "\n\n".join(rules) + +def color(name): + return _COLORS.get(name, name) + +def font_size(name): + return _FONT_SIZES.get(name, name) + +def spacing(name): + return _SPACING.get(str(name), str(name)) + +def rule(selector, **properties): + return _rule(selector, **properties) + +def media_query(query, rules): + inner = "\n".join([" " + line for r in rules for line in r.split("\n")]) + return "@media {} {{\n{}\n}}".format(query, inner) + +def reset_css(): + return stylesheet([ + _rule("*", margin = "0", padding = "0", box_sizing = "border-box"), + _rule("html", font_size = "16px", line_height = "1.5"), + _rule("body", font_family = "system-ui, -apple-system, sans-serif"), + _rule("img", max_width = "100%", height = "auto"), + _rule("a", color = "inherit", text_decoration = "none"), + _rule("ul, ol", list_style = "none"), + _rule("table", border_collapse = "collapse", width = "100%"), + ]) + +def flex_container(direction = "row", wrap = "nowrap", justify = "flex-start", align = "stretch"): + return { + "display": "flex", + "flex_direction": direction, + "flex_wrap": wrap, + "justify_content": justify, + "align_items": align, + } + +def grid_container(columns = "1fr", rows = "auto", gap = "1rem"): + return { + "display": "grid", + "grid_template_columns": columns, + "grid_template_rows": rows, + "gap": gap, + } diff --git a/example/third_party/templates/html.star b/example/third_party/templates/html.star new file mode 100644 index 0000000..ec50dc3 --- /dev/null +++ b/example/third_party/templates/html.star @@ -0,0 +1,110 @@ +_ELEMENTS = { + "div": {"self_closing": False, "block": True}, + "span": {"self_closing": False, "block": False}, + "p": {"self_closing": False, "block": True}, + "a": {"self_closing": False, "block": False}, + "img": {"self_closing": True, "block": False}, + "br": {"self_closing": True, "block": False}, + "hr": {"self_closing": True, "block": True}, + "h1": {"self_closing": False, "block": True}, + "h2": {"self_closing": False, "block": True}, + "h3": {"self_closing": False, "block": True}, + "h4": {"self_closing": False, "block": True}, + "h5": {"self_closing": False, "block": True}, + "h6": {"self_closing": False, "block": True}, + "ul": {"self_closing": False, "block": True}, + "ol": {"self_closing": False, "block": True}, + "li": {"self_closing": False, "block": True}, + "table": {"self_closing": False, "block": True}, + "tr": {"self_closing": False, "block": True}, + "td": {"self_closing": False, "block": False}, + "th": {"self_closing": False, "block": False}, + "thead": {"self_closing": False, "block": True}, + "tbody": {"self_closing": False, "block": True}, + "form": {"self_closing": False, "block": True}, + "input": {"self_closing": True, "block": False}, + "button": {"self_closing": False, "block": False}, + "select": {"self_closing": False, "block": False}, + "option": {"self_closing": False, "block": False}, + "textarea": {"self_closing": False, "block": False}, + "label": {"self_closing": False, "block": False}, + "section": {"self_closing": False, "block": True}, + "article": {"self_closing": False, "block": True}, + "header": {"self_closing": False, "block": True}, + "footer": {"self_closing": False, "block": True}, + "nav": {"self_closing": False, "block": True}, + "main": {"self_closing": False, "block": True}, + "aside": {"self_closing": False, "block": True}, + "pre": {"self_closing": False, "block": True}, + "code": {"self_closing": False, "block": False}, + "blockquote": {"self_closing": False, "block": True}, +} + +def _escape(text): + result = text + result = result.replace("&", "&") + result = result.replace("<", "<") + result = result.replace(">", ">") + result = result.replace('"', """) + return result + +def _render_attrs(attrs): + parts = [] + for key, value in attrs.items(): + parts.append('{}="{}"'.format(key, _escape(str(value)))) + if parts: + return " " + " ".join(parts) + return "" + +def element(tag, content = "", **attrs): + info = _ELEMENTS.get(tag, {"self_closing": False, "block": True}) + attr_str = _render_attrs(attrs) + if info["self_closing"]: + return "<{}{} />".format(tag, attr_str) + return "<{}{}>{}".format(tag, attr_str, content, tag) + +def document(title, body): + return "\n".join([ + "", + "", + "", + " ", + " {}".format(_escape(title)), + "", + "", + body, + "", + "", + ]) + +def list_items(items, ordered = False): + tag = "ol" if ordered else "ul" + li_parts = [element("li", _escape(str(item))) for item in items] + return element(tag, "\n".join(li_parts)) + +def table(headers, rows): + header_cells = [element("th", _escape(str(h))) for h in headers] + header_row = element("tr", "".join(header_cells)) + thead = element("thead", header_row) + body_rows = [] + for row in rows: + cells = [element("td", _escape(str(cell))) for cell in row] + body_rows.append(element("tr", "".join(cells))) + tbody = element("tbody", "\n".join(body_rows)) + return element("table", thead + "\n" + tbody) + +def link(href, text): + return element("a", _escape(text), href = href) + +def image(src, alt = ""): + return element("img", src = src, alt = alt) + +def heading(level, text): + tag = "h" + str(level) + return element(tag, _escape(text)) + +def form_input(name, input_type = "text", value = "", placeholder = ""): + return element("input", type = input_type, name = name, value = value, placeholder = placeholder) + +def paragraph(text): + return element("p", _escape(text)) diff --git a/example/third_party/units/REPO.bazel b/example/third_party/units/REPO.bazel new file mode 100644 index 0000000..506a738 --- /dev/null +++ b/example/third_party/units/REPO.bazel @@ -0,0 +1 @@ +# This is the root of the "@units" repo. diff --git a/example/third_party/units/units.star b/example/third_party/units/units.star new file mode 100644 index 0000000..586d8eb --- /dev/null +++ b/example/third_party/units/units.star @@ -0,0 +1,2 @@ +CM_PER_INCH = 2.54 +KG_PER_LB = 0.453592 diff --git a/runfiles_group/BUILD.bazel b/runfiles_group/BUILD.bazel index 9af1a2b..a719686 100644 --- a/runfiles_group/BUILD.bazel +++ b/runfiles_group/BUILD.bazel @@ -15,7 +15,7 @@ bzl_library( visibility = ["//visibility:public"], deps = [ "//runfiles_group/private/providers:runfiles_group_info", - "//runfiles_group/private/providers:runfiles_group_selection_info", + "//runfiles_group/private/providers:runfiles_group_metadata_info", "//runfiles_group/private/providers:runfiles_group_transform_info", ], ) diff --git a/runfiles_group/private/BUILD.bazel b/runfiles_group/private/BUILD.bazel index 01a79da..64e9908 100644 --- a/runfiles_group/private/BUILD.bazel +++ b/runfiles_group/private/BUILD.bazel @@ -6,6 +6,7 @@ bzl_library( visibility = ["//:__subpackages__"], deps = [ "//runfiles_group/private/providers:runfiles_group_info", + "//runfiles_group/private/providers:runfiles_group_metadata_info", "@bazel_features//:features", ], ) diff --git a/runfiles_group/private/lib.bzl b/runfiles_group/private/lib.bzl index 7ced923..620abdf 100644 --- a/runfiles_group/private/lib.bzl +++ b/runfiles_group/private/lib.bzl @@ -3,33 +3,42 @@ lib.group_names(runfiles_group_info) Returns the list of group names in a RunfilesGroupInfo instance. -lib.ordered_groups(runfiles_group_info, selection_info = None) - Returns a list of (group_name, depset[File]) tuples, filtered and - sorted according to the selection. If selection_info is None, all - groups are included in lexicographic order. - - The selection info supports two forms: - List form (group_names / extra_group_treatment): - Groups returned in the order given by group_names. Extras are - excluded, prepended, or appended (lexicographically). - Functional form (predicate / compare): - Groups filtered by predicate and sorted by compare. - -lib.transform_groups(runfiles_group_info, transform_info = None) - Returns a new RunfilesGroupInfo with groups merged according to - the transform. If transform_info is None, returns the input unchanged. - - The transform info supports two forms: - Dict form (merge_groups / unmatched_group_treatment): - Merges source groups into output groups per the mapping. - Unmatched groups are excluded, kept separate, or merged into - a default group. - Functional form (transform): - Calls transform(runfiles_group_info) and returns the result. +lib.ordered_groups(runfiles_group_info, metadata_info = None) + Returns a list of (group_name, depset[File]) tuples, ordered by rank + (ascending). Within the same rank, order is deterministc, + but consumers should not rely on intra-rank order. + + If metadata_info is None, all groups are included in deterministic order. + Groups not present in metadata get default rank (0). + +lib.transform_groups(runfiles_group_info, metadata_info = None, transform_info = None) + Applies a transform to (RunfilesGroupInfo, RunfilesGroupMetadataInfo). + Returns struct(runfiles_group_info, runfiles_group_metadata_info). + If transform_info is None, returns inputs unchanged. + +lib.merge_to_limit(runfiles_group_info, metadata_info = None, max_groups, default_weight = 0, merged_group_name = None) + Merges groups to fit within max_groups. Groups at the same rank + without do_not_merge may be merged. Lighter groups (by weight) merge first. + Returns struct(runfiles_group_info, runfiles_group_metadata_info, group_count). + The caller must check group_count — if it exceeds max_groups, merging could + not reduce far enough (e.g., due to do_not_merge or groups in different ranks). + If merged_group_name is set, it is called as + merged_group_name(lighter_name, lighter_weight, heavier_name, heavier_weight) + to determine the name of the merged group. If None, the heavier group's name is kept. + +lib.merge_metadata(base, override) + Dict-merges two RunfilesGroupMetadataInfo instances (or None). + Returns RunfilesGroupMetadataInfo or None. Per-key last-wins. """ load("@bazel_features//:features.bzl", "bazel_features") load("//runfiles_group/private/providers:runfiles_group_info.bzl", "RunfilesGroupInfo") +load( + "//runfiles_group/private/providers:runfiles_group_metadata_info.bzl", + "DEFAULT_METADATA", + "RunfilesGroupMetadataInfo", + "group_metadata", +) # Bazel < 9 includes to_json/to_proto in dir() results for providers. _PROVIDER_BUILTINS = [] if bazel_features.rules.no_struct_field_denylist else ["to_json", "to_proto"] @@ -38,85 +47,144 @@ def _group_names(runfiles_group_info): """Returns the list of group names in a RunfilesGroupInfo instance.""" return [n for n in dir(runfiles_group_info) if n not in _PROVIDER_BUILTINS] -def _ordered_groups(runfiles_group_info, runfiles_group_selection_info = None): +def _get_metadata(metadata_info, name): + if metadata_info == None: + return DEFAULT_METADATA + return metadata_info.groups.get(name, DEFAULT_METADATA) + +def _ordered_groups(runfiles_group_info, runfiles_group_metadata_info = None): all_names = _group_names(runfiles_group_info) - selection = runfiles_group_selection_info - if selection == None: + if runfiles_group_metadata_info == None: ordered = sorted(all_names) - elif selection.group_names != None: - all_names_set = {name: True for name in all_names} - listed = [name for name in selection.group_names if name in all_names_set] - - if selection.extra_group_treatment == "exclude": - ordered = listed - else: - listed_set = {name: True for name in selection.group_names} - extras = sorted([name for name in all_names if name not in listed_set]) - if selection.extra_group_treatment == "prepend": - ordered = extras + listed - else: - ordered = listed + extras else: - filtered = [name for name in all_names if selection.predicate(name)] - ordered = _sort_with_compare(filtered, selection.compare) + ordered = sorted( + all_names, + key = lambda name: ( + _get_metadata(runfiles_group_metadata_info, name).rank, + name, + ), + ) return [(name, getattr(runfiles_group_info, name)) for name in ordered] -def _sort_with_compare(items, compare): - result = list(items) - for i in range(1, len(result)): - key = result[i] - insert_at = i - for j in range(i - 1, -1, -1): - if compare(key, result[j]): - result[j + 1] = result[j] - insert_at = j - else: - break - result[insert_at] = key - return result - -def _transform_groups(runfiles_group_info, runfiles_transform_info = None): +def _transform_groups(runfiles_group_info, runfiles_group_metadata_info = None, runfiles_transform_info = None): if runfiles_transform_info == None: - return runfiles_group_info - if runfiles_transform_info.transform != None: - return runfiles_transform_info.transform(runfiles_group_info) - - merge_groups = runfiles_transform_info.merge_groups - treatment = runfiles_transform_info.unmatched_group_treatment - all_names = _group_names(runfiles_group_info) - all_names_set = {name: True for name in all_names} - - matched = {} - for source_names in merge_groups.values(): - for source_name in source_names: - matched[source_name] = True - - result = {} - - for out_name, source_names in merge_groups.items(): - depsets = [getattr(runfiles_group_info, name) for name in source_names if name in all_names_set] - if depsets: - result[out_name] = depset(transitive = depsets) - - unmatched = [name for name in all_names if name not in matched] - - if treatment == "keep_separate": - for name in unmatched: - result[name] = getattr(runfiles_group_info, name) - elif treatment == "merge_default": - default_depsets = [getattr(runfiles_group_info, name) for name in unmatched] - if default_depsets: - default_name = runfiles_transform_info.default_group_name - if default_name in result: - default_depsets.append(result[default_name]) - result[default_name] = depset(transitive = default_depsets) - - return RunfilesGroupInfo(**result) + return struct( + runfiles_group_info = runfiles_group_info, + runfiles_group_metadata_info = runfiles_group_metadata_info, + ) + return runfiles_transform_info.transform(runfiles_group_info, runfiles_group_metadata_info) + +def _effective_weight(entry, default_weight): + return entry.weight if entry.weight != None else default_weight + +def _find_cheapest_pair(groups, meta, default_weight): + """Finds the cheapest same-rank mergeable pair. Returns (lighter, heavier) or None.""" + by_rank = {} + for name in groups: + entry = meta[name] + if entry.do_not_merge: + continue + rank = entry.rank + if rank not in by_rank: + by_rank[rank] = [] + by_rank[rank].append(name) + + best_pair = None + best_cost = None + for rank, mergeable in by_rank.items(): + if len(mergeable) < 2: + continue + weighted = sorted( + [((_effective_weight(meta[n], default_weight), n)) for n in mergeable], + key = lambda pair: (pair[0], pair[1]), + ) + cost = weighted[0][0] + weighted[1][0] + if best_cost == None or cost < best_cost or (cost == best_cost and rank < best_pair[0]): + best_pair = (rank, weighted[0][1], weighted[1][1]) + best_cost = cost + + if best_pair == None: + return None + + lighter_name = best_pair[1] + heavier_name = best_pair[2] + if _effective_weight(meta[lighter_name], default_weight) > _effective_weight(meta[heavier_name], default_weight): + return (heavier_name, lighter_name) + return (lighter_name, heavier_name) + +def _merge_pair(groups, meta, lighter, heavier, default_weight, merged_group_name_fn): + """Merges lighter into heavier, returns new (groups, meta) dicts.""" + merged_depset = depset(transitive = [groups[lighter], groups[heavier]]) + merged_weight = _effective_weight(meta[lighter], default_weight) + \ + _effective_weight(meta[heavier], default_weight) + merged_entry = struct( + rank = meta[heavier].rank, + do_not_merge = False, + weight = merged_weight, + ) + + if merged_group_name_fn != None: + lighter_w = _effective_weight(meta[lighter], default_weight) + heavier_w = _effective_weight(meta[heavier], default_weight) + out_name = merged_group_name_fn(lighter, lighter_w, heavier, heavier_w) + else: + out_name = heavier + + new_groups = {n: d for n, d in groups.items() if n != lighter and n != heavier} + new_groups[out_name] = merged_depset + new_meta = {n: e for n, e in meta.items() if n != lighter and n != heavier} + new_meta[out_name] = merged_entry + return (new_groups, new_meta) + +def _merge_to_limit(runfiles_group_info, runfiles_group_metadata_info = None, *, max_groups, default_weight = 0, merged_group_name = None): + names = _group_names(runfiles_group_info) + if len(names) <= max_groups: + return struct( + runfiles_group_info = runfiles_group_info, + runfiles_group_metadata_info = runfiles_group_metadata_info, + group_count = len(names), + ) + + groups = {name: getattr(runfiles_group_info, name) for name in names} + meta = {} + for name in names: + meta[name] = _get_metadata(runfiles_group_metadata_info, name) + + for _ in range(len(names)): + if len(groups) <= max_groups: + break + pair = _find_cheapest_pair(groups, meta, default_weight) + if pair == None: + break + groups, meta = _merge_pair(groups, meta, pair[0], pair[1], default_weight, merged_group_name) + + merged_rgi = RunfilesGroupInfo(**groups) + merged_metadata = RunfilesGroupMetadataInfo(groups = meta) if meta else runfiles_group_metadata_info + return struct( + runfiles_group_info = merged_rgi, + runfiles_group_metadata_info = merged_metadata, + group_count = len(groups), + ) + +def _merge_metadata(base, override): + if base == None and override == None: + return None + if base == None: + return override + if override == None: + return base + + merged = dict(base.groups) + merged.update(override.groups) + return RunfilesGroupMetadataInfo(groups = merged) lib = struct( + group_metadata = group_metadata, group_names = _group_names, ordered_groups = _ordered_groups, transform_groups = _transform_groups, + merge_to_limit = _merge_to_limit, + merge_metadata = _merge_metadata, ) diff --git a/runfiles_group/private/providers/BUILD.bazel b/runfiles_group/private/providers/BUILD.bazel index 37aea0d..e1a40a1 100644 --- a/runfiles_group/private/providers/BUILD.bazel +++ b/runfiles_group/private/providers/BUILD.bazel @@ -7,8 +7,8 @@ bzl_library( ) bzl_library( - name = "runfiles_group_selection_info", - srcs = ["runfiles_group_selection_info.bzl"], + name = "runfiles_group_metadata_info", + srcs = ["runfiles_group_metadata_info.bzl"], visibility = ["//:__subpackages__"], ) diff --git a/runfiles_group/private/providers/runfiles_group_info.bzl b/runfiles_group/private/providers/runfiles_group_info.bzl index c29bbd2..3fe5f50 100644 --- a/runfiles_group/private/providers/runfiles_group_info.bzl +++ b/runfiles_group/private/providers/runfiles_group_info.bzl @@ -7,7 +7,7 @@ _DOC = """\ Information about grouped runfiles. Each field in this provider is a depset of File objects, representing a category of runfiles. -Merging all depsets from all fields should yield the same set (or a superset) of files as DefaultInfo.default_runfiles. +Merging all depsets from all fields must yield the same set of files as DefaultInfo.default_runfiles. This provider functions similarly to OutputGroupInfo, but its presence in the output of a rule indicates that it can be used instead of DefaultInfo.default_runfiles. It categorizes the runfiles of a target into different groups, allowing for more fine-grained control over which runfiles are used in different contexts. diff --git a/runfiles_group/private/providers/runfiles_group_metadata_info.bzl b/runfiles_group/private/providers/runfiles_group_metadata_info.bzl new file mode 100644 index 0000000..73c69f7 --- /dev/null +++ b/runfiles_group/private/providers/runfiles_group_metadata_info.bzl @@ -0,0 +1,81 @@ +"""Defines provider for metadata about RunfilesGroupInfo groups. + +RunfilesGroupMetadataInfo holds per-group metadata that controls ordering +(rank), merge eligibility (do_not_merge), and merge priority (weight). +""" + +_DOC = """\ +Metadata about groups in a RunfilesGroupInfo instance. + +Each entry maps a group name to a struct with: +- rank (int): Partial ordering key. Lower rank = earlier. Default 0. +- do_not_merge (bool): If True, packager must not merge this group. Default False. +- weight (int or None): Hint for merge priority. Lighter groups merge first. + If None, the packager may apply an undefined default. Default None. + +Groups not present in the dict are treated as having default metadata +(rank=0, do_not_merge=False, weight=None). +""" + +_DEFAULT_RANK = 0 +_DEFAULT_DO_NOT_MERGE = False +_DEFAULT_WEIGHT = None + +def group_metadata(*, rank = _DEFAULT_RANK, do_not_merge = _DEFAULT_DO_NOT_MERGE, weight = _DEFAULT_WEIGHT): + """Creates a validated group metadata struct. + + Args: + rank: Partial ordering key. Lower rank = earlier. Default 0. + do_not_merge: If True, packager must not merge this group. Default False. + weight: Merge priority hint (int >= 0 or None). Default None. + + Returns: + A struct with rank, do_not_merge, and weight fields. + """ + if type(rank) != "int": + fail("group_metadata: rank must be an int, got ", type(rank)) + if type(do_not_merge) != "bool": + fail("group_metadata: do_not_merge must be a bool, got ", type(do_not_merge)) + if weight != None: + if type(weight) != "int": + fail("group_metadata: weight must be an int or None, got ", type(weight)) + if weight < 0: + fail("group_metadata: weight must be >= 0, got ", weight) + return struct(rank = rank, do_not_merge = do_not_merge, weight = weight) + +_DEFAULT_METADATA = group_metadata() + +def _normalize_entry(name, entry): + if type(entry) == "struct": + rank = getattr(entry, "rank", _DEFAULT_RANK) + do_not_merge = getattr(entry, "do_not_merge", _DEFAULT_DO_NOT_MERGE) + weight = getattr(entry, "weight", _DEFAULT_WEIGHT) + return group_metadata(rank = rank, do_not_merge = do_not_merge, weight = weight) + if type(entry) == "dict": + return group_metadata( + rank = entry.get("rank", _DEFAULT_RANK), + do_not_merge = entry.get("do_not_merge", _DEFAULT_DO_NOT_MERGE), + weight = entry.get("weight", _DEFAULT_WEIGHT), + ) + fail("RunfilesGroupMetadataInfo: entry for group '{}' must be a struct or dict, got {}".format(name, type(entry))) + +def _make_runfilesgroupmetadatainfo_init(*, groups): + if type(groups) != "dict": + fail("RunfilesGroupMetadataInfo: groups must be a dict, got ", type(groups)) + normalized = {} + for name, entry in groups.items(): + normalized[name] = _normalize_entry(name, entry) + return {"groups": normalized} + +RunfilesGroupMetadataInfo, _ = provider( + doc = _DOC, + init = _make_runfilesgroupmetadatainfo_init, + fields = { + "groups": """\ +A dict mapping group name (string) to a struct with rank, do_not_merge, and weight fields. +Groups not present get default metadata (rank=0, do_not_merge=False, weight=None). +""", + }, +) + +DEFAULT_METADATA = _DEFAULT_METADATA diff --git a/runfiles_group/private/providers/runfiles_group_selection_info.bzl b/runfiles_group/private/providers/runfiles_group_selection_info.bzl deleted file mode 100644 index 38e0d1c..0000000 --- a/runfiles_group/private/providers/runfiles_group_selection_info.bzl +++ /dev/null @@ -1,73 +0,0 @@ -"""Defines provider for ordering RunfilesGroupInfo. - -Given an instance of RunfilesGroupInfo with an (unordered) set of groups, -RunfilesSelectionInfo can be used to define selection and ordering of groups. -Note: ordering doesn't matter in every context, so RunfilesGroupInfo can stand on it's own. -""" - -_DOC = """\ -Information about filtering and ordering groups of runfiles. -""" - -def _predicate_all(_): - return True - -def _compare_lexicographic(left, right): - return left < right - -def _make_runfilesgroupselectioninfo_init(*, predicate = None, compare = None, group_names = None, extra_group_treatment = None): - functional = predicate != None or compare != None - listed = group_names != None or extra_group_treatment != None - - if functional and listed: - fail("RunfilesGroupSelectionInfo: cannot mix predicate/compare with group_names/extra_group_treatment") - if not functional and not listed: - fail("RunfilesGroupSelectionInfo: need either predicate/compare or group_names/extra_group_treatment") - - if listed: - if group_names == None: - fail("RunfilesGroupSelectionInfo: group_names is required when extra_group_treatment is set") - if extra_group_treatment == None: - extra_group_treatment = "exclude" - if extra_group_treatment not in ["exclude", "prepend", "append"]: - fail("extra_group_treatment must be one of exclude, prepend, or append, but got ", extra_group_treatment) - - return { - "predicate": None, - "compare": None, - "group_names": group_names, - "extra_group_treatment": extra_group_treatment, - } - - return { - "predicate": predicate if predicate != None else _predicate_all, - "compare": compare if compare != None else _compare_lexicographic, - "group_names": None, - "extra_group_treatment": None, - } - -RunfilesGroupSelectionInfo, _ = provider( - doc = _DOC, - init = _make_runfilesgroupselectioninfo_init, - fields = { - "predicate": """\ -A starlark function that takes a single string (group name). -The function should return True if the group should be included in the output (and return False otherwise). -Set in functional form, None in list form. -""", - "compare": """\ -A starlark function that takes two strings as input (group names) -and returns True if the first group name should come before the second (and False otherwise). -Set in functional form, None in list form. -""", - "group_names": """\ -A list of group names defining the desired order. -Set in list form, None in functional form. -Mutually exclusive with predicate and compare. -""", - "extra_group_treatment": """\ -How to treat groups not in group_names. One of "exclude", "prepend", or "append". -Set in list form, None in functional form. -""", - }, -) diff --git a/runfiles_group/private/providers/runfiles_group_transform_info.bzl b/runfiles_group/private/providers/runfiles_group_transform_info.bzl index a7b9fe9..6588e5f 100644 --- a/runfiles_group/private/providers/runfiles_group_transform_info.bzl +++ b/runfiles_group/private/providers/runfiles_group_transform_info.bzl @@ -1,71 +1,31 @@ -"""Defines provider for transforming RunfilesGroupInfo by merging groups. +"""Defines provider for transforming RunfilesGroupInfo and RunfilesGroupMetadataInfo. This provider is intended for use as an aspect_hint on a target -to merge some runfiles groups together, producing a new RunfilesGroupInfo -with fewer or different groups. +to transform runfiles groups, producing new RunfilesGroupInfo +and RunfilesGroupMetadataInfo instances. """ _DOC = """\ -Information about how to transform a RunfilesGroupInfo by merging groups. -""" - -def _make_runfilestransforminfo_init(*, transform = None, merge_groups = None, unmatched_group_treatment = None, default_group_name = None): - functional = transform != None - dict_form = merge_groups != None or unmatched_group_treatment != None or default_group_name != None - - if functional and dict_form: - fail("RunfilesGroupTransformInfo: cannot mix transform with merge_groups/unmatched_group_treatment/default_group_name") - if not functional and not dict_form: - fail("RunfilesGroupTransformInfo: need either transform or merge_groups/unmatched_group_treatment") - - if dict_form: - if merge_groups == None: - fail("RunfilesGroupTransformInfo: merge_groups is required in dict form") - if unmatched_group_treatment == None: - unmatched_group_treatment = "keep_separate" - if unmatched_group_treatment not in ["exclude", "keep_separate", "merge_default"]: - fail("unmatched_group_treatment must be one of exclude, keep_separate, or merge_default, but got ", unmatched_group_treatment) - if unmatched_group_treatment == "merge_default": - if default_group_name == None: - fail("RunfilesGroupTransformInfo: default_group_name is required when unmatched_group_treatment is merge_default") - elif default_group_name != None: - fail("RunfilesGroupTransformInfo: default_group_name is only valid when unmatched_group_treatment is merge_default") +Information about how to transform a RunfilesGroupInfo (and its metadata). - return { - "transform": None, - "merge_groups": merge_groups, - "unmatched_group_treatment": unmatched_group_treatment, - "default_group_name": default_group_name, - } +The transform function receives (RunfilesGroupInfo, RunfilesGroupMetadataInfo_or_None) +and must return a struct with two fields: +- runfiles_group_info: the transformed RunfilesGroupInfo +- runfiles_group_metadata_info: the transformed RunfilesGroupMetadataInfo (or None) +""" - return { - "transform": transform, - "merge_groups": None, - "unmatched_group_treatment": None, - "default_group_name": None, - } +def _make_runfilestransforminfo_init(*, transform): + if transform == None: + fail("RunfilesGroupTransformInfo: transform must not be None") + return {"transform": transform} RunfilesGroupTransformInfo, _ = provider( doc = _DOC, init = _make_runfilestransforminfo_init, fields = { "transform": """\ -A starlark function that takes a RunfilesGroupInfo and returns a new RunfilesGroupInfo. -Set in functional form, None in dict form. -""", - "merge_groups": """\ -A dict mapping output group name (string) to a list of source group names (list of string). -Each source group's depset is merged into the output group. -Set in dict form, None in functional form. -""", - "unmatched_group_treatment": """\ -How to treat groups not listed in any merge_groups value. -One of "exclude", "keep_separate", or "merge_default". -Defaults to "keep_separate" if omitted. Set in dict form, None in functional form. -""", - "default_group_name": """\ -The name of the group that unmatched groups are merged into. -Required when unmatched_group_treatment is "merge_default", None otherwise. +A starlark function (RunfilesGroupInfo, RunfilesGroupMetadataInfo_or_None) -> +struct(runfiles_group_info, runfiles_group_metadata_info). """, }, ) diff --git a/runfiles_group/private/rules/BUILD.bazel b/runfiles_group/private/rules/BUILD.bazel index 0aa1dff..d0667a0 100644 --- a/runfiles_group/private/rules/BUILD.bazel +++ b/runfiles_group/private/rules/BUILD.bazel @@ -7,6 +7,7 @@ bzl_library( deps = [ "//runfiles_group/private:lib", "//runfiles_group/private/providers:runfiles_group_info", + "//runfiles_group/private/providers:runfiles_group_metadata_info", "@bazel_skylib//lib:sets", ], ) diff --git a/runfiles_group/private/rules/runfiles_group_analysis_test.bzl b/runfiles_group/private/rules/runfiles_group_analysis_test.bzl index 8bbda64..9c7b7ce 100644 --- a/runfiles_group/private/rules/runfiles_group_analysis_test.bzl +++ b/runfiles_group/private/rules/runfiles_group_analysis_test.bzl @@ -19,12 +19,16 @@ runfiles_group_analysis_test( load("@bazel_skylib//lib:sets.bzl", "sets") load("//runfiles_group/private:lib.bzl", "lib") load("//runfiles_group/private/providers:runfiles_group_info.bzl", "RunfilesGroupInfo") +load("//runfiles_group/private/providers:runfiles_group_metadata_info.bzl", "RunfilesGroupMetadataInfo") _INDENT = " " def _indent(text): return "\n".join([_INDENT + line for line in text.split("\n")]) +def _join_group_names(lighter_name, _lighter_weight, heavier_name, _heavier_weight): + return lighter_name + "+" + heavier_name + def _test_one(ctx, binary_attr): issues = [] success = True @@ -84,6 +88,50 @@ def _test_one(ctx, binary_attr): # buildifier: disable=print print("WARNING [{}]: {}".format(binary_attr.label, msg)) + # Apply the full resolution protocol (merge + ordering) and check expected group names. + rgi = runfiles_group_info + metadata = binary_attr[RunfilesGroupMetadataInfo] if RunfilesGroupMetadataInfo in binary_attr else None + + if ctx.attr.max_groups >= 0: + merged = lib.merge_to_limit( + rgi, + metadata, + max_groups = ctx.attr.max_groups, + merged_group_name = _join_group_names, + ) + rgi = merged.runfiles_group_info + metadata = merged.runfiles_group_metadata_info + if ctx.attr.expected_group_count >= 0: + if merged.group_count != ctx.attr.expected_group_count: + success = False + issues.append( + "expected {} groups after merging but got {}".format( + ctx.attr.expected_group_count, + merged.group_count, + ), + ) + elif merged.group_count > ctx.attr.max_groups: + success = False + issues.append( + "max_groups={} requested but merging could only reduce to {} groups".format( + ctx.attr.max_groups, + merged.group_count, + ), + ) + + ordered = lib.ordered_groups(rgi, metadata) + actual_names = [name for name, _ in ordered] + + if ctx.attr.expected_group_names: + if actual_names != ctx.attr.expected_group_names: + success = False + issues.append( + "expected ordered group names:\n" + + _INDENT + str(ctx.attr.expected_group_names) + "\n" + + "actual ordered group names:\n" + + _INDENT + str(actual_names), + ) + return (success, issues) def _runfiles_group_analysis_test_impl(ctx): @@ -121,7 +169,9 @@ runfiles_group_analysis_test = rule( Checks that RunfilesGroupInfo is well formed by comparing the runfiles of the executable (DefaultInfo.default_runfiles.files) with the union of all runfiles from RunfilesGroupInfo. -Additionally, it can warn about files appearing in multiple groups (overlapping). +Additionally, it can warn about files appearing in multiple groups (overlapping), +verify the expected ordered group names after applying the full resolution protocol, +and optionally apply merge-to-limit before ordering. """, attrs = { "binaries": attr.label_list( @@ -135,6 +185,24 @@ Additionally, it can warn about files appearing in multiple groups (overlapping) default = "warn", values = ["warn", "ignore", "error"], ), + "expected_group_names": attr.string_list( + doc = """\ +If set, the test verifies that the ordered group names (after optional merging and rank-based ordering) +match this list exactly. Applies to all binaries in the test. +""", + ), + "max_groups": attr.int( + doc = "If >= 0, apply lib.merge_to_limit with this limit before ordering. -1 means no limit.", + default = -1, + ), + "expected_group_count": attr.int( + doc = """\ +If >= 0, verify the exact number of groups after merging (requires max_groups >= 0). +Use this when merging cannot reach max_groups (e.g., due to do_not_merge or rank constraints) +to assert the actual reachable count. -1 means no check (the test fails if group_count > max_groups instead). +""", + default = -1, + ), }, analysis_test = True, ) diff --git a/runfiles_group/providers.bzl b/runfiles_group/providers.bzl index 6c7e3d1..8d002c8 100644 --- a/runfiles_group/providers.bzl +++ b/runfiles_group/providers.bzl @@ -1,9 +1,9 @@ """Public API for runfiles group providers.""" load("//runfiles_group/private/providers:runfiles_group_info.bzl", _RunfilesGroupInfo = "RunfilesGroupInfo") -load("//runfiles_group/private/providers:runfiles_group_selection_info.bzl", _RunfilesGroupSelectionInfo = "RunfilesGroupSelectionInfo") +load("//runfiles_group/private/providers:runfiles_group_metadata_info.bzl", _RunfilesGroupMetadataInfo = "RunfilesGroupMetadataInfo") load("//runfiles_group/private/providers:runfiles_group_transform_info.bzl", _RunfilesGroupTransformInfo = "RunfilesGroupTransformInfo") RunfilesGroupInfo = _RunfilesGroupInfo -RunfilesGroupSelectionInfo = _RunfilesGroupSelectionInfo +RunfilesGroupMetadataInfo = _RunfilesGroupMetadataInfo RunfilesGroupTransformInfo = _RunfilesGroupTransformInfo