From 16c002ed8e4262f18fb53d7c21601344b45bed3d Mon Sep 17 00:00:00 2001 From: Evan Jones Date: Mon, 8 Jan 2018 14:59:00 -0500 Subject: [PATCH] pex_binary: Support PEXes with no entry points (interpreters) When using pex without any entry points, it creates a PEX that is an interpreter that uses the bundled environment. This can be useful to distribute in order to execute other scripts. interpreter_only_test.py: Verify that the PEX starts an interpreter. Fixes the following Skylark exceptions in pex_binary: File ".../bazel_rules_pex/examples/BUILD", line 24 pex_binary(name = 'interpreter_only') File ".../bazel_rules_pex/pex/pex_rules.bzl", line 177, in _pex_binary_impl pex_file_types.filter(ctx.files.srcs)[0] index out of range (index is 0, but sequence has 0 elements) File ".../bazel_rules_pex/examples/BUILD", line 24 pex_binary(name = 'interpreter_only') File ".../bazel_rules_pex/pex/pex_rules.bzl", line 225, in _pex_binary_impl main_pkg name 'main_pkg' is not defined --- examples/BUILD | 11 +++++++++++ examples/interpreter_only_test.py | 17 +++++++++++++++++ pex/pex_rules.bzl | 7 +++++-- 3 files changed, 33 insertions(+), 2 deletions(-) create mode 100755 examples/interpreter_only_test.py diff --git a/examples/BUILD b/examples/BUILD index 3814730c..9b695b3c 100644 --- a/examples/BUILD +++ b/examples/BUILD @@ -19,3 +19,14 @@ pex_pytest( deps = [":libfoo"], size = "small", ) + +# Tests that building a pex without entry points is supported +pex_binary( + name = "interpreter_only", +) +sh_test( + name = "interpreter_only_test", + srcs = ["interpreter_only_test.py"], + data = [":interpreter_only"], + args = ["$(location :interpreter_only)"], +) diff --git a/examples/interpreter_only_test.py b/examples/interpreter_only_test.py new file mode 100755 index 00000000..38968028 --- /dev/null +++ b/examples/interpreter_only_test.py @@ -0,0 +1,17 @@ +#!/usr/bin/env python2.7 + +import sys +import subprocess + +def main(): + if len(sys.argv) != 2: + sys.stderr.write('Error: Pass path to an interpreter pex\n') + sys.exit(1) + interpreter_pex_path = sys.argv[1] + + output = subprocess.check_output([interpreter_pex_path], stderr=subprocess.STDOUT) + assert 'InteractiveConsole' in output + print 'PASS' + +if __name__ == '__main__': + main() diff --git a/pex/pex_rules.bzl b/pex/pex_rules.bzl index a02cd880..08c7d6da 100644 --- a/pex/pex_rules.bzl +++ b/pex/pex_rules.bzl @@ -168,13 +168,16 @@ def _pex_binary_impl(ctx): if ctx.attr.entrypoint and ctx.file.main: fail("Please specify either entrypoint or main, not both.") + main_file = None + main_pkg = '' if ctx.attr.entrypoint: - main_file = None main_pkg = ctx.attr.entrypoint elif ctx.file.main: main_file = ctx.file.main else: - main_file = pex_file_types.filter(ctx.files.srcs)[0] + filtered_srcs = pex_file_types.filter(ctx.files.srcs) + if filtered_srcs: + main_file = filtered_srcs[0] if main_file: # Translate main_file's short path into a python module name main_pkg = main_file.short_path.replace('/', '.')[:-3]