Skip to content

Commit 455454a

Browse files
fmeumcopybara-github
authored andcommitted
Expose current repository name to Java with @AutoBazelRepository
Java targets depending on `@bazel_tools//tools/java/runfiles` can add the new `@AutoBazelRepository` to a class to have an annotation processor generate a companion class with a `BAZEL_REPOSITORY` constant containing the repository name of the target that compiled the class. This requires a small addition to JavaBuilder to parse the repository name out of the target label and pass it to javac as a processor option. Work towards bazelbuild#16124 Closes bazelbuild#16534. PiperOrigin-RevId: 487573496 Change-Id: Id9b6526ce32268089c91c6d17363d1e7682f64a4
1 parent 76100bb commit 455454a

File tree

7 files changed

+410
-18
lines changed

7 files changed

+410
-18
lines changed

src/main/java/com/google/devtools/build/lib/rules/java/JavaCommon.java

+13-4
Original file line numberDiff line numberDiff line change
@@ -371,9 +371,18 @@ public final void initializeJavacOpts() {
371371

372372
/** Computes javacopts for the current rule. */
373373
private ImmutableList<String> computeJavacOpts(Collection<String> extraRuleJavacOpts) {
374-
return ImmutableList.<String>builder()
375-
.addAll(javaToolchain.getJavacOptions(ruleContext))
376-
.addAll(extraRuleJavacOpts)
374+
ImmutableList.Builder<String> javacOpts =
375+
ImmutableList.<String>builder()
376+
.addAll(javaToolchain.getJavacOptions(ruleContext))
377+
.addAll(extraRuleJavacOpts);
378+
if (activePlugins
379+
.plugins()
380+
.processorClasses()
381+
.toSet()
382+
.contains("com.google.devtools.build.runfiles.AutoBazelRepositoryProcessor")) {
383+
javacOpts.add("-Abazel.repository=" + ruleContext.getRepository().getName());
384+
}
385+
return javacOpts
377386
.addAll(computePerPackageJavacOpts(ruleContext, javaToolchain))
378387
.addAll(addModuleJavacopts(ruleContext))
379388
.addAll(ruleContext.getExpander().withDataLocations().tokenized("javacopts"))
@@ -538,8 +547,8 @@ public JavaTargetAttributes.Builder initCommon() {
538547
public JavaTargetAttributes.Builder initCommon(
539548
Collection<Artifact> extraSrcs, Iterable<String> extraJavacOpts) {
540549
Preconditions.checkState(javacOpts == null);
541-
javacOpts = computeJavacOpts(ImmutableList.copyOf(extraJavacOpts));
542550
activePlugins = collectPlugins();
551+
javacOpts = computeJavacOpts(ImmutableList.copyOf(extraJavacOpts));
543552

544553
JavaTargetAttributes.Builder javaTargetAttributes = new JavaTargetAttributes.Builder(semantics);
545554
javaCompilationHelper =

src/main/java/com/google/devtools/build/lib/rules/java/JavaInfoBuildHelper.java

+23-13
Original file line numberDiff line numberDiff line change
@@ -284,6 +284,28 @@ public JavaInfo createJavaCompileAction(
284284

285285
JavaToolchainProvider toolchainProvider = javaToolchain;
286286

287+
JavaPluginInfo pluginInfo = mergeExportedJavaPluginInfo(plugins, deps);
288+
ImmutableList.Builder<String> allJavacOptsBuilder =
289+
ImmutableList.<String>builder()
290+
.addAll(toolchainProvider.getJavacOptions(starlarkRuleContext.getRuleContext()))
291+
.addAll(
292+
javaSemantics.getCompatibleJavacOptions(
293+
starlarkRuleContext.getRuleContext(), toolchainProvider));
294+
if (pluginInfo
295+
.plugins()
296+
.processorClasses()
297+
.toSet()
298+
.contains("com.google.devtools.build.runfiles.AutoBazelRepositoryProcessor")) {
299+
allJavacOptsBuilder.add(
300+
"-Abazel.repository=" + starlarkRuleContext.getRuleContext().getRepository().getName());
301+
}
302+
allJavacOptsBuilder
303+
.addAll(
304+
JavaCommon.computePerPackageJavacOpts(
305+
starlarkRuleContext.getRuleContext(), toolchainProvider))
306+
.addAll(JavaModuleFlagsProvider.toFlags(addExports, addOpens))
307+
.addAll(tokenize(javacOpts));
308+
287309
JavaLibraryHelper helper =
288310
new JavaLibraryHelper(starlarkRuleContext.getRuleContext())
289311
.setOutput(outputJar)
@@ -295,18 +317,7 @@ public JavaInfo createJavaCompileAction(
295317
.setSourcePathEntries(sourcepathEntries)
296318
.addAdditionalOutputs(annotationProcessorAdditionalOutputs)
297319
.enableJspecify(enableJSpecify)
298-
.setJavacOpts(
299-
ImmutableList.<String>builder()
300-
.addAll(toolchainProvider.getJavacOptions(starlarkRuleContext.getRuleContext()))
301-
.addAll(
302-
javaSemantics.getCompatibleJavacOptions(
303-
starlarkRuleContext.getRuleContext(), toolchainProvider))
304-
.addAll(
305-
JavaCommon.computePerPackageJavacOpts(
306-
starlarkRuleContext.getRuleContext(), toolchainProvider))
307-
.addAll(JavaModuleFlagsProvider.toFlags(addExports, addOpens))
308-
.addAll(tokenize(javacOpts))
309-
.build());
320+
.setJavacOpts(allJavacOptsBuilder.build());
310321

311322
if (injectingRuleKind != Starlark.NONE) {
312323
helper.setInjectingRuleKind((String) injectingRuleKind);
@@ -316,7 +327,6 @@ public JavaInfo createJavaCompileAction(
316327
streamProviders(deps, JavaCompilationArgsProvider.class).forEach(helper::addDep);
317328
streamProviders(exports, JavaCompilationArgsProvider.class).forEach(helper::addExport);
318329
helper.setCompilationStrictDepsMode(getStrictDepsMode(Ascii.toUpperCase(strictDepsMode)));
319-
JavaPluginInfo pluginInfo = mergeExportedJavaPluginInfo(plugins, deps);
320330
// Optimization: skip this if there are no annotation processors, to avoid unnecessarily
321331
// disabling the direct classpath optimization if `enable_annotation_processor = False`
322332
// but there aren't any annotation processors.

src/test/shell/bazel/bazel_java_test.sh

+186
Original file line numberDiff line numberDiff line change
@@ -1763,5 +1763,191 @@ EOF
17631763
bazel build //java/main:C2 &>"${TEST_log}" || fail "Expected to build"
17641764
}
17651765

1766+
function test_auto_bazel_repository() {
1767+
cat >> WORKSPACE <<'EOF'
1768+
local_repository(
1769+
name = "other_repo",
1770+
path = "other_repo",
1771+
)
1772+
EOF
1773+
1774+
mkdir -p pkg
1775+
cat > pkg/BUILD.bazel <<'EOF'
1776+
java_library(
1777+
name = "library",
1778+
srcs = ["Library.java"],
1779+
deps = ["@bazel_tools//tools/java/runfiles"],
1780+
visibility = ["//visibility:public"],
1781+
)
1782+
1783+
java_binary(
1784+
name = "binary",
1785+
srcs = ["Binary.java"],
1786+
main_class = "com.example.Binary",
1787+
deps = [
1788+
":library",
1789+
"@bazel_tools//tools/java/runfiles",
1790+
],
1791+
)
1792+
1793+
java_test(
1794+
name = "test",
1795+
srcs = ["Test.java"],
1796+
main_class = "com.example.Test",
1797+
use_testrunner = False,
1798+
deps = [
1799+
":library",
1800+
"@bazel_tools//tools/java/runfiles",
1801+
],
1802+
)
1803+
EOF
1804+
1805+
cat > pkg/Library.java <<'EOF'
1806+
package com.example;
1807+
1808+
import com.google.devtools.build.runfiles.AutoBazelRepository;
1809+
1810+
@AutoBazelRepository
1811+
public class Library {
1812+
public static void printRepositoryName() {
1813+
System.out.printf("in pkg/Library.java: '%s'%n", AutoBazelRepository_Library.NAME);
1814+
}
1815+
}
1816+
EOF
1817+
1818+
cat > pkg/Binary.java <<'EOF'
1819+
package com.example;
1820+
1821+
import com.google.devtools.build.runfiles.AutoBazelRepository;
1822+
1823+
public class Binary {
1824+
@AutoBazelRepository
1825+
private static class Class1 {
1826+
}
1827+
1828+
public static void main(String[] args) {
1829+
System.out.printf("in pkg/Binary.java: '%s'%n", AutoBazelRepository_Binary_Class1.NAME);
1830+
Library.printRepositoryName();
1831+
}
1832+
}
1833+
EOF
1834+
1835+
cat > pkg/Test.java <<'EOF'
1836+
package com.example;
1837+
1838+
import com.google.devtools.build.runfiles.AutoBazelRepository;
1839+
1840+
public class Test {
1841+
private static class Class1 {
1842+
@AutoBazelRepository
1843+
private static class Class2 {
1844+
}
1845+
}
1846+
1847+
public static void main(String[] args) {
1848+
System.out.printf("in pkg/Test.java: '%s'%n", AutoBazelRepository_Test_Class1_Class2.NAME);
1849+
Library.printRepositoryName();
1850+
}
1851+
}
1852+
EOF
1853+
1854+
mkdir -p other_repo
1855+
touch other_repo/WORKSPACE
1856+
1857+
mkdir -p other_repo/pkg
1858+
cat > other_repo/pkg/BUILD.bazel <<'EOF'
1859+
java_library(
1860+
name = "library2",
1861+
srcs = ["Library2.java"],
1862+
deps = ["@bazel_tools//tools/java/runfiles"],
1863+
)
1864+
1865+
java_binary(
1866+
name = "binary",
1867+
srcs = ["Binary.java"],
1868+
main_class = "com.example.Binary",
1869+
deps = [
1870+
":library2",
1871+
"@//pkg:library",
1872+
"@bazel_tools//tools/java/runfiles",
1873+
],
1874+
)
1875+
java_test(
1876+
name = "test",
1877+
srcs = ["Test.java"],
1878+
main_class = "com.example.Test",
1879+
use_testrunner = False,
1880+
deps = [
1881+
":library2",
1882+
"@//pkg:library",
1883+
"@bazel_tools//tools/java/runfiles",
1884+
],
1885+
)
1886+
EOF
1887+
1888+
cat > other_repo/pkg/Library2.java <<'EOF'
1889+
package com.example;
1890+
1891+
import com.google.devtools.build.runfiles.AutoBazelRepository;
1892+
1893+
@AutoBazelRepository
1894+
public class Library2 {
1895+
public static void printRepositoryName() {
1896+
System.out.printf("in external/other_repo/pkg/Library2.java: '%s'%n", AutoBazelRepository_Library2.NAME);
1897+
}
1898+
}
1899+
EOF
1900+
1901+
cat > other_repo/pkg/Binary.java <<'EOF'
1902+
package com.example;
1903+
1904+
import com.google.devtools.build.runfiles.AutoBazelRepository;
1905+
import static com.example.AutoBazelRepository_Binary.NAME;
1906+
1907+
@AutoBazelRepository
1908+
public class Binary {
1909+
public static void main(String[] args) {
1910+
System.out.printf("in external/other_repo/pkg/Binary.java: '%s'%n", NAME);
1911+
Library2.printRepositoryName();
1912+
Library.printRepositoryName();
1913+
}
1914+
}
1915+
EOF
1916+
1917+
cat > other_repo/pkg/Test.java <<'EOF'
1918+
package com.example;
1919+
1920+
import com.google.devtools.build.runfiles.AutoBazelRepository;
1921+
1922+
@AutoBazelRepository
1923+
public class Test {
1924+
public static void main(String[] args) {
1925+
System.out.printf("in external/other_repo/pkg/Test.java: '%s'%n", AutoBazelRepository_Test.NAME);
1926+
Library2.printRepositoryName();
1927+
Library.printRepositoryName();
1928+
}
1929+
}
1930+
EOF
1931+
1932+
bazel run //pkg:binary &>"$TEST_log" || fail "Run should succeed"
1933+
expect_log "in pkg/Binary.java: ''"
1934+
expect_log "in pkg/Library.java: ''"
1935+
1936+
bazel test --test_output=streamed //pkg:test &>"$TEST_log" || fail "Test should succeed"
1937+
expect_log "in pkg/Test.java: ''"
1938+
expect_log "in pkg/Library.java: ''"
1939+
1940+
bazel run @other_repo//pkg:binary &>"$TEST_log" || fail "Run should succeed"
1941+
expect_log "in external/other_repo/pkg/Binary.java: 'other_repo'"
1942+
expect_log "in external/other_repo/pkg/Library2.java: 'other_repo'"
1943+
expect_log "in pkg/Library.java: ''"
1944+
1945+
bazel test --test_output=streamed \
1946+
@other_repo//pkg:test &>"$TEST_log" || fail "Test should succeed"
1947+
expect_log "in external/other_repo/pkg/Test.java: 'other_repo'"
1948+
expect_log "in external/other_repo/pkg/Library2.java: 'other_repo'"
1949+
expect_log "in pkg/Library.java: ''"
1950+
}
1951+
17661952

17671953
run_suite "Java integration tests"
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 {}

0 commit comments

Comments
 (0)