How Ladybird Browser Is Built: CMake and vcpkg Build System Explained

Ladybird Browser uses a CMake-driven build system integrated with vcpkg manifest mode to orchestrate compilation, manage 40+ third-party dependencies, and support cross-platform UI backends including Qt, AppKit, and Android.

Ladybird is a modern, multi-process web browser written in C++23 with a Rust-based JavaScript engine. Understanding how Ladybird is built requires examining the interplay between CMake—which generates the build files and configures platform-specific toolchains—and vcpkg—which supplies deterministic, version-pinned libraries via a manifest. This guide explains the architecture defined in the LadybirdBrowser/ladybird repository and provides practical commands for compiling the browser from source.

CMake Architecture and Build Orchestration

The build process centers on CMakeLists.txt in the repository root, which acts as the single source of truth for project configuration, compiler flags, and target generation.

Project Entry and Requirements

In CMakeLists.txt, the project(ladybird ...) declaration sets the minimum CMake version to 3.30, defines C++23 as the standard, and establishes the global build context【^CMakeLists.txt†L1-L30】. This file immediately sources helper modules from Meta/CMake/ to handle platform detection and toolchain selection before any targets are defined.

Platform-Specific Toolchain Configuration

Early in the configuration phase, conditional blocks detect the host operating system and apply specific settings:

  • Apple platforms: Configures deployment targets and framework linking via if (APPLE ...) blocks.
  • Android: Sets the Android toolchain file and NDK paths when VCPKG_TARGET_ANDROID is defined.
  • Linker selection: Includes Meta/CMake/use_linker.cmake to choose between LLD, GNU ld, or other system linkers for both Ladybird and its dependencies.

These settings ensure that subsequent vcpkg ports compile with the same compiler and linker as the main project.

UI Backend Selection

CMake cache options control which UI toolkit is compiled. When -DENABLE_QT=ON is passed during configuration, the build system executes add_subdirectory(UI) and includes UI/cmake/EnableLagom.cmake, which enables automatic moc, rcc, and uic processing for Qt6【^CMakeLists.txt†L61-L66】. If Qt is disabled, the build defaults to AppKit on macOS, Android UI components on Android, or other platform-specific backends.

vcpkg Manifest Mode and Dependency Management

Ladybird uses vcpkg in manifest mode rather than global installation, ensuring reproducible builds across developer machines.

The vcpkg.json Manifest

The vcpkg.json file lists over 40 third-party libraries—including Skia, OpenSSL, FFmpeg, libjpeg-turbo, and QtBase—and pins exact versions via the overrides section【^vcpkg.json†L1-L75】. During CMake configuration, the vcpkg toolchain reads this manifest and installs all ports into Build/vcpkg_installed within the build tree, isolating dependencies from the system.

Automated Triplet Detection

Before the project is processed, CMake injects Meta/CMake/vcpkg/generate_vcpkg_toolchain_variables.cmake via the CMAKE_PROJECT_ladybird_INCLUDE_BEFORE hook. This script automatically determines the correct vcpkg triplet (e.g., x64-linux-dynamic, arm64-osx) by querying the host system architecture and OS name【^generate_vcpkg_toolchain_variables.cmake†L1-L90】.

The script exports environment variables (CC, CXX, LDFLAGS) and applies platform-specific workarounds—such as Patchelf flags on Linux—to ensure ports compile with the identical toolchain used for Ladybird itself. Custom overlay triplets reside in Meta/CMake/vcpkg/overlay-triplets to handle static versus dynamic linking requirements specific to the browser.

Building Ladybird: Practical Commands

While CMake can be invoked directly, the repository provides Meta/ladybird.py as a convenience wrapper that manages presets, builds, and execution.

Standard Build Workflow

Run these commands from the repository root after installing prerequisites (CMake ≥ 3.30, C++23 compiler, Rust, Qt6):


# Generate CMake configuration and install vcpkg dependencies

./Meta/ladybird.py build

# Compile and launch the browser

./Meta/ladybird.py run

The build subcommand effectively runs cmake --preset default -B Build/release, which triggers the vcpkg toolchain to download and build all manifest dependencies before generating Ninja build files.

Debug Configuration

To build a Debug configuration with full symbols:

BUILD_PRESET=Debug ./Meta/ladybird.py run

This switches the CMake preset to produce unoptimized binaries suitable for debugging with GDB or LLDB.

Customizing the Build Configuration

Developers can fine-tune the build without modifying source files by passing CMake definitions during the configuration phase.

  • Change build directory: cmake --preset default -B MyBuildDir creates isolated build trees for multiple configurations.
  • Reduce linking memory: Set -DLAGOM_LINK_POOL_SIZE=2 to limit parallel link jobs during LTO builds, preventing out-of-memory errors on resource-constrained systems.
  • Disable Qt UI: Pass -DENABLE_QT=OFF (or omit the flag) to use native platform UIs (AppKit on macOS, Android UI on Android).
  • Explicit Qt enable: cmake --preset default -DENABLE_QT=ON forces Qt6 compilation and links against the vcpkg-provided QtBase port.

Summary

  • CMake ≥ 3.30 is required to process the root CMakeLists.txt, which defines C++23 standards and platform-specific logic.
  • vcpkg manifest mode reads vcpkg.json to install 40+ dependencies into Build/vcpkg_installed, using overlay triplets from Meta/CMake/vcpkg/overlay-triplets.
  • Automated triplet detection occurs in generate_vcpkg_toolchain_variables.cmake, matching host architecture (x64, arm64, riscv64) and OS (Linux, macOS, Windows, FreeBSD).
  • UI backends are selected via ENABLE_QT and configured through UI/cmake/EnableLagom.cmake.
  • Wrapper script Meta/ladybird.py simplifies the workflow with build, run, and debug subcommands.

Frequently Asked Questions

What CMake version is required to build Ladybird?

Ladybird requires CMake 3.30 or newer, as specified in the project() declaration in CMakeLists.txt【^CMakeLists.txt†L1-L30】. This version ensures support for C++23 modules and modern preset features used by the vcpkg toolchain integration.

How does vcpkg integrate with Ladybird's CMake build?

The integration happens through CMAKE_PROJECT_ladybird_INCLUDE_BEFORE, which loads Meta/CMake/vcpkg/generate_vcpkg_toolchain_variables.cmake before project evaluation. This script sets the VCPKG_TARGET_TRIPLET and compiler environment variables, then the vcpkg toolchain reads vcpkg.json to install dependencies into the build tree. All third-party libraries are built with the same compiler flags and linker as Ladybird itself.

Can I build Ladybird without Qt?

Yes. The Qt UI is optional and controlled by the ENABLE_QT CMake option. If disabled or omitted, the build system automatically selects alternative backends: AppKit for macOS, Android UI components for Android builds, or other platform-specific implementations. Pass -DENABLE_QT=OFF during configuration to use these native alternatives.

How do I reduce memory usage during linking?

For large builds with Link Time Optimization (LTO), set the CMake cache variable LAGOM_LINK_POOL_SIZE to a low number (e.g., -DLAGOM_LINK_POOL_SIZE=2). This limits the number of concurrent link jobs, reducing peak RAM consumption during the final executable linking stage.

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:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →