Skip to content
C++
Package Manager
Updated 2026-07-14T00:00:00.000Z

xrepo — Cross-Platform C++ Package Manager

xrepo package manager — searching and installing packages, CMake/Meson integration, private repositories, and cross-compilation.

TL;DR

xrepo ships with xmake but works as a standalone package manager for any build system. It indexes 5000+ C++ packages, runs identically on Linux, macOS, and Windows, and handles cross-compilation to Android, iOS, and bare-metal targets without requiring platform-specific package managers. You do not need to use xmake as your build system to benefit from xrepo — CMake and Meson projects can consume xrepo packages via generated flags or environment injection.

bash
# Install a package, then ask for its CMake flags
xrepo install fmt
xrepo fetch --cmake fmt
# -DCMAKE_PREFIX_PATH=... -Dfmt_DIR=...

# Or just drop into a shell where everything is on PATH / in CMAKE_PREFIX_PATH
xrepo env cmake -B build -S .

Key characteristics:

  • Single binary — no Python runtime, no Ruby, no .NET; xmake/xrepo is self-contained
  • Per-project installs by default — packages land in ~/.xmake/packages, keyed by version and configuration
  • Binary caching — previously built packages are reused across projects automatically
  • Build-system neutral — xrepo fetch outputs flags for CMake, pkg-config, and raw compiler invocations

Installation

xrepo is bundled with xmake. Installing xmake gives you both commands.

Linux and macOS

bash
curl -fsSL https://xmake.io/shget.text | bash
# Or with wget:
wget https://xmake.io/shget.text -O - | bash

The installer drops the binary into ~/.local/bin. Restart your shell or source ~/.bashrc (or ~/.zshrc) to pick it up.

Windows — winget

powershell
winget install xmake-io.xmake

Windows — Scoop

powershell
scoop install xmake

Both options add xmake and xrepo to PATH automatically.

Verify the installation

bash
xrepo --version
# xrepo v2.9.x, A cross-platform C/C++ package manager

xrepo and xmake share the same version number — they ship as one release.


Searching and Installing Packages

Finding a package takes one command. xrepo searches the official registry (xmake-repo) by name and prints available versions.

bash
xrepo search fmt
# Results from the official xmake-repo registry:
# fmt       - A modern formatting library
# fmtlog    - fmtlog is a performant fmtlib-style logging library...

Install the latest compatible version:

bash
xrepo install fmt

Pin to a specific version using a quoted version constraint:

bash
xrepo install "fmt 10.x"
xrepo install "fmt 10.2.1"
xrepo install "openssl >=3.0"

Build in release mode (the default for most packages, but explicit is safer in CI):

bash
xrepo install --mode=release fmt
xrepo install --mode=debug fmt

You can have both modes installed simultaneously — xrepo keys the cache by build configuration.

List installed packages

bash
xrepo list
# fmt 10.2.1  release  linux x86_64
# boost 1.83.0  release  linux x86_64

Remove a package

bash
xrepo remove fmt
xrepo remove "fmt 10.2.1"   # remove a specific version

Update all installed packages to their latest allowed versions

bash
xrepo update

Using with CMake

xrepo does not require you to rewrite your CMakeLists.txt. The fetch subcommand prints the CMake variables needed to locate installed packages, and xrepo env injects those paths into the environment before invoking any command you pass.

Option 1 — fetch flags and pass them directly

bash
# Install first
xrepo install fmt nlohmann_json openssl

# Ask for CMake-compatible flags
xrepo fetch --cmake fmt
# Outputs something like:
# -DCMAKE_PREFIX_PATH=/home/user/.xmake/packages/f/fmt/10.2.1/... -Dfmt_DIR=...

Pass those flags to CMake:

bash
cmake -B build $(xrepo fetch --cmake fmt) $(xrepo fetch --cmake nlohmann_json)
cmake --build build

Option 2 — xrepo env (recommended for interactive use)

bash
xrepo env cmake -B build -S .
xrepo env cmake --build build

xrepo env sets CMAKE_PREFIX_PATH, PKG_CONFIG_PATH, LD_LIBRARY_PATH, and compiler hints so that find_package() in CMakeLists.txt resolves installed packages without extra flags.

Option 3 — export and source (useful for scripts or IDEs)

bash
xrepo env --export > env.sh
source env.sh
cmake -B build -S .

The exported file is a plain shell script that sets the environment variables xrepo would inject — portable to any script or IDE that can source a shell file.

Full CMake workflow

bash
# 1. Install dependencies
xrepo install fmt nlohmann_json

# 2. Configure
xrepo env cmake -B build -S . -DCMAKE_BUILD_TYPE=Release

# 3. Build
cmake --build build --parallel $(nproc)

Your CMakeLists.txt stays standard:

cmake
cmake_minimum_required(VERSION 3.25)
project(myapp)

find_package(fmt REQUIRED)
find_package(nlohmann_json REQUIRED)

add_executable(myapp main.cpp)
target_link_libraries(myapp PRIVATE fmt::fmt nlohmann_json::nlohmann_json)

No toolchain file, no generator expressions specific to xrepo — the project remains portable to vcpkg or Conan without modification.


Using with Meson

Meson's pkg-config integration is the cleanest path for xrepo packages. Most packages installed by xrepo generate .pc files; export the path and Meson's dependency resolution picks them up transparently.

bash
# Install a package
xrepo install fmt

# Get the pkg-config output path
xrepo fetch --pkg-config fmt
# /home/user/.xmake/packages/f/fmt/10.2.1/.../lib/pkgconfig

Pass the path to Meson:

bash
PKG_CONFIG_PATH=$(xrepo fetch --pkg-config fmt) meson setup build
ninja -C build

For multiple packages, accumulate the paths:

bash
export PKG_CONFIG_PATH=$(xrepo fetch --pkg-config fmt):$(xrepo fetch --pkg-config zlib)
meson setup build

The xrepo env shortcut works here too:

bash
xrepo env meson setup build
xrepo env ninja -C build

xrepo env sets PKG_CONFIG_PATH alongside CMAKE_PREFIX_PATH, so the same invocation style works regardless of whether your project uses CMake or Meson.


Using with xmake

When xmake is your build system, xrepo integration is native — no fetch step, no env injection. Declare packages in xmake.lua and they are downloaded, built, and linked automatically.

lua
-- xmake.lua
add_rules("mode.release", "mode.debug")

add_requires("fmt 10.x", {configs = {header_only = false}})
add_requires("nlohmann_json", {alias = "json"})
add_requires("openssl >=3.0")

target("myapp")
    set_kind("binary")
    add_files("src/*.cpp")
    add_packages("fmt", "json", "openssl")

Build with dependency resolution in one step:

bash
xmake          # downloads missing packages, then builds
xmake -m release

The difference from standalone xrepo install is that xmake reads package requirements from xmake.lua automatically — you never call xrepo install manually in an xmake project. The xrepo cache is shared, though, so packages installed for one project are reused by all others.

When you run xmake for the first time in a project, it:

  1. Reads add_requires() declarations
  2. Checks ~/.xmake/packages for cached builds matching the version and configuration
  3. Downloads and builds anything missing
  4. Links the packages into the declared targets

There is no lock file separate from xmake.lua — the version constraint in add_requires() is the contract.


Package Versions and Options

xrepo's version syntax handles both exact pins and range constraints. You can also enable or disable package features (called "configs") at install time.

Version pinning and ranges

bash
xrepo install "boost 1.83.0"          # exact version
xrepo install "boost >=1.80.0"        # minimum version
xrepo install "boost >=1.80,<1.85"    # version range
xrepo install "openssl >=3.0"

Selecting package components (features)

Many packages expose optional components as build-time configs. Pass them with --configs:

bash
# Build fmt as a shared library instead of static
xrepo install --configs="shared=true" fmt

# Boost with selected components only
xrepo install --configs="filesystem=true,system=true,thread=false" boost

In xmake.lua, the same option appears inside the add_requires() call:

lua
add_requires("boost", {configs = {filesystem = true, system = true, thread = false}})
add_requires("fmt", {configs = {shared = true}})

Debug vs release installs

bash
xrepo install --mode=release fmt   # optimised, stripped
xrepo install --mode=debug fmt     # symbols included, assertions enabled

Both can coexist in the cache. xrepo fetch accepts the same --mode flag to return paths for the correct variant.

Checking what configs a package supports

bash
xrepo info fmt        # lists available config options, URL, license, deps
xrepo info boost      # shows components that can be toggled

Cross-Compilation

xrepo cross-compilation is first-class, not an afterthought. The --plat and --arch flags tell xrepo to build the package for a different target; the host toolchain is picked up automatically or specified via --sdk.

Generic sysroot-based cross-compilation

bash
xrepo install \
  --plat=cross \
  --arch=aarch64 \
  --sdk=/path/to/aarch64-sysroot \
  fmt zlib

The --sdk path should be the root of your cross toolchain (the directory containing bin/aarch64-linux-gnu-gcc, etc.).

Android NDK

bash
xrepo install \
  --plat=android \
  --arch=arm64-v8a \
  --ndk=/path/to/android-ndk-r26 \
  fmt openssl

Supported Android architectures: arm64-v8a, armeabi-v7a, x86, x86_64.

bash
# Fetch CMake flags for the cross-built package
xrepo fetch --cmake --plat=android --arch=arm64-v8a fmt

iOS

bash
xrepo install --plat=iphoneos --arch=arm64 fmt
xrepo install --plat=iphonesimulator --arch=x86_64 fmt

Requires Xcode and the iOS SDK to be installed on macOS.

WebAssembly (Emscripten)

bash
xrepo install --plat=wasm fmt

xrepo detects the active Emscripten environment (emcc on PATH) and uses it automatically.

Listing cross-built packages

bash
xrepo list --plat=android --arch=arm64-v8a

Each platform/arch combination is stored separately in the cache so host and cross builds never collide.


Private and Custom Repositories

xrepo's package registry is just a Git repository, and you can add your own. Private package definitions live in the same package() DSL as the official registry — once registered, xrepo install treats them identically to public packages.

Adding a remote repository

bash
xrepo add-repo myrepo https://github.com/myorg/xmake-repo.git

xrepo clones the repo and searches it alongside the official registry. Package names from your repo take priority over the official one if there is a conflict.

Adding a local directory repository

bash
xrepo add-repo localrepo /path/to/local/xmake-repo

Useful during development of new package definitions before pushing them upstream.

Listing registered repositories

bash
xrepo repo list
# official  https://github.com/xmake-io/xmake-repo.git
# myrepo    https://github.com/myorg/xmake-repo.git

Package definition format

Package definitions live in packages/<initial-letter>/<package-name>/xmake.lua inside your repo. The structure mirrors the official registry:

lua
-- packages/f/foobar/xmake.lua
package("foobar")
    set_homepage("https://github.com/myorg/foobar")
    set_description("An internal C++ utility library.")
    set_license("MIT")

    add_urls("https://github.com/myorg/foobar/archive/refs/tags/$(version).tar.gz")
    add_versions("1.2.0", "sha256:abcdef1234567890...")
    add_versions("1.3.0", "sha256:fedcba0987654321...")

    add_deps("fmt", "zlib")    -- declare dependencies

    on_install(function (package)
        local configs = {}
        table.insert(configs, "-DCMAKE_BUILD_TYPE=" .. (package:debug() and "Debug" or "Release"))
        table.insert(configs, "-DBUILD_SHARED_LIBS=" .. (package:config("shared") and "ON" or "OFF"))
        import("package.tools.cmake").install(package, configs)
    end)

    on_test(function (package)
        assert(package:has_cfuncs("foobar_init", {includes = "foobar/foobar.h"}))
    end)
package_end()

Key sections:

  • add_urls — download URL(s); $(version) is interpolated from add_versions
  • add_versions — version string and SHA-256 checksum of the archive
  • add_deps — other xrepo packages this one depends on
  • on_install — Lua function that builds and installs; use package.tools.cmake, package.tools.meson, or package.tools.autoconf helpers
  • on_test — optional smoke test run after install

CI Integration

xrepo's package cache lives in ~/.xmake/packages and is trivially cacheable in CI. Caching this directory between runs makes repeated CI builds nearly as fast as local builds.

GitHub Actions — full workflow

yaml
name: C++ CI

on: [push, pull_request]

jobs:
  build:
    runs-on: ubuntu-latest

    steps:
      - uses: actions/checkout@v4

      - name: Install xmake (includes xrepo)
        uses: xmake-io/github-action-setup-xmake@v1
        with:
          xmake-version: latest

      - name: Cache xrepo packages
        uses: actions/cache@v4
        with:
          path: ~/.xmake/packages
          key: xrepo-${{ runner.os }}-${{ hashFiles('xmake.lua') }}
          restore-keys: |
            xrepo-${{ runner.os }}-

      - name: Install dependencies
        run: xrepo install fmt nlohmann_json openssl

      - name: Configure
        run: xrepo env cmake -B build -S . -DCMAKE_BUILD_TYPE=Release

      - name: Build
        run: cmake --build build --parallel

      - name: Test
        run: ctest --test-dir build --output-on-failure

The xmake-io/github-action-setup-xmake action handles PATH setup and platform quirks. The cache key includes the hash of xmake.lua so a changed dependency list invalidates the cache automatically.

Comparing CI overhead to other package managers

xrepo packages are built from source on a cache miss, similar to Conan with --build=missing. On a cache hit, install time is under a second. vcpkg with binary caching via GitHub Packages has comparable hit-time performance but requires more setup. The main xrepo advantage in CI is the single binary dependency — no Python, no pip, no environment setup beyond running the installer script.

Docker-based CI (no cache layer needed)

dockerfile
FROM tboox/xmake:latest AS deps
WORKDIR /build
RUN xrepo install fmt nlohmann_json openssl

FROM deps AS build
COPY . /src
WORKDIR /src
RUN xrepo env cmake -B build -S . -DCMAKE_BUILD_TYPE=Release \
 && cmake --build build --parallel

Splitting into two stages lets Docker cache the dependency layer independently of source changes.


xrepo vs vcpkg vs Conan vs CPM

Choosing a package manager depends on your constraints. The table below reflects the state of each tool as of mid-2026.

FeaturexrepovcpkgConan 2CPM.cmake
Package count5000+2200+1700+ (CCI)any CMake FetchContent source
Binary cachingYes (local)Yes (local + GitHub Packages + Azure)Yes (Conan Center + custom)No
Cross-compilationFirst-class (--plat, --arch, --ndk)Triplets (good, but fiddly)Profiles (powerful, complex)No (inherits CMake toolchain)
CMake integrationVia xrepo env or xrepo fetch --cmakeToolchain file, seamlessCMakeDeps generatorNative (IS cmake)
Meson integrationVia xrepo env or --pkg-configThird-party scriptspkg-config generatorNo
Build-system agnosticYesPartial (CMake-first)YesNo (CMake only)
Runtime dependencyNone (self-contained binary)Git + compilerPython 3.8+CMake 3.14+
Windows supportExcellentExcellent (Microsoft-maintained)GoodGood
Offline modeYes (after first install)Yes (after bootstrap)Yes (with cache)No (fetches at configure time)
Private reposYes (xrepo add-repo)Overlays + registriesCustom remotesAny URL/Git ref
Learning curveLow (one CLI)Low (one CLI)Medium (conanfile.py)Very low

When to pick xrepo:

  • You are already using xmake or are open to it
  • You need Android/iOS/WASM cross-compilation without a complex toolchain setup
  • You want a single binary that works identically on all three platforms with no runtime deps
  • You value a clean CLI where xrepo install just works

When to pick vcpkg:

  • Your team is on Windows and Visual Studio integration matters
  • You need the largest well-maintained package count
  • Azure DevOps binary caching is already in your pipeline

When to pick Conan:

  • You need precise binary compatibility management across many compiler/OS matrix combinations
  • Your project has complex conanfile.py logic that encodes build variants
  • You are in a large organisation with a private Artifactory server

When to pick CPM:

  • Pure CMake projects, zero extra tooling, packages available as CMake targets
  • Acceptable to build everything from source every time (or rely on FetchContent caching)

See Also

  • xmake — the build system xrepo ships with; native package integration via add_requires()
  • vcpkg — Microsoft's package manager; best Windows + CMake story
  • Conan — decentralised, Python-based, strongest binary compatibility model
  • CPM — CMake-native package management via FetchContent
  • CMake — the build system most packages target; works with all four package managers above
Edit on GitHubUpdated 2026-07-14T00:00:00.000Z