C++ Modules in CMake with Visual Studio

Will Buik

We’ve seen a lot of excitement around C++ modules since we announced support in the Microsoft C++ compiler and Visual Studio. Ever since, the community has been asking us when CMake support was coming. I am happy to announce that Visual Studio 2022 17.2 Preview 2 has experimental support for C++ modules in CMake projects. One caveat for this early support, is that you must use the Visual Studio (MSBuild) generator. If you want to try it out, you can download the latest preview of Visual Studio today. We are looking forward to hearing your feedback about how modules work in your CMake projects.

C++ modules are a new feature in C++20. They can help you compartmentalize your code, speed up build times, and they work seamlessly, side-by-side with your existing code. To learn more, I would recommend checking A Tour of C++ Modules in Visual Studio. That post explores the details of how and when to use modules and some of the ways Visual Studio can help you do it.

For an even deeper dive into modules, you can also explore the following series:

Getting Started with Modules and CMake

While CMake support for modules in Visual Studio is still experimental, it is straightforward to start using it. You don’t need to do anything special in your CMake project files. Just make sure you have enabled the C++20 language standard. Starting in this preview, our CMake project template will do that for you, but if you are working with an existing project you will need to add this to your CMakeLists.txt:

set_property(TARGET $TargetName PROPERTY CXX_STANDARD 20)

Note: Enabling C++20 requires CMake 3.12 or higher. Visual Studio ships with the latest version of CMake, but this may be a consideration if you use this project across operating systems or need to use an older version of CMake.

You will also need to make sure you are using the Visual Studio generator with CMake. Support for other generators, such as Ninja, is planned but it isn’t available yet. Ninja is the default generator when working with CMake projects in Visual Studio so you will need to modify your project’s CMakePresets.json or CMakeSettings.json file to change this.

CMake Presets:

If your project is using CMake Presets, in CMakePresets.json, find the “windows-base” configure preset. It will have a “generator” property that is most likely set to “Ninja”. Update it to this:

  "version": 3,
  "configurePresets": [ {
    "name": "windows-base",
    "hidden": true,
    "generator": "Visual Studio 17 2022",

CMake Settings:

If your project is using CMake Settings, you can open the CMakeSettings.json editor and change the Generator setting (under Advanced) to “Visual Studio 17 2022:”

CMake Settings > Advanced > CMake generator

You will need to do this for each of your project’s configurations.

And that’s it, once the Visual Studio generator is selected and the C++20 language standard is enabled for your target you can use modules in your project.

Creating Modules in a CMake Project

To add a module to your project, just right click on any folder and select “Add New Item:”

CMake Context Menu > Add > Add New Item...

And select the “C++ Module Interface Unit (.ixx)” template in in the “Visual C++” category:

New File > Visual C++ > C++ Module Interface Unit (.ixx)

If you are using the Targets View, it is even easier. Just click “Add -> New Module…” in the context menu on any target:

CMake Targets View Context Menu > Add > New Module...

Exporting and Using Modules

Once you have created a Module interface (.ixx) file, you can export functions, classes, and structs. The example below defines a simple module called Printers and exports a single struct:

// Printers.ixx
// The .ixx extension lets the build system know this file contains
// a module interface.

// Begin global module fragment.

// Headers included in the global module fragment (between "module;" and
// "export module Printers;") can be used by the module implementation but
// are not exported. These included headers are invisible to translation
// units that import the Printers module.
#include <iostream>

// Creates the Printers module. This can be imported into other translation
// units with "import Printers;" Any items marked with the export keyword
// will be available in translation units that import the Printers module.
export module Printers;

// This only applies to this module's translation unit. It does not leak
// into translation units that import the Printers module.
using namespace std;

// These constants are not exported, they are invisible from translation
// units that import the Printer module.
const string default_spacer = " ";
const string default_separator = ",\n";

// SimplePrinter is exported and accessible to any code that imports the
// Printers module.
export struct SimplePrinter
    string element_spacer;
    string separator;

    void print_element(int e)
        std::cout << e << element_spacer;

    void print_separator()
        std::cout << separator;

// Exports the function get_default_printer.
// This is accessible from translation units that import the Printers module.
export SimplePrinter get_default_printer()
    return SimplePrinter {
        .element_spacer = default_spacer,
        .seperator = default_seperator

Once you define the module, other source files and module interfaces can consume it with the import keyword. It is possible to import any modules declared in the current target or any of its imports. For example, “PrintVector.cpp” below uses the Printers module we defined above:

// PrintVector.cpp

// Conventional #includes and module imports can be freely mixed.
#include <vector>

// Import the Printers module defined in Printers.ixx.
import Printers;

using namespace std;

void print_vector(const vector &list)
    // SimplePrinter and get_default_printer are imported from the
    // Printers module.
    SimplePrinter printer = get_default_printer();

    for (auto i : list) {

You can do a lot with C++ modules. To learn more, I would recommend reading A Tour of C++ Modules in Visual Studio which goes into much more detail about how to use modules. For instance, it is possible to split module interfaces from their implementations. That post has been updated with some of the latest details about using modules with CMake.


If you are interested in trying out C++ modules in your own CMake projects, please download the latest Visual Studio Preview. Try it out and let us know if you have any questions or feedback. If you find any issues or have a suggestion, the best way to reach out to us is to Report a Problem.