Getting Started with cvcpkg

Install pre-built C/C++ libraries in seconds. No compilation required.

Installation

Install from PyPI:

pip install cvcpkg

Or install from the repository:

git clone https://github.com/transfix/libcvc-deps.git
cd libcvc-deps/tools/cvcpkg
pip install .

Verify the installation:

cvcpkg --version

Quick Start

Install a package into a local prefix:

# Install zlib into ./deps
cvcpkg install zlib --prefix ./deps

# Install multiple packages
cvcpkg install boost hdf5 fftw3 --prefix ./deps

Choose build configuration and link mode:

# Release + shared (default)
cvcpkg install qt6 --prefix ./deps

# Debug + static
cvcpkg install qt6 --prefix ./deps --config debug --link static

List installed packages:

cvcpkg list --prefix ./deps

Requirements Files

Create a cvc-requirements.yaml to declare your dependencies:

# cvc-requirements.yaml
components:
  - name: boost
    version: ">=1.86"
  - name: hdf5
    version: "^1.14"
  - name: qt6
    version: "~6.8"
  - name: vtk
    version: "^9.5"

config: release
link: shared

Install everything from the requirements file:

cvcpkg install --from cvc-requirements.yaml --prefix ./deps

Lock versions for reproducible builds:

cvcpkg lock     # creates cvc-lock.yaml
cvcpkg sync     # installs exactly what's in the lockfile

CLI Reference

Command Description
cvcpkg install Install packages into a prefix
cvcpkg list List installed packages
cvcpkg info <name> Show package details and dependencies
cvcpkg add <name> Add a component to requirements
cvcpkg remove <name> Remove a component from requirements
cvcpkg lock Lock dependency versions
cvcpkg sync Install from lockfile
cvcpkg catalog Browse or refresh the package catalog
cvcpkg verify Verify integrity of installed packages
cvcpkg validate Validate recipe files
cvcpkg gc Remove unused cached downloads
cvcpkg publish Publish archives to a cvcpkg server
cvcpkg world Show the dependency world set

CMake Integration

Point CMAKE_PREFIX_PATH at your cvcpkg prefix:

cmake -B build \
  -DCMAKE_PREFIX_PATH=$(pwd)/deps \
  -DCMAKE_BUILD_TYPE=Release

Use find_package() in your CMakeLists.txt as usual — all packages install standard CMake config files:

find_package(Boost REQUIRED COMPONENTS system filesystem)
find_package(HDF5 REQUIRED COMPONENTS CXX)
find_package(Qt6 REQUIRED COMPONENTS Core Gui Widgets)
find_package(VTK REQUIRED)

Creating Recipes

A recipe describes how to fetch, build, and package a library. Each recipe lives in its own directory under recipes/ with a recipe.yaml and one or more build scripts.

Create a recipe directory:

mkdir -p recipes/mylib
cd recipes/mylib

Write recipe.yaml — the full schema:

schema_version: 1

recipe:
  name: mylib
  upstream_version: "2.1.0"
  cvc_revision: 1
  maintainer: "Your Name"
  maintainer_email: "you@example.com"
  description: "A great library"
  homepage: https://example.com/mylib
  license: MIT
  tags: [utils, io]

source:
  type: tarball
  url: https://example.com/mylib-2.1.0.tar.gz
  sha256: abc123...   # required for tarball sources
  strip_components: 1

depends:
  build:
    - name: zlib      # build-time dependency
    - name: boost
      version: ">=1.86"
  host_tools:
    - cmake
    - ninja

build:
  matrix:
    - platform: linux
      script: build.sh
    - platform: macos
      script: build.sh
    - platform: windows
      script: build.ps1

package:
  files:
    - lib/libmylib*
    - include/mylib/**
  cmake_packages:
    - { name: mylib, targets: [mylib::mylib] }

test:
  script: test.sh

Write a build script (build.sh). Standard CVC_* environment variables are provided:

#!/usr/bin/env bash
set -euo pipefail

cmake -S "$CVC_SOURCE_DIR" -B "$CVC_BUILD_DIR" -G Ninja \
  -DCMAKE_INSTALL_PREFIX="$CVC_INSTALL_DIR" \
  -DCMAKE_PREFIX_PATH="$CVC_DEPS_PREFIX" \
  -DCMAKE_BUILD_TYPE="$CMAKE_BUILD_TYPE" \
  -DBUILD_SHARED_LIBS="$BUILD_SHARED_LIBS"

cmake --build "$CVC_BUILD_DIR" --parallel
cmake --install "$CVC_BUILD_DIR"

Validate your recipe and build locally:

# Validate recipe.yaml schema
cvcpkg validate recipes/mylib

# Build and package
cvcpkg build recipes/mylib --prefix ./deps

# The archive is written to dist/
ls dist/mylib-*.tar.gz

Source types: tarball, git, vcpkg, brew, apt, vendored, and prebuilt. For tarballs, the sha256 field is required. A mirror URL can be specified as a fallback.

Publishing Builds

Publishing requires a token with the publisher or admin role. Publishing to the community archive is admin-gated — contact an administrator for access. Organization members can publish to their own org namespace.

Publish an archive to a cvcpkg server:

cvcpkg publish dist/mylib-2.1.0-linux-x86_64-release-shared.tar.gz \
  --server https://pkg.tx.wtf \
  --token cvctok_...

Publish to an organization namespace:

cvcpkg publish dist/mylib-*.tar.gz \
  --server https://pkg.tx.wtf \
  --token cvctok_... \
  --org my-team

Tag a release (optional; untagged builds are "live"):

cvcpkg publish dist/mylib-*.tar.gz \
  --server https://pkg.tx.wtf \
  --token cvctok_... \
  --release-tag v2.1.0

Token roles: reader (read-only access), publisher (publish + yank), admin (full access including token/org management and hard deletes). Use CVCPKG_SERVER_URL and CVCPKG_TOKEN environment variables to avoid passing flags every time.

Organizations

Organizations let teams publish and manage packages under a shared namespace. Each org has a configurable storage quota (default 10 GiB) set by the CVCPKG_ORG_STORAGE_LIMIT_BYTES environment variable. Admins can adjust the limit per-org via the API.

Create an organization:

curl -X POST https://pkg.tx.wtf/v1/orgs \
  -H "Authorization: Bearer cvctok_..." \
  -H "Content-Type: application/json" \
  -d '{"slug": "my-team", "display_name": "My Team"}'

Add members (requires org owner or admin token):

curl -X POST https://pkg.tx.wtf/v1/orgs/my-team/members \
  -H "Authorization: Bearer cvctok_..." \
  -H "Content-Type: application/json" \
  -d '{"token_name": "alice-token", "role": "member"}'

Update the storage limit (admin only):

# Set to 50 GiB
curl -X PATCH https://pkg.tx.wtf/v1/orgs/my-team \
  -H "Authorization: Bearer cvctok_..." \
  -H "Content-Type: application/json" \
  -d '{"storage_limit_bytes": 53687091200}'

Storage enforcement: When publishing to an organization, the server checks that storage_used + upload_size ≤ storage_limit. If the limit is exceeded the upload is rejected with HTTP 413. Organizations require the database backend (CVCPKG_DATABASE_URL).

Self-Hosting a Package Server

Run a local server for development or private packages:

cvcpkg-server run --state-dir ./my-packages --port 8420

Or use the Docker Compose production stack:

cd tools/cvcpkg
cp .env.production.example .env.production
# Edit .env.production with your secrets
docker compose -f docker-compose.production.yml \
  --env-file .env.production up -d

Create an API token and publish packages:

# Create a publisher token
cvcpkg-server token create --name ci-bot --role publisher

# Publish an archive
cvcpkg publish my-lib-1.0-linux-x86_64-release-shared.tar.zst \
  --server http://localhost:8420 \
  --token cvctok_...

Remote Builders

Remote builders are worker machines that automatically build packages from recipes. The server dispatches build jobs to registered builders via WebSocket. Results (archives and logs) are streamed back and published to the package index.

Push recipes to the server — recipes define how to build a package:

cvcpkg recipe push zlib \
  --server https://pkg.tx.wtf --token cvctok_...

# Or push all local recipes at once
cvcpkg recipe push-all --server https://pkg.tx.wtf --token cvctok_...

Register a builder — create a builder token and start the worker:

# Create a builder token (on the server)
cvcpkg-server token create --name builder-01 --role builder

# Start the builder worker
cvcpkg builder run \
  --server https://pkg.tx.wtf \
  --token cvctok_... \
  --max-jobs 2

Submit build jobs — build a single recipe or a full dependency graph:

# Single build
cvcpkg builds submit zlib --platform linux --arch x86_64 \
  --server https://pkg.tx.wtf --token cvctok_...

# DAG build (resolves dependencies automatically)
cvcpkg builds submit-dag tiff --platform linux --arch x86_64 \
  --server https://pkg.tx.wtf --token cvctok_...

Monitor builds — use the web UI or CLI to track progress:

# List recent builds
cvcpkg builds list --server https://pkg.tx.wtf --token cvctok_...

# Or visit the web dashboard:
#   /builders  — registered builders and status
#   /builds    — all build jobs with filters
#   /build/42  — single build with live log

DAG builds automatically resolve recipe dependencies and submit them in the correct order. Leaf dependencies build first; the target recipe builds only after all its dependencies succeed. Use the Build Jobs dashboard to view DAG progress.

Server Configuration

Server settings are controlled via environment variables or cvcpkg-server run CLI flags. State (index, tokens, audit log, archives) is stored under the state directory (CVCPKG_SERVER_STATE_DIR, default /var/lib/cvcpkg-server). The HMAC signing key is stored in <state-dir>/hmac_key (mode 0600).

Variable / Flag Default Description
CVCPKG_DATABASE_URL
--database-url
empty PostgreSQL URL; enables DB backend (required for orgs)
CVCPKG_SERVER_STATE_DIR
--state-dir
./cvcpkg-server-data Directory for index, tokens, audit log, and archives
CVCPKG_SERVER_STORAGE_URI
--storage
file://<state-dir> Storage backend URI (file, S3, etc.)
CVCPKG_MAX_UPLOAD_BYTES 1 GiB Maximum upload size per file
CVCPKG_CHUNK_SIZE 8 MiB Chunk size for chunked uploads
CVCPKG_UPLOAD_SESSION_TTL 3600 s Chunked upload session timeout
CVCPKG_RATE_LIMIT_RPM 300 Write-endpoint rate limit (requests/min, 0 = disabled)
CVCPKG_ORG_STORAGE_LIMIT_BYTES 10 GiB Default per-organization storage quota
CVCPKG_CORS_ORIGINS empty Comma-separated allowed CORS origins
CVCPKG_SERVER_REQUIRE_AUTH_READS
--require-auth-reads
false Require auth token for read endpoints
CVCPKG_LOG_JSON
--log-json
false Structured JSON log output
--host 0.0.0.0 Bind address
--port 8420 Listen port
--workers 1 Number of uvicorn workers

For Docker deployments, copy .env.production.example and set POSTGRES_PASSWORD, POSTGRES_USER, POSTGRES_DB, BACKEND_PORT, and CVCPKG_RELEASE. See docker-compose.production.yml.

Branding: Customize the landing page with CVCPKG_SITE_TITLE, CVCPKG_SITE_TAGLINE, and CVCPKG_SITE_HERO. Set CVCPKG_GITHUB_REPO to change the GitHub link (default: transfix/libcvc-deps).

REST API

The cvcpkg server exposes a full REST API. Key endpoints:

Method Endpoint Description
GET /v1/packages List all packages (filterable, paginated)
GET /v1/packages/{name} Get builds for a specific package
GET /v1/catalog Full catalog (YAML)
GET /v1/deps Dependency graph and recipe metadata
GET /v1/download/{file} Download a package archive
POST /v1/publish Publish a new package
POST /v1/packages/{name}/{ver}/yank Yank a package version
DEL /v1/packages/{name}/{ver} Delete a package (admin)

See the full interactive API documentation at /docs (Swagger UI) or /redoc (ReDoc).