| #!/bin/bash |
| # |
| # Copyright 2020 The Bazel Authors. All rights reserved. |
| # |
| # Licensed under the Apache License, Version 2.0 (the "License"); |
| # you may not use this file except in compliance with the License. |
| # You may obtain a copy of the License at |
| # |
| # http://www.apache.org/licenses/LICENSE-2.0 |
| # |
| # Unless required by applicable law or agreed to in writing, software |
| # distributed under the License is distributed on an "AS IS" BASIS, |
| # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| # See the License for the specific language governing permissions and |
| # limitations under the License. |
| # |
| # Test the toolchain transition. |
| # |
| |
| # Load the test setup defined in the parent directory |
| CURRENT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" |
| source "${CURRENT_DIR}/../integration_test_setup.sh" \ |
| || { echo "integration_test_setup.sh not found!" >&2; exit 1; } |
| |
| function set_up() { |
| create_new_workspace |
| } |
| |
| function write_constraints() { |
| mkdir constraint |
| cat >constraint/BUILD.bazel <<EOF |
| package(default_visibility = ["//visibility:public"]) |
| |
| # Common constraints for testing. |
| |
| constraint_setting(name = "type") |
| |
| constraint_value( |
| name = "target", |
| constraint_setting = ":type", |
| ) |
| |
| constraint_value( |
| name = "exec", |
| constraint_setting = ":type", |
| ) |
| |
| constraint_value( |
| name = "host", |
| constraint_setting = ":type", |
| ) |
| |
| constraint_setting(name = "level") |
| |
| constraint_value( |
| name = "alpha", |
| constraint_setting = ":level", |
| ) |
| |
| constraint_value( |
| name = "beta", |
| constraint_setting = ":level", |
| ) |
| EOF |
| } |
| |
| function write_platforms() { |
| mkdir platform |
| cat >platform/platform.bzl <<EOF |
| ShowPlatformInfo = provider(fields = ["platform_type", "level"]) |
| |
| def describe_platform_info(platform_info): |
| if platform_info.level: |
| return "%s-%s" % (platform_info.platform_type, platform_info.level) |
| else: |
| return platform_info.platform_type |
| |
| def _show_platform_impl(ctx): |
| target_constraint = ctx.attr._target_constraint[platform_common.ConstraintValueInfo] |
| exec_constraint = ctx.attr._exec_constraint[platform_common.ConstraintValueInfo] |
| host_constraint = ctx.attr._host_constraint[platform_common.ConstraintValueInfo] |
| alpha_constraint = ctx.attr._alpha_constraint[platform_common.ConstraintValueInfo] |
| beta_constraint = ctx.attr._beta_constraint[platform_common.ConstraintValueInfo] |
| type = "unknown" |
| if ctx.target_platform_has_constraint(target_constraint): |
| type = "target" |
| elif ctx.target_platform_has_constraint(exec_constraint): |
| type = "exec" |
| elif ctx.target_platform_has_constraint(host_constraint): |
| type = "host" |
| level = None |
| if ctx.target_platform_has_constraint(alpha_constraint): |
| level = "alpha" |
| elif ctx.target_platform_has_constraint(beta_constraint): |
| level = "beta" |
| |
| return [ShowPlatformInfo( |
| platform_type = type, |
| level = level, |
| )] |
| |
| show_platform = rule( |
| implementation = _show_platform_impl, |
| attrs = { |
| "_target_constraint": attr.label(default = Label("//constraint:target")), |
| "_exec_constraint": attr.label(default = Label("//constraint:exec")), |
| "_host_constraint": attr.label(default = Label("//constraint:host")), |
| "_alpha_constraint": attr.label(default = Label("//constraint:alpha")), |
| "_beta_constraint": attr.label(default = Label("//constraint:beta")), |
| }, |
| provides = [ShowPlatformInfo], |
| ) |
| EOF |
| cat >platform/BUILD.bazel <<EOF |
| load(":platform.bzl", "show_platform") |
| |
| package(default_visibility = ["//visibility:public"]) |
| |
| show_platform(name = "platform") |
| |
| # Common platforms. |
| |
| # Execution platforms. |
| platform( |
| name = "exec_alpha", |
| constraint_values = [ |
| "//constraint:alpha", |
| "//constraint:exec", |
| ], |
| ) |
| |
| platform( |
| name = "exec_beta", |
| constraint_values = [ |
| "//constraint:beta", |
| "//constraint:exec", |
| ], |
| ) |
| |
| # Host platform. |
| platform( |
| name = "host", |
| constraint_values = [ |
| "//constraint:host", |
| ], |
| ) |
| |
| # Target platform. |
| platform( |
| name = "target", |
| constraint_values = [ |
| "//constraint:target", |
| ], |
| ) |
| EOF |
| # Append to WORKSPACE |
| cat >>WORKSPACE <<EOF |
| register_execution_platforms( |
| "//platform:exec_alpha", |
| "//platform:exec_beta", |
| ) |
| EOF |
| } |
| |
| function write_toolchains() { |
| mkdir toolchain |
| cat >toolchain/toolchain.bzl <<EOF |
| load("//platform:platform.bzl", "ShowPlatformInfo", "describe_platform_info") |
| load(":extra_lib.bzl", "ExtraMessageProvider") |
| |
| def _sample_toolchain_impl(ctx): |
| target_dep = describe_platform_info(ctx.attr._target_dep[ShowPlatformInfo]) |
| tool_dep = describe_platform_info(ctx.attr._tool_dep[ShowPlatformInfo]) |
| dep_messages = [] |
| for dep in ctx.attr.deps: |
| message = dep[ExtraMessageProvider].message |
| dep_messages.append(message) |
| message = "sample_toolchain: message: %s, target_dep: %s, tool_dep: %s, extra_deps: [%s]" % ( |
| ctx.attr.message, |
| target_dep, |
| tool_dep, |
| ", ".join(dep_messages), |
| ) |
| |
| toolchain = platform_common.ToolchainInfo( |
| message = message, |
| ) |
| return [toolchain] |
| |
| sample_toolchain = rule( |
| implementation = _sample_toolchain_impl, |
| attrs = { |
| "message": attr.string(), |
| "deps": attr.label_list(), |
| "_target_dep": attr.label(cfg = "target", providers = [ShowPlatformInfo], default = Label("//platform")), |
| "_tool_dep": attr.label(cfg = "exec", providers = [ShowPlatformInfo], default = Label("//platform")), |
| }, |
| ) |
| EOF |
| cat >toolchain/extra_lib.bzl <<EOF |
| load("//platform:platform.bzl", "ShowPlatformInfo", "describe_platform_info") |
| |
| ExtraMessageProvider = provider(fields = ["message"]) |
| |
| def _extra_lib_impl(ctx): |
| target_dep = describe_platform_info(ctx.attr._target_dep[ShowPlatformInfo]) |
| tool_dep = describe_platform_info(ctx.attr._tool_dep[ShowPlatformInfo]) |
| message = "extra_lib: message: %s, target_dep: %s, tool_dep: %s" % ( |
| ctx.attr.message, |
| target_dep, |
| tool_dep, |
| ) |
| provider = ExtraMessageProvider(message = message) |
| |
| return [provider] |
| |
| extra_lib = rule( |
| implementation = _extra_lib_impl, |
| attrs = { |
| "message": attr.string(), |
| "_target_dep": attr.label(cfg = "target", providers = [ShowPlatformInfo], default = Label("//platform")), |
| "_tool_dep": attr.label(cfg = "exec", providers = [ShowPlatformInfo], default = Label("//platform")), |
| }, |
| provides = [ExtraMessageProvider], |
| ) |
| EOF |
| cat >toolchain/BUILD.bazel <<EOF |
| package(default_visibility = ["//visibility:public"]) |
| |
| load(":toolchain.bzl", "sample_toolchain") |
| |
| toolchain_type(name = "toolchain_type") |
| |
| sample_toolchain( |
| name = "sample_toolchain_alpha_impl", |
| message = "alpha toolchain", |
| deps = [ |
| ":extra", |
| ], |
| ) |
| |
| toolchain( |
| name = "sample_toolchain_alpha", |
| exec_compatible_with = [ |
| "//constraint:alpha", |
| ], |
| toolchain = "sample_toolchain_alpha_impl", |
| toolchain_type = ":toolchain_type", |
| ) |
| |
| sample_toolchain( |
| name = "sample_toolchain_beta_impl", |
| message = "beta toolchain", |
| deps = [ |
| ":extra", |
| ], |
| ) |
| |
| load(":extra_lib.bzl", "extra_lib") |
| |
| extra_lib( |
| name = "extra", |
| message = "extra_lib foo", |
| ) |
| |
| toolchain( |
| name = "sample_toolchain_beta", |
| exec_compatible_with = [ |
| "//constraint:beta", |
| ], |
| toolchain = "sample_toolchain_beta_impl", |
| toolchain_type = ":toolchain_type", |
| ) |
| EOF |
| # Append to WORKSPACE |
| cat >>WORKSPACE <<EOF |
| register_toolchains( |
| "//toolchain:sample_toolchain_alpha", |
| "//toolchain:sample_toolchain_beta", |
| ) |
| EOF |
| } |
| |
| function write_rule() { |
| mkdir rule |
| cat >rule/rule.bzl <<EOF |
| load("//platform:platform.bzl", "ShowPlatformInfo", "describe_platform_info") |
| |
| def _sample_impl(ctx): |
| toolchain = ctx.toolchains["//toolchain:toolchain_type"] |
| message = ctx.attr.message |
| exec_platform = describe_platform_info(ctx.attr._exec[ShowPlatformInfo]) |
| |
| str = 'Using toolchain: rule message: "%s", exec platform: "%s", toolchain message: "%s"\n' % (message, exec_platform, toolchain.message) |
| |
| log = ctx.outputs.log |
| ctx.actions.write( |
| output = log, |
| content = str, |
| ) |
| return [DefaultInfo(files = depset([log]))] |
| |
| sample = rule( |
| implementation = _sample_impl, |
| attrs = { |
| "message": attr.string(), |
| "_exec": attr.label(cfg = "exec", providers = [ShowPlatformInfo], default = Label("//platform")), |
| }, |
| outputs = { |
| "log": "%{name}.log", |
| }, |
| toolchains = ["//toolchain:toolchain_type"], |
| incompatible_use_toolchain_transition = True, |
| ) |
| EOF |
| cat >rule/BUILD.bazel <<EOF |
| package(default_visibility = ["//visibility:public"]) |
| |
| EOF |
| } |
| |
| function test_toolchain_transition() { |
| write_constraints |
| write_platforms |
| write_toolchains |
| write_rule |
| |
| cat >BUILD.bazel <<EOF |
| package(default_visibility = ["//visibility:public"]) |
| |
| load("//rule:rule.bzl", "sample") |
| |
| sample( |
| name = "sample", |
| exec_compatible_with = [ |
| "//constraint:beta", |
| ], |
| message = "Hello", |
| ) |
| EOF |
| |
| bazel build \ |
| --platforms=//platform:target \ |
| --host_platform=//platform:host \ |
| //:sample &> $TEST_log || fail "Build failed" |
| |
| # Verify contents of sample.log. |
| cat bazel-bin/sample.log >> $TEST_log |
| # The execution platform should be beta. |
| expect_log 'rule message: "Hello", exec platform: "exec-beta"' |
| # The toolchain should have proper target and exec matching the top target. |
| expect_log 'sample_toolchain: message: beta toolchain, target_dep: target, tool_dep: exec-beta' |
| # The toolchain's dependencies should use alpha for exec. |
| # Make sure the exec platform does not propagate to further dependencies. |
| expect_log 'extra_lib: message: extra_lib foo, target_dep: target, tool_dep: exec-alpha' |
| } |
| |
| run_suite "toolchain transition tests" |