Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implicit include directories are incomplete, resulting in compile errors (CMake + Clang-Tidy) #23444

Closed
Viatorus opened this issue Jan 17, 2025 · 7 comments · Fixed by #23535
Closed

Comments

@Viatorus
Copy link

In order to make clang-tidy (and cppcheck and other static analyzer happy) they need all includes of an compiler.

But here:

if (NOT DEFINED CMAKE_C_IMPLICIT_INCLUDE_DIRECTORIES)
set(CMAKE_C_IMPLICIT_INCLUDE_DIRECTORIES "${EMSCRIPTEN_SYSROOT}/include")
endif()
if (NOT DEFINED CMAKE_CXX_IMPLICIT_INCLUDE_DIRECTORIES)
set(CMAKE_CXX_IMPLICIT_INCLUDE_DIRECTORIES "${EMSCRIPTEN_SYSROOT}/include")
endif()

Only include/ is set. But there are more includes if you run: echo | em++ -xc++ -E -v -

"${EMSCRIPTEN_SYSROOT}/include/compat
"${EMSCRIPTEN_SYSROOT}/include/c++/v1
??"/upstream/lib/clang/20/include
... even more

Maybe cmake_parse_implicit_include_info from CMakeParseImplicitIncludeInfo should be used (it works).

Without the complete list, a simple program is not compileable.

Version of emscripten/emsdk:
3.1.74/4.0.0

Failing command line in full:
.em++ -std=c++20 -isystem $EMSCRIPTEN/cache/sysroot/include/ test.cpp

./em++ -std=c++20 -isystem /home/neubertt/projects/emsdk/upstream/emscripten/cache/sysroot/include/ test.cpp

#include <string>
 In file included from test.cpp:1:
 In file included from $EMSCRIPTEN/cache/sysroot/include/c++/v1/string:589:
 In file included from $EMSCRIPTEN/cache/sysroot/include/c++/v1/__algorithm/max.h:14:
 In file included from $EMSCRIPTEN/cache/sysroot/include/c++/v1/__algorithm/max_element.h:15:
 In file included from $EMSCRIPTEN/cache/sysroot/include/c++/v1/__iterator/iterator_traits.h:14:
 In file included from $EMSCRIPTEN/cache/sysroot/include/c++/v1/__concepts/constructible.h:13:
 In file included from $EMSCRIPTEN/cache/sysroot/include/c++/v1/__concepts/destructible.h:13:
 In file included from $EMSCRIPTEN/cache/sysroot/include/c++/v1/__type_traits/is_nothrow_destructible.h:14:
 In file included from $EMSCRIPTEN/cache/sysroot/include/c++/v1/__type_traits/is_destructible.h:16:
 In file included from $EMSCRIPTEN/cache/sysroot/include/c++/v1/__type_traits/remove_all_extents.h:13:
 $EMSCRIPTEN/cache/sysroot/include/c++/v1/cstddef:45:5: error: <cstddef> tried including <stddef.h> but didn't find libc++'s <stddef.h> header.           This usually means that your header search paths are not configured properly.           The header search paths should contain the C++ Standard Library headers before           any C Standard Library, and you are probably using compiler flags that make that           not be the case.
    45 | #   error <cstddef> tried including <stddef.h> but didn't find libc++'s <stddef.h> header. \
       |     ^
@sbc100
Copy link
Collaborator

sbc100 commented Jan 28, 2025

Can you give an example of how you are using clang-tidy / cppcheck such that it fails? Since you are referring to cmake I imagine they must be getting their information from some kind of cmake metatdata file? Could show the exact command that fail?

@sbc100
Copy link
Collaborator

sbc100 commented Jan 28, 2025

Ah, I see the problem. In Emscripten.cmake we bypass a lot of stuff by default to speed things up. This includes the auto-detection of the include dirs. Can you try adding -DEMSCRIPTEN_FORCE_COMPILERS=OFF to your cmake to see if that fixes the issue?

Also, I do have a fix in flight but I'm trying to figure out how that CMAKE_CXX_IMPLICIT_INCLUDE_DIRECTORIES is used by other tools. I can't currently see how it is. Those paths do not appear in compile_commands.json .. so how are the linters extacting them?

@Viatorus
Copy link
Author

Viatorus commented Jan 29, 2025

Hello, thank you for taking a look at it.

Most projects have this in their CMake file:

# Generate compile_commands.json to make it easier to work with clang based tools
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
# Include implicit directories in the compile commands file
set(CMAKE_CXX_STANDARD_INCLUDE_DIRECTORIES ${CMAKE_CXX_IMPLICIT_INCLUDE_DIRECTORIES})

Take a look: https://github.com/search?q=set%28CMAKE_CXX_STANDARD_INCLUDE_DIRECTORIES+%24%7BCMAKE_CXX_IMPLICIT_INCLUDE_DIRECTORIES%7D%29&type=code

This doesn't yet work for Emscripten.

One workaround would be to do:

if (NOT EMSCRIPTEN)
  set(CMAKE_CXX_STANDARD_INCLUDE_DIRECTORIES ${CMAKE_CXX_IMPLICIT_INCLUDE_DIRECTORIES})
endif ()

But this would mean to adjust many project files.

@sbc100
Copy link
Collaborator

sbc100 commented Jan 29, 2025

Include implicit directories in the compile commands file

set(CMAKE_CXX_STANDARD_INCLUDE_DIRECTORIES ${CMAKE_CXX_IMPLICIT_INCLUDE_DIRECTORIES})

So this is needed to make thing like clang-tidy work? Seems like a big of hack, but if that is what folks do we can certainly make sure we are compatible with that.

@sbc100
Copy link
Collaborator

sbc100 commented Jan 29, 2025

This doesn't yet work for Emscripten.

When you say it "doesn't yet work" for emscripten what exactly do you mean? We do set CMAKE_CXX_IMPLICIT_INCLUDE_DIRECTORIES, right? Are you jut saying that that this list is incomplete are is somehow missing for you?

@Viatorus
Copy link
Author

Seems like a big of hack

Since clang-tidy (and other tools which use compile_commands.json) don't know/test the compiler internals, they rely on a complete include directory list, that's why CMAKE_CXX_IMPLICIT_INCLUDE_DIRECTORIES must be used.

"doesn't yet work"

"yet" means - if could be fixed ;)

Are you jut saying that that this list is incomplete are is somehow missing for you?

Yes. Because the list is incomplete, even Emscripten itself cannot compile a simple program anymore (see the code example above). I think the include problem comes from the fact, that instead this include order is used:

emsdk/upstream/emscripten/cache/sysroot/include/compat
emsdk/upstream/emscripten/cache/sysroot/include/c++/v1
emsdk/upstream/lib/clang/20/include
emsdk/upstream/emscripten/cache/sysroot/include

This one is used:

emsdk/upstream/emscripten/cache/sysroot/include // <-- Comes from CMAKE_CXX_IMPLICIT_INCLUDE_DIRECTORIES
emsdk/upstream/emscripten/cache/sysroot/include/compat
emsdk/upstream/emscripten/cache/sysroot/include/c++/v1
emsdk/upstream/lib/clang/20/include
emsdk/upstream/emscripten/cache/sysroot/include

sbc100 added a commit to sbc100/emscripten that referenced this issue Jan 29, 2025
This fixes CMAKE_C_IMPLICIT_INCLUDE_DIRECTORIES for the case when
we don't use compiler-auto-detection. i.e.
`-DEMSCRIPTEN_FORCE_COMPILERS=OFF` which happens to be the default
today.

As a followup we should consider completely removing
`EMSCRIPTEN_FORCE_COMPILERS`.

Fixes: emscripten-core#23444
sbc100 added a commit to sbc100/emscripten that referenced this issue Jan 29, 2025
This fixes CMAKE_C_IMPLICIT_INCLUDE_DIRECTORIES for the case when
we don't use compiler-auto-detection. i.e.
`-DEMSCRIPTEN_FORCE_COMPILERS=OFF` which happens to be the default
today.

As a followup we should consider completely removing
`EMSCRIPTEN_FORCE_COMPILERS`.

Fixes: emscripten-core#23444
@sbc100
Copy link
Collaborator

sbc100 commented Jan 29, 2025

Ok great. I have an initial fix in #23535. As a followup I hope to completely remove EMSCRIPTEN_FORCE_COMPILERS which is the cause of this issue.

sbc100 added a commit to sbc100/emscripten that referenced this issue Jan 29, 2025
This fixes CMAKE_C_IMPLICIT_INCLUDE_DIRECTORIES for the case when
we don't use compiler-auto-detection. i.e.
`-DEMSCRIPTEN_FORCE_COMPILERS=OFF` which happens to be the default
today.

As a followup we should consider completely removing
`EMSCRIPTEN_FORCE_COMPILERS`.

Fixes: emscripten-core#23444
sbc100 added a commit to sbc100/emscripten that referenced this issue Jan 29, 2025
This fixes CMAKE_C_IMPLICIT_INCLUDE_DIRECTORIES for the case when
we don't use compiler-auto-detection. i.e.
`-DEMSCRIPTEN_FORCE_COMPILERS=OFF` which happens to be the default
today.

As a followup we should consider completely removing
`EMSCRIPTEN_FORCE_COMPILERS`.

Fixes: emscripten-core#23444
sbc100 added a commit to sbc100/emscripten that referenced this issue Jan 29, 2025
This fixes CMAKE_C_IMPLICIT_INCLUDE_DIRECTORIES for the case when
we don't use compiler-auto-detection. i.e.
`-DEMSCRIPTEN_FORCE_COMPILERS=OFF` which happens to be the default
today.

As a followup we should consider completely removing
`EMSCRIPTEN_FORCE_COMPILERS`.

Fixes: emscripten-core#23444
sbc100 added a commit to sbc100/emscripten that referenced this issue Jan 29, 2025
This fixes CMAKE_C_IMPLICIT_INCLUDE_DIRECTORIES for the case when
we don't use compiler-auto-detection. i.e.
`-DEMSCRIPTEN_FORCE_COMPILERS=OFF` which happens to be the default
today.

As a followup we should consider completely removing
`EMSCRIPTEN_FORCE_COMPILERS`.

Fixes: emscripten-core#23444
@sbc100 sbc100 closed this as completed in 1e04f2b Jan 29, 2025
sbc100 added a commit to sbc100/emscripten that referenced this issue Jan 29, 2025
This change disables `EMSCRIPTEN_FORCE_COMPILERS` by default which means
cmake will run all the normal compiler detection phases.  This has the
advantage that things get setup correctly without taking any shortcuts.
See emscripten-core#23444.

The downside is the that cmake phase itself is now slower since its
needs to compiler, link and run a bunch of test binaries.

On my machine running all the cmake tests went from 27 to 36 seconds.
Running a single empty cmake project when from 1s to 4.5s.  Since
running cmake is normally rare compared to building the project itself I
think this slowdown is worth it, but I've left the
`EMSCRIPTEN_FORCE_COMPILERS` setting in place for now that folks that
want fast cmake.

Also, remember that cmake itself caches all this stuff so its only the
first run that get slowed down.
sbc100 added a commit to sbc100/emscripten that referenced this issue Jan 29, 2025
This change disables `EMSCRIPTEN_FORCE_COMPILERS` by default which means
cmake will run all the normal compiler detection phases.  This has the
advantage that things get setup correctly without taking any shortcuts.
See emscripten-core#23444.

The downside is the that cmake phase itself is now slower since its
needs to compiler, link and run a bunch of test binaries.

On my machine running all the cmake tests went from 27 to 36 seconds.
Running a single empty cmake project when from 1s to 4.5s.  Since
running cmake is normally rare compared to building the project itself I
think this slowdown is worth it, but I've left the
`EMSCRIPTEN_FORCE_COMPILERS` setting in place for now that folks that
want fast cmake.

Also, remember that cmake itself caches all this stuff so its only the
first run that get slowed down.
sbc100 added a commit that referenced this issue Jan 30, 2025
This change disables `EMSCRIPTEN_FORCE_COMPILERS` by default which means
cmake will run all the normal compiler detection phases. This has the
advantage that things get setup correctly without taking any shortcuts.
See #23444.

The downside is the that cmake phase itself is now slower since its
needs to compiler, link and run a bunch of test binaries.

On my machine running all the cmake tests went from 27 to 36 seconds.
Running a single empty cmake project when from 1s to 4.5s. Since running
cmake is normally rare compared to building the project itself I think
this slowdown is worth it, but I've left the
`EMSCRIPTEN_FORCE_COMPILERS` setting in place for now that folks that
want fast cmake.

Also, remember that cmake itself caches all this stuff so its only the
first run that get slowed down.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants