Skip to content

Commit 7e91ad6

Browse files
Stephen Twiggiirina
authored andcommitted
Loosen java_library.exports and java_import.*
java_library.exports and java_import.runtime_deps|exports|deps will now accept any label from a rule that has a JavaProvider declared provider. Note that java_library.deps|runtime_deps already had this feature and this simply extends that privilege. This relies on the fact that both those targets (via JavaCommon) are simply searching for jars via JavaProvider anyway. Added test for passing a custom Skylark rule (that provides a JavaProvider) can successfully be added to the deps, runtime_deps, and exports of java_library, java_import, and java_binary (where appropriate). Added integration tests for java_library.exports|runtime_deps (the basic sandwich already tests deps) and java_import.exports|runtime_deps. Note that custom Skylark rules are still unable to provide or propagate a JavaNativeLibraryProvider, which results from a cc dependency. Also, the deps argument for java_import is somewhat odd. Change-Id: I7b2c19c6b99516ce524e8c82193d0c73e2d66530 PiperOrigin-RevId: 156740729
1 parent 512d562 commit 7e91ad6

File tree

5 files changed

+276
-26
lines changed

5 files changed

+276
-26
lines changed

src/main/java/com/google/devtools/build/lib/bazel/rules/java/BazelJavaImportRule.java

Lines changed: 18 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -44,26 +44,32 @@ public RuleClass build(Builder builder, RuleDefinitionEnvironment env) {
4444
The list of other libraries to be linked in to the target.
4545
See <a href="${link java_library.deps}">java_library.deps</a>.
4646
<!-- #END_BLAZE_RULE.ATTRIBUTE --> */
47-
.add(attr("deps", LABEL_LIST)
48-
.allowedRuleClasses(ALLOWED_DEPS)
49-
.allowedFileTypes() // none allowed
50-
.validityPredicate(ANY_EDGE))
47+
.add(
48+
attr("deps", LABEL_LIST)
49+
.allowedRuleClasses(ALLOWED_DEPS)
50+
.allowedFileTypes() // none allowed
51+
.validityPredicate(ANY_EDGE)
52+
.mandatoryProvidersList(BazelJavaRuleClasses.MANDATORY_JAVA_PROVIDER_ONLY))
5153
/* <!-- #BLAZE_RULE(java_import).ATTRIBUTE(exports) -->
5254
Targets to make available to users of this rule.
5355
See <a href="${link java_library.exports}">java_library.exports</a>.
5456
<!-- #END_BLAZE_RULE.ATTRIBUTE --> */
55-
.add(attr("exports", LABEL_LIST)
56-
.allowedRuleClasses(ALLOWED_DEPS)
57-
.allowedFileTypes() // none allowed
58-
.validityPredicate(ANY_EDGE))
57+
.add(
58+
attr("exports", LABEL_LIST)
59+
.allowedRuleClasses(ALLOWED_DEPS)
60+
.allowedFileTypes() // none allowed
61+
.validityPredicate(ANY_EDGE)
62+
.mandatoryProvidersList(BazelJavaRuleClasses.MANDATORY_JAVA_PROVIDER_ONLY))
5963
/* <!-- #BLAZE_RULE(java_import).ATTRIBUTE(runtime_deps) -->
6064
Libraries to make available to the final binary or test at runtime only.
6165
See <a href="${link java_library.runtime_deps}">java_library.runtime_deps</a>.
6266
<!-- #END_BLAZE_RULE.ATTRIBUTE --> */
63-
.add(attr("runtime_deps", LABEL_LIST)
64-
.allowedFileTypes(JavaSemantics.JAR)
65-
.allowedRuleClasses(ALLOWED_DEPS)
66-
.skipAnalysisTimeFileTypeCheck())
67+
.add(
68+
attr("runtime_deps", LABEL_LIST)
69+
.allowedFileTypes(JavaSemantics.JAR)
70+
.allowedRuleClasses(ALLOWED_DEPS)
71+
.mandatoryProvidersList(BazelJavaRuleClasses.MANDATORY_JAVA_PROVIDER_ONLY)
72+
.skipAnalysisTimeFileTypeCheck())
6773
.advertiseProvider(JavaSourceInfoProvider.class)
6874
.build();
6975

src/main/java/com/google/devtools/build/lib/bazel/rules/java/BazelJavaLibraryRule.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -115,8 +115,8 @@ depended on these rules. This is not true for regular (non-exported) <code>deps<
115115
.add(
116116
attr("exports", LABEL_LIST)
117117
.allowedRuleClasses(BazelJavaRuleClasses.ALLOWED_RULES_IN_DEPS)
118-
.allowedFileTypes(/*May not have files in exports!*/ ))
119-
118+
.allowedFileTypes(/*May not have files in exports!*/ )
119+
.mandatoryProvidersList(BazelJavaRuleClasses.MANDATORY_JAVA_PROVIDER_ONLY))
120120
/* <!-- #BLAZE_RULE(java_library).ATTRIBUTE(neverlink) -->
121121
Whether this library should only be used for compilation and not at runtime.
122122
Useful if the library will be provided by the runtime environment during execution. Examples

src/main/java/com/google/devtools/build/lib/bazel/rules/java/BazelJavaRuleClasses.java

Lines changed: 22 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,26 @@ public class BazelJavaRuleClasses {
7474
JavaSemantics.JAVA_LIBRARY_CLASS_JAR,
7575
JavaSemantics.JAVA_LIBRARY_SOURCE_JAR);
7676

77+
/**
78+
* Meant to be an element of {@code mandatoryProvidersLists} in order to accept rules providing
79+
* a {@link JavaProvider} through an attribute. Other providers can be included in
80+
* {@code mandatoryProvidersLists} as well.
81+
*/
82+
public static final ImmutableList<SkylarkProviderIdentifier> CONTAINS_JAVA_PROVIDER =
83+
ImmutableList.of(SkylarkProviderIdentifier.forKey(JavaProvider.JAVA_PROVIDER.getKey()));
84+
85+
public static final ImmutableList<SkylarkProviderIdentifier> CONTAINS_CC_LINK_PARAMS =
86+
ImmutableList.of(
87+
SkylarkProviderIdentifier.forKey(CcLinkParamsProvider.CC_LINK_PARAMS.getKey()));
88+
89+
/**
90+
* Meant to be the value of {@code mandatoryProvidersLists} in order for the rule to provide only
91+
* a {@link JavaProvider} through an attribute.
92+
*/
93+
public static final ImmutableList<ImmutableList<SkylarkProviderIdentifier>>
94+
MANDATORY_JAVA_PROVIDER_ONLY = ImmutableList.of(CONTAINS_JAVA_PROVIDER);
95+
96+
7797
/**
7898
* Common attributes for rules that depend on ijar.
7999
*/
@@ -158,13 +178,7 @@ public RuleClass build(Builder builder, RuleDefinitionEnvironment env) {
158178
.allowedFileTypes(JavaSemantics.JAR)
159179
.allowedRuleClasses(ALLOWED_RULES_IN_DEPS)
160180
.mandatoryProvidersList(
161-
ImmutableList.of(
162-
ImmutableList.of(
163-
SkylarkProviderIdentifier.forKey(
164-
CcLinkParamsProvider.CC_LINK_PARAMS.getKey())),
165-
ImmutableList.of(
166-
SkylarkProviderIdentifier.forKey(
167-
JavaProvider.JAVA_PROVIDER.getKey()))))
181+
ImmutableList.of(CONTAINS_CC_LINK_PARAMS, CONTAINS_JAVA_PROVIDER))
168182
.skipAnalysisTimeFileTypeCheck())
169183
/* <!-- #BLAZE_RULE($java_rule).ATTRIBUTE(runtime_deps) -->
170184
Libraries to make available to the final binary or test at runtime only.
@@ -177,11 +191,7 @@ public RuleClass build(Builder builder, RuleDefinitionEnvironment env) {
177191
attr("runtime_deps", LABEL_LIST)
178192
.allowedFileTypes(JavaSemantics.JAR)
179193
.allowedRuleClasses(ALLOWED_RULES_IN_DEPS)
180-
.mandatoryProvidersList(
181-
ImmutableList.of(
182-
ImmutableList.of(
183-
SkylarkProviderIdentifier.forKey(
184-
JavaProvider.JAVA_PROVIDER.getKey()))))
194+
.mandatoryProvidersList(MANDATORY_JAVA_PROVIDER_ONLY)
185195
.skipAnalysisTimeFileTypeCheck())
186196

187197
/* <!-- #BLAZE_RULE($java_rule).ATTRIBUTE(srcs) -->

src/test/java/com/google/devtools/build/lib/rules/java/JavaSkylarkApiTest.java

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -324,6 +324,102 @@ public void javaProviderPropagation() throws Exception {
324324
jlTopJavaProvider.getProvider(JavaCompilationArgsProvider.class).getJavaCompilationArgs());
325325
}
326326

327+
@Test
328+
public void skylarkJavaToJavaLibraryAttributes() throws Exception {
329+
scratch.file(
330+
"foo/extension.bzl",
331+
"def _impl(ctx):",
332+
" dep_params = ctx.attr.dep[java_common.provider]",
333+
" return struct(providers = [dep_params])",
334+
"my_rule = rule(_impl, attrs = { 'dep' : attr.label() })");
335+
scratch.file(
336+
"foo/BUILD",
337+
"load(':extension.bzl', 'my_rule')",
338+
"java_library(name = 'jl_bottom_for_deps', srcs = ['java/A.java'])",
339+
"java_library(name = 'jl_bottom_for_exports', srcs = ['java/A2.java'])",
340+
"java_library(name = 'jl_bottom_for_runtime_deps', srcs = ['java/A2.java'])",
341+
"my_rule(name = 'mya', dep = ':jl_bottom_for_deps')",
342+
"my_rule(name = 'myb', dep = ':jl_bottom_for_exports')",
343+
"my_rule(name = 'myc', dep = ':jl_bottom_for_runtime_deps')",
344+
"java_library(name = 'lib_exports', srcs = ['java/B.java'], deps = [':mya'],",
345+
" exports = [':myb'], runtime_deps = [':myc'])",
346+
"java_library(name = 'lib_interm', srcs = ['java/C.java'], deps = [':lib_exports'])",
347+
"java_library(name = 'lib_top', srcs = ['java/D.java'], deps = [':lib_interm'])");
348+
assertNoEvents();
349+
350+
// Test that all bottom jars are on the runtime classpath of lib_exports.
351+
ConfiguredTarget jlExports = getConfiguredTarget("//foo:lib_exports");
352+
JavaCompilationArgsProvider jlExportsProvider =
353+
JavaProvider.getProvider(JavaCompilationArgsProvider.class, jlExports);
354+
assertThat(prettyJarNames(jlExportsProvider.getRecursiveJavaCompilationArgs().getRuntimeJars()))
355+
.containsAllOf(
356+
"foo/libjl_bottom_for_deps.jar",
357+
"foo/libjl_bottom_for_runtime_deps.jar",
358+
"foo/libjl_bottom_for_exports.jar");
359+
360+
// Test that libjl_bottom_for_exports.jar is in the recursive java compilation args of lib_top.
361+
ConfiguredTarget jlTop = getConfiguredTarget("//foo:lib_interm");
362+
JavaCompilationArgsProvider jlTopProvider =
363+
JavaProvider.getProvider(JavaCompilationArgsProvider.class, jlTop);
364+
assertThat(prettyJarNames(jlTopProvider.getRecursiveJavaCompilationArgs().getRuntimeJars()))
365+
.contains("foo/libjl_bottom_for_exports.jar");
366+
}
367+
368+
@Test
369+
public void skylarkJavaToJavaBinaryAttributes() throws Exception {
370+
scratch.file(
371+
"foo/extension.bzl",
372+
"def _impl(ctx):",
373+
" dep_params = ctx.attr.dep[java_common.provider]",
374+
" return struct(providers = [dep_params])",
375+
"my_rule = rule(_impl, attrs = { 'dep' : attr.label() })");
376+
scratch.file(
377+
"foo/BUILD",
378+
"load(':extension.bzl', 'my_rule')",
379+
"java_library(name = 'jl_bottom_for_deps', srcs = ['java/A.java'])",
380+
"java_library(name = 'jl_bottom_for_runtime_deps', srcs = ['java/A2.java'])",
381+
"my_rule(name = 'mya', dep = ':jl_bottom_for_deps')",
382+
"my_rule(name = 'myb', dep = ':jl_bottom_for_runtime_deps')",
383+
"java_binary(name = 'binary', srcs = ['java/B.java'], main_class = 'foo.A',",
384+
" deps = [':mya'], runtime_deps = [':myb'])");
385+
assertNoEvents();
386+
387+
// Test that all bottom jars are on the runtime classpath.
388+
ConfiguredTarget binary = getConfiguredTarget("//foo:binary");
389+
assertThat(prettyJarNames(
390+
binary.getProvider(JavaRuntimeClasspathProvider.class).getRuntimeClasspath()))
391+
.containsAllOf(
392+
"foo/libjl_bottom_for_deps.jar", "foo/libjl_bottom_for_runtime_deps.jar");
393+
}
394+
395+
@Test
396+
public void skylarkJavaToJavaImportAttributes() throws Exception {
397+
scratch.file(
398+
"foo/extension.bzl",
399+
"def _impl(ctx):",
400+
" dep_params = ctx.attr.dep[java_common.provider]",
401+
" return struct(providers = [dep_params])",
402+
"my_rule = rule(_impl, attrs = { 'dep' : attr.label() })");
403+
scratch.file(
404+
"foo/BUILD",
405+
"load(':extension.bzl', 'my_rule')",
406+
"java_library(name = 'jl_bottom_for_deps', srcs = ['java/A.java'])",
407+
"java_library(name = 'jl_bottom_for_runtime_deps', srcs = ['java/A2.java'])",
408+
"my_rule(name = 'mya', dep = ':jl_bottom_for_deps')",
409+
"my_rule(name = 'myb', dep = ':jl_bottom_for_runtime_deps')",
410+
"java_import(name = 'import', jars = ['B.jar'], deps = [':mya'], runtime_deps = [':myb'])");
411+
assertNoEvents();
412+
413+
// Test that all bottom jars are on the runtime classpath.
414+
ConfiguredTarget importTarget = getConfiguredTarget("//foo:import");
415+
JavaCompilationArgsProvider compilationProvider =
416+
JavaProvider.getProvider(JavaCompilationArgsProvider.class, importTarget);
417+
assertThat(prettyJarNames(
418+
compilationProvider.getRecursiveJavaCompilationArgs().getRuntimeJars()))
419+
.containsAllOf(
420+
"foo/libjl_bottom_for_deps.jar", "foo/libjl_bottom_for_runtime_deps.jar");
421+
}
422+
327423
@Test
328424
public void strictDepsEnabled() throws Exception {
329425
scratch.file(

src/test/shell/bazel/bazel_java_test.sh

Lines changed: 138 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,111 @@ public class HelloLibrary {
5959
EOF
6060
}
6161

62+
function write_files_for_java_provider_in_attr() {
63+
mkdir -p java/com/google/sandwich
64+
cd java/com/google/sandwich
65+
66+
touch BUILD A.java B.java Main.java java_custom_library.bzl
67+
68+
rule_type="$1" # java_library / java_import
69+
attribute_name="$2" # exports / runtime_deps
70+
srcs_attribute_row="srcs = ['A.java']"
71+
if [ "$rule_type" = "java_import" ]; then
72+
srcs_attribute_row="jars = []"
73+
fi
74+
75+
cat > BUILD <<EOF
76+
load(':java_custom_library.bzl', 'java_custom_library')
77+
78+
java_binary(
79+
name = "Main",
80+
EOF
81+
82+
if [ "$attribute_name" = "runtime_deps" ]; then
83+
cat >> BUILD <<EOF
84+
main_class = "com.google.sandwich.Main",
85+
runtime_deps = [":top"]
86+
)
87+
88+
EOF
89+
else
90+
cat >> BUILD <<EOF
91+
srcs = ["Main.java"],
92+
deps = [":top"]
93+
)
94+
95+
EOF
96+
fi
97+
98+
echo "$rule_type(" >> BUILD
99+
100+
cat >> BUILD <<EOF
101+
name = "top",
102+
EOF
103+
104+
echo " $srcs_attribute_row," >> BUILD
105+
echo " $attribute_name = [':middle']" >> BUILD
106+
107+
cat >> BUILD <<EOF
108+
)
109+
110+
java_custom_library(
111+
name = "middle",
112+
EOF
113+
114+
if [ "$attribute_name" = "runtime_deps" ]; then
115+
cat >> BUILD <<EOF
116+
srcs = ["B.java", "Main.java"],
117+
)
118+
EOF
119+
else
120+
cat >> BUILD <<EOF
121+
srcs = ["B.java"],
122+
)
123+
EOF
124+
fi
125+
126+
cat > B.java <<EOF
127+
package com.google.sandwich;
128+
class B {
129+
public void printB() {
130+
System.out.println("Message from B");
131+
}
132+
}
133+
EOF
134+
135+
if [ "$rule_type" = "java_library" ]; then
136+
cat > A.java <<EOF
137+
package com.google.sandwich;
138+
class A {
139+
public void printA() {
140+
System.out.println("Message from A");
141+
}
142+
}
143+
EOF
144+
fi
145+
146+
cat > Main.java <<EOF
147+
package com.google.sandwich;
148+
class Main {
149+
public static void main(String[] args) {
150+
EOF
151+
152+
if [[ "$rule_type" = "java_library" && "$attribute_name" = "exports" ]]; then
153+
cat >> Main.java <<EOF
154+
A myObjectA = new A();
155+
myObjectA.printA();
156+
EOF
157+
fi
158+
159+
cat >> Main.java <<EOF
160+
B myObjectB = new B();
161+
myObjectB.printB();
162+
}
163+
}
164+
EOF
165+
}
166+
62167
function write_java_custom_rule() {
63168
cat > java_custom_library.bzl << EOF
64169
def _impl(ctx):
@@ -494,6 +599,39 @@ EOF
494599
expect_log "Message from C"
495600
}
496601

602+
function test_java_library_exports_java_sandwich() {
603+
write_files_for_java_provider_in_attr "java_library" "exports"
604+
write_java_custom_rule
605+
606+
bazel run :Main > $TEST_log || fail "Java sandwich build failed"
607+
expect_log "Message from A"
608+
expect_log "Message from B"
609+
}
610+
611+
function test_java_library_runtime_deps_java_sandwich() {
612+
write_files_for_java_provider_in_attr "java_library" "runtime_deps"
613+
write_java_custom_rule
614+
615+
bazel run :Main > $TEST_log || fail "Java sandwich build failed"
616+
expect_log "Message from B"
617+
}
618+
619+
function test_java_import_exports_java_sandwich() {
620+
write_files_for_java_provider_in_attr "java_import" "exports"
621+
write_java_custom_rule
622+
623+
bazel run :Main > $TEST_log || fail "Java sandwich build failed"
624+
expect_log "Message from B"
625+
}
626+
627+
function test_java_import_runtime_deps_java_sandwich() {
628+
write_files_for_java_provider_in_attr "java_import" "runtime_deps"
629+
write_java_custom_rule
630+
631+
bazel run :Main > $TEST_log || fail "Java sandwich build failed"
632+
expect_log "Message from B"
633+
}
634+
497635
function test_java_binary_deps_java_sandwich() {
498636
mkdir -p java/com/google/sandwich
499637
cd java/com/google/sandwich

0 commit comments

Comments
 (0)