-
Notifications
You must be signed in to change notification settings - Fork 1.2k
GCC 15 build failure on Linux: PAGE_SIZE defined by system headers bypasses closure.h 4096u fix #2559
Description
Problem
npm install canvas fails to compile from source on Alpine Linux (musl, x86_64) with GCC 15 and Node 24.
The error is in src/Canvas.cc:646 inside getSafeBufSize:
error: no matching function for call to 'min(uint32_t, int)'
return (std::min)((uint32_t)canvas->getWidth() * canvas->getHeight() * 4, PAGE_SIZE);
GCC 15 is strict about std::min requiring both arguments to be the same type. The first argument is uint32_t, but PAGE_SIZE resolves to int.
Root cause
closure.h defines PAGE_SIZE as 4096u (unsigned), but only when the system doesn't already provide it:
#ifndef PAGE_SIZE
#define PAGE_SIZE 4096u
#endifOn Linux, PAGE_SIZE is defined by system/kernel headers (e.g. via <limits.h>) as an int. The #ifndef guard is false, so the 4096u fallback never takes effect, and the std::min(uint32_t, int) mismatch remains.
This means the fix in 22ed2b7 ("make canvas types unsigned") works on platforms where PAGE_SIZE isn't predefined (macOS, Windows) but not on Linux.
Reproduction
docker run --rm --platform linux/amd64 node:24.13.1-alpine sh -c \
'apk add --no-cache python3 make g++ pkgconfig cairo-dev pango-dev freetype-dev jpeg-dev giflib-dev pixman-dev && \
mkdir /tmp/c && cd /tmp/c && npm init -y && npm install canvas'Fails with canvas@3.2.2 (latest as of 2026-03-22).
Works fine on linux/arm64 Alpine (prebuild available) and on Debian/glibc x86_64 (prebuild available).
Suggested fix
Cast PAGE_SIZE at the call site in Canvas.cc, or rename the internal constant to avoid the POSIX collision:
// Option A: cast at call site
return (std::min)((uint32_t)canvas->getWidth() * canvas->getHeight() * 4, static_cast<uint32_t>(PAGE_SIZE));
// Option B: use a different name in closure.h
#define CANVAS_PAGE_SIZE 4096uEnvironment
- Alpine 3.21 (musl)
- GCC 15.2.0
- Node.js 24.13.1
- canvas 3.2.2