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

> Discover how Ladybird Browser builds using CMake and vcpkg. Learn about dependency management and cross-platform UI backend compilation.

- Repository: [Ladybird/ladybird](https://github.com/LadybirdBrowser/ladybird)
- Tags: internals
- Published: 2026-03-05

---

**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`](https://github.com/LadybirdBrowser/ladybird/blob/main/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`](https://github.com/LadybirdBrowser/ladybird/blob/main/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`](https://github.com/LadybirdBrowser/ladybird/blob/main/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`](https://github.com/LadybirdBrowser/ladybird/blob/main/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):

```bash

# 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:

```bash
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`](https://github.com/LadybirdBrowser/ladybird/blob/main/CMakeLists.txt), which defines C++23 standards and platform-specific logic.
- **vcpkg manifest mode** reads [`vcpkg.json`](https://github.com/LadybirdBrowser/ladybird/blob/main/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`](https://github.com/LadybirdBrowser/ladybird/blob/main/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`](https://github.com/LadybirdBrowser/ladybird/blob/main/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`](https://github.com/LadybirdBrowser/ladybird/blob/main/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.