mirror of
				https://github.com/godotengine/godot.git
				synced 2025-10-31 05:31:01 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			310 lines
		
	
	
	
		
			11 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			310 lines
		
	
	
	
		
			11 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
| """Functions used to generate source files during build time
 | |
| 
 | |
| All such functions are invoked in a subprocess on Windows to prevent build flakiness.
 | |
| 
 | |
| """
 | |
| import json
 | |
| from platform_methods import subprocess_main
 | |
| 
 | |
| 
 | |
| def _spaced(e):
 | |
|     return e if e[-1] == '*' else e + ' '
 | |
| 
 | |
| 
 | |
| def _build_gdnative_api_struct_header(api):
 | |
|     gdnative_api_init_macro = [
 | |
|         '\textern const godot_gdnative_core_api_struct *_gdnative_wrapper_api_struct;'
 | |
|     ]
 | |
| 
 | |
|     for ext in api['extensions']:
 | |
|         name = ext['name']
 | |
|         gdnative_api_init_macro.append(
 | |
|             '\textern const godot_gdnative_ext_{0}_api_struct *_gdnative_wrapper_{0}_api_struct;'.format(name))
 | |
| 
 | |
|     gdnative_api_init_macro.append('\t_gdnative_wrapper_api_struct = options->api_struct;')
 | |
|     gdnative_api_init_macro.append('\tfor (unsigned int i = 0; i < _gdnative_wrapper_api_struct->num_extensions; i++) { ')
 | |
|     gdnative_api_init_macro.append('\t\tswitch (_gdnative_wrapper_api_struct->extensions[i]->type) {')
 | |
| 
 | |
|     for ext in api['extensions']:
 | |
|         name = ext['name']
 | |
|         gdnative_api_init_macro.append(
 | |
|             '\t\t\tcase GDNATIVE_EXT_%s:' % ext['type'])
 | |
|         gdnative_api_init_macro.append(
 | |
|             '\t\t\t\t_gdnative_wrapper_{0}_api_struct = (godot_gdnative_ext_{0}_api_struct *)'
 | |
|             ' _gdnative_wrapper_api_struct->extensions[i];'.format(name))
 | |
|         gdnative_api_init_macro.append('\t\t\t\tbreak;')
 | |
|     gdnative_api_init_macro.append('\t\t}')
 | |
|     gdnative_api_init_macro.append('\t}')
 | |
| 
 | |
|     out = [
 | |
|         '/* THIS FILE IS GENERATED DO NOT EDIT */',
 | |
|         '#ifndef GODOT_GDNATIVE_API_STRUCT_H',
 | |
|         '#define GODOT_GDNATIVE_API_STRUCT_H',
 | |
|         '',
 | |
|         '#include <gdnative/gdnative.h>',
 | |
|         '#include <android/godot_android.h>',
 | |
|         '#include <arvr/godot_arvr.h>',
 | |
|         '#include <nativescript/godot_nativescript.h>',
 | |
|         '#include <pluginscript/godot_pluginscript.h>',
 | |
|         '',
 | |
|         '#define GDNATIVE_API_INIT(options) do {  \\\n' + '  \\\n'.join(gdnative_api_init_macro) + '  \\\n } while (0)',
 | |
|         '',
 | |
|         '#ifdef __cplusplus',
 | |
|         'extern "C" {',
 | |
|         '#endif',
 | |
|         '',
 | |
|         'enum GDNATIVE_API_TYPES {',
 | |
|         '\tGDNATIVE_' + api['core']['type'] + ','
 | |
|     ]
 | |
| 
 | |
|     for ext in api['extensions']:
 | |
|         out += ['\tGDNATIVE_EXT_' + ext['type'] + ',']
 | |
| 
 | |
|     out += ['};', '']
 | |
| 
 | |
|     def generate_extension_struct(name, ext, include_version=True):
 | |
|         ret_val = []
 | |
|         if ext['next']:
 | |
|             ret_val += generate_extension_struct(name, ext['next'])
 | |
| 
 | |
|         ret_val += [
 | |
|             'typedef struct godot_gdnative_ext_' + name + ('' if not include_version else ('_{0}_{1}'.format(ext['version']['major'], ext['version']['minor']))) + '_api_struct {',
 | |
|             '\tunsigned int type;',
 | |
|             '\tgodot_gdnative_api_version version;',
 | |
|             '\tconst godot_gdnative_api_struct *next;'
 | |
|         ]
 | |
| 
 | |
|         for funcdef in ext['api']:
 | |
|             args = ', '.join(['%s%s' % (_spaced(t), n) for t, n in funcdef['arguments']])
 | |
|             ret_val.append('\t%s(*%s)(%s);' % (_spaced(funcdef['return_type']), funcdef['name'], args))
 | |
| 
 | |
|         ret_val += ['} godot_gdnative_ext_' + name + ('' if not include_version else ('_{0}_{1}'.format(ext['version']['major'], ext['version']['minor']))) + '_api_struct;', '']
 | |
| 
 | |
|         return ret_val
 | |
| 
 | |
| 
 | |
|     def generate_core_extension_struct(core):
 | |
|         ret_val = []
 | |
|         if core['next']:
 | |
|             ret_val += generate_core_extension_struct(core['next'])
 | |
|         
 | |
|         ret_val += [
 | |
|             'typedef struct godot_gdnative_core_' + ('{0}_{1}'.format(core['version']['major'], core['version']['minor'])) + '_api_struct {',
 | |
|             '\tunsigned int type;',
 | |
|             '\tgodot_gdnative_api_version version;',
 | |
|             '\tconst godot_gdnative_api_struct *next;',
 | |
|         ]
 | |
|         
 | |
|         for funcdef in core['api']:
 | |
|             args = ', '.join(['%s%s' % (_spaced(t), n) for t, n in funcdef['arguments']])
 | |
|             ret_val.append('\t%s(*%s)(%s);' % (_spaced(funcdef['return_type']), funcdef['name'], args))
 | |
|         
 | |
|         ret_val += ['} godot_gdnative_core_' + '{0}_{1}'.format(core['version']['major'], core['version']['minor']) + '_api_struct;', '']
 | |
|         
 | |
|         return ret_val
 | |
| 
 | |
| 
 | |
|     for ext in api['extensions']:
 | |
|         name = ext['name']
 | |
|         out += generate_extension_struct(name, ext, False)
 | |
| 
 | |
|     if api['core']['next']:
 | |
|         out += generate_core_extension_struct(api['core']['next'])
 | |
| 
 | |
|     out += [
 | |
|         'typedef struct godot_gdnative_core_api_struct {',
 | |
|         '\tunsigned int type;',
 | |
|         '\tgodot_gdnative_api_version version;',
 | |
|         '\tconst godot_gdnative_api_struct *next;',
 | |
|         '\tunsigned int num_extensions;',
 | |
|         '\tconst godot_gdnative_api_struct **extensions;',
 | |
|     ]
 | |
| 
 | |
|     for funcdef in api['core']['api']:
 | |
|         args = ', '.join(['%s%s' % (_spaced(t), n) for t, n in funcdef['arguments']])
 | |
|         out.append('\t%s(*%s)(%s);' % (_spaced(funcdef['return_type']), funcdef['name'], args))
 | |
| 
 | |
|     out += [
 | |
|         '} godot_gdnative_core_api_struct;',
 | |
|         '',
 | |
|         '#ifdef __cplusplus',
 | |
|         '}',
 | |
|         '#endif',
 | |
|         '',
 | |
|         '#endif // GODOT_GDNATIVE_API_STRUCT_H',
 | |
|         ''
 | |
|     ]
 | |
|     return '\n'.join(out)
 | |
| 
 | |
| 
 | |
| def _build_gdnative_api_struct_source(api):
 | |
|     out = [
 | |
|         '/* THIS FILE IS GENERATED DO NOT EDIT */',
 | |
|         '',
 | |
|         '#include <gdnative_api_struct.gen.h>',
 | |
|         ''
 | |
|     ]
 | |
| 
 | |
|     def get_extension_struct_name(name, ext, include_version=True):
 | |
|         return 'godot_gdnative_ext_' + name + ('' if not include_version else ('_{0}_{1}'.format(ext['version']['major'], ext['version']['minor']))) + '_api_struct'
 | |
| 
 | |
|     def get_extension_struct_instance_name(name, ext, include_version=True):
 | |
|         return 'api_extension_' + name + ('' if not include_version else ('_{0}_{1}'.format(ext['version']['major'], ext['version']['minor']))) + '_struct'
 | |
| 
 | |
|     def get_extension_struct_definition(name, ext, include_version=True):
 | |
| 
 | |
|         ret_val = []
 | |
| 
 | |
|         if ext['next']:
 | |
|             ret_val += get_extension_struct_definition(name, ext['next'])
 | |
| 
 | |
|         ret_val += [
 | |
|             'extern const ' + get_extension_struct_name(name, ext, include_version) + ' ' + get_extension_struct_instance_name(name, ext, include_version) + ' = {',
 | |
|             '\tGDNATIVE_EXT_' + ext['type'] + ',',
 | |
|             '\t{' + str(ext['version']['major']) + ', ' + str(ext['version']['minor']) + '},',
 | |
|             '\t' + ('NULL' if not ext['next'] else ('(const godot_gdnative_api_struct *)&' + get_extension_struct_instance_name(name, ext['next']))) + ','
 | |
|         ]
 | |
| 
 | |
|         for funcdef in ext['api']:
 | |
|             ret_val.append('\t%s,' % funcdef['name'])
 | |
| 
 | |
|         ret_val += ['};\n']
 | |
| 
 | |
|         return ret_val
 | |
|     
 | |
|     
 | |
|     def get_core_struct_definition(core):
 | |
|         ret_val = []
 | |
|         
 | |
|         if core['next']:
 | |
|             ret_val += get_core_struct_definition(core['next'])
 | |
|         
 | |
|         ret_val += [
 | |
|             'extern const godot_gdnative_core_' + ('{0}_{1}_api_struct api_{0}_{1}'.format(core['version']['major'], core['version']['minor'])) + ' = {',
 | |
|             '\tGDNATIVE_' + core['type'] + ',',
 | |
|             '\t{' + str(core['version']['major']) + ', ' + str(core['version']['minor']) + '},',
 | |
|             '\t' + ('NULL' if not core['next'] else ('(const godot_gdnative_api_struct *)& api_{0}_{1}'.format(core['version']['major'], core['version']['minor']))) + ','
 | |
|         ]
 | |
|         
 | |
|         for funcdef in core['api']:
 | |
|             ret_val.append('\t%s,' % funcdef['name'])
 | |
|         
 | |
|         ret_val += ['};\n']
 | |
|         
 | |
|         return ret_val
 | |
| 
 | |
|     for ext in api['extensions']:
 | |
|         name = ext['name']
 | |
|         out += get_extension_struct_definition(name, ext, False)
 | |
| 
 | |
|     out += ['', 'const godot_gdnative_api_struct *gdnative_extensions_pointers[] = {']
 | |
| 
 | |
|     for ext in api['extensions']:
 | |
|         name = ext['name']
 | |
|         out += ['\t(godot_gdnative_api_struct *)&api_extension_' + name + '_struct,']
 | |
| 
 | |
|     out += ['};\n']
 | |
|     
 | |
|     if api['core']['next']:
 | |
|         out += get_core_struct_definition(api['core']['next'])
 | |
| 
 | |
|     out += [
 | |
|         'extern const godot_gdnative_core_api_struct api_struct = {',
 | |
|         '\tGDNATIVE_' + api['core']['type'] + ',',
 | |
|         '\t{' + str(api['core']['version']['major']) + ', ' + str(api['core']['version']['minor']) + '},',
 | |
|         '\tNULL,',
 | |
|         '\t' + str(len(api['extensions'])) + ',',
 | |
|         '\tgdnative_extensions_pointers,',
 | |
|     ]
 | |
| 
 | |
|     for funcdef in api['core']['api']:
 | |
|         out.append('\t%s,' % funcdef['name'])
 | |
|     out.append('};\n')
 | |
| 
 | |
|     return '\n'.join(out)
 | |
| 
 | |
| 
 | |
| def build_gdnative_api_struct(target, source, env):
 | |
| 
 | |
|     with open(source[0], 'r') as fd:
 | |
|         api = json.load(fd)
 | |
| 
 | |
|     header, source = target
 | |
|     with open(header, 'w') as fd:
 | |
|         fd.write(_build_gdnative_api_struct_header(api))
 | |
|     with open(source, 'w') as fd:
 | |
|         fd.write(_build_gdnative_api_struct_source(api))
 | |
| 
 | |
| 
 | |
| def _build_gdnative_wrapper_code(api):
 | |
|     out = [
 | |
|         '/* THIS FILE IS GENERATED DO NOT EDIT */',
 | |
|         '',
 | |
|         '#include <gdnative/gdnative.h>',
 | |
|         '#include <nativescript/godot_nativescript.h>',
 | |
|         '#include <pluginscript/godot_pluginscript.h>',
 | |
|         '#include <arvr/godot_arvr.h>',
 | |
|         '',
 | |
|         '#include <gdnative_api_struct.gen.h>',
 | |
|         '',
 | |
|         '#ifdef __cplusplus',
 | |
|         'extern "C" {',
 | |
|         '#endif',
 | |
|         '',
 | |
|         'godot_gdnative_core_api_struct *_gdnative_wrapper_api_struct = 0;',
 | |
|     ]
 | |
| 
 | |
|     for ext in api['extensions']:
 | |
|         name = ext['name']
 | |
|         out.append('godot_gdnative_ext_' + name + '_api_struct *_gdnative_wrapper_' + name + '_api_struct = 0;')
 | |
| 
 | |
|     out += ['']
 | |
| 
 | |
|     for funcdef in api['core']['api']:
 | |
|         args = ', '.join(['%s%s' % (_spaced(t), n) for t, n in funcdef['arguments']])
 | |
|         out.append('%s%s(%s) {' % (_spaced(funcdef['return_type']), funcdef['name'], args))
 | |
| 
 | |
|         args = ', '.join(['%s' % n for t, n in funcdef['arguments']])
 | |
| 
 | |
|         return_line = '\treturn ' if funcdef['return_type'] != 'void' else '\t'
 | |
|         return_line += '_gdnative_wrapper_api_struct->' + funcdef['name'] + '(' + args + ');'
 | |
| 
 | |
|         out.append(return_line)
 | |
|         out.append('}')
 | |
|         out.append('')
 | |
| 
 | |
|     for ext in api['extensions']:
 | |
|         name = ext['name']
 | |
|         for funcdef in ext['api']:
 | |
|             args = ', '.join(['%s%s' % (_spaced(t), n) for t, n in funcdef['arguments']])
 | |
|             out.append('%s%s(%s) {' % (_spaced(funcdef['return_type']), funcdef['name'], args))
 | |
| 
 | |
|             args = ', '.join(['%s' % n for t, n in funcdef['arguments']])
 | |
| 
 | |
|             return_line = '\treturn ' if funcdef['return_type'] != 'void' else '\t'
 | |
|             return_line += '_gdnative_wrapper_' + name + '_api_struct->' + funcdef['name'] + '(' + args + ');'
 | |
| 
 | |
|             out.append(return_line)
 | |
|             out.append('}')
 | |
|             out.append('')
 | |
| 
 | |
|     out += [
 | |
|         '#ifdef __cplusplus',
 | |
|         '}',
 | |
|         '#endif'
 | |
|     ]
 | |
| 
 | |
|     return '\n'.join(out)
 | |
| 
 | |
| 
 | |
| def build_gdnative_wrapper_code(target, source, env):
 | |
|     with open(source[0], 'r') as fd:
 | |
|         api = json.load(fd)
 | |
| 
 | |
|     wrapper_file = target[0]
 | |
|     with open(wrapper_file, 'w') as fd:
 | |
|         fd.write(_build_gdnative_wrapper_code(api))
 | |
| 
 | |
| 
 | |
| if __name__ == '__main__':
 | |
|     subprocess_main(globals())
 | 
