blob: 838b121afe565856ab9dbca347a0ce420ce3feed [file] [log] [blame]
# Copyright (C) 2018 and later: Unicode, Inc. and others.
# License & terms of use: http://www.unicode.org/copyright.html
from . import *
from .. import *
from .. import utils
from ..request_types import *
import os
import shutil
import subprocess
import sys
def run(build_dirs, requests, common_vars, verbose=True, **kwargs):
for bd in build_dirs:
makedirs(bd.format(**common_vars))
for request in requests:
status = run_helper(request, common_vars, verbose=verbose, **kwargs)
if status != 0:
print("!!! ERROR executing above command line: exit code %d" % status)
return 1
if verbose:
print("All data build commands executed")
return 0
def makedirs(dirs):
"""makedirs compatible between Python 2 and 3"""
try:
# Python 3 version
os.makedirs(dirs, exist_ok=True)
except TypeError as e:
# Python 2 version
try:
os.makedirs(dirs)
except OSError as e:
if e.errno != errno.EEXIST:
raise e
def run_helper(request, common_vars, platform, tool_dir, verbose, tool_cfg=None, **kwargs):
if isinstance(request, PrintFileRequest):
output_path = "{DIRNAME}/{FILENAME}".format(
DIRNAME = utils.dir_for(request.output_file).format(**common_vars),
FILENAME = request.output_file.filename,
)
if verbose:
print("Printing to file: %s" % output_path)
with open(output_path, "w") as f:
f.write(request.content)
return 0
if isinstance(request, CopyRequest):
input_path = "{DIRNAME}/{FILENAME}".format(
DIRNAME = utils.dir_for(request.input_file).format(**common_vars),
FILENAME = request.input_file.filename,
)
output_path = "{DIRNAME}/{FILENAME}".format(
DIRNAME = utils.dir_for(request.output_file).format(**common_vars),
FILENAME = request.output_file.filename,
)
if verbose:
print("Copying file to: %s" % output_path)
shutil.copyfile(input_path, output_path)
return 0
if isinstance(request, VariableRequest):
# No-op
return 0
assert isinstance(request.tool, IcuTool)
if platform == "windows":
cmd_template = "{TOOL_DIR}/{TOOL}/{TOOL_CFG}/{TOOL}.exe {{ARGS}}".format(
TOOL_DIR = tool_dir,
TOOL_CFG = tool_cfg,
TOOL = request.tool.name,
**common_vars
)
elif platform == "unix":
cmd_template = "{TOOL_DIR}/{TOOL} {{ARGS}}".format(
TOOL_DIR = tool_dir,
TOOL = request.tool.name,
**common_vars
)
elif platform == "bazel":
cmd_template = "{TOOL_DIR}/{TOOL}/{TOOL} {{ARGS}}".format(
TOOL_DIR = tool_dir,
TOOL = request.tool.name,
**common_vars
)
else:
raise ValueError("Unknown platform: %s" % platform)
if isinstance(request, RepeatedExecutionRequest):
for loop_vars in utils.repeated_execution_request_looper(request):
command_line = utils.format_repeated_request_command(
request,
cmd_template,
loop_vars,
common_vars
)
if platform == "windows":
# Note: this / to \ substitution may be too aggressive?
command_line = command_line.replace("/", "\\")
returncode = run_shell_command(command_line, platform, verbose)
if returncode != 0:
return returncode
return 0
if isinstance(request, SingleExecutionRequest):
command_line = utils.format_single_request_command(
request,
cmd_template,
common_vars
)
if platform == "windows":
# Note: this / to \ substitution may be too aggressive?
command_line = command_line.replace("/", "\\")
returncode = run_shell_command(command_line, platform, verbose)
return returncode
assert False
def run_shell_command(command_line, platform, verbose):
changed_windows_comspec = False
# If the command line length on Windows exceeds the absolute maximum that CMD supports (8191), then
# we temporarily switch over to use PowerShell for the command, and then switch back to CMD.
# We don't want to use PowerShell for everything though, as it tends to be slower.
if (platform == "windows") and (len(command_line) > 8190):
if verbose:
print("Command length exceeds the max length for CMD on Windows, using PowerShell instead.")
previous_comspec = os.environ["COMSPEC"]
os.environ["COMSPEC"] = 'powershell'
changed_windows_comspec = True
if verbose:
print("Running: %s" % command_line)
returncode = subprocess.call(
command_line,
shell = True
)
else:
# Pipe output to /dev/null in quiet mode
with open(os.devnull, "w") as devnull:
returncode = subprocess.call(
command_line,
shell = True,
stdout = devnull,
stderr = devnull
)
if changed_windows_comspec:
os.environ["COMSPEC"] = previous_comspec
return returncode