Created
October 22, 2025 11:31
-
-
Save yoshinari-nomura/3c2521641a77867d819be9e3e04d0d3e to your computer and use it in GitHub Desktop.
clangd-setup - Generate .clangd from compile_commands.json
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/bin/bash | |
| ################################################################ | |
| # * clangd-setup - Generate .clangd from compile_commands.json | |
| # | |
| # Copyright (C) 2025 Yoshinari Nomura <[email protected]> | |
| # LICENSE: MIT | |
| # | |
| # clangd-setup is useful when your project uses GCC/G++ cross-compilers, | |
| # such as in Arduino (CLI) or ESP-IDF projects. | |
| # | |
| # It performs the following steps: | |
| # 1) Finds project-specific compiler executables from {build/,}compile_commands.json | |
| # 2) Queries the compilers for their default include paths | |
| # 3) Generates a .clangd file with CompileFlags: Add: and Remove: sections | |
| # | |
| # * Usage | |
| # | |
| # From your project root directory: | |
| # clangd-setup > .clangd | |
| # | |
| # clangd-setup works similarly to using the clangd --query-driver option. | |
| # However, setting --query-driver for each project individually | |
| # is cumbersome and inconvenient for me. | |
| # | |
| ################################################################ | |
| # Find compiler executable names from compile_commands.json | |
| # | |
| # For an ESP-IDF project: "command": "/usr/bin/gcc ..." | |
| # | |
| # jq -r '.[].command| split(" ")[0]' compile_commands.json | |
| # | |
| # For an Arduino CLI project: "arguments": ["/usr/bin/gcc", ... | |
| # | |
| # jq -r '.[].arguments[0]' compile_commands.json | |
| # | |
| # Combined form: | |
| # | |
| # jq -r '.[]| (.arguments[0]//(.command| split(" ")[0]))' compile_commands.json | |
| # | |
| function find_compilers() { | |
| local compile_commands_json="$1" | |
| jq -r '.[]| (.arguments[0] // (.command| split(" ")[0]))' \ | |
| "$compile_commands_json" | sort | uniq | |
| } | |
| # Show the default include paths for a given compiler | |
| # | |
| function default_include_path() { | |
| local compiler="$1" | |
| echo "" | "$compiler" -xc++ -E -v - 2>&1 | \ | |
| sed -n '1,/^#include <...> .* here:/d; /^End of/q; s/^ *//p' | |
| } | |
| # Find the path to compile_commands.json | |
| # | |
| function find_compile_commands_json() { | |
| for d in . build | |
| do | |
| if [ -f "$d/compile_commands.json" ]; then | |
| echo "$d/compile_commands.json" | |
| return | |
| fi | |
| done | |
| } | |
| ################################################################ | |
| # Find compilers from compile_commands.json | |
| compile_commands_json=$(find_compile_commands_json) | |
| if [ -z "$compile_commands_json" ]; then | |
| echo "compile_commands.json not found." >&2 | |
| exit 1 | |
| fi | |
| compilers=$(find_compilers "$compile_commands_json") | |
| if [ -z "$compilers" ]; then | |
| echo "No compilers found." >&2 | |
| exit 1 | |
| fi | |
| ################################################################ | |
| # Query each compiler for its default include paths | |
| echo "# Add below in your .clangd:" >&2 | |
| cat <<EOH | |
| CompileFlags: | |
| Add: [ | |
| EOH | |
| for compiler in $compilers | |
| do | |
| for include_path in $(default_include_path "$compiler") | |
| do | |
| echo " -I$(realpath $include_path)," | |
| done | |
| done | |
| ################################################################ | |
| # Remove GCC-specific compiler options | |
| cat <<EOF | |
| ] | |
| Remove: [ | |
| -fstrict-volatile-bitfields, | |
| -fno-tree-switch-conversion, | |
| -fno-shrink-wrap, | |
| -fno-tree-switch-conversion | |
| ] | |
| EOF |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment