Make the M4 Builder work with repositories by adding an rsrcnode attribute.
authorstevenknight <stevenknight@fdb21ef1-2011-0410-befe-b5e4ea1792b1>
Mon, 9 Feb 2004 05:44:56 +0000 (05:44 +0000)
committerstevenknight <stevenknight@fdb21ef1-2011-0410-befe-b5e4ea1792b1>
Mon, 9 Feb 2004 05:44:56 +0000 (05:44 +0000)
git-svn-id: http://scons.tigris.org/svn/scons/trunk@896 fdb21ef1-2011-0410-befe-b5e4ea1792b1

doc/man/scons.1
src/CHANGES.txt
src/engine/SCons/Node/FS.py
src/engine/SCons/Node/FSTests.py
src/engine/SCons/Tool/m4.py
test/Repository/M4.py [new file with mode: 0644]

index efa59ba79c5ae63089151d913364b54c33d3ef95..f5c0a705b81785d62ed5013fbaa627186ed53f0b 100644 (file)
@@ -6475,6 +6475,18 @@ The directory containing the source file linked to this file
 through BuildDir.  If this file isn't linked, it just returns the
 directory part of the filename.
 
+.IP rsrcpath
+The directory and file name to the source file linked to this file
+through BuildDir.  If the file does not exist locally but exists in
+a Repository, the path in the Repository is returned.
+If this file isn't linked, it just returns the
+directory and filename unchanged.
+
+.IP rsrcdir
+The Repository directory containing the source file linked to this file
+through BuildDir.  If this file isn't linked, it just returns the
+directory part of the filename.
+
 .LP
 For example, the specified target will
 expand as follows for the corresponding modifiers:
@@ -6492,6 +6504,11 @@ BuildDir('sub/dir','src')
 $SOURCE              => sub/dir/file.x
 ${SOURCE.srcpath}    => src/file.x
 ${SOURCE.srcdir}     => src
+
+Repository('/usr/repository')
+$SOURCE              => sub/dir/file.x
+${SOURCE.rsrcpath}   => /usr/repository/src/file.x
+${SOURCE.rsrcdir}    => /usr/repository/src
 .EE
 
 Lastly, a variable name
index f7d0a2269275dd92cd4604845a12df371327781f..f93a78a23d80770918d38deadaeba1efb51a6d40 100644 (file)
@@ -163,6 +163,13 @@ RELEASE 0.95 - XXX
   - Always use the Builder overrides in substitutions, not just if
     there isn't a target-specific environment.
 
+  - Add new "rsrcpath" and "rsrcdir" and attributes to $TARGET/$SOURCE,
+    so Builder command lines can find things in Repository source
+    directories when using BuildDir.
+
+  - Fix the M4 Builder so that it chdirs to the Repository directory
+    when the input file is in the source directory of a BuildDir.
+
   From Vincent Risi:
 
   - Add support for the bcc32, ilink32 and tlib Borland tools.
index e1aeda3882432914416c83a8a9cb7e3d52761ed5..438cd7fd307580a26d3dfa81db420f3b144c09b5 100644 (file)
@@ -276,18 +276,29 @@ class EntryProxy(SCons.Util.Proxy):
         node via BuildDir(), or the directory of this node if not linked."""
         return EntryProxy(self.get().srcnode().dir)
 
+    def __get_rsrcnode(self):
+        return EntryProxy(self.get().srcnode().rfile())
+
+    def __get_rsrcdir(self):
+        """Returns the directory containing the source node linked to this
+        node via BuildDir(), or the directory of this node if not linked."""
+        return EntryProxy(self.get().srcnode().rfile().dir)
+
     def __get_dir(self):
         return EntryProxy(self.get().dir)
     
-    dictSpecialAttrs = { "base" : __get_base_path,
-                         "posix" : __get_posix_path,
-                         "srcpath" : __get_srcnode,
-                         "srcdir" : __get_srcdir,
-                         "dir" : __get_dir,
-                         "abspath" : __get_abspath,
+    dictSpecialAttrs = { "base"     : __get_base_path,
+                         "posix"    : __get_posix_path,
+                         "srcpath"  : __get_srcnode,
+                         "srcdir"   : __get_srcdir,
+                         "dir"      : __get_dir,
+                         "abspath"  : __get_abspath,
                          "filebase" : __get_filebase,
-                         "suffix" : __get_suffix,
-                         "file" : __get_file }
+                         "suffix"   : __get_suffix,
+                         "file"     : __get_file,
+                         "rsrcpath" : __get_rsrcnode,
+                         "rsrcdir"  : __get_rsrcdir,
+                       }
 
     def __getattr__(self, name):
         # This is how we implement the "special" attributes
index ef1f52aa4901554ccc59bb9d6a759f8f3bb36f19..a84a993f5620ba9ab6cc7209af0edaea6f91221a 100644 (file)
@@ -1721,43 +1721,111 @@ class SpecialAttrTestCase(unittest.TestCase):
     def runTest(self):
         """Test special attributes of file nodes."""
         test=TestCmd(workdir='')
-        fs = SCons.Node.FS.FS(test.workpath(''))
+        fs = SCons.Node.FS.FS(test.workpath('work'))
+
+        f = fs.Entry('foo/bar/baz.blat').get_subst_proxy()
 
-        f=fs.Entry('foo/bar/baz.blat').get_subst_proxy()
-        assert str(f.dir) == os.path.normpath('foo/bar'), str(f.dir)
+        s = str(f.dir)
+        assert s == os.path.normpath('foo/bar'), s
         assert f.dir.is_literal(), f.dir
-        assert f.dir.for_signature() == 'bar', f.dir.for_signature()
-        
-        assert str(f.file) == 'baz.blat', str(f.file)
+        for_sig = f.dir.for_signature()
+        assert for_sig == 'bar', for_sig
+
+        s = str(f.file)
+        assert s == 'baz.blat', s
         assert f.file.is_literal(), f.file
-        assert f.file.for_signature() == 'baz.blat_file', \
-               f.file.for_signature()
-        
-        assert str(f.base) == os.path.normpath('foo/bar/baz'), str(f.base)
+        for_sig = f.file.for_signature()
+        assert for_sig == 'baz.blat_file', for_sig
+
+        s = str(f.base)
+        assert s == os.path.normpath('foo/bar/baz'), s
         assert f.base.is_literal(), f.base
-        assert f.base.for_signature() == 'baz.blat_base', \
-               f.base.for_signature()
-        
-        assert str(f.filebase) == 'baz', str(f.filebase)
+        for_sig = f.base.for_signature()
+        assert for_sig == 'baz.blat_base', for_sig
+
+        s = str(f.filebase)
+        assert s == 'baz', s
         assert f.filebase.is_literal(), f.filebase
-        assert f.filebase.for_signature() == 'baz.blat_filebase', \
-               f.filebase.for_signature()
-        
-        assert str(f.suffix) == '.blat', str(f.suffix)
+        for_sig = f.filebase.for_signature()
+        assert for_sig == 'baz.blat_filebase', for_sig
+
+        s = str(f.suffix)
+        assert s == '.blat', s
         assert f.suffix.is_literal(), f.suffix
-        assert f.suffix.for_signature() == 'baz.blat_suffix', \
-               f.suffix.for_signature()
-        
-        assert str(f.abspath) == test.workpath('foo', 'bar', 'baz.blat'), str(f.abspath)
+        for_sig = f.suffix.for_signature()
+        assert for_sig == 'baz.blat_suffix', for_sig
+
+        s = str(f.abspath)
+        assert s == test.workpath('work', 'foo', 'bar', 'baz.blat'), s
         assert f.abspath.is_literal(), f.abspath
-        assert f.abspath.for_signature() == 'baz.blat_abspath', \
-               f.abspath.for_signature()
-        
-        assert str(f.posix) == 'foo/bar/baz.blat', str(f.posix)
+        for_sig = f.abspath.for_signature()
+        assert for_sig == 'baz.blat_abspath', for_sig
+
+        s = str(f.posix)
+        assert s == 'foo/bar/baz.blat', s
         assert f.posix.is_literal(), f.posix
         if f.posix != f:
-            assert f.posix.for_signature() == 'baz.blat_posix', \
-                   f.posix.for_signature()
+            for_sig = f.posix.for_signature()
+            assert for_sig == 'baz.blat_posix', for_sig
+
+        # And now, combinations!!!
+        s = str(f.srcpath.base)
+        assert s == os.path.normpath('foo/bar/baz'), s
+        s = str(f.srcpath.dir)
+        assert s == str(f.srcdir), s
+        s = str(f.srcpath.posix)
+        assert s == 'foo/bar/baz.blat', s
+
+        # Test what happens with BuildDir()
+        fs.BuildDir('foo', 'baz')
+
+        s = str(f.srcpath)
+        assert s == os.path.normpath('baz/bar/baz.blat'), s
+        assert f.srcpath.is_literal(), f.srcpath
+        g = f.srcpath.get()
+        assert isinstance(g, SCons.Node.FS.Entry), g.__class__
+
+        s = str(f.srcdir)
+        assert s == os.path.normpath('baz/bar'), s
+        assert f.srcdir.is_literal(), f.srcdir
+        g = f.srcdir.get()
+        assert isinstance(g, SCons.Node.FS.Dir), g.__class__
+
+        # And now what happens with BuildDir() + Repository()
+        fs.Repository(test.workpath('repository'))
+
+        f = fs.Entry('foo/sub/file.suffix').get_subst_proxy()
+        test.subdir('repository',
+                    ['repository', 'baz'],
+                    ['repository', 'baz', 'sub'])
+
+        rd = test.workpath('repository', 'baz', 'sub')
+        rf = test.workpath('repository', 'baz', 'sub', 'file.suffix')
+        test.write(rf, "\n")
+
+        s = str(f.srcpath)
+        assert s == os.path.normpath('baz/sub/file.suffix'), s
+        assert f.srcpath.is_literal(), f.srcpath
+        g = f.srcpath.get()
+        assert isinstance(g, SCons.Node.FS.Entry), g.__class__
+
+        s = str(f.srcdir)
+        assert s == os.path.normpath('baz/sub'), s
+        assert f.srcdir.is_literal(), f.srcdir
+        g = f.srcdir.get()
+        assert isinstance(g, SCons.Node.FS.Dir), g.__class__
+
+        s = str(f.rsrcpath)
+        assert s == rf, s
+        assert f.rsrcpath.is_literal(), f.rsrcpath
+        g = f.rsrcpath.get()
+        assert isinstance(g, SCons.Node.FS.File), g.__class__
+
+        s = str(f.rsrcdir)
+        assert s == rd, s
+        assert f.rsrcdir.is_literal(), f.rsrcdir
+        g = f.rsrcdir.get()
+        assert isinstance(g, SCons.Node.FS.Dir), g.__class__
 
         # Check that attempts to access non-existent attributes of the
         # subst proxy generate the right exceptions and messages.
@@ -1785,22 +1853,7 @@ class SpecialAttrTestCase(unittest.TestCase):
             caught = 1
         assert caught, "did not catch expected AttributeError"
 
-        fs.BuildDir('foo', 'baz')
 
-        assert str(f.srcpath) == os.path.normpath('baz/bar/baz.blat'), str(f.srcpath)
-        assert f.srcpath.is_literal(), f.srcpath
-        assert isinstance(f.srcpath.get(), SCons.Node.FS.Entry)
-        
-        assert str(f.srcdir) == os.path.normpath('baz/bar'), str(f.srcdir)
-        assert f.srcdir.is_literal(), f.srcdir
-        assert isinstance(f.srcdir.get(), SCons.Node.FS.Dir)
-
-        # And now, combinations!!!
-        assert str(f.srcpath.base) == os.path.normpath('baz/bar/baz'), str(f.srcpath.base)
-        assert str(f.srcpath.dir) == str(f.srcdir), str(f.srcpath.dir)
-        assert str(f.srcpath.posix) == 'baz/bar/baz.blat', str(f.srcpath.posix)
-        
-        
 
 if __name__ == "__main__":
     suite = unittest.TestSuite()
index 35f323ca212679a7966c021bf90938259d224f39..0c83c66bb22cf77e17e2cfee87373d874b09583b 100644 (file)
@@ -48,7 +48,7 @@ def generate(env):
     # file.cpp.m4 -> file.cpp etc.
     env['M4']      = 'm4'
     env['M4FLAGS'] = '-E'
-    env['M4COM']   = 'cd ${SOURCE.srcdir} && $M4 $M4FLAGS < ${SOURCE.file} > ${TARGET.abspath}'
+    env['M4COM']   = 'cd ${SOURCE.rsrcdir} && $M4 $M4FLAGS < ${SOURCE.file} > ${TARGET.abspath}'
 
 def exists(env):
     return env.Detect('m4')
diff --git a/test/Repository/M4.py b/test/Repository/M4.py
new file mode 100644 (file)
index 0000000..75fa0de
--- /dev/null
@@ -0,0 +1,103 @@
+#!/usr/bin/env python
+#
+# __COPYRIGHT__
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+
+__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
+
+"""
+Test that $M4 and $M4FLAGS work with repositories.
+"""
+
+import os
+import os.path
+import string
+import sys
+import TestSCons
+
+python = TestSCons.python
+
+test = TestSCons.TestSCons()
+
+test.subdir('work', 'repository', ['repository', 'src'])
+
+test.write('mym4.py', """
+import string
+import sys
+contents = sys.stdin.read()
+sys.stdout.write(string.replace(contents, 'M4', 'mym4.py'))
+sys.exit(0)
+""")
+
+
+
+
+opts = "-Y " + test.workpath('repository')
+
+test.write(['repository', 'SConstruct'], """\
+env = Environment(M4 = r'%s %s', tools=['default', 'm4'])
+env.M4(target = 'aaa.x', source = 'aaa.x.m4')
+SConscript('src/SConscript', "env", build_dir="build")
+""" % (python, test.workpath('mym4.py')))
+
+test.write(['repository', 'aaa.x.m4'], """\
+line 1
+M4
+line 3
+""")
+
+test.write(['repository', 'src', 'SConscript'], """
+Import("env")
+env.M4('bbb.y', 'bbb.y.m4')
+""")
+
+test.write(['repository', 'src', 'bbb.y.m4'], """\
+line 1 M4
+line 2
+line 3 M4
+""")
+
+#
+# Make the repository non-writable,
+# so we'll detect if we try to write into it accidentally.
+test.writable('repository', 0)
+
+#
+test.run(chdir = 'work', options = opts, arguments = ".")
+
+expect_aaa_x = """\
+line 1
+mym4.py
+line 3
+"""
+
+expect_bbb_y = """\
+line 1 mym4.py
+line 2
+line 3 mym4.py
+"""
+
+test.fail_test(test.read(test.workpath('work', 'aaa.x'), 'r') != expect_aaa_x)
+test.fail_test(test.read(test.workpath('work', 'build', 'bbb.y'), 'r') != expect_bbb_y)
+
+#
+test.pass_test()