Feature configuration: add a field required_variables on flag_sets.

This allows to prevent expansion of flag sets based on whether build variables
are available. If required_variables is not set, and a variable that is
referenced in the flag_set's flags is not available, the build will fail.

We need the new behavior when some input files (for example profile data in
FDO enabled builds) are only available for a subset of the translation units of
a given target.

--
MOS_MIGRATED_REVID=100028996
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 67581af..c2d7825 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
@@ -393,10 +393,12 @@
   @Immutable
   private static class FlagSet implements Serializable {
     private final ImmutableSet<String> actions;
+    private final ImmutableSet<String> expandIfAllAvailable;
     private final ImmutableList<FlagGroup> flagGroups;
     
     private FlagSet(CToolchain.FlagSet flagSet) throws InvalidConfigurationException {
       this.actions = ImmutableSet.copyOf(flagSet.getActionList());
+      this.expandIfAllAvailable = ImmutableSet.copyOf(flagSet.getExpandIfAllAvailableList());
       ImmutableList.Builder<FlagGroup> builder = ImmutableList.builder();
       for (CToolchain.FlagGroup flagGroup : flagSet.getFlagGroupList()) {
         builder.add(new FlagGroup(flagGroup));
@@ -408,6 +410,11 @@
      * Adds the flags that apply to the given {@code action} to {@code commandLine}.
      */
     private void expandCommandLine(String action, Variables variables, List<String> commandLine) {
+      for (String variable : expandIfAllAvailable) {
+        if (!variables.isAvailable(variable)) {
+          return;
+        }
+      }
       if (!actions.contains(action)) {
         return;
       }
@@ -738,6 +745,13 @@
       }
       return new NestedView(viewMap, sequenceName, sequenceVariables.get(sequenceName));
     }
+
+    /**
+     * Returns whether {@code variable} is set.
+     */
+    private boolean isAvailable(String variable) {
+      return variables.containsKey(variable) || sequenceVariables.containsKey(variable);
+    }
   }
   
   /**
diff --git a/src/main/protobuf/crosstool_config.proto b/src/main/protobuf/crosstool_config.proto
index ea3b7ec..6e3ffb2 100644
--- a/src/main/protobuf/crosstool_config.proto
+++ b/src/main/protobuf/crosstool_config.proto
@@ -107,6 +107,16 @@
     // If 'with_feature' is omitted, the flag set will be applied
     // unconditionally for every action specified.
     repeated FeatureSet with_feature = 3;
+
+    // A list of build variables that this feature set needs, but which are
+    // allowed to not be set. If any of the build variables listed is not
+    // set, the feature set will not be expanded.
+    //
+    // NOTE: Consider alternatives before using this; usually tools should
+    // consistently create the same set of files, even if empty; use this
+    // only for backwards compatibility with already existing behavior in tools
+    // that are currently not worth changing.
+    repeated string expand_if_all_available = 4;
   }
 
   // Contains all flag specifications for one feature.