diff --git a/skills/vcpkg/SKILL.md b/skills/vcpkg/SKILL.md new file mode 100644 index 00000000..8fe2eaa4 --- /dev/null +++ b/skills/vcpkg/SKILL.md @@ -0,0 +1,283 @@ +--- +name: vcpkg +description: Guide for setting up vcpkg in C++ projects, managing dependency versions, and cross-compiling. Covers manifest initialization, CMake and Visual Studio integration, classic-to-manifest migration, version pinning, baselines, overrides, triplets, and cross-compilation. Use when a user is working with vcpkg project setup, installation, version management, or cross-platform builds. For specialized tasks, additional references cover custom registries and overlay ports (references/registries.md), CI/CD and binary caching (references/ci.md), and troubleshooting and dependency lifecycle (references/troubleshooting.md). +--- + +You are a vcpkg expert assistant. When a user asks about vcpkg (Microsoft's C/C++ package manager), use the precise information below to give accurate, complete answers. + +## Additional References (load on demand) + +The information below covers core vcpkg setup, installation, version management, and cross-platform builds. For specialized tasks, consult the following reference files (read them only when the user's request calls for that topic): + +- **`references/registries.md`** — Custom/private registries, overlay ports, private package feeds, `vcpkg-configuration.json`, and default features. Read this when the user asks about custom registries, overlay ports, or private package sources. +- **`references/ci.md`** — CI/CD integration: binary caching (Azure Blob, GitHub Packages/NuGet, local), SBOM generation, automating dependency updates, and multi-triplet CI matrices. Read this when the user asks about GitHub Actions, Azure DevOps, binary caches, or CI optimization. +- **`references/troubleshooting.md`** — Reading build logs, resolving package-not-found errors, and the dependency lifecycle (removing, changing features, replacing libraries, cleaning the cache). Read this when the user encounters vcpkg errors, build failures, or configuration problems. + +## Important Behavioral Rules + +### Classic vs. Manifest Mode + +If it is not clear from the user's project context whether they are using **classic mode** (global `vcpkg install` commands) or **manifest mode** (per-project `vcpkg.json`), **ask the user which mode they are using** before providing instructions. Do not assume one or the other. + +If the user is unsure which to choose, **recommend manifest mode**. Manifest mode is the preferred modern workflow because it: +- Tracks dependencies per-project (not globally) +- Supports version constraints and overrides +- Enables reproducible builds via `builtin-baseline` +- Works seamlessly with CI/CD (dependencies restore automatically) +- Supports features like dev-only dependencies, overlay ports, and custom registries + +Classic mode is simpler for quick one-off installs but lacks version pinning, per-project isolation, and reproducibility. + +### Visual Studio Environment + +If the user is working inside **Visual Studio** (not VS Code), prefer using the **in-box copy of vcpkg that ships with Visual Studio** rather than a standalone vcpkg clone, unless the user indicates they want to use a different installation. The VS-bundled vcpkg: +- Is located under the Visual Studio installation directory (e.g., `C:\Program Files\Microsoft Visual Studio\\\VC\vcpkg\`) +- Is automatically integrated with MSBuild — no need to run `vcpkg integrate install` +- Stays up-to-date with Visual Studio updates +- Works out of the box with CMake projects opened via "Open Folder" or CMake presets + +If the user has a standalone vcpkg installation and prefers to use that instead, respect their preference. + +--- + +## Project Setup + +### Initializing vcpkg in a New Project (Manifest Mode) + +1. Create `vcpkg.json` in your project root: +```json +{ + "name": "my-project", + "version": "1.0.0", + "dependencies": [] +} +``` + +2. Wire into CMakeLists.txt: +```cmake +cmake_minimum_required(VERSION 3.21) +project(my-project) + +find_package(fmt CONFIG REQUIRED) +target_link_libraries(my-app PRIVATE fmt::fmt) +``` + +3. Configure with vcpkg toolchain: +``` +cmake -B build -DCMAKE_TOOLCHAIN_FILE=/scripts/buildsystems/vcpkg.cmake +``` + +### Adding vcpkg to an Existing Visual Studio Solution + +1. Run `vcpkg integrate install` (one-time, system-wide) +2. Create `vcpkg.json` in the solution directory +3. In VS, the integration is automatic via MSBuild props — no project file edits needed +4. Or per-project: add to `.vcxproj`: +```xml + + +``` + +### Classic-to-Manifest Migration + +1. List what's currently installed: `vcpkg list` +2. Create `vcpkg.json` with those dependencies +3. Delete global installs: `vcpkg remove --outdated --recurse` +4. Run `vcpkg install` in your project directory — manifest mode takes precedence +5. Update your build system to use `CMAKE_TOOLCHAIN_FILE` if not already + +--- + +## Installing Dependencies + +### Installing with Features (e.g., curl with SSL + HTTP2) + +In **manifest mode** (`vcpkg.json`), specify features in the dependencies array: +```json +{ + "dependencies": [ + { + "name": "curl", + "features": ["ssl", "http2"] + } + ] +} +``` + +In **classic mode**, use bracket syntax on the command line: +``` +vcpkg install curl[ssl,http2] +``` + +To discover available features for any port: +``` +vcpkg search curl +``` +Or check the port's `vcpkg.json` in the registry: `ports/curl/vcpkg.json` → look at the `"features"` object. + +### Installing for a Specific Triplet + +``` +vcpkg install zlib:x64-linux +vcpkg install zlib:x64-windows +vcpkg install zlib:arm64-windows +``` + +In manifest mode, set the triplet via CMake: +``` +cmake -B build -DVCPKG_TARGET_TRIPLET=x64-linux -DCMAKE_TOOLCHAIN_FILE=[vcpkg root]/scripts/buildsystems/vcpkg.cmake +``` + +Or set the environment variable: +``` +set VCPKG_DEFAULT_TRIPLET=x64-linux +``` + +### Bulk-Adding Multiple Dependencies + +In `vcpkg.json`, list them in the dependencies array: +```json +{ + "dependencies": ["catch2", "cxxopts", "toml11"] +} +``` + +In classic mode: +``` +vcpkg install catch2 cxxopts toml11 +``` + +Then run `vcpkg install` (manifest mode) or the above command to install all at once. + +### Dev-Only Dependencies + +Use the `"host"` field or place test dependencies under a feature: +```json +{ + "dependencies": [ + "fmt", + "spdlog" + ], + "features": { + "tests": { + "description": "Build tests", + "dependencies": ["gtest"] + } + } +} +``` + +Activate with: `vcpkg install --x-feature=tests` or in CMake: `-DVCPKG_MANIFEST_FEATURES=tests` + +--- + +## Version Management + +### Pinning a Specific Version + +In `vcpkg.json`, use `"version>="` with overrides: +```json +{ + "dependencies": ["fmt"], + "overrides": [ + { + "name": "fmt", + "version": "10.2.0" + } + ], + "builtin-baseline": "" +} +``` + +The `builtin-baseline` is **required** when using versioning. Get the latest baseline: +``` +git -C rev-parse HEAD +``` + +### Version Overrides + +To force a specific version of a transitive dependency across your entire project, use `"overrides"` in `vcpkg.json`: +```json +{ + "dependencies": ["protobuf", "grpc"], + "overrides": [ + { + "name": "zlib", + "version": "1.3.1" + } + ], + "builtin-baseline": "" +} +``` + +**Key points:** +- `overrides` takes precedence over all version constraints, including transitive ones +- You **must** have a `builtin-baseline` set for overrides to work +- The version must exist in the vcpkg registry at or after the baseline commit +- Use `vcpkg x-history zlib` to see available versions + +### Updating the Baseline + +The baseline is a Git commit SHA in the vcpkg repository that pins all port versions: +```json +{ + "builtin-baseline": "a1b2c3d4e5f6..." +} +``` + +To update to the latest: +```bash +cd +git pull +git rev-parse HEAD +``` +Then paste the new SHA into `builtin-baseline`. + +**Important:** Updating the baseline may change versions of *all* dependencies. Use `overrides` to pin specific packages if needed. + +--- + +## Cross-Platform + +### Cross-Compiling for arm64 + +``` +vcpkg install :arm64-linux +``` + +Or set the triplet in CMake: +``` +cmake -B build -DVCPKG_TARGET_TRIPLET=arm64-linux -DCMAKE_TOOLCHAIN_FILE=$VCPKG_ROOT/scripts/buildsystems/vcpkg.cmake +``` + +You may need a cross-compilation toolchain installed (e.g., `aarch64-linux-gnu-gcc`). + +For **arm64-windows**, just use the triplet directly — no cross-compiler needed on ARM64 Windows or with MSVC: +``` +vcpkg install :arm64-windows +``` + +### Building for Android (NDK) + +1. Set environment variables: +```bash +export ANDROID_NDK_HOME=/path/to/ndk +export VCPKG_DEFAULT_TRIPLET=arm64-android +``` + +2. Install packages: +``` +vcpkg install :arm64-android +``` + +Available Android triplets: `arm-neon-android`, `arm64-android`, `x86-android`, `x64-android` + +3. In CMake: +``` +cmake -B build \ + -DCMAKE_TOOLCHAIN_FILE=$VCPKG_ROOT/scripts/buildsystems/vcpkg.cmake \ + -DVCPKG_TARGET_TRIPLET=arm64-android \ + -DVCPKG_CHAINLOAD_TOOLCHAIN_FILE=$ANDROID_NDK_HOME/build/cmake/android.toolchain.cmake \ + -DANDROID_ABI=arm64-v8a \ + -DANDROID_PLATFORM=android-24 +``` diff --git a/skills/vcpkg/references/ci.md b/skills/vcpkg/references/ci.md new file mode 100644 index 00000000..39b24782 --- /dev/null +++ b/skills/vcpkg/references/ci.md @@ -0,0 +1,96 @@ +# vcpkg: CI/CD & DevOps + +Reference for the `vcpkg` skill. Use this when a user asks about using vcpkg in CI/CD pipelines, configuring binary caching, setting up devcontainers, generating SBOMs, or automating dependency updates (GitHub Actions, Azure DevOps, binary cache configuration, CI optimization). + +## Binary Caching + +Configure binary caching to avoid rebuilding packages: + +**Azure Blob Storage:** +``` +set VCPKG_BINARY_SOURCES=clear;x-azblob,https://myaccount.blob.core.windows.net/vcpkg-cache,,readwrite +``` + +**GitHub Packages (NuGet):** +``` +set VCPKG_BINARY_SOURCES=clear;nuget,https://nuget.pkg.github.com/your-org/index.json,readwrite +``` + +**Local filesystem:** +``` +set VCPKG_BINARY_SOURCES=clear;files,C:/vcpkg-cache,readwrite +``` + +**Sharing between CI and local dev:** Use the same remote cache (Azure Blob or NuGet feed) in both environments. CI writes (`readwrite`), developers read (`read`): +``` +# CI (writes cache) +set VCPKG_BINARY_SOURCES=clear;x-azblob,https://myaccount.blob.core.windows.net/cache,,readwrite + +# Developer (reads cache) +set VCPKG_BINARY_SOURCES=clear;x-azblob,https://myaccount.blob.core.windows.net/cache,,read +``` + +--- + +## Generating an SBOM (Software Bill of Materials) + +vcpkg can generate an SBOM in SPDX format: +``` +vcpkg install --x-write-nuget-packages-config=packages.config +``` + +For manifest mode, after install check `vcpkg_installed//share/` for SPDX files. Each installed port generates an SPDX JSON document at: +``` +vcpkg_installed//share//sbom.spdx.json +``` + +To aggregate: use `vcpkg x-package-info --x-installed` to list all packages and versions, then feed into your SBOM toolchain (e.g., Microsoft SBOM Tool, CycloneDX). + +--- + +## Automating Dependency Updates + +Option 1: **Dependabot** (GitHub) — configure `.github/dependabot.yml`: +```yaml +version: 2 +updates: + - package-ecosystem: "vcpkg" + directory: "/" + schedule: + interval: "weekly" +``` + +Option 2: **Script-based** — create a scheduled CI job that: +1. Updates the vcpkg clone (`git pull`) +2. Gets the new baseline (`git rev-parse HEAD`) +3. Updates `builtin-baseline` in `vcpkg.json` +4. Runs `vcpkg install` to verify +5. Opens a PR with the changes + +--- + +## Multi-Triplet CI Testing + +Test across multiple triplets in a CI matrix: +```yaml +# GitHub Actions example +strategy: + matrix: + triplet: [x64-windows, x64-linux, x64-osx] + include: + - triplet: x64-windows + os: windows-latest + - triplet: x64-linux + os: ubuntu-latest + - triplet: x64-osx + os: macos-latest + +steps: + - uses: actions/checkout@v4 + - name: Install vcpkg + run: | + git clone https://github.com/microsoft/vcpkg + ./vcpkg/bootstrap-vcpkg.sh + - name: Install dependencies + run: vcpkg install --triplet ${{ matrix.triplet }} +``` diff --git a/skills/vcpkg/references/registries.md b/skills/vcpkg/references/registries.md new file mode 100644 index 00000000..61a5fa37 --- /dev/null +++ b/skills/vcpkg/references/registries.md @@ -0,0 +1,133 @@ +# vcpkg: Custom Registries & Overlay Ports + +Reference for the `vcpkg` skill. Use this when a user asks about creating or configuring custom registries, creating overlay ports, using private package feeds, or configuring `vcpkg-configuration.json` registries. + +## Private / Custom Registry Install + +1. Create `vcpkg-configuration.json` alongside your `vcpkg.json`: +```json +{ + "registries": [ + { + "kind": "git", + "repository": "https://github.com/your-org/vcpkg-registry", + "baseline": "", + "packages": ["company-utils", "internal-lib"] + } + ], + "default-registry": { + "kind": "builtin", + "baseline": "" + } +} +``` + +2. Then add the dependency normally in `vcpkg.json`: +```json +{ + "dependencies": ["company-utils"] +} +``` + +The `"packages"` array in the registry entry controls which packages are resolved from that registry. Packages not listed fall through to `default-registry`. + +--- + +## Configuring Registries in `vcpkg-configuration.json` + +```json +{ + "default-registry": { + "kind": "builtin", + "baseline": "" + }, + "registries": [ + { + "kind": "git", + "repository": "https://github.com/your-org/vcpkg-registry.git", + "baseline": "", + "packages": ["your-package-1", "your-package-2"] + } + ] +} +``` + +Place this file next to `vcpkg.json` in your project root. + +--- + +## Creating an Overlay Port + +An overlay port overrides or adds a port locally. Directory structure: +``` +my-overlays/ + telemetry-sdk/ + portfile.cmake + vcpkg.json +``` + +**`vcpkg.json`** (port metadata): +```json +{ + "name": "telemetry-sdk", + "version": "1.0.0", + "description": "Internal telemetry SDK", + "dependencies": ["curl", "nlohmann-json"] +} +``` + +**`portfile.cmake`** (build instructions): +```cmake +vcpkg_from_github( + OUT_SOURCE_PATH SOURCE_PATH + REPO your-org/telemetry-sdk + REF v1.0.0 + SHA512 +) + +vcpkg_cmake_configure(SOURCE_PATH "${SOURCE_PATH}") +vcpkg_cmake_install() +vcpkg_cmake_config_fixup() + +file(REMOVE_RECURSE "${CURRENT_PACKAGES_DIR}/debug/include") +vcpkg_install_copyright(FILE_LIST "${SOURCE_PATH}/LICENSE") +``` + +Use it: `vcpkg install telemetry-sdk --overlay-ports=./my-overlays` +Or in `vcpkg-configuration.json`: +```json +{ + "overlay-ports": ["./my-overlays"] +} +``` + +--- + +## Default Features + +Set default features in `vcpkg.json` for a port so they're always enabled: +```json +{ + "dependencies": [ + { + "name": "curl", + "default-features": true, + "features": ["ssl", "http2"] + } + ] +} +``` + +To **disable** default features: `"default-features": false` + +In a portfile's `vcpkg.json`, default features are listed under: +```json +{ + "name": "curl", + "default-features": ["ssl", "http2"], + "features": { + "ssl": { "description": "SSL/TLS support" }, + "http2": { "description": "HTTP/2 support" } + } +} +``` diff --git a/skills/vcpkg/references/troubleshooting.md b/skills/vcpkg/references/troubleshooting.md new file mode 100644 index 00000000..664eb8d0 --- /dev/null +++ b/skills/vcpkg/references/troubleshooting.md @@ -0,0 +1,94 @@ +# vcpkg: Troubleshooting & Dependency Lifecycle + +Reference for the `vcpkg` skill. Use this when a user encounters vcpkg build failures, package-not-found errors, needs to read build logs, or manages the dependency lifecycle (removing, changing features, replacing libraries, cleaning the cache). + +## Reading vcpkg Build Logs + +Build logs are stored at: +``` +/buildtrees// +``` + +Key log files: +- `config--out.log` — CMake configure output +- `build--out.log` — Build (compile) output +- `install--out.log` — Install step output +- `config--err.log` — CMake configure errors +- `build--err.log` — Build errors +- `package--out.log` — Packaging output + +When a build fails, vcpkg prints the path to the relevant log. Start with the `-err.log` file for the failing step. + +--- + +## Resolving package-not-found After Install + +If CMake says `Could not find a package configuration file provided by "X"`: + +1. **Check toolchain file** — ensure `-DCMAKE_TOOLCHAIN_FILE=/scripts/buildsystems/vcpkg.cmake` is set +2. **Check triplet match** — the installed triplet must match your build architecture +3. **Check package name** — vcpkg port names may differ from CMake package names (e.g., port `nlohmann-json` → `find_package(nlohmann_json)`) +4. **Check installed list** — run `vcpkg list` to confirm the package is actually installed +5. **Clear CMake cache** — delete `CMakeCache.txt` and reconfigure + +--- + +## Dependency Lifecycle + +### Removing a Library + +1. Remove it from `vcpkg.json` → `"dependencies"` array +2. Run `vcpkg install` to reconcile (manifest mode auto-removes unused packages) + +In classic mode: +``` +vcpkg remove boost-regex +vcpkg remove boost-regex --recurse # also removes dependents +``` + +### Changing Features on an Installed Library + +Update the features in `vcpkg.json`: +```json +{ + "dependencies": [ + { + "name": "curl", + "features": ["ssl", "ssh"] + } + ] +} +``` + +Then run `vcpkg install` — vcpkg will detect the feature change and rebuild. + +In classic mode: +``` +vcpkg install curl[ssl,ssh] # reinstalls with new features +``` + +### Replacing One Library with Another + +1. Remove the old library from `vcpkg.json` +2. Add the new library to `vcpkg.json` +3. Run `vcpkg install` to reconcile +4. Update your source code: change `#include` directives, `find_package()` calls, and `target_link_libraries()` in CMakeLists.txt + +### Cleaning the vcpkg Cache + +```bash +# Remove build trees (intermediate build files) +rm -rf /buildtrees + +# Remove downloaded archives +rm -rf /downloads + +# Remove installed packages (classic mode only) +rm -rf /installed + +# Remove all package build artifacts +vcpkg x-clean + +# In manifest mode, remove the local vcpkg_installed directory +rm -rf vcpkg_installed/ +```