1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
|
# Copyright (C) 2018 and later: Unicode, Inc. and others.
# License & terms of use: http://www.unicode.org/copyright.html
# Python 2/3 Compatibility (ICU-20299)
# TODO(ICU-20301): Remove this.
from __future__ import print_function
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"):
previous_comspec = os.environ["COMSPEC"]
# Add 7 to the length for the argument /c with quotes.
# For example: C:\WINDOWS\system32\cmd.exe /c "<command_line>"
if ((len(previous_comspec) + len(command_line) + 7) > 8190):
if verbose:
print("Command length exceeds the max length for CMD on Windows, using PowerShell instead.")
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
if returncode != 0:
print("Command failed: %s" % command_line, file=sys.stderr)
return returncode
|