gen_odin.py 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535
  1. #-------------------------------------------------------------------------------
  2. # gen_odin.py
  3. #
  4. # Generate Odin bindings.
  5. #-------------------------------------------------------------------------------
  6. import gen_ir
  7. import gen_util as util
  8. import os, shutil, sys
  9. bindings_root = 'sokol-odin'
  10. c_root = f'{bindings_root}/sokol/c'
  11. module_root = f'{bindings_root}/sokol'
  12. module_names = {
  13. 'slog_': 'log',
  14. 'sg_': 'gfx',
  15. 'sapp_': 'app',
  16. 'stm_': 'time',
  17. 'saudio_': 'audio',
  18. 'sgl_': 'gl',
  19. 'sdtx_': 'debugtext',
  20. 'sshape_': 'shape',
  21. 'sglue_': 'glue',
  22. }
  23. system_libs = {
  24. 'sg_': {
  25. 'windows': {
  26. 'd3d11': "",
  27. 'gl': "",
  28. },
  29. 'macos': {
  30. 'metal': '"system:Cocoa.framework","system:QuartzCore.framework","system:Metal.framework","system:MetalKit.framework"',
  31. 'gl': '"system:Cocoa.framework","system:QuartzCore.framework","system:OpenGL.framework"'
  32. },
  33. 'linux': {
  34. 'gl': '"system:GL", "system:dl", "system:pthread"'
  35. }
  36. },
  37. 'sapp_': {
  38. 'windows': {
  39. 'd3d11': '',
  40. 'gl': '',
  41. },
  42. 'macos': {
  43. 'metal': '"system:Cocoa.framework","system:QuartzCore.framework","system:Metal.framework","system:MetalKit.framework"',
  44. 'gl': '"system:Cocoa.framework","system:QuartzCore.framework","system:OpenGL.framework"',
  45. },
  46. 'linux': {
  47. 'gl': '"system:X11", "system:Xi", "system:Xcursor", "system:GL", "system:dl", "system:pthread"'
  48. }
  49. },
  50. 'saudio_': {
  51. 'windows': {
  52. 'd3d11': '',
  53. 'gl': '',
  54. },
  55. 'macos': {
  56. 'metal': '"system:AudioToolbox.framework"',
  57. 'gl': '"system:AudioToolbox.framework"',
  58. },
  59. 'linux': {
  60. 'gl': '"system:asound", "system:dl", "system:pthread"',
  61. }
  62. }
  63. }
  64. c_source_names = {
  65. 'slog_': 'sokol_log.c',
  66. 'sg_': 'sokol_gfx.c',
  67. 'sapp_': 'sokol_app.c',
  68. 'sapp_sg': 'sokol_glue.c',
  69. 'stm_': 'sokol_time.c',
  70. 'saudio_': 'sokol_audio.c',
  71. 'sgl_': 'sokol_gl.c',
  72. 'sdtx_': 'sokol_debugtext.c',
  73. 'sshape_': 'sokol_shape.c',
  74. 'sglue_': 'sokol_glue.c',
  75. }
  76. ignores = [
  77. 'sdtx_printf',
  78. 'sdtx_vprintf',
  79. 'sg_install_trace_hooks',
  80. 'sg_trace_hooks',
  81. ]
  82. # NOTE: syntax for function results: "func_name.RESULT"
  83. overrides = {
  84. 'context': 'ctx', # reserved keyword
  85. 'SGL_NO_ERROR': 'SGL_ERROR_NO_ERROR',
  86. }
  87. prim_types = {
  88. 'int': 'c.int',
  89. 'bool': 'bool',
  90. 'char': 'u8',
  91. 'int8_t': 'i8',
  92. 'uint8_t': 'u8',
  93. 'int16_t': 'i16',
  94. 'uint16_t': 'u16',
  95. 'int32_t': 'i32',
  96. 'uint32_t': 'u32',
  97. 'int64_t': 'i64',
  98. 'uint64_t': 'u64',
  99. 'float': 'f32',
  100. 'double': 'f64',
  101. 'uintptr_t': 'u64',
  102. 'intptr_t': 'i64',
  103. 'size_t': 'u64'
  104. }
  105. prim_defaults = {
  106. 'int': '0',
  107. 'bool': 'false',
  108. 'int8_t': '0',
  109. 'uint8_t': '0',
  110. 'int16_t': '0',
  111. 'uint16_t': '0',
  112. 'int32_t': '0',
  113. 'uint32_t': '0',
  114. 'int64_t': '0',
  115. 'uint64_t': '0',
  116. 'float': '0.0',
  117. 'double': '0.0',
  118. 'uintptr_t': '0',
  119. 'intptr_t': '0',
  120. 'size_t': '0'
  121. }
  122. struct_types = []
  123. enum_types = []
  124. enum_items = {}
  125. out_lines = ''
  126. def reset_globals():
  127. global struct_types
  128. global enum_types
  129. global enum_items
  130. global out_lines
  131. struct_types = []
  132. enum_types = []
  133. enum_items = {}
  134. out_lines = ''
  135. def l(s):
  136. global out_lines
  137. out_lines += s + '\n'
  138. def check_override(name, default=None):
  139. if name in overrides:
  140. return overrides[name]
  141. elif default is None:
  142. return name
  143. else:
  144. return default
  145. def check_ignore(name):
  146. return name in ignores
  147. # PREFIX_BLA_BLUB to BLA_BLUB, prefix_bla_blub to bla_blub
  148. def as_snake_case(s, prefix):
  149. outp = s
  150. if outp.lower().startswith(prefix):
  151. outp = outp[len(prefix):]
  152. return outp
  153. def get_odin_module_path(c_prefix):
  154. return f'{module_root}/{module_names[c_prefix]}'
  155. def get_csource_path(c_prefix):
  156. return f'{c_root}/{c_source_names[c_prefix]}'
  157. def make_odin_module_directory(c_prefix):
  158. path = get_odin_module_path(c_prefix)
  159. if not os.path.isdir(path):
  160. os.makedirs(path)
  161. def as_prim_type(s):
  162. return prim_types[s]
  163. # prefix_bla_blub(_t) => (dep.)Bla_Blub
  164. def as_struct_or_enum_type(s, prefix):
  165. parts = s.lower().split('_')
  166. outp = '' if s.startswith(prefix) else f'{parts[0]}.'
  167. for part in parts[1:]:
  168. # ignore '_t' type postfix
  169. if (part != 't'):
  170. outp += part.capitalize()
  171. outp += '_'
  172. outp = outp[:-1]
  173. return outp
  174. # PREFIX_ENUM_BLA_BLUB => BLA_BLUB, _PREFIX_ENUM_BLA_BLUB => BLA_BLUB
  175. def as_enum_item_name(s):
  176. outp = s.lstrip('_')
  177. parts = outp.split('_')[2:]
  178. outp = '_'.join(parts)
  179. if outp[0].isdigit():
  180. outp = '_' + outp
  181. return outp
  182. def enum_default_item(enum_name):
  183. return enum_items[enum_name][0]
  184. def is_prim_type(s):
  185. return s in prim_types
  186. def is_int_type(s):
  187. return s == "int"
  188. def is_struct_type(s):
  189. return s in struct_types
  190. def is_enum_type(s):
  191. return s in enum_types
  192. def is_const_prim_ptr(s):
  193. for prim_type in prim_types:
  194. if s == f"const {prim_type} *":
  195. return True
  196. return False
  197. def is_prim_ptr(s):
  198. for prim_type in prim_types:
  199. if s == f"{prim_type} *":
  200. return True
  201. return False
  202. def is_const_struct_ptr(s):
  203. for struct_type in struct_types:
  204. if s == f"const {struct_type} *":
  205. return True
  206. return False
  207. def type_default_value(s):
  208. return prim_defaults[s]
  209. def map_type(type, prefix, sub_type):
  210. if sub_type not in ['c_arg', 'odin_arg', 'struct_field']:
  211. sys.exit(f"Error: map_type(): unknown sub_type '{sub_type}")
  212. if type == "void":
  213. return ""
  214. elif is_prim_type(type):
  215. if sub_type == 'odin_arg':
  216. # for Odin args, maps C int (32-bit) to Odin int (pointer-sized),
  217. # and the C bool type to Odin's bool type
  218. if type == 'int' or type == 'uint32_t':
  219. return 'int'
  220. elif type == 'bool':
  221. return 'bool'
  222. return as_prim_type(type)
  223. elif is_struct_type(type):
  224. return as_struct_or_enum_type(type, prefix)
  225. elif is_enum_type(type):
  226. return as_struct_or_enum_type(type, prefix)
  227. elif util.is_void_ptr(type):
  228. return "rawptr"
  229. elif util.is_const_void_ptr(type):
  230. return "rawptr"
  231. elif util.is_string_ptr(type):
  232. return "cstring"
  233. elif is_const_struct_ptr(type):
  234. # pass Odin struct args by value, not by pointer
  235. if sub_type == 'odin_arg':
  236. return f"{as_struct_or_enum_type(util.extract_ptr_type(type), prefix)}"
  237. else:
  238. return f"^{as_struct_or_enum_type(util.extract_ptr_type(type), prefix)}"
  239. elif is_prim_ptr(type):
  240. return f"^{as_prim_type(util.extract_ptr_type(type))}"
  241. elif is_const_prim_ptr(type):
  242. return f"^{as_prim_type(util.extract_ptr_type(type))}"
  243. elif util.is_1d_array_type(type):
  244. array_type = util.extract_array_type(type)
  245. array_sizes = util.extract_array_sizes(type)
  246. return f"[{array_sizes[0]}]{map_type(array_type, prefix, sub_type)}"
  247. elif util.is_2d_array_type(type):
  248. array_type = util.extract_array_type(type)
  249. array_sizes = util.extract_array_sizes(type)
  250. return f"[{array_sizes[0]}][{array_sizes[1]}]{map_type(array_type, prefix, sub_type)}"
  251. elif util.is_func_ptr(type):
  252. res_type = funcptr_result_c(type, prefix)
  253. res_str = '' if res_type == '' else f' -> {res_type}'
  254. return f'proc "c" ({funcptr_args_c(type, prefix)}){res_str}'
  255. else:
  256. sys.exit(f"Error map_type(): unknown type '{type}'")
  257. def funcdecl_args_c(decl, prefix):
  258. s = ''
  259. func_name = decl['name']
  260. for param_decl in decl['params']:
  261. if s != '':
  262. s += ', '
  263. param_name = param_decl['name']
  264. param_type = check_override(f'{func_name}.{param_name}', default=param_decl['type'])
  265. if is_const_struct_ptr(param_type):
  266. s += f"#by_ptr {param_name}: {map_type(param_type, prefix, 'odin_arg')}"
  267. elif is_int_type(param_type):
  268. s += f"#any_int {param_name}: {map_type(param_type, prefix, 'c_arg')}"
  269. else:
  270. s += f"{param_name}: {map_type(param_type, prefix, 'c_arg')}"
  271. return s
  272. def funcptr_args_c(field_type, prefix):
  273. tokens = field_type[field_type.index('(*)')+4:-1].split(',')
  274. s = ''
  275. arg_index = 0
  276. for token in tokens:
  277. arg_type = token.strip()
  278. if s != '':
  279. s += ', '
  280. c_arg = map_type(arg_type, prefix, 'c_arg')
  281. if c_arg == '':
  282. return ''
  283. else:
  284. s += f'a{arg_index}: {c_arg}'
  285. arg_index += 1
  286. return s
  287. def funcptr_result_c(field_type, prefix):
  288. res_type = field_type[:field_type.index('(*)')].strip()
  289. return map_type(res_type, prefix, 'c_arg')
  290. def funcdecl_result_c(decl, prefix):
  291. func_name = decl['name']
  292. decl_type = decl['type']
  293. res_c_type = decl_type[:decl_type.index('(')].strip()
  294. return map_type(check_override(f'{func_name}.RESULT', default=res_c_type), prefix, 'c_arg')
  295. def get_system_libs(module, platform, backend):
  296. if module in system_libs:
  297. if platform in system_libs[module]:
  298. if backend in system_libs[module][platform]:
  299. libs = system_libs[module][platform][backend]
  300. if libs != '':
  301. return f", {libs}"
  302. return ''
  303. def gen_c_imports(inp, c_prefix, prefix):
  304. module_name = inp["module"]
  305. clib_prefix = f'sokol_{module_name}'
  306. clib_import = f'{clib_prefix}_clib'
  307. windows_d3d11_libs = get_system_libs(prefix, 'windows', 'd3d11')
  308. windows_gl_libs = get_system_libs(prefix, 'windows', 'gl')
  309. macos_metal_libs = get_system_libs(prefix, 'macos', 'metal')
  310. macos_gl_libs = get_system_libs(prefix, 'macos', 'gl')
  311. linux_gl_libs = get_system_libs(prefix, 'linux', 'gl')
  312. l( 'import "core:c"')
  313. l( '')
  314. l( 'SOKOL_DEBUG :: #config(SOKOL_DEBUG, ODIN_DEBUG)')
  315. l( '')
  316. l(f'DEBUG :: #config(SOKOL_{module_name.upper()}_DEBUG, SOKOL_DEBUG)')
  317. l( 'USE_GL :: #config(SOKOL_USE_GL, false)')
  318. l( 'USE_DLL :: #config(SOKOL_DLL, false)')
  319. l( '')
  320. l( 'when ODIN_OS == .Windows {')
  321. l( ' when USE_DLL {')
  322. l( ' when USE_GL {')
  323. l(f' when DEBUG {{ foreign import {clib_import} {{ "../sokol_dll_windows_x64_gl_debug.lib"{windows_gl_libs} }} }}')
  324. l(f' else {{ foreign import {clib_import} {{ "../sokol_dll_windows_x64_gl_release.lib"{windows_gl_libs} }} }}')
  325. l( ' } else {')
  326. l(f' when DEBUG {{ foreign import {clib_import} {{ "../sokol_dll_windows_x64_d3d11_debug.lib"{windows_d3d11_libs} }} }}')
  327. l(f' else {{ foreign import {clib_import} {{ "../sokol_dll_windows_x64_d3d11_release.lib"{windows_d3d11_libs} }} }}')
  328. l( ' }')
  329. l( ' } else {')
  330. l( ' when USE_GL {')
  331. l(f' when DEBUG {{ foreign import {clib_import} {{ "{clib_prefix}_windows_x64_gl_debug.lib"{windows_gl_libs} }} }}')
  332. l(f' else {{ foreign import {clib_import} {{ "{clib_prefix}_windows_x64_gl_release.lib"{windows_gl_libs} }} }}')
  333. l( ' } else {')
  334. l(f' when DEBUG {{ foreign import {clib_import} {{ "{clib_prefix}_windows_x64_d3d11_debug.lib"{windows_d3d11_libs} }} }}')
  335. l(f' else {{ foreign import {clib_import} {{ "{clib_prefix}_windows_x64_d3d11_release.lib"{windows_d3d11_libs} }} }}')
  336. l( ' }')
  337. l( ' }')
  338. l( '} else when ODIN_OS == .Darwin {')
  339. l( ' when USE_DLL {')
  340. l(f' when USE_GL && ODIN_ARCH == .arm64 && DEBUG {{ foreign import {clib_import} {{ "../dylib/sokol_dylib_macos_arm64_gl_debug.dylib" }} }}')
  341. l(f' else when USE_GL && ODIN_ARCH == .arm64 && !DEBUG {{ foreign import {clib_import} {{ "../dylib/sokol_dylib_macos_arm64_gl_release.dylib" }} }}')
  342. l(f' else when USE_GL && ODIN_ARCH == .amd64 && DEBUG {{ foreign import {clib_import} {{ "../dylib/sokol_dylib_macos_x64_gl_debug.dylib" }} }}')
  343. l(f' else when USE_GL && ODIN_ARCH == .amd64 && !DEBUG {{ foreign import {clib_import} {{ "../dylib/sokol_dylib_macos_x64_gl_release.dylib" }} }}')
  344. l(f' else when !USE_GL && ODIN_ARCH == .arm64 && DEBUG {{ foreign import {clib_import} {{ "../dylib/sokol_dylib_macos_arm64_metal_debug.dylib" }} }}')
  345. l(f' else when !USE_GL && ODIN_ARCH == .arm64 && !DEBUG {{ foreign import {clib_import} {{ "../dylib/sokol_dylib_macos_arm64_metal_release.dylib" }} }}')
  346. l(f' else when !USE_GL && ODIN_ARCH == .amd64 && DEBUG {{ foreign import {clib_import} {{ "../dylib/sokol_dylib_macos_x64_metal_debug.dylib" }} }}')
  347. l(f' else when !USE_GL && ODIN_ARCH == .amd64 && !DEBUG {{ foreign import {clib_import} {{ "../dylib/sokol_dylib_macos_x64_metal_release.dylib" }} }}')
  348. l( ' } else {')
  349. l( ' when USE_GL {')
  350. l( ' when ODIN_ARCH == .arm64 {')
  351. l(f' when DEBUG {{ foreign import {clib_import} {{ "{clib_prefix}_macos_arm64_gl_debug.a"{macos_gl_libs} }} }}')
  352. l(f' else {{ foreign import {clib_import} {{ "{clib_prefix}_macos_arm64_gl_release.a"{macos_gl_libs} }} }}')
  353. l( ' } else {')
  354. l(f' when DEBUG {{ foreign import {clib_import} {{ "{clib_prefix}_macos_x64_gl_debug.a"{macos_gl_libs} }} }}')
  355. l(f' else {{ foreign import {clib_import} {{ "{clib_prefix}_macos_x64_gl_release.a"{macos_gl_libs} }} }}')
  356. l( ' }')
  357. l( ' } else {')
  358. l( ' when ODIN_ARCH == .arm64 {')
  359. l(f' when DEBUG {{ foreign import {clib_import} {{ "{clib_prefix}_macos_arm64_metal_debug.a"{macos_metal_libs} }} }}')
  360. l(f' else {{ foreign import {clib_import} {{ "{clib_prefix}_macos_arm64_metal_release.a"{macos_metal_libs} }} }}')
  361. l( ' } else {')
  362. l(f' when DEBUG {{ foreign import {clib_import} {{ "{clib_prefix}_macos_x64_metal_debug.a"{macos_metal_libs} }} }}')
  363. l(f' else {{ foreign import {clib_import} {{ "{clib_prefix}_macos_x64_metal_release.a"{macos_metal_libs} }} }}')
  364. l( ' }')
  365. l( ' }')
  366. l( ' }')
  367. l( '} else when ODIN_OS == .Linux {')
  368. l(f' when DEBUG {{ foreign import {clib_import} {{ "{clib_prefix}_linux_x64_gl_debug.a"{linux_gl_libs} }} }}')
  369. l(f' else {{ foreign import {clib_import} {{ "{clib_prefix}_linux_x64_gl_release.a"{linux_gl_libs} }} }}')
  370. l( '} else {')
  371. l( ' #panic("This OS is currently not supported")')
  372. l( '}')
  373. l( '')
  374. # Need to special case sapp_sg to avoid Odin's context keyword
  375. if c_prefix == "sapp_sg":
  376. l(f'@(default_calling_convention="c")')
  377. else:
  378. l(f'@(default_calling_convention="c", link_prefix="{c_prefix}")')
  379. l(f"foreign {clib_import} {{")
  380. prefix = inp['prefix']
  381. for decl in inp['decls']:
  382. if decl['kind'] == 'func' and not decl['is_dep'] and not check_ignore(decl['name']):
  383. args = funcdecl_args_c(decl, prefix)
  384. res_type = funcdecl_result_c(decl, prefix)
  385. res_str = '' if res_type == '' else f'-> {res_type}'
  386. # Need to special case sapp_sg to avoid Odin's context keyword
  387. if c_prefix == "sapp_sg":
  388. l(f' @(link_name="{decl["name"]}")')
  389. l(f" {check_override(as_snake_case(decl['name'], c_prefix))} :: proc({args}) {res_str} ---")
  390. else:
  391. l(f" {as_snake_case(decl['name'], c_prefix)} :: proc({args}) {res_str} ---")
  392. l('}')
  393. l('')
  394. def gen_consts(decl, prefix):
  395. for item in decl['items']:
  396. item_name = check_override(item['name'])
  397. l(f"{as_snake_case(item_name, prefix)} :: {item['value']}")
  398. l('')
  399. def gen_struct(decl, prefix):
  400. c_struct_name = check_override(decl['name'])
  401. struct_name = as_struct_or_enum_type(c_struct_name, prefix)
  402. l(f'{struct_name} :: struct {{')
  403. for field in decl['fields']:
  404. field_name = check_override(field['name'])
  405. field_type = map_type(check_override(f'{c_struct_name}.{field_name}', default=field['type']), prefix, 'struct_field')
  406. # any field name starting with _ is considered private
  407. if field_name.startswith('_'):
  408. l(f' _ : {field_type},')
  409. else:
  410. l(f' {field_name} : {field_type},')
  411. l('}')
  412. l('')
  413. def gen_enum(decl, prefix):
  414. enum_name = check_override(decl['name'])
  415. l(f'{as_struct_or_enum_type(enum_name, prefix)} :: enum i32 {{')
  416. for item in decl['items']:
  417. item_name = as_enum_item_name(check_override(item['name']))
  418. if item_name != 'FORCE_U32' and item_name != 'NUM':
  419. if 'value' in item:
  420. l(f" {item_name} = {item['value']},")
  421. else:
  422. l(f" {item_name},")
  423. l('}')
  424. l('')
  425. def gen_imports(dep_prefixes):
  426. for dep_prefix in dep_prefixes:
  427. dep_module_name = module_names[dep_prefix]
  428. l(f'import {dep_prefix[:-1]} "../{dep_module_name}"')
  429. l('')
  430. def gen_helpers(inp):
  431. if inp['prefix'] == 'sdtx_':
  432. l('import "core:fmt"')
  433. l('import "core:strings"')
  434. l('printf :: proc(s: string, args: ..any) {')
  435. l(' fstr := fmt.tprintf(s, ..args)')
  436. l(' putr(strings.unsafe_string_to_cstring(fstr), len(fstr))')
  437. l('}')
  438. def gen_module(inp, c_prefix, dep_prefixes):
  439. pre_parse(inp)
  440. l('// machine generated, do not edit')
  441. l('')
  442. l(f"package sokol_{inp['module']}")
  443. gen_imports(dep_prefixes)
  444. gen_helpers(inp)
  445. prefix = inp['prefix']
  446. gen_c_imports(inp, c_prefix, prefix)
  447. for decl in inp['decls']:
  448. if not decl['is_dep']:
  449. kind = decl['kind']
  450. if kind == 'consts':
  451. gen_consts(decl, prefix)
  452. elif not check_ignore(decl['name']):
  453. if kind == 'struct':
  454. gen_struct(decl, prefix)
  455. elif kind == 'enum':
  456. gen_enum(decl, prefix)
  457. def pre_parse(inp):
  458. global struct_types
  459. global enum_types
  460. for decl in inp['decls']:
  461. kind = decl['kind']
  462. if kind == 'struct':
  463. struct_types.append(decl['name'])
  464. elif kind == 'enum':
  465. enum_name = decl['name']
  466. enum_types.append(enum_name)
  467. enum_items[enum_name] = []
  468. for item in decl['items']:
  469. enum_items[enum_name].append(as_enum_item_name(item['name']))
  470. def prepare():
  471. print('=== Generating Odin bindings:')
  472. if not os.path.isdir(module_root):
  473. os.makedirs(module_root)
  474. if not os.path.isdir(c_root):
  475. os.makedirs(c_root)
  476. def gen(c_header_path, c_prefix, dep_c_prefixes):
  477. if not c_prefix in module_names:
  478. print(f' >> warning: skipping generation for {c_prefix} prefix...')
  479. return
  480. reset_globals()
  481. make_odin_module_directory(c_prefix)
  482. print(f' {c_header_path} => {module_names[c_prefix]}')
  483. shutil.copyfile(c_header_path, f'{c_root}/{os.path.basename(c_header_path)}')
  484. csource_path = get_csource_path(c_prefix)
  485. module_name = module_names[c_prefix]
  486. ir = gen_ir.gen(c_header_path, csource_path, module_name, c_prefix, dep_c_prefixes)
  487. gen_module(ir, c_prefix, dep_c_prefixes)
  488. with open(f"{module_root}/{ir['module']}/{ir['module']}.odin", 'w', newline='\n') as f_outp:
  489. f_outp.write(out_lines)