204 lines
6.7 KiB
Text
204 lines
6.7 KiB
Text
|
#!/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():
|
||
|
return os.name == 'nt'
|
||
|
|
||
|
def GetWindowsPathWithUNCPrefix(path):
|
||
|
"""
|
||
|
Adding UNC prefix after getting a normalized absolute Windows path,
|
||
|
it's no-op for non-Windows platforms or if running under python2.
|
||
|
"""
|
||
|
path = path.strip()
|
||
|
|
||
|
# No need to add prefix for non-Windows platforms.
|
||
|
# And \\?\ doesn't work in python 2
|
||
|
if not IsWindows() or sys.version_info[0] < 3:
|
||
|
return path
|
||
|
|
||
|
# Lets start the unicode fun
|
||
|
unicode_prefix = "\\\\?\\"
|
||
|
if path.startswith(unicode_prefix):
|
||
|
return path
|
||
|
|
||
|
# os.path.abspath returns a normalized absolute path
|
||
|
return unicode_prefix + os.path.abspath(path)
|
||
|
|
||
|
PYTHON_BINARY = '/usr/bin/python3.6'
|
||
|
if IsWindows() and not PYTHON_BINARY.endswith('.exe'):
|
||
|
PYTHON_BINARY = PYTHON_BINARY + '.exe'
|
||
|
|
||
|
# Find a file in a given search path.
|
||
|
def SearchPath(name):
|
||
|
search_path = os.getenv('PATH', os.defpath).split(os.pathsep)
|
||
|
for directory in search_path:
|
||
|
if directory == '': continue
|
||
|
path = os.path.join(directory, name)
|
||
|
if os.path.isfile(path) and os.access(path, os.X_OK):
|
||
|
return path
|
||
|
return None
|
||
|
|
||
|
def IsRunningFromZip():
|
||
|
return False
|
||
|
|
||
|
# Find the real Python binary if it's not a normal absolute path
|
||
|
def FindPythonBinary(module_space):
|
||
|
if PYTHON_BINARY.startswith('//'):
|
||
|
# Case 1: Path is a label. Not supported yet.
|
||
|
raise AssertionError(
|
||
|
'Bazel does not support execution of Python interpreters via labels yet')
|
||
|
elif PYTHON_BINARY.startswith('/'):
|
||
|
# Case 2: Absolute path.
|
||
|
return PYTHON_BINARY
|
||
|
elif '/' in PYTHON_BINARY:
|
||
|
# Case 3: Path is relative to the repo root.
|
||
|
return os.path.join(module_space, PYTHON_BINARY)
|
||
|
else:
|
||
|
# Case 4: Path has to be looked up in the search path.
|
||
|
return SearchPath(PYTHON_BINARY)
|
||
|
|
||
|
def CreatePythonPathEntries(python_imports, module_space):
|
||
|
parts = python_imports.split(':');
|
||
|
return [module_space] + ["%s/%s" % (module_space, path) for path in parts]
|
||
|
|
||
|
# Find the runfiles tree
|
||
|
def FindModuleSpace():
|
||
|
stub_filename = os.path.abspath(sys.argv[0])
|
||
|
module_space = stub_filename + '.runfiles'
|
||
|
if os.path.isdir(module_space):
|
||
|
return module_space
|
||
|
|
||
|
runfiles_pattern = "(.*\.runfiles)/.*"
|
||
|
if IsWindows():
|
||
|
runfiles_pattern = "(.*\.runfiles)\\.*"
|
||
|
matchobj = re.match(runfiles_pattern, os.path.abspath(sys.argv[0]))
|
||
|
if matchobj:
|
||
|
return matchobj.group(1)
|
||
|
|
||
|
raise AssertionError('Cannot find .runfiles directory for %s' % sys.argv[0])
|
||
|
|
||
|
# Create the runfiles tree by extracting the zip file
|
||
|
def CreateModuleSpace():
|
||
|
ZIP_RUNFILES_DIRECTORY_NAME = "runfiles"
|
||
|
temp_dir = tempfile.mkdtemp("", "Bazel.runfiles_")
|
||
|
zf = zipfile.ZipFile(GetWindowsPathWithUNCPrefix(os.path.dirname(__file__)))
|
||
|
zf.extractall(GetWindowsPathWithUNCPrefix(temp_dir))
|
||
|
return os.path.join(temp_dir, ZIP_RUNFILES_DIRECTORY_NAME)
|
||
|
|
||
|
# Returns repository roots to add to the import path.
|
||
|
def GetRepositoriesImports(module_space, import_all):
|
||
|
if import_all:
|
||
|
repo_dirs = [os.path.join(module_space, d) for d in os.listdir(module_space)]
|
||
|
return [d for d in repo_dirs if os.path.isdir(d)]
|
||
|
return [os.path.join(module_space, "org_tensorflow")]
|
||
|
|
||
|
# Finds the runfiles manifest or the runfiles directory.
|
||
|
def RunfilesEnvvar(module_space):
|
||
|
# If this binary is the data-dependency of another one, the other sets
|
||
|
# RUNFILES_MANIFEST_FILE or RUNFILES_DIR for our sake.
|
||
|
runfiles = os.environ.get('RUNFILES_MANIFEST_FILE', None)
|
||
|
if runfiles:
|
||
|
return ('RUNFILES_MANIFEST_FILE', runfiles)
|
||
|
|
||
|
runfiles = os.environ.get('RUNFILES_DIR', None)
|
||
|
if runfiles:
|
||
|
return ('RUNFILES_DIR', runfiles)
|
||
|
|
||
|
# If running from a zip, there's no manifest file.
|
||
|
if IsRunningFromZip():
|
||
|
return ('RUNFILES_DIR', module_space)
|
||
|
|
||
|
# Look for the runfiles "output" manifest, argv[0] + ".runfiles_manifest"
|
||
|
runfiles = module_space + '_manifest'
|
||
|
if os.path.exists(runfiles):
|
||
|
return ('RUNFILES_MANIFEST_FILE', runfiles)
|
||
|
|
||
|
# Look for the runfiles "input" manifest, argv[0] + ".runfiles/MANIFEST"
|
||
|
runfiles = os.path.join(module_space, 'MANIFEST')
|
||
|
if os.path.exists(runfiles):
|
||
|
return ('RUNFILES_DIR', runfiles)
|
||
|
|
||
|
return (None, None)
|
||
|
|
||
|
def Main():
|
||
|
args = sys.argv[1:]
|
||
|
|
||
|
new_env = {}
|
||
|
|
||
|
if IsRunningFromZip():
|
||
|
module_space = CreateModuleSpace()
|
||
|
else:
|
||
|
module_space = FindModuleSpace()
|
||
|
|
||
|
python_imports = 'protobuf_archive/python'
|
||
|
python_path_entries = CreatePythonPathEntries(python_imports, module_space)
|
||
|
python_path_entries += GetRepositoriesImports(module_space, True)
|
||
|
|
||
|
python_path_entries = [GetWindowsPathWithUNCPrefix(d) for d in python_path_entries]
|
||
|
|
||
|
old_python_path = os.environ.get('PYTHONPATH')
|
||
|
python_path = os.pathsep.join(python_path_entries)
|
||
|
if old_python_path:
|
||
|
python_path += os.pathsep + old_python_path
|
||
|
|
||
|
if IsWindows():
|
||
|
python_path = python_path.replace("/", os.sep)
|
||
|
|
||
|
new_env['PYTHONPATH'] = python_path
|
||
|
runfiles_envkey, runfiles_envvalue = RunfilesEnvvar(module_space)
|
||
|
if runfiles_envkey:
|
||
|
new_env[runfiles_envkey] = runfiles_envvalue
|
||
|
|
||
|
# Now look for my main python source file.
|
||
|
# The magic string percent-main-percent is replaced with the filename of the
|
||
|
# main file of the Python binary in BazelPythonSemantics.java.
|
||
|
rel_path = 'org_tensorflow/tensorflow/contrib/lite/python/tflite_convert.py'
|
||
|
if IsWindows():
|
||
|
rel_path = rel_path.replace("/", os.sep)
|
||
|
|
||
|
main_filename = os.path.join(module_space, rel_path)
|
||
|
main_filename = GetWindowsPathWithUNCPrefix(main_filename)
|
||
|
assert os.path.exists(main_filename), \
|
||
|
'Cannot exec() %r: file not found.' % main_filename
|
||
|
assert os.access(main_filename, os.R_OK), \
|
||
|
'Cannot exec() %r: file not readable.' % main_filename
|
||
|
|
||
|
program = python_program = FindPythonBinary(module_space)
|
||
|
if python_program is None:
|
||
|
raise AssertionError('Could not find python binary: ' + PYTHON_BINARY)
|
||
|
args = [python_program, main_filename] + args
|
||
|
|
||
|
os.environ.update(new_env)
|
||
|
|
||
|
try:
|
||
|
sys.stdout.flush()
|
||
|
if IsRunningFromZip():
|
||
|
# If RUN_UNDER_RUNFILES equals 1, it means we need to
|
||
|
# change directory to the right runfiles directory.
|
||
|
# (So that the data files are accessible)
|
||
|
if os.environ.get("RUN_UNDER_RUNFILES") == "1":
|
||
|
os.chdir(os.path.join(module_space, "org_tensorflow"))
|
||
|
retCode = subprocess.call(args)
|
||
|
shutil.rmtree(os.path.dirname(module_space), True)
|
||
|
exit(retCode)
|
||
|
else:
|
||
|
os.execv(args[0], args)
|
||
|
except EnvironmentError:
|
||
|
# This works from Python 2.4 all the way to 3.x.
|
||
|
e = sys.exc_info()[1]
|
||
|
# This exception occurs when os.execv() fails for some reason.
|
||
|
if not getattr(e, 'filename', None):
|
||
|
e.filename = program # Add info to error message
|
||
|
raise
|
||
|
|
||
|
if __name__ == '__main__':
|
||
|
Main()
|