]>
Commit | Line | Data |
---|---|---|
3d1f044b A |
1 | # Copyright (C) 2018 and later: Unicode, Inc. and others. |
2 | # License & terms of use: http://www.unicode.org/copyright.html | |
3 | ||
4 | # Python 2/3 Compatibility (ICU-20299) | |
5 | # TODO(ICU-20301): Remove this. | |
6 | from __future__ import print_function | |
7 | ||
8 | from . import * | |
9 | from .. import * | |
10 | from .. import utils | |
11 | from ..request_types import * | |
12 | ||
13 | def get_gnumake_rules(build_dirs, requests, makefile_vars, **kwargs): | |
14 | makefile_string = "" | |
15 | ||
16 | # Common Variables | |
17 | common_vars = kwargs["common_vars"] | |
18 | for key, value in sorted(makefile_vars.items()): | |
19 | makefile_string += "{KEY} = {VALUE}\n".format( | |
20 | KEY = key, | |
21 | VALUE = value | |
22 | ) | |
23 | makefile_string += "\n" | |
24 | ||
25 | # Directories | |
26 | dirs_timestamp_file = "{TMP_DIR}/dirs.timestamp".format(**common_vars) | |
27 | makefile_string += "DIRS = {TIMESTAMP_FILE}\n\n".format( | |
28 | TIMESTAMP_FILE = dirs_timestamp_file | |
29 | ) | |
30 | makefile_string += "{TIMESTAMP_FILE}:\n\t$(MKINSTALLDIRS) {ALL_DIRS}\n\techo timestamp > {TIMESTAMP_FILE}\n\n".format( | |
31 | TIMESTAMP_FILE = dirs_timestamp_file, | |
32 | ALL_DIRS = " ".join(build_dirs).format(**common_vars) | |
33 | ) | |
34 | ||
35 | # Generate Rules | |
36 | make_rules = [] | |
37 | for request in requests: | |
38 | make_rules += get_gnumake_rules_helper(request, **kwargs) | |
39 | ||
40 | # Main Commands | |
41 | for rule in make_rules: | |
42 | if isinstance(rule, MakeFilesVar): | |
43 | makefile_string += "{NAME} = {FILE_LIST}\n\n".format( | |
44 | NAME = rule.name, | |
45 | FILE_LIST = files_to_makefile(rule.files, wrap = True, **kwargs), | |
46 | ) | |
47 | continue | |
48 | ||
49 | if isinstance(rule, MakeStringVar): | |
50 | makefile_string += "define {NAME}\n{CONTENT}\nendef\nexport {NAME}\n\n".format( | |
51 | NAME = rule.name, | |
52 | CONTENT = rule.content | |
53 | ) | |
54 | continue | |
55 | ||
56 | assert isinstance(rule, MakeRule) | |
57 | header_line = "{OUT_FILE}: {DEP_FILES} {DEP_LITERALS} | $(DIRS)".format( | |
58 | OUT_FILE = files_to_makefile([rule.output_file], **kwargs), | |
59 | DEP_FILES = files_to_makefile(rule.dep_files, wrap = True, **kwargs), | |
60 | DEP_LITERALS = " ".join(rule.dep_literals) | |
61 | ) | |
62 | ||
63 | if len(rule.cmds) == 0: | |
64 | makefile_string += "%s\n\n" % header_line | |
65 | continue | |
66 | ||
67 | makefile_string += "{HEADER_LINE}\n{RULE_LINES}\n\n".format( | |
68 | HEADER_LINE = header_line, | |
69 | RULE_LINES = "\n".join("\t%s" % cmd for cmd in rule.cmds) | |
70 | ) | |
71 | ||
72 | return makefile_string | |
73 | ||
74 | def files_to_makefile(files, common_vars, wrap = False, **kwargs): | |
75 | if len(files) == 0: | |
76 | return "" | |
77 | dirnames = [utils.dir_for(file).format(**common_vars) for file in files] | |
78 | join_str = " \\\n\t\t" if wrap and len(files) > 2 else " " | |
79 | if len(files) == 1: | |
80 | return "%s/%s" % (dirnames[0], files[0].filename) | |
81 | elif len(set(dirnames)) == 1: | |
82 | return "$(addprefix %s/,%s)" % (dirnames[0], join_str.join(file.filename for file in files)) | |
83 | else: | |
84 | return join_str.join("%s/%s" % (d, f.filename) for d,f in zip(dirnames, files)) | |
85 | ||
86 | def get_gnumake_rules_helper(request, common_vars, **kwargs): | |
87 | ||
88 | if isinstance(request, PrintFileRequest): | |
89 | var_name = "%s_CONTENT" % request.name.upper() | |
90 | return [ | |
91 | MakeStringVar( | |
92 | name = var_name, | |
93 | content = request.content | |
94 | ), | |
95 | MakeRule( | |
96 | name = request.name, | |
97 | dep_literals = [], | |
98 | dep_files = [], | |
99 | output_file = request.output_file, | |
100 | cmds = [ | |
101 | "echo \"$${VAR_NAME}\" > {MAKEFILENAME}".format( | |
102 | VAR_NAME = var_name, | |
103 | MAKEFILENAME = files_to_makefile([request.output_file], common_vars), | |
104 | **common_vars | |
105 | ) | |
106 | ] | |
107 | ) | |
108 | ] | |
109 | ||
110 | ||
111 | if isinstance(request, CopyRequest): | |
112 | return [ | |
113 | MakeRule( | |
114 | name = request.name, | |
115 | dep_literals = [], | |
116 | dep_files = [request.input_file], | |
117 | output_file = request.output_file, | |
118 | cmds = ["cp %s %s" % ( | |
119 | files_to_makefile([request.input_file], common_vars), | |
120 | files_to_makefile([request.output_file], common_vars)) | |
121 | ] | |
122 | ) | |
123 | ] | |
124 | ||
125 | if isinstance(request, VariableRequest): | |
126 | return [ | |
127 | MakeFilesVar( | |
128 | name = request.name.upper(), | |
129 | files = request.input_files | |
130 | ) | |
131 | ] | |
132 | ||
133 | if request.tool.name == "make": | |
134 | cmd_template = "$(MAKE) {ARGS}" | |
135 | elif request.tool.name == "gentest": | |
136 | cmd_template = "$(INVOKE) $(GENTEST) {ARGS}" | |
137 | else: | |
138 | assert isinstance(request.tool, IcuTool) | |
139 | cmd_template = "$(INVOKE) $(TOOLBINDIR)/{TOOL} {{ARGS}}".format( | |
140 | TOOL = request.tool.name | |
141 | ) | |
142 | ||
143 | if isinstance(request, SingleExecutionRequest): | |
144 | cmd = utils.format_single_request_command(request, cmd_template, common_vars) | |
145 | dep_files = request.all_input_files() | |
146 | ||
147 | if len(request.output_files) > 1: | |
148 | # Special case for multiple output files: Makefile rules should have only one | |
149 | # output file apiece. More information: | |
150 | # https://www.gnu.org/software/automake/manual/html_node/Multiple-Outputs.html | |
151 | timestamp_var_name = "%s_ALL" % request.name.upper() | |
152 | timestamp_file = TmpFile("%s.timestamp" % request.name) | |
153 | rules = [ | |
154 | MakeFilesVar( | |
155 | name = timestamp_var_name, | |
156 | files = [timestamp_file] | |
157 | ), | |
158 | MakeRule( | |
159 | name = "%s_all" % request.name, | |
160 | dep_literals = [], | |
161 | dep_files = dep_files, | |
162 | output_file = timestamp_file, | |
163 | cmds = [ | |
164 | cmd, | |
165 | "echo timestamp > {MAKEFILENAME}".format( | |
166 | MAKEFILENAME = files_to_makefile([timestamp_file], common_vars) | |
167 | ) | |
168 | ] | |
169 | ) | |
170 | ] | |
171 | for i, file in enumerate(request.output_files): | |
172 | rules += [ | |
173 | MakeRule( | |
174 | name = "%s_%d" % (request.name, i), | |
175 | dep_literals = ["$(%s)" % timestamp_var_name], | |
176 | dep_files = [], | |
177 | output_file = file, | |
178 | cmds = [] | |
179 | ) | |
180 | ] | |
181 | return rules | |
182 | ||
183 | elif len(dep_files) > 5: | |
184 | # For nicer printing, for long input lists, use a helper variable. | |
185 | dep_var_name = "%s_DEPS" % request.name.upper() | |
186 | return [ | |
187 | MakeFilesVar( | |
188 | name = dep_var_name, | |
189 | files = dep_files | |
190 | ), | |
191 | MakeRule( | |
192 | name = request.name, | |
193 | dep_literals = ["$(%s)" % dep_var_name], | |
194 | dep_files = [], | |
195 | output_file = request.output_files[0], | |
196 | cmds = [cmd] | |
197 | ) | |
198 | ] | |
199 | ||
200 | else: | |
201 | return [ | |
202 | MakeRule( | |
203 | name = request.name, | |
204 | dep_literals = [], | |
205 | dep_files = dep_files, | |
206 | output_file = request.output_files[0], | |
207 | cmds = [cmd] | |
208 | ) | |
209 | ] | |
210 | ||
211 | if isinstance(request, RepeatedExecutionRequest): | |
212 | rules = [] | |
213 | dep_literals = [] | |
214 | # To keep from repeating the same dep files many times, make a variable. | |
215 | if len(request.common_dep_files) > 0: | |
216 | dep_var_name = "%s_DEPS" % request.name.upper() | |
217 | dep_literals = ["$(%s)" % dep_var_name] | |
218 | rules += [ | |
219 | MakeFilesVar( | |
220 | name = dep_var_name, | |
221 | files = request.common_dep_files | |
222 | ) | |
223 | ] | |
224 | # Add a rule for each individual file. | |
225 | for loop_vars in utils.repeated_execution_request_looper(request): | |
226 | (_, specific_dep_files, input_file, output_file) = loop_vars | |
227 | name_suffix = input_file[input_file.filename.rfind("/")+1:input_file.filename.rfind(".")] | |
228 | cmd = utils.format_repeated_request_command( | |
229 | request, | |
230 | cmd_template, | |
231 | loop_vars, | |
232 | common_vars | |
233 | ) | |
234 | rules += [ | |
235 | MakeRule( | |
236 | name = "%s_%s" % (request.name, name_suffix), | |
237 | dep_literals = dep_literals, | |
238 | dep_files = specific_dep_files + [input_file], | |
239 | output_file = output_file, | |
240 | cmds = [cmd] | |
241 | ) | |
242 | ] | |
243 | return rules | |
244 | ||
245 | assert False |