diff options
Diffstat (limited to 'src/main/java/com/google/devtools/build/lib/rules')
5 files changed, 84 insertions, 9 deletions
diff --git a/src/main/java/com/google/devtools/build/lib/rules/python/PyBinary.java b/src/main/java/com/google/devtools/build/lib/rules/python/PyBinary.java index 01829b670f..ae048a0a03 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/python/PyBinary.java +++ b/src/main/java/com/google/devtools/build/lib/rules/python/PyBinary.java @@ -21,10 +21,12 @@ import com.google.devtools.build.lib.analysis.RuleContext; import com.google.devtools.build.lib.analysis.Runfiles; import com.google.devtools.build.lib.analysis.RunfilesProvider; import com.google.devtools.build.lib.analysis.RunfilesSupport; +import com.google.devtools.build.lib.collect.nestedset.NestedSet; import com.google.devtools.build.lib.rules.RuleConfiguredTargetFactory; import com.google.devtools.build.lib.rules.cpp.CcLinkParams; import com.google.devtools.build.lib.rules.cpp.CcLinkParamsProvider; import com.google.devtools.build.lib.rules.cpp.CcLinkParamsStore; +import com.google.devtools.build.lib.vfs.PathFragment; import java.util.ArrayList; import java.util.List; @@ -65,7 +67,12 @@ public abstract class PyBinary implements RuleConfiguredTargetFactory { return null; } - semantics.createExecutable(ruleContext, common, ccLinkParamsStore); + NestedSet<PathFragment> imports = common.collectImports(ruleContext, semantics); + if (ruleContext.hasErrors()) { + return null; + } + + semantics.createExecutable(ruleContext, common, ccLinkParamsStore, imports); Runfiles commonRunfiles = collectCommonRunfiles(ruleContext, common, semantics); Runfiles.Builder defaultRunfilesBuilder = new Runfiles.Builder(ruleContext.getWorkspaceName()) @@ -99,7 +106,8 @@ public abstract class PyBinary implements RuleConfiguredTargetFactory { .setFilesToBuild(common.getFilesToBuild()) .add(RunfilesProvider.class, runfilesProvider) .setRunfilesSupport(runfilesSupport, common.getExecutable()) - .add(CcLinkParamsProvider.class, new CcLinkParamsProvider(ccLinkParamsStore)); + .add(CcLinkParamsProvider.class, new CcLinkParamsProvider(ccLinkParamsStore)) + .add(PythonImportsProvider.class, new PythonImportsProvider(imports)); } private static Runfiles collectCommonRunfiles(RuleContext ruleContext, PyCommon common, diff --git a/src/main/java/com/google/devtools/build/lib/rules/python/PyCommon.java b/src/main/java/com/google/devtools/build/lib/rules/python/PyCommon.java index 969955f55a..9b6813fad5 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/python/PyCommon.java +++ b/src/main/java/com/google/devtools/build/lib/rules/python/PyCommon.java @@ -276,14 +276,31 @@ public final class PyCommon { } private NestedSet<Artifact> collectTransitivePythonSources() { - NestedSetBuilder<Artifact> builder = - NestedSetBuilder.compileOrder(); + NestedSetBuilder<Artifact> builder = NestedSetBuilder.compileOrder(); collectTransitivePythonSourcesFrom(getTargetDeps(), builder); - addSourceFiles(builder, ruleContext - .getPrerequisiteArtifacts("srcs", Mode.TARGET).filter(PyRuleClasses.PYTHON_SOURCE).list()); + addSourceFiles(builder, + ruleContext.getPrerequisiteArtifacts("srcs", Mode.TARGET) + .filter(PyRuleClasses.PYTHON_SOURCE).list()); return builder.build(); } + public NestedSet<PathFragment> collectImports( + RuleContext ruleContext, PythonSemantics semantics) { + NestedSetBuilder<PathFragment> builder = NestedSetBuilder.compileOrder(); + builder.addAll(semantics.getImports(ruleContext)); + collectTransitivePythonImports(builder); + return builder.build(); + } + + private void collectTransitivePythonImports(NestedSetBuilder<PathFragment> builder) { + for (TransitiveInfoCollection dep : getTargetDeps()) { + if (dep.getProvider(PythonImportsProvider.class) != null) { + PythonImportsProvider provider = dep.getProvider(PythonImportsProvider.class); + builder.addTransitive(provider.getTransitivePythonImports()); + } + } + } + /** * Checks that the source file version is compatible with the Python interpreter. */ diff --git a/src/main/java/com/google/devtools/build/lib/rules/python/PyLibrary.java b/src/main/java/com/google/devtools/build/lib/rules/python/PyLibrary.java index eb2e9314c7..95f4c8364e 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/python/PyLibrary.java +++ b/src/main/java/com/google/devtools/build/lib/rules/python/PyLibrary.java @@ -27,6 +27,7 @@ import com.google.devtools.build.lib.rules.RuleConfiguredTargetFactory; import com.google.devtools.build.lib.rules.cpp.CcLinkParams; import com.google.devtools.build.lib.rules.cpp.CcLinkParamsProvider; import com.google.devtools.build.lib.rules.cpp.CcLinkParamsStore; +import com.google.devtools.build.lib.vfs.PathFragment; import java.util.ArrayList; import java.util.List; @@ -50,7 +51,6 @@ public abstract class PyLibrary implements RuleConfiguredTargetFactory { common.validatePackageName(); semantics.validate(ruleContext, common); - List<Artifact> srcs = common.validateSrcs(); List<Artifact> allOutputs = new ArrayList<>(semantics.precompiledPythonFiles(ruleContext, srcs, common)); @@ -69,6 +69,11 @@ public abstract class PyLibrary implements RuleConfiguredTargetFactory { } }; + NestedSet<PathFragment> imports = common.collectImports(ruleContext, semantics); + if (ruleContext.hasErrors()) { + return null; + } + Runfiles.Builder runfilesBuilder = new Runfiles.Builder(ruleContext.getWorkspaceName()); if (common.getConvertedFiles() != null) { runfilesBuilder.addSymlinks(common.getConvertedFiles()); @@ -85,6 +90,7 @@ public abstract class PyLibrary implements RuleConfiguredTargetFactory { .setFilesToBuild(filesToBuild) .add(RunfilesProvider.class, RunfilesProvider.simple(runfilesBuilder.build())) .add(CcLinkParamsProvider.class, new CcLinkParamsProvider(ccLinkParamsStore)) + .add(PythonImportsProvider.class, new PythonImportsProvider(imports)) .build(); } } diff --git a/src/main/java/com/google/devtools/build/lib/rules/python/PythonImportsProvider.java b/src/main/java/com/google/devtools/build/lib/rules/python/PythonImportsProvider.java new file mode 100644 index 0000000000..03bb52aa70 --- /dev/null +++ b/src/main/java/com/google/devtools/build/lib/rules/python/PythonImportsProvider.java @@ -0,0 +1,36 @@ +// Copyright 2016 The Bazel Authors. All rights reserved. +// +// 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.google.devtools.build.lib.rules.python; + +import com.google.devtools.build.lib.analysis.TransitiveInfoProvider; +import com.google.devtools.build.lib.collect.nestedset.NestedSet; +import com.google.devtools.build.lib.concurrent.ThreadSafety.Immutable; +import com.google.devtools.build.lib.vfs.PathFragment; + +/** + * A {@link TransitiveInfoProvider} that supplies import directories for Python dependencies. + */ +@Immutable +public final class PythonImportsProvider implements TransitiveInfoProvider { + + private final NestedSet<PathFragment> transitivePythonImports; + + public PythonImportsProvider(NestedSet<PathFragment> transitivePythonImports) { + this.transitivePythonImports = transitivePythonImports; + } + + public NestedSet<PathFragment> getTransitivePythonImports() { + return transitivePythonImports; + } +} diff --git a/src/main/java/com/google/devtools/build/lib/rules/python/PythonSemantics.java b/src/main/java/com/google/devtools/build/lib/rules/python/PythonSemantics.java index abf6a88246..2168a879ce 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/python/PythonSemantics.java +++ b/src/main/java/com/google/devtools/build/lib/rules/python/PythonSemantics.java @@ -17,10 +17,13 @@ import com.google.devtools.build.lib.actions.Artifact; import com.google.devtools.build.lib.analysis.RuleContext; import com.google.devtools.build.lib.analysis.Runfiles; import com.google.devtools.build.lib.analysis.RunfilesSupport; +import com.google.devtools.build.lib.collect.nestedset.NestedSet; import com.google.devtools.build.lib.rules.cpp.CcLinkParamsStore; import com.google.devtools.build.lib.rules.test.InstrumentedFilesCollector.InstrumentationSpec; +import com.google.devtools.build.lib.vfs.PathFragment; import java.util.Collection; +import java.util.List; /** * Pluggable semantics for Python rules. @@ -56,16 +59,21 @@ public interface PythonSemantics { RuleContext ruleContext, Collection<Artifact> sources, PyCommon common); /** + * Returns a list of PathFragments for the import paths specified in the imports attribute. + */ + List<PathFragment> getImports(RuleContext ruleContext); + + /** * Create the actual executable artifact. * * <p>This should create a generating action for {@code common.getExecutable()}. */ void createExecutable(RuleContext ruleContext, PyCommon common, - CcLinkParamsStore ccLinkParamsStore); + CcLinkParamsStore ccLinkParamsStore, NestedSet<PathFragment> imports); /** * Called at the end of the analysis of {@code py_binary} rules. - * @throws InterruptedException + * @throws InterruptedException */ void postInitBinary(RuleContext ruleContext, RunfilesSupport runfilesSupport, PyCommon common) throws InterruptedException; |