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 pymake import data, parserdata, process, util from pymake import 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 []