From 62446cb66567e967e1af2b6a0c152fdeb98508c8 Mon Sep 17 00:00:00 2001 From: Steven Knight Date: Fri, 23 Aug 2002 02:14:44 +0000 Subject: Implement spawn() using os.system() on Posix OSes. (Anthony Roach) --- src/CHANGES.txt | 4 +++ src/engine/SCons/Action.py | 62 +++++++++++++++++++++++++++++++++------------- test/DVIPDF.py | 3 ++- test/DVIPDFFLAGS.py | 3 ++- test/F77PATH.py | 6 ++--- 5 files changed, 55 insertions(+), 23 deletions(-) diff --git a/src/CHANGES.txt b/src/CHANGES.txt index fb8196e..80a0db6 100644 --- a/src/CHANGES.txt +++ b/src/CHANGES.txt @@ -32,6 +32,10 @@ RELEASE 0.09 - - Fix differently ordered targets causing unnecessary rebuilds on case insensitive systems. + - Use os.system() to execute external commands whenever the "env" + utility is available, which is much faster than fork()/exec(), + and fixes the -j option on several platforms. + RELEASE 0.08 - Mon, 15 Jul 2002 12:08:51 -0500 diff --git a/src/engine/SCons/Action.py b/src/engine/SCons/Action.py index e2fe07f..7aecf00 100644 --- a/src/engine/SCons/Action.py +++ b/src/engine/SCons/Action.py @@ -58,23 +58,51 @@ def quote(x): if os.name == 'posix': - def defaultSpawn(cmd, args, env): - pid = os.fork() - if not pid: - # Child process. - exitval = 127 - args = ['sh', '-c', string.join(map(quote, args))] - try: - os.execvpe('sh', args, env) - except OSError, e: - exitval = exitvalmap[e[0]] - sys.stderr.write("scons: %s: %s\n" % (cmd, e[1])) - os._exit(exitval) - else: - # Parent process. - pid, stat = os.waitpid(pid, 0) - ret = stat >> 8 - return ret + def escape(arg): + "escape shell special characters" + slash = '\\' + special = '"\'`&;><| \t#()*?$~!' + + arg = string.replace(arg, slash, slash+slash) + for c in special: + arg = string.replace(arg, c, slash+c) + + return arg + + # If the env command exists, then we can use os.system() + # to spawn commands, otherwise we fall back on os.fork()/os.exec(). + # os.system() is prefered because it seems to work better with + # threads (i.e. -j) and is more efficient than forking Python. + if SCons.Util.WhereIs('env'): + def defaultSpawn(cmd, args, env): + if env: + s = 'env -i ' + for key in env.keys(): + s = s + '%s=%s '%(key, escape(env[key])) + s = s + 'sh -c ' + s = s + escape(string.join(map(quote, args))) + else: + s = string.join(map(quote, args)) + + return os.system(s) >> 8 + else: + def defaultSpawn(cmd, args, env): + pid = os.fork() + if not pid: + # Child process. + exitval = 127 + args = ['sh', '-c', string.join(map(quote, args))] + try: + os.execvpe('sh', args, env) + except OSError, e: + exitval = exitvalmap[e[0]] + sys.stderr.write("scons: %s: %s\n" % (cmd, e[1])) + os._exit(exitval) + else: + # Parent process. + pid, stat = os.waitpid(pid, 0) + ret = stat >> 8 + return ret elif os.name == 'nt': diff --git a/test/DVIPDF.py b/test/DVIPDF.py index d22cfd8..25856dc 100644 --- a/test/DVIPDF.py +++ b/test/DVIPDF.py @@ -100,8 +100,9 @@ test.fail_test(test.read('test2.pdf') != "This is a .tex test.\n") dvipdf = test.where_is('dvipdf') +tex = test.where_is('tex') -if dvipdf: +if dvipdf and tex: test.write("wrapper.py", """import os import string diff --git a/test/DVIPDFFLAGS.py b/test/DVIPDFFLAGS.py index e6f9146..9962253 100644 --- a/test/DVIPDFFLAGS.py +++ b/test/DVIPDFFLAGS.py @@ -106,8 +106,9 @@ test.fail_test(test.read('test2.pdf') != " -x\nThis is a .tex test.\n") dvipdf = test.where_is('dvipdf') +tex = test.where_is('tex') -if dvipdf: +if dvipdf and tex: test.write("wrapper.py", """import os import string diff --git a/test/F77PATH.py b/test/F77PATH.py index ad38bf1..3dcc280 100644 --- a/test/F77PATH.py +++ b/test/F77PATH.py @@ -42,10 +42,8 @@ args = prog + ' ' + subdir_prog + ' ' + variant_prog test = TestSCons.TestSCons() if not test.where_is('g77'): - print "g77 is not installed on this system." - print "Cannot test F77PATH." - test.no_result(1) - + test.pass_test() + test.subdir('include', 'subdir', ['subdir', 'include'], 'inc2') test.write('SConstruct', """ -- cgit v0.12