/*
* 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.jvm.java.Javac.SRC_ZIP;
import static com.facebook.buck.rules.BuildableProperties.Kind.ANDROID;
import com.facebook.buck.event.ConsoleEvent;
import com.facebook.buck.jvm.java.JarDirectoryStep;
import com.facebook.buck.model.BuildTarget;
import com.facebook.buck.model.BuildTargets;
import com.facebook.buck.rules.AbstractBuildRule;
import com.facebook.buck.rules.AddToRuleKey;
import com.facebook.buck.rules.BuildContext;
import com.facebook.buck.rules.BuildRuleParams;
import com.facebook.buck.rules.BuildableContext;
import com.facebook.buck.rules.BuildableProperties;
import com.facebook.buck.rules.ExplicitBuildTargetSourcePath;
import com.facebook.buck.rules.SourcePath;
import com.facebook.buck.step.Step;
import com.facebook.buck.step.fs.MakeCleanDirectoryStep;
import com.facebook.buck.step.fs.MkdirStep;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.ImmutableSortedSet;
import java.nio.file.Path;
/**
* Buildable for generating a .java file from an .aidl file. Example:
*
* <pre>
* # This will generate IOrcaService.java in the buck-out/gen directory.
* gen_aidl(
* name = 'orcaservice',
* aidl = 'IOrcaService.aidl',
* )
*
* android_library(
* name = 'server',
* srcs = glob(['*.java']) + [':orcaservice'],
* deps = [
* '//first-party/orca/lib-base:lib-base',
* ],
* )
* </pre>
*/
public class GenAidl extends AbstractBuildRule {
private static final BuildableProperties PROPERTIES = new BuildableProperties(ANDROID);
// TODO(#2493457): This rule uses the aidl binary (part of the Android SDK), so the RuleKey
// should incorporate which version of aidl is used.
@AddToRuleKey private final SourcePath aidlFilePath;
@AddToRuleKey private final String importPath;
private final Path output;
private final Path genPath;
GenAidl(BuildRuleParams params, SourcePath aidlFilePath, String importPath) {
super(params);
this.aidlFilePath = aidlFilePath;
this.importPath = importPath;
BuildTarget buildTarget = params.getBuildTarget();
this.genPath = BuildTargets.getGenPath(getProjectFilesystem(), buildTarget, "%s");
this.output =
genPath.resolve(
String.format("lib%s%s", buildTarget.getShortNameAndFlavorPostfix(), SRC_ZIP));
}
@Override
public BuildableProperties getProperties() {
return PROPERTIES;
}
@Override
public SourcePath getSourcePathToOutput() {
return new ExplicitBuildTargetSourcePath(getBuildTarget(), output);
}
@Override
public ImmutableList<Step> getBuildSteps(
BuildContext context, BuildableContext buildableContext) {
ImmutableList.Builder<Step> commands = ImmutableList.builder();
commands.addAll(MakeCleanDirectoryStep.of(getProjectFilesystem(), genPath));
BuildTarget target = getBuildTarget();
Path outputDirectory = BuildTargets.getScratchPath(getProjectFilesystem(), target, "__%s.aidl");
commands.addAll(MakeCleanDirectoryStep.of(getProjectFilesystem(), outputDirectory));
AidlStep command =
new AidlStep(
getProjectFilesystem(),
target,
context.getSourcePathResolver().getAbsolutePath(aidlFilePath),
ImmutableSet.of(importPath),
outputDirectory);
commands.add(command);
// Files must ultimately be written to GEN_DIR to be used as source paths.
Path genDirectory = getProjectFilesystem().getBuckPaths().getGenDir().resolve(importPath);
// Warn the user if the genDirectory is not under the output directory.
if (!importPath.startsWith(target.getBasePath().toString())) {
// TODO(simons): Make this fatal. Give people some time to clean up their rules.
context
.getEventBus()
.post(
ConsoleEvent.warning(
"%s, gen_aidl import path (%s) should be a child of %s",
target, importPath, target.getBasePath()));
}
commands.add(MkdirStep.of(getProjectFilesystem(), genDirectory));
commands.add(
new JarDirectoryStep(
getProjectFilesystem(),
output,
ImmutableSortedSet.of(outputDirectory),
/* main class */ null,
/* manifest */ null));
buildableContext.recordArtifact(output);
return commands.build();
}
}