Sample sokol+dearimgui application compiled with cosmopolitan toolchain.
Download cosmocc at: https://github.com/jart/cosmopolitan/releases.
At least v3.9.5 is required.
With cosmocc in your PATH, run ./build
.
Then run bin/cosmo-sokol
.
Checkout the github workflow for all the required dependencies.
Platform header directories are symlinked into the shims/linux
.
This is done instead of adding -I/usr/include
so that we can restrict what is exposed to the compiler.
Using dlopen, all required dynamic libraries can be dynamically loaded.
Instead of linking directly to those libraries (e.g: libgl, libx11...), we can link to a stub implementation.
When called, it will load the actual library and forward the call to the actual implementation.
e.g: the stub XPending
dynamically loads libX11.so
and then forward the call to the actual XPending
retrieved through dlsym.
gen-x11 is a Python script that generates x11.c.
All undefined references have to be manually added to the list of generated functions.
Take note that a nullary function such as XInitThreads have to be declared as: Status XInitThreads()
.
For OpenGL, the exhaustive list of functions can be found at: https://github.com/KhronosGroup/OpenGL-Registry/blob/main/xml/gl.xml. gen-gl simply requires a minimum version number to generate gl.c.
cosmopolitan's own headers lack a lot of Windows function prototype so we have to ignore implicit-function-declaration
.
However, it has a simple way to import required win32 functions: https://github.com/jart/cosmopolitan/blob/master/libc/nt/master.sh.
Simply list the name, dll and arity in that file.
This requires making upstream changes to cosmopolitan.
As of this writing, the required changes are merged and sokol_app
+ sokol_gfx
can run on Windows.
windows.h
(and its transitive headers) includes a lot of struct definitions and macros.
Unfortunately, including the official windows.h
directly or its MinGW counterpart often results in a lot of duplicated and conflicting definitions when compiling using cosmocc.
Therefore, all relevant definitions are instead replicated inside sokol_windows.c
.
sokol makes use of platform ifdef to selectively compile platform-dependent code. In cosmopolitan, we want to compile all platform-dependent code paths and select the right implementation at runtime instead.
In order to do that with the same library, we can use the following preprocessor trick:
-
For each platform, prefix every sokol public function with its platform name. e.g:
sapp_show_keyboard
becomeslinux_sapp_show_keyboard
andwindows_sapp_show_keyboard
.This can simply be done by
#define sapp_show_keyboard linux_sapp_show_keyboard
right before includingsokol_app.h
. -
Create a multi-platform shim (
sokol_cosmo.c
) that selects the right implementation at runtime.
gen-sokol takes in a list of sokol public functions and generate the required #define
-s and the cosmo shim.