mirror of
https://repo.dactyloidae.xyz/Dactyloidae/UXP.git
synced 2026-08-23 04:43:07 +09:00
248 lines
10 KiB
Python
248 lines
10 KiB
Python
# This Source Code Form is subject to the terms of the Mozilla Public
|
|
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
|
|
from __future__ import absolute_import, unicode_literals
|
|
|
|
import gyp
|
|
import sys
|
|
import os
|
|
import types
|
|
import mozpack.path as mozpath
|
|
from mozpack.files import FileFinder
|
|
from .sandbox import alphabetical_sorted
|
|
from .context import (
|
|
SourcePath,
|
|
TemplateContext,
|
|
VARIABLES,
|
|
)
|
|
from mozbuild.util import (
|
|
expand_variables,
|
|
List,
|
|
memoize,
|
|
)
|
|
from .reader import SandboxValidationError
|
|
|
|
# Define this module as gyp.generator.mozbuild so that gyp can use it
|
|
# as a generator under the name "mozbuild".
|
|
sys.modules['gyp.generator.mozbuild'] = sys.modules[__name__]
|
|
|
|
# build/gyp_chromium does this:
|
|
# script_dir = os.path.dirname(os.path.realpath(__file__))
|
|
# chrome_src = os.path.abspath(os.path.join(script_dir, os.pardir))
|
|
# sys.path.insert(0, os.path.join(chrome_src, 'tools', 'gyp', 'pylib'))
|
|
# We're not importing gyp_chromium, but we want both script_dir and
|
|
# chrome_src for the default includes, so go backwards from the pylib
|
|
# directory, which is the parent directory of gyp module.
|
|
chrome_src = mozpath.abspath(mozpath.join(mozpath.dirname(gyp.__file__),
|
|
'../../../..'))
|
|
script_dir = mozpath.join(chrome_src, 'build')
|
|
|
|
# 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']:
|
|
# Some gyp steps fail if these are empty(!).
|
|
generator_default_variables[dirname] = b'dir'
|
|
|
|
for unused in ['RULE_INPUT_PATH', 'RULE_INPUT_ROOT', 'RULE_INPUT_NAME',
|
|
'RULE_INPUT_DIRNAME', 'RULE_INPUT_EXT',
|
|
'EXECUTABLE_PREFIX', 'EXECUTABLE_SUFFIX',
|
|
'STATIC_LIB_PREFIX', 'STATIC_LIB_SUFFIX',
|
|
'SHARED_LIB_PREFIX', 'SHARED_LIB_SUFFIX',
|
|
'LINKER_SUPPORTS_ICF']:
|
|
generator_default_variables[unused] = b''
|
|
|
|
|
|
class GypContext(TemplateContext):
|
|
"""Specialized Context for use with data extracted from Gyp.
|
|
|
|
config is the ConfigEnvironment for this context.
|
|
relobjdir is the object directory that will be used for this context,
|
|
relative to the topobjdir defined in the ConfigEnvironment.
|
|
"""
|
|
def __init__(self, config, relobjdir):
|
|
self._relobjdir = relobjdir
|
|
TemplateContext.__init__(self, template='Gyp',
|
|
allowed_variables=VARIABLES, config=config)
|
|
|
|
|
|
def encode(value):
|
|
if isinstance(value, unicode):
|
|
return value.encode('utf-8')
|
|
return value
|
|
|
|
|
|
def read_from_gyp(config, path, output, vars, non_unified_sources = set()):
|
|
"""Read a gyp configuration and emits GypContexts for the backend to
|
|
process.
|
|
|
|
config is a ConfigEnvironment, path is the path to a root gyp configuration
|
|
file, output is the base path under which the objdir for the various gyp
|
|
dependencies will be, and vars a dict of variables to pass to the gyp
|
|
processor.
|
|
"""
|
|
|
|
# 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())
|
|
|
|
params = {
|
|
b'parallel': False,
|
|
b'generator_flags': {},
|
|
b'build_files': [path],
|
|
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'))
|
|
|
|
# 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),
|
|
params=params)
|
|
|
|
# Process all targets from the given gyp files and its dependencies.
|
|
# The path given to AllTargets needs to use os.sep, while the frontend code
|
|
# gives us paths normalized with forward slash separator.
|
|
for target in gyp.common.AllTargets(flat_list, targets, path.replace(b'/', os.sep)):
|
|
build_file, target_name, toolset = gyp.common.ParseQualifiedTarget(target)
|
|
|
|
# Each target is given its own objdir. The base of that objdir
|
|
# is derived from the relative path from the root gyp file path
|
|
# to the current build_file, placed under the given output
|
|
# directory. Since several targets can be in a given build_file,
|
|
# separate them in subdirectories using the build_file basename
|
|
# and the target_name.
|
|
reldir = mozpath.relpath(mozpath.dirname(build_file),
|
|
mozpath.dirname(path))
|
|
subdir = '%s_%s' % (
|
|
mozpath.splitext(mozpath.basename(build_file))[0],
|
|
target_name,
|
|
)
|
|
# Emit a context for each target.
|
|
context = GypContext(config, mozpath.relpath(
|
|
mozpath.join(output, reldir, subdir), config.topobjdir))
|
|
context.add_source(mozpath.abspath(build_file))
|
|
# The list of included files returned by gyp are relative to build_file
|
|
for f in data[build_file]['included_files']:
|
|
context.add_source(mozpath.abspath(mozpath.join(
|
|
mozpath.dirname(build_file), f)))
|
|
|
|
spec = targets[target]
|
|
|
|
# Derive which gyp configuration to use based on MOZ_DEBUG.
|
|
c = 'Debug' if config.substs['MOZ_DEBUG'] else 'Release'
|
|
if c not in spec['configurations']:
|
|
raise RuntimeError('Missing %s gyp configuration for target %s '
|
|
'in %s' % (c, target_name, build_file))
|
|
target_conf = spec['configurations'][c]
|
|
|
|
if spec['type'] == 'none':
|
|
continue
|
|
elif spec['type'] == 'static_library':
|
|
# 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')
|
|
# gyp files contain headers and asm sources in sources lists.
|
|
sources = []
|
|
unified_sources = []
|
|
extensions = set()
|
|
for f in spec.get('sources', []):
|
|
ext = mozpath.splitext(f)[-1]
|
|
extensions.add(ext)
|
|
s = SourcePath(context, f)
|
|
if ext == '.h':
|
|
continue
|
|
if ext != '.S' and s not in non_unified_sources:
|
|
unified_sources.append(s)
|
|
else:
|
|
sources.append(s)
|
|
|
|
# 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', []):
|
|
if '=' in define:
|
|
name, value = define.split('=', 1)
|
|
context['DEFINES'][name] = value
|
|
else:
|
|
context['DEFINES'][define] = True
|
|
|
|
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:]))
|
|
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', [])
|
|
flags = target_conf.get('cflags_mozilla', [])
|
|
if flags:
|
|
suffix_map = {
|
|
'.c': 'CFLAGS',
|
|
'.cpp': 'CXXFLAGS',
|
|
'.cc': 'CXXFLAGS',
|
|
'.m': 'CMFLAGS',
|
|
'.mm': 'CMMFLAGS',
|
|
}
|
|
variables = (
|
|
suffix_map[e]
|
|
for e in extensions if e in suffix_map
|
|
)
|
|
for var in variables:
|
|
for f in flags:
|
|
# We may be getting make variable references out of the
|
|
# gyp data, and we don't want those in emitted data, so
|
|
# substitute them with their actual value.
|
|
f = expand_variables(f, config.substs).split()
|
|
if not f:
|
|
continue
|
|
# the result may be a string or a list.
|
|
if isinstance(f, types.StringTypes):
|
|
context[var].append(f)
|
|
else:
|
|
context[var].extend(f)
|
|
else:
|
|
# Ignore other types than static_library 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
|
|
context['DISABLE_STL_WRAPPING'] = True
|
|
|
|
yield context
|