Implement the -u option (Task 39028). (Steve Leblanc)
authorstevenknight <stevenknight@fdb21ef1-2011-0410-befe-b5e4ea1792b1>
Thu, 21 Feb 2002 09:57:19 +0000 (09:57 +0000)
committerstevenknight <stevenknight@fdb21ef1-2011-0410-befe-b5e4ea1792b1>
Thu, 21 Feb 2002 09:57:19 +0000 (09:57 +0000)
git-svn-id: http://scons.tigris.org/svn/scons/trunk@271 fdb21ef1-2011-0410-befe-b5e4ea1792b1

doc/man/scons.1
src/CHANGES.txt
src/RELEASE.txt
src/engine/SCons/Scanner/C.py
src/engine/SCons/Script/__init__.py
test/option-u.py

index 78bf54b51257c4cd05cf449b2c2e08d9535898ce..ef5b66449f8170da579dac75775a7b8d1d48ede5 100644 (file)
@@ -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
index b364ac7036e39371b20c126f4151ae165b9dc606..3b0f2b7df482b5688db879efbd16b32864017694 100644 (file)
@@ -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
index 467677be025b616c930355a20a9024d208f988b4..358a35948862ff4182fd227169e1b9f47663a2bd 100644 (file)
@@ -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.
index 51235c3d3fca1ad19698761cf23a99ecc857330e..6b5b6c647d8257835b3f7f9433d2d677ff5f0a57 100644 (file)
@@ -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
 
index dfd969ec2668847ca86d982e1279c79dc97ec488..6e923bc6063da3e4d032d29e7c13f21a3c736ded 100644 (file)
@@ -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))
index 9f68ac5b86b277ec4e1c28d3e434780f90fd4ab5..dbeec6ac13f734fda5a6fc6edab1cab036d40b4a 100644 (file)
 
 __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()