Skip to content

clang-tidy does not recognize "cmake_pch.hxx.pch" as valid PCH file

clang-tidy expects precompiled header with .pch extension (or so I think), but with g++ compiler under Linux, the output of target_precompile_headers() is cmake_pch.hxx.gch.

Tried using the undocumented CMAKE_PCH_EXTENSION variable to force .pch instead of .gch, but then it will become cmake_pch.hxx.pch instead of cmake_pch.pch. Ideally, I would be able to control the full output name of the generated precompiled header in order to clang-tidy not rejecting it as an invalid PCH.

CMake version: 3.18.4 on Ubuntu 18.04.5 LTS (Updated to cmake version 3.20.1, and issue persists there too) gcc version 7.5.0 (Ubuntu 7.5.0-3ubuntu1~18.04)

Top-level CMakeLists.txt:

cmake_minimum_required(VERSION 3.17)
project(myproject)

# Make sure clang-tidy setup is done before creating the CMake targets.
# https://gitlab.kitware.com/cmake/cmake/-/issues/16869#note_264884
find_program(
    CLANG_TIDY_EXE
    NAMES clang-tidy-10 clang-tidy-9 clang-tidy-8 clang-tidy-7 clang-tidy-6.0 clang-tidy
)
if(NOT CLANG_TIDY_EXE)
    message(STATUS "clang-tidy not found.")
else()
    message(STATUS "clang-tidy found: ${CLANG_TIDY_EXE}")
    set(CMAKE_CXX_CLANG_TIDY "${CLANG_TIDY_EXE}")
endif()

# Default filename for generated precompiled header is cmake_pch.hxx.gch, but
# clang-tidy only recognizes .pch format.
set(CMAKE_PCH_EXTENSION .pch)

add_executable(${PROJECT_NAME} "")

add_compile_options(
        "${CMAKE_CXX_FLAGS}"
        "-Wall"
        "-Wextra"
        "-Wno-invalid-pch"
)
# Setting the global CMAKE_CXX_STANDARD variable would apply it to all targets without
# using set_target_properties, but doesn't work for C++17
set_target_properties(${PROJECT_NAME}
    PROPERTIES
        CXX_STANDARD 17
        CXX_STANDARD_REQUIRED ON
)

set(THREADS_PREFER_PTHREADS_FLAG ON)
find_package(Threads REQUIRED)

add_subdirectory(src)

target_link_libraries(${PROJECT_NAME}
    PRIVATE
        Threads::Threads
)

src/CMakeLists.txt:

target_precompile_headers(${PROJECT_NAME} PRIVATE stdafx.h
)

target_sources(${PROJECT_NAME}
    PRIVATE
        secret.cpp
)

src/stdafx.h:

#pragma once

#include "json.hpp"

#include <cstdint>
#include <cstdlib>
#include <list>
#include <memory>
#include <optional>
#include <string>
#include <unordered_map>

build/CMakeFiles/myproject.dir/cmake_pch.hxx

/* generated by CMake */

#pragma GCC system_header
#ifdef __cplusplus
#include "/home/vagrant/local_projects/myproject/src/stdafx.h"
#endif // __cplusplus

Output:

$ cmake .. && make VERBOSE=1
-- The C compiler identification is GNU 7.5.0
-- The CXX compiler identification is GNU 7.5.0
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working C compiler: /usr/bin/cc - skipped
-- Detecting C compile features
-- Detecting C compile features - done
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Check for working CXX compiler: /usr/bin/c++ - skipped
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- clang-tidy found: /usr/bin/clang-tidy-10
-- Looking for pthread.h
-- Looking for pthread.h - found
-- Performing Test CMAKE_HAVE_LIBC_PTHREAD
-- Performing Test CMAKE_HAVE_LIBC_PTHREAD - Failed
-- Looking for pthread_create in pthreads
-- Looking for pthread_create in pthreads - not found
-- Looking for pthread_create in pthread
-- Looking for pthread_create in pthread - found
-- Found Threads: TRUE   
-- Configuring done
-- Generating done
-- Build files have been written to: /home/vagrant/local_projects/myproject/build
/usr/local/bin/cmake -S/home/vagrant/local_projects/myproject -B/home/vagrant/local_projects/myproject/build --check-build-system CMakeFiles/Makefile.cmake 0
/usr/local/bin/cmake -E cmake_progress_start /home/vagrant/local_projects/myproject/build/CMakeFiles /home/vagrant/local_projects/myproject/build//CMakeFiles/progress.marks
make  -f CMakeFiles/Makefile2 all
make[1]: Entering directory '/home/vagrant/local_projects/myproject/build'
make  -f CMakeFiles/myproject.dir/build.make CMakeFiles/myproject.dir/depend
make[2]: Entering directory '/home/vagrant/local_projects/myproject/build'
cd /home/vagrant/local_projects/myproject/build && /usr/local/bin/cmake -E cmake_depends "Unix Makefiles" /home/vagrant/local_projects/myproject /home/vagrant/local_projects/myproject /home/vagrant/local_projects/myproject/build /home/vagrant/local_projects/cmyproject/build /home/vagrant/local_projects/myproject/build/CMakeFiles/myproject.dir/DependInfo.cmake --color=
Dependee "/home/vagrant/local_projects/myproject/build/CMakeFiles/myproject.dir/DependInfo.cmake" is newer than depender "/home/vagrant/local_projects/myproject/build/CMakeFiles/myproject.dir/depend.internal".
Dependee "/home/vagrant/local_projects/myproject/build/CMakeFiles/CMakeDirectoryInformation.cmake" is newer than depender "/home/vagrant/local_projects/myproject/build/CMakeFiles/myproject.dir/depend.internal".
Scanning dependencies of target myproject
make[2]: Leaving directory '/home/vagrant/local_projects/myproject/build'
make  -f CMakeFiles/myproject.dir/build.make CMakeFiles/myproject.dir/build
make[2]: Entering directory '/home/vagrant/local_projects/myproject/build'
[  1%] Building CXX object CMakeFiles/myproject.dir/cmake_pch.hxx.pch
/usr/local/bin/cmake -E __run_co_compile --tidy="/usr/bin/clang-tidy-10;--extra-arg-before=--driver-mode=g++" --source=/home/vagrant/local_projects/myproject/build/CMakeFiles/myproject.dir/cmake_pch.hxx.cxx -- /usr/bin/c++  -std=gnu++1z -Winvalid-pch -x c++-header -include /home/vagrant/local_projects/myproject/build/CMakeFiles/myproject.dir/cmake_pch.hxx -o CMakeFiles/myproject.dir/cmake_pch.hxx.pch -c /home/vagrant/local_projects/myproject/build/CMakeFiles/myproject.dir/cmake_pch.hxx.cxx
[  2%] Building CXX object CMakeFiles/myproject.dir/src/secret.cpp.o
/usr/local/bin/cmake -E __run_co_compile --tidy="/usr/bin/clang-tidy-10;--extra-arg-before=--driver-mode=g++" --source=/home/vagrant/local_projects/myproject/src/secret.cpp -- /usr/bin/c++ -std=gnu++1z -Winvalid-pch -include /home/vagrant/local_projects/myproject/build/CMakeFiles/myproject.dir/cmake_pch.hxx -o CMakeFiles/myproject.dir/src/secret.cpp.o -c /home/vagrant/local_projects/myproject/src/secret.cpp
error: file '/home/vagrant/local_projects/myproject/build/CMakeFiles/myproject.dir/cmake_pch.hxx.pch' is not a valid precompiled PCH file [clang-diagnostic-error]
error: input is not a PCH file: '/home/vagrant/local_projects/myproject/build/CMakeFiles/myproject.dir/cmake_pch.hxx.pch' [clang-diagnostic-error]
2 errors generated.
Error while processing /home/vagrant/local_projects/myproject/src/secret.cpp.
Found compiler error(s).
CMakeFiles/myproject.dir/build.make:97: recipe for target 'CMakeFiles/myproject.dir/src/secret.cpp.o' failed
make[2]: *** [CMakeFiles/myproject.dir/src/secret.cpp.o] Error 1
make[2]: Leaving directory '/home/vagrant/local_projects/myproject/build'
CMakeFiles/Makefile2:402: recipe for target 'CMakeFiles/myproject.dir/all' failed
make[1]: *** [CMakeFiles/myproject.dir/all] Error 2
make[1]: Leaving directory '/home/vagrant/local_projects/myproject/build'
Makefile:113: recipe for target 'all' failed
make: *** [all] Error 2

Looking at the build output I noticed at the -- /usr/bin/c++ part that -Winvalid-pch error is turned on, even though I specified it in the CMakeLists.txt file to be -Wno-invalid-pch instead. Maybe if I would be able to change that warning, the error would go away.

Workaround: haven't done it yet, maybe coding precompiled header compilation in CMake by hand and link it as target.

Edited by Bálint Kiss
To upload designs, you'll need to enable LFS and have an admin enable hashed storage. More information