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 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 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 errors.MakeError as 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 from langlab.pymake import data, parserdata, process, util, errors # 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 []