parameters: (self, context)
docstring: Convert a Context to tree metadata objects.
  
          This is a generator of mozbuild.frontend.data.ContextDerived instances.
docstring_summary: Convert a Context to tree metadata objects.
docstring_tokens: Convert a Context to tree metadata objects .
function: def emit_from_context(self, context):
          """Convert a Context to tree metadata objects.
  
          This is a generator of mozbuild.frontend.data.ContextDerived instances.
          """
  
          # We only want to emit an InstallationTarget if one of the consulted
          # variables is defined. Later on, we look up FINAL_TARGET, which has
          # the side-effect of populating it. So, we need to do this lookup
          # early.
          if any(k in context for k in ('FINAL_TARGET', 'XPI_NAME', 'DIST_SUBDIR')):
              yield InstallationTarget(context)
  
          # We always emit a directory traversal descriptor. This is needed by
          # the recursive make backend.
          for o in self._emit_directory_traversal_from_context(context): yield o
  
          for path in context['CONFIGURE_SUBST_FILES']:
              yield self._create_substitution(ConfigFileSubstitution, context,
                  path)
  
          for path in context['CONFIGURE_DEFINE_FILES']:
              yield self._create_substitution(HeaderFileSubstitution, context,
                  path)
  
          # XPIDL source files get processed and turned into .h and .xpt files.
          # If there are multiple XPIDL files in a directory, they get linked
          # together into a final .xpt, which has the name defined by
          # XPIDL_MODULE.
          xpidl_module = context['XPIDL_MODULE']
  
          if context['XPIDL_SOURCES'] and not xpidl_module:
              raise SandboxValidationError('XPIDL_MODULE must be defined if '
                  'XPIDL_SOURCES is defined.', context)
  
          if xpidl_module and not context['XPIDL_SOURCES']:
              raise SandboxValidationError('XPIDL_MODULE cannot be defined '
                  'unless there are XPIDL_SOURCES', context)
  
          if context['XPIDL_SOURCES'] and context['NO_DIST_INSTALL']:
              self.log(logging.WARN, 'mozbuild_warning', dict(
                  path=context.main_path),
                  '{path}: NO_DIST_INSTALL has no effect on XPIDL_SOURCES.')
  
          for idl in context['XPIDL_SOURCES']:
              yield XPIDLFile(context, mozpath.join(context.srcdir, idl),
                  xpidl_module)
  
          for symbol in ('SOURCES', 'HOST_SOURCES', 'UNIFIED_SOURCES'):
              for src in (context[symbol] or []):
                  if not os.path.exists(mozpath.join(context.srcdir, src)):
                      raise SandboxValidationError('File listed in %s does not '
                          'exist: \'%s\'' % (symbol, src), context)
  
          # Proxy some variables as-is until we have richer classes to represent
          # them. We should aim to keep this set small because it violates the
          # desired abstraction of the build definition away from makefiles.
          passthru = VariablePassthru(context)
          varlist = [
              'ANDROID_GENERATED_RESFILES',
              'ANDROID_RES_DIRS',
              'DISABLE_STL_WRAPPING',
              'EXTRA_ASSEMBLER_FLAGS',
              'EXTRA_COMPILE_FLAGS',
              'EXTRA_COMPONENTS',
              'EXTRA_DSO_LDOPTS',
              'EXTRA_PP_COMPONENTS',
              'FAIL_ON_WARNINGS',
              'USE_STATIC_LIBS',
              'IS_GYP_DIR',
              'MSVC_ENABLE_PGO',
              'NO_DIST_INSTALL',
              'PYTHON_UNIT_TESTS',
              'RCFILE',
              'RESFILE',
              'RCINCLUDE',
              'DEFFILE',
              'WIN32_EXE_LDFLAGS',
              'LD_VERSION_SCRIPT',
          ]
          for v in varlist:
              if v in context and context[v]:
                  passthru.variables[v] = context[v]
  
          if context.config.substs.get('OS_TARGET') == 'WINNT' and \
                  context['DELAYLOAD_DLLS']:
              context['LDFLAGS'].extend([('-DELAYLOAD:%s' % dll)
                  for dll in context['DELAYLOAD_DLLS']])
              context['OS_LIBS'].append('delayimp')
  
          for v in ['CFLAGS', 'CXXFLAGS', 'CMFLAGS', 'CMMFLAGS', 'LDFLAGS']:
              if v in context and context[v]:
                  passthru.variables['MOZBUILD_' + v] = context[v]
  
          # NO_VISIBILITY_FLAGS is slightly different
          if context['NO_VISIBILITY_FLAGS']:
              passthru.variables['VISIBILITY_FLAGS'] = ''
  
          no_pgo = context.get('NO_PGO')
          sources = context.get('SOURCES', [])
          no_pgo_sources = [f for f in sources if sources[f].no_pgo]
          if no_pgo:
              if no_pgo_sources:
                  raise SandboxValidationError('NO_PGO and SOURCES[...].no_pgo '
                      'cannot be set at the same time', context)
              passthru.variables['NO_PROFILE_GUIDED_OPTIMIZE'] = no_pgo
          if no_pgo_sources:
              passthru.variables['NO_PROFILE_GUIDED_OPTIMIZE'] = no_pgo_sources
  
          # A map from "canonical suffixes" for a particular source file
          # language to the range of suffixes associated with that language.
          #
          # We deliberately don't list the canonical suffix in the suffix list
          # in the definition; we'll add it in programmatically after defining
          # things.
          suffix_map = {
              '.s': set(['.asm']),
              '.c': set(),
              '.m': set(),
              '.mm': set(),
              '.cpp': set(['.cc', '.cxx']),
              '.S': set(),
          }
  
          # The inverse of the above, mapping suffixes to their canonical suffix.
          canonicalized_suffix_map = {}
          for suffix, alternatives in suffix_map.iteritems():
              alternatives.add(suffix)
              for a in alternatives:
                  canonicalized_suffix_map[a] = suffix
  
          def canonical_suffix_for_file(f):
              return canonicalized_suffix_map[mozpath.splitext(f)[1]]
  
          # A map from moz.build variables to the canonical suffixes of file
          # kinds that can be listed therein.
          all_suffixes = list(suffix_map.keys())
          varmap = dict(
              SOURCES=(Sources, all_suffixes),
              HOST_SOURCES=(HostSources, ['.c', '.mm', '.cpp']),
              UNIFIED_SOURCES=(UnifiedSources, ['.c', '.mm', '.cpp']),
              GENERATED_SOURCES=(GeneratedSources, all_suffixes),
          )
  
          for variable, (klass, suffixes) in varmap.items():
              allowed_suffixes = set().union(*[suffix_map[s] for s in suffixes])
  
              # First ensure that we haven't been given filetypes that we don't
              # recognize.
              for f in context[variable]:
                  ext = mozpath.splitext(f)[1]
                  if ext not in allowed_suffixes:
                      raise SandboxValidationError(
                          '%s has an unknown file type.' % f, context)
                  if variable.startswith('GENERATED_'):
                      l = passthru.variables.setdefault('GARBAGE', [])
                      l.append(f)
  
              # Now sort the files to let groupby work.
              sorted_files = sorted(context[variable], key=canonical_suffix_for_file)
              for canonical_suffix, files in itertools.groupby(sorted_files, canonical_suffix_for_file):
                  arglist = [context, list(files), canonical_suffix]
                  if variable.startswith('UNIFIED_') and 'FILES_PER_UNIFIED_FILE' in context:
                      arglist.append(context['FILES_PER_UNIFIED_FILE'])
                  yield klass(*arglist)
  
          sources_with_flags = [f for f in sources if sources[f].flags]
          for f in sources_with_flags:
              ext = mozpath.splitext(f)[1]
              yield PerSourceFlag(context, f, sources[f].flags)
  
          exports = context.get('EXPORTS')
          if exports:
              yield Exports(context, exports,
                  dist_install=not context.get('NO_DIST_INSTALL', False))
  
          generated_files = context.get('GENERATED_FILES')
          if generated_files:
              for f in generated_files:
                  flags = generated_files[f]
                  output = f
                  if flags.script:
                      script = mozpath.join(context.srcdir, flags.script)
                      inputs = [mozpath.join(context.srcdir, i) for i in flags.inputs]
  
                      if not os.path.exists(script):
                          raise SandboxValidationError(
                              'Script for generating %s does not exist: %s'
                              % (f, script), context)
                      if os.path.splitext(script)[1] != '.py':
                          raise SandboxValidationError(
                              'Script for generating %s does not end in .py: %s'
                              % (f, script), context)
                      for i in inputs:
                          if not os.path.exists(i):
                              raise SandboxValidationError(
                                  'Input for generating %s does not exist: %s'
                                  % (f, i), context)
                  else:
                      script = None
                      inputs = []
                  yield GeneratedFile(context, script, output, inputs)
  
          test_harness_files = context.get('TEST_HARNESS_FILES')
          if test_harness_files:
              srcdir_files = defaultdict(list)
              srcdir_pattern_files = defaultdict(list)
              objdir_files = defaultdict(list)
  
              for path, strings in test_harness_files.walk():
                  if not path and strings:
                      raise SandboxValidationError(
                          'Cannot install files to the root of TEST_HARNESS_FILES', context)
  
                  for s in strings:
                      if context.is_objdir_path(s):
                          if s.startswith('!/'):
                              objdir_files[path].append('$(DEPTH)/%s' % s[2:])
                          else:
                              objdir_files[path].append(s[1:])
                      else:
                          resolved = context.resolve_path(s)
                          if '*' in s:
                              srcdir_pattern_files[path].append(s);
                          elif not os.path.exists(resolved):
                              raise SandboxValidationError(
                                  'File listed in TEST_HARNESS_FILES does not exist: %s' % s, context)
                          else:
                              srcdir_files[path].append(resolved)
  
              yield TestHarnessFiles(context, srcdir_files,
                                     srcdir_pattern_files, objdir_files)
  
          defines = context.get('DEFINES')
          if defines:
              yield Defines(context, defines)
  
          resources = context.get('RESOURCE_FILES')
          if resources:
              yield Resources(context, resources, defines)
  
          for pref in sorted(context['JS_PREFERENCE_FILES']):
              yield JsPreferenceFile(context, pref)
  
          for kind, cls in [('PROGRAM', Program), ('HOST_PROGRAM', HostProgram)]:
              program = context.get(kind)
              if program:
                  if program in self._binaries:
                      raise SandboxValidationError(
                          'Cannot use "%s" as %s name, '
                          'because it is already used in %s' % (program, kind,
                          self._binaries[program].relativedir), context)
                  self._binaries[program] = cls(context, program)
                  self._linkage.append((context, self._binaries[program],
                      kind.replace('PROGRAM', 'USE_LIBS')))
  
          for kind, cls in [
                  ('SIMPLE_PROGRAMS', SimpleProgram),
                  ('CPP_UNIT_TESTS', SimpleProgram),
                  ('HOST_SIMPLE_PROGRAMS', HostSimpleProgram)]:
              for program in context[kind]:
                  if program in self._binaries:
                      raise SandboxValidationError(
                          'Cannot use "%s" in %s, '
                          'because it is already used in %s' % (program, kind,
                          self._binaries[program].relativedir), context)
                  self._binaries[program] = cls(context, program,
                      is_unit_test=kind == 'CPP_UNIT_TESTS')
                  self._linkage.append((context, self._binaries[program],
                      'HOST_USE_LIBS' if kind == 'HOST_SIMPLE_PROGRAMS'
                      else 'USE_LIBS'))
  
          extra_js_modules = context.get('EXTRA_JS_MODULES')
          if extra_js_modules:
              yield JavaScriptModules(context, extra_js_modules, 'extra')
  
          extra_pp_js_modules = context.get('EXTRA_PP_JS_MODULES')
          if extra_pp_js_modules:
              yield JavaScriptModules(context, extra_pp_js_modules, 'extra_pp')
  
          test_js_modules = context.get('TESTING_JS_MODULES')
          if test_js_modules:
              yield JavaScriptModules(context, test_js_modules, 'testing')
  
          simple_lists = [
              ('GENERATED_EVENTS_WEBIDL_FILES', GeneratedEventWebIDLFile),
              ('GENERATED_WEBIDL_FILES', GeneratedWebIDLFile),
              ('IPDL_SOURCES', IPDLFile),
              ('GENERATED_INCLUDES', GeneratedInclude),
              ('PREPROCESSED_TEST_WEBIDL_FILES', PreprocessedTestWebIDLFile),
              ('PREPROCESSED_WEBIDL_FILES', PreprocessedWebIDLFile),
              ('TEST_WEBIDL_FILES', TestWebIDLFile),
              ('WEBIDL_FILES', WebIDLFile),
              ('WEBIDL_EXAMPLE_INTERFACES', ExampleWebIDLInterface),
          ]
          for context_var, klass in simple_lists:
              for name in context.get(context_var, []):
                  yield klass(context, name)
  
          for local_include in context.get('LOCAL_INCLUDES', []):
              if local_include.startswith('/'):
                  path = context.config.topsrcdir
                  relative_include = local_include[1:]
              else:
                  path = context.srcdir
                  relative_include = local_include
  
              actual_include = os.path.join(path, relative_include)
              if not os.path.exists(actual_include):
                  raise SandboxValidationError('Path specified in LOCAL_INCLUDES '
                      'does not exist: %s (resolved to %s)' % (local_include, actual_include), context)
              yield LocalInclude(context, local_include)
  
          final_target_files = context.get('FINAL_TARGET_FILES')
          if final_target_files:
              yield FinalTargetFiles(context, final_target_files, context['FINAL_TARGET'])
  
          host_libname = context.get('HOST_LIBRARY_NAME')
          libname = context.get('LIBRARY_NAME')
  
          if host_libname:
              if host_libname == libname:
                  raise SandboxValidationError('LIBRARY_NAME and '
                      'HOST_LIBRARY_NAME must have a different value', context)
              lib = HostLibrary(context, host_libname)
              self._libs[host_libname].append(lib)
              self._linkage.append((context, lib, 'HOST_USE_LIBS'))
  
          final_lib = context.get('FINAL_LIBRARY')
          if not libname and final_lib:
              # If no LIBRARY_NAME is given, create one.
              libname = context.relsrcdir.replace('/', '_')
  
          static_lib = context.get('FORCE_STATIC_LIB')
          shared_lib = context.get('FORCE_SHARED_LIB')
  
          static_name = context.get('STATIC_LIBRARY_NAME')
          shared_name = context.get('SHARED_LIBRARY_NAME')
  
          is_framework = context.get('IS_FRAMEWORK')
          is_component = context.get('IS_COMPONENT')
  
          soname = context.get('SONAME')
  
          lib_defines = context.get('LIBRARY_DEFINES')
  
          shared_args = {}
          static_args = {}
  
          if final_lib:
              if static_lib:
                  raise SandboxValidationError(
                      'FINAL_LIBRARY implies FORCE_STATIC_LIB. '
                      'Please remove the latter.', context)
              if shared_lib:
                  raise SandboxValidationError(
                      'FINAL_LIBRARY conflicts with FORCE_SHARED_LIB. '
                      'Please remove one.', context)
              if is_framework:
                  raise SandboxValidationError(
                      'FINAL_LIBRARY conflicts with IS_FRAMEWORK. '
                      'Please remove one.', context)
              if is_component:
                  raise SandboxValidationError(
                      'FINAL_LIBRARY conflicts with IS_COMPONENT. '
                      'Please remove one.', context)
              static_args['link_into'] = final_lib
              static_lib = True
  
          if libname:
              if is_component:
                  if static_lib:
                      raise SandboxValidationError(
                          'IS_COMPONENT conflicts with FORCE_STATIC_LIB. '
                          'Please remove one.', context)
                  shared_lib = True
                  shared_args['variant'] = SharedLibrary.COMPONENT
  
              if is_framework:
                  if soname:
                      raise SandboxValidationError(
                          'IS_FRAMEWORK conflicts with SONAME. '
                          'Please remove one.', context)
                  shared_lib = True
                  shared_args['variant'] = SharedLibrary.FRAMEWORK
  
              if not static_lib and not shared_lib:
                  static_lib = True
  
              if static_name:
                  if not static_lib:
                      raise SandboxValidationError(
                          'STATIC_LIBRARY_NAME requires FORCE_STATIC_LIB',
                          context)
                  static_args['real_name'] = static_name
  
              if shared_name:
                  if not shared_lib:
                      raise SandboxValidationError(
                          'SHARED_LIBRARY_NAME requires FORCE_SHARED_LIB',
                          context)
                  shared_args['real_name'] = shared_name
  
              if soname:
                  if not shared_lib:
                      raise SandboxValidationError(
                          'SONAME requires FORCE_SHARED_LIB', context)
                  shared_args['soname'] = soname
  
              # If both a shared and a static library are created, only the
              # shared library is meant to be a SDK library.
              if context.get('SDK_LIBRARY'):
                  if shared_lib:
                      shared_args['is_sdk'] = True
                  elif static_lib:
                      static_args['is_sdk'] = True
  
              if shared_lib and static_lib:
                  if not static_name and not shared_name:
                      raise SandboxValidationError(
                          'Both FORCE_STATIC_LIB and FORCE_SHARED_LIB are True, '
                          'but neither STATIC_LIBRARY_NAME or '
                          'SHARED_LIBRARY_NAME is set. At least one is required.',
                          context)
                  if static_name and not shared_name and static_name == libname:
                      raise SandboxValidationError(
                          'Both FORCE_STATIC_LIB and FORCE_SHARED_LIB are True, '
                          'but STATIC_LIBRARY_NAME is the same as LIBRARY_NAME, '
                          'and SHARED_LIBRARY_NAME is unset. Please either '
                          'change STATIC_LIBRARY_NAME or LIBRARY_NAME, or set '
                          'SHARED_LIBRARY_NAME.', context)
                  if shared_name and not static_name and shared_name == libname:
                      raise SandboxValidationError(
                          'Both FORCE_STATIC_LIB and FORCE_SHARED_LIB are True, '
                          'but SHARED_LIBRARY_NAME is the same as LIBRARY_NAME, '
                          'and STATIC_LIBRARY_NAME is unset. Please either '
                          'change SHARED_LIBRARY_NAME or LIBRARY_NAME, or set '
                          'STATIC_LIBRARY_NAME.', context)
                  if shared_name and static_name and shared_name == static_name:
                      raise SandboxValidationError(
                          'Both FORCE_STATIC_LIB and FORCE_SHARED_LIB are True, '
                          'but SHARED_LIBRARY_NAME is the same as '
                          'STATIC_LIBRARY_NAME. Please change one of them.',
                          context)
  
              if shared_lib:
                  lib = SharedLibrary(context, libname, **shared_args)
                  self._libs[libname].append(lib)
                  self._linkage.append((context, lib, 'USE_LIBS'))
              if static_lib:
                  lib = StaticLibrary(context, libname, **static_args)
                  self._libs[libname].append(lib)
                  self._linkage.append((context, lib, 'USE_LIBS'))
  
              if lib_defines:
                  if not libname:
                      raise SandboxValidationError('LIBRARY_DEFINES needs a '
                          'LIBRARY_NAME to take effect', context)
                  lib.defines.update(lib_defines)
  
          # While there are multiple test manifests, the behavior is very similar
          # across them. We enforce this by having common handling of all
          # manifests and outputting a single class type with the differences
          # described inside the instance.
          #
          # Keys are variable prefixes and values are tuples describing how these
          # manifests should be handled:
          #
          #    (flavor, install_prefix, package_tests)
          #
          # flavor identifies the flavor of this test.
          # install_prefix is the path prefix of where to install the files in
          #     the tests directory.
          # package_tests indicates whether to package test files into the test
          #     package; suites that compile the test files should not install
          #     them into the test package.
          #
          test_manifests = dict(
              A11Y=('a11y', 'testing/mochitest', 'a11y', True),
              BROWSER_CHROME=('browser-chrome', 'testing/mochitest', 'browser', True),
              ANDROID_INSTRUMENTATION=('instrumentation', 'instrumentation', '.', False),
              JETPACK_PACKAGE=('jetpack-package', 'testing/mochitest', 'jetpack-package', True),
              JETPACK_ADDON=('jetpack-addon', 'testing/mochitest', 'jetpack-addon', False),
              METRO_CHROME=('metro-chrome', 'testing/mochitest', 'metro', True),
              MOCHITEST=('mochitest', 'testing/mochitest', 'tests', True),
              MOCHITEST_CHROME=('chrome', 'testing/mochitest', 'chrome', True),
              MOCHITEST_WEBAPPRT_CONTENT=('webapprt-content', 'testing/mochitest', 'webapprtContent', True),
              MOCHITEST_WEBAPPRT_CHROME=('webapprt-chrome', 'testing/mochitest', 'webapprtChrome', True),
              WEBRTC_SIGNALLING_TEST=('steeplechase', 'steeplechase', '.', True),
              XPCSHELL_TESTS=('xpcshell', 'xpcshell', '.', True),
          )
  
          for prefix, info in test_manifests.items():
              for path in context.get('%s_MANIFESTS' % prefix, []):
                  for obj in self._process_test_manifest(context, info, path):
                      yield obj
  
          for flavor in ('crashtest', 'reftest'):
              for path in context.get('%s_MANIFESTS' % flavor.upper(), []):
                  for obj in self._process_reftest_manifest(context, flavor, path):
                      yield obj
  
          jar_manifests = context.get('JAR_MANIFESTS', [])
          if len(jar_manifests) > 1:
              raise SandboxValidationError('While JAR_MANIFESTS is a list, '
                  'it is currently limited to one value.', context)
  
          for path in jar_manifests:
              yield JARManifest(context, mozpath.join(context.srcdir, path))
  
          # Temporary test to look for jar.mn files that creep in without using
          # the new declaration. Before, we didn't require jar.mn files to
          # declared anywhere (they were discovered). This will detect people
          # relying on the old behavior.
          if os.path.exists(os.path.join(context.srcdir, 'jar.mn')):
              if 'jar.mn' not in jar_manifests:
                  raise SandboxValidationError('A jar.mn exists but it '
                      'is not referenced in the moz.build file. '
                      'Please define JAR_MANIFESTS.', context)
  
          for name, jar in context.get('JAVA_JAR_TARGETS', {}).items():
              yield ContextWrapped(context, jar)
  
          for name, data in context.get('ANDROID_ECLIPSE_PROJECT_TARGETS', {}).items():
              yield ContextWrapped(context, data)
  
          if passthru.variables:
              yield passthru
function_tokens: def emit_from_context ( self , context ) : # We only want to emit an InstallationTarget if one of the consulted # variables is defined. Later on, we look up FINAL_TARGET, which has # the side-effect of populating it. So, we need to do this lookup # early. if any ( k in context for k in ( 'FINAL_TARGET' , 'XPI_NAME' , 'DIST_SUBDIR' ) ) : yield InstallationTarget ( context ) # We always emit a directory traversal descriptor. This is needed by # the recursive make backend. for o in self . _emit_directory_traversal_from_context ( context ) : yield o for path in context [ 'CONFIGURE_SUBST_FILES' ] : yield self . _create_substitution ( ConfigFileSubstitution , context , path ) for path in context [ 'CONFIGURE_DEFINE_FILES' ] : yield self . _create_substitution ( HeaderFileSubstitution , context , path ) # XPIDL source files get processed and turned into .h and .xpt files. # If there are multiple XPIDL files in a directory, they get linked # together into a final .xpt, which has the name defined by # XPIDL_MODULE. xpidl_module = context [ 'XPIDL_MODULE' ] if context [ 'XPIDL_SOURCES' ] and not xpidl_module : raise SandboxValidationError ( 'XPIDL_MODULE must be defined if ' 'XPIDL_SOURCES is defined.' , context ) if xpidl_module and not context [ 'XPIDL_SOURCES' ] : raise SandboxValidationError ( 'XPIDL_MODULE cannot be defined ' 'unless there are XPIDL_SOURCES' , context ) if context [ 'XPIDL_SOURCES' ] and context [ 'NO_DIST_INSTALL' ] : self . log ( logging . WARN , 'mozbuild_warning' , dict ( path = context . main_path ) , '{path}: NO_DIST_INSTALL has no effect on XPIDL_SOURCES.' ) for idl in context [ 'XPIDL_SOURCES' ] : yield XPIDLFile ( context , mozpath . join ( context . srcdir , idl ) , xpidl_module ) for symbol in ( 'SOURCES' , 'HOST_SOURCES' , 'UNIFIED_SOURCES' ) : for src in ( context [ symbol ] or [ ] ) : if not os . path . exists ( mozpath . join ( context . srcdir , src ) ) : raise SandboxValidationError ( 'File listed in %s does not ' 'exist: \'%s\'' % ( symbol , src ) , context ) # Proxy some variables as-is until we have richer classes to represent # them. We should aim to keep this set small because it violates the # desired abstraction of the build definition away from makefiles. passthru = VariablePassthru ( context ) varlist = [ 'ANDROID_GENERATED_RESFILES' , 'ANDROID_RES_DIRS' , 'DISABLE_STL_WRAPPING' , 'EXTRA_ASSEMBLER_FLAGS' , 'EXTRA_COMPILE_FLAGS' , 'EXTRA_COMPONENTS' , 'EXTRA_DSO_LDOPTS' , 'EXTRA_PP_COMPONENTS' , 'FAIL_ON_WARNINGS' , 'USE_STATIC_LIBS' , 'IS_GYP_DIR' , 'MSVC_ENABLE_PGO' , 'NO_DIST_INSTALL' , 'PYTHON_UNIT_TESTS' , 'RCFILE' , 'RESFILE' , 'RCINCLUDE' , 'DEFFILE' , 'WIN32_EXE_LDFLAGS' , 'LD_VERSION_SCRIPT' , ] for v in varlist : if v in context and context [ v ] : passthru . variables [ v ] = context [ v ] if context . config . substs . get ( 'OS_TARGET' ) == 'WINNT' and context [ 'DELAYLOAD_DLLS' ] : context [ 'LDFLAGS' ] . extend ( [ ( '-DELAYLOAD:%s' % dll ) for dll in context [ 'DELAYLOAD_DLLS' ] ] ) context [ 'OS_LIBS' ] . append ( 'delayimp' ) for v in [ 'CFLAGS' , 'CXXFLAGS' , 'CMFLAGS' , 'CMMFLAGS' , 'LDFLAGS' ] : if v in context and context [ v ] : passthru . variables [ 'MOZBUILD_' + v ] = context [ v ] # NO_VISIBILITY_FLAGS is slightly different if context [ 'NO_VISIBILITY_FLAGS' ] : passthru . variables [ 'VISIBILITY_FLAGS' ] = '' no_pgo = context . get ( 'NO_PGO' ) sources = context . get ( 'SOURCES' , [ ] ) no_pgo_sources = [ f for f in sources if sources [ f ] . no_pgo ] if no_pgo : if no_pgo_sources : raise SandboxValidationError ( 'NO_PGO and SOURCES[...].no_pgo ' 'cannot be set at the same time' , context ) passthru . variables [ 'NO_PROFILE_GUIDED_OPTIMIZE' ] = no_pgo if no_pgo_sources : passthru . variables [ 'NO_PROFILE_GUIDED_OPTIMIZE' ] = no_pgo_sources # A map from "canonical suffixes" for a particular source file # language to the range of suffixes associated with that language. # # We deliberately don't list the canonical suffix in the suffix list # in the definition; we'll add it in programmatically after defining # things. suffix_map = { '.s' : set ( [ '.asm' ] ) , '.c' : set ( ) , '.m' : set ( ) , '.mm' : set ( ) , '.cpp' : set ( [ '.cc' , '.cxx' ] ) , '.S' : set ( ) , } # The inverse of the above, mapping suffixes to their canonical suffix. canonicalized_suffix_map = { } for suffix , alternatives in suffix_map . iteritems ( ) : alternatives . add ( suffix ) for a in alternatives : canonicalized_suffix_map [ a ] = suffix def canonical_suffix_for_file ( f ) : return canonicalized_suffix_map [ mozpath . splitext ( f ) [ 1 ] ] # A map from moz.build variables to the canonical suffixes of file # kinds that can be listed therein. all_suffixes = list ( suffix_map . keys ( ) ) varmap = dict ( SOURCES = ( Sources , all_suffixes ) , HOST_SOURCES = ( HostSources , [ '.c' , '.mm' , '.cpp' ] ) , UNIFIED_SOURCES = ( UnifiedSources , [ '.c' , '.mm' , '.cpp' ] ) , GENERATED_SOURCES = ( GeneratedSources , all_suffixes ) , ) for variable , ( klass , suffixes ) in varmap . items ( ) : allowed_suffixes = set ( ) . union ( * [ suffix_map [ s ] for s in suffixes ] ) # First ensure that we haven't been given filetypes that we don't # recognize. for f in context [ variable ] : ext = mozpath . splitext ( f ) [ 1 ] if ext not in allowed_suffixes : raise SandboxValidationError ( '%s has an unknown file type.' % f , context ) if variable . startswith ( 'GENERATED_' ) : l = passthru . variables . setdefault ( 'GARBAGE' , [ ] ) l . append ( f ) # Now sort the files to let groupby work. sorted_files = sorted ( context [ variable ] , key = canonical_suffix_for_file ) for canonical_suffix , files in itertools . groupby ( sorted_files , canonical_suffix_for_file ) : arglist = [ context , list ( files ) , canonical_suffix ] if variable . startswith ( 'UNIFIED_' ) and 'FILES_PER_UNIFIED_FILE' in context : arglist . append ( context [ 'FILES_PER_UNIFIED_FILE' ] ) yield klass ( * arglist ) sources_with_flags = [ f for f in sources if sources [ f ] . flags ] for f in sources_with_flags : ext = mozpath . splitext ( f ) [ 1 ] yield PerSourceFlag ( context , f , sources [ f ] . flags ) exports = context . get ( 'EXPORTS' ) if exports : yield Exports ( context , exports , dist_install = not context . get ( 'NO_DIST_INSTALL' , False ) ) generated_files = context . get ( 'GENERATED_FILES' ) if generated_files : for f in generated_files : flags = generated_files [ f ] output = f if flags . script : script = mozpath . join ( context . srcdir , flags . script ) inputs = [ mozpath . join ( context . srcdir , i ) for i in flags . inputs ] if not os . path . exists ( script ) : raise SandboxValidationError ( 'Script for generating %s does not exist: %s' % ( f , script ) , context ) if os . path . splitext ( script ) [ 1 ] != '.py' : raise SandboxValidationError ( 'Script for generating %s does not end in .py: %s' % ( f , script ) , context ) for i in inputs : if not os . path . exists ( i ) : raise SandboxValidationError ( 'Input for generating %s does not exist: %s' % ( f , i ) , context ) else : script = None inputs = [ ] yield GeneratedFile ( context , script , output , inputs ) test_harness_files = context . get ( 'TEST_HARNESS_FILES' ) if test_harness_files : srcdir_files = defaultdict ( list ) srcdir_pattern_files = defaultdict ( list ) objdir_files = defaultdict ( list ) for path , strings in test_harness_files . walk ( ) : if not path and strings : raise SandboxValidationError ( 'Cannot install files to the root of TEST_HARNESS_FILES' , context ) for s in strings : if context . is_objdir_path ( s ) : if s . startswith ( '!/' ) : objdir_files [ path ] . append ( '$(DEPTH)/%s' % s [ 2 : ] ) else : objdir_files [ path ] . append ( s [ 1 : ] ) else : resolved = context . resolve_path ( s ) if '*' in s : srcdir_pattern_files [ path ] . append ( s ) elif not os . path . exists ( resolved ) : raise SandboxValidationError ( 'File listed in TEST_HARNESS_FILES does not exist: %s' % s , context ) else : srcdir_files [ path ] . append ( resolved ) yield TestHarnessFiles ( context , srcdir_files , srcdir_pattern_files , objdir_files ) defines = context . get ( 'DEFINES' ) if defines : yield Defines ( context , defines ) resources = context . get ( 'RESOURCE_FILES' ) if resources : yield Resources ( context , resources , defines ) for pref in sorted ( context [ 'JS_PREFERENCE_FILES' ] ) : yield JsPreferenceFile ( context , pref ) for kind , cls in [ ( 'PROGRAM' , Program ) , ( 'HOST_PROGRAM' , HostProgram ) ] : program = context . get ( kind ) if program : if program in self . _binaries : raise SandboxValidationError ( 'Cannot use "%s" as %s name, ' 'because it is already used in %s' % ( program , kind , self . _binaries [ program ] . relativedir ) , context ) self . _binaries [ program ] = cls ( context , program ) self . _linkage . append ( ( context , self . _binaries [ program ] , kind . replace ( 'PROGRAM' , 'USE_LIBS' ) ) ) for kind , cls in [ ( 'SIMPLE_PROGRAMS' , SimpleProgram ) , ( 'CPP_UNIT_TESTS' , SimpleProgram ) , ( 'HOST_SIMPLE_PROGRAMS' , HostSimpleProgram ) ] : for program in context [ kind ] : if program in self . _binaries : raise SandboxValidationError ( 'Cannot use "%s" in %s, ' 'because it is already used in %s' % ( program , kind , self . _binaries [ program ] . relativedir ) , context ) self . _binaries [ program ] = cls ( context , program , is_unit_test = kind == 'CPP_UNIT_TESTS' ) self . _linkage . append ( ( context , self . _binaries [ program ] , 'HOST_USE_LIBS' if kind == 'HOST_SIMPLE_PROGRAMS' else 'USE_LIBS' ) ) extra_js_modules = context . get ( 'EXTRA_JS_MODULES' ) if extra_js_modules : yield JavaScriptModules ( context , extra_js_modules , 'extra' ) extra_pp_js_modules = context . get ( 'EXTRA_PP_JS_MODULES' ) if extra_pp_js_modules : yield JavaScriptModules ( context , extra_pp_js_modules , 'extra_pp' ) test_js_modules = context . get ( 'TESTING_JS_MODULES' ) if test_js_modules : yield JavaScriptModules ( context , test_js_modules , 'testing' ) simple_lists = [ ( 'GENERATED_EVENTS_WEBIDL_FILES' , GeneratedEventWebIDLFile ) , ( 'GENERATED_WEBIDL_FILES' , GeneratedWebIDLFile ) , ( 'IPDL_SOURCES' , IPDLFile ) , ( 'GENERATED_INCLUDES' , GeneratedInclude ) , ( 'PREPROCESSED_TEST_WEBIDL_FILES' , PreprocessedTestWebIDLFile ) , ( 'PREPROCESSED_WEBIDL_FILES' , PreprocessedWebIDLFile ) , ( 'TEST_WEBIDL_FILES' , TestWebIDLFile ) , ( 'WEBIDL_FILES' , WebIDLFile ) , ( 'WEBIDL_EXAMPLE_INTERFACES' , ExampleWebIDLInterface ) , ] for context_var , klass in simple_lists : for name in context . get ( context_var , [ ] ) : yield klass ( context , name ) for local_include in context . get ( 'LOCAL_INCLUDES' , [ ] ) : if local_include . startswith ( '/' ) : path = context . config . topsrcdir relative_include = local_include [ 1 : ] else : path = context . srcdir relative_include = local_include actual_include = os . path . join ( path , relative_include ) if not os . path . exists ( actual_include ) : raise SandboxValidationError ( 'Path specified in LOCAL_INCLUDES ' 'does not exist: %s (resolved to %s)' % ( local_include , actual_include ) , context ) yield LocalInclude ( context , local_include ) final_target_files = context . get ( 'FINAL_TARGET_FILES' ) if final_target_files : yield FinalTargetFiles ( context , final_target_files , context [ 'FINAL_TARGET' ] ) host_libname = context . get ( 'HOST_LIBRARY_NAME' ) libname = context . get ( 'LIBRARY_NAME' ) if host_libname : if host_libname == libname : raise SandboxValidationError ( 'LIBRARY_NAME and ' 'HOST_LIBRARY_NAME must have a different value' , context ) lib = HostLibrary ( context , host_libname ) self . _libs [ host_libname ] . append ( lib ) self . _linkage . append ( ( context , lib , 'HOST_USE_LIBS' ) ) final_lib = context . get ( 'FINAL_LIBRARY' ) if not libname and final_lib : # If no LIBRARY_NAME is given, create one. libname = context . relsrcdir . replace ( '/' , '_' ) static_lib = context . get ( 'FORCE_STATIC_LIB' ) shared_lib = context . get ( 'FORCE_SHARED_LIB' ) static_name = context . get ( 'STATIC_LIBRARY_NAME' ) shared_name = context . get ( 'SHARED_LIBRARY_NAME' ) is_framework = context . get ( 'IS_FRAMEWORK' ) is_component = context . get ( 'IS_COMPONENT' ) soname = context . get ( 'SONAME' ) lib_defines = context . get ( 'LIBRARY_DEFINES' ) shared_args = { } static_args = { } if final_lib : if static_lib : raise SandboxValidationError ( 'FINAL_LIBRARY implies FORCE_STATIC_LIB. ' 'Please remove the latter.' , context ) if shared_lib : raise SandboxValidationError ( 'FINAL_LIBRARY conflicts with FORCE_SHARED_LIB. ' 'Please remove one.' , context ) if is_framework : raise SandboxValidationError ( 'FINAL_LIBRARY conflicts with IS_FRAMEWORK. ' 'Please remove one.' , context ) if is_component : raise SandboxValidationError ( 'FINAL_LIBRARY conflicts with IS_COMPONENT. ' 'Please remove one.' , context ) static_args [ 'link_into' ] = final_lib static_lib = True if libname : if is_component : if static_lib : raise SandboxValidationError ( 'IS_COMPONENT conflicts with FORCE_STATIC_LIB. ' 'Please remove one.' , context ) shared_lib = True shared_args [ 'variant' ] = SharedLibrary . COMPONENT if is_framework : if soname : raise SandboxValidationError ( 'IS_FRAMEWORK conflicts with SONAME. ' 'Please remove one.' , context ) shared_lib = True shared_args [ 'variant' ] = SharedLibrary . FRAMEWORK if not static_lib and not shared_lib : static_lib = True if static_name : if not static_lib : raise SandboxValidationError ( 'STATIC_LIBRARY_NAME requires FORCE_STATIC_LIB' , context ) static_args [ 'real_name' ] = static_name if shared_name : if not shared_lib : raise SandboxValidationError ( 'SHARED_LIBRARY_NAME requires FORCE_SHARED_LIB' , context ) shared_args [ 'real_name' ] = shared_name if soname : if not shared_lib : raise SandboxValidationError ( 'SONAME requires FORCE_SHARED_LIB' , context ) shared_args [ 'soname' ] = soname # If both a shared and a static library are created, only the # shared library is meant to be a SDK library. if context . get ( 'SDK_LIBRARY' ) : if shared_lib : shared_args [ 'is_sdk' ] = True elif static_lib : static_args [ 'is_sdk' ] = True if shared_lib and static_lib : if not static_name and not shared_name : raise SandboxValidationError ( 'Both FORCE_STATIC_LIB and FORCE_SHARED_LIB are True, ' 'but neither STATIC_LIBRARY_NAME or ' 'SHARED_LIBRARY_NAME is set. At least one is required.' , context ) if static_name and not shared_name and static_name == libname : raise SandboxValidationError ( 'Both FORCE_STATIC_LIB and FORCE_SHARED_LIB are True, ' 'but STATIC_LIBRARY_NAME is the same as LIBRARY_NAME, ' 'and SHARED_LIBRARY_NAME is unset. Please either ' 'change STATIC_LIBRARY_NAME or LIBRARY_NAME, or set ' 'SHARED_LIBRARY_NAME.' , context ) if shared_name and not static_name and shared_name == libname : raise SandboxValidationError ( 'Both FORCE_STATIC_LIB and FORCE_SHARED_LIB are True, ' 'but SHARED_LIBRARY_NAME is the same as LIBRARY_NAME, ' 'and STATIC_LIBRARY_NAME is unset. Please either ' 'change SHARED_LIBRARY_NAME or LIBRARY_NAME, or set ' 'STATIC_LIBRARY_NAME.' , context ) if shared_name and static_name and shared_name == static_name : raise SandboxValidationError ( 'Both FORCE_STATIC_LIB and FORCE_SHARED_LIB are True, ' 'but SHARED_LIBRARY_NAME is the same as ' 'STATIC_LIBRARY_NAME. Please change one of them.' , context ) if shared_lib : lib = SharedLibrary ( context , libname , * * shared_args ) self . _libs [ libname ] . append ( lib ) self . _linkage . append ( ( context , lib , 'USE_LIBS' ) ) if static_lib : lib = StaticLibrary ( context , libname , * * static_args ) self . _libs [ libname ] . append ( lib ) self . _linkage . append ( ( context , lib , 'USE_LIBS' ) ) if lib_defines : if not libname : raise SandboxValidationError ( 'LIBRARY_DEFINES needs a ' 'LIBRARY_NAME to take effect' , context ) lib . defines . update ( lib_defines ) # While there are multiple test manifests, the behavior is very similar # across them. We enforce this by having common handling of all # manifests and outputting a single class type with the differences # described inside the instance. # # Keys are variable prefixes and values are tuples describing how these # manifests should be handled: # #    (flavor, install_prefix, package_tests) # # flavor identifies the flavor of this test. # install_prefix is the path prefix of where to install the files in #     the tests directory. # package_tests indicates whether to package test files into the test #     package; suites that compile the test files should not install #     them into the test package. # test_manifests = dict ( A11Y = ( 'a11y' , 'testing/mochitest' , 'a11y' , True ) , BROWSER_CHROME = ( 'browser-chrome' , 'testing/mochitest' , 'browser' , True ) , ANDROID_INSTRUMENTATION = ( 'instrumentation' , 'instrumentation' , '.' , False ) , JETPACK_PACKAGE = ( 'jetpack-package' , 'testing/mochitest' , 'jetpack-package' , True ) , JETPACK_ADDON = ( 'jetpack-addon' , 'testing/mochitest' , 'jetpack-addon' , False ) , METRO_CHROME = ( 'metro-chrome' , 'testing/mochitest' , 'metro' , True ) , MOCHITEST = ( 'mochitest' , 'testing/mochitest' , 'tests' , True ) , MOCHITEST_CHROME = ( 'chrome' , 'testing/mochitest' , 'chrome' , True ) , MOCHITEST_WEBAPPRT_CONTENT = ( 'webapprt-content' , 'testing/mochitest' , 'webapprtContent' , True ) , MOCHITEST_WEBAPPRT_CHROME = ( 'webapprt-chrome' , 'testing/mochitest' , 'webapprtChrome' , True ) , WEBRTC_SIGNALLING_TEST = ( 'steeplechase' , 'steeplechase' , '.' , True ) , XPCSHELL_TESTS = ( 'xpcshell' , 'xpcshell' , '.' , True ) , ) for prefix , info in test_manifests . items ( ) : for path in context . get ( '%s_MANIFESTS' % prefix , [ ] ) : for obj in self . _process_test_manifest ( context , info , path ) : yield obj for flavor in ( 'crashtest' , 'reftest' ) : for path in context . get ( '%s_MANIFESTS' % flavor . upper ( ) , [ ] ) : for obj in self . _process_reftest_manifest ( context , flavor , path ) : yield obj jar_manifests = context . get ( 'JAR_MANIFESTS' , [ ] ) if len ( jar_manifests ) > 1 : raise SandboxValidationError ( 'While JAR_MANIFESTS is a list, ' 'it is currently limited to one value.' , context ) for path in jar_manifests : yield JARManifest ( context , mozpath . join ( context . srcdir , path ) ) # Temporary test to look for jar.mn files that creep in without using # the new declaration. Before, we didn't require jar.mn files to # declared anywhere (they were discovered). This will detect people # relying on the old behavior. if os . path . exists ( os . path . join ( context . srcdir , 'jar.mn' ) ) : if 'jar.mn' not in jar_manifests : raise SandboxValidationError ( 'A jar.mn exists but it ' 'is not referenced in the moz.build file. ' 'Please define JAR_MANIFESTS.' , context ) for name , jar in context . get ( 'JAVA_JAR_TARGETS' , { } ) . items ( ) : yield ContextWrapped ( context , jar ) for name , data in context . get ( 'ANDROID_ECLIPSE_PROJECT_TARGETS' , { } ) . items ( ) : yield ContextWrapped ( context , data ) if passthru . variables : yield passthru