# Undefined Reference error using modules in C++23 with clang and cmake

**URL:** https://discourse.cmake.org/t/undefined-reference-error-using-modules-in-c-23-with-clang-and-cmake/14045
**Category:** Code
**Tags:** os:linux, gen:ninja
**Created:** [May 4, 2025, 11:47pm UTC](https://discourse.cmake.org/t/undefined-reference-error-using-modules-in-c-23-with-clang-and-cmake/14045 "2025-05-04T23:47:18Z")
**Posts on this page:** 5
**Page:** 1

<div class="post-metadata">

### Author: ![saurabh](https://discourse.cmake.org/letter_avatar_proxy/v4/letter/s/ee7513/32.png) [@saurabh](https://discourse.cmake.org/u/saurabh)
#### Post date: [May 4, 2025, 11:47pm UTC](https://discourse.cmake.org/t/undefined-reference-error-using-modules-in-c-23-with-clang-and-cmake/14045/1 "2025-05-04T23:47:18Z")

</div>

Hello,

I’m getting started with C++23 modules and trying to use them in a personal project.

The plan is to create an executable for the entire project, which would contain the output of all unit tests.

Each source `cpp` file has an implementation and a unit test. The module `cppm` file exports unit tests from all source files in the same directory.

These exported unit tests are then called in `main.cpp`.

The project layout is:

```auto
.
|---- CMakeLists.txt
|---- src
| |---- foo
| |---- add.cpp
| |---- subtract.cpp
| |---- foo.cppm
|
|---- main.cpp

```

As I make more progress on this project, there will be other directories in `src/` similar to `foo/`.

Below are the file contents (collapsing to improve overview)

> **\`src/foo/add.cpp\` (\`subtract.cpp\` is similar)**
>
> ```cpp
> import std;
> #include <cassert>
> 
> class AddNumbers {
> public:
> int add(int a, int b) {
> return a + b;
> }
> };
> 
> void testAddNumbers() {
> AddNumbers solution;
> 
> int result = solution.add(2, 2);
> int expected = 4;
> 
> assert(result == expected); // Assert the result
> }
> 
> ```

> **\`src/foo/foo.cppm\`**
>
> ```auto
> export module foo;
> 
> export void testAddNumbers();
> export void testSubtractNumbers();
> 
> ```

> **\`src/main.cpp\`**
>
> ```auto
> import foo;
> 
> int main() {
> testAddNumbers();
> testSubtractNumbers();
> 
> return 0;
> }
> 
> ```

> **\`CMakeLists.txt\`**
>
> ```auto
> cmake_minimum_required(VERSION 3.31)
> 
> set(CMAKE_EXPERIMENTAL_CXX_IMPORT_STD "0e5b6991-d74f-4b3d-a41c-cf096e0b2508")
> set(CMAKE_CXX_MODULE_STD ON)
> set(CXXFLAGS "-Wall -Werror -O2 -Wno-error=sign-compare -Wno-pre-c++20-compat -std=c++23 -stdlib=libc++")
> set(CMAKE_CXX_FLAGS "${CXXFLAGS}")
> set(CMAKE_CXX_COMPILER clang++)
> 
> project(testmod VERSION 1.0 LANGUAGES CXX)
> 
> set(CMAKE_CXX_STANDARD 23)
> set(CMAKE_CXX_STANDARD_REQUIRED YES)
> set(CMAKE_CXX_EXTENSIONS ON)
> 
> add_executable(testmod)
> target_sources(testmod
> PUBLIC
> src/main.cpp
> )
> target_sources(testmod
> PUBLIC
> FILE_SET testmods TYPE CXX_MODULES
> BASE_DIRS
> ${PROJECT_SOURCE_DIR}
> FILES
> src/foo/foo.cppm
> )
> 
> ```

I’m compiling and building this project like:

```auto
cmake -G Ninja -S . -B build
ninja -C build

```

and on the second command I’m getting an error:

```auto
main.cpp:(.text+0x2): undefined reference to `testAddNumbers@foo()'
main.cpp:(.text+0x7): undefined reference to `testSubtractNumbers@foo()'

```

* * *

How can get the project to work correctly ?

---

<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: [May 5, 2025, 11:45am UTC](https://discourse.cmake.org/t/undefined-reference-error-using-modules-in-c-23-with-clang-and-cmake/14045/2 "2025-05-05T11:45:22Z")

</div>

Add a `module foo;` to the top of `add.cpp` and `subtract.cpp` without this, the compiler has no idea that the defined `testAddNumbers` symbol is part of the `foo` module and instead just makes a global module symbol instead.

---

<div class="post-metadata">

### Author: ![saurabh](https://discourse.cmake.org/letter_avatar_proxy/v4/letter/s/ee7513/32.png) [@saurabh](https://discourse.cmake.org/u/saurabh)
#### Post date: [May 6, 2025, 6:48pm UTC](https://discourse.cmake.org/t/undefined-reference-error-using-modules-in-c-23-with-clang-and-cmake/14045/3 "2025-05-06T18:48:30Z")

</div>

I removed the `build/` directory and ran

```auto
cmake -G Ninja -S . -B build
ninja -C build

```

the second command fails with:

```auto
ninja: Entering directory `build'
[12/12] Linking CXX executable testmod
FAILED: testmod 
: && /usr/bin/clang++ -Wall -Werror -O2 -Wno-error=sign-compare -Wno-pre-c++20-compat -std=c++23 -stdlib=libc++ -Xlinker --dependency-file=CMakeFiles/testmod.dir/link.d CMakeFiles/testmod.dir/src/main.cpp.o CMakeFiles/testmod.dir/src/foo/foo.cppm.o -o testmod lib__cmake_cxx23.a && :
/usr/bin/ld: CMakeFiles/testmod.dir/src/main.cpp.o: in function `main':
main.cpp:(.text+0x2): undefined reference to `testAddNumbers@foo()'
/usr/bin/ld: main.cpp:(.text+0x7): undefined reference to `testSubtractNumbers@foo()'
clang++: error: linker command failed with exit code 1 (use -v to see invocation)
ninja: build stopped: subcommand failed.

```

---

<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: [May 7, 2025, 5:49am UTC](https://discourse.cmake.org/t/undefined-reference-error-using-modules-in-c-23-with-clang-and-cmake/14045/4 "2025-05-07T05:49:26Z")

</div>

Did you change the source at all?

---

<div class="post-metadata">

### Author: ![saurabh](https://discourse.cmake.org/letter_avatar_proxy/v4/letter/s/ee7513/32.png) [@saurabh](https://discourse.cmake.org/u/saurabh)
#### Post date: [May 7, 2025, 10:42pm UTC](https://discourse.cmake.org/t/undefined-reference-error-using-modules-in-c-23-with-clang-and-cmake/14045/5 "2025-05-07T22:42:51Z")

</div>

Nope, apart from your suggestion there are no other changes.

Here’s the complete trace:

> **Terminal**
>
> ```auto
> bingletiger@kdefw ~/Desktop/test
> %
> bingletiger@kdefw ~/Desktop/test
> % pwd
> /home/bingletiger/Desktop/test
> bingletiger@kdefw ~/Desktop/test
> %
> bingletiger@kdefw ~/Desktop/test
> %
> bingletiger@kdefw ~/Desktop/test
> % tree .
> .
> ├── CMakeLists.txt
> └── src
> ├── foo
> │ ├── add.cpp
> │ ├── foo.cppm
> │ └── subtract.cpp
> └── main.cpp
> 
> 3 directories, 5 files
> bingletiger@kdefw ~/Desktop/test
> %
> bingletiger@kdefw ~/Desktop/test
> %
> bingletiger@kdefw ~/Desktop/test
> % cat CMakeLists.txt
> cmake_minimum_required(VERSION 3.31)
> 
> set(CMAKE_EXPERIMENTAL_CXX_IMPORT_STD "0e5b6991-d74f-4b3d-a41c-cf096e0b2508")
> set(CMAKE_CXX_MODULE_STD ON)
> set(CXXFLAGS "-Wall -Werror -O2 -Wno-error=sign-compare -Wno-pre-c++20-compat -std=c++23 -stdlib=libc++")
> set(CMAKE_CXX_FLAGS "${CXXFLAGS}")
> set(CMAKE_CXX_COMPILER clang++)
> 
> project(testmod VERSION 1.0 LANGUAGES CXX)
> 
> set(CMAKE_CXX_STANDARD 23)
> set(CMAKE_CXX_STANDARD_REQUIRED YES)
> set(CMAKE_CXX_EXTENSIONS ON)
> 
> add_executable(testmod)
> target_sources(testmod
> PUBLIC
> src/main.cpp
> )
> target_sources(testmod
> PUBLIC
> FILE_SET testmods TYPE CXX_MODULES
> BASE_DIRS
> ${PROJECT_SOURCE_DIR}
> FILES
> src/foo/foo.cppm
> )
> bingletiger@kdefw ~/Desktop/test
> %
> bingletiger@kdefw ~/Desktop/test
> % cat src/main.cpp
> import foo;
> 
> int main()
> {
> testAddNumbers();
> testSubtractNumbers();
> 
> return 0;
> }
> bingletiger@kdefw ~/Desktop/test
> %
> bingletiger@kdefw ~/Desktop/test
> % cat src/foo/add.cpp
> module foo;
> 
> import std;
> #include <cassert>
> 
> class AddNumbers {
> public:
> int add(int a, int b)
> {
> return a + b;
> }
> };
> 
> void testAddNumbers()
> {
> AddNumbers solution;
> 
> int result = solution.add(2, 2);
> int expected = 4;
> 
> assert(result == expected); // Assert the result
> }
> bingletiger@kdefw ~/Desktop/test
> %
> bingletiger@kdefw ~/Desktop/test
> % cat src/foo/subtract.cpp
> module foo;
> 
> import std;
> #include <cassert>
> 
> class SubtractNumbers {
> public:
> int subtract(int a, int b)
> {
> return a + b;
> }
> };
> 
> void testSubtractNumbers()
> {
> SubtractNumbers solution;
> 
> int result = solution.subtract(2, 2);
> int expected = 0;
> 
> assert(result == expected); // Assert the result
> }
> bingletiger@kdefw ~/Desktop/test
> %
> bingletiger@kdefw ~/Desktop/test
> % cat src/foo/foo.cppm
> export module foo;
> 
> export void testAddNumbers();
> export void testSubtractNumbers();
> bingletiger@kdefw ~/Desktop/test
> %
> bingletiger@kdefw ~/Desktop/test
> %
> bingletiger@kdefw ~/Desktop/test
> %
> bingletiger@kdefw ~/Desktop/test
> % cmake -G Ninja -S . -B build
> -- The CXX compiler identification is Clang 20.1.3
> -- Detecting CXX compiler ABI info
> -- Detecting CXX compiler ABI info - done
> -- Check for working CXX compiler: /usr/bin/clang++ - skipped
> -- Detecting CXX compile features
> CMake Warning (dev) at /usr/share/cmake/Modules/Compiler/CMakeCommonCompilerMacros.cmake:248 (cmake_language):
> CMake's support for `import std;` in C++23 and newer is experimental. It
> is meant only for experimentation and feedback to CMake developers.
> Call Stack (most recent call first):
> /usr/share/cmake/Modules/CMakeDetermineCompilerSupport.cmake:113 (cmake_create_cxx_import_std)
> /usr/share/cmake/Modules/CMakeTestCXXCompiler.cmake:83 (CMAKE_DETERMINE_COMPILER_SUPPORT)
> CMakeLists.txt:9 (project)
> This warning is for project developers. Use -Wno-dev to suppress it.
> 
> -- Detecting CXX compile features - done
> -- Configuring done (0.3s)
> -- Generating done (0.0s)
> -- Build files have been written to: /home/bingletiger/Desktop/test/build
> bingletiger@kdefw ~/Desktop/test
> %
> bingletiger@kdefw ~/Desktop/test
> %
> bingletiger@kdefw ~/Desktop/test
> % ninja -C build
> ninja: Entering directory `build'
> [12/12] Linking CXX executable testmod
> FAILED: testmod
> : && /usr/bin/clang++ -Wall -Werror -O2 -Wno-error=sign-compare -Wno-pre-c++20-compat -std=c++23 -stdlib=libc++ -Xlinker --dependency-file=CMakeFiles/testmod.dir/link.dCMakeFiles/testmod.dir/src/main.cpp.o CMakeFiles/testmod.dir/src/foo/foo.cppm.o -o testmod lib__cmake_cxx23.a && :
> /usr/bin/ld: CMakeFiles/testmod.dir/src/main.cpp.o: in function `main':
> main.cpp:(.text+0x2): undefined reference to `testAddNumbers@foo()'
> /usr/bin/ld: main.cpp:(.text+0x7): undefined reference to `testSubtractNumbers@foo()'
> clang++: error: linker command failed with exit code 1 (use -v to see invocation)
> ninja: build stopped: subcommand failed.
> bingletiger@kdefw ~/Desktop/test
> %
> bingletiger@kdefw ~/Desktop/test
> %
> 
> ```
