From caad13fce811464806e50b9f34a03b7e96c0de00 Mon Sep 17 00:00:00 2001 From: Alex Cameron Date: Fri, 21 Aug 2026 06:46:04 +0000 Subject: [PATCH] ci: add IWYU include checks --- .agents/setup | 30 +++++++++++++++++++ .github/workflows/ci.yml | 23 +++++++++++++- AGENTS.md | 4 +++ CMakeLists.txt | 22 ++++++++++++++ include/warpforth/Conversion/Passes.h | 2 -- .../warpforth/Dialect/Forth/ForthDialect.h | 9 ++---- lib/Conversion/ForthToGPU/ForthToGPU.cpp | 5 +--- .../ForthToMemRef/ForthToMemRef.cpp | 1 - lib/Conversion/Passes.cpp | 9 ++---- lib/Dialect/Forth/ForthDialect.cpp | 9 +++--- lib/Translation/ForthToMLIR/ForthToMLIR.cpp | 1 - lib/Translation/MLIRToPTX/MLIRToPTX.cpp | 2 +- tools/warpforth-opt/warpforth-opt.cpp | 11 +------ .../warpforth-translate.cpp | 4 +-- tools/warpforthc/warpforthc.cpp | 10 +++---- 15 files changed, 96 insertions(+), 46 deletions(-) diff --git a/.agents/setup b/.agents/setup index 6543aea..b77ecfc 100755 --- a/.agents/setup +++ b/.agents/setup @@ -26,6 +26,7 @@ install_system_dependencies() { curl doxygen gnupg + libclang-20-dev libmlir-20-dev llvm-20-dev mlir-20-tools @@ -60,6 +61,34 @@ install_system_dependencies() { sudo env DEBIAN_FRONTEND=noninteractive apt-get install -y "${missing[@]}" } +install_iwyu() ( + local iwyu_commit=6e08906c66b3009f2d590e4bd40d60fa303bf803 + local source_dir + local build_dir + + if command -v include-what-you-use >/dev/null 2>&1 && + include-what-you-use --version 2>&1 | grep -q '0\.24'; then + echo "include-what-you-use 0.24 is already installed." + return + fi + + source_dir="$(mktemp -d)" + build_dir="$(mktemp -d)" + trap 'rm -rf "$source_dir" "$build_dir"' EXIT + + git -C "$source_dir" init + git -C "$source_dir" remote add origin \ + https://github.com/include-what-you-use/include-what-you-use.git + git -C "$source_dir" fetch --depth 1 origin "$iwyu_commit" + git -C "$source_dir" checkout --detach FETCH_HEAD + cmake -S "$source_dir" -B "$build_dir" -G Ninja \ + -DCMAKE_BUILD_TYPE=Release \ + -DCMAKE_PREFIX_PATH="$llvm_root" \ + -DCMAKE_INSTALL_PREFIX="$HOME/.local" + cmake --build "$build_dir" --parallel 2 + cmake --install "$build_dir" +) + install_uv() { if command -v uv >/dev/null 2>&1; then echo "uv is already installed." @@ -111,6 +140,7 @@ configure_build() { } run_step "Install system dependencies" install_system_dependencies +run_step "Install include-what-you-use" install_iwyu run_step "Install uv" install_uv run_step "Install locked Python dependencies" uv sync --frozen --project "$repo_root" run_step "Configure login-shell environment" configure_login_shell diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 667bdb7..d2ece84 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -30,9 +30,27 @@ jobs: clang-format-${LLVM_VERSION} \ clang-tidy-${LLVM_VERSION} \ doxygen \ + libclang-${LLVM_VERSION}-dev \ llvm-${LLVM_VERSION}-dev \ libmlir-${LLVM_VERSION}-dev \ - mlir-${LLVM_VERSION}-tools + mlir-${LLVM_VERSION}-tools \ + ninja-build + + - name: Build include-what-you-use + run: | + git init "${RUNNER_TEMP}/iwyu-src" + git -C "${RUNNER_TEMP}/iwyu-src" remote add origin \ + https://github.com/include-what-you-use/include-what-you-use.git + git -C "${RUNNER_TEMP}/iwyu-src" fetch --depth 1 origin \ + 6e08906c66b3009f2d590e4bd40d60fa303bf803 + git -C "${RUNNER_TEMP}/iwyu-src" checkout --detach FETCH_HEAD + cmake -S "${RUNNER_TEMP}/iwyu-src" -B "${RUNNER_TEMP}/iwyu-build" -G Ninja \ + -DCMAKE_BUILD_TYPE=Release \ + -DCMAKE_PREFIX_PATH=/usr/lib/llvm-${LLVM_VERSION} \ + -DCMAKE_INSTALL_PREFIX="${RUNNER_TEMP}/iwyu" + cmake --build "${RUNNER_TEMP}/iwyu-build" --parallel 2 + cmake --install "${RUNNER_TEMP}/iwyu-build" + echo "${RUNNER_TEMP}/iwyu/bin" >> "$GITHUB_PATH" - uses: astral-sh/setup-uv@v4 @@ -61,6 +79,9 @@ jobs: - name: Check C++ with clang-tidy run: cmake --build build --target check-clang-tidy + - name: Check C++ includes + run: cmake --build build --target check-iwyu + - name: Check C++ formatting run: cmake --build build --target check-format diff --git a/AGENTS.md b/AGENTS.md index 67ba09e..fdf579f 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -16,6 +16,9 @@ cmake --build build --target check-warpforth # Run clang-tidy cmake --build build --target check-clang-tidy + +# Check for unused C++ includes +cmake --build build --target check-iwyu ``` Requires Clang 20 and MLIR/LLVM with `MLIR_DIR` and `LLVM_DIR` configured in @@ -108,6 +111,7 @@ uv run ruff format gpu_test/ - C++17 required - Use `clang-format` (config in `.clang-format`) - Run `check-clang-tidy` after C++ changes; do not apply fixes automatically +- Run `check-iwyu` after changing C++ includes ## Commit and PR Titles diff --git a/CMakeLists.txt b/CMakeLists.txt index 14df632..8ee1636 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -63,6 +63,28 @@ add_custom_target(check-clang-tidy VERBATIM ) +find_program(IWYU_EXECUTABLE NAMES include-what-you-use) +find_program(IWYU_TOOL_EXECUTABLE NAMES iwyu_tool.py iwyu_tool) +if(IWYU_EXECUTABLE AND IWYU_TOOL_EXECUTABLE) + find_package(Python3 REQUIRED COMPONENTS Interpreter) + add_custom_target(check-iwyu + COMMAND ${CMAKE_COMMAND} -E env IWYU_BINARY=${IWYU_EXECUTABLE} + ${Python3_EXECUTABLE} + ${IWYU_TOOL_EXECUTABLE} + -p ${PROJECT_BINARY_DIR} + -j 2 + -- + -Xiwyu --no_fwd_decls + DEPENDS + MLIRConversionPassIncGen + MLIRForthOpsIncGen + COMMENT "Checking C++ includes with include-what-you-use" + VERBATIM + ) +else() + message(STATUS "include-what-you-use not found, skipping check-iwyu target") +endif() + # Test infrastructure (lit + FileCheck) find_program(LIT_COMMAND NAMES lit llvm-lit HINTS ${CMAKE_SOURCE_DIR}/.venv/bin) diff --git a/include/warpforth/Conversion/Passes.h b/include/warpforth/Conversion/Passes.h index 68a9dac..f02b244 100644 --- a/include/warpforth/Conversion/Passes.h +++ b/include/warpforth/Conversion/Passes.h @@ -8,10 +8,8 @@ #define WARPFORTH_CONVERSION_PASSES_H #include "mlir/Dialect/GPU/IR/CompilationInterfaces.h" -#include "mlir/Pass/Pass.h" #include "mlir/Pass/PassOptions.h" #include "llvm/Support/CodeGen.h" -#include #include namespace mlir { diff --git a/include/warpforth/Dialect/Forth/ForthDialect.h b/include/warpforth/Dialect/Forth/ForthDialect.h index 3a3e71f..44131da 100644 --- a/include/warpforth/Dialect/Forth/ForthDialect.h +++ b/include/warpforth/Dialect/Forth/ForthDialect.h @@ -7,13 +7,10 @@ #ifndef WARPFORTH_DIALECT_FORTH_FORTHDIALECT_H #define WARPFORTH_DIALECT_FORTH_FORTHDIALECT_H -#include "mlir/Bytecode/BytecodeOpInterface.h" -#include "mlir/IR/Dialect.h" -#include "mlir/IR/OpDefinition.h" -#include "mlir/Interfaces/ControlFlowInterfaces.h" -#include "mlir/Interfaces/SideEffectInterfaces.h" +#include "mlir/Bytecode/BytecodeOpInterface.h" // IWYU pragma: keep +#include "mlir/Interfaces/SideEffectInterfaces.h" // IWYU pragma: keep -#include "warpforth/Dialect/Forth/ForthOpsDialect.h.inc" +#include "warpforth/Dialect/Forth/ForthOpsDialect.h.inc" // IWYU pragma: keep #define GET_TYPEDEF_CLASSES #include "warpforth/Dialect/Forth/ForthOpsTypes.h.inc" diff --git a/lib/Conversion/ForthToGPU/ForthToGPU.cpp b/lib/Conversion/ForthToGPU/ForthToGPU.cpp index 1abce2d..a2c6467 100644 --- a/lib/Conversion/ForthToGPU/ForthToGPU.cpp +++ b/lib/Conversion/ForthToGPU/ForthToGPU.cpp @@ -5,19 +5,16 @@ //===----------------------------------------------------------------------===// #include "warpforth/Conversion/ForthToGPU/ForthToGPU.h" -#include "mlir/Dialect/Arith/IR/Arith.h" #include "mlir/Dialect/Func/IR/FuncOps.h" #include "mlir/Dialect/GPU/IR/GPUDialect.h" -#include "mlir/Dialect/LLVMIR/LLVMDialect.h" +#include "mlir/Dialect/LLVMIR/LLVMDialect.h" // IWYU pragma: keep #include "mlir/Dialect/MemRef/IR/MemRef.h" -#include "mlir/IR/Builders.h" #include "mlir/IR/BuiltinOps.h" #include "mlir/IR/BuiltinTypes.h" #include "mlir/IR/IRMapping.h" #include "mlir/IR/PatternMatch.h" #include "mlir/Pass/Pass.h" #include "mlir/Transforms/DialectConversion.h" -#include "mlir/Transforms/GreedyPatternRewriteDriver.h" #include "warpforth/Dialect/Forth/ForthDialect.h" namespace mlir { diff --git a/lib/Conversion/ForthToMemRef/ForthToMemRef.cpp b/lib/Conversion/ForthToMemRef/ForthToMemRef.cpp index e99ede1..94b3696 100644 --- a/lib/Conversion/ForthToMemRef/ForthToMemRef.cpp +++ b/lib/Conversion/ForthToMemRef/ForthToMemRef.cpp @@ -9,7 +9,6 @@ #include "mlir/Dialect/ControlFlow/IR/ControlFlowOps.h" #include "mlir/Dialect/Func/IR/FuncOps.h" #include "mlir/Dialect/Func/Transforms/FuncConversions.h" -#include "mlir/Dialect/GPU/IR/GPUDialect.h" #include "mlir/Dialect/LLVMIR/LLVMDialect.h" #include "mlir/Dialect/LLVMIR/NVVMDialect.h" #include "mlir/Dialect/Math/IR/Math.h" diff --git a/lib/Conversion/Passes.cpp b/lib/Conversion/Passes.cpp index c28b7cd..058b223 100644 --- a/lib/Conversion/Passes.cpp +++ b/lib/Conversion/Passes.cpp @@ -5,16 +5,13 @@ //===----------------------------------------------------------------------===// #include "warpforth/Conversion/Passes.h" -#include "mlir/Conversion/GPUToNVVM/GPUToNVVMPass.h" -#include "mlir/Conversion/MathToLLVM/MathToLLVM.h" -#include "mlir/Conversion/NVVMToLLVM/NVVMToLLVM.h" +#include "mlir/Conversion/GPUToNVVM/GPUToNVVMPass.h" // IWYU pragma: keep +#include "mlir/Conversion/MathToLLVM/MathToLLVM.h" // IWYU pragma: keep +#include "mlir/Conversion/NVVMToLLVM/NVVMToLLVM.h" // IWYU pragma: keep #include "mlir/Conversion/ReconcileUnrealizedCasts/ReconcileUnrealizedCasts.h" -#include "mlir/Dialect/Func/IR/FuncOps.h" #include "mlir/Dialect/GPU/IR/GPUDialect.h" #include "mlir/Dialect/GPU/Transforms/Passes.h" #include "mlir/Pass/PassManager.h" -#include "mlir/Target/LLVMIR/Dialect/GPU/GPUToLLVMIRTranslation.h" -#include "mlir/Target/LLVMIR/Dialect/NVVM/NVVMToLLVMIRTranslation.h" #include "mlir/Transforms/Passes.h" #include "warpforth/Conversion/ForthToGPU/ForthToGPU.h" #include "warpforth/Conversion/ForthToMemRef/ForthToMemRef.h" diff --git a/lib/Dialect/Forth/ForthDialect.cpp b/lib/Dialect/Forth/ForthDialect.cpp index e439f48..aa410a3 100644 --- a/lib/Dialect/Forth/ForthDialect.cpp +++ b/lib/Dialect/Forth/ForthDialect.cpp @@ -5,15 +5,14 @@ //===----------------------------------------------------------------------===// #include "warpforth/Dialect/Forth/ForthDialect.h" -#include "mlir/IR/Builders.h" -#include "mlir/IR/DialectImplementation.h" -#include "mlir/IR/OpImplementation.h" -#include "llvm/ADT/TypeSwitch.h" +#include "mlir/IR/Builders.h" // IWYU pragma: keep +#include "mlir/IR/DialectImplementation.h" // IWYU pragma: keep +#include "llvm/ADT/TypeSwitch.h" // IWYU pragma: keep using namespace mlir; using namespace mlir::forth; -#include "warpforth/Dialect/Forth/ForthOpsDialect.cpp.inc" +#include "warpforth/Dialect/Forth/ForthOpsDialect.cpp.inc" // IWYU pragma: keep #define GET_TYPEDEF_CLASSES #include "warpforth/Dialect/Forth/ForthOpsTypes.cpp.inc" diff --git a/lib/Translation/ForthToMLIR/ForthToMLIR.cpp b/lib/Translation/ForthToMLIR/ForthToMLIR.cpp index 9727243..335a478 100644 --- a/lib/Translation/ForthToMLIR/ForthToMLIR.cpp +++ b/lib/Translation/ForthToMLIR/ForthToMLIR.cpp @@ -11,7 +11,6 @@ #include "mlir/Dialect/MemRef/IR/MemRef.h" #include "mlir/IR/BuiltinOps.h" #include "mlir/IR/BuiltinTypes.h" -#include "mlir/IR/Diagnostics.h" #include "mlir/Tools/mlir-translate/Translation.h" #include "warpforth/Dialect/Forth/ForthDialect.h" #include "warpforth/Translation/ForthToMLIR/ForthToMLIR.h" diff --git a/lib/Translation/MLIRToPTX/MLIRToPTX.cpp b/lib/Translation/MLIRToPTX/MLIRToPTX.cpp index 8867944..0b1a148 100644 --- a/lib/Translation/MLIRToPTX/MLIRToPTX.cpp +++ b/lib/Translation/MLIRToPTX/MLIRToPTX.cpp @@ -6,7 +6,7 @@ #include "warpforth/Translation/MLIRToPTX/MLIRToPTX.h" #include "mlir/Dialect/GPU/IR/GPUDialect.h" -#include "mlir/Dialect/LLVMIR/NVVMDialect.h" +#include "mlir/Dialect/LLVMIR/NVVMDialect.h" // IWYU pragma: keep #include "mlir/IR/BuiltinOps.h" #include "mlir/Support/LogicalResult.h" #include "mlir/Tools/mlir-translate/Translation.h" diff --git a/tools/warpforth-opt/warpforth-opt.cpp b/tools/warpforth-opt/warpforth-opt.cpp index aad6ea7..2152907 100644 --- a/tools/warpforth-opt/warpforth-opt.cpp +++ b/tools/warpforth-opt/warpforth-opt.cpp @@ -5,23 +5,14 @@ // //===----------------------------------------------------------------------===// -#include "mlir/IR/Dialect.h" -#include "mlir/IR/MLIRContext.h" #include "mlir/InitAllDialects.h" #include "mlir/InitAllExtensions.h" #include "mlir/InitAllPasses.h" -#include "mlir/Pass/Pass.h" -#include "mlir/Pass/PassManager.h" -#include "mlir/Support/FileUtilities.h" #include "mlir/Target/LLVMIR/Dialect/All.h" #include "mlir/Tools/mlir-opt/MlirOptMain.h" -#include "llvm/Support/CommandLine.h" -#include "llvm/Support/InitLLVM.h" -#include "llvm/Support/SourceMgr.h" -#include "llvm/Support/ToolOutputFile.h" #include "warpforth/Conversion/Passes.h" -#include "warpforth/Dialect/Forth/ForthDialect.h" +#include "warpforth/Dialect/Forth/ForthDialect.h" // IWYU pragma: keep int main(int argc, char **argv) { mlir::registerAllPasses(); diff --git a/tools/warpforth-translate/warpforth-translate.cpp b/tools/warpforth-translate/warpforth-translate.cpp index 6e883f4..f52c897 100644 --- a/tools/warpforth-translate/warpforth-translate.cpp +++ b/tools/warpforth-translate/warpforth-translate.cpp @@ -4,13 +4,11 @@ // //===----------------------------------------------------------------------===// -#include "mlir/IR/Dialect.h" -#include "mlir/IR/MLIRContext.h" #include "mlir/InitAllDialects.h" #include "mlir/InitAllTranslations.h" #include "mlir/Support/LogicalResult.h" #include "mlir/Tools/mlir-translate/MlirTranslateMain.h" -#include "warpforth/Dialect/Forth/ForthDialect.h" +#include "warpforth/Dialect/Forth/ForthDialect.h" // IWYU pragma: keep #include "warpforth/Translation/ForthToMLIR/ForthToMLIR.h" #include "warpforth/Translation/MLIRToPTX/MLIRToPTX.h" diff --git a/tools/warpforthc/warpforthc.cpp b/tools/warpforthc/warpforthc.cpp index 5313871..9959d13 100644 --- a/tools/warpforthc/warpforthc.cpp +++ b/tools/warpforthc/warpforthc.cpp @@ -8,23 +8,21 @@ #include "mlir/Conversion/ControlFlowToLLVM/ControlFlowToLLVM.h" #include "mlir/Conversion/FuncToLLVM/ConvertFuncToLLVM.h" #include "mlir/Conversion/MemRefToLLVM/MemRefToLLVM.h" -#include "mlir/Dialect/Arith/IR/Arith.h" -#include "mlir/Dialect/ControlFlow/IR/ControlFlow.h" -#include "mlir/Dialect/Func/IR/FuncOps.h" -#include "mlir/Dialect/MemRef/IR/MemRef.h" +#include "mlir/Dialect/ControlFlow/IR/ControlFlow.h" // IWYU pragma: keep +#include "mlir/Dialect/Func/IR/FuncOps.h" // IWYU pragma: keep +#include "mlir/Dialect/MemRef/IR/MemRef.h" // IWYU pragma: keep #include "mlir/IR/AsmState.h" #include "mlir/IR/BuiltinOps.h" #include "mlir/IR/Diagnostics.h" #include "mlir/IR/MLIRContext.h" #include "mlir/Pass/PassManager.h" -#include "mlir/Pass/PassOptions.h" #include "mlir/Target/LLVM/NVVM/Target.h" #include "mlir/Target/LLVMIR/Dialect/Builtin/BuiltinToLLVMIRTranslation.h" #include "mlir/Target/LLVMIR/Dialect/GPU/GPUToLLVMIRTranslation.h" #include "mlir/Target/LLVMIR/Dialect/LLVMIR/LLVMToLLVMIRTranslation.h" #include "mlir/Target/LLVMIR/Dialect/NVVM/NVVMToLLVMIRTranslation.h" #include "warpforth/Conversion/Passes.h" -#include "warpforth/Dialect/Forth/ForthDialect.h" +#include "warpforth/Dialect/Forth/ForthDialect.h" // IWYU pragma: keep #include "warpforth/Translation/ForthToMLIR/ForthToMLIR.h" #include "warpforth/Translation/MLIRToPTX/MLIRToPTX.h" #include "llvm/Support/CommandLine.h"