Bug 1419892 - Link programs and libraries in the tup backend. r=mshal

MozReview-Commit-ID: 26Yb0QdCn5H

--HG--
extra : rebase_source : 830253545964b14780fe5330fd33f1bd050a89ee
This commit is contained in:
Chris Manchester 2018-03-26 15:29:51 -07:00
Родитель bb69fe14b5
Коммит d4fc213fdc
1 изменённых файлов: 168 добавлений и 8 удалений

Просмотреть файл

@ -34,7 +34,11 @@ from ..frontend.data import (
JARManifest,
ObjdirFiles,
PerSourceFlag,
Program,
HostProgram,
SharedLibrary,
Sources,
StaticLibrary,
VariablePassthru,
)
from ..util import (
@ -62,11 +66,15 @@ class BackendTupfile(object):
self.defines = []
self.host_defines = []
self.delayed_generated_files = []
self.delayed_installed_files = []
self.per_source_flags = defaultdict(list)
self.local_flags = defaultdict(list)
self.sources = defaultdict(list)
self.host_sources = defaultdict(list)
self.variables = {}
self.static_lib = None
self.shared_lib = None
self.program = None
self.fh = FileAvoidWrite(self.name, capture_diff=True)
self.fh.write('# THIS FILE WAS AUTOMATICALLY GENERATED. DO NOT EDIT.\n')
@ -193,6 +201,18 @@ class TupOnly(CommonBackend, PartialBackend):
# in Tup. Express these as a group dependency.
self._early_generated_files = '$(MOZ_OBJ_ROOT)/<early-generated-files>'
# application.ini.h is a special case since we need to process
# the FINAL_TARGET_PP_FILES for application.ini before running
# the GENERATED_FILES script, and tup doesn't handle the rules
# out of order. Similarly, dependentlibs.list uses libxul as
# an input, so must be written after the rule for libxul.
self._delayed_files = (
'application.ini.h',
'dependentlibs.list',
'dependentlibs.list.gtest'
)
def _get_backend_file(self, relobjdir):
objdir = mozpath.normpath(mozpath.join(self.environment.topobjdir, relobjdir))
if objdir not in self._backend_files:
@ -212,6 +232,129 @@ class TupOnly(CommonBackend, PartialBackend):
]
return cmd
def _lib_paths(self, objdir, libs):
return [mozpath.relpath(mozpath.join(l.objdir, l.import_name), objdir)
for l in libs]
def _gen_shared_library(self, backend_file):
if backend_file.shared_lib.name == 'libxul.so':
# This will fail to link currently due to missing rust symbols.
return
if backend_file.shared_lib.cxx_link:
mkshlib = (
[backend_file.environment.substs['CXX']] +
backend_file.local_flags['CXX_LDFLAGS']
)
else:
mkshlib = (
[backend_file.environment.substs['CC']] +
backend_file.local_flags['C_LDFLAGS']
)
mkshlib += (
backend_file.environment.substs['DSO_PIC_CFLAGS'] +
[backend_file.environment.substs['DSO_LDOPTS']] +
['-Wl,-h,%s' % backend_file.shared_lib.soname] +
['-o', backend_file.shared_lib.lib_name]
)
objs, _, shared_libs, os_libs, static_libs = self._expand_libs(backend_file.shared_lib)
static_libs = self._lib_paths(backend_file.objdir, static_libs)
shared_libs = self._lib_paths(backend_file.objdir, shared_libs)
list_file_name = '%s.list' % backend_file.shared_lib.name.replace('.', '_')
list_file = self._make_list_file(backend_file.objdir, objs, list_file_name)
inputs = objs + static_libs + shared_libs
if any(i.endswith('libxul.so') for i in inputs):
# Don't attempt to link anything that depends on libxul.
return
symbols_file = []
if backend_file.shared_lib.symbols_file:
inputs.append(backend_file.shared_lib.symbols_file)
# TODO: Assumes GNU LD
symbols_file = ['-Wl,--version-script,%s' % backend_file.shared_lib.symbols_file]
cmd = (
mkshlib +
[list_file] +
backend_file.local_flags['LDFLAGS'] +
static_libs +
shared_libs +
symbols_file +
[backend_file.environment.substs['OS_LIBS']] +
os_libs
)
backend_file.rule(
cmd=cmd,
inputs=inputs,
outputs=[backend_file.shared_lib.lib_name],
display='LINK %o'
)
def _gen_program(self, backend_file):
cc_or_cxx = 'CXX' if backend_file.program.cxx_link else 'CC'
objs, _, shared_libs, os_libs, static_libs = self._expand_libs(backend_file.program)
static_libs = self._lib_paths(backend_file.objdir, static_libs)
shared_libs = self._lib_paths(backend_file.objdir, shared_libs)
inputs = objs + static_libs + shared_libs
if any(i.endswith('libxul.so') for i in inputs):
# Don't attempt to link anything that depends on libxul.
return
list_file_name = '%s.list' % backend_file.program.name.replace('.', '_')
list_file = self._make_list_file(backend_file.objdir, objs, list_file_name)
outputs = [mozpath.relpath(backend_file.program.output_path.full_path,
backend_file.objdir)]
cmd = (
[backend_file.environment.substs[cc_or_cxx], '-o', '%o'] +
backend_file.local_flags['CXX_LDFLAGS'] +
[list_file] +
backend_file.local_flags['LDFLAGS'] +
static_libs +
[backend_file.environment.substs['MOZ_PROGRAM_LDFLAGS']] +
shared_libs +
[backend_file.environment.substs['OS_LIBS']] +
os_libs
)
backend_file.rule(
cmd=cmd,
inputs=inputs,
outputs=outputs,
display='LINK %o'
)
def _gen_static_library(self, backend_file):
ar = [
backend_file.environment.substs['AR'],
backend_file.environment.substs['AR_FLAGS'].replace('$@', '%o')
]
objs, _, shared_libs, _, static_libs = self._expand_libs(backend_file.static_lib)
static_libs = self._lib_paths(backend_file.objdir, static_libs)
shared_libs = self._lib_paths(backend_file.objdir, shared_libs)
inputs = objs + static_libs
cmd = (
ar +
inputs
)
backend_file.rule(
cmd=cmd,
inputs=inputs,
outputs=[backend_file.static_lib.name],
display='AR %o'
)
def consume_object(self, obj):
"""Write out build files necessary to build with tup."""
@ -234,11 +377,7 @@ class TupOnly(CommonBackend, PartialBackend):
if any(mozpath.match(f, p) for p in skip_files):
return False
if 'application.ini.h' in obj.outputs:
# application.ini.h is a special case since we need to process
# the FINAL_TARGET_PP_FILES for application.ini before running
# the GENERATED_FILES script, and tup doesn't handle the rules
# out of order.
if any([f in obj.outputs for f in self._delayed_files]):
backend_file.delayed_generated_files.append(obj)
else:
self._process_generated_file(backend_file, obj)
@ -270,6 +409,14 @@ class TupOnly(CommonBackend, PartialBackend):
backend_file.host_sources[obj.canonical_suffix].extend(obj.files)
elif isinstance(obj, VariablePassthru):
backend_file.variables = obj.variables
elif isinstance(obj, StaticLibrary):
backend_file.static_lib = obj
elif isinstance(obj, SharedLibrary):
backend_file.shared_lib = obj
elif isinstance(obj, HostProgram):
pass
elif isinstance(obj, Program):
backend_file.program = obj
# The top-level Makefile.in still contains our driver target and some
# things related to artifact builds, so as a special case ensure the
@ -290,9 +437,18 @@ class TupOnly(CommonBackend, PartialBackend):
fh.write(''.join('%s\n' % e for e in sorted(entries)))
for objdir, backend_file in sorted(self._backend_files.items()):
backend_file.gen_sources_rules([self._installed_files])
for condition, gen_method in ((backend_file.shared_lib, self._gen_shared_library),
(backend_file.static_lib and backend_file.static_lib.no_expand_lib,
self._gen_static_library),
(backend_file.program, self._gen_program)):
if condition:
backend_file.export_shell()
gen_method(backend_file)
for obj in backend_file.delayed_generated_files:
self._process_generated_file(backend_file, obj)
backend_file.gen_sources_rules([self._installed_files])
for path, output in backend_file.delayed_installed_files:
backend_file.symlink_rule(path, output=output)
with self._write_file(fh=backend_file):
pass
@ -436,8 +592,12 @@ class TupOnly(CommonBackend, PartialBackend):
output = mozpath.join('$(MOZ_OBJ_ROOT)', target, path,
f.target_basename)
gen_backend_file = self._get_backend_file(f.context.relobjdir)
gen_backend_file.symlink_rule(f.full_path, output=output,
output_group=self._installed_files)
if f.target_basename in self._delayed_files:
gen_backend_file.delayed_installed_files.append((f.full_path, output))
else:
gen_backend_file.symlink_rule(f.full_path, output=output,
output_group=self._installed_files)
def _process_final_target_pp_files(self, obj, backend_file):
for i, (path, files) in enumerate(obj.files.walk()):