Bug 1036894 part 4 - Allow to track library linkage for all kinds of programs and libraries. r=gps

This commit is contained in:
Mike Hommey 2014-07-23 13:29:31 +09:00
parent e97e74b6eb
commit e679e0b8b9
3 changed files with 84 additions and 57 deletions

View File

@ -1120,16 +1120,16 @@ class RecursiveMakeBackend(CommonBackend):
backend_file.write('SDK_LIBRARY := %s\n' % libdef.import_name)
thisobjdir = libdef.objdir
topobjdir = libdef.topobjdir.replace(os.sep, '/')
for objdir, basename in libdef.static_libraries:
topobjdir = mozpath.normsep(libdef.topobjdir)
for obj in libdef.linked_libraries:
# If this is an external objdir (i.e., comm-central), use the other
# directory instead of $(DEPTH).
if objdir.startswith(topobjdir + '/'):
relpath = '$(DEPTH)/%s' % mozpath.relpath(objdir, topobjdir)
if obj.objdir.startswith(topobjdir + '/'):
relpath = '$(DEPTH)/%s' % mozpath.relpath(obj.objdir, topobjdir)
else:
relpath = mozpath.relpath(objdir, thisobjdir)
backend_file.write('SHARED_LIBRARY_LIBS += %s/$(LIB_PREFIX)%s.$(LIB_SUFFIX)\n'
% (relpath, basename))
relpath = mozpath.relpath(obj.objdir, thisobjdir)
backend_file.write('SHARED_LIBRARY_LIBS += %s/%s\n'
% (relpath, obj.static_name))
def _process_host_library(self, libdef, backend_file):
backend_file.write('HOST_LIBRARY_NAME = %s\n' % libdef.basename)

View File

@ -324,7 +324,30 @@ class ExampleWebIDLInterface(SandboxDerived):
self.name = name
class BaseProgram(SandboxDerived):
class LinkageWrongKindError(Exception):
"""Error thrown when trying to link objects of the wrong kind"""
class Linkable(SandboxDerived):
"""Generic sandbox container object for programs and libraries"""
__slots__ = ('linked_libraries')
def __init__(self, sandbox):
SandboxDerived.__init__(self, sandbox)
self.linked_libraries = []
def link_library(self, obj):
assert isinstance(obj, BaseLibrary)
if obj.kind == obj.COMPONENT:
raise LinkageWrongKindError(
'Linkable.link_library() does not take components.')
if obj.KIND != self.KIND:
raise LinkageWrongKindError('%s != %s' % (obj.KIND, self.KIND))
self.linked_libraries.append(obj)
obj.refcount += 1
class BaseProgram(Linkable):
"""Sandbox container object for programs, which is a unicode string.
This class handles automatically appending a binary suffix to the program
@ -336,7 +359,7 @@ class BaseProgram(SandboxDerived):
__slots__ = ('program')
def __init__(self, sandbox, program):
SandboxDerived.__init__(self, sandbox)
Linkable.__init__(self, sandbox)
bin_suffix = sandbox['CONFIG'].get(self.SUFFIX_VAR, '')
if not program.endswith(bin_suffix):
@ -347,38 +370,37 @@ class BaseProgram(SandboxDerived):
class Program(BaseProgram):
"""Sandbox container object for PROGRAM"""
SUFFIX_VAR = 'BIN_SUFFIX'
KIND = 'target'
class HostProgram(BaseProgram):
"""Sandbox container object for HOST_PROGRAM"""
SUFFIX_VAR = 'HOST_BIN_SUFFIX'
KIND = 'host'
class SimpleProgram(BaseProgram):
"""Sandbox container object for each program in SIMPLE_PROGRAMS"""
SUFFIX_VAR = 'BIN_SUFFIX'
KIND = 'target'
class HostSimpleProgram(BaseProgram):
"""Sandbox container object for each program in HOST_SIMPLE_PROGRAMS"""
SUFFIX_VAR = 'HOST_BIN_SUFFIX'
KIND = 'host'
class BaseLibrary(SandboxDerived):
"""Generic sandbox container object for libraries.
The static_libraries member tracks the list of relative directory and
library names of static libraries that are meant to be linked into
the library defined by an instance of this class.
"""
class BaseLibrary(Linkable):
"""Generic sandbox container object for libraries."""
__slots__ = (
'basename',
'import_name',
'is_sdk',
'link_into',
'shared_name',
'static_name',
'soname',
'static_libraries',
'refcount',
)
@ -390,9 +412,10 @@ class BaseLibrary(SandboxDerived):
MAX_TYPE = 6
def __init__(self, sandbox, basename, kind=None, soname=None,
static_name=None, shared_name=None, is_sdk=False):
static_name=None, shared_name=None, is_sdk=False,
link_into=None):
assert(kind in range(1, self.MAX_TYPE))
SandboxDerived.__init__(self, sandbox)
Linkable.__init__(self, sandbox)
self.basename = basename
self.kind = kind
@ -432,20 +455,20 @@ class BaseLibrary(SandboxDerived):
else:
self.soname = self.shared_name
self.is_sdk = is_sdk
self.link_into = link_into
self.refcount = 0
self.static_libraries = []
def link_static_lib(self, objdir, basename):
self.static_libraries.append((objdir, basename))
class Library(BaseLibrary):
"""Sandbox container object for a library"""
KIND = 'target'
class HostLibrary(BaseLibrary):
"""Sandbox container object for a host library"""
KIND = 'host'
def __init__(self, sandbox, basename):
BaseLibrary.__init__(self, sandbox, basename,
kind=self.STATIC)

View File

@ -38,6 +38,7 @@ from .data import (
JARManifest,
JavaScriptModules,
Library,
LinkageWrongKindError,
LocalInclude,
PerSourceFlag,
PreprocessedTestWebIDLFile,
@ -86,9 +87,8 @@ class TreeMetadataEmitter(LoggingMixin):
k = k.encode('ascii')
self.info[k] = v
self._libs = OrderedDefaultDict(OrderedDict)
self._libs = OrderedDefaultDict(list)
self._binaries = OrderedDict()
self._final_libs = []
def emit(self, output):
"""Convert the BuildReader output into data structures.
@ -135,40 +135,45 @@ class TreeMetadataEmitter(LoggingMixin):
yield ReaderSummary(file_count, sandbox_execution_time, emitter_time)
def _emit_libs_derived(self, sandboxes):
for objdir, libname, final_lib in self._final_libs:
if final_lib not in self._libs:
for lib in (l for libs in self._libs.values() for l in libs):
if not lib.link_into:
continue
if lib.link_into not in self._libs:
raise Exception('FINAL_LIBRARY in %s (%s) does not match any '
'LIBRARY_NAME' % (objdir, final_lib))
libs = self._libs[final_lib]
if len(libs) > 1:
'LIBRARY_NAME' % (lib.objdir, lib.link_info))
candidates = self._libs[lib.link_into]
if len(candidates) > 1:
raise Exception('FINAL_LIBRARY in %s (%s) matches a '
'LIBRARY_NAME defined in multiple places (%s)' %
(objdir, final_lib, ', '.join(libs.keys())))
libs.values()[0].link_static_lib(objdir, libname)
self._libs[libname][objdir].refcount += 1
(lib.objdir, lib.link_into,
', '.join(l.objdir for l in candidates)))
# emit_from_sandbox ensures libraries with a FINAL_LIBRARY are
# static.
assert lib.KIND == 'target' and lib.kind == lib.STATIC
candidates[0].link_library(lib)
# The refcount can't go above 1 right now. It might in the future,
# but that will have to be specifically handled. At which point the
# refcount might have to be a list of referencees, for better error
# reporting.
assert self._libs[libname][objdir].refcount <= 1
assert lib.refcount <= 1
def recurse_libs(path, name):
for p, n in self._libs[name][path].static_libraries:
yield p
for q in recurse_libs(p, n):
def recurse_libs(lib):
for obj in lib.linked_libraries:
yield obj.objdir
for q in recurse_libs(obj):
yield q
for basename, libs in self._libs.items():
for path, libdef in libs.items():
# For all root libraries (i.e. libraries that don't have a
# FINAL_LIBRARY), record, for each static library it links
# (recursively), that its FINAL_LIBRARY is that root library.
if not libdef.refcount:
for p in recurse_libs(path, basename):
passthru = VariablePassthru(sandboxes[p])
passthru.variables['FINAL_LIBRARY'] = basename
yield passthru
yield libdef
for lib in (l for libs in self._libs.values() for l in libs):
# For all root libraries (i.e. libraries that don't have a
# FINAL_LIBRARY), record, for each static library it links
# (recursively), that its FINAL_LIBRARY is that root library.
if not lib.refcount:
for p in recurse_libs(lib):
passthru = VariablePassthru(sandboxes[p])
passthru.variables['FINAL_LIBRARY'] = lib.basename
yield passthru
yield lib
for obj in self._binaries.values():
yield obj
@ -391,8 +396,7 @@ class TreeMetadataEmitter(LoggingMixin):
if host_libname == libname:
raise SandboxValidationError('LIBRARY_NAME and '
'HOST_LIBRARY_NAME must have a different value', sandbox)
self._libs[host_libname][sandbox['OBJDIR']] = \
HostLibrary(sandbox, host_libname)
self._libs[host_libname].append(HostLibrary(sandbox, host_libname))
final_lib = sandbox.get('FINAL_LIBRARY')
if not libname and final_lib:
@ -410,6 +414,10 @@ class TreeMetadataEmitter(LoggingMixin):
soname = sandbox.get('SONAME')
args = {
'kind': 0,
}
if final_lib:
if isinstance(sandbox, MozbuildSandbox):
if static_lib:
@ -428,13 +436,10 @@ class TreeMetadataEmitter(LoggingMixin):
raise SandboxValidationError(
'FINAL_LIBRARY conflicts with IS_COMPONENT. '
'Please remove one.', sandbox)
self._final_libs.append((sandbox['OBJDIR'], libname, final_lib))
args['link_into'] = final_lib
static_lib = True
if libname:
args = {
'kind': 0,
}
if is_component:
if shared_lib:
raise SandboxValidationError(
@ -496,8 +501,7 @@ class TreeMetadataEmitter(LoggingMixin):
if sandbox.get('SDK_LIBRARY'):
args['is_sdk'] = True
self._libs[libname][sandbox['OBJDIR']] = \
Library(sandbox, libname, **args)
self._libs[libname].append(Library(sandbox, libname, **args))
# While there are multiple test manifests, the behavior is very similar