blob: e0af03ce2c2ced8837aea897220dbc4542d5895d [file] [log] [blame]
/*
* 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.python;
import static com.facebook.buck.rules.BuildableProperties.Kind.PACKAGING;
import com.facebook.buck.io.ProjectFilesystem;
import com.facebook.buck.model.BuildTargets;
import com.facebook.buck.rules.AbstractBuildRule;
import com.facebook.buck.rules.BinaryBuildRule;
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.RuleKey;
import com.facebook.buck.rules.SourcePathResolver;
import com.facebook.buck.step.Step;
import com.facebook.buck.step.fs.MakeCleanDirectoryStep;
import com.facebook.buck.step.fs.MkdirStep;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableCollection;
import com.google.common.collect.ImmutableList;
import java.nio.file.Path;
public class PythonBinary extends AbstractBuildRule implements BinaryBuildRule {
private static final BuildableProperties OUTPUT_TYPE = new BuildableProperties(PACKAGING);
private final Path pathToPex;
private final Path main;
private final PythonPackageComponents components;
private final PythonEnvironment pythonEnvironment;
protected PythonBinary(
BuildRuleParams params,
SourcePathResolver resolver,
Path pathToPex,
PythonEnvironment pythonEnvironment,
Path main,
PythonPackageComponents components) {
super(params, resolver);
this.pathToPex = pathToPex;
this.pythonEnvironment = pythonEnvironment;
this.main = main;
this.components = components;
}
@Override
public BuildableProperties getProperties() {
return OUTPUT_TYPE;
}
public Path getBinPath() {
return BuildTargets.getBinPath(getBuildTarget(), "%s.pex");
}
@Override
public Path getPathToOutputFile() {
return getBinPath();
}
@VisibleForTesting
protected PythonPackageComponents getComponents() {
return components;
}
@VisibleForTesting
protected Path getMain() {
return main;
}
@Override
public ImmutableList<String> getExecutableCommand(ProjectFilesystem projectFilesystem) {
return ImmutableList.of(
Preconditions.checkNotNull(
projectFilesystem.getAbsolutifier().apply(getBinPath())).toString());
}
@Override
public RuleKey.Builder appendDetailsToRuleKey(RuleKey.Builder builder) {
builder
.setReflectively("packageType", "pex")
.setReflectively("pythonVersion", pythonEnvironment.getPythonVersion().toString())
.setReflectively("mainModule", main.toString())
.setReflectively("components", components);
return builder;
}
@Override
public ImmutableCollection<Path> getInputsToCompareToOutput() {
return ImmutableList.copyOf(getResolver().filterInputsToCompareToOutput(
components.getInputsToCompareToOutput()));
}
@Override
public ImmutableList<Step> getBuildSteps(
BuildContext context,
BuildableContext buildableContext) {
ImmutableList.Builder<Step> steps = ImmutableList.builder();
Path binPath = getBinPath();
// Make sure the parent directory exists.
steps.add(new MkdirStep(binPath.getParent()));
Path workingDirectory = BuildTargets.getGenPath(
getBuildTarget(), "__%s__working_directory");
steps.add(new MakeCleanDirectoryStep(workingDirectory));
// Generate and return the PEX build step.
steps.add(new PexStep(
pathToPex,
pythonEnvironment.getPythonPath(),
workingDirectory,
binPath,
PythonUtil.toModuleName(getBuildTarget(), main.toString()),
getResolver().getMappedPaths(components.getModules()),
getResolver().getMappedPaths(components.getResources()),
getResolver().getMappedPaths(components.getNativeLibraries())));
// Record the executable package for caching.
buildableContext.recordArtifact(getBinPath());
return steps.build();
}
}