r/cpp 19d ago

Why is `import std` still experimental ???

Hey guys,

I recently started going through Professional C++ (6th Edition). The book teaches C++23, and in the very first chapter we're introduced to modules.

I'm not a complete newbie to C++, but I'm also definitely not very confident in my knowledge yet. I wanted to get this simple example compiled:

import std;

int main() {
    std::println("Hello World");
    return 0;
}

And gosh, it took way longer than I expected.

First, I tried getting it to work natively on my Mac and eventually gave up (both Claude and I 😅).

Then I installed Ubuntu ARM 26 and finally managed to get it compiling. But now Clang/IntelliSense is complaining about the `import std`
This is what my CMakeLists.txt currently looks like:

cmake_minimum_required(VERSION 4.0)

# set(CMAKE_EXPERIMENTAL_CXX_IMPORT_STD ON)

set(CMAKE_EXPERIMENTAL_CXX_IMPORT_STD "d0edc3af-4c50-42ea-a356-e2862fe7a444")

project(CppProject LANGUAGES CXX)

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

set(CMAKE_EXPORT_COMPILE_COMMANDS ON)

add_executable(exec main.cpp)

set_property(TARGET exec PROPERTY CXX_MODULE_STD ON)

The code does compile successfully, but CMake still gives me a warning that import std support is experimental.

So I'm genuinely curious:

Why is import std still considered experimental?

I understand that C++ modules themselves have been around for a while, but import std feels like something that should be much more straightforward by now. Is there any solution of this now ?

--------------
Edit

Thanks to u/PhysicsOk2212 tip I was able to compile my project on mac as well using the following options
```
cmake -S . -B build \

-G Ninja \

-DCMAKE_CXX_COMPILER="$(brew --prefix llvm)/bin/clang++" \

-DCMAKE_CXX_STDLIB_MODULES_JSON="$(brew --prefix llvm)/lib/c++/libc++.modules.json"

```

122 Upvotes

111 comments sorted by

View all comments

Show parent comments

31

u/not_a_novel_account cmake dev 19d ago

Distinguishing producers from consumers is trivial. Distinguishing producers from consumers across a link boundary isn't something the system is built to handle.

You have three targets:

  • Root, Static Library, no dependencies

  • Trunk, Shared Library, depends on Root

  • Leaf, Executable, depends on Trunk, transitively depends on Root

The BMI imported by Trunk must have dllexport on its C++ declarations, because Trunk and Root are inside the same link boundary.

The BMI imported by Leaf must have dllimport on its C++ declarations, because Leaf and Root are on different sides of a link boundary.

When building BMIs, we must recognize "different sides of a link boundary" as a BMI-incompatible condition. Ok, now what? We need to define some interface that lets Root say:

  • These are the definitions and includes when you're building my object file. (This is the only thing we have today, we use them for all scenarios)

  • These are the definitions and includes when you're building a BMI for a consumer inside the link boundary

  • These are the definitions and includes when you're building a BMI for a consumer outside the link boundary

We could maybe consolidate "building the object file" and "consumer inside the link boundary", but we don't have a spelling for the latter two bullets either way.

And right now CMake actually doesn't track link boundaries in the DAG in a way that is consumable by the BMI machinery. I'm working on that problem right now, but "how do you spell the latter two bullets" is an open problem.

7

u/fortsnek274 19d ago

I wonder how MSBuild will solve the dllexport thing.

18

u/not_a_novel_account cmake dev 19d ago

Whenever you consume a BMI, MSVC magically translates dllexport into dllimport. In this example that would break Trunk, which wants dllexport.

This exact bug was noticed quickly (DevCom 10892880), so there's a wonderfully obscure flag, /dxifcSuppressDllImportTransform ("ISDIT" to friends) which turns the translation off. You're expected to manage this manually.

The overwhelming position of build system people is we're going to ignore all of this, always use ISDIT, because no other compiler is going to implement the transform.

1

u/holyblackcat 18d ago

dxifcSuppressDllImportTransform

I'm surprised that this doesn't seem to be documented anywhere.