def globpattern(dir, pattern): """ Return leaf names in the specified directory which match the pattern. """ if not hasglob(pattern): if pattern == '': if os.path.isdir(dir): return [''] return [] if os.path.exists(util.normaljoin(dir, pattern)): return [pattern] return [] leaves = os.listdir(dir) + ['.', '..'] # "hidden" filenames are a bit special if not pattern.startswith('.'): leaves = [leaf for leaf in leaves if not leaf.startswith('.')] leaves = fnmatch.filter(leaves, pattern) leaves = filter(lambda l: os.path.exists(util.normaljoin(dir, l)), leaves) leaves.sort() return leaves
def globpattern(dir, pattern): """ Return leaf names in the specified directory which match the pattern. """ if not hasglob(pattern): if pattern == '': if os.path.isdir(dir): return [''] return [] if os.path.exists(util.normaljoin(dir, pattern)): return [pattern] return [] leaves = os.listdir(dir) + ['.', '..'] # "hidden" filenames are a bit special if not pattern.startswith('.'): leaves = [leaf for leaf in leaves if not leaf.startswith('.')] leaves = fnmatch.filter(leaves, pattern) leaves = [l for l in leaves if os.path.exists(util.normaljoin(dir, l))] leaves.sort() return leaves
def glob(fsdir, path): """ Yield paths matching the path glob. Sorts as a bonus. Excludes '.' and '..' """ dir, leaf = os.path.split(path) if dir == '': return globpattern(fsdir, leaf) if hasglob(dir): dirsfound = glob(fsdir, dir) else: dirsfound = [dir] r = [] for dir in dirsfound: fspath = util.normaljoin(fsdir, dir) if not os.path.isdir(fspath): continue r.extend((util.normaljoin(dir, found) for found in globpattern(fspath, leaf))) return r
def resolve(self, makefile, variables, fd, setting): assert os.path.isabs(makefile.workdir) fd.write(' '.join([ util.normaljoin(makefile.workdir, path).replace('\\', '/') for path in self._arguments[0].resolvesplit( makefile, variables, setting) ]))
def call(cline, env, cwd, loc, cb, context, echo, justprint=False): #TODO: call this once up-front somewhere and save the result? shell, msys = util.checkmsyscompat() shellreason = None if msys and cline.startswith('/'): shellreason = "command starts with /" else: argv, badchar = clinetoargv(cline) if argv is None: shellreason = "command contains shell-special character '%s'" % ( badchar, ) elif len(argv) and argv[0] in shellwords: shellreason = "command starts with shell primitive '%s'" % ( argv[0], ) if shellreason is not None: _log.debug("%s: using shell: %s: '%s'", loc, shellreason, cline) if msys: if len(cline) > 3 and cline[1] == ':' and cline[2] == '/': cline = '/' + cline[0] + cline[2:] cline = [shell, "-c", cline] context.call(cline, shell=not msys, env=env, cwd=cwd, cb=cb, echo=echo, justprint=justprint) return if not len(argv): cb(res=0) return if argv[0] == command.makepypath: command.main(argv[1:], env, cwd, cb) return if argv[0:2] == [ sys.executable.replace('\\', '/'), command.makepypath.replace('\\', '/') ]: command.main(argv[2:], env, cwd, cb) return if argv[0].find('/') != -1: executable = util.normaljoin(cwd, argv[0]) else: executable = None context.call(argv, executable=executable, shell=False, env=env, cwd=cwd, cb=cb, echo=echo, justprint=justprint)
def call(cline, env, cwd, loc, cb, context, echo, justprint=False): #TODO: call this once up-front somewhere and save the result? shell, msys = util.checkmsyscompat() shellreason = None if msys and cline.startswith('/'): shellreason = "command starts with /" else: argv, badchar = clinetoargv(cline, blacklist_gray=True) if argv is None: shellreason = "command contains shell-special character '%s'" % (badchar,) elif len(argv) and argv[0] in shellwords: shellreason = "command starts with shell primitive '%s'" % (argv[0],) else: argv = doglobbing(argv, cwd) if shellreason is not None: _log.debug("%s: using shell: %s: '%s'", loc, shellreason, cline) if msys: if len(cline) > 3 and cline[1] == ':' and cline[2] == '/': cline = '/' + cline[0] + cline[2:] cline = [shell, "-c", cline] context.call(cline, shell=False, env=env, cwd=cwd, cb=cb, echo=echo, justprint=justprint) return if not len(argv): cb(res=0) return if argv[0] == command.makepypath: command.main(argv[1:], env, cwd, cb) return if argv[0:2] == [sys.executable.replace('\\', '/'), command.makepypath.replace('\\', '/')]: command.main(argv[2:], env, cwd, cb) return if argv[0].find('/') != -1: executable = util.normaljoin(cwd, argv[0]) else: executable = None context.call(argv, executable=executable, shell=False, env=env, cwd=cwd, cb=cb, echo=echo, justprint=justprint)
def prepare_command(cline, cwd, loc): """ Returns a list of command and arguments for the given command line string. If the command needs to be run through a shell for some reason, the returned list contains the shell invocation. """ #TODO: call this once up-front somewhere and save the result? shell, msys = util.checkmsyscompat() shellreason = None executable = None if msys and cline.startswith('/'): shellreason = "command starts with /" else: argv, badchar = clinetoargv(cline, cwd) if argv is None: shellreason = "command contains shell-special character '%s'" % ( badchar, ) elif len(argv) and argv[0] in shellwords: shellreason = "command starts with shell primitive '%s'" % ( argv[0], ) elif argv and (os.sep in argv[0] or os.altsep and os.altsep in argv[0]): executable = util.normaljoin(cwd, argv[0]) # Avoid "%1 is not a valid Win32 application" errors, assuming # that if the executable path is to be resolved with PATH, it will # be a Win32 executable. if sys.platform == 'win32' and os.path.isfile(executable) and open( executable, 'rb').read(2) == "#!": shellreason = "command executable starts with a hashbang" if shellreason is not None: _log.debug("%s: using shell: %s: '%s'", loc, shellreason, cline) if msys: if len(cline) > 3 and cline[1] == ':' and cline[2] == '/': cline = '/' + cline[0] + cline[2:] argv = [shell, "-c", cline] executable = None return executable, argv
def prepare_command(cline, cwd, loc): """ Returns a list of command and arguments for the given command line string. If the command needs to be run through a shell for some reason, the returned list contains the shell invocation. """ #TODO: call this once up-front somewhere and save the result? shell, msys = util.checkmsyscompat() shellreason = None executable = None if msys and cline.startswith('/'): shellreason = "command starts with /" else: argv, badchar = clinetoargv(cline, cwd) if argv is None: shellreason = "command contains shell-special character '%s'" % (badchar,) elif len(argv) and argv[0] in shellwords: shellreason = "command starts with shell primitive '%s'" % (argv[0],) elif argv and (os.sep in argv[0] or os.altsep and os.altsep in argv[0]): executable = util.normaljoin(cwd, argv[0]) # Avoid "%1 is not a valid Win32 application" errors, assuming # that if the executable path is to be resolved with PATH, it will # be a Win32 executable. if sys.platform == 'win32' and os.path.isfile(executable) and open(executable, 'rb').read(2) == "#!": shellreason = "command executable starts with a hashbang" if shellreason is not None: _log.debug("%s: using shell: %s: '%s'", loc, shellreason, cline) if msys: if len(cline) > 3 and cline[1] == ':' and cline[2] == '/': cline = '/' + cline[0] + cline[2:] argv = [shell, "-c", cline] executable = None return executable, argv
def resolve(self, makefile, variables, fd, setting): assert os.path.isabs(makefile.workdir) fd.write(' '.join([util.normaljoin(makefile.workdir, path).replace('\\', '/') for path in self._arguments[0].resolvesplit(makefile, variables, setting)]))
def main(args, env, cwd, cb): """ Start a single makefile execution, given a command line, working directory, and environment. @param cb a callback to notify with an exit code when make execution is finished. """ try: makelevel = int(env.get('MAKELEVEL', '0')) op = OptionParser() op.add_option('-f', '--file', '--makefile', action='append', dest='makefiles', default=[]) op.add_option('-d', action="store_true", dest="verbose", default=False) op.add_option('-k', '--keep-going', action="store_true", dest="keepgoing", default=False) op.add_option('--debug-log', dest="debuglog", default=None) op.add_option('-C', '--directory', dest="directory", default=None) op.add_option('-v', '--version', action="store_true", dest="printversion", default=False) op.add_option('-j', '--jobs', type="int", dest="jobcount", default=1) op.add_option('-w', '--print-directory', action="store_true", dest="printdir") op.add_option('--no-print-directory', action="store_false", dest="printdir", default=True) op.add_option('-s', '--silent', action="store_true", dest="silent", default=False) op.add_option('-n', '--just-print', '--dry-run', '--recon', action="store_true", dest="justprint", default=False) options, arguments1 = op.parse_args(parsemakeflags(env)) options, arguments2 = op.parse_args(args, values=options) op.destroy() arguments = arguments1 + arguments2 if options.printversion: _version() cb(0) return shortflags = [] longflags = [] if options.keepgoing: shortflags.append('k') if options.printdir: shortflags.append('w') if options.silent: shortflags.append('s') options.printdir = False if options.justprint: shortflags.append('n') loglevel = logging.WARNING if options.verbose: loglevel = logging.DEBUG shortflags.append('d') logkwargs = {} if options.debuglog: logkwargs['filename'] = options.debuglog longflags.append('--debug-log=%s' % options.debuglog) if options.directory is None: workdir = cwd else: workdir = util.normaljoin(cwd, options.directory) if options.jobcount != 1: longflags.append('-j%i' % (options.jobcount, )) makeflags = ''.join(shortflags) if len(longflags): makeflags += ' ' + ' '.join(longflags) logging.basicConfig(level=loglevel, **logkwargs) context = process.getcontext(options.jobcount) if options.printdir: print "make.py[%i]: Entering directory '%s'" % (makelevel, workdir) sys.stdout.flush() if len(options.makefiles) == 0: if os.path.exists(util.normaljoin(workdir, 'Makefile')): options.makefiles.append('Makefile') else: print "No makefile found" cb(2) return ostmts, targets, overrides = parserdata.parsecommandlineargs(arguments) _MakeContext(makeflags, makelevel, workdir, context, env, targets, options, ostmts, overrides, cb) except (util.MakeError), e: print e if options.printdir: print "make.py[%i]: Leaving directory '%s'" % (makelevel, workdir) sys.stdout.flush() cb(2) return
""" Makefile execution. Multiple `makes` can be run within the same process. Each one has an entirely data.Makefile and .Target structure, environment, and working directory. Typically they will all share a parallel execution context, except when a submake specifies -j1 when the parent make is building in parallel. """ import os, subprocess, sys, logging, time, traceback, re from optparse import OptionParser import data, parserdata, process, util # TODO: If this ever goes from relocatable package to system-installed, this may need to be # a configured-in path. makepypath = util.normaljoin(os.path.dirname(__file__), '../make.py') _simpleopts = re.compile(r'^[a-zA-Z]+(\s|$)') def parsemakeflags(env): """ Parse MAKEFLAGS from the environment into a sequence of command-line arguments. """ makeflags = env.get('MAKEFLAGS', '') makeflags = makeflags.strip() if makeflags == '': return []
def main(args, env, cwd, cb): """ Start a single makefile execution, given a command line, working directory, and environment. @param cb a callback to notify with an exit code when make execution is finished. """ try: makelevel = int(env.get('MAKELEVEL', '0')) op = OptionParser() op.add_option('-f', '--file', '--makefile', action='append', dest='makefiles', default=[]) op.add_option('-d', action="store_true", dest="verbose", default=False) op.add_option('-k', '--keep-going', action="store_true", dest="keepgoing", default=False) op.add_option('--debug-log', dest="debuglog", default=None) op.add_option('-C', '--directory', dest="directory", default=None) op.add_option('-v', '--version', action="store_true", dest="printversion", default=False) op.add_option('-j', '--jobs', type="int", dest="jobcount", default=1) op.add_option('-w', '--print-directory', action="store_true", dest="printdir") op.add_option('--no-print-directory', action="store_false", dest="printdir", default=True) op.add_option('-s', '--silent', action="store_true", dest="silent", default=False) op.add_option('-n', '--just-print', '--dry-run', '--recon', action="store_true", dest="justprint", default=False) options, arguments1 = op.parse_args(parsemakeflags(env)) options, arguments2 = op.parse_args(args, values=options) op.destroy() arguments = arguments1 + arguments2 if options.printversion: _version() cb(0) return shortflags = [] longflags = [] if options.keepgoing: shortflags.append('k') if options.printdir: shortflags.append('w') if options.silent: shortflags.append('s') options.printdir = False if options.justprint: shortflags.append('n') loglevel = logging.WARNING if options.verbose: loglevel = logging.DEBUG shortflags.append('d') logkwargs = {} if options.debuglog: logkwargs['filename'] = options.debuglog longflags.append('--debug-log=%s' % options.debuglog) if options.directory is None: workdir = cwd else: workdir = util.normaljoin(cwd, options.directory) if options.jobcount != 1: longflags.append('-j%i' % (options.jobcount,)) makeflags = ''.join(shortflags) if len(longflags): makeflags += ' ' + ' '.join(longflags) logging.basicConfig(level=loglevel, **logkwargs) context = process.getcontext(options.jobcount) if options.printdir: print "make.py[%i]: Entering directory '%s'" % (makelevel, workdir) sys.stdout.flush() if len(options.makefiles) == 0: if os.path.exists(util.normaljoin(workdir, 'Makefile')): options.makefiles.append('Makefile') else: print "No makefile found" cb(2) return ostmts, targets, overrides = parserdata.parsecommandlineargs(arguments) _MakeContext(makeflags, makelevel, workdir, context, env, targets, options, ostmts, overrides, cb) except (util.MakeError), e: print e if options.printdir: print "make.py[%i]: Leaving directory '%s'" % (makelevel, workdir) sys.stdout.flush() cb(2) return
""" Makefile execution. Multiple `makes` can be run within the same process. Each one has an entirely data.Makefile and .Target structure, environment, and working directory. Typically they will all share a parallel execution context, except when a submake specifies -j1 when the parent make is building in parallel. """ import os, subprocess, sys, logging, time, traceback, re from optparse import OptionParser import data, parserdata, process, util # TODO: If this ever goes from relocatable package to system-installed, this may need to be # a configured-in path. makepypath = util.normaljoin(os.path.dirname(__file__), '../make.py') _simpleopts = re.compile(r'^[a-zA-Z]+(\s|$)') def parsemakeflags(env): """ Parse MAKEFLAGS from the environment into a sequence of command-line arguments. """ makeflags = env.get('MAKEFLAGS', '') makeflags = makeflags.strip() if makeflags == '': return [] if _simpleopts.match(makeflags): makeflags = '-' + makeflags