1*f9a78e0eSmrg#! /usr/bin/python2 2*f9a78e0eSmrgimport os.path 3*f9a78e0eSmrgimport sys 4*f9a78e0eSmrgimport shlex 5*f9a78e0eSmrgimport re 6*f9a78e0eSmrgimport subprocess 7*f9a78e0eSmrgimport shutil 8*f9a78e0eSmrgimport pickle 9*f9a78e0eSmrg 10*f9a78e0eSmrgimport multiprocessing 11*f9a78e0eSmrg 12*f9a78e0eSmrgdef find_pound_include (line, use_outside, use_slash): 13*f9a78e0eSmrg inc = re.findall (ur"^\s*#\s*include\s*\"(.+?)\"", line) 14*f9a78e0eSmrg if len(inc) == 1: 15*f9a78e0eSmrg nm = inc[0] 16*f9a78e0eSmrg if use_outside or os.path.exists (nm): 17*f9a78e0eSmrg if use_slash or '/' not in nm: 18*f9a78e0eSmrg return nm 19*f9a78e0eSmrg return "" 20*f9a78e0eSmrg 21*f9a78e0eSmrgdef find_system_include (line): 22*f9a78e0eSmrg inc = re.findall (ur"^\s*#\s*include\s*<(.+?)>", line) 23*f9a78e0eSmrg if len(inc) == 1: 24*f9a78e0eSmrg return inc[0] 25*f9a78e0eSmrg return "" 26*f9a78e0eSmrg 27*f9a78e0eSmrgdef find_pound_define (line): 28*f9a78e0eSmrg inc = re.findall (ur"^\s*#\s*define ([A-Za-z0-9_]+)", line) 29*f9a78e0eSmrg if len(inc) != 0: 30*f9a78e0eSmrg if len(inc) > 1: 31*f9a78e0eSmrg print "What? more than 1 match in #define??" 32*f9a78e0eSmrg print inc 33*f9a78e0eSmrg sys.exit(5) 34*f9a78e0eSmrg return inc[0]; 35*f9a78e0eSmrg return "" 36*f9a78e0eSmrg 37*f9a78e0eSmrgdef is_pound_if (line): 38*f9a78e0eSmrg inc = re.findall ("^\s*#\s*if\s", line) 39*f9a78e0eSmrg if not inc: 40*f9a78e0eSmrg inc = re.findall ("^\s*#\s*if[n]?def\s", line) 41*f9a78e0eSmrg if inc: 42*f9a78e0eSmrg return True 43*f9a78e0eSmrg return False 44*f9a78e0eSmrg 45*f9a78e0eSmrgdef is_pound_endif (line): 46*f9a78e0eSmrg inc = re.findall ("^\s*#\s*endif", line) 47*f9a78e0eSmrg if inc: 48*f9a78e0eSmrg return True 49*f9a78e0eSmrg return False 50*f9a78e0eSmrg 51*f9a78e0eSmrgdef find_pound_if (line): 52*f9a78e0eSmrg inc = re.findall (ur"^\s*#\s*if\s+(.*)", line) 53*f9a78e0eSmrg if len(inc) == 0: 54*f9a78e0eSmrg inc = re.findall (ur"^\s*#\s*elif\s+(.*)", line) 55*f9a78e0eSmrg if len(inc) > 0: 56*f9a78e0eSmrg inc2 = re.findall (ur"defined\s*\((.+?)\)", inc[0]) 57*f9a78e0eSmrg inc3 = re.findall (ur"defined\s+([a-zA-Z0-9_]+)", inc[0]) 58*f9a78e0eSmrg for yy in inc3: 59*f9a78e0eSmrg inc2.append (yy) 60*f9a78e0eSmrg return inc2 61*f9a78e0eSmrg else: 62*f9a78e0eSmrg inc = re.findall (ur"^\s*#\s*ifdef\s(.*)", line) 63*f9a78e0eSmrg if len(inc) == 0: 64*f9a78e0eSmrg inc = re.findall (ur"^\s*#\s*ifndef\s(.*)", line) 65*f9a78e0eSmrg if len(inc) > 0: 66*f9a78e0eSmrg inc2 = re.findall ("[A-Za-z_][A-Za-z_0-9]*", inc[0]) 67*f9a78e0eSmrg return inc2 68*f9a78e0eSmrg if len(inc) == 0: 69*f9a78e0eSmrg return list () 70*f9a78e0eSmrg print "WTF. more than one line returned for find_pound_if" 71*f9a78e0eSmrg print inc 72*f9a78e0eSmrg sys.exit(5) 73*f9a78e0eSmrg 74*f9a78e0eSmrg 75*f9a78e0eSmrg# IINFO - this is a vector of include information. It consists of 7 elements. 76*f9a78e0eSmrg# [0] - base name of the file 77*f9a78e0eSmrg# [1] - path leading to this file. 78*f9a78e0eSmrg# [2] - orderd list of all headers directly included by this file. 79*f9a78e0eSmrg# [3] - Ordered list of any headers included within condionally compiled code. 80*f9a78e0eSmrg# headers files are expected to have all includes one level deep due to 81*f9a78e0eSmrg# the omnipresent guards at the top of the file. 82*f9a78e0eSmrg# [4] - List of all macros which are consumed (used) within this file. 83*f9a78e0eSmrg# [5] - list of all macros which may be defined in this file. 84*f9a78e0eSmrg# [6] - The source code for this file, if cached. 85*f9a78e0eSmrg# [7] - line number info for any headers in the source file. Indexed by base 86*f9a78e0eSmrg# name, returning the line the include is on. 87*f9a78e0eSmrg 88*f9a78e0eSmrgempty_iinfo = ("", "", list(), list(), list(), list(), list()) 89*f9a78e0eSmrg 90*f9a78e0eSmrg# This function will process a file and extract interesting information. 91*f9a78e0eSmrg# DO_MACROS indicates whether macros defined and used should be recorded. 92*f9a78e0eSmrg# KEEP_SRC indicates the source for the file should be cached. 93*f9a78e0eSmrgdef process_include_info (filen, do_macros, keep_src): 94*f9a78e0eSmrg header = False 95*f9a78e0eSmrg if not os.path.exists (filen): 96*f9a78e0eSmrg return empty_iinfo 97*f9a78e0eSmrg 98*f9a78e0eSmrg sfile = open (filen, "r"); 99*f9a78e0eSmrg data = sfile.readlines() 100*f9a78e0eSmrg sfile.close() 101*f9a78e0eSmrg 102*f9a78e0eSmrg # Ignore the initial #ifdef HEADER_H in header files 103*f9a78e0eSmrg if filen[-2:] == ".h": 104*f9a78e0eSmrg nest = -1 105*f9a78e0eSmrg header = True 106*f9a78e0eSmrg else: 107*f9a78e0eSmrg nest = 0 108*f9a78e0eSmrg 109*f9a78e0eSmrg macout = list () 110*f9a78e0eSmrg macin = list() 111*f9a78e0eSmrg incl = list() 112*f9a78e0eSmrg cond_incl = list() 113*f9a78e0eSmrg src_line = { } 114*f9a78e0eSmrg guard = "" 115*f9a78e0eSmrg 116*f9a78e0eSmrg for line in (data): 117*f9a78e0eSmrg if is_pound_if (line): 118*f9a78e0eSmrg nest += 1 119*f9a78e0eSmrg elif is_pound_endif (line): 120*f9a78e0eSmrg nest -= 1 121*f9a78e0eSmrg 122*f9a78e0eSmrg nm = find_pound_include (line, True, True) 123*f9a78e0eSmrg if nm != "" and nm not in incl and nm[-2:] == ".h": 124*f9a78e0eSmrg incl.append (nm) 125*f9a78e0eSmrg if nest > 0: 126*f9a78e0eSmrg cond_incl.append (nm) 127*f9a78e0eSmrg if keep_src: 128*f9a78e0eSmrg src_line[nm] = line 129*f9a78e0eSmrg continue 130*f9a78e0eSmrg 131*f9a78e0eSmrg if do_macros: 132*f9a78e0eSmrg d = find_pound_define (line) 133*f9a78e0eSmrg if d: 134*f9a78e0eSmrg if d not in macout: 135*f9a78e0eSmrg macout.append (d); 136*f9a78e0eSmrg continue 137*f9a78e0eSmrg 138*f9a78e0eSmrg d = find_pound_if (line) 139*f9a78e0eSmrg if d: 140*f9a78e0eSmrg # The first #if in a header file should be the guard 141*f9a78e0eSmrg if header and len (d) == 1 and guard == "": 142*f9a78e0eSmrg if d[0][-2:] == "_H": 143*f9a78e0eSmrg guard = d 144*f9a78e0eSmrg else: 145*f9a78e0eSmrg guard = "Guess there was no guard..." 146*f9a78e0eSmrg else: 147*f9a78e0eSmrg for mac in d: 148*f9a78e0eSmrg if mac != "defined" and mac not in macin: 149*f9a78e0eSmrg macin.append (mac); 150*f9a78e0eSmrg 151*f9a78e0eSmrg if not keep_src: 152*f9a78e0eSmrg data = list() 153*f9a78e0eSmrg 154*f9a78e0eSmrg return (os.path.basename (filen), os.path.dirname (filen), incl, cond_incl, 155*f9a78e0eSmrg macin, macout, data, src_line) 156*f9a78e0eSmrg 157*f9a78e0eSmrg# Extract header info, but no macros or source code. 158*f9a78e0eSmrgdef process_ii (filen): 159*f9a78e0eSmrg return process_include_info (filen, False, False) 160*f9a78e0eSmrg 161*f9a78e0eSmrg# Extract header information, and collect macro information. 162*f9a78e0eSmrgdef process_ii_macro (filen): 163*f9a78e0eSmrg return process_include_info (filen, True, False) 164*f9a78e0eSmrg 165*f9a78e0eSmrg# Extract header information, cache the source lines. 166*f9a78e0eSmrgdef process_ii_src (filen): 167*f9a78e0eSmrg return process_include_info (filen, False, True) 168*f9a78e0eSmrg 169*f9a78e0eSmrg# Extract header information, coolewc macro info and cache the source lines. 170*f9a78e0eSmrgdef process_ii_macro_src (filen): 171*f9a78e0eSmrg return process_include_info (filen, True, True) 172*f9a78e0eSmrg 173*f9a78e0eSmrg 174*f9a78e0eSmrgdef ii_base (iinfo): 175*f9a78e0eSmrg return iinfo[0] 176*f9a78e0eSmrg 177*f9a78e0eSmrgdef ii_path (iinfo): 178*f9a78e0eSmrg return iinfo[1] 179*f9a78e0eSmrg 180*f9a78e0eSmrgdef ii_include_list (iinfo): 181*f9a78e0eSmrg return iinfo[2] 182*f9a78e0eSmrg 183*f9a78e0eSmrgdef ii_include_list_cond (iinfo): 184*f9a78e0eSmrg return iinfo[3] 185*f9a78e0eSmrg 186*f9a78e0eSmrgdef ii_include_list_non_cond (iinfo): 187*f9a78e0eSmrg l = ii_include_list (iinfo) 188*f9a78e0eSmrg for n in ii_include_list_cond (iinfo): 189*f9a78e0eSmrg l.remove (n) 190*f9a78e0eSmrg return l 191*f9a78e0eSmrg 192*f9a78e0eSmrgdef ii_macro_consume (iinfo): 193*f9a78e0eSmrg return iinfo[4] 194*f9a78e0eSmrg 195*f9a78e0eSmrgdef ii_macro_define (iinfo): 196*f9a78e0eSmrg return iinfo[5] 197*f9a78e0eSmrg 198*f9a78e0eSmrgdef ii_src (iinfo): 199*f9a78e0eSmrg return iinfo[6] 200*f9a78e0eSmrg 201*f9a78e0eSmrgdef ii_src_line (iinfo): 202*f9a78e0eSmrg return iinfo[7] 203*f9a78e0eSmrg 204*f9a78e0eSmrgdef ii_read (fname): 205*f9a78e0eSmrg f = open (fname, 'rb') 206*f9a78e0eSmrg incl = pickle.load (f) 207*f9a78e0eSmrg consumes = pickle.load (f) 208*f9a78e0eSmrg defines = pickle.load (f) 209*f9a78e0eSmrg obj = (fname,fname,incl,list(), list(), consumes, defines, list(), list()) 210*f9a78e0eSmrg return obj 211*f9a78e0eSmrg 212*f9a78e0eSmrgdef ii_write (fname, obj): 213*f9a78e0eSmrg f = open (fname, 'wb') 214*f9a78e0eSmrg pickle.dump (obj[2], f) 215*f9a78e0eSmrg pickle.dump (obj[4], f) 216*f9a78e0eSmrg pickle.dump (obj[5], f) 217*f9a78e0eSmrg f.close () 218*f9a78e0eSmrg 219*f9a78e0eSmrg# execute a system command which returns file names 220*f9a78e0eSmrgdef execute_command (command): 221*f9a78e0eSmrg files = list() 222*f9a78e0eSmrg f = os.popen (command) 223*f9a78e0eSmrg for x in f: 224*f9a78e0eSmrg if x[0:2] == "./": 225*f9a78e0eSmrg fn = x.rstrip()[2:] 226*f9a78e0eSmrg else: 227*f9a78e0eSmrg fn = x.rstrip() 228*f9a78e0eSmrg files.append(fn) 229*f9a78e0eSmrg return files 230*f9a78e0eSmrg 231*f9a78e0eSmrg# Try to locate a build directory from PATH 232*f9a78e0eSmrgdef find_gcc_bld_dir (path): 233*f9a78e0eSmrg blddir = "" 234*f9a78e0eSmrg # Look for blddir/gcc/tm.h 235*f9a78e0eSmrg command = "find " + path + " -mindepth 2 -maxdepth 3 -name tm.h" 236*f9a78e0eSmrg files = execute_command (command) 237*f9a78e0eSmrg for y in files: 238*f9a78e0eSmrg p = os.path.dirname (y) 239*f9a78e0eSmrg if os.path.basename (p) == "gcc": 240*f9a78e0eSmrg blddir = p 241*f9a78e0eSmrg break 242*f9a78e0eSmrg # If not found, try looking a bit deeper 243*f9a78e0eSmrg # Dont look this deep initially because a lot of cross target builds may show 244*f9a78e0eSmrg # up in the list before a native build... but those are better than nothing. 245*f9a78e0eSmrg if not blddir: 246*f9a78e0eSmrg command = "find " + path + " -mindepth 3 -maxdepth 5 -name tm.h" 247*f9a78e0eSmrg files = execute_command (command) 248*f9a78e0eSmrg for y in files: 249*f9a78e0eSmrg p = os.path.dirname (y) 250*f9a78e0eSmrg if os.path.basename (p) == "gcc": 251*f9a78e0eSmrg blddir = p 252*f9a78e0eSmrg break 253*f9a78e0eSmrg 254*f9a78e0eSmrg return blddir 255*f9a78e0eSmrg 256*f9a78e0eSmrg 257*f9a78e0eSmrg# Find files matching pattern NAME, return in a list. 258*f9a78e0eSmrg# CURRENT is True if you want to include the current directory 259*f9a78e0eSmrg# DEEPER is True if you want to search 3 levels below the current directory 260*f9a78e0eSmrg# any files with testsuite diurectories are ignored 261*f9a78e0eSmrg 262*f9a78e0eSmrgdef find_gcc_files (name, current, deeper): 263*f9a78e0eSmrg files = list() 264*f9a78e0eSmrg command = "" 265*f9a78e0eSmrg if current: 266*f9a78e0eSmrg if not deeper: 267*f9a78e0eSmrg command = "find -maxdepth 1 -name " + name + " -not -path \"./testsuite/*\"" 268*f9a78e0eSmrg else: 269*f9a78e0eSmrg command = "find -maxdepth 4 -name " + name + " -not -path \"./testsuite/*\"" 270*f9a78e0eSmrg else: 271*f9a78e0eSmrg if deeper: 272*f9a78e0eSmrg command = "find -maxdepth 4 -mindepth 2 -name " + name + " -not -path \"./testsuite/*\"" 273*f9a78e0eSmrg 274*f9a78e0eSmrg if command != "": 275*f9a78e0eSmrg files = execute_command (command) 276*f9a78e0eSmrg 277*f9a78e0eSmrg return files 278*f9a78e0eSmrg 279*f9a78e0eSmrg# find the list of unique include names found in a file. 280*f9a78e0eSmrgdef find_unique_include_list_src (data): 281*f9a78e0eSmrg found = list () 282*f9a78e0eSmrg for line in data: 283*f9a78e0eSmrg d = find_pound_include (line, True, True) 284*f9a78e0eSmrg if d and d not in found and d[-2:] == ".h": 285*f9a78e0eSmrg found.append (d) 286*f9a78e0eSmrg return found 287*f9a78e0eSmrg 288*f9a78e0eSmrg# find the list of unique include names found in a file. 289*f9a78e0eSmrgdef find_unique_include_list (filen): 290*f9a78e0eSmrg data = open (filen).read().splitlines() 291*f9a78e0eSmrg return find_unique_include_list_src (data) 292*f9a78e0eSmrg 293*f9a78e0eSmrg 294*f9a78e0eSmrg# Create the macin, macout, and incl vectors for a file FILEN. 295*f9a78e0eSmrg# macin are the macros that are used in #if* conditional expressions 296*f9a78e0eSmrg# macout are the macros which are #defined 297*f9a78e0eSmrg# incl is the list of incluide files encountered 298*f9a78e0eSmrg# returned as a tuple of the filename followed by the triplet of lists 299*f9a78e0eSmrg# (filen, macin, macout, incl) 300*f9a78e0eSmrg 301*f9a78e0eSmrgdef create_macro_in_out (filen): 302*f9a78e0eSmrg sfile = open (filen, "r"); 303*f9a78e0eSmrg data = sfile.readlines() 304*f9a78e0eSmrg sfile.close() 305*f9a78e0eSmrg 306*f9a78e0eSmrg macout = list () 307*f9a78e0eSmrg macin = list() 308*f9a78e0eSmrg incl = list() 309*f9a78e0eSmrg 310*f9a78e0eSmrg for line in (data): 311*f9a78e0eSmrg d = find_pound_define (line) 312*f9a78e0eSmrg if d != "": 313*f9a78e0eSmrg if d not in macout: 314*f9a78e0eSmrg macout.append (d); 315*f9a78e0eSmrg continue 316*f9a78e0eSmrg 317*f9a78e0eSmrg d = find_pound_if (line) 318*f9a78e0eSmrg if len(d) != 0: 319*f9a78e0eSmrg for mac in d: 320*f9a78e0eSmrg if mac != "defined" and mac not in macin: 321*f9a78e0eSmrg macin.append (mac); 322*f9a78e0eSmrg continue 323*f9a78e0eSmrg 324*f9a78e0eSmrg nm = find_pound_include (line, True, True) 325*f9a78e0eSmrg if nm != "" and nm not in incl: 326*f9a78e0eSmrg incl.append (nm) 327*f9a78e0eSmrg 328*f9a78e0eSmrg return (filen, macin, macout, incl) 329*f9a78e0eSmrg 330*f9a78e0eSmrg# create the macro information for filen, and create .macin, .macout, and .incl 331*f9a78e0eSmrg# files. Return the created macro tuple. 332*f9a78e0eSmrgdef create_include_data_files (filen): 333*f9a78e0eSmrg 334*f9a78e0eSmrg macros = create_macro_in_out (filen) 335*f9a78e0eSmrg depends = macros[1] 336*f9a78e0eSmrg defines = macros[2] 337*f9a78e0eSmrg incls = macros[3] 338*f9a78e0eSmrg 339*f9a78e0eSmrg disp_message = filen 340*f9a78e0eSmrg if len (defines) > 0: 341*f9a78e0eSmrg disp_message = disp_message + " " + str(len (defines)) + " #defines" 342*f9a78e0eSmrg dfile = open (filen + ".macout", "w") 343*f9a78e0eSmrg for x in defines: 344*f9a78e0eSmrg dfile.write (x + "\n") 345*f9a78e0eSmrg dfile.close () 346*f9a78e0eSmrg 347*f9a78e0eSmrg if len (depends) > 0: 348*f9a78e0eSmrg disp_message = disp_message + " " + str(len (depends)) + " #if dependencies" 349*f9a78e0eSmrg dfile = open (filen + ".macin", "w") 350*f9a78e0eSmrg for x in depends: 351*f9a78e0eSmrg dfile.write (x + "\n") 352*f9a78e0eSmrg dfile.close () 353*f9a78e0eSmrg 354*f9a78e0eSmrg if len (incls) > 0: 355*f9a78e0eSmrg disp_message = disp_message + " " + str(len (incls)) + " #includes" 356*f9a78e0eSmrg dfile = open (filen + ".incl", "w") 357*f9a78e0eSmrg for x in incls: 358*f9a78e0eSmrg dfile.write (x + "\n") 359*f9a78e0eSmrg dfile.close () 360*f9a78e0eSmrg 361*f9a78e0eSmrg return macros 362*f9a78e0eSmrg 363*f9a78e0eSmrg 364*f9a78e0eSmrg 365*f9a78e0eSmrg# extract data for include file name_h and enter it into the dictionary. 366*f9a78e0eSmrg# this does not change once read in. use_requires is True if you want to 367*f9a78e0eSmrg# prime the values with already created .requires and .provides files. 368*f9a78e0eSmrgdef get_include_data (name_h, use_requires): 369*f9a78e0eSmrg macin = list() 370*f9a78e0eSmrg macout = list() 371*f9a78e0eSmrg incl = list () 372*f9a78e0eSmrg if use_requires and os.path.exists (name_h + ".requires"): 373*f9a78e0eSmrg macin = open (name_h + ".requires").read().splitlines() 374*f9a78e0eSmrg elif os.path.exists (name_h + ".macin"): 375*f9a78e0eSmrg macin = open (name_h + ".macin").read().splitlines() 376*f9a78e0eSmrg 377*f9a78e0eSmrg if use_requires and os.path.exists (name_h + ".provides"): 378*f9a78e0eSmrg macout = open (name_h + ".provides").read().splitlines() 379*f9a78e0eSmrg elif os.path.exists (name_h + ".macout"): 380*f9a78e0eSmrg macout = open (name_h + ".macout").read().splitlines() 381*f9a78e0eSmrg 382*f9a78e0eSmrg if os.path.exists (name_h + ".incl"): 383*f9a78e0eSmrg incl = open (name_h + ".incl").read().splitlines() 384*f9a78e0eSmrg 385*f9a78e0eSmrg if len(macin) == 0 and len(macout) == 0 and len(incl) == 0: 386*f9a78e0eSmrg return () 387*f9a78e0eSmrg data = ( name_h, macin, macout, incl ) 388*f9a78e0eSmrg return data 389*f9a78e0eSmrg 390*f9a78e0eSmrg# find FIND in src, and replace it with the list of headers in REPLACE. 391*f9a78e0eSmrg# Remove any duplicates of FIND in REPLACE, and if some of the REPLACE 392*f9a78e0eSmrg# headers occur earlier in the include chain, leave them. 393*f9a78e0eSmrg# Return the new SRC only if anything changed. 394*f9a78e0eSmrgdef find_replace_include (find, replace, src): 395*f9a78e0eSmrg res = list() 396*f9a78e0eSmrg seen = { } 397*f9a78e0eSmrg anything = False 398*f9a78e0eSmrg for line in src: 399*f9a78e0eSmrg inc = find_pound_include (line, True, True) 400*f9a78e0eSmrg if inc == find: 401*f9a78e0eSmrg for y in replace: 402*f9a78e0eSmrg if seen.get(y) == None: 403*f9a78e0eSmrg res.append("#include \""+y+"\"\n") 404*f9a78e0eSmrg seen[y] = True 405*f9a78e0eSmrg if y != find: 406*f9a78e0eSmrg anything = True 407*f9a78e0eSmrg# if find isnt in the replacement list, then we are deleting FIND, so changes. 408*f9a78e0eSmrg if find not in replace: 409*f9a78e0eSmrg anything = True 410*f9a78e0eSmrg else: 411*f9a78e0eSmrg if inc in replace: 412*f9a78e0eSmrg if seen.get(inc) == None: 413*f9a78e0eSmrg res.append (line) 414*f9a78e0eSmrg seen[inc] = True 415*f9a78e0eSmrg else: 416*f9a78e0eSmrg res.append (line) 417*f9a78e0eSmrg 418*f9a78e0eSmrg if (anything): 419*f9a78e0eSmrg return res 420*f9a78e0eSmrg else: 421*f9a78e0eSmrg return list() 422*f9a78e0eSmrg 423*f9a78e0eSmrg 424*f9a78e0eSmrg# pass in a require and provide dictionary to be read in. 425*f9a78e0eSmrgdef read_require_provides (require, provide): 426*f9a78e0eSmrg if not os.path.exists ("require-provide.master"): 427*f9a78e0eSmrg print "require-provide.master file is not available. please run data collection." 428*f9a78e0eSmrg sys.exit(1) 429*f9a78e0eSmrg incl_list = open("require-provide.master").read().splitlines() 430*f9a78e0eSmrg for f in incl_list: 431*f9a78e0eSmrg if os.path.exists (f+".requires"): 432*f9a78e0eSmrg require[os.path.basename (f)] = open (f + ".requires").read().splitlines() 433*f9a78e0eSmrg else: 434*f9a78e0eSmrg require[os.path.basename (f)] = list () 435*f9a78e0eSmrg if os.path.exists (f+".provides"): 436*f9a78e0eSmrg provide[os.path.basename (f)] = open (f + ".provides").read().splitlines() 437*f9a78e0eSmrg else: 438*f9a78e0eSmrg provide [os.path.basename (f)] = list () 439*f9a78e0eSmrg 440*f9a78e0eSmrg 441*f9a78e0eSmrgdef build_include_list (filen): 442*f9a78e0eSmrg include_files = list() 443*f9a78e0eSmrg sfile = open (filen, "r") 444*f9a78e0eSmrg data = sfile.readlines() 445*f9a78e0eSmrg sfile.close() 446*f9a78e0eSmrg for line in data: 447*f9a78e0eSmrg nm = find_pound_include (line, False, False) 448*f9a78e0eSmrg if nm != "" and nm[-2:] == ".h": 449*f9a78e0eSmrg if nm not in include_files: 450*f9a78e0eSmrg include_files.append(nm) 451*f9a78e0eSmrg return include_files 452*f9a78e0eSmrg 453*f9a78e0eSmrgdef build_reverse_include_list (filen): 454*f9a78e0eSmrg include_files = list() 455*f9a78e0eSmrg sfile = open (filen, "r") 456*f9a78e0eSmrg data = sfile.readlines() 457*f9a78e0eSmrg sfile.close() 458*f9a78e0eSmrg for line in reversed(data): 459*f9a78e0eSmrg nm = find_pound_include (line, False, False) 460*f9a78e0eSmrg if nm != "": 461*f9a78e0eSmrg if nm not in include_files: 462*f9a78e0eSmrg include_files.append(nm) 463*f9a78e0eSmrg return include_files 464*f9a78e0eSmrg 465*f9a78e0eSmrg# Get compilation return code, and compensate for a warning that we want to 466*f9a78e0eSmrg# consider an error when it comes to inlined templates. 467*f9a78e0eSmrgdef get_make_rc (rc, output): 468*f9a78e0eSmrg rc = rc % 1280 469*f9a78e0eSmrg if rc == 0: 470*f9a78e0eSmrg # This is not considered an error during compilation of an individual file, 471*f9a78e0eSmrg # but it will cause an error during link if it isn't defined. If this 472*f9a78e0eSmrg # warning is seen during compiling a file, make it a build error so we 473*f9a78e0eSmrg # don't remove the header. 474*f9a78e0eSmrg h = re.findall ("warning: inline function.*used but never defined", output) 475*f9a78e0eSmrg if len(h) != 0: 476*f9a78e0eSmrg rc = 1 477*f9a78e0eSmrg return rc; 478*f9a78e0eSmrg 479*f9a78e0eSmrgdef get_make_output (build_dir, make_opt): 480*f9a78e0eSmrg devnull = open('/dev/null', 'w') 481*f9a78e0eSmrg at_a_time = multiprocessing.cpu_count() * 2 482*f9a78e0eSmrg make = "make -j"+str(at_a_time)+ " " 483*f9a78e0eSmrg if build_dir != "": 484*f9a78e0eSmrg command = "cd " + build_dir +"; " + make + make_opt 485*f9a78e0eSmrg else: 486*f9a78e0eSmrg command = make + make_opt 487*f9a78e0eSmrg process = subprocess.Popen(command, stdout=devnull, stderr=subprocess.PIPE, shell=True) 488*f9a78e0eSmrg output = process.communicate(); 489*f9a78e0eSmrg rc = get_make_rc (process.returncode, output[1]) 490*f9a78e0eSmrg return (rc , output[1]) 491*f9a78e0eSmrg 492*f9a78e0eSmrgdef spawn_makes (command_list): 493*f9a78e0eSmrg devnull = open('/dev/null', 'w') 494*f9a78e0eSmrg rc = (0,"", "") 495*f9a78e0eSmrg proc_res = list() 496*f9a78e0eSmrg text = " Trying target builds : " 497*f9a78e0eSmrg for command_pair in command_list: 498*f9a78e0eSmrg tname = command_pair[0] 499*f9a78e0eSmrg command = command_pair[1] 500*f9a78e0eSmrg text += tname + ", " 501*f9a78e0eSmrg c = subprocess.Popen(command, bufsize=-1, stdout=devnull, stderr=subprocess.PIPE, shell=True) 502*f9a78e0eSmrg proc_res.append ((c, tname)) 503*f9a78e0eSmrg 504*f9a78e0eSmrg print text[:-2] 505*f9a78e0eSmrg 506*f9a78e0eSmrg for p in proc_res: 507*f9a78e0eSmrg output = p[0].communicate() 508*f9a78e0eSmrg ret = (get_make_rc (p[0].returncode, output[1]), output[1], p[1]) 509*f9a78e0eSmrg if (ret[0] != 0): 510*f9a78e0eSmrg # Just record the first one. 511*f9a78e0eSmrg if rc[0] == 0: 512*f9a78e0eSmrg rc = ret; 513*f9a78e0eSmrg return rc 514*f9a78e0eSmrg 515*f9a78e0eSmrgdef get_make_output_parallel (targ_list, make_opt, at_a_time): 516*f9a78e0eSmrg command = list() 517*f9a78e0eSmrg targname = list() 518*f9a78e0eSmrg if at_a_time == 0: 519*f9a78e0eSmrg at_a_time = multiprocessing.cpu_count() * 2 520*f9a78e0eSmrg proc_res = [0] * at_a_time 521*f9a78e0eSmrg for x in targ_list: 522*f9a78e0eSmrg if make_opt[-2:] == ".o": 523*f9a78e0eSmrg s = "cd " + x[1] + "/gcc/; make " + make_opt 524*f9a78e0eSmrg else: 525*f9a78e0eSmrg s = "cd " + x[1] +"; make " + make_opt 526*f9a78e0eSmrg command.append ((x[0],s)) 527*f9a78e0eSmrg 528*f9a78e0eSmrg num = len(command) 529*f9a78e0eSmrg rc = (0,"", "") 530*f9a78e0eSmrg loops = num // at_a_time 531*f9a78e0eSmrg 532*f9a78e0eSmrg if (loops > 0): 533*f9a78e0eSmrg for idx in range (loops): 534*f9a78e0eSmrg ret = spawn_makes (command[idx*at_a_time:(idx+1)*at_a_time]) 535*f9a78e0eSmrg if ret[0] != 0: 536*f9a78e0eSmrg rc = ret 537*f9a78e0eSmrg break 538*f9a78e0eSmrg 539*f9a78e0eSmrg if (rc[0] == 0): 540*f9a78e0eSmrg leftover = num % at_a_time 541*f9a78e0eSmrg if (leftover > 0): 542*f9a78e0eSmrg ret = spawn_makes (command[-leftover:]) 543*f9a78e0eSmrg if ret[0] != 0: 544*f9a78e0eSmrg rc = ret 545*f9a78e0eSmrg 546*f9a78e0eSmrg return rc 547*f9a78e0eSmrg 548*f9a78e0eSmrg 549*f9a78e0eSmrgdef readwholefile (src_file): 550*f9a78e0eSmrg sfile = open (src_file, "r") 551*f9a78e0eSmrg src_data = sfile.readlines() 552*f9a78e0eSmrg sfile.close() 553*f9a78e0eSmrg return src_data 554*f9a78e0eSmrg 555