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