Java tutorial
/* * Copyright 2014-present Facebook, Inc. * * 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.facebook.buck.apple; import com.facebook.buck.cxx.CxxDescriptionEnhancer; import com.facebook.buck.cxx.CxxPlatform; import com.facebook.buck.cxx.LinkerMapMode; import com.facebook.buck.cxx.StripStyle; import com.facebook.buck.model.BuildTarget; import com.facebook.buck.model.BuildTargets; import com.facebook.buck.model.Either; import com.facebook.buck.model.Flavor; import com.facebook.buck.model.FlavorDomain; import com.facebook.buck.model.Flavored; import com.facebook.buck.model.HasTests; import com.facebook.buck.model.ImmutableFlavor; import com.facebook.buck.parser.NoSuchBuildTargetException; import com.facebook.buck.rules.AbstractDescriptionArg; import com.facebook.buck.rules.BuildRuleParams; import com.facebook.buck.rules.BuildRuleResolver; import com.facebook.buck.rules.CellPathResolver; import com.facebook.buck.rules.Description; import com.facebook.buck.rules.Hint; import com.facebook.buck.rules.ImplicitDepsInferringDescription; import com.facebook.buck.rules.MetadataProvidingDescription; import com.facebook.buck.rules.SourcePath; import com.facebook.buck.rules.TargetGraph; import com.facebook.infer.annotation.SuppressFieldNotInitialized; import com.google.common.base.Predicates; import com.google.common.collect.FluentIterable; import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableSet; import com.google.common.collect.ImmutableSortedSet; import java.util.Optional; public class AppleBundleDescription implements Description<AppleBundleDescription.Arg>, Flavored, ImplicitDepsInferringDescription<AppleBundleDescription.Arg>, MetadataProvidingDescription<AppleBundleDescription.Arg> { public static final ImmutableSet<Flavor> SUPPORTED_LIBRARY_FLAVORS = ImmutableSet .of(CxxDescriptionEnhancer.STATIC_FLAVOR, CxxDescriptionEnhancer.SHARED_FLAVOR); public static final Flavor WATCH_OS_FLAVOR = ImmutableFlavor.of("watchos-armv7k"); public static final Flavor WATCH_SIMULATOR_FLAVOR = ImmutableFlavor.of("watchsimulator-i386"); private static final Flavor WATCH = ImmutableFlavor.of("watch"); private final AppleBinaryDescription appleBinaryDescription; private final AppleLibraryDescription appleLibraryDescription; private final FlavorDomain<CxxPlatform> cxxPlatformFlavorDomain; private final FlavorDomain<AppleCxxPlatform> appleCxxPlatformsFlavorDomain; private final CxxPlatform defaultCxxPlatform; private final CodeSignIdentityStore codeSignIdentityStore; private final ProvisioningProfileStore provisioningProfileStore; private final AppleConfig appleConfig; public AppleBundleDescription(AppleBinaryDescription appleBinaryDescription, AppleLibraryDescription appleLibraryDescription, FlavorDomain<CxxPlatform> cxxPlatformFlavorDomain, FlavorDomain<AppleCxxPlatform> appleCxxPlatformsFlavorDomain, CxxPlatform defaultCxxPlatform, CodeSignIdentityStore codeSignIdentityStore, ProvisioningProfileStore provisioningProfileStore, AppleConfig appleConfig) { this.appleBinaryDescription = appleBinaryDescription; this.appleLibraryDescription = appleLibraryDescription; this.cxxPlatformFlavorDomain = cxxPlatformFlavorDomain; this.appleCxxPlatformsFlavorDomain = appleCxxPlatformsFlavorDomain; this.defaultCxxPlatform = defaultCxxPlatform; this.codeSignIdentityStore = codeSignIdentityStore; this.provisioningProfileStore = provisioningProfileStore; this.appleConfig = appleConfig; } @Override public Arg createUnpopulatedConstructorArg() { return new Arg(); } @Override public Optional<ImmutableSet<FlavorDomain<?>>> flavorDomains() { ImmutableSet.Builder<FlavorDomain<?>> builder = ImmutableSet.builder(); ImmutableSet<FlavorDomain<?>> localDomains = ImmutableSet.of(AppleDebugFormat.FLAVOR_DOMAIN, AppleDescriptions.INCLUDE_FRAMEWORKS); builder.addAll(localDomains); appleLibraryDescription.flavorDomains().ifPresent(domains -> builder.addAll(domains)); appleBinaryDescription.flavorDomains().ifPresent(domains -> builder.addAll(domains)); return Optional.of(builder.build()); } @Override public boolean hasFlavors(final ImmutableSet<Flavor> flavors) { if (appleLibraryDescription.hasFlavors(flavors)) { return true; } ImmutableSet.Builder<Flavor> flavorBuilder = ImmutableSet.builder(); for (Flavor flavor : flavors) { if (AppleDebugFormat.FLAVOR_DOMAIN.getFlavors().contains(flavor)) { continue; } if (AppleDescriptions.INCLUDE_FRAMEWORKS.getFlavors().contains(flavor)) { continue; } flavorBuilder.add(flavor); } return appleBinaryDescription.hasFlavors(flavorBuilder.build()); } @Override public <A extends Arg> AppleBundle createBuildRule(TargetGraph targetGraph, BuildRuleParams params, BuildRuleResolver resolver, A args) throws NoSuchBuildTargetException { AppleDebugFormat flavoredDebugFormat = AppleDebugFormat.FLAVOR_DOMAIN.getValue(params.getBuildTarget()) .orElse(appleConfig.getDefaultDebugInfoFormatForBinaries()); if (!params.getBuildTarget().getFlavors().contains(flavoredDebugFormat.getFlavor())) { return (AppleBundle) resolver .requireRule(params.getBuildTarget().withAppendedFlavors(flavoredDebugFormat.getFlavor())); } if (!AppleDescriptions.INCLUDE_FRAMEWORKS.getValue(params.getBuildTarget()).isPresent()) { return (AppleBundle) resolver.requireRule( params.getBuildTarget().withAppendedFlavors(AppleDescriptions.NO_INCLUDE_FRAMEWORKS_FLAVOR)); } return AppleDescriptions.createAppleBundle(cxxPlatformFlavorDomain, defaultCxxPlatform, appleCxxPlatformsFlavorDomain, targetGraph, params, resolver, codeSignIdentityStore, provisioningProfileStore, args.binary, args.extension, args.productName, args.infoPlist, args.infoPlistSubstitutions, args.deps, args.tests, flavoredDebugFormat, appleConfig.useDryRunCodeSigning(), appleConfig.cacheBundlesAndPackages()); } /** * Propagate the bundle's platform, debug symbol and strip flavors to its dependents * which are other bundles (e.g. extensions) */ @Override public ImmutableSet<BuildTarget> findDepsForTargetFromConstructorArgs(BuildTarget buildTarget, CellPathResolver cellRoots, AppleBundleDescription.Arg constructorArg) { if (!cxxPlatformFlavorDomain.containsAnyOf(buildTarget.getFlavors())) { buildTarget = BuildTarget.builder(buildTarget) .addAllFlavors(ImmutableSet.of(defaultCxxPlatform.getFlavor())).build(); } Optional<MultiarchFileInfo> fatBinaryInfo = MultiarchFileInfos.create(appleCxxPlatformsFlavorDomain, buildTarget); CxxPlatform cxxPlatform; if (fatBinaryInfo.isPresent()) { AppleCxxPlatform appleCxxPlatform = fatBinaryInfo.get().getRepresentativePlatform(); cxxPlatform = appleCxxPlatform.getCxxPlatform(); } else { cxxPlatform = ApplePlatforms.getCxxPlatformForBuildTarget(cxxPlatformFlavorDomain, defaultCxxPlatform, buildTarget); } String platformName = cxxPlatform.getFlavor().getName(); final Flavor actualWatchFlavor; if (ApplePlatform.isSimulator(platformName)) { actualWatchFlavor = WATCH_SIMULATOR_FLAVOR; } else if (platformName.startsWith(ApplePlatform.IPHONEOS.getName()) || platformName.startsWith(ApplePlatform.WATCHOS.getName())) { actualWatchFlavor = WATCH_OS_FLAVOR; } else { actualWatchFlavor = ImmutableFlavor.of(platformName); } FluentIterable<BuildTarget> depsExcludingBinary = FluentIterable.from(constructorArg.deps) .filter(Predicates.not(constructorArg.binary::equals)); // Propagate platform flavors. Need special handling for watch to map the pseudo-flavor // watch to the actual watch platform (simulator or device) so can't use // BuildTargets.propagateFlavorsInDomainIfNotPresent() { FluentIterable<BuildTarget> targetsWithPlatformFlavors = depsExcludingBinary .filter(BuildTargets.containsFlavors(cxxPlatformFlavorDomain)); FluentIterable<BuildTarget> targetsWithoutPlatformFlavors = depsExcludingBinary .filter(Predicates.not(BuildTargets.containsFlavors(cxxPlatformFlavorDomain))); FluentIterable<BuildTarget> watchTargets = targetsWithoutPlatformFlavors .filter(BuildTargets.containsFlavor(WATCH)).transform(input -> BuildTarget .builder(input.withoutFlavors(WATCH)).addFlavors(actualWatchFlavor).build()); targetsWithoutPlatformFlavors = targetsWithoutPlatformFlavors .filter(Predicates.not(BuildTargets.containsFlavor(WATCH))); // Gather all the deps now that we've added platform flavors to everything. depsExcludingBinary = targetsWithPlatformFlavors.append(watchTargets) .append(BuildTargets.propagateFlavorDomains(buildTarget, ImmutableSet.of(cxxPlatformFlavorDomain), targetsWithoutPlatformFlavors)); } // Propagate some flavors depsExcludingBinary = BuildTargets.propagateFlavorsInDomainIfNotPresent(StripStyle.FLAVOR_DOMAIN, buildTarget, depsExcludingBinary); depsExcludingBinary = BuildTargets.propagateFlavorsInDomainIfNotPresent(AppleDebugFormat.FLAVOR_DOMAIN, buildTarget, depsExcludingBinary); depsExcludingBinary = BuildTargets.propagateFlavorsInDomainIfNotPresent(LinkerMapMode.FLAVOR_DOMAIN, buildTarget, depsExcludingBinary); return ImmutableSet.copyOf(depsExcludingBinary); } @Override public <A extends Arg, U> Optional<U> createMetadata(BuildTarget buildTarget, BuildRuleResolver resolver, A args, Class<U> metadataClass) throws NoSuchBuildTargetException { return resolver.requireMetadata(args.binary, metadataClass); } @SuppressFieldNotInitialized public static class Arg extends AbstractDescriptionArg implements HasAppleBundleFields, HasTests { public Either<AppleBundleExtension, String> extension; public BuildTarget binary; public SourcePath infoPlist; public ImmutableMap<String, String> infoPlistSubstitutions = ImmutableMap.of(); @Hint(isDep = false) public ImmutableSortedSet<BuildTarget> deps = ImmutableSortedSet.of(); @Hint(isDep = false) public ImmutableSortedSet<BuildTarget> tests = ImmutableSortedSet.of(); public Optional<String> xcodeProductType; public Optional<String> productName; @Override public Either<AppleBundleExtension, String> getExtension() { return extension; } @Override public SourcePath getInfoPlist() { return infoPlist; } @Override public ImmutableSortedSet<BuildTarget> getTests() { return tests; } @Override public Optional<String> getXcodeProductType() { return xcodeProductType; } @Override public Optional<String> getProductName() { return productName; } } }