From bdcf7ce2ac8e83e2e9569821eb5c9651c45b134a Mon Sep 17 00:00:00 2001 From: Googler Date: Wed, 8 Nov 2023 22:45:57 -0800 Subject: [PATCH] Support Starlark fragments in subrules Unlike attributes or toolchains, there is fortunately no need to lift these to the rule/aspect class, since these can be looked up directly on the configuration, without any extra Skyframe evaluation. PiperOrigin-RevId: 580786808 Change-Id: Ic3e414b9498b3d9b5b757ade3b5007e4e69260ae --- .../analysis/config/FragmentCollection.java | 13 -- .../starlark/StarlarkRuleClassFunctions.java | 5 +- .../analysis/starlark/StarlarkSubrule.java | 63 +++++++- .../FragmentCollectionApi.java | 17 +- .../StarlarkRuleFunctionsApi.java | 12 +- .../FakeStarlarkRuleFunctionsApi.java | 1 + .../google/devtools/build/lib/analysis/BUILD | 1 + .../starlark/StarlarkSubruleTest.java | 153 ++++++++++++++++++ 8 files changed, 247 insertions(+), 18 deletions(-) diff --git a/src/main/java/com/google/devtools/build/lib/analysis/config/FragmentCollection.java b/src/main/java/com/google/devtools/build/lib/analysis/config/FragmentCollection.java index 4c2d13ef4af00d..a99110232c0eb7 100644 --- a/src/main/java/com/google/devtools/build/lib/analysis/config/FragmentCollection.java +++ b/src/main/java/com/google/devtools/build/lib/analysis/config/FragmentCollection.java @@ -13,7 +13,6 @@ // limitations under the License. package com.google.devtools.build.lib.analysis.config; -import com.google.common.base.Joiner; import com.google.common.collect.ImmutableCollection; import com.google.devtools.build.lib.analysis.RuleContext; import com.google.devtools.build.lib.concurrent.ThreadSafety.Immutable; @@ -47,18 +46,6 @@ public ImmutableCollection getFieldNames() { return ruleContext.getStarlarkFragmentNames(); } - @Override - @Nullable - public String getErrorMessageForUnknownField(String name) { - return String.format( - "There is no configuration fragment named '%s'. Available fragments: %s", - name, fieldsToString()); - } - - private String fieldsToString() { - return String.format("'%s'", Joiner.on("', '").join(getFieldNames())); - } - @Override public String toString() { return "[ " + fieldsToString() + "]"; diff --git a/src/main/java/com/google/devtools/build/lib/analysis/starlark/StarlarkRuleClassFunctions.java b/src/main/java/com/google/devtools/build/lib/analysis/starlark/StarlarkRuleClassFunctions.java index 60e4acead8d247..62e79f05de39da 100644 --- a/src/main/java/com/google/devtools/build/lib/analysis/starlark/StarlarkRuleClassFunctions.java +++ b/src/main/java/com/google/devtools/build/lib/analysis/starlark/StarlarkRuleClassFunctions.java @@ -1256,6 +1256,7 @@ public StarlarkSubruleApi subrule( StarlarkFunction implementation, Dict attrsUnchecked, Sequence toolchainsUnchecked, + Sequence fragmentsUnchecked, StarlarkThread thread) throws EvalException { if (!thread.getSemantics().getBool(BuildLanguageOptions.EXPERIMENTAL_RULE_EXTENSION_API)) { @@ -1263,6 +1264,8 @@ public StarlarkSubruleApi subrule( } ImmutableMap attrs = ImmutableMap.copyOf(Dict.cast(attrsUnchecked, String.class, Descriptor.class, "attrs")); + ImmutableList fragments = + Sequence.noneableCast(fragmentsUnchecked, String.class, "fragments").getImmutableList(); for (Entry attr : attrs.entrySet()) { String attrName = attr.getKey(); Descriptor descriptor = attr.getValue(); @@ -1296,7 +1299,7 @@ public StarlarkSubruleApi subrule( if (toolchains.size() > 1) { throw Starlark.errorf("subrules may require at most 1 toolchain, got: %s", toolchains); } - return new StarlarkSubrule(implementation, attrs, toolchains); + return new StarlarkSubrule(implementation, attrs, toolchains, ImmutableSet.copyOf(fragments)); } private static ImmutableSet parseToolchainTypes( diff --git a/src/main/java/com/google/devtools/build/lib/analysis/starlark/StarlarkSubrule.java b/src/main/java/com/google/devtools/build/lib/analysis/starlark/StarlarkSubrule.java index fda5f4f5f15ba1..3a47a007bdd0ae 100644 --- a/src/main/java/com/google/devtools/build/lib/analysis/starlark/StarlarkSubrule.java +++ b/src/main/java/com/google/devtools/build/lib/analysis/starlark/StarlarkSubrule.java @@ -19,6 +19,7 @@ import com.google.common.annotations.VisibleForTesting; import com.google.common.base.Preconditions; +import com.google.common.collect.ImmutableCollection; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableSet; @@ -29,6 +30,7 @@ import com.google.devtools.build.lib.analysis.BazelRuleAnalysisThreadContext; import com.google.devtools.build.lib.analysis.FilesToRunProvider; import com.google.devtools.build.lib.analysis.RuleContext; +import com.google.devtools.build.lib.analysis.config.Fragment; import com.google.devtools.build.lib.analysis.config.ToolchainTypeRequirement; import com.google.devtools.build.lib.analysis.starlark.StarlarkActionFactory.StarlarkActionContext; import com.google.devtools.build.lib.analysis.starlark.StarlarkAttrModule.Descriptor; @@ -39,6 +41,7 @@ import com.google.devtools.build.lib.packages.AttributeValueSource; import com.google.devtools.build.lib.packages.BuildType; import com.google.devtools.build.lib.packages.StarlarkExportable; +import com.google.devtools.build.lib.starlarkbuildapi.FragmentCollectionApi; import com.google.devtools.build.lib.starlarkbuildapi.StarlarkActionFactoryApi; import com.google.devtools.build.lib.starlarkbuildapi.StarlarkSubruleApi; import com.google.devtools.build.lib.starlarkbuildapi.platform.ToolchainContextApi; @@ -71,6 +74,7 @@ public class StarlarkSubrule implements StarlarkExportable, StarlarkCallable, St private final StarlarkFunction implementation; private final ImmutableSet toolchains; + private final ImmutableSet fragments; // following fields are set on export @Nullable private String exportedName = null; @@ -79,10 +83,12 @@ public class StarlarkSubrule implements StarlarkExportable, StarlarkCallable, St public StarlarkSubrule( StarlarkFunction implementation, ImmutableMap attributes, - ImmutableSet toolchains) { + ImmutableSet toolchains, + ImmutableSet fragments) { this.implementation = implementation; this.attributes = SubruleAttribute.from(attributes); this.toolchains = toolchains; + this.fragments = fragments; } @Override @@ -154,7 +160,7 @@ public Object call(StarlarkThread thread, Tuple args, Dict kwarg namedArgs.put(attr.attrName, value == null ? Starlark.NONE : value); } SubruleContext subruleContext = - new SubruleContext(ruleContext, toolchains, runfilesFromDeps.build()); + new SubruleContext(this, ruleContext, toolchains, runfilesFromDeps.build()); ImmutableList positionals = ImmutableList.builder().add(subruleContext).addAll(args).build(); try { @@ -269,15 +275,19 @@ static ImmutableSet discoverToolchains( private static class SubruleContext implements StarlarkActionContext { // these fields are effectively final, set to null once this instance is no longer usable by // Starlark + private StarlarkSubrule subrule; private StarlarkRuleContext starlarkRuleContext; private ImmutableSet