reduce-headers revision 1.4 1 1.1 mrg #! /usr/bin/python2
2 1.1 mrg import os.path
3 1.1 mrg import sys
4 1.1 mrg import shlex
5 1.1 mrg import re
6 1.1 mrg import tempfile
7 1.1 mrg import copy
8 1.1 mrg
9 1.1 mrg from headerutils import *
10 1.1 mrg
11 1.1 mrg requires = { }
12 1.1 mrg provides = { }
13 1.1 mrg
14 1.1 mrg no_remove = [ "system.h", "coretypes.h", "config.h" , "bconfig.h", "backend.h" ]
15 1.1 mrg
16 1.1 mrg # These targets are the ones which provide "coverage". Typically, if any
17 1.1 mrg # target is going to fail compilation, it's one of these. This was determined
18 1.1 mrg # during the initial runs of reduce-headers... On a full set of target builds,
19 1.1 mrg # every failure which occured was triggered by one of these.
20 1.1 mrg # This list is used during target-list construction simply to put any of these
21 1.1 mrg # *first* in the candidate list, increasing the probability that a failure is
22 1.1 mrg # found quickly.
23 1.1 mrg target_priority = [
24 1.1 mrg "aarch64-linux-gnu",
25 1.1 mrg "arm-netbsdelf",
26 1.1 mrg "c6x-elf",
27 1.1 mrg "epiphany-elf",
28 1.1 mrg "hppa2.0-hpux10.1",
29 1.1 mrg "i686-mingw32crt",
30 1.1 mrg "i686-pc-msdosdjgpp",
31 1.1 mrg "mipsel-elf",
32 1.1 mrg "powerpc-eabisimaltivec",
33 1.1 mrg "rs6000-ibm-aix5.1.0",
34 1.1 mrg "sh-superh-elf",
35 1.4 mrg "sparc64-elf"
36 1.1 mrg ]
37 1.1 mrg
38 1.1 mrg
39 1.1 mrg target_dir = ""
40 1.1 mrg build_dir = ""
41 1.1 mrg ignore_list = list()
42 1.1 mrg target_builds = list()
43 1.1 mrg
44 1.1 mrg target_dict = { }
45 1.1 mrg header_dict = { }
46 1.1 mrg search_path = [ ".", "../include", "../libcpp/include" ]
47 1.1 mrg
48 1.1 mrg remove_count = { }
49 1.1 mrg
50 1.1 mrg
51 1.1 mrg # Given a header name, normalize it. ie. cp/cp-tree.h could be in gcc, while
52 1.1 mrg # the same header could be referenced from within the cp subdirectory as
53 1.1 mrg # just cp-tree.h
54 1.1 mrg # for now, just assume basenames are unique
55 1.1 mrg
56 1.1 mrg def normalize_header (header):
57 1.1 mrg return os.path.basename (header)
58 1.1 mrg
59 1.1 mrg
60 1.1 mrg # Adds a header file and its sub-includes to the global dictionary if they
61 1.1 mrg # aren't already there. Specify s_path since different build directories may
62 1.1 mrg # append themselves on demand to the global list.
63 1.1 mrg # return entry for the specified header, knowing all sub entries are completed
64 1.1 mrg
65 1.1 mrg def get_header_info (header, s_path):
66 1.1 mrg global header_dict
67 1.1 mrg global empty_iinfo
68 1.1 mrg process_list = list ()
69 1.1 mrg location = ""
70 1.1 mrg bname = ""
71 1.1 mrg bname_iinfo = empty_iinfo
72 1.1 mrg for path in s_path:
73 1.1 mrg if os.path.exists (path + "/" + header):
74 1.1 mrg location = path + "/" + header
75 1.1 mrg break
76 1.1 mrg
77 1.1 mrg if location:
78 1.1 mrg bname = normalize_header (location)
79 1.1 mrg if header_dict.get (bname):
80 1.1 mrg bname_iinfo = header_dict[bname]
81 1.1 mrg loc2 = ii_path (bname_iinfo)+ "/" + bname
82 1.1 mrg if loc2[:2] == "./":
83 1.1 mrg loc2 = loc2[2:]
84 1.1 mrg if location[:2] == "./":
85 1.1 mrg location = location[2:]
86 1.1 mrg if loc2 != location:
87 1.1 mrg # Don't use the cache if it isnt the right one.
88 1.1 mrg bname_iinfo = process_ii_macro (location)
89 1.1 mrg return bname_iinfo
90 1.1 mrg
91 1.1 mrg bname_iinfo = process_ii_macro (location)
92 1.1 mrg header_dict[bname] = bname_iinfo
93 1.1 mrg # now decend into the include tree
94 1.1 mrg for i in ii_include_list (bname_iinfo):
95 1.1 mrg get_header_info (i, s_path)
96 1.1 mrg else:
97 1.1 mrg # if the file isnt in the source directories, look in the build and target
98 1.1 mrg # directories. If it is here, then aggregate all the versions.
99 1.1 mrg location = build_dir + "/gcc/" + header
100 1.1 mrg build_inc = target_inc = False
101 1.1 mrg if os.path.exists (location):
102 1.1 mrg build_inc = True
103 1.1 mrg for x in target_dict:
104 1.1 mrg location = target_dict[x] + "/gcc/" + header
105 1.1 mrg if os.path.exists (location):
106 1.1 mrg target_inc = True
107 1.1 mrg break
108 1.1 mrg
109 1.1 mrg if (build_inc or target_inc):
110 1.1 mrg bname = normalize_header(header)
111 1.1 mrg defines = set()
112 1.1 mrg consumes = set()
113 1.1 mrg incl = set()
114 1.1 mrg if build_inc:
115 1.1 mrg iinfo = process_ii_macro (build_dir + "/gcc/" + header)
116 1.1 mrg defines = set (ii_macro_define (iinfo))
117 1.1 mrg consumes = set (ii_macro_consume (iinfo))
118 1.1 mrg incl = set (ii_include_list (iinfo))
119 1.1 mrg
120 1.1 mrg if (target_inc):
121 1.1 mrg for x in target_dict:
122 1.1 mrg location = target_dict[x] + "/gcc/" + header
123 1.1 mrg if os.path.exists (location):
124 1.1 mrg iinfo = process_ii_macro (location)
125 1.1 mrg defines.update (ii_macro_define (iinfo))
126 1.1 mrg consumes.update (ii_macro_consume (iinfo))
127 1.1 mrg incl.update (ii_include_list (iinfo))
128 1.1 mrg
129 1.1 mrg bname_iinfo = (header, "build", list(incl), list(), list(consumes), list(defines), list(), list())
130 1.1 mrg
131 1.1 mrg header_dict[bname] = bname_iinfo
132 1.1 mrg for i in incl:
133 1.1 mrg get_header_info (i, s_path)
134 1.1 mrg
135 1.1 mrg return bname_iinfo
136 1.1 mrg
137 1.1 mrg
138 1.1 mrg # return a list of all headers brought in by this header
139 1.1 mrg def all_headers (fname):
140 1.1 mrg global header_dict
141 1.1 mrg headers_stack = list()
142 1.1 mrg headers_list = list()
143 1.1 mrg if header_dict.get (fname) == None:
144 1.1 mrg return list ()
145 1.1 mrg for y in ii_include_list (header_dict[fname]):
146 1.1 mrg headers_stack.append (y)
147 1.1 mrg
148 1.1 mrg while headers_stack:
149 1.1 mrg h = headers_stack.pop ()
150 1.1 mrg hn = normalize_header (h)
151 1.1 mrg if hn not in headers_list:
152 1.1 mrg headers_list.append (hn)
153 1.1 mrg if header_dict.get(hn):
154 1.1 mrg for y in ii_include_list (header_dict[hn]):
155 1.1 mrg if normalize_header (y) not in headers_list:
156 1.1 mrg headers_stack.append (y)
157 1.1 mrg
158 1.1 mrg return headers_list
159 1.1 mrg
160 1.1 mrg
161 1.1 mrg
162 1.1 mrg
163 1.1 mrg # Search bld_dir for all target tuples, confirm that they have a build path with
164 1.1 mrg # bld_dir/target-tuple/gcc, and build a dictionary of build paths indexed by
165 1.1 mrg # target tuple..
166 1.1 mrg
167 1.1 mrg def build_target_dict (bld_dir, just_these):
168 1.1 mrg global target_dict
169 1.1 mrg target_doct = { }
170 1.1 mrg error = False
171 1.1 mrg if os.path.exists (bld_dir):
172 1.1 mrg if just_these:
173 1.1 mrg ls = just_these
174 1.1 mrg else:
175 1.1 mrg ls = os.listdir(bld_dir)
176 1.1 mrg for t in ls:
177 1.1 mrg if t.find("-") != -1:
178 1.1 mrg target = t.strip()
179 1.1 mrg tpath = bld_dir + "/" + target
180 1.1 mrg if not os.path.exists (tpath + "/gcc"):
181 1.1 mrg print "Error: gcc build directory for target " + t + " Does not exist: " + tpath + "/gcc"
182 1.1 mrg error = True
183 1.1 mrg else:
184 1.1 mrg target_dict[target] = tpath
185 1.1 mrg
186 1.1 mrg if error:
187 1.1 mrg target_dict = { }
188 1.1 mrg
189 1.1 mrg def get_obj_name (src_file):
190 1.1 mrg if src_file[-2:] == ".c":
191 1.1 mrg return src_file.replace (".c", ".o")
192 1.1 mrg elif src_file[-3:] == ".cc":
193 1.1 mrg return src_file.replace (".cc", ".o")
194 1.1 mrg return ""
195 1.1 mrg
196 1.1 mrg def target_obj_exists (target, obj_name):
197 1.1 mrg global target_dict
198 1.1 mrg # look in a subdir if src has a subdir, then check gcc base directory.
199 1.1 mrg if target_dict.get(target):
200 1.1 mrg obj = target_dict[target] + "/gcc/" + obj_name
201 1.1 mrg if not os.path.exists (obj):
202 1.1 mrg obj = target_dict[target] + "/gcc/" + os.path.basename(obj_name)
203 1.1 mrg if os.path.exists (obj):
204 1.1 mrg return True
205 1.1 mrg return False
206 1.1 mrg
207 1.1 mrg # Given a src file, return a list of targets which may build this file.
208 1.1 mrg def find_targets (src_file):
209 1.1 mrg global target_dict
210 1.1 mrg targ_list = list()
211 1.1 mrg obj_name = get_obj_name (src_file)
212 1.1 mrg if not obj_name:
213 1.1 mrg print "Error: " + src_file + " - Cannot determine object name."
214 1.1 mrg return list()
215 1.1 mrg
216 1.1 mrg # Put the high priority targets which tend to trigger failures first
217 1.1 mrg for target in target_priority:
218 1.1 mrg if target_obj_exists (target, obj_name):
219 1.1 mrg targ_list.append ((target, target_dict[target]))
220 1.1 mrg
221 1.1 mrg for target in target_dict:
222 1.1 mrg if target not in target_priority and target_obj_exists (target, obj_name):
223 1.1 mrg targ_list.append ((target, target_dict[target]))
224 1.1 mrg
225 1.1 mrg return targ_list
226 1.1 mrg
227 1.1 mrg
228 1.1 mrg def try_to_remove (src_file, h_list, verbose):
229 1.1 mrg global target_dict
230 1.1 mrg global header_dict
231 1.1 mrg global build_dir
232 1.1 mrg
233 1.1 mrg # build from scratch each time
234 1.1 mrg header_dict = { }
235 1.1 mrg summary = ""
236 1.1 mrg rmcount = 0
237 1.1 mrg
238 1.1 mrg because = { }
239 1.1 mrg src_info = process_ii_macro_src (src_file)
240 1.1 mrg src_data = ii_src (src_info)
241 1.1 mrg if src_data:
242 1.1 mrg inclist = ii_include_list_non_cond (src_info)
243 1.1 mrg # work is done if there are no includes to check
244 1.1 mrg if not inclist:
245 1.1 mrg return src_file + ": No include files to attempt to remove"
246 1.1 mrg
247 1.1 mrg # work on the include list in reverse.
248 1.1 mrg inclist.reverse()
249 1.1 mrg
250 1.1 mrg # Get the target list
251 1.1 mrg targ_list = list()
252 1.1 mrg targ_list = find_targets (src_file)
253 1.1 mrg
254 1.1 mrg spath = search_path
255 1.1 mrg if os.path.dirname (src_file):
256 1.1 mrg spath.append (os.path.dirname (src_file))
257 1.1 mrg
258 1.1 mrg hostbuild = True
259 1.1 mrg if src_file.find("config/") != -1:
260 1.1 mrg # config files dont usually build on the host
261 1.1 mrg hostbuild = False
262 1.1 mrg obn = get_obj_name (os.path.basename (src_file))
263 1.1 mrg if obn and os.path.exists (build_dir + "/gcc/" + obn):
264 1.1 mrg hostbuild = True
265 1.1 mrg if not target_dict:
266 1.1 mrg summary = src_file + ": Target builds are required for config files. None found."
267 1.1 mrg print summary
268 1.1 mrg return summary
269 1.1 mrg if not targ_list:
270 1.1 mrg summary =src_file + ": Cannot find any targets which build this file."
271 1.1 mrg print summary
272 1.1 mrg return summary
273 1.1 mrg
274 1.1 mrg if hostbuild:
275 1.1 mrg # confirm it actually builds before we do anything
276 1.1 mrg print "Confirming source file builds"
277 1.1 mrg res = get_make_output (build_dir + "/gcc", "all")
278 1.1 mrg if res[0] != 0:
279 1.1 mrg message = "Error: " + src_file + " does not build currently."
280 1.1 mrg summary = src_file + " does not build on host."
281 1.1 mrg print message
282 1.1 mrg print res[1]
283 1.1 mrg if verbose:
284 1.1 mrg verbose.write (message + "\n")
285 1.1 mrg verbose.write (res[1]+ "\n")
286 1.1 mrg return summary
287 1.1 mrg
288 1.1 mrg src_requires = set (ii_macro_consume (src_info))
289 1.1 mrg for macro in src_requires:
290 1.1 mrg because[macro] = src_file
291 1.1 mrg header_seen = list ()
292 1.1 mrg
293 1.1 mrg os.rename (src_file, src_file + ".bak")
294 1.1 mrg src_orig = copy.deepcopy (src_data)
295 1.1 mrg src_tmp = copy.deepcopy (src_data)
296 1.1 mrg
297 1.1 mrg try:
298 1.1 mrg # process the includes from bottom to top. This is because we know that
299 1.1 mrg # later includes have are known to be needed, so any dependency from this
300 1.1 mrg # header is a true dependency
301 1.1 mrg for inc_file in inclist:
302 1.1 mrg inc_file_norm = normalize_header (inc_file)
303 1.1 mrg
304 1.1 mrg if inc_file in no_remove:
305 1.1 mrg continue
306 1.1 mrg if len (h_list) != 0 and inc_file_norm not in h_list:
307 1.1 mrg continue
308 1.1 mrg if inc_file_norm[0:3] == "gt-":
309 1.1 mrg continue
310 1.1 mrg if inc_file_norm[0:6] == "gtype-":
311 1.1 mrg continue
312 1.1 mrg if inc_file_norm.replace(".h",".c") == os.path.basename(src_file):
313 1.1 mrg continue
314 1.1 mrg
315 1.1 mrg lookfor = ii_src_line(src_info)[inc_file]
316 1.1 mrg src_tmp.remove (lookfor)
317 1.1 mrg message = "Trying " + src_file + " without " + inc_file
318 1.1 mrg print message
319 1.1 mrg if verbose:
320 1.1 mrg verbose.write (message + "\n")
321 1.1 mrg out = open(src_file, "w")
322 1.1 mrg for line in src_tmp:
323 1.1 mrg out.write (line)
324 1.1 mrg out.close()
325 1.1 mrg
326 1.1 mrg keep = False
327 1.1 mrg if hostbuild:
328 1.1 mrg res = get_make_output (build_dir + "/gcc", "all")
329 1.1 mrg else:
330 1.1 mrg res = (0, "")
331 1.1 mrg
332 1.1 mrg rc = res[0]
333 1.1 mrg message = "Passed Host build"
334 1.1 mrg if (rc != 0):
335 1.1 mrg # host build failed
336 1.1 mrg message = "Compilation failed:\n";
337 1.1 mrg keep = True
338 1.1 mrg else:
339 1.1 mrg if targ_list:
340 1.1 mrg objfile = get_obj_name (src_file)
341 1.1 mrg t1 = targ_list[0]
342 1.1 mrg if objfile and os.path.exists(t1[1] +"/gcc/"+objfile):
343 1.1 mrg res = get_make_output_parallel (targ_list, objfile, 0)
344 1.1 mrg else:
345 1.1 mrg res = get_make_output_parallel (targ_list, "all-gcc", 0)
346 1.1 mrg rc = res[0]
347 1.1 mrg if rc != 0:
348 1.1 mrg message = "Compilation failed on TARGET : " + res[2]
349 1.1 mrg keep = True
350 1.1 mrg else:
351 1.1 mrg message = "Passed host and target builds"
352 1.1 mrg
353 1.1 mrg if keep:
354 1.1 mrg print message + "\n"
355 1.1 mrg
356 1.1 mrg if (rc != 0):
357 1.1 mrg if verbose:
358 1.1 mrg verbose.write (message + "\n");
359 1.1 mrg verbose.write (res[1])
360 1.1 mrg verbose.write ("\n");
361 1.1 mrg if os.path.exists (inc_file):
362 1.1 mrg ilog = open(inc_file+".log","a")
363 1.1 mrg ilog.write (message + " for " + src_file + ":\n\n");
364 1.1 mrg ilog.write ("============================================\n");
365 1.1 mrg ilog.write (res[1])
366 1.1 mrg ilog.write ("\n");
367 1.1 mrg ilog.close()
368 1.1 mrg if os.path.exists (src_file):
369 1.1 mrg ilog = open(src_file+".log","a")
370 1.1 mrg ilog.write (message + " for " +inc_file + ":\n\n");
371 1.1 mrg ilog.write ("============================================\n");
372 1.1 mrg ilog.write (res[1])
373 1.1 mrg ilog.write ("\n");
374 1.1 mrg ilog.close()
375 1.1 mrg
376 1.1 mrg # Given a sequence where :
377 1.1 mrg # #include "tm.h"
378 1.1 mrg # #include "target.h" // includes tm.h
379 1.1 mrg
380 1.1 mrg # target.h was required, and when attempting to remove tm.h we'd see that
381 1.1 mrg # all the macro defintions are "required" since they all look like:
382 1.1 mrg # #ifndef HAVE_blah
383 1.1 mrg # #define HAVE_blah
384 1.1 mrg # endif
385 1.1 mrg
386 1.1 mrg # when target.h was found to be required, tm.h will be tagged as included.
387 1.1 mrg # so when we get this far, we know we dont have to check the macros for
388 1.1 mrg # tm.h since we know it is already been included.
389 1.1 mrg
390 1.1 mrg if inc_file_norm not in header_seen:
391 1.1 mrg iinfo = get_header_info (inc_file, spath)
392 1.1 mrg newlist = all_headers (inc_file_norm)
393 1.1 mrg if ii_path(iinfo) == "build" and not target_dict:
394 1.1 mrg keep = True
395 1.1 mrg text = message + " : Will not remove a build file without some targets."
396 1.1 mrg print text
397 1.1 mrg ilog = open(src_file+".log","a")
398 1.1 mrg ilog.write (text +"\n")
399 1.1 mrg ilog.write ("============================================\n");
400 1.1 mrg ilog.close()
401 1.1 mrg ilog = open("reduce-headers-kept.log","a")
402 1.1 mrg ilog.write (src_file + " " + text +"\n")
403 1.1 mrg ilog.close()
404 1.1 mrg else:
405 1.1 mrg newlist = list()
406 1.1 mrg if not keep and inc_file_norm not in header_seen:
407 1.1 mrg # now look for any macro requirements.
408 1.1 mrg for h in newlist:
409 1.1 mrg if not h in header_seen:
410 1.1 mrg if header_dict.get(h):
411 1.1 mrg defined = ii_macro_define (header_dict[h])
412 1.1 mrg for dep in defined:
413 1.1 mrg if dep in src_requires and dep not in ignore_list:
414 1.1 mrg keep = True;
415 1.1 mrg text = message + ", but must keep " + inc_file + " because it provides " + dep
416 1.1 mrg if because.get(dep) != None:
417 1.1 mrg text = text + " Possibly required by " + because[dep]
418 1.1 mrg print text
419 1.1 mrg ilog = open(inc_file+".log","a")
420 1.1 mrg ilog.write (because[dep]+": Requires [dep] in "+src_file+"\n")
421 1.1 mrg ilog.write ("============================================\n");
422 1.1 mrg ilog.close()
423 1.1 mrg ilog = open(src_file+".log","a")
424 1.1 mrg ilog.write (text +"\n")
425 1.1 mrg ilog.write ("============================================\n");
426 1.1 mrg ilog.close()
427 1.1 mrg ilog = open("reduce-headers-kept.log","a")
428 1.1 mrg ilog.write (src_file + " " + text +"\n")
429 1.1 mrg ilog.close()
430 1.1 mrg if verbose:
431 1.1 mrg verbose.write (text + "\n")
432 1.1 mrg
433 1.1 mrg if keep:
434 1.1 mrg # add all headers 'consumes' to src_requires list, and mark as seen
435 1.1 mrg for h in newlist:
436 1.1 mrg if not h in header_seen:
437 1.1 mrg header_seen.append (h)
438 1.1 mrg if header_dict.get(h):
439 1.1 mrg consume = ii_macro_consume (header_dict[h])
440 1.1 mrg for dep in consume:
441 1.1 mrg if dep not in src_requires:
442 1.1 mrg src_requires.add (dep)
443 1.1 mrg if because.get(dep) == None:
444 1.1 mrg because[dep] = inc_file
445 1.1 mrg
446 1.1 mrg src_tmp = copy.deepcopy (src_data)
447 1.1 mrg else:
448 1.1 mrg print message + " --> removing " + inc_file + "\n"
449 1.1 mrg rmcount += 1
450 1.1 mrg if verbose:
451 1.1 mrg verbose.write (message + " --> removing " + inc_file + "\n")
452 1.1 mrg if remove_count.get(inc_file) == None:
453 1.1 mrg remove_count[inc_file] = 1
454 1.1 mrg else:
455 1.1 mrg remove_count[inc_file] += 1
456 1.1 mrg src_data = copy.deepcopy (src_tmp)
457 1.1 mrg except:
458 1.1 mrg print "Interuption: restoring original file"
459 1.1 mrg out = open(src_file, "w")
460 1.1 mrg for line in src_orig:
461 1.1 mrg out.write (line)
462 1.1 mrg out.close()
463 1.1 mrg raise
464 1.1 mrg
465 1.1 mrg # copy current version, since it is the "right" one now.
466 1.1 mrg out = open(src_file, "w")
467 1.1 mrg for line in src_data:
468 1.1 mrg out.write (line)
469 1.1 mrg out.close()
470 1.1 mrg
471 1.1 mrg # Try a final host bootstrap build to make sure everything is kosher.
472 1.1 mrg if hostbuild:
473 1.1 mrg res = get_make_output (build_dir, "all")
474 1.1 mrg rc = res[0]
475 1.1 mrg if (rc != 0):
476 1.1 mrg # host build failed! return to original version
477 1.1 mrg print "Error: " + src_file + " Failed to bootstrap at end!!! restoring."
478 1.1 mrg print " Bad version at " + src_file + ".bad"
479 1.1 mrg os.rename (src_file, src_file + ".bad")
480 1.1 mrg out = open(src_file, "w")
481 1.1 mrg for line in src_orig:
482 1.1 mrg out.write (line)
483 1.1 mrg out.close()
484 1.1 mrg return src_file + ": failed to build after reduction. Restored original"
485 1.1 mrg
486 1.1 mrg if src_data == src_orig:
487 1.1 mrg summary = src_file + ": No change."
488 1.1 mrg else:
489 1.1 mrg summary = src_file + ": Reduction performed, "+str(rmcount)+" includes removed."
490 1.1 mrg print summary
491 1.1 mrg return summary
492 1.1 mrg
493 1.1 mrg only_h = list ()
494 1.1 mrg ignore_cond = False
495 1.1 mrg
496 1.1 mrg usage = False
497 1.1 mrg src = list()
498 1.1 mrg only_targs = list ()
499 1.1 mrg for x in sys.argv[1:]:
500 1.1 mrg if x[0:2] == "-b":
501 1.1 mrg build_dir = x[2:]
502 1.1 mrg elif x[0:2] == "-f":
503 1.1 mrg fn = normalize_header (x[2:])
504 1.1 mrg if fn not in only_h:
505 1.1 mrg only_h.append (fn)
506 1.1 mrg elif x[0:2] == "-h":
507 1.1 mrg usage = True
508 1.1 mrg elif x[0:2] == "-d":
509 1.1 mrg ignore_cond = True
510 1.1 mrg elif x[0:2] == "-D":
511 1.1 mrg ignore_list.append(x[2:])
512 1.1 mrg elif x[0:2] == "-T":
513 1.1 mrg only_targs.append(x[2:])
514 1.1 mrg elif x[0:2] == "-t":
515 1.1 mrg target_dir = x[2:]
516 1.1 mrg elif x[0] == "-":
517 1.1 mrg print "Error: Unrecognized option " + x
518 1.1 mrg usgae = True
519 1.1 mrg else:
520 1.1 mrg if not os.path.exists (x):
521 1.1 mrg print "Error: specified file " + x + " does not exist."
522 1.1 mrg usage = True
523 1.1 mrg else:
524 1.1 mrg src.append (x)
525 1.1 mrg
526 1.1 mrg if target_dir:
527 1.1 mrg build_target_dict (target_dir, only_targs)
528 1.1 mrg
529 1.1 mrg if build_dir == "" and target_dir == "":
530 1.1 mrg print "Error: Must specify a build directory, and/or a target directory."
531 1.1 mrg usage = True
532 1.1 mrg
533 1.1 mrg if build_dir and not os.path.exists (build_dir):
534 1.1 mrg print "Error: specified build directory does not exist : " + build_dir
535 1.1 mrg usage = True
536 1.1 mrg
537 1.1 mrg if target_dir and not os.path.exists (target_dir):
538 1.1 mrg print "Error: specified target directory does not exist : " + target_dir
539 1.1 mrg usage = True
540 1.1 mrg
541 1.1 mrg if usage:
542 1.1 mrg print "Attempts to remove extraneous include files from source files."
543 1.1 mrg print " "
544 1.1 mrg print "Should be run from the main gcc source directory, and works on a target"
545 1.1 mrg print "directory, as we attempt to make the 'all' target."
546 1.1 mrg print " "
547 1.1 mrg print "By default, gcc-reorder-includes is run on each file before attempting"
548 1.1 mrg print "to remove includes. this removes duplicates and puts some headers in a"
549 1.1 mrg print "canonical ordering"
550 1.1 mrg print " "
551 1.1 mrg print "The build directory should be ready to compile via make. Time is saved"
552 1.1 mrg print "if the build is already complete, so that only changes need to be built."
553 1.1 mrg print " "
554 1.1 mrg print "Usage: [options] file1.c [file2.c] ... [filen.c]"
555 1.1 mrg print " -bdir : the root build directory to attempt buiding .o files."
556 1.1 mrg print " -tdir : the target build directory"
557 1.1 mrg print " -d : Ignore conditional macro dependencies."
558 1.1 mrg print " "
559 1.1 mrg print " -Dmacro : Ignore a specific macro for dependencies"
560 1.1 mrg print " -Ttarget : Only consider target in target directory."
561 1.1 mrg print " -fheader : Specifies a specific .h file to be considered."
562 1.1 mrg print " "
563 1.1 mrg print " -D, -T, and -f can be specified mulitple times and are aggregated."
564 1.1 mrg print " "
565 1.1 mrg print " The original file will be in filen.bak"
566 1.1 mrg print " "
567 1.1 mrg sys.exit (0)
568 1.1 mrg
569 1.1 mrg if only_h:
570 1.1 mrg print "Attempting to remove only these files:"
571 1.1 mrg for x in only_h:
572 1.1 mrg print x
573 1.1 mrg print " "
574 1.1 mrg
575 1.1 mrg logfile = open("reduce-headers.log","w")
576 1.1 mrg
577 1.1 mrg for x in src:
578 1.1 mrg msg = try_to_remove (x, only_h, logfile)
579 1.1 mrg ilog = open("reduce-headers.sum","a")
580 1.1 mrg ilog.write (msg + "\n")
581 1.1 mrg ilog.close()
582 1.1 mrg
583 1.1 mrg ilog = open("reduce-headers.sum","a")
584 1.1 mrg ilog.write ("===============================================================\n")
585 1.1 mrg for x in remove_count:
586 1.1 mrg msg = x + ": Removed " + str(remove_count[x]) + " times."
587 1.1 mrg print msg
588 1.1 mrg logfile.write (msg + "\n")
589 1.1 mrg ilog.write (msg + "\n")
590 1.1 mrg
591 1.1 mrg
592 1.1 mrg
593 1.1 mrg
594 1.1 mrg
595