blob: 4c2ff26a83d917a73242c038b37403c0d54286a3 [file] [log] [blame]
/*
* Copyright 2013-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.java.AccumulateClassNames;
import com.facebook.buck.java.Classpaths;
import com.facebook.buck.java.JavaLibraryRule;
import com.facebook.buck.model.BuildTarget;
import com.facebook.buck.model.BuildTargetPattern;
import com.facebook.buck.rules.AbstractBuildRuleBuilderParams;
import com.facebook.buck.rules.BuildRule;
import com.facebook.buck.rules.BuildRuleResolver;
import com.facebook.buck.rules.DefaultBuildRuleBuilderParams;
import com.facebook.buck.rules.RuleKeyBuilderFactory;
import com.google.common.base.Function;
import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.ImmutableSortedSet;
import java.nio.file.Path;
public class AndroidBinaryGraphEnhancer {
private final ImmutableSortedSet<BuildRule> originalDeps;
private final ImmutableSet<BuildTarget> buildRulesToExcludeFromDex;
private final AbstractBuildRuleBuilderParams buildRuleBuilderParams;
AndroidBinaryGraphEnhancer(
ImmutableSortedSet<BuildRule> originalDeps,
ImmutableSet<BuildTarget> buildRulesToExcludeFromDex,
Function<String, Path> pathRelativizer,
RuleKeyBuilderFactory ruleKeyBuilderFactory) {
this.originalDeps = Preconditions.checkNotNull(originalDeps);
this.buildRulesToExcludeFromDex = Preconditions.checkNotNull(buildRulesToExcludeFromDex);
this.buildRuleBuilderParams = new DefaultBuildRuleBuilderParams(
pathRelativizer, ruleKeyBuilderFactory);
}
/**
* Creates/finds the set of build rules that correspond to pre-dex'd artifacts that should be
* merged to create the final classes.dex for the APK.
* <p>
* This method may modify {@code ruleResolver}, inserting new rules into its index.
*/
ImmutableSet<IntermediateDexRule> createDepsForPreDexing(BuildRuleResolver ruleResolver) {
ImmutableSet.Builder<IntermediateDexRule> preDexDeps = ImmutableSet.builder();
ImmutableSet<JavaLibraryRule> transitiveJavaDeps = Classpaths
.getClasspathEntries(originalDeps).keySet();
for (JavaLibraryRule javaLibraryRule : transitiveJavaDeps) {
// If the rule has no output file (which happens when a java_library has no srcs or
// resources, but export_deps is true), then there will not be anything to dx.
if (javaLibraryRule.getPathToOutputFile() == null) {
continue;
}
// If the rule is in the no_dx list, then do not pre-dex it.
if (buildRulesToExcludeFromDex.contains(javaLibraryRule.getBuildTarget())) {
continue;
}
// See whether the corresponding IntermediateDexRule has already been added to the
// ruleResolver.
BuildTarget originalTarget = javaLibraryRule.getBuildTarget();
BuildTarget preDexTarget = createBuildTargetWithDexFlavor(originalTarget);
IntermediateDexRule preDexRule = (IntermediateDexRule) ruleResolver.get(preDexTarget);
if (preDexRule != null) {
preDexDeps.add(preDexRule);
continue;
}
// Create a rule to get the list of the classes in the JavaLibraryRule.
BuildTarget accumulateClassNamesBuildTarget = new BuildTarget(
originalTarget.getBaseName(), originalTarget.getShortName(), "class_names");
AccumulateClassNames.Builder accumulateClassNamesBuilder = AccumulateClassNames
.newAccumulateClassNamesBuilder(buildRuleBuilderParams)
.setBuildTarget(accumulateClassNamesBuildTarget)
.setJavaLibraryToDex(javaLibraryRule)
.addDep(originalTarget)
.addVisibilityPattern(BuildTargetPattern.MATCH_ALL);
BuildRule accumulateClassNamesRule = ruleResolver.buildAndAddToIndex(
accumulateClassNamesBuilder);
AccumulateClassNames accumulateClassNames =
(AccumulateClassNames) accumulateClassNamesRule.getBuildable();
// Create the IntermediateDexRule and add it to both the ruleResolver and preDexDeps.
IntermediateDexRule.Builder preDexBuilder = IntermediateDexRule
.newPreDexBuilder(buildRuleBuilderParams)
.setBuildTarget(preDexTarget)
.setAccumulateClassNamesDep(accumulateClassNames)
.addDep(accumulateClassNamesBuildTarget)
.addVisibilityPattern(BuildTargetPattern.MATCH_ALL);
IntermediateDexRule preDex = ruleResolver.buildAndAddToIndex(preDexBuilder);
preDexDeps.add(preDex);
}
return preDexDeps.build();
}
private static BuildTarget createBuildTargetWithDexFlavor(BuildTarget originalTarget) {
return new BuildTarget(originalTarget.getBaseName(),
originalTarget.getShortName(),
"dex");
}
}