Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
51 changes: 51 additions & 0 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 5 additions & 1 deletion registry/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ TS_MARKER := $(MARKER_DIR)/ts-built

# Command packages (excludes _types and meta-packages)
CMD_PACKAGES := coreutils sed grep gawk findutils diffutils tar gzip \
curl http-get wget zip unzip jq ripgrep fd tree file sqlite3 duckdb yq codex git
curl http-get wget zip unzip jq ripgrep fd tree file sqlite3 duckdb yq codex git pngcrush

# Meta-packages
META_PACKAGES := common build-essential everything
Expand Down Expand Up @@ -186,6 +186,10 @@ $(COPY_MARKER): $(RUST_MARKER) $(C_MARKER)
@mkdir -p software/git/wasm
@[ -f "$(COMMANDS_DIR)/git" ] && cp -f "$(COMMANDS_DIR)/git" software/git/wasm/ || echo " WARN: git not found"

@# --- pngcrush (C build) ---
@mkdir -p software/pngcrush/wasm
@[ -f "$(COMMANDS_DIR)/pngcrush" ] && cp -f "$(COMMANDS_DIR)/pngcrush" software/pngcrush/wasm/ || echo " WARN: pngcrush not found"

@echo "=== Copy complete ==="
@touch $(COPY_MARKER)

Expand Down
40 changes: 36 additions & 4 deletions registry/native/c/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ NATIVE_CFLAGS := -O0 -g -I include/
COMMANDS_DIR ?= ../target/wasm32-wasip1/release/commands

# Real commands to install (add command names as they are opted in)
COMMANDS := zip unzip envsubst sqlite3 curl wget duckdb
COMMANDS := zip unzip envsubst sqlite3 curl wget duckdb pngcrush

# Programs requiring patched sysroot (Tier 2+ custom host imports)
PATCHED_PROGRAMS := isatty_test getpid_test getppid_test getppid_verify userinfo pipe_test dup_test spawn_child spawn_exit_code pipeline kill_child waitpid_return waitpid_edge syscall_coverage getpwuid_test signal_tests sigaction_behavior delayed_tcp_echo delayed_kill pipe_edge tcp_echo tcp_server udp_echo unix_socket signal_handler http_get dns_lookup sqlite3_cli curl wget
Expand All @@ -88,10 +88,10 @@ endif

WASM_PROG_NAMES := $(sort $(basename $(notdir $(SOURCES))) $(CUSTOM_WASM_PROG_NAMES))
NATIVE_PROG_NAMES := $(basename $(notdir $(SOURCES)))
PROGRAM_REPORT_NAMES := $(WASM_PROG_NAMES) duckdb
PROGRAM_REPORT_NAMES := $(WASM_PROG_NAMES) duckdb pngcrush

# Default WASM output targets
EXTRA_WASM_OUTPUTS := $(BUILD_DIR)/duckdb
EXTRA_WASM_OUTPUTS := $(BUILD_DIR)/duckdb $(BUILD_DIR)/pngcrush
WASM_OUTPUTS := $(addprefix $(BUILD_DIR)/,$(WASM_PROG_NAMES)) $(EXTRA_WASM_OUTPUTS)
# Native output targets
NATIVE_OUTPUTS := $(addprefix $(NATIVE_DIR)/,$(NATIVE_PROG_NAMES))
Expand Down Expand Up @@ -144,6 +144,9 @@ MINIZIP_URL := https://github.com/madler/zlib/archive/refs/tags/v1.3.1.zip
DUCKDB_VERSION := v1.5.0
DUCKDB_GIT_DESCRIBE := $(DUCKDB_VERSION)-0-g0123456789
DUCKDB_URL := https://github.com/duckdb/duckdb/archive/refs/tags/$(DUCKDB_VERSION).tar.gz
# pngcrush — PNG optimizer with bundled libpng and zlib
PNGCRUSH_TAG := pngcrush-20171101
PNGCRUSH_URL := https://github.com/pnggroup/pngcrush/archive/refs/tags/$(PNGCRUSH_TAG).tar.gz

LIBS_DIR := libs
LIBS_CACHE := .cache/libs
Expand Down Expand Up @@ -198,8 +201,17 @@ libs/duckdb/CMakeLists.txt:
@mkdir -p $(LIBS_DIR)/duckdb
@tar -xzf "$(LIBS_CACHE)/duckdb.tar.gz" --strip-components=1 -C $(LIBS_DIR)/duckdb

libs/pngcrush/pngcrush.c:
@echo "Fetching pngcrush $(PNGCRUSH_TAG)..."
@mkdir -p $(LIBS_CACHE)
@curl -fSL "$(PNGCRUSH_URL)" -o "$(LIBS_CACHE)/pngcrush.tar.gz"
@rm -rf $(LIBS_DIR)/pngcrush
@mkdir -p $(LIBS_DIR)/pngcrush
@tar -xzf "$(LIBS_CACHE)/pngcrush.tar.gz" --strip-components=1 -C $(LIBS_DIR)/pngcrush
@cp pngcrush-overlay/pnglibconf.h pngcrush-overlay/cexcept.h $(LIBS_DIR)/pngcrush/

.PHONY: fetch-libs clean-libs
fetch-libs: libs/sqlite3/sqlite3.c libs/zlib/zutil.c libs/minizip/ioapi.c libs/cjson/cJSON.c libs/curl/lib/easy.c libs/duckdb/CMakeLists.txt
fetch-libs: libs/sqlite3/sqlite3.c libs/zlib/zutil.c libs/minizip/ioapi.c libs/cjson/cJSON.c libs/curl/lib/easy.c libs/duckdb/CMakeLists.txt libs/pngcrush/pngcrush.c

clean-libs:
rm -rf $(LIBS_DIR) $(LIBS_CACHE)
Expand Down Expand Up @@ -513,6 +525,26 @@ $(NATIVE_DIR)/unzip: programs/unzip.c $(ZLIB_SRCS) $(MINIZIP_UNZIP_SRCS)
@mkdir -p $(NATIVE_DIR)
$(NATIVE_CC) $(NATIVE_CFLAGS) $(ZIP_INCLUDES) -o $@ programs/unzip.c $(ZLIB_SRCS) $(MINIZIP_UNZIP_SRCS) -lz

# pngcrush: PNG optimizer — compiles pngcrush.c with bundled libpng (unified) and zlib
PNGCRUSH_ZLIB_SRCS := $(addprefix libs/pngcrush/,adler32.c compress.c crc32.c deflate.c \
infback.c inffast.c inflate.c inftrees.c trees.c uncompr.c zutil.c)
PNGCRUSH_CFLAGS := -DLIBPNG_UNIFIED -DNO_GZ -isystem pngcrush-overlay -Ilibs/pngcrush \
-D_WASI_EMULATED_PROCESS_CLOCKS

$(BUILD_DIR)/pngcrush: libs/pngcrush/pngcrush.c $(WASI_SDK_DIR)/bin/clang
@mkdir -p $(BUILD_DIR)
$(CC) --target=wasm32-wasip1 --sysroot=$(WASI_SDK_DIR)/share/wasi-sysroot -O2 -I include/ \
$(PNGCRUSH_CFLAGS) -o $@.wasm \
libs/pngcrush/pngcrush.c $(PNGCRUSH_ZLIB_SRCS) -lm \
-lwasi-emulated-process-clocks
wasm-opt -O3 --strip-debug $@.wasm -o $@
@rm -f $@.wasm

$(NATIVE_DIR)/pngcrush: libs/pngcrush/pngcrush.c
@mkdir -p $(NATIVE_DIR)
$(NATIVE_CC) $(NATIVE_CFLAGS) $(PNGCRUSH_CFLAGS) -o $@ \
libs/pngcrush/pngcrush.c $(PNGCRUSH_ZLIB_SRCS) -lm -lz

# curl_test: links libcurl (HTTP/HTTPS build for WASM via host_net + host_tls)
CURL_SRCS := $(wildcard libs/curl/lib/*.c) $(wildcard libs/curl/lib/vauth/*.c) \
$(wildcard libs/curl/lib/vtls/*.c) $(wildcard libs/curl/lib/vquic/*.c) \
Expand Down
59 changes: 59 additions & 0 deletions registry/native/c/pngcrush-overlay/cexcept.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
/* cexcept.h — WASI-compatible replacement for cexcept exception handling.
*
* The original cexcept.h uses setjmp/longjmp which requires the WASM
* Exception Handling proposal. This simplified version uses a global
* flag and goto-style flow control that works on all WASM runtimes.
*
* Limitations: nested Try/Catch blocks are not reentrant (fine for
* pngcrush which uses them sequentially). Throw from deeply nested
* calls will abort the process via exit(1).
*/

#ifndef CEXCEPT_H
#define CEXCEPT_H

#include <stdlib.h>
#include <stdio.h>

#define define_exception_type(etype) \
struct exception_context { \
int caught; \
int has_throw; \
volatile struct { etype etmp; } v; \
}

#define init_exception_context(ec) ((void)((ec)->caught = 0, (ec)->has_throw = 0))

/* Try/Catch: uses a simple flag-based mechanism instead of setjmp/longjmp.
* Throw sets the flag and the Catch block checks it.
* NOTE: Throw from a subroutine (not directly in the Try block) will
* call exit(1) since we can't longjmp back. pngcrush's error handler
* (pngcrush_cexcept_error) calls Throw, which is invoked from libpng
* callbacks, so we handle that with exit(). */
#define Try \
{ \
the_exception_context->caught = 0; \
the_exception_context->has_throw = 0; \
{ \
do

#define exception__catch(action) \
while (the_exception_context->caught = 0, \
the_exception_context->caught); \
} \
if (the_exception_context->has_throw) { \
the_exception_context->caught = 1; \
} \
} \
if (!the_exception_context->caught || action) { } \
else

#define Catch(e) exception__catch(((e) = the_exception_context->v.etmp, 0))
#define Catch_anonymous exception__catch(0)

#define Throw \
for (;; exit(1)) \
for (the_exception_context->has_throw = 1 ;; ) \
the_exception_context->v.etmp =

#endif /* CEXCEPT_H */
Loading