I’m working on generating Mojo bindings for the OpenGL Core API by parsing the official Khronos XML registry. This process generates around 700 functions, but I’m running into severe compile-time performance issues.
My goal is to create something similar to the files generated by GLAD, where functions are loaded via a window manager’s function pointer loader. I’ve tried two main approaches:
- Single Struct: First, I tried putting all the function pointers into a single, large
GL
struct (see here). The main drawback of this approach is that the API isn’t ergonomic, as this struct would need to be passed everywhere. - Global Functions: Next, I tried using global variables with
_Global
to hold the function pointers for each of the ~700 OpenGL functions (see here). However, the compile time remained extremely slow.
I attempted a few optimizations, such as removing @always_inline
decorators and directly generating the initialization code with a Python script (instead of using a generic load_proc
function), but none of them helped.
Additionally, I’ve found that the generated LLVM IR contains all the imported symbols, even those that aren’t used in my code. I suspect this is not optimal, but I’m unsure how to encourage the compiler to optimize away these unused global variables, especially since they are all initialized at startup. (For example, you can see this by generating the LLVM IR for a simple script that only displays a single color: hello.mojo).
Does anyone have any ideas what might be causing this compiler slowdown? Would splitting the bindings across multiple files (e.g., by OpenGL version) be a sound strategy, or are there better patterns in Mojo for managing large C APIs like this?
I’d appreciate any advice or insights from the Modular team or the community.