1.1 Binary file waf has changed
2.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
2.2 +++ b/waf-tools/cflags.py Fri Oct 23 13:05:56 2009 +0100
2.3 @@ -0,0 +1,192 @@
2.4 +import Logs
2.5 +import Options
2.6 +import Utils
2.7 +
2.8 +
2.9 +class CompilerTraits(object):
2.10 + def get_warnings_flags(self, level):
2.11 + """get_warnings_flags(level) -> list of cflags"""
2.12 + raise NotImplementedError
2.13 +
2.14 + def get_optimization_flags(self, level):
2.15 + """get_optimization_flags(level) -> list of cflags"""
2.16 + raise NotImplementedError
2.17 +
2.18 + def get_debug_flags(self, level):
2.19 + """get_debug_flags(level) -> (list of cflags, list of cppdefines)"""
2.20 + raise NotImplementedError
2.21 +
2.22 +
2.23 +class GccTraits(CompilerTraits):
2.24 + def __init__(self):
2.25 + super(GccTraits, self).__init__()
2.26 + # cumulative list of warnings per level
2.27 + self.warnings_flags = [['-Wall'], ['-Werror'], ['-Wextra']]
2.28 +
2.29 + def get_warnings_flags(self, level):
2.30 + warnings = []
2.31 + for l in range(level):
2.32 + if l < len(self.warnings_flags):
2.33 + warnings.extend(self.warnings_flags[l])
2.34 + else:
2.35 + break
2.36 + return warnings
2.37 +
2.38 + def get_optimization_flags(self, level):
2.39 + if level == 0:
2.40 + return ['-O0']
2.41 + elif level == 1:
2.42 + return ['-O']
2.43 + elif level == 2:
2.44 + return ['-O2']
2.45 + elif level == 3:
2.46 + return ['-O3']
2.47 +
2.48 + def get_debug_flags(self, level):
2.49 + if level == 0:
2.50 + return (['-g0'], ['NDEBUG'])
2.51 + elif level == 1:
2.52 + return (['-g'], [])
2.53 + elif level >= 2:
2.54 + return (['-ggdb', '-g3'], ['_DEBUG'])
2.55 +
2.56 +
2.57 +class IccTraits(CompilerTraits):
2.58 + def __init__(self):
2.59 + super(IccTraits, self).__init__()
2.60 + # cumulative list of warnings per level
2.61 + # icc is _very_ verbose with -Wall, -Werror is barely achievable
2.62 + self.warnings_flags = [[], [], ['-Wall']]
2.63 +
2.64 + def get_warnings_flags(self, level):
2.65 + warnings = []
2.66 + for l in range(level):
2.67 + if l < len(self.warnings_flags):
2.68 + warnings.extend(self.warnings_flags[l])
2.69 + else:
2.70 + break
2.71 + return warnings
2.72 +
2.73 + def get_optimization_flags(self, level):
2.74 + if level == 0:
2.75 + return ['-O0']
2.76 + elif level == 1:
2.77 + return ['-O']
2.78 + elif level == 2:
2.79 + return ['-O2']
2.80 + elif level == 3:
2.81 + return ['-O3']
2.82 +
2.83 + def get_debug_flags(self, level):
2.84 + if level == 0:
2.85 + return (['-g0'], ['NDEBUG'])
2.86 + elif level == 1:
2.87 + return (['-g'], [])
2.88 + elif level >= 2:
2.89 + return (['-ggdb', '-g3'], ['_DEBUG'])
2.90 +
2.91 +
2.92 +
2.93 +class MsvcTraits(CompilerTraits):
2.94 + def __init__(self):
2.95 + super(MsvcTraits, self).__init__()
2.96 + # cumulative list of warnings per level
2.97 + self.warnings_flags = [['/W2'], ['/WX'], ['/Wall']]
2.98 +
2.99 + def get_warnings_flags(self, level):
2.100 + warnings = []
2.101 + for l in range(level):
2.102 + if l < len(self.warnings_flags):
2.103 + warnings.extend(self.warnings_flags[l])
2.104 + else:
2.105 + break
2.106 + return warnings
2.107 +
2.108 + def get_optimization_flags(self, level):
2.109 + if level == 0:
2.110 + return ['/Od']
2.111 + elif level == 1:
2.112 + return []
2.113 + elif level == 2:
2.114 + return ['/O2']
2.115 + elif level == 3:
2.116 + return ['/Ox']
2.117 +
2.118 + def get_debug_flags(self, level):
2.119 + if level == 0:
2.120 + return ([], ['NDEBUG'])
2.121 + elif level == 1:
2.122 + return (['/ZI', '/RTC1'], [])
2.123 + elif level >= 2:
2.124 + return (['/ZI', '/RTC1'], ['_DEBUG'])
2.125 +
2.126 +
2.127 +
2.128 +gcc = GccTraits()
2.129 +icc = IccTraits()
2.130 +msvc = MsvcTraits()
2.131 +
2.132 +# how to map env['COMPILER_CC'] or env['COMPILER_CXX'] into a traits object
2.133 +compiler_mapping = {
2.134 + 'gcc': gcc,
2.135 + 'g++': gcc,
2.136 + 'msvc': msvc,
2.137 + 'icc': icc,
2.138 + 'icpc': icc,
2.139 +}
2.140 +
2.141 +profiles = {
2.142 + # profile name: [optimization_level, warnings_level, debug_level]
2.143 + 'default': [2, 1, 1],
2.144 + 'debug': [0, 2, 3],
2.145 + 'release': [3, 1, 0],
2.146 + }
2.147 +
2.148 +default_profile = 'default'
2.149 +
2.150 +def set_options(opt):
2.151 + assert default_profile in profiles
2.152 + opt.add_option('-d', '--build-profile',
2.153 + action='store',
2.154 + default=default_profile,
2.155 + help=("Specify the build profile. "
2.156 + "Build profiles control the default compilation flags"
2.157 + " used for C/C++ programs, if CCFLAGS/CXXFLAGS are not"
2.158 + " set set in the environment. [Allowed Values: %s]"
2.159 + % ", ".join([repr(p) for p in profiles.keys()])),
2.160 + choices=profiles.keys(),
2.161 + dest='build_profile')
2.162 +
2.163 +def detect(conf):
2.164 + cc = conf.env['COMPILER_CC'] or None
2.165 + cxx = conf.env['COMPILER_CXX'] or None
2.166 + if not (cc or cxx):
2.167 + raise Utils.WafError("neither COMPILER_CC nor COMPILER_CXX are defined; "
2.168 + "maybe the compiler_cc or compiler_cxx tool has not been configured yet?")
2.169 +
2.170 + try:
2.171 + compiler = compiler_mapping[cc]
2.172 + except KeyError:
2.173 + try:
2.174 + compiler = compiler_mapping[cxx]
2.175 + except KeyError:
2.176 + Logs.warn("No compiler flags support for compiler %r or %r"
2.177 + % (cc, cxx))
2.178 + return
2.179 +
2.180 + opt_level, warn_level, dbg_level = profiles[Options.options.build_profile]
2.181 +
2.182 + optimizations = compiler.get_optimization_flags(opt_level)
2.183 + debug, debug_defs = compiler.get_debug_flags(dbg_level)
2.184 + warnings = compiler.get_warnings_flags(warn_level)
2.185 +
2.186 + if cc and not conf.env['CCFLAGS']:
2.187 + conf.env.append_value('CCFLAGS', optimizations)
2.188 + conf.env.append_value('CCFLAGS', debug)
2.189 + conf.env.append_value('CCFLAGS', warnings)
2.190 + conf.env.append_value('CCDEFINES', debug_defs)
2.191 + if cxx and not conf.env['CXXFLAGS']:
2.192 + conf.env.append_value('CXXFLAGS', optimizations)
2.193 + conf.env.append_value('CXXFLAGS', debug)
2.194 + conf.env.append_value('CXXFLAGS', warnings)
2.195 + conf.env.append_value('CXXDEFINES', debug_defs)
3.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
3.2 +++ b/waf-tools/command.py Fri Oct 23 13:05:56 2009 +0100
3.3 @@ -0,0 +1,134 @@
3.4 +from TaskGen import feature, taskgen, before, task_gen
3.5 +import Node, Task, Utils, Build, pproc, Constants
3.6 +import Options
3.7 +
3.8 +import shellcmd
3.9 +shellcmd.subprocess = pproc # the WAF version of the subprocess module is supposedly less buggy
3.10 +
3.11 +from Logs import debug, error
3.12 +shellcmd.debug = debug
3.13 +
3.14 +import Task
3.15 +
3.16 +import re
3.17 +
3.18 +
3.19 +arg_rx = re.compile(r"(?P<dollar>\$\$)|(?P<subst>\$\{(?P<var>\w+)(?P<code>.*?)\})", re.M)
3.20 +
3.21 +class command_task(Task.Task):
3.22 + color = "BLUE"
3.23 + def __init__(self, env, generator):
3.24 + Task.Task.__init__(self, env, normal=1, generator=generator)
3.25 +
3.26 + def __str__(self):
3.27 + "string to display to the user"
3.28 + env = self.env
3.29 + src_str = ' '.join([a.nice_path(env) for a in self.inputs])
3.30 + tgt_str = ' '.join([a.nice_path(env) for a in self.outputs])
3.31 + if self.outputs:
3.32 + sep = ' -> '
3.33 + else:
3.34 + sep = ''
3.35 +
3.36 + pipeline = shellcmd.Pipeline()
3.37 + pipeline.parse(self.generator.command)
3.38 + cmd = pipeline.get_abbreviated_command()
3.39 +
3.40 + return 'command (%s): %s%s%s\n' % (cmd, src_str, sep, tgt_str)
3.41 +
3.42 + def _subst_arg(self, arg, direction, namespace):
3.43 + """
3.44 + @param arg: the command argument (or stdin/stdout/stderr) to substitute
3.45 + @param direction: direction of the argument: 'in', 'out', or None
3.46 + """
3.47 + def repl(match):
3.48 + if match.group('dollar'):
3.49 + return "$"
3.50 + elif match.group('subst'):
3.51 + var = match.group('var')
3.52 + code = match.group('code')
3.53 + result = eval(var+code, namespace)
3.54 + if isinstance(result, Node.Node):
3.55 + if var == 'TGT':
3.56 + return result.bldpath(self.env)
3.57 + elif var == 'SRC':
3.58 + return result.srcpath(self.env)
3.59 + else:
3.60 + raise ValueError("Bad subst variable %r" % var)
3.61 + elif result is self.inputs:
3.62 + if len(self.inputs) == 1:
3.63 + return result[0].srcpath(self.env)
3.64 + else:
3.65 + raise ValueError("${SRC} requested but have multiple sources; which one?")
3.66 + elif result is self.outputs:
3.67 + if len(self.outputs) == 1:
3.68 + return result[0].bldpath(self.env)
3.69 + else:
3.70 + raise ValueError("${TGT} requested but have multiple targets; which one?")
3.71 + else:
3.72 + return result
3.73 + return None
3.74 +
3.75 + return arg_rx.sub(repl, arg)
3.76 +
3.77 + def run(self):
3.78 + pipeline = shellcmd.Pipeline()
3.79 + pipeline.parse(self.generator.command)
3.80 + namespace = self.env.get_merged_dict()
3.81 + if self.generator.variables is not None:
3.82 + namespace.update(self.generator.variables)
3.83 + namespace.update(env=self.env, SRC=self.inputs, TGT=self.outputs)
3.84 + for cmd in pipeline.pipeline:
3.85 + if isinstance(cmd, shellcmd.Command):
3.86 + if isinstance(cmd.stdin, basestring):
3.87 + cmd.stdin = self._subst_arg(cmd.stdin, 'in', namespace)
3.88 + if isinstance(cmd.stdout, basestring):
3.89 + cmd.stdout = self._subst_arg(cmd.stdout, 'out', namespace)
3.90 + if isinstance(cmd.stderr, basestring):
3.91 + cmd.stderr = self._subst_arg(cmd.stderr, 'out', namespace)
3.92 + for argI in xrange(len(cmd.argv)):
3.93 + cmd.argv[argI] = self._subst_arg(cmd.argv[argI], None, namespace)
3.94 + if cmd.env_vars is not None:
3.95 + env_vars = dict()
3.96 + for name, value in cmd.env_vars.iteritems():
3.97 + env_vars[name] = self._subst_arg(value, None, namespace)
3.98 + cmd.env_vars = env_vars
3.99 + elif isinstance(cmd, shellcmd.Chdir):
3.100 + cmd.dir = self._subst_arg(cmd.dir, None, namespace)
3.101 +
3.102 + return pipeline.run(verbose=(Options.options.verbose > 0))
3.103 +
3.104 +@taskgen
3.105 +@feature('command')
3.106 +def init_command(self):
3.107 + Utils.def_attrs(self,
3.108 + # other variables that can be used in the command: ${VARIABLE}
3.109 + variables = None)
3.110 +
3.111 +
3.112 +
3.113 +@taskgen
3.114 +@feature('command')
3.115 +@before('apply_core')
3.116 +def apply_command(self):
3.117 + self.meths.remove('apply_core')
3.118 + # create the task
3.119 + task = self.create_task('command')
3.120 + setattr(task, "dep_vars", getattr(self, "dep_vars", None))
3.121 + # process the sources
3.122 + inputs = []
3.123 + for src in self.to_list(self.source):
3.124 + node = self.path.find_resource(src)
3.125 + if node is None:
3.126 + raise Utils.WafError("source %s not found" % src)
3.127 + inputs.append(node)
3.128 + task.set_inputs(inputs)
3.129 + task.set_outputs([self.path.find_or_declare(tgt) for tgt in self.to_list(self.target)])
3.130 + #Task.file_deps = Task.extract_deps
3.131 +
3.132 +
3.133 +
3.134 +class command_taskgen(task_gen):
3.135 + def __init__(self, *k, **kw):
3.136 + task_gen.__init__(self, *k, **kw)
3.137 + self.features.append('command')
4.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
4.2 +++ b/waf-tools/pkgconfig.py Fri Oct 23 13:05:56 2009 +0100
4.3 @@ -0,0 +1,71 @@
4.4 +# -*- mode: python; encoding: utf-8 -*-
4.5 +# Gustavo Carneiro (gjamc) 2008
4.6 +
4.7 +import Options
4.8 +import Configure
4.9 +import pproc as subprocess
4.10 +import config_c
4.11 +
4.12 +def detect(conf):
4.13 + pkg_config = conf.find_program('pkg-config', var='PKG_CONFIG')
4.14 + if not pkg_config: return
4.15 +
4.16 +@Configure.conf
4.17 +def pkg_check_modules(conf, uselib_name, expression, mandatory=True):
4.18 + pkg_config = conf.env['PKG_CONFIG']
4.19 + if not pkg_config:
4.20 + if mandatory:
4.21 + conf.fatal("pkg-config is not available")
4.22 + else:
4.23 + return False
4.24 +
4.25 + argv = [pkg_config, '--cflags', '--libs', expression]
4.26 + cmd = subprocess.Popen(argv, stdout=subprocess.PIPE)
4.27 + out, dummy = cmd.communicate()
4.28 + retval = cmd.wait()
4.29 +
4.30 + msg_checking = ("pkg-config flags for %s" % (uselib_name,))
4.31 + if Options.options.verbose:
4.32 + if retval == 0:
4.33 + conf.check_message_custom(msg_checking,
4.34 + ('(%s)' % expression), out)
4.35 + else:
4.36 + conf.check_message(msg_checking, ('(%s)' % expression), False)
4.37 + else:
4.38 + conf.check_message(msg_checking, '', (retval == 0), '')
4.39 + conf.log.write('%r: %r (exit code %i)\n' % (argv, out, retval))
4.40 +
4.41 + if retval == 0:
4.42 +
4.43 + config_c.parse_flags(out, uselib_name, conf.env)
4.44 + conf.env[uselib_name] = True
4.45 + return True
4.46 +
4.47 + else:
4.48 +
4.49 + conf.env[uselib_name] = False
4.50 + if mandatory:
4.51 + raise Configure.ConfigurationError('pkg-config check failed')
4.52 + else:
4.53 + return False
4.54 +
4.55 +@Configure.conf
4.56 +def pkg_check_module_variable(conf, module, variable):
4.57 + pkg_config = conf.env['PKG_CONFIG']
4.58 + if not pkg_config:
4.59 + conf.fatal("pkg-config is not available")
4.60 +
4.61 + argv = [pkg_config, '--variable', variable, module]
4.62 + cmd = subprocess.Popen(argv, stdout=subprocess.PIPE)
4.63 + out, dummy = cmd.communicate()
4.64 + retval = cmd.wait()
4.65 + out = out.rstrip() # strip the trailing newline
4.66 +
4.67 + msg_checking = ("pkg-config variable %r in %s" % (variable, module,))
4.68 + conf.check_message_custom(msg_checking, '', out)
4.69 + conf.log.write('%r: %r (exit code %i)\n' % (argv, out, retval))
4.70 +
4.71 + if retval == 0:
4.72 + return out
4.73 + else:
4.74 + raise Configure.ConfigurationError('pkg-config check failed')
5.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
5.2 +++ b/waf-tools/shellcmd.py Fri Oct 23 13:05:56 2009 +0100
5.3 @@ -0,0 +1,345 @@
5.4 +# Copyright (C) 2008 Gustavo J. A. M. Carneiro <gjcarneiro@gmail.com>
5.5 +
5.6 +# This program is free software; you can redistribute it and/or modify
5.7 +# it under the terms of the GNU General Public License as published by
5.8 +# the Free Software Foundation; either version 2 of the License, or
5.9 +# (at your option) any later version.
5.10 +
5.11 +# This program is distributed in the hope that it will be useful,
5.12 +# but WITHOUT ANY WARRANTY; without even the implied warranty of
5.13 +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
5.14 +# GNU General Public License for more details.
5.15 +
5.16 +# You should have received a copy of the GNU General Public License
5.17 +# along with this program; if not, write to the Free Software
5.18 +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
5.19 +
5.20 +import shlex
5.21 +import subprocess
5.22 +import sys
5.23 +import re
5.24 +import os
5.25 +
5.26 +env_var_rx = re.compile(r"^([a-zA-Z0-9_]+)=(\S+)$")
5.27 +
5.28 +def debug(message):
5.29 + print >> sys.stderr, message
5.30 +
5.31 +
5.32 +if sys.platform == 'win32':
5.33 + dev_null = open("NUL:", "w")
5.34 +else:
5.35 + dev_null = open("/dev/null", "w")
5.36 +
5.37 +def _open_out_file(filename):
5.38 + if filename in ['NUL:', '/dev/null']:
5.39 + return dev_null
5.40 + else:
5.41 + return open(filename, 'wb')
5.42 +
5.43 +
5.44 +class Node(object):
5.45 + pass
5.46 +
5.47 +class Op(Node):
5.48 + pass
5.49 +
5.50 +class Pipe(Op):
5.51 + pass
5.52 +
5.53 +class And(Op):
5.54 + pass
5.55 +
5.56 +class Or(Op):
5.57 + pass
5.58 +
5.59 +class Command(Node):
5.60 + class PIPE(object):
5.61 + pass # PIPE is a constant
5.62 + class STDOUT(object):
5.63 + pass # PIPE is a constant
5.64 +
5.65 + def __init__(self, name):
5.66 + super(Command, self).__init__()
5.67 + self.name = name # command name
5.68 + self.argv = [name] # command argv
5.69 + self.stdin = None
5.70 + self.stdout = None
5.71 + self.stderr = None
5.72 + self.env_vars = None
5.73 +
5.74 + def __repr__(self):
5.75 + return "Command(%r, argv=%r, stdin=%r, stdout=%r, stderr=%r)" \
5.76 + % (self.name, self.argv, self.stdin, self.stdout, self.stderr)
5.77 +
5.78 +class Chdir(Node):
5.79 + def __init__(self):
5.80 + super(Chdir, self).__init__()
5.81 + self.dir = None
5.82 +
5.83 + def __repr__(self):
5.84 + return "Chdir(%r)" \
5.85 + % (self.dir)
5.86 +
5.87 +class Pipeline(object):
5.88 + def __init__(self):
5.89 + self.current_command = None
5.90 + self.pipeline = []
5.91 +
5.92 + def _commit_command(self):
5.93 + assert self.current_command is not None
5.94 + self.pipeline.append(self.current_command)
5.95 + self.current_command = None
5.96 +
5.97 + def get_abbreviated_command(self):
5.98 + l = []
5.99 + for node in self.pipeline:
5.100 + if isinstance(node, Command):
5.101 + l.append(node.name)
5.102 + if isinstance(node, Chdir):
5.103 + l.append('cd %s' % node.dir)
5.104 + elif isinstance(node, Pipe):
5.105 + l.append('|')
5.106 + elif isinstance(node, And):
5.107 + l.append('&&')
5.108 + elif isinstance(node, And):
5.109 + l.append('||')
5.110 + return ' '.join(l)
5.111 +
5.112 + def parse(self, command):
5.113 + self.current_command = None
5.114 + self.pipeline = []
5.115 +
5.116 + if isinstance(command, list):
5.117 + tokens = list(command)
5.118 + else:
5.119 + tokens = shlex.split(command)
5.120 + debug("command: shlex: %r" % (tokens,))
5.121 +
5.122 + BEGIN, COMMAND, CHDIR, STDERR, STDOUT, STDIN = range(6)
5.123 + state = BEGIN
5.124 + self.current_command = None
5.125 + env_vars = dict()
5.126 +
5.127 + while tokens:
5.128 + token = tokens.pop(0)
5.129 + if state == BEGIN:
5.130 + env_var_match = env_var_rx.match(token)
5.131 + if env_var_match is not None:
5.132 + env_vars[env_var_match.group(1)] = env_var_match.group(2)
5.133 + else:
5.134 + assert self.current_command is None
5.135 + if token == 'cd':
5.136 + self.current_command = Chdir()
5.137 + assert not env_vars
5.138 + state = CHDIR
5.139 + else:
5.140 + self.current_command = Command(token)
5.141 + if env_vars:
5.142 + self.current_command.env_vars = env_vars
5.143 + env_vars = dict()
5.144 + state = COMMAND
5.145 + elif state == COMMAND:
5.146 + if token == '>':
5.147 + state = STDOUT
5.148 + elif token == '2>':
5.149 + state = STDERR
5.150 + elif token == '2>&1':
5.151 + assert self.current_command.stderr is None
5.152 + self.current_command.stderr = Command.STDOUT
5.153 + elif token == '<':
5.154 + state = STDIN
5.155 + elif token == '|':
5.156 + assert self.current_command.stdout is None
5.157 + self.current_command.stdout = Command.PIPE
5.158 + self._commit_command()
5.159 + self.pipeline.append(Pipe())
5.160 + state = BEGIN
5.161 + elif token == '&&':
5.162 + self._commit_command()
5.163 + self.pipeline.append(And())
5.164 + state = BEGIN
5.165 + elif token == '||':
5.166 + self._commit_command()
5.167 + self.pipeline.append(Or())
5.168 + state = BEGIN
5.169 + else:
5.170 + self.current_command.argv.append(token)
5.171 + elif state == CHDIR:
5.172 + if token == '&&':
5.173 + self._commit_command()
5.174 + self.pipeline.append(And())
5.175 + state = BEGIN
5.176 + else:
5.177 + assert self.current_command.dir is None
5.178 + self.current_command.dir = token
5.179 + elif state == STDOUT:
5.180 + assert self.current_command.stdout is None
5.181 + self.current_command.stdout = token
5.182 + state = COMMAND
5.183 + elif state == STDERR:
5.184 + assert self.current_command.stderr is None
5.185 + self.current_command.stderr = token
5.186 + state = COMMAND
5.187 + elif state == STDIN:
5.188 + assert self.current_command.stdin is None
5.189 + self.current_command.stdin = token
5.190 + state = COMMAND
5.191 + self._commit_command()
5.192 + return self.pipeline
5.193 +
5.194 + def _exec_piped_commands(self, commands):
5.195 + retvals = []
5.196 + for cmd in commands:
5.197 + retvals.append(cmd.wait())
5.198 + retval = 0
5.199 + for r in retvals:
5.200 + if r:
5.201 + retval = retvals[-1]
5.202 + break
5.203 + return retval
5.204 +
5.205 + def run(self, verbose=False):
5.206 + pipeline = list(self.pipeline)
5.207 + files_to_close = []
5.208 + piped_commands = []
5.209 + piped_commands_display = []
5.210 + BEGIN, PIPE = range(2)
5.211 + state = BEGIN
5.212 + cwd = '.'
5.213 + while pipeline:
5.214 + node = pipeline.pop(0)
5.215 +
5.216 + if isinstance(node, Chdir):
5.217 + next_op = pipeline.pop(0)
5.218 + assert isinstance(next_op, And)
5.219 + cwd = os.path.join(cwd, node.dir)
5.220 + if verbose:
5.221 + piped_commands_display.append("cd %s &&" % node.dir)
5.222 + continue
5.223 +
5.224 + assert isinstance(node, (Command, Chdir))
5.225 + cmd = node
5.226 + if verbose:
5.227 + if cmd.env_vars:
5.228 + env_vars_str = ' '.join(['%s=%s' % (key, val) for key, val in cmd.env_vars.iteritems()])
5.229 + piped_commands_display.append("%s %s" % (env_vars_str, ' '.join(cmd.argv)))
5.230 + else:
5.231 + piped_commands_display.append(' '.join(cmd.argv))
5.232 +
5.233 + if state == PIPE:
5.234 + stdin = piped_commands[-1].stdout
5.235 + elif cmd.stdin is not None:
5.236 + stdin = open(cmd.stdin, "r")
5.237 + if verbose:
5.238 + piped_commands_display.append('< %s' % cmd.stdin)
5.239 + files_to_close.append(stdin)
5.240 + else:
5.241 + stdin = None
5.242 +
5.243 + if cmd.stdout is None:
5.244 + stdout = None
5.245 + elif cmd.stdout is Command.PIPE:
5.246 + stdout = subprocess.PIPE
5.247 + else:
5.248 + stdout = _open_out_file(cmd.stdout)
5.249 + files_to_close.append(stdout)
5.250 + if verbose:
5.251 + piped_commands_display.append('> %s' % cmd.stdout)
5.252 +
5.253 + if cmd.stderr is None:
5.254 + stderr = None
5.255 + elif cmd.stderr is Command.PIPE:
5.256 + stderr = subprocess.PIPE
5.257 + elif cmd.stderr is Command.STDOUT:
5.258 + stderr = subprocess.STDOUT
5.259 + if verbose:
5.260 + piped_commands_display.append('2>&1')
5.261 + else:
5.262 + stderr = _open_out_file(cmd.stderr)
5.263 + files_to_close.append(stderr)
5.264 + if verbose:
5.265 + piped_commands_display.append('2> %s' % cmd.stderr)
5.266 +
5.267 + if cmd.env_vars:
5.268 + env = dict(os.environ)
5.269 + env.update(cmd.env_vars)
5.270 + else:
5.271 + env = None
5.272 +
5.273 + if cwd == '.':
5.274 + proc_cwd = None
5.275 + else:
5.276 + proc_cwd = cwd
5.277 +
5.278 + debug("command: subprocess.Popen(argv=%r, stdin=%r, stdout=%r, stderr=%r, env_vars=%r, cwd=%r)"
5.279 + % (cmd.argv, stdin, stdout, stderr, cmd.env_vars, proc_cwd))
5.280 + proc = subprocess.Popen(cmd.argv, stdin=stdin, stdout=stdout, stderr=stderr, env=env, cwd=proc_cwd)
5.281 + del stdin, stdout, stderr
5.282 + piped_commands.append(proc)
5.283 +
5.284 + try:
5.285 + next_node = pipeline.pop(0)
5.286 + except IndexError:
5.287 + try:
5.288 + retval = self._exec_piped_commands(piped_commands)
5.289 + if verbose:
5.290 + print "%s: exit code %i" % (' '.join(piped_commands_display), retval)
5.291 + finally:
5.292 + for f in files_to_close:
5.293 + if f is not dev_null:
5.294 + f.close()
5.295 + files_to_close = []
5.296 + return retval
5.297 + else:
5.298 +
5.299 + if isinstance(next_node, Pipe):
5.300 + state = PIPE
5.301 + piped_commands_display.append('|')
5.302 +
5.303 + elif isinstance(next_node, Or):
5.304 + try:
5.305 + this_retval = self._exec_piped_commands(piped_commands)
5.306 + finally:
5.307 + for f in files_to_close:
5.308 + if f is not dev_null:
5.309 + f.close()
5.310 + files_to_close = []
5.311 + if this_retval == 0:
5.312 + if verbose:
5.313 + print "%s: exit code %i (|| is short-circuited)" % (' '.join(piped_commands_display), retval)
5.314 + return this_retval
5.315 + if verbose:
5.316 + print "%s: exit code %i (|| proceeds)" % (' '.join(piped_commands_display), retval)
5.317 + state = BEGIN
5.318 + piped_commands = []
5.319 + piped_commands_display = []
5.320 +
5.321 + elif isinstance(next_node, And):
5.322 + try:
5.323 + this_retval = self._exec_piped_commands(piped_commands)
5.324 + finally:
5.325 + for f in files_to_close:
5.326 + if f is not dev_null:
5.327 + f.close()
5.328 + files_to_close = []
5.329 + if this_retval != 0:
5.330 + if verbose:
5.331 + print "%s: exit code %i (&& is short-circuited)" % (' '.join(piped_commands_display), retval)
5.332 + return this_retval
5.333 + if verbose:
5.334 + print "%s: exit code %i (&& proceeds)" % (' '.join(piped_commands_display), retval)
5.335 + state = BEGIN
5.336 + piped_commands = []
5.337 + piped_commands_display = []
5.338 +
5.339 +
5.340 +
5.341 +def _main():
5.342 + pipeline = Pipeline()
5.343 + pipeline.parse('./foo.py 2>&1 < xxx | cat && ls')
5.344 + print pipeline.run()
5.345 +
5.346 +if __name__ == '__main__':
5.347 + _main()
5.348 +
6.1 --- a/wscript Fri Oct 23 15:34:14 2009 +0400
6.2 +++ b/wscript Fri Oct 23 13:05:56 2009 +0100
6.3 @@ -27,6 +27,8 @@
6.4 import Configure
6.5 import Scripting
6.6
6.7 +sys.path.insert(0, os.path.abspath('waf-tools'))
6.8 +
6.9 import cflags # override the build profiles from waf
6.10 cflags.profiles = {
6.11 # profile name: [optimization_level, warnings_level, debug_level]