/*
* 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.android;
import com.facebook.buck.jvm.java.CalculateAbiFromClasses;
import com.facebook.buck.jvm.java.HasJavaAbi;
import com.facebook.buck.jvm.java.JavaBuckConfig;
import com.facebook.buck.jvm.java.JavaLibraryRules;
import com.facebook.buck.jvm.java.JavacFactory;
import com.facebook.buck.jvm.java.JavacOptions;
import com.facebook.buck.jvm.java.JavacToJarStepFactory;
import com.facebook.buck.jvm.java.PrebuiltJar;
import com.facebook.buck.model.BuildTargets;
import com.facebook.buck.model.Flavor;
import com.facebook.buck.model.Flavored;
import com.facebook.buck.model.InternalFlavor;
import com.facebook.buck.parser.NoSuchBuildTargetException;
import com.facebook.buck.rules.BuildRule;
import com.facebook.buck.rules.BuildRuleParams;
import com.facebook.buck.rules.BuildRuleResolver;
import com.facebook.buck.rules.CellPathResolver;
import com.facebook.buck.rules.CommonDescriptionArg;
import com.facebook.buck.rules.Description;
import com.facebook.buck.rules.ExplicitBuildTargetSourcePath;
import com.facebook.buck.rules.HasDeclaredDeps;
import com.facebook.buck.rules.SourcePath;
import com.facebook.buck.rules.SourcePathResolver;
import com.facebook.buck.rules.SourcePathRuleFinder;
import com.facebook.buck.rules.TargetGraph;
import com.facebook.buck.util.immutables.BuckStyleImmutable;
import com.google.common.base.Preconditions;
import com.google.common.base.Suppliers;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.ImmutableSortedSet;
import com.google.common.collect.Iterables;
import com.google.common.collect.Sets;
import java.util.Optional;
import org.immutables.value.Value;
/**
* Description for a {@link BuildRule} that wraps an {@code .aar} file as an Android dependency.
*
* <p>This represents an Android Library Project packaged as an {@code .aar} bundle as specified by:
* http://tools.android.com/tech-docs/new-build-system/aar-format. When it is in the packageable
* deps of an {@link AndroidBinary}, its contents will be included in the generated APK.
*
* <p>Note that the {@code aar} may be specified as a {@link SourcePath}, so it could be either a
* binary {@code .aar} file checked into version control, or a zip file that conforms to the {@code
* .aar} specification that is generated by another build rule.
*/
public class AndroidPrebuiltAarDescription
implements Description<AndroidPrebuiltAarDescriptionArg>, Flavored {
private static final Flavor AAR_PREBUILT_JAR_FLAVOR = InternalFlavor.of("aar_prebuilt_jar");
public static final Flavor AAR_UNZIP_FLAVOR = InternalFlavor.of("aar_unzip");
private static final ImmutableSet<Flavor> KNOWN_FLAVORS =
ImmutableSet.of(AAR_PREBUILT_JAR_FLAVOR, AAR_UNZIP_FLAVOR);
@Override
public boolean hasFlavors(ImmutableSet<Flavor> flavors) {
return Sets.difference(flavors, KNOWN_FLAVORS).isEmpty();
}
private final JavaBuckConfig javaBuckConfig;
private final JavacOptions javacOptions;
public AndroidPrebuiltAarDescription(JavaBuckConfig javaBuckConfig, JavacOptions javacOptions) {
this.javaBuckConfig = javaBuckConfig;
this.javacOptions = javacOptions;
}
@Override
public Class<AndroidPrebuiltAarDescriptionArg> getConstructorArgType() {
return AndroidPrebuiltAarDescriptionArg.class;
}
@Override
public BuildRule createBuildRule(
TargetGraph targetGraph,
BuildRuleParams params,
BuildRuleResolver buildRuleResolver,
CellPathResolver cellRoots,
AndroidPrebuiltAarDescriptionArg args)
throws NoSuchBuildTargetException {
SourcePathRuleFinder ruleFinder = new SourcePathRuleFinder(buildRuleResolver);
ImmutableSet<Flavor> flavors = params.getBuildTarget().getFlavors();
if (flavors.contains(AAR_UNZIP_FLAVOR)) {
Preconditions.checkState(flavors.size() == 1);
BuildRuleParams unzipAarParams =
params.copyReplacingDeclaredAndExtraDeps(
Suppliers.ofInstance(ImmutableSortedSet.of()),
Suppliers.ofInstance(
ImmutableSortedSet.copyOf(ruleFinder.filterBuildRuleInputs(args.getAar()))));
return new UnzipAar(unzipAarParams, args.getAar());
}
BuildRule unzipAarRule =
buildRuleResolver.requireRule(params.getBuildTarget().withFlavors(AAR_UNZIP_FLAVOR));
Preconditions.checkState(
unzipAarRule instanceof UnzipAar,
"aar_unzip flavor created rule of unexpected type %s for target %s",
unzipAarRule.getClass(),
params.getBuildTarget());
UnzipAar unzipAar = (UnzipAar) unzipAarRule;
if (HasJavaAbi.isClassAbiTarget(params.getBuildTarget())) {
return CalculateAbiFromClasses.of(
params.getBuildTarget(),
ruleFinder,
params,
new ExplicitBuildTargetSourcePath(
unzipAar.getBuildTarget(), unzipAar.getPathToClassesJar()));
}
SourcePathResolver pathResolver = new SourcePathResolver(ruleFinder);
Iterable<PrebuiltJar> javaDeps =
Iterables.concat(
Iterables.filter(buildRuleResolver.getAllRules(args.getDeps()), PrebuiltJar.class),
Iterables.transform(
Iterables.filter(
buildRuleResolver.getAllRules(args.getDeps()), AndroidPrebuiltAar.class),
AndroidPrebuiltAar::getPrebuiltJar));
if (flavors.contains(AAR_PREBUILT_JAR_FLAVOR)) {
Preconditions.checkState(
flavors.size() == 1,
"Expected only flavor to be %s but also found %s",
AAR_PREBUILT_JAR_FLAVOR,
flavors);
BuildRuleParams buildRuleParams =
params.copyReplacingDeclaredAndExtraDeps(
Suppliers.ofInstance(ImmutableSortedSet.copyOf(javaDeps)),
Suppliers.ofInstance(ImmutableSortedSet.of(unzipAar)));
return new PrebuiltJar(
/* params */ buildRuleParams,
/* resolver */ pathResolver,
/* binaryJar */ new ExplicitBuildTargetSourcePath(
unzipAar.getBuildTarget(), unzipAar.getPathToClassesJar()),
/* sourceJar */ Optional.empty(),
/* gwtJar */ Optional.empty(),
/* javadocUrl */ Optional.empty(),
/* mavenCoords */ Optional.empty(),
/* provided */ false);
}
if (flavors.contains(AndroidResourceDescription.AAPT2_COMPILE_FLAVOR)) {
return new Aapt2Compile(
params.copyAppendingExtraDeps(unzipAarRule), unzipAar.getResDirectory());
}
BuildRule prebuiltJarRule =
buildRuleResolver.requireRule(
BuildTargets.createFlavoredBuildTarget(
params.getBuildTarget().checkUnflavored(), AAR_PREBUILT_JAR_FLAVOR));
Preconditions.checkState(
prebuiltJarRule instanceof PrebuiltJar,
"%s flavor created rule of unexpected type %s for target %s",
AAR_PREBUILT_JAR_FLAVOR,
unzipAarRule.getType(),
params.getBuildTarget());
PrebuiltJar prebuiltJar = (PrebuiltJar) prebuiltJarRule;
Preconditions.checkArgument(
flavors.isEmpty(), "Unexpected flavors for android_prebuilt_aar: %s", flavors);
BuildRuleParams androidLibraryParams =
params.copyReplacingDeclaredAndExtraDeps(
/* declaredDeps */ Suppliers.ofInstance(ImmutableSortedSet.of(prebuiltJar)),
/* extraDeps */ Suppliers.ofInstance(ImmutableSortedSet.of(unzipAar)));
return new AndroidPrebuiltAar(
androidLibraryParams,
/* resolver */ pathResolver,
ruleFinder,
/* proguardConfig */ new ExplicitBuildTargetSourcePath(
unzipAar.getBuildTarget(), unzipAar.getProguardConfig()),
/* nativeLibsDirectory */ new ExplicitBuildTargetSourcePath(
unzipAar.getBuildTarget(), unzipAar.getNativeLibsDirectory()),
/* prebuiltJar */ prebuiltJar,
/* unzipRule */ unzipAar,
/* javacOptions */ javacOptions,
new JavacToJarStepFactory(
JavacFactory.create(ruleFinder, javaBuckConfig, null),
javacOptions,
new BootClasspathAppender()),
/* exportedDeps */ javaDeps,
JavaLibraryRules.getAbiSourcePaths(buildRuleResolver, androidLibraryParams.getBuildDeps()));
}
@BuckStyleImmutable
@Value.Immutable
interface AbstractAndroidPrebuiltAarDescriptionArg extends CommonDescriptionArg, HasDeclaredDeps {
SourcePath getAar();
Optional<SourcePath> getSourceJar();
Optional<String> getJavadocUrl();
}
}