wutils.py
author Tom Henderson <tomh@tomh.org>
Thu, 02 Jul 2009 21:57:00 -0700
changeset 4646 c25ca2e38845
parent 4583 384117906219
permissions -rw-r--r--
some fixes to the manual for IPv4 refactoring
     1 import os
     2 import os.path
     3 import sys
     4 import pproc as subprocess
     5 import shlex
     6 
     7 # WAF modules
     8 import ccroot
     9 import Options
    10 import Utils
    11 import Logs
    12 import TaskGen
    13 import Build
    14 import re
    15 
    16 
    17 # these are set from the main wscript file
    18 APPNAME=None
    19 VERSION=None
    20 bld=None
    21 
    22 #
    23 # The last part of the path name to use to find the regression traces tarball.
    24 # path will be APPNAME + '-' + VERSION + REGRESSION_SUFFIX + TRACEBALL_SUFFIX,
    25 # e.g., ns-3-dev-ref-traces.tar.bz2
    26 #
    27 TRACEBALL_SUFFIX = ".tar.bz2"
    28 
    29 
    30 
    31 def get_command_template(env, arguments=()):
    32     cmd = Options.options.command_template or '%s'
    33     for arg in arguments:
    34         cmd = cmd + " " + arg
    35     return cmd
    36 
    37 
    38 if hasattr(os.path, "relpath"):
    39     relpath = os.path.relpath # since Python 2.6
    40 else:
    41     def relpath(path, start=os.path.curdir):
    42         """Return a relative version of a path"""
    43 
    44         if not path:
    45             raise ValueError("no path specified")
    46 
    47         start_list = os.path.abspath(start).split(os.path.sep)
    48         path_list = os.path.abspath(path).split(os.path.sep)
    49 
    50         # Work out how much of the filepath is shared by start and path.
    51         i = len(os.path.commonprefix([start_list, path_list]))
    52 
    53         rel_list = [os.path.pardir] * (len(start_list)-i) + path_list[i:]
    54         if not rel_list:
    55             return os.path.curdir
    56         return os.path.join(*rel_list)
    57 
    58 
    59 def find_program(program_name, env):
    60     launch_dir = os.path.abspath(Options.cwd_launch)
    61     top_dir = os.path.abspath(Options.launch_dir)
    62     found_programs = []
    63     for obj in bld.all_task_gen:
    64         if not getattr(obj, 'is_ns3_program', False):
    65             continue
    66 
    67         ## filter out programs not in the subtree starting at the launch dir
    68         if not (obj.path.abspath().startswith(launch_dir)
    69                 or obj.path.abspath(env).startswith(launch_dir)):
    70             continue
    71         
    72         name1 = obj.target
    73         name2 = os.path.join(relpath(obj.path.abspath(), top_dir), obj.target)
    74         names = [name1, name2]
    75         found_programs.extend(names)
    76         if program_name in names:
    77             return obj
    78     raise ValueError("program '%s' not found; available programs are: %r"
    79                      % (program_name, found_programs))
    80 
    81 def get_proc_env(os_env=None):
    82     env = bld.env
    83     if sys.platform == 'linux2':
    84         pathvar = 'LD_LIBRARY_PATH'
    85     elif sys.platform == 'darwin':
    86         pathvar = 'DYLD_LIBRARY_PATH'
    87     elif sys.platform == 'win32':
    88         pathvar = 'PATH'
    89     elif sys.platform == 'cygwin':
    90         pathvar = 'PATH'
    91     elif sys.platform.startswith('freebsd'):
    92         pathvar = 'LD_LIBRARY_PATH'
    93     else:
    94         Logs.warn(("Don't know how to configure "
    95                         "dynamic library path for the platform %r;"
    96                         " assuming it's LD_LIBRARY_PATH.") % (sys.platform,))
    97         pathvar = 'LD_LIBRARY_PATH'        
    98 
    99     proc_env = dict(os.environ)
   100     if os_env is not None:
   101         proc_env.update(os_env)
   102 
   103     if pathvar is not None:
   104         if pathvar in proc_env:
   105             proc_env[pathvar] = os.pathsep.join(list(env['NS3_MODULE_PATH']) + [proc_env[pathvar]])
   106         else:
   107             proc_env[pathvar] = os.pathsep.join(list(env['NS3_MODULE_PATH']))
   108 
   109     pymoddir = bld.path.find_dir('bindings/python').abspath(env)
   110     if 'PYTHONPATH' in proc_env:
   111         proc_env['PYTHONPATH'] = os.pathsep.join([pymoddir] + [proc_env['PYTHONPATH']])
   112     else:
   113         proc_env['PYTHONPATH'] = pymoddir
   114 
   115     return proc_env
   116 
   117 def run_argv(argv, env, os_env=None, cwd=None, force_no_valgrind=False):
   118     proc_env = get_proc_env(os_env)
   119     if Options.options.valgrind and not force_no_valgrind:
   120         if Options.options.command_template:
   121             raise Utils.WafError("Options --command-template and --valgrind are conflicting")
   122         if not env['VALGRIND']:
   123             raise Utils.WafError("valgrind is not installed")
   124         argv = [env['VALGRIND'], "--leak-check=full", "--error-exitcode=1"] + argv
   125         proc = subprocess.Popen(argv, env=proc_env, cwd=cwd, stderr=subprocess.PIPE)
   126         reg = re.compile ('definitely lost: ([^ ]+) bytes')
   127         error = False
   128         for line in proc.stderr:
   129             sys.stderr.write(line)
   130             result = reg.search(line)
   131             if result is None:
   132                 continue
   133             if result.group(1) != "0":
   134                 error = True
   135         retval = proc.wait()
   136         if retval == 0 and error:
   137             retval = 1
   138     else:
   139         try:
   140             WindowsError
   141         except NameError:
   142             retval = subprocess.Popen(argv, env=proc_env, cwd=cwd).wait()
   143         else:
   144             try:
   145                 retval = subprocess.Popen(argv, env=proc_env, cwd=cwd).wait()
   146             except WindowsError, ex:
   147                 raise Utils.WafError("Command %s raised exception %s" % (argv, ex))
   148     if retval:
   149         raise Utils.WafError("Command %s exited with code %i" % (argv, retval))
   150     return retval
   151 
   152 def get_run_program(program_string, command_template=None):
   153     """
   154     Return the program name and argv of the process that would be executed by
   155     run_program(program_string, command_template).
   156     """
   157     #print "get_run_program_argv(program_string=%r, command_template=%r)" % (program_string, command_template)
   158     env = bld.env
   159 
   160     if command_template in (None, '%s'):
   161         argv = shlex.split(program_string)
   162         #print "%r ==shlex.split==> %r" % (program_string, argv)
   163         program_name = argv[0]
   164 
   165         try:
   166             program_obj = find_program(program_name, env)
   167         except ValueError, ex:
   168             raise Utils.WafError(str(ex))
   169 
   170         program_node = program_obj.path.find_or_declare(ccroot.get_target_name(program_obj))
   171         #try:
   172         #    program_node = program_obj.path.find_build(ccroot.get_target_name(program_obj))
   173         #except AttributeError:
   174         #    raise Utils.WafError("%s does not appear to be a program" % (program_name,))
   175 
   176         execvec = [program_node.abspath(env)] + argv[1:]
   177 
   178     else:
   179 
   180         program_name = program_string
   181         try:
   182             program_obj = find_program(program_name, env)
   183         except ValueError, ex:
   184             raise Utils.WafError(str(ex))
   185 
   186         program_node = program_obj.path.find_or_declare(ccroot.get_target_name(program_obj))
   187         #try:
   188         #    program_node = program_obj.path.find_build(ccroot.get_target_name(program_obj))
   189         #except AttributeError:
   190         #    raise Utils.WafError("%s does not appear to be a program" % (program_name,))
   191 
   192         tmpl = command_template % (program_node.abspath(env),)
   193         execvec = shlex.split(tmpl.replace('\\', '\\\\'))
   194         #print "%r ==shlex.split==> %r" % (command_template % (program_node.abspath(env),), execvec)
   195     return program_name, execvec
   196 
   197 def run_program(program_string, env, command_template=None, cwd=None):
   198     """
   199     if command_template is not None, then program_string == program
   200     name and argv is given by command_template with %s replaced by the
   201     full path to the program.  Else, program_string is interpreted as
   202     a shell command with first name being the program name.
   203     """
   204     dummy_program_name, execvec = get_run_program(program_string, command_template)
   205     if cwd is None:
   206         if (Options.options.cwd_launch):
   207             cwd = Options.options.cwd_launch
   208         else:
   209             cwd = Options.cwd_launch
   210     return run_argv(execvec, env, cwd=cwd)
   211 
   212 
   213 
   214 def run_python_program(program_string, env):
   215     env = bld.env
   216     execvec = shlex.split(program_string)
   217     if (Options.options.cwd_launch):
   218         cwd = Options.options.cwd_launch
   219     else:
   220         cwd = Options.cwd_launch
   221     return run_argv([env['PYTHON']] + execvec, env, cwd=cwd)
   222 
   223