From 32dff21d00ad7d1bdf50e8761d675a6e7e002de9 Mon Sep 17 00:00:00 2001 From: dbabkin Date: Wed, 10 Jan 2018 05:24:22 -0800 Subject: Create function createJavaInfo with new API. Implement JavaCompilationArgsProvider. Added tests for checking JavaCompilationArgsProvider state. All other providers will be implemented in next CLs. RELNOTES:none PiperOrigin-RevId: 181451235 --- src/main/java/com/google/devtools/build/lib/BUILD | 2 + .../build/lib/rules/java/JavaCompilationArgs.java | 17 +- .../devtools/build/lib/rules/java/JavaInfo.java | 100 +++++- .../build/lib/rules/java/JavaInfoBuildHelper.java | 395 +++++++++++++++++++++ .../build/lib/rules/java/JavaSkylarkCommon.java | 268 +++----------- .../build/lib/rules/java/JavaSkylarkApiTest.java | 332 +++++++++++++++++ src/test/shell/bazel/bazel_java_test.sh | 76 +++- 7 files changed, 955 insertions(+), 235 deletions(-) create mode 100644 src/main/java/com/google/devtools/build/lib/rules/java/JavaInfoBuildHelper.java diff --git a/src/main/java/com/google/devtools/build/lib/BUILD b/src/main/java/com/google/devtools/build/lib/BUILD index fbfb27f16e..4b404b9733 100644 --- a/src/main/java/com/google/devtools/build/lib/BUILD +++ b/src/main/java/com/google/devtools/build/lib/BUILD @@ -869,6 +869,7 @@ java_library( "rules/java/JavaHeaderCompileAction.java", "rules/java/JavaHelper.java", "rules/java/JavaInfo.java", + "rules/java/JavaInfoBuildHelper.java", "rules/java/JavaLibraryHelper.java", "rules/java/JavaNativeLibraryProvider.java", "rules/java/JavaOptions.java", @@ -880,6 +881,7 @@ java_library( "rules/java/JavaRuntimeInfo.java", "rules/java/JavaSemantics.java", "rules/java/JavaSkylarkApiProvider.java", + "rules/java/JavaSkylarkCommon.java", "rules/java/JavaSourceJarsProvider.java", "rules/java/JavaTargetAttributes.java", "rules/java/JavaToolchainProvider.java", diff --git a/src/main/java/com/google/devtools/build/lib/rules/java/JavaCompilationArgs.java b/src/main/java/com/google/devtools/build/lib/rules/java/JavaCompilationArgs.java index f9198eee58..1dc527b81f 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/java/JavaCompilationArgs.java +++ b/src/main/java/com/google/devtools/build/lib/rules/java/JavaCompilationArgs.java @@ -22,7 +22,6 @@ import com.google.devtools.build.lib.collect.nestedset.NestedSet; import com.google.devtools.build.lib.collect.nestedset.NestedSetBuilder; import com.google.devtools.build.lib.collect.nestedset.Order; import com.google.devtools.build.lib.util.FileType; -import java.util.Collection; /** A container of Java compilation artifacts. */ @AutoValue @@ -96,6 +95,15 @@ public abstract class JavaCompilationArgs { private Builder() { } + public static Builder copyOf(Builder builder){ + Builder result = new Builder(); + result.addTransitiveRuntimeJars(builder.runtimeJarsBuilder.build()); + result.addTransitiveCompileTimeJars(builder.compileTimeJarsBuilder.build()); + result.addTransitiveFullCompileTimeJars(builder.fullCompileTimeJarsBuilder.build()); + result.addInstrumentationMetadata(builder.instrumentationMetadataBuilder.build()); + return result; + } + /** * Legacy method for dealing with objects which construct * {@link JavaCompilationArtifacts} objects. @@ -155,6 +163,11 @@ public abstract class JavaCompilationArgs { return this; } + public Builder addFullCompileTimeJar(Artifact fullCompileTimeJar) { + this.fullCompileTimeJarsBuilder.add(fullCompileTimeJar); + return this; + } + public Builder addTransitiveCompileTimeJars(NestedSet compileTimeJars) { this.compileTimeJarsBuilder.addTransitive(compileTimeJars); return this; @@ -170,7 +183,7 @@ public abstract class JavaCompilationArgs { return this; } - public Builder addInstrumentationMetadata(Collection instrumentationMetadata) { + public Builder addInstrumentationMetadata(Iterable instrumentationMetadata) { this.instrumentationMetadataBuilder.addAll(instrumentationMetadata); return this; } diff --git a/src/main/java/com/google/devtools/build/lib/rules/java/JavaInfo.java b/src/main/java/com/google/devtools/build/lib/rules/java/JavaInfo.java index c26679ff51..0f792bb480 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/java/JavaInfo.java +++ b/src/main/java/com/google/devtools/build/lib/rules/java/JavaInfo.java @@ -13,28 +13,40 @@ // limitations under the License. package com.google.devtools.build.lib.rules.java; +import static com.google.devtools.build.lib.syntax.SkylarkType.BOOL; + import com.google.common.base.Preconditions; import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableSet; import com.google.devtools.build.lib.actions.Artifact; +import com.google.devtools.build.lib.analysis.ConfiguredTarget; import com.google.devtools.build.lib.analysis.Runfiles; import com.google.devtools.build.lib.analysis.TransitiveInfoCollection; import com.google.devtools.build.lib.analysis.TransitiveInfoProvider; import com.google.devtools.build.lib.analysis.TransitiveInfoProviderMap; import com.google.devtools.build.lib.analysis.TransitiveInfoProviderMapBuilder; +import com.google.devtools.build.lib.analysis.skylark.SkylarkActionFactory; import com.google.devtools.build.lib.cmdline.Label; import com.google.devtools.build.lib.collect.nestedset.NestedSet; import com.google.devtools.build.lib.collect.nestedset.NestedSetBuilder; import com.google.devtools.build.lib.concurrent.ThreadSafety.Immutable; +import com.google.devtools.build.lib.events.Location; import com.google.devtools.build.lib.packages.NativeInfo; import com.google.devtools.build.lib.packages.NativeProvider; import com.google.devtools.build.lib.skylarkinterface.SkylarkCallable; import com.google.devtools.build.lib.skylarkinterface.SkylarkModule; import com.google.devtools.build.lib.skylarkinterface.SkylarkModuleCategory; import com.google.devtools.build.lib.skylarkinterface.SkylarkValue; +import com.google.devtools.build.lib.syntax.EvalException; +import com.google.devtools.build.lib.syntax.FunctionSignature; +import com.google.devtools.build.lib.syntax.Runtime; import com.google.devtools.build.lib.syntax.SkylarkList; import com.google.devtools.build.lib.syntax.SkylarkNestedSet; +import com.google.devtools.build.lib.syntax.SkylarkType; import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; import java.util.List; import java.util.function.Function; import javax.annotation.Nullable; @@ -48,8 +60,82 @@ import javax.annotation.Nullable; @Immutable public final class JavaInfo extends NativeInfo { + public static final String SKYLARK_NAME = "JavaInfo"; + + private static final SkylarkType SEQUENCE_OF_ARTIFACTS = + SkylarkType.Combination.of(SkylarkType.SEQUENCE, SkylarkType.of(Artifact.class)); + private static final SkylarkType SEQUENCE_OF_JAVA_INFO = + SkylarkType.Combination.of(SkylarkType.SEQUENCE, SkylarkType.of(JavaInfo.class)); + private static final SkylarkType LIST_OF_ARTIFACTS = + SkylarkType.Combination.of(SkylarkType.SEQUENCE, SkylarkType.of(Artifact.class)); + + private static final FunctionSignature.WithValues SIGNATURE = + FunctionSignature.WithValues.create( + FunctionSignature.of( + /*numMandatoryPositionals=*/ 0, + /*numOptionalPositionals=*/ 0, + /*numMandatoryNamedOnly=*/ 1, + /*starArg=*/ false, + /*kwArg=*/ false, + "output_jar", + "sources", + "source_jars", + "use_ijar", + "neverlink", + "deps", + "runtime_deps", + "exports", + "actions", + "java_toolchain"), + + /*defaultValues=*/ Arrays.asList( + SkylarkList.createImmutable(Collections.emptyList()), // sources + SkylarkList.createImmutable(Collections.emptyList()), // source_jars + Boolean.TRUE, // use_ijar + Boolean.FALSE, // neverlink + SkylarkList.createImmutable(Collections.emptyList()), // deps + SkylarkList.createImmutable(Collections.emptyList()), // runtime_deps + SkylarkList.createImmutable(Collections.emptyList()), // exports + Runtime.NONE, // actions + Runtime.NONE), // java_toolchain + /*types=*/ ImmutableList.of( + SkylarkType.of(Artifact.class), // output_jar + SkylarkType.Union.of(SEQUENCE_OF_ARTIFACTS, LIST_OF_ARTIFACTS), // sources + SkylarkType.Union.of(SEQUENCE_OF_ARTIFACTS, LIST_OF_ARTIFACTS), // source_jars + BOOL, // use_ijar + BOOL, // neverlink + SEQUENCE_OF_JAVA_INFO, // deps + SEQUENCE_OF_JAVA_INFO, // runtime_deps + SEQUENCE_OF_JAVA_INFO, // exports + SkylarkType.of(SkylarkActionFactory.class), // actions + SkylarkType.of(ConfiguredTarget.class))); // java_toolchain + public static final NativeProvider PROVIDER = - new NativeProvider(JavaInfo.class, "JavaInfo") {}; + new NativeProvider(JavaInfo.class, SKYLARK_NAME, SIGNATURE) { + + @Override + @SuppressWarnings("unchecked") + protected JavaInfo createInstanceFromSkylark(Object[] args, Location loc) + throws EvalException { + + JavaInfo javaInfo = + JavaInfoBuildHelper.getInstance() + .createJavaInfo( + (Artifact) args[0], + (SkylarkList) args[1], + (SkylarkList) args[2], + (Boolean) args[3], + (Boolean) args[4], + (SkylarkList) args[5], + (SkylarkList) args[6], + (SkylarkList) args[7], + args[8], + args[9], + loc); + + return javaInfo; + } + }; public static final JavaInfo EMPTY = JavaInfo.Builder.create().build(); @@ -206,8 +292,8 @@ public final class JavaInfo extends NativeInfo { return providersList.build(); } - private JavaInfo(TransitiveInfoProviderMap providers, boolean neverlink) { - super(PROVIDER); + private JavaInfo(TransitiveInfoProviderMap providers, boolean neverlink, Location location) { + super(PROVIDER, ImmutableMap.of(), location); this.providers = providers; this.neverlink = neverlink; } @@ -430,6 +516,7 @@ public final class JavaInfo extends NativeInfo { public static class Builder { TransitiveInfoProviderMapBuilder providerMap; private boolean neverlink; + private Location location = Location.BUILTIN; private Builder(TransitiveInfoProviderMapBuilder providerMap) { this.providerMap = providerMap; @@ -449,6 +536,11 @@ public final class JavaInfo extends NativeInfo { return this; } + public Builder setLocation(Location location) { + this.location = location; + return this; + } + public

Builder addProvider( Class

providerClass, TransitiveInfoProvider provider) { Preconditions.checkArgument(ALLOWED_PROVIDERS.contains(providerClass)); @@ -457,7 +549,7 @@ public final class JavaInfo extends NativeInfo { } public JavaInfo build() { - return new JavaInfo(providerMap.build(), neverlink); + return new JavaInfo(providerMap.build(), neverlink, location); } } } diff --git a/src/main/java/com/google/devtools/build/lib/rules/java/JavaInfoBuildHelper.java b/src/main/java/com/google/devtools/build/lib/rules/java/JavaInfoBuildHelper.java new file mode 100644 index 0000000000..6cff33a4e1 --- /dev/null +++ b/src/main/java/com/google/devtools/build/lib/rules/java/JavaInfoBuildHelper.java @@ -0,0 +1,395 @@ +// 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.devtools.build.lib.rules.java.JavaCompilationArgs.ClasspathType.BOTH; +import static com.google.devtools.build.lib.rules.java.JavaCompilationArgs.ClasspathType.COMPILE_ONLY; +import static com.google.devtools.build.lib.rules.java.JavaCompilationArgs.ClasspathType.RUNTIME_ONLY; + +import com.google.common.collect.ImmutableList; +import com.google.common.collect.Iterables; +import com.google.devtools.build.lib.actions.Artifact; +import com.google.devtools.build.lib.analysis.ConfiguredTarget; +import com.google.devtools.build.lib.analysis.FilesToRunProvider; +import com.google.devtools.build.lib.analysis.Runfiles; +import com.google.devtools.build.lib.analysis.actions.CustomCommandLine; +import com.google.devtools.build.lib.analysis.actions.SpawnAction; +import com.google.devtools.build.lib.analysis.actions.SpawnAction.Builder; +import com.google.devtools.build.lib.analysis.config.BuildConfiguration.StrictDepsMode; +import com.google.devtools.build.lib.analysis.skylark.SkylarkActionFactory; +import com.google.devtools.build.lib.analysis.skylark.SkylarkRuleContext; +import com.google.devtools.build.lib.collect.nestedset.NestedSet; +import com.google.devtools.build.lib.collect.nestedset.NestedSetBuilder; +import com.google.devtools.build.lib.collect.nestedset.Order; +import com.google.devtools.build.lib.events.Location; +import com.google.devtools.build.lib.rules.java.JavaCompilationArgs.ClasspathType; +import com.google.devtools.build.lib.syntax.EvalException; +import com.google.devtools.build.lib.syntax.SkylarkList; +import com.google.devtools.build.lib.syntax.SkylarkType; +import com.google.devtools.build.lib.vfs.FileSystemUtils; +import java.util.List; +import javax.annotation.Nullable; + +/** Implements logic for creating JavaInfo from different set of input parameters. */ +final class JavaInfoBuildHelper { + private static final JavaInfoBuildHelper INSTANCE = new JavaInfoBuildHelper(); + + private JavaInfoBuildHelper() {} + + public static JavaInfoBuildHelper getInstance() { + return INSTANCE; + } + + + /** + * Creates JavaInfo instance from outputJar. + * + * @param outputJar the jar that was created as a result of + * a compilation (e.g. javac, scalac, etc) + * @param sourceFiles the sources that were used to create the output jar + * @param sourceJars the source jars that were used to create the output jar + * @param useIjar if an ijar of the output jar should be created and stored in the provider + * @param neverlink if true only use this library for compilation and not at runtime + * @param compileTimeDeps compile time dependencies that were used to create the output jar + * @param runtimeDeps runtime dependencies that are needed for this library + * @param exports libraries to make available for users of this library. + * java_library.exports + * @param action used to create the ijar and single jar actions + * @param javaToolchain the toolchain to be used for retrieving the ijar tool + * @return new created JavaInfo instance + * @throws EvalException if some mandatory parameter are missing + */ + //todo(b/69780248 gh/3769) only populates JavaInfo with JavaCompilationArgsProvider + public JavaInfo createJavaInfo( + Artifact outputJar, + SkylarkList sourceFiles, + SkylarkList sourceJars, + Boolean useIjar, + Boolean neverlink, + SkylarkList compileTimeDeps, + SkylarkList runtimeDeps, + SkylarkList exports, //todo(b/69780248 gh/3769) handle exports. + Object action, + Object javaToolchain, + Location location) + throws EvalException { + + JavaInfo.Builder javaInfoBuilder = JavaInfo.Builder.create(); + javaInfoBuilder.setLocation(location); + + JavaCompilationArgs.Builder javaCompilationArgsBuilder = JavaCompilationArgs.builder(); + + if (useIjar) { + SkylarkActionFactory skylarkActionFactory = checkActionType(action, location); + ConfiguredTarget configuredTarget = checkConfiguredTargetType(javaToolchain, location); + Artifact iJar = buildIjar(outputJar, skylarkActionFactory, configuredTarget); + javaCompilationArgsBuilder.addCompileTimeJar(iJar); + } else { + javaCompilationArgsBuilder.addCompileTimeJar(outputJar); + } + + javaCompilationArgsBuilder.addFullCompileTimeJar(outputJar); + if (!neverlink) { + javaCompilationArgsBuilder.addRuntimeJar(outputJar); + } + + JavaCompilationArgs.Builder recursiveJavaCompilationArgsBuilder = + JavaCompilationArgs.Builder.copyOf(javaCompilationArgsBuilder); + + + ClasspathType type = neverlink ? COMPILE_ONLY : BOTH; + recursiveJavaCompilationArgsBuilder.addTransitiveArgs( + fetchAggregatedRecursiveJavaCompilationArgsFromProvider(compileTimeDeps), type); + + recursiveJavaCompilationArgsBuilder.addTransitiveArgs( + fetchAggregatedRecursiveJavaCompilationArgsFromProvider(runtimeDeps), RUNTIME_ONLY); + + javaInfoBuilder.addProvider( + JavaCompilationArgsProvider.class, + JavaCompilationArgsProvider.create( + javaCompilationArgsBuilder.build(), recursiveJavaCompilationArgsBuilder.build())); + //todo(b/69780248 gh/3769) add other providers. + + return javaInfoBuilder.build(); + } + + public JavaInfo create( + @Nullable Object actionsUnchecked, + NestedSet compileTimeJars, + NestedSet runtimeJars, + Boolean useIjar, + @Nullable Object javaToolchainUnchecked, + NestedSet transitiveCompileTimeJars, + NestedSet transitiveRuntimeJars, + NestedSet sourceJars) + throws EvalException { + + JavaCompilationArgs.Builder javaCompilationArgsBuilder = JavaCompilationArgs.builder(); + if (useIjar && !compileTimeJars.isEmpty()) { + javaCompilationArgsBuilder.addFullCompileTimeJars(compileTimeJars); + SkylarkActionFactory skylarkActionFactory = + checkActionType(actionsUnchecked); + ConfiguredTarget configuredTarget = + checkConfiguredTargetType(javaToolchainUnchecked); + for (Artifact compileJar : compileTimeJars) { + javaCompilationArgsBuilder.addCompileTimeJar( + buildIjar(compileJar, skylarkActionFactory, configuredTarget)); + } + } else { + javaCompilationArgsBuilder.addCompileTimeJars(compileTimeJars); + javaCompilationArgsBuilder.addFullCompileTimeJars(compileTimeJars); + } + + JavaCompilationArgs javaCompilationArgs = + javaCompilationArgsBuilder.addTransitiveRuntimeJars(runtimeJars).build(); + + JavaCompilationArgs.Builder recursiveJavaCompilationArgs = JavaCompilationArgs.builder(); + if (transitiveCompileTimeJars.isEmpty()) { + recursiveJavaCompilationArgs.addTransitiveCompileTimeJars( + javaCompilationArgs.getCompileTimeJars()); + recursiveJavaCompilationArgs.addTransitiveFullCompileTimeJars( + javaCompilationArgs.getFullCompileTimeJars()); + } else { + recursiveJavaCompilationArgs.addTransitiveCompileTimeJars(transitiveCompileTimeJars); + } + + if (transitiveRuntimeJars.isEmpty()) { + recursiveJavaCompilationArgs.addTransitiveRuntimeJars(runtimeJars); + } else { + recursiveJavaCompilationArgs.addTransitiveRuntimeJars(transitiveRuntimeJars); + } + + JavaInfo javaInfo = + JavaInfo.Builder.create() + .addProvider( + JavaCompilationArgsProvider.class, + JavaCompilationArgsProvider.create( + javaCompilationArgs, recursiveJavaCompilationArgs.build())) + .addProvider( + JavaSourceJarsProvider.class, + JavaSourceJarsProvider.create( + NestedSetBuilder.emptySet(Order.STABLE_ORDER), sourceJars)) + .build(); + return javaInfo; + } + + public JavaInfo createJavaCompileAction( + SkylarkRuleContext skylarkRuleContext, + SkylarkList sourceJars, + SkylarkList sourceFiles, + Artifact outputJar, + SkylarkList javacOpts, + SkylarkList deps, + SkylarkList exports, + SkylarkList plugins, + SkylarkList exportedPlugins, + String strictDepsMode, + ConfiguredTarget javaToolchain, + ConfiguredTarget hostJavabase, + SkylarkList sourcepathEntries, + SkylarkList resources, + JavaSemantics javaSemantics) + throws EvalException, InterruptedException { + if (sourceJars.isEmpty() && sourceFiles.isEmpty() && exports.isEmpty()) { + throw new EvalException( + null, "source_jars, sources and exports cannot be simultaneous empty"); + } + + if (hostJavabase.get(JavaRuntimeInfo.PROVIDER) == null) { + throw new EvalException(null, "'host_javabase' must point to a Java runtime"); + } + + JavaLibraryHelper helper = + new JavaLibraryHelper(skylarkRuleContext.getRuleContext()) + .setOutput(outputJar) + .addSourceJars(sourceJars) + .addSourceFiles(sourceFiles) + .addResources(resources) + .setSourcePathEntries(sourcepathEntries) + .setJavacOpts(javacOpts); + + List depsCompilationArgsProviders = + JavaInfo.fetchProvidersFromList(deps, JavaCompilationArgsProvider.class); + List exportsCompilationArgsProviders = + JavaInfo.fetchProvidersFromList(exports, JavaCompilationArgsProvider.class); + helper.addAllDeps(depsCompilationArgsProviders); + helper.addAllExports(exportsCompilationArgsProviders); + helper.setCompilationStrictDepsMode(getStrictDepsMode(strictDepsMode.toUpperCase())); + + helper.addAllPlugins(JavaInfo.fetchProvidersFromList(plugins, JavaPluginInfoProvider.class)); + helper.addAllPlugins(JavaInfo.fetchProvidersFromList(deps, JavaPluginInfoProvider.class)); + + JavaRuleOutputJarsProvider.Builder outputJarsBuilder = JavaRuleOutputJarsProvider.builder(); + + boolean generateMergedSourceJar = + (sourceJars.size() > 1 || !sourceFiles.isEmpty()) + || (sourceJars.isEmpty() && sourceFiles.isEmpty() && !exports.isEmpty()); + Artifact outputSourceJar = + generateMergedSourceJar ? getSourceJar(skylarkRuleContext, outputJar) : sourceJars.get(0); + + JavaCompilationArtifacts artifacts = + helper.build( + javaSemantics, + getJavaToolchainProvider(javaToolchain), + hostJavabase.get(JavaRuntimeInfo.PROVIDER), + SkylarkList.createImmutable(ImmutableList.of()), + outputJarsBuilder, + /*createOutputSourceJar*/ generateMergedSourceJar, + outputSourceJar); + + JavaCompilationArgsProvider javaCompilationArgsProvider = + helper.buildCompilationArgsProvider(artifacts, true); + Runfiles runfiles = + new Runfiles.Builder(skylarkRuleContext.getWorkspaceName()) + .addTransitiveArtifactsWrappedInStableOrder( + javaCompilationArgsProvider.getRecursiveJavaCompilationArgs().getRuntimeJars()) + .build(); + + JavaPluginInfoProvider transitivePluginsProvider = + JavaPluginInfoProvider.merge( + Iterables.concat( + JavaInfo.getProvidersFromListOfJavaProviders( + JavaPluginInfoProvider.class, exportedPlugins), + JavaInfo.getProvidersFromListOfJavaProviders( + JavaPluginInfoProvider.class, exports))); + + ImmutableList outputSourceJars = ImmutableList.of(outputSourceJar); + + NestedSetBuilder transitiveSourceJars = + NestedSetBuilder.stableOrder().addAll(outputSourceJars); + for (JavaSourceJarsProvider sourceJarsProvider : + JavaInfo.getProvidersFromListOfJavaProviders(JavaSourceJarsProvider.class, deps)) { + transitiveSourceJars.addTransitive(sourceJarsProvider.getTransitiveSourceJars()); + } + + return JavaInfo.Builder.create() + .addProvider(JavaCompilationArgsProvider.class, javaCompilationArgsProvider) + .addProvider( + JavaSourceJarsProvider.class, + createJavaSourceJarsProvider(outputSourceJars, transitiveSourceJars.build())) + .addProvider(JavaRuleOutputJarsProvider.class, outputJarsBuilder.build()) + .addProvider(JavaRunfilesProvider.class, new JavaRunfilesProvider(runfiles)) + .addProvider(JavaPluginInfoProvider.class, transitivePluginsProvider) + .build(); + } + + private SkylarkActionFactory checkActionType(Object action) throws EvalException { + return checkActionType(action, /*location=*/ null); + } + + private SkylarkActionFactory checkActionType(Object action, Location location) + throws EvalException { + return SkylarkType.cast( + action, + SkylarkActionFactory.class, + location, + "The value of use_ijar is True. Make sure the ctx.actions argument is valid."); + } + + private ConfiguredTarget checkConfiguredTargetType(Object javaToolchain) throws EvalException { + return checkConfiguredTargetType(javaToolchain, /*location=*/ null); + } + + private ConfiguredTarget checkConfiguredTargetType(Object javaToolchain, Location location) + throws EvalException { + return SkylarkType.cast( + javaToolchain, + ConfiguredTarget.class, + location, + "The value of use_ijar is True. Make sure the java_toolchain argument is a valid."); + } + + private Artifact buildIjar( + Artifact inputJar, SkylarkActionFactory actions, ConfiguredTarget javaToolchain) + throws EvalException { + String ijarBasename = FileSystemUtils.removeExtension(inputJar.getFilename()) + "-ijar.jar"; + Artifact interfaceJar = actions.declareFile(ijarBasename, inputJar); + FilesToRunProvider ijarTarget = getJavaToolchainProvider(javaToolchain).getIjar(); + SpawnAction.Builder actionBuilder = + new Builder() + .addInput(inputJar) + .addOutput(interfaceJar) + .setExecutable(ijarTarget) + .setProgressMessage("Extracting interface for jar %s", inputJar.getFilename()) + .addCommandLine( + CustomCommandLine.builder().addExecPath(inputJar).addExecPath(interfaceJar).build()) + .useDefaultShellEnvironment() + .setMnemonic("JavaIjar"); + actions.registerAction(actionBuilder.build(actions.getActionConstructionContext())); + return interfaceJar; + } + + JavaToolchainProvider getJavaToolchainProvider(ConfiguredTarget javaToolchain) + throws EvalException { + JavaToolchainProvider javaToolchainProvider = JavaToolchainProvider.from(javaToolchain); + if (javaToolchainProvider == null) { + throw new EvalException( + null, javaToolchain.getLabel() + " does not provide JavaToolchainProvider."); + } + return javaToolchainProvider; + } + + + /** + * Merge collection of JavaInfos to one. Gets CompilationArgsProvider and call + * getRecursiveJavaCompilationArgs on it and return. + * + * @see JavaInfo#merge(List) + */ + private JavaCompilationArgs fetchAggregatedRecursiveJavaCompilationArgsFromProvider( + SkylarkList dependencies) { + + JavaInfo aggregatedDependencies = JavaInfo.merge(dependencies); + JavaCompilationArgsProvider compilationArgsProvider = + aggregatedDependencies.getProvider(JavaCompilationArgsProvider.class); + if (compilationArgsProvider == null) { + // this should not happen: JavaInfo.merge() always creates JavaCompilationArgsProvider + throw new IllegalStateException( + "compilationArgsProvider is null. check JavaInfo.merge implementation."); + } + return compilationArgsProvider.getRecursiveJavaCompilationArgs(); + } + + private static StrictDepsMode getStrictDepsMode(String strictDepsMode) { + switch (strictDepsMode) { + case "OFF": + return StrictDepsMode.OFF; + case "ERROR": + case "DEFAULT": + return StrictDepsMode.ERROR; + case "WARN": + return StrictDepsMode.WARN; + default: + throw new IllegalArgumentException( + "StrictDepsMode " + + strictDepsMode + + " not allowed." + + " Only OFF and ERROR values are accepted."); + } + } + + private static Artifact getSourceJar(SkylarkRuleContext skylarkRuleContext, Artifact outputJar) { + return JavaCompilationHelper.derivedArtifact( + skylarkRuleContext.getRuleContext(), outputJar, "", "-src.jar"); + } + + /** Creates a {@link JavaSourceJarsProvider} from the given lists of source jars. */ + private static JavaSourceJarsProvider createJavaSourceJarsProvider( + List sourceJars, NestedSet transitiveSourceJars) { + NestedSet javaSourceJars = + NestedSetBuilder.stableOrder().addAll(sourceJars).build(); + return JavaSourceJarsProvider.create(transitiveSourceJars, javaSourceJars); + } +} diff --git a/src/main/java/com/google/devtools/build/lib/rules/java/JavaSkylarkCommon.java b/src/main/java/com/google/devtools/build/lib/rules/java/JavaSkylarkCommon.java index 2f2e3ab75c..932834b91e 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/java/JavaSkylarkCommon.java +++ b/src/main/java/com/google/devtools/build/lib/rules/java/JavaSkylarkCommon.java @@ -19,18 +19,11 @@ import com.google.common.collect.ImmutableList; import com.google.common.collect.Iterables; import com.google.devtools.build.lib.actions.Artifact; import com.google.devtools.build.lib.analysis.ConfiguredTarget; -import com.google.devtools.build.lib.analysis.FilesToRunProvider; import com.google.devtools.build.lib.analysis.RuleContext; -import com.google.devtools.build.lib.analysis.Runfiles; -import com.google.devtools.build.lib.analysis.actions.CustomCommandLine; -import com.google.devtools.build.lib.analysis.actions.SpawnAction; -import com.google.devtools.build.lib.analysis.actions.SpawnAction.Builder; -import com.google.devtools.build.lib.analysis.config.BuildConfiguration.StrictDepsMode; import com.google.devtools.build.lib.analysis.skylark.SkylarkActionFactory; import com.google.devtools.build.lib.analysis.skylark.SkylarkRuleContext; import com.google.devtools.build.lib.collect.nestedset.NestedSet; import com.google.devtools.build.lib.collect.nestedset.NestedSetBuilder; -import com.google.devtools.build.lib.collect.nestedset.Order; import com.google.devtools.build.lib.packages.Provider; import com.google.devtools.build.lib.skylarkinterface.Param; import com.google.devtools.build.lib.skylarkinterface.ParamType; @@ -40,8 +33,6 @@ import com.google.devtools.build.lib.syntax.EvalException; import com.google.devtools.build.lib.syntax.SkylarkList; import com.google.devtools.build.lib.syntax.SkylarkNestedSet; import com.google.devtools.build.lib.syntax.Type; -import com.google.devtools.build.lib.vfs.FileSystemUtils; -import java.util.List; import javax.annotation.Nullable; /** A module that contains Skylark utilities for Java support. */ @@ -172,70 +163,17 @@ public class JavaSkylarkCommon { Object transitiveRuntimeJars, Object sourceJars) throws EvalException { - NestedSet compileTimeJarsNestedSet = asArtifactNestedSet(compileTimeJars); - NestedSet runtimeJarsNestedSet = asArtifactNestedSet(runtimeJars); - JavaCompilationArgs.Builder javaCompilationArgsBuilder = JavaCompilationArgs.builder(); - if (useIjar && !compileTimeJarsNestedSet.isEmpty()) { - if (!(actionsUnchecked instanceof SkylarkActionFactory)) { - throw new EvalException(null, "In java_common.create_provider the value of use_ijar is " - + "True. Make sure the first argument of the function is the ctx.actions object."); - } - if (!(javaToolchainUnchecked instanceof ConfiguredTarget)) { - throw new EvalException(null, "In java_common.create_provider the value of use_ijar is " - + "True. Make sure the java_toolchain argument is a valid java_toolchain Target."); - } - SkylarkActionFactory actions = (SkylarkActionFactory) actionsUnchecked; - ConfiguredTarget javaToolchain = (ConfiguredTarget) javaToolchainUnchecked; - javaCompilationArgsBuilder.addFullCompileTimeJars(compileTimeJarsNestedSet); - for (Artifact compileJar : compileTimeJarsNestedSet) { - javaCompilationArgsBuilder.addCompileTimeJar( - buildIjar(actions, compileJar, javaToolchain) - ); - } - } else { - javaCompilationArgsBuilder.addCompileTimeJars(compileTimeJarsNestedSet); - javaCompilationArgsBuilder.addFullCompileTimeJars(compileTimeJarsNestedSet); - } - - JavaCompilationArgs javaCompilationArgs = javaCompilationArgsBuilder - .addTransitiveRuntimeJars(runtimeJarsNestedSet) - .build(); - - NestedSet transitiveCompileTimeJarsNestedSet = - asArtifactNestedSet(transitiveCompileTimeJars); - NestedSet transitiveRuntimeJarsNestedSet = asArtifactNestedSet(transitiveRuntimeJars); - - JavaCompilationArgs.Builder recursiveJavaCompilationArgs = JavaCompilationArgs.builder(); - if (transitiveCompileTimeJarsNestedSet.isEmpty()) { - recursiveJavaCompilationArgs - .addTransitiveCompileTimeJars(javaCompilationArgs.getCompileTimeJars()); - recursiveJavaCompilationArgs - .addTransitiveFullCompileTimeJars(javaCompilationArgs.getFullCompileTimeJars()); - } else { - recursiveJavaCompilationArgs - .addTransitiveCompileTimeJars(transitiveCompileTimeJarsNestedSet); - } - - if (transitiveRuntimeJarsNestedSet.isEmpty()) { - recursiveJavaCompilationArgs.addTransitiveRuntimeJars(runtimeJarsNestedSet); - } else { - recursiveJavaCompilationArgs.addTransitiveRuntimeJars(transitiveRuntimeJarsNestedSet); - } - - JavaInfo javaInfo = - JavaInfo.Builder.create() - .addProvider( - JavaCompilationArgsProvider.class, - JavaCompilationArgsProvider.create( - javaCompilationArgs, recursiveJavaCompilationArgs.build())) - .addProvider( - JavaSourceJarsProvider.class, - JavaSourceJarsProvider.create( - NestedSetBuilder.emptySet(Order.STABLE_ORDER), - asArtifactNestedSet(sourceJars))) - .build(); - return javaInfo; + return JavaInfoBuildHelper.getInstance() + .create( + actionsUnchecked, + asArtifactNestedSet(compileTimeJars), + asArtifactNestedSet(runtimeJars), + useIjar, + javaToolchainUnchecked, + asArtifactNestedSet(transitiveCompileTimeJars), + asArtifactNestedSet(transitiveRuntimeJars), + asArtifactNestedSet(sourceJars)); } public JavaSkylarkCommon(JavaSemantics javaSemantics) { @@ -253,18 +191,6 @@ public class JavaSkylarkCommon { return JavaInfo.PROVIDER; } - /** - * Takes an Object that is either a SkylarkNestedSet or a SkylarkList of Artifacts and returns it - * as a NestedSet. - */ - private static NestedSet asArtifactNestedSet(Object o) throws EvalException { - return o instanceof SkylarkNestedSet - ? ((SkylarkNestedSet) o).getSet(Artifact.class) - : NestedSetBuilder.naiveLinkOrder() - .addAll(((SkylarkList) o).getContents(Artifact.class, null)) - .build(); - } - @SkylarkCallable( name = "compile", doc = "Compiles Java source files/jars from the implementation of a Skylark rule and returns a " @@ -403,121 +329,24 @@ public class JavaSkylarkCommon { ConfiguredTarget hostJavabase, SkylarkList sourcepathEntries, SkylarkList resources) throws EvalException, InterruptedException { - if (sourceJars.isEmpty() && sourceFiles.isEmpty() && exports.isEmpty()) { - throw new EvalException( - null, "source_jars, sources and exports cannot be simultaneous empty"); - } - - if (hostJavabase.get(JavaRuntimeInfo.PROVIDER) == null) { - throw new EvalException(null, "'host_javabase' must point to a Java runtime"); - } - JavaLibraryHelper helper = - new JavaLibraryHelper(skylarkRuleContext.getRuleContext()) - .setOutput(outputJar) - .addSourceJars(sourceJars) - .addSourceFiles(sourceFiles) - .addResources(resources) - .setSourcePathEntries(sourcepathEntries) - .setJavacOpts(javacOpts); - - List depsCompilationArgsProviders = - JavaInfo.fetchProvidersFromList(deps, JavaCompilationArgsProvider.class); - List exportsCompilationArgsProviders = - JavaInfo.fetchProvidersFromList(exports, JavaCompilationArgsProvider.class); - helper.addAllDeps(depsCompilationArgsProviders); - helper.addAllExports(exportsCompilationArgsProviders); - helper.setCompilationStrictDepsMode(getStrictDepsMode(strictDepsMode.toUpperCase())); - - helper.addAllPlugins( - JavaInfo.fetchProvidersFromList(plugins, JavaPluginInfoProvider.class)); - helper.addAllPlugins(JavaInfo.fetchProvidersFromList(deps, JavaPluginInfoProvider.class)); - - JavaRuleOutputJarsProvider.Builder outputJarsBuilder = JavaRuleOutputJarsProvider.builder(); - boolean generateMergedSourceJar = (sourceJars.size() > 1 || !sourceFiles.isEmpty()) - || (sourceJars.isEmpty() && sourceFiles.isEmpty() && !exports.isEmpty()); - Artifact outputSourceJar = - generateMergedSourceJar ? getSourceJar(skylarkRuleContext, outputJar) : sourceJars.get(0); - - JavaCompilationArtifacts artifacts = - helper.build( - javaSemantics, - getJavaToolchainProvider(javaToolchain), - hostJavabase.get(JavaRuntimeInfo.PROVIDER), - SkylarkList.createImmutable(ImmutableList.of()), - outputJarsBuilder, - /*createOutputSourceJar*/ generateMergedSourceJar, - outputSourceJar); - - JavaCompilationArgsProvider javaCompilationArgsProvider = - helper.buildCompilationArgsProvider(artifacts, true); - Runfiles runfiles = - new Runfiles.Builder(skylarkRuleContext.getWorkspaceName()) - .addTransitiveArtifactsWrappedInStableOrder( - javaCompilationArgsProvider.getRecursiveJavaCompilationArgs().getRuntimeJars()) - .build(); - - JavaPluginInfoProvider transitivePluginsProvider = - JavaPluginInfoProvider.merge(Iterables.concat( - JavaInfo.getProvidersFromListOfJavaProviders( - JavaPluginInfoProvider.class, exportedPlugins), - JavaInfo.getProvidersFromListOfJavaProviders( - JavaPluginInfoProvider.class, exports) - )); - - ImmutableList outputSourceJars = ImmutableList.of(outputSourceJar); - - NestedSetBuilder transitiveSourceJars = - NestedSetBuilder.stableOrder().addAll(outputSourceJars); - for (JavaSourceJarsProvider sourceJarsProvider : - JavaInfo.getProvidersFromListOfJavaProviders(JavaSourceJarsProvider.class, deps)) { - transitiveSourceJars.addTransitive(sourceJarsProvider.getTransitiveSourceJars()); - } - - return JavaInfo.Builder.create() - .addProvider(JavaCompilationArgsProvider.class, javaCompilationArgsProvider) - .addProvider(JavaSourceJarsProvider.class, - createJavaSourceJarsProvider(outputSourceJars, transitiveSourceJars.build())) - .addProvider(JavaRuleOutputJarsProvider.class, outputJarsBuilder.build()) - .addProvider(JavaRunfilesProvider.class, new JavaRunfilesProvider(runfiles)) - .addProvider(JavaPluginInfoProvider.class, transitivePluginsProvider) - .build(); - } - - private static Artifact getSourceJar(SkylarkRuleContext skylarkRuleContext, Artifact outputJar) { - return JavaCompilationHelper.derivedArtifact( - skylarkRuleContext.getRuleContext(), outputJar, "", "-src.jar"); - } - - private static Artifact buildIjar( - SkylarkActionFactory actions, - Artifact inputJar, - ConfiguredTarget javaToolchain) throws EvalException { - String ijarBasename = FileSystemUtils.removeExtension(inputJar.getFilename()) + "-ijar.jar"; - Artifact interfaceJar = actions.declareFile(ijarBasename, inputJar); - FilesToRunProvider ijarTarget = getJavaToolchainProvider(javaToolchain).getIjar(); - SpawnAction.Builder actionBuilder = new Builder() - .addInput(inputJar) - .addOutput(interfaceJar) - .setExecutable(ijarTarget) - .setProgressMessage("Extracting interface for jar %s", inputJar.getFilename()) - .addCommandLine(CustomCommandLine.builder() - .addExecPath(inputJar) - .addExecPath(interfaceJar) - .build()) - .useDefaultShellEnvironment() - .setMnemonic("JavaIjar"); - actions.registerAction(actionBuilder.build(actions.getActionConstructionContext())); - return interfaceJar; - } - /** - * Creates a {@link JavaSourceJarsProvider} from the given lists of source jars. - */ - private static JavaSourceJarsProvider createJavaSourceJarsProvider( - List sourceJars, NestedSet transitiveSourceJars) { - NestedSet javaSourceJars = - NestedSetBuilder.stableOrder().addAll(sourceJars).build(); - return JavaSourceJarsProvider.create(transitiveSourceJars, javaSourceJars); + return JavaInfoBuildHelper.getInstance() + .createJavaCompileAction( + skylarkRuleContext, + sourceJars, + sourceFiles, + outputJar, + javacOpts, + deps, + exports, + plugins, + exportedPlugins, + strictDepsMode, + javaToolchain, + hostJavabase, + sourcepathEntries, + resources, + javaSemantics); } @SkylarkCallable( @@ -535,7 +364,8 @@ public class JavaSkylarkCommon { RuleContext ruleContext = skylarkRuleContext.getRuleContext(); ConfiguredTarget javaToolchainConfigTarget = (ConfiguredTarget) skylarkRuleContext.getAttr().getValue(javaToolchainAttr); - JavaToolchainProvider toolchain = getJavaToolchainProvider(javaToolchainConfigTarget); + JavaToolchainProvider toolchain = + JavaInfoBuildHelper.getInstance().getJavaToolchainProvider(javaToolchainConfigTarget); ImmutableList javacOptsFromAttr; if (ruleContext.getRule().isAttrDefined("javacopts", Type.STRING_LIST)) { javacOptsFromAttr = ruleContext.getExpander().withDataLocations().tokenized("javacopts"); @@ -578,16 +408,6 @@ public class JavaSkylarkCommon { .build(); } - private static JavaToolchainProvider getJavaToolchainProvider(ConfiguredTarget javaToolchain) - throws EvalException{ - JavaToolchainProvider javaToolchainProvider = - JavaToolchainProvider.from(javaToolchain); - if (javaToolchainProvider == null) { - throw new EvalException( - null, javaToolchain.getLabel() + " does not provide JavaToolchainProvider."); - } - return javaToolchainProvider; - } /** * Returns a new JavaCompilationArgsProvider whose direct-jars part is the union of both the @@ -605,24 +425,6 @@ public class JavaSkylarkCommon { provider.getRunTimeJavaDependencyArtifacts()); } - private static StrictDepsMode getStrictDepsMode(String strictDepsMode) { - switch (strictDepsMode) { - case "OFF": - return StrictDepsMode.OFF; - case "ERROR": - case "DEFAULT": - return StrictDepsMode.ERROR; - case "WARN": - return StrictDepsMode.WARN; - default: - throw new IllegalArgumentException( - "StrictDepsMode " - + strictDepsMode - + " not allowed." - + " Only OFF and ERROR values are accepted."); - } - } - @SkylarkCallable( name = JavaRuntimeInfo.SKYLARK_NAME, doc = @@ -633,4 +435,16 @@ public class JavaSkylarkCommon { public static Provider getJavaRuntimeProvider() { return JavaRuntimeInfo.PROVIDER; } + + /** + * Takes an Object that is either a SkylarkNestedSet or a SkylarkList of Artifacts and returns it + * as a NestedSet. + */ + private NestedSet asArtifactNestedSet(Object o) throws EvalException { + return o instanceof SkylarkNestedSet + ? ((SkylarkNestedSet) o).getSet(Artifact.class) + : NestedSetBuilder.naiveLinkOrder() + .addAll(((SkylarkList) o).getContents(Artifact.class, /*description=*/ null)) + .build(); + } } diff --git a/src/test/java/com/google/devtools/build/lib/rules/java/JavaSkylarkApiTest.java b/src/test/java/com/google/devtools/build/lib/rules/java/JavaSkylarkApiTest.java index 8a15fbe97b..3b9065840a 100644 --- a/src/test/java/com/google/devtools/build/lib/rules/java/JavaSkylarkApiTest.java +++ b/src/test/java/com/google/devtools/build/lib/rules/java/JavaSkylarkApiTest.java @@ -22,6 +22,7 @@ import com.google.devtools.build.lib.actions.Artifact; 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.cmdline.LabelSyntaxException; import com.google.devtools.build.lib.collect.nestedset.NestedSet; import com.google.devtools.build.lib.packages.Info; import com.google.devtools.build.lib.packages.SkylarkProvider.SkylarkKey; @@ -1453,6 +1454,337 @@ public class JavaSkylarkApiTest extends BuildViewTestCase { assertThat(javaToolchainLabel.toString()).isEqualTo("//java/com/google/test:toolchain"); } + @Test + public void javaInfoBuildHelperCreateJavaInfoWithOutputJarOnly() throws Exception { + scratch.file( + "foo/extension.bzl", + "result = provider()", + "def _impl(ctx):", + " javaInfo = JavaInfo(", + " output_jar = ctx.file.output_jar, ", + " use_ijar = False", + " )", + " return [result(property = javaInfo)]", + "my_rule = rule(", + " implementation = _impl,", + " attrs = {", + " 'dep' : attr.label(), ", + " 'output_jar' : attr.label(allow_single_file=True)", + " }", + ")"); + + scratch.file( + "foo/BUILD", + "load(':extension.bzl', 'my_rule')", + "my_rule(", + " name = 'my_skylark_rule',", + " output_jar = 'my_skylark_rule_lib.jar'", + ")"); + assertNoEvents(); + + ConfiguredTarget myRuleTarget = getConfiguredTarget("//foo:my_skylark_rule"); + Info info = + myRuleTarget.get(new SkylarkKey(Label.parseAbsolute("//foo:extension.bzl"), "result")); + + @SuppressWarnings("unchecked") + JavaInfo javaInfo = (JavaInfo) info.getValue("property"); + + JavaCompilationArgsProvider javaCompilationArgsProvider = + javaInfo.getProvider(JavaCompilationArgsProvider.class); + + + assertThat( + prettyJarNames(javaCompilationArgsProvider.getJavaCompilationArgs().getRuntimeJars())) + .containsExactly("foo/my_skylark_rule_lib.jar"); + assertThat( + prettyJarNames( + javaCompilationArgsProvider.getJavaCompilationArgs().getFullCompileTimeJars())) + .containsExactly("foo/my_skylark_rule_lib.jar"); + assertThat( + prettyJarNames( + javaCompilationArgsProvider.getJavaCompilationArgs().getCompileTimeJars())) + .containsExactly("foo/my_skylark_rule_lib.jar"); + + + + + assertThat( + prettyJarNames( + javaCompilationArgsProvider.getRecursiveJavaCompilationArgs().getRuntimeJars())) + .containsExactly("foo/my_skylark_rule_lib.jar"); + assertThat( + prettyJarNames( + javaCompilationArgsProvider + .getRecursiveJavaCompilationArgs() + .getFullCompileTimeJars())) + .containsExactly("foo/my_skylark_rule_lib.jar"); + + + assertThat( + prettyJarNames( + javaCompilationArgsProvider.getRecursiveJavaCompilationArgs().getCompileTimeJars())) + .containsExactly("foo/my_skylark_rule_lib.jar"); + } + + @Test + public void javaInfoBuildHelperCreateJavaInfoWithOutputJarAndUseIJar() throws Exception { + writeBuildFileForJavaToolchain(); + scratch.file( + "foo/extension.bzl", + "result = provider()", + "def _impl(ctx):", + " javaInfo = JavaInfo(", + " output_jar = ctx.file.output_jar,", + " use_ijar = True,", + " actions = ctx.actions,", + " java_toolchain = ctx.attr._java_toolchain", + " )", + " return [result(property = javaInfo)]", + "my_rule = rule(", + " implementation = _impl,", + " attrs = {", + " 'dep' : attr.label(),", + " 'output_jar' : attr.label(allow_single_file=True),", + " '_java_toolchain': attr.label(default = Label('//java/com/google/test:toolchain')),", + " }", + ")"); + + scratch.file( + "foo/BUILD", + "load(':extension.bzl', 'my_rule')", + "my_rule(", + " name = 'my_skylark_rule',", + " output_jar = 'my_skylark_rule_lib.jar'", + ")"); + assertNoEvents(); + + JavaCompilationArgsProvider javaCompilationArgsProvider = + fetchJavaInfo().getProvider(JavaCompilationArgsProvider.class); + + assertThat( + prettyJarNames(javaCompilationArgsProvider.getJavaCompilationArgs().getRuntimeJars())) + .containsExactly("foo/my_skylark_rule_lib.jar"); + assertThat( + prettyJarNames( + javaCompilationArgsProvider.getJavaCompilationArgs().getFullCompileTimeJars())) + .containsExactly("foo/my_skylark_rule_lib.jar"); + assertThat( + prettyJarNames( + javaCompilationArgsProvider.getJavaCompilationArgs().getCompileTimeJars())) + .containsExactly("foo/my_skylark_rule_lib-ijar.jar"); + + assertThat( + prettyJarNames( + javaCompilationArgsProvider.getRecursiveJavaCompilationArgs().getRuntimeJars())) + .containsExactly("foo/my_skylark_rule_lib.jar"); + assertThat( + prettyJarNames( + javaCompilationArgsProvider + .getRecursiveJavaCompilationArgs() + .getFullCompileTimeJars())) + .containsExactly("foo/my_skylark_rule_lib.jar"); + assertThat( + prettyJarNames( + javaCompilationArgsProvider.getRecursiveJavaCompilationArgs().getCompileTimeJars())) + .containsExactly("foo/my_skylark_rule_lib-ijar.jar"); + } + + @Test + public void javaInfoBuildHelperCreateJavaInfoWithDeps() throws Exception { + scratch.file( + "foo/extension.bzl", + "result = provider()", + "def _impl(ctx):", + " dp = [dep[java_common.provider] for dep in ctx.attr.dep]", + " javaInfo = JavaInfo(", + " output_jar = ctx.file.output_jar,", + " use_ijar = False,", + " deps = dp", + " )", + " return [result(property = javaInfo)]", + "my_rule = rule(", + " implementation = _impl,", + " attrs = {", + " 'dep' : attr.label_list(), ", + " 'output_jar' : attr.label(allow_single_file=True), ", + " }", + ")"); + + 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',", + " dep = [':my_java_lib_direct']", + ")"); + assertNoEvents(); + + JavaCompilationArgsProvider javaCompilationArgsProvider = + fetchJavaInfo().getProvider(JavaCompilationArgsProvider.class); + + assertThat( + prettyJarNames(javaCompilationArgsProvider.getJavaCompilationArgs().getRuntimeJars())) + .containsExactly("foo/my_skylark_rule_lib.jar"); + assertThat( + prettyJarNames( + javaCompilationArgsProvider.getJavaCompilationArgs().getFullCompileTimeJars())) + .containsExactly("foo/my_skylark_rule_lib.jar"); + assertThat( + prettyJarNames( + javaCompilationArgsProvider.getJavaCompilationArgs().getCompileTimeJars())) + .containsExactly("foo/my_skylark_rule_lib.jar"); + + assertThat( + prettyJarNames( + javaCompilationArgsProvider.getRecursiveJavaCompilationArgs().getRuntimeJars())) + .containsExactly("foo/my_skylark_rule_lib.jar", "foo/libmy_java_lib_direct.jar"); + assertThat( + prettyJarNames( + javaCompilationArgsProvider + .getRecursiveJavaCompilationArgs() + .getFullCompileTimeJars())) + .containsExactly("foo/my_skylark_rule_lib.jar", "foo/libmy_java_lib_direct.jar"); + assertThat( + prettyJarNames( + javaCompilationArgsProvider.getRecursiveJavaCompilationArgs().getCompileTimeJars())) + .containsExactly("foo/my_skylark_rule_lib.jar", "foo/libmy_java_lib_direct-hjar.jar"); + } + + @Test + public void javaInfoBuildHelperCreateJavaInfoWithRunTimeDeps() throws Exception { + scratch.file( + "foo/extension.bzl", + "result = provider()", + "def _impl(ctx):", + " dp = [dep[java_common.provider] for dep in ctx.attr.dep]", + " javaInfo = JavaInfo(", + " output_jar = ctx.file.output_jar,", + " use_ijar = False,", + " runtime_deps = dp", + " )", + " return [result(property = javaInfo)]", + "my_rule = rule(", + " implementation = _impl,", + " attrs = {", + " 'dep' : attr.label_list(), ", + " 'output_jar' : attr.label(allow_single_file=True), ", + " }", + ")"); + + 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',", + " dep = [':my_java_lib_direct']", + ")"); + assertNoEvents(); + + JavaCompilationArgsProvider javaCompilationArgsProvider = + fetchJavaInfo().getProvider(JavaCompilationArgsProvider.class); + + assertThat( + prettyJarNames(javaCompilationArgsProvider.getJavaCompilationArgs().getRuntimeJars())) + .containsExactly("foo/my_skylark_rule_lib.jar"); + assertThat( + prettyJarNames( + javaCompilationArgsProvider.getJavaCompilationArgs().getFullCompileTimeJars())) + .containsExactly("foo/my_skylark_rule_lib.jar"); + assertThat( + prettyJarNames( + javaCompilationArgsProvider.getJavaCompilationArgs().getCompileTimeJars())) + .containsExactly("foo/my_skylark_rule_lib.jar"); + + assertThat( + prettyJarNames( + javaCompilationArgsProvider.getRecursiveJavaCompilationArgs().getRuntimeJars())) + .containsExactly("foo/my_skylark_rule_lib.jar", "foo/libmy_java_lib_direct.jar"); + assertThat( + prettyJarNames( + javaCompilationArgsProvider + .getRecursiveJavaCompilationArgs() + .getFullCompileTimeJars())) + .containsExactly("foo/my_skylark_rule_lib.jar"); + assertThat( + prettyJarNames( + javaCompilationArgsProvider.getRecursiveJavaCompilationArgs().getCompileTimeJars())) + .containsExactly("foo/my_skylark_rule_lib.jar"); + } + + @Test + public void javaInfoBuildHelperCreateJavaInfoWithDepsAndNeverLink() throws Exception { + scratch.file( + "foo/extension.bzl", + "result = provider()", + "def _impl(ctx):", + " dp = [dep[java_common.provider] for dep in ctx.attr.dep]", + " javaInfo = JavaInfo(", + " output_jar = ctx.file.output_jar, ", + " use_ijar = False,", + " deps = dp,", + " neverlink = True", + " )", + " return [result(property = javaInfo)]", + "my_rule = rule(", + " implementation = _impl,", + " attrs = {", + " 'dep' : attr.label_list(), ", + " 'output_jar' : attr.label(allow_single_file=True), ", + " }", + ")"); + + 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',", + " dep = [':my_java_lib_direct']", + ")"); + assertNoEvents(); + + JavaCompilationArgsProvider javaCompilationArgsProvider = + fetchJavaInfo().getProvider(JavaCompilationArgsProvider.class); + + assertThat( + prettyJarNames(javaCompilationArgsProvider.getJavaCompilationArgs().getRuntimeJars())) + .isEmpty(); + assertThat( + prettyJarNames( + javaCompilationArgsProvider.getJavaCompilationArgs().getFullCompileTimeJars())) + .containsExactly("foo/my_skylark_rule_lib.jar"); + assertThat( + prettyJarNames( + javaCompilationArgsProvider.getJavaCompilationArgs().getCompileTimeJars())) + .containsExactly("foo/my_skylark_rule_lib.jar"); + + assertThat( + prettyJarNames( + javaCompilationArgsProvider.getRecursiveJavaCompilationArgs().getRuntimeJars())) + .isEmpty(); + assertThat( + prettyJarNames( + javaCompilationArgsProvider + .getRecursiveJavaCompilationArgs() + .getFullCompileTimeJars())) + .containsExactly("foo/my_skylark_rule_lib.jar", "foo/libmy_java_lib_direct.jar"); + assertThat( + prettyJarNames( + javaCompilationArgsProvider.getRecursiveJavaCompilationArgs().getCompileTimeJars())) + .containsExactly("foo/my_skylark_rule_lib.jar", "foo/libmy_java_lib_direct-hjar.jar"); + } + + private JavaInfo fetchJavaInfo() throws LabelSyntaxException { + ConfiguredTarget myRuleTarget = getConfiguredTarget("//foo:my_skylark_rule"); + Info info = + myRuleTarget.get(new SkylarkKey(Label.parseAbsolute("//foo:extension.bzl"), "result")); + + @SuppressWarnings("unchecked") + JavaInfo javaInfo = (JavaInfo) info.getValue("property"); + return javaInfo; + } private void writeBuildFileForJavaToolchain() throws Exception { scratch.file("java/com/google/test/turbine_canary_deploy.jar"); scratch.file("java/com/google/test/tzdata.jar"); diff --git a/src/test/shell/bazel/bazel_java_test.sh b/src/test/shell/bazel/bazel_java_test.sh index e19426d36c..d425411da2 100755 --- a/src/test/shell/bazel/bazel_java_test.sh +++ b/src/test/shell/bazel/bazel_java_test.sh @@ -1323,6 +1323,7 @@ EOF expect_log "liba.jar" } + function test_java_common_create_provider_with_ijar_unset_actions() { mkdir -p java/com/google/foo touch java/com/google/foo/{BUILD,A.java,my_rule.bzl} @@ -1355,9 +1356,45 @@ my_rule = rule( EOF bazel build java/com/google/foo:banana >& "$TEST_log" && fail "Unexpected success" - expect_log "In java_common.create_provider the value of use_ijar is True. Make sure the first argument of the function is the ctx.actions object." + expect_log "The value of use_ijar is True. Make sure the ctx.actions argument is valid." +} + + +function test_java_info_constructor_with_ijar_unset_actions() { + mkdir -p java/com/google/foo + touch java/com/google/foo/{BUILD,my_rule.bzl} + cat > java/com/google/foo/BUILD << EOF +load(":my_rule.bzl", "my_rule") +my_rule( + name = 'my_skylark_rule', + output_jar = 'my_skylark_rule_lib.jar' + ) +EOF + + cat > java/com/google/foo/my_rule.bzl << EOF +result = provider() +def _impl(ctx): + javaInfo = JavaInfo( + output_jar = ctx.file.output_jar, + use_ijar = True, + java_toolchain = ctx.attr._java_toolchain + ) + return [result(property = javaInfo)] + +my_rule = rule( + implementation = _impl, + attrs = { + 'output_jar' : attr.label(allow_single_file=True), + "_java_toolchain": attr.label(default = Label("//tools/jdk:toolchain")) + } +) +EOF + + bazel build java/com/google/foo:my_skylark_rule >& "$TEST_log" && fail "Unexpected success" + expect_log "The value of use_ijar is True. Make sure the ctx.actions argument is valid." } + function test_java_common_create_provider_with_ijar_unset_java_toolchain() { mkdir -p java/com/google/foo touch java/com/google/foo/{BUILD,A.java,my_rule.bzl} @@ -1390,9 +1427,44 @@ my_rule = rule( EOF bazel build java/com/google/foo:banana >& "$TEST_log" && fail "Unexpected success" - expect_log "In java_common.create_provider the value of use_ijar is True. Make sure the java_toolchain argument is a valid java_toolchain Target." + expect_log "The value of use_ijar is True. Make sure the java_toolchain argument is a valid." } + +function test_java_info_constructor_with_ijar_unset_java_toolchain() { + mkdir -p java/com/google/foo + touch java/com/google/foo/{BUILD,my_rule.bzl} + cat > java/com/google/foo/BUILD << EOF +load(":my_rule.bzl", "my_rule") +my_rule( + name = 'my_skylark_rule', + output_jar = 'my_skylark_rule_lib.jar' + ) +EOF + + cat > java/com/google/foo/my_rule.bzl << EOF +result = provider() +def _impl(ctx): + javaInfo = JavaInfo( + output_jar = ctx.file.output_jar, + use_ijar = True, + actions = ctx.actions + ) + return [result(property = javaInfo)] + +my_rule = rule( + implementation = _impl, + attrs = { + 'output_jar' : attr.label(allow_single_file=True) + } +) +EOF + + bazel build java/com/google/foo:my_skylark_rule >& "$TEST_log" && fail "Unexpected success" + expect_log "The value of use_ijar is True. Make sure the java_toolchain argument is a valid." +} + + function test_java_test_timeout() { setup_javatest_support mkdir -p javatests/com/google/timeout -- cgit v1.2.3