From 7dea6a38d1cf4c0f527eb28a93c78f7253b3a745 Mon Sep 17 00:00:00 2001 From: Fabian Meumertzheim Date: Thu, 15 Sep 2022 12:45:16 +0200 Subject: [PATCH] Add java_current_repository rule --- .../integration/java_integration_test.sh | 162 ++++++++++++++++++ tools/BUILD | 1 + tools/java/BUILD | 6 + tools/java/BUILD.tools | 6 + tools/java/runfiles/BUILD | 8 + tools/java/runfiles/BUILD.tools | 8 + .../java/runfiles/RunfilesConstants.java.tpl | 25 +++ .../java/runfiles/java_current_repository.bzl | 65 +++++++ 8 files changed, 281 insertions(+) create mode 100644 tools/java/runfiles/RunfilesConstants.java.tpl create mode 100644 tools/java/runfiles/java_current_repository.bzl diff --git a/src/test/shell/integration/java_integration_test.sh b/src/test/shell/integration/java_integration_test.sh index 2bc96a2dbe1876..70f764d1121a51 100755 --- a/src/test/shell/integration/java_integration_test.sh +++ b/src/test/shell/integration/java_integration_test.sh @@ -883,4 +883,166 @@ EOF || fail "aspect Args do not contain both params files" } +function test_java_current_repository() { + cat >> WORKSPACE <<'EOF' +local_repository( + name = "other_repo", + path = "other_repo", +) +EOF + + cat > BUILD.bazel <<'EOF' +load("@bazel_tools//tools/java/runfiles:java_current_repository.bzl", "java_current_repository") + +java_current_repository( + name = "java_current_repository", + tags = ["some_tag"], +) +EOF + + mkdir -p pkg + cat > pkg/BUILD.bazel <<'EOF' +java_library( + name = "library", + srcs = ["Library.java"], + visibility = ["//visibility:public"], + deps = ["//:java_current_repository"], +) +java_binary( + name = "binary", + srcs = ["Binary.java"], + main_class = "com.example.Binary", + deps = [ + ":library", + "//:java_current_repository", + ], +) +java_test( + name = "test", + srcs = ["Test.java"], + main_class = "com.example.Test", + use_testrunner = False, + deps = [ + ":library", + "//:java_current_repository", + ], +) +EOF + + cat > pkg/Library.java <<'EOF' +package com.example; + +import static com.google.devtools.build.runfiles.RunfilesConstants.CURRENT_REPOSITORY; + +public class Library { + public static void printRepositoryName() { + System.out.printf("in pkg/Library.java: '%s'%n", CURRENT_REPOSITORY); + } +} +EOF + + cat > pkg/Binary.java <<'EOF' +package com.example; + +import com.google.devtools.build.runfiles.RunfilesConstants; + +public class Binary { + public static void main(String[] args) { + System.out.printf("in pkg/Binary.java: '%s'%n", RunfilesConstants.CURRENT_REPOSITORY); + Library.printRepositoryName(); + } +} +EOF + + cat > pkg/Test.java <<'EOF' +package com.example; + +import com.google.devtools.build.runfiles.RunfilesConstants; + +public class Test { + public static void main(String[] args) { + System.out.printf("in pkg/Test.java: '%s'%n", RunfilesConstants.CURRENT_REPOSITORY); + Library.printRepositoryName(); + } +} +EOF + + mkdir -p other_repo + touch other_repo/WORKSPACE + + cat > other_repo/BUILD.bazel <<'EOF' +load("@bazel_tools//tools/java/runfiles:java_current_repository.bzl", "java_current_repository") + +java_current_repository( + name = "java_current_repository", +) +EOF +# + mkdir -p other_repo/pkg + cat > other_repo/pkg/BUILD.bazel <<'EOF' +java_binary( + name = "binary", + srcs = ["Binary.java"], + main_class = "com.example.Binary", + deps = [ + "//:java_current_repository", + "@//pkg:library", + ], +) +java_test( + name = "test", + srcs = ["Test.java"], + main_class = "com.example.Test", + use_testrunner = False, + deps = [ + "//:java_current_repository", + "@//pkg:library", + ], +) +EOF + + cat > other_repo/pkg/Binary.java <<'EOF' +package com.example; + +import com.google.devtools.build.runfiles.RunfilesConstants; + +public class Binary { + public static void main(String[] args) { + System.out.printf("in external/other_repo/pkg/Binary.java: '%s'%n", RunfilesConstants.CURRENT_REPOSITORY); + Library.printRepositoryName(); + } +} +EOF + + cat > other_repo/pkg/Test.java <<'EOF' +package com.example; + +import com.google.devtools.build.runfiles.RunfilesConstants; + +public class Test { + public static void main(String[] args) { + System.out.printf("in external/other_repo/pkg/Test.java: '%s'%n", RunfilesConstants.CURRENT_REPOSITORY); + Library.printRepositoryName(); + } +} +EOF + + bazel run //pkg:binary &>"$TEST_log" || fail "Run should succeed" + expect_log "in pkg/Binary.java: ''" + expect_log "in pkg/Library.java: ''" + + bazel test --test_output=streamed //pkg:test &>"$TEST_log" || fail "Test should succeed" + expect_log "in pkg/Test.java: ''" + expect_log "in pkg/Library.java: ''" + + bazel run @other_repo//pkg:binary &>"$TEST_log" || fail "Run should succeed" + expect_log "in external/other_repo/pkg/Binary.java: 'other_repo'" + expect_log "in pkg/Library.java: ''" + + bazel test --test_output=streamed \ + @other_repo//pkg:test &>"$TEST_log" || fail "Test should succeed" + expect_log "in external/other_repo/pkg/Test.java: 'other_repo'" + expect_log "in pkg/Library.java: ''" +} + run_suite "Java integration tests" diff --git a/tools/BUILD b/tools/BUILD index 0f69e23505fc27..6193e55b4587ad 100644 --- a/tools/BUILD +++ b/tools/BUILD @@ -84,6 +84,7 @@ filegroup( "//tools/build_rules:bzl_srcs", "//tools/config:common_settings.bzl", "//tools/cpp:bzl_srcs", + "//tools/java:bzl_srcs", "//tools/jdk:bzl_srcs", "//tools/osx:bzl_srcs", "//tools/python:bzl_srcs", diff --git a/tools/java/BUILD b/tools/java/BUILD index 62d9c3eb981a41..870ae3148b43a1 100644 --- a/tools/java/BUILD +++ b/tools/java/BUILD @@ -10,6 +10,12 @@ filegroup( visibility = ["//tools:__pkg__"], ) +filegroup( + name = "bzl_srcs", + srcs = ["//tools/java/runfiles:bzl_srcs"], + visibility = ["//tools:__pkg__"], +) + genrule( name = "copy_java_stub_template", srcs = [ diff --git a/tools/java/BUILD.tools b/tools/java/BUILD.tools index 8645079c1068ed..6f511f90733ae7 100644 --- a/tools/java/BUILD.tools +++ b/tools/java/BUILD.tools @@ -1 +1,7 @@ +filegroup( + name = "bzl_srcs", + srcs = ["//tools/java/runfiles:bzl_srcs"], + visibility = ["//tools:__pkg__"], +) + exports_files(["java_stub_template.txt"]) diff --git a/tools/java/runfiles/BUILD b/tools/java/runfiles/BUILD index fdd782d87db9dd..44a615a1249cf1 100644 --- a/tools/java/runfiles/BUILD +++ b/tools/java/runfiles/BUILD @@ -14,10 +14,18 @@ filegroup( visibility = ["//tools/java:__pkg__"], ) +filegroup( + name = "bzl_srcs", + srcs = glob(["*.bzl"]), + visibility = ["//tools:__pkg__"], +) + filegroup( name = "embedded_tools", srcs = [ "BUILD.tools", + "RunfilesConstants.java.tpl", + "java_current_repository.bzl", ":java-srcs", ], visibility = ["//tools/java:__pkg__"], diff --git a/tools/java/runfiles/BUILD.tools b/tools/java/runfiles/BUILD.tools index a2ac4f58cd0677..e41563e3a6e3d9 100644 --- a/tools/java/runfiles/BUILD.tools +++ b/tools/java/runfiles/BUILD.tools @@ -6,3 +6,11 @@ java_library( ], visibility = ["//visibility:public"], ) + +filegroup( + name = "bzl_srcs", + srcs = glob(["*.bzl"]), + visibility = ["//tools:__pkg__"], +) + +exports_files(["RunfilesConstants.java.tpl"]) diff --git a/tools/java/runfiles/RunfilesConstants.java.tpl b/tools/java/runfiles/RunfilesConstants.java.tpl new file mode 100644 index 00000000000000..46bc0e1ba028e1 --- /dev/null +++ b/tools/java/runfiles/RunfilesConstants.java.tpl @@ -0,0 +1,25 @@ +// Copyright 2017 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. + +// Automatically generated by the java_current_repository target: +// __LABEL__ + +package com.google.devtools.build.runfiles; + +public final class RunfilesConstants { + + public static final String CURRENT_REPOSITORY = "__CURRENT_REPOSITORY__"; + + private RunfilesConstants() {} +} diff --git a/tools/java/runfiles/java_current_repository.bzl b/tools/java/runfiles/java_current_repository.bzl new file mode 100644 index 00000000000000..5f0249af604f91 --- /dev/null +++ b/tools/java/runfiles/java_current_repository.bzl @@ -0,0 +1,65 @@ +# Copyright 2022 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. + +def _java_current_repository_impl(ctx): + java_file = ctx.actions.declare_file("_java_current_repository/RunfilesConstants.java") + ctx.actions.expand_template( + template = ctx.file._template, + output = java_file, + substitutions = { + "__LABEL__": str(ctx.label), + "__CURRENT_REPOSITORY__": ctx.label.workspace_name, + }, + ) + + jar_file = ctx.actions.declare_file("_java_current_repository/runfiles_constants.jar") + java_info = java_common.compile( + ctx, + java_toolchain = ctx.toolchains["@bazel_tools//tools/jdk:toolchain_type"].java, + # The JLS guarantees that constants are inlined. Since the generated code only contains + # constants, we can remove it from the runtime classpath. This also serves to prevent + # confusion as different repositories will compile against different versions of the + # generated class, with an essentially arbitrary one appearing on the runtime classpath. + neverlink = True, + output = jar_file, + source_files = [java_file], + ) + + return [ + DefaultInfo(files = depset([jar_file])), + java_info, + ] + +_java_current_repository = rule( + attrs = { + "_template": attr.label( + default = "RunfilesConstants.java.tpl", + allow_single_file = True, + ), + }, + implementation = _java_current_repository_impl, + provides = [JavaInfo], + fragments = ["java"], + toolchains = [config_common.toolchain_type("@bazel_tools//tools/jdk:toolchain_type", mandatory = True)], +) + +def java_current_repository(name, visibility = None, **kwargs): + if visibility: + fail("java_current_repository targets are automatically visible in all subpackages and should not be used from other repositories.", attr = "visibility") + + _java_current_repository( + name = name, + visibility = [":__subpackages__"], + **kwargs + )