Extract logic for dealing with CROSSTOOL values and build variables into separate class RELNOTES: None. PiperOrigin-RevId: 196517537
diff --git a/src/main/java/com/google/devtools/build/lib/rules/apple/cpp/AppleCcToolchain.java b/src/main/java/com/google/devtools/build/lib/rules/apple/cpp/AppleCcToolchain.java index 93f1555..5d07a2b 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/apple/cpp/AppleCcToolchain.java +++ b/src/main/java/com/google/devtools/build/lib/rules/apple/cpp/AppleCcToolchain.java
@@ -27,7 +27,7 @@ import com.google.devtools.build.lib.rules.apple.XcodeConfig; import com.google.devtools.build.lib.rules.apple.XcodeConfigProvider; import com.google.devtools.build.lib.rules.cpp.CcToolchain; -import com.google.devtools.build.lib.rules.cpp.CcToolchainFeatures.Variables; +import com.google.devtools.build.lib.rules.cpp.CcToolchainVariables; import java.util.LinkedHashMap; import java.util.Map; @@ -56,7 +56,7 @@ public static final String APPLE_SDK_PLATFORM_VALUE_KEY = "apple_sdk_platform_value"; @Override - protected void addBuildVariables(RuleContext ruleContext, Variables.Builder variables) + protected void addBuildVariables(RuleContext ruleContext, CcToolchainVariables.Builder variables) throws RuleErrorException { AppleConfiguration appleConfiguration = ruleContext.getFragment(AppleConfiguration.class);
diff --git a/src/main/java/com/google/devtools/build/lib/rules/cpp/CcCommon.java b/src/main/java/com/google/devtools/build/lib/rules/cpp/CcCommon.java index 4d6cb3a..ebf00f8 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/cpp/CcCommon.java +++ b/src/main/java/com/google/devtools/build/lib/rules/cpp/CcCommon.java
@@ -46,7 +46,6 @@ import com.google.devtools.build.lib.rules.cpp.CcCompilationHelper.SourceCategory; import com.google.devtools.build.lib.rules.cpp.CcToolchainFeatures.CollidingProvidesException; 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.CppConfiguration.DynamicMode; import com.google.devtools.build.lib.rules.cpp.CppConfiguration.HeadersCheckingMode; import com.google.devtools.build.lib.rules.cpp.FdoSupport.FdoMode; @@ -900,7 +899,7 @@ return null; } - Variables buildVariables = toolchainProvider.getBuildVariables(); + CcToolchainVariables buildVariables = toolchainProvider.getBuildVariables(); String toolchainCcFlags = Joiner.on(" ") .join(
diff --git a/src/main/java/com/google/devtools/build/lib/rules/cpp/CcCompilationHelper.java b/src/main/java/com/google/devtools/build/lib/rules/cpp/CcCompilationHelper.java index 0ce68ce..981152c 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/cpp/CcCompilationHelper.java +++ b/src/main/java/com/google/devtools/build/lib/rules/cpp/CcCompilationHelper.java
@@ -48,8 +48,7 @@ import com.google.devtools.build.lib.packages.RuleClass.ConfiguredTargetFactory.RuleErrorException; import com.google.devtools.build.lib.rules.cpp.CcCommon.CoptsFilter; 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.VariablesExtension; +import com.google.devtools.build.lib.rules.cpp.CcToolchainVariables.VariablesExtension; import com.google.devtools.build.lib.rules.cpp.CppConfiguration.HeadersCheckingMode; import com.google.devtools.build.lib.skylarkinterface.SkylarkCallable; import com.google.devtools.build.lib.skylarkinterface.SkylarkModule; @@ -1474,7 +1473,7 @@ return flagsBuilder.build(); } - private Variables setupCompileBuildVariables( + private CcToolchainVariables setupCompileBuildVariables( CppCompileActionBuilder builder, Label sourceLabel, String outputName,
diff --git a/src/main/java/com/google/devtools/build/lib/rules/cpp/CcLinkingHelper.java b/src/main/java/com/google/devtools/build/lib/rules/cpp/CcLinkingHelper.java index dc65052..e794eb5 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/cpp/CcLinkingHelper.java +++ b/src/main/java/com/google/devtools/build/lib/rules/cpp/CcLinkingHelper.java
@@ -43,7 +43,7 @@ import com.google.devtools.build.lib.packages.RuleClass.ConfiguredTargetFactory.RuleErrorException; 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.VariablesExtension; +import com.google.devtools.build.lib.rules.cpp.CcToolchainVariables.VariablesExtension; import com.google.devtools.build.lib.rules.cpp.Link.LinkTargetType; import com.google.devtools.build.lib.rules.cpp.Link.LinkerOrArchiver; import com.google.devtools.build.lib.rules.cpp.Link.LinkingMode;
diff --git a/src/main/java/com/google/devtools/build/lib/rules/cpp/CcToolchain.java b/src/main/java/com/google/devtools/build/lib/rules/cpp/CcToolchain.java index 7e92423..ab37119 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/cpp/CcToolchain.java +++ b/src/main/java/com/google/devtools/build/lib/rules/cpp/CcToolchain.java
@@ -53,7 +53,6 @@ import com.google.devtools.build.lib.collect.nestedset.Order; import com.google.devtools.build.lib.events.Location; import com.google.devtools.build.lib.packages.License; -import com.google.devtools.build.lib.rules.cpp.CcToolchainFeatures.Variables; import com.google.devtools.build.lib.rules.cpp.CppConfiguration.Tool; import com.google.devtools.build.lib.rules.cpp.FdoSupport.FdoException; import com.google.devtools.build.lib.rules.cpp.FdoSupport.FdoMode; @@ -844,16 +843,17 @@ } /** - * Returns {@link Variables} instance with build variables that only depend on the toolchain. + * Returns {@link com.google.devtools.build.lib.rules.cpp.CcToolchainVariables} instance with + * build variables that only depend on the toolchain. * * @param ruleContext the rule context * @param defaultSysroot the default sysroot * @throws RuleErrorException if there are configuration errors making it impossible to resolve * certain build variables of this toolchain */ - private final Variables getBuildVariables(RuleContext ruleContext, PathFragment defaultSysroot) - throws RuleErrorException { - Variables.Builder variables = new Variables.Builder(); + private final CcToolchainVariables getBuildVariables( + RuleContext ruleContext, PathFragment defaultSysroot) throws RuleErrorException { + CcToolchainVariables.Builder variables = new CcToolchainVariables.Builder(); PathFragment sysroot = calculateSysroot(ruleContext, defaultSysroot); if (sysroot != null) { @@ -866,12 +866,13 @@ } /** - * Add local build variables from subclasses into {@link Variables} returned from {@link + * Add local build variables from subclasses into {@link + * com.google.devtools.build.lib.rules.cpp.CcToolchainVariables} returned from {@link * #getBuildVariables(RuleContext, PathFragment)}. * * <p>This method is meant to be overridden by subclasses of CcToolchain. */ - protected void addBuildVariables(RuleContext ruleContext, Variables.Builder variables) + protected void addBuildVariables(RuleContext ruleContext, CcToolchainVariables.Builder variables) throws RuleErrorException { // To be overridden in subclasses. }
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 2e215f5..5091a36 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
@@ -17,7 +17,6 @@ import com.google.common.annotations.VisibleForTesting; import com.google.common.base.Preconditions; import com.google.common.base.Strings; -import com.google.common.base.Supplier; import com.google.common.base.Throwables; import com.google.common.cache.CacheBuilder; import com.google.common.cache.CacheLoader; @@ -27,15 +26,13 @@ import com.google.common.collect.ImmutableMultimap; import com.google.common.collect.ImmutableSet; import com.google.common.collect.Iterables; -import com.google.common.collect.Sets; -import com.google.common.collect.Sets.SetView; -import com.google.common.collect.Streams; -import com.google.devtools.build.lib.actions.Artifact; import com.google.devtools.build.lib.actions.Artifact.ArtifactExpander; -import com.google.devtools.build.lib.analysis.RuleContext; import com.google.devtools.build.lib.analysis.config.InvalidConfigurationException; -import com.google.devtools.build.lib.collect.nestedset.NestedSet; import com.google.devtools.build.lib.concurrent.ThreadSafety.Immutable; +import com.google.devtools.build.lib.rules.cpp.CcToolchainVariables.Expandable; +import com.google.devtools.build.lib.rules.cpp.CcToolchainVariables.SingleVariables; +import com.google.devtools.build.lib.rules.cpp.CcToolchainVariables.StringChunk; +import com.google.devtools.build.lib.rules.cpp.CcToolchainVariables.StringValueParser; import com.google.devtools.build.lib.skyframe.serialization.autocodec.AutoCodec; import com.google.devtools.build.lib.skyframe.serialization.autocodec.AutoCodec.VisibleForSerialization; import com.google.devtools.build.lib.skylarkinterface.SkylarkModule; @@ -50,13 +47,11 @@ import java.util.Collection; import java.util.HashMap; import java.util.HashSet; -import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.Objects; import java.util.Optional; import java.util.Set; -import java.util.Stack; import java.util.concurrent.ExecutionException; import javax.annotation.Nullable; @@ -107,228 +102,6 @@ "Symbol %s is provided by all of the following features: %s"; /** - * A piece of a single string value. - * - * <p>A single value can contain a combination of text and variables (for example "-f - * %{var1}/%{var2}"). We split the string into chunks, where each chunk represents either a text - * snippet, or a variable that is to be replaced. - */ - interface StringChunk { - /** - * Expands this chunk. - * - * @param variables binding of variable names to their values for a single flag expansion. - */ - String expand(Variables variables); - } - - /** A plain text chunk of a string (containing no variables). */ - @Immutable - @AutoCodec - @VisibleForSerialization - static class StringLiteralChunk implements StringChunk, Serializable { - private final String text; - - @VisibleForSerialization - StringLiteralChunk(String text) { - this.text = text; - } - - @Override - public String expand(Variables variables) { - return text; - } - - @Override - public boolean equals(@Nullable Object object) { - if (this == object) { - return true; - } - if (object instanceof StringLiteralChunk) { - StringLiteralChunk that = (StringLiteralChunk) object; - return text.equals(that.text); - } - return false; - } - - @Override - public int hashCode() { - return Objects.hash(text); - } - } - - /** A chunk of a string value into which a variable should be expanded. */ - @Immutable - @AutoCodec - static class VariableChunk implements StringChunk, Serializable { - private final String variableName; - - @VisibleForSerialization - VariableChunk(String variableName) { - this.variableName = variableName; - } - - @Override - public String expand(Variables variables) { - // We check all variables in FlagGroup.expandCommandLine. - // If we arrive here with the variable not being available, the variable was provided, but - // the nesting level of the NestedSequence was deeper than the nesting level of the flag - // groups. - return variables.getStringVariable(variableName); - } - - @Override - public boolean equals(@Nullable Object object) { - if (this == object) { - return true; - } - if (object instanceof VariableChunk) { - VariableChunk that = (VariableChunk) object; - return variableName.equals(that.variableName); - } - return false; - } - - @Override - public int hashCode() { - return Objects.hash(variableName); - } - } - - /** - * Parser for toolchain string values. - * - * <p>A string value contains a snippet of text supporting variable expansion. For example, a - * string value "-f %{var1}/%{var2}" will expand the values of the variables "var1" and "var2" in - * the corresponding places in the string. - * - * <p>The {@code StringValueParser} takes a string and parses it into a list of {@link - * StringChunk} objects, where each chunk represents either a snippet of text or a variable to be - * expanded. In the above example, the resulting chunks would be ["-f ", var1, "/", var2]. - * - * <p>In addition to the list of chunks, the {@link StringValueParser} also provides the set of - * variables necessary for the expansion of this flag via {@link #getUsedVariables}. - * - * <p>To get a literal percent character, "%%" can be used in the string. - */ - static class StringValueParser { - - private final String value; - - /** - * The current position in {@value} during parsing. - */ - private int current = 0; - - private final ImmutableList.Builder<StringChunk> chunks = ImmutableList.builder(); - private final ImmutableSet.Builder<String> usedVariables = ImmutableSet.builder(); - - StringValueParser(String value) throws InvalidConfigurationException { - this.value = value; - parse(); - } - - /** @return the parsed chunks for this string. */ - ImmutableList<StringChunk> getChunks() { - return chunks.build(); - } - - /** @return all variable names needed to expand this string. */ - ImmutableSet<String> getUsedVariables() { - return usedVariables.build(); - } - - /** - * Parses the string. - * - * @throws InvalidConfigurationException if there is a parsing error. - */ - private void parse() throws InvalidConfigurationException { - while (current < value.length()) { - if (atVariableStart()) { - parseVariableChunk(); - } else { - parseStringChunk(); - } - } - } - - /** - * @return whether the current position is the start of a variable. - */ - private boolean atVariableStart() { - // We parse a variable when value starts with '%', but not '%%'. - return value.charAt(current) == '%' - && (current + 1 >= value.length() || value.charAt(current + 1) != '%'); - } - - /** - * Parses a chunk of text until the next '%', which indicates either an escaped literal '%' - * or a variable. - */ - private void parseStringChunk() { - int start = current; - // We only parse string chunks starting with '%' if they also start with '%%'. - // In that case, we want to have a single '%' in the string, so we start at the second - // character. - // Note that for strings like "abc%%def" this will lead to two string chunks, the first - // referencing the subtring "abc", and a second referencing the substring "%def". - if (value.charAt(current) == '%') { - current = current + 1; - start = current; - } - current = value.indexOf('%', current + 1); - if (current == -1) { - current = value.length(); - } - final String text = value.substring(start, current); - chunks.add(new StringLiteralChunk(text)); - } - - /** - * Parses a variable to be expanded. - * - * @throws InvalidConfigurationException if there is a parsing error. - */ - private void parseVariableChunk() throws InvalidConfigurationException { - current = current + 1; - if (current >= value.length() || value.charAt(current) != '{') { - abort("expected '{'"); - } - current = current + 1; - if (current >= value.length() || value.charAt(current) == '}') { - abort("expected variable name"); - } - int end = value.indexOf('}', current); - final String name = value.substring(current, end); - usedVariables.add(name); - chunks.add(new VariableChunk(name)); - current = end + 1; - } - - /** - * @throws InvalidConfigurationException with the given error text, adding information about - * the current position in the string. - */ - private void abort(String error) throws InvalidConfigurationException { - throw new InvalidConfigurationException("Invalid toolchain configuration: " + error - + " at position " + current + " while parsing a flag containing '" + value + "'"); - } - } - - /** A flag or flag group that can be expanded under a set of variables. */ - interface Expandable { - /** - * Expands the current expandable under the given {@code view}, adding new flags to {@code - * commandLine}. - * - * <p>The {@code variables} controls which variables are visible during the expansion and allows - * to recursively expand nested flag groups. - */ - void expand(Variables variables, @Nullable ArtifactExpander expander, List<String> commandLine); - } - - /** * A single flag to be expanded under a set of variables. */ @Immutable @@ -345,7 +118,9 @@ /** Expand this flag into a single new entry in {@code commandLine}. */ @Override public void expand( - Variables variables, @Nullable ArtifactExpander expander, List<String> commandLine) { + CcToolchainVariables variables, + @Nullable ArtifactExpander expander, + List<String> commandLine) { StringBuilder flag = new StringBuilder(); for (StringChunk chunk : chunks) { flag.append(chunk.expand(variables)); @@ -392,7 +167,7 @@ @Override public void expand( - Variables variables, + CcToolchainVariables variables, @Nullable ArtifactExpander artifactExpander, List<String> commandLine) { commandLine.add(chunk.expand(variables)); @@ -439,10 +214,11 @@ } /** - * Adds the key/value pair this object represents to the given map of environment variables. - * The value of the entry is expanded with the given {@code variables}. + * Adds the key/value pair this object represents to the given map of environment variables. The + * value of the entry is expanded with the given {@code variables}. */ - public void addEnvEntry(Variables variables, ImmutableMap.Builder<String, String> envBuilder) { + public void addEnvEntry( + CcToolchainVariables variables, ImmutableMap.Builder<String, String> envBuilder) { StringBuilder value = new StringBuilder(); for (StringChunk chunk : valueChunks) { value.append(chunk.expand(variables)); @@ -554,14 +330,16 @@ @Override public void expand( - Variables variables, @Nullable ArtifactExpander expander, final List<String> commandLine) { + CcToolchainVariables variables, + @Nullable ArtifactExpander expander, + final List<String> commandLine) { if (!canBeExpanded(variables, expander)) { return; } if (iterateOverVariable != null) { - for (Variables.VariableValue variableValue : + for (CcToolchainVariables.VariableValue variableValue : variables.getSequenceVariable(iterateOverVariable, expander)) { - Variables nestedVariables = + CcToolchainVariables nestedVariables = new SingleVariables(variables, iterateOverVariable, variableValue); for (Expandable expandable : expandables) { expandable.expand(nestedVariables, expander, commandLine); @@ -574,7 +352,8 @@ } } - private boolean canBeExpanded(Variables variables, @Nullable ArtifactExpander expander) { + private boolean canBeExpanded( + CcToolchainVariables variables, @Nullable ArtifactExpander expander) { for (String variable : expandIfAllAvailable) { if (!variables.isAvailable(variable, expander)) { return false; @@ -622,7 +401,9 @@ * </ul> */ private void expandCommandLine( - Variables variables, @Nullable ArtifactExpander expander, final List<String> commandLine) { + CcToolchainVariables variables, + @Nullable ArtifactExpander expander, + final List<String> commandLine) { expand(variables, expander, commandLine); } @@ -726,7 +507,7 @@ /** Adds the flags that apply to the given {@code action} to {@code commandLine}. */ private void expandCommandLine( String action, - Variables variables, + CcToolchainVariables variables, Set<String> enabledFeatureNames, @Nullable ArtifactExpander expander, List<String> commandLine) { @@ -846,12 +627,12 @@ } /** - * Adds the environment key/value pairs that apply to the given {@code action} to - * {@code envBuilder}. + * Adds the environment key/value pairs that apply to the given {@code action} to {@code + * envBuilder}. */ private void expandEnvironment( String action, - Variables variables, + CcToolchainVariables variables, Set<String> enabledFeatureNames, ImmutableMap.Builder<String, String> envBuilder) { if (!actions.contains(action)) { @@ -939,7 +720,7 @@ /** Adds environment variables for the given action to the provided builder. */ private void expandEnvironment( String action, - Variables variables, + CcToolchainVariables variables, Set<String> enabledFeatureNames, ImmutableMap.Builder<String, String> envBuilder) { for (EnvSet envSet : envSets) { @@ -950,7 +731,7 @@ /** Adds the flags that apply to the given {@code action} to {@code commandLine}. */ private void expandCommandLine( String action, - Variables variables, + CcToolchainVariables variables, Set<String> enabledFeatureNames, @Nullable ArtifactExpander expander, List<String> commandLine) { @@ -1140,7 +921,7 @@ /** Adds the flags that apply to this action to {@code commandLine}. */ private void expandCommandLine( - Variables variables, + CcToolchainVariables variables, Set<String> enabledFeatureNames, @Nullable ArtifactExpander expander, List<String> commandLine) { @@ -1189,8 +970,8 @@ */ public String getArtifactName(Map<String, String> variables) { StringBuilder resultBuilder = new StringBuilder(); - Variables artifactNameVariables = - new Variables.Builder().addAllStringVariables(variables).build(); + CcToolchainVariables artifactNameVariables = + new CcToolchainVariables.Builder().addAllStringVariables(variables).build(); for (StringChunk chunk : chunks) { resultBuilder.append(chunk.expand(artifactNameVariables)); } @@ -1199,924 +980,6 @@ } } - /** - * Configured build variables usable by the toolchain configuration. - * - * <p>TODO(b/32655571): Investigate cleanup once implicit iteration is not needed. Variables - * instance could serve as a top level View used to expand all flag_groups. - */ - @SkylarkModule( - name = "variables", - documented = false, - category = SkylarkModuleCategory.BUILTIN, - doc = "Class encapsulating build variables." - ) - public abstract static class Variables { - /** An empty variables instance. */ - public static final Variables EMPTY = new Variables.Builder().build(); - - /** - * Retrieves a {@link StringSequence} variable named {@code variableName} from {@code variables} - * and converts it into a list of plain strings. - * - * <p>Throws {@link ExpansionException} when the variable is not a {@link StringSequence}. - */ - public static final ImmutableList<String> toStringList( - CcToolchainFeatures.Variables variables, String variableName) { - return Streams - .stream(variables.getSequenceVariable(variableName)) - .map(variable -> variable.getStringValue(variableName)) - .collect(ImmutableList.toImmutableList()); - } - - /** - * Get a variable value named @param name. Supports accessing fields in structures (e.g. - * 'libraries_to_link.interface_libraries') - * - * @throws ExpansionException when no such variable or no such field are present, or when - * accessing a field of non-structured variable - */ - VariableValue getVariable(String name) { - return lookupVariable(name, true, null); - } - - VariableValue getVariable(String name, @Nullable ArtifactExpander expander) { - return lookupVariable(name, true, expander); - } - - /** - * Lookup a variable named @param name or return a reason why the variable was not found. - * Supports accessing fields in structures. - * - * @return Pair<VariableValue, String> returns either (variable value, null) or (null, string - * reason why variable was not found) - */ - private VariableValue lookupVariable( - String name, boolean throwOnMissingVariable, @Nullable ArtifactExpander expander) { - VariableValue nonStructuredVariable = getNonStructuredVariable(name); - if (nonStructuredVariable != null) { - return nonStructuredVariable; - } - VariableValue structuredVariable = - getStructureVariable(name, throwOnMissingVariable, expander); - if (structuredVariable != null) { - return structuredVariable; - } else if (throwOnMissingVariable) { - throw new ExpansionException( - String.format( - "Invalid toolchain configuration: Cannot find variable named '%s'.", name)); - } else { - return null; - } - } - - private VariableValue getStructureVariable( - String name, boolean throwOnMissingVariable, @Nullable ArtifactExpander expander) { - if (!name.contains(".")) { - return null; - } - - Stack<String> fieldsToAccess = new Stack<>(); - String structPath = name; - VariableValue variable; - - do { - fieldsToAccess.push(structPath.substring(structPath.lastIndexOf('.') + 1)); - structPath = structPath.substring(0, structPath.lastIndexOf('.')); - variable = getNonStructuredVariable(structPath); - } while (variable == null && structPath.contains(".")); - - if (variable == null) { - return null; - } - - while (!fieldsToAccess.empty()) { - String field = fieldsToAccess.pop(); - variable = variable.getFieldValue(structPath, field, expander); - if (variable == null) { - if (throwOnMissingVariable) { - throw new ExpansionException( - String.format( - "Invalid toolchain configuration: Cannot expand variable '%s.%s': structure %s " - + "doesn't have a field named '%s'", - structPath, field, structPath, field)); - } else { - return null; - } - } - } - return variable; - } - - public String getStringVariable(String variableName) { - return getVariable(variableName, null).getStringValue(variableName); - } - - public Iterable<? extends VariableValue> getSequenceVariable(String variableName) { - return getVariable(variableName, null).getSequenceValue(variableName); - } - - public Iterable<? extends VariableValue> getSequenceVariable( - String variableName, @Nullable ArtifactExpander expander) { - return getVariable(variableName, expander).getSequenceValue(variableName); - } - - /** Returns whether {@code variable} is set. */ - boolean isAvailable(String variable) { - return isAvailable(variable, null); - } - - boolean isAvailable(String variable, @Nullable ArtifactExpander expander) { - return lookupVariable(variable, false, expander) != null; - } - - abstract Map<String, VariableValue> getVariablesMap(); - - abstract Map<String, String> getStringVariablesMap(); - - @Nullable - abstract VariableValue getNonStructuredVariable(String name); - - /** - * Value of a build variable exposed to the CROSSTOOL used for flag expansion. - * - * <p>{@link VariableValue} represent either primitive values or an arbitrarily deeply nested - * recursive structures or sequences. Since there are builds with millions of values, some - * implementations might exist only to optimize memory usage. - * - * <p>Implementations must be immutable and without any side-effects. They will be expanded and - * queried multiple times. - */ - interface VariableValue { - /** - * Returns string value of the variable, if the variable type can be converted to string (e.g. - * StringValue), or throw exception if it cannot (e.g. Sequence). - * - * @param variableName name of the variable value at hand, for better exception message. - */ - String getStringValue(String variableName); - - /** - * Returns Iterable value of the variable, if the variable type can be converted to a Iterable - * (e.g. Sequence), or throw exception if it cannot (e.g. StringValue). - * - * @param variableName name of the variable value at hand, for better exception message. - */ - Iterable<? extends VariableValue> getSequenceValue(String variableName); - - /** - * Returns value of the field, if the variable is of struct type or throw exception if it is - * not or no such field exists. - * - * @param variableName name of the variable value at hand, for better exception message. - */ - VariableValue getFieldValue(String variableName, String field); - - VariableValue getFieldValue( - String variableName, String field, @Nullable ArtifactExpander expander); - - /** Returns true if the variable is truthy */ - boolean isTruthy(); - } - - /** - * Adapter for {@link VariableValue} predefining error handling methods. Override {@link - * #getVariableTypeName()}, {@link #isTruthy()}, and one of {@link #getFieldValue(String, - * String)}, {@link #getSequenceValue(String)}, or {@link #getStringValue(String)}, and you'll - * get error handling for the other methods for free. - */ - abstract static class VariableValueAdapter implements VariableValue { - - /** Returns human-readable variable type name to be used in error messages. */ - public abstract String getVariableTypeName(); - - @Override - public abstract boolean isTruthy(); - - @Override - public VariableValue getFieldValue(String variableName, String field) { - return getFieldValue(variableName, field, null); - } - - @Override - public VariableValue getFieldValue( - String variableName, String field, @Nullable ArtifactExpander expander) { - throw new ExpansionException( - String.format( - "Invalid toolchain configuration: Cannot expand variable '%s.%s': variable '%s' is " - + "%s, expected structure", - variableName, field, variableName, getVariableTypeName())); - } - - @Override - public String getStringValue(String variableName) { - throw new ExpansionException( - String.format( - "Invalid toolchain configuration: Cannot expand variable '%s': expected string, " - + "found %s", - variableName, getVariableTypeName())); - } - - @Override - public Iterable<? extends VariableValue> getSequenceValue(String variableName) { - throw new ExpansionException( - String.format( - "Invalid toolchain configuration: Cannot expand variable '%s': expected sequence, " - + "found %s", - variableName, getVariableTypeName())); - } - } - - /** Interface for VariableValue builders */ - public interface VariableValueBuilder { - VariableValue build(); - } - - /** Builder for StringSequence. */ - public static class StringSequenceBuilder implements VariableValueBuilder { - - private final ImmutableList.Builder<String> values = ImmutableList.builder(); - - /** Adds a value to the sequence. */ - public StringSequenceBuilder addValue(String value) { - values.add(value); - return this; - } - - /** Returns an immutable string sequence. */ - @Override - public StringSequence build() { - return new StringSequence(values.build()); - } - } - - /** Builder for Sequence. */ - public static class SequenceBuilder implements VariableValueBuilder { - - private final ImmutableList.Builder<VariableValue> values = ImmutableList.builder(); - - /** Adds a value to the sequence. */ - public SequenceBuilder addValue(VariableValue value) { - values.add(value); - return this; - } - - /** Adds a value to the sequence. */ - public SequenceBuilder addValue(VariableValueBuilder value) { - Preconditions.checkArgument(value != null, "Cannot use null builder for a sequence value"); - values.add(value.build()); - return this; - } - - /** Returns an immutable sequence. */ - @Override - public Sequence build() { - return new Sequence(values.build()); - } - } - - /** Builder for StructureValue. */ - public static class StructureBuilder implements VariableValueBuilder { - - private final ImmutableMap.Builder<String, VariableValue> fields = ImmutableMap.builder(); - - /** Adds a field to the structure. */ - public StructureBuilder addField(String name, VariableValue value) { - fields.put(name, value); - return this; - } - - /** Adds a field to the structure. */ - public StructureBuilder addField(String name, VariableValueBuilder valueBuilder) { - Preconditions.checkArgument( - valueBuilder != null, - "Cannot use null builder to get a field value for field '%s'", - name); - fields.put(name, valueBuilder.build()); - return this; - } - - /** Adds a field to the structure. */ - public StructureBuilder addField(String name, String value) { - fields.put(name, new StringValue(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; - } - - /** Returns an immutable structure. */ - @Override - public StructureValue build() { - return new StructureValue(fields.build()); - } - } - - /** - * Lazily computed string sequence. Exists as a memory optimization. Make sure the {@param - * supplier} doesn't capture anything that shouldn't outlive analysis phase (e.g. {@link - * RuleContext}). - */ - @AutoCodec - @VisibleForSerialization - static final class LazyStringSequence extends VariableValueAdapter { - private final Supplier<ImmutableList<String>> supplier; - - @VisibleForSerialization - LazyStringSequence(Supplier<ImmutableList<String>> supplier) { - this.supplier = Preconditions.checkNotNull(supplier); - } - - @Override - public Iterable<? extends VariableValue> getSequenceValue(String variableName) { - return supplier - .get() - .stream() - .map(flag -> new StringValue(flag)) - .collect(ImmutableList.toImmutableList()); - } - - @Override - public String getVariableTypeName() { - return Sequence.SEQUENCE_VARIABLE_TYPE_NAME; - } - - @Override - public boolean isTruthy() { - return !supplier.get().isEmpty(); - } - } - - /** - * A sequence of structure values. Exists as a memory optimization - a typical build can contain - * millions of feature values, so getting rid of the overhead of {@code StructureValue} objects - * significantly reduces memory overhead. - */ - @Immutable - @AutoCodec - public static class LibraryToLinkValue extends VariableValueAdapter { - public static final String OBJECT_FILES_FIELD_NAME = "object_files"; - public static final String NAME_FIELD_NAME = "name"; - public static final String TYPE_FIELD_NAME = "type"; - public static final String IS_WHOLE_ARCHIVE_FIELD_NAME = "is_whole_archive"; - - private static final String LIBRARY_TO_LINK_VARIABLE_TYPE_NAME = "structure (LibraryToLink)"; - - @VisibleForSerialization - enum Type { - OBJECT_FILE("object_file"), - OBJECT_FILE_GROUP("object_file_group"), - INTERFACE_LIBRARY("interface_library"), - STATIC_LIBRARY("static_library"), - DYNAMIC_LIBRARY("dynamic_library"), - VERSIONED_DYNAMIC_LIBRARY("versioned_dynamic_library"); - - private final String name; - - Type(String name) { - this.name = name; - } - } - - private final String name; - private final ImmutableList<Artifact> objectFiles; - private final boolean isWholeArchive; - private final Type type; - - public static LibraryToLinkValue forDynamicLibrary(String name) { - return new LibraryToLinkValue( - Preconditions.checkNotNull(name), null, false, Type.DYNAMIC_LIBRARY); - } - - public static LibraryToLinkValue forVersionedDynamicLibrary( - String name) { - return new LibraryToLinkValue( - Preconditions.checkNotNull(name), null, false, Type.VERSIONED_DYNAMIC_LIBRARY); - } - - public static LibraryToLinkValue forInterfaceLibrary(String name) { - return new LibraryToLinkValue( - Preconditions.checkNotNull(name), null, false, Type.INTERFACE_LIBRARY); - } - - public static LibraryToLinkValue forStaticLibrary(String name, boolean isWholeArchive) { - return new LibraryToLinkValue( - Preconditions.checkNotNull(name), null, isWholeArchive, Type.STATIC_LIBRARY); - } - - public static LibraryToLinkValue forObjectFile(String name, boolean isWholeArchive) { - return new LibraryToLinkValue( - Preconditions.checkNotNull(name), null, isWholeArchive, Type.OBJECT_FILE); - } - - public static LibraryToLinkValue forObjectFileGroup( - ImmutableList<Artifact> objects, boolean isWholeArchive) { - Preconditions.checkNotNull(objects); - Preconditions.checkArgument(!objects.isEmpty()); - return new LibraryToLinkValue(null, objects, isWholeArchive, Type.OBJECT_FILE_GROUP); - } - - @VisibleForSerialization - LibraryToLinkValue( - String name, ImmutableList<Artifact> objectFiles, boolean isWholeArchive, Type type) { - this.name = name; - this.objectFiles = objectFiles; - this.isWholeArchive = isWholeArchive; - this.type = type; - } - - @Override - public VariableValue getFieldValue( - String variableName, String field, @Nullable ArtifactExpander expander) { - Preconditions.checkNotNull(field); - if (NAME_FIELD_NAME.equals(field) && !type.equals(Type.OBJECT_FILE_GROUP)) { - return new StringValue(name); - } else if (OBJECT_FILES_FIELD_NAME.equals(field) && type.equals(Type.OBJECT_FILE_GROUP)) { - ImmutableList.Builder<String> expandedObjectFiles = ImmutableList.builder(); - for (Artifact objectFile : objectFiles) { - if (objectFile.isTreeArtifact() && (expander != null)) { - List<Artifact> artifacts = new ArrayList<>(); - expander.expand(objectFile, artifacts); - expandedObjectFiles.addAll( - Iterables.transform(artifacts, artifact -> artifact.getExecPathString())); - } else { - expandedObjectFiles.add(objectFile.getExecPathString()); - } - } - return new StringSequence(expandedObjectFiles.build()); - } else if (TYPE_FIELD_NAME.equals(field)) { - return new StringValue(type.name); - } else if (IS_WHOLE_ARCHIVE_FIELD_NAME.equals(field)) { - return new IntegerValue(isWholeArchive ? 1 : 0); - } else { - return null; - } - } - - @Override - public String getVariableTypeName() { - return LIBRARY_TO_LINK_VARIABLE_TYPE_NAME; - } - - @Override - public boolean isTruthy() { - return true; - } - } - - /** Sequence of arbitrary VariableValue objects. */ - @Immutable - @AutoCodec - @VisibleForSerialization - static final class Sequence extends VariableValueAdapter { - private static final String SEQUENCE_VARIABLE_TYPE_NAME = "sequence"; - - private final ImmutableList<VariableValue> values; - - public Sequence(ImmutableList<VariableValue> values) { - this.values = values; - } - - @Override - public Iterable<? extends VariableValue> getSequenceValue(String variableName) { - return values; - } - - @Override - public String getVariableTypeName() { - return SEQUENCE_VARIABLE_TYPE_NAME; - } - - @Override - public boolean isTruthy() { - return values.isEmpty(); - } - } - - /** - * A sequence of structure values. Exists as a memory optimization - a typical build can contain - * millions of feature values, so getting rid of the overhead of {@code StructureValue} objects - * significantly reduces memory overhead. - */ - @Immutable - @AutoCodec - @VisibleForSerialization - static final class StructureSequence extends VariableValueAdapter { - private final ImmutableList<ImmutableMap<String, VariableValue>> values; - - @VisibleForSerialization - StructureSequence(ImmutableList<ImmutableMap<String, VariableValue>> values) { - Preconditions.checkNotNull(values); - this.values = values; - } - - @Override - public Iterable<? extends VariableValue> getSequenceValue(String variableName) { - final ImmutableList.Builder<VariableValue> sequences = ImmutableList.builder(); - for (ImmutableMap<String, VariableValue> value : values) { - sequences.add(new StructureValue(value)); - } - return sequences.build(); - } - - @Override - public String getVariableTypeName() { - return Sequence.SEQUENCE_VARIABLE_TYPE_NAME; - } - - @Override - public boolean isTruthy() { - return !values.isEmpty(); - } - } - - /** - * A sequence of simple string values. Exists as a memory optimization - a typical build can - * contain millions of feature values, so getting rid of the overhead of {@code StringValue} - * objects significantly reduces memory overhead. - */ - @Immutable - @AutoCodec - static final class StringSequence extends VariableValueAdapter { - private final Iterable<String> values; - - public StringSequence(Iterable<String> values) { - Preconditions.checkNotNull(values); - this.values = values; - } - - @Override - public Iterable<? extends VariableValue> getSequenceValue(String variableName) { - final ImmutableList.Builder<VariableValue> sequences = ImmutableList.builder(); - for (String value : values) { - sequences.add(new StringValue(value)); - } - return sequences.build(); - } - - @Override - public String getVariableTypeName() { - return Sequence.SEQUENCE_VARIABLE_TYPE_NAME; - } - - @Override - public boolean isTruthy() { - return !Iterables.isEmpty(values); - } - } - - /** - * Single structure value. Be careful not to create sequences of single structures, as the - * memory overhead is prohibitively big. Use optimized {@link StructureSequence} instead. - */ - @Immutable - @AutoCodec - @VisibleForSerialization - static final class StructureValue extends VariableValueAdapter { - private static final String STRUCTURE_VARIABLE_TYPE_NAME = "structure"; - - private final ImmutableMap<String, VariableValue> value; - - public StructureValue(ImmutableMap<String, VariableValue> value) { - this.value = value; - } - - @Override - public VariableValue getFieldValue( - String variableName, String field, @Nullable ArtifactExpander expander) { - if (value.containsKey(field)) { - return value.get(field); - } else { - return null; - } - } - - @Override - public String getVariableTypeName() { - return STRUCTURE_VARIABLE_TYPE_NAME; - } - - @Override - public boolean isTruthy() { - return !value.isEmpty(); - } - } - - /** - * The leaves in the variable sequence node tree are simple string values. Note that this should - * never live outside of {@code expand}, as the object overhead is prohibitively expensive. - */ - @Immutable - @AutoCodec - @VisibleForSerialization - static final class StringValue extends VariableValueAdapter { - private static final String STRING_VARIABLE_TYPE_NAME = "string"; - - private final String value; - - public StringValue(String value) { - Preconditions.checkNotNull(value, "Cannot create StringValue from null"); - this.value = value; - } - - @Override - public String getStringValue(String variableName) { - return value; - } - - @Override - public String getVariableTypeName() { - return STRING_VARIABLE_TYPE_NAME; - } - - @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 - @AutoCodec - static final class IntegerValue extends VariableValueAdapter { - private static final String INTEGER_VALUE_TYPE_NAME = "integer"; - private final int value; - - public IntegerValue(int value) { - this.value = value; - } - - @Override - public String getStringValue(String variableName) { - return Integer.toString(value); - } - - @Override - public String getVariableTypeName() { - return INTEGER_VALUE_TYPE_NAME; - } - - @Override - public boolean isTruthy() { - return value != 0; - } - } - - /** - * Builder for {@code Variables}. - */ - // TODO(b/65472725): Forbid sequences with empty string in them. - public static class Builder { - private final Map<String, VariableValue> variablesMap = new LinkedHashMap<>(); - private final Map<String, String> stringVariablesMap = new LinkedHashMap<>(); - private final Variables parent; - - public Builder() { - parent = null; - } - - public Builder(@Nullable Variables parent) { - this.parent = parent; - } - - /** Add an integer variable that expands {@code name} to {@code value}. */ - public Builder addIntegerVariable(String name, int value) { - variablesMap.put(name, new IntegerValue(value)); - return this; - } - - /** Add a string variable that expands {@code name} to {@code value}. */ - public Builder addStringVariable(String name, String value) { - checkVariableNotPresentAlready(name); - Preconditions.checkNotNull( - value, "Cannot set null as a value for variable '%s'", name); - stringVariablesMap.put(name, value); - return this; - } - - /** Overrides a variable to expands {@code name} to {@code value} instead. */ - public Builder overrideStringVariable(String name, String value) { - Preconditions.checkNotNull( - value, "Cannot set null as a value for variable '%s'", name); - stringVariablesMap.put(name, value); - return this; - } - - /** Overrides a variable to expands {@code name} to {@code value} instead. */ - public Builder overrideLazyStringSequenceVariable( - String name, Supplier<ImmutableList<String>> supplier) { - Preconditions.checkNotNull(supplier, "Cannot set null as a value for variable '%s'", name); - variablesMap.put(name, new LazyStringSequence(supplier)); - return this; - } - - /** - * Add a sequence variable that expands {@code name} to {@code values}. - * - * <p>Accepts values as ImmutableSet. As ImmutableList has smaller memory footprint, we copy - * the values into a new list. - */ - public Builder addStringSequenceVariable(String name, ImmutableSet<String> values) { - checkVariableNotPresentAlready(name); - Preconditions.checkNotNull(values, "Cannot set null as a value for variable '%s'", name); - ImmutableList.Builder<String> builder = ImmutableList.builder(); - builder.addAll(values); - variablesMap.put(name, new StringSequence(builder.build())); - return this; - } - - /** - * Add a sequence variable that expands {@code name} to {@code values}. - * - * <p>Accepts values as NestedSet. Nested set is stored directly, not cloned, not flattened. - */ - public Builder addStringSequenceVariable(String name, NestedSet<String> values) { - checkVariableNotPresentAlready(name); - Preconditions.checkNotNull(values, "Cannot set null as a value for variable '%s'", name); - variablesMap.put(name, new StringSequence(values)); - return this; - } - - /** - * Add a sequence variable that expands {@code name} to {@code values}. - * - * <p>Accepts values as Iterable. The iterable is stored directly, not cloned, not iterated. - * Be mindful of memory consumption of the particular Iterable. Prefer ImmutableList, or - * be sure that the iterable always returns the same elements in the same order, without any - * side effects. - */ - public Builder addStringSequenceVariable(String name, Iterable<String> values) { - checkVariableNotPresentAlready(name); - Preconditions.checkNotNull(values, "Cannot set null as a value for variable '%s'", name); - variablesMap.put(name, new StringSequence(values)); - return this; - } - - public Builder addLazyStringSequenceVariable( - String name, Supplier<ImmutableList<String>> supplier) { - checkVariableNotPresentAlready(name); - Preconditions.checkNotNull(supplier, "Cannot set null as a value for variable '%s'", name); - variablesMap.put(name, new LazyStringSequence(supplier)); - return this; - } - - /** - * Add a variable built using {@code VariableValueBuilder} api that expands {@code name} to - * the value returned by the {@code builder}. - */ - public Builder addCustomBuiltVariable(String name, Variables.VariableValueBuilder builder) { - checkVariableNotPresentAlready(name); - Preconditions.checkNotNull( - builder, - "Cannot use null builder to get variable value for variable '%s'", - name); - variablesMap.put(name, builder.build()); - return this; - } - - /** Add all string variables in a map. */ - public Builder addAllStringVariables(Map<String, String> variables) { - for (String name : variables.keySet()) { - checkVariableNotPresentAlready(name); - } - stringVariablesMap.putAll(variables); - return this; - } - - private void checkVariableNotPresentAlready(String name) { - Preconditions.checkNotNull(name); - Preconditions.checkArgument( - !variablesMap.containsKey(name), "Cannot overwrite variable '%s'", name); - Preconditions.checkArgument( - !stringVariablesMap.containsKey(name), "Cannot overwrite variable '%s'", name); - } - - /** - * Adds all variables to this builder. Cannot override already added variables. Does not add - * variables defined in the {@code parent} variables. - */ - public Builder addAllNonTransitive(Variables variables) { - SetView<String> intersection = - Sets.intersection(variables.getVariablesMap().keySet(), variablesMap.keySet()); - SetView<String> stringIntersection = - Sets.intersection( - variables.getStringVariablesMap().keySet(), stringVariablesMap.keySet()); - Preconditions.checkArgument( - intersection.isEmpty(), "Cannot overwrite existing variables: %s", intersection); - Preconditions.checkArgument( - stringIntersection.isEmpty(), - "Cannot overwrite existing variables: %s", stringIntersection); - this.variablesMap.putAll(variables.getVariablesMap()); - this.stringVariablesMap.putAll(variables.getStringVariablesMap()); - return this; - } - - /** @return a new {@link Variables} object. */ - public Variables build() { - if (stringVariablesMap.isEmpty() && variablesMap.size() == 1) { - return new SingleVariables( - parent, - variablesMap.keySet().iterator().next(), - variablesMap.values().iterator().next()); - } - return new MapVariables( - parent, ImmutableMap.copyOf(variablesMap), ImmutableMap.copyOf(stringVariablesMap)); - } - } - - /** - * A group of extra {@code Variable} instances, packaged as logic for adding to a - * {@code Builder} - */ - public interface VariablesExtension { - void addVariables(Builder builder); - } - } - - @Immutable - @AutoCodec.VisibleForSerialization - @AutoCodec - static class MapVariables extends Variables { - private final ImmutableMap<String, VariableValue> variablesMap; - private final ImmutableMap<String, String> stringVariablesMap; - private final Variables parent; - - @AutoCodec.Instantiator - @VisibleForSerialization - MapVariables( - Variables parent, - ImmutableMap<String, VariableValue> variablesMap, - ImmutableMap<String, String> stringVariablesMap) { - this.variablesMap = variablesMap; - this.stringVariablesMap = stringVariablesMap; - this.parent = parent; - } - - @Override - Map<String, VariableValue> getVariablesMap() { - return variablesMap; - } - - @Override - Map<String, String> getStringVariablesMap() { - return stringVariablesMap; - } - - @Override - VariableValue getNonStructuredVariable(String name) { - if (variablesMap.containsKey(name)) { - return variablesMap.get(name); - } - if (stringVariablesMap.containsKey(name)) { - return new StringValue(stringVariablesMap.get(name)); - } - - if (parent != null) { - return parent.getNonStructuredVariable(name); - } - - return null; - } - } - - @Immutable - private static class SingleVariables extends Variables { - private final Variables parent; - private final String name; - private final VariableValue variableValue; - - SingleVariables(Variables parent, String name, VariableValue variableValue) { - this.parent = parent; - this.name = name; - this.variableValue = variableValue; - } - - @Override - Map<String, VariableValue> getVariablesMap() { - return ImmutableMap.of(name, variableValue); - } - - @Override - Map<String, String> getStringVariablesMap() { - return ImmutableMap.of(); - } - - @Override - VariableValue getNonStructuredVariable(String name) { - if (this.name.equals(name)) { - return variableValue; - } - return parent == null ? null : parent.getNonStructuredVariable(name); - } - } - /** Captures the set of enabled features and action configs for a rule. */ @Immutable @AutoCodec @@ -2178,12 +1041,12 @@ } /** @return the command line for the given {@code action}. */ - public List<String> getCommandLine(String action, Variables variables) { + public List<String> getCommandLine(String action, CcToolchainVariables variables) { return getCommandLine(action, variables, null); } public List<String> getCommandLine( - String action, Variables variables, @Nullable ArtifactExpander expander) { + String action, CcToolchainVariables variables, @Nullable ArtifactExpander expander) { List<String> commandLine = new ArrayList<>(); if (actionIsConfigured(action)) { actionConfigByActionName @@ -2200,12 +1063,12 @@ /** @return the flags expanded for the given {@code action} in per-feature buckets. */ public ImmutableList<Pair<String, List<String>>> getPerFeatureExpansions( - String action, Variables variables) { + String action, CcToolchainVariables variables) { return getPerFeatureExpansions(action, variables, null); } public ImmutableList<Pair<String, List<String>>> getPerFeatureExpansions( - String action, Variables variables, @Nullable ArtifactExpander expander) { + String action, CcToolchainVariables variables, @Nullable ArtifactExpander expander) { ImmutableList.Builder<Pair<String, List<String>>> perFeatureExpansions = ImmutableList.builder(); if (actionIsConfigured(action)) { @@ -2226,7 +1089,7 @@ /** @return the environment variables (key/value pairs) for the given {@code action}. */ public ImmutableMap<String, String> getEnvironmentVariables( - String action, Variables variables) { + String action, CcToolchainVariables variables) { ImmutableMap.Builder<String, String> envBuilder = ImmutableMap.builder(); for (Feature feature : enabledFeatures) { feature.expandEnvironment(action, variables, enabledFeatureNames, envBuilder);
diff --git a/src/main/java/com/google/devtools/build/lib/rules/cpp/CcToolchainProvider.java b/src/main/java/com/google/devtools/build/lib/rules/cpp/CcToolchainProvider.java index 66650d0..df328fb 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/cpp/CcToolchainProvider.java +++ b/src/main/java/com/google/devtools/build/lib/rules/cpp/CcToolchainProvider.java
@@ -29,7 +29,6 @@ import com.google.devtools.build.lib.concurrent.ThreadSafety.Immutable; import com.google.devtools.build.lib.events.Location; 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.CppConfiguration.Tool; import com.google.devtools.build.lib.rules.cpp.FdoSupport.FdoMode; import com.google.devtools.build.lib.rules.cpp.Link.LinkingMode; @@ -78,7 +77,7 @@ CcCompilationContext.EMPTY, /* supportsParamFiles= */ false, /* supportsHeaderParsing= */ false, - Variables.EMPTY, + CcToolchainVariables.EMPTY, /* builtinIncludeFiles= */ ImmutableList.<Artifact>of(), /* coverageEnvironment= */ NestedSetBuilder.emptySet(Order.COMPILE_ORDER), /* linkDynamicLibraryTool= */ null, @@ -112,7 +111,7 @@ private final CcCompilationContext ccCompilationContext; private final boolean supportsParamFiles; private final boolean supportsHeaderParsing; - private final Variables buildVariables; + private final CcToolchainVariables buildVariables; private final ImmutableList<Artifact> builtinIncludeFiles; private final NestedSet<Pair<String, String>> coverageEnvironment; @Nullable private final Artifact linkDynamicLibraryTool; @@ -150,7 +149,7 @@ CcCompilationContext ccCompilationContext, boolean supportsParamFiles, boolean supportsHeaderParsing, - Variables buildVariables, + CcToolchainVariables buildVariables, ImmutableList<Artifact> builtinIncludeFiles, NestedSet<Pair<String, String>> coverageEnvironment, Artifact linkDynamicLibraryTool, @@ -548,7 +547,7 @@ } /** Returns build variables to be templated into the crosstool. */ - public Variables getBuildVariables() { + public CcToolchainVariables getBuildVariables() { return buildVariables; }
diff --git a/src/main/java/com/google/devtools/build/lib/rules/cpp/CcToolchainVariables.java b/src/main/java/com/google/devtools/build/lib/rules/cpp/CcToolchainVariables.java new file mode 100644 index 0000000..093837c --- /dev/null +++ b/src/main/java/com/google/devtools/build/lib/rules/cpp/CcToolchainVariables.java
@@ -0,0 +1,1204 @@ +// 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.rules.cpp; + +import com.google.common.base.Preconditions; +import com.google.common.base.Supplier; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.ImmutableSet; +import com.google.common.collect.Iterables; +import com.google.common.collect.Sets; +import com.google.common.collect.Sets.SetView; +import com.google.common.collect.Streams; +import com.google.devtools.build.lib.actions.Artifact; +import com.google.devtools.build.lib.actions.Artifact.ArtifactExpander; +import com.google.devtools.build.lib.analysis.RuleContext; +import com.google.devtools.build.lib.analysis.config.InvalidConfigurationException; +import com.google.devtools.build.lib.collect.nestedset.NestedSet; +import com.google.devtools.build.lib.concurrent.ThreadSafety.Immutable; +import com.google.devtools.build.lib.rules.cpp.CcToolchainFeatures.ExpansionException; +import com.google.devtools.build.lib.skyframe.serialization.autocodec.AutoCodec; +import com.google.devtools.build.lib.skyframe.serialization.autocodec.AutoCodec.VisibleForSerialization; +import com.google.devtools.build.lib.skylarkinterface.SkylarkModule; +import com.google.devtools.build.lib.skylarkinterface.SkylarkModuleCategory; +import java.io.Serializable; +import java.util.ArrayList; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.Stack; +import javax.annotation.Nullable; + +/** + * Configured build variables usable by the toolchain configuration. + * + * <p>TODO(b/32655571): Investigate cleanup once implicit iteration is not needed. Variables + * instance could serve as a top level View used to expand all flag_groups. + */ +@SkylarkModule( + name = "variables", + documented = false, + category = SkylarkModuleCategory.BUILTIN, + doc = "Class encapsulating build variables.") +public abstract class CcToolchainVariables { + + /** + * A piece of a single string value. + * + * <p>A single value can contain a combination of text and variables (for example "-f + * %{var1}/%{var2}"). We split the string into chunks, where each chunk represents either a text + * snippet, or a variable that is to be replaced. + */ + interface StringChunk { + /** + * Expands this chunk. + * + * @param variables binding of variable names to their values for a single flag expansion. + */ + String expand(CcToolchainVariables variables); + } + + /** A plain text chunk of a string (containing no variables). */ + @Immutable + @AutoCodec + @VisibleForSerialization + static class StringLiteralChunk implements StringChunk, Serializable { + private final String text; + + @VisibleForSerialization + StringLiteralChunk(String text) { + this.text = text; + } + + @Override + public String expand(CcToolchainVariables variables) { + return text; + } + + @Override + public boolean equals(@Nullable Object object) { + if (this == object) { + return true; + } + if (object instanceof StringLiteralChunk) { + StringLiteralChunk that = (StringLiteralChunk) object; + return text.equals(that.text); + } + return false; + } + + @Override + public int hashCode() { + return Objects.hash(text); + } + } + + /** A chunk of a string value into which a variable should be expanded. */ + @Immutable + @AutoCodec + static class VariableChunk implements StringChunk, Serializable { + private final String variableName; + + @VisibleForSerialization + VariableChunk(String variableName) { + this.variableName = variableName; + } + + @Override + public String expand(CcToolchainVariables variables) { + // We check all variables in FlagGroup.expandCommandLine. + // If we arrive here with the variable not being available, the variable was provided, but + // the nesting level of the NestedSequence was deeper than the nesting level of the flag + // groups. + return variables.getStringVariable(variableName); + } + + @Override + public boolean equals(@Nullable Object object) { + if (this == object) { + return true; + } + if (object instanceof VariableChunk) { + VariableChunk that = (VariableChunk) object; + return variableName.equals(that.variableName); + } + return false; + } + + @Override + public int hashCode() { + return Objects.hash(variableName); + } + } + + /** + * Parser for toolchain string values. + * + * <p>A string value contains a snippet of text supporting variable expansion. For example, a + * string value "-f %{var1}/%{var2}" will expand the values of the variables "var1" and "var2" in + * the corresponding places in the string. + * + * <p>The {@code StringValueParser} takes a string and parses it into a list of {@link + * StringChunk} objects, where each chunk represents either a snippet of text or a variable to be + * expanded. In the above example, the resulting chunks would be ["-f ", var1, "/", var2]. + * + * <p>In addition to the list of chunks, the {@link StringValueParser} also provides the set of + * variables necessary for the expansion of this flag via {@link #getUsedVariables}. + * + * <p>To get a literal percent character, "%%" can be used in the string. + */ + static class StringValueParser { + + private final String value; + + /** + * The current position in {@value} during parsing. + */ + private int current = 0; + + private final ImmutableList.Builder<StringChunk> chunks = ImmutableList.builder(); + private final ImmutableSet.Builder<String> usedVariables = ImmutableSet.builder(); + + StringValueParser(String value) throws InvalidConfigurationException { + this.value = value; + parse(); + } + + /** @return the parsed chunks for this string. */ + ImmutableList<StringChunk> getChunks() { + return chunks.build(); + } + + /** @return all variable names needed to expand this string. */ + ImmutableSet<String> getUsedVariables() { + return usedVariables.build(); + } + + /** + * Parses the string. + * + * @throws InvalidConfigurationException if there is a parsing error. + */ + private void parse() throws InvalidConfigurationException { + while (current < value.length()) { + if (atVariableStart()) { + parseVariableChunk(); + } else { + parseStringChunk(); + } + } + } + + /** + * @return whether the current position is the start of a variable. + */ + private boolean atVariableStart() { + // We parse a variable when value starts with '%', but not '%%'. + return value.charAt(current) == '%' + && (current + 1 >= value.length() || value.charAt(current + 1) != '%'); + } + + /** + * Parses a chunk of text until the next '%', which indicates either an escaped literal '%' or a + * variable. + */ + private void parseStringChunk() { + int start = current; + // We only parse string chunks starting with '%' if they also start with '%%'. + // In that case, we want to have a single '%' in the string, so we start at the second + // character. + // Note that for strings like "abc%%def" this will lead to two string chunks, the first + // referencing the subtring "abc", and a second referencing the substring "%def". + if (value.charAt(current) == '%') { + current = current + 1; + start = current; + } + current = value.indexOf('%', current + 1); + if (current == -1) { + current = value.length(); + } + final String text = value.substring(start, current); + chunks.add(new StringLiteralChunk(text)); + } + + /** + * Parses a variable to be expanded. + * + * @throws InvalidConfigurationException if there is a parsing error. + */ + private void parseVariableChunk() throws InvalidConfigurationException { + current = current + 1; + if (current >= value.length() || value.charAt(current) != '{') { + abort("expected '{'"); + } + current = current + 1; + if (current >= value.length() || value.charAt(current) == '}') { + abort("expected variable name"); + } + int end = value.indexOf('}', current); + final String name = value.substring(current, end); + usedVariables.add(name); + chunks.add(new VariableChunk(name)); + current = end + 1; + } + + /** + * @throws InvalidConfigurationException with the given error text, adding information about + * the current position in the string. + */ + private void abort(String error) throws InvalidConfigurationException { + throw new InvalidConfigurationException("Invalid toolchain configuration: " + error + + " at position " + current + " while parsing a flag containing '" + value + "'"); + } + } + + /** A flag or flag group that can be expanded under a set of variables. */ + interface Expandable { + /** + * Expands the current expandable under the given {@code view}, adding new flags to {@code + * commandLine}. + * + * <p>The {@code variables} controls which variables are visible during the expansion and allows + * to recursively expand nested flag groups. + */ + void expand( + CcToolchainVariables variables, + @Nullable ArtifactExpander expander, + List<String> commandLine); + } + + /** An empty variables instance. */ + public static final CcToolchainVariables EMPTY = new CcToolchainVariables.Builder().build(); + + /** + * Retrieves a {@link StringSequence} variable named {@code variableName} from {@code variables} + * and converts it into a list of plain strings. + * + * <p>Throws {@link ExpansionException} when the variable is not a {@link StringSequence}. + */ + public static final ImmutableList<String> toStringList( + CcToolchainVariables variables, String variableName) { + return Streams + .stream(variables.getSequenceVariable(variableName)) + .map(variable -> variable.getStringValue(variableName)) + .collect(ImmutableList.toImmutableList()); + } + + /** + * Get a variable value named @param name. Supports accessing fields in structures (e.g. + * 'libraries_to_link.interface_libraries') + * + * @throws ExpansionException when no such variable or no such field are present, or when + * accessing a field of non-structured variable + */ + VariableValue getVariable(String name) { + return lookupVariable(name, /* throwOnMissingVariable= */ true, /* expander= */ null); + } + + VariableValue getVariable(String name, @Nullable ArtifactExpander expander) { + return lookupVariable(name, /* throwOnMissingVariable= */ true, expander); + } + + /** + * Lookup a variable named @param name or return a reason why the variable was not found. + * Supports accessing fields in structures. + * + * @return Pair<VariableValue, String> returns either (variable value, null) or (null, string + * reason why variable was not found) + */ + private VariableValue lookupVariable( + String name, boolean throwOnMissingVariable, @Nullable ArtifactExpander expander) { + VariableValue nonStructuredVariable = getNonStructuredVariable(name); + if (nonStructuredVariable != null) { + return nonStructuredVariable; + } + VariableValue structuredVariable = + getStructureVariable(name, throwOnMissingVariable, expander); + if (structuredVariable != null) { + return structuredVariable; + } else if (throwOnMissingVariable) { + throw new ExpansionException( + String.format( + "Invalid toolchain configuration: Cannot find variable named '%s'.", name)); + } else { + return null; + } + } + + private VariableValue getStructureVariable( + String name, boolean throwOnMissingVariable, @Nullable ArtifactExpander expander) { + if (!name.contains(".")) { + return null; + } + + Stack<String> fieldsToAccess = new Stack<>(); + String structPath = name; + VariableValue variable; + + do { + fieldsToAccess.push(structPath.substring(structPath.lastIndexOf('.') + 1)); + structPath = structPath.substring(0, structPath.lastIndexOf('.')); + variable = getNonStructuredVariable(structPath); + } while (variable == null && structPath.contains(".")); + + if (variable == null) { + return null; + } + + while (!fieldsToAccess.empty()) { + String field = fieldsToAccess.pop(); + variable = variable.getFieldValue(structPath, field, expander); + if (variable == null) { + if (throwOnMissingVariable) { + throw new ExpansionException( + String.format( + "Invalid toolchain configuration: Cannot expand variable '%s.%s': structure %s " + + "doesn't have a field named '%s'", + structPath, field, structPath, field)); + } else { + return null; + } + } + } + return variable; + } + + public String getStringVariable(String variableName) { + return getVariable(variableName, /* expander= */ null).getStringValue(variableName); + } + + public Iterable<? extends VariableValue> getSequenceVariable(String variableName) { + return getVariable(variableName, /* expander= */ null).getSequenceValue(variableName); + } + + public Iterable<? extends VariableValue> getSequenceVariable( + String variableName, @Nullable ArtifactExpander expander) { + return getVariable(variableName, expander).getSequenceValue(variableName); + } + + /** Returns whether {@code variable} is set. */ + boolean isAvailable(String variable) { + return isAvailable(variable, /* expander= */ null); + } + + boolean isAvailable(String variable, @Nullable ArtifactExpander expander) { + return lookupVariable(variable, /* throwOnMissingVariable= */ false, expander) != null; + } + + abstract Map<String, VariableValue> getVariablesMap(); + + abstract Map<String, String> getStringVariablesMap(); + + @Nullable + abstract VariableValue getNonStructuredVariable(String name); + + /** + * Value of a build variable exposed to the CROSSTOOL used for flag expansion. + * + * <p>{@link VariableValue} represent either primitive values or an arbitrarily deeply nested + * recursive structures or sequences. Since there are builds with millions of values, some + * implementations might exist only to optimize memory usage. + * + * <p>Implementations must be immutable and without any side-effects. They will be expanded and + * queried multiple times. + */ + interface VariableValue { + /** + * Returns string value of the variable, if the variable type can be converted to string (e.g. + * StringValue), or throw exception if it cannot (e.g. Sequence). + * + * @param variableName name of the variable value at hand, for better exception message. + */ + String getStringValue(String variableName); + + /** + * Returns Iterable value of the variable, if the variable type can be converted to a Iterable + * (e.g. Sequence), or throw exception if it cannot (e.g. StringValue). + * + * @param variableName name of the variable value at hand, for better exception message. + */ + Iterable<? extends VariableValue> getSequenceValue(String variableName); + + /** + * Returns value of the field, if the variable is of struct type or throw exception if it is + * not or no such field exists. + * + * @param variableName name of the variable value at hand, for better exception message. + */ + VariableValue getFieldValue(String variableName, String field); + + VariableValue getFieldValue( + String variableName, String field, @Nullable ArtifactExpander expander); + + /** Returns true if the variable is truthy */ + boolean isTruthy(); + } + + /** + * Adapter for {@link VariableValue} predefining error handling methods. Override {@link + * #getVariableTypeName()}, {@link #isTruthy()}, and one of {@link #getFieldValue(String, + * String)}, {@link #getSequenceValue(String)}, or {@link #getStringValue(String)}, and you'll + * get error handling for the other methods for free. + */ + abstract static class VariableValueAdapter implements VariableValue { + + /** Returns human-readable variable type name to be used in error messages. */ + public abstract String getVariableTypeName(); + + @Override + public abstract boolean isTruthy(); + + @Override + public VariableValue getFieldValue(String variableName, String field) { + return getFieldValue(variableName, field, /* expander= */ null); + } + + @Override + public VariableValue getFieldValue( + String variableName, String field, @Nullable ArtifactExpander expander) { + throw new ExpansionException( + String.format( + "Invalid toolchain configuration: Cannot expand variable '%s.%s': variable '%s' is " + + "%s, expected structure", + variableName, field, variableName, getVariableTypeName())); + } + + @Override + public String getStringValue(String variableName) { + throw new ExpansionException( + String.format( + "Invalid toolchain configuration: Cannot expand variable '%s': expected string, " + + "found %s", + variableName, getVariableTypeName())); + } + + @Override + public Iterable<? extends VariableValue> getSequenceValue(String variableName) { + throw new ExpansionException( + String.format( + "Invalid toolchain configuration: Cannot expand variable '%s': expected sequence, " + + "found %s", + variableName, getVariableTypeName())); + } + } + + /** Interface for VariableValue builders */ + public interface VariableValueBuilder { + VariableValue build(); + } + + /** Builder for StringSequence. */ + public static class StringSequenceBuilder implements VariableValueBuilder { + + private final ImmutableList.Builder<String> values = ImmutableList.builder(); + + /** Adds a value to the sequence. */ + public StringSequenceBuilder addValue(String value) { + values.add(value); + return this; + } + + /** Returns an immutable string sequence. */ + @Override + public StringSequence build() { + return new StringSequence(values.build()); + } + } + + /** Builder for Sequence. */ + public static class SequenceBuilder implements VariableValueBuilder { + + private final ImmutableList.Builder<VariableValue> values = ImmutableList.builder(); + + /** Adds a value to the sequence. */ + public SequenceBuilder addValue(VariableValue value) { + values.add(value); + return this; + } + + /** Adds a value to the sequence. */ + public SequenceBuilder addValue(VariableValueBuilder value) { + Preconditions.checkArgument(value != null, "Cannot use null builder for a sequence value"); + values.add(value.build()); + return this; + } + + /** Returns an immutable sequence. */ + @Override + public Sequence build() { + return new Sequence(values.build()); + } + } + + /** Builder for StructureValue. */ + public static class StructureBuilder implements VariableValueBuilder { + + private final ImmutableMap.Builder<String, VariableValue> fields = ImmutableMap.builder(); + + /** Adds a field to the structure. */ + public StructureBuilder addField(String name, VariableValue value) { + fields.put(name, value); + return this; + } + + /** Adds a field to the structure. */ + public StructureBuilder addField(String name, VariableValueBuilder valueBuilder) { + Preconditions.checkArgument( + valueBuilder != null, + "Cannot use null builder to get a field value for field '%s'", + name); + fields.put(name, valueBuilder.build()); + return this; + } + + /** Adds a field to the structure. */ + public StructureBuilder addField(String name, String value) { + fields.put(name, new StringValue(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; + } + + /** Returns an immutable structure. */ + @Override + public StructureValue build() { + return new StructureValue(fields.build()); + } + } + + /** + * Lazily computed string sequence. Exists as a memory optimization. Make sure the {@param + * supplier} doesn't capture anything that shouldn't outlive analysis phase (e.g. {@link + * RuleContext}). + */ + @AutoCodec + @VisibleForSerialization + static final class LazyStringSequence extends VariableValueAdapter { + private final Supplier<ImmutableList<String>> supplier; + + @VisibleForSerialization + LazyStringSequence(Supplier<ImmutableList<String>> supplier) { + this.supplier = Preconditions.checkNotNull(supplier); + } + + @Override + public Iterable<? extends VariableValue> getSequenceValue(String variableName) { + return supplier + .get() + .stream() + .map(flag -> new StringValue(flag)) + .collect(ImmutableList.toImmutableList()); + } + + @Override + public String getVariableTypeName() { + return Sequence.SEQUENCE_VARIABLE_TYPE_NAME; + } + + @Override + public boolean isTruthy() { + return !supplier.get().isEmpty(); + } + } + + /** + * A sequence of structure values. Exists as a memory optimization - a typical build can contain + * millions of feature values, so getting rid of the overhead of {@code StructureValue} objects + * significantly reduces memory overhead. + */ + @Immutable + @AutoCodec + public static class LibraryToLinkValue extends VariableValueAdapter { + public static final String OBJECT_FILES_FIELD_NAME = "object_files"; + public static final String NAME_FIELD_NAME = "name"; + public static final String TYPE_FIELD_NAME = "type"; + public static final String IS_WHOLE_ARCHIVE_FIELD_NAME = "is_whole_archive"; + + private static final String LIBRARY_TO_LINK_VARIABLE_TYPE_NAME = "structure (LibraryToLink)"; + + @VisibleForSerialization + enum Type { + OBJECT_FILE("object_file"), + OBJECT_FILE_GROUP("object_file_group"), + INTERFACE_LIBRARY("interface_library"), + STATIC_LIBRARY("static_library"), + DYNAMIC_LIBRARY("dynamic_library"), + VERSIONED_DYNAMIC_LIBRARY("versioned_dynamic_library"); + + private final String name; + + Type(String name) { + this.name = name; + } + } + + private final String name; + private final ImmutableList<Artifact> objectFiles; + private final boolean isWholeArchive; + private final Type type; + + public static LibraryToLinkValue forDynamicLibrary(String name) { + return new LibraryToLinkValue( + Preconditions.checkNotNull(name), + /* objectFiles= */ null, + /* isWholeArchive= */ false, + Type.DYNAMIC_LIBRARY); + } + + public static LibraryToLinkValue forVersionedDynamicLibrary( + String name) { + return new LibraryToLinkValue( + Preconditions.checkNotNull(name), + /* objectFiles= */ null, + /* isWholeArchive= */ false, + Type.VERSIONED_DYNAMIC_LIBRARY); + } + + public static LibraryToLinkValue forInterfaceLibrary(String name) { + return new LibraryToLinkValue( + Preconditions.checkNotNull(name), + /* objectFiles= */ null, + /* isWholeArchive= */ false, + Type.INTERFACE_LIBRARY); + } + + public static LibraryToLinkValue forStaticLibrary(String name, boolean isWholeArchive) { + return new LibraryToLinkValue( + Preconditions.checkNotNull(name), + /* objectFiles= */ null, + isWholeArchive, + Type.STATIC_LIBRARY); + } + + public static LibraryToLinkValue forObjectFile(String name, boolean isWholeArchive) { + return new LibraryToLinkValue( + Preconditions.checkNotNull(name), + /* objectFiles= */ null, + isWholeArchive, + Type.OBJECT_FILE); + } + + public static LibraryToLinkValue forObjectFileGroup( + ImmutableList<Artifact> objects, boolean isWholeArchive) { + Preconditions.checkNotNull(objects); + Preconditions.checkArgument(!objects.isEmpty()); + return new LibraryToLinkValue( + /* name= */ null, objects, isWholeArchive, Type.OBJECT_FILE_GROUP); + } + + @VisibleForSerialization + LibraryToLinkValue( + String name, ImmutableList<Artifact> objectFiles, boolean isWholeArchive, Type type) { + this.name = name; + this.objectFiles = objectFiles; + this.isWholeArchive = isWholeArchive; + this.type = type; + } + + @Override + public VariableValue getFieldValue( + String variableName, String field, @Nullable ArtifactExpander expander) { + Preconditions.checkNotNull(field); + if (NAME_FIELD_NAME.equals(field) && !type.equals(Type.OBJECT_FILE_GROUP)) { + return new StringValue(name); + } else if (OBJECT_FILES_FIELD_NAME.equals(field) && type.equals(Type.OBJECT_FILE_GROUP)) { + ImmutableList.Builder<String> expandedObjectFiles = ImmutableList.builder(); + for (Artifact objectFile : objectFiles) { + if (objectFile.isTreeArtifact() && (expander != null)) { + List<Artifact> artifacts = new ArrayList<>(); + expander.expand(objectFile, artifacts); + expandedObjectFiles.addAll( + Iterables.transform(artifacts, artifact -> artifact.getExecPathString())); + } else { + expandedObjectFiles.add(objectFile.getExecPathString()); + } + } + return new StringSequence(expandedObjectFiles.build()); + } else if (TYPE_FIELD_NAME.equals(field)) { + return new StringValue(type.name); + } else if (IS_WHOLE_ARCHIVE_FIELD_NAME.equals(field)) { + return new IntegerValue(isWholeArchive ? 1 : 0); + } else { + return null; + } + } + + @Override + public String getVariableTypeName() { + return LIBRARY_TO_LINK_VARIABLE_TYPE_NAME; + } + + @Override + public boolean isTruthy() { + return true; + } + } + + /** Sequence of arbitrary VariableValue objects. */ + @Immutable + @AutoCodec + @VisibleForSerialization + static final class Sequence extends VariableValueAdapter { + private static final String SEQUENCE_VARIABLE_TYPE_NAME = "sequence"; + + private final ImmutableList<VariableValue> values; + + public Sequence(ImmutableList<VariableValue> values) { + this.values = values; + } + + @Override + public Iterable<? extends VariableValue> getSequenceValue(String variableName) { + return values; + } + + @Override + public String getVariableTypeName() { + return SEQUENCE_VARIABLE_TYPE_NAME; + } + + @Override + public boolean isTruthy() { + return values.isEmpty(); + } + } + + /** + * A sequence of structure values. Exists as a memory optimization - a typical build can contain + * millions of feature values, so getting rid of the overhead of {@code StructureValue} objects + * significantly reduces memory overhead. + */ + @Immutable + @AutoCodec + @VisibleForSerialization + static final class StructureSequence extends VariableValueAdapter { + private final ImmutableList<ImmutableMap<String, VariableValue>> values; + + @VisibleForSerialization + StructureSequence(ImmutableList<ImmutableMap<String, VariableValue>> values) { + Preconditions.checkNotNull(values); + this.values = values; + } + + @Override + public Iterable<? extends VariableValue> getSequenceValue(String variableName) { + final ImmutableList.Builder<VariableValue> sequences = ImmutableList.builder(); + for (ImmutableMap<String, VariableValue> value : values) { + sequences.add(new StructureValue(value)); + } + return sequences.build(); + } + + @Override + public String getVariableTypeName() { + return Sequence.SEQUENCE_VARIABLE_TYPE_NAME; + } + + @Override + public boolean isTruthy() { + return !values.isEmpty(); + } + } + + /** + * A sequence of simple string values. Exists as a memory optimization - a typical build can + * contain millions of feature values, so getting rid of the overhead of {@code StringValue} + * objects significantly reduces memory overhead. + */ + @Immutable + @AutoCodec + static final class StringSequence extends VariableValueAdapter { + private final Iterable<String> values; + + public StringSequence(Iterable<String> values) { + Preconditions.checkNotNull(values); + this.values = values; + } + + @Override + public Iterable<? extends VariableValue> getSequenceValue(String variableName) { + final ImmutableList.Builder<VariableValue> sequences = ImmutableList.builder(); + for (String value : values) { + sequences.add(new StringValue(value)); + } + return sequences.build(); + } + + @Override + public String getVariableTypeName() { + return Sequence.SEQUENCE_VARIABLE_TYPE_NAME; + } + + @Override + public boolean isTruthy() { + return !Iterables.isEmpty(values); + } + } + + /** + * Single structure value. Be careful not to create sequences of single structures, as the + * memory overhead is prohibitively big. Use optimized {@link StructureSequence} instead. + */ + @Immutable + @AutoCodec + @VisibleForSerialization + static final class StructureValue extends VariableValueAdapter { + private static final String STRUCTURE_VARIABLE_TYPE_NAME = "structure"; + + private final ImmutableMap<String, VariableValue> value; + + public StructureValue(ImmutableMap<String, VariableValue> value) { + this.value = value; + } + + @Override + public VariableValue getFieldValue( + String variableName, String field, @Nullable ArtifactExpander expander) { + if (value.containsKey(field)) { + return value.get(field); + } else { + return null; + } + } + + @Override + public String getVariableTypeName() { + return STRUCTURE_VARIABLE_TYPE_NAME; + } + + @Override + public boolean isTruthy() { + return !value.isEmpty(); + } + } + + /** + * The leaves in the variable sequence node tree are simple string values. Note that this should + * never live outside of {@code expand}, as the object overhead is prohibitively expensive. + */ + @Immutable + @AutoCodec + @VisibleForSerialization + static final class StringValue extends VariableValueAdapter { + private static final String STRING_VARIABLE_TYPE_NAME = "string"; + + private final String value; + + public StringValue(String value) { + Preconditions.checkNotNull(value, "Cannot create StringValue from null"); + this.value = value; + } + + @Override + public String getStringValue(String variableName) { + return value; + } + + @Override + public String getVariableTypeName() { + return STRING_VARIABLE_TYPE_NAME; + } + + @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 + @AutoCodec + static final class IntegerValue extends VariableValueAdapter { + private static final String INTEGER_VALUE_TYPE_NAME = "integer"; + private final int value; + + public IntegerValue(int value) { + this.value = value; + } + + @Override + public String getStringValue(String variableName) { + return Integer.toString(value); + } + + @Override + public String getVariableTypeName() { + return INTEGER_VALUE_TYPE_NAME; + } + + @Override + public boolean isTruthy() { + return value != 0; + } + } + + /** + * Builder for {@code Variables}. + */ + // TODO(b/65472725): Forbid sequences with empty string in them. + public static class Builder { + private final Map<String, VariableValue> variablesMap = new LinkedHashMap<>(); + private final Map<String, String> stringVariablesMap = new LinkedHashMap<>(); + private final CcToolchainVariables parent; + + public Builder() { + parent = null; + } + + public Builder(@Nullable CcToolchainVariables parent) { + this.parent = parent; + } + + /** Add an integer variable that expands {@code name} to {@code value}. */ + public Builder addIntegerVariable(String name, int value) { + variablesMap.put(name, new IntegerValue(value)); + return this; + } + + /** Add a string variable that expands {@code name} to {@code value}. */ + public Builder addStringVariable(String name, String value) { + checkVariableNotPresentAlready(name); + Preconditions.checkNotNull( + value, "Cannot set null as a value for variable '%s'", name); + stringVariablesMap.put(name, value); + return this; + } + + /** Overrides a variable to expands {@code name} to {@code value} instead. */ + public Builder overrideStringVariable(String name, String value) { + Preconditions.checkNotNull( + value, "Cannot set null as a value for variable '%s'", name); + stringVariablesMap.put(name, value); + return this; + } + + /** Overrides a variable to expand {@code name} to {@code value} instead. */ + public Builder overrideLazyStringSequenceVariable( + String name, Supplier<ImmutableList<String>> supplier) { + Preconditions.checkNotNull(supplier, "Cannot set null as a value for variable '%s'", name); + variablesMap.put(name, new LazyStringSequence(supplier)); + return this; + } + + /** + * Add a sequence variable that expands {@code name} to {@code values}. + * + * <p>Accepts values as ImmutableSet. As ImmutableList has smaller memory footprint, we copy + * the values into a new list. + */ + public Builder addStringSequenceVariable(String name, ImmutableSet<String> values) { + checkVariableNotPresentAlready(name); + Preconditions.checkNotNull(values, "Cannot set null as a value for variable '%s'", name); + ImmutableList.Builder<String> builder = ImmutableList.builder(); + builder.addAll(values); + variablesMap.put(name, new StringSequence(builder.build())); + return this; + } + + /** + * Add a sequence variable that expands {@code name} to {@code values}. + * + * <p>Accepts values as NestedSet. Nested set is stored directly, not cloned, not flattened. + */ + public Builder addStringSequenceVariable(String name, NestedSet<String> values) { + checkVariableNotPresentAlready(name); + Preconditions.checkNotNull(values, "Cannot set null as a value for variable '%s'", name); + variablesMap.put(name, new StringSequence(values)); + return this; + } + + /** + * Add a sequence variable that expands {@code name} to {@code values}. + * + * <p>Accepts values as Iterable. The iterable is stored directly, not cloned, not iterated. + * Be mindful of memory consumption of the particular Iterable. Prefer ImmutableList, or + * be sure that the iterable always returns the same elements in the same order, without any + * side effects. + */ + public Builder addStringSequenceVariable(String name, Iterable<String> values) { + checkVariableNotPresentAlready(name); + Preconditions.checkNotNull(values, "Cannot set null as a value for variable '%s'", name); + variablesMap.put(name, new StringSequence(values)); + return this; + } + + public Builder addLazyStringSequenceVariable( + String name, Supplier<ImmutableList<String>> supplier) { + checkVariableNotPresentAlready(name); + Preconditions.checkNotNull(supplier, "Cannot set null as a value for variable '%s'", name); + variablesMap.put(name, new LazyStringSequence(supplier)); + return this; + } + + /** + * Add a variable built using {@code VariableValueBuilder} api that expands {@code name} to the + * value returned by the {@code builder}. + */ + public Builder addCustomBuiltVariable( + String name, CcToolchainVariables.VariableValueBuilder builder) { + checkVariableNotPresentAlready(name); + Preconditions.checkNotNull( + builder, + "Cannot use null builder to get variable value for variable '%s'", + name); + variablesMap.put(name, builder.build()); + return this; + } + + /** Add all string variables in a map. */ + public Builder addAllStringVariables(Map<String, String> variables) { + for (String name : variables.keySet()) { + checkVariableNotPresentAlready(name); + } + stringVariablesMap.putAll(variables); + return this; + } + + private void checkVariableNotPresentAlready(String name) { + Preconditions.checkNotNull(name); + Preconditions.checkArgument( + !variablesMap.containsKey(name), "Cannot overwrite variable '%s'", name); + Preconditions.checkArgument( + !stringVariablesMap.containsKey(name), "Cannot overwrite variable '%s'", name); + } + + /** + * Adds all variables to this builder. Cannot override already added variables. Does not add + * variables defined in the {@code parent} variables. + */ + public Builder addAllNonTransitive(CcToolchainVariables variables) { + SetView<String> intersection = + Sets.intersection(variables.getVariablesMap().keySet(), variablesMap.keySet()); + SetView<String> stringIntersection = + Sets.intersection( + variables.getStringVariablesMap().keySet(), stringVariablesMap.keySet()); + Preconditions.checkArgument( + intersection.isEmpty(), "Cannot overwrite existing variables: %s", intersection); + Preconditions.checkArgument( + stringIntersection.isEmpty(), + "Cannot overwrite existing variables: %s", stringIntersection); + this.variablesMap.putAll(variables.getVariablesMap()); + this.stringVariablesMap.putAll(variables.getStringVariablesMap()); + return this; + } + + /** @return a new {@link CcToolchainVariables} object. */ + public CcToolchainVariables build() { + if (stringVariablesMap.isEmpty() && variablesMap.size() == 1) { + return new SingleVariables( + parent, + variablesMap.keySet().iterator().next(), + variablesMap.values().iterator().next()); + } + return new MapVariables( + parent, ImmutableMap.copyOf(variablesMap), ImmutableMap.copyOf(stringVariablesMap)); + } + } + + /** + * A group of extra {@code Variable} instances, packaged as logic for adding to a + * {@code Builder} + */ + public interface VariablesExtension { + void addVariables(Builder builder); + } + + @Immutable + @AutoCodec.VisibleForSerialization + @AutoCodec + static class MapVariables extends CcToolchainVariables { + private final ImmutableMap<String, VariableValue> variablesMap; + private final ImmutableMap<String, String> stringVariablesMap; + private final CcToolchainVariables parent; + + @AutoCodec.Instantiator + @VisibleForSerialization + MapVariables( + CcToolchainVariables parent, + ImmutableMap<String, VariableValue> variablesMap, + ImmutableMap<String, String> stringVariablesMap) { + this.variablesMap = variablesMap; + this.stringVariablesMap = stringVariablesMap; + this.parent = parent; + } + + @Override + Map<String, VariableValue> getVariablesMap() { + return variablesMap; + } + + @Override + Map<String, String> getStringVariablesMap() { + return stringVariablesMap; + } + + @Override + VariableValue getNonStructuredVariable(String name) { + if (variablesMap.containsKey(name)) { + return variablesMap.get(name); + } + if (stringVariablesMap.containsKey(name)) { + return new StringValue(stringVariablesMap.get(name)); + } + + if (parent != null) { + return parent.getNonStructuredVariable(name); + } + + return null; + } + } + + @Immutable + static class SingleVariables extends CcToolchainVariables { + private final CcToolchainVariables parent; + private final String name; + private final VariableValue variableValue; + + SingleVariables(CcToolchainVariables parent, String name, VariableValue variableValue) { + this.parent = parent; + this.name = name; + this.variableValue = variableValue; + } + + @Override + Map<String, VariableValue> getVariablesMap() { + return ImmutableMap.of(name, variableValue); + } + + @Override + Map<String, String> getStringVariablesMap() { + return ImmutableMap.of(); + } + + @Override + VariableValue getNonStructuredVariable(String name) { + if (this.name.equals(name)) { + return variableValue; + } + return parent == null ? null : parent.getNonStructuredVariable(name); + } + } +}
diff --git a/src/main/java/com/google/devtools/build/lib/rules/cpp/CompileBuildVariables.java b/src/main/java/com/google/devtools/build/lib/rules/cpp/CompileBuildVariables.java index 166805d..3aa90dd 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/cpp/CompileBuildVariables.java +++ b/src/main/java/com/google/devtools/build/lib/rules/cpp/CompileBuildVariables.java
@@ -22,9 +22,8 @@ import com.google.devtools.build.lib.analysis.RuleContext; import com.google.devtools.build.lib.events.Location; 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.StringSequenceBuilder; -import com.google.devtools.build.lib.rules.cpp.CcToolchainFeatures.Variables.VariablesExtension; +import com.google.devtools.build.lib.rules.cpp.CcToolchainVariables.StringSequenceBuilder; +import com.google.devtools.build.lib.rules.cpp.CcToolchainVariables.VariablesExtension; import com.google.devtools.build.lib.syntax.EvalException; import com.google.devtools.build.lib.util.FileType; import com.google.devtools.build.lib.vfs.PathFragment; @@ -104,7 +103,7 @@ this.variableName = variableName; } - public static Variables setupVariablesOrReportRuleError( + public static CcToolchainVariables setupVariablesOrReportRuleError( RuleContext ruleContext, FeatureConfiguration featureConfiguration, CcToolchainProvider ccToolchainProvider, @@ -156,11 +155,11 @@ || CppFileTypes.CLIF_INPUT_PROTO.matches(sourceFile)); } catch (EvalException e) { ruleContext.ruleError(e.getMessage()); - return Variables.EMPTY; + return CcToolchainVariables.EMPTY; } } - public static Variables setupVariablesOrThrowEvalException( + public static CcToolchainVariables setupVariablesOrThrowEvalException( FeatureConfiguration featureConfiguration, CcToolchainProvider ccToolchainProvider, String sourceFile, @@ -191,8 +190,8 @@ Preconditions.checkNotNull(quoteIncludeDirs); Preconditions.checkNotNull(systemIncludeDirs); Preconditions.checkNotNull(defines); - Variables.Builder buildVariables = - new Variables.Builder(ccToolchainProvider.getBuildVariables()); + CcToolchainVariables.Builder buildVariables = + new CcToolchainVariables.Builder(ccToolchainProvider.getBuildVariables()); buildVariables.addStringSequenceVariable( USER_COMPILE_FLAGS.getVariableName(), userCompileFlags);
diff --git a/src/main/java/com/google/devtools/build/lib/rules/cpp/CompileCommandLine.java b/src/main/java/com/google/devtools/build/lib/rules/cpp/CompileCommandLine.java index 2d28909..878391f 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/cpp/CompileCommandLine.java +++ b/src/main/java/com/google/devtools/build/lib/rules/cpp/CompileCommandLine.java
@@ -19,7 +19,6 @@ import com.google.devtools.build.lib.actions.Artifact; import com.google.devtools.build.lib.rules.cpp.CcCommon.CoptsFilter; 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.CppCompileAction.DotdFile; import com.google.devtools.build.lib.skyframe.serialization.autocodec.AutoCodec; import com.google.devtools.build.lib.skyframe.serialization.autocodec.AutoCodec.VisibleForSerialization; @@ -35,7 +34,7 @@ private final Artifact sourceFile; private final CoptsFilter coptsFilter; private final FeatureConfiguration featureConfiguration; - private final CcToolchainFeatures.Variables variables; + private final CcToolchainVariables variables; private final String actionName; private final DotdFile dotdFile; @@ -45,7 +44,7 @@ Artifact sourceFile, CoptsFilter coptsFilter, FeatureConfiguration featureConfiguration, - CcToolchainFeatures.Variables variables, + CcToolchainVariables variables, String actionName, DotdFile dotdFile) { this.sourceFile = Preconditions.checkNotNull(sourceFile); @@ -81,8 +80,7 @@ * @param overwrittenVariables: Variables that will overwrite original build variables. When null, * unmodified original variables are used. */ - protected List<String> getArguments( - @Nullable CcToolchainFeatures.Variables overwrittenVariables) { + protected List<String> getArguments(@Nullable CcToolchainVariables overwrittenVariables) { List<String> commandLine = new ArrayList<>(); // first: The command name. @@ -93,14 +91,12 @@ return commandLine; } - public List<String> getCompilerOptions( - @Nullable CcToolchainFeatures.Variables overwrittenVariables) { + public List<String> getCompilerOptions(@Nullable CcToolchainVariables overwrittenVariables) { List<String> options = new ArrayList<>(); - CcToolchainFeatures.Variables updatedVariables = variables; + CcToolchainVariables updatedVariables = variables; if (variables != null && overwrittenVariables != null) { - CcToolchainFeatures.Variables.Builder variablesBuilder = - new CcToolchainFeatures.Variables.Builder(variables); + CcToolchainVariables.Builder variablesBuilder = new CcToolchainVariables.Builder(variables); variablesBuilder.addAllNonTransitive(overwrittenVariables); updatedVariables = variablesBuilder.build(); } @@ -131,7 +127,7 @@ return dotdFile; } - public Variables getVariables() { + public CcToolchainVariables getVariables() { return variables; } @@ -144,7 +140,7 @@ */ public ImmutableList<String> getCopts() { if (variables.isAvailable(CompileBuildVariables.USER_COMPILE_FLAGS.getVariableName())) { - return Variables.toStringList( + return CcToolchainVariables.toStringList( variables, CompileBuildVariables.USER_COMPILE_FLAGS.getVariableName()); } else { return ImmutableList.of(); @@ -164,7 +160,7 @@ private final Artifact sourceFile; private CoptsFilter coptsFilter; private FeatureConfiguration featureConfiguration; - private CcToolchainFeatures.Variables variables = Variables.EMPTY; + private CcToolchainVariables variables = CcToolchainVariables.EMPTY; private final String actionName; @Nullable private final DotdFile dotdFile; @@ -195,7 +191,7 @@ return this; } - public Builder setVariables(Variables variables) { + public Builder setVariables(CcToolchainVariables variables) { this.variables = variables; return this; }
diff --git a/src/main/java/com/google/devtools/build/lib/rules/cpp/CppCompileAction.java b/src/main/java/com/google/devtools/build/lib/rules/cpp/CppCompileAction.java index 9ff24cf..d5e692f 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/cpp/CppCompileAction.java +++ b/src/main/java/com/google/devtools/build/lib/rules/cpp/CppCompileAction.java
@@ -220,7 +220,7 @@ /** Used modules that are not transitively used through other topLevelModules. */ private Iterable<Artifact> topLevelModules = null; - private CcToolchainFeatures.Variables overwrittenVariables = null; + private CcToolchainVariables overwrittenVariables = null; /** * Creates a new action to compile C/C++ source files. @@ -260,7 +260,7 @@ ActionOwner owner, NestedSet<Artifact> allInputs, FeatureConfiguration featureConfiguration, - CcToolchainFeatures.Variables variables, + CcToolchainVariables variables, Artifact sourceFile, boolean shouldScanIncludes, boolean shouldPruneModules, @@ -371,7 +371,7 @@ Iterable<Artifact> additionalInputs, Collection<Artifact> usedModules, Iterable<Artifact> topLevelModules, - CcToolchainFeatures.Variables overwrittenVariables, + CcToolchainVariables overwrittenVariables, boolean needsDotdInputPruning, boolean needsIncludeValidation, IncludeProcessing includeProcessing, @@ -1021,16 +1021,14 @@ * Extracts all module (.pcm) files from potentialModules and returns a Variables object where * their exec paths are added to the value "module_files". */ - private static CcToolchainFeatures.Variables getOverwrittenVariables( - Iterable<Artifact> potentialModules) { + private static CcToolchainVariables getOverwrittenVariables(Iterable<Artifact> potentialModules) { ImmutableList.Builder<String> usedModulePaths = ImmutableList.builder(); for (Artifact input : potentialModules) { if (input.isFileType(CppFileTypes.CPP_MODULE)) { usedModulePaths.add(input.getExecPathString()); } } - CcToolchainFeatures.Variables.Builder variableBuilder = - new CcToolchainFeatures.Variables.Builder(); + CcToolchainVariables.Builder variableBuilder = new CcToolchainVariables.Builder(); variableBuilder.addStringSequenceVariable("module_files", usedModulePaths.build()); return variableBuilder.build(); }
diff --git a/src/main/java/com/google/devtools/build/lib/rules/cpp/CppCompileActionBuilder.java b/src/main/java/com/google/devtools/build/lib/rules/cpp/CppCompileActionBuilder.java index da8bcdb..866d1a5 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/cpp/CppCompileActionBuilder.java +++ b/src/main/java/com/google/devtools/build/lib/rules/cpp/CppCompileActionBuilder.java
@@ -32,7 +32,6 @@ import com.google.devtools.build.lib.packages.RuleClass.ConfiguredTargetFactory.RuleErrorException; import com.google.devtools.build.lib.rules.cpp.CcCommon.CoptsFilter; 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.CppCompileAction.DotdFile; import com.google.devtools.build.lib.util.FileType; import com.google.devtools.build.lib.vfs.FileSystemUtils; @@ -54,7 +53,7 @@ private final ActionOwner owner; private final BuildConfiguration configuration; private CcToolchainFeatures.FeatureConfiguration featureConfiguration; - private CcToolchainFeatures.Variables variables = Variables.EMPTY; + private CcToolchainVariables variables = CcToolchainVariables.EMPTY; private Artifact sourceFile; private final NestedSetBuilder<Artifact> mandatoryInputsBuilder; private Artifact optionalSourceFile; @@ -529,16 +528,14 @@ return this; } - /** - * Sets the feature build variables to be used for the action. - */ - public CppCompileActionBuilder setVariables(CcToolchainFeatures.Variables variables) { + /** Sets the feature build variables to be used for the action. */ + public CppCompileActionBuilder setVariables(CcToolchainVariables variables) { this.variables = variables; return this; } /** Returns the build variables to be used for the action. */ - public CcToolchainFeatures.Variables getVariables() { + public CcToolchainVariables getVariables() { return variables; }
diff --git a/src/main/java/com/google/devtools/build/lib/rules/cpp/CppCompileActionTemplate.java b/src/main/java/com/google/devtools/build/lib/rules/cpp/CppCompileActionTemplate.java index 7cc7dc3..5592c4f 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/cpp/CppCompileActionTemplate.java +++ b/src/main/java/com/google/devtools/build/lib/rules/cpp/CppCompileActionTemplate.java
@@ -104,8 +104,8 @@ builder.setSourceFile(sourceTreeFileArtifact); builder.setOutputs(outputTreeFileArtifact, null); - CcToolchainFeatures.Variables.Builder buildVariables = - new CcToolchainFeatures.Variables.Builder(cppCompileActionBuilder.getVariables()); + CcToolchainVariables.Builder buildVariables = + new CcToolchainVariables.Builder(cppCompileActionBuilder.getVariables()); buildVariables.overrideStringVariable( "source_file", sourceTreeFileArtifact.getExecPathString()); buildVariables.overrideStringVariable(
diff --git a/src/main/java/com/google/devtools/build/lib/rules/cpp/CppHelper.java b/src/main/java/com/google/devtools/build/lib/rules/cpp/CppHelper.java index eed0942..07082ad 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/cpp/CppHelper.java +++ b/src/main/java/com/google/devtools/build/lib/rules/cpp/CppHelper.java
@@ -60,7 +60,6 @@ import com.google.devtools.build.lib.rules.cpp.CcLinkParams.Linkstamp; import com.google.devtools.build.lib.rules.cpp.CcToolchainFeatures.FeatureConfiguration; import com.google.devtools.build.lib.rules.cpp.CcToolchainFeatures.Tool; -import com.google.devtools.build.lib.rules.cpp.CcToolchainFeatures.Variables; import com.google.devtools.build.lib.rules.cpp.CppConfiguration.DynamicMode; import com.google.devtools.build.lib.rules.cpp.Link.LinkTargetType; import com.google.devtools.build.lib.shell.ShellUtils; @@ -906,8 +905,8 @@ Tool stripTool = Preconditions.checkNotNull( featureConfiguration.getToolForAction(CppCompileAction.STRIP_ACTION_NAME)); - Variables variables = - new Variables.Builder(toolchain.getBuildVariables()) + CcToolchainVariables variables = + new CcToolchainVariables.Builder(toolchain.getBuildVariables()) .addStringVariable( StripBuildVariables.OUTPUT_FILE.getVariableName(), output.getExecPathString()) .addStringSequenceVariable(
diff --git a/src/main/java/com/google/devtools/build/lib/rules/cpp/CppLinkActionBuilder.java b/src/main/java/com/google/devtools/build/lib/rules/cpp/CppLinkActionBuilder.java index 40af3b8..9ec07a3 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/cpp/CppLinkActionBuilder.java +++ b/src/main/java/com/google/devtools/build/lib/rules/cpp/CppLinkActionBuilder.java
@@ -44,8 +44,7 @@ import com.google.devtools.build.lib.packages.RuleErrorConsumer; import com.google.devtools.build.lib.rules.cpp.CcLinkParams.Linkstamp; 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.VariablesExtension; +import com.google.devtools.build.lib.rules.cpp.CcToolchainVariables.VariablesExtension; import com.google.devtools.build.lib.rules.cpp.CppConfiguration.Tool; import com.google.devtools.build.lib.rules.cpp.CppLinkAction.Context; import com.google.devtools.build.lib.rules.cpp.CppLinkAction.LinkArtifactFactory; @@ -954,7 +953,8 @@ : null; // Add build variables necessary to template link args into the crosstool. - Variables.Builder buildVariablesBuilder = new Variables.Builder(toolchain.getBuildVariables()); + CcToolchainVariables.Builder buildVariablesBuilder = + new CcToolchainVariables.Builder(toolchain.getBuildVariables()); Preconditions.checkState(!isLtoIndexing || allowLtoIndexing); Preconditions.checkState(allowLtoIndexing || thinltoParamFile == null); Preconditions.checkState(allowLtoIndexing || thinltoMergedObjectFile == null); @@ -992,7 +992,7 @@ ImmutableSet<Artifact> expandedLinkerArtifactsNoLinkstamps = Sets.difference(expandedLinkerArtifacts, linkstampObjectArtifacts).immutableCopy(); - Variables variables = + CcToolchainVariables variables = LinkBuildVariables.setupVariables( getLinkType().linkerOrArchiver().equals(LinkerOrArchiver.LINKER), configuration, @@ -1020,7 +1020,7 @@ extraVariablesExtension.addVariables(buildVariablesBuilder); } - Variables buildVariables = buildVariablesBuilder.build(); + CcToolchainVariables buildVariables = buildVariablesBuilder.build(); Preconditions.checkArgument( linkType != LinkTargetType.INTERFACE_DYNAMIC_LIBRARY, @@ -1086,8 +1086,8 @@ : linkoptsForVariables; linkCommandLineBuilder.setLinkopts(linkoptsForVariables); - Variables patchedVariables = - new Variables.Builder(buildVariables) + CcToolchainVariables patchedVariables = + new CcToolchainVariables.Builder(buildVariables) .addStringSequenceVariable( LinkBuildVariables.LEGACY_LINK_FLAGS.getVariableName(), getToolchainFlags(linkoptsForVariables))
diff --git a/src/main/java/com/google/devtools/build/lib/rules/cpp/CppLinkstampCompileHelper.java b/src/main/java/com/google/devtools/build/lib/rules/cpp/CppLinkstampCompileHelper.java index 5d23af9..67d020f 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/cpp/CppLinkstampCompileHelper.java +++ b/src/main/java/com/google/devtools/build/lib/rules/cpp/CppLinkstampCompileHelper.java
@@ -20,7 +20,6 @@ import com.google.devtools.build.lib.actions.Artifact; import com.google.devtools.build.lib.analysis.RuleContext; 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.vfs.PathFragment; import java.util.regex.Pattern; @@ -125,7 +124,7 @@ .collect(ImmutableList.toImmutableList()); } - private static Variables getVariables( + private static CcToolchainVariables getVariables( RuleContext ruleContext, Artifact sourceFile, Artifact outputFile,
diff --git a/src/main/java/com/google/devtools/build/lib/rules/cpp/FakeCppCompileAction.java b/src/main/java/com/google/devtools/build/lib/rules/cpp/FakeCppCompileAction.java index e4f36ef..ab00b5c 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/cpp/FakeCppCompileAction.java +++ b/src/main/java/com/google/devtools/build/lib/rules/cpp/FakeCppCompileAction.java
@@ -59,7 +59,7 @@ ActionOwner owner, NestedSet<Artifact> allInputs, FeatureConfiguration featureConfiguration, - CcToolchainFeatures.Variables variables, + CcToolchainVariables variables, Artifact sourceFile, boolean shouldScanIncludes, boolean shouldPruneModules,
diff --git a/src/main/java/com/google/devtools/build/lib/rules/cpp/FdoSupport.java b/src/main/java/com/google/devtools/build/lib/rules/cpp/FdoSupport.java index 0a1223f..e10ca70 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/cpp/FdoSupport.java +++ b/src/main/java/com/google/devtools/build/lib/rules/cpp/FdoSupport.java
@@ -787,26 +787,27 @@ } /** - * Adds the FDO profile output path to the variable builder. - * If FDO is disabled, no build variable is added. + * Adds the FDO profile output path to the variable builder. If FDO is disabled, no build variable + * is added. */ @ThreadSafe - public void getLinkOptions(FeatureConfiguration featureConfiguration, - CcToolchainFeatures.Variables.Builder buildVariables - ) { + public void getLinkOptions( + FeatureConfiguration featureConfiguration, CcToolchainVariables.Builder buildVariables) { if (featureConfiguration.isEnabled(CppRuleClasses.FDO_INSTRUMENT)) { buildVariables.addStringVariable("fdo_instrument_path", fdoInstrument); } } /** - * Adds the AutoFDO profile path to the variable builder and returns the profile artifact. - * If AutoFDO is disabled, no build variable is added and returns null. + * Adds the AutoFDO profile path to the variable builder and returns the profile artifact. If + * AutoFDO is disabled, no build variable is added and returns null. */ @ThreadSafe - public Artifact buildProfileForLtoBackend(FdoSupportProvider fdoSupportProvider, + public Artifact buildProfileForLtoBackend( + FdoSupportProvider fdoSupportProvider, FeatureConfiguration featureConfiguration, - CcToolchainFeatures.Variables.Builder buildVariables, RuleContext ruleContext) { + CcToolchainVariables.Builder buildVariables, + RuleContext ruleContext) { if (!featureConfiguration.isEnabled(CppRuleClasses.AUTOFDO)) { return null; }
diff --git a/src/main/java/com/google/devtools/build/lib/rules/cpp/LibrariesToLinkCollector.java b/src/main/java/com/google/devtools/build/lib/rules/cpp/LibrariesToLinkCollector.java index 56f361f..ad262b8 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/cpp/LibrariesToLinkCollector.java +++ b/src/main/java/com/google/devtools/build/lib/rules/cpp/LibrariesToLinkCollector.java
@@ -20,8 +20,8 @@ import com.google.common.collect.Iterables; import com.google.devtools.build.lib.actions.Artifact; import com.google.devtools.build.lib.rules.cpp.CcToolchainFeatures.FeatureConfiguration; -import com.google.devtools.build.lib.rules.cpp.CcToolchainFeatures.Variables.LibraryToLinkValue; -import com.google.devtools.build.lib.rules.cpp.CcToolchainFeatures.Variables.SequenceBuilder; +import com.google.devtools.build.lib.rules.cpp.CcToolchainVariables.LibraryToLinkValue; +import com.google.devtools.build.lib.rules.cpp.CcToolchainVariables.SequenceBuilder; import com.google.devtools.build.lib.rules.cpp.Link.LinkTargetType; import com.google.devtools.build.lib.rules.cpp.Link.LinkingMode; import com.google.devtools.build.lib.util.Pair;
diff --git a/src/main/java/com/google/devtools/build/lib/rules/cpp/LinkBuildVariables.java b/src/main/java/com/google/devtools/build/lib/rules/cpp/LinkBuildVariables.java index 826bf6a..34d39c3 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/cpp/LinkBuildVariables.java +++ b/src/main/java/com/google/devtools/build/lib/rules/cpp/LinkBuildVariables.java
@@ -18,8 +18,7 @@ import com.google.devtools.build.lib.actions.Artifact; import com.google.devtools.build.lib.analysis.config.BuildConfiguration; 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.SequenceBuilder; +import com.google.devtools.build.lib.rules.cpp.CcToolchainVariables.SequenceBuilder; import com.google.devtools.build.lib.vfs.PathFragment; /** Enum covering all build variables we create for all various {@link CppLinkAction}. */ @@ -92,7 +91,7 @@ return variableName; } - public static Variables setupVariables( + public static CcToolchainVariables setupVariables( boolean isUsingLinkerNotArchiver, BuildConfiguration configuration, Artifact outputArtifact, @@ -113,7 +112,7 @@ Iterable<String> runtimeLibrarySearchDirectories, SequenceBuilder librariesToLink, Iterable<String> librarySearchDirectories) { - Variables.Builder buildVariables = new Variables.Builder(); + CcToolchainVariables.Builder buildVariables = new CcToolchainVariables.Builder(); // symbol counting if (symbolCounts != null) {
diff --git a/src/main/java/com/google/devtools/build/lib/rules/cpp/LinkCommandLine.java b/src/main/java/com/google/devtools/build/lib/rules/cpp/LinkCommandLine.java index 545dd9e..a1c037f 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/cpp/LinkCommandLine.java +++ b/src/main/java/com/google/devtools/build/lib/rules/cpp/LinkCommandLine.java
@@ -24,7 +24,6 @@ import com.google.devtools.build.lib.collect.CollectionUtils; import com.google.devtools.build.lib.concurrent.ThreadSafety.Immutable; 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.Link.LinkTargetType; import com.google.devtools.build.lib.rules.cpp.Link.LinkerOrArchiver; import com.google.devtools.build.lib.skyframe.serialization.autocodec.AutoCodec; @@ -44,7 +43,7 @@ public final class LinkCommandLine extends CommandLine { private final String actionName; private final String forcedToolPath; - private final CcToolchainFeatures.Variables variables; + private final CcToolchainVariables variables; // The feature config can be null for tests. @Nullable private final FeatureConfiguration featureConfiguration; private final ImmutableList<Artifact> buildInfoHeaderArtifacts; @@ -71,7 +70,7 @@ boolean nativeDeps, boolean useTestOnlyFlags, @Nullable Artifact paramFile, - CcToolchainFeatures.Variables variables, + CcToolchainVariables variables, @Nullable FeatureConfiguration featureConfiguration) { this.actionName = actionName; @@ -159,7 +158,7 @@ /** Returns the build variables used to template the crosstool for this linker invocation. */ @VisibleForTesting - public Variables getBuildVariables() { + public CcToolchainVariables getBuildVariables() { return this.variables; } @@ -213,7 +212,7 @@ private final String forcedToolPath; private final FeatureConfiguration featureConfiguration; private final String actionName; - private final Variables variables; + private final CcToolchainVariables variables; public ParamFileCommandLine( Artifact paramsFile, @@ -221,7 +220,7 @@ String forcedToolPath, FeatureConfiguration featureConfiguration, String actionName, - Variables variables) { + CcToolchainVariables variables) { this.paramsFile = paramsFile; this.linkTargetType = linkTargetType; this.forcedToolPath = forcedToolPath; @@ -366,7 +365,7 @@ FeatureConfiguration featureConfiguration, String actionName, LinkTargetType linkTargetType, - Variables variables) { + CcToolchainVariables variables) { List<String> argv = new ArrayList<>(); if (forcedToolPath != null) { argv.add(forcedToolPath); @@ -419,7 +418,7 @@ private boolean nativeDeps; private boolean useTestOnlyFlags; @Nullable private Artifact paramFile; - private Variables variables; + private CcToolchainVariables variables; private FeatureConfiguration featureConfiguration; public Builder(RuleContext ruleContext) { @@ -440,7 +439,7 @@ } if (variables == null) { - variables = Variables.EMPTY; + variables = CcToolchainVariables.EMPTY; } String actionName = linkTargetType.getActionName(); @@ -550,8 +549,8 @@ this.paramFile = paramFile; return this; } - - public Builder setBuildVariables(Variables variables) { + + public Builder setBuildVariables(CcToolchainVariables variables) { this.variables = variables; return this; }
diff --git a/src/main/java/com/google/devtools/build/lib/rules/cpp/LtoBackendArtifacts.java b/src/main/java/com/google/devtools/build/lib/rules/cpp/LtoBackendArtifacts.java index 5aaf1c1..df6dba7 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/cpp/LtoBackendArtifacts.java +++ b/src/main/java/com/google/devtools/build/lib/rules/cpp/LtoBackendArtifacts.java
@@ -20,7 +20,6 @@ import com.google.devtools.build.lib.analysis.RuleContext; import com.google.devtools.build.lib.analysis.config.BuildConfiguration; 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.CppConfiguration.Tool; import com.google.devtools.build.lib.skyframe.serialization.autocodec.AutoCodec; import com.google.devtools.build.lib.skyframe.serialization.autocodec.AutoCodec.VisibleForSerialization; @@ -217,8 +216,8 @@ PathFragment compiler = ccToolchain.getToolPathFragment(Tool.GCC); builder.setExecutable(compiler); - Variables.Builder buildVariablesBuilder = - new Variables.Builder(ccToolchain.getBuildVariables()); + CcToolchainVariables.Builder buildVariablesBuilder = + new CcToolchainVariables.Builder(ccToolchain.getBuildVariables()); if (index != null) { buildVariablesBuilder.addStringVariable("thinlto_index", index.getExecPath().toString()); } else { @@ -250,7 +249,7 @@ List<String> execArgs = new ArrayList<>(); execArgs.addAll(commandLine); - Variables buildVariables = buildVariablesBuilder.build(); + CcToolchainVariables buildVariables = buildVariablesBuilder.build(); // Feature options should go after --copt for consistency with compile actions. execArgs.addAll(featureConfiguration.getCommandLine("lto-backend", buildVariables)); // If this is a PIC compile (set based on the CppConfiguration), the PIC
diff --git a/src/main/java/com/google/devtools/build/lib/rules/objc/CompilationSupport.java b/src/main/java/com/google/devtools/build/lib/rules/objc/CompilationSupport.java index 3d93874..7ebb7aa 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/objc/CompilationSupport.java +++ b/src/main/java/com/google/devtools/build/lib/rules/objc/CompilationSupport.java
@@ -100,8 +100,8 @@ import com.google.devtools.build.lib.rules.cpp.CcToolchain; import com.google.devtools.build.lib.rules.cpp.CcToolchainFeatures.CollidingProvidesException; import com.google.devtools.build.lib.rules.cpp.CcToolchainFeatures.FeatureConfiguration; -import com.google.devtools.build.lib.rules.cpp.CcToolchainFeatures.Variables.VariablesExtension; import com.google.devtools.build.lib.rules.cpp.CcToolchainProvider; +import com.google.devtools.build.lib.rules.cpp.CcToolchainVariables.VariablesExtension; import com.google.devtools.build.lib.rules.cpp.CppCompileAction; import com.google.devtools.build.lib.rules.cpp.CppFileTypes; import com.google.devtools.build.lib.rules.cpp.CppHelper;
diff --git a/src/main/java/com/google/devtools/build/lib/rules/objc/ObjcVariablesExtension.java b/src/main/java/com/google/devtools/build/lib/rules/objc/ObjcVariablesExtension.java index 6040007..f7df33f 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/objc/ObjcVariablesExtension.java +++ b/src/main/java/com/google/devtools/build/lib/rules/objc/ObjcVariablesExtension.java
@@ -27,9 +27,9 @@ import com.google.devtools.build.lib.packages.BuildType; import com.google.devtools.build.lib.rules.apple.AppleConfiguration; import com.google.devtools.build.lib.rules.apple.ApplePlatform; -import com.google.devtools.build.lib.rules.cpp.CcToolchainFeatures; -import com.google.devtools.build.lib.rules.cpp.CcToolchainFeatures.Variables.StringSequenceBuilder; -import com.google.devtools.build.lib.rules.cpp.CcToolchainFeatures.Variables.VariablesExtension; +import com.google.devtools.build.lib.rules.cpp.CcToolchainVariables; +import com.google.devtools.build.lib.rules.cpp.CcToolchainVariables.StringSequenceBuilder; +import com.google.devtools.build.lib.rules.cpp.CcToolchainVariables.VariablesExtension; import com.google.devtools.build.lib.vfs.FileSystemUtils; import java.util.Set; @@ -128,7 +128,7 @@ } @Override - public void addVariables(CcToolchainFeatures.Variables.Builder builder) { + public void addVariables(CcToolchainVariables.Builder builder) { addPchVariables(builder); addFrameworkVariables(builder); addModuleMapVariables(builder); @@ -157,7 +157,7 @@ } } - private void addPchVariables(CcToolchainFeatures.Variables.Builder builder) { + private void addPchVariables(CcToolchainVariables.Builder builder) { if (ruleContext.attributes().has("pch", BuildType.LABEL) && ruleContext.getPrerequisiteArtifact("pch", Mode.TARGET) != null) { builder.addStringVariable( @@ -166,7 +166,7 @@ } } - private void addFrameworkVariables(CcToolchainFeatures.Variables.Builder builder) { + private void addFrameworkVariables(CcToolchainVariables.Builder builder) { ApplePlatform applePlatform = buildConfiguration.getFragment(AppleConfiguration.class).getSingleArchPlatform(); StringSequenceBuilder frameworkSequence = new StringSequenceBuilder(); @@ -177,7 +177,7 @@ builder.addCustomBuiltVariable(FRAMEWORKS_VARIABLE_NAME, frameworkSequence); } - private void addModuleMapVariables(CcToolchainFeatures.Variables.Builder builder) { + private void addModuleMapVariables(CcToolchainVariables.Builder builder) { builder.addStringVariable( MODULES_MAPS_DIR_NAME, intermediateArtifacts @@ -191,7 +191,7 @@ buildConfiguration.getGenfilesFragment() + "/" + OBJC_MODULE_CACHE_DIR_NAME); } - private void addArchiveVariables(CcToolchainFeatures.Variables.Builder builder) { + private void addArchiveVariables(CcToolchainVariables.Builder builder) { builder.addStringVariable( OBJ_LIST_PATH_VARIABLE_NAME, intermediateArtifacts.archiveObjList().getExecPathString()); @@ -199,7 +199,7 @@ ARCHIVE_PATH_VARIABLE_NAME, compilationArtifacts.getArchive().get().getExecPathString()); } - private void addFullyLinkArchiveVariables(CcToolchainFeatures.Variables.Builder builder) { + private void addFullyLinkArchiveVariables(CcToolchainVariables.Builder builder) { builder.addStringVariable( FULLY_LINKED_ARCHIVE_PATH_VARIABLE_NAME, fullyLinkArchive.getExecPathString()); builder.addStringSequenceVariable( @@ -213,7 +213,7 @@ Artifact.toExecPaths(objcProvider.get(IMPORTED_LIBRARY))); } - private void addExecutableLinkVariables(CcToolchainFeatures.Variables.Builder builder) { + private void addExecutableLinkVariables(CcToolchainVariables.Builder builder) { builder.addStringSequenceVariable( FRAMEWORK_NAMES_VARIABLE_NAME, frameworkNames); builder.addStringSequenceVariable( @@ -235,7 +235,7 @@ builder.addStringSequenceVariable(ATTR_LINKOPTS_VARIABLE_NAME, attributeLinkopts); } - private void addDsymVariables(CcToolchainFeatures.Variables.Builder builder) { + private void addDsymVariables(CcToolchainVariables.Builder builder) { builder.addStringVariable( DSYM_BUNDLE_ZIP_VARIABLE_NAME, dsymBundleZip.getShellEscapedExecPathString()); builder.addStringVariable( @@ -243,11 +243,11 @@ FileSystemUtils.removeExtension(dsymBundleZip.getExecPath()).getPathString()); } - private void addLinkmapVariables(CcToolchainFeatures.Variables.Builder builder) { + private void addLinkmapVariables(CcToolchainVariables.Builder builder) { builder.addStringVariable(LINKMAP_EXEC_PATH, linkmap.getExecPathString()); } - private void addBitcodeVariables(CcToolchainFeatures.Variables.Builder builder) { + private void addBitcodeVariables(CcToolchainVariables.Builder builder) { builder.addStringVariable( BITCODE_SYMBOL_MAP_PATH_VARAIBLE_NAME, bitcodeSymbolMap.getExecPathString()); }
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 82f4e74..6c04b60 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
@@ -30,14 +30,13 @@ 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.LibraryToLinkValue; -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; -import com.google.devtools.build.lib.rules.cpp.CcToolchainFeatures.Variables.VariableValue; -import com.google.devtools.build.lib.rules.cpp.CcToolchainFeatures.Variables.VariableValueBuilder; +import com.google.devtools.build.lib.rules.cpp.CcToolchainVariables.IntegerValue; +import com.google.devtools.build.lib.rules.cpp.CcToolchainVariables.LibraryToLinkValue; +import com.google.devtools.build.lib.rules.cpp.CcToolchainVariables.SequenceBuilder; +import com.google.devtools.build.lib.rules.cpp.CcToolchainVariables.StringSequenceBuilder; +import com.google.devtools.build.lib.rules.cpp.CcToolchainVariables.StructureBuilder; +import com.google.devtools.build.lib.rules.cpp.CcToolchainVariables.VariableValue; +import com.google.devtools.build.lib.rules.cpp.CcToolchainVariables.VariableValueBuilder; import com.google.devtools.build.lib.skyframe.serialization.AutoRegistry; import com.google.devtools.build.lib.skyframe.serialization.ObjectCodecs; import com.google.devtools.build.lib.skyframe.serialization.testutils.SerializationTester; @@ -66,7 +65,7 @@ * <p>If there are multiple entries with the same key, the variable will be treated as sequence * type. */ - private Variables createVariables(String... entries) { + private CcToolchainVariables createVariables(String... entries) { if (entries.length % 2 != 0) { throw new IllegalArgumentException( "createVariables takes an even number of arguments (key/value pairs)"); @@ -75,7 +74,7 @@ for (int i = 0; i < entries.length; i += 2) { entryMap.put(entries[i], entries[i + 1]); } - Variables.Builder variables = new Variables.Builder(); + CcToolchainVariables.Builder variables = new CcToolchainVariables.Builder(); for (String name : entryMap.keySet()) { Collection<String> value = entryMap.get(name); if (value.size() == 1) { @@ -302,7 +301,11 @@ return getExpansionOfFlag(value, createVariables()); } - private List<String> getCommandLineForFlagGroups(String groups, Variables variables) + private String getExpansionOfFlag(String value, CcToolchainVariables variables) throws Exception { + return getCommandLineForFlag(value, variables).get(0); + } + + private List<String> getCommandLineForFlagGroups(String groups, CcToolchainVariables variables) throws Exception { FeatureConfiguration configuration = buildFeatures( @@ -317,14 +320,11 @@ return configuration.getCommandLine(CppCompileAction.CPP_COMPILE, variables); } - private List<String> getCommandLineForFlag(String value, Variables variables) throws Exception { + private List<String> getCommandLineForFlag(String value, CcToolchainVariables variables) + throws Exception { return getCommandLineForFlagGroups("flag_group { flag: '" + value + "' }", variables); } - private String getExpansionOfFlag(String value, Variables variables) throws Exception { - return getCommandLineForFlag(value, variables).get(0); - } - private String getFlagParsingError(String value) throws Exception { try { getExpansionOfFlag(value); @@ -335,7 +335,8 @@ } } - private String getFlagExpansionError(String value, Variables variables) throws Exception { + private String getFlagExpansionError(String value, CcToolchainVariables variables) + throws Exception { try { getExpansionOfFlag(value, variables); fail("Expected ExpansionException"); @@ -345,7 +346,7 @@ } } - private String getFlagGroupsExpansionError(String flagGroups, Variables variables) + private String getFlagGroupsExpansionError(String flagGroups, CcToolchainVariables variables) throws Exception { try { getCommandLineForFlagGroups(flagGroups, variables).get(0); @@ -371,7 +372,7 @@ assertThat( getCommandLineForFlagGroups( "flag_group{ iterate_over: 'v' flag: '%{v}' }", - new Variables.Builder() + new CcToolchainVariables.Builder() .addStringSequenceVariable("v", ImmutableList.<String>of()) .build())) .isEmpty(); @@ -384,23 +385,24 @@ assertThat( getCommandLineForFlagGroups( "flag_group { iterate_over: 'lazy' flag: '-lazy-%{lazy}' }", - new Variables.Builder() + new CcToolchainVariables.Builder() .addLazyStringSequenceVariable("lazy", () -> ImmutableList.of("a", "b", "c")) .build())) .containsExactly("-lazy-a", "-lazy-b", "-lazy-c") .inOrder(); } - private Variables createStructureSequenceVariables(String name, StructureBuilder... values) { + private CcToolchainVariables createStructureSequenceVariables( + String name, StructureBuilder... values) { SequenceBuilder builder = new SequenceBuilder(); for (StructureBuilder value : values) { builder.addValue(value.build()); } - return new Variables.Builder().addCustomBuiltVariable(name, builder).build(); + return new CcToolchainVariables.Builder().addCustomBuiltVariable(name, builder).build(); } - private Variables createStructureVariables(String name, StructureBuilder value) { - return new Variables.Builder().addCustomBuiltVariable(name, value).build(); + private CcToolchainVariables createStructureVariables(String name, StructureBuilder value) { + return new CcToolchainVariables.Builder().addCustomBuiltVariable(name, value).build(); } @Test @@ -521,7 +523,7 @@ + " }" + " }" + "}", - new Variables.Builder() + new CcToolchainVariables.Builder() .addCustomBuiltVariable( "struct", new StructureBuilder() @@ -542,7 +544,7 @@ + "}", createStructureVariables( "struct", - new Variables.StructureBuilder() + new CcToolchainVariables.StructureBuilder() .addField("foo", "fooValue") .addField("bar", "barValue")))) .containsExactly("-AfooValue", "-BbarValue"); @@ -559,7 +561,7 @@ + "}", createStructureVariables( "struct", - new Variables.StructureBuilder() + new CcToolchainVariables.StructureBuilder() .addField("foo", "fooValue") .addField("bar", "barValue")))) .isEmpty(); @@ -602,7 +604,7 @@ + "}", createStructureVariables( "struct", - new Variables.StructureBuilder() + new CcToolchainVariables.StructureBuilder() .addField("foo", "fooValue") .addField("bar", "barValue")))) .containsExactly("-AfooValue", "-BbarValue"); @@ -618,7 +620,8 @@ + " flag: '-B%{struct.bar}'" + "}", createStructureVariables( - "struct", new Variables.StructureBuilder().addField("bar", "barValue")))) + "struct", + new CcToolchainVariables.StructureBuilder().addField("bar", "barValue")))) .isEmpty(); } @@ -636,7 +639,8 @@ + " }" + "}", createStructureVariables( - "struct", new Variables.StructureBuilder().addField("bar", "barValue")))) + "struct", + new CcToolchainVariables.StructureBuilder().addField("bar", "barValue")))) .containsExactly("-BbarValue"); } @@ -705,7 +709,7 @@ + "}", createStructureVariables( "struct", - new Variables.StructureBuilder() + new CcToolchainVariables.StructureBuilder() .addField("bool", new IntegerValue(1)) .addField("foo", "fooValue") .addField("bar", "barValue")))) @@ -728,7 +732,7 @@ + "}", createStructureVariables( "struct", - new Variables.StructureBuilder() + new CcToolchainVariables.StructureBuilder() .addField("bool", new IntegerValue(0)) .addField("foo", "fooValue") .addField("bar", "barValue")))) @@ -841,8 +845,8 @@ } } - private Variables createNestedVariables(String name, int depth, int count) { - return new Variables.Builder() + private CcToolchainVariables createNestedVariables(String name, int depth, int count) { + return new CcToolchainVariables.Builder() .addCustomBuiltVariable(name, createNestedSequence(depth, count, "")) .build(); }
diff --git a/src/test/java/com/google/devtools/build/lib/rules/cpp/CcToolchainProviderTest.java b/src/test/java/com/google/devtools/build/lib/rules/cpp/CcToolchainProviderTest.java index d039539..6835970 100644 --- a/src/test/java/com/google/devtools/build/lib/rules/cpp/CcToolchainProviderTest.java +++ b/src/test/java/com/google/devtools/build/lib/rules/cpp/CcToolchainProviderTest.java
@@ -20,7 +20,6 @@ import com.google.devtools.build.lib.actions.Artifact; import com.google.devtools.build.lib.collect.nestedset.NestedSetBuilder; import com.google.devtools.build.lib.collect.nestedset.Order; -import com.google.devtools.build.lib.rules.cpp.CcToolchainFeatures.Variables; import com.google.devtools.build.lib.rules.cpp.FdoSupport.FdoMode; import com.google.devtools.build.lib.vfs.PathFragment; import org.junit.Test; @@ -60,7 +59,7 @@ CcCompilationContext.EMPTY, /* supportsParamFiles= */ false, /* supportsHeaderParsing= */ false, - Variables.EMPTY, + CcToolchainVariables.EMPTY, /* builtinIncludeFiles= */ ImmutableList.<Artifact>of(), /* coverageEnvironment= */ NestedSetBuilder.emptySet(Order.COMPILE_ORDER), /* linkDynamicLibraryTool= */ null, @@ -97,7 +96,7 @@ CcCompilationContext.EMPTY, /* supportsParamFiles= */ false, /* supportsHeaderParsing= */ false, - Variables.EMPTY, + CcToolchainVariables.EMPTY, /* builtinIncludeFiles= */ ImmutableList.<Artifact>of(), /* coverageEnvironment= */ NestedSetBuilder.emptySet(Order.COMPILE_ORDER), /* linkDynamicLibraryTool= */ null,
diff --git a/src/test/java/com/google/devtools/build/lib/rules/cpp/CompileBuildVariablesTest.java b/src/test/java/com/google/devtools/build/lib/rules/cpp/CompileBuildVariablesTest.java index 2714ef5..0e6caea 100644 --- a/src/test/java/com/google/devtools/build/lib/rules/cpp/CompileBuildVariablesTest.java +++ b/src/test/java/com/google/devtools/build/lib/rules/cpp/CompileBuildVariablesTest.java
@@ -22,7 +22,6 @@ import com.google.devtools.build.lib.actions.Artifact; import com.google.devtools.build.lib.analysis.util.AnalysisMock; import com.google.devtools.build.lib.analysis.util.BuildViewTestCase; -import com.google.devtools.build.lib.rules.cpp.CcToolchainFeatures.Variables; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; @@ -48,7 +47,8 @@ } /** Returns active build variables for a compile action of given type for given target. */ - protected Variables getCompileBuildVariables(String label, String name) throws Exception { + protected CcToolchainVariables getCompileBuildVariables(String label, String name) + throws Exception { return getCppCompileAction(label, name).getCompileCommandLine().getVariables(); } @@ -57,7 +57,7 @@ scratch.file("x/BUILD", "cc_binary(name = 'bin', srcs = ['bin.cc'])"); scratch.file("x/bin.cc"); - Variables variables = getCompileBuildVariables("//x:bin", "bin"); + CcToolchainVariables variables = getCompileBuildVariables("//x:bin", "bin"); assertThat(variables.getStringVariable(CompileBuildVariables.SOURCE_FILE.getVariableName())) .contains("x/bin.cc"); @@ -73,10 +73,10 @@ scratch.file("x/BUILD", "cc_binary(name = 'bin', srcs = ['bin.cc'])"); scratch.file("x/bin.cc"); - Variables variables = getCompileBuildVariables("//x:bin", "bin"); + CcToolchainVariables variables = getCompileBuildVariables("//x:bin", "bin"); ImmutableList<String> copts = - Variables.toStringList( + CcToolchainVariables.toStringList( variables, CompileBuildVariables.LEGACY_COMPILE_FLAGS.getVariableName()); assertThat(copts).contains("-foo"); } @@ -89,15 +89,15 @@ scratch.file("x/BUILD", "cc_binary(name = 'bin', srcs = ['bin.cc'], copts = ['-bar'],)"); scratch.file("x/bin.cc"); - Variables variables = getCompileBuildVariables("//x:bin", "bin"); + CcToolchainVariables variables = getCompileBuildVariables("//x:bin", "bin"); ImmutableList<String> userCopts = - Variables.toStringList( + CcToolchainVariables.toStringList( variables, CompileBuildVariables.USER_COMPILE_FLAGS.getVariableName()); assertThat(userCopts).containsAllIn(ImmutableList.<String>of("-foo", "-bar")).inOrder(); ImmutableList<String> legacyCopts = - Variables.toStringList( + CcToolchainVariables.toStringList( variables, CompileBuildVariables.LEGACY_COMPILE_FLAGS.getVariableName()); assertThat(legacyCopts).doesNotContain("-foo"); } @@ -110,10 +110,10 @@ scratch.file("x/BUILD", "cc_binary(name = 'bin', srcs = ['bin.cc'], copts = ['-foo'])"); scratch.file("x/bin.cc"); - Variables variables = getCompileBuildVariables("//x:bin", "bin"); + CcToolchainVariables variables = getCompileBuildVariables("//x:bin", "bin"); ImmutableList<String> copts = - Variables.toStringList( + CcToolchainVariables.toStringList( variables, CompileBuildVariables.USER_COMPILE_FLAGS.getVariableName()); assertThat(copts).contains("-foo"); } @@ -128,10 +128,10 @@ scratch.file("x/BUILD", "cc_binary(name = 'bin', srcs = ['bin.cc'])"); scratch.file("x/bin.cc"); - Variables variables = getCompileBuildVariables("//x:bin", "bin"); + CcToolchainVariables variables = getCompileBuildVariables("//x:bin", "bin"); ImmutableList<String> unfilteredCompileFlags = - Variables.toStringList( + CcToolchainVariables.toStringList( variables, CompileBuildVariables.UNFILTERED_COMPILE_FLAGS.getVariableName()); assertThat(unfilteredCompileFlags).contains("--i_ll_live_forever"); } @@ -142,10 +142,10 @@ scratch.file("x/bin.cc"); useConfiguration("--per_file_copt=//x:bin@-foo", "--per_file_copt=//x:bar\\.cc@-bar"); - Variables variables = getCompileBuildVariables("//x:bin", "bin"); + CcToolchainVariables variables = getCompileBuildVariables("//x:bin", "bin"); ImmutableList<String> copts = - Variables.toStringList( + CcToolchainVariables.toStringList( variables, CompileBuildVariables.USER_COMPILE_FLAGS.getVariableName()); assertThat(copts).containsExactly("-foo").inOrder(); } @@ -160,7 +160,7 @@ scratch.file("x/BUILD", "cc_binary(name = 'bin', srcs = ['bin.cc'])"); scratch.file("x/bin.cc"); - Variables variables = getCompileBuildVariables("//x:bin", "bin"); + CcToolchainVariables variables = getCompileBuildVariables("//x:bin", "bin"); assertThat(variables.getStringVariable(CcCommon.SYSROOT_VARIABLE_NAME)) .isEqualTo("/usr/local/custom-sysroot");
diff --git a/src/test/java/com/google/devtools/build/lib/rules/cpp/CppLinkActionTest.java b/src/test/java/com/google/devtools/build/lib/rules/cpp/CppLinkActionTest.java index 42673d9..8aaefcc 100644 --- a/src/test/java/com/google/devtools/build/lib/rules/cpp/CppLinkActionTest.java +++ b/src/test/java/com/google/devtools/build/lib/rules/cpp/CppLinkActionTest.java
@@ -46,7 +46,7 @@ import com.google.devtools.build.lib.collect.nestedset.Order; import com.google.devtools.build.lib.packages.util.MockCcSupport; import com.google.devtools.build.lib.rules.cpp.CcToolchainFeatures.FeatureConfiguration; -import com.google.devtools.build.lib.rules.cpp.CcToolchainFeatures.Variables.VariableValue; +import com.google.devtools.build.lib.rules.cpp.CcToolchainVariables.VariableValue; import com.google.devtools.build.lib.rules.cpp.CppActionConfigs.CppPlatform; import com.google.devtools.build.lib.rules.cpp.Link.LinkTargetType; import com.google.devtools.build.lib.rules.cpp.Link.LinkerOrArchiver;
diff --git a/src/test/java/com/google/devtools/build/lib/rules/cpp/LinkBuildVariablesTest.java b/src/test/java/com/google/devtools/build/lib/rules/cpp/LinkBuildVariablesTest.java index 1eed5db..bc463b0 100644 --- a/src/test/java/com/google/devtools/build/lib/rules/cpp/LinkBuildVariablesTest.java +++ b/src/test/java/com/google/devtools/build/lib/rules/cpp/LinkBuildVariablesTest.java
@@ -22,9 +22,8 @@ import com.google.devtools.build.lib.analysis.ConfiguredTarget; import com.google.devtools.build.lib.analysis.util.AnalysisMock; import com.google.devtools.build.lib.packages.util.MockCcSupport; -import com.google.devtools.build.lib.rules.cpp.CcToolchainFeatures.Variables; -import com.google.devtools.build.lib.rules.cpp.CcToolchainFeatures.Variables.LibraryToLinkValue; -import com.google.devtools.build.lib.rules.cpp.CcToolchainFeatures.Variables.VariableValue; +import com.google.devtools.build.lib.rules.cpp.CcToolchainVariables.LibraryToLinkValue; +import com.google.devtools.build.lib.rules.cpp.CcToolchainVariables.VariableValue; import com.google.devtools.build.lib.rules.cpp.Link.LinkTargetType; import com.google.devtools.build.lib.util.OsUtils; import java.util.List; @@ -43,7 +42,7 @@ scratch.file("x/a.cc"); ConfiguredTarget target = getConfiguredTarget("//x:bin"); - Variables variables = getLinkBuildVariables(target, Link.LinkTargetType.EXECUTABLE); + CcToolchainVariables variables = getLinkBuildVariables(target, Link.LinkTargetType.EXECUTABLE); String variableValue = getVariableValue(variables, LinkBuildVariables.FORCE_PIC.getVariableName()); assertThat(variableValue).contains(""); @@ -58,7 +57,8 @@ scratch.file("x/a.cc"); ConfiguredTarget target = getConfiguredTarget("//x:foo"); - Variables variables = getLinkBuildVariables(target, LinkTargetType.NODEPS_DYNAMIC_LIBRARY); + CcToolchainVariables variables = + getLinkBuildVariables(target, LinkTargetType.NODEPS_DYNAMIC_LIBRARY); VariableValue librariesToLinkSequence = variables.getVariable(LinkBuildVariables.LIBRARIES_TO_LINK.getVariableName()); assertThat(librariesToLinkSequence).isNotNull(); @@ -87,7 +87,7 @@ scratch.file("x/some-dir/bar.so"); ConfiguredTarget target = getConfiguredTarget("//x:bin"); - Variables variables = getLinkBuildVariables(target, Link.LinkTargetType.EXECUTABLE); + CcToolchainVariables variables = getLinkBuildVariables(target, Link.LinkTargetType.EXECUTABLE); List<String> variableValue = getSequenceVariableValue( variables, LinkBuildVariables.LIBRARY_SEARCH_DIRECTORIES.getVariableName()); @@ -103,7 +103,7 @@ scratch.file("x/some-dir/bar.so"); ConfiguredTarget target = getConfiguredTarget("//x:bin"); - Variables variables = getLinkBuildVariables(target, Link.LinkTargetType.EXECUTABLE); + CcToolchainVariables variables = getLinkBuildVariables(target, Link.LinkTargetType.EXECUTABLE); String variableValue = getVariableValue(variables, LinkBuildVariables.LINKER_PARAM_FILE.getVariableName()); assertThat(variableValue).matches(".*bin/x/bin" + OsUtils.executableExtension() + "-2.params$"); @@ -122,7 +122,8 @@ scratch.file("x/a.cc"); ConfiguredTarget target = getConfiguredTarget("//x:foo"); - Variables variables = getLinkBuildVariables(target, LinkTargetType.NODEPS_DYNAMIC_LIBRARY); + CcToolchainVariables variables = + getLinkBuildVariables(target, LinkTargetType.NODEPS_DYNAMIC_LIBRARY); String interfaceLibraryBuilder = getVariableValue(variables, LinkBuildVariables.INTERFACE_LIBRARY_BUILDER.getVariableName()); @@ -170,7 +171,7 @@ (CppLinkAction) getPredecessorByInputName( backendAction, "x/libfoo.so.lto/x/_objs/foo/x/a.pic.o.thinlto.bc"); - Variables variables = indexAction.getLinkCommandLine().getBuildVariables(); + CcToolchainVariables variables = indexAction.getLinkCommandLine().getBuildVariables(); String interfaceLibraryBuilder = getVariableValue(variables, LinkBuildVariables.INTERFACE_LIBRARY_BUILDER.getVariableName()); @@ -201,7 +202,7 @@ scratch.file("x/a.cc"); ConfiguredTarget target = getConfiguredTarget("//x:foo"); - Variables variables = getLinkBuildVariables(target, LinkTargetType.STATIC_LIBRARY); + CcToolchainVariables variables = getLinkBuildVariables(target, LinkTargetType.STATIC_LIBRARY); String interfaceLibraryBuilder = getVariableValue(variables, LinkBuildVariables.INTERFACE_LIBRARY_BUILDER.getVariableName()); @@ -227,7 +228,8 @@ scratch.file("x/a.cc"); ConfiguredTarget target = getConfiguredTarget("//x:foo"); - Variables variables = getLinkBuildVariables(target, LinkTargetType.NODEPS_DYNAMIC_LIBRARY); + CcToolchainVariables variables = + getLinkBuildVariables(target, LinkTargetType.NODEPS_DYNAMIC_LIBRARY); assertThat(getVariableValue(variables, LinkBuildVariables.OUTPUT_EXECPATH.getVariableName())) .endsWith("x/libfoo.so"); @@ -262,7 +264,7 @@ (CppLinkAction) getPredecessorByInputName( backendAction, "x/libfoo.so.lto/x/_objs/foo/x/a.pic.o.thinlto.bc"); - Variables variables = indexAction.getLinkCommandLine().getBuildVariables(); + CcToolchainVariables variables = indexAction.getLinkCommandLine().getBuildVariables(); assertThat(variables.isAvailable(LinkBuildVariables.OUTPUT_EXECPATH.getVariableName())) .isFalse(); @@ -276,14 +278,16 @@ scratch.file("x/a.cc"); ConfiguredTarget testTarget = getConfiguredTarget("//x:foo_test"); - Variables testVariables = getLinkBuildVariables(testTarget, LinkTargetType.EXECUTABLE); + CcToolchainVariables testVariables = + getLinkBuildVariables(testTarget, LinkTargetType.EXECUTABLE); assertThat( testVariables.getVariable(LinkBuildVariables.IS_CC_TEST.getVariableName()).isTruthy()) .isTrue(); ConfiguredTarget binaryTarget = getConfiguredTarget("//x:foo"); - Variables binaryVariables = getLinkBuildVariables(binaryTarget, LinkTargetType.EXECUTABLE); + CcToolchainVariables binaryVariables = + getLinkBuildVariables(binaryTarget, LinkTargetType.EXECUTABLE); assertThat( binaryVariables.getVariable(LinkBuildVariables.IS_CC_TEST.getVariableName()).isTruthy()) @@ -310,7 +314,7 @@ String stripMode, String compilationMode, boolean isEnabled) throws Exception { useConfiguration("--strip=" + stripMode, "--compilation_mode=" + compilationMode); ConfiguredTarget target = getConfiguredTarget("//x:foo"); - Variables variables = getLinkBuildVariables(target, LinkTargetType.EXECUTABLE); + CcToolchainVariables variables = getLinkBuildVariables(target, LinkTargetType.EXECUTABLE); assertThat(variables.isAvailable(LinkBuildVariables.STRIP_DEBUG_SYMBOLS.getVariableName())) .isEqualTo(isEnabled); } @@ -327,13 +331,14 @@ useConfiguration("--fission=no"); ConfiguredTarget target = getConfiguredTarget("//x:foo"); - Variables variables = getLinkBuildVariables(target, LinkTargetType.EXECUTABLE); + CcToolchainVariables variables = getLinkBuildVariables(target, LinkTargetType.EXECUTABLE); assertThat(variables.isAvailable(LinkBuildVariables.IS_USING_FISSION.getVariableName())) .isFalse(); useConfiguration("--fission=yes"); ConfiguredTarget fissionTarget = getConfiguredTarget("//x:foo"); - Variables fissionVariables = getLinkBuildVariables(fissionTarget, LinkTargetType.EXECUTABLE); + CcToolchainVariables fissionVariables = + getLinkBuildVariables(fissionTarget, LinkTargetType.EXECUTABLE); assertThat(fissionVariables.isAvailable(LinkBuildVariables.IS_USING_FISSION.getVariableName())) .isTrue(); } @@ -349,7 +354,8 @@ scratch.file("x/a.cc"); ConfiguredTarget testTarget = getConfiguredTarget("//x:foo"); - Variables testVariables = getLinkBuildVariables(testTarget, LinkTargetType.EXECUTABLE); + CcToolchainVariables testVariables = + getLinkBuildVariables(testTarget, LinkTargetType.EXECUTABLE); assertThat(testVariables.isAvailable(CcCommon.SYSROOT_VARIABLE_NAME)).isTrue(); }
diff --git a/src/test/java/com/google/devtools/build/lib/rules/cpp/LinkBuildVariablesTestCase.java b/src/test/java/com/google/devtools/build/lib/rules/cpp/LinkBuildVariablesTestCase.java index 3eab78d..f2ba846 100644 --- a/src/test/java/com/google/devtools/build/lib/rules/cpp/LinkBuildVariablesTestCase.java +++ b/src/test/java/com/google/devtools/build/lib/rules/cpp/LinkBuildVariablesTestCase.java
@@ -21,7 +21,6 @@ import com.google.devtools.build.lib.analysis.ConfiguredTarget; import com.google.devtools.build.lib.analysis.util.BuildViewTestCase; 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.vfs.PathFragment; import com.google.devtools.build.lib.view.config.crosstool.CrosstoolConfig.CToolchain; import com.google.protobuf.TextFormat; @@ -61,7 +60,8 @@ } /** Returns active build variables for a link action of given type for given target. */ - protected Variables getLinkBuildVariables(ConfiguredTarget target, Link.LinkTargetType type) { + protected CcToolchainVariables getLinkBuildVariables( + ConfiguredTarget target, Link.LinkTargetType type) { return getCppLinkAction(target, type).getLinkCommandLine().getBuildVariables(); } @@ -76,7 +76,7 @@ } /** Returns the value of a given sequence variable in context of the given Variables instance. */ - protected List<String> getSequenceVariableValue(Variables variables, String variable) + protected List<String> getSequenceVariableValue(CcToolchainVariables variables, String variable) throws Exception { FeatureConfiguration mockFeatureConfiguration = buildFeatures( @@ -95,7 +95,8 @@ } /** Returns the value of a given string variable in context of the given Variables instance. */ - protected String getVariableValue(Variables variables, String variable) throws Exception { + protected String getVariableValue(CcToolchainVariables variables, String variable) + throws Exception { FeatureConfiguration mockFeatureConfiguration = buildFeatures( "feature {",
diff --git a/src/test/java/com/google/devtools/build/lib/rules/objc/ObjcBuildVariablesTest.java b/src/test/java/com/google/devtools/build/lib/rules/objc/ObjcBuildVariablesTest.java index e49d647..5d2eed5 100644 --- a/src/test/java/com/google/devtools/build/lib/rules/objc/ObjcBuildVariablesTest.java +++ b/src/test/java/com/google/devtools/build/lib/rules/objc/ObjcBuildVariablesTest.java
@@ -26,7 +26,7 @@ import com.google.devtools.build.lib.packages.util.MockObjcSupport; import com.google.devtools.build.lib.rules.apple.AppleCommandLineOptions; import com.google.devtools.build.lib.rules.apple.cpp.AppleCcToolchain; -import com.google.devtools.build.lib.rules.cpp.CcToolchainFeatures.Variables; +import com.google.devtools.build.lib.rules.cpp.CcToolchainVariables; import com.google.devtools.build.lib.rules.cpp.CppLinkAction; import com.google.devtools.build.lib.rules.cpp.Link; import com.google.devtools.build.lib.rules.cpp.LinkBuildVariablesTestCase; @@ -39,7 +39,7 @@ /** * Tests that {@code CppLinkAction} is populated with the correct build variables for objective C * builds. - **/ + */ @RunWith(JUnit4.class) public class ObjcBuildVariablesTest extends LinkBuildVariablesTestCase { @@ -78,7 +78,7 @@ scratch.file("x/a.cc"); ConfiguredTarget target = getConfiguredTarget("//x:bin"); - Variables variables = getLinkBuildVariables(target, Link.LinkTargetType.EXECUTABLE); + CcToolchainVariables variables = getLinkBuildVariables(target, Link.LinkTargetType.EXECUTABLE); assertThat( getVariableValue(variables, AppleCcToolchain.XCODE_VERISON_OVERRIDE_VALUE_KEY)) .contains("5.8"); @@ -126,7 +126,7 @@ ActionsTestUtil.getFirstArtifactEndingWith(appleBinLinkAction.getInputs(), "liba.a"); CppLinkAction ccArchiveAction = (CppLinkAction) getGeneratingAction(archive); - Variables variables = ccArchiveAction.getLinkCommandLine().getBuildVariables(); + CcToolchainVariables variables = ccArchiveAction.getLinkCommandLine().getBuildVariables(); assertThat( getVariableValue(variables, AppleCcToolchain.XCODE_VERISON_OVERRIDE_VALUE_KEY)) .contains("5.8"); @@ -174,7 +174,7 @@ ActionsTestUtil.getFirstArtifactEndingWith(appleBinLinkAction.getInputs(), "liba.a"); CppLinkAction ccArchiveAction = (CppLinkAction) getGeneratingAction(archive); - Variables variables = ccArchiveAction.getLinkCommandLine().getBuildVariables(); + CcToolchainVariables variables = ccArchiveAction.getLinkCommandLine().getBuildVariables(); assertThat(getVariableValue(variables, AppleCcToolchain.VERSION_MIN_KEY)) .contains(dummyMinimumOsValue); } @@ -193,7 +193,7 @@ scratch.file("x/a.cc"); ConfiguredTarget target = getConfiguredTarget("//x:bin"); - Variables variables = getLinkBuildVariables(target, Link.LinkTargetType.EXECUTABLE); + CcToolchainVariables variables = getLinkBuildVariables(target, Link.LinkTargetType.EXECUTABLE); assertThat( getVariableValue(variables, AppleCcToolchain.XCODE_VERISON_OVERRIDE_VALUE_KEY)) .contains(MockObjcSupport.DEFAULT_XCODE_VERSION); @@ -239,7 +239,7 @@ ActionsTestUtil.getFirstArtifactEndingWith(appleBinLinkAction.getInputs(), "liba.a"); CppLinkAction ccArchiveAction = (CppLinkAction) getGeneratingAction(archive); - Variables variables = ccArchiveAction.getLinkCommandLine().getBuildVariables(); + CcToolchainVariables variables = ccArchiveAction.getLinkCommandLine().getBuildVariables(); assertThat(getVariableValue(variables, AppleCcToolchain.VERSION_MIN_KEY)) .contains(dummyMinimumOsValue); }