This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
LibAgar is a cross-platform GUI toolkit and application framework written in C. It provides a modular architecture with multiple libraries:
- CORE: Platform abstraction, I/O, object system (non-graphical)
- GUI: Base framework and standard widgets
- MATH: Matrices, vectors, advanced rendering methods
- NET: Network interface, HTTP application server
- VG: Vector graphics library
- AU: Audio interface library
- SG: General-purpose 3D engine
- SK: Sketches with constraints
- MAP: Tile engine
LibAgar supports three build systems. See MESON.md for detailed Meson documentation.
The traditional build system using Autoconf-style configuration:
./configure --help # View all options
./configure --enable-debug # Debug build with type-safety checks
./configure --prefix=$HOME # Custom install location
make depend all # Build with dependencies
make install # Install (may need sudo)Common configure options:
--enable-debug: Enables AG_DEBUG, type-safety, and GUI debugger--enable-warnings: Enable suggested compiler warnings--disable-threads: Disable multi-thread support--disable-{au,map,web}: Disable specific libraries--with-freetype[=PREFIX]: FreeType support (required for GUI)--with-sdl2[=PREFIX]: SDL 2.0 driver support--with-gl[=PREFIX]: OpenGL rendering support
Cross-platform build system with IDE integration:
cmake -S . -B build -DCMAKE_BUILD_TYPE=Release
cmake --build build
cmake --install buildFast, user-friendly build system with excellent dependency management:
# Quick start
meson setup buildDir # Configure with auto-detected dependencies
meson compile -C buildDir # Build (parallel by default)
meson install -C buildDir # Install (may need sudo)
# Common options
meson setup buildDir \
--buildtype=debug \ # debug, release, debugoptimized
-Dgui=true \ # Enable Agar-GUI
-Dmath=true \ # Enable Agar-Math
-Dthreads=enabled # Enable thread support
# View all options
meson configure buildDir
# See MESON.md for complete documentationKey advantages of Meson:
- Fast configuration and compilation (parallel by default)
- Out-of-tree builds (never modifies source directory)
- Better dependency detection and error messages
- Native support for modern build tools (ninja, IDE integration)
- Comprehensive test framework integration
- See MESON.md for ~70 configuration options
Direct makefile invocation (requires prior configuration):
make depend all
make install| Feature | BSDBuild | CMake | Meson |
|---|---|---|---|
| Configuration Style | Autoconf-like (shell scripts) | Imperative (CMake language) | Declarative (Python-like) |
| Build Speed | Fast ("make -j" supported; out-of-tree builds are fastest) | Fast | Fastest (parallel by default) |
| Config Headers | Shell script generation (~110 files) | BB_Save_Define macros | Template-based (4 templates) |
| Out-of-tree Builds | Optional | Yes | Always (required) |
| Dependency Detection | Manual scripting | FindPackage modules | pkg-config + automatic fallbacks |
| IDE Integration | Fair (project file generation via premake) | Excellent (generates project files) | Good (compile_commands.json) |
| Cross-compilation | Manual configuration | Toolchain files | Built-in support |
| Cross-compilation to 8-Bit Systems | Yes | No | No |
| BSD-style "make depend" target | Yes | No | No |
| Incremental Builds | Make-based | Make or Ninja | Ninja (default) |
| Learning Curve | Moderate (documented in manual pages) | Moderate | Low (simple syntax) |
| Maturity in LibAgar | Primary/Legacy (well-tested) | Stable | New (modern approach) |
core/: Non-graphical core and utility library (object system, platform, I/O)gui/: The Agar GUI (graphics, window system, GUI framework and standard widget library)math/: The Agar Math library (vectors, matrices, geometry and advanced rendering methods)net/: Network library (network routines, HTTP application server)vg/: Vector graphics libraryau/: Audio interface and extensions librarysg/: General-purpose 3D engine with visualization widgetsk/: Dimensioned 2D sketches with constraint-solving and visualization widgetmap/: 2D tile engine
configure,configure.in: BSDBuild configuration script and sourceCMakeLists.txt,CMakeChecks.cmake: CMake build systemmeson.build,meson_options.txt: Meson build system (root level)*/meson.build: Per-library Meson build definitionsmeson/: Meson build system support filesmeson/templates/: Config header templates (4 files)config_bool_yes.h.in: Enabled boolean featuresconfig_bool_no.h.in: Disabled boolean featuresconfig_string.h.in: String configuration valuesconfig_symbol.h.in: Symbolic constants (e.g., AG_MODEL)
meson/create_config_symlinks.py: Helper script (legacy, not used in current build)
include/: Generated header files (BSDBuild/CMake builds)buildDir/orbuild/: Meson build output directory (out-of-tree)build/agar/: Symlinks to source directories + generated config headersbuild/agar/config/: ~110 individual config headersbuild/*/libag_*.so.*: Built shared librariesbuild/*/libag_*.a: Built static libraries
tests/: Test suite and examples (includesagartestprogram)mk/: Build system infrastructure (BSDBuild)tools/: Build tools and utilitiesada/: Ada language bindingsp5-Agar/: Perl language bindings
MESON.md: Meson build system documentationCLAUDE.md: This file (AI assistant guidance)README.md,INSTALL.md,CHANGELOG.md: General documentation
LibAgar uses an object-oriented design in C with a hierarchical class system:
- All GUI elements inherit from
AG_Object - Classes are registered at runtime via
AG_RegisterClass() - Objects support serialization, events, timers, and variables
- See
core/object.handcore/object.c
- Event-driven architecture with named events
- Events can have typed arguments (accessed via
AG_EVENT_ARGS()) - Events support both named and positional arguments (when
AG_NAMED_ARGSis defined) - See
core/event.handcore/event.c
All widgets inherit from AG_Widget (which inherits from AG_Object):
- Widgets have a rendering context (OpenGL or framebuffer)
- Each widget has size requisition, allocation, and drawing methods
- Widgets are contained in windows (
AG_Window) - Style attributes are managed via
AG_StyleSheet
Key widget base files:
gui/widget.c,gui/widget.h: Base widget implementationgui/window.c,gui/window.h: Window managementgui/primitive.c,gui/primitive.h: Drawing primitives
LibAgar abstracts graphics backends through drivers:
- Multi-window drivers:
glx(X11+OpenGL),wgl(Windows+OpenGL),cocoa(macOS+OpenGL),sdl2mw(SDL2 multi-window) - Single-window drivers:
sdlfb,sdlgl,sdl2fb,sdl2gl - Drivers are in
gui/drv_*.cfiles
LibAgar supports three memory models (configure via --with-memory-model):
- SMALL: For embedded/retro systems (BBC, C64, NES)
- MEDIUM: Default for 32-bit systems
- LARGE: For 64-bit systems
When --enable-debug is used:
AG_DEBUGis defined- Type-safety checks are performed at runtime (
AG_TYPE_SAFETY) - Object validity checks on API calls
- GUI debugger is available (
AG_GuiDebugger) - Use
AG_Verbose(),AG_Debug()for debug output
LibAgar extensively uses inline functions for performance. Controlled by configure flags:
--with-inline-byteswap: Inline endianness swaps--with-inline-error: Inline malloc() wrappers--with-inline-event: Inline event argument accessors--with-inline-io: Inline serialization frontends--with-inline-object: Inline AG_Object operations--with-inline-surface: Inline pixel access routines--with-inline-widget: Inline AG_Widget functions
Inline implementations are in inline_*.h files within each library directory.
- Public API functions:
AG_FunctionName()(PascalCase with AG_ prefix) - Private/internal functions: lowercase with AG_ prefix or no prefix
- Object methods:
AG_ObjectName+ method name (e.g.,AG_ButtonText()) - Macros: ALL_CAPS with
AG_prefix - Types:
AG_TypeName(PascalCase)
LibAgar uses a sophisticated header system with several key components:
Config Headers:
- Generated during build (~110 individual header files)
- Location varies by build system:
- BSDBuild/CMake:
include/agar/config/ - Meson:
buildDir/agar/config/(symlinked)
- BSDBuild/CMake:
- Four types of config headers (Meson):
- Boolean enabled:
#define MACRO "yes" - Boolean disabled:
#undef MACRO - String values:
#define MACRO "value" - Symbolic constants:
#define MACRO value(no quotes)
- Boolean enabled:
Public API Headers:
*_pub.h: Public subset included by main headerinline_*.h: Inline function implementationsbegin.h,close.h: Compiler attribute management (must be paired)
Header Include Path (Meson builds):
-I../includes project root-I../core,-I../gui, etc. for each library-Ibuild/agarfor symlinked structure + config headers- Order matters: config headers must be found before source headers
Forward Declarations:
- Used to avoid circular dependencies (e.g.,
struct ag_fmt_string;) - Allows pointers to incomplete types
- Common pattern: use
void *with type comments when full type causes circular dependency
When built with --enable-threads:
- Most public API calls are reentrant
- Objects have built-in locking via
AG_ObjectLock()/AG_ObjectUnlock() - Event handlers run in a locked context
- See
core/threads.hfor thread primitives
LibAgar provides two API styles controlled by preprocessor macros:
External API (default for applications):
- Use explicit
AG_prefixed functions:AG_Malloc(),AG_Strlcpy(),AG_Strdup() - Safe for applications linking against LibAgar
Internal API (for LibAgar source code):
- Define
_AGAR_INTERNALor_USE_AGAR_STDto enable shorthand macros - Allows using
Malloc(),Strlcpy(),Strdup()withoutAG_prefix - Defined in wrapper headers (e.g.,
core/ag_string.h) - Warning: Only use these macros within LibAgar source files
Example from core/ag_string.h:
#if defined(_AGAR_INTERNAL) || defined(_USE_AGAR_STD)
# define Strlcat(dst,src,dsize) AG_Strlcat((dst),(src),(dsize))
# define Strlcpy(dst,src,dsize) AG_Strlcpy((dst),(src),(dsize))
# define Strdup(s) AG_Strdup(s)
# define TryStrdup(s) AG_TryStrdup(s)
#endifGlobal Defines (set by build system):
_DARWIN_C_SOURCE: macOS compatibility_NETBSD_SOURCE: NetBSD compatibility- Set globally in build configuration, not per-file
Conditional Compilation:
- Use
HAVE_*defines to check for features (e.g.,HAVE_OPENGL,HAVE_FREETYPE) - Check memory model with
AG_MODEL(AG_SMALL, AG_MEDIUM, AG_LARGE) - Platform detection via standard defines:
__WIN32__,__APPLE__,__linux__
Always use LibAgar's allocators:
AG_Malloc(),AG_Realloc(),AG_Free()instead of standard malloc/realloc/freeAG_TryMalloc(),AG_TryRealloc()for non-fatal allocation attempts- Internal code can use
Malloc(),Realloc(),Free()when_AGAR_INTERNALis defined - Reason: Allows LibAgar to track allocations and provide debugging support
Use LibAgar's safe string functions:
AG_Strlcpy(),AG_Strlcat(): Safe string copying (always NUL-terminates)AG_Strdup(),AG_TryStrdup(): Safe string duplicationAG_Strcasecmp(),AG_Strncasecmp(): Case-insensitive comparison- Available as shorthand (
Strlcpy, etc.) when_AGAR_INTERNALis defined
The tests/ directory contains the test suite:
cd tests
./configure
make depend all
./agartest # Run the interactive test suiteIndividual test programs can be found in subdirectories like tests/agarhello/.
- Create
gui/my_widget.candgui/my_widget.h - Define the widget structure inheriting from
AG_Widget - Implement class methods:
Init,Draw,SizeRequest,SizeAllocate - Register the class:
AG_RegisterClass(&myWidgetClass) - Add to
gui/MakefileinSRCSvariable - Add man page:
gui/AG_MyWidget.3
- Edit
configure.in - Add
register()call for the option - Add
check()or conditional logic - Add corresponding
hdefine()ormdefine()calls - Regenerate configure:
mkconfigure(requires BSDBuild)
Platform detection is done in configure.in:
${host}: Target platform (e.g.,x86_64-linux-gnu)- Conditional compilation via
#ifdef HAVE_FEATUREin C code - Platform-specific sources added via
mappend()in configure.in
AG_Surface represents a software or hardware-accelerated pixel buffer:
- Supports various pixel formats (indexed, RGB, RGBA)
- Can load from BMP, PNG, JPEG (if libraries available)
- Blitting operations in
gui/surface.c - Hardware acceleration when OpenGL is available
- The
include/directory is generated during build - do not edit files there directly - Configuration results are in
Makefile.configandinclude/agar/config/ - LibAgar defines global symbols like
_DARWIN_C_SOURCEand_NETBSD_SOURCEfor platform compatibility - When using inline functions, there's always a non-inline fallback (lowercase function name)
- The style system (
gui/stylesheet.c) allows runtime theming via CSS-like syntax - Always check
HAVE_*defines before using platform-specific features - Use
AG_Malloc(),AG_Realloc(),AG_Free()instead of direct malloc/free calls