diff options
author | 2016-07-27 15:14:29 +0000 | |
---|---|---|
committer | 2016-07-28 18:36:29 -0400 | |
commit | 009e05956acde1e9d61befad72f25375a5bad57b (patch) | |
tree | 8a14ae6bc171e8c98c71701104034af1912b515c /src/main/java/com/google | |
parent | 1b7abbf17405e7168272ab91fef13550cdbef5cc (diff) |
Experimental java annotation support with unpredictable action inputs/outputs in j2objc_library behind flag --experimental_j2objc_annotation_processing
Also added flag --experimental_zip_tree_artifact to switch on and off the zipping implementation of tree artifact generation.
--
MOS_MIGRATED_REVID=128586669
Diffstat (limited to 'src/main/java/com/google')
9 files changed, 553 insertions, 116 deletions
diff --git a/src/main/java/com/google/devtools/build/lib/actions/Artifact.java b/src/main/java/com/google/devtools/build/lib/actions/Artifact.java index bbea1f5ed1..374f8872ba 100644 --- a/src/main/java/com/google/devtools/build/lib/actions/Artifact.java +++ b/src/main/java/com/google/devtools/build/lib/actions/Artifact.java @@ -36,12 +36,10 @@ import com.google.devtools.build.lib.util.FileType; import com.google.devtools.build.lib.util.Preconditions; import com.google.devtools.build.lib.vfs.Path; import com.google.devtools.build.lib.vfs.PathFragment; - import java.util.ArrayList; import java.util.Collection; import java.util.Comparator; import java.util.List; - import javax.annotation.Nullable; /** @@ -155,6 +153,16 @@ public class Artifact } }; + /** + * A Predicate that evaluates to true if the Artifact <b>is</b> a tree artifact. + */ + public static final Predicate<Artifact> IS_TREE_ARTIFACT = new Predicate<Artifact>() { + @Override + public boolean apply(Artifact input) { + return input.isTreeArtifact(); + } + }; + private final int hashCode; private final Path path; private final Root root; diff --git a/src/main/java/com/google/devtools/build/lib/analysis/actions/CustomCommandLine.java b/src/main/java/com/google/devtools/build/lib/analysis/actions/CustomCommandLine.java index 793069ec37..d314388fe4 100644 --- a/src/main/java/com/google/devtools/build/lib/analysis/actions/CustomCommandLine.java +++ b/src/main/java/com/google/devtools/build/lib/analysis/actions/CustomCommandLine.java @@ -27,13 +27,11 @@ import com.google.devtools.build.lib.collect.nestedset.NestedSet; import com.google.devtools.build.lib.concurrent.ThreadSafety.Immutable; import com.google.devtools.build.lib.util.Preconditions; import com.google.devtools.build.lib.vfs.PathFragment; - import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.Set; import java.util.TreeSet; - import javax.annotation.Nullable; /** @@ -136,7 +134,7 @@ public final class CustomCommandLine extends CommandLine { void eval(ImmutableList.Builder<String> builder, ArtifactExpander artifactExpander) { Set<Artifact> expandedArtifacts = new TreeSet<>(); artifactExpander.expand(treeArtifact, expandedArtifacts); - + if (!expandedArtifacts.isEmpty()) { builder.add(Artifact.joinExecPaths(delimiter, expandedArtifacts)); } @@ -151,6 +149,34 @@ public final class CustomCommandLine extends CommandLine { } } + private static final class ExpandedTreeArtifactExecPathsArg + extends TreeArtifactExpansionArgvFragment { + private final Artifact treeArtifact; + + private ExpandedTreeArtifactExecPathsArg(Artifact treeArtifact) { + Preconditions.checkArgument( + treeArtifact.isTreeArtifact(), "%s is not a TreeArtifact", treeArtifact); + this.treeArtifact = treeArtifact; + } + + @Override + void eval(ImmutableList.Builder<String> builder, ArtifactExpander artifactExpander) { + Set<Artifact> expandedArtifacts = new TreeSet<>(); + artifactExpander.expand(treeArtifact, expandedArtifacts); + + for (Artifact expandedArtifact : expandedArtifacts) { + builder.add(expandedArtifact.getExecPathString()); + } + } + + @Override + public String describe() { + return String.format( + "ExpandedTreeArtifactExecPathsArg{ treeArtifact: %s}", + treeArtifact.getExecPathString()); + } + } + private static final class PathWithTemplateArg extends ArgvFragment { private final String template; @@ -515,6 +541,17 @@ public final class CustomCommandLine extends CommandLine { return this; } + /** + * Adds the exec paths (one argument per exec path) of all {@link TreeFileArtifact}s under + * {@code treeArtifact}. + * + * @param treeArtifact the TreeArtifact containing the {@link TreeFileArtifact}s to add. + */ + public Builder addExpandedTreeArtifactExecPaths(Artifact treeArtifact) { + arguments.add(new ExpandedTreeArtifactExecPathsArg(treeArtifact)); + return this; + } + public Builder addBeforeEachPath(String repeated, Iterable<PathFragment> paths) { if (repeated != null && paths != null) { arguments.add(InterspersingArgs.fromStrings(paths, repeated, /*formatEach=*/ null)); diff --git a/src/main/java/com/google/devtools/build/lib/rules/cpp/CppModuleMapAction.java b/src/main/java/com/google/devtools/build/lib/rules/cpp/CppModuleMapAction.java index 183da379fc..817ee99c60 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/cpp/CppModuleMapAction.java +++ b/src/main/java/com/google/devtools/build/lib/rules/cpp/CppModuleMapAction.java @@ -16,15 +16,17 @@ package com.google.devtools.build.lib.rules.cpp; import com.google.common.annotations.VisibleForTesting; import com.google.common.base.Strings; import com.google.common.collect.ImmutableList; +import com.google.common.collect.Iterables; import com.google.devtools.build.lib.actions.ActionExecutionContext; import com.google.devtools.build.lib.actions.ActionOwner; import com.google.devtools.build.lib.actions.Artifact; +import com.google.devtools.build.lib.actions.Artifact.ArtifactExpander; import com.google.devtools.build.lib.actions.ResourceSet; import com.google.devtools.build.lib.analysis.actions.AbstractFileWriteAction; +import com.google.devtools.build.lib.analysis.actions.AbstractFileWriteAction.DeterministicWriter; import com.google.devtools.build.lib.concurrent.ThreadSafety.Immutable; import com.google.devtools.build.lib.util.Fingerprint; import com.google.devtools.build.lib.vfs.PathFragment; - import java.io.IOException; import java.io.OutputStream; import java.nio.charset.StandardCharsets; @@ -72,7 +74,13 @@ public final class CppModuleMapAction extends AbstractFileWriteAction { boolean moduleMapHomeIsCwd, boolean generateSubmodules, boolean externDependencies) { - super(owner, ImmutableList.<Artifact>of(), cppModuleMap.getArtifact(), + super( + owner, + ImmutableList.<Artifact>builder() + .addAll(Iterables.filter(privateHeaders, Artifact.IS_TREE_ARTIFACT)) + .addAll(Iterables.filter(publicHeaders, Artifact.IS_TREE_ARTIFACT)) + .build(), + cppModuleMap.getArtifact(), /*makeExecutable=*/false); this.cppModuleMap = cppModuleMap; this.moduleMapHomeIsCwd = moduleMapHomeIsCwd; @@ -87,6 +95,7 @@ public final class CppModuleMapAction extends AbstractFileWriteAction { @Override public DeterministicWriter newDeterministicWriter(ActionExecutionContext ctx) { + final ArtifactExpander artifactExpander = ctx.getArtifactExpander(); return new DeterministicWriter() { @Override public void writeOutputFile(OutputStream out) throws IOException { @@ -101,11 +110,11 @@ public final class CppModuleMapAction extends AbstractFileWriteAction { content.append(" export *\n"); HashSet<PathFragment> deduper = new HashSet<>(); - for (Artifact artifact : publicHeaders) { + for (Artifact artifact : expandedHeaders(artifactExpander, publicHeaders)) { appendHeader( content, "", artifact.getExecPath(), leadingPeriods, /*canCompile=*/ true, deduper); } - for (Artifact artifact : privateHeaders) { + for (Artifact artifact : expandedHeaders(artifactExpander, privateHeaders)) { appendHeader( content, "private", @@ -137,7 +146,21 @@ public final class CppModuleMapAction extends AbstractFileWriteAction { } }; } - + + private static Iterable<Artifact> expandedHeaders(ArtifactExpander artifactExpander, + Iterable<Artifact> unexpandedHeaders) { + List<Artifact> expandedHeaders = new ArrayList<>(); + for (Artifact unexpandedHeader : unexpandedHeaders) { + if (unexpandedHeader.isTreeArtifact()) { + artifactExpander.expand(unexpandedHeader, expandedHeaders); + } else { + expandedHeaders.add(unexpandedHeader); + } + } + + return ImmutableList.copyOf(expandedHeaders); + } + private void appendHeader(StringBuilder content, String visibilitySpecifier, PathFragment path, String leadingPeriods, boolean canCompile, HashSet<PathFragment> deduper) { if (deduper.contains(path)) { 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 056dd97934..97a4b01d6e 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 @@ -55,9 +55,9 @@ import com.google.common.collect.ImmutableSet; import com.google.common.collect.Iterables; import com.google.common.collect.Lists; import com.google.common.collect.Sets; -import com.google.devtools.build.lib.actions.Action; import com.google.devtools.build.lib.actions.ActionAnalysisMetadata; import com.google.devtools.build.lib.actions.Artifact; +import com.google.devtools.build.lib.actions.Artifact.TreeFileArtifact; import com.google.devtools.build.lib.actions.ParameterFile; import com.google.devtools.build.lib.analysis.AnalysisEnvironment; import com.google.devtools.build.lib.analysis.FilesToRunProvider; @@ -66,9 +66,10 @@ import com.google.devtools.build.lib.analysis.RuleConfiguredTarget.Mode; import com.google.devtools.build.lib.analysis.RuleContext; import com.google.devtools.build.lib.analysis.actions.CommandLine; import com.google.devtools.build.lib.analysis.actions.CustomCommandLine; -import com.google.devtools.build.lib.analysis.actions.FileWriteAction; import com.google.devtools.build.lib.analysis.actions.ParameterFileWriteAction; import com.google.devtools.build.lib.analysis.actions.SpawnAction; +import com.google.devtools.build.lib.analysis.actions.SpawnActionTemplate; +import com.google.devtools.build.lib.analysis.actions.SpawnActionTemplate.OutputPathMapper; import com.google.devtools.build.lib.analysis.config.BuildConfiguration; import com.google.devtools.build.lib.collect.nestedset.NestedSet; import com.google.devtools.build.lib.collect.nestedset.NestedSetBuilder; @@ -180,10 +181,17 @@ public final class CompilationSupport { new Predicate<Artifact>() { @Override public boolean apply(Artifact artifact) { - // The current clang (clang-600.0.57) on Darwin doesn't support 'textual', so we can't - // have '.inc' files in the module map (since they're implictly textual). - // TODO(bazel-team): Use HEADERS file type once clang-700 is the base clang we support. - return artifact.getFilename().endsWith(".h"); + if (artifact.isTreeArtifact()) { + // Tree artifact is basically a directory, which does not have any information about + // the contained files and their extensions. Here we assume the passed in tree artifact + // contains proper header files with .h extension. + return true; + } else { + // The current clang (clang-600.0.57) on Darwin doesn't support 'textual', so we can't + // have '.inc' files in the module map (since they're implictly textual). + // TODO(bazel-team): Use HEADERS file type once clang-700 is the base clang we support. + return artifact.getFilename().endsWith(".h"); + } } }; @@ -234,6 +242,19 @@ public final class CompilationSupport { static final ImmutableList<String> DEFAULT_LINKER_FLAGS = ImmutableList.of("-ObjC"); /** + * A mapper that maps input ObjC source {@link Artifact.TreeFileArtifact}s to output + * object file {@link Artifact.TreeFileArtifact}s. + */ + private static final OutputPathMapper COMPILE_ACTION_TEMPLATE_OUTPUT_PATH_MAPPER = + new OutputPathMapper() { + @Override + public PathFragment parentRelativeOutputPath(TreeFileArtifact inputTreeFileArtifact) { + return FileSystemUtils.replaceExtension( + inputTreeFileArtifact.getParentRelativePath(), ".o"); + } + }; + + /** * Returns information about the given rule's compilation artifacts. */ // TODO(bazel-team): Remove this information from ObjcCommon and move it internal to this class. @@ -398,8 +419,7 @@ public final class CompilationSupport { common.getObjcProvider(), extraCompileArgs, priorityHeaders, - moduleMap, - buildConfiguration.isCodeCoverageEnabled()); + moduleMap); } return this; } @@ -413,8 +433,7 @@ public final class CompilationSupport { ObjcProvider objcProvider, ExtraCompileArgs extraCompileArgs, Iterable<PathFragment> priorityHeaders, - Optional<CppModuleMap> moduleMap, - boolean isCodeCoverageEnabled) { + Optional<CppModuleMap> moduleMap) { ImmutableList.Builder<Artifact> objFiles = new ImmutableList.Builder<>(); for (Artifact sourceFile : compilationArtifacts.getSrcs()) { Artifact objFile = intermediateArtifacts.objFile(sourceFile); @@ -422,30 +441,50 @@ public final class CompilationSupport { if (ObjcRuleClasses.SWIFT_SOURCES.matches(sourceFile.getFilename())) { registerSwiftCompileAction(sourceFile, objFile, objcProvider); } else { + if (objFile.isTreeArtifact()) { + registerCompileActionTemplate( + sourceFile, + objFile, + objcProvider, + priorityHeaders, + moduleMap, + compilationArtifacts, + Iterables.concat(extraCompileArgs, ImmutableList.of("-fobjc-arc"))); + } else { + registerCompileAction( + sourceFile, + objFile, + objcProvider, + priorityHeaders, + moduleMap, + compilationArtifacts, + Iterables.concat(extraCompileArgs, ImmutableList.of("-fobjc-arc"))); + } + } + } + for (Artifact nonArcSourceFile : compilationArtifacts.getNonArcSrcs()) { + Artifact objFile = intermediateArtifacts.objFile(nonArcSourceFile); + objFiles.add(objFile); + if (objFile.isTreeArtifact()) { + registerCompileActionTemplate( + nonArcSourceFile, + objFile, + objcProvider, + priorityHeaders, + moduleMap, + compilationArtifacts, + Iterables.concat(extraCompileArgs, ImmutableList.of("-fno-objc-arc"))); + } else { registerCompileAction( - sourceFile, + nonArcSourceFile, objFile, objcProvider, priorityHeaders, moduleMap, compilationArtifacts, - Iterables.concat(extraCompileArgs, ImmutableList.of("-fobjc-arc")), - isCodeCoverageEnabled); + Iterables.concat(extraCompileArgs, ImmutableList.of("-fno-objc-arc"))); } } - for (Artifact nonArcSourceFile : compilationArtifacts.getNonArcSrcs()) { - Artifact objFile = intermediateArtifacts.objFile(nonArcSourceFile); - objFiles.add(objFile); - registerCompileAction( - nonArcSourceFile, - objFile, - objcProvider, - priorityHeaders, - moduleMap, - compilationArtifacts, - Iterables.concat(extraCompileArgs, ImmutableList.of("-fno-objc-arc")), - isCodeCoverageEnabled); - } objFiles.addAll(compilationArtifacts.getPrecompiledSrcs()); @@ -454,7 +493,7 @@ public final class CompilationSupport { } for (Artifact archive : compilationArtifacts.getArchive().asSet()) { - registerArchiveActions(objFiles, archive); + registerArchiveActions(objFiles.build(), archive); } } @@ -478,35 +517,30 @@ public final class CompilationSupport { return addSource(commandLine, sourceFile); } - private void registerCompileAction( + private CustomCommandLine compileActionCommandLine( Artifact sourceFile, Artifact objFile, ObjcProvider objcProvider, Iterable<PathFragment> priorityHeaders, Optional<CppModuleMap> moduleMap, - CompilationArtifacts compilationArtifacts, + Optional<Artifact> pchFile, + Optional<Artifact> dotdFile, Iterable<String> otherFlags, - boolean isCodeCoverageEnabled) { - ImmutableList.Builder<String> coverageFlags = new ImmutableList.Builder<>(); - ImmutableList.Builder<Artifact> gcnoFiles = new ImmutableList.Builder<>(); - ImmutableList.Builder<Artifact> additionalInputs = new ImmutableList.Builder<>(); - if (isCodeCoverageEnabled && ObjcRuleClasses.isInstrumentable(sourceFile)) { - coverageFlags.addAll(CLANG_COVERAGE_FLAGS); - gcnoFiles.add(intermediateArtifacts.gcnoFile(sourceFile)); - } - CustomCommandLine.Builder commandLine = new CustomCommandLine.Builder() - .add(CLANG); - if (ObjcRuleClasses.CPP_SOURCES.matches(sourceFile.getExecPath())) { + boolean collectCodeCoverage, + boolean isCPlusPlusSource, + boolean hasSwiftSources) { + CustomCommandLine.Builder commandLine = new CustomCommandLine.Builder().add(CLANG); + + if (isCPlusPlusSource) { commandLine.add("-stdlib=libc++"); commandLine.add("-std=gnu++11"); } - if (compilationArtifacts.hasSwiftSources()) { + if (hasSwiftSources) { // Add the directory that contains merged TargetName-Swift.h header to search path, in case // any of ObjC files use it. commandLine.add("-I"); commandLine.addPath(intermediateArtifacts.swiftHeader().getExecPath().getParentDirectory()); - additionalInputs.add(intermediateArtifacts.swiftHeader()); } // The linker needs full debug symbol information to perform binary dead-code stripping. @@ -514,35 +548,67 @@ public final class CompilationSupport { commandLine.add("-g"); } - Artifact dotdFile = intermediateArtifacts.dotdFile(sourceFile); + List<String> coverageFlags = ImmutableList.of(); + if (collectCodeCoverage) { + coverageFlags = CLANG_COVERAGE_FLAGS; + } + commandLine .add(compileFlagsForClang(appleConfiguration)) .add(commonLinkAndCompileFlagsForClang(objcProvider, objcConfiguration, appleConfiguration)) .add(objcConfiguration.getCoptsForCompilationMode()) .addBeforeEachPath("-iquote", ObjcCommon.userHeaderSearchPaths(buildConfiguration)) - .addBeforeEachExecPath("-include", compilationArtifacts.getPchFile().asSet()) + .addBeforeEachExecPath("-include", pchFile.asSet()) .addBeforeEachPath("-I", priorityHeaders) .addBeforeEachPath("-I", objcProvider.get(INCLUDE)) .addBeforeEachPath("-isystem", objcProvider.get(INCLUDE_SYSTEM)) .add(otherFlags) .addFormatEach("-D%s", objcProvider.get(DEFINE)) - .add(coverageFlags.build()) + .add(coverageFlags) .add(getCompileRuleCopts()); - PathFragment sourceExecPathFragment = sourceFile.getExecPath(); - String sourcePath = sourceExecPathFragment.getPathString(); - if (!sourceExecPathFragment.isAbsolute() && objcConfiguration.getUseAbsolutePathsForActions()) { - sourcePath = objcConfiguration.getXcodeWorkspaceRoot() + "/" + sourcePath; + + // Add input source file arguments + commandLine.add("-c"); + if (!sourceFile.getExecPath().isAbsolute() + && objcConfiguration.getUseAbsolutePathsForActions()) { + String workspaceRoot = objcConfiguration.getXcodeWorkspaceRoot(); + + // If the source file is a tree artifact, it means the file is basically a directory that may + // contain multiple concrete source files at execution time. When constructing the command + // line, we insert the source tree artifact as a placeholder, which will be replaced with + // one of its contained source files of type {@link Artifact.TreeFileArtifact} at execution + // time. + // + // We also do something similar for the object file arguments below. + if (sourceFile.isTreeArtifact()) { + commandLine.addPlaceholderTreeArtifactFormattedExecPath(workspaceRoot + "/%s", sourceFile); + } else { + commandLine.addPaths(workspaceRoot + "/%s", sourceFile.getExecPath()); + } + } else { + if (sourceFile.isTreeArtifact()) { + commandLine.addPlaceholderTreeArtifactExecPath(sourceFile); + } else { + commandLine.addPath(sourceFile.getExecPath()); + } } - commandLine - .add("-c").add(sourcePath) - .addExecPath("-o", objFile) - .add("-MD") - .addExecPath("-MF", dotdFile); - if (objcConfiguration.moduleMapsEnabled()) { - additionalInputs.addAll(objcProvider.get(MODULE_MAP)); + // Add output object file arguments. + commandLine.add("-o"); + if (objFile.isTreeArtifact()) { + commandLine.addPlaceholderTreeArtifactExecPath(objFile); + } else { + commandLine.addPath(objFile.getExecPath()); + } + + // Add Dotd file arguments. + if (dotdFile.isPresent()) { + commandLine + .add("-MD") + .addExecPath("-MF", dotdFile.get()); } + // Add module map arguments. if (moduleMap.isPresent()) { // If modules are enabled for the rule, -fmodules is added to the copts already. (This implies // module map usage). Otherwise, we need to pass -fmodule-maps. @@ -564,18 +630,63 @@ public final class CompilationSupport { .add("-fmodule-name=" + moduleMap.get().getName()); } + return commandLine.build(); + } + + private void registerCompileAction( + Artifact sourceFile, + Artifact objFile, + ObjcProvider objcProvider, + Iterable<PathFragment> priorityHeaders, + Optional<CppModuleMap> moduleMap, + CompilationArtifacts compilationArtifacts, + Iterable<String> otherFlags) { + boolean isCPlusPlusSource = ObjcRuleClasses.CPP_SOURCES.matches(sourceFile.getExecPath()); + boolean runCodeCoverage = + buildConfiguration.isCodeCoverageEnabled() && ObjcRuleClasses.isInstrumentable(sourceFile); + boolean hasSwiftSources = compilationArtifacts.hasSwiftSources(); + + CustomCommandLine commandLine = compileActionCommandLine( + sourceFile, + objFile, + objcProvider, + priorityHeaders, + moduleMap, + compilationArtifacts.getPchFile(), + Optional.of(intermediateArtifacts.dotdFile(sourceFile)), + otherFlags, + runCodeCoverage, + isCPlusPlusSource, + hasSwiftSources); + + Optional<Artifact> gcnoFile = Optional.absent(); + if (runCodeCoverage) { + gcnoFile = Optional.of(intermediateArtifacts.gcnoFile(sourceFile)); + } + + Optional<Artifact> swiftHeader = Optional.absent(); + if (hasSwiftSources) { + swiftHeader = Optional.of(intermediateArtifacts.swiftHeader()); + } + + NestedSet<Artifact> moduleMapInputs = NestedSetBuilder.emptySet(Order.STABLE_ORDER); + if (objcConfiguration.moduleMapsEnabled()) { + moduleMapInputs = objcProvider.get(MODULE_MAP); + } + // TODO(bazel-team): Remote private headers from inputs once they're added to the provider. ruleContext.registerAction( ObjcRuleClasses.spawnAppleEnvActionBuilder( appleConfiguration, appleConfiguration.getSingleArchPlatform()) .setMnemonic("ObjcCompile") .setExecutable(xcrunwrapper(ruleContext)) - .setCommandLine(commandLine.build()) + .setCommandLine(commandLine) .addInput(sourceFile) - .addInputs(additionalInputs.build()) + .addInputs(swiftHeader.asSet()) + .addTransitiveInputs(moduleMapInputs) .addOutput(objFile) - .addOutputs(gcnoFiles.build()) - .addOutput(dotdFile) + .addOutputs(gcnoFile.asSet()) + .addOutput(intermediateArtifacts.dotdFile(sourceFile)) .addTransitiveInputs(objcProvider.get(HEADER)) .addInputs(compilationArtifacts.getPrivateHdrs()) .addTransitiveInputs(objcProvider.get(STATIC_FRAMEWORK_FILE)) @@ -585,6 +696,69 @@ public final class CompilationSupport { } /** + * Registers a SpawnActionTemplate to compile the source file tree artifact, {@code sourceFiles}, + * which can contain multiple concrete source files unknown at analysis time. At execution time, + * the SpawnActionTemplate will register one ObjcCompile action for each individual source file + * under {@code sourceFiles}. + * + * <p>Note that this method currently does not support code coverage and sources other than ObjC + * sources. + * + * @param sourceFiles tree artifact containing source files to compile + * @param objFiles tree artifact containing object files compiled from {@code sourceFiles} + * @param objcProvider ObjcProvider instance for this invocation + * @param priorityHeaders priority headers to be included before the dependency headers + * @param moduleMap the module map generated from the associated headers + * @param compilationArtifacts the CompilationArtifacts instance for this invocation + * @param otherFlags extra compilation flags to add to the compile action command line + */ + private void registerCompileActionTemplate( + Artifact sourceFiles, + Artifact objFiles, + ObjcProvider objcProvider, + Iterable<PathFragment> priorityHeaders, + Optional<CppModuleMap> moduleMap, + CompilationArtifacts compilationArtifacts, + Iterable<String> otherFlags) { + CustomCommandLine commandLine = compileActionCommandLine( + sourceFiles, + objFiles, + objcProvider, + priorityHeaders, + moduleMap, + compilationArtifacts.getPchFile(), + Optional.<Artifact>absent(), + otherFlags, + /* runCodeCoverage=*/false, + /* isCPlusPlusSource=*/false, + /* hasSwiftSources=*/false); + + AppleConfiguration appleConfiguration = ruleContext.getFragment(AppleConfiguration.class); + Platform platform = appleConfiguration.getSingleArchPlatform(); + + NestedSet<Artifact> moduleMapInputs = NestedSetBuilder.emptySet(Order.STABLE_ORDER); + if (objcConfiguration.moduleMapsEnabled()) { + moduleMapInputs = objcProvider.get(MODULE_MAP); + } + + ruleContext.registerAction( + new SpawnActionTemplate.Builder(sourceFiles, objFiles) + .setMnemonics("ObjcCompileActionTemplate", "ObjcCompile") + .setExecutable(xcrunwrapper(ruleContext)) + .setCommandLineTemplate(commandLine) + .setEnvironment(ObjcRuleClasses.appleToolchainEnvironment(appleConfiguration, platform)) + .setExecutionInfo(ObjcRuleClasses.darwinActionExecutionRequirement()) + .setOutputPathMapper(COMPILE_ACTION_TEMPLATE_OUTPUT_PATH_MAPPER) + .addCommonTransitiveInputs(objcProvider.get(HEADER)) + .addCommonTransitiveInputs(moduleMapInputs) + .addCommonInputs(compilationArtifacts.getPrivateHdrs()) + .addCommonTransitiveInputs(objcProvider.get(STATIC_FRAMEWORK_FILE)) + .addCommonTransitiveInputs(objcProvider.get(DYNAMIC_FRAMEWORK_FILE)) + .addCommonInputs(compilationArtifacts.getPchFile().asSet()) + .build(ruleContext.getActionOwner())); + } + + /** * Returns the copts for the compile action in the current rule context (using a combination * of the rule's "copts" attribute as well as the current configuration copts). */ @@ -779,23 +953,17 @@ public final class CompilationSupport { .build(ruleContext)); } - private void registerArchiveActions(ImmutableList.Builder<Artifact> objFiles, Artifact archive) { - for (Action action : - archiveActions(objFiles.build(), archive, intermediateArtifacts.archiveObjList())) { - ruleContext.registerAction(action); - } + private void registerArchiveActions(List<Artifact> objFiles, Artifact archive) { + Artifact objList = intermediateArtifacts.archiveObjList(); + registerObjFilelistAction(objFiles, objList); + registerArchiveAction(objFiles, archive); } - private Iterable<Action> archiveActions( + private void registerArchiveAction( Iterable<Artifact> objFiles, - Artifact archive, - Artifact objList) { - - ImmutableList.Builder<Action> actions = new ImmutableList.Builder<>(); - - actions.add(objFilelistAction(objFiles, objList)); - - actions.add(ObjcRuleClasses.spawnAppleEnvActionBuilder( + Artifact archive) { + Artifact objList = intermediateArtifacts.archiveObjList(); + ruleContext.registerAction(ObjcRuleClasses.spawnAppleEnvActionBuilder( appleConfiguration, appleConfiguration.getSingleArchPlatform()) .setMnemonic("ObjcLink") .setExecutable(libtool(ruleContext)) @@ -810,17 +978,31 @@ public final class CompilationSupport { .addInput(objList) .addOutput(archive) .build(ruleContext)); - - return actions.build(); } - private Action objFilelistAction(Iterable<Artifact> objFiles, Artifact objList) { + private void registerObjFilelistAction(Iterable<Artifact> objFiles, Artifact objList) { ImmutableSet<Artifact> dedupedObjFiles = ImmutableSet.copyOf(objFiles); - return new FileWriteAction( + CustomCommandLine.Builder objFilesToLinkParam = new CustomCommandLine.Builder(); + ImmutableList.Builder<Artifact> treeObjFiles = new ImmutableList.Builder<>(); + + for (Artifact objFile : dedupedObjFiles) { + // If the obj file is a tree artifact, we need to expand it into the contained individual + // files properly. + if (objFile.isTreeArtifact()) { + treeObjFiles.add(objFile); + objFilesToLinkParam.addExpandedTreeArtifactExecPaths(objFile); + } else { + objFilesToLinkParam.addPath(objFile.getExecPath()); + } + } + + ruleContext.registerAction(new ParameterFileWriteAction( ruleContext.getActionOwner(), + treeObjFiles.build(), objList, - Artifact.joinExecPaths("\n", dedupedObjFiles), - /*makeExecutable=*/ false); + objFilesToLinkParam.build(), + ParameterFile.ParameterFileType.UNQUOTED, + ISO_8859_1)); } /** @@ -1186,8 +1368,8 @@ public final class CompilationSupport { // resulting in duplicate symbol errors unless they are deduped. objFiles = Iterables.filter(objFiles, Predicates.not(Predicates.in(forceLinkArtifacts))); - ruleContext.registerAction(objFilelistAction(objFiles, inputFileList)); - + registerObjFilelistAction(objFiles, inputFileList); + if (objcConfiguration.shouldPrioritizeStaticLibs()) { commandLine.add("-filelist").add(inputFileList.getExecPathString()); } diff --git a/src/main/java/com/google/devtools/build/lib/rules/objc/IntermediateArtifacts.java b/src/main/java/com/google/devtools/build/lib/rules/objc/IntermediateArtifacts.java index 8d8235dc54..7efef81544 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/objc/IntermediateArtifacts.java +++ b/src/main/java/com/google/devtools/build/lib/rules/objc/IntermediateArtifacts.java @@ -229,7 +229,12 @@ public final class IntermediateArtifacts { * artifact. */ public Artifact objFile(Artifact source) { - return inUniqueObjsDir(source, ".o"); + if (source.isTreeArtifact()) { + PathFragment rootRelativePath = source.getRootRelativePath().replaceName("obj_files"); + return ruleContext.getTreeArtifact(rootRelativePath, ruleContext.getBinOrGenfilesDirectory()); + } else { + return inUniqueObjsDir(source, ".o"); + } } /** diff --git a/src/main/java/com/google/devtools/build/lib/rules/objc/J2ObjcAspect.java b/src/main/java/com/google/devtools/build/lib/rules/objc/J2ObjcAspect.java index a0d3411e80..36aa8d3d5f 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/objc/J2ObjcAspect.java +++ b/src/main/java/com/google/devtools/build/lib/rules/objc/J2ObjcAspect.java @@ -14,6 +14,7 @@ package com.google.devtools.build.lib.rules.objc; +import static com.google.devtools.build.lib.actions.Artifact.IS_TREE_ARTIFACT; import static com.google.devtools.build.lib.packages.Attribute.ConfigurationTransition.HOST; import static com.google.devtools.build.lib.packages.Attribute.attr; import static com.google.devtools.build.lib.packages.BuildType.LABEL; @@ -21,9 +22,11 @@ import static com.google.devtools.build.lib.rules.objc.XcodeProductType.LIBRARY_ import static java.nio.charset.StandardCharsets.ISO_8859_1; import com.google.common.base.Optional; +import com.google.common.base.Predicates; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableSet; import com.google.common.collect.Iterables; +import com.google.devtools.build.lib.actions.Action; import com.google.devtools.build.lib.actions.Artifact; import com.google.devtools.build.lib.actions.ParameterFile; import com.google.devtools.build.lib.analysis.ConfiguredAspect; @@ -34,6 +37,7 @@ 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.ParameterFileWriteAction; +import com.google.devtools.build.lib.analysis.actions.PopulateTreeArtifactAction; import com.google.devtools.build.lib.analysis.actions.SpawnAction; import com.google.devtools.build.lib.analysis.config.BuildConfiguration; import com.google.devtools.build.lib.cmdline.Label; @@ -49,6 +53,7 @@ import com.google.devtools.build.lib.packages.Rule; import com.google.devtools.build.lib.rules.apple.AppleConfiguration; import com.google.devtools.build.lib.rules.apple.AppleToolchain; import com.google.devtools.build.lib.rules.java.JavaCompilationArgsProvider; +import com.google.devtools.build.lib.rules.java.JavaGenJarsProvider; import com.google.devtools.build.lib.rules.java.JavaHelper; import com.google.devtools.build.lib.rules.java.JavaSourceInfoProvider; import com.google.devtools.build.lib.rules.java.Jvm; @@ -56,7 +61,6 @@ import com.google.devtools.build.lib.rules.objc.CompilationSupport.ExtraCompileA import com.google.devtools.build.lib.rules.objc.J2ObjcSource.SourceType; import com.google.devtools.build.lib.util.FileType; import com.google.devtools.build.lib.vfs.PathFragment; - import java.util.List; /** @@ -142,6 +146,10 @@ public class J2ObjcAspect extends NativeAspectClass implements ConfiguredAspectF .direct_compile_time_input() .cfg(HOST) .value(new AppleToolchain.XcodeConfigLabel(toolsRepository))) + .add(attr("$zipper", LABEL) + .cfg(HOST) + .exec() + .value(Label.parseAbsoluteUnchecked(toolsRepository + "//tools/zip:zipper"))) .build(); } @@ -154,17 +162,28 @@ public class J2ObjcAspect extends NativeAspectClass implements ConfiguredAspectF base.getProvider(JavaCompilationArgsProvider.class); JavaSourceInfoProvider sourceInfoProvider = base.getProvider(JavaSourceInfoProvider.class); + JavaGenJarsProvider genJarProvider = + base.getProvider(JavaGenJarsProvider.class); ImmutableSet<Artifact> javaInputFiles = ImmutableSet.<Artifact>builder() .addAll(sourceInfoProvider.getSourceFiles()) .addAll(sourceInfoProvider.getSourceJars()) .addAll(sourceInfoProvider.getSourceJarsForJarFiles()) .build(); + Optional<Artifact> genSrcJar; + boolean annotationProcessingEnabled = ruleContext.getFragment(J2ObjcConfiguration.class) + .annotationProcessingEnabled(); + if (genJarProvider != null && annotationProcessingEnabled) { + genSrcJar = Optional.fromNullable(genJarProvider.getGenSourceJar()); + } else { + genSrcJar = Optional.<Artifact>absent(); + } + XcodeProvider xcodeProvider; ObjcCommon common; if (!javaInputFiles.isEmpty()) { - J2ObjcSource j2ObjcSource = buildJ2ObjcSource(ruleContext, javaInputFiles); + J2ObjcSource j2ObjcSource = buildJ2ObjcSource(ruleContext, javaInputFiles, genSrcJar); J2ObjcMappingFileProvider depJ2ObjcMappingFileProvider = depJ2ObjcMappingFileProvider(ruleContext); createJ2ObjcTranspilationAction( @@ -173,13 +192,23 @@ public class J2ObjcAspect extends NativeAspectClass implements ConfiguredAspectF depJ2ObjcMappingFileProvider.getClassMappingFiles(), javaInputFiles, compilationArgsProvider, - j2ObjcSource); + j2ObjcSource, + genSrcJar); + + boolean zipTreeArtifact = ruleContext.getFragment(J2ObjcConfiguration.class) + .zipTreeArtifact(); + if (genSrcJar.isPresent() && zipTreeArtifact) { + for (Action action : genJarTreeArtifactCreationActions(ruleContext)) { + ruleContext.registerAction(action); + } + } common = common( ruleContext, j2ObjcSource.getObjcSrcs(), j2ObjcSource.getObjcHdrs(), j2ObjcSource.getHeaderSearchPaths(), DEPENDENT_ATTRIBUTES); + xcodeProvider = xcodeProvider( ruleContext, common, @@ -244,13 +273,70 @@ public class J2ObjcAspect extends NativeAspectClass implements ConfiguredAspectF return j2ObjcMappingFileProvider; } - private static void createJ2ObjcTranspilationAction( + private List<Artifact> genJarOutputs(RuleContext ruleContext) { + boolean zipTreeArtifact = ruleContext + .getFragment(J2ObjcConfiguration.class) + .zipTreeArtifact(); + + if (zipTreeArtifact) { + return ImmutableList.of( + j2ObjcGenJarSourceZip(ruleContext), + j2ObjcGenJarSourceZipManifest(ruleContext), + j2ObjcGenJarHeaderZip(ruleContext), + j2ObjcGenJarHeaderZipManifest(ruleContext)); + } else { + return ImmutableList.of( + j2ObjcGenJarTranslatedSourceFiles(ruleContext), + j2objcGenJarTranslatedHeaderFiles(ruleContext)); + } + } + + private List<String> genJarFlags(RuleContext ruleContext) { + boolean zipTreeArtifact = ruleContext.getFragment(J2ObjcConfiguration.class).zipTreeArtifact(); + + if (zipTreeArtifact) { + return ImmutableList.of( + "--output_gen_source_zip", j2ObjcGenJarSourceZip(ruleContext).getExecPathString(), + "--output_gen_header_zip", j2ObjcGenJarHeaderZip(ruleContext).getExecPathString()); + } else { + return ImmutableList.of( + "--output_gen_source_dir", + j2ObjcGenJarTranslatedSourceFiles(ruleContext).getExecPathString(), + "--output_gen_header_dir", + j2objcGenJarTranslatedHeaderFiles(ruleContext).getExecPathString()); + } + } + + private List<Action> genJarTreeArtifactCreationActions(RuleContext ruleContext) { + Artifact sourceFiles = j2ObjcGenJarTranslatedSourceFiles(ruleContext); + Artifact headerFiles = j2objcGenJarTranslatedHeaderFiles(ruleContext); + + ImmutableList.Builder<Action> actions = ImmutableList.builder(); + actions.add(new PopulateTreeArtifactAction( + ruleContext.getActionOwner(), + j2ObjcGenJarSourceZip(ruleContext), + j2ObjcGenJarSourceZipManifest(ruleContext), + sourceFiles, + ruleContext.getExecutablePrerequisite("$zipper", Mode.HOST))); + + actions.add(new PopulateTreeArtifactAction( + ruleContext.getActionOwner(), + j2ObjcGenJarHeaderZip(ruleContext), + j2ObjcGenJarHeaderZipManifest(ruleContext), + headerFiles, + ruleContext.getExecutablePrerequisite("$zipper", Mode.HOST))); + + return actions.build(); + } + + private void createJ2ObjcTranspilationAction( RuleContext ruleContext, NestedSet<Artifact> depsHeaderMappingFiles, NestedSet<Artifact> depsClassMappingFiles, Iterable<Artifact> sources, JavaCompilationArgsProvider compArgsProvider, - J2ObjcSource j2ObjcSource) { + J2ObjcSource j2ObjcSource, + Optional<Artifact> genSrcJar) { CustomCommandLine.Builder argBuilder = CustomCommandLine.builder(); PathFragment javaExecutable = ruleContext.getFragment(Jvm.class, HOST).getJavaExecutable(); argBuilder.add("--java").add(javaExecutable.getPathString()); @@ -259,12 +345,22 @@ public class J2ObjcAspect extends NativeAspectClass implements ConfiguredAspectF argBuilder.addExecPath("--j2objc", j2ObjcDeployJar); argBuilder.add("--main_class").add("com.google.devtools.j2objc.J2ObjC"); - argBuilder.addJoinExecPaths("--translated_source_files", ",", j2ObjcSource.getObjcSrcs()); + argBuilder.addJoinExecPaths( + "--translated_source_files", + ",", + Iterables.filter(j2ObjcSource.getObjcSrcs(), Predicates.not(IS_TREE_ARTIFACT))); argBuilder.add("--objc_file_path").addPath(j2ObjcSource.getObjcFilePath()); Artifact outputDependencyMappingFile = j2ObjcOutputDependencyMappingFile(ruleContext); argBuilder.addExecPath("--output_dependency_mapping_file", outputDependencyMappingFile); + ImmutableList.Builder<Artifact> genSrcOutputFiles = ImmutableList.builder(); + if (genSrcJar.isPresent()) { + genSrcOutputFiles.addAll(genJarOutputs(ruleContext)); + argBuilder.addExecPath("--gen_src_jar", genSrcJar.get()); + argBuilder.add(genJarFlags(ruleContext)); + } + Iterable<String> translationFlags = ruleContext .getFragment(J2ObjcConfiguration.class) .getTranslationFlags(); @@ -307,7 +403,8 @@ public class J2ObjcAspect extends NativeAspectClass implements ConfiguredAspectF ruleContext.getActionOwner(), paramFile, argBuilder.build(), - ParameterFile.ParameterFileType.UNQUOTED, ISO_8859_1)); + ParameterFile.ParameterFileType.UNQUOTED, + ISO_8859_1)); SpawnAction.Builder builder = new SpawnAction.Builder() .setMnemonic("TranspilingJ2objc") @@ -316,16 +413,18 @@ public class J2ObjcAspect extends NativeAspectClass implements ConfiguredAspectF .addInput(j2ObjcDeployJar) .addInput(bootclasspathJar) .addInputs(sources) + .addInputs(genSrcJar.asSet()) .addTransitiveInputs(compileTimeJars) - .addInputs(JavaHelper.getHostJavabaseInputs(ruleContext)) + .addTransitiveInputs(JavaHelper.getHostJavabaseInputs(ruleContext)) .addTransitiveInputs(depsHeaderMappingFiles) .addTransitiveInputs(depsClassMappingFiles) .addInput(paramFile) .setCommandLine(CustomCommandLine.builder() .addPaths("@%s", paramFile.getExecPath()) .build()) - .addOutputs(j2ObjcSource.getObjcSrcs()) - .addOutputs(j2ObjcSource.getObjcHdrs()) + .addOutputs(Iterables.filter(j2ObjcSource.getObjcSrcs(), Predicates.not(IS_TREE_ARTIFACT))) + .addOutputs(Iterables.filter(j2ObjcSource.getObjcHdrs(), Predicates.not(IS_TREE_ARTIFACT))) + .addOutputs(genSrcOutputFiles.build()) .addOutput(outputHeaderMappingFile) .addOutput(outputDependencyMappingFile) .addOutput(archiveSourceMappingFile); @@ -394,8 +493,38 @@ public class J2ObjcAspect extends NativeAspectClass implements ConfiguredAspectF ruleContext, ".archive_source_mapping.j2objc"); } + private static Artifact j2ObjcGenJarTranslatedSourceFiles(RuleContext ruleContext) { + PathFragment rootRelativePath = ruleContext + .getUniqueDirectory("_j2objc/gen_jar_files") + .getRelative("source_files"); + return ruleContext.getTreeArtifact(rootRelativePath, ruleContext.getBinOrGenfilesDirectory()); + } + + private static Artifact j2objcGenJarTranslatedHeaderFiles(RuleContext ruleContext) { + PathFragment rootRelativePath = ruleContext + .getUniqueDirectory("_j2objc/gen_jar_files") + .getRelative("header_files"); + return ruleContext.getTreeArtifact(rootRelativePath, ruleContext.getBinOrGenfilesDirectory()); + } + + private static Artifact j2ObjcGenJarSourceZip(RuleContext ruleContext) { + return ObjcRuleClasses.artifactByAppendingToBaseName(ruleContext, ".genjar_source.zip"); + } + + private static Artifact j2ObjcGenJarSourceZipManifest(RuleContext ruleContext) { + return ObjcRuleClasses.artifactByAppendingToBaseName(ruleContext, ".genjar_source.txt"); + } + + private static Artifact j2ObjcGenJarHeaderZip(RuleContext ruleContext) { + return ObjcRuleClasses.artifactByAppendingToBaseName(ruleContext, ".genjar_header.zip"); + } + + private static Artifact j2ObjcGenJarHeaderZipManifest(RuleContext ruleContext) { + return ObjcRuleClasses.artifactByAppendingToBaseName(ruleContext, ".genjar_header.txt"); + } + private J2ObjcSource buildJ2ObjcSource(RuleContext ruleContext, - Iterable<Artifact> javaInputSourceFiles) { + Iterable<Artifact> javaInputSourceFiles, Optional<Artifact> genSrcJar) { PathFragment objcFileRootRelativePath = ruleContext.getUniqueDirectory("_j2objc"); PathFragment objcFileRootExecPath = ruleContext .getConfiguration() @@ -408,13 +537,23 @@ public class J2ObjcAspect extends NativeAspectClass implements ConfiguredAspectF Iterable<PathFragment> headerSearchPaths = J2ObjcLibrary.j2objcSourceHeaderSearchPaths( ruleContext, objcFileRootExecPath, javaInputSourceFiles); + Optional<Artifact> genJarTranslatedSrcs = Optional.absent(); + Optional<Artifact> genJarTranslatedHdrs = Optional.absent(); + Optional<PathFragment> genJarFileHeaderSearchPaths = Optional.absent(); + + if (genSrcJar.isPresent()) { + genJarTranslatedSrcs = Optional.of(j2ObjcGenJarTranslatedSourceFiles(ruleContext)); + genJarTranslatedHdrs = Optional.of(j2objcGenJarTranslatedHeaderFiles(ruleContext)); + genJarFileHeaderSearchPaths = Optional.of(genJarTranslatedHdrs.get().getExecPath()); + } + return new J2ObjcSource( ruleContext.getRule().getLabel(), - objcSrcs, - objcHdrs, + Iterables.concat(objcSrcs, genJarTranslatedSrcs.asSet()), + Iterables.concat(objcHdrs, genJarTranslatedHdrs.asSet()), objcFileRootExecPath, SourceType.JAVA, - headerSearchPaths); + Iterables.concat(headerSearchPaths, genJarFileHeaderSearchPaths.asSet())); } private Iterable<Artifact> getOutputObjcFiles(RuleContext ruleContext, diff --git a/src/main/java/com/google/devtools/build/lib/rules/objc/J2ObjcCommandLineOptions.java b/src/main/java/com/google/devtools/build/lib/rules/objc/J2ObjcCommandLineOptions.java index 8f438d1825..ad76187a11 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/objc/J2ObjcCommandLineOptions.java +++ b/src/main/java/com/google/devtools/build/lib/rules/objc/J2ObjcCommandLineOptions.java @@ -19,7 +19,6 @@ import com.google.devtools.build.lib.analysis.config.FragmentOptions; import com.google.devtools.build.lib.cmdline.Label; import com.google.devtools.common.options.Converters; import com.google.devtools.common.options.Option; - import java.util.List; /** @@ -52,6 +51,20 @@ public class J2ObjcCommandLineOptions extends FragmentOptions { ) public boolean explicitJreDeps; + @Option(name = "experimental_j2objc_annotation_processing", + defaultValue = "false", + category = "undocumented", + help = "Whether to enable j2objc Java annotation processing." + ) + public boolean annotationProcessingEnabled; + + @Option(name = "experimental_zip_tree_artifact", + defaultValue = "true", + category = "undocumented", + help = "Whether to enable zipping/unzipping implementation of tree artifact creation" + ) + public boolean zipTreeArtifact; + @Override public void addAllLabels(Multimap<String, Label> labelMap) {} } diff --git a/src/main/java/com/google/devtools/build/lib/rules/objc/J2ObjcConfiguration.java b/src/main/java/com/google/devtools/build/lib/rules/objc/J2ObjcConfiguration.java index 0653d43a98..458e2bb6f6 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/objc/J2ObjcConfiguration.java +++ b/src/main/java/com/google/devtools/build/lib/rules/objc/J2ObjcConfiguration.java @@ -24,7 +24,6 @@ import com.google.devtools.build.lib.analysis.config.FragmentOptions; import com.google.devtools.build.lib.concurrent.ThreadSafety.Immutable; import com.google.devtools.build.lib.events.Event; import com.google.devtools.build.lib.events.EventHandler; - import java.util.Collections; import java.util.Set; @@ -78,6 +77,8 @@ public class J2ObjcConfiguration extends Fragment { private final Set<String> translationFlags; private final boolean removeDeadCode; private final boolean explicitJreDeps; + private final boolean annotationProcessingEnabled; + private final boolean zipTreeArtifact; J2ObjcConfiguration(J2ObjcCommandLineOptions j2ObjcOptions) { this.removeDeadCode = j2ObjcOptions.removeDeadCode; @@ -86,6 +87,8 @@ public class J2ObjcConfiguration extends Fragment { .addAll(j2ObjcOptions.translationFlags) .addAll(J2OBJC_ALWAYS_ON_TRANSLATION_FLAGS) .build(); + this.annotationProcessingEnabled = j2ObjcOptions.annotationProcessingEnabled; + this.zipTreeArtifact = j2ObjcOptions.zipTreeArtifact; } /** @@ -116,6 +119,20 @@ public class J2ObjcConfiguration extends Fragment { return explicitJreDeps; } + /** + * Returns whether to enable J2ObjC support for Java annotation processing. + */ + public boolean annotationProcessingEnabled() { + return annotationProcessingEnabled; + } + + /** + * Returns whether to enable the zipping/unzipping implementation of tree artifact creation. + */ + public boolean zipTreeArtifact() { + return zipTreeArtifact; + } + @Override public void reportInvalidOptions(EventHandler reporter, BuildOptions buildOptions) { if (!Collections.disjoint(translationFlags, J2OBJC_BLACKLISTED_TRANSLATION_FLAGS)) { diff --git a/src/main/java/com/google/devtools/build/lib/rules/objc/ObjcRuleClasses.java b/src/main/java/com/google/devtools/build/lib/rules/objc/ObjcRuleClasses.java index e6feaae099..81c8d9bf5e 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/objc/ObjcRuleClasses.java +++ b/src/main/java/com/google/devtools/build/lib/rules/objc/ObjcRuleClasses.java @@ -213,20 +213,33 @@ public class ObjcRuleClasses { */ static SpawnAction.Builder spawnAppleEnvActionBuilder(AppleConfiguration appleConfiguration, Platform targetPlatform) { - ImmutableMap.Builder<String, String> envBuilder = ImmutableMap.<String, String>builder() - .putAll(appleConfiguration.getTargetAppleEnvironment(targetPlatform)) - .putAll(appleConfiguration.getAppleHostSystemEnv()); - return spawnOnDarwinActionBuilder() - .setEnvironment(envBuilder.build()); + .setEnvironment(appleToolchainEnvironment(appleConfiguration, targetPlatform)); + } + + /** + * Returns apple environment variables that are typically needed by the apple toolchain. + */ + static ImmutableMap<String, String> appleToolchainEnvironment( + AppleConfiguration appleConfiguration, Platform targetPlatform) { + return ImmutableMap.<String, String>builder() + .putAll(appleConfiguration.getTargetAppleEnvironment(targetPlatform)) + .putAll(appleConfiguration.getAppleHostSystemEnv()) + .build(); } /** * Creates a new spawn action builder that requires a darwin architecture to run. */ static SpawnAction.Builder spawnOnDarwinActionBuilder() { - return new SpawnAction.Builder() - .setExecutionInfo(ImmutableMap.of(ExecutionRequirements.REQUIRES_DARWIN, "")); + return new SpawnAction.Builder().setExecutionInfo(darwinActionExecutionRequirement()); + } + + /** + * Returns action requirement information for darwin architecture. + */ + static ImmutableMap<String, String> darwinActionExecutionRequirement() { + return ImmutableMap.of(ExecutionRequirements.REQUIRES_DARWIN, ""); } /** |