def GenerateOutput(target_list, target_dicts, data, params):
    options = params['options']
    generator_flags = params.get('generator_flags', {})
    builddir_name = generator_flags.get('output_dir', 'out')
    limit_to_target_all = generator_flags.get('limit_to_target_all', False)
    android_top_dir = os.environ.get('ANDROID_BUILD_TOP')
    assert android_top_dir, '$ANDROID_BUILD_TOP not set; you need to run lunch.'

    def CalculateMakefilePath(build_file, base_name):
        """Determine where to write a Makefile for a given gyp file."""
        # Paths in gyp files are relative to the .gyp file, but we want
        # paths relative to the source root for the master makefile.  Grab
        # the path of the .gyp file as the base to relativize against.
        # E.g. "foo/bar" when we're constructing targets for "foo/bar/baz.gyp".
        base_path = gyp.common.RelativePath(os.path.dirname(build_file),
                                            options.depth)
        # We write the file in the base_path directory.
        output_file = os.path.join(options.depth, base_path, base_name)
        assert not options.generator_output, (
            'The Android backend does not support options.generator_output.')
        base_path = gyp.common.RelativePath(os.path.dirname(build_file),
                                            options.toplevel_dir)
        return base_path, output_file

    # TODO:  search for the first non-'Default' target.  This can go
    # away when we add verification that all targets have the
    # necessary configurations.
    default_configuration = None
    toolsets = set([target_dicts[target]['toolset'] for target in target_list])
    for target in target_list:
        spec = target_dicts[target]
        if spec['default_configuration'] != 'Default':
            default_configuration = spec['default_configuration']
            break
    if not default_configuration:
        default_configuration = 'Default'

    srcdir = '.'
    makefile_name = 'GypAndroid' + options.suffix + '.mk'
    makefile_path = os.path.join(options.toplevel_dir, makefile_name)
    assert not options.generator_output, (
        'The Android backend does not support options.generator_output.')
    make.ensure_directory_exists(makefile_path)
    root_makefile = open(makefile_path, 'w')

    root_makefile.write(header)

    # We set LOCAL_PATH just once, here, to the top of the project tree. This
    # allows all the other paths we use to be relative to the Android.mk file,
    # as the Android build system expects.
    root_makefile.write('\nLOCAL_PATH := $(call my-dir)\n')

    # Find the list of targets that derive from the gyp file(s) being built.
    needed_targets = set()
    for build_file in params['build_files']:
        for target in gyp.common.AllTargets(target_list, target_dicts,
                                            build_file):
            needed_targets.add(target)

    build_files = set()
    include_list = set()
    android_modules = {}
    for qualified_target in target_list:
        build_file, target, toolset = gyp.common.ParseQualifiedTarget(
            qualified_target)
        relative_build_file = gyp.common.RelativePath(build_file,
                                                      options.toplevel_dir)
        build_files.add(relative_build_file)
        included_files = data[build_file]['included_files']
        for included_file in included_files:
            # The included_files entries are relative to the dir of the build file
            # that included them, so we have to undo that and then make them relative
            # to the root dir.
            relative_include_file = gyp.common.RelativePath(
                gyp.common.UnrelativePath(included_file, build_file),
                options.toplevel_dir)
            abs_include_file = os.path.abspath(relative_include_file)
            # If the include file is from the ~/.gyp dir, we should use absolute path
            # so that relocating the src dir doesn't break the path.
            if (params['home_dot_gyp']
                    and abs_include_file.startswith(params['home_dot_gyp'])):
                build_files.add(abs_include_file)
            else:
                build_files.add(relative_include_file)

        base_path, output_file = CalculateMakefilePath(
            build_file, target + '.' + toolset + options.suffix + '.mk')

        spec = target_dicts[qualified_target]
        configs = spec['configurations']

        part_of_all = (qualified_target in needed_targets
                       and not int(spec.get('suppress_wildcard', False)))
        if limit_to_target_all and not part_of_all:
            continue

        relative_target = gyp.common.QualifiedTarget(relative_build_file,
                                                     target, toolset)
        writer = AndroidMkWriter(android_top_dir)
        android_module = writer.Write(qualified_target,
                                      relative_target,
                                      base_path,
                                      output_file,
                                      spec,
                                      configs,
                                      part_of_all=part_of_all)
        if android_module in android_modules:
            print(
                'ERROR: Android module names must be unique. The following '
                'targets both generate Android module name %s.\n  %s\n  %s' %
                (android_module, android_modules[android_module],
                 qualified_target))
            return
        android_modules[android_module] = qualified_target

        # Our root_makefile lives at the source root.  Compute the relative path
        # from there to the output_file for including.
        mkfile_rel_path = gyp.common.RelativePath(
            output_file, os.path.dirname(makefile_path))
        include_list.add(mkfile_rel_path)

    root_makefile.write('GYP_DEFAULT_CONFIGURATION := %s\n' %
                        default_configuration)

    # Write out the sorted list of includes.
    root_makefile.write('\n')
    for include_file in sorted(include_list):
        root_makefile.write('include $(LOCAL_PATH)/' + include_file + '\n')
    root_makefile.write('\n')

    root_makefile.write(SHARED_FOOTER)

    root_makefile.close()
    def Write(self, qualified_target, relative_target, base_path,
              output_filename, spec, configs, part_of_all):
        """The main entry point: writes a .mk file for a single target.

    Arguments:
      qualified_target: target we're generating
      relative_target: qualified target name relative to the root
      base_path: path relative to source root we're building in, used to resolve
                 target-relative paths
      output_filename: output .mk file name to write
      spec, configs: gyp info
      part_of_all: flag indicating this target is part of 'all'
    """
        make.ensure_directory_exists(output_filename)

        self.fp = open(output_filename, 'w')

        self.fp.write(header)

        self.qualified_target = qualified_target
        self.relative_target = relative_target
        self.path = base_path
        self.target = spec['target_name']
        self.type = spec['type']
        self.toolset = spec['toolset']

        deps, link_deps = self.ComputeDeps(spec)

        # Some of the generation below can add extra output, sources, or
        # link dependencies.  All of the out params of the functions that
        # follow use names like extra_foo.
        extra_outputs = []
        extra_sources = []

        self.android_class = MODULE_CLASSES.get(self.type, 'GYP')
        self.android_module = self.ComputeAndroidModule(spec)
        (self.android_stem,
         self.android_suffix) = self.ComputeOutputParts(spec)
        self.output = self.output_binary = self.ComputeOutput(spec)

        # Standard header.
        self.WriteLn('include $(CLEAR_VARS)\n')

        # Module class and name.
        self.WriteLn('LOCAL_MODULE_CLASS := ' + self.android_class)
        self.WriteLn('LOCAL_MODULE := ' + self.android_module)
        # Only emit LOCAL_MODULE_STEM if it's different to LOCAL_MODULE.
        # The library module classes fail if the stem is set. ComputeOutputParts
        # makes sure that stem == modulename in these cases.
        if self.android_stem != self.android_module:
            self.WriteLn('LOCAL_MODULE_STEM := ' + self.android_stem)
        self.WriteLn('LOCAL_MODULE_SUFFIX := ' + self.android_suffix)
        self.WriteLn('LOCAL_MODULE_TAGS := optional')
        if self.toolset == 'host':
            self.WriteLn('LOCAL_IS_HOST_MODULE := true')

        # Grab output directories; needed for Actions and Rules.
        self.WriteLn('gyp_intermediate_dir := $(call local-intermediates-dir)')
        self.WriteLn('gyp_shared_intermediate_dir := '
                     '$(call intermediates-dir-for,GYP,shared)')
        self.WriteLn()

        # List files this target depends on so that actions/rules/copies/sources
        # can depend on the list.
        # TODO: doesn't pull in things through transitive link deps; needed?
        target_dependencies = [x[1] for x in deps if x[0] == 'path']
        self.WriteLn('# Make sure our deps are built first.')
        self.WriteList(target_dependencies,
                       'GYP_TARGET_DEPENDENCIES',
                       local_pathify=True)

        # Actions must come first, since they can generate more OBJs for use below.
        if 'actions' in spec:
            self.WriteActions(spec['actions'], extra_sources, extra_outputs)

        # Rules must be early like actions.
        if 'rules' in spec:
            self.WriteRules(spec['rules'], extra_sources, extra_outputs)

        if 'copies' in spec:
            self.WriteCopies(spec['copies'], extra_outputs)

        # GYP generated outputs.
        self.WriteList(extra_outputs,
                       'GYP_GENERATED_OUTPUTS',
                       local_pathify=True)

        # Set LOCAL_ADDITIONAL_DEPENDENCIES so that Android's build rules depend
        # on both our dependency targets and our generated files.
        self.WriteLn(
            '# Make sure our deps and generated files are built first.')
        self.WriteLn(
            'LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) '
            '$(GYP_GENERATED_OUTPUTS)')
        self.WriteLn()

        # Sources.
        if spec.get('sources', []) or extra_sources:
            self.WriteSources(spec, configs, extra_sources)

        self.WriteTarget(spec, configs, deps, link_deps, part_of_all)

        # Update global list of target outputs, used in dependency tracking.
        target_outputs[qualified_target] = ('path', self.output_binary)

        # Update global list of link dependencies.
        if self.type == 'static_library':
            target_link_deps[qualified_target] = ('static',
                                                  self.android_module)
        elif self.type == 'shared_library':
            target_link_deps[qualified_target] = ('shared',
                                                  self.android_module)

        self.fp.close()
        return self.android_module
Exemple #3
0
def GenerateOutput(target_list, target_dicts, data, params):
  options = params['options']
  generator_flags = params.get('generator_flags', {})
  builddir_name = generator_flags.get('output_dir', 'out')
  limit_to_target_all = generator_flags.get('limit_to_target_all', False)
  android_top_dir = os.environ.get('ANDROID_BUILD_TOP')
  assert android_top_dir, '$ANDROID_BUILD_TOP not set; you need to run lunch.'

  def CalculateMakefilePath(build_file, base_name):
    """Determine where to write a Makefile for a given gyp file."""
    # Paths in gyp files are relative to the .gyp file, but we want
    # paths relative to the source root for the master makefile.  Grab
    # the path of the .gyp file as the base to relativize against.
    # E.g. "foo/bar" when we're constructing targets for "foo/bar/baz.gyp".
    base_path = gyp.common.RelativePath(os.path.dirname(build_file),
                                        options.depth)
    # We write the file in the base_path directory.
    output_file = os.path.join(options.depth, base_path, base_name)
    assert not options.generator_output, (
        'The Android backend does not support options.generator_output.')
    base_path = gyp.common.RelativePath(os.path.dirname(build_file),
                                        options.toplevel_dir)
    return base_path, output_file

  # TODO:  search for the first non-'Default' target.  This can go
  # away when we add verification that all targets have the
  # necessary configurations.
  default_configuration = None
  toolsets = set([target_dicts[target]['toolset'] for target in target_list])
  for target in target_list:
    spec = target_dicts[target]
    if spec['default_configuration'] != 'Default':
      default_configuration = spec['default_configuration']
      break
  if not default_configuration:
    default_configuration = 'Default'

  srcdir = '.'
  makefile_name = 'GypAndroid' + options.suffix + '.mk'
  makefile_path = os.path.join(options.toplevel_dir, makefile_name)
  assert not options.generator_output, (
      'The Android backend does not support options.generator_output.')
  make.ensure_directory_exists(makefile_path)
  root_makefile = open(makefile_path, 'w')

  root_makefile.write(header)

  # We set LOCAL_PATH just once, here, to the top of the project tree. This
  # allows all the other paths we use to be relative to the Android.mk file,
  # as the Android build system expects.
  root_makefile.write('\nLOCAL_PATH := $(call my-dir)\n')

  # Find the list of targets that derive from the gyp file(s) being built.
  needed_targets = set()
  for build_file in params['build_files']:
    for target in gyp.common.AllTargets(target_list, target_dicts, build_file):
      needed_targets.add(target)

  build_files = set()
  include_list = set()
  android_modules = {}
  for qualified_target in target_list:
    build_file, target, toolset = gyp.common.ParseQualifiedTarget(
        qualified_target)
    build_files.add(gyp.common.RelativePath(build_file, options.toplevel_dir))
    included_files = data[build_file]['included_files']
    for included_file in included_files:
      # The included_files entries are relative to the dir of the build file
      # that included them, so we have to undo that and then make them relative
      # to the root dir.
      relative_include_file = gyp.common.RelativePath(
          gyp.common.UnrelativePath(included_file, build_file),
          options.toplevel_dir)
      abs_include_file = os.path.abspath(relative_include_file)
      # If the include file is from the ~/.gyp dir, we should use absolute path
      # so that relocating the src dir doesn't break the path.
      if (params['home_dot_gyp'] and
          abs_include_file.startswith(params['home_dot_gyp'])):
        build_files.add(abs_include_file)
      else:
        build_files.add(relative_include_file)

    base_path, output_file = CalculateMakefilePath(build_file,
        target + '.' + toolset + options.suffix + '.mk')

    spec = target_dicts[qualified_target]
    configs = spec['configurations']

    part_of_all = (qualified_target in needed_targets and
                   not int(spec.get('suppress_wildcard', False)))
    if limit_to_target_all and not part_of_all:
      continue
    writer = AndroidMkWriter(android_top_dir)
    android_module = writer.Write(qualified_target, base_path, output_file,
                                  spec, configs, part_of_all=part_of_all)
    if android_module in android_modules:
      print ('ERROR: Android module names must be unique. The following '
             'targets both generate Android module name %s.\n  %s\n  %s' %
             (android_module, android_modules[android_module],
              qualified_target))
      return
    android_modules[android_module] = qualified_target

    # Our root_makefile lives at the source root.  Compute the relative path
    # from there to the output_file for including.
    mkfile_rel_path = gyp.common.RelativePath(output_file,
                                              os.path.dirname(makefile_path))
    include_list.add(mkfile_rel_path)

  # Some tools need to know the absolute path of the top directory.
  root_makefile.write('GYP_ABS_ANDROID_TOP_DIR := $(shell pwd)\n')
  root_makefile.write('GYP_DEFAULT_CONFIGURATION := %s\n' %
                      default_configuration)

  # Write out the sorted list of includes.
  root_makefile.write('\n')
  for include_file in sorted(include_list):
    root_makefile.write('include $(LOCAL_PATH)/' + include_file + '\n')
  root_makefile.write('\n')

  root_makefile.write(SHARED_FOOTER)

  root_makefile.close()
Exemple #4
0
  def Write(self, qualified_target, base_path, output_filename, spec, configs,
            part_of_all):
    """The main entry point: writes a .mk file for a single target.

    Arguments:
      qualified_target: target we're generating
      base_path: path relative to source root we're building in, used to resolve
                 target-relative paths
      output_filename: output .mk file name to write
      spec, configs: gyp info
      part_of_all: flag indicating this target is part of 'all'
    """
    make.ensure_directory_exists(output_filename)

    self.fp = open(output_filename, 'w')

    self.fp.write(header)

    self.qualified_target = qualified_target
    self.path = base_path
    self.target = spec['target_name']
    self.type = spec['type']
    self.toolset = spec['toolset']

    deps, link_deps = self.ComputeDeps(spec)

    # Some of the generation below can add extra output, sources, or
    # link dependencies.  All of the out params of the functions that
    # follow use names like extra_foo.
    extra_outputs = []
    extra_sources = []

    self.android_class = MODULE_CLASSES.get(self.type, 'GYP')
    self.android_module = self.ComputeAndroidModule(spec)
    (self.android_stem, self.android_suffix) = self.ComputeOutputParts(spec)
    self.output = self.output_binary = self.ComputeOutput(spec)

    # Standard header.
    self.WriteLn('include $(CLEAR_VARS)\n')

    # Module class and name.
    self.WriteLn('LOCAL_MODULE_CLASS := ' + self.android_class)
    self.WriteLn('LOCAL_MODULE := ' + self.android_module)
    # Only emit LOCAL_MODULE_STEM if it's different to LOCAL_MODULE.
    # The library module classes fail if the stem is set. ComputeOutputParts
    # makes sure that stem == modulename in these cases.
    if self.android_stem != self.android_module:
      self.WriteLn('LOCAL_MODULE_STEM := ' + self.android_stem)
    self.WriteLn('LOCAL_MODULE_SUFFIX := ' + self.android_suffix)
    self.WriteLn('LOCAL_MODULE_TAGS := optional')
    if self.toolset == 'host':
      self.WriteLn('LOCAL_IS_HOST_MODULE := true')

    # Grab output directories; needed for Actions and Rules.
    self.WriteLn('gyp_intermediate_dir := $(call local-intermediates-dir)')
    self.WriteLn('gyp_shared_intermediate_dir := '
                 '$(call intermediates-dir-for,GYP,shared)')
    self.WriteLn()

    # List files this target depends on so that actions/rules/copies/sources
    # can depend on the list.
    # TODO: doesn't pull in things through transitive link deps; needed?
    target_dependencies = [x[1] for x in deps if x[0] == 'path']
    self.WriteLn('# Make sure our deps are built first.')
    self.WriteList(target_dependencies, 'GYP_TARGET_DEPENDENCIES',
                   local_pathify=True)

    # Actions must come first, since they can generate more OBJs for use below.
    if 'actions' in spec:
      self.WriteActions(spec['actions'], extra_sources, extra_outputs)

    # Rules must be early like actions.
    if 'rules' in spec:
      self.WriteRules(spec['rules'], extra_sources, extra_outputs)

    if 'copies' in spec:
      self.WriteCopies(spec['copies'], extra_outputs)

    # GYP generated outputs.
    self.WriteList(extra_outputs, 'GYP_GENERATED_OUTPUTS', local_pathify=True)

    # Set LOCAL_ADDITIONAL_DEPENDENCIES so that Android's build rules depend
    # on both our dependency targets and our generated files.
    self.WriteLn('# Make sure our deps and generated files are built first.')
    self.WriteLn('LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) '
                 '$(GYP_GENERATED_OUTPUTS)')
    self.WriteLn()

    # Sources.
    if spec.get('sources', []) or extra_sources:
      self.WriteSources(spec, configs, extra_sources)

    self.WriteTarget(spec, configs, deps, link_deps, part_of_all)

    # Update global list of target outputs, used in dependency tracking.
    target_outputs[qualified_target] = ('path', self.output_binary)

    # Update global list of link dependencies.
    if self.type == 'static_library':
      target_link_deps[qualified_target] = ('static', self.android_module)
    elif self.type == 'shared_library':
      target_link_deps[qualified_target] = ('shared', self.android_module)

    self.fp.close()
    return self.android_module
Exemple #5
0
def GenerateOutput(target_list, target_dicts, data, params):
  options = params['options']
  generator_flags = params.get('generator_flags', {})
  builddir_name = generator_flags.get('output_dir', 'out')
  limit_to_target_all = generator_flags.get('limit_to_target_all', False)
  android_top_dir = os.environ.get('ANDROID_BUILD_TOP')
  assert android_top_dir, '$ANDROID_BUILD_TOP not set; you need to run lunch.'

  def CalculateMakefilePath(build_file, base_name):
    """Determine where to write a Makefile for a given gyp file."""
    # Paths in gyp files are relative to the .gyp file, but we want
    # paths relative to the source root for the master makefile.  Grab
    # the path of the .gyp file as the base to relativize against.
    # E.g. "foo/bar" when we're constructing targets for "foo/bar/baz.gyp".
    base_path = gyp.common.RelativePath(os.path.dirname(build_file),
                                        options.depth)
    # We write the file in the base_path directory.
    output_file = os.path.join(options.depth, base_path, base_name)
    assert not options.generator_output, (
        'The Android backend does not support options.generator_output.')
    base_path = gyp.common.RelativePath(os.path.dirname(build_file),
                                        options.toplevel_dir)
    return base_path, output_file

  # TODO:  search for the first non-'Default' target.  This can go
  # away when we add verification that all targets have the
  # necessary configurations.
  default_configuration = None
  toolsets = set([target_dicts[target]['toolset'] for target in target_list])
  for target in target_list:
    spec = target_dicts[target]
    if spec['default_configuration'] != 'Default':
      default_configuration = spec['default_configuration']
      break
  if not default_configuration:
    default_configuration = 'Default'

  srcdir = '.'
  makefile_name = 'GypAndroid' + options.suffix + '.mk'
  makefile_path = os.path.join(options.toplevel_dir, makefile_name)
  assert not options.generator_output, (
      'The Android backend does not support options.generator_output.')
  make.ensure_directory_exists(makefile_path)
  root_makefile = open(makefile_path, 'w')

  root_makefile.write(header)

  # We set LOCAL_PATH just once, here, to the top of the project tree. This
  # allows all the other paths we use to be relative to the Android.mk file,
  # as the Android build system expects.
  root_makefile.write('\nLOCAL_PATH := $(call my-dir)\n')

  # Find the list of targets that derive from the gyp file(s) being built.
  needed_targets = set()
  for build_file in params['build_files']:
    for target in gyp.common.AllTargets(target_list, target_dicts, build_file):
      needed_targets.add(target)

  build_files = set()
  include_list = set()
  android_modules = {}
  for qualified_target in target_list:
    build_file, target, toolset = gyp.common.ParseQ
Exemple #6
0
def GenerateOutput(target_list, target_dicts, data, params):
    options = params["options"]
    generator_flags = params.get("generator_flags", {})
    builddir_name = generator_flags.get("output_dir", "out")
    limit_to_target_all = generator_flags.get("limit_to_target_all", False)
    android_top_dir = os.environ.get("ANDROID_BUILD_TOP")
    assert android_top_dir, "$ANDROID_BUILD_TOP not set; you need to run lunch."

    def CalculateMakefilePath(build_file, base_name):
        """Determine where to write a Makefile for a given gyp file."""
        # Paths in gyp files are relative to the .gyp file, but we want
        # paths relative to the source root for the master makefile.  Grab
        # the path of the .gyp file as the base to relativize against.
        # E.g. "foo/bar" when we're constructing targets for "foo/bar/baz.gyp".
        base_path = gyp.common.RelativePath(os.path.dirname(build_file), options.depth)
        # We write the file in the base_path directory.
        output_file = os.path.join(options.depth, base_path, base_name)
        assert not options.generator_output, "The Android backend does not support options.generator_output."
        base_path = gyp.common.RelativePath(os.path.dirname(build_file), options.toplevel_dir)
        return base_path, output_file

    # TODO:  search for the first non-'Default' target.  This can go
    # away when we add verification that all targets have the
    # necessary configurations.
    default_configuration = None
    toolsets = set([target_dicts[target]["toolset"] for target in target_list])
    for target in target_list:
        spec = target_dicts[target]
        if spec["default_configuration"] != "Default":
            default_configuration = spec["default_configuration"]
            break
    if not default_configuration:
        default_configuration = "Default"

    srcdir = "."
    makefile_name = "GypAndroid" + options.suffix + ".mk"
    makefile_path = os.path.join(options.toplevel_dir, makefile_name)
    assert not options.generator_output, "The Android backend does not support options.generator_output."
    make.ensure_directory_exists(makefile_path)
    root_makefile = open(makefile_path, "w")

    root_makefile.write(header)

    # We set LOCAL_PATH just once, here, to the top of the project tree. This
    # allows all the other paths we use to be relative to the Android.mk file,
    # as the Android build system expects.
    root_makefile.write("\nLOCAL_PATH := $(call my-dir)\n")

    # Find the list of targets that derive from the gyp file(s) being built.
    needed_targets = set()
    for build_file in params["build_files"]:
        for target in gyp.common.AllTargets(target_list, target_dicts, build_file):
            needed_targets.add(target)

    build_files = set()
    include_list = set()
    android_modules = {}
    for qualified_target in target_list:
        build_file, target, toolset = gyp.common.ParseQualifiedTarget(qualified_target)
        relative_build_file = gyp.common.RelativePath(build_file, options.toplevel_dir)
        build_files.add(relative_build_file)
        included_files = data[build_file]["included_files"]
        for included_file in included_files:
            # The included_files entries are relative to the dir of the build file
            # that included them, so we have to undo that and then make them relative
            # to the root dir.
            relative_include_file = gyp.common.RelativePath(
                gyp.common.UnrelativePath(included_file, build_file), options.toplevel_dir
            )
            abs_include_file = os.path.abspath(relative_include_file)
            # If the include file is from the ~/.gyp dir, we should use absolute path
            # so that relocating the src dir doesn't break the path.
            if params["home_dot_gyp"] and abs_include_file.startswith(params["home_dot_gyp"]):
                build_files.add(abs_include_file)
            else:
                build_files.add(relative_include_file)

        base_path, output_file = CalculateMakefilePath(build_file, target + "." + toolset + options.suffix + ".mk")

        spec = target_dicts[qualified_target]
        configs = spec["configurations"]

        part_of_all = qualified_target in needed_targets and not int(spec.get("suppress_wildcard", False))
        if limit_to_target_all and not part_of_all:
            continue

        relative_target = gyp.common.QualifiedTarget(relative_build_file, target, toolset)
        writer = AndroidMkWriter(android_top_dir)
        android_module = writer.Write(
            qualified_target, relative_target, base_path, output_file, spec, configs, part_of_all=part_of_all
        )
        if android_module in android_modules:
            print (
                "ERROR: Android module names must be unique. The following "
                "targets both generate Android module name %s.\n  %s\n  %s"
                % (android_module, android_modules[android_module], qualified_target)
            )
            return
        android_modules[android_module] = qualified_target

        # Our root_makefile lives at the source root.  Compute the relative path
        # from there to the output_file for including.
        mkfile_rel_path = gyp.common.RelativePath(output_file, os.path.dirname(makefile_path))
        include_list.add(mkfile_rel_path)

    root_makefile.write("GYP_CONFIGURATION ?= %s\n" % default_configuration)

    # Write out the sorted list of includes.
    root_makefile.write("\n")
    for include_file in sorted(include_list):
        root_makefile.write("include $(LOCAL_PATH)/" + include_file + "\n")
    root_makefile.write("\n")

    root_makefile.write(SHARED_FOOTER)

    root_makefile.close()