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 09c864e77fb7a8..62df64e98583e6 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 @@ -17,8 +17,6 @@ import com.google.devtools.build.lib.actions.MutableActionGraph.ActionConflictException; import com.google.devtools.build.lib.analysis.ConfiguredTarget; import com.google.devtools.build.lib.analysis.LicensesProvider; -import com.google.devtools.build.lib.analysis.LicensesProvider.TargetLicense; -import com.google.devtools.build.lib.analysis.LicensesProviderImpl; import com.google.devtools.build.lib.analysis.MiddlemanProvider; import com.google.devtools.build.lib.analysis.RuleConfiguredTargetBuilder; import com.google.devtools.build.lib.analysis.RuleConfiguredTargetFactory; @@ -26,11 +24,7 @@ import com.google.devtools.build.lib.analysis.Runfiles; import com.google.devtools.build.lib.analysis.RunfilesProvider; import com.google.devtools.build.lib.analysis.TemplateVariableInfo; -import com.google.devtools.build.lib.collect.nestedset.NestedSet; -import com.google.devtools.build.lib.collect.nestedset.NestedSetBuilder; -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.vfs.PathFragment; import java.util.HashMap; @@ -48,10 +42,13 @@ public class CcToolchain implements RuleConfiguredTargetFactory { @Override public ConfiguredTarget create(RuleContext ruleContext) throws InterruptedException, RuleErrorException, ActionConflictException { - CcToolchainProvider ccToolchainProvider = - CcToolchainProviderHelper.getCcToolchainProvider( + CcToolchainAttributesProvider attributes = + new CcToolchainAttributesProvider( ruleContext, isAppleToolchain(), getAdditionalBuildVariables(ruleContext)); + CcToolchainProvider ccToolchainProvider = + CcToolchainProviderHelper.getCcToolchainProvider(ruleContext, attributes); + if (ccToolchainProvider == null) { return null; } @@ -71,22 +68,8 @@ public ConfiguredTarget create(RuleContext ruleContext) .addProvider(RunfilesProvider.simple(Runfiles.EMPTY)) .addProvider(new MiddlemanProvider(ccToolchainProvider.getCrosstoolMiddleman())); - // If output_license is specified on the cc_toolchain rule, override the transitive licenses - // with that one. This is necessary because cc_toolchain is used in the target configuration, - // but it is sort-of-kind-of a tool, but various parts of it are linked into the output... - // ...so we trust the judgment of the author of the cc_toolchain rule to figure out what - // licenses should be propagated to C++ targets. - // TODO(elenairina): Remove this and use Attribute.Builder.useOutputLicenses() on the - // :cc_toolchain attribute instead. - final License outputLicense = - ruleContext.getRule().getToolOutputLicense(ruleContext.attributes()); - if (outputLicense != null && !outputLicense.equals(License.NO_LICENSE)) { - final NestedSet license = NestedSetBuilder.create(Order.STABLE_ORDER, - new TargetLicense(ruleContext.getLabel(), outputLicense)); - LicensesProvider licensesProvider = - new LicensesProviderImpl( - license, new TargetLicense(ruleContext.getLabel(), outputLicense)); - builder.add(LicensesProvider.class, licensesProvider); + if (attributes.getLicensesProvider() != null) { + builder.add(LicensesProvider.class, attributes.getLicensesProvider()); } return builder.build(); @@ -118,8 +101,8 @@ private static TemplateVariableInfo createMakeVariableProvider( /** * Add local build variables from subclasses into {@link CcToolchainVariables} returned from - * {@link CcToolchainProviderHelper#getBuildVariables(RuleContext, PathFragment, - * CcToolchainVariables)}. + * {@link CcToolchainProviderHelper#getBuildVariables(RuleContext, CcToolchainAttributesProvider, + * PathFragment, CcToolchainVariables)}. * *

This method is meant to be overridden by subclasses of CcToolchain. */ diff --git a/src/main/java/com/google/devtools/build/lib/rules/cpp/CcToolchainAttributesProvider.java b/src/main/java/com/google/devtools/build/lib/rules/cpp/CcToolchainAttributesProvider.java new file mode 100644 index 00000000000000..f2599a74cb0d20 --- /dev/null +++ b/src/main/java/com/google/devtools/build/lib/rules/cpp/CcToolchainAttributesProvider.java @@ -0,0 +1,409 @@ +// 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 static com.google.devtools.build.lib.packages.BuildType.NODEP_LABEL; +import static com.google.devtools.build.lib.syntax.Type.BOOLEAN; + +import com.google.common.base.Preconditions; +import com.google.common.collect.ImmutableList; +import com.google.devtools.build.lib.actions.Actions; +import com.google.devtools.build.lib.actions.Artifact; +import com.google.devtools.build.lib.analysis.FileProvider; +import com.google.devtools.build.lib.analysis.LicensesProvider; +import com.google.devtools.build.lib.analysis.LicensesProvider.TargetLicense; +import com.google.devtools.build.lib.analysis.LicensesProviderImpl; +import com.google.devtools.build.lib.analysis.MiddlemanProvider; +import com.google.devtools.build.lib.analysis.RuleContext; +import com.google.devtools.build.lib.analysis.TransitiveInfoCollection; +import com.google.devtools.build.lib.analysis.configuredtargets.RuleConfiguredTarget.Mode; +import com.google.devtools.build.lib.cmdline.Label; +import com.google.devtools.build.lib.collect.nestedset.NestedSet; +import com.google.devtools.build.lib.collect.nestedset.NestedSetBuilder; +import com.google.devtools.build.lib.collect.nestedset.Order; +import com.google.devtools.build.lib.packages.License; +import com.google.devtools.build.lib.packages.NativeInfo; +import com.google.devtools.build.lib.packages.NativeProvider; +import com.google.devtools.build.lib.syntax.Type; + +/** + * Provider encapsulating all the information from the cc_toolchain rule that affects creation of + * {@link CcToolchainProvider} + */ +public class CcToolchainAttributesProvider extends NativeInfo { + + public static final NativeProvider PROVIDER = + new NativeProvider( + CcToolchainAttributesProvider.class, "CcToolchainAttributesInfo") {}; + + private final boolean supportsParamFiles; + private final boolean supportsHeaderParsing; + private final NestedSet crosstool; + private final NestedSet crosstoolMiddleman; + private final NestedSet compile; + private final NestedSet compileWithoutIncludes; + private final NestedSet strip; + private final NestedSet objcopy; + private final NestedSet as; + private final NestedSet ar; + private final NestedSet link; + private final NestedSet dwp; + private final NestedSet libc; + private final NestedSet libcMiddleman; + private final NestedSet fullInputsForCrosstool; + private final NestedSet fullInputsForLink; + private final NestedSet coverage; + private final String compiler; + private final String proto; + private final String cpu; + private final Artifact ifsoBuilder; + private final Artifact linkDynamicLibraryTool; + private final FdoProfileProvider fdoOptimizeProvider; + private final TransitiveInfoCollection fdoOptimize; + private final ImmutableList fdoOptimizeArtifacts; + private final FdoPrefetchHintsProvider fdoPrefetch; + private final TransitiveInfoCollection libcTop; + private final TransitiveInfoCollection moduleMap; + private final Artifact moduleMapArtifact; + private final Artifact zipper; + private final String purposePrefix; + private final String runtimeSolibDirBase; + private final ImmutableList staticRuntimesLibs; + private final ImmutableList dynamicRuntimesLibs; + private final LicensesProvider licensesProvider; + private final Label toolchainType; + private final CcToolchainVariables additionalBuildVariables; + private final CcToolchainConfigInfo ccToolchainConfigInfo; + private final String toolchainIdentifier; + private final FdoProfileProvider fdoProfileProvider; + private final Label ccToolchainLabel; + + public CcToolchainAttributesProvider( + RuleContext ruleContext, + boolean isAppleToolchain, + CcToolchainVariables additionalBuildVariables) { + super(PROVIDER); + this.ccToolchainLabel = ruleContext.getLabel(); + this.toolchainIdentifier = ruleContext.attributes().get("toolchain_identifier", Type.STRING); + this.cpu = ruleContext.attributes().get("cpu", Type.STRING); + this.compiler = ruleContext.attributes().get("compiler", Type.STRING); + this.proto = ruleContext.attributes().get("proto", Type.STRING); + this.supportsParamFiles = ruleContext.attributes().get("supports_param_files", BOOLEAN); + this.supportsHeaderParsing = ruleContext.attributes().get("supports_header_parsing", BOOLEAN); + this.crosstool = + ruleContext + .getPrerequisite("all_files", Mode.HOST) + .getProvider(FileProvider.class) + .getFilesToBuild(); + this.crosstoolMiddleman = getMiddlemanOrFiles(ruleContext, "all_files"); + this.compile = getMiddlemanOrFiles(ruleContext, "compiler_files"); + this.compileWithoutIncludes = + getOptionalMiddlemanOrFiles(ruleContext, "compiler_files_without_includes"); + this.strip = getMiddlemanOrFiles(ruleContext, "strip_files"); + this.objcopy = getMiddlemanOrFiles(ruleContext, "objcopy_files"); + this.as = getOptionalMiddlemanOrFiles(ruleContext, "as_files"); + this.ar = getOptionalMiddlemanOrFiles(ruleContext, "ar_files"); + this.link = getMiddlemanOrFiles(ruleContext, "linker_files"); + this.dwp = getMiddlemanOrFiles(ruleContext, "dwp_files"); + this.libcMiddleman = + getOptionalMiddlemanOrFiles(ruleContext, CcToolchainRule.LIBC_TOP_ATTR, Mode.TARGET); + this.libc = getOptionalFiles(ruleContext, CcToolchainRule.LIBC_TOP_ATTR, Mode.TARGET); + this.fullInputsForCrosstool = + NestedSetBuilder.stableOrder() + .addTransitive(crosstoolMiddleman) + .addTransitive(libcMiddleman) + .build(); + ; + this.fullInputsForLink = fullInputsForLink(ruleContext, link, libcMiddleman, isAppleToolchain); + NestedSet coverageAttribute = + getOptionalMiddlemanOrFiles(ruleContext, "coverage_files"); + if (coverageAttribute.isEmpty()) { + this.coverage = Preconditions.checkNotNull(this.crosstool); + } else { + this.coverage = coverageAttribute; + } + this.ifsoBuilder = ruleContext.getPrerequisiteArtifact("$interface_library_builder", Mode.HOST); + this.linkDynamicLibraryTool = + ruleContext.getPrerequisiteArtifact("$link_dynamic_library_tool", Mode.HOST); + this.fdoProfileProvider = + ruleContext.getPrerequisite( + CcToolchainRule.FDO_PROFILE_ATTR, Mode.TARGET, FdoProfileProvider.PROVIDER); + this.fdoOptimizeProvider = + ruleContext.getPrerequisite( + CcToolchainRule.FDO_OPTIMIZE_ATTR, Mode.TARGET, FdoProfileProvider.PROVIDER); + this.fdoOptimize = ruleContext.getPrerequisite(CcToolchainRule.FDO_OPTIMIZE_ATTR, Mode.TARGET); + this.fdoOptimizeArtifacts = + ruleContext.getPrerequisiteArtifacts(CcToolchainRule.FDO_OPTIMIZE_ATTR, Mode.TARGET).list(); + this.fdoPrefetch = + ruleContext.getPrerequisite( + ":fdo_prefetch_hints", Mode.TARGET, FdoPrefetchHintsProvider.PROVIDER); + this.libcTop = ruleContext.getPrerequisite(CcToolchainRule.LIBC_TOP_ATTR, Mode.TARGET); + this.moduleMap = ruleContext.getPrerequisite("module_map", Mode.HOST); + this.moduleMapArtifact = ruleContext.getPrerequisiteArtifact("module_map", Mode.HOST); + this.zipper = ruleContext.getPrerequisiteArtifact(":zipper", Mode.HOST); + this.purposePrefix = Actions.escapeLabel(ruleContext.getLabel()) + "_"; + this.runtimeSolibDirBase = "_solib_" + "_" + Actions.escapeLabel(ruleContext.getLabel()); + this.staticRuntimesLibs = + ImmutableList.copyOf(ruleContext.getPrerequisites("static_runtime_libs", Mode.TARGET)); + this.dynamicRuntimesLibs = + ImmutableList.copyOf(ruleContext.getPrerequisites("dynamic_runtime_libs", Mode.TARGET)); + this.ccToolchainConfigInfo = + ruleContext.getPrerequisite( + CcToolchainRule.TOOLCHAIN_CONFIG_ATTR, Mode.TARGET, CcToolchainConfigInfo.PROVIDER); + + // If output_license is specified on the cc_toolchain rule, override the transitive licenses + // with that one. This is necessary because cc_toolchain is used in the target configuration, + // but it is sort-of-kind-of a tool, but various parts of it are linked into the output... + // ...so we trust the judgment of the author of the cc_toolchain rule to figure out what + // licenses should be propagated to C++ targets. + // TODO(elenairina): Remove this and use Attribute.Builder.useOutputLicenses() on the + // :cc_toolchain attribute instead. + final License outputLicense = + ruleContext.getRule().getToolOutputLicense(ruleContext.attributes()); + if (outputLicense != null && !outputLicense.equals(License.NO_LICENSE)) { + final NestedSet license = + NestedSetBuilder.create( + Order.STABLE_ORDER, new TargetLicense(ruleContext.getLabel(), outputLicense)); + this.licensesProvider = + new LicensesProviderImpl( + license, new TargetLicense(ruleContext.getLabel(), outputLicense)); + } else { + this.licensesProvider = null; + } + // TODO(b/65835260): Remove this conditional once j2objc can learn the toolchain type. + if (ruleContext.attributes().has(CcToolchain.CC_TOOLCHAIN_TYPE_ATTRIBUTE_NAME)) { + this.toolchainType = + ruleContext.attributes().get(CcToolchain.CC_TOOLCHAIN_TYPE_ATTRIBUTE_NAME, NODEP_LABEL); + } else { + this.toolchainType = null; + } + this.additionalBuildVariables = additionalBuildVariables; + } + + public String getCpu() { + return cpu; + } + + public boolean isSupportsParamFiles() { + return supportsParamFiles; + } + + public String getPurposePrefix() { + return purposePrefix; + } + + public String getRuntimeSolibDirBase() { + return runtimeSolibDirBase; + } + + public FdoPrefetchHintsProvider getFdoPrefetch() { + return fdoPrefetch; + } + + public String getToolchainIdentifier() { + return toolchainIdentifier; + } + + public Label getToolchainType() { + return toolchainType; + } + + public CcToolchainConfigInfo getCcToolchainConfigInfo() { + return ccToolchainConfigInfo; + } + + public ImmutableList getFdoOptimizeArtifacts() { + return fdoOptimizeArtifacts; + } + + public ImmutableList getStaticRuntimesLibs() { + return staticRuntimesLibs; + } + + public LicensesProvider getLicensesProvider() { + return licensesProvider; + } + + public ImmutableList getDynamicRuntimesLibs() { + return dynamicRuntimesLibs; + } + + public boolean isSupportsHeaderParsing() { + return supportsHeaderParsing; + } + + public CcToolchainVariables getAdditionalBuildVariables() { + return additionalBuildVariables; + } + + public NestedSet getCrosstool() { + return crosstool; + } + + public NestedSet getCrosstoolMiddleman() { + return crosstoolMiddleman; + } + + public NestedSet getCompile() { + return compile; + } + + public NestedSet getStrip() { + return strip; + } + + public NestedSet getObjcopy() { + return objcopy; + } + + public TransitiveInfoCollection getFdoOptimize() { + return fdoOptimize; + } + + public Artifact getLinkDynamicLibraryTool() { + + return linkDynamicLibraryTool; + } + + public TransitiveInfoCollection getModuleMap() { + return moduleMap; + } + + public NestedSet getAs() { + return as; + } + + public NestedSet getAr() { + return ar; + } + + public TransitiveInfoCollection getLibcTop() { + return libcTop; + } + + public NestedSet getLink() { + return link; + } + + public NestedSet getDwp() { + return dwp; + } + + public FdoProfileProvider getFdoOptimizeProvider() { + return fdoOptimizeProvider; + } + + public Artifact getModuleMapArtifact() { + return moduleMapArtifact; + } + + public String getProto() { + return proto; + } + + public NestedSet getFullInputsForCrosstool() { + return fullInputsForCrosstool; + } + + public FdoProfileProvider getFdoProfileProvider() { + return fdoProfileProvider; + } + + public Artifact getZipper() { + return zipper; + } + + public NestedSet getFullInputsForLink() { + return fullInputsForLink; + } + + public Label getCcToolchainLabel() { + return ccToolchainLabel; + } + + public NestedSet getCoverage() { + return coverage; + } + + public NestedSet getCompileWithoutIncludes() { + return compileWithoutIncludes; + } + + public NestedSet getLibc() { + return libc; + } + + public String getCompiler() { + return compiler; + } + + public Artifact getIfsoBuilder() { + return ifsoBuilder; + } + + private static NestedSet getMiddlemanOrFiles(RuleContext context, String attribute) { + return getMiddlemanOrFiles(context, attribute, Mode.HOST); + } + + private static NestedSet getMiddlemanOrFiles( + RuleContext context, String attribute, Mode mode) { + TransitiveInfoCollection dep = context.getPrerequisite(attribute, mode); + MiddlemanProvider middlemanProvider = dep.getProvider(MiddlemanProvider.class); + // We use the middleman if we can (if the dep is a filegroup), otherwise, just the regular + // filesToBuild (e.g. if it is a simple input file) + return middlemanProvider != null + ? middlemanProvider.getMiddlemanArtifact() + : dep.getProvider(FileProvider.class).getFilesToBuild(); + } + + private static NestedSet getOptionalMiddlemanOrFiles( + RuleContext context, String attribute) { + return getOptionalMiddlemanOrFiles(context, attribute, Mode.HOST); + } + + private static NestedSet getOptionalMiddlemanOrFiles( + RuleContext context, String attribute, Mode mode) { + TransitiveInfoCollection dep = context.getPrerequisite(attribute, mode); + return dep != null + ? getMiddlemanOrFiles(context, attribute, mode) + : NestedSetBuilder.emptySet(Order.STABLE_ORDER); + } + + private static NestedSet getOptionalFiles( + RuleContext ruleContext, String attribute, Mode mode) { + TransitiveInfoCollection dep = ruleContext.getPrerequisite(attribute, mode); + return dep != null + ? dep.getProvider(FileProvider.class).getFilesToBuild() + : NestedSetBuilder.emptySet(Order.STABLE_ORDER); + } + + /** + * Returns the crosstool-derived link action inputs for a given rule. Adds the given set of + * artifacts as extra inputs. + */ + private static NestedSet fullInputsForLink( + RuleContext ruleContext, + NestedSet link, + NestedSet libcMiddleman, + boolean isAppleToolchain) { + NestedSetBuilder builder = + NestedSetBuilder.stableOrder().addTransitive(link).addTransitive(libcMiddleman); + if (!isAppleToolchain) { + builder + .add(ruleContext.getPrerequisiteArtifact("$interface_library_builder", Mode.HOST)) + .add(ruleContext.getPrerequisiteArtifact("$link_dynamic_library_tool", Mode.HOST)); + } + return builder.build(); + } +} diff --git a/src/main/java/com/google/devtools/build/lib/rules/cpp/CcToolchainProviderHelper.java b/src/main/java/com/google/devtools/build/lib/rules/cpp/CcToolchainProviderHelper.java index 11640bcf9671fe..748166dfdd99e7 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/cpp/CcToolchainProviderHelper.java +++ b/src/main/java/com/google/devtools/build/lib/rules/cpp/CcToolchainProviderHelper.java @@ -13,18 +13,13 @@ // limitations under the License. package com.google.devtools.build.lib.rules.cpp; -import static com.google.devtools.build.lib.syntax.Type.BOOLEAN; -import static com.google.devtools.build.lib.syntax.Type.STRING; - import com.google.common.base.Preconditions; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; import com.google.common.collect.Iterables; -import com.google.devtools.build.lib.actions.Actions; import com.google.devtools.build.lib.actions.Artifact; import com.google.devtools.build.lib.analysis.CompilationHelper; import com.google.devtools.build.lib.analysis.FileProvider; -import com.google.devtools.build.lib.analysis.MiddlemanProvider; import com.google.devtools.build.lib.analysis.RuleContext; import com.google.devtools.build.lib.analysis.TransitiveInfoCollection; import com.google.devtools.build.lib.analysis.actions.CustomCommandLine; @@ -33,7 +28,6 @@ import com.google.devtools.build.lib.analysis.config.BuildConfiguration; import com.google.devtools.build.lib.analysis.config.CompilationMode; import com.google.devtools.build.lib.analysis.config.InvalidConfigurationException; -import com.google.devtools.build.lib.analysis.configuredtargets.RuleConfiguredTarget.Mode; import com.google.devtools.build.lib.cmdline.Label; import com.google.devtools.build.lib.cmdline.LabelSyntaxException; import com.google.devtools.build.lib.cmdline.PackageIdentifier; @@ -44,7 +38,6 @@ import com.google.devtools.build.lib.rules.cpp.CcSkyframeSupportFunction.CcSkyframeSupportException; import com.google.devtools.build.lib.rules.cpp.CppConfiguration.Tool; import com.google.devtools.build.lib.rules.cpp.FdoProvider.FdoMode; -import com.google.devtools.build.lib.syntax.Type; import com.google.devtools.build.lib.util.FileType; import com.google.devtools.build.lib.util.Pair; import com.google.devtools.build.lib.util.StringUtil; @@ -182,9 +175,8 @@ private static ImmutableMap getToolchainForSkylark( } private static PathFragment calculateSysroot( - RuleContext ruleContext, PathFragment defaultSysroot) { - TransitiveInfoCollection sysrootTarget = - ruleContext.getPrerequisite(CcToolchainRule.LIBC_TOP_ATTR, Mode.TARGET); + CcToolchainAttributesProvider attributes, PathFragment defaultSysroot) { + TransitiveInfoCollection sysrootTarget = attributes.getLibcTop(); if (sysrootTarget == null) { return defaultSysroot; } @@ -222,7 +214,10 @@ private static Artifact getPrefetchHintsArtifact( * the indexed format (.profdata) if necessary. */ private static Artifact convertLLVMRawProfileToIndexed( - PathFragment fdoProfile, CppToolchainInfo toolchainInfo, RuleContext ruleContext) { + CcToolchainAttributesProvider attributes, + PathFragment fdoProfile, + CppToolchainInfo toolchainInfo, + RuleContext ruleContext) { Artifact profileArtifact = ruleContext.getUniqueDirectoryArtifact( @@ -245,7 +240,7 @@ private static Artifact convertLLVMRawProfileToIndexed( if (CppFileTypes.LLVM_PROFILE_ZIP.matches(fdoProfile)) { // Get the zipper binary for unzipping the profile. - Artifact zipperBinaryArtifact = ruleContext.getPrerequisiteArtifact(":zipper", Mode.HOST); + Artifact zipperBinaryArtifact = attributes.getZipper(); if (zipperBinaryArtifact == null) { ruleContext.ruleError("Cannot find zipper binary to unzip the profile"); return null; @@ -315,7 +310,7 @@ private static Artifact convertLLVMRawProfileToIndexed( ruleContext.registerAction( new SpawnAction.Builder() .addInput(rawProfileArtifact) - .addTransitiveInputs(getMiddlemanOrFiles(ruleContext, "all_files")) + .addTransitiveInputs(attributes.getCrosstoolMiddleman()) .addOutput(profileArtifact) .useDefaultShellEnvironment() .setExecutable(toolchainInfo.getToolPathFragment(Tool.LLVM_PROFDATA)) @@ -334,9 +329,7 @@ private static Artifact convertLLVMRawProfileToIndexed( } static CcToolchainProvider getCcToolchainProvider( - RuleContext ruleContext, - boolean isAppleToolchain, - CcToolchainVariables additionalBuildVariables) + RuleContext ruleContext, CcToolchainAttributesProvider attributes) throws RuleErrorException, InterruptedException { BuildConfiguration configuration = Preconditions.checkNotNull(ruleContext.getConfiguration()); CppConfiguration cppConfiguration = @@ -348,9 +341,7 @@ static CcToolchainProvider getCcToolchainProvider( boolean allowInference = true; if (configuration.getCompilationMode() == CompilationMode.OPT) { if (cppConfiguration.getFdoPrefetchHintsLabel() != null) { - FdoPrefetchHintsProvider provider = - ruleContext.getPrerequisite( - ":fdo_prefetch_hints", Mode.TARGET, FdoPrefetchHintsProvider.PROVIDER); + FdoPrefetchHintsProvider provider = attributes.getFdoPrefetch(); prefetchHints = provider.getInputFile(); } if (cppConfiguration.getFdoPath() != null) { @@ -359,17 +350,12 @@ static CcToolchainProvider getCcToolchainProvider( // If fdo_profile rule is used, do not allow inferring proto.profile from AFDO profile. allowInference = false; - FdoProfileProvider fdoProfileProvider = - ruleContext.getPrerequisite( - CcToolchainRule.FDO_OPTIMIZE_ATTR, Mode.TARGET, FdoProfileProvider.PROVIDER); + FdoProfileProvider fdoProfileProvider = attributes.getFdoOptimizeProvider(); if (fdoProfileProvider != null) { fdoZip = fdoProfileProvider.getProfilePathFragment(); protoProfileArtifact = fdoProfileProvider.getProtoProfileArtifact(); } else { - ImmutableList fdoArtifacts = - ruleContext - .getPrerequisiteArtifacts(CcToolchainRule.FDO_OPTIMIZE_ATTR, Mode.TARGET) - .list(); + ImmutableList fdoArtifacts = attributes.getFdoOptimizeArtifacts(); if (fdoArtifacts.size() != 1) { ruleContext.ruleError("--fdo_optimize does not point to a single target"); return null; @@ -380,10 +366,7 @@ static CcToolchainProvider getCcToolchainProvider( ruleContext.ruleError("--fdo_optimize points to a target that is not an input file"); return null; } - Label fdoLabel = - ruleContext - .getPrerequisite(CcToolchainRule.FDO_OPTIMIZE_ATTR, Mode.TARGET) - .getLabel(); + Label fdoLabel = attributes.getFdoOptimize().getLabel(); if (!fdoLabel .getPackageIdentifier() .getPathUnderExecRoot() @@ -395,9 +378,7 @@ static CcToolchainProvider getCcToolchainProvider( fdoZip = fdoArtifact.getPath().asFragment(); } } else if (cppConfiguration.getFdoProfileLabel() != null) { - FdoProfileProvider fdoProvider = - ruleContext.getPrerequisite( - CcToolchainRule.FDO_PROFILE_ATTR, Mode.TARGET, FdoProfileProvider.PROVIDER); + FdoProfileProvider fdoProvider = attributes.getFdoProfileProvider(); fdoZip = fdoProvider.getProfilePathFragment(); protoProfileArtifact = fdoProvider.getProtoProfileArtifact(); } @@ -422,7 +403,7 @@ static CcToolchainProvider getCcToolchainProvider( } // Is there a toolchain proto available on the target directly? - CToolchain toolchain = parseToolchainFromAttributes(ruleContext); + CToolchain toolchain = parseToolchainFromAttributes(ruleContext, attributes); Label ccToolchainSuiteLabelIfNeeded = null; if (toolchain == null && cppConfiguration.getCrosstoolFromCcToolchainProtoAttribute() == null) { ccToolchainSuiteLabelIfNeeded = cppConfiguration.getCrosstoolTop(); @@ -445,36 +426,17 @@ static CcToolchainProvider getCcToolchainProvider( } CppToolchainInfo toolchainInfo = - getCppToolchainInfo(ruleContext, cppConfiguration, ccSkyframeSupportValue, toolchain); - - final Label label = ruleContext.getLabel(); - final NestedSet crosstool = - ruleContext - .getPrerequisite("all_files", Mode.HOST) - .getProvider(FileProvider.class) - .getFilesToBuild(); - final NestedSet crosstoolMiddleman = getMiddlemanOrFiles(ruleContext, "all_files"); - final NestedSet compile = getMiddlemanOrFiles(ruleContext, "compiler_files"); - final NestedSet compileWithoutIncludes = - getOptionalMiddlemanOrFiles(ruleContext, "compiler_files_without_includes"); - final NestedSet strip = getMiddlemanOrFiles(ruleContext, "strip_files"); - final NestedSet objcopy = getMiddlemanOrFiles(ruleContext, "objcopy_files"); - final NestedSet as = getOptionalMiddlemanOrFiles(ruleContext, "as_files"); - final NestedSet ar = getOptionalMiddlemanOrFiles(ruleContext, "ar_files"); - final NestedSet link = getMiddlemanOrFiles(ruleContext, "linker_files"); - final NestedSet dwp = getMiddlemanOrFiles(ruleContext, "dwp_files"); - final NestedSet libcMiddleman = - getOptionalMiddlemanOrFiles(ruleContext, CcToolchainRule.LIBC_TOP_ATTR, Mode.TARGET); - final NestedSet libc = - getOptionalFiles(ruleContext, CcToolchainRule.LIBC_TOP_ATTR, Mode.TARGET); - String purposePrefix = Actions.escapeLabel(label) + "_"; - String runtimeSolibDirBase = "_solib_" + "_" + Actions.escapeLabel(label); + getCppToolchainInfo( + ruleContext, cppConfiguration, attributes, ccSkyframeSupportValue, toolchain); + + String purposePrefix = attributes.getPurposePrefix(); + String runtimeSolibDirBase = attributes.getRuntimeSolibDirBase(); final PathFragment runtimeSolibDir = configuration.getBinFragment().getRelative(runtimeSolibDirBase); // Static runtime inputs. TransitiveInfoCollection staticRuntimeLibDep = - selectDep(ruleContext, "static_runtime_libs", toolchainInfo.getStaticRuntimeLibsLabel()); + selectDep(attributes.getStaticRuntimesLibs(), toolchainInfo.getStaticRuntimeLibsLabel()); final NestedSet staticRuntimeLinkInputs; final Artifact staticRuntimeLinkMiddleman; if (toolchainInfo.supportsEmbeddedRuntimes()) { @@ -501,7 +463,7 @@ static CcToolchainProvider getCcToolchainProvider( // Dynamic runtime inputs. TransitiveInfoCollection dynamicRuntimeLibDep = - selectDep(ruleContext, "dynamic_runtime_libs", toolchainInfo.getDynamicRuntimeLibsLabel()); + selectDep(attributes.getDynamicRuntimesLibs(), toolchainInfo.getDynamicRuntimeLibsLabel()); NestedSet dynamicRuntimeLinkSymlinks; List dynamicRuntimeLinkInputs = new ArrayList<>(); Artifact dynamicRuntimeLinkMiddleman; @@ -547,23 +509,15 @@ static CcToolchainProvider getCcToolchainProvider( CcCompilationContext.Builder ccCompilationContextBuilder = new CcCompilationContext.Builder(ruleContext); - CppModuleMap moduleMap = createCrosstoolModuleMap(ruleContext); + CppModuleMap moduleMap = createCrosstoolModuleMap(attributes); if (moduleMap != null) { ccCompilationContextBuilder.setCppModuleMap(moduleMap); } final CcCompilationContext ccCompilationContext = ccCompilationContextBuilder.build(); - boolean supportsParamFiles = ruleContext.attributes().get("supports_param_files", BOOLEAN); - boolean supportsHeaderParsing = - ruleContext.attributes().get("supports_header_parsing", BOOLEAN); NestedSetBuilder> coverageEnvironment = NestedSetBuilder.compileOrder(); - NestedSet coverage = getOptionalMiddlemanOrFiles(ruleContext, "coverage_files"); - if (coverage.isEmpty()) { - coverage = crosstool; - } - - PathFragment sysroot = calculateSysroot(ruleContext, toolchainInfo.getDefaultSysroot()); + PathFragment sysroot = calculateSysroot(attributes, toolchainInfo.getDefaultSysroot()); ImmutableList.Builder builtInIncludeDirectoriesBuilder = ImmutableList.builder(); for (String s : toolchainInfo.getRawBuiltInIncludeDirectories()) { @@ -589,7 +543,10 @@ static CcToolchainProvider getCcToolchainProvider( if (fdoMode == FdoMode.LLVM_FDO) { profileArtifact = convertLLVMRawProfileToIndexed( - ccSkyframeSupportValue.getFdoZipPath().asFragment(), toolchainInfo, ruleContext); + attributes, + ccSkyframeSupportValue.getFdoZipPath().asFragment(), + toolchainInfo, + ruleContext); if (ruleContext.hasErrors()) { return null; } @@ -614,35 +571,36 @@ static CcToolchainProvider getCcToolchainProvider( cppConfiguration, toolchainInfo, cppConfiguration.getCrosstoolTopPathFragment(), - crosstool, - /* crosstoolMiddleman= */ NestedSetBuilder.stableOrder() - .addTransitive(crosstoolMiddleman) - .addTransitive(libcMiddleman) - .build(), - compile, - compileWithoutIncludes, - strip, - objcopy, - as, - ar, - fullInputsForLink(ruleContext, link, libcMiddleman, isAppleToolchain), - ruleContext.getPrerequisiteArtifact("$interface_library_builder", Mode.HOST), - dwp, - coverage, - libc, + attributes.getCrosstool(), + attributes.getFullInputsForCrosstool(), + attributes.getCompile(), + attributes.getCompileWithoutIncludes(), + attributes.getStrip(), + attributes.getObjcopy(), + attributes.getAs(), + attributes.getAr(), + attributes.getFullInputsForLink(), + attributes.getIfsoBuilder(), + attributes.getDwp(), + attributes.getCoverage(), + attributes.getLibc(), staticRuntimeLinkInputs, staticRuntimeLinkMiddleman, dynamicRuntimeLinkSymlinks, dynamicRuntimeLinkMiddleman, runtimeSolibDir, ccCompilationContext, - supportsParamFiles, - supportsHeaderParsing, - getBuildVariables(ruleContext, toolchainInfo.getDefaultSysroot(), additionalBuildVariables), - getBuiltinIncludes(libc), + attributes.isSupportsParamFiles(), + attributes.isSupportsHeaderParsing(), + getBuildVariables( + ruleContext, + attributes, + toolchainInfo.getDefaultSysroot(), + attributes.getAdditionalBuildVariables()), + getBuiltinIncludes(attributes.getLibc()), coverageEnvironment.build(), toolchainInfo.supportsInterfaceSharedObjects() - ? ruleContext.getPrerequisiteArtifact("$link_dynamic_library_tool", Mode.HOST) + ? attributes.getLinkDynamicLibraryTool() : null, builtInIncludeDirectories, sysroot, @@ -664,15 +622,15 @@ static CcToolchainProvider getCcToolchainProvider( private static CppToolchainInfo getCppToolchainInfo( RuleContext ruleContext, CppConfiguration cppConfiguration, + CcToolchainAttributesProvider attributes, CcSkyframeSupportValue ccSkyframeSupportValue, CToolchain toolchainFromCcToolchainAttribute) throws RuleErrorException { if (cppConfiguration.enableCcToolchainConfigInfoFromSkylark()) { // Attempt to obtain CppToolchainInfo from the 'toolchain_config' attribute of cc_toolchain. - CcToolchainConfigInfo configInfo = - ruleContext.getPrerequisite( - CcToolchainRule.TOOLCHAIN_CONFIG_ATTR, Mode.TARGET, CcToolchainConfigInfo.PROVIDER); + CcToolchainConfigInfo configInfo = attributes.getCcToolchainConfigInfo(); + if (configInfo != null) { try { return CppToolchainInfo.create( @@ -691,7 +649,9 @@ private static CppToolchainInfo getCppToolchainInfo( // Attempt to find a toolchain based on the target attributes, not the configuration. CToolchain toolchain = toolchainFromCcToolchainAttribute; if (toolchain == null) { - toolchain = getToolchainFromAttributes(ruleContext, cppConfiguration, ccSkyframeSupportValue); + toolchain = + getToolchainFromAttributes( + ruleContext, attributes, cppConfiguration, ccSkyframeSupportValue); } // If we found a toolchain, use it. @@ -702,7 +662,7 @@ private static CppToolchainInfo getCppToolchainInfo( CcToolchainConfigInfo ccToolchainConfigInfo = CcToolchainConfigInfo.fromToolchain(toolchain); return CppToolchainInfo.create( cppConfiguration.getCrosstoolTopPathFragment(), - cppConfiguration.getCcToolchainRuleLabel(), + attributes.getCcToolchainLabel(), ccToolchainConfigInfo, cppConfiguration.disableLegacyCrosstoolFields(), cppConfiguration.disableCompilationModeFlags(), @@ -713,9 +673,9 @@ private static CppToolchainInfo getCppToolchainInfo( } @Nullable - private static CToolchain parseToolchainFromAttributes(RuleContext ruleContext) - throws RuleErrorException { - String protoAttribute = StringUtil.emptyToNull(ruleContext.attributes().get("proto", STRING)); + private static CToolchain parseToolchainFromAttributes( + RuleContext ruleContext, CcToolchainAttributesProvider attributes) throws RuleErrorException { + String protoAttribute = StringUtil.emptyToNull(attributes.getProto()); if (protoAttribute == null) { return null; } @@ -750,13 +710,10 @@ private static void reportInvalidOptions(RuleContext ruleContext, CppToolchainIn @Nullable private static CToolchain getToolchainFromAttributes( RuleContext ruleContext, + CcToolchainAttributesProvider attributes, CppConfiguration cppConfiguration, CcSkyframeSupportValue ccSkyframeSupportValue) throws RuleErrorException { - - String toolchainIdentifier = ruleContext.attributes().get("toolchain_identifier", Type.STRING); - String cpu = ruleContext.attributes().get("cpu", Type.STRING); - String compiler = ruleContext.attributes().get("compiler", Type.STRING); try { CrosstoolRelease crosstoolRelease; if (cppConfiguration.getCrosstoolFromCcToolchainProtoAttribute() != null) { @@ -768,9 +725,9 @@ private static CToolchain getToolchainFromAttributes( } return CToolchainSelectionUtils.selectCToolchain( - toolchainIdentifier, - cpu, - compiler, + attributes.getToolchainIdentifier(), + attributes.getCpu(), + attributes.getCompiler(), cppConfiguration.getTransformedCpuFromOptions(), cppConfiguration.getCompilerFromOptions(), crosstoolRelease); @@ -792,11 +749,11 @@ private static ImmutableList getBuiltinIncludes(NestedSet li return result.build(); } - private static CppModuleMap createCrosstoolModuleMap(RuleContext ruleContext) { - if (ruleContext.getPrerequisite("module_map", Mode.HOST) == null) { + private static CppModuleMap createCrosstoolModuleMap(CcToolchainAttributesProvider attributes) { + if (attributes.getModuleMap() == null) { return null; } - Artifact moduleMapArtifact = ruleContext.getPrerequisiteArtifact("module_map", Mode.HOST); + Artifact moduleMapArtifact = attributes.getModuleMapArtifact(); if (moduleMapArtifact == null) { return null; } @@ -804,50 +761,14 @@ private static CppModuleMap createCrosstoolModuleMap(RuleContext ruleContext) { } static TransitiveInfoCollection selectDep( - RuleContext ruleContext, String attribute, Label label) { - for (TransitiveInfoCollection dep : ruleContext.getPrerequisites(attribute, Mode.TARGET)) { + ImmutableList deps, Label label) { + for (TransitiveInfoCollection dep : deps) { if (dep.getLabel().equals(label)) { return dep; } } - return ruleContext.getPrerequisites(attribute, Mode.TARGET).get(0); - } - - private static NestedSet getMiddlemanOrFiles(RuleContext context, String attribute) { - return getMiddlemanOrFiles(context, attribute, Mode.HOST); - } - - private static NestedSet getMiddlemanOrFiles( - RuleContext context, String attribute, Mode mode) { - TransitiveInfoCollection dep = context.getPrerequisite(attribute, mode); - MiddlemanProvider middlemanProvider = dep.getProvider(MiddlemanProvider.class); - // We use the middleman if we can (if the dep is a filegroup), otherwise, just the regular - // filesToBuild (e.g. if it is a simple input file) - return middlemanProvider != null - ? middlemanProvider.getMiddlemanArtifact() - : dep.getProvider(FileProvider.class).getFilesToBuild(); - } - - private static NestedSet getOptionalMiddlemanOrFiles( - RuleContext context, String attribute) { - return getOptionalMiddlemanOrFiles(context, attribute, Mode.HOST); - } - - private static NestedSet getOptionalMiddlemanOrFiles( - RuleContext context, String attribute, Mode mode) { - TransitiveInfoCollection dep = context.getPrerequisite(attribute, mode); - return dep != null - ? getMiddlemanOrFiles(context, attribute, mode) - : NestedSetBuilder.emptySet(Order.STABLE_ORDER); - } - - private static NestedSet getOptionalFiles( - RuleContext ruleContext, String attribute, Mode mode) { - TransitiveInfoCollection dep = ruleContext.getPrerequisite(attribute, mode); - return dep != null - ? dep.getProvider(FileProvider.class).getFilesToBuild() - : NestedSetBuilder.emptySet(Order.STABLE_ORDER); + return deps.get(0); } /** @@ -862,6 +783,7 @@ private static NestedSet getOptionalFiles( */ private static final CcToolchainVariables getBuildVariables( RuleContext ruleContext, + CcToolchainAttributesProvider attributes, PathFragment defaultSysroot, CcToolchainVariables additionalBuildVariables) { CcToolchainVariables.Builder variables = new CcToolchainVariables.Builder(); @@ -873,7 +795,7 @@ private static final CcToolchainVariables getBuildVariables( variables.addStringVariable(CcCommon.MINIMUM_OS_VERSION_VARIABLE_NAME, minOsVersion); } - PathFragment sysroot = calculateSysroot(ruleContext, defaultSysroot); + PathFragment sysroot = calculateSysroot(attributes, defaultSysroot); if (sysroot != null) { variables.addStringVariable(CcCommon.SYSROOT_VARIABLE_NAME, sysroot.getPathString()); } @@ -882,23 +804,4 @@ private static final CcToolchainVariables getBuildVariables( return variables.build(); } - - /** - * Returns the crosstool-derived link action inputs for a given rule. Adds the given set of - * artifacts as extra inputs. - */ - private static NestedSet fullInputsForLink( - RuleContext ruleContext, - NestedSet link, - NestedSet libcLink, - boolean isAppleToolchain) { - NestedSetBuilder builder = - NestedSetBuilder.stableOrder().addTransitive(link).addTransitive(libcLink); - if (!isAppleToolchain) { - builder - .add(ruleContext.getPrerequisiteArtifact("$interface_library_builder", Mode.HOST)) - .add(ruleContext.getPrerequisiteArtifact("$link_dynamic_library_tool", Mode.HOST)); - } - return builder.build(); - } }