wutils.py
author Josh Pelkey <jpelkey@gatech.edu>
Wed, 11 Aug 2010 11:37:37 -0400
changeset 6553 fb5ad9c7755a
parent 5975 c85cb9b073a0
permissions -rw-r--r--
update release notes and fix doxygen warnings
     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     if 'PATH' in proc_env:
   116         proc_env['PATH'] = os.pathsep.join(list(env['NS3_EXECUTABLE_PATH']) + [proc_env['PATH']])
   117     else:
   118         proc_env['PATH'] = os.pathsep.join(list(env['NS3_EXECUTABLE_PATH']))
   119 
   120     return proc_env
   121 
   122 def run_argv(argv, env, os_env=None, cwd=None, force_no_valgrind=False):
   123     proc_env = get_proc_env(os_env)
   124     if Options.options.valgrind and not force_no_valgrind:
   125         if Options.options.command_template:
   126             raise Utils.WafError("Options --command-template and --valgrind are conflicting")
   127         if not env['VALGRIND']:
   128             raise Utils.WafError("valgrind is not installed")
   129         argv = [env['VALGRIND'], "--leak-check=full", "--show-reachable=yes", "--error-exitcode=1"] + argv
   130         proc = subprocess.Popen(argv, env=proc_env, cwd=cwd, stderr=subprocess.PIPE)
   131         error = False
   132         for line in proc.stderr:
   133             sys.stderr.write(line)
   134             if "== LEAK SUMMARY" in line:
   135                 error = True
   136         retval = proc.wait()
   137         if retval == 0 and error:
   138             retval = 1
   139     else:
   140         try:
   141             WindowsError
   142         except NameError:
   143             retval = subprocess.Popen(argv, env=proc_env, cwd=cwd).wait()
   144         else:
   145             try:
   146                 retval = subprocess.Popen(argv, env=proc_env, cwd=cwd).wait()
   147             except WindowsError, ex:
   148                 raise Utils.WafError("Command %s raised exception %s" % (argv, ex))
   149     if retval:
   150         signame = None
   151         if retval < 0: # signal?
   152             import signal
   153             for name, val in vars(signal).iteritems():
   154                 if len(name) > 3 and name[:3] == 'SIG' and name[3] != '_':
   155                     if val == -retval:
   156                         signame = name
   157                         break
   158         if signame:
   159             raise Utils.WafError("Command %s terminated with signal %s."
   160                                  " Run it under a debugger to get more information "
   161                                  "(./waf --run <program> --command-template=\"gdb --args %%s <args>\")." % (argv, signame))
   162         else:
   163             raise Utils.WafError("Command %s exited with code %i" % (argv, retval))
   164     return retval
   165 
   166 def get_run_program(program_string, command_template=None):
   167     """
   168     Return the program name and argv of the process that would be executed by
   169     run_program(program_string, command_template).
   170     """
   171     #print "get_run_program_argv(program_string=%r, command_template=%r)" % (program_string, command_template)
   172     env = bld.env
   173 
   174     if command_template in (None, '%s'):
   175         argv = shlex.split(program_string)
   176         #print "%r ==shlex.split==> %r" % (program_string, argv)
   177         program_name = argv[0]
   178 
   179         try:
   180             program_obj = find_program(program_name, env)
   181         except ValueError, ex:
   182             raise Utils.WafError(str(ex))
   183 
   184         program_node = program_obj.path.find_or_declare(ccroot.get_target_name(program_obj))
   185         #try:
   186         #    program_node = program_obj.path.find_build(ccroot.get_target_name(program_obj))
   187         #except AttributeError:
   188         #    raise Utils.WafError("%s does not appear to be a program" % (program_name,))
   189 
   190         execvec = [program_node.abspath(env)] + argv[1:]
   191 
   192     else:
   193 
   194         program_name = program_string
   195         try:
   196             program_obj = find_program(program_name, env)
   197         except ValueError, ex:
   198             raise Utils.WafError(str(ex))
   199 
   200         program_node = program_obj.path.find_or_declare(ccroot.get_target_name(program_obj))
   201         #try:
   202         #    program_node = program_obj.path.find_build(ccroot.get_target_name(program_obj))
   203         #except AttributeError:
   204         #    raise Utils.WafError("%s does not appear to be a program" % (program_name,))
   205 
   206         tmpl = command_template % (program_node.abspath(env),)
   207         execvec = shlex.split(tmpl.replace('\\', '\\\\'))
   208         #print "%r ==shlex.split==> %r" % (command_template % (program_node.abspath(env),), execvec)
   209     return program_name, execvec
   210 
   211 def run_program(program_string, env, command_template=None, cwd=None):
   212     """
   213     if command_template is not None, then program_string == program
   214     name and argv is given by command_template with %s replaced by the
   215     full path to the program.  Else, program_string is interpreted as
   216     a shell command with first name being the program name.
   217     """
   218     dummy_program_name, execvec = get_run_program(program_string, command_template)
   219     if cwd is None:
   220         if (Options.options.cwd_launch):
   221             cwd = Options.options.cwd_launch
   222         else:
   223             cwd = Options.cwd_launch
   224     return run_argv(execvec, env, cwd=cwd)
   225 
   226 
   227 
   228 def run_python_program(program_string, env):
   229     env = bld.env
   230     execvec = shlex.split(program_string)
   231     if (Options.options.cwd_launch):
   232         cwd = Options.options.cwd_launch
   233     else:
   234         cwd = Options.cwd_launch
   235     return run_argv([env['PYTHON']] + execvec, env, cwd=cwd)
   236 
   237