blob: b3d08b168b20e57f13f3ed7c8c9869eb712182e3 [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.LIBRARY;
import com.facebook.buck.model.BuildTarget;
import com.facebook.buck.rules.AbstractBuildRuleBuilderParams;
import com.facebook.buck.rules.AbstractBuildable;
import com.facebook.buck.rules.BuildContext;
import com.facebook.buck.rules.BuildRuleParams;
import com.facebook.buck.rules.BuildRuleResolver;
import com.facebook.buck.rules.BuildRuleType;
import com.facebook.buck.rules.BuildableContext;
import com.facebook.buck.rules.BuildableProperties;
import com.facebook.buck.rules.RuleKey;
import com.facebook.buck.rules.SrcsAttributeBuilder;
import com.facebook.buck.step.Step;
import com.facebook.buck.step.fs.CopyStep;
import com.facebook.buck.step.fs.MakeCleanDirectoryStep;
import com.facebook.buck.step.fs.MkdirStep;
import com.facebook.buck.util.BuckConstant;
import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSortedSet;
import java.io.IOException;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.List;
import javax.annotation.Nullable;
public class PythonLibrary extends AbstractBuildable {
private final static BuildableProperties OUTPUT_TYPE = new BuildableProperties(LIBRARY);
private final BuildTarget buildTarget;
// TODO(simons): Convert to using Paths
private final ImmutableSortedSet<String> srcs;
private final Path pythonPathDirectory;
protected PythonLibrary(BuildRuleParams buildRuleParams,
ImmutableSortedSet<String> srcs) {
Preconditions.checkArgument(!srcs.isEmpty(),
"Must specify srcs for %s.",
buildRuleParams.getBuildTarget());
this.buildTarget = buildRuleParams.getBuildTarget();
this.srcs = ImmutableSortedSet.copyOf(srcs);
this.pythonPathDirectory = getPathToPythonPathDirectory();
}
@Nullable
@Override
public String getPathToOutputFile() {
return null;
}
@Override
public RuleKey.Builder appendDetailsToRuleKey(RuleKey.Builder builder) throws IOException {
return builder.set("srcs", srcs);
}
private Path getPathToPythonPathDirectory() {
return Paths.get(
BuckConstant.GEN_DIR,
buildTarget.getBasePath(),
getPathUnderGenDirectory());
}
private String getPathUnderGenDirectory() {
return "__pylib_" + buildTarget.getShortName();
}
public ImmutableSortedSet<String> getPythonSrcs() {
return srcs;
}
@Override
public Iterable<String> getInputsToCompareToOutput() {
return srcs;
}
public Path getPythonPathDirectory() {
return pythonPathDirectory;
}
@Override
public List<Step> getBuildSteps(BuildContext context, BuildableContext buildableContext)
throws IOException {
ImmutableList.Builder<Step> commands = ImmutableList.builder();
// Copy all of the sources to a generated directory so that the generated directory can be
// included as a $PYTHONPATH element. TODO(mbolin): Symlinks would be more efficient, but we
// need to include this structure in the artifact, which is not guaranteed to be zip-friendly.
commands.add(new MakeCleanDirectoryStep(pythonPathDirectory));
ImmutableSortedSet.Builder<Path> directories = ImmutableSortedSet.naturalOrder();
ImmutableList.Builder<Step> copySteps = ImmutableList.builder();
for (String src : srcs) {
Path srcPath = Paths.get(src);
Path relativeSrc = Paths.get(buildTarget.getBasePath()).relativize(srcPath);
Path target = pythonPathDirectory.resolve(relativeSrc);
directories.add(target.getParent());
copySteps.add(new CopyStep(srcPath, target));
Path pathToArtifact = Paths.get(getPathUnderGenDirectory()).resolve(relativeSrc);
buildableContext.recordArtifact(pathToArtifact);
}
for (Path path : directories.build()) {
commands.add(new MkdirStep(path));
}
commands.addAll(copySteps.build());
return commands.build();
}
@Override
public BuildableProperties getProperties() {
return OUTPUT_TYPE;
}
public static Builder newPythonLibraryBuilder(AbstractBuildRuleBuilderParams params) {
return new Builder(params);
}
public static class Builder extends AbstractBuildable.Builder
implements SrcsAttributeBuilder {
protected ImmutableSortedSet.Builder<String> srcs = ImmutableSortedSet.naturalOrder();
private Builder(AbstractBuildRuleBuilderParams params) {
super(params);
}
@Override
public Builder addSrc(String src) {
srcs.add(src);
return this;
}
@Override
public BuildRuleType getType() {
return BuildRuleType.PYTHON_LIBRARY;
}
@Override
protected PythonLibrary newBuildable(BuildRuleParams params, BuildRuleResolver resolver) {
return new PythonLibrary(params, srcs.build());
}
}
}