[ci] Add lint check to prevent powf in core and base entity platforms

Add a ci-custom.py check that prevents powf() from being introduced
into esphome/core/ and base entity platform components (sensor, light,
climate, etc.). These files are linked into every build, and powf
pulls in __ieee754_powf (~2.3KB flash).

Existing legitimate uses of powf with non-integer exponents (gamma
correction in helpers.cpp) are excluded. New uses can opt out with
// NOLINT if truly necessary.
This commit is contained in:
J. Nick Koston
2026-02-19 15:52:34 -06:00
parent 6a8844e2fc
commit eb83c85a08
3 changed files with 51 additions and 3 deletions

View File

@@ -714,7 +714,7 @@ float gamma_correct(float value, float gamma) {
if (gamma <= 0.0f)
return value;
return powf(value, gamma);
return powf(value, gamma); // NOLINT - deprecated, removal 2026.9.0
}
float gamma_uncorrect(float value, float gamma) {
if (value <= 0.0f)
@@ -722,7 +722,7 @@ float gamma_uncorrect(float value, float gamma) {
if (gamma <= 0.0f)
return value;
return powf(value, 1 / gamma);
return powf(value, 1 / gamma); // NOLINT - deprecated, removal 2026.9.0
}
void rgb_to_hsv(float red, float green, float blue, int &hue, float &saturation, float &value) {

View File

@@ -440,7 +440,7 @@ template<size_t STACK_SIZE, typename T = uint8_t> class SmallBufferWithHeapFallb
///@{
/// Compute 10^exp using iterative multiplication/division.
/// Avoids pulling in powf/__ieee754_powf (~2.3KB flash) for small integer exponents.
/// Avoids pulling in powf/__ieee754_powf (~2.3KB flash) for small integer exponents. // NOLINT
/// Exact for non-negative exponents up to 10 (powers of 10 up to 10^10 are exact in float).
inline float pow10_int(int8_t exp) {
float result = 1.0f;

View File

@@ -825,6 +825,54 @@ def lint_no_scanf(fname, match):
)
# Base entity platforms - these are linked into most builds and should not
# pull in powf/__ieee754_powf (~2.3KB flash).
BASE_ENTITY_PLATFORMS = [
"alarm_control_panel",
"binary_sensor",
"button",
"climate",
"cover",
"datetime",
"event",
"fan",
"light",
"lock",
"media_player",
"number",
"select",
"sensor",
"switch",
"text",
"text_sensor",
"update",
"valve",
"water_heater",
]
# Directories protected from powf: core + all base entity platforms
POWF_PROTECTED_DIRS = ["esphome/core"] + [
f"esphome/components/{p}" for p in BASE_ENTITY_PLATFORMS
]
@lint_re_check(
r"[^\w]powf\s*\(" + CPP_RE_EOL,
include=[
f"{d}/*.{ext}" for d in POWF_PROTECTED_DIRS for ext in ["h", "cpp", "tcc"]
],
)
def lint_no_powf_in_core(fname, match):
return (
f"{highlight('powf()')} pulls in __ieee754_powf (~2.3KB flash) and is not allowed in "
f"core or base entity platform code. These files are linked into every build.\n"
f"Please use alternatives:\n"
f" - {highlight('pow10_int(exp)')} for integer powers of 10 (from helpers.h)\n"
f" - Precomputed lookup tables for gamma/non-integer exponents\n"
f"(If powf is strictly necessary, add `// NOLINT` to the line)"
)
@lint_content_find_check(
"ESP_LOG",
include=["*.h", "*.tcc"],