From f20154b1b32af7a51f98dda22200c9c9f98add6f Mon Sep 17 00:00:00 2001 From: Claude Date: Fri, 6 Nov 2026 05:30:30 +0000 Subject: [PATCH] php: build ext/gd against the external libgd 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. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_01WGAwvvTwDg2yknFkmZ3qzs --- CLAUDE.md | 28 +++-- docs/notes/php.md | 110 ++++++++++++++++++- docs/notes/plas_stack_readme.md | 2 +- sys/lib/tests/hostkencc/php-mirror.sh | 10 +- sys/lib/tests/php-smoke.php | 56 +++++++++- sys/src/ape/cmd/php/cfg/main/php_config.h | 61 +++++++++- sys/src/ape/cmd/php/internal_functions_cli.c | 14 ++- sys/src/ape/cmd/php/mkfile | 25 ++++- 8 files changed, 284 insertions(+), 22 deletions(-) diff --git a/CLAUDE.md b/CLAUDE.md index 8703d763d..1ee816802 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -1230,15 +1230,29 @@ silent: (NTS)`, and `php-smoke.php` is **44 of 45** on the VM -- PHP_INT_SIZE 8, strlen, max, str_repeat at 100k, preg, json, and `/net/tcp/stats` read as 404 bytes. Notes in `docs/notes/php.md`.** -***AND TWELVE EXTENSIONS ARE BUILT NOW***: the four Phoronix REQUIRES -(libxml, dom, simplexml, zlib -- `system-info` runs) plus eight of the -nine it calls OPTIONAL -- posix, pcntl, bz2, readline, openssl -(LibreSSL), curl, sqlite3, zip. **579 TUs compile and `--undefined` +***AND THIRTEEN EXTENSIONS ARE BUILT NOW***: the four Phoronix +REQUIRES (libxml, dom, simplexml, zlib -- `system-info` runs), eight +of the nine it calls OPTIONAL -- posix, pcntl, bz2, readline, openssl +(LibreSSL), curl, sqlite3, zip -- **and gd, which was the ninth and +was impossible until `lib/gd` existed**. php takes upstream's +EXTERNAL arm, so it is `gd.c` + `gd_compat.c`, **two objects and not +the forty of php's bundled libgd** -- which is also the copy not +worth keeping, since it announces `2.0.35` while carrying AVIF, WebP +and the interpolation code. *`HAVE_LIBGD` is the gate, not +`HAVE_GD`*, and the first probe got the empty-TU result again. +***ITS FORMAT ANSWERS ARE A CONFIGURE PROBE THAT WOULD LIE, THE +FOURTH OF THAT FAMILY***: php asks the installed libgd what it can do +by LINKING `gdImageCreateFromJpeg`/`...Avif`/`...Webp`/`...Xpm`, and +**all four link** -- upstream compiles those files with no library +present and stubs each to `gd_error("... has been disabled")`. `nm` +over the archive says so. Answered **no** by hand, because otherwise +`function_exists('imagejpeg')` and `imagetypes() & IMG_JPG`, the two +documented ways to ask, both lie. *`HAVE_GD_FREETYPE` is the one +where probe and truth agree* -- `gdFontCacheShutdown` is genuinely +absent. **579 TUs compile and `--undefined` resolves 1120 symbols** against libap and eight library trees, all of which come in by `#pragma lib` from their own headers, so `cmd/php` -still has no `LIB=` line. *GD is impossible* (no libgd here; libpng is -not a drawing library) and **`ext/sockets` is deferred to a libap -change**: no `struct cmsghdr`, no `CMSG_*`, no `msg_flags`, `sendmsg` +still has no `LIB=` line. **`ext/sockets` is deferred to a libap change**: no `struct cmsghdr`, no `CMSG_*`, no `msg_flags`, `sendmsg` a stub and **`recvmsg` declared-by-the-header-and-defined-nowhere**. ***THE MEASUREMENT THAT NEARLY SHIPPED WAS AN EMPTY TRANSLATION UNIT***: five of these wrap their whole body in `#ifdef HAVE_`, so diff --git a/docs/notes/php.md b/docs/notes/php.md index e3cc41c48..593bb9baa 100644 --- a/docs/notes/php.md +++ b/docs/notes/php.md @@ -1225,8 +1225,12 @@ cannot be found by reading the subject.* Phoronix's `system-info` lists nine OPTIONAL extensions once the four required ones are in: OpenSSL, GD, Bzip2, SQLite3, PCNTL, POSIX, CURL, -Sockets, Readline. **Eight are built. GD is impossible and Sockets is -deferred**, and the two reasons are different in kind. +Sockets, Readline. **Eight were built in that round and GD followed +once `lib/gd` existed; only Sockets is still deferred.** *This +paragraph said "GD is impossible" and that was true only of the tree +as it stood* -- php bundles a libgd and the dependencies were already +here, so the sentence was about a missing vendored library rather +than about the platform. See the ext/gd section at the end. Eight of the nine already had a library in this tree — `lib/bz2`, `lib/readline`+`lib/history`, `lib/libressl`, `lib/curl`, `lib/sqlite`, @@ -1442,3 +1446,105 @@ phrase occurs nowhere under `sys/src`. It is the 9front kernel's own advisory as it grows a process's fd table, and it is a notice rather than a limit. Worth a second look only if the number keeps climbing, which would be a leak rather than a large working set. + +## ext/gd, against the external libgd — and a configure probe that lies + +With `lib/gd` building a real `libgd.a` (2.3.3, vendored at +`sys/src/external/libgd`), php takes **upstream's external arm**: +`ext/gd/gd.c` plus the `gd_compat.c` shim, **two objects instead of +forty**. 581 translation units compile, 0 errors. + +**The bundled copy is the one to not keep.** php ships its own libgd +under `ext/gd/libgd`, and building it would put a second, divergent +copy in a tree that now has the real one — and php's is the worse of +the two to carry: it still announces `GD_VERSION_STRING "2.0.35"` +while carrying `gd_avif.c`, `gd_webp.c`, `gd_bmp.c` and the whole +interpolation file, none of which existed in 2.0.35. + +**`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 the +empty-translation-unit result that five extensions already produced +once — *caught by the same `_module_entry` grep*, which reports +11 references now. + +### The format answers are a configure probe that would lie + +php's external arm asks the installed libgd what it can do by +**linking** `gdImageCreateFromJpeg`, `...Avif`, `...Webp` and +`...Xpm`. **All four link.** `nm` over the archive this tree builds: + +``` +gdImageCreateFromPng DEFINED gdImageCreateFromJpeg DEFINED +gdImageCreateFromAvif DEFINED gdImageCreateFromXpm DEFINED +gdImageCreateFromWebp DEFINED gdFontCacheShutdown absent +``` + +Upstream libgd compiles `gd_jpeg.c`, `gd_avif.c`, `gd_webp.c` and +`gdxpm.c` **even with no such library** and gives each a stub: +`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, a +fourth time, and the first where the stub is **upstream's deliberate +design** rather than a gap in this tree. + +They are answered **no** by hand, and the difference reaches scripts +rather than being academic: 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**, and the +failure would surface later as a false return from a function that +should not exist. + +**`HAVE_GD_FREETYPE` is the one where probe and truth agree**: php +checks `gdFontCacheShutdown`, which exists only inside `gdft.c`'s +`HAVE_LIBFREETYPE` arm and so is genuinely absent from the archive. +The three yes answers — `HAVE_GD_PNG`, `HAVE_GD_LIBVERSION`, +`HAVE_GD_GET_INTERPOLATION` — are link-level facts from the same `nm`. + +### The link, and 110 names that look missing and are not + +`--undefined` reports **`defined 1121, declared-only 116, absent 45`** +over 581 translation units. The `declared-only` figure jumped from 6 +to 116, and **all 110 new ones are `gd*`**. + +They are not missing. libgd writes every definition as + +```c +BGD_DECLARE(gdImagePtr) gdImageCreateTrueColor (int sx, int sy) +``` + +so the **return type** sits inside a macro call, and a +definition-shaped regex expecting `type name(` cannot match it. That +is the `BZ2_*` caveat arriving from the other side: *bzip2 hides the +NAME in a macro, libgd hides the RETURN TYPE* — two ways to blind the +same regex, and the sweep's own header already says to read this +column rather than gate on it. + +**Checked rather than assumed**: `nm -g --defined-only` over the +host-built `libgd.a` against those 110 names gives **110 defined, 0 +missing**. The mirror prints the caveat and that number now, so the +next reader compares instead of re-deriving. + +*An unrelated caution learned here*: re-running `apfunc-sweep.py` by +hand with only the new `--root` and dropping the other nine reported +**923** declared-only, which looks exactly like a catastrophic +finding and is just a short command line. + +### What the smoke test adds + +`php-smoke.php` grows a gd block that is a **round trip, not a +version string**: draw into a truecolour image, read a pixel back, +`imagepng()` to an output buffer, check the 8-byte signature, +`imagecreatefromstring()` it back, and compare the pixel and the +width. That exercises `ext/gd`, `libgd.a`, `libpng.a` and `libz.a` +together, and it is what says `lib/gd` actually linked. + +**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 of them — which is the control +working, not a bug. "JPEG is absent" is a statement about this port's +libgd, not about php or about gd. 0 failures on host php 8.3.6, which +happens also to ship GD 2.3.3. diff --git a/docs/notes/plas_stack_readme.md b/docs/notes/plas_stack_readme.md index 8786f1091..eed38fe8f 100644 --- a/docs/notes/plas_stack_readme.md +++ b/docs/notes/plas_stack_readme.md @@ -80,7 +80,7 @@ objects into `OFILES`, the `phpext_*_ptr` into and a rebuild. **Not built**: PDO and `pdo_sqlite` (use the `SQLite3` class instead), -mbstring, GD (there is no libgd in the tree), and `ext/sockets` (which +mbstring and `ext/sockets` (which needs `struct cmsghdr` and a real `recvmsg` in libap). To check the build on the machine: diff --git a/sys/lib/tests/hostkencc/php-mirror.sh b/sys/lib/tests/hostkencc/php-mirror.sh index 13b2176bc..fe75d44e8 100755 --- a/sys/lib/tests/hostkencc/php-mirror.sh +++ b/sys/lib/tests/hostkencc/php-mirror.sh @@ -301,7 +301,7 @@ EOF n=$(wc -l < "$OUT/undefined") echo "php-mirror: $n symbol(s) the link must find outside php" echo "php-mirror: the list is in $OUT/undefined; asking libap --" - # ***NINE LIBRARIES NOW, NOT ONE.*** php pulls each of them + # ***TEN LIBRARIES NOW, NOT ONE.*** php pulls each of them # through `#pragma lib' in its own header, so a sweep that knows # only libap answers `absent' for every `xmlParseFile', # `deflateInit_', `SSL_new' and `curl_easy_init' -- 241 of the @@ -319,6 +319,7 @@ EOF --root sys/src/external/libzip \ --root sys/src/external/readline \ --root sys/src/external/bzip2 \ + --root sys/src/external/libgd \ --file "$OUT/undefined" | grep -v ' *defined ' || true echo "php-mirror: ^ anything here is READ, not a failure -- the" @@ -333,6 +334,13 @@ EOF echo "php-mirror: the NAME IS INSIDE A MACRO and no regex over" echo "php-mirror: definition sites can see it. **A name here" echo "php-mirror: that is not on that list is the finding.**" + echo "php-mirror: Likewise 110 'declared' gd* names: libgd" + echo "php-mirror: writes every definition as" + echo "php-mirror: BGD_DECLARE(gdImagePtr) gdImageCreateTrueColor(...)" + echo "php-mirror: so the RETURN TYPE is inside a macro where BZ2_" + echo "php-mirror: hides the NAME -- two ways to blind the same" + echo "php-mirror: regex. All 110 were checked with nm against the" + echo "php-mirror: host-built libgd.a: 110 of 110 defined, 0 missing." exit 0 fi echo "php-mirror: compiled $ok, errors $bad, missing $missing" diff --git a/sys/lib/tests/php-smoke.php b/sys/lib/tests/php-smoke.php index e7f8676f0..2989818d1 100644 --- a/sys/lib/tests/php-smoke.php +++ b/sys/lib/tests/php-smoke.php @@ -288,7 +288,7 @@ function eq($what, $got, $want) { $want = ['core', 'date', 'pcre', 'hash', 'json', 'random', 'Reflection', 'SPL', 'standard', 'libxml', 'dom', 'SimpleXML', 'zlib', 'posix', 'pcntl', 'bz2', 'readline', 'openssl', 'curl', - 'sqlite3', 'zip']; + 'sqlite3', 'zip', 'gd']; $missing = []; foreach ($want as $e) { if (!extension_loaded($e)) $missing[] = $e; @@ -416,5 +416,59 @@ function eq($what, $got, $want) { echo " INFO readline " . $i['library_version'] . "\n"; } +/* gd -- against the EXTERNAL libgd, so this also proves lib/gd links. */ +if (extension_loaded('gd')) { + $i = gd_info(); + echo " INFO GD Version: " . ($i['GD Version'] ?? '?') . "\n"; + /* + * ***THE CAPABILITY FLAGS ARE THE POINT OF THIS BLOCK, NOT THE + * DRAWING.*** libgd compiles stub entry points for JPEG, WebP, + * AVIF and XPM even with no such library -- they LINK and then + * call `gd_error("... has been disabled")' -- so a configure + * probe answers yes and `imagetypes()' would lie. APExp answers + * those `HAVE_GD_*' no by hand, and these two lines are what + * says the hand answer reached PHP. + */ + eq("PNG support is reported", (bool)(imagetypes() & IMG_PNG), true); + /* + * Asserted on Plan9 ONLY, by Section 7's rule: "JPEG is absent" + * is a statement about THIS PORT's libgd, not about php or gd, + * and a build host with a full libgd fails it while being + * perfectly correct. It did -- which is the control working. + */ + if (PHP_OS === 'Plan9') { + eq("JPEG is NOT reported (libgd has only a stub)", + (bool)(imagetypes() & IMG_JPG), false); + eq("imagejpeg() is absent rather than failing later", + function_exists('imagejpeg'), false); + } else { + printf(" INFO not on Plan9; this host reports JPEG=%s\n", + (imagetypes() & IMG_JPG) ? 'yes' : 'no'); + } + + /* A real round trip: draw, encode to PNG, decode, read a pixel. */ + $im = imagecreatetruecolor(40, 30); + eq("imagecreatetruecolor", $im !== false, true); + if ($im !== false) { + $col = imagecolorallocate($im, 0x20, 0x90, 0xd0); + imagefilledrectangle($im, 0, 0, 39, 29, $col); + eq("pixel reads back", imagecolorat($im, 10, 10) & 0xffffff, 0x2090d0); + ob_start(); + $wrote = imagepng($im); + $png = ob_get_clean(); + eq("imagepng wrote something", $wrote && strlen($png) > 50, true); + eq("PNG signature", substr($png, 0, 8), "\x89PNG\r\n\x1a\n"); + $im2 = imagecreatefromstring($png); + eq("decoded the PNG back", $im2 !== false, true); + if ($im2 !== false) { + eq("round-tripped width", imagesx($im2), 40); + eq("round-tripped pixel", + imagecolorat($im2, 10, 10) & 0xffffff, 0x2090d0); + imagedestroy($im2); + } + imagedestroy($im); + } +} + printf("\nphp-smoke: %d failures\n", $fails); exit($fails); diff --git a/sys/src/ape/cmd/php/cfg/main/php_config.h b/sys/src/ape/cmd/php/cfg/main/php_config.h index 80d5d7c57..f4e622eee 100644 --- a/sys/src/ape/cmd/php/cfg/main/php_config.h +++ b/sys/src/ape/cmd/php/cfg/main/php_config.h @@ -385,8 +385,9 @@ * four required ones are in. Eight of them have a library in this * tree already -- `lib/bz2', `lib/readline'+`lib/history', * `lib/libressl', `lib/curl', `lib/sqlite', `lib/zip' -- and two need - * no library at all. **GD is the one that is impossible**: there is - * no libgd here, only libpng, and libpng is not a drawing library. + * no library at all. GD was the ninth and needed a libgd this tree + * did not have at the time; **it does now** (`lib/gd', 2.3.3), and + * `ext/gd' is answered further down. * * ***FIVE OF THE EIGHT "COMPILED CLEAN" BEFORE A SINGLE LINE BELOW * EXISTED, AND THAT WAS AN EMPTY TRANSLATION UNIT EACH TIME.*** Every @@ -534,6 +535,62 @@ #define HAVE_CANCEL_CALLBACK 1 #define HAVE_METHOD_SUPPORTED 1 +/* + * ---- ext/gd, against the EXTERNAL libgd (`lib/gd', 2.3.3) -------- + * + * **`HAVE_GD_BUNDLED' is deliberately NOT defined.** php ships its + * own copy of libgd under `ext/gd/libgd' and would build 40 objects + * from it; this tree has a real `libgd.a' now, so php takes the + * external arm and builds TWO -- `gd.c' and `gd_compat.c'. That + * avoids a second, divergent libgd in the tree, and php's bundled + * copy is the worse one to keep: it announces `GD_VERSION_STRING + * "2.0.35"' while carrying AVIF, WebP, BMP and the interpolation + * code, none of which existed in 2.0.35. + * + * ***`HAVE_LIBGD' IS THE GATE, NOT `HAVE_GD'.*** `php_gd.h:24' is + * `#if defined(HAVE_LIBGD) || defined(HAVE_GD_BUNDLED)', so with + * neither name the file declares `phpext_gd_ptr NULL' and `gd.c' + * compiles to nothing -- the empty-translation-unit shape that cost + * a measurement on five extensions already. + * + * ***AND THE FORMAT ANSWERS ARE WHERE A WORKING configure WOULD GET + * THIS WRONG, FOR THE FOURTH TIME.*** php probes the installed + * libgd by LINKING `gdImageCreateFromJpeg', `...Avif', `...Webp' and + * `...Xpm'. **All four link.** Upstream libgd compiles + * `gd_jpeg.c', `gd_avif.c', `gd_webp.c' and `gdxpm.c' even with no + * such library and gives each a stub -- `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' and + * `fsync' and `statvfs' in their exact shape. + * + * They are answered NO, and the difference is visible to scripts + * rather than academic: with them yes php registers `imagejpeg()' + * and sets the bit in `imagetypes()', so `function_exists()' and + * `imagetypes() & IMG_JPG' -- the two documented ways to ask what gd + * can do -- would both LIE, and the failure would arrive later as a + * false return from a function that should not exist. + * + * The three yes answers are link-level facts, checked with `nm' over + * the archive this tree builds rather than assumed: + * `gdImageCreateFromPng', `gdVersionString' and + * `gdImageGetInterpolationMethod' are all defined. + * **`HAVE_GD_FREETYPE' is a genuine link-level NO**: php probes + * `gdFontCacheShutdown', which exists only inside gdft.c's + * `HAVE_LIBFREETYPE' arm, so it is absent from the archive -- the + * one format-ish answer where the probe and the truth agree. + */ +#define HAVE_LIBGD 1 +#define HAVE_GD_PNG 1 +#define HAVE_GD_LIBVERSION 1 +#define HAVE_GD_GET_INTERPOLATION 1 +/* #undef HAVE_GD_BUNDLED */ +/* #undef HAVE_GD_JPG */ +/* #undef HAVE_GD_AVIF */ +/* #undef HAVE_GD_WEBP */ +/* #undef HAVE_GD_XPM */ +/* #undef HAVE_GD_FREETYPE */ + /* * ---- ext/sockets is NOT built, and the reason is in libap rather * than in php. `' has no `struct cmsghdr', no diff --git a/sys/src/ape/cmd/php/internal_functions_cli.c b/sys/src/ape/cmd/php/internal_functions_cli.c index 2424de21e..9111ce1cb 100644 --- a/sys/src/ape/cmd/php/internal_functions_cli.c +++ b/sys/src/ape/cmd/php/internal_functions_cli.c @@ -70,6 +70,7 @@ #include "ext/curl/php_curl.h" #include "ext/sqlite3/php_sqlite3.h" #include "ext/zip/php_zip.h" +#include "ext/gd/php_gd.h" static zend_module_entry * const php_builtin_extensions[] = { @@ -100,9 +101,9 @@ static zend_module_entry * const php_builtin_extensions[] = { * pcre)' -- and pcre is the second entry in this array, so the * order below is free and is the order the mkfile lists them in. * - * GD is the ninth and is absent because there is no libgd in - * this tree; ext/sockets is the tenth and is deferred to a libap - * change. Both are explained in `php_config.h'. + * ext/sockets is the one still missing, deferred to a libap + * change; `php_config.h' explains it. gd is below, against the + * external `lib/gd'. */ phpext_posix_ptr, phpext_pcntl_ptr, @@ -112,6 +113,13 @@ static zend_module_entry * const php_builtin_extensions[] = { phpext_curl_ptr, phpext_sqlite3_ptr, phpext_zip_ptr, + /* + * gd against the EXTERNAL libgd (`lib/gd'), not php's bundled + * copy -- `php_config.h' leaves HAVE_GD_BUNDLED undefined, and + * the gate for this pointer is HAVE_LIBGD. It declares no + * dependency on another extension. + */ + phpext_gd_ptr, }; diff --git a/sys/src/ape/cmd/php/mkfile b/sys/src/ape/cmd/php/mkfile index 682e5f694..37ef3ddcd 100644 --- a/sys/src/ape/cmd/php/mkfile +++ b/sys/src/ape/cmd/php/mkfile @@ -512,10 +512,10 @@ OFILES=\ ext/zlib/zlib.$O\ ext/zlib/zlib_fopen_wrapper.$O\ ext/zlib/zlib_filter.$O\ -# ***THE EIGHT OPTIONAL EXTENSIONS PHORONIX ASKS FOR.*** Nine are\ -# listed; **GD is the one left out and it is not a choice** -- there\ -# is no libgd in this tree, only libpng, and libpng is not a drawing\ -# library. `ext/sockets' is the ninth and is deferred: it needs\ +# ***THE OPTIONAL EXTENSIONS PHORONIX ASKS FOR.*** Nine are listed\ +# and eight are here; **gd is the ninth and is further down**, built\ +# against the external `lib/gd' once that existed. `ext/sockets' is\ +# the one still missing, and is deferred: it needs\ # `struct cmsghdr', the `CMSG_*' macros, `msg_flags' and a real\ # `recvmsg' in libap, which is a public-struct change. The\ # `php_config.h' entry has the detail.\ @@ -556,6 +556,21 @@ OFILES=\ # ext/zip\ ext/zip/php_zip.$O\ ext/zip/zip_stream.$O\ +# ***ext/gd AGAINST THE EXTERNAL libgd, WHICH IS WHY THIS IS TWO\ +# OBJECTS AND NOT FORTY.*** php bundles its own libgd under\ +# `ext/gd/libgd' and `HAVE_GD_BUNDLED' would build all 40 of them;\ +# `lib/gd' builds a real `libgd.a' from `external/libgd' (2.3.3), so\ +# `php_config.h' leaves `HAVE_GD_BUNDLED' undefined and php takes\ +# upstream's external arm: `gd.c' plus the `gd_compat.c' shim, and\ +# nothing else. *Keeping php's bundled copy instead would put a\ +# second, divergent libgd in the tree* -- and the worse one, since it\ +# still announces version 2.0.35.\ +#\ +# `' carries three `#pragma lib' lines -- libgd, libpng, libz --\ +# so this still needs no `LIB='.\ +# ext/gd\ + ext/gd/gd.$O\ + ext/gd/gd_compat.$O\ # ext/opcache\ ext/opcache/ZendAccelerator.$O\ ext/opcache/shared_alloc_mmap.$O\ @@ -861,7 +876,7 @@ OBJDIRS=\ ext/libxml ext/dom ext/dom/parentnode\ ext/dom/lexbor/selectors-adapted ext/simplexml ext/zlib\ ext/posix ext/pcntl ext/bz2 ext/readline ext/openssl\ - ext/curl ext/sqlite3 ext/zip\ + ext/curl ext/sqlite3 ext/zip ext/gd\ ext/pcre ext/pcre/pcre2lib ext/random ext/reflection ext/spl\ ext/standard ext/standard/libavifinfo ext/uri\ ext/uri/uriparser/src main main/streams sapi/cli