Merge pull request #4293 from marcelhollerbach/master

Performance optimize the install part generation
pull/4203/head
Jussi Pakkanen 6 years ago committed by GitHub
commit 88054c48a6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 57
      mesonbuild/backend/backends.py
  2. 68
      mesonbuild/build.py

@ -27,9 +27,6 @@ from collections import OrderedDict
import shlex
from functools import lru_cache
@lru_cache(maxsize=None)
def get_target_macos_dylib_install_name(ld):
return get_macos_dylib_install_name(ld.prefix, ld.name, ld.suffix, ld.soversion)
class CleanTrees:
@ -970,61 +967,11 @@ class Backend:
with open(install_data_file, 'wb') as ofile:
pickle.dump(d, ofile)
def get_target_install_dirs(self, t):
# Find the installation directory.
if isinstance(t, build.SharedModule):
default_install_dir = self.environment.get_shared_module_dir()
elif isinstance(t, build.SharedLibrary):
default_install_dir = self.environment.get_shared_lib_dir()
elif isinstance(t, build.StaticLibrary):
default_install_dir = self.environment.get_static_lib_dir()
elif isinstance(t, build.Executable):
default_install_dir = self.environment.get_bindir()
elif isinstance(t, build.CustomTarget):
default_install_dir = None
else:
assert(isinstance(t, build.BuildTarget))
# XXX: Add BuildTarget-specific install dir cases here
default_install_dir = self.environment.get_libdir()
outdirs = t.get_custom_install_dir()
if outdirs[0] is not None and outdirs[0] != default_install_dir and outdirs[0] is not True:
# Either the value is set to a non-default value, or is set to
# False (which means we want this specific output out of many
# outputs to not be installed).
custom_install_dir = True
else:
custom_install_dir = False
outdirs[0] = default_install_dir
return outdirs, custom_install_dir
def get_target_link_deps_mappings(self, t, prefix):
'''
On macOS, we need to change the install names of all built libraries
that a target depends on using install_name_tool so that the target
continues to work after installation. For this, we need a dictionary
mapping of the install_name value to the new one, so we can change them
on install.
'''
result = {}
if isinstance(t, build.StaticLibrary):
return result
for ld in t.get_all_link_deps():
if ld is t or not isinstance(ld, build.SharedLibrary):
continue
old = get_target_macos_dylib_install_name(ld)
if old in result:
continue
fname = ld.get_filename()
outdirs, _ = self.get_target_install_dirs(ld)
new = os.path.join(prefix, outdirs[0], fname)
result.update({old: new})
return result
def generate_target_install(self, d):
for t in self.build.get_targets().values():
if not t.should_install():
continue
outdirs, custom_install_dir = self.get_target_install_dirs(t)
outdirs, custom_install_dir = t.get_install_dir(self.environment)
# Sanity-check the outputs and install_dirs
num_outdirs, num_out = len(outdirs), len(t.get_outputs())
if num_outdirs != 1 and num_outdirs != num_out:
@ -1039,7 +986,7 @@ class Backend:
# Install primary build output (library/executable/jar, etc)
# Done separately because of strip/aliases/rpath
if outdirs[0] is not False:
mappings = self.get_target_link_deps_mappings(t, d.prefix)
mappings = t.get_link_deps_mapping(d.prefix, self.environment)
i = TargetInstallData(self.get_target_filename(t), outdirs[0],
t.get_aliases(), should_strip, mappings,
t.install_rpath, install_mode)

@ -25,7 +25,7 @@ from .mesonlib import File, MesonException, listify, extract_as_list, OrderedSet
from .mesonlib import typeslistify, stringlistify, classify_unity_sources
from .mesonlib import get_filenames_templates_dict, substitute_values
from .mesonlib import for_windows, for_darwin, for_cygwin, for_android, has_path_sep
from .compilers import is_object, clink_langs, sort_clink, lang_suffixes
from .compilers import is_object, clink_langs, sort_clink, lang_suffixes, get_macos_dylib_install_name
from .interpreterbase import FeatureNew
pch_kwargs = set(['c_pch', 'cpp_pch'])
@ -90,6 +90,10 @@ known_shmod_kwargs = known_build_target_kwargs
known_stlib_kwargs = known_build_target_kwargs | {'pic'}
known_jar_kwargs = known_exe_kwargs | {'main_class'}
@lru_cache(maxsize=None)
def get_target_macos_dylib_install_name(ld):
return get_macos_dylib_install_name(ld.prefix, ld.name, ld.suffix, ld.soversion)
class InvalidArguments(MesonException):
pass
@ -325,6 +329,20 @@ a hard error in the future.''' % name)
self.build_always_stale = False
self.option_overrides = {}
def get_install_dir(self, environment):
# Find the installation directory.
default_install_dir = self.get_default_install_dir(environment)
outdirs = self.get_custom_install_dir()
if outdirs[0] is not None and outdirs[0] != default_install_dir and outdirs[0] is not True:
# Either the value is set to a non-default value, or is set to
# False (which means we want this specific output out of many
# outputs to not be installed).
custom_install_dir = True
else:
custom_install_dir = False
outdirs[0] = default_install_dir
return outdirs, custom_install_dir
def get_basename(self):
return self.name
@ -679,6 +697,20 @@ class BuildTarget(Target):
result += i.get_all_link_deps()
return result
def get_link_deps_mapping(self, prefix, environment):
return self.get_transitive_link_deps_mapping(prefix, environment)
@lru_cache(maxsize=None)
def get_transitive_link_deps_mapping(self, prefix, environment):
result = {}
for i in self.link_targets:
mapping = i.get_link_deps_mapping(prefix, environment)
#we are merging two dictionaries, while keeping the earlier one dominant
result_tmp = mapping.copy()
result_tmp.update(result)
result = result_tmp
return result
@lru_cache(maxsize=None)
def get_link_dep_subdirs(self):
result = OrderedSet()
@ -687,6 +719,9 @@ class BuildTarget(Target):
result.update(i.get_link_dep_subdirs())
return result
def get_default_install_dir(self, environment):
return environment.get_libdir()
def get_custom_install_dir(self):
return self.install_dir
@ -1327,6 +1362,9 @@ class Executable(BuildTarget):
# Only linkwithable if using export_dynamic
self.is_linkwithable = self.export_dynamic
def get_default_install_dir(self, environment):
return environment.get_bindir()
def description(self):
'''Human friendly description of the executable'''
return self.name
@ -1388,6 +1426,12 @@ class StaticLibrary(BuildTarget):
self.filename = self.prefix + self.name + '.' + self.suffix
self.outputs = [self.filename]
def get_link_deps_mapping(self, prefix, environment):
return {}
def get_default_install_dir(self, environment):
return environment.get_static_lib_dir()
def type_suffix(self):
return "@sta"
@ -1434,6 +1478,21 @@ class SharedLibrary(BuildTarget):
self.basic_filename_tpl = '{0.prefix}{0.name}.{0.suffix}'
self.determine_filenames(is_cross, environment)
def get_link_deps_mapping(self, prefix, environment):
result = {}
mappings = self.get_transitive_link_deps_mapping(prefix, environment)
old = get_target_macos_dylib_install_name(self)
if old not in mappings:
fname = self.get_filename()
outdirs, _ = self.get_install_dir(self.environment)
new = os.path.join(prefix, outdirs[0], fname)
result.update({old: new})
mappings.update(result)
return mappings
def get_default_install_dir(self, environment):
return environment.get_shared_lib_dir()
def determine_filenames(self, is_cross, env):
"""
See https://github.com/mesonbuild/meson/pull/417 for details.
@ -1705,6 +1764,10 @@ class SharedModule(SharedLibrary):
raise MesonException('Shared modules must not specify the soversion kwarg.')
super().__init__(name, subdir, subproject, is_cross, sources, objects, environment, kwargs)
def get_default_install_dir(self, environment):
return environment.get_shared_module_dir()
class CustomTarget(Target):
known_kwargs = set([
'input',
@ -1742,6 +1805,9 @@ class CustomTarget(Target):
mlog.warning('Unknown keyword arguments in target %s: %s' %
(self.name, ', '.join(unknowns)))
def get_default_install_dir(self, environment):
return None
def __lt__(self, other):
return self.get_id() < other.get_id()

Loading…
Cancel
Save