gdnative_builders.py 12 KB

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