blob: acb9d719c2e607b7f792259ec72dd77c8cb6595d [file] [log] [blame]
// Copyright 2018 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.
package com.google.devtools.build.lib.rules.java;
import static com.google.common.truth.Truth.assertThat;
import static com.google.devtools.build.lib.actions.util.ActionsTestUtil.prettyArtifactNames;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Streams;
import com.google.devtools.build.lib.analysis.ConfiguredTarget;
import com.google.devtools.build.lib.analysis.util.BuildViewTestCase;
import com.google.devtools.build.lib.cmdline.Label;
import com.google.devtools.build.lib.packages.SkylarkProvider.SkylarkKey;
import com.google.devtools.build.lib.packages.StructImpl;
import com.google.devtools.build.lib.rules.java.JavaRuleOutputJarsProvider.OutputJar;
import com.google.devtools.build.lib.testutil.TestConstants;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameters;
/** Tests JavaInfo API for Skylark. */
@RunWith(Parameterized.class)
public class JavaInfoSkylarkApiTest extends BuildViewTestCase {
private static final String HOST_JAVA_RUNTIME_LABEL =
TestConstants.TOOLS_REPOSITORY + "//tools/jdk:current_host_java_runtime";
@Parameters(name = "Use legacy JavaInfo constructor: {0}")
public static Iterable<Object[]> legacyJavaInfoConstructor() {
return ImmutableList.of(new Object[] {false}, new Object[] {true});
}
private final boolean legacyJavaInfoConstructor;
public JavaInfoSkylarkApiTest(boolean legacyJavaInfoConstructor) {
this.legacyJavaInfoConstructor = legacyJavaInfoConstructor;
}
@Before
public void setIncompatibleFlag() throws Exception {
if (legacyJavaInfoConstructor) {
setSkylarkSemanticsOptions("--noincompatible_disallow_legacy_javainfo");
}
}
@Test
public void buildHelperCreateJavaInfoWithOutputJarOnly() throws Exception {
ruleBuilder().build();
scratch.file(
"foo/BUILD",
"load(':extension.bzl', 'my_rule')",
"my_rule(",
" name = 'my_skylark_rule',",
" output_jar = 'my_skylark_rule_lib.jar',",
" source_jars = ['my_skylark_rule_src.jar']",
")");
assertNoEvents();
JavaCompilationArgsProvider javaCompilationArgsProvider =
fetchJavaInfo().getProvider(JavaCompilationArgsProvider.class);
assertThat(prettyArtifactNames(javaCompilationArgsProvider.getDirectCompileTimeJars()))
.containsExactly("foo/my_skylark_rule_lib.jar");
assertThat(prettyArtifactNames(javaCompilationArgsProvider.getDirectFullCompileTimeJars()))
.containsExactly("foo/my_skylark_rule_lib.jar");
assertThat(prettyArtifactNames(javaCompilationArgsProvider.getRuntimeJars()))
.containsExactly("foo/my_skylark_rule_lib.jar");
assertThat(prettyArtifactNames(javaCompilationArgsProvider.getTransitiveCompileTimeJars()))
.containsExactly("foo/my_skylark_rule_lib.jar");
}
@Test
public void buildHelperCreateJavaInfoWithOutputJarAndUseIJar() throws Exception {
ruleBuilder().withIJar().build();
scratch.file(
"foo/BUILD",
"load(':extension.bzl', 'my_rule')",
"my_rule(",
" name = 'my_skylark_rule',",
" output_jar = 'my_skylark_rule_lib.jar',",
" source_jars = ['my_skylark_rule_src.jar']",
")");
assertNoEvents();
JavaCompilationArgsProvider javaCompilationArgsProvider =
fetchJavaInfo().getProvider(JavaCompilationArgsProvider.class);
assertThat(prettyArtifactNames(javaCompilationArgsProvider.getDirectCompileTimeJars()))
.containsExactly("foo/my_skylark_rule_lib-ijar.jar");
assertThat(prettyArtifactNames(javaCompilationArgsProvider.getDirectFullCompileTimeJars()))
.containsExactly("foo/my_skylark_rule_lib.jar");
assertThat(prettyArtifactNames(javaCompilationArgsProvider.getRuntimeJars()))
.containsExactly("foo/my_skylark_rule_lib.jar");
assertThat(prettyArtifactNames(javaCompilationArgsProvider.getTransitiveCompileTimeJars()))
.containsExactly("foo/my_skylark_rule_lib-ijar.jar");
}
@Test
public void buildHelperCreateJavaInfoJavaRuleOutputJarsProviderSourceJarOutputJarAndUseIJar()
throws Exception {
ruleBuilder().withIJar().build();
scratch.file(
"foo/BUILD",
"load(':extension.bzl', 'my_rule')",
"my_rule(",
" name = 'my_skylark_rule',",
" output_jar = 'my_skylark_rule_lib.jar',",
" source_jars = ['my_skylark_rule_src.jar'],",
")");
assertNoEvents();
JavaRuleOutputJarsProvider javaRuleOutputJarsProvider =
fetchJavaInfo().getProvider(JavaRuleOutputJarsProvider.class);
assertThat(prettyArtifactNames(javaRuleOutputJarsProvider.getAllSrcOutputJars()))
.containsExactly("foo/my_skylark_rule_src.jar");
assertThat(prettyArtifactNames(javaRuleOutputJarsProvider.getAllClassOutputJars()))
.containsExactly("foo/my_skylark_rule_lib.jar");
assertThat(javaRuleOutputJarsProvider.getOutputJars()).hasSize(1);
OutputJar outputJar = javaRuleOutputJarsProvider.getOutputJars().get(0);
assertThat(outputJar.getIJar().prettyPrint()).isEqualTo("foo/my_skylark_rule_lib-ijar.jar");
}
@Test
public void buildHelperCreateJavaInfoWithDeps() throws Exception {
ruleBuilder().build();
scratch.file(
"foo/BUILD",
"load(':extension.bzl', 'my_rule')",
"java_library(name = 'my_java_lib_direct', srcs = ['java/A.java'])",
"my_rule(name = 'my_skylark_rule',",
" output_jar = 'my_skylark_rule_lib.jar',",
" source_jars = ['my_skylark_rule_src.jar'],",
" dep = [':my_java_lib_direct']",
")");
assertNoEvents();
JavaCompilationArgsProvider javaCompilationArgsProvider =
fetchJavaInfo().getProvider(JavaCompilationArgsProvider.class);
assertThat(prettyArtifactNames(javaCompilationArgsProvider.getDirectCompileTimeJars()))
.containsExactly("foo/my_skylark_rule_lib.jar");
assertThat(prettyArtifactNames(javaCompilationArgsProvider.getDirectFullCompileTimeJars()))
.containsExactly("foo/my_skylark_rule_lib.jar");
assertThat(prettyArtifactNames(javaCompilationArgsProvider.getRuntimeJars()))
.containsExactly("foo/my_skylark_rule_lib.jar", "foo/libmy_java_lib_direct.jar");
assertThat(prettyArtifactNames(javaCompilationArgsProvider.getTransitiveCompileTimeJars()))
.containsExactly("foo/my_skylark_rule_lib.jar", "foo/libmy_java_lib_direct-hjar.jar");
}
@Test
public void buildHelperCreateJavaInfoWithRunTimeDeps() throws Exception {
ruleBuilder().build();
scratch.file(
"foo/BUILD",
"load(':extension.bzl', 'my_rule')",
"java_library(name = 'my_java_lib_direct', srcs = ['java/A.java'])",
"my_rule(name = 'my_skylark_rule',",
" output_jar = 'my_skylark_rule_lib.jar',",
" source_jars = ['my_skylark_rule_src.jar'],",
" dep_runtime = [':my_java_lib_direct']",
")");
assertNoEvents();
JavaCompilationArgsProvider javaCompilationArgsProvider =
fetchJavaInfo().getProvider(JavaCompilationArgsProvider.class);
assertThat(prettyArtifactNames(javaCompilationArgsProvider.getDirectCompileTimeJars()))
.containsExactly("foo/my_skylark_rule_lib.jar");
assertThat(prettyArtifactNames(javaCompilationArgsProvider.getDirectFullCompileTimeJars()))
.containsExactly("foo/my_skylark_rule_lib.jar");
assertThat(prettyArtifactNames(javaCompilationArgsProvider.getRuntimeJars()))
.containsExactly("foo/my_skylark_rule_lib.jar", "foo/libmy_java_lib_direct.jar");
assertThat(prettyArtifactNames(javaCompilationArgsProvider.getTransitiveCompileTimeJars()))
.containsExactly("foo/my_skylark_rule_lib.jar");
}
@Test
public void buildHelperCreateJavaInfoWithDepsAndNeverLink() throws Exception {
ruleBuilder().withNeverLink().build();
scratch.file(
"foo/BUILD",
"load(':extension.bzl', 'my_rule')",
"java_library(name = 'my_java_lib_direct', srcs = ['java/A.java'])",
"my_rule(name = 'my_skylark_rule',",
" output_jar = 'my_skylark_rule_lib.jar',",
" source_jars = ['my_skylark_rule_src.jar'],",
" dep = [':my_java_lib_direct']",
")");
assertNoEvents();
JavaCompilationArgsProvider javaCompilationArgsProvider =
fetchJavaInfo().getProvider(JavaCompilationArgsProvider.class);
assertThat(prettyArtifactNames(javaCompilationArgsProvider.getDirectCompileTimeJars()))
.containsExactly("foo/my_skylark_rule_lib.jar");
assertThat(prettyArtifactNames(javaCompilationArgsProvider.getDirectFullCompileTimeJars()))
.containsExactly("foo/my_skylark_rule_lib.jar");
assertThat(prettyArtifactNames(javaCompilationArgsProvider.getRuntimeJars())).isEmpty();
assertThat(prettyArtifactNames(javaCompilationArgsProvider.getTransitiveCompileTimeJars()))
.containsExactly("foo/my_skylark_rule_lib.jar", "foo/libmy_java_lib_direct-hjar.jar");
}
@Test
public void buildHelperCreateJavaInfoSourceJarsProviderWithSourceJars() throws Exception {
ruleBuilder().build();
scratch.file(
"foo/BUILD",
"load(':extension.bzl', 'my_rule')",
"my_rule(name = 'my_skylark_rule',",
" output_jar = 'my_skylark_rule_lib.jar',",
" source_jars = ['my_skylark_rule_src.jar']",
")");
assertNoEvents();
JavaSourceJarsProvider sourceJarsProvider =
fetchJavaInfo().getProvider(JavaSourceJarsProvider.class);
assertThat(prettyArtifactNames(sourceJarsProvider.getSourceJars()))
.containsExactly("foo/my_skylark_rule_src.jar");
assertThat(prettyArtifactNames(sourceJarsProvider.getTransitiveSourceJars()))
.containsExactly("foo/my_skylark_rule_src.jar");
}
@Test
public void buildHelperCreateJavaInfoWithSourcesFiles() throws Exception {
ruleBuilder().withSourceFiles().build();
scratch.file(
"foo/BUILD",
"load(':extension.bzl', 'my_rule')",
"my_rule(",
" name = 'my_skylark_rule',",
" output_jar = 'my_skylark_rule_lib.jar',",
" sources = ['ClassA.java', 'ClassB.java', 'ClassC.java', 'ClassD.java'],",
")");
assertNoEvents();
JavaRuleOutputJarsProvider javaRuleOutputJarsProvider =
fetchJavaInfo().getProvider(JavaRuleOutputJarsProvider.class);
assertThat(prettyArtifactNames(javaRuleOutputJarsProvider.getAllSrcOutputJars()))
.containsExactly("foo/my_skylark_rule_lib-src.jar");
JavaSourceJarsProvider sourceJarsProvider =
fetchJavaInfo().getProvider(JavaSourceJarsProvider.class);
assertThat(prettyArtifactNames(sourceJarsProvider.getSourceJars()))
.containsExactly("foo/my_skylark_rule_lib-src.jar");
assertThat(prettyArtifactNames(sourceJarsProvider.getTransitiveSourceJars()))
.containsExactly("foo/my_skylark_rule_lib-src.jar");
}
@Test
public void buildHelperCreateJavaInfoWithSourcesFilesAndSourcesJars() throws Exception {
ruleBuilder().withSourceFiles().build();
scratch.file(
"foo/BUILD",
"load(':extension.bzl', 'my_rule')",
"my_rule(",
" name = 'my_skylark_rule',",
" output_jar = 'my_skylark_rule_lib.jar',",
" sources = ['ClassA.java', 'ClassB.java', 'ClassC.java', 'ClassD.java'],",
" source_jars = ['my_skylark_rule_src-A.jar']",
")");
assertNoEvents();
JavaRuleOutputJarsProvider javaRuleOutputJarsProvider =
fetchJavaInfo().getProvider(JavaRuleOutputJarsProvider.class);
assertThat(prettyArtifactNames(javaRuleOutputJarsProvider.getAllSrcOutputJars()))
.containsExactly("foo/my_skylark_rule_lib-src.jar");
JavaSourceJarsProvider sourceJarsProvider =
fetchJavaInfo().getProvider(JavaSourceJarsProvider.class);
assertThat(prettyArtifactNames(sourceJarsProvider.getSourceJars()))
.containsExactly("foo/my_skylark_rule_lib-src.jar");
assertThat(prettyArtifactNames(sourceJarsProvider.getTransitiveSourceJars()))
.containsExactly("foo/my_skylark_rule_lib-src.jar");
}
@Test
public void buildHelperCreateJavaInfoSourceJarsProviderWithDeps() throws Exception {
ruleBuilder().build();
scratch.file(
"foo/BUILD",
"load(':extension.bzl', 'my_rule')",
"java_library(name = 'my_java_lib_direct', srcs = ['java/A.java'])",
"my_rule(name = 'my_skylark_rule',",
" output_jar = 'my_skylark_rule_lib.jar',",
" source_jars = ['my_skylark_rule_src.jar'],",
" dep = [':my_java_lib_direct']",
")");
assertNoEvents();
JavaSourceJarsProvider sourceJarsProvider =
fetchJavaInfo().getProvider(JavaSourceJarsProvider.class);
assertThat(prettyArtifactNames(sourceJarsProvider.getSourceJars()))
.containsExactly("foo/my_skylark_rule_src.jar");
assertThat(prettyArtifactNames(sourceJarsProvider.getTransitiveSourceJars()))
.containsExactly("foo/my_skylark_rule_src.jar", "foo/libmy_java_lib_direct-src.jar");
}
@Test
public void buildHelperCreateJavaInfoJavaSourceJarsProviderAndRuntimeDeps() throws Exception {
ruleBuilder().build();
scratch.file(
"foo/BUILD",
"load(':extension.bzl', 'my_rule')",
"java_library(name = 'my_java_lib_direct', srcs = ['java/A.java'])",
"my_rule(name = 'my_skylark_rule',",
" output_jar = 'my_skylark_rule_lib.jar',",
" source_jars = ['my_skylark_rule_src.jar'],",
" dep_runtime = [':my_java_lib_direct']",
")");
assertNoEvents();
JavaSourceJarsProvider sourceJarsProvider =
fetchJavaInfo().getProvider(JavaSourceJarsProvider.class);
assertThat(prettyArtifactNames(sourceJarsProvider.getSourceJars()))
.containsExactly("foo/my_skylark_rule_src.jar");
assertThat(prettyArtifactNames(sourceJarsProvider.getTransitiveSourceJars()))
.containsExactly("foo/my_skylark_rule_src.jar", "foo/libmy_java_lib_direct-src.jar");
}
@Test
public void buildHelperCreateJavaInfoJavaSourceJarsProviderAndTransitiveDeps() throws Exception {
ruleBuilder().build();
scratch.file(
"foo/BUILD",
"load(':extension.bzl', 'my_rule')",
"java_library(name = 'my_java_lib_transitive', srcs = ['java/B.java'])",
"java_library(name = 'my_java_lib_direct',",
" srcs = ['java/A.java'],",
" deps = [':my_java_lib_transitive'])",
"my_rule(name = 'my_skylark_rule',",
" output_jar = 'my_skylark_rule_lib.jar',",
" source_jars = ['my_skylark_rule_src.jar'],",
" dep = [':my_java_lib_direct']",
")");
assertNoEvents();
JavaSourceJarsProvider sourceJarsProvider =
fetchJavaInfo().getProvider(JavaSourceJarsProvider.class);
assertThat(prettyArtifactNames(sourceJarsProvider.getSourceJars()))
.containsExactly("foo/my_skylark_rule_src.jar");
assertThat(prettyArtifactNames(sourceJarsProvider.getTransitiveSourceJars()))
.containsExactly(
"foo/my_skylark_rule_src.jar",
"foo/libmy_java_lib_direct-src.jar",
"foo/libmy_java_lib_transitive-src.jar");
}
@Test
public void buildHelperCreateJavaInfoJavaSourceJarsProviderAndTransitiveRuntimeDeps()
throws Exception {
ruleBuilder().build();
scratch.file(
"foo/BUILD",
"load(':extension.bzl', 'my_rule')",
"java_library(name = 'my_java_lib_transitive', srcs = ['java/B.java'])",
"java_library(name = 'my_java_lib_direct',",
" srcs = ['java/A.java'],",
" deps = [':my_java_lib_transitive'])",
"my_rule(name = 'my_skylark_rule',",
" output_jar = 'my_skylark_rule_lib.jar',",
" source_jars = ['my_skylark_rule_src.jar'],",
" dep = [':my_java_lib_direct']",
")");
assertNoEvents();
JavaSourceJarsProvider sourceJarsProvider =
fetchJavaInfo().getProvider(JavaSourceJarsProvider.class);
assertThat(prettyArtifactNames(sourceJarsProvider.getSourceJars()))
.containsExactly("foo/my_skylark_rule_src.jar");
assertThat(prettyArtifactNames(sourceJarsProvider.getTransitiveSourceJars()))
.containsExactly(
"foo/my_skylark_rule_src.jar",
"foo/libmy_java_lib_direct-src.jar",
"foo/libmy_java_lib_transitive-src.jar");
}
/** Tests that JavaExportsProvider is empty by default. */
@Test
public void buildHelperCreateJavaInfoExportIsEmpty() throws Exception {
ruleBuilder().build();
scratch.file(
"foo/BUILD",
"load(':extension.bzl', 'my_rule')",
"my_rule(name = 'my_skylark_rule',",
" output_jar = 'my_skylark_rule_lib.jar',",
" source_jars = ['my_skylark_rule_src.jar']",
")");
assertNoEvents();
JavaExportsProvider exportsProvider = fetchJavaInfo().getProvider(JavaExportsProvider.class);
assertThat(exportsProvider.getTransitiveExports()).isEmpty();
}
/** Test exports adds dependencies to JavaCompilationArgsProvider. */
@Test
public void buildHelperCreateJavaInfoExportProviderExportsDepsAdded() throws Exception {
ruleBuilder().build();
scratch.file(
"foo/BUILD",
"load(':extension.bzl', 'my_rule')",
"java_library(name = 'my_java_lib_exports', srcs = ['java/A.java'])",
"my_rule(name = 'my_skylark_rule',",
" output_jar = 'my_skylark_rule_lib.jar',",
" dep_exports = [':my_java_lib_exports']",
")");
assertNoEvents();
JavaInfo javaInfo = fetchJavaInfo();
JavaExportsProvider exportsProvider = javaInfo.getProvider(JavaExportsProvider.class);
assertThat(exportsProvider.getTransitiveExports()).isEmpty();
JavaSourceJarsProvider javaSourceJarsProvider =
javaInfo.getProvider(JavaSourceJarsProvider.class);
assertThat(javaSourceJarsProvider.getSourceJars()).isEmpty();
JavaCompilationArgsProvider javaCompilationArgsProvider =
javaInfo.getProvider(JavaCompilationArgsProvider.class);
assertThat(prettyArtifactNames(javaCompilationArgsProvider.getDirectCompileTimeJars()))
.containsExactly("foo/my_skylark_rule_lib.jar", "foo/libmy_java_lib_exports-hjar.jar");
assertThat(prettyArtifactNames(javaCompilationArgsProvider.getDirectFullCompileTimeJars()))
.containsExactly("foo/my_skylark_rule_lib.jar", "foo/libmy_java_lib_exports.jar");
assertThat(prettyArtifactNames(javaCompilationArgsProvider.getRuntimeJars()))
.containsExactly("foo/my_skylark_rule_lib.jar", "foo/libmy_java_lib_exports.jar");
assertThat(prettyArtifactNames(javaCompilationArgsProvider.getTransitiveCompileTimeJars()))
.containsExactly("foo/my_skylark_rule_lib.jar", "foo/libmy_java_lib_exports-hjar.jar");
}
/**
* Test exports adds itself and recursive dependencies to JavaCompilationArgsProvider and
* JavaExportsProvider populated.
*/
@Test
public void buildHelperCreateJavaInfoExportProvider() throws Exception {
ruleBuilder().build();
scratch.file(
"foo/BUILD",
"load(':extension.bzl', 'my_rule')",
"java_library(name = 'my_java_lib_c', srcs = ['java/C.java'])",
"java_library(name = 'my_java_lib_b', srcs = ['java/B.java'])",
"java_library(name = 'my_java_lib_a', srcs = ['java/A.java'],",
" deps = [':my_java_lib_b', ':my_java_lib_c'],",
" exports = [':my_java_lib_b']",
" )",
"my_rule(name = 'my_skylark_rule',",
" output_jar = 'my_skylark_rule_lib.jar',",
" dep_exports = [':my_java_lib_a']",
")");
assertNoEvents();
JavaInfo javaInfo = fetchJavaInfo();
JavaExportsProvider exportsProvider = javaInfo.getProvider(JavaExportsProvider.class);
assertThat(exportsProvider.getTransitiveExports())
.containsExactly(Label.parseAbsolute("//foo:my_java_lib_b", ImmutableMap.of()));
JavaCompilationArgsProvider javaCompilationArgsProvider =
javaInfo.getProvider(JavaCompilationArgsProvider.class);
assertThat(prettyArtifactNames(javaCompilationArgsProvider.getDirectCompileTimeJars()))
.containsExactly(
"foo/my_skylark_rule_lib.jar",
"foo/libmy_java_lib_a-hjar.jar",
"foo/libmy_java_lib_b-hjar.jar");
assertThat(prettyArtifactNames(javaCompilationArgsProvider.getDirectFullCompileTimeJars()))
.containsExactly(
"foo/my_skylark_rule_lib.jar", "foo/libmy_java_lib_a.jar", "foo/libmy_java_lib_b.jar");
assertThat(prettyArtifactNames(javaCompilationArgsProvider.getRuntimeJars()))
.containsExactly(
"foo/my_skylark_rule_lib.jar",
"foo/libmy_java_lib_a.jar",
"foo/libmy_java_lib_b.jar",
"foo/libmy_java_lib_c.jar");
assertThat(prettyArtifactNames(javaCompilationArgsProvider.getTransitiveCompileTimeJars()))
.containsExactly(
"foo/my_skylark_rule_lib.jar",
"foo/libmy_java_lib_a-hjar.jar",
"foo/libmy_java_lib_b-hjar.jar",
"foo/libmy_java_lib_c-hjar.jar");
}
/**
* Tests case: my_lib // \ a c // \\ b d
*
* <p>where single line is normal dependency and double is exports dependency.
*/
@Test
public void buildHelperCreateJavaInfoExportProvider001() throws Exception {
ruleBuilder().build();
scratch.file(
"foo/BUILD",
"load(':extension.bzl', 'my_rule')",
"java_library(name = 'my_java_lib_b', srcs = ['java/B.java'])",
"java_library(name = 'my_java_lib_a', srcs = ['java/A.java'],",
" deps = [':my_java_lib_b'],",
" exports = [':my_java_lib_b']",
" )",
"java_library(name = 'my_java_lib_d', srcs = ['java/D.java'])",
"java_library(name = 'my_java_lib_c', srcs = ['java/C.java'],",
" deps = [':my_java_lib_d'],",
" exports = [':my_java_lib_d']",
" )",
"my_rule(name = 'my_skylark_rule',",
" output_jar = 'my_skylark_rule_lib.jar',",
" dep = [':my_java_lib_a', ':my_java_lib_c'],",
" dep_exports = [':my_java_lib_a']",
")");
assertNoEvents();
JavaInfo javaInfo = fetchJavaInfo();
JavaExportsProvider exportsProvider = javaInfo.getProvider(JavaExportsProvider.class);
assertThat(exportsProvider.getTransitiveExports())
.containsExactly(Label.parseAbsolute("//foo:my_java_lib_b", ImmutableMap.of()));
JavaCompilationArgsProvider javaCompilationArgsProvider =
javaInfo.getProvider(JavaCompilationArgsProvider.class);
assertThat(prettyArtifactNames(javaCompilationArgsProvider.getDirectCompileTimeJars()))
.containsExactly(
"foo/my_skylark_rule_lib.jar",
"foo/libmy_java_lib_a-hjar.jar",
"foo/libmy_java_lib_b-hjar.jar");
assertThat(prettyArtifactNames(javaCompilationArgsProvider.getDirectFullCompileTimeJars()))
.containsExactly(
"foo/my_skylark_rule_lib.jar", "foo/libmy_java_lib_a.jar", "foo/libmy_java_lib_b.jar");
assertThat(prettyArtifactNames(javaCompilationArgsProvider.getRuntimeJars()))
.containsExactly(
"foo/my_skylark_rule_lib.jar",
"foo/libmy_java_lib_a.jar",
"foo/libmy_java_lib_b.jar",
"foo/libmy_java_lib_c.jar",
"foo/libmy_java_lib_d.jar");
assertThat(prettyArtifactNames(javaCompilationArgsProvider.getTransitiveCompileTimeJars()))
.containsExactly(
"foo/my_skylark_rule_lib.jar",
"foo/libmy_java_lib_a-hjar.jar",
"foo/libmy_java_lib_b-hjar.jar",
"foo/libmy_java_lib_c-hjar.jar",
"foo/libmy_java_lib_d-hjar.jar");
}
@Test
public void buildHelperCreateJavaInfoPlugins() throws Exception {
ruleBuilder().build();
scratch.file("java/test/lib.jar");
scratch.file(
"java/test/BUILD",
"load(':custom_rule.bzl', 'java_custom_library')",
"java_custom_library(",
" name = 'custom',",
" export = ':export',",
")");
scratch.file(
"foo/BUILD",
"load(':extension.bzl', 'my_rule')",
"java_library(name = 'plugin_dep',",
" srcs = [ 'ProcessorDep.java'])",
"java_plugin(name = 'plugin',",
" srcs = ['AnnotationProcessor.java'],",
" processor_class = 'com.google.process.stuff',",
" deps = [ ':plugin_dep' ])",
"java_library(",
" name = 'export',",
" exported_plugins = [ ':plugin'],",
")",
"my_rule(name = 'my_skylark_rule',",
" output_jar = 'my_skylark_rule_lib.jar',",
" dep_exports = [':export']",
")");
assertNoEvents();
assertThat(
fetchJavaInfo().getProvider(JavaPluginInfoProvider.class).plugins().processorClasses())
.containsExactly("com.google.process.stuff");
}
@Test
public void buildHelperCreateJavaInfoWithOutputJarAndStampJar() throws Exception {
if (legacyJavaInfoConstructor) {
// Unsupported mode, don't test this
return;
}
ruleBuilder().withStampJar().build();
scratch.file(
"foo/BUILD",
"load(':extension.bzl', 'my_rule')",
"my_rule(",
" name = 'my_skylark_rule',",
" output_jar = 'my_skylark_rule_lib.jar',",
" source_jars = ['my_skylark_rule_src.jar']",
")");
assertNoEvents();
JavaCompilationArgsProvider javaCompilationArgsProvider =
fetchJavaInfo().getProvider(JavaCompilationArgsProvider.class);
assertThat(prettyArtifactNames(javaCompilationArgsProvider.getDirectFullCompileTimeJars()))
.containsExactly("foo/my_skylark_rule_lib.jar");
assertThat(prettyArtifactNames(javaCompilationArgsProvider.getDirectCompileTimeJars()))
.containsExactly("foo/my_skylark_rule_lib-stamped.jar");
assertThat(prettyArtifactNames(javaCompilationArgsProvider.getRuntimeJars()))
.containsExactly("foo/my_skylark_rule_lib.jar");
assertThat(prettyArtifactNames(javaCompilationArgsProvider.getTransitiveCompileTimeJars()))
.containsExactly("foo/my_skylark_rule_lib-stamped.jar");
}
@Test
public void buildHelperCreateJavaInfoWithJdeps_javaRuleOutputJarsProvider() throws Exception {
ruleBuilder().build();
scratch.file(
"foo/BUILD",
"load(':extension.bzl', 'my_rule')",
"java_library(name = 'my_java_lib_direct', srcs = ['java/A.java'])",
"my_rule(",
" name = 'my_skylark_rule',",
" output_jar = 'my_skylark_rule_lib.jar',",
" source_jars = ['my_skylark_rule_src.jar'],",
" dep = [':my_java_lib_direct'],",
" jdeps = 'my_jdeps.pb',",
")");
assertNoEvents();
JavaRuleOutputJarsProvider ruleOutputs =
fetchJavaInfo().getProvider(JavaRuleOutputJarsProvider.class);
assertThat(
prettyArtifactNames(
ruleOutputs.getOutputJars().stream()
.map(o -> o.getClassJar())
.collect(ImmutableList.toImmutableList())))
.containsExactly("foo/my_skylark_rule_lib.jar");
assertThat(
prettyArtifactNames(
ruleOutputs.getOutputJars().stream()
.flatMap(o -> Streams.stream(o.getSrcJars()))
.collect(ImmutableList.toImmutableList())))
.containsExactly("foo/my_skylark_rule_src.jar");
assertThat(ruleOutputs.getJdeps().prettyPrint()).isEqualTo("foo/my_jdeps.pb");
}
@Test
public void testMixMatchNewAndLegacyArgsIsError() throws Exception {
ImmutableList.Builder<String> lines = ImmutableList.builder();
lines.add(
"result = provider()",
"def _impl(ctx):",
" output_jar = ctx.actions.declare_file('output_jar')",
" source_jar = ctx.actions.declare_file('source_jar')",
" javaInfo = JavaInfo(",
" output_jar = output_jar, ",
" source_jar = source_jar,",
" source_jars = [source_jar],",
" )",
" return [result(property = javaInfo)]",
"my_rule = rule(",
" implementation = _impl,",
")");
scratch.file("foo/extension.bzl", lines.build().toArray(new String[] {}));
checkError(
"foo",
"my_skylark_rule",
"Cannot use deprecated arguments at the same time",
"load(':extension.bzl', 'my_rule')",
"my_rule(name = 'my_skylark_rule')");
}
@Test
public void testIncompatibleDisallowLegacyJavaInfo() throws Exception {
setSkylarkSemanticsOptions("--incompatible_disallow_legacy_javainfo");
ImmutableList.Builder<String> lines = ImmutableList.builder();
lines.add(
"result = provider()",
"def _impl(ctx):",
" output_jar = ctx.actions.declare_file('output_jar')",
" source_jar = ctx.actions.declare_file('source_jar')",
" javaInfo = JavaInfo(",
" output_jar = output_jar,",
" source_jars = [source_jar],", // No longer allowed
" )",
" return [result(property = javaInfo)]",
"my_rule = rule(",
" implementation = _impl,",
")");
scratch.file("foo/extension.bzl", lines.build().toArray(new String[] {}));
checkError(
"foo",
"my_skylark_rule",
"Cannot use deprecated argument when --incompatible_disallow_legacy_javainfo is set. ",
"load(':extension.bzl', 'my_rule')",
"my_rule(name = 'my_skylark_rule')");
}
private RuleBuilder ruleBuilder() {
return new RuleBuilder();
}
private class RuleBuilder {
private boolean useIJar = false;
private boolean stampJar;
private boolean neverLink = false;
private boolean sourceFiles = false;
private RuleBuilder withIJar() {
useIJar = true;
return this;
}
private RuleBuilder withStampJar() {
stampJar = true;
return this;
}
private RuleBuilder withNeverLink() {
neverLink = true;
return this;
}
private RuleBuilder withSourceFiles() {
sourceFiles = true;
return this;
}
private String[] legacyJavaInfo() {
assertThat(stampJar).isFalse();
return new String[] {
" javaInfo = JavaInfo(",
" output_jar = ctx.outputs.output_jar, ",
useIJar ? " use_ijar = True," : " use_ijar = False,",
neverLink ? " neverlink = True," : "",
" source_jars = ctx.files.source_jars,",
" sources = ctx.files.sources,",
" deps = dp,",
" runtime_deps = dp_runtime,",
" exports = dp_exports,",
" jdeps = ctx.file.jdeps,",
useIJar || sourceFiles ? " actions = ctx.actions," : "",
useIJar || sourceFiles
? " java_toolchain = ctx.attr._toolchain[java_common.JavaToolchainInfo],"
: "",
sourceFiles
? " host_javabase = ctx.attr._host_javabase[java_common.JavaRuntimeInfo],"
: "",
" )",
" return [result(property = javaInfo)]"
};
}
private String[] newJavaInfo() {
assertThat(useIJar && stampJar).isFalse();
ImmutableList.Builder<String> lines = ImmutableList.builder();
if (useIJar) {
lines.add(
" compile_jar = java_common.run_ijar(",
" ctx.actions,",
" jar = ctx.outputs.output_jar,",
" java_toolchain = ctx.attr._toolchain[java_common.JavaToolchainInfo],",
" )");
} else if (stampJar) {
lines.add(
" compile_jar = java_common.stamp_jar(",
" ctx.actions,",
" jar = ctx.outputs.output_jar,",
" target_label = ctx.label,",
" java_toolchain = ctx.attr._toolchain[java_common.JavaToolchainInfo],",
" )");
} else {
lines.add(" compile_jar = ctx.outputs.output_jar");
}
if (sourceFiles) {
lines.add(
" source_jar = java_common.pack_sources(",
" ctx.actions,",
" output_jar = ctx.outputs.output_jar,",
" sources = ctx.files.sources,",
" source_jars = ctx.files.source_jars,",
" java_toolchain = ctx.attr._toolchain[java_common.JavaToolchainInfo],",
" host_javabase = ctx.attr._host_javabase[java_common.JavaRuntimeInfo],",
")");
} else {
lines.add(
" if ctx.files.source_jars:",
" source_jar = list(ctx.files.source_jars)[0]",
" else:",
" source_jar = None");
}
lines.add(
" javaInfo = JavaInfo(",
" output_jar = ctx.outputs.output_jar,",
" compile_jar = compile_jar,",
" source_jar = source_jar,",
neverLink ? " neverlink = True," : "",
" deps = dp,",
" runtime_deps = dp_runtime,",
" exports = dp_exports,",
" jdeps = ctx.file.jdeps,",
" )",
" return [result(property = javaInfo)]");
return lines.build().toArray(new String[] {});
}
private void build() throws Exception {
if (useIJar || stampJar || sourceFiles) {
writeBuildFileForJavaToolchain();
}
ImmutableList.Builder<String> lines = ImmutableList.builder();
lines.add(
"result = provider()",
"def _impl(ctx):",
" ctx.actions.write(ctx.outputs.output_jar, 'JavaInfo API Test', is_executable=False) ",
" dp = [dep[java_common.provider] for dep in ctx.attr.dep]",
" dp_runtime = [dep[java_common.provider] for dep in ctx.attr.dep_runtime]",
" dp_exports = [dep[java_common.provider] for dep in ctx.attr.dep_exports]");
lines.add(legacyJavaInfoConstructor ? legacyJavaInfo() : newJavaInfo());
lines.add(
"my_rule = rule(",
" implementation = _impl,",
" attrs = {",
" 'dep' : attr.label_list(),",
" 'dep_runtime' : attr.label_list(),",
" 'dep_exports' : attr.label_list(),",
" 'output_jar' : attr.output(default=None, mandatory=True),",
" 'source_jars' : attr.label_list(allow_files=['.jar']),",
" 'sources' : attr.label_list(allow_files=['.java']),",
" 'jdeps' : attr.label(allow_single_file=True),",
useIJar || stampJar || sourceFiles
? " '_toolchain': attr.label(default = Label('//java/com/google/test:toolchain')),"
: "",
sourceFiles
? " '_host_javabase': attr.label(default = Label('"
+ HOST_JAVA_RUNTIME_LABEL
+ "')),"
: "",
" }",
")");
scratch.file("foo/extension.bzl", lines.build().toArray(new String[] {}));
}
}
private JavaInfo fetchJavaInfo() throws Exception {
ConfiguredTarget myRuleTarget = getConfiguredTarget("//foo:my_skylark_rule");
StructImpl info =
(StructImpl)
myRuleTarget.get(
new SkylarkKey(
Label.parseAbsolute("//foo:extension.bzl", ImmutableMap.of()), "result"));
@SuppressWarnings("unchecked")
JavaInfo javaInfo = (JavaInfo) info.getValue("property");
return javaInfo;
}
}