blob: 9b2005b07d91de0f7dd67248744702da6eb53db1 [file] [log] [blame]
# 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