# clang-tidy + cxx\_modules

**URL:** https://discourse.cmake.org/t/clang-tidy-cxx-modules/7938
**Category:** Usage
**Created:** [April 20, 2023, 9:39am UTC](https://discourse.cmake.org/t/clang-tidy-cxx-modules/7938 "2023-04-20T09:39:35Z")
**Posts on this page:** 12
**Page:** 1

<div class="post-metadata">

### Author: ![Lecris](https://discourse.cmake.org/user_avatar/discourse.cmake.org/lecris/32/3193_2.png) [@Lecris](https://discourse.cmake.org/u/Lecris)
#### Post date: [April 20, 2023, 9:39am UTC](https://discourse.cmake.org/t/clang-tidy-cxx-modules/7938/1 "2023-04-20T09:39:35Z")

</div>

I have tried to enable the clang-tidy on cxx\_module project using `CMAKE_CLANG_TIDY`. But it seems to fail and I don’t know if it is an issue in how cmake calls it or an issue on clang-tidy side. Here is a mwe:

```cmake
# CMakeLists.txt
cmake_minimum_required(VERSION 3.26)
project(clang-tidy-issue
		LANGUAGES CXX)

set(CMAKE_CXX_STANDARD 20)
set(CMAKE_EXPERIMENTAL_CXX_MODULE_CMAKE_API 2182bf5c-ef0d-489a-91da-49dbc3090d2a)
set(CMAKE_EXPERIMENTAL_CXX_MODULE_DYNDEP TRUE)
set(CMAKE_CXX_EXTENSIONS OFF)
set(CMAKE_EXPERIMENTAL_CXX_MODULE_MAP_FORMAT clang)
set(CMAKE_CXX_CLANG_TIDY "clang-tidy;-checks=*")

add_library(test_library)
target_sources(test_library PUBLIC
		FILE_SET cxx_modules
		TYPE CXX_MODULES
		FILES
		test_module.ixx
		)

```

```cpp
// test_module.ixx
module;

#include <string>

export module test_module;

export namespace test_module {
	consteval std::string_view version(){
		return "0.0.0";
	}
}

```

---

<div class="post-metadata">

### Author: ![ClausKlein](https://discourse.cmake.org/user_avatar/discourse.cmake.org/clausklein/32/352_2.png) [@ClausKlein](https://discourse.cmake.org/u/ClausKlein)
#### Post date: [April 20, 2023, 9:02pm UTC](https://discourse.cmake.org/t/clang-tidy-cxx-modules/7938/2 "2023-04-20T21:02:54Z")

</div>

see [C++20 modules API example - #3 by ClausKlein](https://discourse.cmake.org/t/c-20-modules-api-example/7303/3)

---

<div class="post-metadata">

### Author: ![Lecris](https://discourse.cmake.org/user_avatar/discourse.cmake.org/lecris/32/3193_2.png) [@Lecris](https://discourse.cmake.org/u/Lecris)
#### Post date: [April 20, 2023, 9:38pm UTC](https://discourse.cmake.org/t/clang-tidy-cxx-modules/7938/3 "2023-04-20T21:38:58Z")

</div>

So it’s supposed to be:

```cmake
set(CMAKE_CXX_CLANG_TIDY "clang-tidy;-checks=*,-llvmlibc-*,-fuchsia-*,-cppcoreguidelines-init-variables")

```

Maybe the missing llvmlibc-\*?

---

<div class="post-metadata">

### Author: ![buildSystemPerson](https://discourse.cmake.org/user_avatar/discourse.cmake.org/buildsystemperson/32/2851_2.png) [@buildSystemPerson](https://discourse.cmake.org/u/buildSystemPerson)
#### Post date: [April 20, 2023, 10:58pm UTC](https://discourse.cmake.org/t/clang-tidy-cxx-modules/7938/4 "2023-04-20T22:58:30Z")

</div>

```auto
# First find clang-tidy, this also allows users to provide hints
find_program(CLANG_TIDY NAMES clang-tidy)

# Then I have this which is essentially calls clang-tidy with warnings as errors (For CI)
set(CMAKE_CXX_CLANG_TIDY "${CLANG_TIDY};")

```

clang-tidy then finds the .clang-tidy file in my build without issue. So I don’t have to list all the checks in the CMake code.

From the clang-tidy docs:

```auto
# clang-tidy attempts to read configuration for each source file from a
# .clang-tidy file located in the closest parent directory of the source
# file. The .clang-tidy file is specified in YAML format. If any configuration
# options have a corresponding command-line option, command-line option takes precedence.

```

---

<div class="post-metadata">

### Author: ![ClausKlein](https://discourse.cmake.org/user_avatar/discourse.cmake.org/clausklein/32/352_2.png) [@ClausKlein](https://discourse.cmake.org/u/ClausKlein)
#### Post date: [April 21, 2023, 5:19am UTC](https://discourse.cmake.org/t/clang-tidy-cxx-modules/7938/5 "2023-04-21T05:19:44Z")

</div>

The notes above are right, but it is a _standalone working example_ only.

The real question is why does clang-tidy ends with an `clang-diagnostic-error`:

```auto
bash-3.2$ ninja -C build/
ninja: Entering directory `build/'
[0/1] Re-running CMake...
CMake Warning (dev) at CMakeLists.txt:70 (target_sources):
  CMake's C++ module support is experimental. It is meant only for
  experimentation and feedback to CMake developers.
This warning is for project developers. Use -Wno-dev to suppress it.

-- Configuring done (0.1s)
CMake Warning (dev):
  C++20 modules support via CMAKE_EXPERIMENTAL_CXX_MODULE_DYNDEP is
  experimental. It is meant only for compiler developers to try.
This warning is for project developers. Use -Wno-dev to suppress it.

-- Generating done (0.0s)
-- Build files have been written to: /Users/clausklein/Workspace/cpp/cxx20/test/build
[4/8] Building CXX object CMakeFiles/foo.dir/foo.cxx.o
/Users/clausklein/Workspace/cpp/cxx20/test/foo.cxx:8:14: warning: class 'foo' defines a non-default destructor but does not define a copy constructor, a copy assignment operator, a move constructor or a move assignment operator [cppcoreguidelines-special-member-functions,hicpp-special-member-functions]
export class foo {
             ^
/Users/clausklein/Workspace/cpp/cxx20/test/foo.cxx:8:14: warning: invalid case style for class 'foo' [readability-identifier-naming]
export class foo {
             ^~~
             Foo
/Users/clausklein/Workspace/cpp/cxx20/test/foo.cxx:15:11: warning: method 'helloworld' can be made static [readability-convert-member-functions-to-static]
void foo::helloworld() { std::cout << "hello world\n"; }
          ^
[7/8] Building CXX object CMakeFiles/hello.dir/main.cxx.o
FAILED: CMakeFiles/hello.dir/main.cxx.o 
/usr/local/Cellar/cmake/3.26.3/bin/cmake -E __run_co_compile --tidy="clang-tidy;-checks=*,-llvmlibc-*,-fuchsia-*,-cppcoreguidelines-init-variables;--extra-arg-before=--driver-mode=g++" --source=/Users/clausklein/Workspace/cpp/cxx20/test/main.cxx -- /usr/local/opt/llvm/bin/clang++ -std=c++20 -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX13.3.sdk -MD -MT CMakeFiles/hello.dir/main.cxx.o -MF CMakeFiles/hello.dir/main.cxx.o.d @CMakeFiles/hello.dir/main.cxx.o.modmap -o CMakeFiles/hello.dir/main.cxx.o -c /Users/clausklein/Workspace/cpp/cxx20/test/main.cxx
/Users/clausklein/Workspace/cpp/cxx20/test/main.cxx:1:8: error: module 'foo' not found [clang-diagnostic-error]
import foo;
~~~~~~~^~~
1 error generated.
Error while processing /Users/clausklein/Workspace/cpp/cxx20/test/main.cxx.
Found compiler error(s).
ninja: build stopped: subcommand failed.
bash-3.2$ 

```

---

<div class="post-metadata">

### Author: ![ClausKlein](https://discourse.cmake.org/user_avatar/discourse.cmake.org/clausklein/32/352_2.png) [@ClausKlein](https://discourse.cmake.org/u/ClausKlein)
#### Post date: [April 21, 2023, 7:42am UTC](https://discourse.cmake.org/t/clang-tidy-cxx-modules/7938/6 "2023-04-21T07:42:15Z")

</div>

## I got it!

`-fprebuilt-module-path=CMakeFiles/foo.dir/` must be set:

```bash
bash-3.2$ pwd
/Users/clausklein/Workspace/cpp/cxx20/test/build

bash-3.2$ /usr/local/opt/llvm/bin/clang-tidy -extra-arg=-fprebuilt-module-path=CMakeFiles/foo.dir/ -p=/Users/clausklein/Workspace/cpp/cxx20/test/build /Users/clausklein/Workspace/cpp/cxx20/test/main.cxx
77759 warnings generated.
Suppressed 77759 warnings (77759 in non-user code).
Use -header-filter=.* to display errors from all non-system headers. Use -system-headers to display errors from system headers as well.
/usr/local/opt/llvm/bin/clang-tidy -extra-arg=-fprebuilt-module-path=CMakeFiles/foo.dir/ -p=/Users/clausklein/Workspace/cpp/cxx20/test/build /Users/clausklein/Workspace/cpp/cxx20/test/foo.cxx
/Users/clausklein/Workspace/cpp/cxx20/test/foo.cxx:15:11: warning: method 'helloworld' can be made static [readability-convert-member-functions-to-static]
void foo::helloworld() { std::cout << "hello world\n"; }
          ^
85168 warnings generated.
Suppressed 85167 warnings (85167 in non-user code).
Use -header-filter=.* to display errors from all non-system headers. Use -system-headers to display errors from system headers as well.
bash-3.2$ 

```

---

<div class="post-metadata">

### Author: ![Lecris](https://discourse.cmake.org/user_avatar/discourse.cmake.org/lecris/32/3193_2.png) [@Lecris](https://discourse.cmake.org/u/Lecris)
#### Post date: [April 21, 2023, 7:45am UTC](https://discourse.cmake.org/t/clang-tidy-cxx-modules/7938/7 "2023-04-21T07:45:52Z")

</div>

I have tried out these approaches and none of them worked. I realized I forgot to add the error encountered so:

```auto
====================[Build | test_library | Debug]============================
/usr/bin/cmake --build /clang-tidy-issue/cmake-build-debug --target test_library -j 14
[1/2] Building CXX object CMakeFiles/test_library.dir/test_module.ixx.o
FAILED: CMakeFiles/test_library.dir/test_module.ixx.o CMakeFiles/test_library.dir/test_module.pcm 
/usr/bin/cmake -E __run_co_compile --tidy="clang-tidy;-checks=*,-llvmlibc-*,-fuchsia-*,-cppcoreguidelines-init-variables;--extra-arg-before=--driver-mode=g++" --source=/clang-tidy-issue/test_module.ixx -- /usr/bin/clang++ -g -std=c++20 -fcolor-diagnostics -MD -MT CMakeFiles/test_library.dir/test_module.ixx.o -MF CMakeFiles/test_library.dir/test_module.ixx.o.d @CMakeFiles/test_library.dir/test_module.ixx.o.modmap -o CMakeFiles/test_library.dir/test_module.ixx.o -c /clang-tidy-issue/test_module.ixx
error: unable to handle compilation, expected exactly one compiler job in '' [clang-diagnostic-error]
warning: /home/lecris/CLionProjects/clang-tidy-issue/test_module.ixx: 'linker' input unused [clang-diagnostic-unused-command-line-argument]
warning: argument unused during compilation: '-c' [clang-diagnostic-unused-command-line-argument]
warning: argument unused during compilation: '-g' [clang-diagnostic-unused-command-line-argument]
Error while processing /clang-tidy-issue/test_module.ixx.
Found compiler error(s).
ninja: build stopped: subcommand failed.

```

Details of setup:

- Fedora 38
- `clang-tidy`: 16.0.0
- `cmake`: 3.26.3

---

<div class="post-metadata">

### Author: ![Lecris](https://discourse.cmake.org/user_avatar/discourse.cmake.org/lecris/32/3193_2.png) [@Lecris](https://discourse.cmake.org/u/Lecris)
#### Post date: [April 21, 2023, 8:03am UTC](https://discourse.cmake.org/t/clang-tidy-cxx-modules/7938/8 "2023-04-21T08:03:31Z")

</div>

It seems to be an issue with the file name suffix `.ixx`, `.cxx` seems to work sometimes

---

<div class="post-metadata">

### Author: ![ClausKlein](https://discourse.cmake.org/user_avatar/discourse.cmake.org/clausklein/32/352_2.png) [@ClausKlein](https://discourse.cmake.org/u/ClausKlein)
#### Post date: [April 21, 2023, 8:04am UTC](https://discourse.cmake.org/t/clang-tidy-cxx-modules/7938/9 "2023-04-21T08:04:03Z")

</div>

Dit you use my updated `CMakeLists.txt`?

---

<div class="post-metadata">

### Author: ![Lecris](https://discourse.cmake.org/user_avatar/discourse.cmake.org/lecris/32/3193_2.png) [@Lecris](https://discourse.cmake.org/u/Lecris)
#### Post date: [April 21, 2023, 8:05am UTC](https://discourse.cmake.org/t/clang-tidy-cxx-modules/7938/10 "2023-04-21T08:05:43Z")

</div>

Yes, I have tested your cmakelists and it worked perfectly fine, which puzzled me. But I managed to systematically reproduce the issue when I use `.ixx` suffix.

It seems the extensions are not in `clnag-tidy 16` yet:

> <https://github.com/llvm/llvm-project/commit/5b37cddff8e0140420ad776066529cf8f41d64d2>
>
> Re-introduce the patch that was reverted previously.
> In the first attempt, the c…hecks would not be able to
> read from the global option, since getLocalOrGlobal
> only works with string types. Additional logic is needed
> in order to support both use cases in the transition
> period. All that logic will be removed when the local
> options are fully removed.
> 
> We have a number of checks designed to analyze problems
> in header files only, for example:
> 
> bugprone-suspicious-include
> google-build-namespaces
> llvm-header-guard
> misc-definitions-in-header
> ...
> 
> All these checks duplicate the same logic and options
> to determine whether a location is placed in the main
> source file or in the header. More checks are coming
> up with similar requirements.
> 
> Thus, to remove duplication, let's move this option
> to the top-level configuration of clang-tidy (since
> it's something all checks should share).
> 
> Add a deprecation notice for all checks that use the
> local option, prompting to update to the global option.
> 
> Differential Revision: https://reviews.llvm.org/D142655

---

<div class="post-metadata">

### Author: ![Lecris](https://discourse.cmake.org/user_avatar/discourse.cmake.org/lecris/32/3193_2.png) [@Lecris](https://discourse.cmake.org/u/Lecris)
#### Post date: [April 21, 2023, 12:59pm UTC](https://discourse.cmake.org/t/clang-tidy-cxx-modules/7938/11 "2023-04-21T12:59:34Z")

</div>

I have tested that commit and that doesn’t solve the issue either ☹

---

<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: [April 24, 2023, 6:42pm UTC](https://discourse.cmake.org/t/clang-tidy-cxx-modules/7938/12 "2023-04-24T18:42:17Z")

</div>

See also discussion here:

> [@How to control the location of the c++20 Binary Module Interface (BMI) output directory?](https://discourse.cmake.org/t/how-to-control-the-location-of-the-c-20-binary-module-interface-bmi-output-directory/7968/4):
>
> This has not been worked on; clang-tidy may need to learn how to read the modmap file clang will use (though it should exist by the time we’re compiling… The fact that it doesn’t work with compile\_commands.json when the @modmap arguments are there tells me that clang-tidy is ignoring something… Certainly not share as they are arch-dependent. I suspect where they go will be a Linux distro discussion in the FHS umbrella, Apple will just decree for itself, and Microsoft will do Windows things. …
