commit d21fe910e3488d0208c11234b687ef6a04bfcd23
parent 8b827e0b7a69b5d251c68104c24c5b731256819e
Author: Jack Mordaunt <jackmordaunt.dev@gmail.com>
Date: Sun, 20 Sep 2026 15:07:29 -0300
tools: port transpile.sh to ccgo v4
ccgo v3 could not do this job any more: it does not build on Go 1.27, and
against libwebp 1.6.0 it failed to resolve objects at all, either reporting
"no objects to link" from the archive or panicking in ccgo.go:1281:find on
explicit object paths.
v4 is a direct compiler, so the autotools configure, the compile database and
the static archive all go away; it takes the source files. It also supplies
target predefines through --goos/--goarch, but not target libc headers, so
each cross target still needs a header source:
linux/amd64 the host
linux/arm64 aarch64-linux-gnu-gcc
darwin/* zig's bundled any-macos-any headers
windows/* x86_64-w64-mingw32-gcc
zig is what removes the osxcross requirement, and with it the need for an
Apple SDK that cannot be redistributed. It does not help for linux: ccgo
cannot parse zig's generic-glibc bits/types.h.
Two patches are carried. libwebp declares GetCoeffs as a volatile function
pointer and v4 cannot emit a call through one; threading is disabled here so
dropping volatile is safe, and it is applied in place with a restore trap
because ccgo resolves modernc.org/libc through the module it runs from.
sharpyuv_stub.c replaces the sharpyuv library, whose sharpyuv_gamma.c is the
only caller of expf/logf in libwebp — modernc.org/libc provides Xexpf and
Xlogf for linux only, so transpiling it fails to link on darwin and windows.
Nothing reaches sharpyuv unless WebPConfig.use_sharp_yuv is set, which this
package never does.
Diffstat:
2 files changed, 114 insertions(+), 174 deletions(-)
diff --git a/tools/sharpyuv_stub.c b/tools/sharpyuv_stub.c
@@ -0,0 +1,37 @@
+// Stub replacements for libwebp's sharpyuv library, used by the transpiled
+// backend only.
+//
+// sharpyuv/sharpyuv_gamma.c is the only file in libwebp that calls expf() and
+// logf(), and modernc.org/libc provides Xexpf/Xlogf for linux targets only.
+// Transpiling sharpyuv therefore fails to link on darwin and windows.
+//
+// Nothing here is reachable: sharpyuv is entered only through
+// WebPConfig.use_sharp_yuv, and this package always encodes via
+// WebPEncodeRGBA / WebPEncodeLosslessRGBA, which use the default config.
+// SharpYuvConvert returning 0 is the library's own failure signal, so a
+// caller that did enable sharp YUV would get a clean encode error rather
+// than wrong output.
+
+#include "sharpyuv/sharpyuv.h"
+#include "sharpyuv/sharpyuv_csp.h"
+#include "src/dsp/cpu.h"
+
+void SharpYuvInit(VP8CPUInfo cpu_info_func) { (void)cpu_info_func; }
+
+const SharpYuvConversionMatrix* SharpYuvGetConversionMatrix(
+ SharpYuvMatrixType matrix_type) {
+ (void)matrix_type;
+ return NULL;
+}
+
+int SharpYuvConvert(const void* r_ptr, const void* g_ptr, const void* b_ptr,
+ int rgb_step, int rgb_stride, int rgb_bit_depth,
+ void* y_ptr, int y_stride, void* u_ptr, int u_stride,
+ void* v_ptr, int v_stride, int yuv_bit_depth, int width,
+ int height, const SharpYuvConversionMatrix* yuv_matrix) {
+ (void)r_ptr; (void)g_ptr; (void)b_ptr; (void)rgb_step; (void)rgb_stride;
+ (void)rgb_bit_depth; (void)y_ptr; (void)y_stride; (void)u_ptr;
+ (void)u_stride; (void)v_ptr; (void)v_stride; (void)yuv_bit_depth;
+ (void)width; (void)height; (void)yuv_matrix;
+ return 0;
+}
diff --git a/tools/transpile.sh b/tools/transpile.sh
@@ -1,178 +1,81 @@
#!/bin/sh
+#
+# Transpile libwebp to Go with ccgo v4, one file per GOOS/GOARCH.
+#
+# Requires:
+# ccgo v4 go install modernc.org/ccgo/v4@latest
+# zig darwin headers (replaces osxcross; no Apple SDK needed)
+# x86_64-w64-mingw32-gcc windows headers
+# aarch64-linux-gnu-gcc linux/arm64 headers
+#
+# ccgo v4 supplies target predefines via --goos/--goarch but not target libc
+# headers, so each cross target needs a header source. zig covers darwin from
+# its bundled any-macos-any headers, which is what removes the osxcross and
+# Apple SDK requirement. It does not cover linux: ccgo cannot parse zig's
+# generic-glibc bits/types.h, so linux/arm64 still uses a real cross compiler
+# and linux/amd64 just uses the host.
set -eux
-cd ./c-lib/
-
-# Linux transpile.
-
-NATIVE_CC=$(which gcc)
-NATIVE_CXX=$(which c++)
-NATIVE_AR=$(which ar)
-
-make distclean || true
-./autogen.sh
-./configure \
- CC=$NATIVE_CC \
- CXX=$NATIVE_CXX \
- --host=x86_64-linux-gnu \
- --disable-libwebpmux \
- --disable-libwebpdemux \
- --disable-sse4.1 \
- --disable-sse2 \
- --disable-neon \
- --disable-neon-rtcd \
- --disable-threading \
- --disable-gl \
- --disable-sdl \
- --disable-png \
- --disable-jpeg \
- --disable-tiff \
- --disable-gif \
- --disable-wic \
- --disable-shared
-
-rm cdb-linux.json || true
-
-CC=$NATIVE_CC \
-CXX=$NATIVE_CXX \
-AR=$NATIVE_AR \
-ccgo -compiledb cdb-linux.json make
-
-CC=$NATIVE_CC \
-CXX=$NATIVE_CXX \
-AR=$NATIVE_AR \
-ccgo -pkgname webp -trace-translation-units -o ../lib/transpiled/webp/libwebp_linux_amd64.go cdb-linux.json src/.libs/libwebp.a
-
-gofmt -s -w ../lib/transpiled/webp/libwebp_linux_amd64.go
-
-# Linux arm64.
-
-LINUX_ARM_HOST=aarch64-linux-gnu
-LINUX_ARM_CC=$(which $LINUX_ARM_HOST-gcc)
-LINUX_ARM_CXX=$(which $LINUX_ARM_HOST-c++)
-LINUX_ARM_AR=$(which $LINUX_ARM_HOST-ar)
-
-make distclean || true
-./autogen.sh
-./configure \
- CC=$LINUX_ARM_CC \
- CXX=$LINUX_ARM_CXX \
- --host=$LINUX_ARM_HOST \
- --disable-libwebpmux \
- --disable-libwebpdemux \
- --disable-sse4.1 \
- --disable-sse2 \
- --disable-neon \
- --disable-neon-rtcd \
- --disable-threading \
- --disable-gl \
- --disable-sdl \
- --disable-png \
- --disable-jpeg \
- --disable-tiff \
- --disable-gif \
- --disable-wic \
- --disable-shared
-
-rm cdb-linux-arm64.json || true
-
-CC=$LINUX_ARM_CC \
-CXX=$LINUX_ARM_CXX \
-AR=$LINUX_ARM_AR \
-ccgo -compiledb cdb-linux-arm64.json make
-
-CC=$LINUX_ARM_CC \
-CXX=$LINUX_ARM_CXX \
-AR=$LINUX_ARM_AR \
-ccgo -pkgname webp -trace-translation-units -o ../lib/transpiled/webp/libwebp_linux_arm64.go cdb-linux-arm64.json src/.libs/libwebp.a
-
-gofmt -s -w ../lib/transpiled/webp/libwebp_linux_arm64.go
-
-# macOS transpile.
-
-MACOS_HOST=x86_64-apple-darwin15
-MACOS_CC=$(which $MACOS_HOST-cc)
-MACOS_CXX=$(which $MACOS_HOST-c++)
-MACOS_AR=$(which $MACOS_HOST-ar)
-
-make distclean || true
-./autogen.sh
-./configure \
- CC=$MACOS_CC \
- CXX=$MACOS_CXX \
- --host=$MACOS_HOST \
- --disable-libwebpmux \
- --disable-libwebpdemux \
- --disable-sse4.1 \
- --disable-sse2 \
- --disable-neon \
- --disable-neon-rtcd \
- --disable-threading \
- --disable-gl \
- --disable-sdl \
- --disable-png \
- --disable-jpeg \
- --disable-tiff \
- --disable-gif \
- --disable-wic \
- --disable-shared
-
-rm cdb-darwin.json || true
-
-CC=$MACOS_CC \
-CXX=$MACOS_CXX \
-AR=$MACOS_AR \
-ccgo -compiledb cdb-darwin.json make
-
-CC=$MACOS_CC \
-CXX=$MACOS_CXX \
-AR=$MACOS_AR \
-ccgo -pkgname webp -trace-translation-units -o ../lib/transpiled/webp/libwebp_darwin_amd64.go cdb-darwin.json src/.libs/libwebp.a
-
-gofmt -s -w ../lib/transpiled/webp/libwebp_darwin_amd64.go
-
-# Windows transpile.
-
-WINDOWS_HOST=x86_64-w64-mingw32
-WINDOWS_CC=$(which x86_64-w64-mingw32-gcc)
-WINDOWS_CXX=$(which x86_64-w64-mingw32-g++)
-WINDOWS_AR=$(which x86_64-w64-mingw32-ar)
-
-make distclean || true
-./autogen.sh
-./configure \
- CC=$WINDOWS_CC \
- CXX=$WINDOWS_CXX \
- --host=$WINDOWS_HOST \
- --disable-libwebpmux \
- --disable-libwebpdemux \
- --disable-sse4.1 \
- --disable-sse2 \
- --disable-neon \
- --disable-neon-rtcd \
- --disable-threading \
- --disable-gl \
- --disable-sdl \
- --disable-png \
- --disable-jpeg \
- --disable-tiff \
- --disable-gif \
- --disable-wic \
- --disable-shared
-
-rm cdb-windows.json || true
-
-CC=$WINDOWS_CC \
-CXX=$WINDOWS_CXX \
-AR=$WINDOWS_AR \
-ccgo -compiledb cdb-windows.json make
-
-CC=$WINDOWS_CC \
-CXX=$WINDOWS_CXX \
-AR=$WINDOWS_AR \
-ccgo -windows -pkgname webp -trace-translation-units -o ../lib/transpiled/webp/libwebp_windows_amd64.go cdb-windows.json src/.libs/libwebp.a
-
-gofmt -s -w ../lib/transpiled/webp/libwebp_windows_amd64.go
-
-
+HERE=$(cd "$(dirname "$0")" && pwd)
+SRC=$HERE/../c-lib
+OUT=$HERE/../lib/transpiled/webp
+ZIG=${ZIG:-zig}
+ZIGLIB=$($ZIG env | sed -n 's/.*\.lib_dir[ ]*=[ ]*"\([^"]*\)".*/\1/p')
+
+# dsp.h only enables SIMD when HAVE_CONFIG_H is set together with
+# WEBP_HAVE_SSE2, so an empty config.h selects the scalar paths. ccgo has no
+# -msse2 to turn off.
+INC=$(mktemp -d)
+mkdir -p "$INC/src/webp"
+# HAVE_BUILTIN_BSWAP* matter: endian_inl_utils.h only probes for the builtins
+# when HAVE_CONFIG_H is absent, so without these libwebp falls back to x86
+# inline asm, which ccgo turns into a runtime assertion that fires on the
+# first lossy decode. A real autotools configure detects these too.
+cat > "$INC/src/webp/config.h" <<'CONFIG'
+#define HAVE_BUILTIN_BSWAP16 1
+#define HAVE_BUILTIN_BSWAP32 1
+#define HAVE_BUILTIN_BSWAP64 1
+CONFIG
+trap 'rm -rf "$INC"' EXIT
+
+# libwebp declares GetCoeffs as a volatile function pointer; ccgo v4 cannot
+# emit a call through one and aborts. Threading is disabled in this build, so
+# dropping volatile is safe.
+#
+# Patched in place rather than in a scratch copy: ccgo resolves
+# modernc.org/libc through the module it is run from, so it has to run inside
+# this repository.
+VP8DEC=$SRC/src/dec/vp8_dec.c
+cp "$VP8DEC" "$VP8DEC.orig"
+trap 'mv -f "$VP8DEC.orig" "$VP8DEC"; rm -rf "$INC"' EXIT
+sed -i 's/^static volatile GetCoeffsFunc GetCoeffs = NULL;/static GetCoeffsFunc GetCoeffs = NULL;/' \
+ "$VP8DEC"
+
+transpile() {
+ goos=$1
+ goarch=$2
+ shift 2
+ echo "=== $goos/$goarch ==="
+ ( cd "$SRC" && ccgo \
+ --goos="$goos" --goarch="$goarch" \
+ --package-name=webp \
+ -ignore-asm-errors \
+ "$@" \
+ -o "$OUT/libwebp_${goos}_${goarch}.go" \
+ -DNDEBUG -DHAVE_CONFIG_H -I"$INC" -I. \
+ src/dec/*.c src/enc/*.c src/utils/*.c src/dsp/*.c \
+ "$HERE/sharpyuv_stub.c" )
+ gofmt -w "$OUT/libwebp_${goos}_${goarch}.go"
+}
+
+MACOS="-nostdinc -isystem $ZIGLIB/include -isystem $ZIGLIB/libc/include/any-macos-any"
+
+transpile linux amd64
+transpile linux arm64 --cpp=aarch64-linux-gnu-gcc
+transpile darwin amd64 $MACOS
+transpile darwin arm64 $MACOS
+transpile windows amd64 --cpp=x86_64-w64-mingw32-gcc
+transpile windows arm64 --cpp=x86_64-w64-mingw32-gcc
+
+ls -la "$OUT"