Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(135)

Side by Side Diff: base/android/jni_generator/jni_generator.py

Issue 136773002: Android: upstream few more jni_generator changes. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 6 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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 300 matching lines...) Expand 10 before | Expand all | Expand 10 after
311 311
312 def ExtractNatives(contents, ptr_type): 312 def ExtractNatives(contents, ptr_type):
313 """Returns a list of dict containing information about a native method.""" 313 """Returns a list of dict containing information about a native method."""
314 contents = contents.replace('\n', '') 314 contents = contents.replace('\n', '')
315 natives = [] 315 natives = []
316 re_native = re.compile(r'(@NativeClassQualifiedName' 316 re_native = re.compile(r'(@NativeClassQualifiedName'
317 '\(\"(?P<native_class_name>.*?)\"\))?\s*' 317 '\(\"(?P<native_class_name>.*?)\"\))?\s*'
318 '(@NativeCall(\(\"(?P<java_class_name>.*?)\"\)))?\s*' 318 '(@NativeCall(\(\"(?P<java_class_name>.*?)\"\)))?\s*'
319 '(?P<qualifiers>\w+\s\w+|\w+|\s+)\s*?native ' 319 '(?P<qualifiers>\w+\s\w+|\w+|\s+)\s*?native '
320 '(?P<return_type>\S*?) ' 320 '(?P<return_type>\S*?) '
321 '(?P<name>\w+?)\((?P<params>.*?)\);') 321 '(?P<name>native\w+?)\((?P<params>.*?)\);')
322 for match in re.finditer(re_native, contents): 322 for match in re.finditer(re_native, contents):
323 native = NativeMethod( 323 native = NativeMethod(
324 static='static' in match.group('qualifiers'), 324 static='static' in match.group('qualifiers'),
325 java_class_name=match.group('java_class_name'), 325 java_class_name=match.group('java_class_name'),
326 native_class_name=match.group('native_class_name'), 326 native_class_name=match.group('native_class_name'),
327 return_type=match.group('return_type'), 327 return_type=match.group('return_type'),
328 name=match.group('name').replace('native', ''), 328 name=match.group('name').replace('native', ''),
329 params=JniParams.Parse(match.group('params')), 329 params=JniParams.Parse(match.group('params')),
330 ptr_type=ptr_type) 330 ptr_type=ptr_type)
331 natives += [native] 331 natives += [native]
(...skipping 194 matching lines...) Expand 10 before | Expand all | Expand 10 after
526 self.inl_header_file_generator = InlHeaderFileGenerator( 526 self.inl_header_file_generator = InlHeaderFileGenerator(
527 self.namespace, self.fully_qualified_class, [], 527 self.namespace, self.fully_qualified_class, [],
528 self.called_by_natives, options) 528 self.called_by_natives, options)
529 529
530 def GetContent(self): 530 def GetContent(self):
531 return self.inl_header_file_generator.GetContent() 531 return self.inl_header_file_generator.GetContent()
532 532
533 @staticmethod 533 @staticmethod
534 def CreateFromClass(class_file, options): 534 def CreateFromClass(class_file, options):
535 class_name = os.path.splitext(os.path.basename(class_file))[0] 535 class_name = os.path.splitext(os.path.basename(class_file))[0]
536 p = subprocess.Popen(args=['javap', '-s', class_name], 536 p = subprocess.Popen(args=[options.javap, '-s', class_name],
537 cwd=os.path.dirname(class_file), 537 cwd=os.path.dirname(class_file),
538 stdout=subprocess.PIPE, 538 stdout=subprocess.PIPE,
539 stderr=subprocess.PIPE) 539 stderr=subprocess.PIPE)
540 stdout, _ = p.communicate() 540 stdout, _ = p.communicate()
541 jni_from_javap = JNIFromJavaP(stdout.split('\n'), options) 541 jni_from_javap = JNIFromJavaP(stdout.split('\n'), options)
542 return jni_from_javap 542 return jni_from_javap
543 543
544 544
545 class JNIFromJavaSource(object): 545 class JNIFromJavaSource(object):
546 """Uses the given java source file to generate the JNI header file.""" 546 """Uses the given java source file to generate the JNI header file."""
547 547
548 def __init__(self, contents, fully_qualified_class, options): 548 def __init__(self, contents, fully_qualified_class, options):
549 contents = self._RemoveComments(contents) 549 contents = self._RemoveComments(contents, options)
550 JniParams.SetFullyQualifiedClass(fully_qualified_class) 550 JniParams.SetFullyQualifiedClass(fully_qualified_class)
551 JniParams.ExtractImportsAndInnerClasses(contents) 551 JniParams.ExtractImportsAndInnerClasses(contents)
552 jni_namespace = ExtractJNINamespace(contents) or options.namespace 552 jni_namespace = ExtractJNINamespace(contents) or options.namespace
553 natives = ExtractNatives(contents, options.ptr_type) 553 natives = ExtractNatives(contents, options.ptr_type)
554 called_by_natives = ExtractCalledByNatives(contents) 554 called_by_natives = ExtractCalledByNatives(contents)
555 if len(natives) == 0 and len(called_by_natives) == 0: 555 if len(natives) == 0 and len(called_by_natives) == 0:
556 raise SyntaxError('Unable to find any JNI methods for %s.' % 556 raise SyntaxError('Unable to find any JNI methods for %s.' %
557 fully_qualified_class) 557 fully_qualified_class)
558 inl_header_file_generator = InlHeaderFileGenerator( 558 inl_header_file_generator = InlHeaderFileGenerator(
559 jni_namespace, fully_qualified_class, natives, called_by_natives, 559 jni_namespace, fully_qualified_class, natives, called_by_natives,
560 options) 560 options)
561 self.content = inl_header_file_generator.GetContent() 561 self.content = inl_header_file_generator.GetContent()
562 562
563 def _RemoveComments(self, contents): 563 def _RemoveComments(self, contents, options):
564 # We need to support both inline and block comments, and we need to handle 564 # We need to support both inline and block comments, and we need to handle
565 # strings that contain '//' or '/*'. Rather than trying to do all that with 565 # strings that contain '//' or '/*'. Rather than trying to do all that with
566 # regexps, we just pipe the contents through the C preprocessor. We tell cpp 566 # regexps, we just pipe the contents through the C preprocessor. We tell cpp
567 # the file has already been preprocessed, so it just removes comments and 567 # the file has already been preprocessed, so it just removes comments and
568 # doesn't try to parse #include, #pragma etc. 568 # doesn't try to parse #include, #pragma etc.
569 # 569 #
570 # TODO(husky): This is a bit hacky. It would be cleaner to use a real Java 570 # TODO(husky): This is a bit hacky. It would be cleaner to use a real Java
571 # parser. Maybe we could ditch JNIFromJavaSource and just always use 571 # parser. Maybe we could ditch JNIFromJavaSource and just always use
572 # JNIFromJavaP; or maybe we could rewrite this script in Java and use APT. 572 # JNIFromJavaP; or maybe we could rewrite this script in Java and use APT.
573 # http://code.google.com/p/chromium/issues/detail?id=138941 573 # http://code.google.com/p/chromium/issues/detail?id=138941
574 p = subprocess.Popen(args=['cpp', '-fpreprocessed'], 574 p = subprocess.Popen(args=[options.cpp, '-fpreprocessed'],
575 stdin=subprocess.PIPE, 575 stdin=subprocess.PIPE,
576 stdout=subprocess.PIPE, 576 stdout=subprocess.PIPE,
577 stderr=subprocess.PIPE) 577 stderr=subprocess.PIPE)
578 stdout, _ = p.communicate(contents) 578 stdout, _ = p.communicate(contents)
579 return stdout 579 return stdout
580 580
581 def GetContent(self): 581 def GetContent(self):
582 return self.content 582 return self.content
583 583
584 @staticmethod 584 @staticmethod
(...skipping 13 matching lines...) Expand all
598 self.fully_qualified_class = fully_qualified_class 598 self.fully_qualified_class = fully_qualified_class
599 self.class_name = self.fully_qualified_class.split('/')[-1] 599 self.class_name = self.fully_qualified_class.split('/')[-1]
600 self.natives = natives 600 self.natives = natives
601 self.called_by_natives = called_by_natives 601 self.called_by_natives = called_by_natives
602 self.header_guard = fully_qualified_class.replace('/', '_') + '_JNI' 602 self.header_guard = fully_qualified_class.replace('/', '_') + '_JNI'
603 self.options = options 603 self.options = options
604 self.init_native = self.ExtractInitNative(options) 604 self.init_native = self.ExtractInitNative(options)
605 605
606 def ExtractInitNative(self, options): 606 def ExtractInitNative(self, options):
607 for native in self.natives: 607 for native in self.natives:
608 if options.jni_init_native_name == native.name: 608 if options.jni_init_native_name == 'native' + native.name:
609 self.natives.remove(native) 609 self.natives.remove(native)
610 return native 610 return native
611 return None 611 return None
612 612
613 def GetContent(self): 613 def GetContent(self):
614 """Returns the content of the JNI binding file.""" 614 """Returns the content of the JNI binding file."""
615 template = Template("""\ 615 template = Template("""\
616 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 616 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
617 // Use of this source code is governed by a BSD-style license that can be 617 // Use of this source code is governed by a BSD-style license that can be
618 // found in the LICENSE file. 618 // found in the LICENSE file.
(...skipping 205 matching lines...) Expand 10 before | Expand all | Expand 10 after
824 extern "C" JNIEXPORT bool JNICALL 824 extern "C" JNIEXPORT bool JNICALL
825 Java_${FULLY_QUALIFIED_CLASS}_${INIT_NATIVE_NAME}(JNIEnv* env, jclass clazz) { 825 Java_${FULLY_QUALIFIED_CLASS}_${INIT_NATIVE_NAME}(JNIEnv* env, jclass clazz) {
826 return ${NAMESPACE}RegisterNativesImpl(env, clazz); 826 return ${NAMESPACE}RegisterNativesImpl(env, clazz);
827 } 827 }
828 """) 828 """)
829 fully_qualified_class = self.fully_qualified_class.replace('/', '_') 829 fully_qualified_class = self.fully_qualified_class.replace('/', '_')
830 namespace = '' 830 namespace = ''
831 if self.namespace: 831 if self.namespace:
832 namespace = self.namespace + '::' 832 namespace = self.namespace + '::'
833 values = {'FULLY_QUALIFIED_CLASS': fully_qualified_class, 833 values = {'FULLY_QUALIFIED_CLASS': fully_qualified_class,
834 'INIT_NATIVE_NAME': self.init_native.name, 834 'INIT_NATIVE_NAME': 'native' + self.init_native.name,
835 'NAMESPACE': namespace, 835 'NAMESPACE': namespace,
836 'REGISTER_NATIVES_IMPL': self.GetRegisterNativesImplString() 836 'REGISTER_NATIVES_IMPL': self.GetRegisterNativesImplString()
837 } 837 }
838 return template.substitute(values) 838 return template.substitute(values)
839 839
840 def GetOpenNamespaceString(self): 840 def GetOpenNamespaceString(self):
841 if self.namespace: 841 if self.namespace:
842 all_namespaces = ['namespace %s {' % ns 842 all_namespaces = ['namespace %s {' % ns
843 for ns in self.namespace.split('::')] 843 for ns in self.namespace.split('::')]
844 return '\n'.join(all_namespaces) 844 return '\n'.join(all_namespaces)
(...skipping 418 matching lines...) Expand 10 before | Expand all | Expand 10 after
1263 'method with this name is not present in the Java ' 1263 'method with this name is not present in the Java '
1264 'source file, setting this option is a no-op. When ' 1264 'source file, setting this option is a no-op. When '
1265 'a method with this name is found however, the ' 1265 'a method with this name is found however, the '
1266 'naming convention Java_<packageName>_<className> ' 1266 'naming convention Java_<packageName>_<className> '
1267 'will limit the initialization to only the ' 1267 'will limit the initialization to only the '
1268 'top-level class.') 1268 'top-level class.')
1269 option_parser.add_option('--eager_called_by_natives', 1269 option_parser.add_option('--eager_called_by_natives',
1270 action='store_true', dest='eager_called_by_natives', 1270 action='store_true', dest='eager_called_by_natives',
1271 help='When true, the called-by-native methods will ' 1271 help='When true, the called-by-native methods will '
1272 'be initialized in a non-atomic way.') 1272 'be initialized in a non-atomic way.')
1273 option_parser.add_option('--cpp', default='cpp',
1274 help='The path to cpp command.')
1275 option_parser.add_option('--javap', default='javap',
1276 help='The path to javap command.')
1273 options, args = option_parser.parse_args(argv) 1277 options, args = option_parser.parse_args(argv)
1274 if options.jar_file: 1278 if options.jar_file:
1275 input_file = ExtractJarInputFile(options.jar_file, options.input_file, 1279 input_file = ExtractJarInputFile(options.jar_file, options.input_file,
1276 options.output_dir) 1280 options.output_dir)
1277 elif options.input_file: 1281 elif options.input_file:
1278 input_file = options.input_file 1282 input_file = options.input_file
1279 else: 1283 else:
1280 option_parser.print_help() 1284 option_parser.print_help()
1281 print '\nError: Must specify --jar_file or --input_file.' 1285 print '\nError: Must specify --jar_file or --input_file.'
1282 return 1 1286 return 1
1283 output_file = None 1287 output_file = None
1284 if options.output_dir: 1288 if options.output_dir:
1285 root_name = os.path.splitext(os.path.basename(input_file))[0] 1289 root_name = os.path.splitext(os.path.basename(input_file))[0]
1286 output_file = os.path.join(options.output_dir, root_name) + '_jni.h' 1290 output_file = os.path.join(options.output_dir, root_name) + '_jni.h'
1287 if options.jarjar: 1291 if options.jarjar:
1288 with open(options.jarjar) as f: 1292 with open(options.jarjar) as f:
1289 JniParams.SetJarJarMappings(f.read()) 1293 JniParams.SetJarJarMappings(f.read())
1290 GenerateJNIHeader(input_file, output_file, options) 1294 GenerateJNIHeader(input_file, output_file, options)
1291 1295
1292 1296
1293 if __name__ == '__main__': 1297 if __name__ == '__main__':
1294 sys.exit(main(sys.argv)) 1298 sys.exit(main(sys.argv))
OLDNEW
« no previous file with comments | « no previous file | base/android/jni_generator/jni_generator_tests.py » ('j') | base/android/jni_generator/jni_generator_tests.py » ('J')

Powered by Google App Engine
This is Rietveld 408576698