diff options
author | Googler <noreply@google.com> | 2015-05-12 20:29:32 +0000 |
---|---|---|
committer | Damien Martin-Guillerez <dmarting@google.com> | 2015-05-15 09:40:06 +0000 |
commit | 71d843f41b0e968dca1d2b2b192265505a3eb7b1 (patch) | |
tree | 9d076e3924f1dfe57c5d9fff8b3b4a77bc198169 /src | |
parent | 5e14a92104c8862849d26badc764b5ea2b8f01bb (diff) |
Add a genrule that generates a dummy J2ObjC dead code removal script in tools/objc/BUILD.
--
MOS_MIGRATED_REVID=93447039
Diffstat (limited to 'src')
16 files changed, 265 insertions, 34 deletions
diff --git a/src/main/java/com/google/devtools/build/lib/rules/objc/BinaryLinkingTargetFactory.java b/src/main/java/com/google/devtools/build/lib/rules/objc/BinaryLinkingTargetFactory.java index fde2683978..e822a0f3fc 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/objc/BinaryLinkingTargetFactory.java +++ b/src/main/java/com/google/devtools/build/lib/rules/objc/BinaryLinkingTargetFactory.java @@ -145,7 +145,8 @@ abstract class BinaryLinkingTargetFactory implements RuleConfiguredTargetFactory Optional.of(xcodeProvider), Optional.of(objcProvider), xcTestAppProvider, - Optional.<J2ObjcSrcsProvider>absent()); + Optional.<J2ObjcSrcsProvider>absent(), + Optional.<J2ObjcMappingFileProvider>absent()); for (RunfilesSupport runfilesSupport : maybeRunfilesSupport.asSet()) { target.setRunfilesSupport(runfilesSupport, runfilesSupport.getExecutable()); } 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 132cf86c4c..ed6edea8ab 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 @@ -14,6 +14,7 @@ package com.google.devtools.build.lib.rules.objc; +import static com.google.devtools.build.lib.rules.objc.J2ObjcSource.SourceType; import static com.google.devtools.build.lib.rules.objc.ObjcProvider.DEFINE; import static com.google.devtools.build.lib.rules.objc.ObjcProvider.FORCE_LOAD_LIBRARY; import static com.google.devtools.build.lib.rules.objc.ObjcProvider.FRAMEWORK_DIR; @@ -48,6 +49,7 @@ 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.SpawnAction; +import com.google.devtools.build.lib.collect.nestedset.NestedSet; import com.google.devtools.build.lib.rules.objc.ObjcCommon.CompilationAttributes; import com.google.devtools.build.lib.rules.objc.XcodeProvider.Builder; import com.google.devtools.build.lib.shell.ShellUtils; @@ -410,11 +412,28 @@ final class CompilationSupport { */ CompilationSupport registerJ2ObjcCompileAndArchiveActions( OptionsProvider optionsProvider, ObjcProvider objcProvider) { - for (J2ObjcSource j2ObjcSource : ObjcRuleClasses.j2ObjcSrcsProvider(ruleContext).getSrcs()) { + J2ObjcSrcsProvider provider = ObjcRuleClasses.j2ObjcSrcsProvider(ruleContext); + Iterable<J2ObjcSource> j2ObjcSources = provider.getSrcs(); + J2ObjcConfiguration j2objcConfiguration = ruleContext.getFragment(J2ObjcConfiguration.class); + + // Only perform J2ObjC dead code stripping if flag --j2objc_dead_code_removal is specified and + // users have specified entry classes. + boolean stripJ2ObjcDeadCode = j2objcConfiguration.removeDeadCode() + && !provider.getEntryClasses().isEmpty(); + + if (stripJ2ObjcDeadCode) { + registerJ2ObjcDeadCodeRemovalActions(j2ObjcSources, provider.getEntryClasses()); + } + + for (J2ObjcSource j2ObjcSource : j2ObjcSources) { + J2ObjcSource sourceToCompile = + j2ObjcSource.getSourceType() == SourceType.JAVA && stripJ2ObjcDeadCode + ? j2ObjcSource.toPrunedSource(ruleContext) + : j2ObjcSource; IntermediateArtifacts intermediateArtifacts = - ObjcRuleClasses.j2objcIntermediateArtifacts(ruleContext, j2ObjcSource); + ObjcRuleClasses.j2objcIntermediateArtifacts(ruleContext, sourceToCompile); CompilationArtifacts compilationArtifact = new CompilationArtifacts.Builder() - .addNonArcSrcs(j2ObjcSource.getObjcSrcs()) + .addNonArcSrcs(sourceToCompile.getObjcSrcs()) .setIntermediateArtifacts(intermediateArtifacts) .setPchFile(Optional.<Artifact>absent()) .build(); @@ -425,6 +444,40 @@ final class CompilationSupport { return this; } + private void registerJ2ObjcDeadCodeRemovalActions(Iterable<J2ObjcSource> j2ObjcSources, + Iterable<String> entryClasses) { + Artifact pruner = ruleContext.getPrerequisiteArtifact("$j2objc_dead_code_pruner", Mode.HOST); + J2ObjcMappingFileProvider provider = ObjcRuleClasses.j2ObjcMappingFileProvider(ruleContext); + NestedSet<Artifact> j2ObjcDependencyMappingFiles = provider.getDependencyMappingFiles(); + NestedSet<Artifact> j2ObjcHeaderMappingFiles = provider.getHeaderMappingFiles(); + + for (J2ObjcSource j2ObjcSource : j2ObjcSources) { + if (j2ObjcSource.getSourceType() == SourceType.JAVA) { + Iterable<Artifact> sourceArtifacts = j2ObjcSource.getObjcSrcs(); + Iterable<Artifact> prunedSourceArtifacts = + j2ObjcSource.toPrunedSource(ruleContext).getObjcSrcs(); + PathFragment objcFilePath = j2ObjcSource.getObjcFilePath(); + ruleContext.registerAction(new SpawnAction.Builder() + .setMnemonic("DummyPruner") + .setExecutable(pruner) + .addInput(pruner) + .addInputs(sourceArtifacts) + .addTransitiveInputs(j2ObjcDependencyMappingFiles) + .addTransitiveInputs(j2ObjcHeaderMappingFiles) + .setCommandLine(CustomCommandLine.builder() + .addJoinExecPaths("--input_files", ",", sourceArtifacts) + .addJoinExecPaths("--output_files", ",", prunedSourceArtifacts) + .addJoinExecPaths("--dependency_mapping_files", ",", j2ObjcDependencyMappingFiles) + .addJoinExecPaths("--header_mapping_files", ",", j2ObjcHeaderMappingFiles) + .add("--entry_classes").add(Joiner.on(",").join(entryClasses)) + .add("--objc_file_path").add(objcFilePath.getPathString()) + .build()) + .addOutputs(prunedSourceArtifacts) + .build(ruleContext)); + } + } + } + /** * Sets compilation-related Xcode project information on the given provider builder. * 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 d6d9cad47f..7d1f88b4d4 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 @@ -35,6 +35,14 @@ public class J2ObjcCommandLineOptions extends FragmentOptions { ) public List<String> translationFlags; + @Option(name = "j2objc_dead_code_removal", + defaultValue = "false", + category = "undocumented", + help = "Whether to perform J2ObjC dead code removal to strip unused code from the final app " + + "bundle." + ) + public boolean removeDeadCode; + @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 35b24d1ce9..116030b2ab 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 @@ -20,7 +20,8 @@ import com.google.devtools.build.lib.analysis.config.BuildConfiguration.Fragment import com.google.devtools.build.lib.analysis.config.BuildOptions; import com.google.devtools.build.lib.analysis.config.ConfigurationEnvironment; import com.google.devtools.build.lib.analysis.config.ConfigurationFragmentFactory; -import com.google.devtools.build.lib.analysis.config.InvalidConfigurationException; +import com.google.devtools.build.lib.events.Event; +import com.google.devtools.build.lib.events.EventHandler; import java.util.Collections; import java.util.Set; @@ -56,8 +57,7 @@ public class J2ObjcConfiguration extends Fragment { */ public static class Loader implements ConfigurationFragmentFactory { @Override - public Fragment create(ConfigurationEnvironment env, BuildOptions buildOptions) - throws InvalidConfigurationException { + public Fragment create(ConfigurationEnvironment env, BuildOptions buildOptions) { return new J2ObjcConfiguration(buildOptions.get(J2ObjcCommandLineOptions.class)); } @@ -67,23 +67,15 @@ public class J2ObjcConfiguration extends Fragment { } } - private Iterable<String> translationFlags; - private String cacheKey; + private final Set<String> translationFlags; + private final boolean removeDeadCode; - J2ObjcConfiguration(J2ObjcCommandLineOptions j2ObjcOptions) throws InvalidConfigurationException { - Set<String> translationFlags = ImmutableSet.<String>builder() + J2ObjcConfiguration(J2ObjcCommandLineOptions j2ObjcOptions) { + this.removeDeadCode = j2ObjcOptions.removeDeadCode; + this.translationFlags = ImmutableSet.<String>builder() .addAll(j2ObjcOptions.translationFlags) .addAll(J2OBJC_ALWAYS_ON_TRANSLATION_FLAGS) .build(); - - if (Collections.disjoint(translationFlags, J2OBJC_BLACKLISTED_TRANSLATION_FLAGS)) { - this.translationFlags = translationFlags; - this.cacheKey = Joiner.on(" ").join(this.translationFlags); - } else { - throw new InvalidConfigurationException(String.format(INVALID_TRANSLATION_FLAGS_MSG_TEMPLATE, - Joiner.on(",").join(translationFlags), - Joiner.on(",").join(J2OBJC_BLACKLISTED_TRANSLATION_FLAGS))); - } } /** @@ -96,6 +88,16 @@ public class J2ObjcConfiguration extends Fragment { return translationFlags; } + /** + * Returns whether to perform J2ObjC dead code removal. If true, the list of entry classes will be + * collected transitively throuh "entry_classes" attribute on j2objc_library and used as entry + * points to perform dead code analysis. Unused classes will then be removed from the final ObjC + * app bundle. + */ + public boolean removeDeadCode() { + return removeDeadCode; + } + @Override public String getName() { return "J2ObjC"; @@ -103,6 +105,16 @@ public class J2ObjcConfiguration extends Fragment { @Override public String cacheKey() { - return cacheKey; + return Joiner.on(" ").join(translationFlags) + "-" + String.valueOf(removeDeadCode); + } + + @Override + public void reportInvalidOptions(EventHandler reporter, BuildOptions buildOptions) { + if (!Collections.disjoint(translationFlags, J2OBJC_BLACKLISTED_TRANSLATION_FLAGS)) { + String errorMsg = String.format(INVALID_TRANSLATION_FLAGS_MSG_TEMPLATE, + Joiner.on(",").join(translationFlags), + Joiner.on(",").join(J2OBJC_BLACKLISTED_TRANSLATION_FLAGS)); + reporter.handle(Event.error(errorMsg)); + } } } diff --git a/src/main/java/com/google/devtools/build/lib/rules/objc/J2ObjcMappingFileProvider.java b/src/main/java/com/google/devtools/build/lib/rules/objc/J2ObjcMappingFileProvider.java index 7ee799e3df..4714ca2d24 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/objc/J2ObjcMappingFileProvider.java +++ b/src/main/java/com/google/devtools/build/lib/rules/objc/J2ObjcMappingFileProvider.java @@ -17,6 +17,7 @@ package com.google.devtools.build.lib.rules.objc; import com.google.devtools.build.lib.actions.Artifact; import com.google.devtools.build.lib.analysis.TransitiveInfoProvider; import com.google.devtools.build.lib.collect.nestedset.NestedSet; +import com.google.devtools.build.lib.collect.nestedset.NestedSetBuilder; import com.google.devtools.build.lib.concurrent.ThreadSafety.Immutable; /** @@ -28,11 +29,26 @@ public final class J2ObjcMappingFileProvider implements TransitiveInfoProvider { private final NestedSet<Artifact> headerMappingFiles; private final NestedSet<Artifact> classMappingFiles; + private final NestedSet<Artifact> dependencyMappingFiles; + /** + * Constructs a {@link J2ObjcMappingFileProvider} with mapping files to export mappings required + * by J2ObjC translation and proto compilation. + * + * @param headerMappingFiles a nested set of header mapping files which map Java classes to + * their associated translated ObjC header. Used by J2ObjC to output correct import directives + * during translation. + * @param classMappingFiles a nested set of class mapping files which map Java class names to + * their associated ObjC class names. Used to support J2ObjC package prefixes. + * @param dependencyMappingFiles a nested set of dependency mapping files which map translated + * ObjC files to their translated direct dependency files. Used to support J2ObjC dead code + * analysis and removal. + */ public J2ObjcMappingFileProvider(NestedSet<Artifact> headerMappingFiles, - NestedSet<Artifact> classMappingFiles) { + NestedSet<Artifact> classMappingFiles, NestedSet<Artifact> dependencyMappingFiles) { this.headerMappingFiles = headerMappingFiles; this.classMappingFiles = classMappingFiles; + this.dependencyMappingFiles = dependencyMappingFiles; } /** @@ -52,4 +68,36 @@ public final class J2ObjcMappingFileProvider implements TransitiveInfoProvider { public NestedSet<Artifact> getClassMappingFiles() { return classMappingFiles; } + + /** + * Returns the mapping files containing file dependency information among the translated ObjC + * source files. They are used to strip unused translated files before the compilation and linking + * actions at binary level. + */ + public NestedSet<Artifact> getDependencyMappingFiles() { + return dependencyMappingFiles; + } + + /** + * A builder for this provider that is optimized for collection information from transitive + * dependencies. + */ + public static final class Builder { + private final NestedSetBuilder<Artifact> headerMappingFiles = NestedSetBuilder.stableOrder(); + private final NestedSetBuilder<Artifact> classMappingFiles = NestedSetBuilder.stableOrder(); + private final NestedSetBuilder<Artifact> depEntryFiles = NestedSetBuilder.stableOrder(); + + public Builder addTransitive(J2ObjcMappingFileProvider provider) { + headerMappingFiles.addTransitive(provider.getHeaderMappingFiles()); + classMappingFiles.addTransitive(provider.getClassMappingFiles()); + depEntryFiles.addTransitive(provider.getDependencyMappingFiles()); + + return this; + } + + public J2ObjcMappingFileProvider build() { + return new J2ObjcMappingFileProvider( + headerMappingFiles.build(), classMappingFiles.build(), depEntryFiles.build()); + } + } } diff --git a/src/main/java/com/google/devtools/build/lib/rules/objc/J2ObjcSource.java b/src/main/java/com/google/devtools/build/lib/rules/objc/J2ObjcSource.java index 81ba292314..dc7251ee3a 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/objc/J2ObjcSource.java +++ b/src/main/java/com/google/devtools/build/lib/rules/objc/J2ObjcSource.java @@ -15,9 +15,13 @@ package com.google.devtools.build.lib.rules.objc; import com.google.common.base.Objects; +import com.google.common.collect.ImmutableList; import com.google.common.collect.Iterators; import com.google.devtools.build.lib.actions.Artifact; +import com.google.devtools.build.lib.analysis.AnalysisUtils; +import com.google.devtools.build.lib.analysis.RuleContext; import com.google.devtools.build.lib.syntax.Label; +import com.google.devtools.build.lib.vfs.FileSystemUtils; import com.google.devtools.build.lib.vfs.PathFragment; /** @@ -67,6 +71,41 @@ public class J2ObjcSource { } /** + * Returns a corresponding {@link J2ObjcSource} with source artifacts replaced by the outputs of + * the J2objC dead code removal script, for use after that action has processed the originals. + * + * <p>The script in question builds a dependency graph with entry classes specified + * transitively on j2objc_library rules as roots. Translated files from this (original) + * {@link J2ObjcSource} which are reachable in the graph from the roots will be copied over to the + * source file paths in the returned pruned {@link J2ObjcSource} with full original contents. + * Unreachable files will not be copied over and the artifacts pointed to by the returned pruned + * {@link J2ObjcSource} will only contain empty files. + * + * @param ruleContext the {@link RuleContext} of the current rule + */ + public J2ObjcSource toPrunedSource(RuleContext ruleContext) { + ImmutableList.Builder<Artifact> prunedSourceArtifacts = ImmutableList.builder(); + + for (Artifact sourceArtifact : getObjcSrcs()) { + PathFragment scopedPath = AnalysisUtils.getUniqueDirectory( + ruleContext.getRule().getLabel(), new PathFragment("_j2objc_pruned")); + PathFragment prunedSourceArtifactPath = FileSystemUtils.appendWithoutExtension( + scopedPath.getRelative(sourceArtifact.getRootRelativePath()), "_pruned"); + + Artifact prunedArtifact = ruleContext.getAnalysisEnvironment().getDerivedArtifact( + prunedSourceArtifactPath, ruleContext.getBinOrGenfilesDirectory()); + prunedSourceArtifacts.add(prunedArtifact); + } + + return new J2ObjcSource( + getTargetLabel(), + prunedSourceArtifacts.build(), + getObjcHdrs(), + getObjcFilePath(), + getSourceType()); + } + + /** * Returns the label of the associated target. */ public Label getTargetLabel() { diff --git a/src/main/java/com/google/devtools/build/lib/rules/objc/J2ObjcSrcsProvider.java b/src/main/java/com/google/devtools/build/lib/rules/objc/J2ObjcSrcsProvider.java index 1e577c5939..4a887ba492 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/objc/J2ObjcSrcsProvider.java +++ b/src/main/java/com/google/devtools/build/lib/rules/objc/J2ObjcSrcsProvider.java @@ -14,10 +14,13 @@ package com.google.devtools.build.lib.rules.objc; +import com.google.common.collect.ImmutableSet; import com.google.devtools.build.lib.analysis.TransitiveInfoProvider; import com.google.devtools.build.lib.collect.nestedset.NestedSet; import com.google.devtools.build.lib.concurrent.ThreadSafety.Immutable; +import java.util.Set; + /** * This provider is exported by java_library rules to supply J2ObjC-translated ObjC sources to * objc_binary for compilation and linking. @@ -25,10 +28,23 @@ import com.google.devtools.build.lib.concurrent.ThreadSafety.Immutable; @Immutable public final class J2ObjcSrcsProvider implements TransitiveInfoProvider { private final NestedSet<J2ObjcSource> srcs; + private final ImmutableSet<String> entryClasses; private final boolean hasProtos; - public J2ObjcSrcsProvider(NestedSet<J2ObjcSource> srcs, boolean hasProtos) { + /** + * Constructs a {@link J2ObjcSrcsProvider} to supply J2ObjC-translated ObjC sources to + * objc_binary for compilation and linking. + * + * @param srcs a nested set of {@link J2ObjcSource}s containing translated source files + * @param entryClasses a set of names of Java classes to used as entry point for J2ObjC dead code + * analysis. The Java class names should be in canonical format as defined by the Java + * Language Specification. + * @param hasProtos whether the translated files in this provider have J2ObjC proto files + */ + public J2ObjcSrcsProvider(NestedSet<J2ObjcSource> srcs, ImmutableSet<String> entryClasses, + boolean hasProtos) { this.srcs = srcs; + this.entryClasses = entryClasses; this.hasProtos = hasProtos; } @@ -37,6 +53,14 @@ public final class J2ObjcSrcsProvider implements TransitiveInfoProvider { } /** + * Returns a set of entry classes specified on attribute entry_classes of j2objc_library targets + * transitively. + */ + public Set<String> getEntryClasses() { + return entryClasses; + } + + /** * Returns whether the translated source files in the provider has proto files. */ public boolean hasProtos() { diff --git a/src/main/java/com/google/devtools/build/lib/rules/objc/ObjcBundle.java b/src/main/java/com/google/devtools/build/lib/rules/objc/ObjcBundle.java index 6585cbaf73..7eb806c1a5 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/objc/ObjcBundle.java +++ b/src/main/java/com/google/devtools/build/lib/rules/objc/ObjcBundle.java @@ -46,6 +46,7 @@ public class ObjcBundle implements RuleConfiguredTargetFactory { Optional.<XcodeProvider>absent(), Optional.of(common.getObjcProvider()), Optional.<XcTestAppProvider>absent(), - Optional.<J2ObjcSrcsProvider>absent()); + Optional.<J2ObjcSrcsProvider>absent(), + Optional.<J2ObjcMappingFileProvider>absent()); } } diff --git a/src/main/java/com/google/devtools/build/lib/rules/objc/ObjcBundleLibrary.java b/src/main/java/com/google/devtools/build/lib/rules/objc/ObjcBundleLibrary.java index 4506e6e1ae..fcf9c315b4 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/objc/ObjcBundleLibrary.java +++ b/src/main/java/com/google/devtools/build/lib/rules/objc/ObjcBundleLibrary.java @@ -69,7 +69,8 @@ public class ObjcBundleLibrary implements RuleConfiguredTargetFactory { Optional.of(xcodeProviderBuilder.build()), Optional.of(nestedBundleProvider), Optional.<XcTestAppProvider>absent(), - Optional.<J2ObjcSrcsProvider>absent()); + Optional.<J2ObjcSrcsProvider>absent(), + Optional.<J2ObjcMappingFileProvider>absent()); } private OptionsProvider optionsProvider(RuleContext ruleContext) { diff --git a/src/main/java/com/google/devtools/build/lib/rules/objc/ObjcCommon.java b/src/main/java/com/google/devtools/build/lib/rules/objc/ObjcCommon.java index 775a211555..20806aff82 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/objc/ObjcCommon.java +++ b/src/main/java/com/google/devtools/build/lib/rules/objc/ObjcCommon.java @@ -589,7 +589,8 @@ public final class ObjcCommon { public RuleConfiguredTargetBuilder configuredTargetBuilder(NestedSet<Artifact> filesToBuild, Optional<XcodeProvider> maybeTargetProvider, Optional<ObjcProvider> maybeExportedProvider, Optional<XcTestAppProvider> maybeXcTestAppProvider, - Optional<J2ObjcSrcsProvider> maybeJ2ObjcSrcsProvider) { + Optional<J2ObjcSrcsProvider> maybeJ2ObjcSrcsProvider, + Optional<J2ObjcMappingFileProvider> maybeJ2ObjcMappingFileProvider) { NestedSet<Artifact> allFilesToBuild = NestedSetBuilder.<Artifact>stableOrder() .addTransitive(filesToBuild) .build(); @@ -615,6 +616,10 @@ public final class ObjcCommon { for (J2ObjcSrcsProvider j2ObjcSrcsProvider : maybeJ2ObjcSrcsProvider.asSet()) { target.addProvider(J2ObjcSrcsProvider.class, j2ObjcSrcsProvider); } + for (J2ObjcMappingFileProvider j2ObjcMappingFileProvider + : maybeJ2ObjcMappingFileProvider.asSet()) { + target.addProvider(J2ObjcMappingFileProvider.class, j2ObjcMappingFileProvider); + } return target; } @@ -632,8 +637,9 @@ public final class ObjcCommon { public ConfiguredTarget configuredTarget(NestedSet<Artifact> filesToBuild, Optional<XcodeProvider> maybeTargetProvider, Optional<ObjcProvider> maybeExportedProvider, Optional<XcTestAppProvider> maybeXcTestAppProvider, - Optional<J2ObjcSrcsProvider> maybeJ2ObjcSrcsProvider) { + Optional<J2ObjcSrcsProvider> maybeJ2ObjcSrcsProvider, + Optional<J2ObjcMappingFileProvider> maybeJ2ObjcMappingFileProvider) { return configuredTargetBuilder(filesToBuild, maybeTargetProvider, maybeExportedProvider, - maybeXcTestAppProvider, maybeJ2ObjcSrcsProvider).build(); + maybeXcTestAppProvider, maybeJ2ObjcSrcsProvider, maybeJ2ObjcMappingFileProvider).build(); } } diff --git a/src/main/java/com/google/devtools/build/lib/rules/objc/ObjcFramework.java b/src/main/java/com/google/devtools/build/lib/rules/objc/ObjcFramework.java index c6a003757e..5e670f6dd5 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/objc/ObjcFramework.java +++ b/src/main/java/com/google/devtools/build/lib/rules/objc/ObjcFramework.java @@ -55,6 +55,7 @@ public class ObjcFramework implements RuleConfiguredTargetFactory { Optional.<XcodeProvider>absent(), Optional.of(common.getObjcProvider()), Optional.<XcTestAppProvider>absent(), - Optional.<J2ObjcSrcsProvider>absent()); + Optional.<J2ObjcSrcsProvider>absent(), + Optional.<J2ObjcMappingFileProvider>absent()); } } diff --git a/src/main/java/com/google/devtools/build/lib/rules/objc/ObjcImport.java b/src/main/java/com/google/devtools/build/lib/rules/objc/ObjcImport.java index 6c4bf2290a..dc80de46d5 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/objc/ObjcImport.java +++ b/src/main/java/com/google/devtools/build/lib/rules/objc/ObjcImport.java @@ -66,6 +66,7 @@ public class ObjcImport implements RuleConfiguredTargetFactory { Optional.of(xcodeProviderBuilder.build()), Optional.of(common.getObjcProvider()), Optional.<XcTestAppProvider>absent(), - Optional.<J2ObjcSrcsProvider>absent()); + Optional.<J2ObjcSrcsProvider>absent(), + Optional.<J2ObjcMappingFileProvider>absent()); } } diff --git a/src/main/java/com/google/devtools/build/lib/rules/objc/ObjcLibrary.java b/src/main/java/com/google/devtools/build/lib/rules/objc/ObjcLibrary.java index 7d62173376..28c9314d55 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/objc/ObjcLibrary.java +++ b/src/main/java/com/google/devtools/build/lib/rules/objc/ObjcLibrary.java @@ -111,7 +111,8 @@ public class ObjcLibrary implements RuleConfiguredTargetFactory { Optional.of(xcodeProviderBuilder.build()), Optional.of(common.getObjcProvider()), Optional.<XcTestAppProvider>absent(), - Optional.of(ObjcRuleClasses.j2ObjcSrcsProvider(ruleContext))); + Optional.of(ObjcRuleClasses.j2ObjcSrcsProvider(ruleContext)), + Optional.of(ObjcRuleClasses.j2ObjcMappingFileProvider(ruleContext))); } private OptionsProvider optionsProvider(RuleContext ruleContext) { diff --git a/src/main/java/com/google/devtools/build/lib/rules/objc/ObjcProtoLibrary.java b/src/main/java/com/google/devtools/build/lib/rules/objc/ObjcProtoLibrary.java index c11c7bb213..ae6464dd95 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/objc/ObjcProtoLibrary.java +++ b/src/main/java/com/google/devtools/build/lib/rules/objc/ObjcProtoLibrary.java @@ -215,7 +215,8 @@ public class ObjcProtoLibrary implements RuleConfiguredTargetFactory { Optional.of(xcodeProvider), Optional.of(common.getObjcProvider()), Optional.<XcTestAppProvider>absent(), - Optional.<J2ObjcSrcsProvider>absent()); + Optional.<J2ObjcSrcsProvider>absent(), + Optional.<J2ObjcMappingFileProvider>absent()); } private NestedSet<Artifact> maybeGetProtoSources(RuleContext ruleContext) { 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 e038039b73..024fbe1211 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 @@ -153,12 +153,14 @@ public class ObjcRuleClasses { builder.addAll(currentSource.asSet()); boolean hasProtos = currentSource.isPresent() && currentSource.get().getSourceType() == J2ObjcSource.SourceType.PROTO; + ImmutableSet.Builder<String> entryClasses = ImmutableSet.builder(); if (ruleContext.attributes().has("deps", Type.LABEL_LIST)) { for (J2ObjcSrcsProvider provider : ruleContext.getPrerequisites("deps", Mode.TARGET, J2ObjcSrcsProvider.class)) { builder.addTransitive(provider.getSrcs()); hasProtos |= provider.hasProtos(); + entryClasses.addAll(provider.getEntryClasses()); } } @@ -167,10 +169,35 @@ public class ObjcRuleClasses { ruleContext.getPrerequisites("exports", Mode.TARGET, J2ObjcSrcsProvider.class)) { builder.addTransitive(provider.getSrcs()); hasProtos |= provider.hasProtos(); + entryClasses.addAll(provider.getEntryClasses()); } } - return new J2ObjcSrcsProvider(builder.build(), hasProtos); + if (ruleContext.attributes().has("entry_classes", Type.STRING_LIST)) { + entryClasses.addAll(ruleContext.attributes().get("entry_classes", Type.STRING_LIST)); + } + + return new J2ObjcSrcsProvider(builder.build(), entryClasses.build(), hasProtos); + } + + + /** + * Returns a {@link J2ObjcMappingFileProvider} containing J2ObjC mapping files from rules + * that can be reached transitively through the "deps" attribute. + * + * @param ruleContext the rule context of the current rule + * @return a {@link J2ObjcMappingFileProvider} containing J2ObjC mapping files information from + * the transitive closure. + */ + public static J2ObjcMappingFileProvider j2ObjcMappingFileProvider(RuleContext ruleContext) { + J2ObjcMappingFileProvider.Builder builder = new J2ObjcMappingFileProvider.Builder(); + Iterable<J2ObjcMappingFileProvider> providers = + ruleContext.getPrerequisites("deps", Mode.TARGET, J2ObjcMappingFileProvider.class); + for (J2ObjcMappingFileProvider provider : providers) { + builder.addTransitive(provider); + } + + return builder.build(); } public static Artifact artifactByAppendingToBaseName(RuleContext context, String suffix) { @@ -669,6 +696,12 @@ public class ObjcRuleClasses { return configuration.getFragment(ObjcConfiguration.class).getDumpSymsLabel(); } })) + .add(attr("$j2objc_dead_code_pruner", LABEL) + .allowedFileTypes(FileType.of(".py")) + .cfg(HOST) + .exec() + .singleArtifact() + .value(env.getLabel("//tools/objc:j2objc_dead_code_pruner"))) .build(); } @Override diff --git a/src/main/java/com/google/devtools/build/lib/rules/objc/ReleaseBundlingTargetFactory.java b/src/main/java/com/google/devtools/build/lib/rules/objc/ReleaseBundlingTargetFactory.java index bdbad39901..b3e27c1363 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/objc/ReleaseBundlingTargetFactory.java +++ b/src/main/java/com/google/devtools/build/lib/rules/objc/ReleaseBundlingTargetFactory.java @@ -108,7 +108,8 @@ public abstract class ReleaseBundlingTargetFactory implements RuleConfiguredTarg Optional.of(xcodeProviderBuilder.build()), exposedObjcProvider, Optional.of(releaseBundlingSupport.xcTestAppProvider()), - Optional.<J2ObjcSrcsProvider>absent()); + Optional.<J2ObjcSrcsProvider>absent(), + Optional.<J2ObjcMappingFileProvider>absent()); configureTarget(target, ruleContext, releaseBundlingSupport); return target.build(); } |