/*
* 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.JavaLibrary;
import com.facebook.buck.jvm.java.JavaLibraryDescription;
import com.facebook.buck.jvm.java.JavaSourceJar;
import com.facebook.buck.jvm.java.JavacFactory;
import com.facebook.buck.jvm.java.JavacOptions;
import com.facebook.buck.jvm.java.JavacOptionsFactory;
import com.facebook.buck.model.BuildTarget;
import com.facebook.buck.model.Flavor;
import com.facebook.buck.model.Flavored;
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.BuildRuleType;
import com.facebook.buck.rules.CellPathResolver;
import com.facebook.buck.rules.Description;
import com.facebook.buck.rules.ImplicitDepsInferringDescription;
import com.facebook.buck.rules.SourcePath;
import com.facebook.buck.rules.SourcePathRuleFinder;
import com.facebook.buck.rules.TargetGraph;
import com.facebook.buck.rules.query.Query;
import com.facebook.buck.rules.query.QueryUtils;
import com.facebook.buck.util.DependencyMode;
import com.facebook.buck.util.MoreCollectors;
import com.facebook.buck.util.RichStream;
import com.facebook.buck.util.immutables.BuckStyleImmutable;
import com.google.common.base.Preconditions;
import com.google.common.base.Supplier;
import com.google.common.base.Suppliers;
import com.google.common.collect.ImmutableCollection;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.ImmutableSortedSet;
import com.google.common.collect.Iterables;
import com.google.common.collect.Ordering;
import java.util.Optional;
import org.immutables.value.Value;
public class AndroidLibraryDescription
implements Description<AndroidLibraryDescriptionArg>,
Flavored,
ImplicitDepsInferringDescription<
AndroidLibraryDescription.AbstractAndroidLibraryDescriptionArg> {
public static final BuildRuleType TYPE = BuildRuleType.of("android_library");
private static final Flavor DUMMY_R_DOT_JAVA_FLAVOR =
AndroidLibraryGraphEnhancer.DUMMY_R_DOT_JAVA_FLAVOR;
public enum JvmLanguage {
JAVA,
KOTLIN,
SCALA,
}
private final JavaBuckConfig javaBuckConfig;
private final JavacOptions defaultOptions;
private final AndroidLibraryCompilerFactory compilerFactory;
public AndroidLibraryDescription(
JavaBuckConfig javaBuckConfig,
JavacOptions defaultOptions,
AndroidLibraryCompilerFactory compilerFactory) {
this.javaBuckConfig = javaBuckConfig;
this.defaultOptions = defaultOptions;
this.compilerFactory = compilerFactory;
}
@Override
public Class<AndroidLibraryDescriptionArg> getConstructorArgType() {
return AndroidLibraryDescriptionArg.class;
}
@Override
public BuildRule createBuildRule(
TargetGraph targetGraph,
BuildRuleParams params,
BuildRuleResolver resolver,
CellPathResolver cellRoots,
AndroidLibraryDescriptionArg args)
throws NoSuchBuildTargetException {
if (params.getBuildTarget().getFlavors().contains(JavaLibrary.SRC_JAR)) {
return new JavaSourceJar(params, args.getSrcs(), args.getMavenCoords());
}
SourcePathRuleFinder ruleFinder = new SourcePathRuleFinder(resolver);
boolean hasDummyRDotJavaFlavor =
params.getBuildTarget().getFlavors().contains(DUMMY_R_DOT_JAVA_FLAVOR);
if (HasJavaAbi.isClassAbiTarget(params.getBuildTarget())) {
Preconditions.checkArgument(!hasDummyRDotJavaFlavor);
BuildTarget libraryTarget = HasJavaAbi.getLibraryTarget(params.getBuildTarget());
BuildRule libraryRule = resolver.requireRule(libraryTarget);
return CalculateAbiFromClasses.of(
params.getBuildTarget(),
ruleFinder,
params,
Preconditions.checkNotNull(libraryRule.getSourcePathToOutput()));
}
JavacOptions javacOptions = JavacOptionsFactory.create(defaultOptions, params, resolver, args);
final Supplier<ImmutableList<BuildRule>> queriedDepsSupplier =
args.getDepsQuery().isPresent()
? Suppliers.memoize(
() ->
QueryUtils.resolveDepQuery(
params.getBuildTarget(),
args.getDepsQuery().get(),
resolver,
cellRoots,
targetGraph,
args.getDeps())
.collect(MoreCollectors.toImmutableList()))
: ImmutableList::of;
final Supplier<ImmutableList<BuildRule>> exportedDepsSupplier =
Suppliers.memoize(
() ->
resolver
.getAllRulesStream(args.getExportedDeps())
.collect(MoreCollectors.toImmutableList()));
AndroidLibraryGraphEnhancer graphEnhancer =
new AndroidLibraryGraphEnhancer(
params.getBuildTarget(),
params.copyReplacingExtraDeps(
() ->
ImmutableSortedSet.copyOf(
Iterables.concat(queriedDepsSupplier.get(), exportedDepsSupplier.get()))),
JavacFactory.create(ruleFinder, javaBuckConfig, args),
javacOptions,
DependencyMode.FIRST_ORDER,
/* forceFinalResourceIds */ false,
args.getResourceUnionPackage(),
args.getFinalRName(),
false);
Optional<DummyRDotJava> dummyRDotJava =
graphEnhancer.getBuildableForAndroidResources(
resolver, /* createBuildableIfEmpty */ hasDummyRDotJavaFlavor);
if (hasDummyRDotJavaFlavor) {
return dummyRDotJava.get();
} else {
ImmutableSortedSet<BuildRule> declaredDeps =
RichStream.fromSupplierOfIterable(params.getDeclaredDeps())
.concat(RichStream.from(dummyRDotJava))
.concat(RichStream.fromSupplierOfIterable(queriedDepsSupplier))
.toImmutableSortedSet(Ordering.natural());
BuildRuleParams androidLibraryParams =
params.copyReplacingDeclaredAndExtraDeps(
Suppliers.ofInstance(declaredDeps), params.getExtraDeps());
ImmutableSortedSet.Builder<BuildTarget> providedDepsTargetsBuilder =
ImmutableSortedSet.<BuildTarget>naturalOrder().addAll(args.getProvidedDeps());
if (args.getProvidedDepsQuery().isPresent()) {
QueryUtils.resolveDepQuery(
params.getBuildTarget(),
args.getProvidedDepsQuery().get(),
resolver,
cellRoots,
targetGraph,
args.getProvidedDeps())
.map(BuildRule::getBuildTarget)
.forEach(providedDepsTargetsBuilder::add);
}
return AndroidLibrary.builder(
androidLibraryParams, resolver, javaBuckConfig, javacOptions, args, compilerFactory)
.setArgs(args)
.setJavacOptions(javacOptions)
.setProvidedDeps(providedDepsTargetsBuilder.build())
.setTests(args.getTests())
.build();
}
}
@Override
public boolean hasFlavors(ImmutableSet<Flavor> flavors) {
return flavors.isEmpty()
|| flavors.equals(ImmutableSet.of(JavaLibrary.SRC_JAR))
|| flavors.equals(ImmutableSet.of(DUMMY_R_DOT_JAVA_FLAVOR));
}
@Override
public void findDepsForTargetFromConstructorArgs(
BuildTarget buildTarget,
CellPathResolver cellRoots,
AbstractAndroidLibraryDescriptionArg constructorArg,
ImmutableCollection.Builder<BuildTarget> extraDepsBuilder,
ImmutableCollection.Builder<BuildTarget> targetGraphOnlyDepsBuilder) {
compilerFactory
.getCompiler(constructorArg.getLanguage().orElse(JvmLanguage.JAVA))
.findDepsForTargetFromConstructorArgs(
buildTarget, cellRoots, constructorArg, extraDepsBuilder, targetGraphOnlyDepsBuilder);
}
public interface CoreArg extends JavaLibraryDescription.CoreArg {
Optional<SourcePath> getManifest();
Optional<String> getResourceUnionPackage();
Optional<String> getFinalRName();
Optional<JvmLanguage> getLanguage();
Optional<Query> getDepsQuery();
Optional<Query> getProvidedDepsQuery();
}
@BuckStyleImmutable
@Value.Immutable
interface AbstractAndroidLibraryDescriptionArg extends CoreArg {}
}