diff --git a/examples/08_using_build_setting/BUILD b/examples/07_select_on_build_setting/BUILD similarity index 100% rename from examples/08_using_build_setting/BUILD rename to examples/07_select_on_build_setting/BUILD diff --git a/examples/07_select_on_build_setting/README.md b/examples/07_select_on_build_setting/README.md new file mode 100644 index 0000000..751535c --- /dev/null +++ b/examples/07_select_on_build_setting/README.md @@ -0,0 +1,87 @@ +# Example 07: Select on build settings + +Like examples 03 (select on constraint) and 04 (select on platform), this +example demonstrates how to affect a build target via configuration. + +## Commands + +``` +bazel build //examples/07_select_on_build_setting +> yolo_library( +> name = 'a', +> toolchain = { +> 'targetting_cpu': 'host', +> 'targetting_os': 'host', +> 'executing_on_cpu': 'host', +> 'executing_on_os': 'host', +> }, +> ) + +bazel build //examples/07_select_on_build_setting:a --//examples/07_select_on_build_setting:foo_enabled +> yolo_library( +> name = 'a', +> toolchain = { +> 'targetting_cpu': 'host', +> 'targetting_os': 'host', +> 'executing_on_cpu': 'host', +> 'executing_on_os': 'host', +> }, +> ) +> yolo_library( +> name = 'only_with_foo', +> toolchain = { +> 'targetting_cpu': 'host', +> 'targetting_os': 'host', +> 'executing_on_cpu': 'host', +> 'executing_on_os': 'host', +> }, +> ) + +bazel build //examples/07_select_on_build_setting:a --//examples/07_select_on_build_setting:foo_enabled=0 + +> yolo_library( +> name = 'a', +> toolchain = { +> 'targetting_cpu': 'host', +> 'targetting_os': 'host', +> 'executing_on_cpu': 'host', +> 'executing_on_os': 'host', +> }, +> ) + +bazel build //examples/07_select_on_build_setting:a --//examples/07_select_on_build_setting:foo_enabled=1 + +> yolo_library( +> name = 'a', +> toolchain = { +> 'targetting_cpu': 'host', +> 'targetting_os': 'host', +> 'executing_on_cpu': 'host', +> 'executing_on_os': 'host', +> }, +> ) +> yolo_library( +> name = 'only_with_foo', +> toolchain = { +> 'targetting_cpu': 'host', +> 'targetting_os': 'host', +> 'executing_on_cpu': 'host', +> 'executing_on_os': 'host', +> }, +> ) +``` + +## Description + +Here we show how to use Bazel's [Starlark build settings](https://docs.bazel.build/versions/master/skylark/config.html) to +trigger different build variations. Build settings are pieces of configuration +that are defined and instantiated in Starlark as targets. They are integrated +with [`select`](https://docs.bazel.build/versions/master/skylark/config.html#build-settings-and-select) as seen here, and can also be accessed in other [rule implementation +functions](https://docs.bazel.build/versions/master/skylark/config.html#depending-on-build-settings) and during [configuration transitions](https://docs.bazel.build/versions/master/skylark/config.html#defining-transitions-in-starlark). + +Since we only need a simple build setting in this example, we use the standard `bool`-typed +build setting defined in [Skylib's +common_settings.bzl](https://github.com/bazelbuild/bazel-skylib/blob/master/rules/common_settings.bzl). +We highly recommend using these standard definitions in your project unless you need something more +complicated, like [a more complexly-typed build +setting](https://docs.bazel.build/versions/master/skylark/config.html#using-ctxbuild_setting_value). diff --git a/examples/07_using_define/BUILD b/examples/07_using_define/BUILD deleted file mode 100644 index ad33499..0000000 --- a/examples/07_using_define/BUILD +++ /dev/null @@ -1,24 +0,0 @@ -load("//yolo:defs.bzl", "yolo_library") - -config_setting( - name = "is_foo_defined", - values = { - "define": "is_foo_defined=true", - }, -) - -filegroup( - name = "everything", - srcs = [":a"] + select({ - ":is_foo_defined": [":only_with_foo"], - "//conditions:default": [], - }), -) - -yolo_library( - name = "a", -) - -yolo_library( - name = "only_with_foo", -) diff --git a/examples/07_using_define/README.md b/examples/07_using_define/README.md deleted file mode 100644 index a99de2c..0000000 --- a/examples/07_using_define/README.md +++ /dev/null @@ -1,56 +0,0 @@ -# Example 07: Using --define - -Example demonstraint the use of -[`--define`](https://docs.bazel.build/versions/master/command-line-reference.html#flag--define). - -## Commands - -``` -bazel build //examples/07_using_define:everything - -> yolo_library( -> name = 'a', -> toolchain = { -> 'targetting_cpu': 'host', -> 'targetting_os': 'host', -> 'executing_on_cpu': 'host', -> 'executing_on_os': 'host', -> }, -> ) - -bazel build //examples/07_using_define:everything --define is_foo_defined=true - -> yolo_library( -> name = 'only_with_foo', -> toolchain = { -> 'targetting_cpu': 'host', -> 'targetting_os': 'host', -> 'executing_on_cpu': 'host', -> 'executing_on_os': 'host', -> }, -> ) -> yolo_library( -> name = 'a', -> toolchain = { -> 'targetting_cpu': 'host', -> 'targetting_os': 'host', -> 'executing_on_cpu': 'host', -> 'executing_on_os': 'host', -> }, -> ) - -``` - -# Description - -Here we have a simple example how to use -[`--define`](https://docs.bazel.build/versions/master/command-line-reference.html#flag--define). -`--define` is one of the simplest configurability mechanism in Bazel, it's also -one of the oldest and least expressive. - -`--define` is typically used when more sophistication is not needed. It should -not be used for toolchain selection, for configuring the build with that -logically belongs platforms and constraints, and for configuration state that is -read by rules themselves. - - diff --git a/examples/08_deps_with_different_platforms/BUILD b/examples/08_deps_with_different_platforms/BUILD new file mode 100644 index 0000000..e007610 --- /dev/null +++ b/examples/08_deps_with_different_platforms/BUILD @@ -0,0 +1,8 @@ +load("//examples/08_deps_with_different_platforms:defs.bzl", "my_rule") + +my_rule( + name = "my_rule", + dep = ":dep" +) + +my_rule(name = "dep") diff --git a/examples/08_deps_with_different_platforms/README.md b/examples/08_deps_with_different_platforms/README.md new file mode 100644 index 0000000..21423c2 --- /dev/null +++ b/examples/08_deps_with_different_platforms/README.md @@ -0,0 +1,37 @@ +# Example 08: Building deps on different platforms +This example demonstrates how to build dependencies of a rule for a +different platform from the rule itself. + +## Commands +``` +bazel build //examples/08_deps_with_different_platforms:my_rule +> Running implementation fxn of dep +> platform from config: //:linux_platform +> Running implementation fxn of my_rule +> platform from config: @local_config_platform//:host + +bazel build //examples/08_deps_with_different_platforms:my_rule --platforms=//:windows_platform +> Running implementation fxn of dep +> platform from config: //:linux_platform +> Running implementation fxn of my_rule +> platform from config: //:windows_platform + +``` + +## Description +Sometimes you want to write a rule that can build its +dependencies for different platforms. Instead of two +seperate Bazel builds, you can specify building +dependencies with a different configuration using +Starlark [transitions](https://docs.bazel.build/versions/0.27.0/skylark/config.html#user-defined-transitions). + +While starlark transitions are designed to transition on [build +settings](https://docs.bazel.build/versions/0.27.0/skylark/config.html#user-defined-build-settings) +(see example 07), this example shows how they can also work on native options. + +Since starlark transitions create new configured targets, they have the +potential to exponentially grow your configured target graph size. They have +a built in whitelisting mechanism controlled by the mandatory `_whitelist_function_transition` +attribute. If you'd like to control your own whitelist for your project, you can create one +at the location `//tools/whitelists/function_transition_whitelist` in your project. Otherwise, +you can set the attribute to the all-encompassing list at `@bazel_tools//tools/whitelists/function_transition_whitelist` (as seen in the example). \ No newline at end of file diff --git a/examples/08_deps_with_different_platforms/defs.bzl b/examples/08_deps_with_different_platforms/defs.bzl new file mode 100644 index 0000000..8c87e8e --- /dev/null +++ b/examples/08_deps_with_different_platforms/defs.bzl @@ -0,0 +1,26 @@ + +def _transition_impl(settings, attr): + return {"//command_line_option:platforms": [Label("//:linux_platform")]} + +windows_transition = transition( + implementation = _transition_impl, + inputs = [], + outputs = ["//command_line_option:platforms"], + ) + +def _impl(ctx): + print("Running implementation fxn of " + ctx.attr.name) + platform_data = ctx.fragments.platform + print("platform from config: " + str(platform_data.platform)) + return [] + +my_rule = rule( + implementation = _impl, + attrs = { + # this build the 'dep' attr with the windows platform + "dep" : attr.label(cfg = windows_transition), + "_whitelist_function_transition": + attr.label(default = "@bazel_tools//tools/whitelists/function_transition_whitelist"), + }, + fragments = ["platform"] +) diff --git a/examples/08_using_build_setting/README.md b/examples/08_using_build_setting/README.md deleted file mode 100644 index 9cc8fa9..0000000 --- a/examples/08_using_build_setting/README.md +++ /dev/null @@ -1,81 +0,0 @@ -# Example 08: Using build_setting - -This example demonstrates how to use Starlark configuration options. - -## Commands - -``` -bazel build //examples/08_using_build_setting:a - -> yolo_library( -> name = 'a', -> toolchain = { -> 'targetting_cpu': 'host', -> 'targetting_os': 'host', -> 'executing_on_cpu': 'host', -> 'executing_on_os': 'host', -> }, -> ) - -bazel build //examples/08_using_build_setting:a --//examples/08_using_build_setting:foo_enabled - -> yolo_library( -> name = 'a', -> toolchain = { -> 'targetting_cpu': 'host', -> 'targetting_os': 'host', -> 'executing_on_cpu': 'host', -> 'executing_on_os': 'host', -> }, -> ) -> yolo_library( -> name = 'only_with_foo', -> toolchain = { -> 'targetting_cpu': 'host', -> 'targetting_os': 'host', -> 'executing_on_cpu': 'host', -> 'executing_on_os': 'host', -> }, -> ) - -bazel build //examples/08_using_build_setting:a --//examples/08_using_build_setting:foo_enabled=0 - -> yolo_library( -> name = 'a', -> toolchain = { -> 'targetting_cpu': 'host', -> 'targetting_os': 'host', -> 'executing_on_cpu': 'host', -> 'executing_on_os': 'host', -> }, -> ) - -bazel build //examples/08_using_build_setting:a --//examples/08_using_build_setting:foo_enabled=1 - -> yolo_library( -> name = 'a', -> toolchain = { -> 'targetting_cpu': 'host', -> 'targetting_os': 'host', -> 'executing_on_cpu': 'host', -> 'executing_on_os': 'host', -> }, -> ) -> yolo_library( -> name = 'only_with_foo', -> toolchain = { -> 'targetting_cpu': 'host', -> 'targetting_os': 'host', -> 'executing_on_cpu': 'host', -> 'executing_on_os': 'host', -> }, -> ) -``` - -## Description - -Here we show how to use Bazel's [Starlark configuration -options](https://docs.bazel.build/versions/master/skylark/config.html) to -express exactly what exercise 07 - Using --define does. To simplify our example -we make use of [Skylib's -common_settings.bzl](https://github.com/bazelbuild/bazel-skylib/blob/master/rules/common_settings.bzl). diff --git a/examples/09_config_inside_rule_impl/BUILD b/examples/09_config_inside_rule_impl/BUILD new file mode 100644 index 0000000..43164e2 --- /dev/null +++ b/examples/09_config_inside_rule_impl/BUILD @@ -0,0 +1,9 @@ +load("@bazel_skylib//rules:common_settings.bzl", "bool_flag") +load("//examples/09_config_inside_rule_impl:defs.bzl", "my_rule") + +bool_flag( + name = "foo_enabled_flag", + build_setting_default = False, +) + +my_rule(name = "my_rule",) \ No newline at end of file diff --git a/examples/09_config_inside_rule_impl/README.md b/examples/09_config_inside_rule_impl/README.md new file mode 100644 index 0000000..35394e7 --- /dev/null +++ b/examples/09_config_inside_rule_impl/README.md @@ -0,0 +1,31 @@ +# Example 09: Reading configurations inside rule implementation +This example demonstrates how to access configuration information +by depending on build setting targets + +## Commands +``` +bazel build //examples/09_config_inside_rule_impl:my_rule +> Printing from my_rule +> _foo_enabled = False + +bazel build //examples/09_config_inside_rule_impl:my_rule \ + --//examples/09_config_inside_rule_impl:foo_enabled_flag=True +> Printing from my_rule +> _foo_enabled = True +``` + +## Description +Traditionally, you would need to use the +[`fragments`](https://docs.bazel.build/versions/master/skylark/rules.html#configuration-fragments) +API to access configuration, but with Starlark-defined build settings +rules can declare regular dependencies on build settings and read their +current values. That means if a build setting was changed at any point +in the build before this rule is analyzed (i.e. on the command line or +by a [configuration +transition](https://docs.bazel.build/versions/0.27.0/skylark/config.html#user-defined-transition)) +, the updated value will be read by the rule here. + +This example also shows the best practice of reading build settings via +[private attributes](https://docs.bazel.build/versions/master/skylark/rules.html#private-attributes-and-implicit-dependencies). By picking an attribute +name beginning with and underscore, the attribute becomes private i.e. users +can't override the value. \ No newline at end of file diff --git a/examples/09_config_inside_rule_impl/defs.bzl b/examples/09_config_inside_rule_impl/defs.bzl new file mode 100644 index 0000000..a6a4528 --- /dev/null +++ b/examples/09_config_inside_rule_impl/defs.bzl @@ -0,0 +1,13 @@ +load("@bazel_skylib//rules:common_settings.bzl", "BuildSettingInfo") + +def _impl(ctx): + print("Printing from " + ctx.attr.name) + print("_foo_enabled = " + str(ctx.attr._foo_enabled[BuildSettingInfo].value)) + return [] + +my_rule = rule( + implementation = _impl, + attrs = { + "_foo_enabled": attr.label(default = Label("//examples/09_config_inside_rule_impl:foo_enabled_flag")) + } +) \ No newline at end of file