OLD | NEW |
1 #!/usr/bin/env python | 1 #!/usr/bin/env python |
2 # Copyright (c) 2012 The Chromium Authors. All rights reserved. | 2 # Copyright (c) 2012 The Chromium Authors. All rights reserved. |
3 # Use of this source code is governed by a BSD-style license that can be | 3 # Use of this source code is governed by a BSD-style license that can be |
4 # found in the LICENSE file. | 4 # found in the LICENSE file. |
5 | 5 |
6 """Extracts native methods from a Java file and generates the JNI bindings. | 6 """Extracts native methods from a Java file and generates the JNI bindings. |
7 If you change this, please run and update the tests.""" | 7 If you change this, please run and update the tests.""" |
8 | 8 |
9 import collections | 9 import collections |
10 import errno | 10 import errno |
(...skipping 159 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
170 'void': '' | 170 'void': '' |
171 } | 171 } |
172 return java_pod_type_map.get(java_type, 'NULL') | 172 return java_pod_type_map.get(java_type, 'NULL') |
173 | 173 |
174 | 174 |
175 class JniParams(object): | 175 class JniParams(object): |
176 _imports = [] | 176 _imports = [] |
177 _fully_qualified_class = '' | 177 _fully_qualified_class = '' |
178 _package = '' | 178 _package = '' |
179 _inner_classes = [] | 179 _inner_classes = [] |
180 _remappings = [] | |
181 _implicit_imports = [] | 180 _implicit_imports = [] |
182 | 181 |
183 @staticmethod | 182 @staticmethod |
184 def SetFullyQualifiedClass(fully_qualified_class): | 183 def SetFullyQualifiedClass(fully_qualified_class): |
185 JniParams._fully_qualified_class = 'L' + fully_qualified_class | 184 JniParams._fully_qualified_class = 'L' + fully_qualified_class |
186 JniParams._package = '/'.join(fully_qualified_class.split('/')[:-1]) | 185 JniParams._package = '/'.join(fully_qualified_class.split('/')[:-1]) |
187 | 186 |
188 @staticmethod | 187 @staticmethod |
189 def AddAdditionalImport(class_name): | 188 def AddAdditionalImport(class_name): |
190 assert class_name.endswith('.class') | 189 assert class_name.endswith('.class') |
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
261 while param[-2:] == '[]': | 260 while param[-2:] == '[]': |
262 prefix += '[' | 261 prefix += '[' |
263 param = param[:-2] | 262 param = param[:-2] |
264 # Generic? | 263 # Generic? |
265 if '<' in param: | 264 if '<' in param: |
266 param = param[:param.index('<')] | 265 param = param[:param.index('<')] |
267 if param in pod_param_map: | 266 if param in pod_param_map: |
268 return prefix + pod_param_map[param] | 267 return prefix + pod_param_map[param] |
269 if '/' in param: | 268 if '/' in param: |
270 # Coming from javap, use the fully qualified param directly. | 269 # Coming from javap, use the fully qualified param directly. |
271 return prefix + 'L' + JniParams.RemapClassName(param) + ';' | 270 return prefix + 'L' + param + ';' |
272 | 271 |
273 for qualified_name in (object_param_list + | 272 for qualified_name in (object_param_list + |
274 [JniParams._fully_qualified_class] + | 273 [JniParams._fully_qualified_class] + |
275 JniParams._inner_classes): | 274 JniParams._inner_classes): |
276 if (qualified_name.endswith('/' + param) or | 275 if (qualified_name.endswith('/' + param) or |
277 qualified_name.endswith('$' + param.replace('.', '$')) or | 276 qualified_name.endswith('$' + param.replace('.', '$')) or |
278 qualified_name == 'L' + param): | 277 qualified_name == 'L' + param): |
279 return prefix + JniParams.RemapClassName(qualified_name) + ';' | 278 return prefix + qualified_name + ';' |
280 | 279 |
281 # Is it from an import? (e.g. referecing Class from import pkg.Class; | 280 # Is it from an import? (e.g. referecing Class from import pkg.Class; |
282 # note that referencing an inner class Inner from import pkg.Class.Inner | 281 # note that referencing an inner class Inner from import pkg.Class.Inner |
283 # is not supported). | 282 # is not supported). |
284 for qualified_name in JniParams._imports: | 283 for qualified_name in JniParams._imports: |
285 if qualified_name.endswith('/' + param): | 284 if qualified_name.endswith('/' + param): |
286 # Ensure it's not an inner class. | 285 # Ensure it's not an inner class. |
287 components = qualified_name.split('/') | 286 components = qualified_name.split('/') |
288 if len(components) > 2 and components[-2][0].isupper(): | 287 if len(components) > 2 and components[-2][0].isupper(): |
289 raise SyntaxError('Inner class (%s) can not be imported ' | 288 raise SyntaxError('Inner class (%s) can not be imported ' |
290 'and used by JNI (%s). Please import the outer ' | 289 'and used by JNI (%s). Please import the outer ' |
291 'class and use Outer.Inner instead.' % | 290 'class and use Outer.Inner instead.' % |
292 (qualified_name, param)) | 291 (qualified_name, param)) |
293 return prefix + JniParams.RemapClassName(qualified_name) + ';' | 292 return prefix + qualified_name + ';' |
294 | 293 |
295 # Is it an inner class from an outer class import? (e.g. referencing | 294 # Is it an inner class from an outer class import? (e.g. referencing |
296 # Class.Inner from import pkg.Class). | 295 # Class.Inner from import pkg.Class). |
297 if '.' in param: | 296 if '.' in param: |
298 components = param.split('.') | 297 components = param.split('.') |
299 outer = '/'.join(components[:-1]) | 298 outer = '/'.join(components[:-1]) |
300 inner = components[-1] | 299 inner = components[-1] |
301 for qualified_name in JniParams._imports: | 300 for qualified_name in JniParams._imports: |
302 if qualified_name.endswith('/' + outer): | 301 if qualified_name.endswith('/' + outer): |
303 return (prefix + JniParams.RemapClassName(qualified_name) + | 302 return (prefix + qualified_name + '$' + inner + ';') |
304 '$' + inner + ';') | |
305 raise SyntaxError('Inner class (%s) can not be ' | 303 raise SyntaxError('Inner class (%s) can not be ' |
306 'used directly by JNI. Please import the outer ' | 304 'used directly by JNI. Please import the outer ' |
307 'class, probably:\n' | 305 'class, probably:\n' |
308 'import %s.%s;' % | 306 'import %s.%s;' % |
309 (param, JniParams._package.replace('/', '.'), | 307 (param, JniParams._package.replace('/', '.'), |
310 outer.replace('/', '.'))) | 308 outer.replace('/', '.'))) |
311 | 309 |
312 JniParams._CheckImplicitImports(param) | 310 JniParams._CheckImplicitImports(param) |
313 | 311 |
314 # Type not found, falling back to same package as this class. | 312 # Type not found, falling back to same package as this class. |
315 return (prefix + 'L' + | 313 return (prefix + 'L' + JniParams._package + '/' + param + ';') |
316 JniParams.RemapClassName(JniParams._package + '/' + param) + ';') | |
317 | 314 |
318 @staticmethod | 315 @staticmethod |
319 def _CheckImplicitImports(param): | 316 def _CheckImplicitImports(param): |
320 # Ensure implicit imports, such as java.lang.*, are not being treated | 317 # Ensure implicit imports, such as java.lang.*, are not being treated |
321 # as being in the same package. | 318 # as being in the same package. |
322 if not JniParams._implicit_imports: | 319 if not JniParams._implicit_imports: |
323 # This file was generated from android.jar and lists | 320 # This file was generated from android.jar and lists |
324 # all classes that are implicitly imported. | 321 # all classes that are implicitly imported. |
325 with file(os.path.join(os.path.dirname(sys.argv[0]), | 322 with file(os.path.join(os.path.dirname(sys.argv[0]), |
326 'android_jar.classes'), 'r') as f: | 323 'android_jar.classes'), 'r') as f: |
(...skipping 30 matching lines...) Expand all Loading... |
357 items = p.split(' ') | 354 items = p.split(' ') |
358 if 'final' in items: | 355 if 'final' in items: |
359 items.remove('final') | 356 items.remove('final') |
360 param = Param( | 357 param = Param( |
361 datatype=items[0], | 358 datatype=items[0], |
362 name=(items[1] if len(items) > 1 else 'p%s' % len(ret)), | 359 name=(items[1] if len(items) > 1 else 'p%s' % len(ret)), |
363 ) | 360 ) |
364 ret += [param] | 361 ret += [param] |
365 return ret | 362 return ret |
366 | 363 |
367 @staticmethod | |
368 def RemapClassName(class_name): | |
369 """Remaps class names using the jarjar mapping table.""" | |
370 for old, new in JniParams._remappings: | |
371 if old.endswith('**') and old[:-2] in class_name: | |
372 return class_name.replace(old[:-2], new, 1) | |
373 if '*' not in old and class_name.endswith(old): | |
374 return class_name.replace(old, new, 1) | |
375 | |
376 return class_name | |
377 | |
378 @staticmethod | |
379 def SetJarJarMappings(mappings): | |
380 """Parse jarjar mappings from a string.""" | |
381 JniParams._remappings = [] | |
382 for line in mappings.splitlines(): | |
383 rule = line.split() | |
384 if rule[0] != 'rule': | |
385 continue | |
386 _, src, dest = rule | |
387 src = src.replace('.', '/') | |
388 dest = dest.replace('.', '/') | |
389 if src.endswith('**'): | |
390 src_real_name = src[:-2] | |
391 else: | |
392 assert not '*' in src | |
393 src_real_name = src | |
394 | |
395 if dest.endswith('@0'): | |
396 JniParams._remappings.append((src, dest[:-2] + src_real_name)) | |
397 elif dest.endswith('@1'): | |
398 assert '**' in src | |
399 JniParams._remappings.append((src, dest[:-2])) | |
400 else: | |
401 assert not '@' in dest | |
402 JniParams._remappings.append((src, dest)) | |
403 | |
404 | 364 |
405 def ExtractJNINamespace(contents): | 365 def ExtractJNINamespace(contents): |
406 re_jni_namespace = re.compile('.*?@JNINamespace\("(.*?)"\)') | 366 re_jni_namespace = re.compile('.*?@JNINamespace\("(.*?)"\)') |
407 m = re.findall(re_jni_namespace, contents) | 367 m = re.findall(re_jni_namespace, contents) |
408 if not m: | 368 if not m: |
409 return '' | 369 return '' |
410 return m[0] | 370 return m[0] |
411 | 371 |
412 | 372 |
413 def ExtractFullyQualifiedJavaClassName(java_file_name, contents): | 373 def ExtractFullyQualifiedJavaClassName(java_file_name, contents): |
(...skipping 322 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
736 def __init__(self, namespace, fully_qualified_class, natives, | 696 def __init__(self, namespace, fully_qualified_class, natives, |
737 called_by_natives, constant_fields, options): | 697 called_by_natives, constant_fields, options): |
738 self.namespace = namespace | 698 self.namespace = namespace |
739 self.fully_qualified_class = fully_qualified_class | 699 self.fully_qualified_class = fully_qualified_class |
740 self.class_name = self.fully_qualified_class.split('/')[-1] | 700 self.class_name = self.fully_qualified_class.split('/')[-1] |
741 self.natives = natives | 701 self.natives = natives |
742 self.called_by_natives = called_by_natives | 702 self.called_by_natives = called_by_natives |
743 self.header_guard = fully_qualified_class.replace('/', '_') + '_JNI' | 703 self.header_guard = fully_qualified_class.replace('/', '_') + '_JNI' |
744 self.constant_fields = constant_fields | 704 self.constant_fields = constant_fields |
745 self.options = options | 705 self.options = options |
746 self.init_native = self.ExtractInitNative(options) | |
747 | 706 |
748 def ExtractInitNative(self, options): | |
749 for native in self.natives: | |
750 if options.jni_init_native_name == 'native' + native.name: | |
751 self.natives.remove(native) | |
752 return native | |
753 return None | |
754 | 707 |
755 def GetContent(self): | 708 def GetContent(self): |
756 """Returns the content of the JNI binding file.""" | 709 """Returns the content of the JNI binding file.""" |
757 template = Template("""\ | 710 template = Template("""\ |
758 // Copyright 2014 The Chromium Authors. All rights reserved. | 711 // Copyright 2014 The Chromium Authors. All rights reserved. |
759 // Use of this source code is governed by a BSD-style license that can be | 712 // Use of this source code is governed by a BSD-style license that can be |
760 // found in the LICENSE file. | 713 // found in the LICENSE file. |
761 | 714 |
762 | 715 |
763 // This file is autogenerated by | 716 // This file is autogenerated by |
764 // ${SCRIPT_NAME} | 717 // ${SCRIPT_NAME} |
765 // For | 718 // For |
766 // ${FULLY_QUALIFIED_CLASS} | 719 // ${FULLY_QUALIFIED_CLASS} |
767 | 720 |
768 #ifndef ${HEADER_GUARD} | 721 #ifndef ${HEADER_GUARD} |
769 #define ${HEADER_GUARD} | 722 #define ${HEADER_GUARD} |
770 | 723 |
771 #include <jni.h> | 724 #include <jni.h> |
772 | 725 |
773 ${INCLUDES} | 726 ${INCLUDES} |
774 | 727 |
775 #include "base/android/jni_int_wrapper.h" | 728 #include "base/android/jni_int_wrapper.h" |
776 | 729 |
777 // Step 1: forward declarations. | 730 // Step 1: forward declarations. |
778 namespace { | 731 namespace { |
779 $CLASS_PATH_DEFINITIONS | 732 $CLASS_PATH_DEFINITIONS |
780 $METHOD_ID_DEFINITIONS | 733 |
781 } // namespace | 734 } // namespace |
782 | 735 |
783 $OPEN_NAMESPACE | 736 $OPEN_NAMESPACE |
784 | 737 |
785 $CONSTANT_FIELDS | 738 $CONSTANT_FIELDS |
786 | 739 |
787 // Step 2: method stubs. | 740 // Step 2: method stubs. |
788 $METHOD_STUBS | 741 $METHOD_STUBS |
789 | 742 |
790 // Step 3: RegisterNatives. | 743 // Step 3: RegisterNatives. |
791 $JNI_NATIVE_METHODS | 744 $JNI_NATIVE_METHODS |
792 $REGISTER_NATIVES | 745 $REGISTER_NATIVES |
793 $CLOSE_NAMESPACE | 746 $CLOSE_NAMESPACE |
794 $JNI_REGISTER_NATIVES | 747 |
795 #endif // ${HEADER_GUARD} | 748 #endif // ${HEADER_GUARD} |
796 """) | 749 """) |
797 values = { | 750 values = { |
798 'SCRIPT_NAME': self.options.script_name, | 751 'SCRIPT_NAME': self.options.script_name, |
799 'FULLY_QUALIFIED_CLASS': self.fully_qualified_class, | 752 'FULLY_QUALIFIED_CLASS': self.fully_qualified_class, |
800 'CLASS_PATH_DEFINITIONS': self.GetClassPathDefinitionsString(), | 753 'CLASS_PATH_DEFINITIONS': self.GetClassPathDefinitionsString(), |
801 'METHOD_ID_DEFINITIONS': self.GetMethodIDDefinitionsString(), | |
802 'CONSTANT_FIELDS': self.GetConstantFieldsString(), | 754 'CONSTANT_FIELDS': self.GetConstantFieldsString(), |
803 'METHOD_STUBS': self.GetMethodStubsString(), | 755 'METHOD_STUBS': self.GetMethodStubsString(), |
804 'OPEN_NAMESPACE': self.GetOpenNamespaceString(), | 756 'OPEN_NAMESPACE': self.GetOpenNamespaceString(), |
805 'JNI_NATIVE_METHODS': self.GetJNINativeMethodsString(), | 757 'JNI_NATIVE_METHODS': self.GetJNINativeMethodsString(), |
806 'REGISTER_NATIVES': self.GetRegisterNativesString(), | 758 'REGISTER_NATIVES': self.GetRegisterNativesString(), |
807 'CLOSE_NAMESPACE': self.GetCloseNamespaceString(), | 759 'CLOSE_NAMESPACE': self.GetCloseNamespaceString(), |
808 'HEADER_GUARD': self.header_guard, | 760 'HEADER_GUARD': self.header_guard, |
809 'INCLUDES': self.GetIncludesString(), | 761 'INCLUDES': self.GetIncludesString(), |
810 'JNI_REGISTER_NATIVES': self.GetJNIRegisterNativesString() | |
811 } | 762 } |
812 return WrapOutput(template.substitute(values)) | 763 return WrapOutput(template.substitute(values)) |
813 | 764 |
814 def GetClassPathDefinitionsString(self): | 765 def GetClassPathDefinitionsString(self): |
815 ret = [] | 766 ret = [] |
816 ret += [self.GetClassPathDefinitions()] | 767 ret += [self.GetClassPathDefinitions()] |
817 return '\n'.join(ret) | 768 return '\n'.join(ret) |
818 | 769 |
819 def GetMethodIDDefinitionsString(self): | |
820 """Returns the definition of method ids for the called by native methods.""" | |
821 if not self.options.eager_called_by_natives: | |
822 return '' | |
823 template = Template("""\ | |
824 jmethodID g_${JAVA_CLASS}_${METHOD_ID_VAR_NAME} = NULL;""") | |
825 ret = [] | |
826 for called_by_native in self.called_by_natives: | |
827 values = { | |
828 'JAVA_CLASS': called_by_native.java_class_name or self.class_name, | |
829 'METHOD_ID_VAR_NAME': called_by_native.method_id_var_name, | |
830 } | |
831 ret += [template.substitute(values)] | |
832 return '\n'.join(ret) | |
833 | |
834 def GetConstantFieldsString(self): | 770 def GetConstantFieldsString(self): |
835 if not self.constant_fields: | 771 if not self.constant_fields: |
836 return '' | 772 return '' |
837 ret = ['enum Java_%s_constant_fields {' % self.class_name] | 773 ret = ['enum Java_%s_constant_fields {' % self.class_name] |
838 for c in self.constant_fields: | 774 for c in self.constant_fields: |
839 ret += [' %s = %s,' % (c.name, c.value)] | 775 ret += [' %s = %s,' % (c.name, c.value)] |
840 ret += ['};'] | 776 ret += ['};'] |
841 return '\n'.join(ret) | 777 return '\n'.join(ret) |
842 | 778 |
843 def GetMethodStubsString(self): | 779 def GetMethodStubsString(self): |
844 """Returns the code corresponding to method stubs.""" | 780 """Returns the code corresponding to method stubs.""" |
845 ret = [] | 781 ret = [] |
846 for native in self.natives: | 782 for native in self.natives: |
847 ret += [self.GetNativeStub(native)] | 783 ret += [self.GetNativeStub(native)] |
848 if self.options.eager_called_by_natives: | 784 ret += self.GetLazyCalledByNativeMethodStubs() |
849 ret += self.GetEagerCalledByNativeMethodStubs() | |
850 else: | |
851 ret += self.GetLazyCalledByNativeMethodStubs() | |
852 return '\n'.join(ret) | 785 return '\n'.join(ret) |
853 | 786 |
854 def GetLazyCalledByNativeMethodStubs(self): | 787 def GetLazyCalledByNativeMethodStubs(self): |
855 return [self.GetLazyCalledByNativeMethodStub(called_by_native) | 788 return [self.GetLazyCalledByNativeMethodStub(called_by_native) |
856 for called_by_native in self.called_by_natives] | 789 for called_by_native in self.called_by_natives] |
857 | 790 |
858 def GetEagerCalledByNativeMethodStubs(self): | |
859 ret = [] | |
860 if self.called_by_natives: | |
861 ret += ['namespace {'] | |
862 for called_by_native in self.called_by_natives: | |
863 ret += [self.GetEagerCalledByNativeMethodStub(called_by_native)] | |
864 ret += ['} // namespace'] | |
865 return ret | |
866 | |
867 def GetIncludesString(self): | 791 def GetIncludesString(self): |
868 if not self.options.includes: | 792 if not self.options.includes: |
869 return '' | 793 return '' |
870 includes = self.options.includes.split(',') | 794 includes = self.options.includes.split(',') |
871 return '\n'.join('#include "%s"' % x for x in includes) | 795 return '\n'.join('#include "%s"' % x for x in includes) |
872 | 796 |
873 def GetKMethodsString(self, clazz): | 797 def GetKMethodsString(self, clazz): |
874 ret = [] | 798 ret = [] |
875 for native in self.natives: | 799 for native in self.natives: |
876 if (native.java_class_name == clazz or | 800 if (native.java_class_name == clazz or |
(...skipping 19 matching lines...) Expand all Loading... |
896 """Returns the implementation of the array of native methods.""" | 820 """Returns the implementation of the array of native methods.""" |
897 if self.options.native_exports and not self.options.native_exports_optional: | 821 if self.options.native_exports and not self.options.native_exports_optional: |
898 return '' | 822 return '' |
899 template = Template("""\ | 823 template = Template("""\ |
900 static const JNINativeMethod kMethods${JAVA_CLASS}[] = { | 824 static const JNINativeMethod kMethods${JAVA_CLASS}[] = { |
901 ${KMETHODS} | 825 ${KMETHODS} |
902 }; | 826 }; |
903 """) | 827 """) |
904 return self.SubstituteNativeMethods(template) | 828 return self.SubstituteNativeMethods(template) |
905 | 829 |
906 def GetRegisterCalledByNativesImplString(self): | |
907 """Returns the code for registering the called by native methods.""" | |
908 if not self.options.eager_called_by_natives: | |
909 return '' | |
910 template = Template("""\ | |
911 g_${JAVA_CLASS}_${METHOD_ID_VAR_NAME} = ${GET_METHOD_ID_IMPL} | |
912 if (g_${JAVA_CLASS}_${METHOD_ID_VAR_NAME} == NULL) { | |
913 return false; | |
914 } | |
915 """) | |
916 ret = [] | |
917 for called_by_native in self.called_by_natives: | |
918 values = { | |
919 'JAVA_CLASS': called_by_native.java_class_name or self.class_name, | |
920 'METHOD_ID_VAR_NAME': called_by_native.method_id_var_name, | |
921 'GET_METHOD_ID_IMPL': self.GetMethodIDImpl(called_by_native), | |
922 } | |
923 ret += [template.substitute(values)] | |
924 return '\n'.join(ret) | |
925 | |
926 def GetRegisterNativesString(self): | 830 def GetRegisterNativesString(self): |
927 """Returns the code for RegisterNatives.""" | 831 """Returns the code for RegisterNatives.""" |
928 template = Template("""\ | 832 template = Template("""\ |
929 ${REGISTER_NATIVES_SIGNATURE} { | 833 ${REGISTER_NATIVES_SIGNATURE} { |
930 ${EARLY_EXIT} | 834 ${EARLY_EXIT} |
931 ${CLASSES} | 835 ${CLASSES} |
932 ${NATIVES} | 836 ${NATIVES} |
933 ${CALLED_BY_NATIVES} | |
934 return true; | 837 return true; |
935 } | 838 } |
936 """) | 839 """) |
937 signature = 'static bool RegisterNativesImpl(JNIEnv* env' | 840 signature = 'static bool RegisterNativesImpl(JNIEnv* env)' |
938 if self.init_native: | |
939 signature += ', jclass clazz)' | |
940 else: | |
941 signature += ')' | |
942 | |
943 early_exit = '' | 841 early_exit = '' |
944 if self.options.native_exports_optional: | 842 if self.options.native_exports_optional: |
945 early_exit = """\ | 843 early_exit = """\ |
946 if (base::android::IsManualJniRegistrationDisabled()) return true; | 844 if (base::android::IsManualJniRegistrationDisabled()) return true; |
947 """ | 845 """ |
948 | 846 |
949 natives = self.GetRegisterNativesImplString() | 847 natives = self.GetRegisterNativesImplString() |
950 called_by_natives = self.GetRegisterCalledByNativesImplString() | |
951 values = {'REGISTER_NATIVES_SIGNATURE': signature, | 848 values = {'REGISTER_NATIVES_SIGNATURE': signature, |
952 'EARLY_EXIT': early_exit, | 849 'EARLY_EXIT': early_exit, |
953 'CLASSES': self.GetFindClasses(), | 850 'CLASSES': self.GetFindClasses(), |
954 'NATIVES': natives, | 851 'NATIVES': natives, |
955 'CALLED_BY_NATIVES': called_by_natives, | |
956 } | 852 } |
957 return template.substitute(values) | 853 return template.substitute(values) |
958 | 854 |
959 def GetRegisterNativesImplString(self): | 855 def GetRegisterNativesImplString(self): |
960 """Returns the shared implementation for RegisterNatives.""" | 856 """Returns the shared implementation for RegisterNatives.""" |
961 if self.options.native_exports and not self.options.native_exports_optional: | 857 if self.options.native_exports and not self.options.native_exports_optional: |
962 return '' | 858 return '' |
963 | 859 |
964 template = Template("""\ | 860 template = Template("""\ |
965 const int kMethods${JAVA_CLASS}Size = arraysize(kMethods${JAVA_CLASS}); | 861 const int kMethods${JAVA_CLASS}Size = arraysize(kMethods${JAVA_CLASS}); |
966 | 862 |
967 if (env->RegisterNatives(${JAVA_CLASS}_clazz(env), | 863 if (env->RegisterNatives(${JAVA_CLASS}_clazz(env), |
968 kMethods${JAVA_CLASS}, | 864 kMethods${JAVA_CLASS}, |
969 kMethods${JAVA_CLASS}Size) < 0) { | 865 kMethods${JAVA_CLASS}Size) < 0) { |
970 jni_generator::HandleRegistrationError( | 866 jni_generator::HandleRegistrationError( |
971 env, ${JAVA_CLASS}_clazz(env), __FILE__); | 867 env, ${JAVA_CLASS}_clazz(env), __FILE__); |
972 return false; | 868 return false; |
973 } | 869 } |
974 """) | 870 """) |
975 return self.SubstituteNativeMethods(template) | 871 return self.SubstituteNativeMethods(template) |
976 | 872 |
977 def GetJNIRegisterNativesString(self): | |
978 """Returns the implementation for the JNI registration of native methods.""" | |
979 if not self.init_native: | |
980 return '' | |
981 | |
982 template = Template("""\ | |
983 extern "C" JNIEXPORT bool JNICALL | |
984 Java_${FULLY_QUALIFIED_CLASS}_${INIT_NATIVE_NAME}(JNIEnv* env, jclass clazz) { | |
985 return ${NAMESPACE}RegisterNativesImpl(env, clazz); | |
986 } | |
987 """) | |
988 | |
989 if self.options.native_exports: | |
990 java_name = JniParams.RemapClassName(self.fully_qualified_class) | |
991 java_name = java_name.replace('_', '_1').replace('/', '_') | |
992 else: | |
993 java_name = self.fully_qualified_class.replace('/', '_') | |
994 | |
995 namespace = '' | |
996 if self.namespace: | |
997 namespace = self.namespace + '::' | |
998 values = {'FULLY_QUALIFIED_CLASS': java_name, | |
999 'INIT_NATIVE_NAME': 'native' + self.init_native.name, | |
1000 'NAMESPACE': namespace, | |
1001 'REGISTER_NATIVES_IMPL': self.GetRegisterNativesImplString() | |
1002 } | |
1003 return template.substitute(values) | |
1004 | |
1005 def GetOpenNamespaceString(self): | 873 def GetOpenNamespaceString(self): |
1006 if self.namespace: | 874 if self.namespace: |
1007 all_namespaces = ['namespace %s {' % ns | 875 all_namespaces = ['namespace %s {' % ns |
1008 for ns in self.namespace.split('::')] | 876 for ns in self.namespace.split('::')] |
1009 return '\n'.join(all_namespaces) | 877 return '\n'.join(all_namespaces) |
1010 return '' | 878 return '' |
1011 | 879 |
1012 def GetCloseNamespaceString(self): | 880 def GetCloseNamespaceString(self): |
1013 if self.namespace: | 881 if self.namespace: |
1014 all_namespaces = ['} // namespace %s' % ns | 882 all_namespaces = ['} // namespace %s' % ns |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1070 """Return the name of the stub function for this native method. | 938 """Return the name of the stub function for this native method. |
1071 | 939 |
1072 Args: | 940 Args: |
1073 native: the native dictionary describing the method. | 941 native: the native dictionary describing the method. |
1074 | 942 |
1075 Returns: | 943 Returns: |
1076 A string with the stub function name (used by the JVM). | 944 A string with the stub function name (used by the JVM). |
1077 """ | 945 """ |
1078 template = Template("Java_${JAVA_NAME}_native${NAME}") | 946 template = Template("Java_${JAVA_NAME}_native${NAME}") |
1079 | 947 |
1080 java_name = JniParams.RemapClassName(self.fully_qualified_class) | 948 java_name = self.fully_qualified_class.replace('_', '_1').replace('/', '_') |
1081 java_name = java_name.replace('_', '_1').replace('/', '_') | |
1082 if native.java_class_name: | 949 if native.java_class_name: |
1083 java_name += '_00024' + native.java_class_name | 950 java_name += '_00024' + native.java_class_name |
1084 | 951 |
1085 values = {'NAME': native.name, | 952 values = {'NAME': native.name, |
1086 'JAVA_NAME': java_name} | 953 'JAVA_NAME': java_name} |
1087 return template.substitute(values) | 954 return template.substitute(values) |
1088 | 955 |
1089 def GetJavaParamRefForCall(self, c_type, name): | 956 def GetJavaParamRefForCall(self, c_type, name): |
1090 return Template('JavaParamRef<${TYPE}>(env, ${NAME})').substitute({ | 957 return Template('JavaParamRef<${TYPE}>(env, ${NAME})').substitute({ |
1091 'TYPE': c_type, | 958 'TYPE': c_type, |
1092 'NAME': name, | 959 'NAME': name, |
1093 }) | 960 }) |
1094 | 961 |
1095 def GetJNIFirstParamForCall(self, native): | 962 def GetJNIFirstParamForCall(self, native): |
1096 c_type = self.GetJNIFirstParamType(native) | 963 c_type = self.GetJNIFirstParamType(native) |
1097 return [self.GetJavaParamRefForCall(c_type, 'jcaller')] | 964 return [self.GetJavaParamRefForCall(c_type, 'jcaller')] |
1098 | 965 |
1099 def GetNativeStub(self, native): | 966 def GetNativeStub(self, native): |
1100 is_method = native.type == 'method' | 967 is_method = native.type == 'method' |
1101 | 968 |
1102 if is_method: | 969 if is_method: |
1103 params = native.params[1:] | 970 params = native.params[1:] |
1104 else: | 971 else: |
1105 params = native.params | 972 params = native.params |
1106 params_in_call = [] | 973 params_in_call = ['env'] + self.GetJNIFirstParamForCall(native) |
1107 if not self.options.pure_native_methods: | |
1108 params_in_call = ['env'] + self.GetJNIFirstParamForCall(native) | |
1109 for p in params: | 974 for p in params: |
1110 c_type = JavaDataTypeToC(p.datatype) | 975 c_type = JavaDataTypeToC(p.datatype) |
1111 if re.match(RE_SCOPED_JNI_TYPES, c_type): | 976 if re.match(RE_SCOPED_JNI_TYPES, c_type): |
1112 params_in_call.append(self.GetJavaParamRefForCall(c_type, p.name)) | 977 params_in_call.append(self.GetJavaParamRefForCall(c_type, p.name)) |
1113 else: | 978 else: |
1114 params_in_call.append(p.name) | 979 params_in_call.append(p.name) |
1115 params_in_call = ', '.join(params_in_call) | 980 params_in_call = ', '.join(params_in_call) |
1116 | 981 |
1117 if self.options.native_exports: | 982 if self.options.native_exports: |
1118 stub_visibility = 'extern "C" __attribute__((visibility("default")))\n' | 983 stub_visibility = 'extern "C" __attribute__((visibility("default")))\n' |
(...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1220 'PRE_CALL': pre_call, | 1085 'PRE_CALL': pre_call, |
1221 'POST_CALL': post_call, | 1086 'POST_CALL': post_call, |
1222 'ENV_CALL': called_by_native.env_call, | 1087 'ENV_CALL': called_by_native.env_call, |
1223 'FIRST_PARAM_IN_CALL': first_param_in_call, | 1088 'FIRST_PARAM_IN_CALL': first_param_in_call, |
1224 'PARAMS_IN_CALL': params_in_call, | 1089 'PARAMS_IN_CALL': params_in_call, |
1225 'METHOD_ID_VAR_NAME': called_by_native.method_id_var_name, | 1090 'METHOD_ID_VAR_NAME': called_by_native.method_id_var_name, |
1226 'CHECK_EXCEPTION': check_exception, | 1091 'CHECK_EXCEPTION': check_exception, |
1227 'GET_METHOD_ID_IMPL': self.GetMethodIDImpl(called_by_native) | 1092 'GET_METHOD_ID_IMPL': self.GetMethodIDImpl(called_by_native) |
1228 } | 1093 } |
1229 | 1094 |
1230 def GetEagerCalledByNativeMethodStub(self, called_by_native): | |
1231 """Returns the implementation of the called by native method.""" | |
1232 template = Template(""" | |
1233 static ${RETURN_TYPE} ${METHOD_ID_VAR_NAME}(\ | |
1234 JNIEnv* env${FIRST_PARAM_IN_DECLARATION}${PARAMS_IN_DECLARATION}) { | |
1235 ${RETURN_DECLARATION}${PRE_CALL}env->${ENV_CALL}(${FIRST_PARAM_IN_CALL}, | |
1236 g_${JAVA_CLASS}_${METHOD_ID_VAR_NAME}${PARAMS_IN_CALL})${POST_CALL}; | |
1237 ${RETURN_CLAUSE} | |
1238 }""") | |
1239 values = self.GetCalledByNativeValues(called_by_native) | |
1240 return template.substitute(values) | |
1241 | 1095 |
1242 def GetLazyCalledByNativeMethodStub(self, called_by_native): | 1096 def GetLazyCalledByNativeMethodStub(self, called_by_native): |
1243 """Returns a string.""" | 1097 """Returns a string.""" |
1244 function_signature_template = Template("""\ | 1098 function_signature_template = Template("""\ |
1245 static ${RETURN_TYPE} Java_${JAVA_CLASS}_${METHOD_ID_VAR_NAME}(\ | 1099 static ${RETURN_TYPE} Java_${JAVA_CLASS}_${METHOD_ID_VAR_NAME}(\ |
1246 JNIEnv* env${FIRST_PARAM_IN_DECLARATION}${PARAMS_IN_DECLARATION})""") | 1100 JNIEnv* env${FIRST_PARAM_IN_DECLARATION}${PARAMS_IN_DECLARATION})""") |
1247 function_header_template = Template("""\ | 1101 function_header_template = Template("""\ |
1248 ${FUNCTION_SIGNATURE} {""") | 1102 ${FUNCTION_SIGNATURE} {""") |
1249 function_header_with_unused_template = Template("""\ | 1103 function_header_with_unused_template = Template("""\ |
1250 ${FUNCTION_SIGNATURE} __attribute__ ((unused)); | 1104 ${FUNCTION_SIGNATURE} __attribute__ ((unused)); |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1303 called_by_native_classes = self.GetUniqueClasses(self.called_by_natives) | 1157 called_by_native_classes = self.GetUniqueClasses(self.called_by_natives) |
1304 if self.options.native_exports: | 1158 if self.options.native_exports: |
1305 all_classes = called_by_native_classes | 1159 all_classes = called_by_native_classes |
1306 else: | 1160 else: |
1307 all_classes = native_classes | 1161 all_classes = native_classes |
1308 all_classes.update(called_by_native_classes) | 1162 all_classes.update(called_by_native_classes) |
1309 | 1163 |
1310 for clazz in all_classes: | 1164 for clazz in all_classes: |
1311 values = { | 1165 values = { |
1312 'JAVA_CLASS': clazz, | 1166 'JAVA_CLASS': clazz, |
1313 'JNI_CLASS_PATH': JniParams.RemapClassName(all_classes[clazz]), | 1167 'JNI_CLASS_PATH': all_classes[clazz], |
1314 } | 1168 } |
1315 ret += [template.substitute(values)] | 1169 ret += [template.substitute(values)] |
1316 ret += '' | 1170 ret += '' |
1317 | 1171 |
1318 class_getter_methods = [] | 1172 class_getter_methods = [] |
1319 if self.options.native_exports: | 1173 if self.options.native_exports: |
1320 template = Template("""\ | 1174 template = Template("""\ |
1321 // Leaking this jclass as we cannot use LazyInstance from some threads. | 1175 // Leaking this jclass as we cannot use LazyInstance from some threads. |
1322 base::subtle::AtomicWord g_${JAVA_CLASS}_clazz __attribute__((unused)) = 0; | 1176 base::subtle::AtomicWord g_${JAVA_CLASS}_clazz __attribute__((unused)) = 0; |
1323 #define ${JAVA_CLASS}_clazz(env) \ | 1177 #define ${JAVA_CLASS}_clazz(env) \ |
1324 base::android::LazyGetClass(env, k${JAVA_CLASS}ClassPath, \ | 1178 base::android::LazyGetClass(env, k${JAVA_CLASS}ClassPath, \ |
1325 &g_${JAVA_CLASS}_clazz)""") | 1179 &g_${JAVA_CLASS}_clazz)""") |
1326 else: | 1180 else: |
1327 template = Template("""\ | 1181 template = Template("""\ |
1328 // Leaking this jclass as we cannot use LazyInstance from some threads. | 1182 // Leaking this jclass as we cannot use LazyInstance from some threads. |
1329 jclass g_${JAVA_CLASS}_clazz = NULL; | 1183 jclass g_${JAVA_CLASS}_clazz = NULL; |
1330 #define ${JAVA_CLASS}_clazz(env) g_${JAVA_CLASS}_clazz""") | 1184 #define ${JAVA_CLASS}_clazz(env) g_${JAVA_CLASS}_clazz""") |
1331 | 1185 |
1332 for clazz in called_by_native_classes: | 1186 for clazz in called_by_native_classes: |
1333 values = { | 1187 values = { |
1334 'JAVA_CLASS': clazz, | 1188 'JAVA_CLASS': clazz, |
1335 } | 1189 } |
1336 ret += [template.substitute(values)] | 1190 ret += [template.substitute(values)] |
1337 | 1191 |
1338 return '\n'.join(ret) | 1192 return '\n'.join(ret) |
1339 | 1193 |
1340 def GetFindClasses(self): | 1194 def GetFindClasses(self): |
1341 """Returns the imlementation of FindClass for all known classes.""" | 1195 """Returns the imlementation of FindClass for all known classes.""" |
1342 if self.init_native: | 1196 if self.options.native_exports: |
1343 if self.options.native_exports: | 1197 return '\n' |
1344 template = Template("""\ | 1198 template = Template("""\ |
1345 base::subtle::Release_Store(&g_${JAVA_CLASS}_clazz, | |
1346 static_cast<base::subtle::AtomicWord>(env->NewWeakGlobalRef(clazz));""") | |
1347 else: | |
1348 template = Template("""\ | |
1349 g_${JAVA_CLASS}_clazz = static_cast<jclass>(env->NewWeakGlobalRef(clazz));""") | |
1350 else: | |
1351 if self.options.native_exports: | |
1352 return '\n' | |
1353 template = Template("""\ | |
1354 g_${JAVA_CLASS}_clazz = reinterpret_cast<jclass>(env->NewGlobalRef( | 1199 g_${JAVA_CLASS}_clazz = reinterpret_cast<jclass>(env->NewGlobalRef( |
1355 base::android::GetClass(env, k${JAVA_CLASS}ClassPath).obj()));""") | 1200 base::android::GetClass(env, k${JAVA_CLASS}ClassPath).obj()));""") |
1356 ret = [] | 1201 ret = [] |
1357 for clazz in self.GetUniqueClasses(self.called_by_natives): | 1202 for clazz in self.GetUniqueClasses(self.called_by_natives): |
1358 values = {'JAVA_CLASS': clazz} | 1203 values = {'JAVA_CLASS': clazz} |
1359 ret += [template.substitute(values)] | 1204 ret += [template.substitute(values)] |
1360 return '\n'.join(ret) | 1205 return '\n'.join(ret) |
1361 | 1206 |
1362 def GetMethodIDImpl(self, called_by_native): | 1207 def GetMethodIDImpl(self, called_by_native): |
1363 """Returns the implementation of GetMethodID.""" | 1208 """Returns the implementation of GetMethodID.""" |
1364 if self.options.eager_called_by_natives: | 1209 template = Template("""\ |
1365 template = Template("""\ | |
1366 env->Get${STATIC_METHOD_PART}MethodID( | |
1367 ${JAVA_CLASS}_clazz(env), | |
1368 "${JNI_NAME}", ${JNI_SIGNATURE});""") | |
1369 else: | |
1370 template = Template("""\ | |
1371 base::android::MethodID::LazyGet< | 1210 base::android::MethodID::LazyGet< |
1372 base::android::MethodID::TYPE_${STATIC}>( | 1211 base::android::MethodID::TYPE_${STATIC}>( |
1373 env, ${JAVA_CLASS}_clazz(env), | 1212 env, ${JAVA_CLASS}_clazz(env), |
1374 "${JNI_NAME}", | 1213 "${JNI_NAME}", |
1375 ${JNI_SIGNATURE}, | 1214 ${JNI_SIGNATURE}, |
1376 &g_${JAVA_CLASS}_${METHOD_ID_VAR_NAME}); | 1215 &g_${JAVA_CLASS}_${METHOD_ID_VAR_NAME}); |
1377 """) | 1216 """) |
1378 jni_name = called_by_native.name | 1217 jni_name = called_by_native.name |
1379 jni_return_type = called_by_native.return_type | 1218 jni_return_type = called_by_native.return_type |
1380 if called_by_native.is_constructor: | 1219 if called_by_native.is_constructor: |
1381 jni_name = '<init>' | 1220 jni_name = '<init>' |
1382 jni_return_type = 'void' | 1221 jni_return_type = 'void' |
1383 if called_by_native.signature: | 1222 if called_by_native.signature: |
1384 signature = called_by_native.signature | 1223 signature = called_by_native.signature |
1385 else: | 1224 else: |
1386 signature = JniParams.Signature(called_by_native.params, | 1225 signature = JniParams.Signature(called_by_native.params, |
1387 jni_return_type, | 1226 jni_return_type, |
1388 True) | 1227 True) |
1389 values = { | 1228 values = { |
1390 'JAVA_CLASS': called_by_native.java_class_name or self.class_name, | 1229 'JAVA_CLASS': called_by_native.java_class_name or self.class_name, |
1391 'JNI_NAME': jni_name, | 1230 'JNI_NAME': jni_name, |
1392 'METHOD_ID_VAR_NAME': called_by_native.method_id_var_name, | 1231 'METHOD_ID_VAR_NAME': called_by_native.method_id_var_name, |
1393 'STATIC': 'STATIC' if called_by_native.static else 'INSTANCE', | 1232 'STATIC': 'STATIC' if called_by_native.static else 'INSTANCE', |
1394 'STATIC_METHOD_PART': 'Static' if called_by_native.static else '', | |
1395 'JNI_SIGNATURE': signature, | 1233 'JNI_SIGNATURE': signature, |
1396 } | 1234 } |
1397 return template.substitute(values) | 1235 return template.substitute(values) |
1398 | 1236 |
1399 | 1237 |
1400 def WrapOutput(output): | 1238 def WrapOutput(output): |
1401 ret = [] | 1239 ret = [] |
1402 for line in output.splitlines(): | 1240 for line in output.splitlines(): |
1403 # Do not wrap lines under 80 characters or preprocessor directives. | 1241 # Do not wrap lines under 80 characters or preprocessor directives. |
1404 if len(line) < 80 or line.lstrip()[:1] == '#': | 1242 if len(line) < 80 or line.lstrip()[:1] == '#': |
(...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1506 help='Single input file name. The output file name ' | 1344 help='Single input file name. The output file name ' |
1507 'will be derived from it. Must be used with ' | 1345 'will be derived from it. Must be used with ' |
1508 '--output_dir.') | 1346 '--output_dir.') |
1509 option_parser.add_option('--output_dir', | 1347 option_parser.add_option('--output_dir', |
1510 help='The output directory. Must be used with ' | 1348 help='The output directory. Must be used with ' |
1511 '--input') | 1349 '--input') |
1512 option_parser.add_option('--optimize_generation', type="int", | 1350 option_parser.add_option('--optimize_generation', type="int", |
1513 default=0, help='Whether we should optimize JNI ' | 1351 default=0, help='Whether we should optimize JNI ' |
1514 'generation by not regenerating files if they have ' | 1352 'generation by not regenerating files if they have ' |
1515 'not changed.') | 1353 'not changed.') |
1516 option_parser.add_option('--jarjar', | |
1517 help='Path to optional jarjar rules file.') | |
1518 option_parser.add_option('--script_name', default=GetScriptName(), | 1354 option_parser.add_option('--script_name', default=GetScriptName(), |
1519 help='The name of this script in the generated ' | 1355 help='The name of this script in the generated ' |
1520 'header.') | 1356 'header.') |
1521 option_parser.add_option('--includes', | 1357 option_parser.add_option('--includes', |
1522 help='The comma-separated list of header files to ' | 1358 help='The comma-separated list of header files to ' |
1523 'include in the generated header.') | 1359 'include in the generated header.') |
1524 option_parser.add_option('--pure_native_methods', | |
1525 action='store_true', dest='pure_native_methods', | |
1526 help='When true, the native methods will be called ' | |
1527 'without any JNI-specific arguments.') | |
1528 option_parser.add_option('--ptr_type', default='int', | 1360 option_parser.add_option('--ptr_type', default='int', |
1529 type='choice', choices=['int', 'long'], | 1361 type='choice', choices=['int', 'long'], |
1530 help='The type used to represent native pointers in ' | 1362 help='The type used to represent native pointers in ' |
1531 'Java code. For 32-bit, use int; ' | 1363 'Java code. For 32-bit, use int; ' |
1532 'for 64-bit, use long.') | 1364 'for 64-bit, use long.') |
1533 option_parser.add_option('--jni_init_native_name', default='', | |
1534 help='The name of the JNI registration method that ' | |
1535 'is used to initialize all native methods. If a ' | |
1536 'method with this name is not present in the Java ' | |
1537 'source file, setting this option is a no-op. When ' | |
1538 'a method with this name is found however, the ' | |
1539 'naming convention Java_<packageName>_<className> ' | |
1540 'will limit the initialization to only the ' | |
1541 'top-level class.') | |
1542 option_parser.add_option('--eager_called_by_natives', | |
1543 action='store_true', dest='eager_called_by_natives', | |
1544 help='When true, the called-by-native methods will ' | |
1545 'be initialized in a non-atomic way.') | |
1546 option_parser.add_option('--cpp', default='cpp', | 1365 option_parser.add_option('--cpp', default='cpp', |
1547 help='The path to cpp command.') | 1366 help='The path to cpp command.') |
1548 option_parser.add_option('--javap', default='javap', | 1367 option_parser.add_option('--javap', default='javap', |
1549 help='The path to javap command.') | 1368 help='The path to javap command.') |
1550 option_parser.add_option('--native_exports', action='store_true', | 1369 option_parser.add_option('--native_exports', action='store_true', |
1551 help='Native method registration through .so ' | 1370 help='Native method registration through .so ' |
1552 'exports.') | 1371 'exports.') |
1553 option_parser.add_option('--native_exports_optional', action='store_true', | 1372 option_parser.add_option('--native_exports_optional', action='store_true', |
1554 help='Support both explicit and native method' | 1373 help='Support both explicit and native method' |
1555 'registration.') | 1374 'registration.') |
1556 options, args = option_parser.parse_args(argv) | 1375 options, args = option_parser.parse_args(argv) |
1557 if options.native_exports_optional: | 1376 if options.native_exports_optional: |
1558 options.native_exports = True | 1377 options.native_exports = True |
1559 if options.jar_file: | 1378 if options.jar_file: |
1560 input_file = ExtractJarInputFile(options.jar_file, options.input_file, | 1379 input_file = ExtractJarInputFile(options.jar_file, options.input_file, |
1561 options.output_dir) | 1380 options.output_dir) |
1562 elif options.input_file: | 1381 elif options.input_file: |
1563 input_file = options.input_file | 1382 input_file = options.input_file |
1564 else: | 1383 else: |
1565 option_parser.print_help() | 1384 option_parser.print_help() |
1566 print '\nError: Must specify --jar_file or --input_file.' | 1385 print '\nError: Must specify --jar_file or --input_file.' |
1567 return 1 | 1386 return 1 |
1568 output_file = None | 1387 output_file = None |
1569 if options.output_dir: | 1388 if options.output_dir: |
1570 root_name = os.path.splitext(os.path.basename(input_file))[0] | 1389 root_name = os.path.splitext(os.path.basename(input_file))[0] |
1571 output_file = os.path.join(options.output_dir, root_name) + '_jni.h' | 1390 output_file = os.path.join(options.output_dir, root_name) + '_jni.h' |
1572 if options.jarjar: | |
1573 with open(options.jarjar) as f: | |
1574 JniParams.SetJarJarMappings(f.read()) | |
1575 GenerateJNIHeader(input_file, output_file, options) | 1391 GenerateJNIHeader(input_file, output_file, options) |
1576 | 1392 |
1577 if options.depfile: | 1393 if options.depfile: |
1578 build_utils.WriteDepfile( | 1394 build_utils.WriteDepfile( |
1579 options.depfile, | 1395 options.depfile, |
1580 build_utils.GetPythonDependencies()) | 1396 build_utils.GetPythonDependencies()) |
1581 | 1397 |
1582 | 1398 |
1583 if __name__ == '__main__': | 1399 if __name__ == '__main__': |
1584 sys.exit(main(sys.argv)) | 1400 sys.exit(main(sys.argv)) |
OLD | NEW |