Skip to content

clangd compile database injects GCC builtin include dirs from every cached toolchain (wrong-arch headers in IDE search path) #1538

Description

@zackees

What

fbuild clangd-config (and every other consumer of CompileDatabase::translate_for_clang) bakes GCC builtin include directories into the emitted compile_commands.json as -isystem — but it collects them from every toolchain in the fbuild cache, not from the toolchain the project actually builds with.

builtin_isystem_args() (crates/fbuild-build-engine/src/compile_database/clang.rs:92) calls find_gcc_builtin_include_dirs() (crates/fbuild-toolchain/src/toolchain/clang.rs:290), which walks the whole ~/.fbuild/prod/cache/toolchains/ tree recursively (find_gcc_includes_recursive, depth ≤ 6) and returns every lib/gcc/<triple>/<version>/include that contains stdbool.h.

Observed

For bench/blink -e esp32s3 (ESP32-S3, xtensa-esp32s3-elf toolchain), the clangd database carries:

-isystem .../toolchains/3bbf.../8.4.0+2021r2-patch5/lib/gcc/xtensa-esp32s3-elf/8.4.0/include   <- correct
-isystem .../toolchains/arduino-tools/08e1.../7.3.0-atmel3.6.1-arduino7/avr/lib/gcc/avr/7.3.0/include
-isystem .../toolchains/developer-gnu/e064.../15.2.Rel1/arm-gnu-toolchain-15.2.rel1-x86_64-arm-none-eabi/lib/gcc/arm-none-eabi/15.2.1/include
-isystem .../toolchains/dl-toolchain-gccarmnoneeabi-.../9.2.1/lib/gcc/arm-none-eabi/9.2.1/include
-isystem .../toolchains/dl-toolchain-xtensa-linux_x86_64-2.100300.220621/.../2.100300.220621/lib/gcc/xtensa-lx106-elf/10.3.0/include
-isystem .../toolchains/earlephilhower-esp-quick-toolchain/.../3.2.0-gcc10.3/xtensa-lx106-elf/lib/gcc/xtensa-lx106-elf/10.3.0/include
... (10 `-isystem` entries total)

AVR, ARM, and xtensa-lx106 (ESP8266) builtin headers are on the search path of an ESP32-S3 project.

Why it matters

-isystem dirs are searched before the compiler's own builtins, and these directories hold the freestanding C headers (stdint.h, stddef.h, stdarg.h, stdbool.h, ...) whose contents are architecture-specific. With AVR/ARM/lx106 dirs ahead of the esp32s3 one, clangd can resolve #include <stdint.h> — or any of those freestanding headers — to another target's copy, so go-to-definition, hover, and diagnostics describe the wrong architecture. It is also a silent source of "works in the IDE, fails on the board" confusion.

Build correctness is not affected: the real g++ invocation carries no -isystem at all (compile_commands.raw.json has 0 -isystem entries), so this is confined to the clangd/IDE database.

Suspected fix

Restrict the lookup to the toolchain actually selected for the env being emitted — plumb the resolved toolchain (or its lib/gcc/<triple> root) into translate_for_clang instead of scanning the cache root. Note the call site is also unconditional on target arch, so a project building for both AVR and ESP32-S3 in one fbuild.ini needs the dirs chosen per env, not once per database.

Found while investigating #1537.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions