blob: 7f85eecf4fb9c41682ca78f8b68454cbdd65869e [file] [log] [blame]
/*
* Copyright 2014-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 com.facebook.buck.cxx.CxxPlatform;
import com.facebook.buck.io.MorePaths;
import com.facebook.buck.model.BuildTarget;
import com.facebook.buck.graph.AbstractBreadthFirstTraversal;
import com.facebook.buck.rules.BuildRule;
import com.facebook.buck.rules.BuildRuleParams;
import com.facebook.buck.rules.SourcePath;
import com.facebook.buck.rules.SourcePathResolver;
import com.facebook.buck.rules.coercer.Either;
import com.facebook.buck.util.HumanReadableException;
import com.google.common.base.Optional;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSortedSet;
import java.nio.file.Path;
import java.nio.file.Paths;
public class PythonUtil {
private PythonUtil() {}
public static ImmutableMap<Path, SourcePath> toModuleMap(
BuildTarget target,
SourcePathResolver resolver,
String parameter,
Path baseModule,
Optional<Either<ImmutableSortedSet<SourcePath>, ImmutableMap<String, SourcePath>>> inputs) {
if (!inputs.isPresent()) {
return ImmutableMap.of();
}
final ImmutableMap<String, SourcePath> namesAndSourcePaths;
if (inputs.get().isLeft()) {
namesAndSourcePaths = resolver.getSourcePathNames(
target,
parameter,
inputs.get().getLeft());
} else {
namesAndSourcePaths = inputs.get().getRight();
}
ImmutableMap.Builder<Path, SourcePath> moduleNamesAndSourcePaths = ImmutableMap.builder();
for (ImmutableMap.Entry<String, SourcePath> entry : namesAndSourcePaths.entrySet()) {
moduleNamesAndSourcePaths.put(
baseModule.resolve(entry.getKey()),
entry.getValue());
}
return moduleNamesAndSourcePaths.build();
}
/** Convert a path to a module to it's module name as referenced in import statements. */
public static String toModuleName(BuildTarget target, String name) {
int ext = name.lastIndexOf('.');
if (ext == -1) {
throw new HumanReadableException(
"%s: missing extension for module path: %s",
target,
name);
}
name = name.substring(0, ext);
return MorePaths.pathWithUnixSeparators(name).replace('/', '.');
}
public static ImmutableSortedSet<BuildRule> getDepsFromComponents(
SourcePathResolver resolver,
PythonPackageComponents components) {
return ImmutableSortedSet.<BuildRule>naturalOrder()
.addAll(resolver.filterBuildRuleInputs(components.getModules().values()))
.addAll(resolver.filterBuildRuleInputs(components.getResources().values()))
.addAll(resolver.filterBuildRuleInputs(components.getNativeLibraries().values()))
.build();
}
public static PythonPackageComponents getAllComponents(
BuildRuleParams params,
PythonPackageComponents packageComponents,
final CxxPlatform cxxPlatform) {
final PythonPackageComponents.Builder components =
new PythonPackageComponents.Builder(params.getBuildTarget());
// Add components from our self.
components.addComponent(packageComponents, params.getBuildTarget());
// Walk all our transitive deps to build our complete package that we'll
// turn into an executable.
new AbstractBreadthFirstTraversal<BuildRule>(params.getDeps()) {
@Override
public ImmutableSortedSet<BuildRule> visit(BuildRule rule) {
// We only process and recurse on instances of PythonPackagable.
if (rule instanceof PythonPackagable) {
PythonPackagable lib = (PythonPackagable) rule;
// Add all components from the python packable into our top-level
// package.
components.addComponent(
lib.getPythonPackageComponents(cxxPlatform),
rule.getBuildTarget());
// Return all our deps to recurse on them.
return rule.getDeps();
}
// Don't recurse on anything from other rules.
return ImmutableSortedSet.of();
}
}.start();
return components.build();
}
public static Path getBasePath(BuildTarget target, Optional<String> override) {
return override.isPresent()
? Paths.get(override.get().replace('.', '/'))
: target.getBasePath();
}
}