Skip to content

php: build ext/gd against the external libgd - #737

Merged
staalmannen merged 1 commit into
mainfrom
claude/upgrade-ape-c-library-mmZGd
Nov 6, 2026
Merged

staalmannen merged 1 commit into
mainfrom
claude/upgrade-ape-c-library-mmZGd

Conversation

@staalmannen

Copy link
Copy Markdown
Owner

libgd was already in the default build list -- _IMAGE_LIBS' in sys/src/ape/lib/mkfile' is in DIRS', so a tree-wide mk install' builds it -- so this round is php only.

php takes upstream's EXTERNAL arm, not its bundled libgd: two objects (gd.c' and the gd_compat.c' shim) instead of forty. Keeping the bundled copy would put a second, divergent libgd in a tree that now has the real one, and php's is the worse of the two to carry -- it announces GD_VERSION_STRING "2.0.35" while shipping gd_avif.c, gd_webp.c, gd_bmp.c and the interpolation file, none of which existed in 2.0.35.

581 translation units compile, 0 errors.

HAVE_LIBGD' is the gate, not HAVE_GD': php_gd.h:24 is `#if defined(HAVE_LIBGD) || defined(HAVE_GD_BUNDLED)', and with neither name the header defines phpext_gd_ptr as NULL and gd.c compiles to nothing. The first probe used -DHAVE_GD=1 and got that empty translation unit -- caught by the same _module_entry grep that caught it on five extensions before, which reports 11 now.

THE FORMAT ANSWERS ARE A CONFIGURE PROBE THAT WOULD LIE, AND THAT IS THE FOURTH TIME FOR THIS FAMILY. php asks the installed libgd what it can do by LINKING gdImageCreateFromJpeg, ...Avif, ...Webp and ...Xpm. All four link. Upstream compiles gd_jpeg.c, gd_avif.c, gd_webp.c and gdxpm.c even with no such library and stubs each one -- gd_jpeg.c:1209's _noJpegError() calls gd_error("JPEG image support has been disabled") and returns. So the probe succeeds and the capability is absent, which is HAVE_WORKING_MPROTECT, fsync and statvfs in their exact shape, and the first where the stub is upstream's deliberate design rather than a gap here.

Answered no by hand, and it reaches scripts: with them yes php registers imagejpeg() and sets the bit in imagetypes(), so function_exists('imagejpeg') and imagetypes() & IMG_JPG -- the two documented ways to ask what gd can do -- would both lie. HAVE_GD_FREETYPE is the one where probe and truth agree, since gdFontCacheShutdown lives only inside gdft.c's HAVE_LIBFREETYPE arm. The three yes answers are link-level facts from nm over the archive.

--undefined gives defined 1121, declared-only 116, absent 45'. The declared-only figure jumped 6 -> 116 and all 110 new ones are gd*: libgd writes every definition as BGD_DECLARE(gdImagePtr) gdImage...', so the RETURN TYPE is inside a macro where BZ2_ hides the NAME -- two ways to blind the same regex. nm against the host-built libgd.a says 110 of 110 defined, 0 missing, so the link is predicted to succeed. The mirror prints that caveat and the number now.

php-smoke.php gains a gd block that is a round trip rather than a version string: draw, read a pixel, imagepng() to a buffer, check the signature, imagecreatefromstring() back, compare pixel and width -- which exercises ext/gd, libgd.a, libpng.a and libz.a together. The two capability assertions are Plan9-only by Section 7's rule, and the host proved why: a build host with a full libgd reports JPEG yes and failed both, which is the control working. 0 failures on host php 8.3.6.

Also removes the "GD is impossible / there is no libgd in this tree" claim from the five places that carried it; it was true of the tree as it stood and is not now.

Claude-Session: https://claude.ai/code/session_01WGAwvvTwDg2yknFkmZ3qzs

libgd was already in the default build list -- `_IMAGE_LIBS' in
`sys/src/ape/lib/mkfile' is in `DIRS', so a tree-wide `mk install'
builds it -- so this round is php only.

php takes upstream's EXTERNAL arm, not its bundled libgd: two objects
(`gd.c' and the `gd_compat.c' shim) instead of forty.  Keeping the
bundled copy would put a second, divergent libgd in a tree that now
has the real one, and php's is the worse of the two to carry -- it
announces GD_VERSION_STRING "2.0.35" while shipping gd_avif.c,
gd_webp.c, gd_bmp.c and the interpolation file, none of which existed
in 2.0.35.

581 translation units compile, 0 errors.

`HAVE_LIBGD' is the gate, not `HAVE_GD': php_gd.h:24 is
`#if defined(HAVE_LIBGD) || defined(HAVE_GD_BUNDLED)', and with
neither name the header defines phpext_gd_ptr as NULL and gd.c
compiles to nothing.  The first probe used -DHAVE_GD=1 and got that
empty translation unit -- caught by the same <ext>_module_entry grep
that caught it on five extensions before, which reports 11 now.

***THE FORMAT ANSWERS ARE A CONFIGURE PROBE THAT WOULD LIE, AND THAT
IS THE FOURTH TIME FOR THIS FAMILY.***  php asks the installed libgd
what it can do by LINKING gdImageCreateFromJpeg, ...Avif, ...Webp and
...Xpm.  All four link.  Upstream compiles gd_jpeg.c, gd_avif.c,
gd_webp.c and gdxpm.c even with no such library and stubs each one --
gd_jpeg.c:1209's _noJpegError() calls gd_error("JPEG image support
has been disabled") and returns.  So the probe succeeds and the
capability is absent, which is HAVE_WORKING_MPROTECT, fsync and
statvfs in their exact shape, and the first where the stub is
upstream's deliberate design rather than a gap here.

Answered no by hand, and it reaches scripts: with them yes php
registers imagejpeg() and sets the bit in imagetypes(), so
function_exists('imagejpeg') and imagetypes() & IMG_JPG -- the two
documented ways to ask what gd can do -- would both lie.
HAVE_GD_FREETYPE is the one where probe and truth agree, since
gdFontCacheShutdown lives only inside gdft.c's HAVE_LIBFREETYPE arm.
The three yes answers are link-level facts from nm over the archive.

--undefined gives `defined 1121, declared-only 116, absent 45'.  The
declared-only figure jumped 6 -> 116 and all 110 new ones are gd*:
libgd writes every definition as `BGD_DECLARE(gdImagePtr) gdImage...',
so the RETURN TYPE is inside a macro where BZ2_ hides the NAME -- two
ways to blind the same regex.  nm against the host-built libgd.a says
110 of 110 defined, 0 missing, so the link is predicted to succeed.
The mirror prints that caveat and the number now.

php-smoke.php gains a gd block that is a round trip rather than a
version string: draw, read a pixel, imagepng() to a buffer, check the
signature, imagecreatefromstring() back, compare pixel and width --
which exercises ext/gd, libgd.a, libpng.a and libz.a together.  The
two capability assertions are Plan9-only by Section 7's rule, and the
host proved why: a build host with a full libgd reports JPEG yes and
failed both, which is the control working.  0 failures on host php
8.3.6.

Also removes the "GD is impossible / there is no libgd in this tree"
claim from the five places that carried it; it was true of the tree
as it stood and is not now.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WGAwvvTwDg2yknFkmZ3qzs
@staalmannen
staalmannen merged commit f5f5ab1 into main Nov 6, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants