2008-11-18 13:48:26 +00:00
|
|
|
import os
|
|
|
|
|
import os.path
|
2013-04-01 22:33:46 +02:00
|
|
|
import re
|
2008-11-18 13:48:26 +00:00
|
|
|
import sys
|
2011-09-08 16:13:40 +01:00
|
|
|
import subprocess
|
2008-11-18 13:48:26 +00:00
|
|
|
import shlex
|
2008-12-29 13:28:54 +00:00
|
|
|
|
|
|
|
|
# WAF modules
|
2013-04-01 22:33:46 +02:00
|
|
|
from waflib import Options, Utils, Logs, TaskGen, Build, Context
|
2011-09-08 16:13:40 +01:00
|
|
|
from waflib.Errors import WafError
|
2008-11-18 13:48:26 +00:00
|
|
|
|
|
|
|
|
# these are set from the main wscript file
|
|
|
|
|
APPNAME=None
|
|
|
|
|
VERSION=None
|
2009-04-13 23:10:37 +01:00
|
|
|
bld=None
|
2008-12-29 13:28:54 +00:00
|
|
|
|
2008-11-18 13:48:26 +00:00
|
|
|
|
|
|
|
|
|
2009-01-24 18:09:29 +00:00
|
|
|
def get_command_template(env, arguments=()):
|
2009-04-16 16:47:02 +01:00
|
|
|
cmd = Options.options.command_template or '%s'
|
2008-11-18 13:48:26 +00:00
|
|
|
for arg in arguments:
|
|
|
|
|
cmd = cmd + " " + arg
|
|
|
|
|
return cmd
|
|
|
|
|
|
|
|
|
|
|
2009-01-18 19:59:46 +00:00
|
|
|
if hasattr(os.path, "relpath"):
|
|
|
|
|
relpath = os.path.relpath # since Python 2.6
|
|
|
|
|
else:
|
|
|
|
|
def relpath(path, start=os.path.curdir):
|
|
|
|
|
"""Return a relative version of a path"""
|
|
|
|
|
|
|
|
|
|
if not path:
|
|
|
|
|
raise ValueError("no path specified")
|
|
|
|
|
|
|
|
|
|
start_list = os.path.abspath(start).split(os.path.sep)
|
|
|
|
|
path_list = os.path.abspath(path).split(os.path.sep)
|
|
|
|
|
|
|
|
|
|
# Work out how much of the filepath is shared by start and path.
|
|
|
|
|
i = len(os.path.commonprefix([start_list, path_list]))
|
|
|
|
|
|
|
|
|
|
rel_list = [os.path.pardir] * (len(start_list)-i) + path_list[i:]
|
|
|
|
|
if not rel_list:
|
|
|
|
|
return os.path.curdir
|
|
|
|
|
return os.path.join(*rel_list)
|
|
|
|
|
|
2013-04-01 22:33:46 +02:00
|
|
|
|
2008-11-18 13:48:26 +00:00
|
|
|
def find_program(program_name, env):
|
2011-09-08 16:13:40 +01:00
|
|
|
launch_dir = os.path.abspath(Context.launch_dir)
|
|
|
|
|
#top_dir = os.path.abspath(Options.cwd_launch)
|
2008-11-18 13:48:26 +00:00
|
|
|
found_programs = []
|
2009-04-13 23:10:37 +01:00
|
|
|
for obj in bld.all_task_gen:
|
2008-11-18 13:48:26 +00:00
|
|
|
if not getattr(obj, 'is_ns3_program', False):
|
|
|
|
|
continue
|
|
|
|
|
|
|
|
|
|
## filter out programs not in the subtree starting at the launch dir
|
|
|
|
|
if not (obj.path.abspath().startswith(launch_dir)
|
2012-04-17 11:26:31 +01:00
|
|
|
or obj.path.get_bld().abspath().startswith(launch_dir)):
|
2008-11-18 13:48:26 +00:00
|
|
|
continue
|
|
|
|
|
|
2012-01-14 00:40:15 +00:00
|
|
|
name1 = obj.name
|
|
|
|
|
name2 = os.path.join(relpath(obj.path.abspath(), launch_dir), obj.name)
|
2009-01-18 19:59:46 +00:00
|
|
|
names = [name1, name2]
|
|
|
|
|
found_programs.extend(names)
|
|
|
|
|
if program_name in names:
|
2008-11-18 13:48:26 +00:00
|
|
|
return obj
|
|
|
|
|
raise ValueError("program '%s' not found; available programs are: %r"
|
|
|
|
|
% (program_name, found_programs))
|
|
|
|
|
|
|
|
|
|
def get_proc_env(os_env=None):
|
2009-04-13 23:10:37 +01:00
|
|
|
env = bld.env
|
2015-09-03 21:14:55 -07:00
|
|
|
if sys.platform == 'linux2' or sys.platform == 'linux':
|
2008-11-18 13:48:26 +00:00
|
|
|
pathvar = 'LD_LIBRARY_PATH'
|
|
|
|
|
elif sys.platform == 'darwin':
|
|
|
|
|
pathvar = 'DYLD_LIBRARY_PATH'
|
|
|
|
|
elif sys.platform == 'win32':
|
|
|
|
|
pathvar = 'PATH'
|
|
|
|
|
elif sys.platform == 'cygwin':
|
|
|
|
|
pathvar = 'PATH'
|
|
|
|
|
elif sys.platform.startswith('freebsd'):
|
|
|
|
|
pathvar = 'LD_LIBRARY_PATH'
|
|
|
|
|
else:
|
2008-12-29 13:28:54 +00:00
|
|
|
Logs.warn(("Don't know how to configure "
|
2008-11-18 13:48:26 +00:00
|
|
|
"dynamic library path for the platform %r;"
|
|
|
|
|
" assuming it's LD_LIBRARY_PATH.") % (sys.platform,))
|
|
|
|
|
pathvar = 'LD_LIBRARY_PATH'
|
|
|
|
|
|
|
|
|
|
proc_env = dict(os.environ)
|
|
|
|
|
if os_env is not None:
|
|
|
|
|
proc_env.update(os_env)
|
|
|
|
|
|
|
|
|
|
if pathvar is not None:
|
|
|
|
|
if pathvar in proc_env:
|
2015-09-07 22:52:47 -07:00
|
|
|
proc_env[pathvar] = os.pathsep.join(list(env['NS3_MODULE_PATH']) + [proc_env[pathvar]])
|
2008-11-18 13:48:26 +00:00
|
|
|
else:
|
2015-09-07 22:52:47 -07:00
|
|
|
proc_env[pathvar] = os.pathsep.join(list(env['NS3_MODULE_PATH']))
|
2008-11-18 13:48:26 +00:00
|
|
|
|
2011-09-08 16:13:40 +01:00
|
|
|
pymoddir = bld.path.find_dir('bindings/python').get_bld().abspath()
|
2011-03-27 13:49:16 +01:00
|
|
|
pyvizdir = bld.path.find_dir('src/visualizer').abspath()
|
2008-11-18 13:48:26 +00:00
|
|
|
if 'PYTHONPATH' in proc_env:
|
2010-12-06 17:26:06 +00:00
|
|
|
proc_env['PYTHONPATH'] = os.pathsep.join([pymoddir, pyvizdir] + [proc_env['PYTHONPATH']])
|
2008-11-18 13:48:26 +00:00
|
|
|
else:
|
2010-12-06 17:26:06 +00:00
|
|
|
proc_env['PYTHONPATH'] = os.pathsep.join([pymoddir, pyvizdir])
|
2008-11-18 13:48:26 +00:00
|
|
|
|
2010-02-05 10:15:18 -08:00
|
|
|
if 'PATH' in proc_env:
|
|
|
|
|
proc_env['PATH'] = os.pathsep.join(list(env['NS3_EXECUTABLE_PATH']) + [proc_env['PATH']])
|
|
|
|
|
else:
|
|
|
|
|
proc_env['PATH'] = os.pathsep.join(list(env['NS3_EXECUTABLE_PATH']))
|
|
|
|
|
|
2008-11-18 13:48:26 +00:00
|
|
|
return proc_env
|
|
|
|
|
|
2009-04-21 11:13:19 +01:00
|
|
|
def run_argv(argv, env, os_env=None, cwd=None, force_no_valgrind=False):
|
2008-11-18 13:48:26 +00:00
|
|
|
proc_env = get_proc_env(os_env)
|
2019-03-20 16:58:01 +03:00
|
|
|
|
|
|
|
|
if Options.options.valgrind and Options.options.command_template:
|
|
|
|
|
raise WafError("Options --command-template and --valgrind are conflicting")
|
2019-03-20 18:42:38 +03:00
|
|
|
if Options.options.gdb and Options.options.command_template:
|
|
|
|
|
raise WafError("Options --command-template and --gdb are conflicting")
|
|
|
|
|
if Options.options.gdb and Options.options.valgrind:
|
|
|
|
|
raise WafError("Options --valgrind and --gdb are conflicting")
|
|
|
|
|
|
|
|
|
|
if Options.options.gdb:
|
|
|
|
|
argv = ["gdb", "--args"] + argv
|
|
|
|
|
proc = subprocess.Popen(argv, env=proc_env, cwd=cwd)
|
|
|
|
|
retval = proc.wait()
|
|
|
|
|
return retval
|
|
|
|
|
elif Options.options.valgrind and not force_no_valgrind:
|
2009-04-16 16:47:02 +01:00
|
|
|
if not env['VALGRIND']:
|
2011-09-08 16:13:40 +01:00
|
|
|
raise WafError("valgrind is not installed")
|
2015-11-15 09:15:28 -08:00
|
|
|
# Use the first program found in the env['VALGRIND'] list
|
|
|
|
|
argv = [env['VALGRIND'][0], "--leak-check=full", "--show-reachable=yes", "--error-exitcode=1"] + argv
|
2009-04-16 16:47:02 +01:00
|
|
|
proc = subprocess.Popen(argv, env=proc_env, cwd=cwd, stderr=subprocess.PIPE)
|
2015-11-15 09:15:28 -08:00
|
|
|
stderrdata = proc.communicate()[1]
|
|
|
|
|
stderrdata = stderrdata.decode('utf-8')
|
2009-04-16 16:47:02 +01:00
|
|
|
error = False
|
2015-11-15 09:15:28 -08:00
|
|
|
for line in stderrdata:
|
2009-04-16 16:47:02 +01:00
|
|
|
sys.stderr.write(line)
|
2010-01-19 16:56:44 +01:00
|
|
|
if "== LEAK SUMMARY" in line:
|
2009-04-16 16:47:02 +01:00
|
|
|
error = True
|
|
|
|
|
retval = proc.wait()
|
|
|
|
|
if retval == 0 and error:
|
|
|
|
|
retval = 1
|
|
|
|
|
else:
|
2009-06-24 16:12:09 +01:00
|
|
|
try:
|
|
|
|
|
WindowsError
|
|
|
|
|
except NameError:
|
|
|
|
|
retval = subprocess.Popen(argv, env=proc_env, cwd=cwd).wait()
|
|
|
|
|
else:
|
|
|
|
|
try:
|
|
|
|
|
retval = subprocess.Popen(argv, env=proc_env, cwd=cwd).wait()
|
2015-09-03 21:14:55 -07:00
|
|
|
except WindowsError as ex:
|
2011-09-08 16:13:40 +01:00
|
|
|
raise WafError("Command %s raised exception %s" % (argv, ex))
|
2008-11-18 13:48:26 +00:00
|
|
|
if retval:
|
2010-04-23 15:55:15 +01:00
|
|
|
signame = None
|
|
|
|
|
if retval < 0: # signal?
|
|
|
|
|
import signal
|
2015-09-03 21:14:55 -07:00
|
|
|
for name, val in vars(signal).items():
|
2010-04-23 15:55:15 +01:00
|
|
|
if len(name) > 3 and name[:3] == 'SIG' and name[3] != '_':
|
|
|
|
|
if val == -retval:
|
|
|
|
|
signame = name
|
|
|
|
|
break
|
|
|
|
|
if signame:
|
2011-09-08 16:13:40 +01:00
|
|
|
raise WafError("Command %s terminated with signal %s."
|
2010-04-23 15:55:15 +01:00
|
|
|
" Run it under a debugger to get more information "
|
2019-03-20 18:42:38 +03:00
|
|
|
"(./waf --run <program> --gdb\")." % (argv, signame))
|
2010-04-23 15:55:15 +01:00
|
|
|
else:
|
2011-09-08 16:13:40 +01:00
|
|
|
raise WafError("Command %s exited with code %i" % (argv, retval))
|
2008-11-18 13:48:26 +00:00
|
|
|
return retval
|
|
|
|
|
|
2008-11-26 14:55:35 +00:00
|
|
|
def get_run_program(program_string, command_template=None):
|
2008-11-18 13:48:26 +00:00
|
|
|
"""
|
2008-11-26 14:55:35 +00:00
|
|
|
Return the program name and argv of the process that would be executed by
|
|
|
|
|
run_program(program_string, command_template).
|
2008-11-18 13:48:26 +00:00
|
|
|
"""
|
2008-11-26 14:55:35 +00:00
|
|
|
#print "get_run_program_argv(program_string=%r, command_template=%r)" % (program_string, command_template)
|
2009-04-13 23:10:37 +01:00
|
|
|
env = bld.env
|
2008-11-18 13:48:26 +00:00
|
|
|
|
|
|
|
|
if command_template in (None, '%s'):
|
|
|
|
|
argv = shlex.split(program_string)
|
2009-06-24 18:42:07 +01:00
|
|
|
#print "%r ==shlex.split==> %r" % (program_string, argv)
|
2008-11-18 13:48:26 +00:00
|
|
|
program_name = argv[0]
|
2020-08-31 19:09:35 +02:00
|
|
|
|
|
|
|
|
# if the script name ends with .cc - strip it
|
|
|
|
|
if program_name.endswith('.cc'):
|
|
|
|
|
program_name = program_name.rsplit('.', 1)[0]
|
2008-11-18 13:48:26 +00:00
|
|
|
|
|
|
|
|
try:
|
|
|
|
|
program_obj = find_program(program_name, env)
|
2015-09-03 21:14:55 -07:00
|
|
|
except ValueError as ex:
|
2011-09-08 16:13:40 +01:00
|
|
|
raise WafError(str(ex))
|
2008-11-18 13:48:26 +00:00
|
|
|
|
2011-09-08 16:13:40 +01:00
|
|
|
program_node = program_obj.path.find_or_declare(program_obj.target)
|
2008-12-29 13:28:54 +00:00
|
|
|
#try:
|
|
|
|
|
# program_node = program_obj.path.find_build(ccroot.get_target_name(program_obj))
|
|
|
|
|
#except AttributeError:
|
|
|
|
|
# raise Utils.WafError("%s does not appear to be a program" % (program_name,))
|
2008-11-18 13:48:26 +00:00
|
|
|
|
2011-09-08 16:13:40 +01:00
|
|
|
execvec = [program_node.abspath()] + argv[1:]
|
2008-11-18 13:48:26 +00:00
|
|
|
|
|
|
|
|
else:
|
|
|
|
|
|
|
|
|
|
program_name = program_string
|
2020-08-31 19:09:35 +02:00
|
|
|
|
|
|
|
|
# if the script name ends with .cc - strip it
|
|
|
|
|
if program_name.endswith('.cc'):
|
|
|
|
|
program_name = program_name.rsplit('.', 1)[0]
|
|
|
|
|
|
2008-11-18 13:48:26 +00:00
|
|
|
try:
|
|
|
|
|
program_obj = find_program(program_name, env)
|
2015-09-03 21:14:55 -07:00
|
|
|
except ValueError as ex:
|
2011-09-08 16:13:40 +01:00
|
|
|
raise WafError(str(ex))
|
2008-12-29 13:28:54 +00:00
|
|
|
|
2011-09-08 16:13:40 +01:00
|
|
|
program_node = program_obj.path.find_or_declare(program_obj.target)
|
2008-12-29 13:28:54 +00:00
|
|
|
#try:
|
|
|
|
|
# program_node = program_obj.path.find_build(ccroot.get_target_name(program_obj))
|
|
|
|
|
#except AttributeError:
|
|
|
|
|
# raise Utils.WafError("%s does not appear to be a program" % (program_name,))
|
2008-11-18 13:48:26 +00:00
|
|
|
|
2011-09-23 11:58:59 +01:00
|
|
|
tmpl = command_template % (program_node.abspath(),)
|
2009-06-24 18:42:07 +01:00
|
|
|
execvec = shlex.split(tmpl.replace('\\', '\\\\'))
|
|
|
|
|
#print "%r ==shlex.split==> %r" % (command_template % (program_node.abspath(env),), execvec)
|
2008-11-26 14:55:35 +00:00
|
|
|
return program_name, execvec
|
2008-11-18 13:48:26 +00:00
|
|
|
|
2010-12-06 17:26:06 +00:00
|
|
|
def run_program(program_string, env, command_template=None, cwd=None, visualize=False):
|
2008-11-26 14:55:35 +00:00
|
|
|
"""
|
|
|
|
|
if command_template is not None, then program_string == program
|
|
|
|
|
name and argv is given by command_template with %s replaced by the
|
|
|
|
|
full path to the program. Else, program_string is interpreted as
|
|
|
|
|
a shell command with first name being the program name.
|
|
|
|
|
"""
|
|
|
|
|
dummy_program_name, execvec = get_run_program(program_string, command_template)
|
2009-01-18 22:47:25 +00:00
|
|
|
if cwd is None:
|
|
|
|
|
if (Options.options.cwd_launch):
|
|
|
|
|
cwd = Options.options.cwd_launch
|
|
|
|
|
else:
|
|
|
|
|
cwd = Options.cwd_launch
|
2010-12-06 17:26:06 +00:00
|
|
|
if visualize:
|
|
|
|
|
execvec.append("--SimulatorImplementationType=ns3::VisualSimulatorImpl")
|
2009-04-16 16:47:02 +01:00
|
|
|
return run_argv(execvec, env, cwd=cwd)
|
2008-11-18 13:48:26 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2010-12-06 17:26:06 +00:00
|
|
|
def run_python_program(program_string, env, visualize=False):
|
2009-04-13 23:10:37 +01:00
|
|
|
env = bld.env
|
2008-11-18 13:48:26 +00:00
|
|
|
execvec = shlex.split(program_string)
|
2009-02-10 17:14:41 +00:00
|
|
|
if (Options.options.cwd_launch):
|
|
|
|
|
cwd = Options.options.cwd_launch
|
|
|
|
|
else:
|
|
|
|
|
cwd = Options.cwd_launch
|
2010-12-06 17:26:06 +00:00
|
|
|
if visualize:
|
|
|
|
|
execvec.append("--SimulatorImplementationType=ns3::VisualSimulatorImpl")
|
2011-09-20 11:23:59 +01:00
|
|
|
return run_argv([env['PYTHON'][0]] + execvec, env, cwd=cwd)
|
2008-11-18 13:48:26 +00:00
|
|
|
|
2011-09-24 13:00:29 +01:00
|
|
|
|
2014-03-13 06:37:04 -07:00
|
|
|
def uniquify_list(seq):
|
|
|
|
|
"""Remove duplicates while preserving order
|
|
|
|
|
From Dave Kirby http://www.peterbe.com/plog/uniqifiers-benchmark
|
|
|
|
|
"""
|
|
|
|
|
seen = set()
|
|
|
|
|
return [ x for x in seq if x not in seen and not seen.add(x)]
|
|
|
|
|
|