diff options
author | Matt A. Tobin <email@mattatobin.com> | 2021-11-20 21:15:14 -0500 |
---|---|---|
committer | Matt A. Tobin <email@mattatobin.com> | 2021-11-20 21:15:14 -0500 |
commit | c8761155bc5b7869cf10d76da68573567b58e035 (patch) | |
tree | 853ded0b335dc75b52a8ed4b1ac522344d598d5d /python | |
parent | 0309b34b339742e39dddc4d22e82e6c02ee480a3 (diff) | |
download | aura-central-c8761155bc5b7869cf10d76da68573567b58e035.tar.gz |
[NSS/GYP] Updates to handle NSS
Bug 1295937
Diffstat (limited to 'python')
-rw-r--r-- | python/mozbuild/mozbuild/frontend/context.py | 9 | ||||
-rw-r--r-- | python/mozbuild/mozbuild/frontend/gyp_reader.py | 214 | ||||
-rw-r--r-- | python/mozbuild/mozbuild/frontend/reader.py | 6 |
3 files changed, 182 insertions, 47 deletions
diff --git a/python/mozbuild/mozbuild/frontend/context.py b/python/mozbuild/mozbuild/frontend/context.py index f81665b52..7c44a6836 100644 --- a/python/mozbuild/mozbuild/frontend/context.py +++ b/python/mozbuild/mozbuild/frontend/context.py @@ -1567,7 +1567,10 @@ VARIABLES = { 'variables': dict, 'input': unicode, 'sandbox_vars': dict, + 'no_chromium': bool, + 'no_unified': bool, 'non_unified_sources': StrictOrderingOnAppendList, + 'action_overrides': dict, }), list, """Defines a list of object directories handled by gyp configurations. @@ -1582,9 +1585,15 @@ VARIABLES = { - sandbox_vars, a dictionary containing variables and values to pass to the mozbuild processor on top of those derived from gyp configuration. + - no_chromium, a boolean which if set to True disables some + special handling that emulates gyp_chromium. + - no_unified, a boolean which if set to True disables source + file unification entirely. - non_unified_sources, a list containing sources files, relative to the current moz.build, that should be excluded from source file unification. + - action_overrides, a dict of action_name to values of the `script` + attribute to use for GENERATED_FILES for the specified action. Typical use looks like: GYP_DIRS += ['foo', 'bar'] diff --git a/python/mozbuild/mozbuild/frontend/gyp_reader.py b/python/mozbuild/mozbuild/frontend/gyp_reader.py index 459c553c3..ef24c0dc4 100644 --- a/python/mozbuild/mozbuild/frontend/gyp_reader.py +++ b/python/mozbuild/mozbuild/frontend/gyp_reader.py @@ -5,6 +5,7 @@ from __future__ import absolute_import, unicode_literals import gyp +import gyp.msvs_emulation import sys import os import types @@ -12,6 +13,7 @@ import mozpack.path as mozpath from mozpack.files import FileFinder from .sandbox import alphabetical_sorted from .context import ( + ObjDirPath, SourcePath, TemplateContext, VARIABLES, @@ -38,13 +40,20 @@ chrome_src = mozpath.abspath(mozpath.join(mozpath.dirname(gyp.__file__), '../../../..')) script_dir = mozpath.join(chrome_src, 'build') + +def encode(value): + if isinstance(value, unicode): + return value.encode('utf-8') + return value + + # Default variables gyp uses when evaluating gyp files. generator_default_variables = { } -for dirname in ['INTERMEDIATE_DIR', 'SHARED_INTERMEDIATE_DIR', 'PRODUCT_DIR', - 'LIB_DIR', 'SHARED_LIB_DIR']: +for dirname in [b'INTERMEDIATE_DIR', b'SHARED_INTERMEDIATE_DIR', b'PRODUCT_DIR', + b'LIB_DIR', b'SHARED_LIB_DIR']: # Some gyp steps fail if these are empty(!). - generator_default_variables[dirname] = b'dir' + generator_default_variables[dirname] = b'$' + dirname for unused in ['RULE_INPUT_PATH', 'RULE_INPUT_ROOT', 'RULE_INPUT_NAME', 'RULE_INPUT_DIRNAME', 'RULE_INPUT_EXT', @@ -68,13 +77,37 @@ class GypContext(TemplateContext): allowed_variables=VARIABLES, config=config) -def encode(value): - if isinstance(value, unicode): - return value.encode('utf-8') - return value +def handle_actions(actions, context, action_overrides): + idir = '$INTERMEDIATE_DIR/' + for action in actions: + name = action['action_name'] + if name not in action_overrides: + raise RuntimeError('GYP action %s not listed in action_overrides' % name) + outputs = action['outputs'] + if len(outputs) > 1: + raise NotImplementedError('GYP actions with more than one output not supported: %s' % name) + output = outputs[0] + if not output.startswith(idir): + raise NotImplementedError('GYP actions outputting to somewhere other than <(INTERMEDIATE_DIR) not supported: %s' % output) + output = output[len(idir):] + context['GENERATED_FILES'] += [output] + g = context['GENERATED_FILES'][output] + g.script = action_overrides[name] + g.inputs = action['inputs'] +def handle_copies(copies, context): + dist = '$PRODUCT_DIR/dist/' + for copy in copies: + dest = copy['destination'] + if not dest.startswith(dist): + raise NotImplementedError('GYP copies to somewhere other than <(PRODUCT_DIR)/dist not supported: %s' % dest) + dest_paths = dest[len(dist):].split('/') + exports = context['EXPORTS'] + while dest_paths: + exports = getattr(exports, dest_paths.pop(0)) + exports += sorted(copy['files'], key=lambda x: x.lower()) -def read_from_gyp(config, path, output, vars, non_unified_sources = set()): +def read_from_gyp(config, path, output, vars, no_chromium, no_unified, action_overrides, non_unified_sources = set()): """Read a gyp configuration and emits GypContexts for the backend to process. @@ -84,10 +117,17 @@ def read_from_gyp(config, path, output, vars, non_unified_sources = set()): processor. """ + is_win = config.substs['OS_TARGET'] == 'WINNT' + is_msvc = bool(config.substs['_MSC_VER']) # gyp expects plain str instead of unicode. The frontend code gives us # unicode strings, so convert them. path = encode(path) str_vars = dict((name, encode(value)) for name, value in vars.items()) + if is_msvc: + # This isn't actually used anywhere in this generator, but it's needed + # to override the registry detection of VC++ in gyp. + os.environ['GYP_MSVS_OVERRIDE_PATH'] = 'fake_path' + os.environ['GYP_MSVS_VERSION'] = config.substs['MSVS_VERSION'] params = { b'parallel': False, @@ -96,18 +136,23 @@ def read_from_gyp(config, path, output, vars, non_unified_sources = set()): b'root_targets': None, } - # Files that gyp_chromium always includes - includes = [encode(mozpath.join(script_dir, 'common.gypi'))] - finder = FileFinder(chrome_src, find_executables=False) - includes.extend(encode(mozpath.join(chrome_src, name)) - for name, _ in finder.find('*/supplement.gypi')) + if no_chromium: + includes = [] + depth = mozpath.dirname(path) + else: + depth = chrome_src + # Files that gyp_chromium always includes + includes = [encode(mozpath.join(script_dir, 'common.gypi'))] + finder = FileFinder(chrome_src, find_executables=False) + includes.extend(encode(mozpath.join(chrome_src, name)) + for name, _ in finder.find('*/supplement.gypi')) # Read the given gyp file and its dependencies. generator, flat_list, targets, data = \ gyp.Load([path], format=b'mozbuild', default_variables=str_vars, includes=includes, - depth=encode(chrome_src), + depth=encode(depth), params=params) # Process all targets from the given gyp files and its dependencies. @@ -146,60 +191,134 @@ def read_from_gyp(config, path, output, vars, non_unified_sources = set()): 'in %s' % (c, target_name, build_file)) target_conf = spec['configurations'][c] + if 'actions' in spec: + handle_actions(spec['actions'], context, action_overrides) + if 'copies' in spec: + handle_copies(spec['copies'], context) + + use_libs = [] + libs = [] + def add_deps(s): + for t in s.get('dependencies', []) + s.get('dependencies_original', []): + ty = targets[t]['type'] + if ty in ('static_library', 'shared_library'): + use_libs.append(targets[t]['target_name']) + # Manually expand out transitive dependencies-- + # gyp won't do this for static libs or none targets. + if ty in ('static_library', 'none'): + add_deps(targets[t]) + libs.extend(spec.get('libraries', [])) + #XXX: this sucks, but webrtc breaks with this right now because + # it builds a library called 'gtest' and we just get lucky + # that it isn't in USE_LIBS by that name anywhere. + if no_chromium: + add_deps(spec) + + os_libs = [] + for l in libs: + if l.startswith('-'): + os_libs.append(l) + elif l.endswith('.lib'): + os_libs.append(l[:-4]) + elif l: + # For library names passed in from moz.build. + use_libs.append(os.path.basename(l)) + if spec['type'] == 'none': + if not ('actions' in spec or 'copies' in spec): continue - elif spec['type'] == 'static_library': + elif spec['type'] in ('static_library', 'shared_library', 'executable'): # Remove leading 'lib' from the target_name if any, and use as # library name. name = spec['target_name'] - if name.startswith('lib'): - name = name[3:] - # The context expects an unicode string. - context['LIBRARY_NAME'] = name.decode('utf-8') + if spec['type'] in ('static_library', 'shared_library'): + if name.startswith('lib'): + name = name[3:] + # The context expects an unicode string. + context['LIBRARY_NAME'] = name.decode('utf-8') + else: + context['PROGRAM'] = name.decode('utf-8') + if spec['type'] == 'shared_library': + context['FORCE_SHARED_LIB'] = True + elif spec['type'] == 'static_library' and spec.get('variables', {}).get('no_expand_libs', '0') == '1': + # PSM links a NSS static library, but our folded libnss + # doesn't actually export everything that all of the + # objects within would need, so that one library + # should be built as a real static library. + context['NO_EXPAND_LIBS'] = True + if use_libs: + context['USE_LIBS'] = sorted(use_libs, key=lambda s: s.lower()) + if os_libs: + context['OS_LIBS'] = os_libs # gyp files contain headers and asm sources in sources lists. sources = [] unified_sources = [] extensions = set() + use_defines_in_asflags = False for f in spec.get('sources', []): ext = mozpath.splitext(f)[-1] extensions.add(ext) - s = SourcePath(context, f) + if f.startswith('$INTERMEDIATE_DIR/'): + s = ObjDirPath(context, f.replace('$INTERMEDIATE_DIR/', '!')) + else: + s = SourcePath(context, f) if ext == '.h': continue - if ext != '.S' and s not in non_unified_sources: + if ext == '.def': + context['SYMBOLS_FILE'] = s + elif ext != '.S' and not no_unified and s not in non_unified_sources: unified_sources.append(s) else: sources.append(s) + # The Mozilla build system doesn't use DEFINES for building + # ASFILES. + if ext == '.s': + use_defines_in_asflags = True # The context expects alphabetical order when adding sources context['SOURCES'] = alphabetical_sorted(sources) context['UNIFIED_SOURCES'] = alphabetical_sorted(unified_sources) - for define in target_conf.get('defines', []): + defines = target_conf.get('defines', []) + if is_msvc and no_chromium: + msvs_settings = gyp.msvs_emulation.MsvsSettings(spec, {}) + defines.extend(msvs_settings.GetComputedDefines(c)) + for define in defines: if '=' in define: name, value = define.split('=', 1) context['DEFINES'][name] = value else: context['DEFINES'][define] = True + product_dir_dist = '$PRODUCT_DIR/dist/' for include in target_conf.get('include_dirs', []): - # moz.build expects all LOCAL_INCLUDES to exist, so ensure they do. - # - # NB: gyp files sometimes have actual absolute paths (e.g. - # /usr/include32) and sometimes paths that moz.build considers - # absolute, i.e. starting from topsrcdir. There's no good way - # to tell them apart here, and the actual absolute paths are - # likely bogus. In any event, actual absolute paths will be - # filtered out by trying to find them in topsrcdir. - if include.startswith('/'): - resolved = mozpath.abspath(mozpath.join(config.topsrcdir, include[1:])) + if include.startswith(product_dir_dist): + # special-case includes of <(PRODUCT_DIR)/dist/ to match + # handle_copies above. This is used for NSS' exports. + include = '!/dist/include/' + include[len(product_dir_dist):] + elif include.startswith(config.topobjdir): + # NSPR_INCLUDE_DIR gets passed into the NSS build this way. + include = '!/' + mozpath.relpath(include, config.topobjdir) else: - resolved = mozpath.abspath(mozpath.join(mozpath.dirname(build_file), include)) - if not os.path.exists(resolved): - continue + # moz.build expects all LOCAL_INCLUDES to exist, so ensure they do. + # + # NB: gyp files sometimes have actual absolute paths (e.g. + # /usr/include32) and sometimes paths that moz.build considers + # absolute, i.e. starting from topsrcdir. There's no good way + # to tell them apart here, and the actual absolute paths are + # likely bogus. In any event, actual absolute paths will be + # filtered out by trying to find them in topsrcdir. + if include.startswith('/'): + resolved = mozpath.abspath(mozpath.join(config.topsrcdir, include[1:])) + else: + resolved = mozpath.abspath(mozpath.join(mozpath.dirname(build_file), include)) + if not os.path.exists(resolved): + continue context['LOCAL_INCLUDES'] += [include] context['ASFLAGS'] = target_conf.get('asflags_mozilla', []) + if use_defines_in_asflags and defines: + context['ASFLAGS'] += ['-D' + d for d in defines] flags = target_conf.get('cflags_mozilla', []) if flags: suffix_map = { @@ -227,22 +346,23 @@ def read_from_gyp(config, path, output, vars, non_unified_sources = set()): else: context[var].extend(f) else: - # Ignore other types than static_library because we don't have + # Ignore other types because we don't have # anything using them, and we're not testing them. They can be # added when that becomes necessary. raise NotImplementedError('Unsupported gyp target type: %s' % spec['type']) - # Add some features to all contexts. Put here in case LOCAL_INCLUDES - # order matters. - context['LOCAL_INCLUDES'] += [ - '!/ipc/ipdl/_ipdlheaders', - '/ipc/chromium/src', - '/ipc/glue', - ] - # These get set via VC project file settings for normal GYP builds. - if config.substs['OS_TARGET'] == 'WINNT': - context['DEFINES']['UNICODE'] = True - context['DEFINES']['_UNICODE'] = True + if not no_chromium: + # Add some features to all contexts. Put here in case LOCAL_INCLUDES + # order matters. + context['LOCAL_INCLUDES'] += [ + '!/ipc/ipdl/_ipdlheaders', + '/ipc/chromium/src', + '/ipc/glue', + ] + # These get set via VC project file settings for normal GYP builds. + if is_win: + context['DEFINES']['UNICODE'] = True + context['DEFINES']['_UNICODE'] = True context['DISABLE_STL_WRAPPING'] = True yield context diff --git a/python/mozbuild/mozbuild/frontend/reader.py b/python/mozbuild/mozbuild/frontend/reader.py index a7d7e8b71..165a8b711 100644 --- a/python/mozbuild/mozbuild/frontend/reader.py +++ b/python/mozbuild/mozbuild/frontend/reader.py @@ -1128,12 +1128,18 @@ class BuildReader(object): raise SandboxValidationError('Cannot find %s.' % source, context) non_unified_sources.add(source) + action_overrides = {} + for action, script in gyp_dir.action_overrides.iteritems(): + action_overrides[action] = SourcePath(context, script) time_start = time.time() for gyp_context in read_from_gyp(context.config, mozpath.join(curdir, gyp_dir.input), mozpath.join(context.objdir, target_dir), gyp_dir.variables, + gyp_dir.no_chromium, + gyp_dir.no_unified, + action_overrides, non_unified_sources = non_unified_sources): gyp_context.update(gyp_dir.sandbox_vars) gyp_contexts.append(gyp_context) |