From bb96c93761732781f51f46d44fd57fef86ec42f0 Mon Sep 17 00:00:00 2001 From: Luca Di Grazia Date: Sun, 4 Sep 2022 20:11:05 +0200 Subject: [PATCH] Move some error reporting from cc_toolchain to rules This is unfortunate, confusing for the user, and less accurate than what the original behavior was, but because cc_toolchain cannot access (currently, with platforms enabled) the target configuration, there is nothing we can do other than showing the error for the target. https://github.com/bazelbuild/bazel/issues/6516 RELNOTES: None PiperOrigin-RevId: 240345500 --- .../lib/bazel/rules/BazelRulesModule.java | 13 - .../build/lib/rules/cpp/CcBinary.java | 2 +- .../build/lib/rules/cpp/CcCommon.java | 93 ++- .../build/lib/rules/cpp/CcImport.java | 1 + .../build/lib/rules/cpp/CcLibrary.java | 4 +- .../lib/rules/cpp/CcToolchainProvider.java | 188 +++++- .../rules/cpp/CcToolchainProviderHelper.java | 557 ++++++++++++++---- .../build/lib/rules/cpp/CcToolchainSuite.java | 21 +- 8 files changed, 731 insertions(+), 148 deletions(-) diff --git a/dataset/GitHub_Java/bazelbuild.bazel/src/main/java/com/google/devtools/build/lib/bazel/rules/BazelRulesModule.java b/dataset/GitHub_Java/bazelbuild.bazel/src/main/java/com/google/devtools/build/lib/bazel/rules/BazelRulesModule.java index d8682134423..68f95e53559 100644 --- a/dataset/GitHub_Java/bazelbuild.bazel/src/main/java/com/google/devtools/build/lib/bazel/rules/BazelRulesModule.java +++ b/dataset/GitHub_Java/bazelbuild.bazel/src/main/java/com/google/devtools/build/lib/bazel/rules/BazelRulesModule.java @@ -43,19 +43,6 @@ public class BazelRulesModule extends BlazeModule { /** This is where deprecated options go to die. */ public static class GraveyardOptions extends OptionsBase { - @Option( - name = "incompatible_disable_legacy_crosstool_fields", - oldName = "experimental_disable_legacy_crosstool_fields", - defaultValue = "true", - documentationCategory = OptionDocumentationCategory.UNDOCUMENTED, - effectTags = {OptionEffectTag.LOADING_AND_ANALYSIS}, - metadataTags = { - OptionMetadataTag.INCOMPATIBLE_CHANGE, - OptionMetadataTag.TRIGGERED_BY_ALL_INCOMPATIBLE_CHANGES - }, - help = "Deprecated no-op.") - public boolean disableLegacyCrosstoolFields; - @Option( name = "incompatible_require_feature_configuration_for_pic", defaultValue = "true", diff --git a/dataset/GitHub_Java/bazelbuild.bazel/src/main/java/com/google/devtools/build/lib/rules/cpp/CcBinary.java b/dataset/GitHub_Java/bazelbuild.bazel/src/main/java/com/google/devtools/build/lib/rules/cpp/CcBinary.java index 9dba0a7859e..dfc5d044495 100644 --- a/dataset/GitHub_Java/bazelbuild.bazel/src/main/java/com/google/devtools/build/lib/rules/cpp/CcBinary.java +++ b/dataset/GitHub_Java/bazelbuild.bazel/src/main/java/com/google/devtools/build/lib/rules/cpp/CcBinary.java @@ -218,7 +218,7 @@ private static Runfiles collectRunfiles( // inputs for compilation. Node that these cannot be middlemen because Runfiles does not // know how to expand them. builder.addTransitiveArtifacts(toolchain.getAllFiles()); - builder.addTransitiveArtifacts(toolchain.getLibcLink(cppConfiguration)); + builder.addTransitiveArtifacts(toolchain.getLibcLink()); // Add the sources files that are used to compile the object files. // We add the headers in the transitive closure and our own sources in the srcs // attribute. We do not provide the auxiliary inputs, because they are only used when we diff --git a/dataset/GitHub_Java/bazelbuild.bazel/src/main/java/com/google/devtools/build/lib/rules/cpp/CcCommon.java b/dataset/GitHub_Java/bazelbuild.bazel/src/main/java/com/google/devtools/build/lib/rules/cpp/CcCommon.java index 2fa773acaf4..4971c41a280 100644 --- a/dataset/GitHub_Java/bazelbuild.bazel/src/main/java/com/google/devtools/build/lib/rules/cpp/CcCommon.java +++ b/dataset/GitHub_Java/bazelbuild.bazel/src/main/java/com/google/devtools/build/lib/rules/cpp/CcCommon.java @@ -141,6 +141,18 @@ public void collectMetadataArtifacts(Iterable objectFiles, .addAll(ALL_OTHER_ACTIONS) .build(); + /** Features we request to enable unless a rule explicitly doesn't support them. */ + private static final ImmutableSet DEFAULT_FEATURES = + ImmutableSet.of( + CppRuleClasses.DEPENDENCY_FILE, + CppRuleClasses.RANDOM_SEED, + CppRuleClasses.MODULE_MAPS, + CppRuleClasses.MODULE_MAP_HOME_CWD, + CppRuleClasses.HEADER_MODULE_COMPILE, + CppRuleClasses.INCLUDE_PATHS, + CppRuleClasses.PIC, + CppRuleClasses.PREPROCESSOR_DEFINES); + public static final String CC_TOOLCHAIN_DEFAULT_ATTRIBUTE_NAME = ":cc_toolchain"; private static final String SYSROOT_FLAG = "--sysroot="; @@ -412,6 +424,21 @@ public void reportInvalidOptions(RuleContext ruleContext) { public static void reportInvalidOptions( RuleContext ruleContext, CppConfiguration cppConfiguration, CcToolchainProvider ccToolchain) { + if (cppConfiguration.fissionIsActiveForCurrentCompilationMode() + && !ccToolchain.supportsFission()) { + ruleContext.ruleWarning( + "Fission is not supported by this crosstool. Please use a " + + "supporting crosstool to enable fission"); + } + if (cppConfiguration.buildTestDwpIsActivated() + && !(ccToolchain.supportsFission() + && cppConfiguration.fissionIsActiveForCurrentCompilationMode())) { + ruleContext.ruleWarning( + "Test dwp file requested, but Fission is not enabled. To generate a " + + "dwp for the test executable, use '--fission=yes' with a toolchain that supports " + + "Fission to build statically."); + } + if (cppConfiguration.getLibcTopLabel() != null && ccToolchain.getDefaultSysroot() == null) { ruleContext.ruleError( "The selected toolchain " @@ -735,6 +762,46 @@ public static ImmutableList getCoverageFeatures(CppConfiguration cppConf return coverageFeatures.build(); } + /** + * Determines whether to statically link the C++ runtimes. + * + *

This is complicated because it depends both on a legacy field in the CROSSTOOL + * protobuf--supports_embedded_runtimes--and the newer crosstool + * feature--statically_link_cpp_runtimes. Neither, one, or both could be present or set. Or they + * could be set in to conflicting values. + * + * @return true if we should statically link, false otherwise. + */ + private static boolean enableStaticLinkCppRuntimesFeature( + ImmutableSet requestedFeatures, + ImmutableSet disabledFeatures, + CcToolchainProvider toolchain) { + // All of these cases are encountered in various unit tests, + // integration tests, and obscure CROSSTOOLs. + + // A. If the legacy field "supports_embedded_runtimes" is false (or not present): + // dynamically link the cpp runtimes. Done. + if (!toolchain.supportsEmbeddedRuntimes()) { + return false; + } + // From here, the toolchain _can_ statically link the cpp runtime. + // + // B. If the feature static_link_cpp_runtimes is disabled: + // dynamically link the cpp runtimes. Done. + if (disabledFeatures.contains(CppRuleClasses.STATIC_LINK_CPP_RUNTIMES)) { + return false; + } + // C. If the feature is not requested: + // the feature is neither disabled nor requested: statically + // link (for compatibility with the legacy field). + if (!requestedFeatures.contains(CppRuleClasses.STATIC_LINK_CPP_RUNTIMES)) { + return true; + } + // D. The feature is requested: + // statically link the cpp runtimes. Done. + return true; + } + /** * Creates a feature configuration for a given rule. Assumes strictly cc sources. * @@ -791,6 +858,20 @@ public static FeatureConfiguration configureFeaturesOrThrowEvalException( unsupportedFeaturesBuilder.add(CppRuleClasses.MODULE_MAPS); } + if (toolchain.supportsEmbeddedRuntimes()) { + if (!cppConfiguration.disableLegacyCrosstoolFields()) { + // If we're not using legacy crosstool fields, we assume 'static_link_cpp_runtimes' feature + // is enabled by default for toolchains that support it, and can be disabled by the user + // when needed using --feature=-static_link_cpp_runtimes option or + // features = [ '-static_link_cpp_runtimes' ] rule attribute. + if (enableStaticLinkCppRuntimesFeature(requestedFeatures, unsupportedFeatures, toolchain)) { + allRequestedFeaturesBuilder.add(CppRuleClasses.STATIC_LINK_CPP_RUNTIMES); + } else { + unsupportedFeaturesBuilder.add(CppRuleClasses.STATIC_LINK_CPP_RUNTIMES); + } + } + } + if (cppConfiguration.forcePic()) { if (unsupportedFeatures.contains(CppRuleClasses.SUPPORTS_PIC)) { throw new EvalException(/* location= */ null, PIC_CONFIGURATION_ERROR); @@ -819,6 +900,10 @@ public static FeatureConfiguration configureFeaturesOrThrowEvalException( ImmutableList.Builder allFeatures = new ImmutableList.Builder() .addAll(ImmutableSet.of(cppConfiguration.getCompilationMode().toString())) + .addAll( + cppConfiguration.disableLegacyCrosstoolFields() + ? ImmutableList.of() + : DEFAULT_FEATURES) .addAll(DEFAULT_ACTION_CONFIGS) .addAll(requestedFeatures) .addAll(toolchain.getFeatures().getDefaultFeaturesAndActionConfigs()); @@ -831,6 +916,12 @@ public static FeatureConfiguration configureFeaturesOrThrowEvalException( } } + if (cppConfiguration.fissionIsActiveForCurrentCompilationMode() + && toolchain.supportsFission() + && !cppConfiguration.disableLegacyCrosstoolFields()) { + allFeatures.add(CppRuleClasses.PER_OBJECT_DEBUG_INFO); + } + allFeatures.addAll(getCoverageFeatures(cppConfiguration)); String fdoInstrument = cppConfiguration.getFdoInstrument(); @@ -894,7 +985,7 @@ public static FeatureConfiguration configureFeaturesOrThrowEvalException( + "This is most likely a misconfiguration in the C++ toolchain."); } } - if ((cppConfiguration.forcePic()) + if ((cppConfiguration.forcePic() || toolchain.toolchainNeedsPic()) && (!featureConfiguration.isEnabled(CppRuleClasses.PIC) && !featureConfiguration.isEnabled(CppRuleClasses.SUPPORTS_PIC))) { throw new EvalException(/* location= */ null, PIC_CONFIGURATION_ERROR); diff --git a/dataset/GitHub_Java/bazelbuild.bazel/src/main/java/com/google/devtools/build/lib/rules/cpp/CcImport.java b/dataset/GitHub_Java/bazelbuild.bazel/src/main/java/com/google/devtools/build/lib/rules/cpp/CcImport.java index b93932adac6..83d08bfdf6e 100644 --- a/dataset/GitHub_Java/bazelbuild.bazel/src/main/java/com/google/devtools/build/lib/rules/cpp/CcImport.java +++ b/dataset/GitHub_Java/bazelbuild.bazel/src/main/java/com/google/devtools/build/lib/rules/cpp/CcImport.java @@ -165,6 +165,7 @@ public ConfiguredTarget create(RuleContext ruleContext) ccToolchain.getFdoContext()) .addPublicHeaders(common.getHeaders()) .setHeadersCheckingMode(HeadersCheckingMode.STRICT) + .addQuoteIncludeDirs(semantics.getQuoteIncludes(ruleContext)) .setCodeCoverageEnabled(CcCompilationHelper.isCodeCoverageEnabled(ruleContext)) .compile(); diff --git a/dataset/GitHub_Java/bazelbuild.bazel/src/main/java/com/google/devtools/build/lib/rules/cpp/CcLibrary.java b/dataset/GitHub_Java/bazelbuild.bazel/src/main/java/com/google/devtools/build/lib/rules/cpp/CcLibrary.java index b4cf8cb239f..cc08f656299 100644 --- a/dataset/GitHub_Java/bazelbuild.bazel/src/main/java/com/google/devtools/build/lib/rules/cpp/CcLibrary.java +++ b/dataset/GitHub_Java/bazelbuild.bazel/src/main/java/com/google/devtools/build/lib/rules/cpp/CcLibrary.java @@ -282,12 +282,12 @@ public static void init( CompilationInfo compilationInfo = compilationHelper.compile(); CcCompilationOutputs precompiledFilesObjects = - CcCompilationOutputs.builder() + new CcCompilationOutputs.Builder() .addObjectFiles(precompiledFiles.getObjectFiles(/* usePic= */ true)) .addPicObjectFiles(precompiledFiles.getObjectFiles(/* usePic= */ true)) .build(); CcCompilationOutputs ccCompilationOutputs = - CcCompilationOutputs.builder() + new CcCompilationOutputs.Builder() .merge(precompiledFilesObjects) .merge(compilationInfo.getCcCompilationOutputs()) .build(); diff --git a/dataset/GitHub_Java/bazelbuild.bazel/src/main/java/com/google/devtools/build/lib/rules/cpp/CcToolchainProvider.java b/dataset/GitHub_Java/bazelbuild.bazel/src/main/java/com/google/devtools/build/lib/rules/cpp/CcToolchainProvider.java index 9613069fb74..23aa991ff21 100644 --- a/dataset/GitHub_Java/bazelbuild.bazel/src/main/java/com/google/devtools/build/lib/rules/cpp/CcToolchainProvider.java +++ b/dataset/GitHub_Java/bazelbuild.bazel/src/main/java/com/google/devtools/build/lib/rules/cpp/CcToolchainProvider.java @@ -16,10 +16,12 @@ import com.google.common.base.Function; import com.google.common.base.Preconditions; import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableListMultimap; import com.google.common.collect.ImmutableMap; import com.google.devtools.build.lib.actions.Artifact; import com.google.devtools.build.lib.analysis.LicensesProvider; 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.platform.ToolchainInfo; import com.google.devtools.build.lib.cmdline.Label; import com.google.devtools.build.lib.collect.nestedset.NestedSet; @@ -32,10 +34,12 @@ import com.google.devtools.build.lib.rules.cpp.CcToolchainFeatures.FeatureConfiguration; import com.google.devtools.build.lib.rules.cpp.CppConfiguration.Tool; import com.google.devtools.build.lib.rules.cpp.LibraryToLink.CcLinkingContext; +import com.google.devtools.build.lib.rules.cpp.Link.LinkingMode; import com.google.devtools.build.lib.skyframe.serialization.autocodec.AutoCodec; import com.google.devtools.build.lib.skylarkbuildapi.cpp.CcToolchainProviderApi; import com.google.devtools.build.lib.syntax.SkylarkNestedSet; import com.google.devtools.build.lib.vfs.PathFragment; +import com.google.devtools.build.lib.view.config.crosstool.CrosstoolConfig.CToolchain; import java.util.Map; import javax.annotation.Nullable; @@ -273,6 +277,7 @@ public boolean usePicForDynamicLibrariesFromStarlark( public boolean usePicForDynamicLibraries( CppConfiguration cppConfiguration, FeatureConfiguration featureConfiguration) { return cppConfiguration.forcePic() + || toolchainNeedsPic() || featureConfiguration.isEnabled(CppRuleClasses.SUPPORTS_PIC); } @@ -525,6 +530,14 @@ public Label getCcToolchainLabel() { return toolchainInfo.getCcToolchainLabel(); } + /** + * Returns whether shared libraries must be compiled with position independent code on this + * platform. + */ + public boolean toolchainNeedsPic() { + return toolchainInfo.toolchainNeedsPic(); + } + /** * Returns the run time sysroot, which is where the dynamic linker and system libraries are found * at runtime. This is usually an absolute path. If the toolchain compiler does not support @@ -544,7 +557,16 @@ public String getSolibDirectory() { /** Returns whether the toolchain supports dynamic linking. */ public boolean supportsDynamicLinker(FeatureConfiguration featureConfiguration) { - return featureConfiguration.isEnabled(CppRuleClasses.SUPPORTS_DYNAMIC_LINKER); + return toolchainInfo.supportsDynamicLinker() + || featureConfiguration.isEnabled(CppRuleClasses.SUPPORTS_DYNAMIC_LINKER); + } + + /** + * Returns whether the toolchain supports linking C/C++ runtime libraries + * supplied inside the toolchain distribution. + */ + public boolean supportsEmbeddedRuntimes() { + return toolchainInfo.supportsEmbeddedRuntimes(); } public boolean doNotSplitLinkingCmdline() { @@ -555,12 +577,14 @@ public boolean doNotSplitLinkingCmdline() { /** Returns whether the toolchain supports the --start-lib/--end-lib options. */ public boolean supportsStartEndLib(FeatureConfiguration featureConfiguration) { - return featureConfiguration.isEnabled(CppRuleClasses.SUPPORTS_START_END_LIB); + return toolchainInfo.supportsStartEndLib() + || featureConfiguration.isEnabled(CppRuleClasses.SUPPORTS_START_END_LIB); } /** Returns whether this toolchain supports interface shared libraries. */ public boolean supportsInterfaceSharedLibraries(FeatureConfiguration featureConfiguration) { - return featureConfiguration.isEnabled(CppRuleClasses.SUPPORTS_INTERFACE_SHARED_LIBRARIES); + return toolchainInfo.supportsInterfaceSharedLibraries() + || featureConfiguration.isEnabled(CppRuleClasses.SUPPORTS_INTERFACE_SHARED_LIBRARIES); } /** @@ -647,6 +671,24 @@ public String getAbiGlibcVersion() { return toolchainInfo.getAbiGlibcVersion(); } + /** + * Returns a label that references the library files needed to statically + * link the C++ runtime (i.e. libgcc.a, libgcc_eh.a, libstdc++.a) for the + * target architecture. + */ + public Label getStaticRuntimeLibsLabel() { + return toolchainInfo.getStaticRuntimeLibsLabel(); + } + + /** + * Returns a label that references the library files needed to dynamically + * link the C++ runtime (i.e. libgcc_s.so, libstdc++.so) for the target + * architecture. + */ + public Label getDynamicRuntimeLibsLabel() { + return toolchainInfo.getDynamicRuntimeLibsLabel(); + } + /** Returns the compiler version string (e.g. "gcc-4.1.1"). */ @Override public String getCompiler() { @@ -692,6 +734,18 @@ public FdoContext getFdoContext() { return fdoContext; } + /** + * Returns whether the toolchain supports "Fission" C++ builds, i.e. builds where compilation + * partitions object code and debug symbols into separate output files. + */ + public boolean supportsFission() { + return toolchainInfo.supportsFission(); + } + + public ImmutableList getUnfilteredCompilerOptions() { + return toolchainInfo.getUnfilteredCompilerOptions(/* sysroot= */ null); + } + /** * Unused, for compatibility with things internal to Google. * @@ -702,11 +756,132 @@ public String getTargetOS() { return toolchainInfo.getTargetOS(); } + /** + * Returns test-only link options such that certain test-specific features can be configured + * separately (e.g. lazy binding). + */ + public ImmutableList getTestOnlyLinkOptions() { + return toolchainInfo.getTestOnlyLinkOptions(); + } + /** Returns the system name which is required by the toolchain to run. */ public String getHostSystemName() { return toolchainInfo.getHostSystemName(); } + /** + * Returns the list of options to be used with 'objcopy' when converting binary files to object + * files, or {@code null} if this operation is not supported. + */ + public ImmutableList getObjCopyOptionsForEmbedding() { + return toolchainInfo.getObjCopyOptionsForEmbedding(); + } + + /** + * Returns the list of options to be used with 'ld' when converting binary files to object files, + * or {@code null} if this operation is not supported. + */ + public ImmutableList getLdOptionsForEmbedding() { + return toolchainInfo.getLdOptionsForEmbedding(); + } + + /** + * Returns link options for the specified flag list, combined with universal options for all + * shared libraries (regardless of link staticness). + */ + ImmutableList getSharedLibraryLinkOptions(ImmutableList flags) { + return toolchainInfo.getSharedLibraryLinkOptions(flags); + } + + /** Returns compiler flags arising from the {@link CToolchain}. */ + ImmutableList getToolchainCompilerFlags() { + return toolchainInfo.getCompilerFlags(); + } + + /** Returns additional compiler flags for C++ arising from the {@link CToolchain} */ + ImmutableList getToolchainCxxFlags() { + return toolchainInfo.getCxxFlags(); + } + + /** + * Returns compiler flags arising from the {@link CToolchain} for C compilation by compilation + * mode. + */ + ImmutableListMultimap getCFlagsByCompilationMode() { + return toolchainInfo.getCFlagsByCompilationMode(); + } + + /** + * Returns compiler flags arising from the {@link CToolchain} for C++ compilation by compilation + * mode. + */ + ImmutableListMultimap getCxxFlagsByCompilationMode() { + return toolchainInfo.getCxxFlagsByCompilationMode(); + } + + /** Returns linker flags for fully statically linked outputs. */ + ImmutableList getLegacyFullyStaticLinkFlags(CompilationMode compilationMode) { + return configureAllLegacyLinkOptions(compilationMode, LinkingMode.LEGACY_FULLY_STATIC); + } + + /** Returns linker flags for mostly static linked outputs. */ + ImmutableList getLegacyMostlyStaticLinkFlags(CompilationMode compilationMode) { + return configureAllLegacyLinkOptions(compilationMode, LinkingMode.STATIC); + } + + /** Returns linker flags for mostly static shared linked outputs. */ + ImmutableList getLegacyMostlyStaticSharedLinkFlags(CompilationMode compilationMode) { + return configureAllLegacyLinkOptions( + compilationMode, LinkingMode.LEGACY_MOSTLY_STATIC_LIBRARIES); + } + + /** Returns linker flags for artifacts that are not fully or mostly statically linked. */ + ImmutableList getLegacyDynamicLinkFlags(CompilationMode compilationMode) { + return configureAllLegacyLinkOptions(compilationMode, LinkingMode.DYNAMIC); + } + + /** + * Return all flags coming from naked {@code linker_flag} fields in the crosstool. {@code + * linker_flag}s coming from linking_mode_flags and compilation_mode_flags are not included. If + * you need all possible linker flags, use {@link #configureAllLegacyLinkOptions(CompilationMode, + * LinkingMode)}. + */ + public ImmutableList getLegacyLinkOptions() { + return toolchainInfo.getLegacyLinkOptions(); + } + + /** + * Return all flags coming from {@code compiler_flag} crosstool fields excluding flags coming from + * --copt options and copts attribute. + */ + public ImmutableList getLegacyCompileOptions() { + ImmutableList.Builder coptsBuilder = + ImmutableList.builder() + .addAll(getToolchainCompilerFlags()) + .addAll(getCFlagsByCompilationMode().get(cppConfiguration.getCompilationMode())); + + if (cppConfiguration.isOmitfp()) { + coptsBuilder.add("-fomit-frame-pointer"); + coptsBuilder.add("-fasynchronous-unwind-tables"); + coptsBuilder.add("-DNO_FRAME_POINTER"); + } + + return coptsBuilder.build(); + } + + public ImmutableList getLegacyCompileOptionsWithCopts() { + return ImmutableList.builder() + .addAll(getLegacyCompileOptions()) + .addAll(cppConfiguration.getCopts()) + .build(); + } + + /** Return all possible {@code linker_flag} flags from the crosstool. */ + ImmutableList configureAllLegacyLinkOptions( + CompilationMode compilationMode, LinkingMode linkingMode) { + return toolchainInfo.configureAllLegacyLinkOptions(compilationMode, linkingMode); + } + /** Returns the GNU System Name */ @Override public String getTargetGnuSystemName() { @@ -722,6 +897,13 @@ public final boolean isLLVMCompiler() { return toolchainInfo.isLLVMCompiler(); } + public ImmutableList getLegacyCxxOptions() { + return ImmutableList.builder() + .addAll(getToolchainCxxFlags()) + .addAll(getCxxFlagsByCompilationMode().get(cppConfiguration.getCompilationMode())) + .build(); + } + /** * WARNING: This method is only added to allow incremental migration of existing users. Please do * not use in new code. Will be removed soon as part of the new Skylark API to the C++ toolchain. diff --git a/dataset/GitHub_Java/bazelbuild.bazel/src/main/java/com/google/devtools/build/lib/rules/cpp/CcToolchainProviderHelper.java b/dataset/GitHub_Java/bazelbuild.bazel/src/main/java/com/google/devtools/build/lib/rules/cpp/CcToolchainProviderHelper.java index 6a346889428..444aa7fc8c1 100644 --- a/dataset/GitHub_Java/bazelbuild.bazel/src/main/java/com/google/devtools/build/lib/rules/cpp/CcToolchainProviderHelper.java +++ b/dataset/GitHub_Java/bazelbuild.bazel/src/main/java/com/google/devtools/build/lib/rules/cpp/CcToolchainProviderHelper.java @@ -22,7 +22,11 @@ import com.google.devtools.build.lib.analysis.FileProvider; 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; +import com.google.devtools.build.lib.analysis.actions.SpawnAction; +import com.google.devtools.build.lib.analysis.actions.SymlinkAction; 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.cmdline.Label; import com.google.devtools.build.lib.cmdline.LabelSyntaxException; @@ -31,10 +35,14 @@ 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.RuleClass.ConfiguredTargetFactory.RuleErrorException; -import com.google.devtools.build.lib.rules.cpp.CcSkyframeCrosstoolSupportFunction.CcSkyframeCrosstoolSupportException; +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.FdoContext.BranchFdoMode; import com.google.devtools.build.lib.syntax.EvalException; +import com.google.devtools.build.lib.util.FileType; +import com.google.devtools.build.lib.util.Pair; import com.google.devtools.build.lib.util.StringUtil; +import com.google.devtools.build.lib.vfs.FileSystemUtils; import com.google.devtools.build.lib.vfs.PathFragment; import com.google.devtools.build.lib.view.config.crosstool.CrosstoolConfig.CToolchain; import com.google.devtools.build.lib.view.config.crosstool.CrosstoolConfig.CrosstoolRelease; @@ -64,7 +72,291 @@ public class CcToolchainProviderHelper { private static final String PACKAGE_START = "%package("; private static final String PACKAGE_END = ")%"; - public static CcToolchainProvider getCcToolchainProvider( + /** + * Returns the profile name with the same file name as fdoProfile and an extension that matches + * {@link FileType}. + */ + private static String getLLVMProfileFileName(FdoInputFile fdoProfile, FileType type) { + if (type.matches(fdoProfile)) { + return fdoProfile.getBasename(); + } else { + return FileSystemUtils.removeExtension(fdoProfile.getBasename()) + + type.getExtensions().get(0); + } + } + + /** + * Resolve the given include directory. + * + *

If it starts with %sysroot%/, that part is replaced with the actual sysroot. + * + *

If it starts with %workspace%/, that part is replaced with the empty string (essentially + * making it relative to the build directory). + * + *

If it starts with %crosstool_top%/ or is any relative path, it is interpreted relative to + * the crosstool top. The use of assumed-crosstool-relative specifications is considered + * deprecated, and all such uses should eventually be replaced by "%crosstool_top%/". + * + *

If it is of the form %package(@repository//my/package)%/folder, then it is interpreted as + * the named folder in the appropriate package. All of the normal package syntax is supported. The + * /folder part is optional. + * + *

It is illegal if it starts with a % and does not match any of the above forms to avoid + * accidentally silently ignoring misspelled prefixes. + * + *

If it is absolute, it remains unchanged. + */ + static PathFragment resolveIncludeDir( + String s, PathFragment sysroot, PathFragment crosstoolTopPathFragment) + throws InvalidConfigurationException { + PathFragment pathPrefix; + String pathString; + int packageEndIndex = s.indexOf(PACKAGE_END); + if (packageEndIndex != -1 && s.startsWith(PACKAGE_START)) { + String packageString = s.substring(PACKAGE_START.length(), packageEndIndex); + try { + pathPrefix = PackageIdentifier.parse(packageString).getSourceRoot(); + } catch (LabelSyntaxException e) { + throw new InvalidConfigurationException("The package '" + packageString + "' is not valid"); + } + int pathStartIndex = packageEndIndex + PACKAGE_END.length(); + if (pathStartIndex + 1 < s.length()) { + if (s.charAt(pathStartIndex) != '/') { + throw new InvalidConfigurationException( + "The path in the package for '" + s + "' is not valid"); + } + pathString = s.substring(pathStartIndex + 1, s.length()); + } else { + pathString = ""; + } + } else if (s.startsWith(SYSROOT_START)) { + if (sysroot == null) { + throw new InvalidConfigurationException( + "A %sysroot% prefix is only allowed if the " + "default_sysroot option is set"); + } + pathPrefix = sysroot; + pathString = s.substring(SYSROOT_START.length(), s.length()); + } else if (s.startsWith(WORKSPACE_START)) { + pathPrefix = PathFragment.EMPTY_FRAGMENT; + pathString = s.substring(WORKSPACE_START.length(), s.length()); + } else { + pathPrefix = crosstoolTopPathFragment; + if (s.startsWith(CROSSTOOL_START)) { + pathString = s.substring(CROSSTOOL_START.length(), s.length()); + } else if (s.startsWith("%")) { + throw new InvalidConfigurationException( + "The include path '" + s + "' has an " + "unrecognized %prefix%"); + } else { + pathString = s; + } + } + + if (!PathFragment.isNormalized(pathString)) { + throw new InvalidConfigurationException("The include path '" + s + "' is not normalized."); + } + PathFragment path = PathFragment.create(pathString); + return pathPrefix.getRelative(path); + } + + private static String getSkylarkValueForTool(Tool tool, CppToolchainInfo cppToolchainInfo) { + PathFragment toolPath = cppToolchainInfo.getToolPathFragment(tool); + return toolPath != null ? toolPath.getPathString() : ""; + } + + private static ImmutableMap getToolchainForSkylark( + CppToolchainInfo cppToolchainInfo) { + return ImmutableMap.builder() + .put("objcopy_executable", getSkylarkValueForTool(Tool.OBJCOPY, cppToolchainInfo)) + .put("compiler_executable", getSkylarkValueForTool(Tool.GCC, cppToolchainInfo)) + .put("preprocessor_executable", getSkylarkValueForTool(Tool.CPP, cppToolchainInfo)) + .put("nm_executable", getSkylarkValueForTool(Tool.NM, cppToolchainInfo)) + .put("objdump_executable", getSkylarkValueForTool(Tool.OBJDUMP, cppToolchainInfo)) + .put("ar_executable", getSkylarkValueForTool(Tool.AR, cppToolchainInfo)) + .put("strip_executable", getSkylarkValueForTool(Tool.STRIP, cppToolchainInfo)) + .put("ld_executable", getSkylarkValueForTool(Tool.LD, cppToolchainInfo)) + .build(); + } + + private static PathFragment calculateSysroot( + CcToolchainAttributesProvider attributes, PathFragment defaultSysroot) { + TransitiveInfoCollection sysrootTarget = attributes.getLibcTop(); + if (sysrootTarget == null) { + return defaultSysroot; + } + + return sysrootTarget.getLabel().getPackageFragment(); + } + + private static Artifact getPrefetchHintsArtifact( + FdoInputFile prefetchHintsFile, RuleContext ruleContext) { + if (prefetchHintsFile == null) { + return null; + } + Artifact prefetchHintsArtifact = prefetchHintsFile.getArtifact(); + if (prefetchHintsArtifact != null) { + return prefetchHintsArtifact; + } + + prefetchHintsArtifact = + ruleContext.getUniqueDirectoryArtifact( + "fdo", + prefetchHintsFile.getAbsolutePath().getBaseName(), + ruleContext.getBinOrGenfilesDirectory()); + ruleContext.registerAction( + SymlinkAction.toAbsolutePath( + ruleContext.getActionOwner(), + PathFragment.create(prefetchHintsFile.getAbsolutePath().getPathString()), + prefetchHintsArtifact, + "Symlinking LLVM Cache Prefetch Hints Profile " + + prefetchHintsFile.getAbsolutePath().getPathString())); + return prefetchHintsArtifact; + } + + private static void symlinkTo( + RuleContext ruleContext, + Artifact symlink, + FdoInputFile fdoInputFile, + String progressMessage) { + if (fdoInputFile.getArtifact() != null) { + ruleContext.registerAction( + SymlinkAction.toArtifact( + ruleContext.getActionOwner(), fdoInputFile.getArtifact(), symlink, progressMessage)); + } else { + ruleContext.registerAction( + SymlinkAction.toAbsolutePath( + ruleContext.getActionOwner(), + fdoInputFile.getAbsolutePath(), + symlink, + progressMessage)); + } + } + + /* + * This function checks the format of the input profile data and converts it to + * the indexed format (.profdata) if necessary. + */ + private static Artifact convertLLVMRawProfileToIndexed( + CcToolchainAttributesProvider attributes, + FdoInputFile fdoProfile, + CppToolchainInfo toolchainInfo, + RuleContext ruleContext) { + + Artifact profileArtifact = + ruleContext.getUniqueDirectoryArtifact( + "fdo", + getLLVMProfileFileName(fdoProfile, CppFileTypes.LLVM_PROFILE), + ruleContext.getBinOrGenfilesDirectory()); + + // If the profile file is already in the desired format, symlink to it and return. + if (CppFileTypes.LLVM_PROFILE.matches(fdoProfile)) { + symlinkTo( + ruleContext, + profileArtifact, + fdoProfile, + "Symlinking LLVM Profile " + fdoProfile.getBasename()); + return profileArtifact; + } + + Artifact rawProfileArtifact; + + if (CppFileTypes.LLVM_PROFILE_ZIP.matches(fdoProfile)) { + // Get the zipper binary for unzipping the profile. + Artifact zipperBinaryArtifact = attributes.getZipper(); + if (zipperBinaryArtifact == null) { + ruleContext.ruleError("Cannot find zipper binary to unzip the profile"); + return null; + } + + // TODO(zhayu): find a way to avoid hard-coding cpu architecture here (b/65582760) + String rawProfileFileName = "fdocontrolz_profile.profraw"; + String cpu = toolchainInfo.getTargetCpu(); + if (!"k8".equals(cpu)) { + rawProfileFileName = "fdocontrolz_profile-" + cpu + ".profraw"; + } + rawProfileArtifact = + ruleContext.getUniqueDirectoryArtifact( + "fdo", rawProfileFileName, ruleContext.getBinOrGenfilesDirectory()); + + // Symlink to the zipped profile file to extract the contents. + Artifact zipProfileArtifact = + ruleContext.getUniqueDirectoryArtifact( + "fdo", fdoProfile.getBasename(), ruleContext.getBinOrGenfilesDirectory()); + symlinkTo( + ruleContext, + zipProfileArtifact, + fdoProfile, + "Symlinking LLVM ZIP Profile " + fdoProfile.getBasename()); + + // Unzip the profile. + ruleContext.registerAction( + new SpawnAction.Builder() + .addInput(zipProfileArtifact) + .addInput(zipperBinaryArtifact) + .addOutput(rawProfileArtifact) + .useDefaultShellEnvironment() + .setExecutable(zipperBinaryArtifact) + .setProgressMessage( + "LLVMUnzipProfileAction: Generating %s", rawProfileArtifact.prettyPrint()) + .setMnemonic("LLVMUnzipProfileAction") + .addCommandLine( + CustomCommandLine.builder() + .addExecPath("xf", zipProfileArtifact) + .add( + "-d", + rawProfileArtifact.getExecPath().getParentDirectory().getSafePathString()) + .build()) + .build(ruleContext)); + } else { + rawProfileArtifact = + ruleContext.getUniqueDirectoryArtifact( + "fdo", + getLLVMProfileFileName(fdoProfile, CppFileTypes.LLVM_PROFILE_RAW), + ruleContext.getBinOrGenfilesDirectory()); + symlinkTo( + ruleContext, + rawProfileArtifact, + fdoProfile, + "Symlinking LLVM Raw Profile " + fdoProfile.getBasename()); + } + + if (toolchainInfo.getToolPathFragment(Tool.LLVM_PROFDATA) == null) { + ruleContext.ruleError( + "llvm-profdata not available with this crosstool, needed for profile conversion"); + return null; + } + + // Convert LLVM raw profile to indexed format. + ruleContext.registerAction( + new SpawnAction.Builder() + .addInput(rawProfileArtifact) + .addTransitiveInputs(attributes.getAllFilesMiddleman()) + .addOutput(profileArtifact) + .useDefaultShellEnvironment() + .setExecutable(toolchainInfo.getToolPathFragment(Tool.LLVM_PROFDATA)) + .setProgressMessage("LLVMProfDataAction: Generating %s", profileArtifact.prettyPrint()) + .setMnemonic("LLVMProfDataAction") + .addCommandLine( + CustomCommandLine.builder() + .add("merge") + .add("-o") + .addExecPath(profileArtifact) + .addExecPath(rawProfileArtifact) + .build()) + .build(ruleContext)); + + return profileArtifact; + } + + static Pair getFdoInputs( + RuleContext ruleContext, FdoProfileProvider fdoProfileProvider) { + if (fdoProfileProvider == null) { + ruleContext.ruleError("--fdo_profile/--xbinary_fdo input needs to be an fdo_profile rule"); + return null; + } + return Pair.of(fdoProfileProvider.getInputFile(), fdoProfileProvider.getProtoProfileArtifact()); + } + + static CcToolchainProvider getCcToolchainProvider( RuleContext ruleContext, CcToolchainAttributesProvider attributes, CrosstoolRelease crosstoolFromCcToolchainSuiteProtoAttribute) @@ -73,8 +365,44 @@ public static CcToolchainProvider getCcToolchainProvider( CppConfiguration cppConfiguration = Preconditions.checkNotNull(configuration.getFragment(CppConfiguration.class)); + PathFragment fdoZip = null; + FdoInputFile fdoInputFile = null; + FdoInputFile prefetchHints = null; + Artifact protoProfileArtifact = null; + Pair fdoInputs = null; + if (configuration.getCompilationMode() == CompilationMode.OPT) { + if (cppConfiguration.getFdoPrefetchHintsLabel() != null) { + FdoPrefetchHintsProvider provider = attributes.getFdoPrefetch(); + prefetchHints = provider.getInputFile(); + } + if (cppConfiguration.getFdoPath() != null) { + fdoZip = cppConfiguration.getFdoPath(); + } else if (cppConfiguration.getFdoOptimizeLabel() != null) { + FdoProfileProvider fdoProfileProvider = attributes.getFdoOptimizeProvider(); + if (fdoProfileProvider != null) { + fdoInputs = getFdoInputs(ruleContext, fdoProfileProvider); + } else { + fdoInputFile = fdoInputFileFromArtifacts(ruleContext, attributes); + } + } else if (cppConfiguration.getFdoProfileLabel() != null) { + fdoInputs = getFdoInputs(ruleContext, attributes.getFdoProfileProvider()); + } else if (cppConfiguration.getXFdoProfileLabel() != null) { + fdoInputs = getFdoInputs(ruleContext, attributes.getXFdoProfileProvider()); + } + } + + if (ruleContext.hasErrors()) { + return null; + } + + if (fdoInputs != null) { + fdoInputFile = fdoInputs.getFirst(); + protoProfileArtifact = fdoInputs.getSecond(); + } + + CcSkyframeSupportValue ccSkyframeSupportValue = null; + SkyKey ccSupportKey = null; CToolchain toolchain = null; - CrosstoolRelease crosstoolFromCrosstoolFile = null; if (cppConfiguration.disableCrosstool() && attributes.getCcToolchainConfigInfo() == null) { ruleContext.ruleError( @@ -82,31 +410,43 @@ public static CcToolchainProvider getCcToolchainProvider( + "https://github.com/bazelbuild/bazel/issues/7320 for details."); } - if (attributes.getCcToolchainConfigInfo() == null) { + if (attributes.getCcToolchainConfigInfo() != null) { + if (fdoZip != null) { + ccSupportKey = CcSkyframeSupportValue.key(fdoZip, /* packageWithCrosstoolInIt= */ null); + } + } else { // Is there a toolchain proto available on the target directly? toolchain = parseToolchainFromAttributes(ruleContext, attributes); PackageIdentifier packageWithCrosstoolInIt = null; if (toolchain == null && crosstoolFromCcToolchainSuiteProtoAttribute == null) { packageWithCrosstoolInIt = ruleContext.getLabel().getPackageIdentifier(); } - if (packageWithCrosstoolInIt != null) { - SkyKey crosstoolKey = CcSkyframeCrosstoolSupportValue.key(packageWithCrosstoolInIt); - SkyFunction.Environment skyframeEnv = ruleContext.getAnalysisEnvironment().getSkyframeEnv(); - try { - CcSkyframeCrosstoolSupportValue ccSkyframeCrosstoolSupportValue = - (CcSkyframeCrosstoolSupportValue) - skyframeEnv.getValueOrThrow( - crosstoolKey, CcSkyframeCrosstoolSupportException.class); - if (skyframeEnv.valuesMissing()) { - return null; - } - crosstoolFromCrosstoolFile = ccSkyframeCrosstoolSupportValue.getCrosstoolRelease(); - } catch (CcSkyframeCrosstoolSupportException e) { - throw ruleContext.throwWithRuleError(e.getMessage()); - } + if (packageWithCrosstoolInIt != null || fdoZip != null) { + ccSupportKey = CcSkyframeSupportValue.key(fdoZip, packageWithCrosstoolInIt); + } + } + if (ccSupportKey != null) { + SkyFunction.Environment skyframeEnv = ruleContext.getAnalysisEnvironment().getSkyframeEnv(); + try { + ccSkyframeSupportValue = + (CcSkyframeSupportValue) + skyframeEnv.getValueOrThrow(ccSupportKey, CcSkyframeSupportException.class); + } catch (CcSkyframeSupportException e) { + throw ruleContext.throwWithRuleError(e.getMessage()); + } + if (skyframeEnv.valuesMissing()) { + return null; } } + if (fdoZip != null) { + // fdoZip should be set if the profile is a path, fdoInputFile if it is an artifact, but never + // both + Preconditions.checkState(fdoInputFile == null); + fdoInputFile = + FdoInputFile.fromAbsolutePath(ccSkyframeSupportValue.getFdoZipPath().asFragment()); + } + CppToolchainInfo toolchainInfo = getCppToolchainInfo( ruleContext, @@ -115,15 +455,57 @@ public static CcToolchainProvider getCcToolchainProvider( cppConfiguration.getTransformedCpuFromOptions(), cppConfiguration.getCompilerFromOptions(), attributes, - crosstoolFromCrosstoolFile, + ccSkyframeSupportValue, toolchain, crosstoolFromCcToolchainSuiteProtoAttribute); - FdoContext fdoContext = - FdoHelper.getFdoContext( - ruleContext, attributes, configuration, cppConfiguration, toolchainInfo); - if (fdoContext == null) { - return null; + FdoContext.BranchFdoProfile branchFdoProfile = null; + if (fdoInputFile != null) { + BranchFdoMode branchFdoMode; + if (CppFileTypes.GCC_AUTO_PROFILE.matches(fdoInputFile)) { + branchFdoMode = BranchFdoMode.AUTO_FDO; + } else if (CppFileTypes.XBINARY_PROFILE.matches(fdoInputFile)) { + branchFdoMode = BranchFdoMode.XBINARY_FDO; + } else if (CppFileTypes.LLVM_PROFILE.matches(fdoInputFile)) { + branchFdoMode = BranchFdoMode.LLVM_FDO; + } else if (CppFileTypes.LLVM_PROFILE_RAW.matches(fdoInputFile)) { + branchFdoMode = BranchFdoMode.LLVM_FDO; + } else if (CppFileTypes.LLVM_PROFILE_ZIP.matches(fdoInputFile)) { + branchFdoMode = BranchFdoMode.LLVM_FDO; + } else { + ruleContext.ruleError("invalid extension for FDO profile file."); + return null; + } + if (branchFdoMode != BranchFdoMode.XBINARY_FDO + && cppConfiguration.getXFdoProfileLabel() != null) { + ruleContext.throwWithRuleError( + "--xbinary_fdo cannot accept profile input other than *.xfdo"); + } + + if (configuration.isCodeCoverageEnabled()) { + ruleContext.throwWithRuleError("coverage mode is not compatible with FDO optimization"); + } + // This tries to convert LLVM profiles to the indexed format if necessary. + Artifact profileArtifact = null; + if (branchFdoMode == BranchFdoMode.LLVM_FDO) { + profileArtifact = + convertLLVMRawProfileToIndexed(attributes, fdoInputFile, toolchainInfo, ruleContext); + if (ruleContext.hasErrors()) { + return null; + } + } else if (branchFdoMode == BranchFdoMode.AUTO_FDO + || branchFdoMode == BranchFdoMode.XBINARY_FDO) { + profileArtifact = + ruleContext.getUniqueDirectoryArtifact( + "fdo", fdoInputFile.getBasename(), ruleContext.getBinOrGenfilesDirectory()); + symlinkTo( + ruleContext, + profileArtifact, + fdoInputFile, + "Symlinking FDO profile " + fdoInputFile.getBasename()); + } + branchFdoProfile = + new FdoContext.BranchFdoProfile(branchFdoMode, profileArtifact, protoProfileArtifact); } String purposePrefix = attributes.getPurposePrefix(); @@ -226,6 +608,8 @@ public static CcToolchainProvider getCcToolchainProvider( ImmutableList builtInIncludeDirectories = builtInIncludeDirectoriesBuilder.build(); + Artifact prefetchHintsArtifact = getPrefetchHintsArtifact(prefetchHints, ruleContext); + return new CcToolchainProvider( getToolchainForSkylark(toolchainInfo), cppConfiguration, @@ -261,111 +645,36 @@ public static CcToolchainProvider getCcToolchainProvider( attributes.getLinkDynamicLibraryTool(), builtInIncludeDirectories, sysroot, - fdoContext, + new FdoContext(branchFdoProfile, prefetchHintsArtifact), configuration.isHostConfiguration(), attributes.getLicensesProvider()); } - /** - * Resolve the given include directory. - * - *

If it starts with %sysroot%/, that part is replaced with the actual sysroot. - * - *

If it starts with %workspace%/, that part is replaced with the empty string (essentially - * making it relative to the build directory). - * - *

If it starts with %crosstool_top%/ or is any relative path, it is interpreted relative to - * the crosstool top. The use of assumed-crosstool-relative specifications is considered - * deprecated, and all such uses should eventually be replaced by "%crosstool_top%/". - * - *

If it is of the form %package(@repository//my/package)%/folder, then it is interpreted as - * the named folder in the appropriate package. All of the normal package syntax is supported. The - * /folder part is optional. - * - *

It is illegal if it starts with a % and does not match any of the above forms to avoid - * accidentally silently ignoring misspelled prefixes. - * - *

If it is absolute, it remains unchanged. - */ - static PathFragment resolveIncludeDir( - String s, PathFragment sysroot, PathFragment crosstoolTopPathFragment) - throws InvalidConfigurationException { - PathFragment pathPrefix; - String pathString; - int packageEndIndex = s.indexOf(PACKAGE_END); - if (packageEndIndex != -1 && s.startsWith(PACKAGE_START)) { - String packageString = s.substring(PACKAGE_START.length(), packageEndIndex); - try { - pathPrefix = PackageIdentifier.parse(packageString).getSourceRoot(); - } catch (LabelSyntaxException e) { - throw new InvalidConfigurationException("The package '" + packageString + "' is not valid"); - } - int pathStartIndex = packageEndIndex + PACKAGE_END.length(); - if (pathStartIndex + 1 < s.length()) { - if (s.charAt(pathStartIndex) != '/') { - throw new InvalidConfigurationException( - "The path in the package for '" + s + "' is not valid"); - } - pathString = s.substring(pathStartIndex + 1, s.length()); - } else { - pathString = ""; - } - } else if (s.startsWith(SYSROOT_START)) { - if (sysroot == null) { - throw new InvalidConfigurationException( - "A %sysroot% prefix is only allowed if the " + "default_sysroot option is set"); - } - pathPrefix = sysroot; - pathString = s.substring(SYSROOT_START.length(), s.length()); - } else if (s.startsWith(WORKSPACE_START)) { - pathPrefix = PathFragment.EMPTY_FRAGMENT; - pathString = s.substring(WORKSPACE_START.length(), s.length()); - } else { - pathPrefix = crosstoolTopPathFragment; - if (s.startsWith(CROSSTOOL_START)) { - pathString = s.substring(CROSSTOOL_START.length(), s.length()); - } else if (s.startsWith("%")) { - throw new InvalidConfigurationException( - "The include path '" + s + "' has an " + "unrecognized %prefix%"); - } else { - pathString = s; - } + private static FdoInputFile fdoInputFileFromArtifacts( + RuleContext ruleContext, CcToolchainAttributesProvider attributes) { + ImmutableList fdoArtifacts = attributes.getFdoOptimizeArtifacts(); + if (fdoArtifacts.size() != 1) { + ruleContext.ruleError("--fdo_optimize does not point to a single target"); + return null; } - if (!PathFragment.isNormalized(pathString)) { - throw new InvalidConfigurationException("The include path '" + s + "' is not normalized."); + Artifact fdoArtifact = fdoArtifacts.get(0); + if (!fdoArtifact.isSourceArtifact()) { + ruleContext.ruleError("--fdo_optimize points to a target that is not an input file"); + return null; } - PathFragment path = PathFragment.create(pathString); - return pathPrefix.getRelative(path); - } - private static String getSkylarkValueForTool(Tool tool, CppToolchainInfo cppToolchainInfo) { - PathFragment toolPath = cppToolchainInfo.getToolPathFragment(tool); - return toolPath != null ? toolPath.getPathString() : ""; - } - - private static ImmutableMap getToolchainForSkylark( - CppToolchainInfo cppToolchainInfo) { - return ImmutableMap.builder() - .put("objcopy_executable", getSkylarkValueForTool(Tool.OBJCOPY, cppToolchainInfo)) - .put("compiler_executable", getSkylarkValueForTool(Tool.GCC, cppToolchainInfo)) - .put("preprocessor_executable", getSkylarkValueForTool(Tool.CPP, cppToolchainInfo)) - .put("nm_executable", getSkylarkValueForTool(Tool.NM, cppToolchainInfo)) - .put("objdump_executable", getSkylarkValueForTool(Tool.OBJDUMP, cppToolchainInfo)) - .put("ar_executable", getSkylarkValueForTool(Tool.AR, cppToolchainInfo)) - .put("strip_executable", getSkylarkValueForTool(Tool.STRIP, cppToolchainInfo)) - .put("ld_executable", getSkylarkValueForTool(Tool.LD, cppToolchainInfo)) - .build(); - } - - private static PathFragment calculateSysroot( - CcToolchainAttributesProvider attributes, PathFragment defaultSysroot) { - TransitiveInfoCollection sysrootTarget = attributes.getLibcTop(); - if (sysrootTarget == null) { - return defaultSysroot; + Label fdoLabel = attributes.getFdoOptimize().getLabel(); + if (!fdoLabel + .getPackageIdentifier() + .getPathUnderExecRoot() + .getRelative(fdoLabel.getName()) + .equals(fdoArtifact.getExecPath())) { + ruleContext.ruleError("--fdo_optimize points to a target that is not an input file"); + return null; } - return sysrootTarget.getLabel().getPackageFragment(); + return FdoInputFile.fromArtifact(fdoArtifact); } /** Finds an appropriate {@link CppToolchainInfo} for this target. */ @@ -376,7 +685,7 @@ private static CppToolchainInfo getCppToolchainInfo( String cpuFromOptions, String compilerFromOptions, CcToolchainAttributesProvider attributes, - CrosstoolRelease crosstoolFromCrosstoolFile, + CcSkyframeSupportValue ccSkyframeSupportValue, CToolchain toolchainFromCcToolchainAttribute, CrosstoolRelease crosstoolFromCcToolchainSuiteProtoAttribute) throws RuleErrorException, InterruptedException { @@ -405,7 +714,7 @@ private static CppToolchainInfo getCppToolchainInfo( cpuFromOptions, compilerFromOptions, crosstoolFromCcToolchainSuiteProtoAttribute, - crosstoolFromCrosstoolFile); + ccSkyframeSupportValue); } // If we found a toolchain, use it. @@ -454,7 +763,7 @@ private static CToolchain getToolchainFromAttributes( String cpuFromOptions, String compilerFromOptions, CrosstoolRelease crosstoolFromCcToolchainSuiteProtoAttribute, - CrosstoolRelease crosstoolFromCrosstoolFile) + CcSkyframeSupportValue ccSkyframeSupportValue) throws RuleErrorException { try { CrosstoolRelease crosstoolRelease; @@ -463,7 +772,7 @@ private static CToolchain getToolchainFromAttributes( crosstoolRelease = crosstoolFromCcToolchainSuiteProtoAttribute; } else { // We use the proto from the CROSSTOOL file - crosstoolRelease = crosstoolFromCrosstoolFile; + crosstoolRelease = ccSkyframeSupportValue.getCrosstoolRelease(); } return CToolchainSelectionUtils.selectCToolchain( diff --git a/dataset/GitHub_Java/bazelbuild.bazel/src/main/java/com/google/devtools/build/lib/rules/cpp/CcToolchainSuite.java b/dataset/GitHub_Java/bazelbuild.bazel/src/main/java/com/google/devtools/build/lib/rules/cpp/CcToolchainSuite.java index 5ddec98942a..cd5c5804878 100644 --- a/dataset/GitHub_Java/bazelbuild.bazel/src/main/java/com/google/devtools/build/lib/rules/cpp/CcToolchainSuite.java +++ b/dataset/GitHub_Java/bazelbuild.bazel/src/main/java/com/google/devtools/build/lib/rules/cpp/CcToolchainSuite.java @@ -25,9 +25,12 @@ import com.google.devtools.build.lib.analysis.RunfilesProvider; import com.google.devtools.build.lib.analysis.TemplateVariableInfo; import com.google.devtools.build.lib.analysis.TransitiveInfoCollection; +import com.google.devtools.build.lib.analysis.config.InvalidConfigurationException; import com.google.devtools.build.lib.analysis.platform.ToolchainInfo; import com.google.devtools.build.lib.cmdline.Label; import com.google.devtools.build.lib.packages.BuildType; +import com.google.devtools.build.lib.syntax.Type; +import com.google.devtools.build.lib.view.config.crosstool.CrosstoolConfig.CrosstoolRelease; import java.util.Map; /** @@ -42,14 +45,23 @@ public class CcToolchainSuite implements RuleConfiguredTargetFactory { @Override public ConfiguredTarget create(RuleContext ruleContext) throws InterruptedException, RuleErrorException, ActionConflictException { - CcCommon.checkRuleLoadedThroughMacro(ruleContext); CppConfiguration cppConfiguration = ruleContext.getFragment(CppConfiguration.class); - String transformedCpu = ruleContext.getConfiguration().getCpu(); + String transformedCpu = cppConfiguration.getTransformedCpuFromOptions(); String compiler = cppConfiguration.getCompilerFromOptions(); String key = transformedCpu + (compiler == null ? "" : ("|" + compiler)); Map toolchains = ruleContext.attributes().get("toolchains", BuildType.LABEL_DICT_UNARY); + CrosstoolRelease crosstoolFromProtoAttribute = null; + if (ruleContext.attributes().isAttributeValueExplicitlySpecified("proto")) { + try { + crosstoolFromProtoAttribute = + CcSkyframeSupportFunction.toReleaseConfiguration( + ruleContext.attributes().get("proto", Type.STRING)); + } catch (InvalidConfigurationException e) { + ruleContext.throwWithRuleError(e.getMessage()); + } + } Label selectedCcToolchain = toolchains.get(key); CcToolchainProvider ccToolchainProvider; @@ -75,7 +87,8 @@ public ConfiguredTarget create(RuleContext ruleContext) compiler, selectedCcToolchain); ccToolchainProvider = - CcToolchainProviderHelper.getCcToolchainProvider(ruleContext, selectedAttributes); + CcToolchainProviderHelper.getCcToolchainProvider( + ruleContext, selectedAttributes, crosstoolFromProtoAttribute); if (ccToolchainProvider == null) { // Skyframe restart @@ -114,7 +127,7 @@ private T selectCcToolchain( throws RuleErrorException { T selectedAttributes = null; for (TransitiveInfoCollection dep : ruleContext.getPrerequisiteMap("toolchains").values()) { - T attributes = clazz.cast(dep.get(ToolchainInfo.PROVIDER)); + T attributes = (T) dep.get(ToolchainInfo.PROVIDER); if (attributes != null && attributes.getCcToolchainLabel().equals(selectedCcToolchain)) { selectedAttributes = attributes; break;