This page covers Ladybird's CMake-based build system, the Meta/ladybird.py developer script, vcpkg dependency management, the AK core utility library, and the code generators that produce C++ source from WebIDL interface files and JSON specification files. For how generated WebIDL bindings integrate with the JavaScript engine at runtime, see WebIDL Bindings System. For the multi-process runtime architecture, see Multi-Process Architecture.
Ladybird requires CMake 3.30+ with Ninja as the build backend. The root CMakePresets.json is the entry point for all configuration.
The file includes a platform-specific preset file at configuration time:
Meta/CMake/presets/CMake${hostSystemName}Presets.json
This resolves to CMakeLinuxPresets.json, CMakeDarwinPresets.json, or CMakeWindowsPresets.json depending on the build host. Each file defines the Ninja generator, build directory paths, toolchain settings, and platform-specific CMake options.
| Preset | Build Directory | Use Case |
|---|---|---|
Release | Build/release | Default production build |
Debug | Build/debug | Debug symbols, assertions enabled |
All_Debug | Build/alldebug | All libraries in debug mode |
Sanitizer | Build/sanitizers | AddressSanitizer + UndefinedBehaviorSanitizer |
Distribution | Build/distribution | Stripped release for packaging |
Sources: CMakePresets.json1-30 Meta/ladybird.py261-273
Each library has its own CMakeLists.txt. LibWeb's begins with:
Libraries/LibWeb/CMakeLists.txt1-4
The libweb_generators CMake module defines the libweb_js_bindings() macro and the add_custom_command entries that invoke each code generator before compiling the library.
Meta/ladybird.py is the unified developer entry point. It wraps CMake, Ninja, and ctest into a single interface.
| Command | What It Does |
|---|---|
build [target] | Configure if needed, then compile with Ninja |
run [target] | Build then launch the application |
test [pattern] | Build then run ctest --preset <preset> |
debug [target] | Build then start gdb or lldb |
profile [target] | Build then run under valgrind --tool=callgrind |
install [target] | Build then cmake --install |
vcpkg | Bootstrap or update vcpkg dependencies |
clean | Remove the build directory |
rebuild | Clean then build |
addr2line | Resolve crash addresses to source locations |
The --preset flag (or BUILD_PRESET environment variable, defaulting to Release) selects which preset to use for all commands.
configure_main() checks whether build.ninja already exists in the build directory; if so, CMake configuration is skipped. Otherwise it calls validate_cmake_version() (must be ≥ 3.30), selects a compiler via pick_host_compiler(), and invokes cmake --preset. build_vcpkg() always runs first to ensure the dependency cache is current.
Developer build flow:
Sources: Meta/ladybird.py189-340 CMakePresets.json1-30
All third-party libraries are managed by vcpkg. vcpkg.json at the repository root declares every dependency with exact pinned versions in the overrides block.
Toolchain/BuildVcpkg.py installs vcpkg itself into Build/vcpkg. Meta/ladybird.py exports VCPKG_ROOT pointing at this directory and prepends it to PATH. On uncommon architectures (e.g. riscv64), VCPKG_FORCE_SYSTEM_BINARIES=1 is set to allow vcpkg to use system-provided CMake and Ninja.
| Package | Purpose | Platform Notes |
|---|---|---|
skia | 2D graphics backend | Metal feature on macOS; Vulkan on Linux/Windows |
angle | OpenGL ES / EGL (WebGL support) | Metal feature on macOS |
harfbuzz | Text shaping | CoreText feature on macOS |
icu | Unicode, locale, internationalization | All platforms |
ffmpeg | Media demuxing and decoding | All platforms |
curl | HTTP networking | All platforms |
openssl | TLS | All platforms |
sqlite3 | IndexedDB storage | All platforms |
fontconfig | System font enumeration | Linux, BSD, macOS |
vulkan + vulkan-headers | GPU rendering / compute | All platforms |
qtbase | Native UI shell | FreeBSD, Windows |
sdl3 | Window / input abstraction | All platforms |
libavif, libjpeg-turbo, libpng, libwebp, libjxl, tiff | Image decoders | All platforms |
simdjson | Fast JSON parsing | All platforms |
simdutf | Fast UTF transcoding | All platforms |
woff2 | Web font decompression | All platforms |
libxml2 | XML parsing | All platforms |
libtommath | Arbitrary-precision arithmetic | All platforms |
dbus | D-Bus IPC | Linux, FreeBSD |
cpptrace, libdwarf | Stack trace symbolization | Linux, Windows, macOS |
Sources: vcpkg.json1-373
AK ("Agnostic Kit") is Ladybird's foundational utility library with no external dependencies. It is used by every other library in the project.
| Header / Source | Provides |
|---|---|
String.h, ByteString.h | UTF-8 and byte-oriented string types |
FlyString.h | Interned (deduplicated) string, used for HTML/CSS identifiers |
StringBuilder.h | Efficient incremental string construction |
Vector.h, HashMap.h, HashTable.h | Generic containers |
JsonParser.h, JsonObject.h, JsonArray.h, JsonValue.h | JSON parsing, used extensively by CSS code generators |
SourceGenerator.h | @placeholder@-style template engine used by all code generators |
Error.h | Error and ErrorOr<T> for structured error propagation |
Format.h | dbgln(), outln(), warnln() formatted output |
GenericLexer.h | Character-level lexer base class |
SourceGenerator is the code-generation templating mechanism used by every generator in Meta/Lagom/Tools/. Its core API:
set("name", value) — registers a @name@ substitutionappend(template_text) — appends text with active substitutions appliedfork() — creates a scoped child generator inheriting parent bindingsSources: AK/CMakeLists.txt1-40 Meta/Lagom/Tools/CodeGenerators/LibWeb/BindingsGenerator/IDLGenerators.cpp1-30
A large fraction of LibWeb's C++ source is generated at build time. All generators live in Meta/Lagom/Tools/CodeGenerators/LibWeb/ and are compiled as standalone executables during a "Lagom Tools" sub-build. CMake custom commands in the libweb_generators module invoke them before LibWeb is compiled.
Sources: Meta/Lagom/Tools/CodeGenerators/LibWeb/GenerateCSSPropertyID.cpp29-81 Documentation/CSSGeneratedFiles.md1-40 Libraries/LibWeb/idl_files.cmake1-10
The IDL bindings generator reads .idl interface files and produces C++ wrapper classes that expose browser APIs to JavaScript. It is the most complex generator in the project.
Generator source: Meta/Lagom/Tools/CodeGenerators/LibWeb/BindingsGenerator/IDLGenerators.cpp
IDL file registry: Libraries/LibWeb/idl_files.cmake
Every IDL interface that needs a JavaScript binding is registered with the libweb_js_bindings() CMake macro:
Libraries/LibWeb/idl_files.cmake96-129
Optional flags per binding entry:
| Flag | Effect on Generated Code |
|---|---|
| (none) | Standard interface wrapper with prototype chain |
ITERABLE | Adds Symbol.iterator, entries, keys, values, forEach methods |
ASYNC_ITERABLE | Adds Symbol.asyncIterator and async iterator class |
GLOBAL | Marks as a global scope object (e.g. Window, DedicatedWorkerGlobalScope) |
NAMESPACE | Generates a namespace object rather than a constructor |
All output is produced via AK::SourceGenerator.
| Function | Role |
|---|---|
idl_type_name_to_cpp_type(Type, Interface) | Maps an IDL Type to a CppType struct with C++ name and container storage class |
generate_to_cpp(...) | Emits code converting a JS::Value parameter to the appropriate C++ type |
generate_to_string(...) | Emits string coercion respecting USVString, ByteString, FlyString, Utf16 distinctions |
generate_to_integral(...) | Emits numeric coercion with EnforceRange / Clamp extended attribute support |
generate_from_cpp(...) | Emits code converting a C++ return value back to a JS::Value |
generate_from_integral(...) | Emits integer-to-JS::Value conversion |
emit_includes_for_all_imports(...) | Recursively resolves transitive IDL includes and emits #include directives |
Meta/Lagom/Tools/CodeGenerators/LibWeb/BindingsGenerator/IDLGenerators.cpp256-460
Sources: Meta/Lagom/Tools/CodeGenerators/LibWeb/BindingsGenerator/IDLGenerators.cpp256-370
Multiple independent generator programs each consume one or more JSON specification files and emit C++ enums and lookup functions. All use AK::SourceGenerator.
Documentation/CSSGeneratedFiles.md1-80
Source: Meta/Lagom/Tools/CodeGenerators/LibWeb/GenerateCSSPropertyID.cpp
Inputs:
| Argument | File |
|---|---|
--properties-json-path | Libraries/LibWeb/CSS/Properties.json |
--enums-json-path | Libraries/LibWeb/CSS/Enums.json |
--groups-json-path | Logical property groups JSON |
Outputs: CSS/PropertyID.h, CSS/PropertyID.cpp
Each entry in Properties.json describes one CSS property: accepted value types, whether it is inherited, its initial value, animation support, its longhand list (for shorthands), and any logical alias. The generator's internal steps:
replace_logical_aliases() — resolves logical-alias-for references by cloning metadata from the corresponding physical property.populate_all_property_longhands() — flattens longhands arrays for shorthand properties.generate_header_file() — emits the CSS::PropertyID enum and function declarations.generate_implementation_file() — emits property_id_from_string(), string_from_property_id(), property_is_animatable(), and type-specific generate_bounds_checking_function() overloads.Meta/Lagom/Tools/CodeGenerators/LibWeb/GenerateCSSPropertyID.cpp29-200
| Generator Executable | Input JSON | Generated Output | Primary Symbol |
|---|---|---|---|
GenerateCSSKeywordID | CSS/Keywords.json | CSS/Keyword.h, CSS/Keyword.cpp | CSS::Keyword enum |
GenerateCSSPseudoClass | CSS/PseudoClasses.json | CSS/PseudoClass.h | CSS::PseudoClass enum |
GenerateCSSPseudoElement | CSS/PseudoElements.json | CSS/PseudoElement.h | CSS::PseudoElement enum |
GenerateCSSMediaFeatureID | CSS/MediaFeatures.json | CSS/MediaFeatureID.h, .cpp | CSS::MediaFeatureID enum |
GenerateCSSDescriptorID | CSS/Descriptors.json | CSS/DescriptorID.h, .cpp | CSS::DescriptorID enum |
GenerateCSSTransformFunctions | CSS/TransformFunctions.json | CSS/TransformFunctions.h, .cpp | CSS::TransformFunction enum |
The PseudoClass and PseudoElement enums are consumed directly by CSS/SelectorEngine.cpp and CSS/Parser/SelectorParsing.cpp. The PropertyID and Keyword enums are used throughout the CSS parsing and style computation stack.
Sources: Documentation/CSSGeneratedFiles.md10-100
Source: Meta/Lagom/Tools/CodeGenerators/LibWeb/GenerateWebGLRenderingContext.cpp
This generator reads the WebGL 1 and WebGL 2 IDL files and produces C++ implementations for WebGLRenderingContext and WebGL2RenderingContext, including the method dispatch and argument marshaling. See WebGL Rendering Context for a detailed discussion of the generated output and the runtime architecture it supports.
A Flatpak manifest for Linux desktop distribution is provided at Meta/CMake/flatpak/org.ladybird.Ladybird.json.
Meta/CMake/flatpak/org.ladybird.Ladybird.json1-30
| Setting | Value |
|---|---|
| App ID | org.ladybird.Ladybird |
| Runtime | org.kde.Platform 6.9 |
| SDK Extension | org.freedesktop.Sdk.Extension.llvm20 (Clang 20) |
| Display | Wayland socket with X11 fallback |
| Audio | PulseAudio socket |
| Network | Shared |
| GPU | DRI device access |
Dependencies not bundled in the KDE runtime (such as simdjson, simdutf, and others pinned beyond what the runtime ships) are built from source as Flatpak modules inside the manifest file.
Sources: Meta/CMake/flatpak/org.ladybird.Ladybird.json1-50
CI is managed via GitHub Actions. The reusable workflow is .github/workflows/lagom-template.yml, dispatched by .github/workflows/ci.yml across a matrix of configurations.
| OS | Arch | Preset | Toolchain | Notes |
|---|---|---|---|---|
| Linux | x86_64 | Sanitizer | GNU | |
| Linux | x86_64 | Sanitizer | Clang | With clang plugins enabled |
| Linux | x86_64 | All_Debug | Clang | |
| Linux | x86_64 | Fuzzers | Clang | Separate Lagom tools sub-build |
| Linux | arm64 | Sanitizer | Clang | VCPKG_FORCE_SYSTEM_BINARIES=1 |
| macOS | arm64 | Sanitizer | Clang | |
| Windows | x86_64 | Sanitizer | ClangCL | MSVC environment required |
The setup action at .github/actions/setup/action.yml installs system packages, bootstraps vcpkg via Toolchain/BuildVcpkg.py, and downloads wasm-tools before any CMake configuration runs.
Sources: .github/workflows/ci.yml1-80 .github/actions/setup/action.yml1-50
Refresh this wiki