Skip to content

Commit 6bb5306

Browse files
fmeumrules_java Copybara
authored and
rules_java Copybara
committed
Copy over runfiles library from Bazel
Copybara Import from #239 BEGIN_PUBLIC Copy over runfiles library from Bazel (#239) The runfiles library can be maintained independently of Bazel releases and `bazel_tools` can refer to it via an alias. Also set flags to build and test with a hermetic JDK 8 to ensure compatibility with that version. Closes #239 END_PUBLIC COPYBARA_INTEGRATE_REVIEW=#239 from fmeum:runfiles 6428328 PiperOrigin-RevId: 696993940 Change-Id: Id2ee9f4f2d15a1063c4db1e913b375ba40b8e439
1 parent 865f285 commit 6bb5306

File tree

13 files changed

+1526
-3
lines changed

13 files changed

+1526
-3
lines changed

Diff for: .gitignore

+2
Original file line numberDiff line numberDiff line change
@@ -17,3 +17,5 @@
1717
# Ignore jekyll build output.
1818
/production
1919
/.sass-cache
20+
# Ignore MODULE.bazel.lock as this is a library project.
21+
MODULE.bazel.lock

Diff for: MODULE.bazel

+6-3
Original file line numberDiff line numberDiff line change
@@ -89,11 +89,14 @@ REMOTE_JDK_REPOS = [(("remote_jdk" if version == "8" else "remotejdk") + version
8989

9090
[register_toolchains("@" + name + "_toolchain_config_repo//:all") for name in REMOTE_JDK_REPOS]
9191

92+
# Compatibility layer
93+
compat = use_extension("//java:extensions.bzl", "compatibility_proxy")
94+
use_repo(compat, "compatibility_proxy")
95+
9296
# Dev dependencies
9397
bazel_dep(name = "rules_pkg", version = "0.9.1", dev_dependency = True)
9498
bazel_dep(name = "stardoc", version = "0.7.1", dev_dependency = True)
9599
bazel_dep(name = "rules_shell", version = "0.2.0", dev_dependency = True)
96100

97-
# Compatibility layer
98-
compat = use_extension("//java:extensions.bzl", "compatibility_proxy")
99-
use_repo(compat, "compatibility_proxy")
101+
test_repositories = use_extension("//test:repositories.bzl", "test_repositories_ext", dev_dependency = True)
102+
use_repo(test_repositories, "guava", "truth")

Diff for: WORKSPACE

+4
Original file line numberDiff line numberDiff line change
@@ -50,3 +50,7 @@ rules_java_toolchains()
5050
load("@stardoc//:setup.bzl", "stardoc_repositories")
5151

5252
stardoc_repositories()
53+
54+
load("//test:repositories.bzl", "test_repositories")
55+
56+
test_repositories()

Diff for: java/runfiles/BUILD.bazel

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
alias(
2+
name = "runfiles",
3+
actual = "//java/runfiles/src/main/java/com/google/devtools/build/runfiles",
4+
visibility = ["//visibility:public"],
5+
)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
// Copyright 2022 The Bazel Authors. All rights reserved.
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
package com.google.devtools.build.runfiles;
16+
17+
import java.lang.annotation.ElementType;
18+
import java.lang.annotation.Retention;
19+
import java.lang.annotation.RetentionPolicy;
20+
import java.lang.annotation.Target;
21+
22+
/**
23+
* Annotating a class {@code Fooer} with this annotation generates a class {@code
24+
* AutoBazelRepository_Fooer} defining a {@link String} constant {@code NAME} containing the
25+
* canonical name of the repository containing the Bazel target that compiled the annotated class.
26+
*/
27+
@Retention(RetentionPolicy.SOURCE)
28+
@Target(ElementType.TYPE)
29+
public @interface AutoBazelRepository {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
// Copyright 2022 The Bazel Authors. All rights reserved.
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
package com.google.devtools.build.runfiles;
16+
17+
import java.io.IOException;
18+
import java.io.PrintWriter;
19+
import java.util.ArrayDeque;
20+
import java.util.Deque;
21+
import java.util.Set;
22+
import javax.annotation.processing.AbstractProcessor;
23+
import javax.annotation.processing.RoundEnvironment;
24+
import javax.annotation.processing.SupportedAnnotationTypes;
25+
import javax.annotation.processing.SupportedOptions;
26+
import javax.lang.model.SourceVersion;
27+
import javax.lang.model.element.Element;
28+
import javax.lang.model.element.TypeElement;
29+
import javax.tools.Diagnostic.Kind;
30+
31+
/** Processor for {@link AutoBazelRepository}. */
32+
@SupportedAnnotationTypes("com.google.devtools.build.runfiles.AutoBazelRepository")
33+
@SupportedOptions(AutoBazelRepositoryProcessor.BAZEL_REPOSITORY_OPTION)
34+
public final class AutoBazelRepositoryProcessor extends AbstractProcessor {
35+
36+
static final String BAZEL_REPOSITORY_OPTION = "bazel.repository";
37+
38+
@Override
39+
public SourceVersion getSupportedSourceVersion() {
40+
return SourceVersion.latestSupported();
41+
}
42+
43+
@Override
44+
public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
45+
annotations.stream()
46+
.flatMap(element -> roundEnv.getElementsAnnotatedWith(element).stream())
47+
.map(element -> (TypeElement) element)
48+
.forEach(this::emitClass);
49+
return false;
50+
}
51+
52+
private void emitClass(TypeElement annotatedClass) {
53+
// This option is always provided by the Java rule implementations.
54+
if (!processingEnv.getOptions().containsKey(BAZEL_REPOSITORY_OPTION)) {
55+
processingEnv
56+
.getMessager()
57+
.printMessage(
58+
Kind.ERROR,
59+
String.format(
60+
"The %1$s annotation processor option is not set. To use this annotation"
61+
+ " processor, provide the canonical repository name of the current target as"
62+
+ " the value of the -A%1$s flag.",
63+
BAZEL_REPOSITORY_OPTION),
64+
annotatedClass);
65+
return;
66+
}
67+
String repositoryName = processingEnv.getOptions().get(BAZEL_REPOSITORY_OPTION);
68+
if (repositoryName == null) {
69+
// javac translates '-Abazel.repository=' into a null value.
70+
// https://github.com/openjdk/jdk/blob/7a49c9baa1d4ad7df90e7ca626ec48ba76881822/src/jdk.compiler/share/classes/com/sun/tools/javac/processing/JavacProcessingEnvironment.java#L651
71+
repositoryName = "";
72+
}
73+
74+
// For a nested class Outer.Middle.Inner, generate a class with simple name
75+
// AutoBazelRepository_Outer_Middle_Inner.
76+
// Note: There can be collisions when local classes are involved, but since the definition of a
77+
// class depends only on the containing Bazel target, this does not result in ambiguity.
78+
Deque<String> classNameSegments = new ArrayDeque<>();
79+
Element element = annotatedClass;
80+
while (element instanceof TypeElement) {
81+
classNameSegments.addFirst(element.getSimpleName().toString());
82+
element = element.getEnclosingElement();
83+
}
84+
classNameSegments.addFirst("AutoBazelRepository");
85+
String generatedClassSimpleName = String.join("_", classNameSegments);
86+
87+
String generatedClassPackage =
88+
processingEnv.getElementUtils().getPackageOf(annotatedClass).getQualifiedName().toString();
89+
90+
String generatedClassName =
91+
generatedClassPackage.isEmpty()
92+
? generatedClassSimpleName
93+
: generatedClassPackage + "." + generatedClassSimpleName;
94+
95+
try (PrintWriter out =
96+
new PrintWriter(
97+
processingEnv.getFiler().createSourceFile(generatedClassName).openWriter())) {
98+
if (!generatedClassPackage.isEmpty()) {
99+
// This annotation may exist on a class which is at the root package
100+
out.printf("package %s;\n", generatedClassPackage);
101+
}
102+
out.printf("\n");
103+
out.printf("class %s {\n", generatedClassSimpleName);
104+
out.printf(" /**\n");
105+
out.printf(" * The canonical name of the repository containing the Bazel target that\n");
106+
out.printf(" * compiled {@link %s}.\n", annotatedClass.getQualifiedName().toString());
107+
out.printf(" */\n");
108+
out.printf(" static final String NAME = \"%s\";\n", repositoryName);
109+
out.printf("\n");
110+
out.printf(" private %s() {}\n", generatedClassSimpleName);
111+
out.printf("}\n");
112+
} catch (IOException e) {
113+
processingEnv
114+
.getMessager()
115+
.printMessage(
116+
Kind.ERROR,
117+
String.format("Failed to generate %s: %s", generatedClassName, e.getMessage()),
118+
annotatedClass);
119+
}
120+
}
121+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
load("@rules_java//java:defs.bzl", "java_library", "java_plugin")
2+
3+
java_library(
4+
name = "runfiles",
5+
srcs = [
6+
"Runfiles.java",
7+
"Util.java",
8+
],
9+
exported_plugins = [":auto_bazel_repository_processor"],
10+
visibility = ["//java/runfiles:__pkg__"],
11+
exports = [":auto_bazel_repository"],
12+
)
13+
14+
java_library(
15+
name = "auto_bazel_repository",
16+
srcs = ["AutoBazelRepository.java"],
17+
)
18+
19+
java_plugin(
20+
name = "auto_bazel_repository_processor",
21+
srcs = ["AutoBazelRepositoryProcessor.java"],
22+
processor_class = "com.google.devtools.build.runfiles.AutoBazelRepositoryProcessor",
23+
)

0 commit comments

Comments
 (0)