246 lines
8.7 KiB
Python
246 lines
8.7 KiB
Python
# 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 *
|
|
|
|
def get_gnumake_rules(build_dirs, requests, makefile_vars, **kwargs):
|
|
makefile_string = ""
|
|
|
|
# Common Variables
|
|
common_vars = kwargs["common_vars"]
|
|
for key, value in sorted(makefile_vars.items()):
|
|
makefile_string += "{KEY} = {VALUE}\n".format(
|
|
KEY = key,
|
|
VALUE = value
|
|
)
|
|
makefile_string += "\n"
|
|
|
|
# Directories
|
|
dirs_timestamp_file = "{TMP_DIR}/dirs.timestamp".format(**common_vars)
|
|
makefile_string += "DIRS = {TIMESTAMP_FILE}\n\n".format(
|
|
TIMESTAMP_FILE = dirs_timestamp_file
|
|
)
|
|
makefile_string += "{TIMESTAMP_FILE}:\n\t$(MKINSTALLDIRS) {ALL_DIRS}\n\techo timestamp > {TIMESTAMP_FILE}\n\n".format(
|
|
TIMESTAMP_FILE = dirs_timestamp_file,
|
|
ALL_DIRS = " ".join(build_dirs).format(**common_vars)
|
|
)
|
|
|
|
# Generate Rules
|
|
make_rules = []
|
|
for request in requests:
|
|
make_rules += get_gnumake_rules_helper(request, **kwargs)
|
|
|
|
# Main Commands
|
|
for rule in make_rules:
|
|
if isinstance(rule, MakeFilesVar):
|
|
makefile_string += "{NAME} = {FILE_LIST}\n\n".format(
|
|
NAME = rule.name,
|
|
FILE_LIST = files_to_makefile(rule.files, wrap = True, **kwargs),
|
|
)
|
|
continue
|
|
|
|
if isinstance(rule, MakeStringVar):
|
|
makefile_string += "define {NAME}\n{CONTENT}\nendef\nexport {NAME}\n\n".format(
|
|
NAME = rule.name,
|
|
CONTENT = rule.content
|
|
)
|
|
continue
|
|
|
|
assert isinstance(rule, MakeRule)
|
|
header_line = "{OUT_FILE}: {DEP_FILES} {DEP_LITERALS} | $(DIRS)".format(
|
|
OUT_FILE = files_to_makefile([rule.output_file], **kwargs),
|
|
DEP_FILES = files_to_makefile(rule.dep_files, wrap = True, **kwargs),
|
|
DEP_LITERALS = " ".join(rule.dep_literals)
|
|
)
|
|
|
|
if len(rule.cmds) == 0:
|
|
makefile_string += "%s\n\n" % header_line
|
|
continue
|
|
|
|
makefile_string += "{HEADER_LINE}\n{RULE_LINES}\n\n".format(
|
|
HEADER_LINE = header_line,
|
|
RULE_LINES = "\n".join("\t%s" % cmd for cmd in rule.cmds)
|
|
)
|
|
|
|
return makefile_string
|
|
|
|
def files_to_makefile(files, common_vars, wrap = False, **kwargs):
|
|
if len(files) == 0:
|
|
return ""
|
|
dirnames = [utils.dir_for(file).format(**common_vars) for file in files]
|
|
join_str = " \\\n\t\t" if wrap and len(files) > 2 else " "
|
|
if len(files) == 1:
|
|
return "%s/%s" % (dirnames[0], files[0].filename)
|
|
elif len(set(dirnames)) == 1:
|
|
return "$(addprefix %s/,%s)" % (dirnames[0], join_str.join(file.filename for file in files))
|
|
else:
|
|
return join_str.join("%s/%s" % (d, f.filename) for d,f in zip(dirnames, files))
|
|
|
|
def get_gnumake_rules_helper(request, common_vars, **kwargs):
|
|
|
|
if isinstance(request, PrintFileRequest):
|
|
var_name = "%s_CONTENT" % request.name.upper()
|
|
return [
|
|
MakeStringVar(
|
|
name = var_name,
|
|
content = request.content
|
|
),
|
|
MakeRule(
|
|
name = request.name,
|
|
dep_literals = [],
|
|
dep_files = [],
|
|
output_file = request.output_file,
|
|
cmds = [
|
|
"echo \"$${VAR_NAME}\" > {MAKEFILENAME}".format(
|
|
VAR_NAME = var_name,
|
|
MAKEFILENAME = files_to_makefile([request.output_file], common_vars),
|
|
**common_vars
|
|
)
|
|
]
|
|
)
|
|
]
|
|
|
|
|
|
if isinstance(request, CopyRequest):
|
|
return [
|
|
MakeRule(
|
|
name = request.name,
|
|
dep_literals = [],
|
|
dep_files = [request.input_file],
|
|
output_file = request.output_file,
|
|
cmds = ["cp %s %s" % (
|
|
files_to_makefile([request.input_file], common_vars),
|
|
files_to_makefile([request.output_file], common_vars))
|
|
]
|
|
)
|
|
]
|
|
|
|
if isinstance(request, VariableRequest):
|
|
return [
|
|
MakeFilesVar(
|
|
name = request.name.upper(),
|
|
files = request.input_files
|
|
)
|
|
]
|
|
|
|
if request.tool.name == "make":
|
|
cmd_template = "$(MAKE) {ARGS}"
|
|
elif request.tool.name == "gentest":
|
|
cmd_template = "$(INVOKE) $(GENTEST) {ARGS}"
|
|
else:
|
|
assert isinstance(request.tool, IcuTool)
|
|
cmd_template = "$(INVOKE) $(TOOLBINDIR)/{TOOL} {{ARGS}}".format(
|
|
TOOL = request.tool.name
|
|
)
|
|
|
|
if isinstance(request, SingleExecutionRequest):
|
|
cmd = utils.format_single_request_command(request, cmd_template, common_vars)
|
|
dep_files = request.all_input_files()
|
|
|
|
if len(request.output_files) > 1:
|
|
# Special case for multiple output files: Makefile rules should have only one
|
|
# output file apiece. More information:
|
|
# https://www.gnu.org/software/automake/manual/html_node/Multiple-Outputs.html
|
|
timestamp_var_name = "%s_ALL" % request.name.upper()
|
|
timestamp_file = TmpFile("%s.timestamp" % request.name)
|
|
rules = [
|
|
MakeFilesVar(
|
|
name = timestamp_var_name,
|
|
files = [timestamp_file]
|
|
),
|
|
MakeRule(
|
|
name = "%s_all" % request.name,
|
|
dep_literals = [],
|
|
dep_files = dep_files,
|
|
output_file = timestamp_file,
|
|
cmds = [
|
|
cmd,
|
|
"echo timestamp > {MAKEFILENAME}".format(
|
|
MAKEFILENAME = files_to_makefile([timestamp_file], common_vars)
|
|
)
|
|
]
|
|
)
|
|
]
|
|
for i, file in enumerate(request.output_files):
|
|
rules += [
|
|
MakeRule(
|
|
name = "%s_%d" % (request.name, i),
|
|
dep_literals = ["$(%s)" % timestamp_var_name],
|
|
dep_files = [],
|
|
output_file = file,
|
|
cmds = []
|
|
)
|
|
]
|
|
return rules
|
|
|
|
elif len(dep_files) > 5:
|
|
# For nicer printing, for long input lists, use a helper variable.
|
|
dep_var_name = "%s_DEPS" % request.name.upper()
|
|
return [
|
|
MakeFilesVar(
|
|
name = dep_var_name,
|
|
files = dep_files
|
|
),
|
|
MakeRule(
|
|
name = request.name,
|
|
dep_literals = ["$(%s)" % dep_var_name],
|
|
dep_files = [],
|
|
output_file = request.output_files[0],
|
|
cmds = [cmd]
|
|
)
|
|
]
|
|
|
|
else:
|
|
return [
|
|
MakeRule(
|
|
name = request.name,
|
|
dep_literals = [],
|
|
dep_files = dep_files,
|
|
output_file = request.output_files[0],
|
|
cmds = [cmd]
|
|
)
|
|
]
|
|
|
|
if isinstance(request, RepeatedExecutionRequest):
|
|
rules = []
|
|
dep_literals = []
|
|
# To keep from repeating the same dep files many times, make a variable.
|
|
if len(request.common_dep_files) > 0:
|
|
dep_var_name = "%s_DEPS" % request.name.upper()
|
|
dep_literals = ["$(%s)" % dep_var_name]
|
|
rules += [
|
|
MakeFilesVar(
|
|
name = dep_var_name,
|
|
files = request.common_dep_files
|
|
)
|
|
]
|
|
# Add a rule for each individual file.
|
|
for loop_vars in utils.repeated_execution_request_looper(request):
|
|
(_, specific_dep_files, input_file, output_file) = loop_vars
|
|
name_suffix = input_file[input_file.filename.rfind("/")+1:input_file.filename.rfind(".")]
|
|
cmd = utils.format_repeated_request_command(
|
|
request,
|
|
cmd_template,
|
|
loop_vars,
|
|
common_vars
|
|
)
|
|
rules += [
|
|
MakeRule(
|
|
name = "%s_%s" % (request.name, name_suffix),
|
|
dep_literals = dep_literals,
|
|
dep_files = specific_dep_files + [input_file],
|
|
output_file = output_file,
|
|
cmds = [cmd]
|
|
)
|
|
]
|
|
return rules
|
|
|
|
assert False
|