Java tutorial
// Copyright 2016 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.base.Optional; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableListMultimap; import com.google.common.collect.ImmutableMap; import com.google.common.collect.Iterables; import com.google.devtools.build.lib.actions.Artifact; import com.google.devtools.build.lib.analysis.RuleConfiguredTarget.Mode; import com.google.devtools.build.lib.analysis.RuleContext; import com.google.devtools.build.lib.analysis.TransitiveInfoCollection; 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; import com.google.devtools.build.lib.packages.RuleClass.ConfiguredTargetFactory.RuleErrorException; import com.google.devtools.build.lib.rules.apple.Platform; import com.google.devtools.build.lib.rules.objc.CompilationSupport.ExtraLinkArgs; import com.google.devtools.build.lib.rules.objc.ObjcCommon.ResourceAttributes; import java.util.List; import java.util.Map; import java.util.Set; /** * Support utility for creating multi-arch Apple binaries. */ public class MultiArchBinarySupport { private final RuleContext ruleContext; /** * @param ruleContext the current rule context */ public MultiArchBinarySupport(RuleContext ruleContext) { this.ruleContext = ruleContext; } /** * Registers actions to create a multi-arch Apple binary. * * @param platform the platform for which the binary is targeted * @param extraLinkArgs the extra linker args to add to link actions linking single-architecture * binaries together * @param configurationToObjcProvider a map from from dependency configuration to the * {@link ObjcProvider} which comprises all information about the dependencies in that * configuration. Can be obtained via {@link #objcProviderByDepConfiguration} * @param extraLinkInputs the extra linker inputs to be made available during link actions * @param configToDepsCollectionMap a multimap from dependency configuration to the * list of provider collections which are propagated from the dependencies of that * configuration * @param outputLipoBinary the artifact (lipo'ed binary) which should be output as a result of * this support * @throws RuleErrorException if there are attribute errors in the current rule context */ public void registerActions(Platform platform, ExtraLinkArgs extraLinkArgs, Map<BuildConfiguration, ObjcProvider> configurationToObjcProvider, Iterable<Artifact> extraLinkInputs, ImmutableListMultimap<BuildConfiguration, TransitiveInfoCollection> configToDepsCollectionMap, Artifact outputLipoBinary) throws RuleErrorException, InterruptedException { NestedSetBuilder<Artifact> binariesToLipo = NestedSetBuilder.<Artifact>stableOrder(); for (BuildConfiguration childConfig : configurationToObjcProvider.keySet()) { IntermediateArtifacts intermediateArtifacts = ObjcRuleClasses.intermediateArtifacts(ruleContext, childConfig); ImmutableList.Builder<J2ObjcMappingFileProvider> j2ObjcMappingFileProviders = ImmutableList.builder(); J2ObjcEntryClassProvider.Builder j2ObjcEntryClassProviderBuilder = new J2ObjcEntryClassProvider.Builder(); for (TransitiveInfoCollection dep : configToDepsCollectionMap.get(childConfig)) { if (dep.getProvider(J2ObjcMappingFileProvider.class) != null) { j2ObjcMappingFileProviders.add(dep.getProvider(J2ObjcMappingFileProvider.class)); } if (dep.getProvider(J2ObjcEntryClassProvider.class) != null) { j2ObjcEntryClassProviderBuilder.addTransitive(dep.getProvider(J2ObjcEntryClassProvider.class)); } } J2ObjcMappingFileProvider j2ObjcMappingFileProvider = J2ObjcMappingFileProvider .union(j2ObjcMappingFileProviders.build()); J2ObjcEntryClassProvider j2ObjcEntryClassProvider = j2ObjcEntryClassProviderBuilder.build(); binariesToLipo.add(intermediateArtifacts.strippedSingleArchitectureBinary()); ObjcProvider objcProvider = configurationToObjcProvider.get(childConfig); CompilationArtifacts compilationArtifacts = CompilationSupport.compilationArtifacts(ruleContext, ObjcRuleClasses.intermediateArtifacts(ruleContext, childConfig)); CompilationSupport.createForConfig(ruleContext, childConfig) .registerCompileAndArchiveActions(compilationArtifacts, objcProvider) .registerLinkActions(objcProvider, j2ObjcMappingFileProvider, j2ObjcEntryClassProvider, extraLinkArgs, extraLinkInputs, DsymOutputType.APP) .validateAttributes(); ruleContext.assertNoErrors(); } new LipoSupport(ruleContext).registerCombineArchitecturesAction(binariesToLipo.build(), outputLipoBinary, platform); } /** * Returns a map from from dependency configuration to the {@link ObjcCommon} which comprises all * information about the dependencies in that configuration. This can be used both to register * actions in {@link #registerActions} and collect provider information to be propagated upstream. * * @param childConfigurations the set of configurations in which dependencies of the current rule * are built * @param configToDepsCollectionMap a map from child configuration to providers that "deps" of the * current rule have propagated in that configuration * @param configurationToNonPropagatedObjcMap a map from child configuration to providers that * "non_propagated_deps" of the current rule have propagated in that configuration * @param dylibObjcProviders {@link ObjcProvider}s that dynamic library dependencies of the * current rule have propagated * @param dylibProtoProviders {@link ObjcProtoProvider} providers that dynamic library * dependencies of the current rule have propagated * @param bundleLoaderObjcProvider Optional ObjcProvider containing artifacts and paths to be * included in this binary's compilation actions * @throws RuleErrorException if there are attribute errors in the current rule context */ public Map<BuildConfiguration, ObjcProvider> objcProviderByDepConfiguration( Set<BuildConfiguration> childConfigurations, ImmutableListMultimap<BuildConfiguration, TransitiveInfoCollection> configToDepsCollectionMap, ImmutableListMultimap<BuildConfiguration, ObjcProvider> configurationToNonPropagatedObjcMap, Iterable<ObjcProvider> dylibObjcProviders, Iterable<ObjcProtoProvider> dylibProtoProviders) throws RuleErrorException, InterruptedException { ImmutableMap.Builder<BuildConfiguration, ObjcProvider> configurationToObjcProviderBuilder = ImmutableMap .builder(); for (BuildConfiguration childConfig : childConfigurations) { Optional<ObjcProvider> protosObjcProvider; if (ObjcRuleClasses.objcConfiguration(ruleContext).enableAppleBinaryNativeProtos()) { ProtobufSupport protoSupport = new ProtobufSupport(ruleContext, childConfig, protoArtifactsToAvoid(dylibProtoProviders)).registerGenerationActions() .registerCompilationActions(); protosObjcProvider = protoSupport.getObjcProvider(); } else { protosObjcProvider = Optional.absent(); } IntermediateArtifacts intermediateArtifacts = ObjcRuleClasses.intermediateArtifacts(ruleContext, childConfig); Iterable<ObjcProvider> additionalDepProviders = Iterables.concat(dylibObjcProviders, ruleContext.getPrerequisites("bundles", Mode.TARGET, ObjcProvider.class), protosObjcProvider.asSet()); ObjcCommon common = common(ruleContext, childConfig, intermediateArtifacts, nullToEmptyList(configToDepsCollectionMap.get(childConfig)), nullToEmptyList(configurationToNonPropagatedObjcMap.get(childConfig)), additionalDepProviders); ObjcProvider objcProvider = common.getObjcProvider().subtractSubtrees(dylibObjcProviders); configurationToObjcProviderBuilder.put(childConfig, objcProvider); } return configurationToObjcProviderBuilder.build(); } private ObjcCommon common(RuleContext ruleContext, BuildConfiguration buildConfiguration, IntermediateArtifacts intermediateArtifacts, List<TransitiveInfoCollection> propagatedDeps, List<ObjcProvider> nonPropagatedObjcDeps, Iterable<ObjcProvider> additionalDepProviders) { CompilationArtifacts compilationArtifacts = CompilationSupport.compilationArtifacts(ruleContext, intermediateArtifacts); ObjcCommon.Builder commonBuilder = new ObjcCommon.Builder(ruleContext, buildConfiguration) .setCompilationAttributes(CompilationAttributes.Builder.fromRuleContext(ruleContext).build()) .setCompilationArtifacts(compilationArtifacts) .setResourceAttributes(new ResourceAttributes(ruleContext)) .addDefines(ruleContext.getTokenizedStringListAttr("defines")).addDeps(propagatedDeps) .addDepObjcProviders(additionalDepProviders).addNonPropagatedDepObjcProviders(nonPropagatedObjcDeps) .setIntermediateArtifacts(intermediateArtifacts).setAlwayslink(false) // TODO(b/29152500): Enable module map generation. .setLinkedBinary(intermediateArtifacts.strippedSingleArchitectureBinary()); if (ObjcRuleClasses.objcConfiguration(ruleContext).generateDsym()) { commonBuilder.addDebugArtifacts(DsymOutputType.APP); } return commonBuilder.build(); } private <T> List<T> nullToEmptyList(List<T> inputList) { return inputList != null ? inputList : ImmutableList.<T>of(); } private static NestedSet<Artifact> protoArtifactsToAvoid(Iterable<ObjcProtoProvider> avoidedProviders) { NestedSetBuilder<Artifact> avoidArtifacts = NestedSetBuilder.stableOrder(); for (ObjcProtoProvider avoidProvider : avoidedProviders) { for (NestedSet<Artifact> avoidProviderOutputGroup : avoidProvider.getProtoGroups()) { avoidArtifacts.addTransitive(avoidProviderOutputGroup); } } return avoidArtifacts.build(); } }