From afe09c1385b55bdf2d8d245ea7c8c73b3fa87e28 Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Fri, 4 Sep 2009 11:30:19 -0400 Subject: QAR-1619: Replace RunBuildTest.cmake with run_build_test.py for LSL tests. RunBuildTest.cmake can't handle pathnames containing spaces. run_build_test.py accepts an arbitrary number of individually-quoted command-line arguments, passing each through to Python's subprocess.call(). --- indra/cmake/run_build_test.py | 97 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 97 insertions(+) create mode 100644 indra/cmake/run_build_test.py (limited to 'indra/cmake/run_build_test.py') diff --git a/indra/cmake/run_build_test.py b/indra/cmake/run_build_test.py new file mode 100644 index 0000000000..1882b644a0 --- /dev/null +++ b/indra/cmake/run_build_test.py @@ -0,0 +1,97 @@ +#!/usr/bin/python +"""\ +@file run_build_test.py +@author Nat Goodspeed +@date 2009-09-03 +@brief Helper script to allow CMake to run some command after setting + environment variables. + +CMake has commands to run an external program. But remember that each CMake +command must be backed by multiple build-system implementations. Unfortunately +it seems CMake can't promise that every target build system can set specified +environment variables before running the external program of interest. + +This helper script is a workaround. It simply sets the requested environment +variables and then executes the program specified on the rest of its command +line. + +Example: + +python run_build_test.py -DFOO=bar myprog somearg otherarg + +sets environment variable FOO=bar, then runs: +myprog somearg otherarg + +$LicenseInfo:firstyear=2009&license=internal$ +Copyright (c) 2009, Linden Research, Inc. +$/LicenseInfo$ +""" + +import os +import sys +import subprocess + +def main(command, libpath=[], vars={}): + """Pass: + command is a sequence (e.g. a list) of strings. The first item in the list + must be the command name, the rest are its arguments. + + libpath is a sequence of directory pathnames. These will be appended to + the platform-specific dynamic library search path environment variable. + + vars is a dict of arbitrary (var, value) pairs to be added to the + environment before running 'command'. + + This function runs the specified command, waits for it to terminate and + returns its return code. This will be negative if the command terminated + with a signal, else it will be the process's specified exit code. + """ + # Handle platform-dependent libpath first. + if sys.platform == "win32": + lpvars = ["PATH"] + elif sys.platform == "darwin": + lpvars = ["LD_LIBRARY_PATH", "DYLD_LIBRARY_PATH"] + elif sys.platform.startswith("linux"): + lpvars = ["LD_LIBRARY_PATH"] + else: + # No idea what the right pathname might be! But only crump if this + # feature is requested. + if libpath: + raise NotImplemented("run_build_test: unknown platform %s" % sys.platform) + lpvars = [] + for var in lpvars: + # Split the existing path + dirs = os.environ[var].split(os.pathsep) + # Append the sequence in libpath + dirs.extend(libpath) + # Now rebuild the path string. This way we use a minimum of separators + # -- and we avoid adding a pointless separator when libpath is empty. + os.environ[var] = os.pathsep.join(dirs) + # Now handle arbitrary environment variables. The tricky part is ensuring + # that all the keys and values we try to pass are actually strings. + os.environ.update(dict([(str(key), str(value)) for key, value in vars.iteritems()])) + # Run the child process. + return subprocess.call(command) + +if __name__ == "__main__": + from optparse import OptionParser + parser = OptionParser(usage="usage: %prog [options] command args...") + parser.add_option("-D", "--define", dest="vars", default=[], action="append", + metavar="VAR=value", + help="Add VAR=value to the env variables defined") + parser.add_option("-l", "--libpath", dest="libpath", default=[], action="append", + metavar="DIR", + help="Add DIR to the platform-dependent DLL search path") + opts, args = parser.parse_args() + # What we have in opts.vars is a list of strings of the form "VAR=value" + # or possibly just "VAR". What we want is a dict. We can build that dict by + # constructing a list of ["VAR", "value"] pairs -- so split each + # "VAR=value" string on the '=' sign (but only once, in case we have + # "VAR=some=user=string"). To handle the case of just "VAR", append "" to + # the list returned by split(), then slice off anything after the pair we + # want. + rc = main(command=args, libpath=opts.libpath, + vars=dict([(pair.split('=', 1) + [""])[:2] for pair in opts.vars])) + print >>sys.stderr, "Failure running: %s" % " ".join(args) + print >>sys.stderr, "Error: %s" % rc + sys.exit((rc < 0) and 255 or rc) -- cgit v1.2.3 From b9546a33e90df60e2d47735b4627de4eb97ba6b9 Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Tue, 8 Sep 2009 12:03:32 -0400 Subject: QAR-1619: Finish replacing RunBuildTest.cmake with run_build_test.py. Because the details of RunBuildTest.cmake versus run_build_test.py had to be changed in so many different places, introduce LL_TEST_COMMAND CMake macro (in LLTestCommand.cmake) to encapsulate construction of the actual command line. Use LL_TEST_COMMAND in LL_ADD_PROJECT_UNIT_TESTS, LL_ADD_INTEGRATION_TEST, the big indra/test monolith and the various LslCompilerMacros. Fix run_build_test.py to pass through the test executable's own options (e.g. --touch, --output) without inspection. Defend it against the case when the platform-specific library path environment variable doesn't yet exist. Make it report errors only on nonzero test-program rc. Remove RunBuildTest.cmake. --- indra/cmake/run_build_test.py | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) (limited to 'indra/cmake/run_build_test.py') diff --git a/indra/cmake/run_build_test.py b/indra/cmake/run_build_test.py index 1882b644a0..17bce6f434 100644 --- a/indra/cmake/run_build_test.py +++ b/indra/cmake/run_build_test.py @@ -60,22 +60,35 @@ def main(command, libpath=[], vars={}): raise NotImplemented("run_build_test: unknown platform %s" % sys.platform) lpvars = [] for var in lpvars: - # Split the existing path - dirs = os.environ[var].split(os.pathsep) + # Split the existing path. Bear in mind that the variable in question + # might not exist; instead of KeyError, just use an empty string. + dirs = os.environ.get(var, "").split(os.pathsep) # Append the sequence in libpath +## print "%s += %r" % (var, libpath) dirs.extend(libpath) # Now rebuild the path string. This way we use a minimum of separators # -- and we avoid adding a pointless separator when libpath is empty. os.environ[var] = os.pathsep.join(dirs) # Now handle arbitrary environment variables. The tricky part is ensuring # that all the keys and values we try to pass are actually strings. +## if vars: +## print "Setting:" +## for key, value in vars.iteritems(): +## print "%s=%s" % (key, value) os.environ.update(dict([(str(key), str(value)) for key, value in vars.iteritems()])) # Run the child process. +## print "Running: %s" % " ".join(command) return subprocess.call(command) if __name__ == "__main__": from optparse import OptionParser parser = OptionParser(usage="usage: %prog [options] command args...") + # We want optparse support for the options we ourselves handle -- but we + # DO NOT want it looking at options for the executable we intend to run, + # rejecting them as invalid because we don't define them. So configure the + # parser to stop looking for options as soon as it sees the first + # positional argument (traditional Unix syntax). + parser.disable_interspersed_args() parser.add_option("-D", "--define", dest="vars", default=[], action="append", metavar="VAR=value", help="Add VAR=value to the env variables defined") @@ -92,6 +105,7 @@ if __name__ == "__main__": # want. rc = main(command=args, libpath=opts.libpath, vars=dict([(pair.split('=', 1) + [""])[:2] for pair in opts.vars])) - print >>sys.stderr, "Failure running: %s" % " ".join(args) - print >>sys.stderr, "Error: %s" % rc + if rc not in (None, 0): + print >>sys.stderr, "Failure running: %s" % " ".join(args) + print >>sys.stderr, "Error: %s" % rc sys.exit((rc < 0) and 255 or rc) -- cgit v1.2.3