gdnative_builders.py 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311
  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 <pluginscript/godot_pluginscript.h>',
  39. '',
  40. '#define GDNATIVE_API_INIT(options) do { \\\n' + ' \\\n'.join(gdnative_api_init_macro) + ' \\\n } while (0)',
  41. '',
  42. '#ifdef __cplusplus',
  43. 'extern "C" {',
  44. '#endif',
  45. '',
  46. 'enum GDNATIVE_API_TYPES {',
  47. '\tGDNATIVE_' + api['core']['type'] + ','
  48. ]
  49. for ext in api['extensions']:
  50. out += ['\tGDNATIVE_EXT_' + ext['type'] + ',']
  51. out += ['};', '']
  52. def generate_extension_struct(name, ext, include_version=True):
  53. ret_val = []
  54. if ext['next']:
  55. ret_val += generate_extension_struct(name, ext['next'])
  56. ret_val += [
  57. 'typedef struct godot_gdnative_ext_' + name + ('' if not include_version else ('_{0}_{1}'.format(ext['version']['major'], ext['version']['minor']))) + '_api_struct {',
  58. '\tunsigned int type;',
  59. '\tgodot_gdnative_api_version version;',
  60. '\tconst godot_gdnative_api_struct *next;'
  61. ]
  62. for funcdef in ext['api']:
  63. args = ', '.join(['%s%s' % (_spaced(t), n) for t, n in funcdef['arguments']])
  64. ret_val.append('\t%s(*%s)(%s);' % (_spaced(funcdef['return_type']), funcdef['name'], args))
  65. ret_val += ['} godot_gdnative_ext_' + name + ('' if not include_version else ('_{0}_{1}'.format(ext['version']['major'], ext['version']['minor']))) + '_api_struct;', '']
  66. return ret_val
  67. def generate_core_extension_struct(core):
  68. ret_val = []
  69. if core['next']:
  70. ret_val += generate_core_extension_struct(core['next'])
  71. ret_val += [
  72. 'typedef struct godot_gdnative_core_' + ('{0}_{1}'.format(core['version']['major'], core['version']['minor'])) + '_api_struct {',
  73. '\tunsigned int type;',
  74. '\tgodot_gdnative_api_version version;',
  75. '\tconst godot_gdnative_api_struct *next;',
  76. ]
  77. for funcdef in core['api']:
  78. args = ', '.join(['%s%s' % (_spaced(t), n) for t, n in funcdef['arguments']])
  79. ret_val.append('\t%s(*%s)(%s);' % (_spaced(funcdef['return_type']), funcdef['name'], args))
  80. ret_val += ['} godot_gdnative_core_' + '{0}_{1}'.format(core['version']['major'], core['version']['minor']) + '_api_struct;', '']
  81. return ret_val
  82. for ext in api['extensions']:
  83. name = ext['name']
  84. out += generate_extension_struct(name, ext, False)
  85. if api['core']['next']:
  86. out += generate_core_extension_struct(api['core']['next'])
  87. out += [
  88. 'typedef struct godot_gdnative_core_api_struct {',
  89. '\tunsigned int type;',
  90. '\tgodot_gdnative_api_version version;',
  91. '\tconst godot_gdnative_api_struct *next;',
  92. '\tunsigned int num_extensions;',
  93. '\tconst godot_gdnative_api_struct **extensions;',
  94. ]
  95. for funcdef in api['core']['api']:
  96. args = ', '.join(['%s%s' % (_spaced(t), n) for t, n in funcdef['arguments']])
  97. out.append('\t%s(*%s)(%s);' % (_spaced(funcdef['return_type']), funcdef['name'], args))
  98. out += [
  99. '} godot_gdnative_core_api_struct;',
  100. '',
  101. '#ifdef __cplusplus',
  102. '}',
  103. '#endif',
  104. '',
  105. '#endif // GODOT_GDNATIVE_API_STRUCT_H',
  106. ''
  107. ]
  108. return '\n'.join(out)
  109. def _build_gdnative_api_struct_source(api):
  110. out = [
  111. '/* THIS FILE IS GENERATED DO NOT EDIT */',
  112. '',
  113. '#include <gdnative_api_struct.gen.h>',
  114. ''
  115. ]
  116. def get_extension_struct_name(name, ext, include_version=True):
  117. return 'godot_gdnative_ext_' + name + ('' if not include_version else ('_{0}_{1}'.format(ext['version']['major'], ext['version']['minor']))) + '_api_struct'
  118. def get_extension_struct_instance_name(name, ext, include_version=True):
  119. return 'api_extension_' + name + ('' if not include_version else ('_{0}_{1}'.format(ext['version']['major'], ext['version']['minor']))) + '_struct'
  120. def get_extension_struct_definition(name, ext, include_version=True):
  121. ret_val = []
  122. if ext['next']:
  123. ret_val += get_extension_struct_definition(name, ext['next'])
  124. ret_val += [
  125. 'extern const ' + get_extension_struct_name(name, ext, include_version) + ' ' + get_extension_struct_instance_name(name, ext, include_version) + ' = {',
  126. '\tGDNATIVE_EXT_' + ext['type'] + ',',
  127. '\t{' + str(ext['version']['major']) + ', ' + str(ext['version']['minor']) + '},',
  128. '\t' + ('NULL' if not ext['next'] else ('(const godot_gdnative_api_struct *)&' + get_extension_struct_instance_name(name, ext['next']))) + ','
  129. ]
  130. for funcdef in ext['api']:
  131. ret_val.append('\t%s,' % funcdef['name'])
  132. ret_val += ['};\n']
  133. return ret_val
  134. def get_core_struct_definition(core):
  135. ret_val = []
  136. if core['next']:
  137. ret_val += get_core_struct_definition(core['next'])
  138. ret_val += [
  139. 'extern const godot_gdnative_core_' + ('{0}_{1}_api_struct api_{0}_{1}'.format(core['version']['major'], core['version']['minor'])) + ' = {',
  140. '\tGDNATIVE_' + core['type'] + ',',
  141. '\t{' + str(core['version']['major']) + ', ' + str(core['version']['minor']) + '},',
  142. '\t' + ('NULL' if not core['next'] else ('(const godot_gdnative_api_struct *)& api_{0}_{1}'.format(core['version']['major'], core['version']['minor']))) + ','
  143. ]
  144. for funcdef in core['api']:
  145. ret_val.append('\t%s,' % funcdef['name'])
  146. ret_val += ['};\n']
  147. return ret_val
  148. for ext in api['extensions']:
  149. name = ext['name']
  150. out += get_extension_struct_definition(name, ext, False)
  151. out += ['', 'const godot_gdnative_api_struct *gdnative_extensions_pointers[] = {']
  152. for ext in api['extensions']:
  153. name = ext['name']
  154. out += ['\t(godot_gdnative_api_struct *)&api_extension_' + name + '_struct,']
  155. out += ['};\n']
  156. if api['core']['next']:
  157. out += get_core_struct_definition(api['core']['next'])
  158. out += [
  159. 'extern const godot_gdnative_core_api_struct api_struct = {',
  160. '\tGDNATIVE_' + api['core']['type'] + ',',
  161. '\t{' + str(api['core']['version']['major']) + ', ' + str(api['core']['version']['minor']) + '},',
  162. '\tNULL,',
  163. '\t' + str(len(api['extensions'])) + ',',
  164. '\tgdnative_extensions_pointers,',
  165. ]
  166. for funcdef in api['core']['api']:
  167. out.append('\t%s,' % funcdef['name'])
  168. out.append('};\n')
  169. return '\n'.join(out)
  170. def build_gdnative_api_struct(target, source, env):
  171. with open(source[0], 'r') as fd:
  172. api = json.load(fd)
  173. header, source = target
  174. with open(header, 'w') as fd:
  175. fd.write(_build_gdnative_api_struct_header(api))
  176. with open(source, 'w') as fd:
  177. fd.write(_build_gdnative_api_struct_source(api))
  178. def _build_gdnative_wrapper_code(api):
  179. out = [
  180. '/* THIS FILE IS GENERATED DO NOT EDIT */',
  181. '',
  182. '#include <gdnative/gdnative.h>',
  183. '#include <nativescript/godot_nativescript.h>',
  184. '#include <pluginscript/godot_pluginscript.h>',
  185. '#include <arvr/godot_arvr.h>',
  186. '',
  187. '#include <gdnative_api_struct.gen.h>',
  188. '',
  189. '#ifdef __cplusplus',
  190. 'extern "C" {',
  191. '#endif',
  192. '',
  193. 'godot_gdnative_core_api_struct *_gdnative_wrapper_api_struct = 0;',
  194. ]
  195. for ext in api['extensions']:
  196. name = ext['name']
  197. out.append('godot_gdnative_ext_' + name + '_api_struct *_gdnative_wrapper_' + name + '_api_struct = 0;')
  198. out += ['']
  199. for funcdef in api['core']['api']:
  200. args = ', '.join(['%s%s' % (_spaced(t), n) for t, n in funcdef['arguments']])
  201. out.append('%s%s(%s) {' % (_spaced(funcdef['return_type']), funcdef['name'], args))
  202. args = ', '.join(['%s' % n for t, n in funcdef['arguments']])
  203. return_line = '\treturn ' if funcdef['return_type'] != 'void' else '\t'
  204. return_line += '_gdnative_wrapper_api_struct->' + funcdef['name'] + '(' + args + ');'
  205. out.append(return_line)
  206. out.append('}')
  207. out.append('')
  208. for ext in api['extensions']:
  209. name = ext['name']
  210. for funcdef in ext['api']:
  211. args = ', '.join(['%s%s' % (_spaced(t), n) for t, n in funcdef['arguments']])
  212. out.append('%s%s(%s) {' % (_spaced(funcdef['return_type']), funcdef['name'], args))
  213. args = ', '.join(['%s' % n for t, n in funcdef['arguments']])
  214. return_line = '\treturn ' if funcdef['return_type'] != 'void' else '\t'
  215. return_line += '_gdnative_wrapper_' + name + '_api_struct->' + funcdef['name'] + '(' + args + ');'
  216. out.append(return_line)
  217. out.append('}')
  218. out.append('')
  219. out += [
  220. '#ifdef __cplusplus',
  221. '}',
  222. '#endif'
  223. ]
  224. return '\n'.join(out)
  225. def build_gdnative_wrapper_code(target, source, env):
  226. with open(source[0], 'r') as fd:
  227. api = json.load(fd)
  228. wrapper_file = target[0]
  229. with open(wrapper_file, 'w') as fd:
  230. fd.write(_build_gdnative_wrapper_code(api))
  231. if __name__ == '__main__':
  232. subprocess_main(globals())