Native Libraries
Weir packages can include native C source files that are automatically compiled and linked. This is how Weir integrates with system libraries like OpenGL, GLFW, and audio frameworks.
Declaring Native Code
Section titled “Declaring Native Code”In weir.pkg, use the native section to declare C sources and link libraries:
(package (name "weir-gl") (version "0.1.0") (sources "lib.weir") (native (sources "gl_helper.c") (link "glfw" "GL" "m")))| Field | Description |
|---|---|
sources | C source files to compile (relative to weir.pkg) |
link | System libraries to link (-l flags) |
How It Works
Section titled “How It Works”The build process depends on the execution mode:
JIT Mode (weir run)
Section titled “JIT Mode (weir run)”- All native C sources from all packages are collected
- Compiled into a shared library via
cc -shared -fPIC -o tmp/libweir_native.so - The shared library is loaded via
dlopenbefore JIT execution - Symbols are resolved via
dlsymwhen extern functions are called
cd demos/tetris && weir run# Internally: cc -shared -fPIC -o tmp/libweir_native.so gl_helper.c -lglfw -lGL -lm# Then: dlopen("tmp/libweir_native.so")# Then: JIT compile and runAOT Mode (weir build)
Section titled “AOT Mode (weir build)”- Native C sources are passed as extra arguments to the C compiler
- Link libraries are passed as
-lflags - Everything is linked into a single standalone binary
cd demos/tetris && weir build -o ../../tmp/tetris# Internally: cc -o tetris program.o gl_helper.c -lglfw -lGL -lmDev Mode (weir dev)
Section titled “Dev Mode (weir dev)”Same as JIT mode — the native library is compiled and loaded once at startup.
Dependency Chains
Section titled “Dependency Chains”When an application depends on a library that has native code, the native sources and link flags are collected from all packages in the dependency tree:
demos/tetris/weir.pkg └── deps: weir-gl └── native: gl_helper.c, link: glfw GL mAll native sources and link flags bubble up to the top-level build.
Manual Approach
Section titled “Manual Approach”Before the package system, native code required manual commands:
# Manual AOT:weir build demos/tetris.weir -o tmp/tetris --cc-arg gl_helper.c -l glfw -l GL -l m
# Manual JIT:cc -shared -fPIC -o tmp/libgl.so gl_helper.c -lglfw -lGL -lmweir run demos/tetris.weir --load tmp/libgl.soThe package system makes this declarative — just weir build or weir run.
The --load Flag
Section titled “The --load Flag”For JIT mode without a package system, you can manually pre-load shared libraries:
weir run game.weir --load /usr/lib/libglfw.so --load ./mylib.soThe --load flag calls dlopen with RTLD_GLOBAL, making all symbols available for dlsym resolution.
The --cc-arg and -l Flags
Section titled “The --cc-arg and -l Flags”For AOT builds without a package system:
weir build game.weir --cc-arg helper.c --cc-arg audio.c -l glfw -l GL -l openal--cc-arg passes raw arguments to the C compiler. -l passes library link flags.
Example: weir-gl
Section titled “Example: weir-gl”The weir-gl library package provides OpenGL/GLFW bindings:
weir-gl/ weir.pkg # Package manifest lib.weir # Weir extern "C" declarations gl_helper.c # C wrapper functionsgl_helper.c contains C functions that wrap verbose OpenGL/GLFW APIs into simpler interfaces:
// gl_helper.c (simplified)#include <GLFW/glfw3.h>
static GLFWwindow* window;
int64_t gl_init(int64_t w, int64_t h, const char* title) { glfwInit(); window = glfwCreateWindow(w, h, title, NULL, NULL); glfwMakeContextCurrent(window); return window != NULL;}lib.weir declares these functions for Weir:
(extern "C" (defn gl_init ((w : i64) (h : i64) (title : String)) : i64) (defn gl_should_close () : i64) (defn gl_begin_frame () : Unit) (defn gl_draw_rect ((x : f64) (y : f64) (w : f64) (h : f64) (r : f64) (g : f64) (b : f64) (a : f64)) : Unit) (defn gl_end_frame () : Unit) (defn gl_cleanup () : Unit))Applications then import from the package:
(import weir-gl (gl_init gl_draw_rect gl_cleanup ...))