Debugging Tools and Techniques for ArmorPaint Development: A Complete Guide
ArmorPaint provides a comprehensive debugging ecosystem including --debug command-line builds that generate symbol-rich binaries, an in-app Debug tab for real-time GPU diagnostics, console logging utilities, and support for external native debuggers like GDB, LLDB, and Visual Studio.
ArmorPaint is a 3D painting tool built by the armory3d/armorpaint repository with a hybrid JavaScript build system and C rendering engine. Understanding the debugging tools and techniques for ArmorPaint development is essential for contributors working across both the scripting layer and native graphics code.
Enabling Debug Builds from the Command Line
The build pipeline in base/tools/make.js orchestrates Debug configuration through the --debug flag. When invoked, the script sets goptions.debug to true at line 970, triggering compiler flags that generate binaries with full debug symbols.
Additionally, the runtime in paint/project.js parses command-line arguments at line 5, storing the debug state in flags.embed. This allows the application to detect if it was launched with --debug or --embed flags.
To build and run in Debug mode:
# Generate Debug binaries with symbols
node base/tools/make.js --debug
# Launch with debug runtime checks
./build/Debug/ArmorPaint --debug
The resulting executable retains symbol tables required for breakpoint debugging and enables additional runtime assertions throughout the codebase.
Runtime Debugging Features
Once running a Debug build, ArmorPaint exposes several diagnostic interfaces compiled conditionally via the is_debug macro.
The Debug UI Tab (tab_debug.c)
The dedicated Debug tab, implemented in paint/sources/ui/tab_debug.c, provides visual inspection of render targets and performance counters. This UI component only registers when is_debug is defined during compilation.
In paint/sources/ui/ui_base.c at line 351, conditional blocks push draw callbacks into the UI array when debugging is active:
#ifdef is_debug
// Add a draw callback that visualises the current render target
any_array_push(a0, _draw_callback_create(tab_debug_draw));
#endif
This allows developers to overlay texture previews and diagnostic geometry directly in the viewport without affecting Release builds.
In-App Console Logging (console.c)
The central logging API in paint/sources/console.c routes diagnostic messages to the internal console pane. The functions console_log, console_error, console_info, and console_toast provide runtime feedback without external tooling.
Example usage from native code:
console_log("Loaded texture %s", texture_name);
console_error("Failed to load mesh");
These calls appear in the Console tab (tab_console.c), creating a unified logging surface for both JavaScript build messages and C runtime events.
External Debugger Integration
Because Debug builds emit full symbol information, ArmorPaint supports attaching industry-standard native debuggers. The build system generates platform-specific project files that you can open directly in your IDE.
On Linux, navigate to the output directory and launch GDB:
cd build/Debug
gdb ./ArmorPaint
(gdb) run
# Set breakpoints, inspect variables, step through rendering code
For Windows development, running make.js with --debug emits .vcxproj files compatible with Visual Studio. The generated ArmorPaint.sln includes proper Debug configurations with working directory settings and symbol paths pre-configured. On macOS, the script produces .xcodeproj files for LLDB debugging within Xcode.
Performance Profiling and Hot Reloading
Beyond static debugging, ArmorPaint includes dynamic analysis tools for GPU optimization and script iteration.
Frame Performance Monitoring (main.c)
The Debug tab captures real-time metrics through the notification system defined in paint/sources/main.c at line 391. Using sys_notify_on_next_frame callbacks, the engine records frame times, draw-call counts, and GPU memory allocation statistics.
This instrumentation helps identify bottlenecks in the rendering pipeline by correlating CPU-side code execution with GPU frame metrics displayed in the Debug UI.
Script Console for Rapid Iteration (tab_console.c)
The console supports hot-reloading via text_to_text_node_run, allowing developers to execute JavaScript commands at runtime by typing into the Console tab. Errors return immediately to the console pane, creating a fast feedback loop for testing build logic or automation scripts without restarting the application.
Summary
- Debug builds are enabled via
--debuginmake.js, generating symbol-rich binaries inbuild/Debug/with the_DEBUGandis_debugdefinitions. - In-app diagnostics include the Debug tab (
tab_debug.c) for render target inspection and the Console (console.c) for logging viaconsole_log()and related functions. - Conditional compilation wraps debug-only code in
#ifdef is_debugblocks, ensuring zero overhead in Release binaries. - External tooling integrates with GDB, LLDB, Visual Studio, and Xcode through automatically generated project files.
- Performance profiling leverages frame callbacks in
main.cto display real-time GPU statistics.
Frequently Asked Questions
How do I compile ArmorPaint in Debug mode?
Run the build script with the --debug flag: node base/tools/make.js --debug. This sets goptions.debug in the build configuration, passes -g to the compiler, and defines is_debug for conditional compilation.
Where are debug symbols stored in ArmorPaint builds?
Debug symbols are embedded directly into the executables located in build/Debug/. The make.js script configures the compiler to generate these symbols automatically when the Debug flag is present.
Can I use Visual Studio to debug ArmorPaint?
Yes. The build system generates .vcxproj and .sln files when you run the Debug configuration. Open ArmorPaint.sln in Visual Studio, set breakpoints in the C source files, and press F5 to launch the debugger with full symbol support.
How do I view render targets and GPU performance in real-time?
Open the Debug tab in the UI, which is available only in Debug builds. This panel, driven by tab_debug.c and updated via callbacks in main.c, displays live render target previews, frame times, and memory statistics without requiring external profiling tools.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →