Skip to content

Commit

Permalink
Bug 644081 - Use relative paths as much as possible in expandlibs.py.…
Browse files Browse the repository at this point in the history
… r=ted
  • Loading branch information
glandium committed Mar 25, 2011
1 parent cffe141 commit 40c393b
Show file tree
Hide file tree
Showing 5 changed files with 102 additions and 32 deletions.
31 changes: 27 additions & 4 deletions config/expandlibs.py
Expand Up @@ -63,6 +63,29 @@
import sys, os
import expandlibs_config as conf

def relativize(path):
'''Returns a path relative to the current working directory, if it is
shorter than the given path'''
def splitpath(path):
dir, file = os.path.split(path)
if os.path.splitdrive(dir)[1] == os.sep:
return [file]
return splitpath(dir) + [file]

if not os.path.exists(path):
return path
curdir = splitpath(os.path.abspath(os.curdir))
abspath = splitpath(os.path.abspath(path))
while curdir and abspath and curdir[0] == abspath[0]:
del curdir[0]
del abspath[0]
if not curdir and not abspath:
return '.'
relpath = os.path.join(*[os.pardir for i in curdir] + abspath)
if len(path) > len(relpath):
return relpath
return path

class LibDescriptor(dict):
KEYS = ['OBJS', 'LIBS']

Expand Down Expand Up @@ -99,23 +122,23 @@ def _expand(self, arg):
'''Internal function doing the actual work'''
(root, ext) = os.path.splitext(arg)
if ext != conf.LIB_SUFFIX or not os.path.basename(root).startswith(conf.LIB_PREFIX):
return [arg]
return [relativize(arg)]
if len(conf.IMPORT_LIB_SUFFIX):
dll = root + conf.IMPORT_LIB_SUFFIX
else:
dll = root.replace(conf.LIB_PREFIX, conf.DLL_PREFIX, 1) + conf.DLL_SUFFIX
if os.path.exists(dll):
return [dll]
return [relativize(dll)]
if os.path.exists(arg):
return [arg]
return [relativize(arg)]
return self._expand_desc(arg)

def _expand_desc(self, arg):
'''Internal function taking care of lib descriptor expansion only'''
if os.path.exists(arg + conf.LIBS_DESC_SUFFIX):
with open(arg + conf.LIBS_DESC_SUFFIX, 'r') as f:
desc = LibDescriptor(f.readlines())
objs = desc['OBJS']
objs = [relativize(o) for o in desc['OBJS']]
for lib in desc['LIBS']:
objs += self._expand(lib)
return objs
Expand Down
4 changes: 2 additions & 2 deletions config/expandlibs_exec.py
Expand Up @@ -52,7 +52,7 @@
from __future__ import with_statement
import sys
import os
from expandlibs import ExpandArgs
from expandlibs import ExpandArgs, relativize
import expandlibs_config as conf
from optparse import OptionParser
import subprocess
Expand Down Expand Up @@ -93,7 +93,7 @@ def _extract(self, args):
subprocess.call(ar_extract + [os.path.abspath(arg)], cwd=tmp)
objs = []
for root, dirs, files in os.walk(tmp):
objs += [os.path.join(root, f) for f in files if os.path.splitext(f)[1] == conf.OBJ_SUFFIX]
objs += [relativize(os.path.join(root, f)) for f in files if os.path.splitext(f)[1] == conf.OBJ_SUFFIX]
newlist += objs
else:
newlist += [arg]
Expand Down
64 changes: 44 additions & 20 deletions config/tests/unit-expandlibs.py
Expand Up @@ -7,6 +7,7 @@
from tempfile import mkdtemp
from shutil import rmtree
sys.path.append(os.path.join(os.path.dirname(__file__), '..'))
from mozunit import MozTestRunner

from UserString import UserString
# Create a controlled configuration for use by expandlibs
Expand Down Expand Up @@ -35,7 +36,7 @@

config = sys.modules['expandlibs_config'] = imp.new_module('expandlibs_config')

from expandlibs import LibDescriptor, ExpandArgs
from expandlibs import LibDescriptor, ExpandArgs, relativize
from expandlibs_gen import generate
from expandlibs_exec import ExpandArgsMore

Expand All @@ -52,6 +53,21 @@ def ImportLib(name):
if not len(config.IMPORT_LIB_SUFFIX): return Dll(name)
return config.LIB_PREFIX + name + config.IMPORT_LIB_SUFFIX

class TestRelativize(unittest.TestCase):
def test_relativize(self):
'''Test relativize()'''
os_path_exists = os.path.exists
def exists(path):
return True
os.path.exists = exists
self.assertEqual(relativize(os.path.abspath(os.curdir)), os.curdir)
self.assertEqual(relativize(os.path.abspath(os.pardir)), os.pardir)
self.assertEqual(relativize(os.path.join(os.curdir, 'a')), 'a')
self.assertEqual(relativize(os.path.join(os.path.abspath(os.curdir), 'a')), 'a')
# relativize is expected to return the absolute path if it is shorter
self.assertEqual(relativize(os.sep), os.sep)
os.path.exists = os.path.exists

class TestLibDescriptor(unittest.TestCase):
def test_serialize(self):
'''Test LibDescriptor's serialization'''
Expand Down Expand Up @@ -83,8 +99,12 @@ def _method(self):
for key in conf:
setattr(config, key, conf[key])
self.init()
wrapped_method(self)
self.cleanup()
try:
wrapped_method(self)
except:
raise
finally:
self.cleanup()
return _method

class ReplicateTests(type):
Expand All @@ -101,7 +121,7 @@ def __new__(cls, clsName, bases, dict):
class TestCaseWithTmpDir(unittest.TestCase):
__metaclass__ = ReplicateTests
def init(self):
self.tmpdir = mkdtemp()
self.tmpdir = os.path.abspath(mkdtemp(dir=os.curdir))

def cleanup(self):
rmtree(self.tmpdir)
Expand Down Expand Up @@ -149,51 +169,55 @@ def init(self):
self.arg_files += [self.tmpfile(Lib('f'))]
self.touch(self.files)

def assertRelEqual(self, args1, args2):
self.assertEqual(args1, [relativize(a) for a in args2])

class TestExpandArgs(TestExpandInit):
def test_expand(self):
'''Test library expansion'''
# Expanding arguments means libraries with a descriptor are expanded
# with the descriptor content, and import libraries are used when
# a library doesn't exist
args = ExpandArgs(['foo', '-bar'] + self.arg_files + [self.tmpfile('liby', Lib('y'))])
self.assertEqual(args, ['foo', '-bar'] + self.files + self.liby_files + self.libx_files)
self.assertRelEqual(args, ['foo', '-bar'] + self.files + self.liby_files + self.libx_files)

# When a library exists at the same time as a descriptor, we just use
# the library
self.touch([self.tmpfile('libx', Lib('x'))])
args = ExpandArgs(['foo', '-bar'] + self.arg_files + [self.tmpfile('liby', Lib('y'))])
self.assertEqual(args, ['foo', '-bar'] + self.files + self.liby_files + [self.tmpfile('libx', Lib('x'))])
self.assertRelEqual(args, ['foo', '-bar'] + self.files + self.liby_files + [self.tmpfile('libx', Lib('x'))])

self.touch([self.tmpfile('liby', Lib('y'))])
args = ExpandArgs(['foo', '-bar'] + self.arg_files + [self.tmpfile('liby', Lib('y'))])
self.assertEqual(args, ['foo', '-bar'] + self.files + [self.tmpfile('liby', Lib('y'))])
self.assertRelEqual(args, ['foo', '-bar'] + self.files + [self.tmpfile('liby', Lib('y'))])

class TestExpandArgsMore(TestExpandInit):
def test_makelist(self):
'''Test grouping object files in lists'''
# ExpandArgsMore does the same as ExpandArgs
with ExpandArgsMore(['foo', '-bar'] + self.arg_files + [self.tmpfile('liby', Lib('y'))]) as args:
self.assertEqual(args, ['foo', '-bar'] + self.files + self.liby_files + self.libx_files)
self.assertRelEqual(args, ['foo', '-bar'] + self.files + self.liby_files + self.libx_files)

# But also has an extra method replacing object files with a list
args.makelist()
# self.files has objects at #1, #2, #4
self.assertEqual(args[:3], ['foo', '-bar'] + self.files[:1])
self.assertEqual(args[4:], [self.files[3]] + self.files[5:] + [self.tmpfile('liby', Lib('z'))])
self.assertRelEqual(args[:3], ['foo', '-bar'] + self.files[:1])
self.assertRelEqual(args[4:], [self.files[3]] + self.files[5:] + [self.tmpfile('liby', Lib('z'))])

# Check the list file content
objs = [f for f in self.files + self.liby_files + self.libx_files if f.endswith(config.OBJ_SUFFIX)]
if config.EXPAND_LIBS_LIST_STYLE == "linkerscript":
self.assertNotEqual(args[3][0], '@')
filename = args[3]
content = ["INPUT(%s)" % f for f in objs]
content = ["INPUT(%s)" % relativize(f) for f in objs]
with open(filename, 'r') as f:
self.assertEqual([l.strip() for l in f.readlines() if len(l.strip())], content)
elif config.EXPAND_LIBS_LIST_STYLE == "list":
self.assertEqual(args[3][0], '@')
filename = args[3][1:]
content = objs

with open(filename, 'r') as f:
self.assertEqual([l.strip() for l in f.readlines() if len(l.strip())], content)
with open(filename, 'r') as f:
self.assertRelEqual([l.strip() for l in f.readlines() if len(l.strip())], content)

tmp = args.tmp
# Check that all temporary files are properly removed
Expand All @@ -207,9 +231,9 @@ def test_extract(self):
def call(args, **kargs):
# The command called is always AR_EXTRACT
ar_extract = config.AR_EXTRACT.split()
self.assertEqual(args[:len(ar_extract)], ar_extract)
self.assertRelEqual(args[:len(ar_extract)], ar_extract)
# Remaining argument is always one library
self.assertEqual([os.path.splitext(arg)[1] for arg in args[len(ar_extract):]], [config.LIB_SUFFIX])
self.assertRelEqual([os.path.splitext(arg)[1] for arg in args[len(ar_extract):]], [config.LIB_SUFFIX])
# Simulate AR_EXTRACT extracting one object file for the library
lib = os.path.splitext(os.path.basename(args[len(ar_extract)]))[0]
extracted[lib] = os.path.join(kargs['cwd'], "%s" % Obj(lib))
Expand All @@ -219,7 +243,7 @@ def call(args, **kargs):
# ExpandArgsMore does the same as ExpandArgs
self.touch([self.tmpfile('liby', Lib('y'))])
with ExpandArgsMore(['foo', '-bar'] + self.arg_files + [self.tmpfile('liby', Lib('y'))]) as args:
self.assertEqual(args, ['foo', '-bar'] + self.files + [self.tmpfile('liby', Lib('y'))])
self.assertRelEqual(args, ['foo', '-bar'] + self.files + [self.tmpfile('liby', Lib('y'))])

# ExpandArgsMore also has an extra method extracting static libraries
# when possible
Expand All @@ -230,11 +254,11 @@ def call(args, **kargs):
# If we don't have an AR_EXTRACT, extract() expands libraries with a
# descriptor when the corresponding library exists (which ExpandArgs
# alone doesn't)
self.assertEqual(args, ['foo', '-bar'] + files)
self.assertRelEqual(args, ['foo', '-bar'] + files)
else:
# With AR_EXTRACT, it uses the descriptors when there are, and actually
# extracts the remaining libraries
self.assertEqual(args, ['foo', '-bar'] + [extracted[os.path.splitext(os.path.basename(f))[0]] if f.endswith(config.LIB_SUFFIX) else f for f in files])
self.assertRelEqual(args, ['foo', '-bar'] + [extracted[os.path.splitext(os.path.basename(f))[0]] if f.endswith(config.LIB_SUFFIX) else f for f in files])

tmp = args.tmp
# Check that all temporary files are properly removed
Expand All @@ -244,4 +268,4 @@ def call(args, **kargs):
subprocess.call = subprocess_call

if __name__ == '__main__':
unittest.main()
unittest.main(testRunner=MozTestRunner())
31 changes: 27 additions & 4 deletions js/src/config/expandlibs.py
Expand Up @@ -63,6 +63,29 @@
import sys, os
import expandlibs_config as conf

def relativize(path):
'''Returns a path relative to the current working directory, if it is
shorter than the given path'''
def splitpath(path):
dir, file = os.path.split(path)
if os.path.splitdrive(dir)[1] == os.sep:
return [file]
return splitpath(dir) + [file]

if not os.path.exists(path):
return path
curdir = splitpath(os.path.abspath(os.curdir))
abspath = splitpath(os.path.abspath(path))
while curdir and abspath and curdir[0] == abspath[0]:
del curdir[0]
del abspath[0]
if not curdir and not abspath:
return '.'
relpath = os.path.join(*[os.pardir for i in curdir] + abspath)
if len(path) > len(relpath):
return relpath
return path

class LibDescriptor(dict):
KEYS = ['OBJS', 'LIBS']

Expand Down Expand Up @@ -99,23 +122,23 @@ def _expand(self, arg):
'''Internal function doing the actual work'''
(root, ext) = os.path.splitext(arg)
if ext != conf.LIB_SUFFIX or not os.path.basename(root).startswith(conf.LIB_PREFIX):
return [arg]
return [relativize(arg)]
if len(conf.IMPORT_LIB_SUFFIX):
dll = root + conf.IMPORT_LIB_SUFFIX
else:
dll = root.replace(conf.LIB_PREFIX, conf.DLL_PREFIX, 1) + conf.DLL_SUFFIX
if os.path.exists(dll):
return [dll]
return [relativize(dll)]
if os.path.exists(arg):
return [arg]
return [relativize(arg)]
return self._expand_desc(arg)

def _expand_desc(self, arg):
'''Internal function taking care of lib descriptor expansion only'''
if os.path.exists(arg + conf.LIBS_DESC_SUFFIX):
with open(arg + conf.LIBS_DESC_SUFFIX, 'r') as f:
desc = LibDescriptor(f.readlines())
objs = desc['OBJS']
objs = [relativize(o) for o in desc['OBJS']]
for lib in desc['LIBS']:
objs += self._expand(lib)
return objs
Expand Down
4 changes: 2 additions & 2 deletions js/src/config/expandlibs_exec.py
Expand Up @@ -52,7 +52,7 @@
from __future__ import with_statement
import sys
import os
from expandlibs import ExpandArgs
from expandlibs import ExpandArgs, relativize
import expandlibs_config as conf
from optparse import OptionParser
import subprocess
Expand Down Expand Up @@ -93,7 +93,7 @@ def _extract(self, args):
subprocess.call(ar_extract + [os.path.abspath(arg)], cwd=tmp)
objs = []
for root, dirs, files in os.walk(tmp):
objs += [os.path.join(root, f) for f in files if os.path.splitext(f)[1] == conf.OBJ_SUFFIX]
objs += [relativize(os.path.join(root, f)) for f in files if os.path.splitext(f)[1] == conf.OBJ_SUFFIX]
newlist += objs
else:
newlist += [arg]
Expand Down

0 comments on commit 40c393b

Please sign in to comment.