| Index: make_gyp_wrapper.py | 
| diff --git a/make_gyp_wrapper.py b/make_gyp_wrapper.py | 
| new file mode 100755 | 
| index 0000000000000000000000000000000000000000..1bf2761bfdc18be29950f44f26e971fe359df9b5 | 
| --- /dev/null | 
| +++ b/make_gyp_wrapper.py | 
| @@ -0,0 +1,122 @@ | 
| +#!/usr/bin/env python | 
| +# coding: utf-8 | 
| +"""This script fixes the support of manually compiled static libraries for | 
| +android NDK build system. | 
| + | 
| +Issue: | 
| +Let's say there are some manually compiled libraries specified in | 
| +link_settings.libraries or in ldflags of a gyp file. In this case ndk-build | 
| +passes them to a linker after system libraries, like c++_static, and | 
| +as the result linker cannot find functions from system libraries. | 
| + | 
| +Desire: | 
| +Pass manually compiled libraries after regular dependencies. | 
| + | 
| +How it works: | 
| +The recommended way to do it is to use LOCAL_STATIC_LIBRARIES. However, to | 
| +simply add libraries to the list is not enough because here ndk-build is trying | 
| +to be too smart and removes any libraries which are not defined in Makefiles. | 
| + | 
| +So, the idea is to monkey patch gyp to inject definition of static libraries | 
| +and add them to LOCAL_STATIC_LIBRARIES. The former is to prevent them from | 
| +being removed. | 
| + | 
| +Firstly some excerpts from gyp codebase: | 
| +source: gyp/pylib/gyp/generator/make.py | 
| + | 
| +MakefileWriter(object): | 
| +    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. | 
| +        ... | 
| +        if android: | 
| +           self.WriteAndroidNdkModuleRule(...) | 
| + | 
| +    def WriteAndroidNdkModuleRule(self, module_name, all_sources, link_deps): | 
| +    /* Write a set of LOCAL_XXX definitions for Android NDK. | 
| + | 
| +    These variable definitions will be used by Android NDK but do nothing for | 
| +    non-Android applications. | 
| + | 
| +    Arguments: | 
| +      module_name: Android NDK module name, which must be unique among all | 
| +          module names. | 
| +      all_sources: A list of source files (will be filtered by Compilable). | 
| +      link_deps: A list of link dependencies, which must be sorted in | 
| +          the order from dependencies to dependents. | 
| +    */ | 
| +        ... | 
| +        self.WriteList( | 
| +                DepsToModules(link_deps, | 
| +                              generator_default_variables['STATIC_LIB_PREFIX'], | 
| +                              generator_default_variables['STATIC_LIB_SUFFIX']), | 
| +                'LOCAL_STATIC_LIBRARIES') | 
| +        .... | 
| + | 
| +    def WriteList(self, value_list, variable=None, prefix='', | 
| +                quoter=QuoteIfNecessary): | 
| +    // Write a variable definition that is a list of values. | 
| + | 
| +The only class which is writing Makefiles is MakefileWriter and the "entry | 
| +point" is MakefileWriter.Write. To write LOCAL_STATIC_LIBRARIES it uses | 
| +MakefileWriter.WriteList, so one could simply override | 
| +- Write method to store all required information and to define (CLEAR_VARS, | 
| +  LOCAL_MODULE, etc) libraries. | 
| +- WriteList to change the value of LOCAL_STATIC_LIBRARIES. | 
| +However merely to reduce any potential influence we override | 
| +MakefileWriter.WriteAndroidNdkModuleRule to define manually compiled libraries | 
| +and override WriteList only while we are in the WriteAndroidNdkModuleRule method. | 
| +The aim of the latter method is exactly to write Rules for ndk-build and it is | 
| +called at the end of Write. However, since WriteAndroidNdkModuleRule lacks | 
| +required information, we override method Write to store configurations as | 
| +_abp_configs attribute of instance of MakefileWriter. | 
| +""" | 
| + | 
| +import os | 
| +import sys | 
| +import types | 
| + | 
| +base_dir = os.path.abspath(os.path.dirname(__file__)) | 
| +sys.path.append(os.path.join(base_dir, 'third_party', 'gyp', 'pylib')) | 
| +import gyp | 
| +from gyp.generator.make import MakefileWriter, QuoteIfNecessary | 
| + | 
| + | 
| +orig_MakefileWriter_Write = MakefileWriter.Write | 
| +orig_MakefileWriter_WriteAndroidNdkModuleRule = MakefileWriter.WriteAndroidNdkModuleRule | 
| + | 
| +def overridden_Write(self, qualified_target, base_path, output_filename, spec, configs, part_of_all): | 
| +    if hasattr(self, "_abp_configs"): | 
| +      sys.exit("MakefileWriter already has property _abp_configs") | 
| +    self._abp_configs = configs | 
| +    orig_MakefileWriter_Write(self, qualified_target, base_path, output_filename, spec, configs, part_of_all) | 
| +    delattr(self, "_abp_configs") | 
| + | 
| +def overridden_WriteAndroidNdkModuleRule(self, module_name, all_sources, link_deps): | 
| +    for config in self._abp_configs: | 
| +        libs = self._abp_configs[config].get("user_libraries") | 
| +        if not libs: | 
| +            continue | 
| +        self.WriteLn("ifeq (${{BUILDTYPE}}, {})".format(config)) | 
| +        for lib in libs: | 
| +            self.WriteLn("include $(CLEAR_VARS)") | 
| +            self.WriteLn("LOCAL_MODULE := {}".format(lib)) | 
| +            self.WriteLn("LOCAL_SRC_FILES := {}".format(lib)) | 
| +            self.WriteLn("include $(PREBUILT_STATIC_LIBRARY)") | 
| +            self.WriteLn("ABP_STATIC_LIBRARIES_${{BUILDTYPE}} += {}".format(lib)) | 
| +        self.WriteLn("endif") | 
| +    orig_WriteList = self.WriteList | 
| +    def overridden_WriteList(self, orig_value_list, variable=None, prefix='', quoter=QuoteIfNecessary): | 
| +        value_list = orig_value_list[:] | 
| +        if variable == "LOCAL_STATIC_LIBRARIES": | 
| +            value_list.append("${ABP_STATIC_LIBRARIES_${BUILDTYPE}}") | 
| +        orig_WriteList(value_list, variable, prefix, quoter) | 
| +    self.WriteList = types.MethodType(overridden_WriteList, self) | 
| +    orig_MakefileWriter_WriteAndroidNdkModuleRule(self, module_name, all_sources, link_deps) | 
| +    self.WriteList = orig_WriteList | 
| + | 
| +MakefileWriter.Write = overridden_Write | 
| +MakefileWriter.WriteAndroidNdkModuleRule = overridden_WriteAndroidNdkModuleRule | 
| + | 
| +if __name__ == '__main__': | 
| +    gyp.main(sys.argv[1:]) | 
|  |