What changed, and why it matters
This commit adds a new automated CI (Continuous Integration) job that runs a tool called Include What You Use (IWYU) to check that source files include only the headers they actually need. It also makes minor supporting changes: adding a CI configuration, installing the IWYU tool, adjusting build scripts, adding a mapping file for IWYU, and removing an unused <tuple> header from one source file. There is no change to Bitcoin Core's runtime behavior, consensus rules, networking, wallet logic, or any user-facing functionality. It is purely a code-quality and tooling improvement.
No security action required. This is a normal infrastructure/code-quality commit. Reviewers may verify the CI job runs successfully and that the IWYU configuration does not inadvertently suppress legitimate warnings.
Security signals we found
No strong security signals were identified.
Evidence from the diff
The commit introduces a new GitHub Actions CI job named ‘iwyu’ configured via .github/workflows/ci.yml and ci/test/00_setup_env_native_iwyu.sh. It installs IWYU from source in ci/test/01_base_install.sh, adjusts patch application and CMake compile-commands generation in ci/test/03_test_script.sh, adds an IWYU symbol mapping in contrib/devtools/iwyu/bitcoin.core.imp, and removes an unused #include
Changed components
CI/CD configuration (.github/workflows/ci.yml)CI setup scripts (ci/test/00_setup_env_native_iwyu.sh, ci/test/01_base_install.sh, ci/test/03_test_script.sh)IWYU mapping file (contrib/devtools/iwyu/bitcoin.core.imp)Source hygiene only: src/crypto/hex_base.cpp (unused include removal)Inspect captured patch +48 / −8
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index f5dc7721..d1476f5a 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -522,6 +522,12 @@ jobs:
fail-fast: false
matrix:
include:
+ - name: 'iwyu'
+ cirrus-runner: 'ghcr.io/cirruslabs/ubuntu-runner-amd64:24.04-md'
+ fallback-runner: 'ubuntu-24.04'
+ timeout-minutes: 120
+ file-env: './ci/test/00_setup_env_native_iwyu.sh'
+
- name: '32 bit ARM'
cirrus-runner: 'ubuntu-24.04-arm' # Cirrus' Arm runners are Apple (with virtual Linux aarch64), which doesn't support 32-bit mode
fallback-runner: 'ubuntu-24.04-arm'
diff --git a/ci/test/00_setup_env_native_iwyu.sh b/ci/test/00_setup_env_native_iwyu.sh
new file mode 100755
index 00000000..dbb45ed7
--- /dev/null
+++ b/ci/test/00_setup_env_native_iwyu.sh
@@ -0,0 +1,25 @@
+#!/usr/bin/env bash
+#
+# Copyright (c) 2023-present The Bitcoin Core developers
+# Distributed under the MIT software license, see the accompanying
+# file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+export LC_ALL=C.UTF-8
+
+export CI_IMAGE_NAME_TAG="mirror.gcr.io/debian:trixie" # To build codegen, CMake must be 3.31 or newer.
+export CONTAINER_NAME=ci_native_iwyu
+export TIDY_LLVM_V="21"
+export APT_LLVM_V="${TIDY_LLVM_V}"
+export PACKAGES="clang-${TIDY_LLVM_V} libclang-${TIDY_LLVM_V}-dev llvm-${TIDY_LLVM_V}-dev jq libevent-dev libboost-dev libzmq3-dev systemtap-sdt-dev qt6-base-dev qt6-tools-dev qt6-l10n-tools libqrencode-dev libsqlite3-dev libcapnp-dev capnproto"
+export NO_DEPENDS=1
+export RUN_UNIT_TESTS=false
+export RUN_FUNCTIONAL_TESTS=false
+export RUN_FUZZ_TESTS=false
+export RUN_CHECK_DEPS=false
+export RUN_IWYU=true
+export GOAL="codegen"
+export BITCOIN_CONFIG="\
+ --preset dev-mode -DBUILD_GUI=OFF \
+ -DCMAKE_C_COMPILER=clang-${TIDY_LLVM_V} \
+ -DCMAKE_CXX_COMPILER=clang++-${TIDY_LLVM_V} \
+"
diff --git a/ci/test/01_base_install.sh b/ci/test/01_base_install.sh
index f1accd71..0ac56208 100755
--- a/ci/test/01_base_install.sh
+++ b/ci/test/01_base_install.sh
@@ -79,7 +79,7 @@ if [[ -n "${USE_INSTRUMENTED_LIBCPP}" ]]; then
rm -rf /llvm-project
fi
-if [[ "${RUN_TIDY}" == "true" ]]; then
+if [[ "${RUN_IWYU}" == true ]]; then
${CI_RETRY_EXE} git clone --depth=1 https://github.com/include-what-you-use/include-what-you-use -b clang_"${TIDY_LLVM_V}" /include-what-you-use
(cd /include-what-you-use && patch -p1 < /ci_container_base/ci/test/01_iwyu.patch)
cmake -B /iwyu-build/ -G 'Unix Makefiles' -DCMAKE_PREFIX_PATH=/usr/lib/llvm-"${TIDY_LLVM_V}" -S /include-what-you-use
diff --git a/ci/test/03_test_script.sh b/ci/test/03_test_script.sh
index e61dc33e..32739a13 100755
--- a/ci/test/03_test_script.sh
+++ b/ci/test/03_test_script.sh
@@ -41,10 +41,10 @@ echo "=== BEGIN env ==="
env
echo "=== END env ==="
-# Don't apply patches in the tidy job, because it relies on the `git diff`
-# command to detect IWYU errors. It is safe to skip this patch in the tidy job
+# Don't apply patches in the iwyu job, because it relies on the `git diff`
+# command to detect IWYU errors. It is safe to skip this patch in the iwyu job
# because it doesn't run a UB detector.
-if [ "$RUN_TIDY" != "true" ]; then
+if [[ "${RUN_IWYU}" != true ]]; then
# compact->outputs[i].file_size is uninitialized memory, so reading it is UB.
# The statistic bytes_written is only used for logging, which is disabled in
# CI, so as a temporary minimal fix to work around UB and CI failures, leave
@@ -120,7 +120,7 @@ BASE_BUILD_DIR=${BASE_BUILD_DIR:-$BASE_SCRATCH_DIR/build-$HOST}
BITCOIN_CONFIG_ALL="$BITCOIN_CONFIG_ALL -DCMAKE_INSTALL_PREFIX=$BASE_OUTDIR -Werror=dev"
-if [[ "${RUN_TIDY}" == "true" ]]; then
+if [[ "${RUN_IWYU}" == true || "${RUN_TIDY}" == true ]]; then
BITCOIN_CONFIG_ALL="$BITCOIN_CONFIG_ALL -DCMAKE_EXPORT_COMPILE_COMMANDS=ON"
fi
@@ -132,11 +132,15 @@ cmake -S "$BASE_ROOT_DIR" -B "$BASE_BUILD_DIR" "${CMAKE_ARGS[@]}" || (
false
)
+if [[ "${GOAL}" != all && "${GOAL}" != codegen ]]; then
+ GOAL="all ${GOAL}"
+fi
+
# shellcheck disable=SC2086
-cmake --build "${BASE_BUILD_DIR}" "$MAKEJOBS" --target all $GOAL || (
+cmake --build "${BASE_BUILD_DIR}" "$MAKEJOBS" --target $GOAL || (
echo "Build failure. Verbose build follows."
# shellcheck disable=SC2086
- cmake --build "${BASE_BUILD_DIR}" -j1 --target all $GOAL --verbose
+ cmake --build "${BASE_BUILD_DIR}" -j1 --target $GOAL --verbose
false
)
@@ -204,7 +208,9 @@ if [ "${RUN_TIDY}" = "true" ]; then
echo "^^^ ⚠️ Failure generated from clang-tidy"
false
fi
+fi
+if [[ "${RUN_IWYU}" == true ]]; then
# TODO: Consider enforcing IWYU across the entire codebase.
FILES_WITH_ENFORCED_IWYU="/src/(crypto|index)/.*\\.cpp"
jq --arg patterns "$FILES_WITH_ENFORCED_IWYU" 'map(select(.file | test($patterns)))' "${BASE_BUILD_DIR}/compile_commands.json" > "${BASE_BUILD_DIR}/compile_commands_iwyu_errors.json"
diff --git a/contrib/devtools/iwyu/bitcoin.core.imp b/contrib/devtools/iwyu/bitcoin.core.imp
index c3195e51..9067bc32 100644
--- a/contrib/devtools/iwyu/bitcoin.core.imp
+++ b/contrib/devtools/iwyu/bitcoin.core.imp
@@ -13,4 +13,8 @@
{ "symbol": ["SEEK_CUR", "private", "<cstdio>", "public"] },
{ "symbol": ["SEEK_END", "private", "<cstdio>", "public"] },
{ "symbol": ["SEEK_SET", "private", "<cstdio>", "public"] },
+
+ # IWYU bug.
+ # See: https://github.com/include-what-you-use/include-what-you-use/issues/1863.
+ { "symbol": ["std::vector", "private", "<vector>", "public"] },
]
diff --git a/src/crypto/hex_base.cpp b/src/crypto/hex_base.cpp
index 7098aba7..f8b1ca2f 100644
--- a/src/crypto/hex_base.cpp
+++ b/src/crypto/hex_base.cpp
@@ -8,7 +8,6 @@
#include <cassert>
#include <cstring>
#include <string>
-#include <tuple>
namespace {
Why this scored 15/100
Community notes
Notes can correct, qualify, or add evidence to the AI analysis. Every note shown here has been validated by a human moderator.
The AI analysis stands alone for now. Submit a note if you can add evidence or important context.