diff options
Diffstat (limited to 'src/main/java/com/google/devtools/build/lib')
6 files changed, 312 insertions, 118 deletions
diff --git a/src/main/java/com/google/devtools/build/lib/rules/objc/CompilationSupport.java b/src/main/java/com/google/devtools/build/lib/rules/objc/CompilationSupport.java index 9911481ca3..adad227027 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/objc/CompilationSupport.java +++ b/src/main/java/com/google/devtools/build/lib/rules/objc/CompilationSupport.java @@ -227,7 +227,18 @@ public abstract class CompilationSupport { static final ImmutableList<String> DEFAULT_COMPILER_FLAGS = ImmutableList.of("-DOS_IOS"); static final ImmutableList<String> DEFAULT_LINKER_FLAGS = ImmutableList.of("-ObjC"); - + + /** + * Set of {@link com.google.devtools.build.lib.util.FileType} of source artifacts that are + * compatible with header thinning. + */ + protected static final FileTypeSet SOURCES_FOR_HEADER_THINNING = + FileTypeSet.of( + CppFileTypes.OBJC_SOURCE, + CppFileTypes.OBJCPP_SOURCE, + CppFileTypes.CPP_SOURCE, + CppFileTypes.C_SOURCE); + /** * Returns information about the given rule's compilation artifacts. */ @@ -1119,6 +1130,11 @@ public abstract class CompilationSupport { this.headersListFile = Preconditions.checkNotNull(headersListFile); this.arguments = Preconditions.checkNotNull(arguments); } + + public ObjcHeaderThinningInfo( + Artifact sourceFile, Artifact headersListFile, Iterable<String> arguments) { + this(sourceFile, headersListFile, ImmutableList.copyOf(arguments)); + } } /** @@ -1142,6 +1158,10 @@ public abstract class CompilationSupport { .getProvider(FilesToRunProvider.class); } + /** + * Creates and registers ObjcHeaderScanning {@link SpawnAction}. Groups all the actions by their + * compilation command line arguments and creates a ObjcHeaderScanning action for each unique one. + */ protected void registerHeaderScanningActions( ImmutableList<ObjcHeaderThinningInfo> headerThinningInfo, ObjcProvider objcProvider, diff --git a/src/main/java/com/google/devtools/build/lib/rules/objc/CrosstoolCompilationSupport.java b/src/main/java/com/google/devtools/build/lib/rules/objc/CrosstoolCompilationSupport.java index 52cf6b828c..81cb9ed82b 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/objc/CrosstoolCompilationSupport.java +++ b/src/main/java/com/google/devtools/build/lib/rules/objc/CrosstoolCompilationSupport.java @@ -16,6 +16,7 @@ package com.google.devtools.build.lib.rules.objc; import static com.google.devtools.build.lib.rules.objc.ObjcProvider.DEFINE; import static com.google.devtools.build.lib.rules.objc.ObjcProvider.DYNAMIC_FRAMEWORK_FILE; +import static com.google.devtools.build.lib.rules.objc.ObjcProvider.HEADER; import static com.google.devtools.build.lib.rules.objc.ObjcProvider.IMPORTED_LIBRARY; import static com.google.devtools.build.lib.rules.objc.ObjcProvider.INCLUDE; import static com.google.devtools.build.lib.rules.objc.ObjcProvider.INCLUDE_SYSTEM; @@ -28,7 +29,9 @@ import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableSet; import com.google.common.collect.ImmutableSortedSet; import com.google.common.collect.Iterables; +import com.google.devtools.build.lib.actions.ActionAnalysisMetadata; import com.google.devtools.build.lib.actions.Artifact; +import com.google.devtools.build.lib.analysis.AnalysisEnvironment; import com.google.devtools.build.lib.analysis.RuleConfiguredTarget.Mode; import com.google.devtools.build.lib.analysis.RuleContext; import com.google.devtools.build.lib.analysis.config.BuildConfiguration; @@ -36,6 +39,7 @@ import com.google.devtools.build.lib.packages.BuildType; import com.google.devtools.build.lib.packages.RuleClass.ConfiguredTargetFactory.RuleErrorException; import com.google.devtools.build.lib.rules.apple.AppleConfiguration; import com.google.devtools.build.lib.rules.cpp.CcLibraryHelper; +import com.google.devtools.build.lib.rules.cpp.CcLibraryHelper.Info; import com.google.devtools.build.lib.rules.cpp.CcToolchainFeatures.FeatureConfiguration; import com.google.devtools.build.lib.rules.cpp.CcToolchainFeatures.Variables.VariablesExtension; import com.google.devtools.build.lib.rules.cpp.CcToolchainProvider; @@ -147,8 +151,8 @@ public class CrosstoolCompilationSupport extends CompilationSupport { createCcLibraryHelper( objcProvider, compilationArtifacts, extension.build(), ccToolchain, fdoSupport); } - - helper.build(); + + registerHeaderScanningActions(helper.build(), objcProvider, compilationArtifacts); return this; } @@ -264,9 +268,25 @@ public class CrosstoolCompilationSupport extends CompilationSupport { return this; } - private CcLibraryHelper createCcLibraryHelper(ObjcProvider objcProvider, - CompilationArtifacts compilationArtifacts, VariablesExtension extension, - CcToolchainProvider ccToolchain, FdoSupportProvider fdoSupport) { + + private IncludeProcessing createIncludeProcessing( + Iterable<Artifact> potentialInputs, @Nullable Artifact pchHdr) { + if (isHeaderThinningEnabled()) { + if (pchHdr != null) { + potentialInputs = Iterables.concat(potentialInputs, ImmutableList.of(pchHdr)); + } + return new HeaderThinning(potentialInputs); + } else { + return new NoProcessing(); + } + } + + private CcLibraryHelper createCcLibraryHelper( + ObjcProvider objcProvider, + CompilationArtifacts compilationArtifacts, + VariablesExtension extension, + CcToolchainProvider ccToolchain, + FdoSupportProvider fdoSupport) { PrecompiledFiles precompiledFiles = new PrecompiledFiles(ruleContext); Collection<Artifact> arcSources = ImmutableSortedSet.copyOf(compilationArtifacts.getSrcs()); Collection<Artifact> nonArcSources = @@ -274,14 +294,22 @@ public class CrosstoolCompilationSupport extends CompilationSupport { Collection<Artifact> privateHdrs = ImmutableSortedSet.copyOf(compilationArtifacts.getPrivateHdrs()); Collection<Artifact> publicHdrs = ImmutableSortedSet.copyOf(attributes.hdrs()); - IncludeProcessing includeProcessing = new NoProcessing(); + Artifact pchHdr = null; + if (ruleContext.attributes().has("pch", BuildType.LABEL)) { + pchHdr = ruleContext.getPrerequisiteArtifact("pch", Mode.TARGET); + } + ObjcCppSemantics semantics = + new ObjcCppSemantics( + objcProvider, + createIncludeProcessing( + Iterables.concat(privateHdrs, publicHdrs, objcProvider.get(HEADER)), pchHdr), + ruleContext.getFragment(ObjcConfiguration.class), + isHeaderThinningEnabled(), + intermediateArtifacts); CcLibraryHelper result = new CcLibraryHelper( ruleContext, - new ObjcCppSemantics( - objcProvider, - includeProcessing, - ruleContext.getFragment(ObjcConfiguration.class)), + semantics, getFeatureConfiguration(ruleContext, buildConfiguration), CcLibraryHelper.SourceCategory.CC_AND_OBJC, ccToolchain, @@ -309,10 +337,6 @@ public class CrosstoolCompilationSupport extends CompilationSupport { .setNeverLink(true) .addVariableExtension(extension); - Artifact pchHdr = null; - if (ruleContext.attributes().has("pch", BuildType.LABEL)) { - pchHdr = ruleContext.getPrerequisiteArtifact("pch", Mode.TARGET); - } if (pchHdr != null) { result.addNonModuleMapHeader(pchHdr); } @@ -369,4 +393,33 @@ public class CrosstoolCompilationSupport extends CompilationSupport { } return result.build(); } + + private void registerHeaderScanningActions( + Info info, ObjcProvider objcProvider, CompilationArtifacts compilationArtifacts) { + // PIC is not used for Obj-C builds, if that changes this method will need to change + if (!isHeaderThinningEnabled() + || info.getCcCompilationOutputs().getObjectFiles(false).isEmpty()) { + return; + } + + ImmutableList.Builder<ObjcHeaderThinningInfo> headerThinningInfos = ImmutableList.builder(); + AnalysisEnvironment analysisEnvironment = ruleContext.getAnalysisEnvironment(); + for (Artifact objectFile : info.getCcCompilationOutputs().getObjectFiles(false)) { + ActionAnalysisMetadata generatingAction = + analysisEnvironment.getLocalGeneratingAction(objectFile); + if (generatingAction instanceof CppCompileAction) { + CppCompileAction action = (CppCompileAction) generatingAction; + Artifact sourceFile = action.getSourceFile(); + if (!sourceFile.isTreeArtifact() + && SOURCES_FOR_HEADER_THINNING.matches(sourceFile.getFilename())) { + headerThinningInfos.add( + new ObjcHeaderThinningInfo( + sourceFile, + intermediateArtifacts.headersListFile(sourceFile), + action.getCompilerOptions())); + } + } + } + registerHeaderScanningActions(headerThinningInfos.build(), objcProvider, compilationArtifacts); + } } diff --git a/src/main/java/com/google/devtools/build/lib/rules/objc/HeaderThinning.java b/src/main/java/com/google/devtools/build/lib/rules/objc/HeaderThinning.java new file mode 100644 index 0000000000..8f678af07c --- /dev/null +++ b/src/main/java/com/google/devtools/build/lib/rules/objc/HeaderThinning.java @@ -0,0 +1,173 @@ +// Copyright 2014 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.objc; + +import com.google.common.collect.ImmutableList; +import com.google.devtools.build.lib.actions.ActionExecutionContext; +import com.google.devtools.build.lib.actions.Artifact; +import com.google.devtools.build.lib.actions.EnvironmentalExecException; +import com.google.devtools.build.lib.actions.ExecException; +import com.google.devtools.build.lib.actions.UserExecException; +import com.google.devtools.build.lib.collect.nestedset.NestedSet; +import com.google.devtools.build.lib.rules.cpp.CppCompileAction; +import com.google.devtools.build.lib.rules.cpp.IncludeProcessing; +import com.google.devtools.build.lib.rules.cpp.IncludeScanner.IncludeScannerSupplier; +import com.google.devtools.build.lib.vfs.FileSystemUtils; +import com.google.devtools.build.lib.vfs.PathFragment; +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import javax.annotation.Nullable; + +/** + * Returns all inclusions that were discovered by the header scanner tool to implement the header + * thinning feature. + * + * <p>Reads the .headers_list output file if one was generated for the actions source file and + * returns the Artifact objects associated with the headers that were found. + */ +public class HeaderThinning implements IncludeProcessing { + + private final Iterable<Artifact> potentialInputs; + + public HeaderThinning(Iterable<Artifact> potentialInputs) { + // Just store this, don't create map of potential inputs at construction so that it is done + // later at execution time rather than analysis time when this is instantiated. + this.potentialInputs = potentialInputs; + } + + private Map<PathFragment, Artifact> getAllowedInputsMap() { + Map<PathFragment, Artifact> allowedInputsMap = new HashMap<>(); + for (Artifact input : potentialInputs) { + allowedInputsMap.put(input.getExecPath(), input); + } + return allowedInputsMap; + } + + @Nullable + private static Artifact findHeadersListFile(NestedSet<Artifact> artifacts) { + for (Artifact artifact : artifacts) { + if (artifact.getExtension().equals("headers_list")) { + return artifact; + } + } + return null; + } + + @Override + public Iterable<Artifact> determineAdditionalInputs( + @Nullable IncludeScannerSupplier includeScannerSupplier, + CppCompileAction action, + ActionExecutionContext actionExecutionContext) + throws ExecException { + Artifact headersListFile = findHeadersListFile(action.getMandatoryInputs()); + if (headersListFile == null) { + return null; + } + return findRequiredHeaderInputs(action.getSourceFile(), headersListFile, getAllowedInputsMap()); + } + + /** + * Reads the header scanning output file and discovers all of those headers as input artifacts. + * + * @param sourceFile the source that requires these headers + * @param headersListFile .headers_list file output from header_scanner tool to be read + * @param inputArtifactsMap map of PathFragment to Artifact of possible headers + * @return collection of header artifacts that are required for {@code action} to compile + * @throws ExecException on environmental (IO) or user errors + */ + public static Iterable<Artifact> findRequiredHeaderInputs( + Artifact sourceFile, Artifact headersListFile, Map<PathFragment, Artifact> inputArtifactsMap) + throws ExecException { + try { + ImmutableList.Builder<Artifact> includeBuilder = ImmutableList.builder(); + List<PathFragment> missing = new ArrayList<>(); + for (String line : + FileSystemUtils.readLines(headersListFile.getPath(), StandardCharsets.UTF_8)) { + if (line.isEmpty()) { + continue; + } + + PathFragment headerPath = new PathFragment(line); + Artifact header = inputArtifactsMap.get(headerPath); + if (header == null) { + missing.add(headerPath); + } else { + includeBuilder.add(header); + } + } + + if (!missing.isEmpty()) { + includeBuilder.addAll( + findRequiredHeaderInputsInTreeArtifacts(sourceFile, inputArtifactsMap, missing)); + } + return includeBuilder.build(); + } catch (IOException ex) { + throw new EnvironmentalExecException( + String.format("Error reading headers file %s", headersListFile.getExecPathString()), ex); + } + } + + /** + * Headers inside a TreeArtifact will not have their ExecPath as a key in the map as they do not + * have their own Artifact object. These headers must be mapped to their containing TreeArtifact. + * We are unable to select individual files from within a TreeArtifact so must discover the entire + * TreeArtifact as an input. + */ + private static Iterable<Artifact> findRequiredHeaderInputsInTreeArtifacts( + Artifact sourceFile, + Map<PathFragment, Artifact> inputArtifactsMap, + List<PathFragment> missing) + throws ExecException { + ImmutableList.Builder<Artifact> includeBuilder = ImmutableList.builder(); + ImmutableList.Builder<PathFragment> treeArtifactPathsBuilder = ImmutableList.builder(); + for (Entry<PathFragment, Artifact> inputEntry : inputArtifactsMap.entrySet()) { + if (inputEntry.getValue().isTreeArtifact()) { + treeArtifactPathsBuilder.add(inputEntry.getKey()); + } + } + + ImmutableList<PathFragment> treeArtifactPaths = treeArtifactPathsBuilder.build(); + for (PathFragment missingPath : missing) { + includeBuilder.add( + findRequiredHeaderInputInTreeArtifacts( + sourceFile, treeArtifactPaths, inputArtifactsMap, missingPath)); + } + return includeBuilder.build(); + } + + private static Artifact findRequiredHeaderInputInTreeArtifacts( + Artifact sourceFile, + List<PathFragment> treeArtifactPaths, + Map<PathFragment, Artifact> inputArtifactsMap, + PathFragment missingPath) + throws ExecException { + for (PathFragment treeArtifactPath : treeArtifactPaths) { + if (missingPath.startsWith(treeArtifactPath)) { + return inputArtifactsMap.get(treeArtifactPath); + } + } + + throw new UserExecException( + String.format( + "Unable to map header file (%s) found during header scanning of %s." + + " This is usually the result of a case mismatch.", + missingPath, sourceFile.getExecPathString())); + } +} diff --git a/src/main/java/com/google/devtools/build/lib/rules/objc/LegacyCompilationSupport.java b/src/main/java/com/google/devtools/build/lib/rules/objc/LegacyCompilationSupport.java index 3af3a1fe2b..befa6b20e7 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/objc/LegacyCompilationSupport.java +++ b/src/main/java/com/google/devtools/build/lib/rules/objc/LegacyCompilationSupport.java @@ -64,10 +64,8 @@ import com.google.devtools.build.lib.rules.apple.DottedVersion; import com.google.devtools.build.lib.rules.apple.Platform; import com.google.devtools.build.lib.rules.cpp.CcToolchainProvider; import com.google.devtools.build.lib.rules.cpp.CppCompileAction.DotdFile; -import com.google.devtools.build.lib.rules.cpp.CppFileTypes; import com.google.devtools.build.lib.rules.cpp.CppModuleMap; import com.google.devtools.build.lib.rules.cpp.FdoSupportProvider; -import com.google.devtools.build.lib.util.FileTypeSet; import com.google.devtools.build.lib.util.Preconditions; import com.google.devtools.build.lib.vfs.FileSystemUtils; import com.google.devtools.build.lib.vfs.PathFragment; @@ -96,17 +94,6 @@ public class LegacyCompilationSupport extends CompilationSupport { }; /** - * Set of {@link com.google.devtools.build.lib.util.FileType} of source artifacts that are - * compatible with header thinning. - */ - private static final FileTypeSet SOURCES_FOR_HEADER_THINNING = - FileTypeSet.of( - CppFileTypes.OBJC_SOURCE, - CppFileTypes.OBJCPP_SOURCE, - CppFileTypes.CPP_SOURCE, - CppFileTypes.C_SOURCE); - - /** * Returns information about the given rule's compilation artifacts. Dependencies specified in the * current rule's attributes are obtained via {@code ruleContext}. Output locations are determined * using the given {@code intermediateArtifacts} object. The fact that these are distinct objects diff --git a/src/main/java/com/google/devtools/build/lib/rules/objc/ObjcCompileAction.java b/src/main/java/com/google/devtools/build/lib/rules/objc/ObjcCompileAction.java index 8087928219..e5be5fd6e9 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/objc/ObjcCompileAction.java +++ b/src/main/java/com/google/devtools/build/lib/rules/objc/ObjcCompileAction.java @@ -28,6 +28,7 @@ import com.google.devtools.build.lib.actions.ActionInput; import com.google.devtools.build.lib.actions.ActionOwner; import com.google.devtools.build.lib.actions.Artifact; import com.google.devtools.build.lib.actions.ArtifactResolver; +import com.google.devtools.build.lib.actions.ExecException; import com.google.devtools.build.lib.actions.Executor; import com.google.devtools.build.lib.actions.ResourceSet; import com.google.devtools.build.lib.actions.RunfilesSupplier; @@ -49,16 +50,11 @@ import com.google.devtools.build.lib.rules.cpp.HeaderDiscovery; import com.google.devtools.build.lib.rules.cpp.IncludeScanningContext; import com.google.devtools.build.lib.util.DependencySet; import com.google.devtools.build.lib.util.Fingerprint; -import com.google.devtools.build.lib.vfs.FileSystemUtils; import com.google.devtools.build.lib.vfs.Path; import com.google.devtools.build.lib.vfs.PathFragment; import java.io.IOException; -import java.nio.charset.StandardCharsets; -import java.util.ArrayList; import java.util.LinkedHashMap; -import java.util.List; import java.util.Map; -import java.util.Map.Entry; import javax.annotation.Nullable; /** @@ -187,90 +183,21 @@ public class ObjcCompileAction extends SpawnAction { public synchronized Iterable<Artifact> discoverInputs( ActionExecutionContext actionExecutionContext) throws ActionExecutionException, InterruptedException { - discoveredInputs = headersListFile != null ? findRequiredHeaderInputs() : filterHeaderFiles(); - return discoveredInputs; - } - - /** Reads the header scanning output file and discovers all those headers as outputs. */ - private Iterable<Artifact> findRequiredHeaderInputs() - throws ActionExecutionException, InterruptedException { - try { - Map<PathFragment, Artifact> inputArtifactsMap = getAllowedDerivedInputsMap(false); - ImmutableList.Builder<Artifact> includeBuilder = ImmutableList.builder(); - List<PathFragment> missing = new ArrayList<>(); - for (String line : - FileSystemUtils.readLines(headersListFile.getPath(), StandardCharsets.UTF_8)) { - if (line.isEmpty()) { - continue; - } - - PathFragment headerPath = new PathFragment(line); - Artifact header = inputArtifactsMap.get(headerPath); - if (header == null) { - missing.add(headerPath); - } else { - includeBuilder.add(header); - } - } - - if (!missing.isEmpty()) { - includeBuilder.addAll(findRequiredHeaderInputsInTreeArtifacts(inputArtifactsMap, missing)); - } - return includeBuilder.build(); - } catch (IOException ex) { - throw new ActionExecutionException( - String.format("Error reading headers file %s", headersListFile.getExecPathString()), - ex, - this, - false); - } - } - - /** - * Headers inside a TreeArtifact will not have their ExecPath as a key in the map as they do not - * have their own Artifact object. These headers must be mapped to their containing TreeArtifact. - * We are unable to select individual files from within a TreeArtifact so must discover the entire - * TreeArtifact as an input. - */ - private Iterable<Artifact> findRequiredHeaderInputsInTreeArtifacts( - Map<PathFragment, Artifact> inputArtifactsMap, List<PathFragment> missing) - throws ActionExecutionException { - ImmutableList.Builder<Artifact> includeBuilder = ImmutableList.builder(); - ImmutableList.Builder<PathFragment> treeArtifactPathsBuilder = ImmutableList.builder(); - for (Entry<PathFragment, Artifact> inputEntry : inputArtifactsMap.entrySet()) { - if (inputEntry.getValue().isTreeArtifact()) { - treeArtifactPathsBuilder.add(inputEntry.getKey()); - } - } - - ImmutableList<PathFragment> treeArtifactPaths = treeArtifactPathsBuilder.build(); - for (PathFragment missingPath : missing) { - includeBuilder.add( - findRequiredHeaderInputInTreeArtifacts( - treeArtifactPaths, inputArtifactsMap, missingPath)); - } - - return includeBuilder.build(); - } - - private Artifact findRequiredHeaderInputInTreeArtifacts( - ImmutableList<PathFragment> treeArtifactPaths, - Map<PathFragment, Artifact> inputArtifactsMap, - PathFragment missingPath) - throws ActionExecutionException { - for (PathFragment treeArtifactPath : treeArtifactPaths) { - if (missingPath.startsWith(treeArtifactPath)) { - return inputArtifactsMap.get(treeArtifactPath); + if (headersListFile != null) { + try { + discoveredInputs = + HeaderThinning.findRequiredHeaderInputs( + sourceFile, headersListFile, getAllowedDerivedInputsMap(false)); + } catch (ExecException e) { + throw e.toActionExecutionException( + "Header thinning of rule '" + getOwner().getLabel() + "'", + actionExecutionContext.getExecutor().getVerboseFailures(), + this); } + } else { + discoveredInputs = filterHeaderFiles(); } - - throw new ActionExecutionException( - String.format( - "Unable to map header file (%s) found during header scanning of %s." - + " This is usually the result of a case mismatch.", - missingPath, sourceFile.getExecPathString()), - this, - true); + return discoveredInputs; } @Override diff --git a/src/main/java/com/google/devtools/build/lib/rules/objc/ObjcCppSemantics.java b/src/main/java/com/google/devtools/build/lib/rules/objc/ObjcCppSemantics.java index e2d49af3e9..bca6ccfc66 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/objc/ObjcCppSemantics.java +++ b/src/main/java/com/google/devtools/build/lib/rules/objc/ObjcCppSemantics.java @@ -18,6 +18,7 @@ import static com.google.devtools.build.lib.rules.objc.ObjcProvider.DYNAMIC_FRAM import static com.google.devtools.build.lib.rules.objc.ObjcProvider.HEADER; import static com.google.devtools.build.lib.rules.objc.ObjcProvider.STATIC_FRAMEWORK_FILE; +import com.google.common.collect.ImmutableList; import com.google.devtools.build.lib.actions.Artifact; import com.google.devtools.build.lib.analysis.RuleContext; import com.google.devtools.build.lib.collect.nestedset.NestedSet; @@ -26,9 +27,11 @@ import com.google.devtools.build.lib.rules.cpp.CppCompileActionBuilder; import com.google.devtools.build.lib.rules.cpp.CppCompileActionContext; import com.google.devtools.build.lib.rules.cpp.CppConfiguration; import com.google.devtools.build.lib.rules.cpp.CppConfiguration.HeadersCheckingMode; +import com.google.devtools.build.lib.rules.cpp.CppFileTypes; import com.google.devtools.build.lib.rules.cpp.CppSemantics; import com.google.devtools.build.lib.rules.cpp.HeaderDiscovery.DotdPruningMode; import com.google.devtools.build.lib.rules.cpp.IncludeProcessing; +import com.google.devtools.build.lib.util.FileTypeSet; import com.google.devtools.build.lib.vfs.PathFragment; /** @@ -39,21 +42,43 @@ public class ObjcCppSemantics implements CppSemantics { private final IncludeProcessing includeProcessing; private final ObjcProvider objcProvider; private final ObjcConfiguration config; + private final boolean isHeaderThinningEnabled; + private final IntermediateArtifacts intermediateArtifacts; + + /** + * Set of {@link com.google.devtools.build.lib.util.FileType} of source artifacts that are + * compatible with header thinning. + */ + private static final FileTypeSet SOURCES_FOR_HEADER_THINNING = + FileTypeSet.of( + CppFileTypes.OBJC_SOURCE, + CppFileTypes.OBJCPP_SOURCE, + CppFileTypes.CPP_SOURCE, + CppFileTypes.C_SOURCE); /** * Creates an instance of ObjcCppSemantics * * @param objcProvider the provider that should be used in determining objc-specific inputs to * actions - * @param config the ObjcConfiguration for this build * @param includeProcessing the closure providing the strategy for processing of includes for * actions + * @param config the ObjcConfiguration for this build + * @param isHeaderThinningEnabled true if headers_list artifacts should be generated and added as + * input to compiling actions + * @param intermediateArtifacts used to create headers_list artifacts */ public ObjcCppSemantics( - ObjcProvider objcProvider, IncludeProcessing includeProcessing, ObjcConfiguration config) { - this.includeProcessing = includeProcessing; + ObjcProvider objcProvider, + IncludeProcessing includeProcessing, + ObjcConfiguration config, + boolean isHeaderThinningEnabled, + IntermediateArtifacts intermediateArtifacts) { this.objcProvider = objcProvider; + this.includeProcessing = includeProcessing; this.config = config; + this.isHeaderThinningEnabled = isHeaderThinningEnabled; + this.intermediateArtifacts = intermediateArtifacts; } @Override @@ -73,6 +98,15 @@ public class ObjcCppSemantics implements CppSemantics { actionBuilder.addTransitiveMandatoryInputs(objcProvider.get(STATIC_FRAMEWORK_FILE)); actionBuilder.addTransitiveMandatoryInputs(objcProvider.get(DYNAMIC_FRAMEWORK_FILE)); + + if (isHeaderThinningEnabled) { + Artifact sourceFile = actionBuilder.getSourceFile(); + if (!sourceFile.isTreeArtifact() + && SOURCES_FOR_HEADER_THINNING.matches(sourceFile.getFilename())) { + actionBuilder.addMandatoryInputs( + ImmutableList.of(intermediateArtifacts.headersListFile(sourceFile))); + } + } } @Override |