| #!/bin/bash | |
| # | |
| # Copyright 2015 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 handling of Skylark loads from and in external repositories. | |
| # | |
| # 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; } | |
| # The following tests build an instance of a Skylark macro loaded from a | |
| # local_repository, which in turns loads another Skylark file either from | |
| # the external repo or the main repo, depending on the test parameters. | |
| # The tests cover all the valid syntactic variants of the second load. The | |
| # package structure used for the tests is as follows: | |
| # | |
| # ${WORKSPACE_DIR}/ | |
| # WORKSPACE | |
| # local_pkg/ | |
| # BUILD | |
| # another_local_pkg/ | |
| # BUILD | |
| # local_constants.bzl | |
| # ${external_repo}/ | |
| # external_pkg/ | |
| # BUILD | |
| # macro_def.bzl | |
| # external_constants.bzl | |
| function run_external_skylark_load_test() { | |
| load_target_to_test=$1 | |
| expected_test_output=$2 | |
| create_new_workspace | |
| external_repo=${new_workspace_dir} | |
| cat > ${WORKSPACE_DIR}/WORKSPACE <<EOF | |
| local_repository(name = "external_repo", path = "${external_repo}") | |
| EOF | |
| mkdir ${WORKSPACE_DIR}/local_pkg | |
| cat > ${WORKSPACE_DIR}/local_pkg/BUILD <<EOF | |
| load("@external_repo//external_pkg:macro_def.bzl", "macro") | |
| macro(name="macro_instance") | |
| EOF | |
| mkdir ${WORKSPACE_DIR}/another_local_pkg | |
| touch ${WORKSPACE_DIR}/another_local_pkg/BUILD | |
| cat > ${WORKSPACE_DIR}/another_local_pkg/local_constants.bzl <<EOF | |
| OUTPUT_STRING = "LOCAL!" | |
| EOF | |
| mkdir ${external_repo}/external_pkg | |
| touch ${external_repo}/external_pkg/BUILD | |
| cat > ${external_repo}/external_pkg/macro_def.bzl <<EOF | |
| load("${load_target_to_test}", "OUTPUT_STRING") | |
| def macro(name): | |
| native.genrule( | |
| name = name, | |
| outs = [name + ".txt"], | |
| cmd = "echo " + OUTPUT_STRING + " > \$@", | |
| ) | |
| EOF | |
| cat > ${external_repo}/external_pkg/external_constants.bzl <<EOF | |
| OUTPUT_STRING = "EXTERNAL!" | |
| EOF | |
| cd ${WORKSPACE_DIR} | |
| bazel build local_pkg:macro_instance >& $TEST_log || \ | |
| fail "Expected build to succeed" | |
| assert_contains "${expected_test_output}" \ | |
| bazel-genfiles/local_pkg/macro_instance.txt | |
| } | |
| # A label with an explicit external repo reference should be resolved relative | |
| # to the external repo. | |
| function test_load_skylark_from_external_repo_with_pkg_relative_label_load() { | |
| run_external_skylark_load_test \ | |
| "@external_repo//external_pkg:external_constants.bzl" "EXTERNAL!" | |
| } | |
| # A relative label should be resolved relative to the external package. | |
| function test_load_skylark_from_external_repo_with_pkg_relative_label_load() { | |
| run_external_skylark_load_test ":external_constants.bzl" "EXTERNAL!" | |
| } | |
| # An absolute label with no repo prefix should be resolved relative to the | |
| # current (external) repo. | |
| function test_load_skylark_from_external_repo_with_pkg_relative_path_load() { | |
| run_external_skylark_load_test "//external_pkg:external_constants.bzl" \ | |
| "EXTERNAL!" | |
| } | |
| # An absolute label with the special "@" prefix should cause be resolved | |
| # relative to the default repo. | |
| function test_load_skylark_from_external_repo_with_repo_relative_label_load() { | |
| run_external_skylark_load_test "@//another_local_pkg:local_constants.bzl" \ | |
| "LOCAL!" | |
| } | |
| function test_skylark_repository_relative_label() { | |
| repo2=$TEST_TMPDIR/repo2 | |
| mkdir -p $repo2 | |
| touch $repo2/WORKSPACE $repo2/BUILD | |
| cat > $repo2/remote.bzl <<EOF | |
| def _impl(ctx): | |
| print(Label("//foo:bar")) | |
| remote_rule = rule( | |
| implementation = _impl, | |
| ) | |
| EOF | |
| cat > WORKSPACE <<EOF | |
| local_repository( | |
| name = "r", | |
| path = "$repo2", | |
| ) | |
| EOF | |
| cat > BUILD <<EOF | |
| load('@r//:remote.bzl', 'remote_rule') | |
| remote_rule(name = 'local') | |
| EOF | |
| bazel build //:local &> $TEST_log || fail "Building local failed" | |
| expect_log "@r//foo:bar" | |
| cat > $repo2/remote.bzl <<EOF | |
| def _impl(ctx): | |
| print(Label("//foo:bar", relative_to_caller_repository = True)) | |
| remote_rule = rule( | |
| implementation = _impl, | |
| ) | |
| EOF | |
| bazel build //:local &> $TEST_log || fail "Building local failed" | |
| expect_log "//foo:bar" | |
| } | |
| # Going one level deeper: if we have: | |
| # local/ | |
| # BUILD | |
| # r1/ | |
| # BUILD | |
| # r2/ | |
| # BUILD | |
| # remote.bzl | |
| # If //foo in local depends on //bar in r1, which is a Skylark rule | |
| # defined in r2/remote.bzl, then a Label in remote.bzl should either | |
| # resolve to @r2//whatever or @r1//whatever. | |
| function test_skylark_repository_nested_relative_label() { | |
| repo1=$TEST_TMPDIR/repo1 | |
| repo2=$TEST_TMPDIR/repo2 | |
| mkdir -p $repo1 $repo2 | |
| # local | |
| cat > WORKSPACE <<EOF | |
| local_repository( | |
| name = "r1", | |
| path = "$repo1", | |
| ) | |
| local_repository( | |
| name = "r2", | |
| path = "$repo2", | |
| ) | |
| EOF | |
| cat > BUILD <<'EOF' | |
| genrule( | |
| name = "foo", | |
| srcs = ["@r1//:bar"], | |
| outs = ["foo.out"], | |
| cmd = "echo '$(SRCS)' > $@", | |
| ) | |
| EOF | |
| # r1 | |
| touch $repo1/WORKSPACE | |
| cat > $repo1/BUILD <<EOF | |
| load('@r2//:remote.bzl', 'remote_rule') | |
| remote_rule( | |
| name = 'bar', | |
| visibility = ["//visibility:public"] | |
| ) | |
| EOF | |
| # r2 | |
| touch $repo2/WORKSPACE $repo2/BUILD | |
| cat > $repo2/remote.bzl <<EOF | |
| def _impl(ctx): | |
| print(Label("//foo:bar")) | |
| remote_rule = rule( | |
| implementation = _impl, | |
| ) | |
| EOF | |
| bazel build //:foo &> $TEST_log || fail "Building local failed" | |
| expect_log "@r2//foo:bar" | |
| cat > $repo2/remote.bzl <<EOF | |
| def _impl(ctx): | |
| print(Label("//foo:bar", relative_to_caller_repository = True)) | |
| remote_rule = rule( | |
| implementation = _impl, | |
| ) | |
| EOF | |
| bazel build //:foo &> $TEST_log || fail "Building local failed" | |
| expect_log "@r1//foo:bar" | |
| } | |
| function test_aspects_and_skylark_repositories() { | |
| cat > WORKSPACE <<EOF | |
| bind(name="x1", actual="//:x1") | |
| load("//:repo.bzl", "repo") | |
| bind(name="x2", actual="//:x2") | |
| EOF | |
| cat > BUILD <<EOF | |
| load("//:rule.bzl", "test_rule") | |
| filegroup(name = "x1", visibility = ["//visibility:public"]) | |
| filegroup(name = "x2", visibility = ["//visibility:public"]) | |
| test_rule( | |
| name = "tr", | |
| deps = ["//external:x1", "//external:x2"], | |
| ) | |
| EOF | |
| cat > repo.bzl <<EOF | |
| def repo(): | |
| pass | |
| EOF | |
| cat > rule.bzl <<EOF | |
| def test_aspect_impl(target, ctx): | |
| return struct() | |
| test_aspect = aspect( | |
| attrs = { | |
| "_x": attr.label_list(default = [ | |
| Label("//external:x1"), | |
| Label("//external:x2"), | |
| ]), | |
| }, | |
| implementation = test_aspect_impl, | |
| ) | |
| def test_rule_impl(ctx): | |
| return struct() | |
| test_rule = rule( | |
| attrs = { | |
| "deps": attr.label_list( | |
| allow_files = True, | |
| allow_rules = [ | |
| "filegroup", | |
| ], | |
| aspects = [test_aspect], | |
| ), | |
| }, | |
| implementation = test_rule_impl, | |
| ) | |
| EOF | |
| bazel build //:tr || fail "build failed" | |
| } | |
| run_suite "Test Skylark loads from/in external repositories" |