| #!/usr/bin/env ${PY_STRING} |
| ## |
| # Licensed to the Apache Software Foundation (ASF) under one |
| # or more contributor license agreements. See the NOTICE file |
| # distributed with this work for additional information |
| # regarding copyright ownership. The ASF licenses this file |
| # to you under the Apache License, Version 2.0 (the |
| # "License"); you may not use this file except in compliance |
| # with the License. You may obtain a copy of the License at |
| # |
| # http://www.apache.org/licenses/LICENSE-2.0 |
| # |
| # Unless required by applicable law or agreed to in writing, |
| # software distributed under the License is distributed on an |
| # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| # KIND, either express or implied. See the License for the |
| # specific language governing permissions and limitations |
| # under the License |
| # |
| |
| from __future__ import unicode_literals |
| from __future__ import division |
| from __future__ import absolute_import |
| from __future__ import print_function |
| |
| """ |
| Run a tool or test in a build tree with the correct PATH, PYTHONPATH, etc. |
| Run with no arguments for help. |
| """ |
| |
| usage=""" |
| Run a tool or test in a build tree with the correct PATH, PYTHONPATH, etc. |
| |
| Usage: |
| run.py <program> [<arg>....] # Run a program, can be an interactive shell. Use PATH. |
| run.py -m <python-module> [<arg>....] # Run a python module. Use PYTHONPATH. |
| run.py -s <python-script>.py [<arg>....] # Run a python script. |
| run.py -x <program> [<arg>....] # Run an executable with the test runner |
| run.py --sh # Print a shell script to set the run.py environment. |
| """ |
| |
| import os, sys, runpy |
| from subprocess import Popen, PIPE |
| |
| extra_paths = [ |
| "${CMAKE_SOURCE_DIR}/python", |
| "${CMAKE_BINARY_DIR}/python", |
| "${CMAKE_SOURCE_DIR}/tests" |
| ] |
| |
| def dedup(l): |
| """Remove duplicates from list l, keep first instance. Keep order of l.""" |
| s = set() |
| return [i for i in l if i not in s and (s.add(i) or True)] |
| |
| def getpath(env): |
| """Return a path environment variable split into a list""" |
| path = os.environ.get(env) |
| if path: |
| return path.split(os.pathsep) |
| return [] |
| |
| sys.path = dedup(extra_paths + sys.path) |
| python_path = dedup(extra_paths + getpath("PYTHONPATH")) |
| |
| # runner program (e.g. valgrind) and args used to run qdrouterd |
| qdrouterd_runner = "${QDROUTERD_RUNNER}" |
| |
| env_vars = { |
| 'PYTHONPATH': os.pathsep.join(python_path), |
| 'PATH': os.pathsep.join(dedup(["${CMAKE_BINARY_DIR}", |
| os.path.join("${CMAKE_BINARY_DIR}", 'tests'), |
| os.path.join("${CMAKE_BINARY_DIR}", 'router'), |
| os.path.join("${CMAKE_SOURCE_DIR}", 'tools'), |
| os.path.join("${CMAKE_BINARY_DIR}", 'tools'), |
| os.path.join("${CMAKE_SOURCE_DIR}", 'bin')] + |
| getpath('PATH'))), |
| 'MANPATH' : os.pathsep.join([os.path.join("${CMAKE_BINARY_DIR}",'doc','man')] + |
| getpath('MANPATH')), |
| 'SOURCE_DIR': "${CMAKE_SOURCE_DIR}", |
| 'BUILD_DIR': "${CMAKE_BINARY_DIR}", |
| 'QPID_DISPATCH_HOME': "${CMAKE_SOURCE_DIR}", |
| 'QPID_DISPATCH_LIB': "${CMAKE_BINARY_DIR}/src/${QPID_DISPATCH_LIB}", |
| 'QPID_DISPATCH_RUNNER': qdrouterd_runner, |
| 'MALLOC_CHECK_': "3", # 3 = print error and abort |
| 'MALLOC_PERTURB_': "153", # 153 = 0x99 freed memory pattern |
| 'TSAN_OPTIONS': "${RUNTIME_TSAN_ENV_OPTIONS}", |
| 'ASAN_OPTIONS': "${RUNTIME_ASAN_ENV_OPTIONS}", |
| 'LSAN_OPTIONS': "${RUNTIME_LSAN_ENV_OPTIONS}", |
| } |
| os.environ.update(env_vars) |
| |
| |
| def find_exe(program): |
| """Find an executable in the system PATH""" |
| def is_exe(fpath): |
| return os.path.isfile(fpath) and os.access(fpath, os.X_OK) |
| mydir, name = os.path.split(program) |
| if mydir: |
| if is_exe(program): return program |
| else: |
| for path in os.environ["PATH"].split(os.pathsep): |
| exe_file = os.path.join(path, program) |
| if is_exe(exe_file): return exe_file |
| return None |
| |
| def is_binary_exe(program): |
| """True if the program is a binary executable""" |
| if not program: return None |
| p = Popen(['file', '-bi', program], stdout=PIPE, stderr=PIPE) |
| return p.communicate()[0].startswith('application/x-executable') |
| |
| def run_path(file_path, run_name=None): |
| """Wrapper for run path that falls back to exec python for python < 2.7""" |
| if hasattr(runpy, 'run_path'): |
| runpy.run_path(file_path, run_name=run_name) |
| else: # Python < 2.7 |
| os.execvp(sys.executable, [sys.executable]+sys.argv) |
| |
| if __name__ == "__main__": |
| error_prefix = "" |
| try: |
| if len(sys.argv) == 1: |
| print("%s" % usage) |
| elif sys.argv[1] == '-m': |
| sys.argv = sys.argv[2:] |
| error_prefix = "Run python module '%s': "%(sys.argv[0]) |
| runpy.run_module(sys.argv[0], alter_sys=True, run_name="__main__") |
| elif sys.argv[1] == '-s': |
| sys.argv = sys.argv[2:] |
| error_prefix = "Run python script '%s':"%(sys.argv[0]) |
| run_path(sys.argv[0], run_name="__main__") |
| elif sys.argv[1] == '--sh': |
| for name, value in env_vars.items(): print('%s="%s"'%(name, value)) |
| print("export %s"%' '.join(env_vars.keys())) |
| elif sys.argv[1] == '-x': |
| args = qdrouterd_runner.split() + sys.argv[2:] |
| error_prefix = "Running '%s': "%(args) |
| os.execvp(args[0], args) |
| elif sys.argv[1].startswith('-'): |
| print(usage) |
| else: |
| args = sys.argv[1:] |
| error_prefix = "Running '%s': "%(args) |
| os.execvp(args[0], args) |
| except Exception as e: |
| print("%s%s: %s"%(error_prefix, type(e).__name__, e)) |
| raise |
| |