Search code examples
c++cmakebuildheaderprecompiled-headers

CMake uses C-style precompiled headers instead of C++ version of the precompiled header


My project directory is as follows:

<PROJECT-ROOT>:
    - build
    - MyProject:
        - src:
            - main.cpp
            - hello.h (basic file that contains a simple function that prints something using iostream)
        - pch.h (precompiled header)
    - CMakeLists.txt

And CMakeLists.txt file is as follows:

cmake_minimum_required(VERSION 3.16)
project(MyProject)

if(MSVC)
    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /W4")
else()
    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra -Wpedantic -std=c++11")
endif()

include_directories(
                    MyProject
                    MyProject/src
)


add_executable(${PROJECT_NAME} ${CMAKE_SOURCE_DIR}/MyProject/pch.h 
                               ${CMAKE_SOURCE_DIR}/MyProject/src/main.cpp
                               ${CMAKE_SOURCE_DIR}/MyProject/src/hello.h)
target_precompile_headers(${PROJECT_NAME} PRIVATE ${CMAKE_SOURCE_DIR}/MyProject/pch.h)

As expected, CMake generates the following precompiled header files in build/CMakeFiles/MyProject.dir/ :

cmake_pch.c
cmake_pch.cxx
cmake_pch.cxx.obj
cmake_pch_cxx.pch
cmake_pch.h
cmake_pch.hxx

I am using this CMake project in Visual Studio 2019, and when I try to run main.cpp, Visual Studio gives me a bunch of errors, such as:

C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.29.30133\include\cstdlib(23): error C2061: syntax error: identifier 'noexcept'
C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.29.30133\include\cstdlib(23): error C2059: syntax error: ';'
C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.29.30133\include\cstdlib(23): error C2449: found '{' at file scope (missing function header?)
C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.29.30133\include\cstdlib(25): error C2059: syntax error: '}'
C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.29.30133\include\cstdlib(31): error C2061: syntax error: identifier 'noexcept'
C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.29.30133\include\cstdlib(31): error C2059: syntax error: ';'
C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.29.30133\include\cstdlib(31): error C2449: found '{' at file scope (missing function header?)
C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.29.30133\include\cstdlib(33): error C2059: syntax error: '}'
C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.29.30133\include\xtr1common(19): error C2061: syntax error: identifier 'std'
C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.29.30133\include\xtr1common(19): error C2059: syntax error: ';'
C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.29.30133\include\xtr1common(19): error C2449: found '{' at file scope (missing function header?)
C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.29.30133\include\xtr1common(235): error C2059: syntax error: '}'
C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.29.30133\include\iosfwd(175): warning C4157: pragma was ignored by C compiler
C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.29.30133\include\iosfwd(180): warning C4157: pragma was ignored by C compiler
C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.29.30133\include\type_traits(307): error C4233: nonstandard extension used: '__is_union' keyword only supported in C++, not C
C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.29.30133\include\type_traits(310): error C4233: nonstandard extension used: '__is_union' keyword only supported in C++, not C
C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.29.30133\include\type_traits(313): error C4233: nonstandard extension used: '__is_class' keyword only supported in C++, not C
C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.29.30133\include\type_traits(316): error C4233: nonstandard extension used: '__is_class' keyword only supported in C++, not C
C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.29.30133\include\type_traits(325): error C4233: nonstandard extension used: '__is_convertible_to' keyword only supported in C++, not C
C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.29.30133\include\type_traits(330): error C4233: nonstandard extension used: '__is_convertible_to' keyword only supported in C++, not C
C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.29.30133\include\type_traits(359): error C4233: nonstandard extension used: '__is_enum' keyword only supported in C++, not C
C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.29.30133\include\type_traits(362): error C4233: nonstandard extension used: '__is_enum' keyword only supported in C++, not C
C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.29.30133\include\type_traits(499): error C4233: nonstandard extension used: '__is_pod' keyword only supported in C++, not C

When I searched error code C4233 online, I learned that it is because a C code is trying to be compiled as a C++ code. Also, build process from Visual Studio (I guess uses ninja) shows that:

[1/33] Building C object CMakeFiles\MyProject.dir\cmake_pch.c.obj

Hence, I guess it tries to build my precompiled header as a c source, instead it is a C++ source. I also tried to change the pch extension to .hpp but it didn't work either. How can I specify CMake to mark precompiled header as C++ (or I guess CXX) source instead of pure C?

EDIT: When I disable the target_precompile_headers the program runs fine, hence I am certain that this is a precompiled header issue.


Solution

  • Thanks to @drescherjm, adding target_precompile_headers(${PROJECT_NAME} PRIVATE "$<$<COMPILE_LANGUAGE:CXX>:${CMAKE_SOURCE_DIR}/MyProject/pch.h>" got rid of the errors.