2
0

gdnative_builders.py 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313
  1. """Functions used to generate source files during build time
  2. All such functions are invoked in a subprocess on Windows to prevent build flakiness.
  3. """
  4. import json
  5. from platform_methods import subprocess_main
  6. def _spaced(e):
  7. return e if e[-1] == '*' else e + ' '
  8. def _build_gdnative_api_struct_header(api):
  9. gdnative_api_init_macro = [
  10. '\textern const godot_gdnative_core_api_struct *_gdnative_wrapper_api_struct;'
  11. ]
  12. for ext in api['extensions']:
  13. name = ext['name']
  14. gdnative_api_init_macro.append(
  15. '\textern const godot_gdnative_ext_{0}_api_struct *_gdnative_wrapper_{0}_api_struct;'.format(name))
  16. gdnative_api_init_macro.append('\t_gdnative_wrapper_api_struct = options->api_struct;')
  17. gdnative_api_init_macro.append('\tfor (unsigned int i = 0; i < _gdnative_wrapper_api_struct->num_extensions; i++) { ')
  18. gdnative_api_init_macro.append('\t\tswitch (_gdnative_wrapper_api_struct->extensions[i]->type) {')
  19. for ext in api['extensions']:
  20. name = ext['name']
  21. gdnative_api_init_macro.append(
  22. '\t\t\tcase GDNATIVE_EXT_%s:' % ext['type'])
  23. gdnative_api_init_macro.append(
  24. '\t\t\t\t_gdnative_wrapper_{0}_api_struct = (godot_gdnative_ext_{0}_api_struct *)'
  25. ' _gdnative_wrapper_api_struct->extensions[i];'.format(name))
  26. gdnative_api_init_macro.append('\t\t\t\tbreak;')
  27. gdnative_api_init_macro.append('\t\t}')
  28. gdnative_api_init_macro.append('\t}')
  29. out = [
  30. '/* THIS FILE IS GENERATED DO NOT EDIT */',
  31. '#ifndef GODOT_GDNATIVE_API_STRUCT_H',
  32. '#define GODOT_GDNATIVE_API_STRUCT_H',
  33. '',
  34. '#include <gdnative/gdnative.h>',
  35. '#include <android/godot_android.h>',
  36. '#include <arvr/godot_arvr.h>',
  37. '#include <nativescript/godot_nativescript.h>',
  38. '#include <net/godot_net.h>',
  39. '#include <pluginscript/godot_pluginscript.h>',
  40. '#include <videodecoder/godot_videodecoder.h>',
  41. '',
  42. '#define GDNATIVE_API_INIT(options) do { \\\n' + ' \\\n'.join(gdnative_api_init_macro) + ' \\\n } while (0)',
  43. '',
  44. '#ifdef __cplusplus',
  45. 'extern "C" {',
  46. '#endif',
  47. '',
  48. 'enum GDNATIVE_API_TYPES {',
  49. '\tGDNATIVE_' + api['core']['type'] + ','
  50. ]
  51. for ext in api['extensions']:
  52. out += ['\tGDNATIVE_EXT_' + ext['type'] + ',']
  53. out += ['};', '']
  54. def generate_extension_struct(name, ext, include_version=True):
  55. ret_val = []
  56. if ext['next']:
  57. ret_val += generate_extension_struct(name, ext['next'])
  58. ret_val += [
  59. 'typedef struct godot_gdnative_ext_' + name + ('' if not include_version else ('_{0}_{1}'.format(ext['version']['major'], ext['version']['minor']))) + '_api_struct {',
  60. '\tunsigned int type;',
  61. '\tgodot_gdnative_api_version version;',
  62. '\tconst godot_gdnative_api_struct *next;'
  63. ]
  64. for funcdef in ext['api']:
  65. args = ', '.join(['%s%s' % (_spaced(t), n) for t, n in funcdef['arguments']])
  66. ret_val.append('\t%s(*%s)(%s);' % (_spaced(funcdef['return_type']), funcdef['name'], args))
  67. ret_val += ['} godot_gdnative_ext_' + name + ('' if not include_version else ('_{0}_{1}'.format(ext['version']['major'], ext['version']['minor']))) + '_api_struct;', '']
  68. return ret_val
  69. def generate_core_extension_struct(core):
  70. ret_val = []
  71. if core['next']:
  72. ret_val += generate_core_extension_struct(core['next'])
  73. ret_val += [
  74. 'typedef struct godot_gdnative_core_' + ('{0}_{1}'.format(core['version']['major'], core['version']['minor'])) + '_api_struct {',
  75. '\tunsigned int type;',
  76. '\tgodot_gdnative_api_version version;',
  77. '\tconst godot_gdnative_api_struct *next;',
  78. ]
  79. for funcdef in core['api']:
  80. args = ', '.join(['%s%s' % (_spaced(t), n) for t, n in funcdef['arguments']])
  81. ret_val.append('\t%s(*%s)(%s);' % (_spaced(funcdef['return_type']), funcdef['name'], args))
  82. ret_val += ['} godot_gdnative_core_' + '{0}_{1}'.format(core['version']['major'], core['version']['minor']) + '_api_struct;', '']
  83. return ret_val
  84. for ext in api['extensions']:
  85. name = ext['name']
  86. out += generate_extension_struct(name, ext, False)
  87. if api['core']['next']:
  88. out += generate_core_extension_struct(api['core']['next'])
  89. out += [
  90. 'typedef struct godot_gdnative_core_api_struct {',
  91. '\tunsigned int type;',
  92. '\tgodot_gdnative_api_version version;',
  93. '\tconst godot_gdnative_api_struct *next;',
  94. '\tunsigned int num_extensions;',
  95. '\tconst godot_gdnative_api_struct **extensions;',
  96. ]
  97. for funcdef in api['core']['api']:
  98. args = ', '.join(['%s%s' % (_spaced(t), n) for t, n in funcdef['arguments']])
  99. out.append('\t%s(*%s)(%s);' % (_spaced(funcdef['return_type']), funcdef['name'], args))
  100. out += [
  101. '} godot_gdnative_core_api_struct;',
  102. '',
  103. '#ifdef __cplusplus',
  104. '}',
  105. '#endif',
  106. '',
  107. '#endif // GODOT_GDNATIVE_API_STRUCT_H',
  108. ''
  109. ]
  110. return '\n'.join(out)
  111. def _build_gdnative_api_struct_source(api):
  112. out = [
  113. '/* THIS FILE IS GENERATED DO NOT EDIT */',
  114. '',
  115. '#include <gdnative_api_struct.gen.h>',
  116. ''
  117. ]
  118. def get_extension_struct_name(name, ext, include_version=True):
  119. return 'godot_gdnative_ext_' + name + ('' if not include_version else ('_{0}_{1}'.format(ext['version']['major'], ext['version']['minor']))) + '_api_struct'
  120. def get_extension_struct_instance_name(name, ext, include_version=True):
  121. return 'api_extension_' + name + ('' if not include_version else ('_{0}_{1}'.format(ext['version']['major'], ext['version']['minor']))) + '_struct'
  122. def get_extension_struct_definition(name, ext, include_version=True):
  123. ret_val = []
  124. if ext['next']:
  125. ret_val += get_extension_struct_definition(name, ext['next'])
  126. ret_val += [
  127. 'extern const ' + get_extension_struct_name(name, ext, include_version) + ' ' + get_extension_struct_instance_name(name, ext, include_version) + ' = {',
  128. '\tGDNATIVE_EXT_' + ext['type'] + ',',
  129. '\t{' + str(ext['version']['major']) + ', ' + str(ext['version']['minor']) + '},',
  130. '\t' + ('NULL' if not ext['next'] else ('(const godot_gdnative_api_struct *)&' + get_extension_struct_instance_name(name, ext['next']))) + ','
  131. ]
  132. for funcdef in ext['api']:
  133. ret_val.append('\t%s,' % funcdef['name'])
  134. ret_val += ['};\n']
  135. return ret_val
  136. def get_core_struct_definition(core):
  137. ret_val = []
  138. if core['next']:
  139. ret_val += get_core_struct_definition(core['next'])
  140. ret_val += [
  141. 'extern const godot_gdnative_core_' + ('{0}_{1}_api_struct api_{0}_{1}'.format(core['version']['major'], core['version']['minor'])) + ' = {',
  142. '\tGDNATIVE_' + core['type'] + ',',
  143. '\t{' + str(core['version']['major']) + ', ' + str(core['version']['minor']) + '},',
  144. '\t' + ('NULL' if not core['next'] else ('(const godot_gdnative_api_struct *)& api_{0}_{1}'.format(core['version']['major'], core['version']['minor']))) + ','
  145. ]
  146. for funcdef in core['api']:
  147. ret_val.append('\t%s,' % funcdef['name'])
  148. ret_val += ['};\n']
  149. return ret_val
  150. for ext in api['extensions']:
  151. name = ext['name']
  152. out += get_extension_struct_definition(name, ext, False)
  153. out += ['', 'const godot_gdnative_api_struct *gdnative_extensions_pointers[] = {']
  154. for ext in api['extensions']:
  155. name = ext['name']
  156. out += ['\t(godot_gdnative_api_struct *)&api_extension_' + name + '_struct,']
  157. out += ['};\n']
  158. if api['core']['next']:
  159. out += get_core_struct_definition(api['core']['next'])
  160. out += [
  161. 'extern const godot_gdnative_core_api_struct api_struct = {',
  162. '\tGDNATIVE_' + api['core']['type'] + ',',
  163. '\t{' + str(api['core']['version']['major']) + ', ' + str(api['core']['version']['minor']) + '},',
  164. '\t(const godot_gdnative_api_struct *)&api_1_1,',
  165. '\t' + str(len(api['extensions'])) + ',',
  166. '\tgdnative_extensions_pointers,',
  167. ]
  168. for funcdef in api['core']['api']:
  169. out.append('\t%s,' % funcdef['name'])
  170. out.append('};\n')
  171. return '\n'.join(out)
  172. def build_gdnative_api_struct(target, source, env):
  173. with open(source[0], 'r') as fd:
  174. api = json.load(fd)
  175. header, source = target
  176. with open(header, 'w') as fd:
  177. fd.write(_build_gdnative_api_struct_header(api))
  178. with open(source, 'w') as fd:
  179. fd.write(_build_gdnative_api_struct_source(api))
  180. def _build_gdnative_wrapper_code(api):
  181. out = [
  182. '/* THIS FILE IS GENERATED DO NOT EDIT */',
  183. '',
  184. '#include <gdnative/gdnative.h>',
  185. '#include <nativescript/godot_nativescript.h>',
  186. '#include <pluginscript/godot_pluginscript.h>',
  187. '#include <arvr/godot_arvr.h>',
  188. '#include <videodecoder/godot_videodecoder.h>',
  189. '',
  190. '#include <gdnative_api_struct.gen.h>',
  191. '',
  192. '#ifdef __cplusplus',
  193. 'extern "C" {',
  194. '#endif',
  195. '',
  196. 'godot_gdnative_core_api_struct *_gdnative_wrapper_api_struct = 0;',
  197. ]
  198. for ext in api['extensions']:
  199. name = ext['name']
  200. out.append('godot_gdnative_ext_' + name + '_api_struct *_gdnative_wrapper_' + name + '_api_struct = 0;')
  201. out += ['']
  202. for funcdef in api['core']['api']:
  203. args = ', '.join(['%s%s' % (_spaced(t), n) for t, n in funcdef['arguments']])
  204. out.append('%s%s(%s) {' % (_spaced(funcdef['return_type']), funcdef['name'], args))
  205. args = ', '.join(['%s' % n for t, n in funcdef['arguments']])
  206. return_line = '\treturn ' if funcdef['return_type'] != 'void' else '\t'
  207. return_line += '_gdnative_wrapper_api_struct->' + funcdef['name'] + '(' + args + ');'
  208. out.append(return_line)
  209. out.append('}')
  210. out.append('')
  211. for ext in api['extensions']:
  212. name = ext['name']
  213. for funcdef in ext['api']:
  214. args = ', '.join(['%s%s' % (_spaced(t), n) for t, n in funcdef['arguments']])
  215. out.append('%s%s(%s) {' % (_spaced(funcdef['return_type']), funcdef['name'], args))
  216. args = ', '.join(['%s' % n for t, n in funcdef['arguments']])
  217. return_line = '\treturn ' if funcdef['return_type'] != 'void' else '\t'
  218. return_line += '_gdnative_wrapper_' + name + '_api_struct->' + funcdef['name'] + '(' + args + ');'
  219. out.append(return_line)
  220. out.append('}')
  221. out.append('')
  222. out += [
  223. '#ifdef __cplusplus',
  224. '}',
  225. '#endif'
  226. ]
  227. return '\n'.join(out)
  228. def build_gdnative_wrapper_code(target, source, env):
  229. with open(source[0], 'r') as fd:
  230. api = json.load(fd)
  231. wrapper_file = target[0]
  232. with open(wrapper_file, 'w') as fd:
  233. fd.write(_build_gdnative_wrapper_code(api))
  234. if __name__ == '__main__':
  235. subprocess_main(globals())