aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/main/java
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/java')
-rw-r--r--src/main/java/com/google/devtools/build/lib/bazel/rules/python/BazelPythonSemantics.java71
-rw-r--r--src/main/java/com/google/devtools/build/lib/bazel/rules/python/stub_template.txt40
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/python/PyCommon.java6
3 files changed, 73 insertions, 44 deletions
diff --git a/src/main/java/com/google/devtools/build/lib/bazel/rules/python/BazelPythonSemantics.java b/src/main/java/com/google/devtools/build/lib/bazel/rules/python/BazelPythonSemantics.java
index 3ea19fe034..3d95040236 100644
--- a/src/main/java/com/google/devtools/build/lib/bazel/rules/python/BazelPythonSemantics.java
+++ b/src/main/java/com/google/devtools/build/lib/bazel/rules/python/BazelPythonSemantics.java
@@ -41,7 +41,6 @@ import com.google.devtools.build.lib.rules.test.InstrumentedFilesCollector.Instr
import com.google.devtools.build.lib.syntax.Type;
import com.google.devtools.build.lib.util.FileTypeSet;
import com.google.devtools.build.lib.vfs.PathFragment;
-import java.io.File;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
@@ -105,6 +104,16 @@ public class BazelPythonSemantics implements PythonSemantics {
return result;
}
+ /** @return An artifact next to the executable file with ".zip" suffix */
+ public Artifact getPythonZipArtifact(RuleContext ruleContext, Artifact executable) {
+ return ruleContext.getRelatedArtifact(executable.getRootRelativePath(), ".zip");
+ }
+
+ /** @return An artifact next to the executable file with ".temp" suffix */
+ public Artifact getPythonTemplateMainArtifact(RuleContext ruleContext, Artifact executable) {
+ return ruleContext.getRelatedArtifact(executable.getRootRelativePath(), ".temp");
+ }
+
@Override
public void createExecutable(
RuleContext ruleContext,
@@ -133,46 +142,45 @@ public class BazelPythonSemantics implements PythonSemantics {
Substitution.of("%main%", main),
Substitution.of("%python_binary%", pythonBinary),
Substitution.of("%imports%", Joiner.on(":").join(imports)),
- Substitution.of("%workspace_name%", ruleContext.getWorkspaceName())),
+ Substitution.of("%workspace_name%", ruleContext.getWorkspaceName()),
+ Substitution.of("%is_zipfile%", "False")),
true));
} else {
- Artifact zipFile = common.getPythonZipArtifact();
+ Artifact zipFile = getPythonZipArtifact(ruleContext, executable);
+ Artifact templateMain = getPythonTemplateMainArtifact(ruleContext, executable);
PathFragment workspaceName = getWorkspaceNameForPythonZip(ruleContext.getWorkspaceName());
main = workspaceName.getRelative(common.determineMainExecutableSource(false)).toString();
PathFragment defaultWorkspacename = new PathFragment(Label.DEFAULT_REPOSITORY_DIRECTORY);
- StringBuilder importPaths = new StringBuilder();
- importPaths.append(File.pathSeparator).append("$PYTHON_RUNFILES/").append(workspaceName);
+ List<PathFragment> importPaths = new ArrayList<>();
for (PathFragment path : imports) {
if (path.startsWith(defaultWorkspacename)) {
path = new PathFragment(workspaceName, path.subFragment(1, path.segmentCount()));
}
- importPaths.append(File.pathSeparator).append("$PYTHON_RUNFILES/").append(path);
+ importPaths.add(path);
}
// The executable zip file wil unzip itself into a tmp directory and then run from there
- String zipHeader =
- "#!/bin/sh\n"
- + "export TMPDIR=${TMPDIR:-/tmp/Bazel}\n"
- + "mkdir -p \"${TMPDIR}\"\n"
- + "export PYTHON_RUNFILES=$(mktemp -d \"${TMPDIR%%/}/runfiles.XXXXXXXX\")\n"
- + "export PYTHONPATH=\"$PYTHONPATH"
- + importPaths
- + "\"\n"
- + "unzip -q -o $0 -d \"$PYTHON_RUNFILES\" 2> /dev/null\n"
- + "retCode=0\n"
- + pythonBinary
- + " \"$PYTHON_RUNFILES/"
- + main
- + "\" $@ || retCode=$?\n"
- + "rm -rf \"$PYTHON_RUNFILES\"\n"
- + "exit $retCode\n";
+ ruleContext.registerAction(
+ new TemplateExpansionAction(
+ ruleContext.getActionOwner(),
+ templateMain,
+ STUB_TEMPLATE,
+ ImmutableList.of(
+ Substitution.of("%main%", main),
+ Substitution.of("%python_binary%", pythonBinary),
+ Substitution.of("%imports%", Joiner.on(":").join(importPaths)),
+ Substitution.of("%workspace_name%", ruleContext.getWorkspaceName()),
+ Substitution.of("%is_zipfile%", "True")),
+ true));
+
ruleContext.registerAction(
new SpawnAction.Builder()
.addInput(zipFile)
+ .addInput(templateMain)
.addOutput(executable)
.setShellCommand(
- "echo '"
- + zipHeader
- + "' | cat - "
+ "cat "
+ + templateMain.getExecPathString()
+ + " "
+ zipFile.getExecPathString()
+ " > "
+ executable.getExecPathString())
@@ -187,12 +195,13 @@ public class BazelPythonSemantics implements PythonSemantics {
PyCommon common) throws InterruptedException {
if (ruleContext.getConfiguration().buildPythonZip()) {
FilesToRunProvider zipper = ruleContext.getExecutablePrerequisite("$zipper", Mode.HOST);
+ Artifact executable = common.getExecutable();
if (!ruleContext.hasErrors()) {
createPythonZipAction(
ruleContext,
- common.getExecutable(),
- common.getPythonZipArtifact(),
- common.determineMainExecutableSource(false),
+ executable,
+ getPythonZipArtifact(ruleContext, executable),
+ getPythonTemplateMainArtifact(ruleContext, executable),
zipper,
runfilesSupport);
}
@@ -230,15 +239,15 @@ public class BazelPythonSemantics implements PythonSemantics {
RuleContext ruleContext,
Artifact executable,
Artifact zipFile,
- String main,
+ Artifact templateMain,
FilesToRunProvider zipper,
RunfilesSupport runfilesSupport) {
NestedSetBuilder<Artifact> inputsBuilder = NestedSetBuilder.stableOrder();
PathFragment workspaceName = getWorkspaceNameForPythonZip(ruleContext.getWorkspaceName());
CustomCommandLine.Builder argv = new CustomCommandLine.Builder();
-
- argv.add("__main__.py=" + main);
+ inputsBuilder.add(templateMain);
+ argv.add("__main__.py=" + templateMain.getExecPathString());
// Creating __init__.py files under each directory
argv.add("__init__.py=");
diff --git a/src/main/java/com/google/devtools/build/lib/bazel/rules/python/stub_template.txt b/src/main/java/com/google/devtools/build/lib/bazel/rules/python/stub_template.txt
index 8e561a55c3..ac0b8bd337 100644
--- a/src/main/java/com/google/devtools/build/lib/bazel/rules/python/stub_template.txt
+++ b/src/main/java/com/google/devtools/build/lib/bazel/rules/python/stub_template.txt
@@ -1,9 +1,12 @@
-#!/usr/bin/python
+#!/usr/bin/env python
import os
import re
+import tempfile
+import shutil
import sys
import subprocess
+import zipfile
# Return True if running on Windows
def IsWindows():
@@ -23,6 +26,9 @@ def SearchPath(name):
return path
return None
+def IsRunningFromZip():
+ return %is_zipfile%
+
# Find the real Python binary if it's not a normal absolute path
def FindPythonBinary():
if PYTHON_BINARY.startswith('//'):
@@ -43,11 +49,8 @@ def CreatePythonPathEntries(python_imports, module_space):
parts = python_imports.split(':');
return [module_space] + ["%s/%s" % (module_space, path) for path in parts]
-def Main():
- args = sys.argv[1:]
-
- new_env = {}
-
+# Find the runfiles tree
+def FindModuleSpace():
# Follow symlinks, looking for my module space
stub_filename = os.path.abspath(sys.argv[0])
while True:
@@ -73,6 +76,24 @@ def Main():
raise AssertionError('Cannot find .runfiles directory for %s' %
sys.argv[0])
+ return module_space
+
+# Create the runfiles tree by extracting the zip file
+def CreateModuleSpace():
+ module_space = tempfile.mkdtemp("", "Bazel.runfiles_")
+ zf = zipfile.ZipFile(os.path.dirname(__file__))
+ zf.extractall(module_space)
+ return module_space
+
+def Main():
+ args = sys.argv[1:]
+
+ new_env = {}
+
+ if IsRunningFromZip():
+ module_space = CreateModuleSpace()
+ else:
+ module_space = FindModuleSpace()
python_imports = '%imports%'
python_path_entries = CreatePythonPathEntries(python_imports, module_space)
@@ -109,7 +130,12 @@ def Main():
try:
sys.stdout.flush()
- os.execv(args[0], args)
+ if IsRunningFromZip():
+ retCode = subprocess.call(args)
+ shutil.rmtree(module_space, True)
+ exit(retCode)
+ else:
+ os.execv(args[0], args)
except EnvironmentError as e:
# This exception occurs when os.execv() fails for some reason.
if not getattr(e, 'filename', None):
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 d03f380e9d..ab3f3210f3 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
@@ -448,12 +448,6 @@ public final class PyCommon {
public Artifact getExecutable() {
return executable;
}
- /** @return An artifact next to the executable file with ".zip" suffix */
- public Artifact getPythonZipArtifact() {
- PathFragment original = executable.getRootRelativePath();
- return ruleContext.getDerivedArtifact(
- original.replaceName(original.getBaseName() + ".zip"), executable.getRoot());
- }
public Map<PathFragment, Artifact> getConvertedFiles() {
return convertedFiles;