diff options
Diffstat (limited to 'src')
3 files changed, 158 insertions, 4 deletions
diff --git a/src/main/java/com/google/devtools/build/lib/rules/cpp/CcToolchainFeatures.java b/src/main/java/com/google/devtools/build/lib/rules/cpp/CcToolchainFeatures.java index 4515aaaec3..5894035668 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/cpp/CcToolchainFeatures.java +++ b/src/main/java/com/google/devtools/build/lib/rules/cpp/CcToolchainFeatures.java @@ -340,6 +340,8 @@ public class CcToolchainFeatures implements Serializable { private final ImmutableSet<String> usedVariables; private String iterateOverVariable; private final ImmutableSet<String> expandIfAllAvailable; + private final String expandIfTrue; + private final String expandIfFalse; /** * TODO(b/32655571): Cleanup and get rid of usedVariables field once implicit iteration is not @@ -375,14 +377,14 @@ public class CcToolchainFeatures implements Serializable { this.usedVariables = usedVariables.build(); this.expandables = expandables.build(); this.expandIfAllAvailable = ImmutableSet.copyOf(flagGroup.getExpandIfAllAvailableList()); + this.expandIfTrue = flagGroup.getExpandIfTrue(); + this.expandIfFalse = flagGroup.getExpandIfFalse(); } @Override public void expand(Variables variables, final List<String> commandLine) { - for (String variable : expandIfAllAvailable) { - if (!variables.isAvailable(variable)) { - return; - } + if (!canBeExpanded(variables)) { + return; } if (iterateOverVariable == null) { // TODO(b/32655571): Remove branch once implicit iteration is not needed anymore. @@ -402,6 +404,25 @@ public class CcToolchainFeatures implements Serializable { } } + private boolean canBeExpanded(Variables variables) { + for (String variable : expandIfAllAvailable) { + if (!variables.isAvailable(variable)) { + return false; + } + } + if (expandIfTrue != null + && variables.isAvailable(expandIfTrue) + && !variables.getVariable(expandIfTrue).isTruthy()) { + return false; + } + if (expandIfFalse != null + && variables.isAvailable(expandIfFalse) + && variables.getVariable(expandIfFalse).isTruthy()) { + return false; + } + return true; + } + private Set<String> getUsedVariables() { return usedVariables; } @@ -798,6 +819,9 @@ public class CcToolchainFeatures implements Serializable { * @param variableName name of the variable value at hand, for better exception message. */ VariableValue getFieldValue(String variableName, String field); + + /** Return true if the variable is truthy */ + boolean isTruthy(); } /** Interface for VariableValue builders */ @@ -905,6 +929,12 @@ public class CcToolchainFeatures implements Serializable { } /** Adds a field to the structure. */ + public StructureBuilder addField(String name, int value) { + fields.put(name, new IntegerValue(value)); + return this; + } + + /** Adds a field to the structure. */ public StructureBuilder addField(String name, ImmutableList<String> values) { fields.put(name, new StringSequence(values)); return this; @@ -962,6 +992,11 @@ public class CcToolchainFeatures implements Serializable { + "found sequence", variableName)); } + + @Override + public boolean isTruthy() { + return !values.isEmpty(); + } } /** @@ -1010,6 +1045,11 @@ public class CcToolchainFeatures implements Serializable { + "found sequence", variableName)); } + + @Override + public boolean isTruthy() { + return !Iterables.isEmpty(values); + } } /** Sequence of arbitrary VariableValue objects. */ @@ -1049,6 +1089,11 @@ public class CcToolchainFeatures implements Serializable { + "found sequence", variableName)); } + + @Override + public boolean isTruthy() { + return values.isEmpty(); + } } /** @@ -1095,6 +1140,11 @@ public class CcToolchainFeatures implements Serializable { public boolean isSequence() { return false; } + + @Override + public boolean isTruthy() { + return !value.isEmpty(); + } } /** @@ -1138,6 +1188,59 @@ public class CcToolchainFeatures implements Serializable { public boolean isSequence() { return false; } + + @Override + public boolean isTruthy() { + return !value.isEmpty(); + } + } + + /** + * The leaves in the variable sequence node tree are simple integer values. Note that this + * should never live outside of {@code expand}, as the object overhead is prohibitively + * expensive. + */ + @Immutable + static final class IntegerValue implements VariableValue { + + private final int value; + + public IntegerValue(int value) { + this.value = value; + } + + @Override + public String getStringValue(String variableName) { + return Integer.toString(value); + } + + @Override + public Iterable<? extends VariableValue> getSequenceValue(String variableName) { + throw new ExpansionException( + String.format( + "Invalid toolchain configuration: Cannot expand variable '%s': expected sequence, " + + "found integer", + variableName)); + } + + @Override + public VariableValue getFieldValue(String variableName, String field) { + throw new ExpansionException( + String.format( + "Invalid toolchain configuration: Cannot expand variable '%s.%s': variable '%s' is " + + "integer, expected structure", + variableName, field, variableName)); + } + + @Override + public boolean isSequence() { + return false; + } + + @Override + public boolean isTruthy() { + return value != 0; + } } /** diff --git a/src/main/protobuf/crosstool_config.proto b/src/main/protobuf/crosstool_config.proto index 51cb5db33b..190c3f546e 100644 --- a/src/main/protobuf/crosstool_config.proto +++ b/src/main/protobuf/crosstool_config.proto @@ -100,6 +100,10 @@ message CToolchain { optional string iterate_over = 3; repeated string expand_if_all_available = 4; + + optional string expand_if_true = 5; + + optional string expand_if_false = 6; } // A key/value pair to be added as an environment variable. The value of diff --git a/src/test/java/com/google/devtools/build/lib/rules/cpp/CcToolchainFeaturesTest.java b/src/test/java/com/google/devtools/build/lib/rules/cpp/CcToolchainFeaturesTest.java index 5161ae5f4e..9efbb6229d 100644 --- a/src/test/java/com/google/devtools/build/lib/rules/cpp/CcToolchainFeaturesTest.java +++ b/src/test/java/com/google/devtools/build/lib/rules/cpp/CcToolchainFeaturesTest.java @@ -27,6 +27,7 @@ import com.google.devtools.build.lib.rules.cpp.CcToolchainFeatures.ActionConfig; import com.google.devtools.build.lib.rules.cpp.CcToolchainFeatures.ExpansionException; import com.google.devtools.build.lib.rules.cpp.CcToolchainFeatures.FeatureConfiguration; import com.google.devtools.build.lib.rules.cpp.CcToolchainFeatures.Variables; +import com.google.devtools.build.lib.rules.cpp.CcToolchainFeatures.Variables.IntegerValue; import com.google.devtools.build.lib.rules.cpp.CcToolchainFeatures.Variables.SequenceBuilder; import com.google.devtools.build.lib.rules.cpp.CcToolchainFeatures.Variables.StringSequenceBuilder; import com.google.devtools.build.lib.rules.cpp.CcToolchainFeatures.Variables.StructureBuilder; @@ -525,6 +526,52 @@ public class CcToolchainFeaturesTest { } @Test + public void testExpandIfTrueExpandsIfOne() throws Exception { + assertThat( + getCommandLineForFlagGroups( + "flag_group {" + + " expand_if_true: 'struct.bool'" + + " flag: '-A%{struct.foo}'" + + " flag: '-B%{struct.bar}'" + + "}" + + "flag_group {" + + " expand_if_false: 'struct.bool'" + + " flag: '-X%{struct.foo}'" + + " flag: '-Y%{struct.bar}'" + + "}", + createStructureVariables( + "struct", + new Variables.StructureBuilder() + .addField("bool", new IntegerValue(1)) + .addField("foo", "fooValue") + .addField("bar", "barValue")))) + .containsExactly("-AfooValue", "-BbarValue"); + } + + @Test + public void testExpandIfTrueExpandsIfZero() throws Exception { + assertThat( + getCommandLineForFlagGroups( + "flag_group {" + + " expand_if_true: 'struct.bool'" + + " flag: '-A%{struct.foo}'" + + " flag: '-B%{struct.bar}'" + + "}" + + "flag_group {" + + " expand_if_false: 'struct.bool'" + + " flag: '-X%{struct.foo}'" + + " flag: '-Y%{struct.bar}'" + + "}", + createStructureVariables( + "struct", + new Variables.StructureBuilder() + .addField("bool", new IntegerValue(0)) + .addField("foo", "fooValue") + .addField("bar", "barValue")))) + .containsExactly("-XfooValue", "-YbarValue"); + } + + @Test public void testLegacyListVariableExpansion() throws Exception { assertThat(getCommandLineForFlag("%{v}", createVariables("v", "1", "v", "2"))) .containsExactly("1", "2"); |