From a27a5aa83696200e22a459950081eb443e01e427 Mon Sep 17 00:00:00 2001 From: Liam Miller-Cushon Date: Mon, 16 Jan 2017 23:06:11 +0000 Subject: Initial implementation of java_runtime and java_runtime_suite These rules can be used to configure JDKs, as an alternative to the filegroups and filegroups-of-filegroups used currently. -- PiperOrigin-RevId: 144655277 MOS_MIGRATED_REVID=144655277 --- src/main/java/com/google/devtools/build/lib/BUILD | 5 + .../lib/bazel/rules/BazelRuleClassProvider.java | 4 + .../devtools/build/lib/rules/java/JavaRuntime.java | 47 +++++ .../build/lib/rules/java/JavaRuntimeProvider.java | 34 +++ .../build/lib/rules/java/JavaRuntimeRule.java | 71 +++++++ .../build/lib/rules/java/JavaRuntimeSuite.java | 46 +++++ .../build/lib/rules/java/JavaRuntimeSuiteRule.java | 80 ++++++++ .../lib/rules/java/JvmConfigurationLoader.java | 228 ++++++++++++++------- 8 files changed, 436 insertions(+), 79 deletions(-) create mode 100644 src/main/java/com/google/devtools/build/lib/rules/java/JavaRuntime.java create mode 100644 src/main/java/com/google/devtools/build/lib/rules/java/JavaRuntimeProvider.java create mode 100644 src/main/java/com/google/devtools/build/lib/rules/java/JavaRuntimeRule.java create mode 100644 src/main/java/com/google/devtools/build/lib/rules/java/JavaRuntimeSuite.java create mode 100644 src/main/java/com/google/devtools/build/lib/rules/java/JavaRuntimeSuiteRule.java diff --git a/src/main/java/com/google/devtools/build/lib/BUILD b/src/main/java/com/google/devtools/build/lib/BUILD index 9f9708107d..b174fd42f3 100644 --- a/src/main/java/com/google/devtools/build/lib/BUILD +++ b/src/main/java/com/google/devtools/build/lib/BUILD @@ -753,8 +753,12 @@ java_library( "rules/java/JavaPlugin.java", "rules/java/JavaPrimaryClassProvider.java", "rules/java/JavaProvider.java", + "rules/java/JavaRuntime.java", "rules/java/JavaRuntimeClasspathProvider.java", "rules/java/JavaRuntimeJarProvider.java", + "rules/java/JavaRuntimeRule.java", + "rules/java/JavaRuntimeSuite.java", + "rules/java/JavaRuntimeSuiteRule.java", "rules/java/JavaSkylarkCommon.java", "rules/java/JavaSourceInfoProvider.java", "rules/java/JavaToolchain.java", @@ -842,6 +846,7 @@ java_library( "rules/java/JavaPluginInfoProvider.java", "rules/java/JavaRuleOutputJarsProvider.java", "rules/java/JavaRunfilesProvider.java", + "rules/java/JavaRuntimeProvider.java", "rules/java/JavaSemantics.java", "rules/java/JavaSkylarkApiProvider.java", "rules/java/JavaSourceJarsProvider.java", diff --git a/src/main/java/com/google/devtools/build/lib/bazel/rules/BazelRuleClassProvider.java b/src/main/java/com/google/devtools/build/lib/bazel/rules/BazelRuleClassProvider.java index 362fd2709b..87dc0d5504 100644 --- a/src/main/java/com/google/devtools/build/lib/bazel/rules/BazelRuleClassProvider.java +++ b/src/main/java/com/google/devtools/build/lib/bazel/rules/BazelRuleClassProvider.java @@ -116,6 +116,8 @@ import com.google.devtools.build.lib.rules.genquery.GenQueryRule; import com.google.devtools.build.lib.rules.java.JavaConfigurationLoader; import com.google.devtools.build.lib.rules.java.JavaImportBaseRule; import com.google.devtools.build.lib.rules.java.JavaOptions; +import com.google.devtools.build.lib.rules.java.JavaRuntimeRule; +import com.google.devtools.build.lib.rules.java.JavaRuntimeSuiteRule; import com.google.devtools.build.lib.rules.java.JavaSkylarkCommon; import com.google.devtools.build.lib.rules.java.JavaToolchainRule; import com.google.devtools.build.lib.rules.java.JvmConfigurationLoader; @@ -484,6 +486,8 @@ public class BazelRuleClassProvider { builder.addRuleDefinition(new BazelJavaTestRule()); builder.addRuleDefinition(new BazelJavaPluginRule()); builder.addRuleDefinition(new JavaToolchainRule()); + builder.addRuleDefinition(new JavaRuntimeRule()); + builder.addRuleDefinition(new JavaRuntimeSuiteRule()); builder.addRuleDefinition(new ExtraActionRule()); builder.addRuleDefinition(new ActionListenerRule()); diff --git a/src/main/java/com/google/devtools/build/lib/rules/java/JavaRuntime.java b/src/main/java/com/google/devtools/build/lib/rules/java/JavaRuntime.java new file mode 100644 index 0000000000..e8ff3a8105 --- /dev/null +++ b/src/main/java/com/google/devtools/build/lib/rules/java/JavaRuntime.java @@ -0,0 +1,47 @@ +// Copyright 2017 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 com.google.devtools.build.lib.actions.Actions; +import com.google.devtools.build.lib.actions.Artifact; +import com.google.devtools.build.lib.analysis.CompilationHelper; +import com.google.devtools.build.lib.analysis.ConfiguredTarget; +import com.google.devtools.build.lib.analysis.MiddlemanProvider; +import com.google.devtools.build.lib.analysis.PrerequisiteArtifacts; +import com.google.devtools.build.lib.analysis.RuleConfiguredTarget.Mode; +import com.google.devtools.build.lib.analysis.RuleConfiguredTargetBuilder; +import com.google.devtools.build.lib.analysis.RuleContext; +import com.google.devtools.build.lib.analysis.RunfilesProvider; +import com.google.devtools.build.lib.collect.nestedset.NestedSet; +import com.google.devtools.build.lib.rules.RuleConfiguredTargetFactory; + +/** Implementation for the {@code java_runtime} rule. */ +public class JavaRuntime implements RuleConfiguredTargetFactory { + @Override + public ConfiguredTarget create(RuleContext ruleContext) + throws InterruptedException, RuleErrorException { + NestedSet filesToBuild = + PrerequisiteArtifacts.nestedSet(ruleContext, "srcs", Mode.TARGET); + NestedSet middleman = + CompilationHelper.getAggregatingMiddleman( + ruleContext, Actions.escapeLabel(ruleContext.getLabel()), filesToBuild); + return new RuleConfiguredTargetBuilder(ruleContext) + .addProvider(RunfilesProvider.class, RunfilesProvider.EMPTY) + .setFilesToBuild(filesToBuild) + .addProvider(JavaRuntimeProvider.class, JavaRuntimeProvider.create(filesToBuild)) + .addProvider(MiddlemanProvider.class, new MiddlemanProvider(middleman)) + .build(); + } +} diff --git a/src/main/java/com/google/devtools/build/lib/rules/java/JavaRuntimeProvider.java b/src/main/java/com/google/devtools/build/lib/rules/java/JavaRuntimeProvider.java new file mode 100644 index 0000000000..7ecd58c35e --- /dev/null +++ b/src/main/java/com/google/devtools/build/lib/rules/java/JavaRuntimeProvider.java @@ -0,0 +1,34 @@ +// Copyright 2017 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 com.google.auto.value.AutoValue; +import com.google.devtools.build.lib.actions.Artifact; +import com.google.devtools.build.lib.analysis.TransitiveInfoProvider; +import com.google.devtools.build.lib.collect.nestedset.NestedSet; +import com.google.devtools.build.lib.concurrent.ThreadSafety.Immutable; + +/** Information about the Java runtime used by the java_* rules. */ +@AutoValue +@Immutable +public abstract class JavaRuntimeProvider implements TransitiveInfoProvider { + + public static JavaRuntimeProvider create(NestedSet javaBaseInputs) { + return new AutoValue_JavaRuntimeProvider(javaBaseInputs); + } + + /** All input artifacts in the javabase. */ + public abstract NestedSet javaBaseInputs(); +} diff --git a/src/main/java/com/google/devtools/build/lib/rules/java/JavaRuntimeRule.java b/src/main/java/com/google/devtools/build/lib/rules/java/JavaRuntimeRule.java new file mode 100644 index 0000000000..ef526863f8 --- /dev/null +++ b/src/main/java/com/google/devtools/build/lib/rules/java/JavaRuntimeRule.java @@ -0,0 +1,71 @@ +// Copyright 2017 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.packages.Attribute.attr; +import static com.google.devtools.build.lib.packages.BuildType.LABEL_LIST; +import static com.google.devtools.build.lib.packages.BuildType.LICENSE; +import static com.google.devtools.build.lib.syntax.Type.STRING; + +import com.google.devtools.build.lib.analysis.BaseRuleClasses; +import com.google.devtools.build.lib.analysis.RuleDefinition; +import com.google.devtools.build.lib.analysis.RuleDefinitionEnvironment; +import com.google.devtools.build.lib.packages.RuleClass; +import com.google.devtools.build.lib.packages.RuleClass.Builder; +import com.google.devtools.build.lib.util.FileTypeSet; + +/** Rule definition for {@code java_runtime} */ +public final class JavaRuntimeRule implements RuleDefinition { + @Override + public RuleClass build(Builder builder, RuleDefinitionEnvironment env) { + return builder + /* + All files in the runtime. + */ + .add(attr("srcs", LABEL_LIST).allowedFileTypes(FileTypeSet.ANY_FILE).mandatory()) + /* + The relative path to the root of the runtime. + */ + .add(attr("java_home", STRING)) + .add(attr("output_licenses", LICENSE)) + .build(); + } + + @Override + public Metadata getMetadata() { + return RuleDefinition.Metadata.builder() + .name("java_runtime") + .ancestors(BaseRuleClasses.BaseRule.class) + .factoryClass(JavaRuntime.class) + .build(); + } +} +/* + +

+Specifies the configuration for a Java runtime. +

+ +

Example:

+ +
+java_runtime(
+    name = "jdk-9-ea+153",
+    srcs = glob(["jdk9-ea+153/**"]),
+    java_home = "jdk9-ea+153",
+)
+
+ +*/ diff --git a/src/main/java/com/google/devtools/build/lib/rules/java/JavaRuntimeSuite.java b/src/main/java/com/google/devtools/build/lib/rules/java/JavaRuntimeSuite.java new file mode 100644 index 0000000000..2a42e5e560 --- /dev/null +++ b/src/main/java/com/google/devtools/build/lib/rules/java/JavaRuntimeSuite.java @@ -0,0 +1,46 @@ +// Copyright 2017 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 com.google.devtools.build.lib.analysis.ConfiguredTarget; +import com.google.devtools.build.lib.analysis.FileProvider; +import com.google.devtools.build.lib.analysis.RuleConfiguredTarget.Mode; +import com.google.devtools.build.lib.analysis.RuleConfiguredTargetBuilder; +import com.google.devtools.build.lib.analysis.RuleContext; +import com.google.devtools.build.lib.analysis.RunfilesProvider; +import com.google.devtools.build.lib.analysis.TransitiveInfoCollection; +import com.google.devtools.build.lib.rules.RuleConfiguredTargetFactory; + +/** Implementation for the {@code java_runtime_suite} rule. */ +public class JavaRuntimeSuite implements RuleConfiguredTargetFactory { + @Override + public ConfiguredTarget create(RuleContext ruleContext) + throws InterruptedException, RuleErrorException { + TransitiveInfoCollection runtime = + ruleContext.getPrerequisiteMap("runtimes").get(ruleContext.getConfiguration().getCpu()); + if (runtime == null) { + runtime = ruleContext.getPrerequisite("default", Mode.TARGET); + } + if (runtime == null) { + ruleContext.throwWithRuleError( + "could not resolve runtime for cpu " + ruleContext.getConfiguration().getCpu()); + } + return new RuleConfiguredTargetBuilder(ruleContext) + .addProvider(JavaRuntimeProvider.class, runtime.getProvider(JavaRuntimeProvider.class)) + .addProvider(RunfilesProvider.class, runtime.getProvider(RunfilesProvider.class)) + .setFilesToBuild(runtime.getProvider(FileProvider.class).getFilesToBuild()) + .build(); + } +} diff --git a/src/main/java/com/google/devtools/build/lib/rules/java/JavaRuntimeSuiteRule.java b/src/main/java/com/google/devtools/build/lib/rules/java/JavaRuntimeSuiteRule.java new file mode 100644 index 0000000000..63aa2683ed --- /dev/null +++ b/src/main/java/com/google/devtools/build/lib/rules/java/JavaRuntimeSuiteRule.java @@ -0,0 +1,80 @@ +// Copyright 2017 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.packages.Attribute.attr; +import static com.google.devtools.build.lib.packages.BuildType.LICENSE; + +import com.google.common.collect.ImmutableList; +import com.google.devtools.build.lib.analysis.BaseRuleClasses; +import com.google.devtools.build.lib.analysis.RuleDefinition; +import com.google.devtools.build.lib.analysis.RuleDefinitionEnvironment; +import com.google.devtools.build.lib.analysis.TransitiveInfoProvider; +import com.google.devtools.build.lib.packages.BuildType; +import com.google.devtools.build.lib.packages.RuleClass; +import com.google.devtools.build.lib.packages.RuleClass.Builder; +import com.google.devtools.build.lib.util.FileTypeSet; + +/** Rule definition for {@code java_runtime_suite} */ +public final class JavaRuntimeSuiteRule implements RuleDefinition { + @Override + public RuleClass build(Builder builder, RuleDefinitionEnvironment env) { + return builder + /* + A map from each supported architecture to the corresponding java_runtime. + */ + .add(attr("runtimes", BuildType.LABEL_DICT_UNARY)) + /* + A map from each supported architecture to the corresponding java_runtime. + */ + .add( + attr("default", BuildType.LABEL) + .mandatoryNativeProviders( + ImmutableList.>of( + JavaRuntimeProvider.class)) + .allowedFileTypes(FileTypeSet.NO_FILE)) + .add(attr("output_licenses", LICENSE)) + .build(); + } + + @Override + public Metadata getMetadata() { + return RuleDefinition.Metadata.builder() + .name("java_runtime_suite") + .ancestors(BaseRuleClasses.BaseRule.class) + .factoryClass(JavaRuntimeSuite.class) + .build(); + } +} +/* + +

+Specifies the configuration for the Java runtimes for each architecture. +

+ +

Example:

+ +
+java_runtime_suite(
+   name = "jdk9",
+   runtimes = {
+     "k8": ":jdk9-k8",
+     "ppc": ":jdk9-ppc",
+     "arm": ":jdk9-arm",
+   },
+)
+
+ +*/ diff --git a/src/main/java/com/google/devtools/build/lib/rules/java/JvmConfigurationLoader.java b/src/main/java/com/google/devtools/build/lib/rules/java/JvmConfigurationLoader.java index 942d2abca3..a8fb7aaad4 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/java/JvmConfigurationLoader.java +++ b/src/main/java/com/google/devtools/build/lib/rules/java/JvmConfigurationLoader.java @@ -29,23 +29,30 @@ import com.google.devtools.build.lib.events.Event; import com.google.devtools.build.lib.packages.BuildType; import com.google.devtools.build.lib.packages.NoSuchPackageException; import com.google.devtools.build.lib.packages.NoSuchTargetException; +import com.google.devtools.build.lib.packages.NoSuchThingException; import com.google.devtools.build.lib.packages.RawAttributeMapper; import com.google.devtools.build.lib.packages.Rule; import com.google.devtools.build.lib.packages.Target; import com.google.devtools.build.lib.syntax.Type; import com.google.devtools.build.lib.vfs.PathFragment; import java.util.List; +import java.util.Map; import javax.annotation.Nullable; /** * A provider to load jvm configurations from the package path. * - *

If the given {@code javaHome} is a label, i.e. starts with {@code "//"}, - * then the loader will look at the target it refers to. If the target is a - * filegroup, then the loader will look in it's srcs for a filegroup that ends - * with {@code -}. It will use that filegroup to construct the actual - * {@link Jvm} instance, using the filegroups {@code path} attribute to - * construct the new {@code javaHome} path. + *

If the given {@code javaHome} is a label, i.e. starts with {@code "//"}, then the loader will + * look at the target it refers to. + * + *

    + *
  • If the target is a {@code java_runtime_suite}, the loader will select the runtime from the + * entry in {@code java_runtime_suite.runtimes} for {@code cpu}. + *
  • If the target is a filegroup, then the loader will look in it's srcs for a filegroup that + * ends with {@code -}. It will use that filegroup to construct the actual {@link Jvm} + * instance, using the filegroups {@code path} attribute to construct the new {@code javaHome} + * path. + *
* *

The loader also supports legacy mode, where the JVM can be defined with an abolute path. */ @@ -90,88 +97,151 @@ public final class JvmConfigurationLoader implements ConfigurationFragmentFactor return null; } Target javaHomeTarget = lookup.getTarget(label); - if ((javaHomeTarget instanceof Rule) && - "filegroup".equals(((Rule) javaHomeTarget).getRuleClass())) { - RawAttributeMapper javaHomeAttributes = RawAttributeMapper.of((Rule) javaHomeTarget); - if (javaHomeAttributes.isConfigurable("srcs", BuildType.LABEL_LIST)) { - throw new InvalidConfigurationException("\"srcs\" in " + javaHome - + " is configurable. JAVABASE targets don't support configurable attributes"); - } - List