<commit_before>---
layout: documentation
title: Starlark Build Configurations
---

# Starlark Build Configurations

User-definable configuration is coming to Starlark!

This makes it possible to:

* define custom flags for your project, obsoleting the need for
[`--define`](configurable-attributes.html#custom-keys)
* write
[transitions](skylark/lib/transition.html#modules.transition)
  to configure deps in different configurations     than their parents (e.g.`--     compilation_mode=opt` or `--cpu=arm`)
* bake better defaults into rules (e.g. automatically build `//my:android_app`
  with a specified SDK)

and more, all completely from .bzl files
(no Bazel release required).
<!-- [TOC] -->

## Current Status

As of Q2'19, this effort is
[partially rolled out](https://github.com/bazelbuild/bazel/issues/5574#issuecomment-458349702)
. Much functionality is guarded while we work out concerns about
memory and performance
at scale.

Related issues:
* [#5574](https://github.com/bazelbuild/bazel/issues/5574) - Starlark support for custom configuration transitions
* [#5575](https://github.com/bazelbuild/bazel/issues/5575) - Starlark support for multi-arch ("fat") binaries
* [#5577](https://github.com/bazelbuild/bazel/issues/5577) - Starlark support for custom build flags
* [#5578](https://github.com/bazelbuild/bazel/issues/5578) - Configuration doesn't block native ->
Skylark rules migration

## User-defined Build Settings
A build setting is a single piece of
[configuration](skylark/rules.html#configurations)
information. Think of a configuration as a key/value map. Setting `--cpu=ppc`
and `--copt="-DFoo"` produces a configuration that looks like
`{cpu: ppc, copt: "-DFoo"}`. Each entry is a build setting.

Traditional flags like `cpu` and `copt` are native settings i.e.
their keys are defined and their values are set inside native bazel java code.
Bazel users can only read and write them via the command line
and other APIs maintained natively. Changing native flags, and the APIs
that expose them, requires a bazel release. User-defined build
settings are defined in `.bzl` files (and thus, don't need a bazel release to
register changes). They also can be set via the command line
(if they're designated as `flags`, see more below), but can also be
set via [user-defined transitions](#user-defined-transitions).

### Defining Build Settings

#### The `build_setting` `rule()` Parameter
Build settings are rules like any other rule and are differentiated using the
Starlark `rule()` function's `build_setting` [attribute](skylark/lib/globals.html#rule.build_setting).

```python
# example/buildsettings/build_settings.bzl
string_flag = rule(
    implementation = _impl,
    build_setting = config.string(flag = True)
)
```

The `build_setting` attribute takes a function that designates the type of the
build setting. The type is limited to a set of basic Starlark types like
`bool` and `string`. See the `config` module [documentation](skylark/lib/config.html)
for details. More complicated typing can be done in the rule's implementation
function. More on this below.

The `config` function also takes an optional boolean parameter, `flag`, which is
set to false by default. if `flag` is set to true, the build setting can be set
on the command line by users as well as internally by rule writers via default
values and
[transitions](skylark/lib/transition.html#modules.transition)
.  Not all settings should be settable by
users. For example if you as a rule writer have some debug mode that you'd like
to turn on inside test rules, you don't want to give users the ability to
indiscriminately turn on that feature inside other non-test rules.

#### Using `ctx.build_setting_value`
Like all rules, build setting rules have [implementation functions](skylark/rules.html#implementation-function).
The basic Starlark-type value of the build settings can be accessed via the
`ctx.build_setting_value` method. This method is only available to [`ctx`](skylark/lib/ctx.html)
objects of build setting rules. These implementation methods can directly
forward the build settings value or do additional work on it, like type checking
or more complex struct creation. Here's how you would implement an `enum`-typed
build setting:

```python
# example/buildsettings/build_settings.bzl
TemperatureProvider = provider(fields = ['type'])

temperatures = ["HOT", "LUKEWARM", "ICED"]

def _impl(ctx):
    raw_temperature = ctx.build_setting_value
    if raw_temperature not in temperatures:
        fail(ctx.label + " build setting allowed to take values "
             + temperatures + " but was set to unallowed value "
             + raw_temperature)
    return TemperatureProvider(type = value)

temperature = rule(
    implementation = _impl,
    build_setting = config.string(flag = True)
)
```

Note: if a rule depends on a build setting, it will receive whatever providers
the build setting implementation function returns, like any other dependency.
But all other references to the value of the build setting (e.g. in transitions)
will see its basic Starlark-typed value, not this post implementation function
value.

#### Instantiating Build Settings
Rules defined with the `build_setting` parameter have an implicit mandatory
`build_setting_default` attribute. This attribute takes on the same type as
declared by the `build_setting` param.

```python
# example/buildsettings/build_settings.bzl
FlavorProvider = provider(fields = ['type'])

def _impl(ctx):
    return FlavorProvider(type = ctx.build_setting_value)<commit_msg>Fix a couple of bugs in[]<commit_after>---
layout: documentation
title: Starlark Build Configurations
---

# Starlark Build Configurations

User-definable configuration is coming to Starlark!

This makes it possible to:

* define custom flags for your project, obsoleting the need for
[`--define`](configurable-attributes.html#custom-keys)
* write
[transitions](skylark/lib/transition.html#modules.transition)
  to configure deps in different configurations     than their parents (e.g.`--     compilation_mode=opt` or `--cpu=arm`)
* bake better defaults into rules (e.g. automatically build `//my:android_app`
  with a specified SDK)

and more, all completely from .bzl files
(no Bazel release required).
<!-- [TOC] -->

## Current Status

As of Q2'19, this effort is
[partially rolled out](https://github.com/bazelbuild/bazel/issues/5574#issuecomment-458349702)
. Much functionality is guarded while we work out concerns about
memory and performance
at scale.

Related issues:
* [#5574](https://github.com/bazelbuild/bazel/issues/5574) - Starlark support for custom configuration transitions
* [#5575](https://github.com/bazelbuild/bazel/issues/5575) - Starlark support for multi-arch ("fat") binaries
* [#5577](https://github.com/bazelbuild/bazel/issues/5577) - Starlark support for custom build flags
* [#5578](https://github.com/bazelbuild/bazel/issues/5578) - Configuration doesn't block native ->
Skylark rules migration

## User-defined Build Settings
A build setting is a single piece of
[configuration](skylark/rules.html#configurations)
information. Think of a configuration as a key/value map. Setting `--cpu=ppc`
and `--copt="-DFoo"` produces a configuration that looks like
`{cpu: ppc, copt: "-DFoo"}`. Each entry is a build setting.

Traditional flags like `cpu` and `copt` are native settings i.e.
their keys are defined and their values are set inside native bazel java code.
Bazel users can only read and write them via the command line
and other APIs maintained natively. Changing native flags, and the APIs
that expose them, requires a bazel release. User-defined build
settings are defined in `.bzl` files (and thus, don't need a bazel release to
register changes). They also can be set via the command line
(if they're designated as `flags`, see more below), but can also be
set via [user-defined transitions](#user-defined-transitions).

### Defining Build Settings

#### The `build_setting` `rule()` Parameter
Build settings are rules like any other rule and are differentiated using the
Starlark `rule()` function's `build_setting` [attribute](skylark/lib/globals.html#rule.build_setting).

```python
# example/buildsettings/build_settings.bzl
string_flag = rule(
    implementation = _impl,
    build_setting = config.string(flag = True)
)
```

The `build_setting` attribute takes a function that designates the type of the
build setting. The type is limited to a set of basic Starlark types like
`bool` and `string`. See the `config` module [documentation](skylark/lib/config.html)
for details. More complicated typing can be done in the rule's implementation
function. More on this below.

The `config` function also takes an optional boolean parameter, `flag`, which is
set to false by default. if `flag` is set to true, the build setting can be set
on the command line by users as well as internally by rule writers via default
values and
[transitions](skylark/lib/transition.html#modules.transition)
.  Not all settings should be settable by
users. For example if you as a rule writer have some debug mode that you'd like
to turn on inside test rules, you don't want to give users the ability to
indiscriminately turn on that feature inside other non-test rules.

#### Using `ctx.build_setting_value`
Like all rules, build setting rules have [implementation functions](skylark/rules.html#implementation-function).
The basic Starlark-type value of the build settings can be accessed via the
`ctx.build_setting_value` method. This method is only available to [`ctx`](skylark/lib/ctx.html)
objects of build setting rules. These implementation methods can directly
forward the build settings value or do additional work on it, like type checking
or more complex struct creation. Here's how you would implement an `enum`-typed
build setting:

```python
# example/buildsettings/build_settings.bzl
TemperatureProvider = provider(fields = ['type'])

temperatures = ["HOT", "LUKEWARM", "ICED"]

def _impl(ctx):
    raw_temperature = ctx.build_setting_value
    if raw_temperature not in temperatures:
        fail(str(ctx.label) + " build setting allowed to take values {"
             + ", ".join(temperatures) + "} but was set to unallowed value "
             + raw_temperature)
    return TemperatureProvider(type = raw_temperature)

temperature = rule(
    implementation = _impl,
    build_setting = config.string(flag = True)
)
```

Note: if a rule depends on a build setting, it will receive whatever providers
the build setting implementation function returns, like any other dependency.
But all other references to the value of the build setting (e.g. in transitions)
will see its basic Starlark-typed value, not this post implementation function
value.

#### Instantiating Build Settings
Rules defined with the `build_setting` parameter have an implicit mandatory
`build_setting_default` attribute. This attribute takes on the same type as
declared by the `build_setting` param.

```python
# example/buildsettings/build_settings.bzl
FlavorProvider = provider(fields = ['type'])

def _impl(ctx):
    return FlavorProvider(type = ctx.build_setting_value)
{'fraction_non_alphanumeric': 0.08733153638814016, 'fraction_numerical': 0.00862533692722372, 'mean_word_length': 4.74948347107438, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 7, 'https://': 10, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7362381', 'n_tokens_mistral': 3171, 'n_tokens_neox': 3000, 'n_words': 1300}