summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSteven Knight <knight@baldmt.com>2002-02-21 09:57:19 (GMT)
committerSteven Knight <knight@baldmt.com>2002-02-21 09:57:19 (GMT)
commit8c5d400a01f307aa7ef91366e390eb73b7551ba0 (patch)
tree1f225540585caf22ae901417051425e4eb4fbe27
parentf4ee118fe5616605078a067e3ac0a45cad49adfd (diff)
downloadSCons-8c5d400a01f307aa7ef91366e390eb73b7551ba0.zip
SCons-8c5d400a01f307aa7ef91366e390eb73b7551ba0.tar.gz
SCons-8c5d400a01f307aa7ef91366e390eb73b7551ba0.tar.bz2
Implement the -u option (Task 39028). (Steve Leblanc)
-rw-r--r--doc/man/scons.143
-rw-r--r--src/CHANGES.txt8
-rw-r--r--src/RELEASE.txt4
-rw-r--r--src/engine/SCons/Scanner/C.py4
-rw-r--r--src/engine/SCons/Script/__init__.py84
-rw-r--r--test/option-u.py48
6 files changed, 141 insertions, 50 deletions
diff --git a/doc/man/scons.1 b/doc/man/scons.1
index 78bf54b..ef5b664 100644
--- a/doc/man/scons.1
+++ b/doc/man/scons.1
@@ -147,18 +147,18 @@ built:
scons src/subdir
.EE
-.\" or changing directory and invoking scons with the
-.\" .B -u
-.\" option, which traverses up the directory
-.\" hierarchy until it finds the
-.\" .I SConstruct
-.\" file, and then builds
-.\" targets relatively to the current subdirectory:
-.\"
-.\" .ES
-.\" cd src/subdir
-.\" scons -u .
-.\" .EE
+or by changing directory and invoking scons with the
+.B -u
+option, which traverses up the directory
+hierarchy until it finds the
+.I SConstruct
+file, and then builds
+targets relatively to the current subdirectory:
+
+.ES
+cd src/subdir
+scons -u .
+.EE
.B scons
supports building multiple targets in parallel via a
@@ -482,15 +482,16 @@ Ignored for compatibility with GNU
appear up-to-date is unnecessary when using
.BR scons .)
-.\" .TP
-.\" -u
-.\" Traverse up directories until an
-.\" .I SConstruct
-.\" or
-.\" .I sconstruct
-.\" file is found, and use that
-.\" as the top of the directory tree. Only targets at or below the
-.\" current directory will be built.
+.TP
+-u
+Walks up the directory structure until an
+.I SConstruct ,
+.I Sconstruct
+or
+.I sconstruct
+file is found, and uses that
+as the top of the directory tree. Only targets at or below the
+current directory will be built.
.TP
-v, --version
diff --git a/src/CHANGES.txt b/src/CHANGES.txt
index b364ac7..3b0f2b7 100644
--- a/src/CHANGES.txt
+++ b/src/CHANGES.txt
@@ -68,10 +68,18 @@ RELEASE 0.05 -
- Efficiency: don't scan dependencies more than once during the
walk of a tree.
+ From Steve Leblanc:
+
+ - Add support for the -u option.
+
+ - Add .cc and .hh file suffixes to the C Scanner.
+
From Anthony Roach:
- Make the scons script return an error code on failures.
+ - Add support for using code to generate a command to build a target.
+
RELEASE 0.04 - Wed, 30 Jan 2002 11:09:42 -0600
diff --git a/src/RELEASE.txt b/src/RELEASE.txt
index 467677b..358a359 100644
--- a/src/RELEASE.txt
+++ b/src/RELEASE.txt
@@ -98,8 +98,8 @@ RELEASE 0.04 - Wed, 30 Jan 2002 11:09:42 -0600
- No support yet for the following command-line options:
-d -e -l --list-actions --list-derived --list-where
- -o -p -q -r -R --random -u -w --write-filenames -W
- --warn-undefined-variables
+ -o -p -q -r -R --random -w --write-filenames -W
+ --warn-undefined-variables
Thank you for your interest, and please let us know how we can help
improve SCons for your needs.
diff --git a/src/engine/SCons/Scanner/C.py b/src/engine/SCons/Scanner/C.py
index 51235c3..6b5b6c6 100644
--- a/src/engine/SCons/Scanner/C.py
+++ b/src/engine/SCons/Scanner/C.py
@@ -43,8 +43,8 @@ include_cache = {}
def CScan(fs = SCons.Node.FS.default_fs):
"Return a prototype Scanner instance for scanning C/C++ source files"
cs = CScanner(scan, "CScan", [fs, ()],
- [".c", ".C", ".cxx", ".cpp", ".c++",
- ".h", ".H", ".hxx", ".hpp"])
+ [".c", ".C", ".cxx", ".cpp", ".c++", ".cc",
+ ".h", ".H", ".hxx", ".hpp", ".hh"])
cs.fs = fs
return cs
diff --git a/src/engine/SCons/Script/__init__.py b/src/engine/SCons/Script/__init__.py
index dfd969e..6e923bc 100644
--- a/src/engine/SCons/Script/__init__.py
+++ b/src/engine/SCons/Script/__init__.py
@@ -126,6 +126,8 @@ ignore_errors = 0
keep_going_on_error = 0
help_option = None
print_tree = 0
+climb_up = 0
+target_top = None
exit_status = 0 # exit status, assume success by default
# utility functions
@@ -353,7 +355,6 @@ def options_init():
def opt_C(opt, arg):
try:
os.chdir(arg)
- SCons.Node.FS.default_fs.set_toplevel_dir(os.getcwd())
except:
sys.stderr.write("Could not change directory to 'arg'\n")
@@ -514,7 +515,11 @@ def options_init():
short = 's', long = ['silent', 'quiet'],
help = "Don't print commands.")
- Option(func = opt_not_yet, future = 1,
+ def opt_u(opt, arg):
+ global climb_up
+ climb_up = 1
+
+ Option(func = opt_u,
short = 'u', long = ['up', 'search-up'],
help = "Search up directory tree for SConstruct.")
@@ -578,6 +583,18 @@ options_init()
+def _SConstruct_exists(dirname=''):
+ """This function checks that an SConstruct file exists in a directory.
+ If so, it returns the path of the file. By default, it checks the
+ current directory.
+ """
+ for file in ['SConstruct', 'Sconstruct', 'sconstruct']:
+ sfile = os.path.join(dirname, file)
+ if os.path.isfile(sfile):
+ return sfile
+ return None
+
+
def UsageString():
help_opts = filter(lambda x: x.helpline, option_list)
s = "Usage: scons [OPTION] [TARGET] ...\n" + "Options:\n" + \
@@ -587,7 +604,7 @@ def UsageString():
def _main():
- global scripts, num_jobs, task_class, calc
+ global scripts, num_jobs, task_class, calc, target_top
targets = []
@@ -625,11 +642,27 @@ def _main():
targets.append(a)
SCons.Script.SConscript._scons_add_args(xmit_args)
+ if climb_up:
+ target_top = '' # directory to prepend to targets
+ script_dir = os.getcwd() # location of script
+ while script_dir and not _SConstruct_exists(script_dir):
+ script_dir, last_part = os.path.split(script_dir)
+ if last_part:
+ target_top = os.path.join(last_part, target_top)
+ else:
+ script_dir = ''
+ if script_dir:
+ print "scons: Entering directory %s" % script_dir
+ os.chdir(script_dir)
+ else:
+ raise UserError, "No SConstruct file found."
+
+ SCons.Node.FS.default_fs.set_toplevel_dir(os.getcwd())
+
if not scripts:
- for file in ['SConstruct', 'Sconstruct', 'sconstruct']:
- if os.path.isfile(file):
- scripts.append(file)
- break
+ sfile = _SConstruct_exists()
+ if sfile:
+ scripts.append(sfile)
if help_option == 'H':
print UsageString()
@@ -671,19 +704,30 @@ def _main():
if not targets:
targets = SCons.Script.SConscript.default_targets
-
- def Entry(x):
- if isinstance(x, SCons.Node.Node):
- return x
- try:
- node = SCons.Node.FS.default_fs.Entry(x, create = 0)
- except UserError:
- str = "scons: *** Do not know how to make target `%s'." % x
- if not keep_going_on_error:
- sys.stderr.write(str + " Stop.\n")
- sys.exit(2)
- sys.stderr.write(str + "\n")
- node = None
+
+ if target_top:
+ target_top = SCons.Node.FS.default_fs.Dir(target_top)
+
+ def Entry(x, top = target_top):
+ if isinstance(x, SCons.Node.Node):
+ node = x
+ else:
+ try:
+ node = SCons.Node.FS.default_fs.Entry(x,
+ directory = top,
+ create = 0)
+ except UserError:
+ string = "scons: *** Do not know how to make target `%s'." % x
+ if not keep_going_on_error:
+ sys.stderr.write(string + " Stop.\n")
+ sys.exit(2)
+ sys.stderr.write(string + "\n")
+ node = None
+ if top and not node.is_under(top):
+ if isinstance(node, SCons.Node.FS.Dir) and top.is_under(node):
+ node = top
+ else:
+ node = None
return node
nodes = filter(lambda x: x is not None, map(Entry, targets))
diff --git a/test/option-u.py b/test/option-u.py
index 9f68ac5..dbeec6a 100644
--- a/test/option-u.py
+++ b/test/option-u.py
@@ -24,16 +24,54 @@
__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
-import TestSCons
-import string
+import os.path
import sys
+import TestSCons
+
test = TestSCons.TestSCons()
-test.write('SConstruct', "")
+python = sys.executable
+
+test.subdir('sub1', 'sub2', 'sub3')
+
+test.write('build.py', r"""
+import sys
+contents = open(sys.argv[2], 'rb').read()
+file = open(sys.argv[1], 'wb')
+file.write(contents)
+file.close()
+""")
+
+test.write('SConstruct', """
+B = Builder(name='B', action='%s build.py $TARGET $SOURCES')
+env = Environment(BUILDERS = [B])
+env.B(target = 'sub1/foo.out', source = 'sub1/foo.in')
+Default('.')
+Export('env')
+SConscript('sub2/SConscript')
+env.B(target = 'sub3/baz.out', source = 'sub3/baz.in')
+""" % python)
+
+test.write(['sub2', 'SConscript'], """
+Import('env')
+env.B(target = 'bar.out', source = 'bar.in')
+""")
+
+test.write(['sub1', 'foo.in'], "sub1/foo.in")
+test.write(['sub2', 'bar.in'], "sub2/bar.in")
+test.write(['sub3', 'baz.in'], "sub3/baz.in")
+
+test.run(arguments = '-u foo.out', chdir = 'sub1')
+
+test.fail_test(test.read(['sub1', 'foo.out']) != "sub1/foo.in")
+test.fail_test(os.path.exists(test.workpath('sub2', 'bar.out')))
+test.fail_test(os.path.exists(test.workpath('sub3', 'baz.out')))
+
+test.run(chdir = 'sub2', arguments = '-u')
-test.run(arguments = '-u',
- stderr = "Warning: the -u option is not yet implemented\n")
+test.fail_test(test.read(['sub2', 'bar.out']) != "sub2/bar.in")
+test.fail_test(os.path.exists(test.workpath('sub3', 'baz.out')))
test.pass_test()