ci/fix_has_include_README.md
Files that use the FL_HAS_INCLUDE() macro need to include "fl/stl/has_include.h", otherwise the macro evaluates to 0 (undefined), causing incorrect behavior.
Example Bug: tests/crash_handler.h was using FL_HAS_INCLUDE(<execinfo.h>) without the include, causing it to select the wrong crash handler implementation and resulting in test failures.
Two scripts have been created to prevent this issue:
ci/fix_has_include.py - Auto-Fixer (Manual Tool)Purpose: Find and fix files missing the fl/stl/has_include.h include.
Usage:
# Dry-run mode (just reports issues)
uv run python ci/fix_has_include.py
# Fix mode (automatically adds missing includes)
uv run python ci/fix_has_include.py --fix
# Help
uv run python ci/fix_has_include.py --help
Options:
--fix - Automatically add missing includes (default: dry-run)--macro NAME - Search for different macro (default: FL_HAS_INCLUDE)--include PATH - Check for different include (default: fl/stl/has_include.h)Features:
.h, .hpp, .cpp, .ino)ci/lint_cpp/has_include_checker.py - CI LinterPurpose: Prevent the issue from happening again by checking in CI.
Usage:
# Run the checker
uv run python ci/lint_cpp/has_include_checker.py
# Returns 0 if all files are OK
# Returns 1 if any files are missing the include
Integration: This checker can be integrated into the unified C++ linting system.
Find files using FL_HAS_INCLUDE:
FL_HAS_INCLUDE\s*\(#define FL_HAS_INCLUDE lines (macro definition).git, .build, .venv, etc.src/fl/stl/has_include.h itself (defines the macro)Check for include:
#include "fl/stl/has_include.h" or #include <fl/stl/compiler_control.h>^\s*#\s*include\s+[<"].*fl/stl/has_include.h[">]Report difference:
When adding the include, the script uses this priority order:
After header guard (preferred)
#ifndef MYHEADER_H
#define MYHEADER_H
#include "fl/stl/has_include.h" // IWYU pragma: keep <-- INSERTED HERE
Before first #include
#pragma once
#include "fl/stl/has_include.h" // IWYU pragma: keep <-- INSERTED HERE
#include "other_header.h"
After any #define
After #ifndef
Beginning of file (fallback)
Current Status (2026-02-14):
FL_HAS_INCLUDEfl/stl/has_include.h ✅Files Fixed:
tests/crash_handler.h (manual fix)src/fl/serial.h (auto-fix)src/fl/undef.h (auto-fix)The script adds // IWYU pragma: keep to prevent Include-What-You-Use from removing the include:
#include "fl/stl/has_include.h" // IWYU pragma: keep
This is necessary because IWYU doesn't understand that preprocessor macros need their defining headers.
ci/lint_cpp/run_all_checkers.pysrc/fl/stl/has_include.h - Defines FL_HAS_INCLUDE macroci/lint_cpp/banned_macros_checker.py - Bans raw __has_include usageci/lint_cpp/attribute_checker.py - Similar pattern checker for attributesci/lint_cpp/banned_macros_checker.py