diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..8f34883 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,149 @@ +name: CI + +on: + push: + branches: [ master ] + + pull_request: + branches: [ master ] + +jobs: + + download-subprojects: + runs-on: ubuntu-latest + container: + image: ubuntu:22.04 + + steps: + + - uses: actions/checkout@v4 + + - id: downloads_cache + name: Cache subproject downloads + uses: actions/cache@v4 + with: + key: subprojects-${{ hashFiles('subprojects/*.wrap') }} + restore-keys: subprojects- + path: ./subprojects/packagecache + + - if: steps.downloads_cache.outputs.cache-hit != 'true' + name: Install dependencies + run: | + apt-get update + apt-get install -y ca-certificates patch + + - if: steps.downloads_cache.outputs.cache-hit != 'true' + name: Install uv + uses: astral-sh/setup-uv@v7 + + - if: steps.downloads_cache.outputs.cache-hit != 'true' + name: Download subprojects + run: | + uv venv + uv run meson.py subprojects download + + build-llvm: + runs-on: ubuntu-latest + needs: download-subprojects + container: + image: ubuntu:22.04 + + steps: + + - uses: actions/checkout@v4 + + - name: Cache LLVM + uses: actions/cache@v4 + id: llvm_cache + with: + key: llvm-${{ runner.os }}-${{ hashFiles('subprojects/llvm.wrap', 'subprojects/packagefiles/llvm/*') }} + restore-keys: llvm-${{ runner.os }}- + path: | + ./build/llvm + ./build/zlib + + - if: steps.llvm_cache.outputs.cache-hit != 'true' + name: Retrieve subproject downloads + uses: actions/cache/restore@v4 + with: + key: subprojects-${{ hashFiles('subprojects/*.wrap') }} + fail-on-cache-miss: true + path: ./subprojects/packagecache + + - if: steps.llvm_cache.outputs.cache-hit != 'true' + name: Install dependencies + run: | + apt-get update + apt-get install -y build-essential ninja-build cmake + + - if: steps.llvm_cache.outputs.cache-hit != 'true' + name: Install uv + uses: astral-sh/setup-uv@v7 + + - name: Setup ccache + if: steps.llvm_cache.outputs.cache-hit != 'true' + uses: hendrikmuhs/ccache-action@v1.2 + with: + key: ccache-llvm-${{ runner.os }} + + - if: steps.llvm_cache.outputs.cache-hit != 'true' + name: Build LLVM + run: | + uv venv + make `pwd`/build/llvm/.stamp + + build-standalone: + runs-on: ubuntu-latest + needs: [ download-subprojects, build-llvm ] + container: + image: ubuntu:22.04 + + steps: + + - uses: actions/checkout@v4 + + - name: Retrieve subproject downloads + uses: actions/cache/restore@v4 + with: + key: subprojects-${{ hashFiles('subprojects/*.wrap') }} + fail-on-cache-miss: true + path: ./subprojects/packagecache + + - name: Retrieve + uses: actions/cache/restore@v4 + with: + key: llvm-${{ runner.os }}-${{ hashFiles('subprojects/llvm.wrap', 'subprojects/packagefiles/llvm/*') }} + fail-on-cache-miss: true + path: | + ./build/llvm + ./build/zlib + + - name: Install dependencies + run: | + apt-get update + apt-get install -y build-essential ninja-build cmake flex bison + + - name: Install uv + uses: astral-sh/setup-uv@v7 + + - name: Setup ccache + uses: hendrikmuhs/ccache-action@v1.2 + with: + key: ccache-standalone-${{ runner.os }} + + - name: Build standalone + run: | + mkdir build/build-zlib + touch build/build-zlib/.stamp + touch build/zlib/.stamp + mkdir build/build-llvm + touch build/build-llvm/.stamp + touch build/llvm/.stamp + uv venv + make standalone + + - uses: actions/upload-artifact@v4 + with: + name: standalone + path: dist/usr/bin/rustica-engine + diff --git a/.gitignore b/.gitignore index fa35ea6..88d6dd9 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,6 @@ /.idea/ -/*.so -/src/**/*.bc -/src/**/*.o -/vendor/ +/.venv/ +/build/ +/data/ +/dist/ +/.python-version diff --git a/Makefile b/Makefile index bff4ca0..5dbb790 100644 --- a/Makefile +++ b/Makefile @@ -1,349 +1,104 @@ -# Shared global config -DEV = 0 -DEBUG = 0 -GC = 1 -BUNDLE_LLVM = 0 -VENDOR_DIR = vendor -WAMR_VERSION = 2.1.2 -LLHTTP_VERSION = 9.2.1 -MODULE_big = rustica-engine -SQL_BACKDOOR = 0 +BUILD_DIR = $(shell pwd)/build +DIST_DIR = $(shell pwd)/dist +DEV_DATA_DIR = $(shell pwd)/data +DEV_LLVM_DIR = /usr/lib/llvm18 -# Vendor paths -WAMR_DIR = $(VENDOR_DIR)/wamr-$(WAMR_VERSION) -WAMR_CORE_ROOT = $(WAMR_DIR)/core -WAMR_IWASM_ROOT = $(WAMR_CORE_ROOT)/iwasm -WAMR_SHARED_ROOT = $(WAMR_CORE_ROOT)/shared -WAMR_TARBALL = $(VENDOR_DIR)/wamr-$(WAMR_VERSION).tar.gz -LLHTTP_TARBALL = $(VENDOR_DIR)/llhttp-$(LLHTTP_VERSION).tar.gz -LLHTTP_SRC = $(VENDOR_DIR)/llhttp-$(LLHTTP_VERSION) +# Default target: build for development +.PHONY: build +build: $(BUILD_DIR)/install -# PostgreSQL for development -ifeq ($(DEV),1) -DEV_PG_VERSION = 16.3 -DEV_PG_TARBALL = $(VENDOR_DIR)/pg-$(DEV_PG_VERSION).tar.gz -DEV_PG_SRC = $(VENDOR_DIR)/pg-$(DEV_PG_VERSION) -DEV_PG_INSTALL = $(VENDOR_DIR)/pg-$(DEV_PG_VERSION)-install -DEV_PG_DATA = $(VENDOR_DIR)/pg-$(DEV_PG_VERSION)-data -DEV_PG_LOG = $(VENDOR_DIR)/pg-$(DEV_PG_VERSION).log -endif +$(BUILD_DIR)/build/.stamp: + uv run meson.py setup $(BUILD_DIR)/build --prefix=/ -Dllvm_dir=$(DEV_LLVM_DIR) + touch $@ -ifeq ($(BUNDLE_LLVM),1) -LLVM_BUILD_DIR = $(WAMR_CORE_ROOT)/deps/llvm/build -endif - -# PGXS config begin -OBJS = \ - $(WAMR_SHARED_ROOT)/platform/linux/platform_init.o \ - $(WAMR_SHARED_ROOT)/platform/common/posix/posix_thread.o \ - $(WAMR_SHARED_ROOT)/platform/common/posix/posix_time.o \ - $(WAMR_SHARED_ROOT)/platform/common/posix/posix_malloc.o \ - $(WAMR_SHARED_ROOT)/platform/common/posix/posix_memmap.o \ - $(WAMR_SHARED_ROOT)/mem-alloc/mem_alloc.o \ - $(WAMR_SHARED_ROOT)/mem-alloc/ems/ems_kfc.o \ - $(WAMR_SHARED_ROOT)/mem-alloc/ems/ems_alloc.o \ - $(WAMR_SHARED_ROOT)/mem-alloc/ems/ems_hmu.o \ - $(WAMR_SHARED_ROOT)/utils/bh_assert.o \ - $(WAMR_SHARED_ROOT)/utils/bh_bitmap.o \ - $(WAMR_SHARED_ROOT)/utils/bh_common.o \ - $(WAMR_SHARED_ROOT)/utils/bh_hashmap.o \ - $(WAMR_SHARED_ROOT)/utils/bh_leb128.o \ - $(WAMR_SHARED_ROOT)/utils/bh_list.o \ - $(WAMR_SHARED_ROOT)/utils/bh_log.o \ - $(WAMR_SHARED_ROOT)/utils/bh_queue.o \ - $(WAMR_SHARED_ROOT)/utils/bh_vector.o \ - $(WAMR_SHARED_ROOT)/utils/runtime_timer.o \ - $(WAMR_IWASM_ROOT)/common/wasm_application.o \ - $(WAMR_IWASM_ROOT)/common/wasm_runtime_common.o \ - $(WAMR_IWASM_ROOT)/common/wasm_native.o \ - $(WAMR_IWASM_ROOT)/common/wasm_exec_env.o \ - $(WAMR_IWASM_ROOT)/common/wasm_loader_common.o \ - $(WAMR_IWASM_ROOT)/common/wasm_memory.o \ - $(WAMR_IWASM_ROOT)/common/wasm_c_api.o \ - $(WAMR_IWASM_ROOT)/aot/aot_loader.o \ - $(WAMR_IWASM_ROOT)/aot/arch/aot_reloc_x86_64.o \ - $(WAMR_IWASM_ROOT)/aot/aot_runtime.o \ - $(WAMR_IWASM_ROOT)/aot/aot_intrinsic.o \ - $(WAMR_IWASM_ROOT)/compilation/aot.o \ - $(WAMR_IWASM_ROOT)/compilation/aot_compiler.o \ - $(WAMR_IWASM_ROOT)/compilation/aot_emit_aot_file.o \ - $(WAMR_IWASM_ROOT)/compilation/aot_emit_compare.o \ - $(WAMR_IWASM_ROOT)/compilation/aot_emit_const.o \ - $(WAMR_IWASM_ROOT)/compilation/aot_emit_control.o \ - $(WAMR_IWASM_ROOT)/compilation/aot_emit_conversion.o \ - $(WAMR_IWASM_ROOT)/compilation/aot_emit_exception.o \ - $(WAMR_IWASM_ROOT)/compilation/aot_emit_function.o \ - $(WAMR_IWASM_ROOT)/compilation/aot_emit_memory.o \ - $(WAMR_IWASM_ROOT)/compilation/aot_emit_numberic.o \ - $(WAMR_IWASM_ROOT)/compilation/aot_emit_parametric.o \ - $(WAMR_IWASM_ROOT)/compilation/aot_emit_stringref.o \ - $(WAMR_IWASM_ROOT)/compilation/aot_emit_table.o \ - $(WAMR_IWASM_ROOT)/compilation/aot_emit_variable.o \ - $(WAMR_IWASM_ROOT)/compilation/aot_llvm.o \ - $(WAMR_IWASM_ROOT)/compilation/aot_llvm_extra2.o \ - $(WAMR_IWASM_ROOT)/compilation/aot_llvm_extra.o \ - $(WAMR_IWASM_ROOT)/compilation/aot_orc_extra2.o \ - $(WAMR_IWASM_ROOT)/compilation/aot_orc_extra.o \ - $(WAMR_IWASM_ROOT)/compilation/simd/simd_access_lanes.o \ - $(WAMR_IWASM_ROOT)/compilation/simd/simd_bitmask_extracts.o \ - $(WAMR_IWASM_ROOT)/compilation/simd/simd_bit_shifts.o \ - $(WAMR_IWASM_ROOT)/compilation/simd/simd_bitwise_ops.o \ - $(WAMR_IWASM_ROOT)/compilation/simd/simd_bool_reductions.o \ - $(WAMR_IWASM_ROOT)/compilation/simd/simd_common.o \ - $(WAMR_IWASM_ROOT)/compilation/simd/simd_comparisons.o \ - $(WAMR_IWASM_ROOT)/compilation/simd/simd_construct_values.o \ - $(WAMR_IWASM_ROOT)/compilation/simd/simd_conversions.o \ - $(WAMR_IWASM_ROOT)/compilation/simd/simd_floating_point.o \ - $(WAMR_IWASM_ROOT)/compilation/simd/simd_int_arith.o \ - $(WAMR_IWASM_ROOT)/compilation/simd/simd_load_store.o \ - $(WAMR_IWASM_ROOT)/compilation/simd/simd_sat_int_arith.o \ - $(WAMR_IWASM_ROOT)/interpreter/wasm_runtime.o \ - $(WAMR_IWASM_ROOT)/interpreter/wasm_loader.o \ - $(WAMR_IWASM_ROOT)/interpreter/wasm_interp_classic.o \ - $(LLHTTP_SRC)/src/api.o \ - $(LLHTTP_SRC)/src/http.o \ - $(LLHTTP_SRC)/src/llhttp.o \ - $(patsubst %.c,%.o,$(shell find src -type f -name "*.c")) - -WAMR_DEFINES = \ - -DBUILD_TARGET_X86_64 \ - -DBH_MALLOC=wasm_runtime_malloc \ - -DBH_FREE=wasm_runtime_free \ - -DWASM_ENABLE_LOG=1 \ - -DWASM_ENABLE_AOT=1 \ - -DWASM_ENABLE_AOT_INTRINSICS=1 \ - -DWASM_ENABLE_QUICK_AOT_ENTRY=1 \ - -DWASM_ENABLE_WORD_ALIGN_READ=0 \ - -DWASM_MEM_DUAL_BUS_MIRROR=0 \ - -DWASM_ENABLE_FAST_INTERP=0 \ - -DWASM_ENABLE_INTERP=1 \ - -DWASM_ENABLE_MINI_LOADER=0 \ - -DWASM_ENABLE_SHARED_MEMORY=0 \ - -DWASM_ENABLE_BULK_MEMORY=1 \ - -DWASM_ENABLE_LIBC_BUILTIN=0 \ - -DWASM_CONFIGURABLE_BOUNDS_CHECKS=0 \ - -DWASM_ENABLE_LIBC_WASI=0 \ - -DWASM_ENABLE_MODULE_INST_CONTEXT=1 \ - -DWASM_ENABLE_MULTI_MODULE=1 \ - -DWASM_ENABLE_THREAD_MGR=0 \ - -DWASM_ENABLE_LIB_WASI_THREADS=0 \ - -DWASM_ENABLE_LIB_PTHREAD=0 \ - -DWASM_ENABLE_LIB_PTHREAD_SEMAPHORE=0 \ - -DWASM_DISABLE_HW_BOUND_CHECK=0 \ - -DWASM_DISABLE_STACK_HW_BOUND_CHECK=0 \ - -DWASM_DISABLE_WAKEUP_BLOCKING_OP=1 \ - -DWASM_DISABLE_WRITE_GS_BASE=1 \ - -DWASM_ENABLE_LOAD_CUSTOM_SECTION=1 \ - -DWASM_ENABLE_CUSTOM_NAME_SECTION=1 \ - -DWASM_ENABLE_GLOBAL_HEAP_POOL=0 \ - -DWASM_MEM_ALLOC_WITH_USAGE=0 \ - -DWASM_ENABLE_SPEC_TEST=0 \ - -DWASM_ENABLE_REF_TYPES=1 \ - -DWASM_ENABLE_TAIL_CALL=1 \ - -DWASM_ENABLE_EXCE_HANDLING=0 \ - -DWASM_ENABLE_TAGS=0 \ - -DWASM_ENABLE_WAMR_COMPILER=1 \ - -DWASM_ENABLE_SIMD=1 \ - -DWASM_HAVE_MREMAP=1 \ - -DWASM_CONFIGURABLE_BOUNDS_CHECKS=0 \ - -DWASM_ENABLE_AOT_STACK_FRAME=1 \ - -DWASM_ENABLE_DUMP_CALL_STACK=1 \ - -DWASM_ENABLE_HEAP_AUX_STACK_ALLOCATION=1 \ - -DWASM_ENABLE_MEMORY64=0 - -ALL_INCLUDES = \ - -Isrc \ - -I$(WAMR_CORE_ROOT) \ - -I$(WAMR_IWASM_ROOT)/include \ - -I$(WAMR_IWASM_ROOT)/common \ - -I$(WAMR_IWASM_ROOT)/aot \ - -I$(WAMR_IWASM_ROOT)/compilation \ - -I$(WAMR_IWASM_ROOT)/interpreter \ - -I$(WAMR_SHARED_ROOT)/include \ - -I$(WAMR_SHARED_ROOT)/platform/include \ - -I$(WAMR_SHARED_ROOT)/platform/linux \ - -I$(WAMR_SHARED_ROOT)/utils \ - -I$(WAMR_SHARED_ROOT)/mem-alloc \ - -I$(LLHTTP_SRC)/include - -ifeq ($(DEBUG),1) - WAMR_DEFINES += \ - -DWASM_ENABLE_PERF_PROFILING=0 \ - -DWASM_ENABLE_GC_PERF_PROFILING=0 \ - -DWASM_ENABLE_LINUX_PERF=1 \ - -DWASM_ENABLE_MEMORY_PROFILING=1 \ - -DWASM_ENABLE_MEMORY_TRACING=1 \ - -DBH_DEBUG=1 -# -DWASM_ENABLE_DEBUG_AOT=1 - OBJS += \ - $(WAMR_IWASM_ROOT)/aot/aot_perf_map.o \ - $(WAMR_IWASM_ROOT)/aot/debug/elf_parser.o -# $(WAMR_IWASM_ROOT)/aot/debug/jit_debug.o \ -# $(WAMR_IWASM_ROOT)/compilation/debug/dwarf_extractor.o - ALL_INCLUDES += \ - -I$(WAMR_IWASM_ROOT)/aot/debug \ - -I$(WAMR_IWASM_ROOT)/compilation/debug - SHLIB_LINK += -llldb - PG_CFLAGS += -g -O0 -Wno-incompatible-pointer-types - PG_CXXFLAGS += -g -O0 -endif - -ifeq ($(GC),1) - WAMR_DEFINES += \ - -DWASM_ENABLE_GC=1 \ - -DWASM_GC_MANUALLY=0 - OBJS += \ - $(WAMR_SHARED_ROOT)/mem-alloc/ems/ems_gc.o \ - $(WAMR_IWASM_ROOT)/common/gc/gc_common.o \ - $(WAMR_IWASM_ROOT)/common/gc/gc_type.o \ - $(WAMR_IWASM_ROOT)/common/gc/gc_object.o \ - $(WAMR_IWASM_ROOT)/compilation/aot_emit_gc.o - ALL_INCLUDES += \ - -I$(WAMR_IWASM_ROOT)/common/gc -endif - -ifeq ($(BUNDLE_LLVM),1) - ALL_INCLUDES += \ - -I$(LLVM_BUILD_DIR)/include - SHLIB_LINK += \ - -Wl,--whole-archive \ - $(LLVM_BUILD_DIR)/lib/*.a \ - -Wl,--no-whole-archive -else - SHLIB_LINK += -lLLVM -endif - -ifeq ($(SQL_BACKDOOR),1) - WAMR_DEFINES += -DRUSTICA_SQL_BACKDOOR=1 -endif - -PG_CFLAGS += \ - -Wno-vla \ - -Wno-int-conversion \ - -Wno-declaration-after-statement \ - -Wno-missing-prototypes \ - -Wno-implicit-function-declaration - -PG_CPPFLAGS += $(WAMR_DEFINES) $(ALL_INCLUDES) -PG_CXXFLAGS += -fno-rtti - -SHLIB_LINK += -lstdc++ \ - $(WAMR_IWASM_ROOT)/common/arch/invokeNative_em64_simd.o - -EXTENSION = rustica-engine -DATA = sql/rustica-engine--1.0.sql - -ifeq ($(DEV),1) -include $(DEV_PG_INSTALL)/.stub -PG_CONFIG = $(DEV_PG_INSTALL)/bin/pg_config -else -PG_CONFIG = pg_config -endif -PGXS := $(shell $(PG_CONFIG) --pgxs) - -include $(PGXS) -# PGXS config end - -# WAMR source -$(WAMR_TARBALL): - mkdir -p $(VENDOR_DIR) - wget -O $(WAMR_TARBALL) \ - "https://github.com/bytecodealliance/wasm-micro-runtime/archive/refs/tags/WAMR-$(WAMR_VERSION).tar.gz" - -$(WAMR_DIR)/.stub: $(WAMR_TARBALL) - mkdir -p $(WAMR_DIR) - tar xvf $(WAMR_TARBALL) -C $(WAMR_DIR) --strip-components=1 - patch -p1 -d $(WAMR_DIR) < patches/0001-Support-circular-calls-when-multi-module-enabled.patch - patch -p1 -d $(WAMR_DIR) < patches/0002-wamrc-allow-building-without-DUMP_CALL_STACK.patch - patch -p1 -d $(WAMR_DIR) < patches/0003-fix-parameter-handling-in-wasm_loader-with-GC-enable.patch - patch -p1 -d $(WAMR_DIR) < patches/0004-Tweak-submodule-loading-hooks.patch - patch -p1 -d $(WAMR_DIR) < patches/0005-Support-custom-global-resolver.patch - echo > $(WAMR_DIR)/.stub -ifeq ($(BUNDLE_LLVM),1) - cd $(WAMR_DIR)/wamr-compiler && python3 -m pip install -r ../build-scripts/requirements.txt && python3 ../build-scripts/build_llvm.py -endif - -include $(WAMR_DIR)/.stub - -# Include ASM manually because LLVM can't generate bytecode from ASM -$(WAMR_IWASM_ROOT)/common/arch/invokeNative_em64_simd.s: $(WAMR_DIR)/.stub - -%.o : %.s - @if test ! -d $(DEPDIR); then mkdir -p $(DEPDIR); fi - $(COMPILE.c) -o $@ $< -MMD -MP -MF $(DEPDIR)/$(*F).Po - -all-shared-lib: $(WAMR_IWASM_ROOT)/common/arch/invokeNative_em64_simd.o - -# llhttp source -$(LLHTTP_TARBALL): - mkdir -p $(VENDOR_DIR) - wget -O $(LLHTTP_TARBALL) \ - "https://github.com/nodejs/llhttp/archive/refs/tags/release/v$(LLHTTP_VERSION).tar.gz" - -$(LLHTTP_SRC)/.stub: $(LLHTTP_TARBALL) - mkdir -p $(LLHTTP_SRC) - tar xvf $(LLHTTP_TARBALL) -C $(LLHTTP_SRC) --strip-components=1 - echo > $(LLHTTP_SRC)/.stub - -include $(LLHTTP_SRC)/.stub - -# Development commands -ifeq ($(DEV),1) -$(DEV_PG_TARBALL): - mkdir -p $(VENDOR_DIR) - wget -O $(DEV_PG_TARBALL) \ - "https://ftp.postgresql.org/pub/source/v$(DEV_PG_VERSION)/postgresql-$(DEV_PG_VERSION).tar.gz" - -$(DEV_PG_SRC): $(DEV_PG_TARBALL) - mkdir -p $(DEV_PG_SRC) - tar xvf $(DEV_PG_TARBALL) -C $(DEV_PG_SRC) --strip-components=1 - -CLEAN_ENV = env -i PATH=$(PATH) HOME=$(HOME) USER=$(USER) CFLAGS=-O0 -$(DEV_PG_INSTALL): $(DEV_PG_SRC) - mkdir -p $(DEV_PG_INSTALL) - $(eval DEV_PG_INSTALL_PREFIX := $(shell realpath $(DEV_PG_INSTALL))) - cd $(DEV_PG_SRC) && \ - $(CLEAN_ENV) ./configure \ - --prefix $(DEV_PG_INSTALL_PREFIX) \ - --with-uuid=e2fs \ - --enable-debug \ - --enable-cassert \ - --enable-depend \ - && \ - $(CLEAN_ENV) $(MAKE) -j $(shell nproc) && \ - $(CLEAN_ENV) $(MAKE) install && \ - $(CLEAN_ENV) $(MAKE) -C contrib install - -$(DEV_PG_INSTALL)/.stub: $(DEV_PG_INSTALL) - echo > $(DEV_PG_INSTALL)/.stub - -$(DEV_PG_DATA): - $(DEV_PG_INSTALL)/bin/initdb -D $(DEV_PG_DATA) - echo "shared_preload_libraries = 'rustica-engine.so'" >> $(DEV_PG_DATA)/postgresql.conf - echo "rustica.database = 'postgres'" >> $(DEV_PG_DATA)/postgresql.conf - -%.bc: - @true - -.PHONY: stop -stop: - @$(DEV_PG_INSTALL)/bin/pg_ctl -D $(DEV_PG_DATA) -l $(DEV_PG_LOG) stop 2>/dev/null || true - -.PHONY: reload -reload: $(DEV_PG_INSTALL) $(DEV_PG_DATA) stop install - $(DEV_PG_INSTALL)/bin/pg_ctl -D $(DEV_PG_DATA) -l $(DEV_PG_LOG) start || tail $(DEV_PG_LOG) +$(BUILD_DIR)/install/.stamp: $(BUILD_DIR)/build/.stamp + uv run meson.py install -C $(BUILD_DIR)/build --destdir=$(BUILD_DIR)/install + touch $@ +# Run a development PostgreSQL instance .PHONY: run -run: $(DEV_PG_INSTALL) $(DEV_PG_DATA) stop install - $(DEV_PG_INSTALL)/bin/postgres -D $(DEV_PG_DATA) - -endif - -# All other commands -.PHONY: format -format: - find src -name '*.h' -o -name "*.c" | xargs clang-format -i - -.PHONY: nuke -nuke: clean - rm -rf $(VENDOR_DIR) +run: $(DEV_DATA_DIR)/.stamp + $(BUILD_DIR)/install/bin/postgres -D $(DEV_DATA_DIR) + +$(DEV_DATA_DIR)/.stamp: $(BUILD_DIR)/install/.stamp + $(BUILD_DIR)/install/bin/initdb --auth=trust -D $(DEV_DATA_DIR) + touch $@ + +# Build standalone binary with all dependencies embedded statically for production use +.PHONY: standalone +standalone: $(DIST_DIR)/usr/bin/rustica-engine + +$(DIST_DIR)/usr/bin/rustica-engine: $(BUILD_DIR)/llvm/.stamp + uv run meson.py \ + setup $(BUILD_DIR)/build \ + --prefix=/usr \ + --buildtype=release \ + -Dembed_libs=true \ + -Dllvm_dir=$(BUILD_DIR)/llvm \ + -Dzlib_dir=$(BUILD_DIR)/zlib + uv run meson.py \ + install -C $(BUILD_DIR)/build \ + --destdir=$(DIST_DIR) \ + --skip-subprojects \ + --tags standalone + strip $@ + +$(BUILD_DIR)/build-zlib/.stamp: + uv run meson.py \ + setup $(BUILD_DIR)/build-zlib \ + --prefix=$(BUILD_DIR)/zlib \ + --buildtype=release \ + -Dbuild_zlib_only=true + touch $@ + +$(BUILD_DIR)/zlib/.stamp: $(BUILD_DIR)/build-zlib/.stamp + uv run meson.py install -C $(BUILD_DIR)/build-zlib + touch $@ + +$(BUILD_DIR)/build-llvm/.stamp: $(BUILD_DIR)/zlib/.stamp + uv run meson.py \ + setup $(BUILD_DIR)/build-llvm \ + --prefix=$(BUILD_DIR)/llvm \ + --buildtype=release \ + -Dbuild_llvm_only=true \ + -Dzlib_dir=$(BUILD_DIR)/zlib + touch $@ + +$(BUILD_DIR)/llvm/.stamp: $(BUILD_DIR)/build-llvm/.stamp + uv run meson.py install -C $(BUILD_DIR)/build-llvm + touch $@ + +# Build PostgreSQL extension with LLVM embedded statically for production use +.PHONY: extension +extension: $(DIST_DIR)/usr/lib/postgresql/rustica-engine.so + +$(DIST_DIR)/usr/lib/postgresql/rustica-engine.so: $(BUILD_DIR)/llvm/.stamp + uv run meson.py \ + setup $(BUILD_DIR)/build \ + --prefix=/usr \ + --buildtype=release \ + -Dllvm_dir=$(BUILD_DIR)/llvm \ + -Dzlib_dir=$(BUILD_DIR)/zlib + uv run meson.py \ + install -C $(BUILD_DIR)/build \ + --destdir=$(DIST_DIR) \ + --skip-subprojects \ + --tags extension + strip $@ + +# Build both standalone binary and PostgreSQL extension for OS distribution packaging +.PHONY: dist +dist: + uv run meson.py setup $(BUILD_DIR)/build --prefix=/usr -Dllvm_dir=$(DEV_LLVM_DIR) --buildtype=release + uv run meson.py install -C $(BUILD_DIR)/build --destdir=$(DIST_DIR) --skip-subprojects + strip $(DIST_DIR)/usr/bin/rustica-engine $(DIST_DIR)/usr/lib/postgresql/rustica-engine.so + +# Delete all build artifacts and installed files for development +.PHONY: clean +clean: + rm -rf $(BUILD_DIR)/build $(BUILD_DIR)/install + +# Delete all build artifacts, development files, and distribution files +.PHONY: distclean +distclean: clean + rm -rf $(BUILD_DIR) $(DIST_DIR) $(DEV_DATA_DIR) diff --git a/README.md b/README.md index 98fb8d8..350d87b 100644 --- a/README.md +++ b/README.md @@ -11,81 +11,69 @@ modules in the database securely, turning your database into an API server. This project is a work in progress and not ready for production use. -## Design Goals +## Features * **Fast**: AoT-compiled WASM (by WAMR/LLVM) and prepared queries * **Secure**: strictly sandboxed in bgworker processes * **Native**: PostgreSQL types/Datums directly in the guest * **Zero-Copy**: operate on network buffers and database pages +Rustica Engine does not use WASI or Component Model, but defines a custom +set of FFIs at a finer granularity, providing optimized bindings for various +PostgreSQL data types and functions. -## Installation +Currently, the following programming languages can generate WebAssembly +modules suitable for the Rustica Engine: -1. Install system dependencies (Arch Linux) +* Rustica (using MoonGRES backend) +* MoonBit (via MoonGRES extension) - ``` - $ sudo pacman -S llvm postgresql - ``` - -2. Build and install - - ``` - $ make - $ sudo make install - ``` +Rustica Engine is also packaged as a standalone command-line application, +statically linked with PostgreSQL backend code, which can run the same +WebAssembly programs without starting a database server. +This is particularly useful for debugging and testing. ## Development +This project is configured with a modified Meson, built by uv, and uses Ninja +as the build system. The `Makefile` provides some convenient command wrappers. + * Install system dependencies (Arch Linux) ``` - $ sudo pacman -S llvm lldb + $ sudo pacman -S make gcc ninja uv llvm18 bison flex ``` * Build extension and run the dev Postgres: ``` - $ make run DEV=1 -j $(nproc) - ``` - -* When you changed settings in Makefile, rebuild extension files: - - ``` - $ make clean DEV=1 - ``` - -* When you need to nuke the environment: - - ``` - $ make nuke + $ make + $ make run ``` ## Testing -1. Convert WASM binary to octets for step 2: +1. Install MoonGRES: ``` - $ xxd -p target/wasm-gc/release/build/main/main.wasm | tr -d '\n' + $ curl ...TBD... | sh ``` -2. Deploy the WASM application: +2. Replace the `rustica-engine` bundled with MoonGRES with the one freshly built: ``` - $ psql -h /tmp postgres - postgres=# CREATE EXTENSION "rustica-engine" CASCADE; - postgres=# DELETE FROM rustica.queries; - postgres=# DELETE FROM rustica.modules; - postgres=# WITH wasm AS (SELECT '\x0061736d01000000010f035e7801600364007f7f017f600000020c0103656e760473656e6400010304030102020401000503010001060100070a01065f737461727400030801020901000c01010a21030a0020002001200210000b02000b110041004133fb0900004100413310011a0b0b36010133485454502f312e3020323030204f4b0d0a436f6e74656e742d4c656e6774683a2031320d0a0d0a68656c6c6f20776f726c640a'::bytea AS code), compiled AS (SELECT rustica.compile_wasm(code) AS result FROM wasm) INSERT INTO rustica.modules SELECT 'main', code, (result).bin_code, (result).heap_types FROM wasm, compiled RETURNING name; + $ ln -sf $(pwd)/install/bin/rustica-engine ~/.moon/bin/rustica-engine ``` -3. Invoke the API: +3. Run MoonBit core test suite: ``` - $ curl localhost:8080 + $ cd ~/.moon/lib/core && moon test --target moongres ``` + ## License This project is dual-licensed under: diff --git a/README.zh.md b/README.zh.md index bf351b0..0ca9f7e 100644 --- a/README.zh.md +++ b/README.zh.md @@ -12,79 +12,63 @@ 这个项目还在开发中,请勿用于生产环境。 -## 设计目标 +## 特性 * **快速**:使用 WAMR/LLVM,预编译 WASM 和查询语句 * **安全**:多进程模型,严格的隔离设计 * **原生**:镜像 PostgreSQL 的数据和类型 * **零拷贝**:直接访问网络缓冲区和数据库共享内存 +燕几图引擎没有使用 WASI 或是 Component Model,而是在更细的粒度上定义了一套 +FFI 接口,为各种 PostgreSQL 的数据类型和函数提供了更优化的封装。 -## 安装 +目前,以下编程语言可以生成适用于燕几图引擎的 WebAssembly 模块: -1. 安装系统依赖 (以 Arch Linux 为例): +* 燕几图编程语言(使用 MoonGRES 后端) +* 月兔编程语言(通过 MoonGRES 扩展) - ``` - $ sudo pacman -S llvm postgresql - ``` - -2. 构建并安装: - - ``` - $ make - $ sudo make install - ``` +燕几图引擎还有一种独立的命令行形态,静态链接了 PostgreSQL +的后端代码,可以在不启动数据库的情况下,作为运行时来执行相同的 +WebAssembly 程序,这对于调试和测试非常有用。 ## 开发 +此项目由改装过的 Meson 配置,Ninja 构建,而 Meson 本身的改装由 uv +来跑。`Makefile` 只提供一些便捷的命令封装。 + * 安装系统依赖 (以 Arch Linux 为例): ``` - $ sudo pacman -S llvm lldb + $ sudo pacman -S make gcc ninja uv llvm18 bison flex ``` * 构建扩展程序并运行开发版的 Postgres: ``` - $ make run DEV=1 -j $(nproc) - ``` - -* 当你修改了 Makefile 中的设置时,重新构建扩展程序: - - ``` - $ make clean DEV=1 - ``` - -* 彻底清空构建文件: - - ``` - $ make nuke + $ make + $ make run ``` ## 测试 -1. 将 WASM 二进制文件转换为八进制数,以便进行下一步操作: +1. 安装 MoonGRES: ``` - $ xxd -p target/wasm-gc/release/build/main/main.wasm | tr -d '\n' + $ curl ...TBD... | sh ``` -2. 部署 WASM 应用程序: +2. 用之前构建的 `rustica-engine` 替代 MoonGRES 自带的 `rustica-engine`: ``` - $ psql -h /tmp postgres - postgres=# CREATE EXTENSION "rustica-engine" CASCADE; - postgres=# DELETE FROM rustica.queries; - postgres=# DELETE FROM rustica.modules; - postgres=# WITH wasm AS (SELECT '\x0061736d01000000010f035e7801600364007f7f017f600000020c0103656e760473656e6400010304030102020401000503010001060100070a01065f737461727400030801020901000c01010a21030a0020002001200210000b02000b110041004133fb0900004100413310011a0b0b36010133485454502f312e3020323030204f4b0d0a436f6e74656e742d4c656e6774683a2031320d0a0d0a68656c6c6f20776f726c640a'::bytea AS code), compiled AS (SELECT rustica.compile_wasm(code) AS result FROM wasm) INSERT INTO rustica.modules SELECT 'main', code, (result).bin_code, (result).heap_types FROM wasm, compiled RETURNING name; + $ ln -sf $(pwd)/install/bin/rustica-engine ~/.moon/bin/rustica-engine ``` -3. 访问 API: +3. 运行 MoonBit core 测试套件: ``` - $ curl localhost:8080 + $ cd ~/.moon/lib/core && moon test --target moongres ``` diff --git a/dist/PKGBUILD b/dist/PKGBUILD deleted file mode 100644 index bda056a..0000000 --- a/dist/PKGBUILD +++ /dev/null @@ -1,38 +0,0 @@ -# Maintainer: yanji tech -pkgname=rustica-wamr -pkgver=1.0 -pkgrel=1 -pkgdesc="Rustica Engine - Postgres as an API Server!" -arch=('x86_64') -url="https://yanji.tech/" -license=('MulanPSL-v2') -depends=('postgresql' 'llvm') -makedepends=() -checkdepends=() -optdepends=() -backup=() -options=() -install= -_wamr_revision='d3e89895be21e976231efed50337ac2518f74041' -source=( - "git+file://$(realpath ..)" - "https://github.com/bytecodealliance/wasm-micro-runtime/archive/${_wamr_revision}.zip") -sha256sums=('SKIP' - 'e4ea0f9c14714c2342feb447f58206349921136d9b0743c0ae400627ce1848bc') - -prepare() { - cd "${pkgname}" - mkdir -p vendor - rm -f "vendor/wamr-2.1.0" - ln -s "${srcdir}/wasm-micro-runtime-${_wamr_revision}/" "vendor/wamr-2.1.0" -} - -build() { - cd "$pkgname" - make -} - -package() { - cd "$pkgname" - make DESTDIR="${pkgdir}" install -} diff --git a/meson.build b/meson.build new file mode 100644 index 0000000..a5effeb --- /dev/null +++ b/meson.build @@ -0,0 +1,319 @@ +# SPDX-FileCopyrightText: 2025 燕几(北京)科技有限公司 +# SPDX-License-Identifier: Apache-2.0 OR MulanPSL-2.0 + +project( + 'rustica-engine', 'c', + version : '1.0.0', + default_options : [] +) + +fs = import('fs') + +if get_option('build_zlib_only') + subproject('zlib', default_options: ['default_library=static']) + subdir_done() +elif get_option('build_llvm_only') + subproject('llvm', default_options: ['zlib_dir=' + get_option('zlib_dir')]) + subdir_done() +endif + +if get_option('embed_libs') + add_project_arguments('-static-libstdc++', '-static-libgcc', language: ['c', 'cpp']) + subproject('lz4', default_options: ['default_library=static']) + subproject( + 'util-linux', + default_options: [ + 'default_library=static', + 'tinfo=disabled', + 'ncursesw=disabled', + 'ncurses=disabled', + 'slang=disabled', + 'cryptsetup=disabled', + 'cryptsetup-dlopen=disabled', + 'zlib=disabled', + 'readline=disabled', + 'nls=disabled', + 'libutil=disabled', + 'libutempter=disabled', + 'libpcre2-posix=disabled', + 'libuser=disabled', + 'selinux=disabled', + 'audit=disabled', + 'smack=disabled', + 'magic=disabled', + 'econf=disabled', + 'systemd=disabled', + 'sysvinit=disabled', + 'btrfs=disabled', + 'widechar=disabled', + 'translate-docs=disabled', + 'cryptsetup=disabled', + 'build-plymouth-support=disabled', + 'build-python=disabled', + 'python=disabled', + 'build-libblkid=disabled', + 'build-liblastlog2=disabled', + 'build-pam-lastlog2=disabled', + 'build-libmount=disabled', + 'build-libsmartcols=disabled', + 'build-libfdisk=disabled', + 'build-fdisks=disabled', + 'build-mount=disabled', + 'build-swapon=disabled', + 'build-swapoff=disabled', + 'build-chcpu=disabled', + 'build-losetup=disabled', + 'build-zramctl=disabled', + 'build-lsns=disabled', + 'build-mkfs=disabled', + 'build-fsck=disabled', + 'build-partx=disabled', + 'build-script=disabled', + 'build-scriptutils=disabled', + 'build-bits=disabled', + 'build-col=disabled', + 'build-colcrt=disabled', + 'build-colrm=disabled', + 'build-rev=disabled', + 'build-uuidd=disabled', + 'build-choom=disabled', + 'build-isosize=disabled', + 'build-waitpid=disabled', + 'build-wipefs=disabled', + 'build-mountpoint=disabled', + 'build-fallocate=disabled', + 'build-unshare=disabled', + 'build-nsenter=disabled', + 'build-setpriv=disabled', + 'build-hardlink=disabled', + 'build-eject=disabled', + 'build-agetty=disabled', + 'build-cramfs=disabled', + 'build-bfs=disabled', + 'build-minix=disabled', + 'build-fdformat=disabled', + 'build-blockdev=disabled', + 'build-hwclock=disabled', + 'build-lslogins=disabled', + 'build-wdctl=disabled', + 'build-cal=disabled', + 'build-logger=disabled', + 'build-look=disabled', + 'build-mcookie=disabled', + 'build-namei=disabled', + 'build-whereis=disabled', + 'build-lsblk=disabled', + 'build-lslocks=disabled', + 'build-findmnt=disabled', + 'build-lsfd=disabled', + 'build-switch_root=disabled', + 'build-pivot_root=disabled', + 'build-flock=disabled', + 'build-lsmem=disabled', + 'build-lsirq=disabled', + 'build-irqtop=disabled', + 'build-chmem=disabled', + 'build-ipcmk=disabled', + 'build-ipcrm=disabled', + 'build-ipcs=disabled', + 'build-rfkill=disabled', + 'build-tunelp=disabled', + 'build-fstrim=disabled', + 'build-dmesg=disabled', + 'build-ctrlaltdel=disabled', + 'build-exch=disabled', + 'build-fsfreeze=disabled', + 'build-blkdiscard=disabled', + 'build-blkzone=disabled', + 'build-blkpr=disabled', + 'build-ldattach=disabled', + 'build-rtcwake=disabled', + 'build-setarch=disabled', + 'build-kill=disabled', + 'build-last=disabled', + 'build-utmpdump=disabled', + 'build-line=disabled', + 'build-mesg=disabled', + 'build-raw=disabled', + 'build-rename=disabled', + 'build-vipw=disabled', + 'build-newgrp=disabled', + 'build-chfn-chsh=disabled', + 'build-login=disabled', + 'build-nologin=disabled', + 'build-sulogin=disabled', + 'build-su=disabled', + 'build-runuser=disabled', + 'build-ul=disabled', + 'build-more=disabled', + 'build-pg=disabled', + 'build-pipesz=disabled', + 'build-fadvise=disabled', + 'build-enosys=disabled', + 'build-lsclocks=disabled', + 'build-getopt=disabled', + 'build-setterm=disabled', + 'build-schedutils=disabled', + 'build-wall=disabled', + 'build-write=disabled', + 'build-bash-completion=disabled', + 'build-pylibmount=disabled', + 'build-hexdump=disabled', + 'build-findfs=disabled', + ], + ) + subproject('icu', default_options: ['default_library=static']) + subproject('openssl', default_options: ['default_library=static']) +endif + +# Include PostgreSQL subproject + +pg = subproject( + 'postgresql', + default_options: [ + 'prefix=postgres', + 'docs=disabled', # we don't need docs + 'readline=disabled', # for psql + 'zlib=disabled', # for pgdump/pgrestore + 'libxml=disabled', # for XML type + 'libxslt=disabled', # for XML transformations + 'systemd=disabled', # for systemd support + 'pam=disabled', # for PAM auth + 'gssapi=disabled', # for GSSAPI auth + 'ldap=disabled', # for LDAP lookup + 'zstd=disabled', # for WAL compression + 'plperl=disabled', + 'plpython=disabled', + 'pltcl=disabled', + 'uuid=e2fs', + ], +) + +add_project_arguments(pg.get_variable('cflags'), language: ['c']) +add_project_arguments(pg.get_variable('cppflags'), language: ['c']) +add_project_arguments(pg.get_variable('cflags_warn'), language: ['c']) +add_project_arguments(pg.get_variable('cxxflags'), language: ['cpp']) +add_project_arguments(pg.get_variable('cppflags'), language: ['cpp']) +add_project_arguments(pg.get_variable('cxxflags_warn'), language: ['cpp']) +add_project_link_arguments(pg.get_variable('ldflags'), language: ['c', 'cpp']) + +backend_link_with = pg.get_variable('backend_link_with') +backend_build_deps = pg.get_variable('backend_build_deps') + +backend_sources = [] +foreach src : pg.get_variable('backend_sources') + if not src.full_path().endswith('src/backend/main/main.c') + backend_sources += [src] + endif +endforeach + +postgres_pure_lib = static_library('postgres_lib', + backend_sources + pg.get_variable('timezone_sources') + pg.get_variable('generated_backend_sources'), + link_whole: backend_link_with, + dependencies: backend_build_deps, + c_pch: pg.get_variable('pch_postgres_h'), + kwargs: pg.get_variable('internal_lib_args'), +) + +# Include WAMR subproject + +cc = meson.get_compiler('c') +llvm_inc_flag = '-I' + (get_option('llvm_dir') / 'include') +wamr_c_flags = ['-Wno-incompatible-pointer-types', llvm_inc_flag] +# https://github.com/bytecodealliance/wasm-micro-runtime/issues/4640 +if cc.has_argument('-fzero-init-padding-bits=unions') + wamr_c_flags += ['-fzero-init-padding-bits=unions'] +endif + +cmake = import('cmake') +wamr_var = cmake.subproject_options() +wamr_var.add_cmake_defines({ + 'WAMR_BUILD_GC': 1, + 'WAMR_BUILD_LIBC_BUILTIN': 0, + 'WAMR_BUILD_LIBC_WASI': 0, + 'WAMR_BUILD_DUMP_CALL_STACK': 1, + 'WAMR_BUILD_AOT_STACK_FRAME': 1, + 'WAMR_BUILD_LOAD_CUSTOM_SECTION': 1, + 'WAMR_BUILD_CUSTOM_NAME_SECTION': 1, + 'WAMR_BUILD_TAIL_CALL': 1, + 'WAMR_BUILD_EXTENDED_CONST_EXPR': 1, + 'WAMR_BUILD_EXCE_HANDLING': 1, + 'WAMR_BUILD_JIT': 1, + + 'CMAKE_C_FLAGS': ' '.join(wamr_c_flags), + 'CMAKE_CXX_FLAGS': llvm_inc_flag, + 'WAMR_BH_VPRINTF': 'pg_log_vprintf', + 'WAMR_BH_LOG': 'pg_bh_log', + 'LLVM_DIR': get_option('llvm_dir') / 'lib/cmake/llvm', +}) +if get_option('zlib_dir') != '' + zlib_prefix = get_option('zlib_dir') + wamr_var.add_cmake_defines( + { + 'ZLIB_LIBRARY': zlib_prefix / 'lib' / 'libz.a', + 'ZLIB_INCLUDE_DIR': zlib_prefix / 'include', + } + ) +endif +wamr = cmake.subproject('wamr', options: wamr_var) +vmlib = wamr.dependency('vmlib') + +uncommon_shared_lib = shared_library('uncommon_shared', + wamr.get_cmake_variable('UNCOMMON_SHARED_SOURCE'), + dependencies: [vmlib], + c_args: ['-DBH_MALLOC=palloc', '-DBH_FREE=pfree'], + build_by_default: false, + install: false, +) + +# Build the Rustica Engine + +rustica_shared = files( + 'src/rustica/env.c', +) +rustica_deps = [vmlib, pg.get_variable('uuid')] +rustica_cargs = wamr.get_cmake_definitions('-DWASM') + +executable('rustica-engine', + [ + 'src/rustica/main.c', + 'src/rustica/moontest.c', + ], + sources: rustica_shared + pg.get_variable('post_export_backend_sources'), + objects: [ + postgres_pure_lib.extract_all_objects(recursive: false), + uncommon_shared_lib.extract_all_objects(recursive: false), + pg.get_variable('uuid_ossp').extract_all_objects(recursive: false), + ], + include_directories: 'src', + link_args: pg.get_variable('backend_link_args') + ( + get_option('embed_libs') ? ['-static-libstdc++', '-static-libgcc'] : [] + ), + link_with: backend_link_with, + link_depends: pg.get_variable('backend_link_depends'), + export_dynamic: true, + implib: 'postgres', + dependencies: backend_build_deps + rustica_deps, + kwargs: pg.get_variable('default_bin_args'), + c_args: rustica_cargs, + install_tag: 'standalone', +) + +pg_mod_args = pg.get_variable('pg_mod_args') +shared_module( + 'rustica-engine', + 'src/rustica/extension.c', + sources: rustica_shared, + include_directories: 'src', + c_args: rustica_cargs, + install_tag: 'extension', + kwargs: pg_mod_args + { + 'dependencies': rustica_deps + [pg_mod_args['dependencies']], + }, +) +install_data( + 'rustica-engine.control', + 'sql/rustica-engine--1.0.sql', + install_tag: 'extension', + kwargs: pg.get_variable('contrib_data_args'), +) diff --git a/meson.py b/meson.py new file mode 100755 index 0000000..eb48596 --- /dev/null +++ b/meson.py @@ -0,0 +1,98 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +# SPDX-FileCopyrightText: 2025 燕几(北京)科技有限公司 +# SPDX-License-Identifier: Apache-2.0 OR MulanPSL-2.0 + +from __future__ import annotations +import pathlib +import re +import sys +import typing as T + +from mesonbuild.interpreterbase import noKwargs, typed_pos_args +from mesonbuild.cmake import interpreter +from mesonbuild.mesonmain import main +from mesonbuild.modules import cmake +from mesonbuild.mesonlib import File + +if T.TYPE_CHECKING: + from mesonbuild.modules import ModuleState + from mesonbuild.interpreter import SubprojectHolder + from mesonbuild.interpreterbase import InterpreterObject, TYPE_kwargs, TYPE_var + + +class CMakeSubproject(cmake.CMakeSubproject): + def __init__(self, subp: SubprojectHolder): + super().__init__(subp) + self.methods["get_cmake_variable"] = self.get_cmake_variable + self.methods["get_cmake_definitions"] = self.get_cmake_definitions + + @noKwargs + @typed_pos_args("cmake.subproject.get_cmake_variable", str, optargs=[str]) + def get_cmake_variable( + self, + state: ModuleState, + args: T.Tuple[str, T.Optional[str]], + kwargs: TYPE_kwargs, + ) -> T.Union[TYPE_var, InterpreterObject]: + rv = self.cm_interpreter.trace.get_cmake_var(args[0]) + return [File.from_absolute_file(x) for x in rv] + + @noKwargs + @typed_pos_args("cmake.subproject.get_cmake_definitions", str) + def get_cmake_definitions( + self, + state: ModuleState, + args: T.Tuple[str], + kwargs: TYPE_kwargs, + ) -> T.Union[TYPE_var, InterpreterObject]: + return [d for d in self.cm_interpreter.trace.definitions if d.startswith(args[0])] + + +class CMakeTraceParser(interpreter.CMakeTraceParser): + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + self.definitions = [] + self.functions["add_definitions"] = self.add_definitions + + def add_definitions(self, tline: CMakeTraceLine) -> None: + self.definitions.extend(tline.args) + + +class CMakeSubprojectOptions(cmake.CMakeSubprojectOptions): + def __init__(self): + super().__init__() + self.methods["add_extra_cmake_option"] = self.add_extra_cmake_option + + @typed_pos_args('subproject_options.add_extra_cmake_option', str) + @noKwargs + def add_extra_cmake_option( + self, + state: ModuleState, + args: T.Tuple[str], + kwargs: TYPE_kwargs, + ) -> None: + self.cmake_options.append(args[0]) + + +class CMakeExecutor(interpreter.CMakeExecutor): + def call(self, args, *posargs, **kwargs): + new_args = [] + override_source = None + for a in args: + if a.startswith('-S'): + override_source = a[2:] + else: + new_args.append(a) + if override_source is not None: + new_args[-1] = str(pathlib.Path(new_args[-1]) / override_source) + return super().call(new_args, *posargs, **kwargs) + + +if __name__ == "__main__": + cmake.CMakeSubproject = CMakeSubproject + cmake.CMakeSubprojectOptions = CMakeSubprojectOptions + interpreter.CMakeExecutor = CMakeExecutor + interpreter.CMakeTraceParser = CMakeTraceParser + sys.argv[0] = re.sub(r"(-script\.pyw|\.exe)?$", "", sys.argv[0]) + sys.exit(main()) diff --git a/meson_options.txt b/meson_options.txt new file mode 100644 index 0000000..7db9b86 --- /dev/null +++ b/meson_options.txt @@ -0,0 +1,30 @@ +option( + 'embed_libs', + type: 'boolean', + value: false, + description: 'Link all dependencies statically except libc', +) +option( + 'llvm_dir', + type: 'string', + value: '', + description: 'Path to a pre-built LLVM toolchain to use for building WAMR', +) +option( + 'build_llvm_only', + type: 'boolean', + value: false, + description: 'Only build LLVM subproject and skip the rest', +) +option( + 'zlib_dir', + type: 'string', + value: '', + description: 'Path to a pre-installed zlib (e.g., /path/to/zlib) for building LLVM', +) +option( + 'build_zlib_only', + type: 'boolean', + value: false, + description: 'Only build zlib subproject and skip the rest', +) diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 0000000..18b6c42 --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,10 @@ +[project] +name = "rustica-engine" +version = "0.1.0" +description = "Add your description here" +readme = "README.md" +requires-python = ">=3.9" +dependencies = [ + "meson>=1.9.0", + "requests>=2.32.5", +] diff --git a/sql/rustica-engine--1.0.sql b/sql/rustica-engine--1.0.sql index 1751ede..d674c3d 100644 --- a/sql/rustica-engine--1.0.sql +++ b/sql/rustica-engine--1.0.sql @@ -1,7 +1,5 @@ -/* - * SPDX-FileCopyrightText: 2024 燕几(北京)科技有限公司 - * SPDX-License-Identifier: Apache-2.0 OR MulanPSL-2.0 - */ +-- SPDX-FileCopyrightText: 2024 燕几(北京)科技有限公司 +-- SPDX-License-Identifier: Apache-2.0 OR MulanPSL-2.0 CREATE SCHEMA rustica; diff --git a/src/rustica/adt/bytea.c b/src/rustica/adt/bytea.c index 0d54f42..d2ca757 100644 --- a/src/rustica/adt/bytea.c +++ b/src/rustica/adt/bytea.c @@ -1,7 +1,5 @@ -/* - * SPDX-FileCopyrightText: 2025 燕几(北京)科技有限公司 - * SPDX-License-Identifier: Apache-2.0 OR MulanPSL-2.0 - */ +// SPDX-FileCopyrightText: 2025 燕几(北京)科技有限公司 +// SPDX-License-Identifier: Apache-2.0 OR MulanPSL-2.0 #include "postgres.h" #include "mb/pg_wchar.h" diff --git a/src/rustica/adt/date.c b/src/rustica/adt/date.c index eeea872..5ca1e59 100644 --- a/src/rustica/adt/date.c +++ b/src/rustica/adt/date.c @@ -1,7 +1,5 @@ -/* - * SPDX-FileCopyrightText: 2025 燕几(北京)科技有限公司 - * SPDX-License-Identifier: Apache-2.0 OR MulanPSL-2.0 - */ +// SPDX-FileCopyrightText: 2025 燕几(北京)科技有限公司 +// SPDX-License-Identifier: Apache-2.0 OR MulanPSL-2.0 #include "postgres.h" #include "catalog/pg_type_d.h" diff --git a/src/rustica/adt/json.c b/src/rustica/adt/json.c index 40821ec..4117e28 100644 --- a/src/rustica/adt/json.c +++ b/src/rustica/adt/json.c @@ -1,7 +1,5 @@ -/* - * SPDX-FileCopyrightText: 2025 燕几(北京)科技有限公司 - * SPDX-License-Identifier: Apache-2.0 OR MulanPSL-2.0 - */ +// SPDX-FileCopyrightText: 2025 燕几(北京)科技有限公司 +// SPDX-License-Identifier: Apache-2.0 OR MulanPSL-2.0 #include "postgres.h" #include "catalog/pg_type_d.h" diff --git a/src/rustica/adt/jsonb.c b/src/rustica/adt/jsonb.c index 97ba747..2b18b1c 100644 --- a/src/rustica/adt/jsonb.c +++ b/src/rustica/adt/jsonb.c @@ -1,7 +1,5 @@ -/* - * SPDX-FileCopyrightText: 2025 燕几(北京)科技有限公司 - * SPDX-License-Identifier: Apache-2.0 OR MulanPSL-2.0 - */ +// SPDX-FileCopyrightText: 2025 燕几(北京)科技有限公司 +// SPDX-License-Identifier: Apache-2.0 OR MulanPSL-2.0 #include "postgres.h" #include "common/jsonapi.h" diff --git a/src/rustica/adt/primitives.c b/src/rustica/adt/primitives.c index 5ad9c63..ed2d786 100644 --- a/src/rustica/adt/primitives.c +++ b/src/rustica/adt/primitives.c @@ -1,7 +1,5 @@ -/* - * SPDX-FileCopyrightText: 2025 燕几(北京)科技有限公司 - * SPDX-License-Identifier: Apache-2.0 OR MulanPSL-2.0 - */ +// SPDX-FileCopyrightText: 2025 燕几(北京)科技有限公司 +// SPDX-License-Identifier: Apache-2.0 OR MulanPSL-2.0 #include "postgres.h" #include "utils/builtins.h" diff --git a/src/rustica/adt/stringbuilder.c b/src/rustica/adt/stringbuilder.c index 434ca73..2bb1820 100644 --- a/src/rustica/adt/stringbuilder.c +++ b/src/rustica/adt/stringbuilder.c @@ -1,7 +1,5 @@ -/* - * SPDX-FileCopyrightText: 2025 燕几(北京)科技有限公司 - * SPDX-License-Identifier: Apache-2.0 OR MulanPSL-2.0 - */ +// SPDX-FileCopyrightText: 2025 燕几(北京)科技有限公司 +// SPDX-License-Identifier: Apache-2.0 OR MulanPSL-2.0 #include "postgres.h" #include "varatt.h" diff --git a/src/rustica/adt/text.c b/src/rustica/adt/text.c index 1126db0..58fb5b1 100644 --- a/src/rustica/adt/text.c +++ b/src/rustica/adt/text.c @@ -1,7 +1,5 @@ -/* - * SPDX-FileCopyrightText: 2025 燕几(北京)科技有限公司 - * SPDX-License-Identifier: Apache-2.0 OR MulanPSL-2.0 - */ +// SPDX-FileCopyrightText: 2025 燕几(北京)科技有限公司 +// SPDX-License-Identifier: Apache-2.0 OR MulanPSL-2.0 #include "postgres.h" #include "fmgr.h" diff --git a/src/rustica/adt/timestamp.c b/src/rustica/adt/timestamp.c index 0da48a4..483819c 100644 --- a/src/rustica/adt/timestamp.c +++ b/src/rustica/adt/timestamp.c @@ -1,7 +1,5 @@ -/* - * SPDX-FileCopyrightText: 2025 燕几(北京)科技有限公司 - * SPDX-License-Identifier: Apache-2.0 OR MulanPSL-2.0 - */ +// SPDX-FileCopyrightText: 2025 燕几(北京)科技有限公司 +// SPDX-License-Identifier: Apache-2.0 OR MulanPSL-2.0 #include "postgres.h" #include "catalog/pg_type_d.h" diff --git a/src/rustica/adt/uuid.c b/src/rustica/adt/uuid.c index 67457d2..deaf83e 100644 --- a/src/rustica/adt/uuid.c +++ b/src/rustica/adt/uuid.c @@ -1,7 +1,5 @@ -/* - * SPDX-FileCopyrightText: 2025 燕几(北京)科技有限公司 - * SPDX-License-Identifier: Apache-2.0 OR MulanPSL-2.0 - */ +// SPDX-FileCopyrightText: 2025 燕几(北京)科技有限公司 +// SPDX-License-Identifier: Apache-2.0 OR MulanPSL-2.0 #include "postgres.h" #include "catalog/pg_type_d.h" diff --git a/src/rustica/compiler.c b/src/rustica/compiler.c index ba8efba..cc114ae 100644 --- a/src/rustica/compiler.c +++ b/src/rustica/compiler.c @@ -1,7 +1,5 @@ -/* - * SPDX-FileCopyrightText: 2024 燕几(北京)科技有限公司 - * SPDX-License-Identifier: Apache-2.0 OR MulanPSL-2.0 - */ +// SPDX-FileCopyrightText: 2024 燕几(北京)科技有限公司 +// SPDX-License-Identifier: Apache-2.0 OR MulanPSL-2.0 #include "postgres.h" #include "funcapi.h" diff --git a/src/rustica/compiler.h b/src/rustica/compiler.h index c500e21..b4346e5 100644 --- a/src/rustica/compiler.h +++ b/src/rustica/compiler.h @@ -1,7 +1,5 @@ -/* - * SPDX-FileCopyrightText: 2024 燕几(北京)科技有限公司 - * SPDX-License-Identifier: Apache-2.0 OR MulanPSL-2.0 - */ +// SPDX-FileCopyrightText: 2024 燕几(北京)科技有限公司 +// SPDX-License-Identifier: Apache-2.0 OR MulanPSL-2.0 #ifndef RUSTICA_COMPILER_H #define RUSTICA_COMPILER_H diff --git a/src/rustica/datatypes.c b/src/rustica/datatypes.c index 4a1370e..9a7df4f 100644 --- a/src/rustica/datatypes.c +++ b/src/rustica/datatypes.c @@ -1,7 +1,5 @@ -/* - * SPDX-FileCopyrightText: 2025 燕几(北京)科技有限公司 - * SPDX-License-Identifier: Apache-2.0 OR MulanPSL-2.0 - */ +// SPDX-FileCopyrightText: 2025 燕几(北京)科技有限公司 +// SPDX-License-Identifier: Apache-2.0 OR MulanPSL-2.0 #include "postgres.h" #include "utils/builtins.h" diff --git a/src/rustica/datatypes.h b/src/rustica/datatypes.h index 074078c..4e59536 100644 --- a/src/rustica/datatypes.h +++ b/src/rustica/datatypes.h @@ -1,7 +1,5 @@ -/* - * SPDX-FileCopyrightText: 2025 燕几(北京)科技有限公司 - * SPDX-License-Identifier: Apache-2.0 OR MulanPSL-2.0 - */ +// SPDX-FileCopyrightText: 2025 燕几(北京)科技有限公司 +// SPDX-License-Identifier: Apache-2.0 OR MulanPSL-2.0 #ifndef RUSTICA_DATATYPES_H #define RUSTICA_DATATYPES_H diff --git a/src/rustica/env.c b/src/rustica/env.c new file mode 100644 index 0000000..332b947 --- /dev/null +++ b/src/rustica/env.c @@ -0,0 +1,312 @@ +// SPDX-FileCopyrightText: 2025 燕几(北京)科技有限公司 +// SPDX-License-Identifier: Apache-2.0 OR MulanPSL-2.0 + +#include +#include +#include + +#include "postgres.h" +#include "mb/pg_wchar.h" +#include "portability/instr_time.h" + +#include "bh_log.h" + +#include "rustica/env.h" + +char **saved_argv; +int saved_argc; + +static void +obj_finalizer(const wasm_obj_t obj, void *data) { + rustica_value_t val = + (rustica_value_t)wasm_anyref_obj_get_value((wasm_anyref_obj_t)obj); + pfree(val); +} + +rustica_value_t +rustica_value_new(const uint8_t type, void *ptr, const size_t size) { + const rustica_value_t rv = palloc0(sizeof(RusticaValue) + size); + rv->type = type; + if (size == 0) { + rv->ptr = ptr; + } + else { + rv->data = rv->vardata; + if (ptr != NULL) + memcpy(rv->data, ptr, size); + } + return rv; +} + +wasm_externref_obj_t +rustica_value_to_wasm(wasm_exec_env_t exec_env, rustica_value_t val) { + wasm_externref_obj_t rv = wasm_externref_obj_new(exec_env, val); + wasm_obj_set_gc_finalizer(exec_env, + wasm_externref_obj_to_internal_obj(rv), + obj_finalizer, + exec_env); + return rv; +} + +rustica_value_t +rustica_value_from_wasm(wasm_obj_t refobj, uint8_t expected_type) { + wasm_obj_t anyref = + wasm_externref_obj_to_internal_obj((wasm_externref_obj_t)refobj); + rustica_value_t rv = + (rustica_value_t)wasm_anyref_obj_get_value((wasm_anyref_obj_t)anyref); + return rv->type == expected_type ? rv : NULL; +} + +static void +print_char(wasm_exec_env_t exec_env, int ch) { + char buf[5]; + const int len = pg_wchar2mb_with_len((pg_wchar *)&ch, buf, 1); + Assert(len < 5); + buf[len] = 0; + printf("%s", buf); +} + +static NativeSymbol spectest_symbols[] = { + { "print_char", print_char, "(i)", NULL }, +}; + +static void +exception_throw(wasm_exec_env_t exec_env) { + wasm_module_inst_t inst = wasm_runtime_get_module_inst(exec_env); + wasm_runtime_set_exception(inst, "panic"); +} + +static NativeSymbol exception_symbols[] = { + { "throw", exception_throw, "()", NULL }, +}; + +static StringReader * +fs_begin_read_string(wasm_exec_env_t exec_env, wasm_obj_t ref) { + rustica_value_t val = rustica_value_from_wasm(ref, RUSTICA_ENV_CSTRING); + StringReader *buf = palloc(sizeof(StringReader)); + buf->offset = 0; + buf->size = strlen(val->data); + buf->data = val->data; + return buf; +} + +static int32_t +fs_string_read_char(wasm_exec_env_t exec_env, StringReader *buf) { + int ch; + pg_wchar char_code[2] = { '?', 0 }; + if (buf->offset >= buf->size) { + return -1; // EOF + } + // Read the next Unicode char code using Postgres C functions + ch = pg_utf_mblen((unsigned char *)buf->data + buf->offset); + if (ch > 0) { + pg_encoding_mb2wchar_with_len(PG_UTF8, + buf->data + buf->offset, + char_code, + ch); + buf->offset += ch; + } + else { + // Invalid UTF-8 sequence, skip one byte + buf->offset += 1; + } + return (int32_t)char_code[0]; +} + +static void +fs_finish_read_string(wasm_exec_env_t exec_env, StringReader *buf) { + pfree(buf); +} + +static ArrayReader * +fs_begin_read_string_array(wasm_exec_env_t exec_env, wasm_obj_t ref) { + rustica_value_t val = + rustica_value_from_wasm(ref, RUSTICA_ENV_CSTRING_ARRAY); + ArrayReader *reader = palloc(sizeof(ArrayReader)); + reader->offset = 0; + reader->arr = val->arr; + return reader; +} + +static wasm_externref_obj_t +fs_string_array_read_string(wasm_exec_env_t exec_env, ArrayReader *reader) { + rustica_value_t rv; + if (reader->offset >= reader->arr->size) { + rv = rustica_value_new(RUSTICA_ENV_CSTRING, + "ffi_end_of_/string_array", + 0); + } + else { + rv = rustica_value_new(RUSTICA_ENV_CSTRING, + reader->arr->items[reader->offset], + 0); + reader->offset += 1; + } + return rustica_value_to_wasm(exec_env, rv); +} + +static void +fs_finish_read_string_array(wasm_exec_env_t exec_env, ArrayReader *reader) { + pfree(reader); +} + +static wasm_externref_obj_t +fs_current_dir(wasm_exec_env_t exec_env) { + char buf[1024]; + rustica_value_t rv; + + getcwd(buf, sizeof(buf)); + rv = rustica_value_new(RUSTICA_ENV_CSTRING, buf, strlen(buf) + 1); + return rustica_value_to_wasm(exec_env, rv); +} + +static wasm_externref_obj_t +fs_args_get(wasm_exec_env_t exec_env) { + // return sys argv as rustica_value_t + rustica_value_t rv = rustica_value_new(RUSTICA_ENV_CSTRING_ARRAY, + NULL, + sizeof(RusticaPointerArray) + + sizeof(char *) * saved_argc); + rv->arr->size = saved_argc; + for (int i = 0; i < saved_argc; i++) { + rv->arr->items[i] = saved_argv[i]; + } + return rustica_value_to_wasm(exec_env, rv); +} + +static NativeSymbol fs_symbols[] = { + { "begin_read_string", fs_begin_read_string, "(r)r", NULL }, + { "string_read_char", fs_string_read_char, "(r)i", NULL }, + { "finish_read_string", fs_finish_read_string, "(r)", NULL }, + { "begin_read_string_array", fs_begin_read_string_array, "(r)r", NULL }, + { "string_array_read_string", fs_string_array_read_string, "(r)r", NULL }, + { "finish_read_string_array", fs_finish_read_string_array, "(r)", NULL }, + { "current_dir", fs_current_dir, "()r", NULL }, + { "args_get", fs_args_get, "()r", NULL }, +}; + +static uint64_t +time_now(wasm_exec_env_t exec_env) { + // return current time in milliseconds since epoch + struct timespec ts; + clock_gettime(CLOCK_REALTIME, &ts); + return (uint64_t)ts.tv_sec * 1000 + ts.tv_nsec / 1000000; +} + +static wasm_externref_obj_t +time_instant_now(wasm_exec_env_t exec_env) { + rustica_value_t rv = + rustica_value_new(RUSTICA_ENV_INSTR_TIME, NULL, sizeof(instr_time)); + INSTR_TIME_SET_CURRENT(*rv->instr_time); + return rustica_value_to_wasm(exec_env, rv); +} + +static double +time_instant_elapsed_as_secs_f64(wasm_exec_env_t exec_env, wasm_obj_t ref) { + rustica_value_t val = rustica_value_from_wasm(ref, RUSTICA_ENV_INSTR_TIME); + instr_time it; + INSTR_TIME_SET_CURRENT(it); + INSTR_TIME_SUBTRACT(it, *val->instr_time); + return INSTR_TIME_GET_DOUBLE(it); +} + +static NativeSymbol time_symbols[] = { + { "now", time_now, "()I", NULL }, + { "instant_now", time_instant_now, "()r", NULL }, + { "instant_elapsed_as_secs_f64", + time_instant_elapsed_as_secs_f64, + "(r)F", + NULL }, +}; + +void +rustica_register_natives() { + if (!wasm_runtime_register_natives("spectest", + spectest_symbols, + sizeof(spectest_symbols) + / sizeof(NativeSymbol))) + ereport(ERROR, errmsg("Failed to register spectest natives")); + if (!wasm_runtime_register_natives("exception", + exception_symbols, + sizeof(exception_symbols) + / sizeof(NativeSymbol))) + ereport(ERROR, errmsg("Failed to register exception natives")); + if (!wasm_runtime_register_natives("__moonbit_fs_unstable", + fs_symbols, + sizeof(fs_symbols) + / sizeof(NativeSymbol))) + ereport(ERROR, errmsg("Failed to register fs natives")); + if (!wasm_runtime_register_natives("__moonbit_time_unstable", + time_symbols, + sizeof(time_symbols) + / sizeof(NativeSymbol))) + ereport(ERROR, errmsg("Failed to register time natives")); +} + +int +pg_log_vprintf(const char *format, va_list ap) { + int rv = 0; + ereport_domain(LOG, "WAMR", ({ + StringInfoData buf; + initStringInfo(&buf); + for (;;) { + const int needed = + appendStringInfoVA(&buf, format, ap); + if (needed == 0) + break; + enlargeStringInfo(&buf, needed); + } + while (buf.len > 0 && buf.data[buf.len - 1] == '\n') { + buf.data[buf.len - 1] = '\0'; + buf.len -= 1; + } + rv = buf.len; + errmsg_internal(buf.data); + pfree(buf.data); + })); + return rv; +} + +void +pg_bh_log(LogLevel log_level, const char *file, int line, const char *fmt, ...) { + int elevel = LOG; + switch (log_level) { + case BH_LOG_LEVEL_FATAL: + elevel = FATAL; + break; + case BH_LOG_LEVEL_ERROR: + elevel = ERROR; + break; + case BH_LOG_LEVEL_WARNING: + elevel = WARNING; + break; + case BH_LOG_LEVEL_DEBUG: + elevel = DEBUG1; + break; + case BH_LOG_LEVEL_VERBOSE: + elevel = DEBUG3; + break; + } + do { + pg_prevent_errno_in_scope(); + if (errstart(elevel, "WAMR")) { + StringInfoData buf; + initStringInfo(&buf); + for (;;) { + va_list ap; + int needed; + va_start(ap, fmt); + needed = appendStringInfoVA(&buf, fmt, ap); + va_end(ap); + if (needed == 0) + break; + enlargeStringInfo(&buf, needed); + } + errmsg_internal(buf.data); + pfree(buf.data); + errfinish(file, line, "-"); + } + if (elevel >= ERROR) + pg_unreachable(); + } while(0); +} diff --git a/src/rustica/env.h b/src/rustica/env.h new file mode 100644 index 0000000..40770f5 --- /dev/null +++ b/src/rustica/env.h @@ -0,0 +1,58 @@ +// SPDX-FileCopyrightText: 2025 燕几(北京)科技有限公司 +// SPDX-License-Identifier: Apache-2.0 OR MulanPSL-2.0 + +#ifndef RUSTICA_ENV_H +#define RUSTICA_ENV_H + +#include "portability/instr_time.h" +#include "gc_export.h" + +#define RUSTICA_ENV_CSTRING 0x01 +#define RUSTICA_ENV_CSTRING_ARRAY 0x02 +#define RUSTICA_ENV_INSTR_TIME 0x03 + +extern char **saved_argv; +extern int saved_argc; + +typedef struct RusticaPointerArray { + size_t size; + void *items[]; +} RusticaPointerArray; + +typedef struct RusticaValue { + uint8_t type; + union { + void *ptr; + char *data; + RusticaPointerArray *arr; + instr_time *instr_time; + }; + char vardata[]; +} RusticaValue; + +typedef RusticaValue *rustica_value_t; + +typedef struct StringReader { + uint32_t offset; + uint32_t size; + char *data; +} StringReader; + +typedef struct ArrayReader { + size_t offset; + RusticaPointerArray *arr; +} ArrayReader; + +rustica_value_t +rustica_value_new(uint8_t type, void *ptr, size_t size); + +wasm_externref_obj_t +rustica_value_to_wasm(wasm_exec_env_t exec_env, rustica_value_t val); + +rustica_value_t +rustica_value_from_wasm(wasm_obj_t refobj, uint8_t expected_type); + +void +rustica_register_natives(); + +#endif diff --git a/src/rustica/event_set.c b/src/rustica/event_set.c index eb36853..3346164 100644 --- a/src/rustica/event_set.c +++ b/src/rustica/event_set.c @@ -1,7 +1,5 @@ -/* - * SPDX-FileCopyrightText: 2024 燕几(北京)科技有限公司 - * SPDX-License-Identifier: Apache-2.0 OR MulanPSL-2.0 - */ +// SPDX-FileCopyrightText: 2024 燕几(北京)科技有限公司 +// SPDX-License-Identifier: Apache-2.0 OR MulanPSL-2.0 #include "rustica/event_set.h" diff --git a/src/rustica/event_set.h b/src/rustica/event_set.h index 1d21b2b..d874954 100644 --- a/src/rustica/event_set.h +++ b/src/rustica/event_set.h @@ -1,7 +1,5 @@ -/* - * SPDX-FileCopyrightText: 2024 燕几(北京)科技有限公司 - * SPDX-License-Identifier: Apache-2.0 OR MulanPSL-2.0 - */ +// SPDX-FileCopyrightText: 2024 燕几(北京)科技有限公司 +// SPDX-License-Identifier: Apache-2.0 OR MulanPSL-2.0 #ifndef RUSTICA_EVENT_SET_H #define RUSTICA_EVENT_SET_H diff --git a/src/rustica/extension.c b/src/rustica/extension.c new file mode 100644 index 0000000..0661989 --- /dev/null +++ b/src/rustica/extension.c @@ -0,0 +1,44 @@ +// SPDX-FileCopyrightText: 2025 燕几(北京)科技有限公司 +// SPDX-License-Identifier: Apache-2.0 OR MulanPSL-2.0 + +#include "postgres.h" +#include "postmaster/bgworker.h" +#include "utils/memutils.h" + +#include "rustica/compiler.h" +#include "rustica/gucs.h" +#include "rustica/wamr.h" + +PG_MODULE_MAGIC; + +PG_FUNCTION_INFO_V1(compile_wasm); + +void +_PG_init() { + rst_init_gucs(); + + MemoryContext tx_mctx = MemoryContextSwitchTo(TopMemoryContext); + rst_init_wamr(); + MemoryContextSwitchTo(tx_mctx); + + // Start up the Rustica master process + BackgroundWorker master = { .bgw_flags = BGWORKER_SHMEM_ACCESS, + .bgw_start_time = BgWorkerStart_PostmasterStart, + .bgw_restart_time = 10, + .bgw_notify_pid = 0 }; + snprintf(master.bgw_name, BGW_MAXLEN, "rustica master"); + snprintf(master.bgw_type, BGW_MAXLEN, "rustica master"); + snprintf(master.bgw_library_name, BGW_MAXLEN, "rustica-engine"); + snprintf(master.bgw_function_name, BGW_MAXLEN, "rustica_master"); + RegisterBackgroundWorker(&master); +} + +Datum +compile_wasm(PG_FUNCTION_ARGS) { + return rst_compile(fcinfo); +} + +void +_PG_fini() { + rst_fini_wamr(); +} diff --git a/src/rustica/gucs.c b/src/rustica/gucs.c index 35c53a2..79ed340 100644 --- a/src/rustica/gucs.c +++ b/src/rustica/gucs.c @@ -1,7 +1,5 @@ -/* - * SPDX-FileCopyrightText: 2024 燕几(北京)科技有限公司 - * SPDX-License-Identifier: Apache-2.0 OR MulanPSL-2.0 - */ +// SPDX-FileCopyrightText: 2024 燕几(北京)科技有限公司 +// SPDX-License-Identifier: Apache-2.0 OR MulanPSL-2.0 #include "postgres.h" #include "utils/guc.h" diff --git a/src/rustica/gucs.h b/src/rustica/gucs.h index 76b9b7d..58b7586 100644 --- a/src/rustica/gucs.h +++ b/src/rustica/gucs.h @@ -1,7 +1,5 @@ -/* - * SPDX-FileCopyrightText: 2024 燕几(北京)科技有限公司 - * SPDX-License-Identifier: Apache-2.0 OR MulanPSL-2.0 - */ +// SPDX-FileCopyrightText: 2024 燕几(北京)科技有限公司 +// SPDX-License-Identifier: Apache-2.0 OR MulanPSL-2.0 #ifndef RUSTICA_GUCS_H #define RUSTICA_GUCS_H diff --git a/src/rustica/main.c b/src/rustica/main.c index 629b660..6b2325f 100644 --- a/src/rustica/main.c +++ b/src/rustica/main.c @@ -1,46 +1,399 @@ -/* - * SPDX-FileCopyrightText: 2024 燕几(北京)科技有限公司 - * SPDX-License-Identifier: Apache-2.0 OR MulanPSL-2.0 - */ +// SPDX-FileCopyrightText: 2025 燕几(北京)科技有限公司 +// SPDX-License-Identifier: Apache-2.0 OR MulanPSL-2.0 #include "postgres.h" -#include "postmaster/bgworker.h" +#include "getopt_long.h" #include "utils/memutils.h" +#include "utils/pg_locale.h" -#include "rustica/compiler.h" -#include "rustica/gucs.h" -#include "rustica/wamr.h" +#include "bh_platform.h" +#include "bh_read_file.h" +#include "gc_export.h" +#include "aot_export.h" -PG_MODULE_MAGIC; +#include "rustica/env.h" +#include "rustica/moontest.h" -PG_FUNCTION_INFO_V1(compile_wasm); +#define HEAP_M 512 +#define STACK_K 512 -void -_PG_init() { - rst_init_gucs(); +const char *progname; - MemoryContext tx_mctx = MemoryContextSwitchTo(TopMemoryContext); - rst_init_wamr(); - MemoryContextSwitchTo(tx_mctx); +static void +run_start(wasm_exec_env_t exec_env, va_list args); - // Start up the Rustica master process - BackgroundWorker master = { .bgw_flags = BGWORKER_SHMEM_ACCESS, - .bgw_start_time = BgWorkerStart_PostmasterStart, - .bgw_restart_time = 10, - .bgw_notify_pid = 0 }; - snprintf(master.bgw_name, BGW_MAXLEN, "rustica master"); - snprintf(master.bgw_type, BGW_MAXLEN, "rustica master"); - snprintf(master.bgw_library_name, BGW_MAXLEN, "rustica-engine"); - snprintf(master.bgw_function_name, BGW_MAXLEN, "rustica_master"); - RegisterBackgroundWorker(&master); +static void +run_moontest(wasm_exec_env_t exec_env, va_list args); + +static void +run_wasm_with(const char *wasm_file, + bool use_aot, + void (*fn)(wasm_exec_env_t, va_list), + ...); + +static void +init_locale(const char *categoryname, int category, const char *locale); + +typedef enum Subcommand { + RUN = 0, + MOONTEST, + HELP, + VERSION, + BAD_ARGS, +} Subcommand; + +static void +help() { + printf(_("%s is a WebAssembly runtime with PostgreSQL backend.\n\n"), + progname); + printf(_("Usage:\n")); + printf(_(" %s run \n"), progname); + printf(_(" %s moontest --spec \n\n"), progname); + printf(_("Options:\n")); + printf(_(" -m, --mode compilation mode: aot, jit\n")); + printf(_(" -h, --help show this help, then exit\n")); + printf(_(" -V, --version output version information, then exit\n")); +} + +static Subcommand +parse_args(int argc, char **argv, bool *out_aot) { + struct option long_options[] = { { "mode", required_argument, NULL, 'm' }, + { "help", no_argument, NULL, 'h' }, + { "version", no_argument, NULL, 'V' }, + { NULL, 0, NULL, 0 } }; + + int c; + const char *mode = getenv("RUSTICA_ENGINE_MODE"); + if (mode) { + if (strcasecmp(mode, "aot") == 0) + *out_aot = true; + else if (strcasecmp(mode, "jit") == 0) + *out_aot = false; + else + ereport(ERROR, + (errmsg("Unknown RUSTICA_ENGINE_MODE value '%s', " + "available: aot, jit", + mode))); + } + + while ((c = getopt_long(argc, argv, "+m:hV", long_options, NULL)) != -1) { + switch (c) { + case 'm': + if (!optarg) + ereport(ERROR, errmsg("-m requires an argument")); + if (strcasecmp(optarg, "aot") == 0) + *out_aot = true; + else if (strcasecmp(optarg, "jit") == 0) + *out_aot = false; + else + ereport(ERROR, + (errmsg("Unknown mode '%s', available: aot, jit", + optarg))); + break; + + case 'h': + return HELP; + + case 'V': + return VERSION; + + default: + return BAD_ARGS; + } + } + + if (optind >= argc) + return HELP; + if (strcmp(argv[optind], "run") == 0) { + optind++; + return RUN; + } + if (strcmp(argv[optind], "moontest") == 0) { + optind++; + return MOONTEST; + } + + help(); + ereport(ERROR, (errmsg("Unsupported command '%s'", argv[optind]))); } -Datum -compile_wasm(PG_FUNCTION_ARGS) { - return rst_compile(fcinfo); +int +main(int argc, char *argv[]) { + bool use_aot = true; + int rv = 0; + + saved_argc = argc; + saved_argv = argv; + progname = get_progname(argv[0]); + + MemoryContextInit(); + + set_pglocale_pgservice(argv[0], PG_TEXTDOMAIN("postgres")); + init_locale("LC_COLLATE", LC_COLLATE, ""); + init_locale("LC_CTYPE", LC_CTYPE, ""); +#ifdef LC_MESSAGES + init_locale("LC_MESSAGES", LC_MESSAGES, ""); +#endif + init_locale("LC_MONETARY", LC_MONETARY, "C"); + init_locale("LC_NUMERIC", LC_NUMERIC, "C"); + init_locale("LC_TIME", LC_TIME, "C"); + + unsetenv("LC_ALL"); + + PG_TRY(); + { + Subcommand subcmd = parse_args(argc, argv, &use_aot); + switch (subcmd) { + case RUN: + if (optind >= argc) + ereport(ERROR, errmsg("No wasm file specified for 'run'")); + run_wasm_with(argv[optind], use_aot, run_start); + break; + + case MOONTEST: + { + const char *moontest_spec, *wasm_file; + if (moontest_parse_args(argc, + argv, + &moontest_spec, + &wasm_file)) { + if (wasm_file) + run_wasm_with(wasm_file, + use_aot, + run_moontest, + moontest_spec); + } + else { + rv = 1; + } + } break; + + case HELP: + help(); + break; + + case VERSION: + printf("%s (PostgreSQL %s)\n", progname, PG_VERSION); + break; + + case BAD_ARGS: + rv = 1; + break; + } + } + PG_CATCH(); + { + ErrorData *edata = CopyErrorData(); + fprintf(stderr, "Error: %s\n", edata->message); + FlushErrorState(); + FreeErrorData(edata); + rv = 1; + } + PG_END_TRY(); + return rv; +} + +static inline void +init_wamr() { + RuntimeInitArgs init_args = { + .mem_alloc_type = Alloc_With_Allocator, + .mem_alloc_option = { .allocator = { .malloc_func = palloc, + .realloc_func = repalloc, + .free_func = pfree } }, + .gc_heap_size = (uint32_t)HEAP_M * 1024 * 1024, + .running_mode = Mode_LLVM_JIT, + }; + + if (!wasm_runtime_full_init(&init_args)) + ereport(ERROR, errmsg("Failed to initialize WASM runtime")); + + rustica_register_natives(); +} + +static inline uint8_t * +read_wasm_file(const char *wasm_file, uint32_t *out_size) { + uint8_t *buffer; + const char *dot; + + // 检查文件扩展名是否为 .wasm + dot = strrchr(wasm_file, '.'); + if (!dot || strcasecmp(dot, ".wasm") != 0) { + ereport(ERROR, (errmsg("Unsupported file type: %s", wasm_file))); + } + + buffer = (uint8_t *)bh_read_file_to_buffer(wasm_file, out_size); + if (!buffer) { + ereport(ERROR, (errmsg("Failed to read wasm file: %s", wasm_file))); + } + return buffer; +} + +static inline wasm_module_t +load_wasm_module(uint8_t *buffer, const uint32_t size) { + char error_buf[128]; + wasm_module_t module = + wasm_runtime_load(buffer, size, error_buf, sizeof(error_buf)); + if (!module) + ereport(ERROR, (errmsg("Error loading wasm module: %s", error_buf))); + return module; +} + +static inline uint8_t * +compile_aot(uint8_t *byte_code, + const uint32_t size, + uint32_t *out_aot_file_size) { + AOTCompOption option = { + .enable_gc = true, + .aux_stack_frame_type = AOT_STACK_FRAME_TYPE_STANDARD, + .call_stack_features = { + .func_idx = true, + .bounds_checks = true, + .values = true, + }, + .enable_tail_call = true, + .enable_extended_const = true, + .output_format = AOT_FORMAT_FILE, + .enable_simd = true, + .enable_aux_stack_check = true, + .bounds_checks = true, + .enable_bulk_memory = true, + }; + wasm_module_t module = NULL; + aot_comp_data_t comp_data = NULL; + aot_comp_context_t comp_ctx = NULL; + uint8_t *rv = NULL; + + PG_TRY(); + { + module = load_wasm_module(byte_code, size); + if (!(comp_data = aot_create_comp_data(module, NULL, true))) + ereport(ERROR, + (errmsg("Error creating AOT compilation data: %s", + aot_get_last_error()))); + if (!(comp_ctx = aot_create_comp_context(comp_data, &option))) + ereport(ERROR, + (errmsg("Error creating AOT compilation context: %s", + aot_get_last_error()))); + if (!aot_compile_wasm(comp_ctx)) + ereport(ERROR, + (errmsg("Error compiling wasm module: %s", + aot_get_last_error()))); + if (!(rv = aot_emit_aot_file_buf(comp_ctx, + comp_data, + out_aot_file_size))) + ereport( + ERROR, + (errmsg("Error emitting AOT file: %s", aot_get_last_error()))); + } + PG_FINALLY(); + { + if (comp_ctx) + aot_destroy_comp_context(comp_ctx); + if (comp_data) + aot_destroy_comp_data(comp_data); + if (module) + wasm_runtime_unload(module); + } + PG_END_TRY(); + return rv; +} + +static void +run_start(wasm_exec_env_t exec_env, va_list args) { + wasm_module_inst_t module_inst = wasm_runtime_get_module_inst(exec_env); + wasm_function_inst_t start_func = + wasm_runtime_lookup_function(module_inst, "_start"); + if (start_func) + if (!wasm_runtime_call_wasm(exec_env, start_func, 0, NULL)) { + const char *exc = wasm_runtime_get_exception(module_inst); + StringInfoData msg; + initStringInfo(&msg); + enlargeStringInfo(&msg, 4096); + msg.len += (int)wasm_runtime_dump_call_stack_to_buf( + exec_env, + msg.data + msg.len, + msg.maxlen - msg.len - 1); + while (msg.len >= 2 && msg.data[msg.len - 2] == '\n') + msg.data[msg.len-- - 2] = '\0'; + ereport(ERROR, ({ + errmsg("%s:\n%s", exc ? exc : "Error", msg.data); + pfree(msg.data); + })); + } +} + +static void +run_moontest(wasm_exec_env_t exec_env, va_list args) { + const char *moontest_spec = va_arg(args, const char *); + moontest_run(exec_env, moontest_spec); +} + +static void +run_wasm_with(const char *wasm_file, + bool use_aot, + void (*fn)(wasm_exec_env_t, va_list), + ...) { + bool wamr_inited = false; + uint8_t *buffer = NULL; + uint32 size; + wasm_module_t module = NULL; + wasm_module_inst_t module_inst = NULL; + wasm_exec_env_t exec_env = NULL; + va_list args; + + PG_TRY(); + { + init_wamr(); + wamr_inited = true; + buffer = read_wasm_file(wasm_file, &size); + if (use_aot) { + uint8_t *aot_buffer = compile_aot(buffer, size, &size); + pfree(buffer); + buffer = aot_buffer; + } + module = load_wasm_module(buffer, size); + { + char error_buf[128]; + if (!(module_inst = + wasm_runtime_instantiate(module, + STACK_K * 1024, + (uint32_t)HEAP_M * 1024 * 1024, + error_buf, + sizeof(error_buf)))) + ereport( + ERROR, + (errmsg("Error instantiating wasm module: %s", error_buf))); + } + if (!(exec_env = + wasm_runtime_create_exec_env(module_inst, STACK_K * 1024))) + ereport(ERROR, errmsg("Error creating execution environment")); + + va_start(args, fn); + fn(exec_env, args); + va_end(args); + } + PG_FINALLY(); + { + if (exec_env) + wasm_runtime_destroy_exec_env(exec_env); + if (module_inst) + wasm_runtime_deinstantiate(module_inst); + if (module) + wasm_runtime_unload(module); + if (buffer) + pfree(buffer); + if (wamr_inited) + wasm_runtime_destroy(); + } + PG_END_TRY(); } -void -_PG_fini() { - rst_fini_wamr(); +static void +init_locale(const char *categoryname, int category, const char *locale) { + if (pg_perm_setlocale(category, locale) == NULL + && pg_perm_setlocale(category, "C") == NULL) + elog(FATAL, + "could not adopt \"%s\" locale nor C locale for %s", + locale, + categoryname); } diff --git a/src/rustica/master.c b/src/rustica/master.c index 5164c78..5c1bfed 100644 --- a/src/rustica/master.c +++ b/src/rustica/master.c @@ -1,7 +1,5 @@ -/* - * SPDX-FileCopyrightText: 2024 燕几(北京)科技有限公司 - * SPDX-License-Identifier: Apache-2.0 OR MulanPSL-2.0 - */ +// SPDX-FileCopyrightText: 2024 燕几(北京)科技有限公司 +// SPDX-License-Identifier: Apache-2.0 OR MulanPSL-2.0 #include diff --git a/src/rustica/module.c b/src/rustica/module.c index 73f5b0e..e513f98 100644 --- a/src/rustica/module.c +++ b/src/rustica/module.c @@ -1,7 +1,5 @@ -/* - * SPDX-FileCopyrightText: 2024 燕几(北京)科技有限公司 - * SPDX-License-Identifier: Apache-2.0 OR MulanPSL-2.0 - */ +// SPDX-FileCopyrightText: 2024 燕几(北京)科技有限公司 +// SPDX-License-Identifier: Apache-2.0 OR MulanPSL-2.0 #include "postgres.h" #include "executor/spi.h" diff --git a/src/rustica/module.h b/src/rustica/module.h index d1a9493..1ca1394 100644 --- a/src/rustica/module.h +++ b/src/rustica/module.h @@ -1,7 +1,5 @@ -/* - * SPDX-FileCopyrightText: 2024 燕几(北京)科技有限公司 - * SPDX-License-Identifier: Apache-2.0 OR MulanPSL-2.0 - */ +// SPDX-FileCopyrightText: 2024 燕几(北京)科技有限公司 +// SPDX-License-Identifier: Apache-2.0 OR MulanPSL-2.0 #ifndef RUSTICA_MODULE_H #define RUSTICA_MODULE_H diff --git a/src/rustica/moontest.c b/src/rustica/moontest.c new file mode 100644 index 0000000..d122f40 --- /dev/null +++ b/src/rustica/moontest.c @@ -0,0 +1,444 @@ +// SPDX-FileCopyrightText: 2025 燕几(北京)科技有限公司 +// SPDX-License-Identifier: Apache-2.0 OR MulanPSL-2.0 + +#include "postgres.h" +#include "getopt_long.h" +#include "common/jsonapi.h" +#include "mb/pg_wchar.h" +#include "utils/builtins.h" +#include "utils/json.h" + +#include "rustica/env.h" +#include "rustica/moontest.h" + +extern const char *progname; + +struct option moontest_options[] = { { "spec", required_argument, NULL, 's' }, + { "help", no_argument, NULL, 'h' }, + { NULL, 0, NULL, 0 } }; + +bool +moontest_parse_args(int argc, + char *argv[], + const char **out_spec, + const char **out_wasm_file) { + int c; + const char *spec = NULL; + while ((c = getopt_long(argc, argv, "+s:h", moontest_options, NULL)) + != -1) { + switch (c) { + case 's': + spec = optarg; + break; + case 'h': + printf(_("Usage:\n")); + printf(" %s moontest --spec \n", progname); + printf(_("Options:\n")); + printf(_( + " --spec JSON spec describing tests to run\n")); + printf(_(" -h, --help show this help, then exit\n")); + *out_wasm_file = NULL; + *out_spec = spec; + return true; + default: + return false; + } + } + if (optind >= argc) + ereport(ERROR, (errmsg("No wasm file specified for 'moontest'"))); + if (!spec) + ereport(ERROR, (errmsg("--spec requires an argument"))); + *out_wasm_file = argv[optind]; + *out_spec = spec; + return true; +} + +typedef enum Expect { + E_TOP = 0, + E_TOP_FIELD, + E_PACKAGE_NAME, + E_FILE_ARRAY, + E_FILE_TUPLE, + E_FILE_NAME, + E_RANGE_ARRAY, + E_RANGE_OBJECT, + E_RANGE_FIELD, + E_RANGE_START, + E_RANGE_END, + E_FILE_END, + E_END, + +} Expect; + +typedef struct JsonParseState { + Expect expect; + + wasm_exec_env_t exec_env; + wasm_module_inst_t module_inst; + wasm_function_inst_t exec; + + char *package; + StringInfo package_buf; + + int current_file_index; + char *filename; + + int current_range_index; + int range_start; + int range_end; + bool range_start_set; + bool range_end_set; +} JsonParseState; + +static JsonParseErrorType +json_object_start_cb(void *state); +static JsonParseErrorType +json_object_end_cb(void *state); +static JsonParseErrorType +json_array_start_cb(void *state); +static JsonParseErrorType +json_array_end_cb(void *state); +static JsonParseErrorType +json_object_field_start_cb(void *state, char *fname, bool isnull); +static JsonParseErrorType +json_scalar_cb(void *state, char *token, JsonTokenType tokentype); + +void +moontest_run(wasm_exec_env_t exec_env, const char *moontest_spec) { + JsonLexContext *lex; + JsonSemAction sem; + JsonParseState parse_state; + + /* Initialize parsing state */ + memset(&parse_state, 0, sizeof(JsonParseState)); + parse_state.exec_env = exec_env; + parse_state.module_inst = wasm_runtime_get_module_inst(exec_env); + parse_state.package = "\"\""; + parse_state.exec = + wasm_runtime_lookup_function(parse_state.module_inst, + "moonbit_test_driver_internal_execute"); + if (!parse_state.exec) + ereport(ERROR, + (errcode(ERRCODE_UNDEFINED_FUNCTION), + errmsg("Function 'moonbit_test_driver_internal_execute' " + "not found in module"))); + + /* Set up JSON semantic actions */ + memset(&sem, 0, sizeof(JsonSemAction)); + sem.semstate = &parse_state; + sem.object_start = json_object_start_cb; + sem.object_end = json_object_end_cb; + sem.array_start = json_array_start_cb; + sem.array_end = json_array_end_cb; + sem.object_field_start = json_object_field_start_cb; + sem.scalar = json_scalar_cb; + + /* Create lexer context and parse JSON once */ + lex = makeJsonLexContextCstringLen(NULL, + moontest_spec, + strlen(moontest_spec), + PG_UTF8, + true); + PG_TRY(); + { + pg_parse_json(lex, &sem); + } + PG_FINALLY(); + { + freeJsonLexContext(lex); + if (parse_state.package_buf) + destroyStringInfo(parse_state.package_buf); + if (parse_state.filename) + pfree(parse_state.filename); + } + PG_END_TRY(); +} + +static JsonParseErrorType +json_object_start_cb(void *state) { + JsonParseState *parse_state = state; + + switch (parse_state->expect) { + case E_TOP: + parse_state->expect = E_TOP_FIELD; + break; + + case E_RANGE_OBJECT: + parse_state->expect = E_RANGE_FIELD; + parse_state->range_start_set = false; + parse_state->range_end_set = false; + break; + + default: + return JSON_SEM_ACTION_FAILED; + } + return JSON_SUCCESS; +} + +static JsonParseErrorType +json_object_end_cb(void *state) { + JsonParseState *parse_state = state; + wasm_function_inst_t func; + rustica_value_t filename = NULL; + uintptr_t filename_ref = 0; + StringInfo filename_buf = NULL, msg = NULL, escaped_msg = NULL; + const char *exc; + + switch (parse_state->expect) { + case E_RANGE_FIELD: + if (!parse_state->range_start_set || !parse_state->range_end_set) + ereport( + ERROR, + (errcode(ERRCODE_INVALID_PARAMETER_VALUE), + errmsg("Range object missing 'start' or 'end' field"))); + for (int i = parse_state->range_start; i < parse_state->range_end; + i++) { + wasm_val_t args[2]; + if (!filename) { + Assert(parse_state->filename != NULL); + filename = rustica_value_new(RUSTICA_ENV_CSTRING, + parse_state->filename, + 0); + } + if (!filename_ref) + filename_ref = + (uintptr_t)rustica_value_to_wasm(parse_state->exec_env, + filename); + + args[0].kind = WASM_EXTERNREF; + args[0].of.foreign = filename_ref; + args[1].kind = WASM_I32; + args[1].of.i32 = i; + + if (!wasm_runtime_call_wasm_a(parse_state->exec_env, + parse_state->exec, + 0, + NULL, + 2, + args)) { + if (!filename_buf) { + filename_buf = makeStringInfo(); + escape_json(filename_buf, filename->ptr); + } + if (msg) { + resetStringInfo(msg); + } + else { + msg = makeStringInfo(); + enlargeStringInfo(msg, 4096); + } + exc = wasm_runtime_get_exception(parse_state->module_inst); + appendStringInfoString(msg, exc ? exc : "Error: \n"); + msg->len += (int)wasm_runtime_dump_call_stack_to_buf( + parse_state->exec_env, + msg->data + msg->len, + msg->maxlen - msg->len - 1); + while (msg->len >= 2 && msg->data[msg->len - 2] == '\n') + msg->data[msg->len-- - 2] = '\0'; + if (escaped_msg) + resetStringInfo(escaped_msg); + else + escaped_msg = makeStringInfo(); + escape_json(escaped_msg, msg->data); + + printf("----- BEGIN MOON TEST RESULT -----\n"); + printf("{\"package\": %s, \"filename\": %s, \"index\": " + "\"%d\", " + "\"test_name\": \"%d\", \"message\": %s}\n", + parse_state->package, + filename_buf->data, + i, + i, + escaped_msg->data); + printf("----- END MOON TEST RESULT -----\n"); + wasm_runtime_set_exception(parse_state->module_inst, NULL); + } + } + if (filename_buf) + destroyStringInfo(filename_buf); + if (msg) + destroyStringInfo(msg); + if (escaped_msg) + destroyStringInfo(escaped_msg); + parse_state->current_range_index += 1; + parse_state->expect = E_RANGE_OBJECT; + break; + + case E_TOP_FIELD: + parse_state->expect = E_END; + func = wasm_runtime_lookup_function(parse_state->module_inst, + "moonbit_test_driver_finish"); + if (func) + wasm_runtime_call_wasm(parse_state->exec_env, func, 0, NULL); + break; + + default: + return JSON_SEM_ACTION_FAILED; + } + + return JSON_SUCCESS; +} + +static JsonParseErrorType +json_array_start_cb(void *state) { + JsonParseState *parse_state = state; + + switch (parse_state->expect) { + case E_FILE_ARRAY: + parse_state->expect = E_FILE_TUPLE; + break; + + case E_FILE_TUPLE: + parse_state->expect = E_FILE_NAME; + break; + + case E_RANGE_ARRAY: + parse_state->expect = E_RANGE_OBJECT; + parse_state->current_range_index = 0; + break; + + default: + return JSON_SEM_ACTION_FAILED; + } + return JSON_SUCCESS; +} + +static JsonParseErrorType +json_array_end_cb(void *state) { + JsonParseState *parse_state = state; + + switch (parse_state->expect) { + case E_RANGE_OBJECT: + parse_state->expect = E_FILE_END; + break; + + case E_FILE_END: + pfree(parse_state->filename); + parse_state->filename = NULL; + parse_state->expect = E_FILE_TUPLE; + break; + + default: + return JSON_SEM_ACTION_FAILED; + } + + return JSON_SUCCESS; +} + +static JsonParseErrorType +json_object_field_start_cb(void *state, char *fname, bool isnull) { + JsonParseState *parse_state = state; + JsonParseErrorType rv = JSON_SUCCESS; + + PG_TRY(); + { + switch (parse_state->expect) { + case E_TOP_FIELD: + if (strcmp(fname, "package") == 0) { + if (!isnull) + parse_state->expect = E_PACKAGE_NAME; + } + else if (strcmp(fname, "file_and_index") == 0) { + if (!isnull) + parse_state->expect = E_FILE_ARRAY; + } + else + ereport(ERROR, + (errcode(ERRCODE_INVALID_PARAMETER_VALUE), + errmsg("Unexpected field '%s' in top-level object", + fname))); + break; + + case E_RANGE_FIELD: + if (strcmp(fname, "start") == 0) { + if (!isnull) + parse_state->expect = E_RANGE_START; + } + else if (strcmp(fname, "end") == 0) { + if (!isnull) + parse_state->expect = E_RANGE_END; + } + else + ereport(ERROR, + (errcode(ERRCODE_INVALID_PARAMETER_VALUE), + errmsg("Unexpected field '%s' in range object", + fname))); + break; + + default: + rv = JSON_SEM_ACTION_FAILED; + } + } + PG_FINALLY(); + { + pfree(fname); + } + PG_END_TRY(); + return rv; +} + +static JsonParseErrorType +json_scalar_cb(void *state, char *token, JsonTokenType tokentype) { + JsonParseState *parse_state = state; + JsonParseErrorType rv = JSON_SUCCESS; + + PG_TRY(); + { + switch (parse_state->expect) { + case E_PACKAGE_NAME: + if (tokentype != JSON_TOKEN_STRING) + ereport(ERROR, + (errcode(ERRCODE_INVALID_PARAMETER_VALUE), + errmsg("Expected string for 'package' field"))); + parse_state->package_buf = makeStringInfo(); + escape_json(parse_state->package_buf, token); + parse_state->package = parse_state->package_buf->data; + parse_state->expect = E_TOP_FIELD; + break; + + case E_FILE_NAME: + if (tokentype != JSON_TOKEN_STRING) + ereport(ERROR, + (errcode(ERRCODE_INVALID_PARAMETER_VALUE), + errmsg("Expected string for filename in " + "file_and_index entry"))); + parse_state->filename = token; + token = NULL; + parse_state->expect = E_RANGE_ARRAY; + break; + + case E_RANGE_START: + if (tokentype != JSON_TOKEN_NUMBER) + ereport( + ERROR, + (errcode(ERRCODE_INVALID_PARAMETER_VALUE), + errmsg( + "Expected number for 'start' in range object"))); + parse_state->range_start = pg_strtoint32(token); + parse_state->range_start_set = true; + parse_state->expect = E_RANGE_FIELD; + break; + + case E_RANGE_END: + if (tokentype != JSON_TOKEN_NUMBER) + ereport( + ERROR, + (errcode(ERRCODE_INVALID_PARAMETER_VALUE), + errmsg("Expected number for 'end' in range object"))); + parse_state->range_end = pg_strtoint32(token); + parse_state->range_end_set = true; + parse_state->expect = E_RANGE_FIELD; + break; + + default: + rv = JSON_SEM_ACTION_FAILED; + } + } + PG_FINALLY(); + { + if (token) + pfree(token); + } + PG_END_TRY(); + return rv; +} diff --git a/src/rustica/moontest.h b/src/rustica/moontest.h new file mode 100644 index 0000000..5f93e56 --- /dev/null +++ b/src/rustica/moontest.h @@ -0,0 +1,16 @@ +// SPDX-FileCopyrightText: 2025 燕几(北京)科技有限公司 +// SPDX-License-Identifier: Apache-2.0 OR MulanPSL-2.0 + +#ifndef RUSTICA_MOONTEST_H +#define RUSTICA_MOONTEST_H + +bool +moontest_parse_args(int argc, + char *argv[], + const char **out_spec, + const char **out_wasm_file); + +void +moontest_run(wasm_exec_env_t exec_env, const char *moontest_spec); + +#endif /* RUSTICA_MOONTEST_H */ diff --git a/src/rustica/query.c b/src/rustica/query.c index 30fd40e..d52fd06 100644 --- a/src/rustica/query.c +++ b/src/rustica/query.c @@ -1,7 +1,5 @@ -/* - * SPDX-FileCopyrightText: 2024 燕几(北京)科技有限公司 - * SPDX-License-Identifier: Apache-2.0 OR MulanPSL-2.0 - */ +// SPDX-FileCopyrightText: 2024 燕几(北京)科技有限公司 +// SPDX-License-Identifier: Apache-2.0 OR MulanPSL-2.0 #include "postgres.h" #include "executor/spi.h" diff --git a/src/rustica/query.h b/src/rustica/query.h index f5188d4..9e5e25b 100644 --- a/src/rustica/query.h +++ b/src/rustica/query.h @@ -1,7 +1,5 @@ -/* - * SPDX-FileCopyrightText: 2024 燕几(北京)科技有限公司 - * SPDX-License-Identifier: Apache-2.0 OR MulanPSL-2.0 - */ +// SPDX-FileCopyrightText: 2024 燕几(北京)科技有限公司 +// SPDX-License-Identifier: Apache-2.0 OR MulanPSL-2.0 #ifndef RUSTICA_QUERY_H #define RUSTICA_QUERY_H diff --git a/src/rustica/utils.c b/src/rustica/utils.c index 04d832c..bb02fde 100644 --- a/src/rustica/utils.c +++ b/src/rustica/utils.c @@ -1,7 +1,5 @@ -/* - * SPDX-FileCopyrightText: 2024 燕几(北京)科技有限公司 - * SPDX-License-Identifier: Apache-2.0 OR MulanPSL-2.0 - */ +// SPDX-FileCopyrightText: 2024 燕几(北京)科技有限公司 +// SPDX-License-Identifier: Apache-2.0 OR MulanPSL-2.0 #include #include diff --git a/src/rustica/utils.h b/src/rustica/utils.h index 65f5af4..8563826 100644 --- a/src/rustica/utils.h +++ b/src/rustica/utils.h @@ -1,7 +1,5 @@ -/* - * SPDX-FileCopyrightText: 2024 燕几(北京)科技有限公司 - * SPDX-License-Identifier: Apache-2.0 OR MulanPSL-2.0 - */ +// SPDX-FileCopyrightText: 2024 燕几(北京)科技有限公司 +// SPDX-License-Identifier: Apache-2.0 OR MulanPSL-2.0 #ifndef RUSTICA_UTILS_H #define RUSTICA_UTILS_H diff --git a/src/rustica/wamr.c b/src/rustica/wamr.c index 410cc83..c92f15e 100644 --- a/src/rustica/wamr.c +++ b/src/rustica/wamr.c @@ -1,7 +1,5 @@ -/* - * SPDX-FileCopyrightText: 2024 燕几(北京)科技有限公司 - * SPDX-License-Identifier: Apache-2.0 OR MulanPSL-2.0 - */ +// SPDX-FileCopyrightText: 2024 燕几(北京)科技有限公司 +// SPDX-License-Identifier: Apache-2.0 OR MulanPSL-2.0 #include "postgres.h" #include "catalog/pg_type_d.h" diff --git a/src/rustica/wamr.h b/src/rustica/wamr.h index 1663bf9..55a5dba 100644 --- a/src/rustica/wamr.h +++ b/src/rustica/wamr.h @@ -1,7 +1,5 @@ -/* - * SPDX-FileCopyrightText: 2024 燕几(北京)科技有限公司 - * SPDX-License-Identifier: Apache-2.0 OR MulanPSL-2.0 - */ +// SPDX-FileCopyrightText: 2024 燕几(北京)科技有限公司 +// SPDX-License-Identifier: Apache-2.0 OR MulanPSL-2.0 #ifndef RUSTICA_WAMR_H #define RUSTICA_WAMR_H diff --git a/src/rustica/worker.c b/src/rustica/worker.c index 42751b2..b28176f 100644 --- a/src/rustica/worker.c +++ b/src/rustica/worker.c @@ -1,7 +1,5 @@ -/* - * SPDX-FileCopyrightText: 2024 燕几(北京)科技有限公司 - * SPDX-License-Identifier: Apache-2.0 OR MulanPSL-2.0 - */ +// SPDX-FileCopyrightText: 2024 燕几(北京)科技有限公司 +// SPDX-License-Identifier: Apache-2.0 OR MulanPSL-2.0 #include diff --git a/subprojects/.gitignore b/subprojects/.gitignore new file mode 100644 index 0000000..099ccf7 --- /dev/null +++ b/subprojects/.gitignore @@ -0,0 +1,10 @@ +/packagecache/ +.wraplock +/postgresql-*/ +/wasm-micro-runtime-WAMR-*/ +/util-linux-*/ +/lz4-*/ +/icu/ +/openssl-*/ +/llvm-project-*.src/ +/zlib-*/ diff --git a/subprojects/icu.wrap b/subprojects/icu.wrap new file mode 100644 index 0000000..a9989ce --- /dev/null +++ b/subprojects/icu.wrap @@ -0,0 +1,14 @@ +[wrap-file] +directory = icu +source_url = https://github.com/unicode-org/icu/releases/download/release-77-1/icu4c-77_1-src.tgz +source_filename = icu4c-77_1-src.tgz +source_hash = 588e431f77327c39031ffbb8843c0e3bc122c211374485fa87dc5f3faff24061 +patch_filename = icu_77.1-3_patch.zip +patch_url = https://wrapdb.mesonbuild.com/v2/icu_77.1-3/get_patch +patch_hash = df23a720ece4cd8c76ef50bcafe0d800c8c11117806bf207d65973a95f0dcea7 +source_fallback_url = https://github.com/mesonbuild/wrapdb/releases/download/icu_77.1-3/icu4c-77_1-src.tgz +wrapdb_version = 77.1-3 + +[provide] +dependency_names = icu-data, icu-i18n, icu-io, icu-uc +program_names = genbrk, genccode, gencmn diff --git a/subprojects/llvm.wrap b/subprojects/llvm.wrap new file mode 100644 index 0000000..169967b --- /dev/null +++ b/subprojects/llvm.wrap @@ -0,0 +1,9 @@ +[wrap-file] +directory = llvm-project-18.1.8.src +source_url = https://github.com/llvm/llvm-project/releases/download/llvmorg-18.1.8/llvm-project-18.1.8.src.tar.xz +source_filename = llvm-project-18.1.8.src.tar.xz +source_hash = 0b58557a6d32ceee97c8d533a59b9212d87e0fc4d2833924eb6c611247db2f2a +diff_files = + llvm/0001_Add_cstdint_to_SmallVector_101761.patch, + llvm/0002_Add_missing_include_to_X86MCTargetDesc.h_123320.patch, + llvm/0003_Add_Meson_Build.patch diff --git a/subprojects/lz4.wrap b/subprojects/lz4.wrap new file mode 100644 index 0000000..7732b9a --- /dev/null +++ b/subprojects/lz4.wrap @@ -0,0 +1,13 @@ +[wrap-file] +directory = lz4-1.10.0 +source_url = https://github.com/lz4/lz4/archive/v1.10.0.tar.gz +source_filename = lz4-1.10.0.tgz +source_hash = 537512904744b35e232912055ccf8ec66d768639ff3abe5788d90d792ec5f48b +patch_filename = lz4_1.10.0-2_patch.zip +patch_url = https://wrapdb.mesonbuild.com/v2/lz4_1.10.0-2/get_patch +patch_hash = ce568b4e1a7a593bb233f3ec97af88ceb850524cef802fe3f916b21d8a79b6b6 +source_fallback_url = https://github.com/mesonbuild/wrapdb/releases/download/lz4_1.10.0-2/lz4-1.10.0.tgz +wrapdb_version = 1.10.0-2 + +[provide] +liblz4 = liblz4_dep diff --git a/subprojects/openssl.wrap b/subprojects/openssl.wrap new file mode 100644 index 0000000..873d551 --- /dev/null +++ b/subprojects/openssl.wrap @@ -0,0 +1,15 @@ +[wrap-file] +directory = openssl-3.0.8 +source_url = https://www.openssl.org/source/openssl-3.0.8.tar.gz +source_filename = openssl-3.0.8.tar.gz +source_hash = 6c13d2bf38fdf31eac3ce2a347073673f5d63263398f1f69d0df4a41253e4b3e +patch_filename = openssl_3.0.8-3_patch.zip +patch_url = https://wrapdb.mesonbuild.com/v2/openssl_3.0.8-3/get_patch +patch_hash = 300da189e106942347d61a4a4295aa2edbcf06184f8d13b4cee0bed9fb936963 +source_fallback_url = https://github.com/mesonbuild/wrapdb/releases/download/openssl_3.0.8-3/openssl-3.0.8.tar.gz +wrapdb_version = 3.0.8-3 + +[provide] +libcrypto = libcrypto_dep +libssl = libssl_dep +openssl = openssl_dep diff --git a/subprojects/packagefiles/llvm/0001_Add_cstdint_to_SmallVector_101761.patch b/subprojects/packagefiles/llvm/0001_Add_cstdint_to_SmallVector_101761.patch new file mode 100644 index 0000000..c7ed0e1 --- /dev/null +++ b/subprojects/packagefiles/llvm/0001_Add_cstdint_to_SmallVector_101761.patch @@ -0,0 +1,28 @@ +From aa01bd3a71399edb05fa9b0ab8e0bd35585aa1c5 Mon Sep 17 00:00:00 2001 +From: Sam James +Date: Fri, 2 Aug 2024 23:07:21 +0100 +Subject: [PATCH 1/2] Add `` to SmallVector (#101761) + +SmallVector uses `uint32_t`, `uint64_t` without including `` +which fails to build w/ GCC 15 after a change in libstdc++ [0] + +[0] https://gcc.gnu.org/git/?p=gcc.git;a=commit;h=3a817a4a5a6d94da9127af3be9f84a74e3076ee2 +--- + llvm/include/llvm/ADT/SmallVector.h | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/llvm/include/llvm/ADT/SmallVector.h b/llvm/include/llvm/ADT/SmallVector.h +index e34702bdb..1c0f3465b 100644 +--- a/llvm/include/llvm/ADT/SmallVector.h ++++ b/llvm/include/llvm/ADT/SmallVector.h +@@ -19,6 +19,7 @@ + #include + #include + #include ++#include + #include + #include + #include +-- +2.51.0 + diff --git a/subprojects/packagefiles/llvm/0002_Add_missing_include_to_X86MCTargetDesc.h_123320.patch b/subprojects/packagefiles/llvm/0002_Add_missing_include_to_X86MCTargetDesc.h_123320.patch new file mode 100644 index 0000000..29c640c --- /dev/null +++ b/subprojects/packagefiles/llvm/0002_Add_missing_include_to_X86MCTargetDesc.h_123320.patch @@ -0,0 +1,32 @@ +From 3ba14e5ea319e138f8d0f5c06fd2f76d425e4093 Mon Sep 17 00:00:00 2001 +From: Stephan Hageboeck +Date: Mon, 20 Jan 2025 17:52:47 +0100 +Subject: [PATCH 2/2] Add missing include to X86MCTargetDesc.h (#123320) + +In gcc-15, explicit includes of `` are required when fixed-size +integers are used. In this file, this include only happened as a side +effect of including SmallVector.h + +Although llvm compiles fine, the root-project would benefit from +explicitly including it here, so we can backport the patch. + +Maybe interesting for @hahnjo and @vgvassilev +--- + llvm/lib/Target/X86/MCTargetDesc/X86MCTargetDesc.h | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/llvm/lib/Target/X86/MCTargetDesc/X86MCTargetDesc.h b/llvm/lib/Target/X86/MCTargetDesc/X86MCTargetDesc.h +index d0530bd4d..10b59462a 100644 +--- a/llvm/lib/Target/X86/MCTargetDesc/X86MCTargetDesc.h ++++ b/llvm/lib/Target/X86/MCTargetDesc/X86MCTargetDesc.h +@@ -13,6 +13,7 @@ + #ifndef LLVM_LIB_TARGET_X86_MCTARGETDESC_X86MCTARGETDESC_H + #define LLVM_LIB_TARGET_X86_MCTARGETDESC_X86MCTARGETDESC_H + ++#include + #include + #include + +-- +2.51.0 + diff --git a/subprojects/packagefiles/llvm/0003_Add_Meson_Build.patch b/subprojects/packagefiles/llvm/0003_Add_Meson_Build.patch new file mode 100644 index 0000000..ed2da71 --- /dev/null +++ b/subprojects/packagefiles/llvm/0003_Add_Meson_Build.patch @@ -0,0 +1,84 @@ +diff --git a/meson.build b/meson.build +new file mode 100644 +index 000000000..9caad419d +--- /dev/null ++++ b/meson.build +@@ -0,0 +1,66 @@ ++project('llvm', 'cpp') ++ ++llvm_defines = { ++ 'CMAKE_BUILD_TYPE': 'Release', ++ 'CMAKE_EXPORT_COMPILE_COMMANDS': 'ON', ++ 'LLVM_APPEND_VC_REV': 'ON', ++ 'LLVM_BUILD_EXAMPLES': 'OFF', ++ 'LLVM_BUILD_LLVM_DYLIB': 'OFF', ++ 'LLVM_ENABLE_BINDINGS': 'OFF', ++ 'LLVM_ENABLE_IDE': 'OFF', ++ 'LLVM_ENABLE_LIBEDIT': 'OFF', ++ 'LLVM_ENABLE_TERMINFO': 'OFF', ++ 'LLVM_ENABLE_ZLIB': 'ON', ++ 'LLVM_INCLUDE_BENCHMARKS': 'OFF', ++ 'LLVM_INCLUDE_DOCS': 'OFF', ++ 'LLVM_INCLUDE_EXAMPLES': 'OFF', ++ 'LLVM_INCLUDE_UTILS': 'OFF', ++ 'LLVM_INCLUDE_TESTS': 'OFF', ++ 'LLVM_OPTIMIZED_TABLEGEN': 'ON', ++ 'LLVM_TARGETS_TO_BUILD': 'AArch64;ARM;RISCV;X86;LoongArch', ++ 'LLVM_ENABLE_PROJECTS': 'clang', ++ 'LLVM_ENABLE_LIBXML2': 'OFF', ++ 'LLVM_INCLUDE_TOOLS': 'OFF', ++ 'LLVM_ENABLE_ZSTD': 'OFF', ++ 'CMAKE_INSTALL_PREFIX': get_option('prefix'), ++} ++ ++if host_machine.system() != 'windows' ++ llvm_defines += { ++ 'LLVM_CCACHE_BUILD': 'ON', ++ } ++endif ++if host_machine.system() == 'linux' ++ llvm_defines += { ++ 'LLVM_USE_PERF': 'ON', ++ } ++endif ++ ++if get_option('zlib_dir') != '' ++ zlib_prefix = get_option('zlib_dir') ++ llvm_defines += { ++ 'ZLIB_LIBRARY': zlib_prefix / 'lib' / 'libz.a', ++ 'ZLIB_INCLUDE_DIR': zlib_prefix / 'include', ++ } ++endif ++ ++build_dir = meson.project_build_root() ++source_dir = meson.project_source_root() ++ ++command_cmake = ['cmake', '-G', 'Ninja', '-S', source_dir / 'llvm', '-B', build_dir] ++foreach key, val : llvm_defines ++ command_cmake += ['-D' + key + '=' + val] ++endforeach ++ ++cmake_configure = custom_target('cmake_configure', ++ command: command_cmake + ['&&', 'touch', '@OUTPUT@'], ++ output: 'configure.stamp', ++ build_by_default: true ++) ++ ++cmake_build_install = custom_target('cmake_build_install', ++ command: ['cmake', '--build', build_dir, '--target', 'install', '&&', 'touch', '@OUTPUT@'], ++ output: 'install.stamp', ++ depends: cmake_configure, ++ build_by_default: true ++) +diff --git a/meson_options.txt b/meson_options.txt +new file mode 100644 +index 000000000..cd1f58c4c +--- /dev/null ++++ b/meson_options.txt +@@ -0,0 +1,6 @@ ++option( ++ 'zlib_dir', ++ type: 'string', ++ value: '', ++ description: 'Path to a pre-installed zlib (e.g., /path/to/zlib)', ++) diff --git a/subprojects/packagefiles/postgresql/embed-libs.patch b/subprojects/packagefiles/postgresql/embed-libs.patch new file mode 100644 index 0000000..b8bf86f --- /dev/null +++ b/subprojects/packagefiles/postgresql/embed-libs.patch @@ -0,0 +1,47 @@ +--- a/meson.build 2025-10-08 11:20:39.778284410 +0800 ++++ b/meson.build 2025-10-08 11:21:46.519045315 +0800 +@@ -1369,11 +1369,8 @@ + ssl_int = [ssl_lib, crypto_lib] + ssl = declare_dependency(dependencies: ssl_int, include_directories: postgres_inc) + endif +- elif cc.has_header('openssl/ssl.h', args: test_c_args, dependencies: ssl, required: openssl_required) and \ +- cc.has_header('openssl/err.h', args: test_c_args, dependencies: ssl, required: openssl_required) +- ssl_int = [ssl] + else +- ssl = not_found_dep ++ ssl_int = [ssl] + endif + + if ssl.found() +@@ -1408,16 +1405,15 @@ + are_openssl_funcs_complete = true + foreach c : check_funcs + func = c.get(0) +- val = cc.has_function(func, args: test_c_args, dependencies: ssl_int) + required = c.get(1, {}).get('required', false) +- if required and not val ++ if required + are_openssl_funcs_complete = false + if openssl_required + error('openssl function @0@ is required'.format(func)) + endif + break + elif not required +- cdata.set('HAVE_' + func.to_upper(), val ? 1 : false) ++ cdata.set('HAVE_' + func.to_upper(), 1) + endif + endforeach + +@@ -1480,12 +1476,6 @@ + error('unknown uuid build option value: @0@'.format(uuidopt)) + endif + +- if not cc.has_header_symbol(uuidheader, uuidfunc, +- args: test_c_args, +- include_directories: postgres_inc, +- dependencies: uuid) +- error('uuid library @0@ missing required function @1@'.format(uuidopt, uuidfunc)) +- endif + cdata.set('HAVE_@0@'.format(uuidheader.underscorify().to_upper()), 1) + + cdata.set('HAVE_UUID_@0@'.format(uuidname), 1, diff --git a/subprojects/packagefiles/postgresql/meson-0.56.patch b/subprojects/packagefiles/postgresql/meson-0.56.patch new file mode 100644 index 0000000..12b9cc9 --- /dev/null +++ b/subprojects/packagefiles/postgresql/meson-0.56.patch @@ -0,0 +1,301 @@ +diff --git a/contrib/dblink/meson.build b/contrib/dblink/meson.build +index 45eeb58c618..10cbafa6ce0 100644 +--- a/contrib/dblink/meson.build ++++ b/contrib/dblink/meson.build +@@ -34,6 +34,6 @@ tests += { + 'sql': [ + 'dblink', + ], +- 'regress_args': ['--dlpath', meson.build_root() / 'src/test/regress'], ++ 'regress_args': ['--dlpath', meson.project_build_root() / 'src/test/regress'], + }, + } +diff --git a/contrib/postgres_fdw/meson.build b/contrib/postgres_fdw/meson.build +index f0803ee077e..32f38d2b142 100644 +--- a/contrib/postgres_fdw/meson.build ++++ b/contrib/postgres_fdw/meson.build +@@ -38,6 +38,6 @@ tests += { + 'postgres_fdw', + 'query_cancel', + ], +- 'regress_args': ['--dlpath', meson.build_root() / 'src/test/regress'], ++ 'regress_args': ['--dlpath', meson.project_build_root() / 'src/test/regress'], + }, + } +diff --git a/meson.build b/meson.build +index 5c33f569b43..3e4b7e8df34 100644 +--- a/meson.build ++++ b/meson.build +@@ -14,7 +14,7 @@ project('postgresql', + # We want < 0.56 for python 3.5 compatibility on old platforms. EPEL for + # RHEL 7 has 0.55. < 0.54 would require replacing some uses of the fs + # module, < 0.53 all uses of fs. So far there's no need to go to >=0.56. +- meson_version: '>=0.54', ++ meson_version: '>=0.56', + default_options: [ + 'warning_level=1', #-Wall equivalent + 'b_pch=false', +@@ -362,8 +362,8 @@ if flex.found() + endif + flex_wrapper = files('src/tools/pgflex') + flex_cmd = [python, flex_wrapper, +- '--builddir', '@BUILD_ROOT@', +- '--srcdir', '@SOURCE_ROOT@', ++ '--builddir', meson.project_build_root(), ++ '--srcdir', meson.project_source_root(), + '--privatedir', '@PRIVATE_DIR@', + '--flex', flex, '--perl', perl, + '-i', '@INPUT@', '-o', '@OUTPUT0@', +@@ -2975,7 +2975,7 @@ catalog_pm = files('src/backend/catalog/Catalog.pm') + perfect_hash_pm = files('src/tools/PerfectHash.pm') + gen_kwlist_deps = [perfect_hash_pm] + gen_kwlist_cmd = [ +- perl, '-I', '@SOURCE_ROOT@/src/tools', ++ perl, '-I', '@0@/src/tools'.format(meson.project_source_root()), + files('src/tools/gen_keywordlist.pl'), + '--output', '@OUTDIR@', '@INPUT@'] + +@@ -2986,13 +2986,13 @@ gen_kwlist_cmd = [ + ### + + if host_system == 'windows' +- pg_ico = meson.source_root() / 'src' / 'port' / 'win32.ico' ++ pg_ico = meson.project_source_root() / 'src' / 'port' / 'win32.ico' + win32ver_rc = files('src/port/win32ver.rc') + rcgen = find_program('src/tools/rcgen', native: true) + + rcgen_base_args = [ + '--srcdir', '@SOURCE_DIR@', +- '--builddir', meson.build_root(), ++ '--builddir', meson.project_build_root(), + '--rcout', '@OUTPUT0@', + '--out', '@OUTPUT1@', + '--input', '@INPUT@', +@@ -3231,7 +3231,7 @@ foreach t1 : configure_files + potentially_conflicting_files += meson.current_build_dir() / t + endforeach + foreach sub, fnames : generated_sources_ac +- sub = meson.build_root() / sub ++ sub = meson.project_build_root() / sub + foreach fname : fnames + potentially_conflicting_files += sub / fname + endforeach +@@ -3331,7 +3331,7 @@ run_target('install-test-files', + ############################################################### + + # DESTDIR for the installation we'll run tests in +-test_install_destdir = meson.build_root() / 'tmp_install/' ++test_install_destdir = meson.project_build_root() / 'tmp_install/' + + # DESTDIR + prefix appropriately munged + if build_system != 'windows' +@@ -3374,7 +3374,7 @@ test('install_test_files', + is_parallel: false, + suite: ['setup']) + +-test_result_dir = meson.build_root() / 'testrun' ++test_result_dir = meson.project_build_root() / 'testrun' + + + # XXX: pg_regress doesn't assign unique ports on windows. To avoid the +@@ -3385,12 +3385,12 @@ testport = 40000 + + test_env = environment() + +-test_initdb_template = meson.build_root() / 'tmp_install' / 'initdb-template' ++test_initdb_template = meson.project_build_root() / 'tmp_install' / 'initdb-template' + test_env.set('PG_REGRESS', pg_regress.full_path()) + test_env.set('REGRESS_SHLIB', regress_module.full_path()) + test_env.set('INITDB_TEMPLATE', test_initdb_template) + # for Cluster.pm's portlock logic +-test_env.set('top_builddir', meson.build_root()) ++test_env.set('top_builddir', meson.project_build_root()) + + # Test suites that are not safe by default but can be run if selected + # by the user via the whitespace-separated list in variable PG_TEST_EXTRA. +@@ -3458,7 +3458,7 @@ testwrap = files('src/tools/testwrap') + foreach test_dir : tests + testwrap_base = [ + testwrap, +- '--basedir', meson.build_root(), ++ '--basedir', meson.project_build_root(), + '--srcdir', test_dir['sd'], + ] + +@@ -3571,7 +3571,7 @@ foreach test_dir : tests + + test_command = [ + perl.path(), +- '-I', meson.source_root() / 'src/test/perl', ++ '-I', meson.project_source_root() / 'src/test/perl', + '-I', test_dir['sd'], + ] + +@@ -3687,7 +3687,7 @@ tar_gz = custom_target('tar.gz', + '--format', 'tar.gz', + '-9', + '--prefix', distdir + '/', +- '-o', join_paths(meson.build_root(), '@OUTPUT@'), ++ '-o', join_paths(meson.project_build_root(), '@OUTPUT@'), + pg_git_revision], + output: distdir + '.tar.gz', + ) +@@ -3701,7 +3701,7 @@ if bzip2.found() + 'archive', + '--format', 'tar.bz2', + '--prefix', distdir + '/', +- '-o', join_paths(meson.build_root(), '@OUTPUT@'), ++ '-o', join_paths(meson.project_build_root(), '@OUTPUT@'), + pg_git_revision], + output: distdir + '.tar.bz2', + ) +diff --git a/src/backend/jit/llvm/meson.build b/src/backend/jit/llvm/meson.build +index b76e2e70547..80f5090d2d7 100644 +--- a/src/backend/jit/llvm/meson.build ++++ b/src/backend/jit/llvm/meson.build +@@ -68,9 +68,9 @@ bitcode_cflags += get_option('c_args') + bitcode_cflags += cppflags + + # XXX: Worth improving on the logic to find directories here +-bitcode_cflags += '-I@BUILD_ROOT@/src/include' +-bitcode_cflags += '-I@BUILD_ROOT@/src/backend/utils/misc' +-bitcode_cflags += '-I@SOURCE_ROOT@/src/include' ++bitcode_cflags += '-I@0@/src/include'.format(meson.project_build_root()) ++bitcode_cflags += '-I@0@/src/backend/utils/misc'.format(meson.project_build_root()) ++bitcode_cflags += '-I@0@/src/include'.format(meson.project_source_root()) + + + # Note this is intentionally not installed to bitcodedir, as it's not for +diff --git a/src/bin/psql/meson.build b/src/bin/psql/meson.build +index f3a6392138a..9ba92cb163a 100644 +--- a/src/bin/psql/meson.build ++++ b/src/bin/psql/meson.build +@@ -29,7 +29,7 @@ sql_help = custom_target('psql_help', + depfile: 'sql_help.dep', + command: [ + perl, files('create_help.pl'), +- '--docdir', '@SOURCE_ROOT@/doc/src/sgml/ref', ++ '--docdir', '@0@/doc/src/sgml/ref'.format(meson.project_source_root()), + '--depfile', '@DEPFILE@', + '--outdir', '@OUTDIR@', + '--basename', 'sql_help', +diff --git a/src/common/unicode/meson.build b/src/common/unicode/meson.build +index b9a4181c320..0c6d37bae6e 100644 +--- a/src/common/unicode/meson.build ++++ b/src/common/unicode/meson.build +@@ -174,7 +174,7 @@ update_unicode = custom_target('update-unicode', + depends: update_unicode_dep, + output: ['dont-exist'], + input: update_unicode_targets, +- command: [cp, '@INPUT@', '@SOURCE_ROOT@/src/include/common/'], ++ command: [cp, '@INPUT@', '@0@/src/include/common/'.format(meson.project_source_root())], + build_by_default: false, + build_always_stale: true, + ) +diff --git a/src/include/catalog/meson.build b/src/include/catalog/meson.build +index f70d1daba52..0194baa3f9a 100644 +--- a/src/include/catalog/meson.build ++++ b/src/include/catalog/meson.build +@@ -136,7 +136,7 @@ generated_catalog_headers = custom_target('generated_catalog_headers', + command: [ + perl, + files('../../backend/catalog/genbki.pl'), +- '--include-path=@SOURCE_ROOT@/src/include', ++ '--include-path=@0@/src/include'.format(meson.project_source_root()), + '--set-version=' + pg_version_major.to_string(), + '--output=@OUTDIR@', '@INPUT@' + ], +diff --git a/src/include/nodes/meson.build b/src/include/nodes/meson.build +index b665e55b657..cef59ef8098 100644 +--- a/src/include/nodes/meson.build ++++ b/src/include/nodes/meson.build +@@ -27,7 +27,7 @@ node_support_input_i = [ + + node_support_input = [] + foreach i : node_support_input_i +- node_support_input += meson.source_root() / 'src' / 'include' / i ++ node_support_input += meson.project_source_root() / 'src' / 'include' / i + endforeach + + node_support_output = [ +diff --git a/src/include/pch/meson.build b/src/include/pch/meson.build +index 942d4c9956f..48a2e876176 100644 +--- a/src/include/pch/meson.build ++++ b/src/include/pch/meson.build +@@ -1,6 +1,6 @@ + # Copyright (c) 2022-2024, PostgreSQL Global Development Group + + # See https://github.com/mesonbuild/meson/issues/10338 +-pch_c_h = meson.source_root() / meson.current_source_dir() / 'c_pch.h' +-pch_postgres_h = meson.source_root() / meson.current_source_dir() / 'postgres_pch.h' +-pch_postgres_fe_h = meson.source_root() / meson.current_source_dir() / 'postgres_fe_pch.h' ++pch_c_h = meson.project_source_root() / meson.current_source_dir() / 'c_pch.h' ++pch_postgres_h = meson.project_source_root() / meson.current_source_dir() / 'postgres_pch.h' ++pch_postgres_fe_h = meson.project_source_root() / meson.current_source_dir() / 'postgres_fe_pch.h' +diff --git a/src/include/utils/meson.build b/src/include/utils/meson.build +index 8d0cd456536..1173a728b50 100644 +--- a/src/include/utils/meson.build ++++ b/src/include/utils/meson.build +@@ -62,7 +62,7 @@ fmgrtab_target = custom_target('fmgrtab', + input: '../catalog/pg_proc.dat', + output : fmgrtab_output, + depend_files: catalog_pm, +- command: [perl, '-I', '@SOURCE_ROOT@/src/backend/catalog/', files('../../backend/utils/Gen_fmgrtab.pl'), '--include-path=@SOURCE_ROOT@/src/include', '--output=@OUTDIR@', '@INPUT@'], ++ command: [perl, '-I', '@0@/src/backend/catalog/'.format(meson.project_source_root()), files('../../backend/utils/Gen_fmgrtab.pl'), '--include-path=@SOURCE_ROOT@/subprojects/postgresql-17.6/src/include', '--output=@OUTDIR@', '@INPUT@'], + install: true, + install_dir: [dir_include_server / 'utils', dir_include_server / 'utils', false], + ) +diff --git a/src/interfaces/ecpg/test/meson.build b/src/interfaces/ecpg/test/meson.build +index a0d0f38d19a..021252a4d35 100644 +--- a/src/interfaces/ecpg/test/meson.build ++++ b/src/interfaces/ecpg/test/meson.build +@@ -46,7 +46,7 @@ ecpg_preproc_test_command_start = [ + ecpg_exe, + '--regression', + '-I@CURRENT_SOURCE_DIR@', +- '-I@SOURCE_ROOT@' + '/src/interfaces/ecpg/include/', ++ '-I@0@'.format(meson.project_source_root()) + '/src/interfaces/ecpg/include/', + ] + ecpg_preproc_test_command_end = [ + '-o', '@OUTPUT@', '@INPUT@' +diff --git a/src/makefiles/meson.build b/src/makefiles/meson.build +index 5618050b306..5e8cbce9e0a 100644 +--- a/src/makefiles/meson.build ++++ b/src/makefiles/meson.build +@@ -49,8 +49,8 @@ pgxs_kv = { + 'PORTNAME': portname, + 'PG_SYSROOT': pg_sysroot, + +- 'abs_top_builddir': meson.build_root(), +- 'abs_top_srcdir': meson.source_root(), ++ 'abs_top_builddir': meson.project_build_root(), ++ 'abs_top_srcdir': meson.project_source_root(), + + 'enable_rpath': get_option('rpath') ? 'yes' : 'no', + 'enable_nls': libintl.found() ? 'yes' : 'no', +diff --git a/src/pl/plperl/meson.build b/src/pl/plperl/meson.build +index 006f7356e6b..50e679f9161 100644 +--- a/src/pl/plperl/meson.build ++++ b/src/pl/plperl/meson.build +@@ -96,7 +96,7 @@ tests += { + 'plperl_transaction', + 'plperl_env', + ], +- 'regress_args': ['--dlpath', meson.build_root() / 'src/test/regress'], ++ 'regress_args': ['--dlpath', meson.project_build_root() / 'src/test/regress'], + }, + } + +diff --git a/src/test/modules/injection_points/meson.build b/src/test/modules/injection_points/meson.build +index c1892d760aa..d0bdc8c78e6 100644 +--- a/src/test/modules/injection_points/meson.build ++++ b/src/test/modules/injection_points/meson.build +@@ -36,7 +36,7 @@ tests += { + 'reindex_conc', + 'vacuum', + ], +- 'regress_args': ['--dlpath', meson.build_root() / 'src/test/regress'], ++ 'regress_args': ['--dlpath', meson.project_build_root() / 'src/test/regress'], + # The injection points are cluster-wide, so disable installcheck + 'runningcheck': false, + }, diff --git a/subprojects/packagefiles/util-linux/3761.patch b/subprojects/packagefiles/util-linux/3761.patch new file mode 100644 index 0000000..51cf4b9 --- /dev/null +++ b/subprojects/packagefiles/util-linux/3761.patch @@ -0,0 +1,13 @@ +diff --git a/meson.build b/meson.build +index 4ebf0eed407..6d216644757 100644 +--- a/meson.build ++++ b/meson.build +@@ -1473,7 +1473,7 @@ has_seminfo_type = cc.has_type('struct seminfo', args : '-D_GNU_SOURCE', prefix + + posixipc_libs = [] + if not cc.has_function('shm_open') and conf.get('HAVE_SYS_MMAN_H').to_string() == '1' +- posixipc_libs = cc.find_library('rt', required : true) ++ posixipc_libs += cc.find_library('rt', required : true) + endif + + if not cc.has_function('sem_close') and conf.get('HAVE_SEMAPHORE_H').to_string() == '1' diff --git a/subprojects/packagefiles/util-linux/uuid_h.patch b/subprojects/packagefiles/util-linux/uuid_h.patch new file mode 100644 index 0000000..0878ba3 --- /dev/null +++ b/subprojects/packagefiles/util-linux/uuid_h.patch @@ -0,0 +1,135 @@ +diff -ru util-linux-2.41.2.orig/libuuid/src/uuid/uuid.h util-linux-2.41.2/libuuid/src/uuid/uuid.h +--- util-linux-2.41.2.orig/libuuid/src/uuid/uuid.h 2025-10-12 22:34:55.954062201 +0800 ++++ util-linux-2.41.2/libuuid/src/uuid/uuid.h 2025-10-12 22:34:08.554390525 +0800 +@@ -0,0 +1,131 @@ ++/* ++ * Public include file for the UUID library ++ * ++ * Copyright (C) 1996, 1997, 1998 Theodore Ts'o. ++ * ++ * %Begin-Header% ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions ++ * are met: ++ * 1. Redistributions of source code must retain the above copyright ++ * notice, and the entire permission notice in its entirety, ++ * including the disclaimer of warranties. ++ * 2. Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * 3. The name of the author may not be used to endorse or promote ++ * products derived from this software without specific prior ++ * written permission. ++ * ++ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED ++ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES ++ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ALL OF ++ * WHICH ARE HEREBY DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE ++ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR ++ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT ++ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR ++ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF ++ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE ++ * USE OF THIS SOFTWARE, EVEN IF NOT ADVISED OF THE POSSIBILITY OF SUCH ++ * DAMAGE. ++ * %End-Header% ++ */ ++ ++#ifndef _UL_LIBUUID_UUID_H ++#define _UL_LIBUUID_UUID_H ++ ++#include ++#ifndef _WIN32 ++#include ++#endif ++#include ++ ++typedef unsigned char uuid_t[16]; ++ ++/* UUID Variant definitions */ ++#define UUID_VARIANT_NCS 0 ++#define UUID_VARIANT_DCE 1 ++#define UUID_VARIANT_MICROSOFT 2 ++#define UUID_VARIANT_OTHER 3 ++ ++#define UUID_VARIANT_SHIFT 5 ++#define UUID_VARIANT_MASK 0x7 ++ ++/* UUID Type definitions */ ++#define UUID_TYPE_DCE_NIL 0 ++#define UUID_TYPE_DCE_TIME 1 ++#define UUID_TYPE_DCE_SECURITY 2 ++#define UUID_TYPE_DCE_MD5 3 ++#define UUID_TYPE_DCE_RANDOM 4 ++#define UUID_TYPE_DCE_SHA1 5 ++#define UUID_TYPE_DCE_TIME_V6 6 ++#define UUID_TYPE_DCE_TIME_V7 7 ++#define UUID_TYPE_DCE_VENDOR 8 ++ ++#define UUID_TYPE_SHIFT 4 ++#define UUID_TYPE_MASK 0xf ++ ++#define UUID_STR_LEN 37 ++ ++/* Allow UUID constants to be defined */ ++#ifdef __GNUC__ ++#define UUID_DEFINE(name,u0,u1,u2,u3,u4,u5,u6,u7,u8,u9,u10,u11,u12,u13,u14,u15) \ ++ static const uuid_t name __attribute__ ((unused)) = {u0,u1,u2,u3,u4,u5,u6,u7,u8,u9,u10,u11,u12,u13,u14,u15} ++#else ++#define UUID_DEFINE(name,u0,u1,u2,u3,u4,u5,u6,u7,u8,u9,u10,u11,u12,u13,u14,u15) \ ++ static const uuid_t name = {u0,u1,u2,u3,u4,u5,u6,u7,u8,u9,u10,u11,u12,u13,u14,u15} ++#endif ++ ++#ifdef __cplusplus ++extern "C" { ++#endif ++ ++/* clear.c */ ++extern void uuid_clear(uuid_t uu); ++ ++/* compare.c */ ++extern int uuid_compare(const uuid_t uu1, const uuid_t uu2); ++ ++/* copy.c */ ++extern void uuid_copy(uuid_t dst, const uuid_t src); ++ ++/* gen_uuid.c */ ++extern void uuid_generate(uuid_t out); ++extern void uuid_generate_random(uuid_t out); ++extern void uuid_generate_time(uuid_t out); ++extern int uuid_generate_time_safe(uuid_t out); ++extern void uuid_generate_time_v6(uuid_t out); ++extern void uuid_generate_time_v7(uuid_t out); ++ ++extern void uuid_generate_md5(uuid_t out, const uuid_t ns, const char *name, size_t len); ++extern void uuid_generate_sha1(uuid_t out, const uuid_t ns, const char *name, size_t len); ++ ++/* isnull.c */ ++extern int uuid_is_null(const uuid_t uu); ++ ++/* parse.c */ ++extern int uuid_parse(const char *in, uuid_t uu); ++extern int uuid_parse_range(const char *in_start, const char *in_end, uuid_t uu); ++ ++/* unparse.c */ ++extern void uuid_unparse(const uuid_t uu, char *out); ++extern void uuid_unparse_lower(const uuid_t uu, char *out); ++extern void uuid_unparse_upper(const uuid_t uu, char *out); ++ ++/* uuid_time.c */ ++#if defined(__USE_TIME_BITS64) && defined(__GLIBC__) ++# define uuid_time uuid_time64 ++#endif ++extern time_t uuid_time(const uuid_t uu, struct timeval *ret_tv); ++extern int uuid_type(const uuid_t uu); ++extern int uuid_variant(const uuid_t uu); ++ ++/* predefined.c */ ++extern const uuid_t *uuid_get_template(const char *alias); ++ ++#ifdef __cplusplus ++} ++#endif ++ ++#endif /* _UL_LIBUUID_UUID_H */ diff --git a/patches/0001-Support-circular-calls-when-multi-module-enabled.patch b/subprojects/packagefiles/wamr/0001-Support-circular-calls-when-multi-module-enabled.patch similarity index 100% rename from patches/0001-Support-circular-calls-when-multi-module-enabled.patch rename to subprojects/packagefiles/wamr/0001-Support-circular-calls-when-multi-module-enabled.patch diff --git a/subprojects/packagefiles/wamr/0001.patch b/subprojects/packagefiles/wamr/0001.patch new file mode 100644 index 0000000..94389f3 --- /dev/null +++ b/subprojects/packagefiles/wamr/0001.patch @@ -0,0 +1,39 @@ +From af896e1c1de2bfd8add4b841fb820f13214761e7 Mon Sep 17 00:00:00 2001 +From: Xenia Lu +Date: Fri, 3 Oct 2025 11:18:17 +0800 +Subject: [PATCH 1/4] fix: false OOB in array.fill for interp + +--- + core/iwasm/interpreter/wasm_interp_classic.c | 2 +- + core/iwasm/interpreter/wasm_interp_fast.c | 2 +- + 2 files changed, 2 insertions(+), 2 deletions(-) + +diff --git a/core/iwasm/interpreter/wasm_interp_classic.c b/core/iwasm/interpreter/wasm_interp_classic.c +index edc473f2..d0ac01bd 100644 +--- a/core/iwasm/interpreter/wasm_interp_classic.c ++++ b/core/iwasm/interpreter/wasm_interp_classic.c +@@ -3162,7 +3162,7 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, + + if (len > 0) { + if ((uint64)start_offset + len +- >= wasm_array_obj_length(array_obj)) { ++ > wasm_array_obj_length(array_obj)) { + wasm_set_exception( + module, "out of bounds array access"); + goto got_exception; +diff --git a/core/iwasm/interpreter/wasm_interp_fast.c b/core/iwasm/interpreter/wasm_interp_fast.c +index 36d4538f..8f6bceb5 100644 +--- a/core/iwasm/interpreter/wasm_interp_fast.c ++++ b/core/iwasm/interpreter/wasm_interp_fast.c +@@ -2562,7 +2562,7 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, + + if (len > 0) { + if ((uint64)start_offset + len +- >= wasm_array_obj_length(array_obj)) { ++ > wasm_array_obj_length(array_obj)) { + wasm_set_exception( + module, "out of bounds array access"); + goto got_exception; +-- +2.51.0 + diff --git a/patches/0002-wamrc-allow-building-without-DUMP_CALL_STACK.patch b/subprojects/packagefiles/wamr/0002-wamrc-allow-building-without-DUMP_CALL_STACK.patch similarity index 100% rename from patches/0002-wamrc-allow-building-without-DUMP_CALL_STACK.patch rename to subprojects/packagefiles/wamr/0002-wamrc-allow-building-without-DUMP_CALL_STACK.patch diff --git a/subprojects/packagefiles/wamr/0002.patch b/subprojects/packagefiles/wamr/0002.patch new file mode 100644 index 0000000..fb63c86 --- /dev/null +++ b/subprojects/packagefiles/wamr/0002.patch @@ -0,0 +1,62 @@ +From a0999fbf49f7d89f789c809f3561817e98704728 Mon Sep 17 00:00:00 2001 +From: Xenia Lu +Date: Wed, 24 Sep 2025 09:14:14 +0800 +Subject: [PATCH 2/4] loader: fix block/loop ref params type checking + +--- + core/iwasm/interpreter/wasm_loader.c | 29 ++++++++++++++++++++++++++++ + 1 file changed, 29 insertions(+) + +diff --git a/core/iwasm/interpreter/wasm_loader.c b/core/iwasm/interpreter/wasm_loader.c +index 3f8c68db..b86c32d9 100644 +--- a/core/iwasm/interpreter/wasm_loader.c ++++ b/core/iwasm/interpreter/wasm_loader.c +@@ -11911,9 +11911,25 @@ re_scan: + WASMFuncType *wasm_type = block_type.u.type; + + BranchBlock *cur_block = loader_ctx->frame_csp - 1; ++#if WASM_ENABLE_GC != 0 ++ WASMRefType *ref_type; ++ uint32 j = 0; ++#endif + #if WASM_ENABLE_FAST_INTERP != 0 + uint32 cell_num; + available_params = block_type.u.type->param_count; ++#endif ++#if WASM_ENABLE_GC != 0 ++ /* find the index of the last param ++ * in wasm_type->ref_type_maps as j */ ++ for (i = 0; i < block_type.u.type->param_count; i++) { ++ if (wasm_is_type_multi_byte_type(wasm_type->types[i])) { ++ j += 1; ++ } ++ } ++ if (j > 0) { ++ j -= 1; ++ } + #endif + for (i = 0; i < block_type.u.type->param_count; i++) { + +@@ -11927,6 +11943,19 @@ re_scan: + #endif + break; + } ++#if WASM_ENABLE_GC != 0 ++ if (wasm_is_type_multi_byte_type( ++ wasm_type ++ ->types[wasm_type->param_count - i - 1])) { ++ bh_assert(wasm_type->ref_type_maps[j].index ++ == wasm_type->param_count - i - 1); ++ ref_type = wasm_type->ref_type_maps[j].ref_type; ++ bh_memcpy_s(&wasm_ref_type, sizeof(WASMRefType), ++ ref_type, ++ wasm_reftype_struct_size(ref_type)); ++ j--; ++ } ++#endif + + POP_TYPE( + wasm_type->types[wasm_type->param_count - i - 1]); +-- +2.51.0 + diff --git a/patches/0003-fix-parameter-handling-in-wasm_loader-with-GC-enable.patch b/subprojects/packagefiles/wamr/0003-fix-parameter-handling-in-wasm_loader-with-GC-enable.patch similarity index 100% rename from patches/0003-fix-parameter-handling-in-wasm_loader-with-GC-enable.patch rename to subprojects/packagefiles/wamr/0003-fix-parameter-handling-in-wasm_loader-with-GC-enable.patch diff --git a/patches/0004-Tweak-submodule-loading-hooks.patch b/subprojects/packagefiles/wamr/0004-Tweak-submodule-loading-hooks.patch similarity index 100% rename from patches/0004-Tweak-submodule-loading-hooks.patch rename to subprojects/packagefiles/wamr/0004-Tweak-submodule-loading-hooks.patch diff --git a/subprojects/packagefiles/wamr/0004.patch b/subprojects/packagefiles/wamr/0004.patch new file mode 100644 index 0000000..aa4ab47 --- /dev/null +++ b/subprojects/packagefiles/wamr/0004.patch @@ -0,0 +1,25 @@ +From 0df937642752c70d4d67136554c17c4f1430282f Mon Sep 17 00:00:00 2001 +From: Xenia Lu +Date: Sun, 5 Oct 2025 09:36:44 +0800 +Subject: [PATCH 4/4] fix: typo in AOT stack dump with GC + +--- + core/iwasm/aot/aot_runtime.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/core/iwasm/aot/aot_runtime.c b/core/iwasm/aot/aot_runtime.c +index d2621fb2..85d7a3ca 100644 +--- a/core/iwasm/aot/aot_runtime.c ++++ b/core/iwasm/aot/aot_runtime.c +@@ -4477,7 +4477,7 @@ aot_create_call_stack(struct WASMExecEnv *exec_env) + frame.frame_ref = (uint8 *)frame.lp + (frame_ref - (uint8 *)lp); + /* copy local ref flags from AOT module */ + bh_memcpy_s(frame.frame_ref, local_ref_flags_cell_num, +- local_ref_flags, lp_size); ++ local_ref_flags, local_ref_flags_cell_num); + #endif + } + +-- +2.51.0 + diff --git a/patches/0005-Support-custom-global-resolver.patch b/subprojects/packagefiles/wamr/0005-Support-custom-global-resolver.patch similarity index 100% rename from patches/0005-Support-custom-global-resolver.patch rename to subprojects/packagefiles/wamr/0005-Support-custom-global-resolver.patch diff --git a/subprojects/postgresql.wrap b/subprojects/postgresql.wrap new file mode 100644 index 0000000..6f080bc --- /dev/null +++ b/subprojects/postgresql.wrap @@ -0,0 +1,6 @@ +[wrap-file] +directory = postgresql-17.6 +source_url = https://ftp.postgresql.org/pub/source/v17.6/postgresql-17.6.tar.gz +source_filename = postgresql-17.6.tar.gz +source_hash = 2910b85283674da2dae6ac13fe5ebbaaf3c482446396cba32e6728d3cc736d86 +diff_files = postgresql/meson-0.56.patch, postgresql/embed-libs.patch diff --git a/subprojects/util-linux.wrap b/subprojects/util-linux.wrap new file mode 100644 index 0000000..7f9a7b1 --- /dev/null +++ b/subprojects/util-linux.wrap @@ -0,0 +1,9 @@ +[wrap-file] +directory = util-linux-2.41.2 +source_url = https://github.com/util-linux/util-linux/archive/refs/tags/v2.41.2.tar.gz +source_filename = util-linux-2.41.2.tar.gz +source_hash = 534aa113a323d6866c5f46baf909618dcc60c391ad24a91814e5d21511cefd30 +diff_files = util-linux/3761.patch, util-linux/uuid_h.patch + +[provide] +uuid = uuid_dep diff --git a/subprojects/wamr.wrap b/subprojects/wamr.wrap new file mode 100644 index 0000000..3ceccd5 --- /dev/null +++ b/subprojects/wamr.wrap @@ -0,0 +1,7 @@ +[wrap-file] +directory = wasm-micro-runtime-WAMR-2.4.2 +source_url = https://github.com/bytecodealliance/wasm-micro-runtime/archive/refs/tags/WAMR-2.4.2.tar.gz +source_filename = wamr-2.4.2.tar.gz +source_hash = 73380561a01f4863506e855c2c265cf03c5b6efb17bbb8c9bbafe80745fd00ef +diff_files = wamr/0001.patch, wamr/0002.patch, wamr/0004.patch +method = cmake diff --git a/subprojects/zlib.wrap b/subprojects/zlib.wrap new file mode 100644 index 0000000..e2f2958 --- /dev/null +++ b/subprojects/zlib.wrap @@ -0,0 +1,13 @@ +[wrap-file] +directory = zlib-1.3.1 +source_url = http://zlib.net/fossils/zlib-1.3.1.tar.gz +source_fallback_url = https://github.com/mesonbuild/wrapdb/releases/download/zlib_1.3.1-2/zlib-1.3.1.tar.gz +source_filename = zlib-1.3.1.tar.gz +source_hash = 9a93b2b7dfdac77ceba5a558a580e74667dd6fede4585b91eefb60f03b72df23 +patch_filename = zlib_1.3.1-2_patch.zip +patch_url = https://wrapdb.mesonbuild.com/v2/zlib_1.3.1-2/get_patch +patch_hash = 9cacea02e1119964bc51e92dd2359b14df723a36cfe0df1c78d55d9c9f2763ae +wrapdb_version = 1.3.1-2 + +[provide] +zlib = zlib_dep diff --git a/uv.lock b/uv.lock new file mode 100644 index 0000000..5ecb207 --- /dev/null +++ b/uv.lock @@ -0,0 +1,144 @@ +version = 1 +revision = 3 +requires-python = ">=3.9" + +[[package]] +name = "certifi" +version = "2025.10.5" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/4c/5b/b6ce21586237c77ce67d01dc5507039d444b630dd76611bbca2d8e5dcd91/certifi-2025.10.5.tar.gz", hash = "sha256:47c09d31ccf2acf0be3f701ea53595ee7e0b8fa08801c6624be771df09ae7b43", size = 164519, upload-time = "2025-10-05T04:12:15.808Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/e4/37/af0d2ef3967ac0d6113837b44a4f0bfe1328c2b9763bd5b1744520e5cfed/certifi-2025.10.5-py3-none-any.whl", hash = "sha256:0f212c2744a9bb6de0c56639a6f68afe01ecd92d91f14ae897c4fe7bbeeef0de", size = 163286, upload-time = "2025-10-05T04:12:14.03Z" }, +] + +[[package]] +name = "charset-normalizer" +version = "3.4.3" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/83/2d/5fd176ceb9b2fc619e63405525573493ca23441330fcdaee6bef9460e924/charset_normalizer-3.4.3.tar.gz", hash = "sha256:6fce4b8500244f6fcb71465d4a4930d132ba9ab8e71a7859e6a5d59851068d14", size = 122371, upload-time = "2025-08-09T07:57:28.46Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/d6/98/f3b8013223728a99b908c9344da3aa04ee6e3fa235f19409033eda92fb78/charset_normalizer-3.4.3-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:fb7f67a1bfa6e40b438170ebdc8158b78dc465a5a67b6dde178a46987b244a72", size = 207695, upload-time = "2025-08-09T07:55:36.452Z" }, + { url = "https://files.pythonhosted.org/packages/21/40/5188be1e3118c82dcb7c2a5ba101b783822cfb413a0268ed3be0468532de/charset_normalizer-3.4.3-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:cc9370a2da1ac13f0153780040f465839e6cccb4a1e44810124b4e22483c93fe", size = 147153, upload-time = "2025-08-09T07:55:38.467Z" }, + { url = "https://files.pythonhosted.org/packages/37/60/5d0d74bc1e1380f0b72c327948d9c2aca14b46a9efd87604e724260f384c/charset_normalizer-3.4.3-cp310-cp310-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:07a0eae9e2787b586e129fdcbe1af6997f8d0e5abaa0bc98c0e20e124d67e601", size = 160428, upload-time = "2025-08-09T07:55:40.072Z" }, + { url = "https://files.pythonhosted.org/packages/85/9a/d891f63722d9158688de58d050c59dc3da560ea7f04f4c53e769de5140f5/charset_normalizer-3.4.3-cp310-cp310-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:74d77e25adda8581ffc1c720f1c81ca082921329452eba58b16233ab1842141c", size = 157627, upload-time = "2025-08-09T07:55:41.706Z" }, + { url = "https://files.pythonhosted.org/packages/65/1a/7425c952944a6521a9cfa7e675343f83fd82085b8af2b1373a2409c683dc/charset_normalizer-3.4.3-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d0e909868420b7049dafd3a31d45125b31143eec59235311fc4c57ea26a4acd2", size = 152388, upload-time = "2025-08-09T07:55:43.262Z" }, + { url = "https://files.pythonhosted.org/packages/f0/c9/a2c9c2a355a8594ce2446085e2ec97fd44d323c684ff32042e2a6b718e1d/charset_normalizer-3.4.3-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:c6f162aabe9a91a309510d74eeb6507fab5fff92337a15acbe77753d88d9dcf0", size = 150077, upload-time = "2025-08-09T07:55:44.903Z" }, + { url = "https://files.pythonhosted.org/packages/3b/38/20a1f44e4851aa1c9105d6e7110c9d020e093dfa5836d712a5f074a12bf7/charset_normalizer-3.4.3-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:4ca4c094de7771a98d7fbd67d9e5dbf1eb73efa4f744a730437d8a3a5cf994f0", size = 161631, upload-time = "2025-08-09T07:55:46.346Z" }, + { url = "https://files.pythonhosted.org/packages/a4/fa/384d2c0f57edad03d7bec3ebefb462090d8905b4ff5a2d2525f3bb711fac/charset_normalizer-3.4.3-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:02425242e96bcf29a49711b0ca9f37e451da7c70562bc10e8ed992a5a7a25cc0", size = 159210, upload-time = "2025-08-09T07:55:47.539Z" }, + { url = "https://files.pythonhosted.org/packages/33/9e/eca49d35867ca2db336b6ca27617deed4653b97ebf45dfc21311ce473c37/charset_normalizer-3.4.3-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:78deba4d8f9590fe4dae384aeff04082510a709957e968753ff3c48399f6f92a", size = 153739, upload-time = "2025-08-09T07:55:48.744Z" }, + { url = "https://files.pythonhosted.org/packages/2a/91/26c3036e62dfe8de8061182d33be5025e2424002125c9500faff74a6735e/charset_normalizer-3.4.3-cp310-cp310-win32.whl", hash = "sha256:d79c198e27580c8e958906f803e63cddb77653731be08851c7df0b1a14a8fc0f", size = 99825, upload-time = "2025-08-09T07:55:50.305Z" }, + { url = "https://files.pythonhosted.org/packages/e2/c6/f05db471f81af1fa01839d44ae2a8bfeec8d2a8b4590f16c4e7393afd323/charset_normalizer-3.4.3-cp310-cp310-win_amd64.whl", hash = "sha256:c6e490913a46fa054e03699c70019ab869e990270597018cef1d8562132c2669", size = 107452, upload-time = "2025-08-09T07:55:51.461Z" }, + { url = "https://files.pythonhosted.org/packages/7f/b5/991245018615474a60965a7c9cd2b4efbaabd16d582a5547c47ee1c7730b/charset_normalizer-3.4.3-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:b256ee2e749283ef3ddcff51a675ff43798d92d746d1a6e4631bf8c707d22d0b", size = 204483, upload-time = "2025-08-09T07:55:53.12Z" }, + { url = "https://files.pythonhosted.org/packages/c7/2a/ae245c41c06299ec18262825c1569c5d3298fc920e4ddf56ab011b417efd/charset_normalizer-3.4.3-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:13faeacfe61784e2559e690fc53fa4c5ae97c6fcedb8eb6fb8d0a15b475d2c64", size = 145520, upload-time = "2025-08-09T07:55:54.712Z" }, + { url = "https://files.pythonhosted.org/packages/3a/a4/b3b6c76e7a635748c4421d2b92c7b8f90a432f98bda5082049af37ffc8e3/charset_normalizer-3.4.3-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:00237675befef519d9af72169d8604a067d92755e84fe76492fef5441db05b91", size = 158876, upload-time = "2025-08-09T07:55:56.024Z" }, + { url = "https://files.pythonhosted.org/packages/e2/e6/63bb0e10f90a8243c5def74b5b105b3bbbfb3e7bb753915fe333fb0c11ea/charset_normalizer-3.4.3-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:585f3b2a80fbd26b048a0be90c5aae8f06605d3c92615911c3a2b03a8a3b796f", size = 156083, upload-time = "2025-08-09T07:55:57.582Z" }, + { url = "https://files.pythonhosted.org/packages/87/df/b7737ff046c974b183ea9aa111b74185ac8c3a326c6262d413bd5a1b8c69/charset_normalizer-3.4.3-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:0e78314bdc32fa80696f72fa16dc61168fda4d6a0c014e0380f9d02f0e5d8a07", size = 150295, upload-time = "2025-08-09T07:55:59.147Z" }, + { url = "https://files.pythonhosted.org/packages/61/f1/190d9977e0084d3f1dc169acd060d479bbbc71b90bf3e7bf7b9927dec3eb/charset_normalizer-3.4.3-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:96b2b3d1a83ad55310de8c7b4a2d04d9277d5591f40761274856635acc5fcb30", size = 148379, upload-time = "2025-08-09T07:56:00.364Z" }, + { url = "https://files.pythonhosted.org/packages/4c/92/27dbe365d34c68cfe0ca76f1edd70e8705d82b378cb54ebbaeabc2e3029d/charset_normalizer-3.4.3-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:939578d9d8fd4299220161fdd76e86c6a251987476f5243e8864a7844476ba14", size = 160018, upload-time = "2025-08-09T07:56:01.678Z" }, + { url = "https://files.pythonhosted.org/packages/99/04/baae2a1ea1893a01635d475b9261c889a18fd48393634b6270827869fa34/charset_normalizer-3.4.3-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:fd10de089bcdcd1be95a2f73dbe6254798ec1bda9f450d5828c96f93e2536b9c", size = 157430, upload-time = "2025-08-09T07:56:02.87Z" }, + { url = "https://files.pythonhosted.org/packages/2f/36/77da9c6a328c54d17b960c89eccacfab8271fdaaa228305330915b88afa9/charset_normalizer-3.4.3-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:1e8ac75d72fa3775e0b7cb7e4629cec13b7514d928d15ef8ea06bca03ef01cae", size = 151600, upload-time = "2025-08-09T07:56:04.089Z" }, + { url = "https://files.pythonhosted.org/packages/64/d4/9eb4ff2c167edbbf08cdd28e19078bf195762e9bd63371689cab5ecd3d0d/charset_normalizer-3.4.3-cp311-cp311-win32.whl", hash = "sha256:6cf8fd4c04756b6b60146d98cd8a77d0cdae0e1ca20329da2ac85eed779b6849", size = 99616, upload-time = "2025-08-09T07:56:05.658Z" }, + { url = "https://files.pythonhosted.org/packages/f4/9c/996a4a028222e7761a96634d1820de8a744ff4327a00ada9c8942033089b/charset_normalizer-3.4.3-cp311-cp311-win_amd64.whl", hash = "sha256:31a9a6f775f9bcd865d88ee350f0ffb0e25936a7f930ca98995c05abf1faf21c", size = 107108, upload-time = "2025-08-09T07:56:07.176Z" }, + { url = "https://files.pythonhosted.org/packages/e9/5e/14c94999e418d9b87682734589404a25854d5f5d0408df68bc15b6ff54bb/charset_normalizer-3.4.3-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:e28e334d3ff134e88989d90ba04b47d84382a828c061d0d1027b1b12a62b39b1", size = 205655, upload-time = "2025-08-09T07:56:08.475Z" }, + { url = "https://files.pythonhosted.org/packages/7d/a8/c6ec5d389672521f644505a257f50544c074cf5fc292d5390331cd6fc9c3/charset_normalizer-3.4.3-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0cacf8f7297b0c4fcb74227692ca46b4a5852f8f4f24b3c766dd94a1075c4884", size = 146223, upload-time = "2025-08-09T07:56:09.708Z" }, + { url = "https://files.pythonhosted.org/packages/fc/eb/a2ffb08547f4e1e5415fb69eb7db25932c52a52bed371429648db4d84fb1/charset_normalizer-3.4.3-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:c6fd51128a41297f5409deab284fecbe5305ebd7e5a1f959bee1c054622b7018", size = 159366, upload-time = "2025-08-09T07:56:11.326Z" }, + { url = "https://files.pythonhosted.org/packages/82/10/0fd19f20c624b278dddaf83b8464dcddc2456cb4b02bb902a6da126b87a1/charset_normalizer-3.4.3-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:3cfb2aad70f2c6debfbcb717f23b7eb55febc0bb23dcffc0f076009da10c6392", size = 157104, upload-time = "2025-08-09T07:56:13.014Z" }, + { url = "https://files.pythonhosted.org/packages/16/ab/0233c3231af734f5dfcf0844aa9582d5a1466c985bbed6cedab85af9bfe3/charset_normalizer-3.4.3-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:1606f4a55c0fd363d754049cdf400175ee96c992b1f8018b993941f221221c5f", size = 151830, upload-time = "2025-08-09T07:56:14.428Z" }, + { url = "https://files.pythonhosted.org/packages/ae/02/e29e22b4e02839a0e4a06557b1999d0a47db3567e82989b5bb21f3fbbd9f/charset_normalizer-3.4.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:027b776c26d38b7f15b26a5da1044f376455fb3766df8fc38563b4efbc515154", size = 148854, upload-time = "2025-08-09T07:56:16.051Z" }, + { url = "https://files.pythonhosted.org/packages/05/6b/e2539a0a4be302b481e8cafb5af8792da8093b486885a1ae4d15d452bcec/charset_normalizer-3.4.3-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:42e5088973e56e31e4fa58eb6bd709e42fc03799c11c42929592889a2e54c491", size = 160670, upload-time = "2025-08-09T07:56:17.314Z" }, + { url = "https://files.pythonhosted.org/packages/31/e7/883ee5676a2ef217a40ce0bffcc3d0dfbf9e64cbcfbdf822c52981c3304b/charset_normalizer-3.4.3-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:cc34f233c9e71701040d772aa7490318673aa7164a0efe3172b2981218c26d93", size = 158501, upload-time = "2025-08-09T07:56:18.641Z" }, + { url = "https://files.pythonhosted.org/packages/c1/35/6525b21aa0db614cf8b5792d232021dca3df7f90a1944db934efa5d20bb1/charset_normalizer-3.4.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:320e8e66157cc4e247d9ddca8e21f427efc7a04bbd0ac8a9faf56583fa543f9f", size = 153173, upload-time = "2025-08-09T07:56:20.289Z" }, + { url = "https://files.pythonhosted.org/packages/50/ee/f4704bad8201de513fdc8aac1cabc87e38c5818c93857140e06e772b5892/charset_normalizer-3.4.3-cp312-cp312-win32.whl", hash = "sha256:fb6fecfd65564f208cbf0fba07f107fb661bcd1a7c389edbced3f7a493f70e37", size = 99822, upload-time = "2025-08-09T07:56:21.551Z" }, + { url = "https://files.pythonhosted.org/packages/39/f5/3b3836ca6064d0992c58c7561c6b6eee1b3892e9665d650c803bd5614522/charset_normalizer-3.4.3-cp312-cp312-win_amd64.whl", hash = "sha256:86df271bf921c2ee3818f0522e9a5b8092ca2ad8b065ece5d7d9d0e9f4849bcc", size = 107543, upload-time = "2025-08-09T07:56:23.115Z" }, + { url = "https://files.pythonhosted.org/packages/65/ca/2135ac97709b400c7654b4b764daf5c5567c2da45a30cdd20f9eefe2d658/charset_normalizer-3.4.3-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:14c2a87c65b351109f6abfc424cab3927b3bdece6f706e4d12faaf3d52ee5efe", size = 205326, upload-time = "2025-08-09T07:56:24.721Z" }, + { url = "https://files.pythonhosted.org/packages/71/11/98a04c3c97dd34e49c7d247083af03645ca3730809a5509443f3c37f7c99/charset_normalizer-3.4.3-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:41d1fc408ff5fdfb910200ec0e74abc40387bccb3252f3f27c0676731df2b2c8", size = 146008, upload-time = "2025-08-09T07:56:26.004Z" }, + { url = "https://files.pythonhosted.org/packages/60/f5/4659a4cb3c4ec146bec80c32d8bb16033752574c20b1252ee842a95d1a1e/charset_normalizer-3.4.3-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:1bb60174149316da1c35fa5233681f7c0f9f514509b8e399ab70fea5f17e45c9", size = 159196, upload-time = "2025-08-09T07:56:27.25Z" }, + { url = "https://files.pythonhosted.org/packages/86/9e/f552f7a00611f168b9a5865a1414179b2c6de8235a4fa40189f6f79a1753/charset_normalizer-3.4.3-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:30d006f98569de3459c2fc1f2acde170b7b2bd265dc1943e87e1a4efe1b67c31", size = 156819, upload-time = "2025-08-09T07:56:28.515Z" }, + { url = "https://files.pythonhosted.org/packages/7e/95/42aa2156235cbc8fa61208aded06ef46111c4d3f0de233107b3f38631803/charset_normalizer-3.4.3-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:416175faf02e4b0810f1f38bcb54682878a4af94059a1cd63b8747244420801f", size = 151350, upload-time = "2025-08-09T07:56:29.716Z" }, + { url = "https://files.pythonhosted.org/packages/c2/a9/3865b02c56f300a6f94fc631ef54f0a8a29da74fb45a773dfd3dcd380af7/charset_normalizer-3.4.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:6aab0f181c486f973bc7262a97f5aca3ee7e1437011ef0c2ec04b5a11d16c927", size = 148644, upload-time = "2025-08-09T07:56:30.984Z" }, + { url = "https://files.pythonhosted.org/packages/77/d9/cbcf1a2a5c7d7856f11e7ac2d782aec12bdfea60d104e60e0aa1c97849dc/charset_normalizer-3.4.3-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:fdabf8315679312cfa71302f9bd509ded4f2f263fb5b765cf1433b39106c3cc9", size = 160468, upload-time = "2025-08-09T07:56:32.252Z" }, + { url = "https://files.pythonhosted.org/packages/f6/42/6f45efee8697b89fda4d50580f292b8f7f9306cb2971d4b53f8914e4d890/charset_normalizer-3.4.3-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:bd28b817ea8c70215401f657edef3a8aa83c29d447fb0b622c35403780ba11d5", size = 158187, upload-time = "2025-08-09T07:56:33.481Z" }, + { url = "https://files.pythonhosted.org/packages/70/99/f1c3bdcfaa9c45b3ce96f70b14f070411366fa19549c1d4832c935d8e2c3/charset_normalizer-3.4.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:18343b2d246dc6761a249ba1fb13f9ee9a2bcd95decc767319506056ea4ad4dc", size = 152699, upload-time = "2025-08-09T07:56:34.739Z" }, + { url = "https://files.pythonhosted.org/packages/a3/ad/b0081f2f99a4b194bcbb1934ef3b12aa4d9702ced80a37026b7607c72e58/charset_normalizer-3.4.3-cp313-cp313-win32.whl", hash = "sha256:6fb70de56f1859a3f71261cbe41005f56a7842cc348d3aeb26237560bfa5e0ce", size = 99580, upload-time = "2025-08-09T07:56:35.981Z" }, + { url = "https://files.pythonhosted.org/packages/9a/8f/ae790790c7b64f925e5c953b924aaa42a243fb778fed9e41f147b2a5715a/charset_normalizer-3.4.3-cp313-cp313-win_amd64.whl", hash = "sha256:cf1ebb7d78e1ad8ec2a8c4732c7be2e736f6e5123a4146c5b89c9d1f585f8cef", size = 107366, upload-time = "2025-08-09T07:56:37.339Z" }, + { url = "https://files.pythonhosted.org/packages/8e/91/b5a06ad970ddc7a0e513112d40113e834638f4ca1120eb727a249fb2715e/charset_normalizer-3.4.3-cp314-cp314-macosx_10_13_universal2.whl", hash = "sha256:3cd35b7e8aedeb9e34c41385fda4f73ba609e561faedfae0a9e75e44ac558a15", size = 204342, upload-time = "2025-08-09T07:56:38.687Z" }, + { url = "https://files.pythonhosted.org/packages/ce/ec/1edc30a377f0a02689342f214455c3f6c2fbedd896a1d2f856c002fc3062/charset_normalizer-3.4.3-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b89bc04de1d83006373429975f8ef9e7932534b8cc9ca582e4db7d20d91816db", size = 145995, upload-time = "2025-08-09T07:56:40.048Z" }, + { url = "https://files.pythonhosted.org/packages/17/e5/5e67ab85e6d22b04641acb5399c8684f4d37caf7558a53859f0283a650e9/charset_normalizer-3.4.3-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:2001a39612b241dae17b4687898843f254f8748b796a2e16f1051a17078d991d", size = 158640, upload-time = "2025-08-09T07:56:41.311Z" }, + { url = "https://files.pythonhosted.org/packages/f1/e5/38421987f6c697ee3722981289d554957c4be652f963d71c5e46a262e135/charset_normalizer-3.4.3-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:8dcfc373f888e4fb39a7bc57e93e3b845e7f462dacc008d9749568b1c4ece096", size = 156636, upload-time = "2025-08-09T07:56:43.195Z" }, + { url = "https://files.pythonhosted.org/packages/a0/e4/5a075de8daa3ec0745a9a3b54467e0c2967daaaf2cec04c845f73493e9a1/charset_normalizer-3.4.3-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:18b97b8404387b96cdbd30ad660f6407799126d26a39ca65729162fd810a99aa", size = 150939, upload-time = "2025-08-09T07:56:44.819Z" }, + { url = "https://files.pythonhosted.org/packages/02/f7/3611b32318b30974131db62b4043f335861d4d9b49adc6d57c1149cc49d4/charset_normalizer-3.4.3-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:ccf600859c183d70eb47e05a44cd80a4ce77394d1ac0f79dbd2dd90a69a3a049", size = 148580, upload-time = "2025-08-09T07:56:46.684Z" }, + { url = "https://files.pythonhosted.org/packages/7e/61/19b36f4bd67f2793ab6a99b979b4e4f3d8fc754cbdffb805335df4337126/charset_normalizer-3.4.3-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:53cd68b185d98dde4ad8990e56a58dea83a4162161b1ea9272e5c9182ce415e0", size = 159870, upload-time = "2025-08-09T07:56:47.941Z" }, + { url = "https://files.pythonhosted.org/packages/06/57/84722eefdd338c04cf3030ada66889298eaedf3e7a30a624201e0cbe424a/charset_normalizer-3.4.3-cp314-cp314-musllinux_1_2_s390x.whl", hash = "sha256:30a96e1e1f865f78b030d65241c1ee850cdf422d869e9028e2fc1d5e4db73b92", size = 157797, upload-time = "2025-08-09T07:56:49.756Z" }, + { url = "https://files.pythonhosted.org/packages/72/2a/aff5dd112b2f14bcc3462c312dce5445806bfc8ab3a7328555da95330e4b/charset_normalizer-3.4.3-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:d716a916938e03231e86e43782ca7878fb602a125a91e7acb8b5112e2e96ac16", size = 152224, upload-time = "2025-08-09T07:56:51.369Z" }, + { url = "https://files.pythonhosted.org/packages/b7/8c/9839225320046ed279c6e839d51f028342eb77c91c89b8ef2549f951f3ec/charset_normalizer-3.4.3-cp314-cp314-win32.whl", hash = "sha256:c6dbd0ccdda3a2ba7c2ecd9d77b37f3b5831687d8dc1b6ca5f56a4880cc7b7ce", size = 100086, upload-time = "2025-08-09T07:56:52.722Z" }, + { url = "https://files.pythonhosted.org/packages/ee/7a/36fbcf646e41f710ce0a563c1c9a343c6edf9be80786edeb15b6f62e17db/charset_normalizer-3.4.3-cp314-cp314-win_amd64.whl", hash = "sha256:73dc19b562516fc9bcf6e5d6e596df0b4eb98d87e4f79f3ae71840e6ed21361c", size = 107400, upload-time = "2025-08-09T07:56:55.172Z" }, + { url = "https://files.pythonhosted.org/packages/c2/ca/9a0983dd5c8e9733565cf3db4df2b0a2e9a82659fd8aa2a868ac6e4a991f/charset_normalizer-3.4.3-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:70bfc5f2c318afece2f5838ea5e4c3febada0be750fcf4775641052bbba14d05", size = 207520, upload-time = "2025-08-09T07:57:11.026Z" }, + { url = "https://files.pythonhosted.org/packages/39/c6/99271dc37243a4f925b09090493fb96c9333d7992c6187f5cfe5312008d2/charset_normalizer-3.4.3-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:23b6b24d74478dc833444cbd927c338349d6ae852ba53a0d02a2de1fce45b96e", size = 147307, upload-time = "2025-08-09T07:57:12.4Z" }, + { url = "https://files.pythonhosted.org/packages/e4/69/132eab043356bba06eb333cc2cc60c6340857d0a2e4ca6dc2b51312886b3/charset_normalizer-3.4.3-cp39-cp39-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:34a7f768e3f985abdb42841e20e17b330ad3aaf4bb7e7aeeb73db2e70f077b99", size = 160448, upload-time = "2025-08-09T07:57:13.712Z" }, + { url = "https://files.pythonhosted.org/packages/04/9a/914d294daa4809c57667b77470533e65def9c0be1ef8b4c1183a99170e9d/charset_normalizer-3.4.3-cp39-cp39-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:fb731e5deb0c7ef82d698b0f4c5bb724633ee2a489401594c5c88b02e6cb15f7", size = 157758, upload-time = "2025-08-09T07:57:14.979Z" }, + { url = "https://files.pythonhosted.org/packages/b0/a8/6f5bcf1bcf63cb45625f7c5cadca026121ff8a6c8a3256d8d8cd59302663/charset_normalizer-3.4.3-cp39-cp39-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:257f26fed7d7ff59921b78244f3cd93ed2af1800ff048c33f624c87475819dd7", size = 152487, upload-time = "2025-08-09T07:57:16.332Z" }, + { url = "https://files.pythonhosted.org/packages/c4/72/d3d0e9592f4e504f9dea08b8db270821c909558c353dc3b457ed2509f2fb/charset_normalizer-3.4.3-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:1ef99f0456d3d46a50945c98de1774da86f8e992ab5c77865ea8b8195341fc19", size = 150054, upload-time = "2025-08-09T07:57:17.576Z" }, + { url = "https://files.pythonhosted.org/packages/20/30/5f64fe3981677fe63fa987b80e6c01042eb5ff653ff7cec1b7bd9268e54e/charset_normalizer-3.4.3-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:2c322db9c8c89009a990ef07c3bcc9f011a3269bc06782f916cd3d9eed7c9312", size = 161703, upload-time = "2025-08-09T07:57:20.012Z" }, + { url = "https://files.pythonhosted.org/packages/e1/ef/dd08b2cac9284fd59e70f7d97382c33a3d0a926e45b15fc21b3308324ffd/charset_normalizer-3.4.3-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:511729f456829ef86ac41ca78c63a5cb55240ed23b4b737faca0eb1abb1c41bc", size = 159096, upload-time = "2025-08-09T07:57:21.329Z" }, + { url = "https://files.pythonhosted.org/packages/45/8c/dcef87cfc2b3f002a6478f38906f9040302c68aebe21468090e39cde1445/charset_normalizer-3.4.3-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:88ab34806dea0671532d3f82d82b85e8fc23d7b2dd12fa837978dad9bb392a34", size = 153852, upload-time = "2025-08-09T07:57:22.608Z" }, + { url = "https://files.pythonhosted.org/packages/63/86/9cbd533bd37883d467fcd1bd491b3547a3532d0fbb46de2b99feeebf185e/charset_normalizer-3.4.3-cp39-cp39-win32.whl", hash = "sha256:16a8770207946ac75703458e2c743631c79c59c5890c80011d536248f8eaa432", size = 99840, upload-time = "2025-08-09T07:57:23.883Z" }, + { url = "https://files.pythonhosted.org/packages/ce/d6/7e805c8e5c46ff9729c49950acc4ee0aeb55efb8b3a56687658ad10c3216/charset_normalizer-3.4.3-cp39-cp39-win_amd64.whl", hash = "sha256:d22dbedd33326a4a5190dd4fe9e9e693ef12160c77382d9e87919bce54f3d4ca", size = 107438, upload-time = "2025-08-09T07:57:25.287Z" }, + { url = "https://files.pythonhosted.org/packages/8a/1f/f041989e93b001bc4e44bb1669ccdcf54d3f00e628229a85b08d330615c5/charset_normalizer-3.4.3-py3-none-any.whl", hash = "sha256:ce571ab16d890d23b5c278547ba694193a45011ff86a9162a71307ed9f86759a", size = 53175, upload-time = "2025-08-09T07:57:26.864Z" }, +] + +[[package]] +name = "idna" +version = "3.10" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/f1/70/7703c29685631f5a7590aa73f1f1d3fa9a380e654b86af429e0934a32f7d/idna-3.10.tar.gz", hash = "sha256:12f65c9b470abda6dc35cf8e63cc574b1c52b11df2c86030af0ac09b01b13ea9", size = 190490, upload-time = "2024-09-15T18:07:39.745Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/76/c6/c88e154df9c4e1a2a66ccf0005a88dfb2650c1dffb6f5ce603dfbd452ce3/idna-3.10-py3-none-any.whl", hash = "sha256:946d195a0d259cbba61165e88e65941f16e9b36ea6ddb97f00452bae8b1287d3", size = 70442, upload-time = "2024-09-15T18:07:37.964Z" }, +] + +[[package]] +name = "meson" +version = "1.9.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/0a/8a/8315a2711dd269533019d7fdad1cf79416aadff454c539c2da88bc6e7200/meson-1.9.0.tar.gz", hash = "sha256:cd27277649b5ed50d19875031de516e270b22e890d9db65ed9af57d18ebc498d", size = 2366082, upload-time = "2025-08-24T17:01:46.984Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/23/ed/a449e8fb5764a7f6df6e887a2d350001deca17efd6ecd5251d2fb6202009/meson-1.9.0-py3-none-any.whl", hash = "sha256:45e51ddc41e37d961582d06e78c48e0f9039011587f3495c4d6b0781dad92357", size = 1029634, upload-time = "2025-08-24T17:01:44.14Z" }, +] + +[[package]] +name = "requests" +version = "2.32.5" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "certifi" }, + { name = "charset-normalizer" }, + { name = "idna" }, + { name = "urllib3" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/c9/74/b3ff8e6c8446842c3f5c837e9c3dfcfe2018ea6ecef224c710c85ef728f4/requests-2.32.5.tar.gz", hash = "sha256:dbba0bac56e100853db0ea71b82b4dfd5fe2bf6d3754a8893c3af500cec7d7cf", size = 134517, upload-time = "2025-08-18T20:46:02.573Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/1e/db/4254e3eabe8020b458f1a747140d32277ec7a271daf1d235b70dc0b4e6e3/requests-2.32.5-py3-none-any.whl", hash = "sha256:2462f94637a34fd532264295e186976db0f5d453d1cdd31473c85a6a161affb6", size = 64738, upload-time = "2025-08-18T20:46:00.542Z" }, +] + +[[package]] +name = "rustica-engine" +version = "0.1.0" +source = { virtual = "." } +dependencies = [ + { name = "meson" }, + { name = "requests" }, +] + +[package.metadata] +requires-dist = [ + { name = "meson", specifier = ">=1.9.0" }, + { name = "requests", specifier = ">=2.32.5" }, +] + +[[package]] +name = "urllib3" +version = "2.5.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/15/22/9ee70a2574a4f4599c47dd506532914ce044817c7752a79b6a51286319bc/urllib3-2.5.0.tar.gz", hash = "sha256:3fc47733c7e419d4bc3f6b3dc2b4f890bb743906a30d56ba4a5bfa4bbff92760", size = 393185, upload-time = "2025-06-18T14:07:41.644Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/a7/c2/fe1e52489ae3122415c51f387e221dd0773709bad6c6cdaa599e8a2c5185/urllib3-2.5.0-py3-none-any.whl", hash = "sha256:e6b01673c0fa6a13e374b50871808eb3bf7046c4b125b216f6bf1cc604cff0dc", size = 129795, upload-time = "2025-06-18T14:07:40.39Z" }, +]