惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

T
Threat Research - Cisco Blogs
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
Last Week in AI
Last Week in AI
大猫的无限游戏
大猫的无限游戏
博客园 - 三生石上(FineUI控件)
WordPress大学
WordPress大学
博客园 - Franky
V2EX - 技术
V2EX - 技术
V
V2EX
T
Tailwind CSS Blog
P
Privacy International News Feed
S
Securelist
腾讯CDC
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
NISL@THU
NISL@THU
C
CXSECURITY Database RSS Feed - CXSecurity.com
有赞技术团队
有赞技术团队
人人都是产品经理
人人都是产品经理
月光博客
月光博客
T
The Blog of Author Tim Ferriss
博客园 - 【当耐特】
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
Simon Willison's Weblog
Simon Willison's Weblog
C
Check Point Blog
Cisco Talos Blog
Cisco Talos Blog
Recorded Future
Recorded Future
L
LangChain Blog
The Hacker News
The Hacker News
Project Zero
Project Zero
GbyAI
GbyAI
Stack Overflow Blog
Stack Overflow Blog
宝玉的分享
宝玉的分享
云风的 BLOG
云风的 BLOG
Latest news
Latest news
S
Schneier on Security
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
博客园 - 叶小钗
C
Cisco Blogs
I
Intezer
Recent Announcements
Recent Announcements
Hugging Face - Blog
Hugging Face - Blog
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
The Register - Security
The Register - Security
I
InfoQ
Engineering at Meta
Engineering at Meta
博客园 - 司徒正美
小众软件
小众软件
V
Vulnerabilities – Threatpost
Schneier on Security
Schneier on Security
TaoSecurity Blog
TaoSecurity Blog

C++ Team Blog

Pure Virtual C++ 2026 Is Now Live! - C++ Team Blog Pure Virtual C++ 2026 Is Tomorrow and On-Demand Sessions Are Now Available - C++ Team Blog Faster C++ iterative builds with GitHub Copilot - C++ Team Blog Pure Virtual C++ 2026 [Meet the Speakers, Part 3]: Modernizing C++ - C++ Team Blog MSVC Build Tools Preview updates - July 2026 - C++ Team Blog Rethinking C++ Performance: Faster Code Navigation and GitHub Copilot Tools with Whole Codebase Indexing - C++ Team Blog Pure Virtual C++ 2026 [Meet the Speakers, Part 2]: The AI-Native C++ Developer Workflow - C++ Team Blog Pure Virtual C++ 2026 [Meet the Speakers, Part 1]: Build Faster, Run Faster - C++ Team Blog What's New in vcpkg (June 2026) - C++ Team Blog Pure Virtual C++ 2026 Talks Announced - C++ Team Blog Save the Date: Pure Virtual C++ 2026 - C++ Team Blog Streamline C++ Code Intelligence Setup in Copilot CLI - C++ Team Blog Boosting Adobe Photoshop’s Performance with MSVC and SPGO - C++ Team Blog GitHub Copilot modernization for C++ is out of preview MSVC Build Tools Preview updates – June 2026 What’s New in vcpkg (May 2026) What’s New for C++ Developers in Visual Studio 2026 (18.1 – 18.6) Introducing Sample Profile Guided Optimization in MSVC NuGet PackageReference for C++ Projects in Visual Studio Segment Heap support for C++ projects in Visual Studio MSVC Build Tools Preview updates – May 2026 MSVC Build Tools version 14.51 (GA) now available Project-Specific Build Optimizations with GitHub Copilot What's New in vcpkg (Apr 2026) - C++ Team Blog Giving Copilot more C++ context using custom instructions in VS Code Take the 2026 ISO C++ Developer Survey! - C++ Team Blog C++ Code Intelligence for GitHub Copilot CLI (Preview) - C++ Team Blog MSVC Build Tools Version 14.51 Release Candidate Now Available C++23 Support in MSVC Build Tools 14.51 What’s New in vcpkg (Feb 2026 – Mar 2026): Parallel file installation and more! Visual Studio at GDC Festival of Gaming 2026 C++ Performance Improvements in MSVC Build Tools v14.51 C++ symbol context and CMake build configuration awareness for GitHub Copilot in VS Code Microsoft C++ (MSVC) Build Tools v14.51 Preview Released: How to Opt In What’s New in vcpkg (Nov 2025 – Jan 2026) MSVC Build Tools Versions 14.30 – 14.43 Now Available in Visual Studio 2026 GitHub Copilot app modernization for C++ is now in Public Preview Visual Studio Code CMake Tools 1.22: Target bookmarks and better CTest output
C++ Dependencies Without the Headache: vcpkg + Copilot CLI - C++ Team Blog
Augustin Popa · 2026-07-21 · via C++ Team Blog

C++ dependency setup and maintenance still slows down many teams. In my Pure Virtual C++ 2026 session, I show a terminal-first workflow that ends with a working CLI app that formats and prints programming quotes, built with CMake and Microsoft C++ (MSVC) Build Tools. All of this is powered by GitHub Copilot CLI, which does the work of generating the code and project files, identifying appropriate open-source library dependencies, installing the vcpkg package manager, and integrating the libraries into the project.

What is GitHub Copilot CLI?

GitHub Copilot CLI is the command-line implementation for GitHub Copilot, allowing you to run agents in a terminal window. You can use it as an AI chat interface, give it work to do semi- or fully autonomously, optionally across multiple parallel subagents. For C++ developers, Copilot CLI is a valuable tool for work you would be comfortable doing in the command line yourself, from generating code to compiling projects and debugging issues. You can persist and manage Copilot sessions, customize your environment with plugins, custom agents, MCP servers, skills, hooks, and models, and seamlessly switch from working in the command line to using Copilot in another environment like Visual Studio Code (VS Code). Once you get into the groove, using it feels as natural as a web browser or an IDE.

Check out the Pure Virtual C++ video

What this demo covers

This walkthrough will show you the following:

  1. You can use Copilot to help you install the tools you need, including the vcpkg package manager. Copilot can also help you identify appropriate library dependencies, describe what each one does, and integrate them into your project.
  2. vcpkg removes manual dependency wiring. You declare dependencies once in vcpkg.json, and restore is part of your normal configure/build flow.
  3. Copilot helps you complete multi-step setup work without context-switching between docs and terminal commands.
  4. You can work with Copilot on additional instructions, like setting an appropriate builtin-baseline to pin dependencies for reproducible builds while retaining the flexibility to upgrade later without introducing ABI-breaking changes in your dependency graph.

This walkthrough starts from the first prompt and ends with a successful build: start in an empty folder, stay in the terminal, and avoid hand-managed include and link paths.

Read-along Walkthrough

This section is written so you can follow along with the video demo.

Step 0: Configure Copilot CLI environment

Before you get started, make sure your environment is set up and ready to go:

  1. Install GitHub Copilot CLI with your preferred package manager or a script.
  2. Make sure you have CMake and a compiler installed on your system. In this video I used CMake with MSVC Build Tools on Windows.
  3. Choose your preferred terminal application. On Windows, I recommend Windows Terminal, which supports multiple color-coded, custom-named tabs as I show in the video.
  4. Create and navigate to a directory to work in (e.g. mkdir quotecli). Add a subfolder called data with a quotes.json file that looks something like this:
    {
        "quotes": [
            { "text": "Any sufficiently advanced technology is indistinguishable from magic.", "author": "Arthur C. Clarke" },
            { "text": "Simplicity is prerequisite for reliability.", "author": "Edsger W. Dijkstra" },
            { "text": "Controlling complexity is the essence of computer programming.", "author": "Brian Kernighan" },
            { "text": "That brain of mine is something more than merely mortal, as time will show.", "author": "Ada Lovelace" },
            { "text": "First, solve the problem. Then, write the code.", "author": "John Johnson" },
            { "text": "The most important property of a program is whether it accomplishes the intention of its user.", "author": "C.A.R. Hoare" },
            { "text": "Programs must be written for people to read, and only incidentally for machines to execute.", "author": "Harold Abelson" },
            { "text": "Premature optimization is the root of all evil.", "author": "Donald Knuth" }
        ]
    }
  5. Run Copilot in your terminal from your working directory root by typing copilot. Copilot welcome screen
  6. Install the C++ language server protocol plugin, described in Streamline C++ code intelligence setup in Copilot CLI. This is recommended for any C++ work with Copilot CLI, as it enables the semantic intelligence you’re used to in Visual Studio and VS Code in the CLI environment. In Copilot CLI, run /plugin install cpp-language-server@copilot-plugins.
  7. Select your preferred model by running /model. I recommend starting with “Auto”, which lets Copilot select an appropriate model per task (optimizing between token cost and correctness). You can also manually select a specific model.
  8. Optional: Install a vcpkg custom skill I wrote that gives Copilot additional guidance when working with vcpkg. Copilot does a pretty good job on its own, but this lets you handle more advanced scenarios in a more prescriptive way. Plus you can always edit the skill later to further control Copilot’s behavior. To install, download it to your machine, and run /skill add local-path-to-skill. Note: This skill isn’t officially maintained by Microsoft; it’s there to get you started with a customizable workflow, should you want it.

Step 1: Set the context and ask Copilot CLI to build a plan

Begin by typing Shift+Tab until you transition Copilot into Plan Mode. This mode causes Copilot to discuss an implementation plan with you before it begins working, and is useful if you want to use Copilot on something complex, such as a multi-step workflow. This allows you to check what Copilot wants to do before doing it, so you can intervene and correct it if necessary.

Next, type a prompt similar to the following:

I want to write a C++ console application that prints a random software development quote with pretty formatting from a list specified in data/quotes.json. I want to build with CMake and MSVC with some open-source libraries from vcpkg. I already have both CMake and MSVC installed, but don't have vcpkg. Install vcpkg and include it in this directory for use. I don't know what C++ libraries to use, help me work that out too.

Expected result: Copilot produces a plan describing what it wants to build, how the project will be structured, the expected behavior of the app, and docs (README file).

Step 2: Accept plan and build

Once Copilot has prepared the plan, if you are satisfied with it, you can select Accept plan and build on default permissions. This allows Copilot to begin working, while continuing to ask your permission to run commands and modify files. You could instead choose Accept plan and build on autopilot if you want Copilot to work autonomously and notify you when it finishes. You can also suggest changes if you’re not happy with the plan, and iterate until you’re ready to proceed.

Expected result: Copilot CLI proposes library choices, sets up a CMake project, installs and initializes vcpkg in the repo, creates a vcpkg.json manifest, and builds the project to test that there are no errors. It may iterate on its work several times as it identifies new issues that need to be addressed (e.g. selecting the appropriate CMake generator for what you have installed on your system).

Step 3: Ask clarifying questions

You can ask Copilot to explain its decisions or to give you a better understanding of the resulting project. Here are some example prompts:

Explain each library you chose, what problem it solves in this app, and where we use it.
Can you give me some boilerplate code for using <library> in a similar context?
How do I build and run this project?

Expected result: you get a short technical explanation for the topic(s) you want explained. Based on the answers, you can decide whether to instruct Copilot to make further changes.

Step 4: Test the application

In a separate terminal window/tab, configure CMake, build, and run:

cmake --preset msvc-debug
cmake --build --preset build-debug
.\build\msvc-debug\bin\Debug\quotecli.exe

Running Quotes App

Expected result: Program runs successfully, generating a random quote each time it is run from the list of available quotes.

Step 5: Make a change: set a versioning baseline

Now suppose you want to set and pin your library versions to achieve reproducible builds. Once again, Copilot can guide you once you instruct it with a simple prompt:

I want to pin my dependencies to the latest official vcpkg release so I can achieve reproducible builds. How can I do that in vcpkg?

Expected result: Copilot is able to add a builtin-baseline field to vcpkg.json, choosing a reasonable baseline based on the latest official vcpkg release, and provide you with guidance on what it all means and how to maintain it going further. You can ask Copilot to clarify specific topics along the way.

Step 6: Inspect the generated project shape

At the end of all this, your project should have a layout similar to this:

  1. vcpkg.json with your dependency list and builtin-baseline.
  2. CMakeLists.txt with find_package(...) entries and linked targets.
  3. CMakePresets.json
  4. App source code, particularly src/main.cpp.
  5. The quotes data file: data/quotes.json.

Directory layout:

quotecli
├── build
├── data
│   └── quotes.json
├── src
│   └── main.cpp
├── vcpkg
│   └── <vcpkg files>
├── CMakeLists.txt
├── CMakePresets.json
├── README.md
└── vcpkg.json

This is what each of the major files looks like in my demo:

quotes.json

{
  "quotes": [
    { "text": "Any sufficiently advanced technology is indistinguishable from magic.", "author": "Arthur C. Clarke" },
    { "text": "Simplicity is prerequisite for reliability.", "author": "Edsger W. Dijkstra" },
    { "text": "Controlling complexity is the essence of computer programming.", "author": "Brian Kernighan" },
    { "text": "That brain of mine is something more than merely mortal, as time will show.", "author": "Ada Lovelace" },
    { "text": "First, solve the problem. Then, write the code.", "author": "John Johnson" },
    { "text": "The most important property of a program is whether it accomplishes the intention of its user.", "author": "C.A.R. Hoare" },
    { "text": "Programs must be written for people to read, and only incidentally for machines to execute.", "author": "Harold Abelson" },
    { "text": "Premature optimization is the root of all evil.", "author": "Donald Knuth" }
  ]
}

main.cpp:

#include <cctype>
#include <filesystem>
#include <fstream>
#include <iostream>
#include <random>
#include <stdexcept>
#include <string>
#include <vector>

#include <fmt/core.h>
#include <nlohmann/json.hpp>
#include <rang.hpp>

namespace {

struct Quote {
    std::string text;
    std::string author;
};

std::vector<std::string> WrapText(const std::string& text, const std::size_t maxWidth) {
    std::vector<std::string> lines;
    std::string currentLine;
    std::string currentWord;

    auto flushWord = [&]() {
        if (currentWord.empty()) {
            return;
        }
        if (currentLine.empty()) {
            currentLine = currentWord;
        } else if (currentLine.size() + 1 + currentWord.size() <= maxWidth) {
            currentLine += " " + currentWord;
        } else {
            lines.push_back(currentLine);
            currentLine = currentWord;
        }
        currentWord.clear();
    };

    for (const char ch : text) {
        if (std::isspace(static_cast<unsigned char>(ch)) != 0) {
            flushWord();
        } else {
            currentWord.push_back(ch);
        }
    }
    flushWord();

    if (!currentLine.empty()) {
        lines.push_back(currentLine);
    }

    if (lines.empty()) {
        lines.emplace_back();
    }

    return lines;
}

std::filesystem::path ResolveQuotePath(const char* argv0) {
    namespace fs = std::filesystem;

    const fs::path cwdCandidate = fs::current_path() / "data" / "quotes.json";
    if (fs::exists(cwdCandidate)) {
        return cwdCandidate;
    }

    const fs::path executablePath = fs::absolute(fs::path(argv0)).parent_path();
    const std::vector<fs::path> candidates = {
        executablePath / "data" / "quotes.json",
        executablePath.parent_path() / "data" / "quotes.json",
        executablePath.parent_path().parent_path() / "data" / "quotes.json"
    };

    for (const auto& candidate : candidates) {
        if (fs::exists(candidate)) {
            return candidate;
        }
    }

    throw std::runtime_error("Could not find data/quotes.json.");
}

std::vector<Quote> LoadQuotes(const std::filesystem::path& jsonPath) {
    std::ifstream file(jsonPath);
    if (!file) {
        throw std::runtime_error(fmt::format("Failed to open '{}'.", jsonPath.string()));
    }

    nlohmann::json document;
    file >> document;

    if (!document.is_object() || !document.contains("quotes") || !document["quotes"].is_array()) {
        throw std::runtime_error("Invalid JSON: expected an object with a 'quotes' array.");
    }

    std::vector<Quote> quotes;
    for (const auto& entry : document["quotes"]) {
        if (!entry.is_object() || !entry.contains("text") || !entry.contains("author") ||
            !entry["text"].is_string() || !entry["author"].is_string()) {
            throw std::runtime_error("Invalid quote entry: each quote must have string 'text' and 'author'.");
        }

        quotes.push_back({
            entry["text"].get<std::string>(),
            entry["author"].get<std::string>()
        });
    }

    if (quotes.empty()) {
        throw std::runtime_error("The quotes array is empty.");
    }

    return quotes;
}

const Quote& PickRandomQuote(const std::vector<Quote>& quotes) {
    std::random_device randomDevice;
    std::mt19937 generator(randomDevice());
    std::uniform_int_distribution<std::size_t> distribution(0, quotes.size() - 1);
    return quotes[distribution(generator)];
}

void PrintQuoteCard(const Quote& quote) {
    constexpr std::size_t bodyWidth = 72;
    const std::string border = "+" + std::string(bodyWidth + 2, '-') + "+";
    const std::string title = " Random Software Dev Quote ";
    const std::string authorLine = fmt::format("- {}", quote.author);
    const auto wrappedQuote = WrapText(quote.text, bodyWidth);

    rang::setControlMode(rang::control::Auto);

    std::cout << rang::fgB::blue << border << rang::style::reset << '\n';
    std::cout << rang::fgB::blue << "|"
              << rang::style::bold << rang::fgB::green
              << fmt::format("{:^{}}", title, bodyWidth + 2)
              << rang::style::reset
              << rang::fgB::blue << "|" << rang::style::reset << '\n';
    std::cout << rang::fgB::blue << border << rang::style::reset << '\n';

    for (const auto& line : wrappedQuote) {
        std::cout << rang::fgB::blue << "| "
                  << rang::style::italic << rang::fg::gray
                  << fmt::format("{:<{}}", line, bodyWidth)
                  << rang::style::reset
                  << rang::fgB::blue << " |"
                  << rang::style::reset << '\n';
    }

    std::cout << rang::fgB::blue << "| "
              << fmt::format("{:<{}}", "", bodyWidth)
              << " |" << rang::style::reset << '\n';

    std::cout << rang::fgB::blue << "| "
              << rang::style::bold << rang::fgB::yellow
              << fmt::format("{:>{}}", authorLine, bodyWidth)
              << rang::style::reset
              << rang::fgB::blue << " |"
              << rang::style::reset << '\n';
    std::cout << rang::fgB::blue << border << rang::style::reset << '\n';
}

}  // namespace

int main(const int argc, char* argv[]) {
    if (argc < 1 || argv == nullptr || argv[0] == nullptr) {
        std::cerr << "Unable to resolve executable path." << '\n';
        return 1;
    }

    try {
        const auto quotePath = ResolveQuotePath(argv[0]);
        const auto quotes = LoadQuotes(quotePath);
        PrintQuoteCard(PickRandomQuote(quotes));
    } catch (const std::exception& ex) {
        std::cerr << fmt::format("Error: {}", ex.what()) << '\n';
        return 1;
    }

    return 0;
}

CMakeLists.txt:

cmake_minimum_required(VERSION 3.21)

project(quotecli VERSION 0.1.0 LANGUAGES CXX)

set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)

find_package(nlohmann_json CONFIG REQUIRED)
find_package(fmt CONFIG REQUIRED)
find_package(rang CONFIG REQUIRED)

add_executable(quotecli src/main.cpp)

target_link_libraries(quotecli PRIVATE
    nlohmann_json::nlohmann_json
    fmt::fmt-header-only
    rang::rang
)

if(MSVC)
    target_compile_options(quotecli PRIVATE /W4 /permissive-)
else()
    target_compile_options(quotecli PRIVATE -Wall -Wextra -Wpedantic)
endif()

set_target_properties(quotecli PROPERTIES
    RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin"
)

add_custom_command(TARGET quotecli POST_BUILD
    COMMAND ${CMAKE_COMMAND} -E copy_directory
            "${CMAKE_SOURCE_DIR}/data"
            "$<TARGET_FILE_DIR:quotecli>/data"
    COMMENT "Copying quote data to output directory"
)

CMakePresets.json:

{
  "version": 3,
  "cmakeMinimumRequired": {
    "major": 3,
    "minor": 21,
    "patch": 0
  },
  "configurePresets": [
    {
      "name": "msvc-debug",
      "displayName": "MSVC Debug",
      "generator": "Visual Studio 18 2026",
      "binaryDir": "${sourceDir}\\build\\${presetName}",
      "architecture": {
        "value": "x64"
      },
      "cacheVariables": {
        "CMAKE_TOOLCHAIN_FILE": "${sourceDir}\\vcpkg\\scripts\\buildsystems\\vcpkg.cmake",
        "VCPKG_MANIFEST_MODE": "ON"
      }
    },
    {
      "name": "msvc-release",
      "displayName": "MSVC Release",
      "generator": "Visual Studio 18 2026",
      "binaryDir": "${sourceDir}\\build\\${presetName}",
      "architecture": {
        "value": "x64"
      },
      "cacheVariables": {
        "CMAKE_TOOLCHAIN_FILE": "${sourceDir}\\vcpkg\\scripts\\buildsystems\\vcpkg.cmake",
        "VCPKG_MANIFEST_MODE": "ON"
      }
    }
  ],
  "buildPresets": [
    {
      "name": "build-debug",
      "configurePreset": "msvc-debug",
      "configuration": "Debug"
    },
    {
      "name": "build-release",
      "configurePreset": "msvc-release",
      "configuration": "Release"
    }
  ]
}

vcpkg.json:

{
  "name": "quotecli",
  "version-string": "0.1.0",
  "builtin-baseline": "cd61e1e26a038e82d6550a3ebbe0fbbfe7da78e3",
  "dependencies": [
    "nlohmann-json",
    "fmt",
    "rang"
  ]
}

Optional: improve prompts with a vcpkg-focused skill

You can run this walkthrough with plain GitHub Copilot CLI and no extra skill installed. But if you want to guide and control Copilot’s usage of vcpkg further, especially for more advanced work, you can try out this custom vcpkg skill I wrote. See About agent skills for more information on how to integrate a skill into your Copilot workflow. This skill provides additional guidance for Copilot when dealing with custom registries, continuous integration workflows, and vcpkg troubleshooting issues. Let us know if you have any feedback in the comments below!

For more public examples of community-maintained skills and other custom Copilot workflows, see the awesome-copilot repo.

Note: Treat community skills as guidance accelerators, not official Microsoft product features with a formal support bar. You are also welcome to edit and customize them to your liking within your environment. Copilot CLI can help you write or modify skills on demand.

Try it out and share feedback

Resources:

I also recommend checking out Sinem Akinci’s Pure Virtual C++ session during the event, C++ semantic awareness in the CLI: From Project Load to Code Change, which goes more in-depth into Copilot CLI’s C++ capabilities with the Microsoft C++ language server.

Let us know what you think about Copilot CLI and vcpkg in the comments below!

Category

Topics

Author

Augustin Popa

Product manager on the Microsoft C++ team working on Visual Studio, MSVC Build Tools, and vcpkg.