meta2deps.py (268437) | meta2deps.py (281812) |
---|---|
1#!/usr/bin/env python 2 3from __future__ import print_function 4 5""" 6This script parses each "meta" file and extracts the 7information needed to deduce build and src dependencies. 8 --- 23 unchanged lines hidden (view full) --- 32 33'V' the filemon version, this record is used as a clue 34 that we have reached the interesting bit. 35 36""" 37 38""" 39RCSid: | 1#!/usr/bin/env python 2 3from __future__ import print_function 4 5""" 6This script parses each "meta" file and extracts the 7information needed to deduce build and src dependencies. 8 --- 23 unchanged lines hidden (view full) --- 32 33'V' the filemon version, this record is used as a clue 34 that we have reached the interesting bit. 35 36""" 37 38""" 39RCSid: |
40 $Id: meta2deps.py,v 1.17 2014/04/05 22:56:54 sjg Exp $ | 40 $Id: meta2deps.py,v 1.18 2015/04/03 18:23:25 sjg Exp $ |
41 42 Copyright (c) 2011-2013, Juniper Networks, Inc. 43 All rights reserved. 44 45 Redistribution and use in source and binary forms, with or without 46 modification, are permitted provided that the following conditions 47 are met: 48 1. Redistributions of source code must retain the above copyright --- 58 unchanged lines hidden (view full) --- 107 """ 108 Return an absolute path, resolving via cwd or last_dir if needed. 109 this gets called a lot, so we try to avoid calling realpath 110 until we know we have something. 111 """ 112 rpath = resolve(path, cwd, last_dir, debug, debug_out) 113 if rpath: 114 path = rpath | 41 42 Copyright (c) 2011-2013, Juniper Networks, Inc. 43 All rights reserved. 44 45 Redistribution and use in source and binary forms, with or without 46 modification, are permitted provided that the following conditions 47 are met: 48 1. Redistributions of source code must retain the above copyright --- 58 unchanged lines hidden (view full) --- 107 """ 108 Return an absolute path, resolving via cwd or last_dir if needed. 109 this gets called a lot, so we try to avoid calling realpath 110 until we know we have something. 111 """ 112 rpath = resolve(path, cwd, last_dir, debug, debug_out) 113 if rpath: 114 path = rpath |
115 if (path.find('./') > 0 or | 115 if (path.find('/') < 0 or 116 path.find('./') > 0 or |
116 path.endswith('/..') or 117 os.path.islink(path)): 118 return os.path.realpath(path) 119 return path 120 121def sort_unique(list, cmp=None, key=None, reverse=False): 122 list.sort(cmp, key, reverse) 123 nl = [] --- 13 unchanged lines hidden (view full) --- 137class MetaFile: 138 """class to parse meta files generated by bmake.""" 139 140 conf = None 141 dirdep_re = None 142 host_target = None 143 srctops = [] 144 objroots = [] | 117 path.endswith('/..') or 118 os.path.islink(path)): 119 return os.path.realpath(path) 120 return path 121 122def sort_unique(list, cmp=None, key=None, reverse=False): 123 list.sort(cmp, key, reverse) 124 nl = [] --- 13 unchanged lines hidden (view full) --- 138class MetaFile: 139 """class to parse meta files generated by bmake.""" 140 141 conf = None 142 dirdep_re = None 143 host_target = None 144 srctops = [] 145 objroots = [] |
145 | 146 excludes = [] |
146 seen = {} 147 obj_deps = [] 148 src_deps = [] 149 file_deps = [] 150 151 def __init__(self, name, conf={}): 152 """if name is set we will parse it now. 153 conf can have the follwing keys: --- 20 unchanged lines hidden (view full) --- 174 175 DPDEPS names an optional file to which per file dependencies 176 will be appended. 177 For example if 'some/path/foo.h' is read from SRCTOP 178 then 'DPDEPS_some/path/foo.h +=' "RELDIR" is output. 179 This can allow 'bmake' to learn all the dirs within 180 the tree that depend on 'foo.h' 181 | 147 seen = {} 148 obj_deps = [] 149 src_deps = [] 150 file_deps = [] 151 152 def __init__(self, name, conf={}): 153 """if name is set we will parse it now. 154 conf can have the follwing keys: --- 20 unchanged lines hidden (view full) --- 175 176 DPDEPS names an optional file to which per file dependencies 177 will be appended. 178 For example if 'some/path/foo.h' is read from SRCTOP 179 then 'DPDEPS_some/path/foo.h +=' "RELDIR" is output. 180 This can allow 'bmake' to learn all the dirs within 181 the tree that depend on 'foo.h' 182 |
183 EXCLUDES 184 A list of paths to ignore. 185 ccache(1) can otherwise be trouble. 186 |
|
182 debug desired debug level 183 184 debug_out open file to send debug output to (sys.stderr) 185 186 """ 187 188 self.name = name 189 self.debug = getv(conf, 'debug', 0) --- 41 unchanged lines hidden (view full) --- 231 if objroot[-1] == '/': 232 _objroot += '/' 233 if not _objroot in self.objroots: 234 self.objroots.append(_objroot) 235 236 # we want the longest match 237 self.srctops.sort(reverse=True) 238 self.objroots.sort(reverse=True) | 187 debug desired debug level 188 189 debug_out open file to send debug output to (sys.stderr) 190 191 """ 192 193 self.name = name 194 self.debug = getv(conf, 'debug', 0) --- 41 unchanged lines hidden (view full) --- 236 if objroot[-1] == '/': 237 _objroot += '/' 238 if not _objroot in self.objroots: 239 self.objroots.append(_objroot) 240 241 # we want the longest match 242 self.srctops.sort(reverse=True) 243 self.objroots.sort(reverse=True) |
239 | 244 245 self.excludes = getv(conf, 'EXCLUDES', []) 246 |
240 if self.debug: 241 print("host_target=", self.host_target, file=self.debug_out) 242 print("srctops=", self.srctops, file=self.debug_out) 243 print("objroots=", self.objroots, file=self.debug_out) | 247 if self.debug: 248 print("host_target=", self.host_target, file=self.debug_out) 249 print("srctops=", self.srctops, file=self.debug_out) 250 print("objroots=", self.objroots, file=self.debug_out) |
251 print("excludes=", self.excludes, file=self.debug_out) |
|
244 245 self.dirdep_re = re.compile(r'([^/]+)/(.+)') 246 247 if self.dpdeps and not self.reldir: 248 if self.debug: 249 print("need reldir:", end=' ', file=self.debug_out) 250 if self.curdir: 251 srctop = self.find_top(self.curdir, self.srctops) 252 if srctop: 253 self.reldir = self.curdir.replace(srctop,'') 254 if self.debug: 255 print(self.reldir, file=self.debug_out) 256 if not self.reldir: 257 self.dpdeps = None # we cannot do it? 258 259 self.cwd = os.getcwd() # make sure this is initialized | 252 253 self.dirdep_re = re.compile(r'([^/]+)/(.+)') 254 255 if self.dpdeps and not self.reldir: 256 if self.debug: 257 print("need reldir:", end=' ', file=self.debug_out) 258 if self.curdir: 259 srctop = self.find_top(self.curdir, self.srctops) 260 if srctop: 261 self.reldir = self.curdir.replace(srctop,'') 262 if self.debug: 263 print(self.reldir, file=self.debug_out) 264 if not self.reldir: 265 self.dpdeps = None # we cannot do it? 266 267 self.cwd = os.getcwd() # make sure this is initialized |
268 self.last_dir = self.cwd |
|
260 261 if name: 262 self.try_parse() 263 264 def reset(self): 265 """reset state if we are being passed meta files from multiple directories.""" 266 self.seen = {} 267 self.obj_deps = [] --- 87 unchanged lines hidden (view full) --- 355 CWD "cwd" 356 TARGET "target" 357 -- command output -- 358 -- filemon acquired metadata -- 359 # buildmon version 3 360 V 3 361 C "pid" "cwd" 362 E "pid" "path" | 269 270 if name: 271 self.try_parse() 272 273 def reset(self): 274 """reset state if we are being passed meta files from multiple directories.""" 275 self.seen = {} 276 self.obj_deps = [] --- 87 unchanged lines hidden (view full) --- 364 CWD "cwd" 365 TARGET "target" 366 -- command output -- 367 -- filemon acquired metadata -- 368 # buildmon version 3 369 V 3 370 C "pid" "cwd" 371 E "pid" "path" |
363 F "pid" "child" | 372 F "pid" "child" |
364 R "pid" "path" 365 W "pid" "path" 366 X "pid" "status" | 373 R "pid" "path" 374 W "pid" "path" 375 X "pid" "status" |
367 D "pid" "path" 368 L "pid" "src" "target" 369 M "pid" "old" "new" 370 S "pid" "path" 371 # Bye bye | 376 D "pid" "path" 377 L "pid" "src" "target" 378 M "pid" "old" "new" 379 S "pid" "path" 380 # Bye bye |
372 | 381 |
373 We go to some effort to avoid processing a dependency more than once. 374 Of the above record types only C,E,F,L,R,V and W are of interest. | 382 We go to some effort to avoid processing a dependency more than once. 383 Of the above record types only C,E,F,L,R,V and W are of interest. |
375 """ 376 377 version = 0 # unknown 378 if name: 379 self.name = name; 380 if file: 381 f = file | 384 """ 385 386 version = 0 # unknown 387 if name: 388 self.name = name; 389 if file: 390 f = file |
382 cwd = last_dir = self.cwd | 391 cwd = self.last_dir = self.cwd |
383 else: 384 f = open(self.name, 'r') 385 skip = True 386 pid_cwd = {} 387 pid_last_dir = {} 388 last_pid = 0 389 390 self.line = 0 --- 16 unchanged lines hidden (view full) --- 407 version = int(w[1]) 408 """ 409 if version < 4: 410 # we cannot ignore 'W' records 411 # as they may be 'rw' 412 interesting += 'W' 413 """ 414 elif w[0] == 'CWD': | 392 else: 393 f = open(self.name, 'r') 394 skip = True 395 pid_cwd = {} 396 pid_last_dir = {} 397 last_pid = 0 398 399 self.line = 0 --- 16 unchanged lines hidden (view full) --- 416 version = int(w[1]) 417 """ 418 if version < 4: 419 # we cannot ignore 'W' records 420 # as they may be 'rw' 421 interesting += 'W' 422 """ 423 elif w[0] == 'CWD': |
415 self.cwd = cwd = last_dir = w[1] | 424 self.cwd = cwd = self.last_dir = w[1] |
416 self.seenit(cwd) # ignore this 417 if self.debug: 418 print("%s: CWD=%s" % (self.name, cwd), file=self.debug_out) 419 continue 420 421 pid = int(w[1]) 422 if pid != last_pid: 423 if last_pid: 424 pid_cwd[last_pid] = cwd | 425 self.seenit(cwd) # ignore this 426 if self.debug: 427 print("%s: CWD=%s" % (self.name, cwd), file=self.debug_out) 428 continue 429 430 pid = int(w[1]) 431 if pid != last_pid: 432 if last_pid: 433 pid_cwd[last_pid] = cwd |
425 pid_last_dir[last_pid] = last_dir | 434 pid_last_dir[last_pid] = self.last_dir |
426 cwd = getv(pid_cwd, pid, self.cwd) | 435 cwd = getv(pid_cwd, pid, self.cwd) |
427 last_dir = getv(pid_last_dir, pid, self.cwd) | 436 self.last_dir = getv(pid_last_dir, pid, self.cwd) |
428 last_pid = pid 429 430 # process operations 431 if w[0] == 'F': 432 npid = int(w[2]) 433 pid_cwd[npid] = cwd 434 pid_last_dir[npid] = cwd 435 last_pid = npid 436 continue 437 elif w[0] == 'C': 438 cwd = abspath(w[2], cwd, None, self.debug, self.debug_out) 439 if cwd.endswith('/.'): 440 cwd = cwd[0:-2] | 437 last_pid = pid 438 439 # process operations 440 if w[0] == 'F': 441 npid = int(w[2]) 442 pid_cwd[npid] = cwd 443 pid_last_dir[npid] = cwd 444 last_pid = npid 445 continue 446 elif w[0] == 'C': 447 cwd = abspath(w[2], cwd, None, self.debug, self.debug_out) 448 if cwd.endswith('/.'): 449 cwd = cwd[0:-2] |
441 last_dir = cwd | 450 self.last_dir = cwd |
442 if self.debug > 1: 443 print("cwd=", cwd, file=self.debug_out) 444 continue 445 446 if w[2] in self.seen: 447 if self.debug > 2: 448 print("seen:", w[2], file=self.debug_out) 449 continue 450 # file operations 451 if w[0] in 'ML': | 451 if self.debug > 1: 452 print("cwd=", cwd, file=self.debug_out) 453 continue 454 455 if w[2] in self.seen: 456 if self.debug > 2: 457 print("seen:", w[2], file=self.debug_out) 458 continue 459 # file operations 460 if w[0] in 'ML': |
452 path = w[2].strip("'") 453 else: 454 path = w[2] 455 # we are never interested in .dirdep files as dependencies 456 if path.endswith('.dirdep'): | 461 # these are special, tread src as read and 462 # target as write 463 self.parse_path(w[1].strip("'"), cwd, 'R', w) 464 self.parse_path(w[2].strip("'"), cwd, 'W', w) |
457 continue | 465 continue |
458 # we don't want to resolve the last component if it is 459 # a symlink 460 path = resolve(path, cwd, last_dir, self.debug, self.debug_out) 461 if not path: 462 continue 463 dir,base = os.path.split(path) 464 if dir in self.seen: | 466 elif w[0] in 'ERWS': 467 path = w[2] 468 self.parse_path(path, cwd, w[0], w) 469 470 if not file: 471 f.close() 472 473 def parse_path(self, path, cwd, op=None, w=[]): 474 """look at a path for the op specified""" 475 476 if not op: 477 op = w[0] 478 479 # we are never interested in .dirdep files as dependencies 480 if path.endswith('.dirdep'): 481 return 482 for p in self.excludes: 483 if p and path.startswith(p): |
465 if self.debug > 2: | 484 if self.debug > 2: |
466 print("seen:", dir, file=self.debug_out) 467 continue 468 # we can have a path in an objdir which is a link 469 # to the src dir, we may need to add dependencies for each 470 rdir = dir 471 dir = abspath(dir, cwd, last_dir, self.debug, self.debug_out) 472 if rdir == dir or rdir.find('./') > 0: 473 rdir = None 474 # now put path back together 475 path = '/'.join([dir,base]) 476 if self.debug > 1: 477 print("raw=%s rdir=%s dir=%s path=%s" % (w[2], rdir, dir, path), file=self.debug_out) 478 if w[0] in 'SRWL': 479 if w[0] == 'W' and path.endswith('.dirdep'): 480 continue 481 if path in [last_dir, cwd, self.cwd, self.curdir]: 482 if self.debug > 1: 483 print("skipping:", path, file=self.debug_out) 484 continue 485 if os.path.isdir(path): 486 if w[0] in 'RW': 487 last_dir = path; 488 if self.debug > 1: 489 print("ldir=", last_dir, file=self.debug_out) 490 continue | 485 print >> self.debug_out, "exclude:", p, path 486 return 487 # we don't want to resolve the last component if it is 488 # a symlink 489 path = resolve(path, cwd, self.last_dir, self.debug, self.debug_out) 490 if not path: 491 return 492 dir,base = os.path.split(path) 493 if dir in self.seen: 494 if self.debug > 2: 495 print("seen:", dir, file=self.debug_out) 496 return 497 # we can have a path in an objdir which is a link 498 # to the src dir, we may need to add dependencies for each 499 rdir = dir 500 dir = abspath(dir, cwd, self.last_dir, self.debug, self.debug_out) 501 if rdir == dir or rdir.find('./') > 0: 502 rdir = None 503 # now put path back together 504 path = '/'.join([dir,base]) 505 if self.debug > 1: 506 print("raw=%s rdir=%s dir=%s path=%s" % (w[2], rdir, dir, path), file=self.debug_out) 507 if op in 'RWS': 508 if path in [self.last_dir, cwd, self.cwd, self.curdir]: 509 if self.debug > 1: 510 print("skipping:", path, file=self.debug_out) 511 return 512 if os.path.isdir(path): 513 if op in 'RW': 514 self.last_dir = path; 515 if self.debug > 1: 516 print("ldir=", self.last_dir, file=self.debug_out) 517 return |
491 | 518 |
492 if w[0] in 'REWML': 493 # finally, we get down to it 494 if dir == self.cwd or dir == self.curdir: 495 continue 496 srctop = self.find_top(path, self.srctops) 497 if srctop: 498 if self.dpdeps: 499 self.add(self.file_deps, path.replace(srctop,''), 'file') 500 self.add(self.src_deps, dir.replace(srctop,''), 'src') 501 self.seenit(w[2]) 502 self.seenit(dir) 503 if rdir and not rdir.startswith(srctop): 504 dir = rdir # for below 505 rdir = None 506 else: 507 continue | 519 if op in 'ERW': 520 # finally, we get down to it 521 if dir == self.cwd or dir == self.curdir: 522 return 523 srctop = self.find_top(path, self.srctops) 524 if srctop: 525 if self.dpdeps: 526 self.add(self.file_deps, path.replace(srctop,''), 'file') 527 self.add(self.src_deps, dir.replace(srctop,''), 'src') 528 self.seenit(w[2]) 529 self.seenit(dir) 530 if rdir and not rdir.startswith(srctop): 531 dir = rdir # for below 532 rdir = None 533 else: 534 return |
508 | 535 |
509 objroot = None 510 for dir in [dir,rdir]: 511 if not dir: 512 continue 513 objroot = self.find_top(dir, self.objroots) 514 if objroot: 515 break | 536 objroot = None 537 for dir in [dir,rdir]: 538 if not dir: 539 continue 540 objroot = self.find_top(dir, self.objroots) |
516 if objroot: | 541 if objroot: |
517 ddep = self.find_obj(objroot, dir, path, w[2]) 518 if ddep: 519 self.add(self.obj_deps, ddep, 'obj') 520 else: 521 # don't waste time looking again 522 self.seenit(w[2]) 523 self.seenit(dir) 524 if not file: 525 f.close() | 542 break 543 if objroot: 544 ddep = self.find_obj(objroot, dir, path, w[2]) 545 if ddep: 546 self.add(self.obj_deps, ddep, 'obj') 547 else: 548 # don't waste time looking again 549 self.seenit(w[2]) 550 self.seenit(dir) |
526 527 528def main(argv, klass=MetaFile, xopts='', xoptf=None): 529 """Simple driver for class MetaFile. 530 531 Usage: | 551 552 553def main(argv, klass=MetaFile, xopts='', xoptf=None): 554 """Simple driver for class MetaFile. 555 556 Usage: |
532 script [options] [key=value ...] "meta" ... | 557 script [options] [key=value ...] "meta" ... |
533 534 Options and key=value pairs contribute to the 535 dictionary passed to MetaFile. 536 537 -S "SRCTOP" | 558 559 Options and key=value pairs contribute to the 560 dictionary passed to MetaFile. 561 562 -S "SRCTOP" |
538 add "SRCTOP" to the "SRCTOPS" list. | 563 add "SRCTOP" to the "SRCTOPS" list. |
539 540 -C "CURDIR" 541 542 -O "OBJROOT" | 564 565 -C "CURDIR" 566 567 -O "OBJROOT" |
543 add "OBJROOT" to the "OBJROOTS" list. | 568 add "OBJROOT" to the "OBJROOTS" list. |
544 545 -m "MACHINE" 546 547 -a "MACHINE_ARCH" 548 549 -H "HOST_TARGET" 550 551 -D "DPDEPS" 552 | 569 570 -m "MACHINE" 571 572 -a "MACHINE_ARCH" 573 574 -H "HOST_TARGET" 575 576 -D "DPDEPS" 577 |
553 -d bumps debug level | 578 -d bumps debug level |
554 555 """ 556 import getopt 557 558 # import Psyco if we can 559 # it can speed things up quite a bit 560 have_psyco = 0 561 try: 562 import psyco 563 psyco.full() 564 have_psyco = 1 565 except: 566 pass 567 568 conf = { 569 'SRCTOPS': [], 570 'OBJROOTS': [], | 579 580 """ 581 import getopt 582 583 # import Psyco if we can 584 # it can speed things up quite a bit 585 have_psyco = 0 586 try: 587 import psyco 588 psyco.full() 589 have_psyco = 1 590 except: 591 pass 592 593 conf = { 594 'SRCTOPS': [], 595 'OBJROOTS': [], |
596 'EXCLUDES': [], |
|
571 } 572 573 try: 574 machine = os.environ['MACHINE'] 575 if machine: 576 conf['MACHINE'] = machine 577 machine_arch = os.environ['MACHINE_ARCH'] 578 if machine_arch: --- 5 unchanged lines hidden (view full) --- 584 if objroot: 585 conf['OBJROOTS'].append(objroot) 586 except: 587 pass 588 589 debug = 0 590 output = True 591 | 597 } 598 599 try: 600 machine = os.environ['MACHINE'] 601 if machine: 602 conf['MACHINE'] = machine 603 machine_arch = os.environ['MACHINE_ARCH'] 604 if machine_arch: --- 5 unchanged lines hidden (view full) --- 610 if objroot: 611 conf['OBJROOTS'].append(objroot) 612 except: 613 pass 614 615 debug = 0 616 output = True 617 |
592 opts, args = getopt.getopt(argv[1:], 'a:dS:C:O:R:m:D:H:qT:' + xopts) | 618 opts, args = getopt.getopt(argv[1:], 'a:dS:C:O:R:m:D:H:qT:X:' + xopts) |
593 for o, a in opts: 594 if o == '-a': 595 conf['MACHINE_ARCH'] = a 596 elif o == '-d': 597 debug += 1 598 elif o == '-q': 599 output = False 600 elif o == '-H': --- 9 unchanged lines hidden (view full) --- 610 elif o == '-R': 611 conf['RELDIR'] = a 612 elif o == '-D': 613 conf['DPDEPS'] = a 614 elif o == '-m': 615 conf['MACHINE'] = a 616 elif o == '-T': 617 conf['TARGET_SPEC'] = a | 619 for o, a in opts: 620 if o == '-a': 621 conf['MACHINE_ARCH'] = a 622 elif o == '-d': 623 debug += 1 624 elif o == '-q': 625 output = False 626 elif o == '-H': --- 9 unchanged lines hidden (view full) --- 636 elif o == '-R': 637 conf['RELDIR'] = a 638 elif o == '-D': 639 conf['DPDEPS'] = a 640 elif o == '-m': 641 conf['MACHINE'] = a 642 elif o == '-T': 643 conf['TARGET_SPEC'] = a |
644 elif o == '-X': 645 if a not in conf['EXCLUDES']: 646 conf['EXCLUDES'].append(a) |
|
618 elif xoptf: 619 xoptf(o, a, conf) 620 621 conf['debug'] = debug 622 623 # get any var=val assignments 624 eaten = [] 625 for a in args: --- 18 unchanged lines hidden (view full) --- 644 debug_out = getv(conf, 'debug_out', sys.stderr) 645 646 if debug: 647 print("config:", file=debug_out) 648 print("psyco=", have_psyco, file=debug_out) 649 for k,v in list(conf.items()): 650 print("%s=%s" % (k,v), file=debug_out) 651 | 647 elif xoptf: 648 xoptf(o, a, conf) 649 650 conf['debug'] = debug 651 652 # get any var=val assignments 653 eaten = [] 654 for a in args: --- 18 unchanged lines hidden (view full) --- 673 debug_out = getv(conf, 'debug_out', sys.stderr) 674 675 if debug: 676 print("config:", file=debug_out) 677 print("psyco=", have_psyco, file=debug_out) 678 for k,v in list(conf.items()): 679 print("%s=%s" % (k,v), file=debug_out) 680 |
681 m = None |
|
652 for a in args: 653 if a.endswith('.meta'): | 682 for a in args: 683 if a.endswith('.meta'): |
684 if not os.path.exists(a): 685 continue |
|
654 m = klass(a, conf) 655 elif a.startswith('@'): 656 # there can actually multiple files per line 657 for line in open(a[1:]): 658 for f in line.strip().split(): | 686 m = klass(a, conf) 687 elif a.startswith('@'): 688 # there can actually multiple files per line 689 for line in open(a[1:]): 690 for f in line.strip().split(): |
691 if not os.path.exists(f): 692 continue |
|
659 m = klass(f, conf) 660 | 693 m = klass(f, conf) 694 |
661 if output: | 695 if output and m: |
662 print(m.dirdeps()) 663 664 print(m.src_dirdeps('\nsrc:')) 665 666 dpdeps = getv(conf, 'DPDEPS') 667 if dpdeps: 668 m.file_depends(open(dpdeps, 'wb')) 669 670 return m 671 672if __name__ == '__main__': 673 try: 674 main(sys.argv) 675 except: 676 # yes, this goes to stdout 677 print("ERROR: ", sys.exc_info()[1]) 678 raise 679 | 696 print(m.dirdeps()) 697 698 print(m.src_dirdeps('\nsrc:')) 699 700 dpdeps = getv(conf, 'DPDEPS') 701 if dpdeps: 702 m.file_depends(open(dpdeps, 'wb')) 703 704 return m 705 706if __name__ == '__main__': 707 try: 708 main(sys.argv) 709 except: 710 # yes, this goes to stdout 711 print("ERROR: ", sys.exc_info()[1]) 712 raise 713 |