aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/main/java
diff options
context:
space:
mode:
authorGravatar Googler <noreply@google.com>2017-03-03 06:38:39 +0000
committerGravatar Yue Gan <yueg@google.com>2017-03-03 10:39:21 +0000
commitcf0af4c059bdf1d1cc54c9c1a1315696a7472dc4 (patch)
tree6670472050c4246f7f1864a20c5b3997d0125e11 /src/main/java
parentdfffa11c5b5869f4a5f410512389cd28a158800f (diff)
Adds support for the header thinning feature to the new Objective-C rule implementation that uses crosstool for compilation.
-- PiperOrigin-RevId: 149083774 MOS_MIGRATED_REVID=149083774
Diffstat (limited to 'src/main/java')
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/objc/CompilationSupport.java22
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/objc/CrosstoolCompilationSupport.java81
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/objc/HeaderThinning.java173
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/objc/LegacyCompilationSupport.java13
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/objc/ObjcCompileAction.java101
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/objc/ObjcCppSemantics.java40
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