"Fossies" - the Fresh Open Source Software Archive

Member "node-v12.18.4-win-x64/node_modules/npm/node_modules/node-gyp/gyp/pylib/gyp/generator/android.py" (14 Feb 2020, 46465 Bytes) of package /windows/www/node-v12.18.4-win-x64.zip:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) Python source code syntax highlighting (style: standard) with prefixed line numbers. Alternatively you can here view or download the uninterpreted source code file.

    1 # Copyright (c) 2012 Google Inc. All rights reserved.
    2 # Use of this source code is governed by a BSD-style license that can be
    3 # found in the LICENSE file.
    4 
    5 # Notes:
    6 #
    7 # This generates makefiles suitable for inclusion into the Android build system
    8 # via an Android.mk file. It is based on make.py, the standard makefile
    9 # generator.
   10 #
   11 # The code below generates a separate .mk file for each target, but
   12 # all are sourced by the top-level GypAndroid.mk.  This means that all
   13 # variables in .mk-files clobber one another, and furthermore that any
   14 # variables set potentially clash with other Android build system variables.
   15 # Try to avoid setting global variables where possible.
   16 
   17 from __future__ import print_function
   18 
   19 import gyp
   20 import gyp.common
   21 import gyp.generator.make as make  # Reuse global functions from make backend.
   22 import os
   23 import re
   24 import subprocess
   25 
   26 generator_default_variables = {
   27   'OS': 'android',
   28   'EXECUTABLE_PREFIX': '',
   29   'EXECUTABLE_SUFFIX': '',
   30   'STATIC_LIB_PREFIX': 'lib',
   31   'SHARED_LIB_PREFIX': 'lib',
   32   'STATIC_LIB_SUFFIX': '.a',
   33   'SHARED_LIB_SUFFIX': '.so',
   34   'INTERMEDIATE_DIR': '$(gyp_intermediate_dir)',
   35   'SHARED_INTERMEDIATE_DIR': '$(gyp_shared_intermediate_dir)',
   36   'PRODUCT_DIR': '$(gyp_shared_intermediate_dir)',
   37   'SHARED_LIB_DIR': '$(builddir)/lib.$(TOOLSET)',
   38   'LIB_DIR': '$(obj).$(TOOLSET)',
   39   'RULE_INPUT_ROOT': '%(INPUT_ROOT)s',  # This gets expanded by Python.
   40   'RULE_INPUT_DIRNAME': '%(INPUT_DIRNAME)s',  # This gets expanded by Python.
   41   'RULE_INPUT_PATH': '$(RULE_SOURCES)',
   42   'RULE_INPUT_EXT': '$(suffix $<)',
   43   'RULE_INPUT_NAME': '$(notdir $<)',
   44   'CONFIGURATION_NAME': '$(GYP_CONFIGURATION)',
   45 }
   46 
   47 # Make supports multiple toolsets
   48 generator_supports_multiple_toolsets = True
   49 
   50 
   51 # Generator-specific gyp specs.
   52 generator_additional_non_configuration_keys = [
   53     # Boolean to declare that this target does not want its name mangled.
   54     'android_unmangled_name',
   55     # Map of android build system variables to set.
   56     'aosp_build_settings',
   57 ]
   58 generator_additional_path_sections = []
   59 generator_extra_sources_for_rules = []
   60 
   61 
   62 ALL_MODULES_FOOTER = """\
   63 # "gyp_all_modules" is a concatenation of the "gyp_all_modules" targets from
   64 # all the included sub-makefiles. This is just here to clarify.
   65 gyp_all_modules:
   66 """
   67 
   68 header = """\
   69 # This file is generated by gyp; do not edit.
   70 
   71 """
   72 
   73 # Map gyp target types to Android module classes.
   74 MODULE_CLASSES = {
   75     'static_library': 'STATIC_LIBRARIES',
   76     'shared_library': 'SHARED_LIBRARIES',
   77     'executable': 'EXECUTABLES',
   78 }
   79 
   80 
   81 def IsCPPExtension(ext):
   82   return make.COMPILABLE_EXTENSIONS.get(ext) == 'cxx'
   83 
   84 
   85 def Sourceify(path):
   86   """Convert a path to its source directory form. The Android backend does not
   87      support options.generator_output, so this function is a noop."""
   88   return path
   89 
   90 
   91 # Map from qualified target to path to output.
   92 # For Android, the target of these maps is a tuple ('static', 'modulename'),
   93 # ('dynamic', 'modulename'), or ('path', 'some/path') instead of a string,
   94 # since we link by module.
   95 target_outputs = {}
   96 # Map from qualified target to any linkable output.  A subset
   97 # of target_outputs.  E.g. when mybinary depends on liba, we want to
   98 # include liba in the linker line; when otherbinary depends on
   99 # mybinary, we just want to build mybinary first.
  100 target_link_deps = {}
  101 
  102 
  103 class AndroidMkWriter(object):
  104   """AndroidMkWriter packages up the writing of one target-specific Android.mk.
  105 
  106   Its only real entry point is Write(), and is mostly used for namespacing.
  107   """
  108 
  109   def __init__(self, android_top_dir):
  110     self.android_top_dir = android_top_dir
  111 
  112   def Write(self, qualified_target, relative_target, base_path, output_filename,
  113             spec, configs, part_of_all, write_alias_target, sdk_version):
  114     """The main entry point: writes a .mk file for a single target.
  115 
  116     Arguments:
  117       qualified_target: target we're generating
  118       relative_target: qualified target name relative to the root
  119       base_path: path relative to source root we're building in, used to resolve
  120                  target-relative paths
  121       output_filename: output .mk file name to write
  122       spec, configs: gyp info
  123       part_of_all: flag indicating this target is part of 'all'
  124       write_alias_target: flag indicating whether to create short aliases for
  125                           this target
  126       sdk_version: what to emit for LOCAL_SDK_VERSION in output
  127     """
  128     gyp.common.EnsureDirExists(output_filename)
  129 
  130     self.fp = open(output_filename, 'w')
  131 
  132     self.fp.write(header)
  133 
  134     self.qualified_target = qualified_target
  135     self.relative_target = relative_target
  136     self.path = base_path
  137     self.target = spec['target_name']
  138     self.type = spec['type']
  139     self.toolset = spec['toolset']
  140 
  141     deps, link_deps = self.ComputeDeps(spec)
  142 
  143     # Some of the generation below can add extra output, sources, or
  144     # link dependencies.  All of the out params of the functions that
  145     # follow use names like extra_foo.
  146     extra_outputs = []
  147     extra_sources = []
  148 
  149     self.android_class = MODULE_CLASSES.get(self.type, 'GYP')
  150     self.android_module = self.ComputeAndroidModule(spec)
  151     (self.android_stem, self.android_suffix) = self.ComputeOutputParts(spec)
  152     self.output = self.output_binary = self.ComputeOutput(spec)
  153 
  154     # Standard header.
  155     self.WriteLn('include $(CLEAR_VARS)\n')
  156 
  157     # Module class and name.
  158     self.WriteLn('LOCAL_MODULE_CLASS := ' + self.android_class)
  159     self.WriteLn('LOCAL_MODULE := ' + self.android_module)
  160     # Only emit LOCAL_MODULE_STEM if it's different to LOCAL_MODULE.
  161     # The library module classes fail if the stem is set. ComputeOutputParts
  162     # makes sure that stem == modulename in these cases.
  163     if self.android_stem != self.android_module:
  164       self.WriteLn('LOCAL_MODULE_STEM := ' + self.android_stem)
  165     self.WriteLn('LOCAL_MODULE_SUFFIX := ' + self.android_suffix)
  166     if self.toolset == 'host':
  167       self.WriteLn('LOCAL_IS_HOST_MODULE := true')
  168       self.WriteLn('LOCAL_MULTILIB := $(GYP_HOST_MULTILIB)')
  169     elif sdk_version > 0:
  170       self.WriteLn('LOCAL_MODULE_TARGET_ARCH := '
  171                    '$(TARGET_$(GYP_VAR_PREFIX)ARCH)')
  172       self.WriteLn('LOCAL_SDK_VERSION := %s' % sdk_version)
  173 
  174     # Grab output directories; needed for Actions and Rules.
  175     if self.toolset == 'host':
  176       self.WriteLn('gyp_intermediate_dir := '
  177                    '$(call local-intermediates-dir,,$(GYP_HOST_VAR_PREFIX))')
  178     else:
  179       self.WriteLn('gyp_intermediate_dir := '
  180                    '$(call local-intermediates-dir,,$(GYP_VAR_PREFIX))')
  181     self.WriteLn('gyp_shared_intermediate_dir := '
  182                  '$(call intermediates-dir-for,GYP,shared,,,$(GYP_VAR_PREFIX))')
  183     self.WriteLn()
  184 
  185     # List files this target depends on so that actions/rules/copies/sources
  186     # can depend on the list.
  187     # TODO: doesn't pull in things through transitive link deps; needed?
  188     target_dependencies = [x[1] for x in deps if x[0] == 'path']
  189     self.WriteLn('# Make sure our deps are built first.')
  190     self.WriteList(target_dependencies, 'GYP_TARGET_DEPENDENCIES',
  191                    local_pathify=True)
  192 
  193     # Actions must come first, since they can generate more OBJs for use below.
  194     if 'actions' in spec:
  195       self.WriteActions(spec['actions'], extra_sources, extra_outputs)
  196 
  197     # Rules must be early like actions.
  198     if 'rules' in spec:
  199       self.WriteRules(spec['rules'], extra_sources, extra_outputs)
  200 
  201     if 'copies' in spec:
  202       self.WriteCopies(spec['copies'], extra_outputs)
  203 
  204     # GYP generated outputs.
  205     self.WriteList(extra_outputs, 'GYP_GENERATED_OUTPUTS', local_pathify=True)
  206 
  207     # Set LOCAL_ADDITIONAL_DEPENDENCIES so that Android's build rules depend
  208     # on both our dependency targets and our generated files.
  209     self.WriteLn('# Make sure our deps and generated files are built first.')
  210     self.WriteLn('LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) '
  211                  '$(GYP_GENERATED_OUTPUTS)')
  212     self.WriteLn()
  213 
  214     # Sources.
  215     if spec.get('sources', []) or extra_sources:
  216       self.WriteSources(spec, configs, extra_sources)
  217 
  218     self.WriteTarget(spec, configs, deps, link_deps, part_of_all,
  219                      write_alias_target)
  220 
  221     # Update global list of target outputs, used in dependency tracking.
  222     target_outputs[qualified_target] = ('path', self.output_binary)
  223 
  224     # Update global list of link dependencies.
  225     if self.type == 'static_library':
  226       target_link_deps[qualified_target] = ('static', self.android_module)
  227     elif self.type == 'shared_library':
  228       target_link_deps[qualified_target] = ('shared', self.android_module)
  229 
  230     self.fp.close()
  231     return self.android_module
  232 
  233 
  234   def WriteActions(self, actions, extra_sources, extra_outputs):
  235     """Write Makefile code for any 'actions' from the gyp input.
  236 
  237     extra_sources: a list that will be filled in with newly generated source
  238                    files, if any
  239     extra_outputs: a list that will be filled in with any outputs of these
  240                    actions (used to make other pieces dependent on these
  241                    actions)
  242     """
  243     for action in actions:
  244       name = make.StringToMakefileVariable('%s_%s' % (self.relative_target,
  245                                                       action['action_name']))
  246       self.WriteLn('### Rules for action "%s":' % action['action_name'])
  247       inputs = action['inputs']
  248       outputs = action['outputs']
  249 
  250       # Build up a list of outputs.
  251       # Collect the output dirs we'll need.
  252       dirs = set()
  253       for out in outputs:
  254         if not out.startswith('$'):
  255           print('WARNING: Action for target "%s" writes output to local path '
  256                  '"%s".' % (self.target, out))
  257         dir = os.path.split(out)[0]
  258         if dir:
  259           dirs.add(dir)
  260       if int(action.get('process_outputs_as_sources', False)):
  261         extra_sources += outputs
  262 
  263       # Prepare the actual command.
  264       command = gyp.common.EncodePOSIXShellList(action['action'])
  265       if 'message' in action:
  266         quiet_cmd = 'Gyp action: %s ($@)' % action['message']
  267       else:
  268         quiet_cmd = 'Gyp action: %s ($@)' % name
  269       if len(dirs) > 0:
  270         command = 'mkdir -p %s' % ' '.join(dirs) + '; ' + command
  271 
  272       cd_action = 'cd $(gyp_local_path)/%s; ' % self.path
  273       command = cd_action + command
  274 
  275       # The makefile rules are all relative to the top dir, but the gyp actions
  276       # are defined relative to their containing dir.  This replaces the gyp_*
  277       # variables for the action rule with an absolute version so that the
  278       # output goes in the right place.
  279       # Only write the gyp_* rules for the "primary" output (:1);
  280       # it's superfluous for the "extra outputs", and this avoids accidentally
  281       # writing duplicate dummy rules for those outputs.
  282       main_output = make.QuoteSpaces(self.LocalPathify(outputs[0]))
  283       self.WriteLn('%s: gyp_local_path := $(LOCAL_PATH)' % main_output)
  284       self.WriteLn('%s: gyp_var_prefix := $(GYP_VAR_PREFIX)' % main_output)
  285       self.WriteLn('%s: gyp_intermediate_dir := '
  286                    '$(abspath $(gyp_intermediate_dir))' % main_output)
  287       self.WriteLn('%s: gyp_shared_intermediate_dir := '
  288                    '$(abspath $(gyp_shared_intermediate_dir))' % main_output)
  289 
  290       # Android's envsetup.sh adds a number of directories to the path including
  291       # the built host binary directory. This causes actions/rules invoked by
  292       # gyp to sometimes use these instead of system versions, e.g. bison.
  293       # The built host binaries may not be suitable, and can cause errors.
  294       # So, we remove them from the PATH using the ANDROID_BUILD_PATHS variable
  295       # set by envsetup.
  296       self.WriteLn('%s: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))'
  297                    % main_output)
  298 
  299       # Don't allow spaces in input/output filenames, but make an exception for
  300       # filenames which start with '$(' since it's okay for there to be spaces
  301       # inside of make function/macro invocations.
  302       for input in inputs:
  303         if not input.startswith('$(') and ' ' in input:
  304           raise gyp.common.GypError(
  305               'Action input filename "%s" in target %s contains a space' %
  306               (input, self.target))
  307       for output in outputs:
  308         if not output.startswith('$(') and ' ' in output:
  309           raise gyp.common.GypError(
  310               'Action output filename "%s" in target %s contains a space' %
  311               (output, self.target))
  312 
  313       self.WriteLn('%s: %s $(GYP_TARGET_DEPENDENCIES)' %
  314                    (main_output, ' '.join(map(self.LocalPathify, inputs))))
  315       self.WriteLn('\t@echo "%s"' % quiet_cmd)
  316       self.WriteLn('\t$(hide)%s\n' % command)
  317       for output in outputs[1:]:
  318         # Make each output depend on the main output, with an empty command
  319         # to force make to notice that the mtime has changed.
  320         self.WriteLn('%s: %s ;' % (self.LocalPathify(output), main_output))
  321 
  322       extra_outputs += outputs
  323       self.WriteLn()
  324 
  325     self.WriteLn()
  326 
  327 
  328   def WriteRules(self, rules, extra_sources, extra_outputs):
  329     """Write Makefile code for any 'rules' from the gyp input.
  330 
  331     extra_sources: a list that will be filled in with newly generated source
  332                    files, if any
  333     extra_outputs: a list that will be filled in with any outputs of these
  334                    rules (used to make other pieces dependent on these rules)
  335     """
  336     if len(rules) == 0:
  337       return
  338 
  339     for rule in rules:
  340       if len(rule.get('rule_sources', [])) == 0:
  341         continue
  342       name = make.StringToMakefileVariable('%s_%s' % (self.relative_target,
  343                                                       rule['rule_name']))
  344       self.WriteLn('\n### Generated for rule "%s":' % name)
  345       self.WriteLn('# "%s":' % rule)
  346 
  347       inputs = rule.get('inputs')
  348       for rule_source in rule.get('rule_sources', []):
  349         (rule_source_dirname, rule_source_basename) = os.path.split(rule_source)
  350         (rule_source_root, rule_source_ext) = \
  351             os.path.splitext(rule_source_basename)
  352 
  353         outputs = [self.ExpandInputRoot(out, rule_source_root,
  354                                         rule_source_dirname)
  355                    for out in rule['outputs']]
  356 
  357         dirs = set()
  358         for out in outputs:
  359           if not out.startswith('$'):
  360             print('WARNING: Rule for target %s writes output to local path %s'
  361                    % (self.target, out))
  362           dir = os.path.dirname(out)
  363           if dir:
  364             dirs.add(dir)
  365         extra_outputs += outputs
  366         if int(rule.get('process_outputs_as_sources', False)):
  367           extra_sources.extend(outputs)
  368 
  369         components = []
  370         for component in rule['action']:
  371           component = self.ExpandInputRoot(component, rule_source_root,
  372                                            rule_source_dirname)
  373           if '$(RULE_SOURCES)' in component:
  374             component = component.replace('$(RULE_SOURCES)',
  375                                           rule_source)
  376           components.append(component)
  377 
  378         command = gyp.common.EncodePOSIXShellList(components)
  379         cd_action = 'cd $(gyp_local_path)/%s; ' % self.path
  380         command = cd_action + command
  381         if dirs:
  382           command = 'mkdir -p %s' % ' '.join(dirs) + '; ' + command
  383 
  384         # We set up a rule to build the first output, and then set up
  385         # a rule for each additional output to depend on the first.
  386         outputs = map(self.LocalPathify, outputs)
  387         main_output = outputs[0]
  388         self.WriteLn('%s: gyp_local_path := $(LOCAL_PATH)' % main_output)
  389         self.WriteLn('%s: gyp_var_prefix := $(GYP_VAR_PREFIX)' % main_output)
  390         self.WriteLn('%s: gyp_intermediate_dir := '
  391                      '$(abspath $(gyp_intermediate_dir))' % main_output)
  392         self.WriteLn('%s: gyp_shared_intermediate_dir := '
  393                      '$(abspath $(gyp_shared_intermediate_dir))' % main_output)
  394 
  395         # See explanation in WriteActions.
  396         self.WriteLn('%s: export PATH := '
  397                      '$(subst $(ANDROID_BUILD_PATHS),,$(PATH))' % main_output)
  398 
  399         main_output_deps = self.LocalPathify(rule_source)
  400         if inputs:
  401           main_output_deps += ' '
  402           main_output_deps += ' '.join([self.LocalPathify(f) for f in inputs])
  403 
  404         self.WriteLn('%s: %s $(GYP_TARGET_DEPENDENCIES)' %
  405                      (main_output, main_output_deps))
  406         self.WriteLn('\t%s\n' % command)
  407         for output in outputs[1:]:
  408           # Make each output depend on the main output, with an empty command
  409           # to force make to notice that the mtime has changed.
  410           self.WriteLn('%s: %s ;' % (output, main_output))
  411         self.WriteLn()
  412 
  413     self.WriteLn()
  414 
  415 
  416   def WriteCopies(self, copies, extra_outputs):
  417     """Write Makefile code for any 'copies' from the gyp input.
  418 
  419     extra_outputs: a list that will be filled in with any outputs of this action
  420                    (used to make other pieces dependent on this action)
  421     """
  422     self.WriteLn('### Generated for copy rule.')
  423 
  424     variable = make.StringToMakefileVariable(self.relative_target + '_copies')
  425     outputs = []
  426     for copy in copies:
  427       for path in copy['files']:
  428         # The Android build system does not allow generation of files into the
  429         # source tree. The destination should start with a variable, which will
  430         # typically be $(gyp_intermediate_dir) or
  431         # $(gyp_shared_intermediate_dir). Note that we can't use an assertion
  432         # because some of the gyp tests depend on this.
  433         if not copy['destination'].startswith('$'):
  434           print('WARNING: Copy rule for target %s writes output to '
  435                  'local path %s' % (self.target, copy['destination']))
  436 
  437         # LocalPathify() calls normpath, stripping trailing slashes.
  438         path = Sourceify(self.LocalPathify(path))
  439         filename = os.path.split(path)[1]
  440         output = Sourceify(self.LocalPathify(os.path.join(copy['destination'],
  441                                                           filename)))
  442 
  443         self.WriteLn('%s: %s $(GYP_TARGET_DEPENDENCIES) | $(ACP)' %
  444                      (output, path))
  445         self.WriteLn('\t@echo Copying: $@')
  446         self.WriteLn('\t$(hide) mkdir -p $(dir $@)')
  447         self.WriteLn('\t$(hide) $(ACP) -rpf $< $@')
  448         self.WriteLn()
  449         outputs.append(output)
  450     self.WriteLn('%s = %s' % (variable,
  451                               ' '.join(map(make.QuoteSpaces, outputs))))
  452     extra_outputs.append('$(%s)' % variable)
  453     self.WriteLn()
  454 
  455 
  456   def WriteSourceFlags(self, spec, configs):
  457     """Write out the flags and include paths used to compile source files for
  458     the current target.
  459 
  460     Args:
  461       spec, configs: input from gyp.
  462     """
  463     for configname, config in sorted(configs.items()):
  464       extracted_includes = []
  465 
  466       self.WriteLn('\n# Flags passed to both C and C++ files.')
  467       cflags, includes_from_cflags = self.ExtractIncludesFromCFlags(
  468           config.get('cflags', []) + config.get('cflags_c', []))
  469       extracted_includes.extend(includes_from_cflags)
  470       self.WriteList(cflags, 'MY_CFLAGS_%s' % configname)
  471 
  472       self.WriteList(config.get('defines'), 'MY_DEFS_%s' % configname,
  473                      prefix='-D', quoter=make.EscapeCppDefine)
  474 
  475       self.WriteLn('\n# Include paths placed before CFLAGS/CPPFLAGS')
  476       includes = list(config.get('include_dirs', []))
  477       includes.extend(extracted_includes)
  478       includes = map(Sourceify, map(self.LocalPathify, includes))
  479       includes = self.NormalizeIncludePaths(includes)
  480       self.WriteList(includes, 'LOCAL_C_INCLUDES_%s' % configname)
  481 
  482       self.WriteLn('\n# Flags passed to only C++ (and not C) files.')
  483       self.WriteList(config.get('cflags_cc'), 'LOCAL_CPPFLAGS_%s' % configname)
  484 
  485     self.WriteLn('\nLOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) '
  486                  '$(MY_DEFS_$(GYP_CONFIGURATION))')
  487     # Undefine ANDROID for host modules
  488     # TODO: the source code should not use macro ANDROID to tell if it's host
  489     # or target module.
  490     if self.toolset == 'host':
  491       self.WriteLn('# Undefine ANDROID for host modules')
  492       self.WriteLn('LOCAL_CFLAGS += -UANDROID')
  493     self.WriteLn('LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) '
  494                                      '$(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))')
  495     self.WriteLn('LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))')
  496     # Android uses separate flags for assembly file invocations, but gyp expects
  497     # the same CFLAGS to be applied:
  498     self.WriteLn('LOCAL_ASFLAGS := $(LOCAL_CFLAGS)')
  499 
  500 
  501   def WriteSources(self, spec, configs, extra_sources):
  502     """Write Makefile code for any 'sources' from the gyp input.
  503     These are source files necessary to build the current target.
  504     We need to handle shared_intermediate directory source files as
  505     a special case by copying them to the intermediate directory and
  506     treating them as a genereated sources. Otherwise the Android build
  507     rules won't pick them up.
  508 
  509     Args:
  510       spec, configs: input from gyp.
  511       extra_sources: Sources generated from Actions or Rules.
  512     """
  513     sources = filter(make.Compilable, spec.get('sources', []))
  514     generated_not_sources = [x for x in extra_sources if not make.Compilable(x)]
  515     extra_sources = filter(make.Compilable, extra_sources)
  516 
  517     # Determine and output the C++ extension used by these sources.
  518     # We simply find the first C++ file and use that extension.
  519     all_sources = sources + extra_sources
  520     local_cpp_extension = '.cpp'
  521     for source in all_sources:
  522       (root, ext) = os.path.splitext(source)
  523       if IsCPPExtension(ext):
  524         local_cpp_extension = ext
  525         break
  526     if local_cpp_extension != '.cpp':
  527       self.WriteLn('LOCAL_CPP_EXTENSION := %s' % local_cpp_extension)
  528 
  529     # We need to move any non-generated sources that are coming from the
  530     # shared intermediate directory out of LOCAL_SRC_FILES and put them
  531     # into LOCAL_GENERATED_SOURCES. We also need to move over any C++ files
  532     # that don't match our local_cpp_extension, since Android will only
  533     # generate Makefile rules for a single LOCAL_CPP_EXTENSION.
  534     local_files = []
  535     for source in sources:
  536       (root, ext) = os.path.splitext(source)
  537       if '$(gyp_shared_intermediate_dir)' in source:
  538         extra_sources.append(source)
  539       elif '$(gyp_intermediate_dir)' in source:
  540         extra_sources.append(source)
  541       elif IsCPPExtension(ext) and ext != local_cpp_extension:
  542         extra_sources.append(source)
  543       else:
  544         local_files.append(os.path.normpath(os.path.join(self.path, source)))
  545 
  546     # For any generated source, if it is coming from the shared intermediate
  547     # directory then we add a Make rule to copy them to the local intermediate
  548     # directory first. This is because the Android LOCAL_GENERATED_SOURCES
  549     # must be in the local module intermediate directory for the compile rules
  550     # to work properly. If the file has the wrong C++ extension, then we add
  551     # a rule to copy that to intermediates and use the new version.
  552     final_generated_sources = []
  553     # If a source file gets copied, we still need to add the original source
  554     # directory as header search path, for GCC searches headers in the
  555     # directory that contains the source file by default.
  556     origin_src_dirs = []
  557     for source in extra_sources:
  558       local_file = source
  559       if not '$(gyp_intermediate_dir)/' in local_file:
  560         basename = os.path.basename(local_file)
  561         local_file = '$(gyp_intermediate_dir)/' + basename
  562       (root, ext) = os.path.splitext(local_file)
  563       if IsCPPExtension(ext) and ext != local_cpp_extension:
  564         local_file = root + local_cpp_extension
  565       if local_file != source:
  566         self.WriteLn('%s: %s' % (local_file, self.LocalPathify(source)))
  567         self.WriteLn('\tmkdir -p $(@D); cp $< $@')
  568         origin_src_dirs.append(os.path.dirname(source))
  569       final_generated_sources.append(local_file)
  570 
  571     # We add back in all of the non-compilable stuff to make sure that the
  572     # make rules have dependencies on them.
  573     final_generated_sources.extend(generated_not_sources)
  574     self.WriteList(final_generated_sources, 'LOCAL_GENERATED_SOURCES')
  575 
  576     origin_src_dirs = gyp.common.uniquer(origin_src_dirs)
  577     origin_src_dirs = map(Sourceify, map(self.LocalPathify, origin_src_dirs))
  578     self.WriteList(origin_src_dirs, 'GYP_COPIED_SOURCE_ORIGIN_DIRS')
  579 
  580     self.WriteList(local_files, 'LOCAL_SRC_FILES')
  581 
  582     # Write out the flags used to compile the source; this must be done last
  583     # so that GYP_COPIED_SOURCE_ORIGIN_DIRS can be used as an include path.
  584     self.WriteSourceFlags(spec, configs)
  585 
  586 
  587   def ComputeAndroidModule(self, spec):
  588     """Return the Android module name used for a gyp spec.
  589 
  590     We use the complete qualified target name to avoid collisions between
  591     duplicate targets in different directories. We also add a suffix to
  592     distinguish gyp-generated module names.
  593     """
  594 
  595     if int(spec.get('android_unmangled_name', 0)):
  596       assert self.type != 'shared_library' or self.target.startswith('lib')
  597       return self.target
  598 
  599     if self.type == 'shared_library':
  600       # For reasons of convention, the Android build system requires that all
  601       # shared library modules are named 'libfoo' when generating -l flags.
  602       prefix = 'lib_'
  603     else:
  604       prefix = ''
  605 
  606     if spec['toolset'] == 'host':
  607       suffix = '_$(TARGET_$(GYP_VAR_PREFIX)ARCH)_host_gyp'
  608     else:
  609       suffix = '_gyp'
  610 
  611     if self.path:
  612       middle = make.StringToMakefileVariable('%s_%s' % (self.path, self.target))
  613     else:
  614       middle = make.StringToMakefileVariable(self.target)
  615 
  616     return ''.join([prefix, middle, suffix])
  617 
  618 
  619   def ComputeOutputParts(self, spec):
  620     """Return the 'output basename' of a gyp spec, split into filename + ext.
  621 
  622     Android libraries must be named the same thing as their module name,
  623     otherwise the linker can't find them, so product_name and so on must be
  624     ignored if we are building a library, and the "lib" prepending is
  625     not done for Android.
  626     """
  627     assert self.type != 'loadable_module' # TODO: not supported?
  628 
  629     target = spec['target_name']
  630     target_prefix = ''
  631     target_ext = ''
  632     if self.type == 'static_library':
  633       target = self.ComputeAndroidModule(spec)
  634       target_ext = '.a'
  635     elif self.type == 'shared_library':
  636       target = self.ComputeAndroidModule(spec)
  637       target_ext = '.so'
  638     elif self.type == 'none':
  639       target_ext = '.stamp'
  640     elif self.type != 'executable':
  641       print("ERROR: What output file should be generated?",
  642              "type", self.type, "target", target)
  643 
  644     if self.type != 'static_library' and self.type != 'shared_library':
  645       target_prefix = spec.get('product_prefix', target_prefix)
  646       target = spec.get('product_name', target)
  647       product_ext = spec.get('product_extension')
  648       if product_ext:
  649         target_ext = '.' + product_ext
  650 
  651     target_stem = target_prefix + target
  652     return (target_stem, target_ext)
  653 
  654 
  655   def ComputeOutputBasename(self, spec):
  656     """Return the 'output basename' of a gyp spec.
  657 
  658     E.g., the loadable module 'foobar' in directory 'baz' will produce
  659       'libfoobar.so'
  660     """
  661     return ''.join(self.ComputeOutputParts(spec))
  662 
  663 
  664   def ComputeOutput(self, spec):
  665     """Return the 'output' (full output path) of a gyp spec.
  666 
  667     E.g., the loadable module 'foobar' in directory 'baz' will produce
  668       '$(obj)/baz/libfoobar.so'
  669     """
  670     if self.type == 'executable':
  671       # We install host executables into shared_intermediate_dir so they can be
  672       # run by gyp rules that refer to PRODUCT_DIR.
  673       path = '$(gyp_shared_intermediate_dir)'
  674     elif self.type == 'shared_library':
  675       if self.toolset == 'host':
  676         path = '$($(GYP_HOST_VAR_PREFIX)HOST_OUT_INTERMEDIATE_LIBRARIES)'
  677       else:
  678         path = '$($(GYP_VAR_PREFIX)TARGET_OUT_INTERMEDIATE_LIBRARIES)'
  679     else:
  680       # Other targets just get built into their intermediate dir.
  681       if self.toolset == 'host':
  682         path = ('$(call intermediates-dir-for,%s,%s,true,,'
  683                 '$(GYP_HOST_VAR_PREFIX))' % (self.android_class,
  684                                              self.android_module))
  685       else:
  686         path = ('$(call intermediates-dir-for,%s,%s,,,$(GYP_VAR_PREFIX))'
  687                 % (self.android_class, self.android_module))
  688 
  689     assert spec.get('product_dir') is None # TODO: not supported?
  690     return os.path.join(path, self.ComputeOutputBasename(spec))
  691 
  692   def NormalizeIncludePaths(self, include_paths):
  693     """ Normalize include_paths.
  694     Convert absolute paths to relative to the Android top directory.
  695 
  696     Args:
  697       include_paths: A list of unprocessed include paths.
  698     Returns:
  699       A list of normalized include paths.
  700     """
  701     normalized = []
  702     for path in include_paths:
  703       if path[0] == '/':
  704         path = gyp.common.RelativePath(path, self.android_top_dir)
  705       normalized.append(path)
  706     return normalized
  707 
  708   def ExtractIncludesFromCFlags(self, cflags):
  709     """Extract includes "-I..." out from cflags
  710 
  711     Args:
  712       cflags: A list of compiler flags, which may be mixed with "-I.."
  713     Returns:
  714       A tuple of lists: (clean_clfags, include_paths). "-I.." is trimmed.
  715     """
  716     clean_cflags = []
  717     include_paths = []
  718     for flag in cflags:
  719       if flag.startswith('-I'):
  720         include_paths.append(flag[2:])
  721       else:
  722         clean_cflags.append(flag)
  723 
  724     return (clean_cflags, include_paths)
  725 
  726   def FilterLibraries(self, libraries):
  727     """Filter the 'libraries' key to separate things that shouldn't be ldflags.
  728 
  729     Library entries that look like filenames should be converted to android
  730     module names instead of being passed to the linker as flags.
  731 
  732     Args:
  733       libraries: the value of spec.get('libraries')
  734     Returns:
  735       A tuple (static_lib_modules, dynamic_lib_modules, ldflags)
  736     """
  737     static_lib_modules = []
  738     dynamic_lib_modules = []
  739     ldflags = []
  740     for libs in libraries:
  741       # Libs can have multiple words.
  742       for lib in libs.split():
  743         # Filter the system libraries, which are added by default by the Android
  744         # build system.
  745         if (lib == '-lc' or lib == '-lstdc++' or lib == '-lm' or
  746             lib.endswith('libgcc.a')):
  747           continue
  748         match = re.search(r'([^/]+)\.a$', lib)
  749         if match:
  750           static_lib_modules.append(match.group(1))
  751           continue
  752         match = re.search(r'([^/]+)\.so$', lib)
  753         if match:
  754           dynamic_lib_modules.append(match.group(1))
  755           continue
  756         if lib.startswith('-l'):
  757           ldflags.append(lib)
  758     return (static_lib_modules, dynamic_lib_modules, ldflags)
  759 
  760 
  761   def ComputeDeps(self, spec):
  762     """Compute the dependencies of a gyp spec.
  763 
  764     Returns a tuple (deps, link_deps), where each is a list of
  765     filenames that will need to be put in front of make for either
  766     building (deps) or linking (link_deps).
  767     """
  768     deps = []
  769     link_deps = []
  770     if 'dependencies' in spec:
  771       deps.extend([target_outputs[dep] for dep in spec['dependencies']
  772                    if target_outputs[dep]])
  773       for dep in spec['dependencies']:
  774         if dep in target_link_deps:
  775           link_deps.append(target_link_deps[dep])
  776       deps.extend(link_deps)
  777     return (gyp.common.uniquer(deps), gyp.common.uniquer(link_deps))
  778 
  779 
  780   def WriteTargetFlags(self, spec, configs, link_deps):
  781     """Write Makefile code to specify the link flags and library dependencies.
  782 
  783     spec, configs: input from gyp.
  784     link_deps: link dependency list; see ComputeDeps()
  785     """
  786     # Libraries (i.e. -lfoo)
  787     # These must be included even for static libraries as some of them provide
  788     # implicit include paths through the build system.
  789     libraries = gyp.common.uniquer(spec.get('libraries', []))
  790     static_libs, dynamic_libs, ldflags_libs = self.FilterLibraries(libraries)
  791 
  792     if self.type != 'static_library':
  793       for configname, config in sorted(configs.items()):
  794         ldflags = list(config.get('ldflags', []))
  795         self.WriteLn('')
  796         self.WriteList(ldflags, 'LOCAL_LDFLAGS_%s' % configname)
  797       self.WriteList(ldflags_libs, 'LOCAL_GYP_LIBS')
  798       self.WriteLn('LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION)) '
  799                    '$(LOCAL_GYP_LIBS)')
  800 
  801     # Link dependencies (i.e. other gyp targets this target depends on)
  802     # These need not be included for static libraries as within the gyp build
  803     # we do not use the implicit include path mechanism.
  804     if self.type != 'static_library':
  805       static_link_deps = [x[1] for x in link_deps if x[0] == 'static']
  806       shared_link_deps = [x[1] for x in link_deps if x[0] == 'shared']
  807     else:
  808       static_link_deps = []
  809       shared_link_deps = []
  810 
  811     # Only write the lists if they are non-empty.
  812     if static_libs or static_link_deps:
  813       self.WriteLn('')
  814       self.WriteList(static_libs + static_link_deps,
  815                      'LOCAL_STATIC_LIBRARIES')
  816       self.WriteLn('# Enable grouping to fix circular references')
  817       self.WriteLn('LOCAL_GROUP_STATIC_LIBRARIES := true')
  818     if dynamic_libs or shared_link_deps:
  819       self.WriteLn('')
  820       self.WriteList(dynamic_libs + shared_link_deps,
  821                      'LOCAL_SHARED_LIBRARIES')
  822 
  823 
  824   def WriteTarget(self, spec, configs, deps, link_deps, part_of_all,
  825                   write_alias_target):
  826     """Write Makefile code to produce the final target of the gyp spec.
  827 
  828     spec, configs: input from gyp.
  829     deps, link_deps: dependency lists; see ComputeDeps()
  830     part_of_all: flag indicating this target is part of 'all'
  831     write_alias_target: flag indicating whether to create short aliases for this
  832                         target
  833     """
  834     self.WriteLn('### Rules for final target.')
  835 
  836     if self.type != 'none':
  837       self.WriteTargetFlags(spec, configs, link_deps)
  838 
  839     settings = spec.get('aosp_build_settings', {})
  840     if settings:
  841       self.WriteLn('### Set directly by aosp_build_settings.')
  842       for k, v in settings.items():
  843         if isinstance(v, list):
  844           self.WriteList(v, k)
  845         else:
  846           self.WriteLn('%s := %s' % (k, make.QuoteIfNecessary(v)))
  847       self.WriteLn('')
  848 
  849     # Add to the set of targets which represent the gyp 'all' target. We use the
  850     # name 'gyp_all_modules' as the Android build system doesn't allow the use
  851     # of the Make target 'all' and because 'all_modules' is the equivalent of
  852     # the Make target 'all' on Android.
  853     if part_of_all and write_alias_target:
  854       self.WriteLn('# Add target alias to "gyp_all_modules" target.')
  855       self.WriteLn('.PHONY: gyp_all_modules')
  856       self.WriteLn('gyp_all_modules: %s' % self.android_module)
  857       self.WriteLn('')
  858 
  859     # Add an alias from the gyp target name to the Android module name. This
  860     # simplifies manual builds of the target, and is required by the test
  861     # framework.
  862     if self.target != self.android_module and write_alias_target:
  863       self.WriteLn('# Alias gyp target name.')
  864       self.WriteLn('.PHONY: %s' % self.target)
  865       self.WriteLn('%s: %s' % (self.target, self.android_module))
  866       self.WriteLn('')
  867 
  868     # Add the command to trigger build of the target type depending
  869     # on the toolset. Ex: BUILD_STATIC_LIBRARY vs. BUILD_HOST_STATIC_LIBRARY
  870     # NOTE: This has to come last!
  871     modifier = ''
  872     if self.toolset == 'host':
  873       modifier = 'HOST_'
  874     if self.type == 'static_library':
  875       self.WriteLn('include $(BUILD_%sSTATIC_LIBRARY)' % modifier)
  876     elif self.type == 'shared_library':
  877       self.WriteLn('LOCAL_PRELINK_MODULE := false')
  878       self.WriteLn('include $(BUILD_%sSHARED_LIBRARY)' % modifier)
  879     elif self.type == 'executable':
  880       self.WriteLn('LOCAL_CXX_STL := libc++_static')
  881       # Executables are for build and test purposes only, so they're installed
  882       # to a directory that doesn't get included in the system image.
  883       self.WriteLn('LOCAL_MODULE_PATH := $(gyp_shared_intermediate_dir)')
  884       self.WriteLn('include $(BUILD_%sEXECUTABLE)' % modifier)
  885     else:
  886       self.WriteLn('LOCAL_MODULE_PATH := $(PRODUCT_OUT)/gyp_stamp')
  887       self.WriteLn('LOCAL_UNINSTALLABLE_MODULE := true')
  888       if self.toolset == 'target':
  889         self.WriteLn('LOCAL_2ND_ARCH_VAR_PREFIX := $(GYP_VAR_PREFIX)')
  890       else:
  891         self.WriteLn('LOCAL_2ND_ARCH_VAR_PREFIX := $(GYP_HOST_VAR_PREFIX)')
  892       self.WriteLn()
  893       self.WriteLn('include $(BUILD_SYSTEM)/base_rules.mk')
  894       self.WriteLn()
  895       self.WriteLn('$(LOCAL_BUILT_MODULE): $(LOCAL_ADDITIONAL_DEPENDENCIES)')
  896       self.WriteLn('\t$(hide) echo "Gyp timestamp: $@"')
  897       self.WriteLn('\t$(hide) mkdir -p $(dir $@)')
  898       self.WriteLn('\t$(hide) touch $@')
  899       self.WriteLn()
  900       self.WriteLn('LOCAL_2ND_ARCH_VAR_PREFIX :=')
  901 
  902 
  903   def WriteList(self, value_list, variable=None, prefix='',
  904                 quoter=make.QuoteIfNecessary, local_pathify=False):
  905     """Write a variable definition that is a list of values.
  906 
  907     E.g. WriteList(['a','b'], 'foo', prefix='blah') writes out
  908          foo = blaha blahb
  909     but in a pretty-printed style.
  910     """
  911     values = ''
  912     if value_list:
  913       value_list = [quoter(prefix + l) for l in value_list]
  914       if local_pathify:
  915         value_list = [self.LocalPathify(l) for l in value_list]
  916       values = ' \\\n\t' + ' \\\n\t'.join(value_list)
  917     self.fp.write('%s :=%s\n\n' % (variable, values))
  918 
  919 
  920   def WriteLn(self, text=''):
  921     self.fp.write(text + '\n')
  922 
  923 
  924   def LocalPathify(self, path):
  925     """Convert a subdirectory-relative path into a normalized path which starts
  926     with the make variable $(LOCAL_PATH) (i.e. the top of the project tree).
  927     Absolute paths, or paths that contain variables, are just normalized."""
  928     if '$(' in path or os.path.isabs(path):
  929       # path is not a file in the project tree in this case, but calling
  930       # normpath is still important for trimming trailing slashes.
  931       return os.path.normpath(path)
  932     local_path = os.path.join('$(LOCAL_PATH)', self.path, path)
  933     local_path = os.path.normpath(local_path)
  934     # Check that normalizing the path didn't ../ itself out of $(LOCAL_PATH)
  935     # - i.e. that the resulting path is still inside the project tree. The
  936     # path may legitimately have ended up containing just $(LOCAL_PATH), though,
  937     # so we don't look for a slash.
  938     assert local_path.startswith('$(LOCAL_PATH)'), (
  939            'Path %s attempts to escape from gyp path %s !)' % (path, self.path))
  940     return local_path
  941 
  942 
  943   def ExpandInputRoot(self, template, expansion, dirname):
  944     if '%(INPUT_ROOT)s' not in template and '%(INPUT_DIRNAME)s' not in template:
  945       return template
  946     path = template % {
  947         'INPUT_ROOT': expansion,
  948         'INPUT_DIRNAME': dirname,
  949         }
  950     return os.path.normpath(path)
  951 
  952 
  953 def PerformBuild(data, configurations, params):
  954   # The android backend only supports the default configuration.
  955   options = params['options']
  956   makefile = os.path.abspath(os.path.join(options.toplevel_dir,
  957                                           'GypAndroid.mk'))
  958   env = dict(os.environ)
  959   env['ONE_SHOT_MAKEFILE'] = makefile
  960   arguments = ['make', '-C', os.environ['ANDROID_BUILD_TOP'], 'gyp_all_modules']
  961   print('Building: %s' % arguments)
  962   subprocess.check_call(arguments, env=env)
  963 
  964 
  965 def GenerateOutput(target_list, target_dicts, data, params):
  966   options = params['options']
  967   generator_flags = params.get('generator_flags', {})
  968   builddir_name = generator_flags.get('output_dir', 'out')
  969   limit_to_target_all = generator_flags.get('limit_to_target_all', False)
  970   write_alias_targets = generator_flags.get('write_alias_targets', True)
  971   sdk_version = generator_flags.get('aosp_sdk_version', 0)
  972   android_top_dir = os.environ.get('ANDROID_BUILD_TOP')
  973   assert android_top_dir, '$ANDROID_BUILD_TOP not set; you need to run lunch.'
  974 
  975   def CalculateMakefilePath(build_file, base_name):
  976     """Determine where to write a Makefile for a given gyp file."""
  977     # Paths in gyp files are relative to the .gyp file, but we want
  978     # paths relative to the source root for the master makefile.  Grab
  979     # the path of the .gyp file as the base to relativize against.
  980     # E.g. "foo/bar" when we're constructing targets for "foo/bar/baz.gyp".
  981     base_path = gyp.common.RelativePath(os.path.dirname(build_file),
  982                                         options.depth)
  983     # We write the file in the base_path directory.
  984     output_file = os.path.join(options.depth, base_path, base_name)
  985     assert not options.generator_output, (
  986         'The Android backend does not support options.generator_output.')
  987     base_path = gyp.common.RelativePath(os.path.dirname(build_file),
  988                                         options.toplevel_dir)
  989     return base_path, output_file
  990 
  991   # TODO:  search for the first non-'Default' target.  This can go
  992   # away when we add verification that all targets have the
  993   # necessary configurations.
  994   default_configuration = None
  995   toolsets = set([target_dicts[target]['toolset'] for target in target_list])
  996   for target in target_list:
  997     spec = target_dicts[target]
  998     if spec['default_configuration'] != 'Default':
  999       default_configuration = spec['default_configuration']
 1000       break
 1001   if not default_configuration:
 1002     default_configuration = 'Default'
 1003 
 1004   srcdir = '.'
 1005   makefile_name = 'GypAndroid' + options.suffix + '.mk'
 1006   makefile_path = os.path.join(options.toplevel_dir, makefile_name)
 1007   assert not options.generator_output, (
 1008       'The Android backend does not support options.generator_output.')
 1009   gyp.common.EnsureDirExists(makefile_path)
 1010   root_makefile = open(makefile_path, 'w')
 1011 
 1012   root_makefile.write(header)
 1013 
 1014   # We set LOCAL_PATH just once, here, to the top of the project tree. This
 1015   # allows all the other paths we use to be relative to the Android.mk file,
 1016   # as the Android build system expects.
 1017   root_makefile.write('\nLOCAL_PATH := $(call my-dir)\n')
 1018 
 1019   # Find the list of targets that derive from the gyp file(s) being built.
 1020   needed_targets = set()
 1021   for build_file in params['build_files']:
 1022     for target in gyp.common.AllTargets(target_list, target_dicts, build_file):
 1023       needed_targets.add(target)
 1024 
 1025   build_files = set()
 1026   include_list = set()
 1027   android_modules = {}
 1028   for qualified_target in target_list:
 1029     build_file, target, toolset = gyp.common.ParseQualifiedTarget(
 1030         qualified_target)
 1031     relative_build_file = gyp.common.RelativePath(build_file,
 1032                                                   options.toplevel_dir)
 1033     build_files.add(relative_build_file)
 1034     included_files = data[build_file]['included_files']
 1035     for included_file in included_files:
 1036       # The included_files entries are relative to the dir of the build file
 1037       # that included them, so we have to undo that and then make them relative
 1038       # to the root dir.
 1039       relative_include_file = gyp.common.RelativePath(
 1040           gyp.common.UnrelativePath(included_file, build_file),
 1041           options.toplevel_dir)
 1042       abs_include_file = os.path.abspath(relative_include_file)
 1043       # If the include file is from the ~/.gyp dir, we should use absolute path
 1044       # so that relocating the src dir doesn't break the path.
 1045       if (params['home_dot_gyp'] and
 1046           abs_include_file.startswith(params['home_dot_gyp'])):
 1047         build_files.add(abs_include_file)
 1048       else:
 1049         build_files.add(relative_include_file)
 1050 
 1051     base_path, output_file = CalculateMakefilePath(build_file,
 1052         target + '.' + toolset + options.suffix + '.mk')
 1053 
 1054     spec = target_dicts[qualified_target]
 1055     configs = spec['configurations']
 1056 
 1057     part_of_all = qualified_target in needed_targets
 1058     if limit_to_target_all and not part_of_all:
 1059       continue
 1060 
 1061     relative_target = gyp.common.QualifiedTarget(relative_build_file, target,
 1062                                                  toolset)
 1063     writer = AndroidMkWriter(android_top_dir)
 1064     android_module = writer.Write(qualified_target, relative_target, base_path,
 1065                                   output_file, spec, configs,
 1066                                   part_of_all=part_of_all,
 1067                                   write_alias_target=write_alias_targets,
 1068                                   sdk_version=sdk_version)
 1069     if android_module in android_modules:
 1070       print('ERROR: Android module names must be unique. The following '
 1071              'targets both generate Android module name %s.\n  %s\n  %s' %
 1072              (android_module, android_modules[android_module],
 1073               qualified_target))
 1074       return
 1075     android_modules[android_module] = qualified_target
 1076 
 1077     # Our root_makefile lives at the source root.  Compute the relative path
 1078     # from there to the output_file for including.
 1079     mkfile_rel_path = gyp.common.RelativePath(output_file,
 1080                                               os.path.dirname(makefile_path))
 1081     include_list.add(mkfile_rel_path)
 1082 
 1083   root_makefile.write('GYP_CONFIGURATION ?= %s\n' % default_configuration)
 1084   root_makefile.write('GYP_VAR_PREFIX ?=\n')
 1085   root_makefile.write('GYP_HOST_VAR_PREFIX ?=\n')
 1086   root_makefile.write('GYP_HOST_MULTILIB ?= first\n')
 1087 
 1088   # Write out the sorted list of includes.
 1089   root_makefile.write('\n')
 1090   for include_file in sorted(include_list):
 1091     root_makefile.write('include $(LOCAL_PATH)/' + include_file + '\n')
 1092   root_makefile.write('\n')
 1093 
 1094   if write_alias_targets:
 1095     root_makefile.write(ALL_MODULES_FOOTER)
 1096 
 1097   root_makefile.close()