Bug 780414 - Fix ConfigStatus.py for the case where top_srcdir is a path relative to topobjdir. r=khuey
authorMike Hommey <mh+mozilla@glandium.org>
Sun, 05 Aug 2012 17:48:22 +0200
changeset 107501 d83147d64e0639164ea7cf43f4a7ca5f7cca50ba
parent 107500 a2d271ce54ffcd1cc5ec08fab56d86fb0062b76d
child 107502 91de8ff323d4147463f8252714f7d92dfd7c7af4
push id214
push userakeybl@mozilla.com
push dateWed, 14 Nov 2012 20:38:59 +0000
treeherdermozilla-release@c8b08ec8e1aa [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerskhuey
bugs780414
milestone17.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 780414 - Fix ConfigStatus.py for the case where top_srcdir is a path relative to topobjdir. r=khuey
build/ConfigStatus.py
build/tests/unit-ConfigStatus.py
js/src/build/ConfigStatus.py
--- a/build/ConfigStatus.py
+++ b/build/ConfigStatus.py
@@ -119,17 +119,18 @@ class ConfigEnvironment(object):
          preprocessor command lines. The order in which defines were given
          when creating the ConfigEnvironment is preserved.
        - ALLDEFINES contains the defines in the form #define NAME VALUE, in
          sorted order, for use in config files, for an automatic listing of
          defines.
 
     ConfigEnvironment expects a "top_srcdir" subst to be set with the top
     source directory, in msys format on windows. It is used to derive a
-    "srcdir" subst when treating config files.
+    "srcdir" subst when treating config files. It can either be an absolute
+    path or a path relative to the topobjdir.
     '''
 
     def __init__(self, topobjdir = '.', topsrcdir = '.',
                  defines = [], non_global_defines = [], substs = []):
         self.defines = dict(defines)
         self.substs = dict(substs)
         self.topsrcdir = topsrcdir
         self.topobjdir = topobjdir
@@ -142,22 +143,32 @@ class ConfigEnvironment(object):
         using / as a path separator.
         '''
         assert(isinstance(file, basestring))
         dir = posixpath.dirname(relpath(file, self.topobjdir).replace(os.sep, '/'))
         if dir:
             return dir
         return '.'
 
+    def get_top_srcdir(self, file):
+        '''Returns a normalized top_srcdir for the given file: if
+        substs['top_srcdir'] is a relative path, it is relative to the
+        topobjdir. Adjust it to be relative to the file path.'''
+        top_srcdir = self.substs['top_srcdir']
+        if posixpath.isabs(top_srcdir):
+            return top_srcdir
+        return posixpath.normpath(posixpath.join(self.get_depth(file), top_srcdir))
+
     def get_file_srcdir(self, file):
         '''Returns the srcdir for the given file, where srcdir is in msys
         format on windows, thus derived from top_srcdir.
         '''
         dir = self.get_relative_srcdir(file)
-        return posixpath.normpath(posixpath.join(self.substs['top_srcdir'], dir))
+        top_srcdir = self.get_top_srcdir(file)
+        return posixpath.normpath(posixpath.join(top_srcdir, dir))
 
     def get_depth(self, file):
         '''Returns the DEPTH for the given file, that is, the path to the
         object directory relative to the directory containing the given file.
         Always uses / as a path separator.
         '''
         return relpath(self.topobjdir, os.path.dirname(file)).replace(os.sep, '/')
 
@@ -176,16 +187,17 @@ class ConfigEnvironment(object):
         Additional substs are defined according to the file being treated:
             "srcdir" for its the path to its source directory
             "relativesrcdir" for its source directory relative to the top
             "DEPTH" for the path to the top object directory
         '''
         input = self.get_input(path)
         pp = Preprocessor()
         pp.context.update(self.substs)
+        pp.context.update(top_srcdir = self.get_top_srcdir(path))
         pp.context.update(srcdir = self.get_file_srcdir(path))
         pp.context.update(relativesrcdir = self.get_relative_srcdir(path))
         pp.context.update(DEPTH = self.get_depth(path))
         pp.do_filter('attemptSubstitution')
         pp.setMarker(None)
         with FileAvoidWrite(path) as pp.out:
             pp.do_include(input)
 
--- a/build/tests/unit-ConfigStatus.py
+++ b/build/tests/unit-ConfigStatus.py
@@ -1,22 +1,25 @@
 from __future__ import with_statement
-import os
+import os, posixpath
 from StringIO import StringIO
 import unittest
 from mozunit import main, MockedOpen
 import ConfigStatus
 from ConfigStatus import FileAvoidWrite
 
 class ConfigEnvironment(ConfigStatus.ConfigEnvironment):
     def __init__(self, **args):
         ConfigStatus.ConfigEnvironment.__init__(self, **args)
         # Be helpful to unit tests
         if not 'top_srcdir' in self.substs:
-            self.substs['top_srcdir'] = self.topsrcdir.replace(os.sep, '/')
+            if os.path.isabs(self.topsrcdir):
+                self.substs['top_srcdir'] = self.topsrcdir.replace(os.sep, '/')
+            else:
+                self.substs['top_srcdir'] = ConfigStatus.relpath(self.topsrcdir, self.topobjdir).replace(os.sep, '/')
 
 class TestFileAvoidWrite(unittest.TestCase):
     def test_file_avoid_write(self):
         '''Test the FileAvoidWrite class
         '''
         with MockedOpen({'file': 'content'}):
             # Overwriting an existing file replaces its content
             with FileAvoidWrite('file') as file:
@@ -135,34 +138,44 @@ class TestPathsLocalBuildDir(TestPaths):
         self.assertEqual(env.get_relative_srcdir('dir/file'), 'dir')
         self.assertEqual(env.get_relative_srcdir('deeply/nested/path/to/file'), 'deeply/nested/path/to')
         self.assertEqual(env.get_depth('file'), '.')
         self.assertEqual(env.get_depth('dir/file'), '..')
         self.assertEqual(env.get_depth('deeply/nested/path/to/file'), '../../../..')
         return env
 
     def test_paths_local_build_local_src(self):
+        # topsrcdir = . ; topobjdir = .
         env = self.get_env('.')
         self.assertEqual(env.get_input('file'), 'file.in')
         self.assertEqual(env.get_input('dir/file'), os.path.join('dir', 'file.in'))
+        self.assertEqual(env.get_top_srcdir('file'), '.')
+        self.assertEqual(env.get_top_srcdir('dir/file'), '..')
         self.assertEqual(env.get_file_srcdir('file'), '.')
-        self.assertEqual(env.get_file_srcdir('dir/file'), 'dir')
+        self.assertEqual(env.get_file_srcdir('dir/file'), '../dir')
 
     def test_paths_local_build_parent_src(self):
+        # topsrcdir = .. ; topobjdir = .
         env = self.get_env('..')
         self.assertEqual(env.get_input('file'), os.path.join('..', 'file.in'))
         self.assertEqual(env.get_input('dir/file'), os.path.join('..', 'dir', 'file.in'))
+        self.assertEqual(env.get_top_srcdir('file'), '..')
+        self.assertEqual(env.get_top_srcdir('dir/file'), '../..')
         self.assertEqual(env.get_file_srcdir('file'), '..')
-        self.assertEqual(env.get_file_srcdir('dir/file'), '../dir')
+        self.assertEqual(env.get_file_srcdir('dir/file'), '../../dir')
 
     def test_paths_local_build_absolute_src(self):
+        # topsrcdir = /absolute ; topobjdir = /absolute
         env = self.get_env(self.absolute)
         self.assertEqual(env.get_input('file'), os.path.join(self.absolute, 'file.in'))
         self.assertEqual(env.get_input('dir/file'), os.path.join(self.absolute, 'dir', 'file.in'))
         self.assertEqual(env.get_input('%s/file' % self.dir), os.path.join(self.absolute, self.dir, 'file.in'))
+        self.assertEqual(env.get_top_srcdir('file'), '/absolute')
+        self.assertEqual(env.get_top_srcdir('dir/file'), '/absolute')
+        self.assertEqual(env.get_top_srcdir('%s/file' % dir), '/absolute')
         self.assertEqual(env.get_file_srcdir('file'), '/absolute')
         self.assertEqual(env.get_file_srcdir('dir/file'), '/absolute/dir')
         self.assertEqual(env.get_file_srcdir('%s/file' % dir), '/absolute/%s' % dir)
 
 class TestPathsParentBuildDir(TestPaths):
     def get_env(self, topsrcdir):
         env = ConfigEnvironment(topsrcdir = topsrcdir, topobjdir = '..')
         self.assertEqual(env.get_relative_srcdir('..'), '.')
@@ -171,78 +184,102 @@ class TestPathsParentBuildDir(TestPaths)
         self.assertEqual(env.get_relative_srcdir('deeply/nested/path/to/file'), '%s/deeply/nested/path/to' % self.dir)
         self.assertEqual(env.get_depth('../file'), '.')
         self.assertEqual(env.get_depth('file'), '..')
         self.assertEqual(env.get_depth('dir/file'), '../..')
         self.assertEqual(env.get_depth('deeply/nested/path/to/file'), '../../../../..')
         return env
 
     def test_paths_parent_build_parent_src(self):
+        # topsrcdir = .. ; topobjdir = ..
         env = self.get_env('..')
         self.assertEqual(env.get_input('../file'), os.path.join('..', 'file.in'))
         self.assertEqual(env.get_input('file'), os.path.join('..', self.dir, 'file.in'))
         self.assertEqual(env.get_input('dir/file'), os.path.join('..', self.dir, 'dir', 'file.in'))
-        self.assertEqual(env.get_file_srcdir('../file'), '..')
+        self.assertEqual(env.get_top_srcdir('../file'), '.')
+        self.assertEqual(env.get_top_srcdir('file'), '..')
+        self.assertEqual(env.get_top_srcdir('dir/file'), '../..')
+        self.assertEqual(env.get_file_srcdir('../file'), '.')
         self.assertEqual(env.get_file_srcdir('file'), '../%s' % self.dir)
-        self.assertEqual(env.get_file_srcdir('dir/file'), '../%s/dir' % self.dir)
+        self.assertEqual(env.get_file_srcdir('dir/file'), '../../%s/dir' % self.dir)
 
     def test_paths_parent_build_ancestor_src(self):
+        # topsrcdir = ../.. ; topobjdir = ..
         env = self.get_env('../..')
         self.assertEqual(env.get_input('../file'), os.path.join('..', '..', 'file.in'))
         self.assertEqual(env.get_input('file'), os.path.join('..', '..', self.dir, 'file.in'))
         self.assertEqual(env.get_input('dir/file'), os.path.join('..', '..', self.dir, 'dir', 'file.in'))
-        self.assertEqual(env.get_file_srcdir('../file'), '../..')
+        self.assertEqual(env.get_top_srcdir('../file'), '..')
+        self.assertEqual(env.get_top_srcdir('file'), '../..')
+        self.assertEqual(env.get_top_srcdir('dir/file'), '../../..')
+        self.assertEqual(env.get_file_srcdir('../file'), '..')
         self.assertEqual(env.get_file_srcdir('file'), '../../%s' % self.dir)
-        self.assertEqual(env.get_file_srcdir('dir/file'), '../../%s/dir' % self.dir)
+        self.assertEqual(env.get_file_srcdir('dir/file'), '../../../%s/dir' % self.dir)
 
     def test_paths_parent_build_absolute_src(self):
+        # topsrcdir = /absolute ; topobjdir = ..
         env = self.get_env(self.absolute)
         self.assertEqual(env.get_input('../file'), os.path.join(self.absolute, 'file.in'))
         self.assertEqual(env.get_input('file'), os.path.join(self.absolute, self.dir, 'file.in'))
         self.assertEqual(env.get_input('dir/file'), os.path.join(self.absolute, self.dir, 'dir', 'file.in'))
+        self.assertEqual(env.get_top_srcdir('../file'), '/absolute')
+        self.assertEqual(env.get_top_srcdir('file'), '/absolute')
+        self.assertEqual(env.get_top_srcdir('dir/file'), '/absolute')
         self.assertEqual(env.get_file_srcdir('../file'), '/absolute')
         self.assertEqual(env.get_file_srcdir('file'), '/absolute/%s' % self.dir)
         self.assertEqual(env.get_file_srcdir('dir/file'), '/absolute/%s/dir' % self.dir)
 
 class TestPathsRelativeBuild(TestPaths):
     def get_env(self, topsrcdir):
         env = ConfigEnvironment(topsrcdir = topsrcdir, topobjdir = 'relative')
         self.assertEqual(env.get_relative_srcdir('relative/file'), '.')
         self.assertEqual(env.get_relative_srcdir('relative/dir/file'), 'dir')
         self.assertEqual(env.get_relative_srcdir('relative/deeply/nested/path/to/file'), 'deeply/nested/path/to')
         self.assertEqual(env.get_depth('relative/file'), '.')
         self.assertEqual(env.get_depth('relative/dir/file'), '..')
         self.assertEqual(env.get_depth('relative/deeply/nested/path/to/file'), '../../../..')
         return env
 
     def test_paths_relative_build_relative_src(self):
+        # topsrcdir = relative ; topobjdir = relative
         env = self.get_env('relative')
         self.assertEqual(env.get_input('relative/file'), os.path.join('relative', 'file.in'))
         self.assertEqual(env.get_input('relative/dir/file'), os.path.join('relative', 'dir', 'file.in'))
-        self.assertEqual(env.get_file_srcdir('relative/file'), 'relative')
-        self.assertEqual(env.get_file_srcdir('relative/dir/file'), 'relative/dir')
+        self.assertEqual(env.get_top_srcdir('relative/file'), '.')
+        self.assertEqual(env.get_top_srcdir('relative/dir/file'), '..')
+        self.assertEqual(env.get_file_srcdir('relative/file'), '.')
+        self.assertEqual(env.get_file_srcdir('relative/dir/file'), '../dir')
 
     def test_paths_relative_build_local_src(self):
+        # topsrcdir = . ; topobjdir = relative
         env = self.get_env('.')
         self.assertEqual(env.get_input('relative/file'), 'file.in')
         self.assertEqual(env.get_input('relative/dir/file'), os.path.join('dir', 'file.in'))
-        self.assertEqual(env.get_file_srcdir('relative/file'), '.')
-        self.assertEqual(env.get_file_srcdir('relative/dir/file'), 'dir')
+        self.assertEqual(env.get_top_srcdir('relative/file'), '..')
+        self.assertEqual(env.get_top_srcdir('relative/dir/file'), '../..')
+        self.assertEqual(env.get_file_srcdir('relative/file'), '..')
+        self.assertEqual(env.get_file_srcdir('relative/dir/file'), '../../dir')
 
     def test_paths_relative_build_parent_src(self):
+        # topsrcdir = .. ; topobjdir = relative
         env = self.get_env('..')
         self.assertEqual(env.get_input('relative/file'), os.path.join('..', 'file.in'))
         self.assertEqual(env.get_input('relative/dir/file'), os.path.join('..', 'dir', 'file.in'))
-        self.assertEqual(env.get_file_srcdir('relative/file'), '..')
-        self.assertEqual(env.get_file_srcdir('relative/dir/file'), '../dir')
+        self.assertEqual(env.get_top_srcdir('relative/file'), '../..')
+        self.assertEqual(env.get_top_srcdir('relative/dir/file'), '../../..')
+        self.assertEqual(env.get_file_srcdir('relative/file'), '../..')
+        self.assertEqual(env.get_file_srcdir('relative/dir/file'), '../../../dir')
 
     def test_paths_relative_build_absolute_src(self):
+        # topsrcdir = /absolute ; topobjdir = relative
         env = self.get_env(self.absolute)
         self.assertEqual(env.get_input('relative/file'), os.path.join(self.absolute, 'file.in'))
         self.assertEqual(env.get_input('relative/dir/file'), os.path.join(self.absolute, 'dir', 'file.in'))
+        self.assertEqual(env.get_top_srcdir('relative/file'), '/absolute')
+        self.assertEqual(env.get_top_srcdir('relative/dir/file'), '/absolute')
         self.assertEqual(env.get_file_srcdir('relative/file'), '/absolute')
         self.assertEqual(env.get_file_srcdir('relative/dir/file'), '/absolute/dir')
 
 class TestPathsAbsoluteBuild(unittest.TestCase):
     def setUp(self):
         self.absolute_build = os.path.normpath('/absolute/build')
 
     def get_env(self, topsrcdir):
@@ -251,32 +288,41 @@ class TestPathsAbsoluteBuild(unittest.Te
         self.assertEqual(env.get_relative_srcdir('/absolute/build/dir/file'), 'dir')
         self.assertEqual(env.get_relative_srcdir('/absolute/build/deeply/nested/path/to/file'), 'deeply/nested/path/to')
         self.assertEqual(env.get_depth('/absolute/build/file'), '.')
         self.assertEqual(env.get_depth('/absolute/build/dir/file'), '..')
         self.assertEqual(env.get_depth('/absolute/build/deeply/nested/path/to/file'), '../../../..')
         return env
 
     def test_paths_absolute_build_same_src(self):
+        # topsrcdir = /absolute/build ; topobjdir = /absolute/build
         env = self.get_env(self.absolute_build)
         self.assertEqual(env.get_input('/absolute/build/file'), os.path.join(self.absolute_build, 'file.in'))
         self.assertEqual(env.get_input('/absolute/build/dir/file'), os.path.join(self.absolute_build, 'dir', 'file.in'))
+        self.assertEqual(env.get_top_srcdir('/absolute/build/file'), '/absolute/build')
+        self.assertEqual(env.get_top_srcdir('/absolute/build/dir/file'), '/absolute/build')
         self.assertEqual(env.get_file_srcdir('/absolute/build/file'), '/absolute/build')
         self.assertEqual(env.get_file_srcdir('/absolute/build/dir/file'), '/absolute/build/dir')
 
     def test_paths_absolute_build_ancestor_src(self):
+        # topsrcdir = /absolute ; topobjdir = /absolute/build
         absolute = os.path.dirname(self.absolute_build)
         env = self.get_env(absolute)
         self.assertEqual(env.get_input('/absolute/build/file'), os.path.join(absolute, 'file.in'))
         self.assertEqual(env.get_input('/absolute/build/dir/file'), os.path.join(absolute, 'dir', 'file.in'))
+        self.assertEqual(env.get_top_srcdir('/absolute/build/file'), '/absolute')
+        self.assertEqual(env.get_top_srcdir('/absolute/build/dir/file'), '/absolute')
         self.assertEqual(env.get_file_srcdir('/absolute/build/file'), '/absolute')
         self.assertEqual(env.get_file_srcdir('/absolute/build/dir/file'), '/absolute/dir')
 
     def test_paths_absolute_build_different_src(self):
+        # topsrcdir = /some/path ; topobjdir = /absolute/build
         absolute = os.path.normpath('/some/path')
         env = self.get_env(absolute)
         self.assertEqual(env.get_input('/absolute/build/file'), os.path.join(absolute, 'file.in'))
         self.assertEqual(env.get_input('/absolute/build/dir/file'), os.path.join(absolute, 'dir', 'file.in'))
+        self.assertEqual(env.get_top_srcdir('/absolute/build/file'), '/some/path')
+        self.assertEqual(env.get_top_srcdir('/absolute/build/dir/file'), '/some/path')
         self.assertEqual(env.get_file_srcdir('/absolute/build/file'), '/some/path')
         self.assertEqual(env.get_file_srcdir('/absolute/build/dir/file'), '/some/path/dir')
 
 if __name__ == "__main__":
     main()
--- a/js/src/build/ConfigStatus.py
+++ b/js/src/build/ConfigStatus.py
@@ -119,17 +119,18 @@ class ConfigEnvironment(object):
          preprocessor command lines. The order in which defines were given
          when creating the ConfigEnvironment is preserved.
        - ALLDEFINES contains the defines in the form #define NAME VALUE, in
          sorted order, for use in config files, for an automatic listing of
          defines.
 
     ConfigEnvironment expects a "top_srcdir" subst to be set with the top
     source directory, in msys format on windows. It is used to derive a
-    "srcdir" subst when treating config files.
+    "srcdir" subst when treating config files. It can either be an absolute
+    path or a path relative to the topobjdir.
     '''
 
     def __init__(self, topobjdir = '.', topsrcdir = '.',
                  defines = [], non_global_defines = [], substs = []):
         self.defines = dict(defines)
         self.substs = dict(substs)
         self.topsrcdir = topsrcdir
         self.topobjdir = topobjdir
@@ -142,22 +143,32 @@ class ConfigEnvironment(object):
         using / as a path separator.
         '''
         assert(isinstance(file, basestring))
         dir = posixpath.dirname(relpath(file, self.topobjdir).replace(os.sep, '/'))
         if dir:
             return dir
         return '.'
 
+    def get_top_srcdir(self, file):
+        '''Returns a normalized top_srcdir for the given file: if
+        substs['top_srcdir'] is a relative path, it is relative to the
+        topobjdir. Adjust it to be relative to the file path.'''
+        top_srcdir = self.substs['top_srcdir']
+        if posixpath.isabs(top_srcdir):
+            return top_srcdir
+        return posixpath.normpath(posixpath.join(self.get_depth(file), top_srcdir))
+
     def get_file_srcdir(self, file):
         '''Returns the srcdir for the given file, where srcdir is in msys
         format on windows, thus derived from top_srcdir.
         '''
         dir = self.get_relative_srcdir(file)
-        return posixpath.normpath(posixpath.join(self.substs['top_srcdir'], dir))
+        top_srcdir = self.get_top_srcdir(file)
+        return posixpath.normpath(posixpath.join(top_srcdir, dir))
 
     def get_depth(self, file):
         '''Returns the DEPTH for the given file, that is, the path to the
         object directory relative to the directory containing the given file.
         Always uses / as a path separator.
         '''
         return relpath(self.topobjdir, os.path.dirname(file)).replace(os.sep, '/')
 
@@ -176,16 +187,17 @@ class ConfigEnvironment(object):
         Additional substs are defined according to the file being treated:
             "srcdir" for its the path to its source directory
             "relativesrcdir" for its source directory relative to the top
             "DEPTH" for the path to the top object directory
         '''
         input = self.get_input(path)
         pp = Preprocessor()
         pp.context.update(self.substs)
+        pp.context.update(top_srcdir = self.get_top_srcdir(path))
         pp.context.update(srcdir = self.get_file_srcdir(path))
         pp.context.update(relativesrcdir = self.get_relative_srcdir(path))
         pp.context.update(DEPTH = self.get_depth(path))
         pp.do_filter('attemptSubstitution')
         pp.setMarker(None)
         with FileAvoidWrite(path) as pp.out:
             pp.do_include(input)