Skip to content

Commit

Permalink
Bug 1024620 - Use object files next to archives when extracting them …
Browse files Browse the repository at this point in the history
…at link time, or in a subdirectory. r=ted
  • Loading branch information
glandium committed Jun 14, 2014
1 parent 31328a6 commit cd48864
Show file tree
Hide file tree
Showing 2 changed files with 71 additions and 26 deletions.
19 changes: 18 additions & 1 deletion config/expandlibs_exec.py
Expand Up @@ -74,6 +74,12 @@ def _extract(self, args):
'''
ar_extract = conf.AR_EXTRACT.split()
newlist = []

def lookup(base, f):
for root, dirs, files in os.walk(base):
if f in files:
return os.path.join(root, f)

for arg in args:
if os.path.splitext(arg)[1] == conf.LIB_SUFFIX:
if os.path.exists(arg + conf.LIBS_DESC_SUFFIX):
Expand All @@ -95,8 +101,19 @@ def _extract(self, args):
else:
subprocess.call(ar_extract + [os.path.abspath(arg)], cwd=tmp)
objs = []
basedir = os.path.dirname(arg)
for root, dirs, files in os.walk(tmp):
objs += [relativize(os.path.join(root, f)) for f in files if isObject(f)]
for f in files:
if isObject(f):
# If the file extracted from the library also
# exists in the directory containing the
# library, or one of its subdirectories, use
# that instead.
maybe_obj = lookup(os.path.join(basedir, os.path.relpath(root, tmp), f)
if maybe_obj:
objs.append(relativize(maybe_obj))
else:
objs.append(relativize(os.path.join(root, f)))
newlist += sorted(objs)
continue
newlist += [arg]
Expand Down
78 changes: 53 additions & 25 deletions config/tests/unit-expandlibs.py
Expand Up @@ -250,7 +250,7 @@ def test_extract(self):
'''Test library extraction'''
# Divert subprocess.call
subprocess_call = subprocess.call
extracted = {}
subprocess_check_output = subprocess.check_output
def call(args, **kargs):
if config.AR == 'lib':
self.assertEqual(args[:2], [config.AR, '-NOLOGO'])
Expand Down Expand Up @@ -294,31 +294,59 @@ def check_output(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.assertRelEqual(args, ['foo', '-bar'] + self.files + [self.tmpfile('liby', Lib('y'))])

# ExpandArgsMore also has an extra method extracting static libraries
# when possible
args.extract()

files = self.files + self.liby_files + self.libx_files
# With AR_EXTRACT, it uses the descriptors when there are, and
# actually
# extracts the remaining libraries
extracted_args = []
for f in files:
if f.endswith(config.LIB_SUFFIX):
extracted_args.extend(sorted(extracted[os.path.splitext(os.path.basename(f))[0]]))
else:
extracted_args.append(f)
self.assertRelEqual(args, ['foo', '-bar'] + extracted_args)

tmp = args.tmp
# Check that all temporary files are properly removed
self.assertEqual(True, all([not os.path.exists(f) for f in tmp]))

# Restore subprocess.call
for iteration in (1, 2):
with ExpandArgsMore(['foo', '-bar'] + self.arg_files + [self.tmpfile('liby', Lib('y'))]) as args:
self.assertRelEqual(args, ['foo', '-bar'] + self.files + [self.tmpfile('liby', Lib('y'))])

extracted = {}
# ExpandArgsMore also has an extra method extracting static libraries
# when possible
args.extract()

files = self.files + self.liby_files + self.libx_files
# With AR_EXTRACT, it uses the descriptors when there are, and
# actually
# extracts the remaining libraries
extracted_args = []
for f in files:
if f.endswith(config.LIB_SUFFIX):
base = os.path.splitext(os.path.basename(f))[0]
# On the first iteration, we test the behavior of
# extracting archives that don't have a copy of their
# contents next to them, which is to use the file
# extracted from the archive in a temporary directory.
# On the second iteration, we test extracting archives
# that do have a copy of their contents next to them,
# in which case those contents are used instead of the
# temporarily extracted files.
if iteration == 1:
extracted_args.extend(sorted(extracted[base]))
else:
dirname = os.path.dirname(f[len(self.tmpdir)+1:])
if base.endswith('f'):
dirname = os.path.join(dirname, 'foo', 'bar')
extracted_args.extend([self.tmpfile(dirname, Obj(base)), self.tmpfile(dirname, Obj(base + '2'))])
else:
extracted_args.append(f)
self.assertRelEqual(args, ['foo', '-bar'] + extracted_args)

tmp = args.tmp
# Check that all temporary files are properly removed
self.assertEqual(True, all([not os.path.exists(f) for f in tmp]))

# Create archives contents next to them for the second iteration.
base = os.path.splitext(Lib('_'))[0]
self.touch(self.tmpfile(Obj(base.replace('_', suffix))) for suffix in ('a', 'a2', 'd', 'd2'))
try:
os.makedirs(self.tmpfile('foo', 'bar'))
except:
pass
self.touch(self.tmpfile('foo', 'bar', Obj(base.replace('_', suffix))) for suffix in ('f', 'f2'))
self.touch(self.tmpfile('liby', Obj(base.replace('_', suffix))) for suffix in ('z', 'z2'))

# Restore subprocess.call and subprocess.check_output
subprocess.call = subprocess_call
subprocess.check_output = subprocess_check_output

class FakeProcess(object):
def __init__(self, out, err = ''):
Expand Down

0 comments on commit cd48864

Please sign in to comment.