# Import C++ Standard Library Headers on CMake 3.30

**URL:** https://discourse.cmake.org/t/import-c-standard-library-headers-on-cmake-3-30/11354
**Category:** Code
**Tags:** os:macos, comp:clang
**Created:** [July 30, 2024, 3:40pm UTC](https://discourse.cmake.org/t/import-c-standard-library-headers-on-cmake-3-30/11354 "2024-07-30T15:40:19Z")
**Posts on this page:** 4
**Page:** 1

<div class="post-metadata">

### Author: ![04a](https://discourse.cmake.org/letter_avatar_proxy/v4/letter/0/22d042/32.png) [@04a](https://discourse.cmake.org/u/04a)
#### Post date: [July 30, 2024, 3:40pm UTC](https://discourse.cmake.org/t/import-c-standard-library-headers-on-cmake-3-30/11354/1 "2024-07-30T15:40:20Z")

</div>

Hi,

I’m trying to write a CMakeLists to compile C++ code with `import <...>;`, like:

```cpp
// main.cpp
import <iostream>;
int main() {
  std::cout << "Hello World" << std::endl;
  return 0;
}

```

It can be compiled by a simple command with clang18:

```shell
/usr/local/Cellar/llvm/18.1.8/bin/clang++ -std=c++20 -fmodules main.cpp   

```

But when I tried to write CMakeLists, like this:

```cmake
# File No.1
cmake_minimum_required(VERSION 3.30)
project(Cpp20Sample CXX)
set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)
set(CMAKE_CXX_SCAN_FOR_MODULES ON)
add_executable(main main.cpp)

# File No.2
cmake_minimum_required(VERSION 3.30)
project(Cpp20Sample CXX)
set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)
add_executable(main main.cpp)

# File No.3
cmake_minimum_required(VERSION 3.30)
project(Cpp20Sample CXX)
set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)
set(CMAKE_CXX_SCAN_FOR_MODULES ON)
add_executable(main)
target_sources(main PUBLIC FILE_SET CXX_MODULES FILES main.cpp)

```

All of them failed with a message:

```auto
error: header file <iostream> (aka '/usr/local/Cellar/llvm/18.1.8/bin/../include/c++/v1/iostream') cannot be imported because it is not known to be a header unit

```

---

<div class="post-metadata">

### Author: ![04a](https://discourse.cmake.org/letter_avatar_proxy/v4/letter/0/22d042/32.png) [@04a](https://discourse.cmake.org/u/04a)
#### Post date: [July 30, 2024, 3:42pm UTC](https://discourse.cmake.org/t/import-c-standard-library-headers-on-cmake-3-30/11354/2 "2024-07-30T15:42:24Z")

</div>

When I searching for solutions, I found this:

> [@cmake 3.28 and importing C++ headers in gcc](https://discourse.cmake.org/t/cmake-3-28-and-importing-c-headers-in-gcc/9311/6):
>
> Correct, there is zero support for importing header units at the moment.

Seems it’s still unsolved on CMake 3.30?

---

<div class="post-metadata">

### Author: ![ben.boeckel](https://discourse.cmake.org/letter_avatar_proxy/v4/letter/b/ea5d25/32.png) [@ben.boeckel](https://discourse.cmake.org/u/ben.boeckel)
#### Post date: [July 30, 2024, 5:30pm UTC](https://discourse.cmake.org/t/import-c-standard-library-headers-on-cmake-3-30/11354/3 "2024-07-30T17:30:36Z")

</div>

Yes, header units are pretty much the last thing we can support; all kinds of other patterns show up in header unit support only “more complex”.

---

<div class="post-metadata">

### Author: ![andrej](https://discourse.cmake.org/letter_avatar_proxy/v4/letter/a/d9b06d/32.png) [@andrej](https://discourse.cmake.org/u/andrej)
#### Post date: [September 29, 2024, 9:49pm UTC](https://discourse.cmake.org/t/import-c-standard-library-headers-on-cmake-3-30/11354/4 "2024-09-29T21:49:50Z")

</div>

> [@04a](#):
>
> It can be compiled by a simple command with clang18:
> 
> ```auto
> /usr/local/Cellar/llvm/18.1.8/bin/clang++ -std=c++20 -fmodules main.cpp   
> 
> ```

It can’t, unless the distro ships precompiled header units correctly. Many distros still don’t, e.g. ArchLinux doesn’t. Here’s an example (`hello.c++`):

```cpp
import <iostream>;
int main() { std::cout << "hello world\n"; }

```

```terminal
$ clang++ -std=c++23 -fmodules hello.c++ -o hello
hello.c++:1:8: error: header file <iostream> (aka '/usr/bin/../lib64/gcc/x86_64-pc-linux-gnu/14.2.1/../../../../include/c++/14.2.1/iostream') cannot be imported because it is not known to be a header unit
    1 | import <iostream>;
      | ^
hello.c++:2:14: error: use of undeclared identifier 'std'
    2 | int main() { std::cout << "hello world\n"; }
      | ^
2 errors generated.

```

Not good. However, if we first precompile the header unit manually, [as documented here](https://clang.llvm.org/docs/StandardCPlusPlusModules.html#header-units), then it will work just fine:

```bash
$ clang++ -std=c++23 -xc++-system-header --precompile iostream -o iostream.pcm
$ clang++ -std=c++23 -fmodule-file=iostream.pcm hello.c++ -o hello
$ ./hello
hello world

```

The problem is that (1) many of these command-line flags may be `clang++`-specific and (2) (re)building of standard C++ header units again for each project is not a great approach. Distros should make sure that `.pcm` files are available out-of-the-box.
