Add Starlark mechanism for default_copts and defaults_hdrs_check
We add a new native computed default class which can only be seen from builtins. This ensures that not only are we able to get the value of default_copts and default_hdrs_check as set in the package() rule, but that when the values in package() changes, the dependency server is able to compute the affected targets properly.
This is not a long term mechanism and should be replaced by something more generic as described in b/200065655#comment3
This CL also adds two additional methods to CcStarlarkInternal, init_make_variables and create_linkstamp.
RELNOTES:none
PiperOrigin-RevId: 415258162
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/AspectAwareAttributeMapper.java b/src/main/java/com/google/devtools/build/lib/analysis/AspectAwareAttributeMapper.java
index c2c5041..6e5e797 100644
--- a/src/main/java/com/google/devtools/build/lib/analysis/AspectAwareAttributeMapper.java
+++ b/src/main/java/com/google/devtools/build/lib/analysis/AspectAwareAttributeMapper.java
@@ -148,6 +148,11 @@
}
@Override
+ public boolean isPackageDefaultHdrsCheckSet() {
+ return ruleAttributes.isPackageDefaultHdrsCheckSet();
+ }
+
+ @Override
public Boolean getPackageDefaultTestOnly() {
return ruleAttributes.getPackageDefaultTestOnly();
}
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/starlark/StarlarkAttrModule.java b/src/main/java/com/google/devtools/build/lib/analysis/starlark/StarlarkAttrModule.java
index 6c2d9cd..b0270b5 100644
--- a/src/main/java/com/google/devtools/build/lib/analysis/starlark/StarlarkAttrModule.java
+++ b/src/main/java/com/google/devtools/build/lib/analysis/starlark/StarlarkAttrModule.java
@@ -41,6 +41,7 @@
import com.google.devtools.build.lib.packages.Type;
import com.google.devtools.build.lib.packages.Type.ConversionException;
import com.google.devtools.build.lib.packages.Type.LabelClass;
+import com.google.devtools.build.lib.starlarkbuildapi.NativeComputedDefaultApi;
import com.google.devtools.build.lib.starlarkbuildapi.StarlarkAttrModuleApi;
import com.google.devtools.build.lib.util.FileType;
import com.google.devtools.build.lib.util.FileTypeSet;
@@ -136,6 +137,11 @@
new StarlarkComputedDefaultTemplate(type, callback.getParameterNames(), callback));
} else if (defaultValue instanceof StarlarkLateBoundDefault) {
builder.value((StarlarkLateBoundDefault) defaultValue); // unchecked cast
+ } else if (defaultValue instanceof NativeComputedDefaultApi) {
+ // TODO(b/200065655#comment3): This hack exists until default_copts and default_hdrs_check
+ // in package() is replaced by proper package defaults. We don't check the particular
+ // instance to avoid adding a dependency to the C++ package.
+ builder.value((NativeComputedDefaultApi) defaultValue);
} else {
BazelModuleContext moduleContext =
BazelModuleContext.of(Module.ofInnermostEnclosingStarlarkFunction(thread));
@@ -420,11 +426,7 @@
@Override
public Descriptor stringAttribute(
- String defaultValue,
- String doc,
- Boolean mandatory,
- Sequence<?> values,
- StarlarkThread thread)
+ Object defaultValue, String doc, Boolean mandatory, Sequence<?> values, StarlarkThread thread)
throws EvalException {
BazelStarlarkContext.from(thread).checkLoadingOrWorkspacePhase("attr.string");
return createAttrDescriptor(
@@ -497,11 +499,7 @@
@Override
public Descriptor stringListAttribute(
- Boolean mandatory,
- Boolean allowEmpty,
- Sequence<?> defaultValue,
- String doc,
- StarlarkThread thread)
+ Boolean mandatory, Boolean allowEmpty, Object defaultValue, String doc, StarlarkThread thread)
throws EvalException {
BazelStarlarkContext.from(thread).checkLoadingOrWorkspacePhase("attr.string_list");
return createAttrDescriptor(
diff --git a/src/main/java/com/google/devtools/build/lib/packages/AbstractAttributeMapper.java b/src/main/java/com/google/devtools/build/lib/packages/AbstractAttributeMapper.java
index 60a28ec..4c34b48 100644
--- a/src/main/java/com/google/devtools/build/lib/packages/AbstractAttributeMapper.java
+++ b/src/main/java/com/google/devtools/build/lib/packages/AbstractAttributeMapper.java
@@ -148,6 +148,11 @@
}
@Override
+ public boolean isPackageDefaultHdrsCheckSet() {
+ return rule.getPackage().isDefaultHdrsCheckSet();
+ }
+
+ @Override
public Boolean getPackageDefaultTestOnly() {
return rule.getPackage().getDefaultTestOnly();
}
diff --git a/src/main/java/com/google/devtools/build/lib/packages/Attribute.java b/src/main/java/com/google/devtools/build/lib/packages/Attribute.java
index 5b673e8..558ab43 100644
--- a/src/main/java/com/google/devtools/build/lib/packages/Attribute.java
+++ b/src/main/java/com/google/devtools/build/lib/packages/Attribute.java
@@ -41,6 +41,7 @@
import com.google.devtools.build.lib.packages.Type.LabelClass;
import com.google.devtools.build.lib.skyframe.serialization.autocodec.AutoCodec;
import com.google.devtools.build.lib.skyframe.serialization.autocodec.SerializationConstant;
+import com.google.devtools.build.lib.starlarkbuildapi.NativeComputedDefaultApi;
import com.google.devtools.build.lib.util.FileType;
import com.google.devtools.build.lib.util.FileTypeSet;
import com.google.devtools.build.lib.util.StringUtil;
@@ -554,34 +555,6 @@
}
/**
- * See value(TYPE) above. This method is only meant for Starlark usage.
- *
- * <p>The parameter {@code context} is relevant iff the default value is a Label string. In this
- * case, {@code context} must point to the parent Label in order to be able to convert the
- * default value string to a proper Label.
- *
- * @param parameterName The name of the attribute to use in error messages
- */
- public Builder<TYPE> defaultValue(
- Object defaultValue, Object context, @Nullable String parameterName)
- throws ConversionException {
- Preconditions.checkState(!valueSet, "the default value is already set");
- value =
- type.convert(
- defaultValue,
- ((parameterName == null) ? "" : String.format("parameter '%s' of ", parameterName))
- + String.format("attribute '%s'", name),
- context);
- valueSet = true;
- return this;
- }
-
- /** See value(TYPE) above. This method is only meant for Starlark usage. */
- public Builder<TYPE> defaultValue(Object defaultValue) throws ConversionException {
- return defaultValue(defaultValue, null, null);
- }
-
- /**
* Sets the attribute default value to a computed default value - use this when the default
* value is a function of other attributes of the Rule. The type of the computed default value
* for a mandatory attribute must match the type parameter: (e.g. list=[], integer=0, string="",
@@ -599,6 +572,15 @@
return this;
}
+ /** Used for b/200065655#comment3. */
+ public Builder<TYPE> value(NativeComputedDefaultApi defaultValue) {
+ Preconditions.checkState(!valueSet, "the default value is already set");
+ value = defaultValue;
+ valueSource = AttributeValueSource.NATIVE_COMPUTED_DEFAULT;
+ valueSet = true;
+ return this;
+ }
+
/**
* Sets the attribute default value to a Starlark computed default template. Like a native
* Computed Default, this allows a Starlark-defined Rule Class to specify that the default value
@@ -633,6 +615,34 @@
return this;
}
+ /**
+ * See value(TYPE) above. This method is only meant for Starlark usage.
+ *
+ * <p>The parameter {@code context} is relevant iff the default value is a Label string. In this
+ * case, {@code context} must point to the parent Label in order to be able to convert the
+ * default value string to a proper Label.
+ *
+ * @param parameterName The name of the attribute to use in error messages
+ */
+ public Builder<TYPE> defaultValue(
+ Object defaultValue, Object context, @Nullable String parameterName)
+ throws ConversionException {
+ Preconditions.checkState(!valueSet, "the default value is already set");
+ value =
+ type.convert(
+ defaultValue,
+ ((parameterName == null) ? "" : String.format("parameter '%s' of ", parameterName))
+ + String.format("attribute '%s'", name),
+ context);
+ valueSet = true;
+ return this;
+ }
+
+ /** See value(TYPE) above. This method is only meant for Starlark usage. */
+ public Builder<TYPE> defaultValue(Object defaultValue) throws ConversionException {
+ return defaultValue(defaultValue, null, null);
+ }
+
/** Returns where the value of this attribute comes from. Useful only for Starlark. */
public AttributeValueSource getValueSource() {
return valueSource;
diff --git a/src/main/java/com/google/devtools/build/lib/packages/AttributeMap.java b/src/main/java/com/google/devtools/build/lib/packages/AttributeMap.java
index ffac418..cc27242 100644
--- a/src/main/java/com/google/devtools/build/lib/packages/AttributeMap.java
+++ b/src/main/java/com/google/devtools/build/lib/packages/AttributeMap.java
@@ -142,6 +142,8 @@
// a more generic interface.
String getPackageDefaultHdrsCheck();
+ boolean isPackageDefaultHdrsCheckSet();
+
Boolean getPackageDefaultTestOnly();
String getPackageDefaultDeprecation();
diff --git a/src/main/java/com/google/devtools/build/lib/packages/AttributeValueSource.java b/src/main/java/com/google/devtools/build/lib/packages/AttributeValueSource.java
index 7e013b7..683e02c 100644
--- a/src/main/java/com/google/devtools/build/lib/packages/AttributeValueSource.java
+++ b/src/main/java/com/google/devtools/build/lib/packages/AttributeValueSource.java
@@ -21,6 +21,7 @@
* from.
*/
public enum AttributeValueSource {
+ NATIVE_COMPUTED_DEFAULT("$", false),
COMPUTED_DEFAULT("$", true),
LATE_BOUND(":", true),
DIRECT("$", false);
diff --git a/src/main/java/com/google/devtools/build/lib/packages/DelegatingAttributeMapper.java b/src/main/java/com/google/devtools/build/lib/packages/DelegatingAttributeMapper.java
index 4b27dff..165d87f 100644
--- a/src/main/java/com/google/devtools/build/lib/packages/DelegatingAttributeMapper.java
+++ b/src/main/java/com/google/devtools/build/lib/packages/DelegatingAttributeMapper.java
@@ -99,6 +99,11 @@
}
@Override
+ public boolean isPackageDefaultHdrsCheckSet() {
+ return delegate.isPackageDefaultHdrsCheckSet();
+ }
+
+ @Override
public Boolean getPackageDefaultTestOnly() {
return delegate.getPackageDefaultTestOnly();
}
diff --git a/src/main/java/com/google/devtools/build/lib/rules/cpp/CcStarlarkInternal.java b/src/main/java/com/google/devtools/build/lib/rules/cpp/CcStarlarkInternal.java
index 2ca71d6..5e3a520 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/cpp/CcStarlarkInternal.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/cpp/CcStarlarkInternal.java
@@ -14,18 +14,28 @@
package com.google.devtools.build.lib.rules.cpp;
+import com.google.common.collect.ImmutableMap;
import com.google.devtools.build.docgen.annot.DocCategory;
import com.google.devtools.build.lib.actions.Artifact;
+import com.google.devtools.build.lib.actions.CommandLineExpansionException;
+import com.google.devtools.build.lib.analysis.MakeVariableSupplier.MapBackedMakeVariableSupplier;
+import com.google.devtools.build.lib.analysis.RuleContext;
import com.google.devtools.build.lib.analysis.StaticallyLinkedMarkerProvider;
import com.google.devtools.build.lib.analysis.TransitiveInfoCollection;
import com.google.devtools.build.lib.analysis.config.BuildConfigurationValue;
import com.google.devtools.build.lib.analysis.configuredtargets.PackageGroupConfiguredTarget;
+import com.google.devtools.build.lib.analysis.starlark.StarlarkActionFactory;
import com.google.devtools.build.lib.analysis.starlark.StarlarkRuleContext;
import com.google.devtools.build.lib.collect.nestedset.Depset;
+import com.google.devtools.build.lib.packages.Attribute.ComputedDefault;
+import com.google.devtools.build.lib.packages.AttributeMap;
import com.google.devtools.build.lib.packages.Provider;
import com.google.devtools.build.lib.packages.RuleClass.ConfiguredTargetFactory.RuleErrorException;
import com.google.devtools.build.lib.rules.cpp.CcBinary.CcLauncherInfo;
+import com.google.devtools.build.lib.rules.cpp.CcCommon.CcFlagsSupplier;
+import com.google.devtools.build.lib.rules.cpp.CcLinkingContext.Linkstamp;
import com.google.devtools.build.lib.starlarkbuildapi.FileApi;
+import com.google.devtools.build.lib.starlarkbuildapi.NativeComputedDefaultApi;
import com.google.devtools.build.lib.starlarkbuildapi.core.ProviderApi;
import com.google.devtools.build.lib.vfs.PathFragment;
import net.starlark.java.annot.Param;
@@ -183,6 +193,23 @@
}
@StarlarkMethod(
+ name = "init_make_variables",
+ documented = false,
+ parameters = {
+ @Param(name = "ctx", positional = false, named = true),
+ @Param(name = "cc_toolchain", positional = false, named = true),
+ })
+ public void initMakeVariables(
+ StarlarkRuleContext starlarkRuleContext, CcToolchainProvider ccToolchain) {
+ ImmutableMap.Builder<String, String> toolchainMakeVariables = ImmutableMap.builder();
+ ccToolchain.addGlobalMakeVariables(toolchainMakeVariables);
+ RuleContext ruleContext = starlarkRuleContext.getRuleContext();
+ ruleContext.initConfigurationMakeVariableContext(
+ new MapBackedMakeVariableSupplier(toolchainMakeVariables.buildOrThrow()),
+ new CcFlagsSupplier(starlarkRuleContext.getRuleContext()));
+ }
+
+ @StarlarkMethod(
name = "get_build_info",
documented = false,
parameters = {@Param(name = "ctx")})
@@ -197,6 +224,65 @@
return CcLauncherInfo.PROVIDER;
}
+ @StarlarkMethod(
+ name = "create_linkstamp",
+ documented = false,
+ parameters = {
+ @Param(name = "actions", positional = false, named = true),
+ @Param(name = "linkstamp", positional = false, named = true),
+ @Param(name = "compilation_context", positional = false, named = true),
+ })
+ public Linkstamp createLinkstamp(
+ StarlarkActionFactory starlarkActionFactoryApi,
+ Artifact linkstamp,
+ CcCompilationContext ccCompilationContext)
+ throws EvalException {
+ try {
+ return new Linkstamp( // throws InterruptedException
+ linkstamp,
+ ccCompilationContext.getDeclaredIncludeSrcs(),
+ starlarkActionFactoryApi.getActionConstructionContext().getActionKeyContext());
+ } catch (CommandLineExpansionException | InterruptedException ex) {
+ throw new EvalException(ex);
+ }
+ }
+
+ static class DefaultCoptsBuiltinComputedDefault extends ComputedDefault
+ implements NativeComputedDefaultApi {
+ @Override
+ public Object getDefault(AttributeMap rule) {
+ return rule.getPackageDefaultCopts();
+ }
+
+ @Override
+ public boolean resolvableWithRawAttributes() {
+ return true;
+ }
+ }
+
+ @StarlarkMethod(name = "default_copts_computed_default", documented = false)
+ public ComputedDefault getDefaultCoptsComputedDefault() {
+ return new DefaultCoptsBuiltinComputedDefault();
+ }
+
+ static class DefaultHdrsCheckBuiltinComputedDefault extends ComputedDefault
+ implements NativeComputedDefaultApi {
+ @Override
+ public Object getDefault(AttributeMap rule) {
+ return rule.isPackageDefaultHdrsCheckSet() ? rule.getPackageDefaultHdrsCheck() : "";
+ }
+
+ @Override
+ public boolean resolvableWithRawAttributes() {
+ return true;
+ }
+ }
+
+ @StarlarkMethod(name = "default_hdrs_check_computed_default", documented = false)
+ public ComputedDefault getDefaultHdrsCheckComputedDefault() {
+ return new DefaultHdrsCheckBuiltinComputedDefault();
+ }
+
// TODO(b/207761932): perhaps move this to another internal module
@StarlarkMethod(
name = "declare_shareable_artifact",
diff --git a/src/main/java/com/google/devtools/build/lib/starlarkbuildapi/NativeComputedDefaultApi.java b/src/main/java/com/google/devtools/build/lib/starlarkbuildapi/NativeComputedDefaultApi.java
new file mode 100644
index 0000000..867e856
--- /dev/null
+++ b/src/main/java/com/google/devtools/build/lib/starlarkbuildapi/NativeComputedDefaultApi.java
@@ -0,0 +1,26 @@
+// 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.starlarkbuildapi;
+
+import com.google.devtools.build.docgen.annot.DocCategory;
+import net.starlark.java.annot.StarlarkBuiltin;
+import net.starlark.java.eval.StarlarkValue;
+
+/**
+ * The interface for native computed default in Starlark. This will go away once proper package
+ * defaults exist.
+ */
+@StarlarkBuiltin(name = "NativeComputedDefault", category = DocCategory.BUILTIN, documented = false)
+public interface NativeComputedDefaultApi extends StarlarkValue {}
diff --git a/src/main/java/com/google/devtools/build/lib/starlarkbuildapi/StarlarkAttrModuleApi.java b/src/main/java/com/google/devtools/build/lib/starlarkbuildapi/StarlarkAttrModuleApi.java
index 0e7dc1e..5edd471 100644
--- a/src/main/java/com/google/devtools/build/lib/starlarkbuildapi/StarlarkAttrModuleApi.java
+++ b/src/main/java/com/google/devtools/build/lib/starlarkbuildapi/StarlarkAttrModuleApi.java
@@ -188,6 +188,10 @@
name = DEFAULT_ARG,
defaultValue = "''",
doc = DEFAULT_DOC,
+ allowedTypes = {
+ @ParamType(type = String.class),
+ @ParamType(type = NativeComputedDefaultApi.class)
+ },
named = true,
positional = false),
@Param(
@@ -214,7 +218,7 @@
},
useStarlarkThread = true)
Descriptor stringAttribute(
- String defaultValue, String doc, Boolean mandatory, Sequence<?> values, StarlarkThread thread)
+ Object defaultValue, String doc, Boolean mandatory, Sequence<?> values, StarlarkThread thread)
throws EvalException;
@StarlarkMethod(
@@ -360,7 +364,10 @@
@Param(name = ALLOW_EMPTY_ARG, defaultValue = "True", doc = ALLOW_EMPTY_DOC, named = true),
@Param(
name = DEFAULT_ARG,
- allowedTypes = {@ParamType(type = Sequence.class, generic1 = String.class)},
+ allowedTypes = {
+ @ParamType(type = Sequence.class, generic1 = String.class),
+ @ParamType(type = NativeComputedDefaultApi.class)
+ },
defaultValue = "[]",
doc = DEFAULT_DOC,
named = true,
@@ -369,11 +376,7 @@
},
useStarlarkThread = true)
Descriptor stringListAttribute(
- Boolean mandatory,
- Boolean allowEmpty,
- Sequence<?> defaultValue,
- String doc,
- StarlarkThread thread)
+ Boolean mandatory, Boolean allowEmpty, Object defaultValue, String doc, StarlarkThread thread)
throws EvalException;
@StarlarkMethod(
diff --git a/src/main/java/com/google/devtools/build/skydoc/fakebuildapi/FakeStarlarkAttrModuleApi.java b/src/main/java/com/google/devtools/build/skydoc/fakebuildapi/FakeStarlarkAttrModuleApi.java
index ee4af2c..20a7785 100644
--- a/src/main/java/com/google/devtools/build/skydoc/fakebuildapi/FakeStarlarkAttrModuleApi.java
+++ b/src/main/java/com/google/devtools/build/skydoc/fakebuildapi/FakeStarlarkAttrModuleApi.java
@@ -47,7 +47,7 @@
@Override
public Descriptor stringAttribute(
- String defaultString,
+ Object defaultString,
String doc,
Boolean mandatory,
Sequence<?> values,
@@ -85,11 +85,7 @@
@Override
public Descriptor stringListAttribute(
- Boolean mandatory,
- Boolean allowEmpty,
- Sequence<?> defaultList,
- String doc,
- StarlarkThread thread)
+ Boolean mandatory, Boolean allowEmpty, Object defaultList, String doc, StarlarkThread thread)
throws EvalException {
return new FakeDescriptor(
AttributeType.STRING_LIST, doc, mandatory, ImmutableList.of(), defaultList);
diff --git a/src/main/java/net/starlark/java/eval/ParamDescriptor.java b/src/main/java/net/starlark/java/eval/ParamDescriptor.java
index 5f66f1f..23f7e1b 100644
--- a/src/main/java/net/starlark/java/eval/ParamDescriptor.java
+++ b/src/main/java/net/starlark/java/eval/ParamDescriptor.java
@@ -15,6 +15,7 @@
package net.starlark.java.eval;
import com.google.common.base.Preconditions;
+import com.google.common.collect.ImmutableList;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;
@@ -105,11 +106,16 @@
// "a or b"
// "a, b, or c"
StringBuilder buf = new StringBuilder();
- for (int i = 0, n = allowedClasses.size(); i < n; i++) {
+ // TODO(b/200065655#comment3): Remove when we have an official way for package defaults.
+ ImmutableList<Class<?>> allowedClassesFiltered =
+ allowedClasses.stream()
+ .filter(x -> !Starlark.classType(x).equals("NativeComputedDefault"))
+ .collect(ImmutableList.toImmutableList());
+ for (int i = 0, n = allowedClassesFiltered.size(); i < n; i++) {
if (i > 0) {
buf.append(n == 2 ? " or " : i < n - 1 ? ", " : ", or ");
}
- buf.append(Starlark.classType(allowedClasses.get(i)));
+ buf.append(Starlark.classType(allowedClassesFiltered.get(i)));
}
return buf.toString();
}
diff --git a/src/test/java/com/google/devtools/build/lib/testutil/FakeAttributeMapper.java b/src/test/java/com/google/devtools/build/lib/testutil/FakeAttributeMapper.java
index 0201e2a..39b75b2 100644
--- a/src/test/java/com/google/devtools/build/lib/testutil/FakeAttributeMapper.java
+++ b/src/test/java/com/google/devtools/build/lib/testutil/FakeAttributeMapper.java
@@ -122,6 +122,11 @@
}
@Override
+ public boolean isPackageDefaultHdrsCheckSet() {
+ return false;
+ }
+
+ @Override
public Boolean getPackageDefaultTestOnly() {
return false;
}