/** Create the C++ compile and link actions, and the corresponding C++-related providers. */ public Info build() { // Fail early if there is no lipo context collector on the rule - otherwise we end up failing // in lipo optimization. Preconditions.checkState( // 'cc_inc_library' rules do not compile, and thus are not affected by LIPO. ruleContext.getRule().getRuleClass().equals("cc_inc_library") || ruleContext.getRule().isAttrDefined(":lipo_context_collector", BuildType.LABEL)); if (checkDepsGenerateCpp) { for (LanguageDependentFragment dep : AnalysisUtils.getProviders(deps, LanguageDependentFragment.class)) { LanguageDependentFragment.Checker.depSupportsLanguage( ruleContext, dep, CppRuleClasses.LANGUAGE); } } CppModel model = initializeCppModel(); CppCompilationContext cppCompilationContext = initializeCppCompilationContext(model); model.setContext(cppCompilationContext); boolean compileHeaderModules = featureConfiguration.isEnabled(CppRuleClasses.HEADER_MODULES); Preconditions.checkState( !compileHeaderModules || cppCompilationContext.getCppModuleMap() != null, "All cc rules must support module maps."); // Create compile actions (both PIC and non-PIC). CcCompilationOutputs ccOutputs = model.createCcCompileActions(); if (!objectFiles.isEmpty() || !picObjectFiles.isEmpty()) { // Merge the pre-compiled object files into the compiler outputs. ccOutputs = new CcCompilationOutputs.Builder() .merge(ccOutputs) .addLTOBitcodeFile(ccOutputs.getLtoBitcodeFiles()) .addObjectFiles(objectFiles) .addPicObjectFiles(picObjectFiles) .build(); } // Create link actions (only if there are object files or if explicitly requested). CcLinkingOutputs ccLinkingOutputs = CcLinkingOutputs.EMPTY; if (emitLinkActionsIfEmpty || !ccOutputs.isEmpty()) { // On some systems, the linker gives an error message if there are no input files. Even with // the check above, this can still happen if there is a .nopic.o or .o files in srcs, but no // other files. To fix that, we'd have to check for each link action individually. // // An additional pre-existing issue is that the header check tokens are dropped if we don't // generate any link actions, effectively disabling header checking in some cases. if (linkType.isStaticLibraryLink()) { // TODO(bazel-team): This can't create the link action for a cc_binary yet. ccLinkingOutputs = model.createCcLinkActions(ccOutputs); } } CcLinkingOutputs originalLinkingOutputs = ccLinkingOutputs; if (!(staticLibraries.isEmpty() && picStaticLibraries.isEmpty() && dynamicLibraries.isEmpty())) { // Merge the pre-compiled libraries (static & dynamic) into the linker outputs. ccLinkingOutputs = new CcLinkingOutputs.Builder() .merge(ccLinkingOutputs) .addStaticLibraries(staticLibraries) .addPicStaticLibraries(picStaticLibraries) .addDynamicLibraries(dynamicLibraries) .addExecutionDynamicLibraries(dynamicLibraries) .build(); } DwoArtifactsCollector dwoArtifacts = DwoArtifactsCollector.transitiveCollector(ccOutputs, deps); Runfiles cppStaticRunfiles = collectCppRunfiles(ccLinkingOutputs, true); Runfiles cppSharedRunfiles = collectCppRunfiles(ccLinkingOutputs, false); // By very careful when adding new providers here - it can potentially affect a lot of rules. // We should consider merging most of these providers into a single provider. Map<Class<? extends TransitiveInfoProvider>, TransitiveInfoProvider> providers = new LinkedHashMap<>(); providers.put( CppRunfilesProvider.class, new CppRunfilesProvider(cppStaticRunfiles, cppSharedRunfiles)); providers.put(CppCompilationContext.class, cppCompilationContext); providers.put( CppDebugFileProvider.class, new CppDebugFileProvider( dwoArtifacts.getDwoArtifacts(), dwoArtifacts.getPicDwoArtifacts())); providers.put(TransitiveLipoInfoProvider.class, collectTransitiveLipoInfo(ccOutputs)); Map<String, NestedSet<Artifact>> outputGroups = new TreeMap<>(); outputGroups.put(OutputGroupProvider.TEMP_FILES, getTemps(ccOutputs)); if (emitCompileProviders) { boolean isLipoCollector = ruleContext.getFragment(CppConfiguration.class).isLipoContextCollector(); boolean processHeadersInDependencies = ruleContext.getFragment(CppConfiguration.class).processHeadersInDependencies(); boolean usePic = CppHelper.usePic(ruleContext, false); outputGroups.put( OutputGroupProvider.FILES_TO_COMPILE, ccOutputs.getFilesToCompile(isLipoCollector, processHeadersInDependencies, usePic)); outputGroups.put( OutputGroupProvider.COMPILATION_PREREQUISITES, CcCommon.collectCompilationPrerequisites(ruleContext, cppCompilationContext)); } // TODO(bazel-team): Maybe we can infer these from other data at the places where they are // used. if (emitCcNativeLibrariesProvider) { providers.put( CcNativeLibraryProvider.class, new CcNativeLibraryProvider(collectNativeCcLibraries(ccLinkingOutputs))); } providers.put( CcExecutionDynamicLibrariesProvider.class, collectExecutionDynamicLibraryArtifacts(ccLinkingOutputs.getExecutionDynamicLibraries())); boolean forcePic = ruleContext.getFragment(CppConfiguration.class).forcePic(); if (emitCcSpecificLinkParamsProvider) { providers.put( CcSpecificLinkParamsProvider.class, new CcSpecificLinkParamsProvider( createCcLinkParamsStore(ccLinkingOutputs, cppCompilationContext, forcePic))); } else { providers.put( CcLinkParamsProvider.class, new CcLinkParamsProvider( createCcLinkParamsStore(ccLinkingOutputs, cppCompilationContext, forcePic))); } return new Info( providers, outputGroups, ccOutputs, ccLinkingOutputs, originalLinkingOutputs, cppCompilationContext); }