# Extending the rules

:::{important}
**This is public, but volatile, functionality.**

Extending and customizing the rules is supported functionality, but with weaker
backwards compatibility guarantees, and is not fully subject to the normal
backwards compatibility procedures and policies. It's simply not feasible to
support every possible customization with strong backwards compatibility
guarantees.
:::

Because of the rich ecosystem of tools and variety of use cases, APIs are
provided to make it easy to create custom rules using the existing rules as a
basis. This allows implementing behaviors that aren't possible using
wrapper macros around the core rules, and can make certain types of changes
much easier and transparent to implement.

:::{note}
It is not required to extend a core rule. The minimum requirement for a custom
rule is to return the appropriate provider (e.g. {bzl:obj}`PyInfo` etc).
Extending the core rules is most useful when you want all or most of the
behavior of a core rule.
:::

Follow or comment on {gh-issue}`1647`
for the development of APIs to support custom derived rules.

## Creating custom rules

Custom rules can be created using the core rules as a basis by using their rule
builder APIs.

* [`//python/apis:executables.bzl`](#python-apis-executables-bzl): builders for
  executables.
* [`//python/apis:libraries.bzl`](#python-apis-libraries-bzl): builders for
  libraries.

These builders create {bzl:obj}`ruleb.Rule` objects, which are thin
wrappers around the keyword arguments eventually passed to the `rule()`
function. These builder APIs give access to the _entire_ rule definition and
allow arbitrary modifications.

This level of control is powerful but also volatile. A rule definition
contains many details that _must_ change as the implementation changes. What
is more or less likely to change isn't known in advance, but some general
rules of thumb are:

* Additive behavior to public attributes will be less prone to breaking.
* Internal attributes that directly support a public attribute are likely
  reliable.
* Internal attributes that support an action are more likely to change.
* Rule toolchains are moderately stable (toolchains are mostly internal to
  how a rule works, but custom toolchains are supported).

## Example: validating a source file

In this example, we derive a custom rule from `py_library` that verifies source
code contains the word "snakes". It does this by:

* Adding an implicit dependency on a checker program
* Calling the base implementation function
* Running the checker on the srcs files
* Adding the result to the `_validation` output group (a special output
  group for validation behaviors).

To users, they can use `has_snakes_library` the same as `py_library`. The same
is true for other targets that might consume the rule.

```
load("@rules_python//python/api:libraries.bzl", "libraries")
load("@rules_python//python/api:attr_builders.bzl", "attrb")

def _has_snakes_impl(ctx, base):
    providers = base(ctx)

    out = ctx.actions.declare_file(ctx.label.name + "_snakes.check")
    ctx.actions.run(
        inputs = ctx.files.srcs,
        outputs = [out],
        executable = ctx.attr._checker[DefaultInfo].files_to_run,
        args = [out.path] + [f.path for f in ctx.files.srcs],
    )
    prior_ogi = None
    for i, p in enumerate(providers):
        if type(p) == "OutputGroupInfo":
            prior_ogi = (i, p)
            break
    if prior_ogi:
        groups = {k: getattr(prior_ogi[1], k) for k in dir(prior_ogi)}
        if "_validation" in groups:
            groups["_validation"] = depset([out], transitive=groups["_validation"])
        else:
            groups["_validation"] = depset([out])
        providers[prior_ogi[0]] = OutputGroupInfo(**groups)
    else:
        providers.append(OutputGroupInfo(_validation=depset([out])))
    return providers

def create_has_snakes_rule():
    r = libraries.py_library_builder()
    base_impl = r.implementation()
    r.set_implementation(lambda ctx: _has_snakes_impl(ctx, base_impl))
    r.attrs["_checker"] = attrb.Label(
        default="//:checker",
        executable = True,
    )
    return r.build()
has_snakes_library = create_has_snakes_rule()
```

## Example: adding transitions

In this example, we derive a custom rule from `py_binary` to force building for a particular
platform. We do this by:

* Adding an additional output to the rule's cfg
* Calling the base transition function
* Returning the new transition outputs

```starlark

load("@rules_python//python/api:executables.bzl", "executables")

def _force_linux_impl(settings, attr, base_impl):
    settings = base_impl(settings, attr)
    settings["//command_line_option:platforms"] = ["//my/platforms:linux"]
    return settings

def create_rule():
    r = executables.py_binary_rule_builder()
    base_impl = r.cfg.implementation()
    r.cfg.set_implementation(
        lambda settings, attr: _force_linux_impl(settings, attr, base_impl)
    )
    r.cfg.add_output("//command_line_option:platforms")
    return r.build()

py_linux_binary = create_rule()
```

Users can then use `py_linux_binary` the same as a regular `py_binary`. It will
act as if `--platforms=//my/platforms:linux` was specified when building it.
