/*
* Copyright 2012-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 static com.facebook.buck.rules.BuildableProperties.Kind.ANDROID;
import com.facebook.buck.rules.AddToRuleKey;
import com.facebook.buck.rules.BuildRule;
import com.facebook.buck.rules.BuildRuleParams;
import com.facebook.buck.rules.BuildTargetSourcePath;
import com.facebook.buck.rules.BuildableProperties;
import com.facebook.buck.rules.SourcePath;
import com.facebook.buck.rules.SourcePathResolver;
import com.facebook.buck.rules.SourcePathRuleFinder;
import com.facebook.buck.rules.args.Arg;
import com.facebook.buck.shell.Genrule;
import com.facebook.buck.step.ExecutionContext;
import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableMap;
import java.util.List;
import java.util.Optional;
/**
* A specialization of a genrule that specifically allows the modification of apks. This is useful
* for processes that modify an APK, such as zipaligning it or signing it.
*
* <p>The generated APK will be at <code><em>rule_name</em>.apk</code>.
*
* <pre>
* apk_genrule(
* name = 'fb4a_signed',
* apk = ':fbandroid_release'
* deps = [
* '//java/com/facebook/sign:fbsign_jar',
* ],
* cmd = '${//java/com/facebook/sign:fbsign_jar} --input $APK --output $OUT'
* )
* </pre>
*/
public class ApkGenrule extends Genrule implements HasInstallableApk {
private static final BuildableProperties PROPERTIES = new BuildableProperties(ANDROID);
@AddToRuleKey private final BuildTargetSourcePath apk;
private final HasInstallableApk hasInstallableApk;
ApkGenrule(
BuildRuleParams params,
SourcePathRuleFinder ruleFinder,
List<SourcePath> srcs,
Optional<Arg> cmd,
Optional<Arg> bash,
Optional<Arg> cmdExe,
Optional<String> type,
SourcePath apk) {
super(
params,
srcs,
cmd,
bash,
cmdExe,
type,
/* out */ params.getBuildTarget().getShortNameAndFlavorPostfix() + ".apk");
Preconditions.checkState(apk instanceof BuildTargetSourcePath);
this.apk = (BuildTargetSourcePath) apk;
BuildRule rule = ruleFinder.getRuleOrThrow(this.apk);
Preconditions.checkState(rule instanceof HasInstallableApk);
this.hasInstallableApk = (HasInstallableApk) rule;
}
@Override
public BuildableProperties getProperties() {
return PROPERTIES;
}
public HasInstallableApk getInstallableApk() {
return hasInstallableApk;
}
@Override
public ApkInfo getApkInfo() {
return ApkInfo.builder()
.from(hasInstallableApk.getApkInfo())
.setApkPath(getSourcePathToOutput())
.build();
}
@Override
protected void addEnvironmentVariables(
SourcePathResolver pathResolver,
ExecutionContext context,
ImmutableMap.Builder<String, String> environmentVariablesBuilder) {
super.addEnvironmentVariables(pathResolver, context, environmentVariablesBuilder);
// We have to use an absolute path, because genrules are run in a temp directory.
String apkAbsolutePath =
pathResolver.getAbsolutePath(hasInstallableApk.getApkInfo().getApkPath()).toString();
environmentVariablesBuilder.put("APK", apkAbsolutePath);
}
}