Raylib
Raylib is a C library and in order to use it with Jai I need bindings. Luckily Jai has the most powerful metaprogramming capabilities of any programming language. To build a Jai program I can write a Jai metaprogram, which is just a Jai program which runs at compile time. This metaprogram can do anything we want, and in my case I want to automatically generate Raylib bindings when necessary.
Inspired by another closed beta member I wrote the following function which will generate the Raylib module:
generate_raylib_module : : (module_name: string , raylib_path: string ) {
using options: Generate_Bindings_Options;
// Add definitions for things that are missing in the { module.jai } header.
header = #string MODULE_HEADER
va_list : : * void ;
MODULE_HEADER
// Link against system libraries we need in the { module.jai } footer (order matters).
footer = #string MODULE_FOOTER
user32 : : #library,system,link_always,no_dll "user32" ;
gdi32 : : #library,system,link_always,no_dll "gdi32" ;
shell32 : : #library,system,link_always,no_dll "shell32" ;
winmm : : #library,system,link_always,no_dll "winmm" ;
raylib : : #library,no_dll "lib/raylib" ;
MODULE_FOOTER
// Add { Raylib } files to the generator.
raylib_lib_directory : = tprint("%/lib" , raylib_path);
raylib_include_directory : = tprint("%/include" , raylib_path);
array_add(* libpaths, raylib_lib_directory);
array_add(* libnames, "raylib" );
array_add(* include_paths, raylib_include_directory);
array_add(* source_files, ..string .["raylib.h" , "raymath.h" , "rlgl.h" ]);
// Generate module directory.
raylib_module_directory : = tprint("%/%" , LOCAL_MODULE_IMPORT_DIRECTORY, module_name);
raylib_module_lib_directory : = tprint("%/lib" , raylib_module_directory);
raylib_module_file : = tprint("%/module.jai" , raylib_module_directory);
// Recursively create directories for the Raylib module:
make_directory_if_it_does_not_exist(raylib_module_lib_directory, true );
// Generate bindings and save them as module.jai.
generate_bindings(options, raylib_module_file);
// Copy over the lib file:
copy_file(
tprint("%/raylib.lib" , raylib_lib_directory),
tprint("%/raylib.lib" , raylib_module_lib_directory)
);
}
This function may be called at any point during the build to generate a Raylib module (library). I decided to turn Raylib into a module because it allows me to easily separate it from my project and namespace it like so:
rl : : #import "raylib_win64" ;
// Hello, Window example:
main : : () {
rl.InitWindow(1920 , 1080 , "Hello, Sailor!" );
defer rl.CloseWindow();
while ! rl.WindowShouldClose() {
rl.BeginDrawing();
defer rl.EndDrawing();
rl.ClearBackground(.{ 40 , 80 , 160 , 255 });
}
}
This funnily enough makes using Raylib with Jai much better than using it with C or C++, because Raylib collides with many symbols defined in Windows headers and working around those collisions is annoying.
When I compile and run this program I get what is surely the best looking platform window:

This empty window is the canvas upon which I will project the horrors unimaginable. Stay tuned!
Next: Oil Rig : Card rendering - First pass of the card renderer.