From 3f475f486e2b9f3043074ff9af3ee89bc201d2dc Mon Sep 17 00:00:00 2001 From: Xenia Lu Date: Fri, 10 Oct 2025 22:29:16 +0800 Subject: [PATCH 01/21] Revert "Initial PGXS layout" This reverts commit 554c44d16175081b805522b16086c333b846c1af. --- .gitignore | 3 --- Makefile | 10 ---------- rustica-wamr.control | 2 -- sql/rustica-wamr--1.0.sql | 0 src/master.c | 0 5 files changed, 15 deletions(-) delete mode 100644 .gitignore delete mode 100644 Makefile delete mode 100644 rustica-wamr.control delete mode 100644 sql/rustica-wamr--1.0.sql delete mode 100644 src/master.c diff --git a/.gitignore b/.gitignore deleted file mode 100644 index 810ac37..0000000 --- a/.gitignore +++ /dev/null @@ -1,3 +0,0 @@ -/*.so -/src/*.bc -/src/*.o diff --git a/Makefile b/Makefile deleted file mode 100644 index eb3d559..0000000 --- a/Makefile +++ /dev/null @@ -1,10 +0,0 @@ -MODULE_big = rustica-wamr -OBJS = src/master.o - -EXTENSION = rustica-wamr -DATA = sql/rustica-wamr--1.0.sql - -PG_CONFIG = pg_config -PGXS := $(shell $(PG_CONFIG) --pgxs) - -include $(PGXS) diff --git a/rustica-wamr.control b/rustica-wamr.control deleted file mode 100644 index 921c589..0000000 --- a/rustica-wamr.control +++ /dev/null @@ -1,2 +0,0 @@ -comment = 'The Rustica Database extension - WAMR runtime' -default_version = '1.0' diff --git a/sql/rustica-wamr--1.0.sql b/sql/rustica-wamr--1.0.sql deleted file mode 100644 index e69de29..0000000 diff --git a/src/master.c b/src/master.c deleted file mode 100644 index e69de29..0000000 From 7bbda01a77623f269db1605d52d9f40152531b26 Mon Sep 17 00:00:00 2001 From: Xenia Lu Date: Sun, 21 Sep 2025 11:03:16 +0800 Subject: [PATCH 02/21] feat: meson-powered Postgres backend CLI --- main.c | 79 ++++++ meson.build | 48 ++++ subprojects/.gitignore | 3 + subprojects/packagefiles/meson-0.56.patch | 301 ++++++++++++++++++++++ subprojects/postgresql.wrap | 6 + 5 files changed, 437 insertions(+) create mode 100644 main.c create mode 100644 meson.build create mode 100644 subprojects/.gitignore create mode 100644 subprojects/packagefiles/meson-0.56.patch create mode 100644 subprojects/postgresql.wrap diff --git a/main.c b/main.c new file mode 100644 index 0000000..0d6265a --- /dev/null +++ b/main.c @@ -0,0 +1,79 @@ +#include "postgres.h" +#include "getopt_long.h" +#include "utils/memutils.h" +#include "utils/pg_locale.h" + +const char *progname; + + +static void init_locale(const char *categoryname, int category, const char *locale); + +static void +help(const char *progname) +{ + printf(_("%s is a custom PostgreSQL CLI tool.\n\n"), progname); + printf(_("Usage:\n")); + printf(_(" %s [OPTION]...\n\n"), progname); + printf(_("Options:\n")); + printf(_(" -h, --help show this help, then exit\n")); + printf(_(" -V, --version output version information, then exit\n")); +} + +int +main(int argc, char *argv[]) +{ + static struct option long_options[] = { + {"help", no_argument, NULL, 'h'}, + {"version", no_argument, NULL, 'V'}, + {NULL, 0, NULL, 0} + }; + + int c; + + 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"); + + while ((c = getopt_long(argc, argv, "hV", long_options, NULL)) != -1) + { + switch (c) + { + case 'h': + help(progname); + exit(0); + case 'V': + puts("rustica_cli (PostgreSQL) " PG_VERSION); + exit(0); + default: + fprintf(stderr, _("Try \"%s --help\" for more information.\n"), progname); + exit(1); + } + } + + printf("Hello from Rustica CLI!\n"); + printf("This is a custom PostgreSQL-based CLI tool.\n"); + printf("You can add your custom logic here.\n"); + + return 0; +} + +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/meson.build b/meson.build new file mode 100644 index 0000000..f2dd798 --- /dev/null +++ b/meson.build @@ -0,0 +1,48 @@ +project( + 'rustica-engine', 'c', + version : '1.0.0', + default_options : [] +) + +pg = subproject('postgresql', default_options: ['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'), +) + +backend_objs = [postgres_pure_lib.extract_all_objects(recursive: false)] + +executable('rustica-engine', + 'main.c', + sources: pg.get_variable('post_export_backend_sources'), + objects: backend_objs, + link_args: pg.get_variable('backend_link_args'), + link_with: backend_link_with, + link_depends: pg.get_variable('backend_link_depends'), + export_dynamic: true, + implib: 'postgres', + dependencies: backend_build_deps, + kwargs: pg.get_variable('default_bin_args'), +) diff --git a/subprojects/.gitignore b/subprojects/.gitignore new file mode 100644 index 0000000..fa4c1e5 --- /dev/null +++ b/subprojects/.gitignore @@ -0,0 +1,3 @@ +/packagecache/ +.wraplock +/postgresql-*/ diff --git a/subprojects/packagefiles/meson-0.56.patch b/subprojects/packagefiles/meson-0.56.patch new file mode 100644 index 0000000..12b9cc9 --- /dev/null +++ b/subprojects/packagefiles/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/postgresql.wrap b/subprojects/postgresql.wrap new file mode 100644 index 0000000..fee4b1f --- /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 = meson-0.56.patch From a8b04e8dade5119915dd737f9db84f1147a90a62 Mon Sep 17 00:00:00 2001 From: Xenia Lu Date: Mon, 22 Sep 2025 08:51:40 +0800 Subject: [PATCH 03/21] feat: add basic WAMR with patched meson --- .gitignore | 2 + README.md | 176 +++++++++++++++++++++++++++++++++++++++++ main.c | 83 +++++++++++++++++-- meson.build | 36 ++++++++- meson.py | 39 +++++++++ pyproject.toml | 9 +++ subprojects/.gitignore | 1 + subprojects/wamr.wrap | 5 ++ uv.lock | 23 ++++++ 9 files changed, 363 insertions(+), 11 deletions(-) create mode 100644 .gitignore create mode 100644 README.md create mode 100755 meson.py create mode 100644 pyproject.toml create mode 100644 subprojects/wamr.wrap create mode 100644 uv.lock diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..e1a2dea --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +/.venv/ +/.python-version diff --git a/README.md b/README.md new file mode 100644 index 0000000..7c80add --- /dev/null +++ b/README.md @@ -0,0 +1,176 @@ +# Rustica Engine + +Rustica Engine 是一个将 WebAssembly 运行时 (WAMR) 与 PostgreSQL 后端集成的工具,允许在 PostgreSQL 环境中执行 WebAssembly 模块。 + +## 功能特性 + +- 基于 WAMR (WebAssembly Micro Runtime) 2.4.2 +- 集成 PostgreSQL 17.6 后端 +- 支持 WebAssembly GC (垃圾回收) +- 支持自定义原生函数绑定 +- 支持调试功能(调用栈转储、自定义名称段等) + +## 系统要求 + +### 依赖项 + +#### 构建工具 +- **Python** >= 3.13 +- **Meson** >= 1.9.0 +- **Ninja** (构建后端) +- **uv** (Python 包管理器) +- **CMake** (用于构建 WAMR) + +#### PostgreSQL 依赖 +- **开发库和头文件**: + - `libreadline-dev` (命令行编辑) + - `zlib1g-dev` (压缩支持) + - `libssl-dev` (SSL/TLS 支持) + - `libxml2-dev` (XML 支持,可选) + - `libxslt1-dev` (XSLT 支持,可选) + - `liblz4-dev` (LZ4 压缩,可选) + - `libzstd-dev` (Zstandard 压缩,可选) + - `libpam0g-dev` (PAM 认证,可选) + - `libldap2-dev` (LDAP 支持,可选) + - `libsystemd-dev` (systemd 集成,可选) + - `libicu-dev` (国际化支持) + - `libedit-dev` (命令行编辑,readline 的替代) + +#### UUID 支持 +- **e2fsprogs** (`uuid-dev` 或 `e2fsprogs-devel`) + - 项目配置为使用 e2fs 的 UUID 实现而非 ossp-uuid + +#### 编译器 +- GCC 或 Clang (支持 C11 标准) + +### 在 Ubuntu/Debian 上安装依赖 + +```bash +# 安装基础构建工具 +sudo apt-get update +sudo apt-get install -y build-essential cmake ninja-build + +# 安装 PostgreSQL 依赖 +sudo apt-get install -y \ + libreadline-dev \ + zlib1g-dev \ + libssl-dev \ + libicu-dev \ + libedit-dev \ + uuid-dev + +# 安装可选的 PostgreSQL 依赖 +sudo apt-get install -y \ + libxml2-dev \ + libxslt1-dev \ + liblz4-dev \ + libzstd-dev \ + libpam0g-dev \ + libldap2-dev \ + libsystemd-dev + +# 安装 Python 和 uv +curl -LsSf https://astral.sh/uv/install.sh | sh +``` + +### 在 Arch Linux 上安装依赖 + +```bash +# 安装基础构建工具 +sudo pacman -S base-devel cmake ninja + +# 安装 PostgreSQL 依赖 +sudo pacman -S \ + readline \ + zlib \ + openssl \ + icu \ + libedit \ + e2fsprogs + +# 安装可选的 PostgreSQL 依赖 +sudo pacman -S \ + libxml2 \ + libxslt \ + lz4 \ + zstd \ + pam \ + libldap \ + systemd-libs + +# 安装 Python 和 uv +curl -LsSf https://astral.sh/uv/install.sh | sh +``` + +## 构建 + +1. 克隆仓库: +```bash +git clone https://github.com/yourusername/rustica-engine.git +cd rustica-engine +``` + +2. 使用 uv 设置 Python 环境: +```bash +uv sync +``` + +3. 配置构建: +```bash +uv run meson.py setup build +``` + +4. 编译 rustica-engine: +```bash +ninja -C build rustica-engine +``` + +## 使用方法 + +运行 WebAssembly 文件: +```bash +./build/rustica-engine +``` + +查看帮助信息: +```bash +./build/rustica-engine --help +``` + +查看版本信息: +```bash +./build/rustica-engine --version +``` + +## 示例 + +```bash +# 运行一个 WebAssembly 模块 +./build/rustica-engine example.wasm + +# 查看版本 +./build/rustica-engine -V +# 输出: rustica-engine (PostgreSQL 17.6, WAMR 2.4.2) +``` + +## 项目结构 + +- `main.c` - 主程序入口,包含 WAMR 运行时初始化和 WebAssembly 模块加载逻辑 +- `meson.build` - Meson 构建配置文件 +- `meson.py` - 扩展 Meson 功能,如获取 cmake 的变量 +- `pyproject.toml` - Python 项目配置 +- `subprojects/` - 子项目依赖(PostgreSQL 和 WAMR) + +## 技术细节 + +### WebAssembly 支持 +- 使用 WAMR 2.4.2 作为 WebAssembly 运行时 +- 启用了 GC(垃圾回收)支持 +- 支持扩展常量表达式 +- 支持自定义段加载 +- 支持调用栈转储用于调试 + +### PostgreSQL 集成 +- 基于 PostgreSQL 17.6 +- 使用 PostgreSQL 的内存管理和错误处理机制 +- 支持 PostgreSQL 的本地化功能 diff --git a/main.c b/main.c index 0d6265a..7eb91e3 100644 --- a/main.c +++ b/main.c @@ -1,7 +1,12 @@ +#include + #include "postgres.h" #include "getopt_long.h" #include "utils/memutils.h" #include "utils/pg_locale.h" +#include "bh_platform.h" +#include "bh_read_file.h" +#include "wasm_export.h" const char *progname; @@ -9,16 +14,25 @@ const char *progname; static void init_locale(const char *categoryname, int category, const char *locale); static void -help(const char *progname) +help() { - printf(_("%s is a custom PostgreSQL CLI tool.\n\n"), progname); + printf(_("%s is a WebAssembly runtime with PostgreSQL backend.\n\n"), progname); printf(_("Usage:\n")); - printf(_(" %s [OPTION]...\n\n"), progname); + printf(_(" %s [OPTION]... \n\n"), progname); printf(_("Options:\n")); printf(_(" -h, --help show this help, then exit\n")); printf(_(" -V, --version output version information, then exit\n")); } +static void +print_char(wasm_exec_env_t exec_env, int ch) { + wprintf(L"%lc", ch); +} + +static NativeSymbol native_symbols[] = { + { "print_char", print_char, "(i)", NULL }, +}; + int main(int argc, char *argv[]) { @@ -29,6 +43,9 @@ main(int argc, char *argv[]) }; int c; + char error_buf[128]; + uint32 size; + uint8_t *buffer; progname = get_progname(argv[0]); @@ -46,15 +63,16 @@ main(int argc, char *argv[]) unsetenv("LC_ALL"); + // 先处理命令行选项 while ((c = getopt_long(argc, argv, "hV", long_options, NULL)) != -1) { switch (c) { case 'h': - help(progname); + help(); exit(0); case 'V': - puts("rustica_cli (PostgreSQL) " PG_VERSION); + printf("%s (PostgreSQL %s)\n", progname, PG_VERSION); exit(0); default: fprintf(stderr, _("Try \"%s --help\" for more information.\n"), progname); @@ -62,9 +80,58 @@ main(int argc, char *argv[]) } } - printf("Hello from Rustica CLI!\n"); - printf("This is a custom PostgreSQL-based CLI tool.\n"); - printf("You can add your custom logic here.\n"); + // 检查是否提供了wasm文件路径 + if (optind >= argc) { + fprintf(stderr, "Error: No wasm file specified\n"); + fprintf(stderr, "Usage: %s [OPTION]... \n", progname); + fprintf(stderr, "Try '%s --help' for more information.\n", progname); + return 1; + } + + // 初始化WASM运行时并加载文件 + wasm_runtime_init(); + buffer = (uint8_t *)bh_read_file_to_buffer(argv[optind], &size); + if (!buffer) { + fprintf(stderr, "Error: Failed to read file: %s\n", argv[optind]); + return 1; + } + + wasm_runtime_register_natives("spectest", native_symbols, 1); + wasm_module_t module = wasm_runtime_load(buffer, size, error_buf, sizeof(error_buf)); + if (!module) { + fprintf(stderr, "Error loading wasm module: %s\n", error_buf); + return 1; + } + + wasm_module_inst_t module_inst = wasm_runtime_instantiate(module, 32768, 32768, + error_buf, sizeof(error_buf)); + if (!module_inst) { + fprintf(stderr, "Error instantiating wasm module: %s\n", error_buf); + return 1; + } + + wasm_exec_env_t exec_env = wasm_runtime_create_exec_env(module_inst, 32768); + if (!exec_env) { + fprintf(stderr, "Error creating execution environment\n"); + return 1; + } + + wasm_function_inst_t start_func = wasm_runtime_lookup_function(module_inst, "_start"); + if (!start_func) { + fprintf(stderr, "Error: _start function not found\n"); + return 1; + } + + wasm_runtime_call_wasm(exec_env, start_func, 0, NULL); + const char *exc = wasm_runtime_get_exception(module_inst); + if (exc) + printf("Exception: %s\n", exc); + + // 清理资源 + wasm_runtime_destroy_exec_env(exec_env); + wasm_runtime_deinstantiate(module_inst); + wasm_runtime_unload(module); + wasm_runtime_destroy(); return 0; } diff --git a/meson.build b/meson.build index f2dd798..8694a37 100644 --- a/meson.build +++ b/meson.build @@ -4,6 +4,8 @@ project( default_options : [] ) +# Include PostgreSQL subproject + pg = subproject('postgresql', default_options: ['uuid=e2fs']) add_project_arguments(pg.get_variable('cflags'), language: ['c']) @@ -32,17 +34,45 @@ postgres_pure_lib = static_library('postgres_lib', kwargs: pg.get_variable('internal_lib_args'), ) -backend_objs = [postgres_pure_lib.extract_all_objects(recursive: false)] +# Include WAMR subproject + +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_LOAD_CUSTOM_SECTION': 1, + 'WAMR_BUILD_CUSTOM_NAME_SECTION': 1, + 'WAMR_BUILD_FAST_INTERP': 0, + 'WAMR_BUILD_EXTENDED_CONST_EXPR': 1, + + # https://github.com/bytecodealliance/wasm-micro-runtime/issues/4640 + 'CMAKE_C_FLAGS': '-fzero-init-padding-bits=unions', +}) +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], +) + +# Build the rustica-engine executable executable('rustica-engine', 'main.c', sources: pg.get_variable('post_export_backend_sources'), - objects: backend_objs, + objects: [ + postgres_pure_lib.extract_all_objects(recursive: false), + uncommon_shared_lib.extract_all_objects(recursive: false), + ], link_args: pg.get_variable('backend_link_args'), link_with: backend_link_with, link_depends: pg.get_variable('backend_link_depends'), export_dynamic: true, implib: 'postgres', - dependencies: backend_build_deps, + dependencies: backend_build_deps + [vmlib], kwargs: pg.get_variable('default_bin_args'), ) diff --git a/meson.py b/meson.py new file mode 100755 index 0000000..fadf4b1 --- /dev/null +++ b/meson.py @@ -0,0 +1,39 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +from __future__ import annotations +import re +import sys +import typing as T + +from mesonbuild.interpreterbase import noKwargs, typed_pos_args +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 TYPE_kwargs, TYPE_var, InterpreterObject + + +class CMakeSubproject(cmake.CMakeSubproject): + def __init__(self, subp: SubprojectHolder): + super().__init__(subp) + self.methods["get_cmake_variable"] = self.get_cmake_variable + + @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] + + +if __name__ == "__main__": + cmake.CMakeSubproject = CMakeSubproject + sys.argv[0] = re.sub(r"(-script\.pyw|\.exe)?$", "", sys.argv[0]) + sys.exit(main()) diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 0000000..cf110de --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,9 @@ +[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", +] diff --git a/subprojects/.gitignore b/subprojects/.gitignore index fa4c1e5..f8e6c44 100644 --- a/subprojects/.gitignore +++ b/subprojects/.gitignore @@ -1,3 +1,4 @@ /packagecache/ .wraplock /postgresql-*/ +/wasm-micro-runtime-WAMR-*/ diff --git a/subprojects/wamr.wrap b/subprojects/wamr.wrap new file mode 100644 index 0000000..961a825 --- /dev/null +++ b/subprojects/wamr.wrap @@ -0,0 +1,5 @@ +[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 --git a/uv.lock b/uv.lock new file mode 100644 index 0000000..255ae3c --- /dev/null +++ b/uv.lock @@ -0,0 +1,23 @@ +version = 1 +revision = 3 +requires-python = ">=3.9" + +[[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 = "rustica-engine" +version = "0.1.0" +source = { virtual = "." } +dependencies = [ + { name = "meson" }, +] + +[package.metadata] +requires-dist = [{ name = "meson", specifier = ">=1.9.0" }] From b3ae1b3f4eef6700b6cb3956408521b504624f83 Mon Sep 17 00:00:00 2001 From: Xenia Lu Date: Sun, 28 Sep 2025 09:24:58 +0800 Subject: [PATCH 04/21] feat: support moon test with core lib This uses the WAMR classic interpreter. --- .clang-format | 31 ++ main.c | 146 ------ meson.build | 10 +- src/rustica/env.c | 227 +++++++++ src/rustica/env.h | 53 +++ src/rustica/main.c | 227 +++++++++ src/rustica/moontest.c | 442 ++++++++++++++++++ src/rustica/moontest.h | 13 + .../{ => postgresql}/meson-0.56.patch | 0 subprojects/packagefiles/wamr/0001.patch | 80 ++++ subprojects/packagefiles/wamr/0002.patch | 125 +++++ subprojects/packagefiles/wamr/0003.patch | 32 ++ subprojects/postgresql.wrap | 2 +- subprojects/wamr.wrap | 1 + 14 files changed, 1240 insertions(+), 149 deletions(-) create mode 100644 .clang-format delete mode 100644 main.c create mode 100644 src/rustica/env.c create mode 100644 src/rustica/env.h create mode 100644 src/rustica/main.c create mode 100644 src/rustica/moontest.c create mode 100644 src/rustica/moontest.h rename subprojects/packagefiles/{ => postgresql}/meson-0.56.patch (100%) create mode 100644 subprojects/packagefiles/wamr/0001.patch create mode 100644 subprojects/packagefiles/wamr/0002.patch create mode 100644 subprojects/packagefiles/wamr/0003.patch diff --git a/.clang-format b/.clang-format new file mode 100644 index 0000000..f4b3f5f --- /dev/null +++ b/.clang-format @@ -0,0 +1,31 @@ +BasedOnStyle: Mozilla +IndentWidth: 4 +ContinuationIndentWidth: 4 +TabWidth: 4 +UseTab: Never +ColumnLimit: 80 +AlignAfterOpenBracket: Align +BreakBeforeBraces: Custom +BraceWrapping: + AfterCaseLabel: true + AfterClass: true + AfterControlStatement: false + AfterEnum: false + AfterNamespace: false + AfterObjCDeclaration: false + AfterStruct: false + AfterUnion: false + AfterExternBlock: false + BeforeCatch: false + BeforeElse: true + IndentBraces: false + SplitEmptyFunction: true + SplitEmptyRecord: false + SplitEmptyNamespace: true +BreakBeforeBinaryOperators: NonAssignment +AlignEscapedNewlines: Left +AllowAllParametersOfDeclarationOnNextLine: false +AllowAllArgumentsOnNextLine: false +PointerAlignment: Right +SpaceAroundPointerQualifiers: After +SortIncludes: false diff --git a/main.c b/main.c deleted file mode 100644 index 7eb91e3..0000000 --- a/main.c +++ /dev/null @@ -1,146 +0,0 @@ -#include - -#include "postgres.h" -#include "getopt_long.h" -#include "utils/memutils.h" -#include "utils/pg_locale.h" -#include "bh_platform.h" -#include "bh_read_file.h" -#include "wasm_export.h" - -const char *progname; - - -static void init_locale(const char *categoryname, int category, const char *locale); - -static void -help() -{ - printf(_("%s is a WebAssembly runtime with PostgreSQL backend.\n\n"), progname); - printf(_("Usage:\n")); - printf(_(" %s [OPTION]... \n\n"), progname); - printf(_("Options:\n")); - printf(_(" -h, --help show this help, then exit\n")); - printf(_(" -V, --version output version information, then exit\n")); -} - -static void -print_char(wasm_exec_env_t exec_env, int ch) { - wprintf(L"%lc", ch); -} - -static NativeSymbol native_symbols[] = { - { "print_char", print_char, "(i)", NULL }, -}; - -int -main(int argc, char *argv[]) -{ - static struct option long_options[] = { - {"help", no_argument, NULL, 'h'}, - {"version", no_argument, NULL, 'V'}, - {NULL, 0, NULL, 0} - }; - - int c; - char error_buf[128]; - uint32 size; - uint8_t *buffer; - - 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"); - - // 先处理命令行选项 - while ((c = getopt_long(argc, argv, "hV", long_options, NULL)) != -1) - { - switch (c) - { - case 'h': - help(); - exit(0); - case 'V': - printf("%s (PostgreSQL %s)\n", progname, PG_VERSION); - exit(0); - default: - fprintf(stderr, _("Try \"%s --help\" for more information.\n"), progname); - exit(1); - } - } - - // 检查是否提供了wasm文件路径 - if (optind >= argc) { - fprintf(stderr, "Error: No wasm file specified\n"); - fprintf(stderr, "Usage: %s [OPTION]... \n", progname); - fprintf(stderr, "Try '%s --help' for more information.\n", progname); - return 1; - } - - // 初始化WASM运行时并加载文件 - wasm_runtime_init(); - buffer = (uint8_t *)bh_read_file_to_buffer(argv[optind], &size); - if (!buffer) { - fprintf(stderr, "Error: Failed to read file: %s\n", argv[optind]); - return 1; - } - - wasm_runtime_register_natives("spectest", native_symbols, 1); - wasm_module_t module = wasm_runtime_load(buffer, size, error_buf, sizeof(error_buf)); - if (!module) { - fprintf(stderr, "Error loading wasm module: %s\n", error_buf); - return 1; - } - - wasm_module_inst_t module_inst = wasm_runtime_instantiate(module, 32768, 32768, - error_buf, sizeof(error_buf)); - if (!module_inst) { - fprintf(stderr, "Error instantiating wasm module: %s\n", error_buf); - return 1; - } - - wasm_exec_env_t exec_env = wasm_runtime_create_exec_env(module_inst, 32768); - if (!exec_env) { - fprintf(stderr, "Error creating execution environment\n"); - return 1; - } - - wasm_function_inst_t start_func = wasm_runtime_lookup_function(module_inst, "_start"); - if (!start_func) { - fprintf(stderr, "Error: _start function not found\n"); - return 1; - } - - wasm_runtime_call_wasm(exec_env, start_func, 0, NULL); - const char *exc = wasm_runtime_get_exception(module_inst); - if (exc) - printf("Exception: %s\n", exc); - - // 清理资源 - wasm_runtime_destroy_exec_env(exec_env); - wasm_runtime_deinstantiate(module_inst); - wasm_runtime_unload(module); - wasm_runtime_destroy(); - - return 0; -} - -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/meson.build b/meson.build index 8694a37..d5187a9 100644 --- a/meson.build +++ b/meson.build @@ -47,9 +47,10 @@ wamr_var.add_cmake_defines({ 'WAMR_BUILD_CUSTOM_NAME_SECTION': 1, 'WAMR_BUILD_FAST_INTERP': 0, 'WAMR_BUILD_EXTENDED_CONST_EXPR': 1, + 'WAMR_BUILD_EXCE_HANDLING': 1, # https://github.com/bytecodealliance/wasm-micro-runtime/issues/4640 - 'CMAKE_C_FLAGS': '-fzero-init-padding-bits=unions', + 'CMAKE_C_FLAGS': '-fzero-init-padding-bits=unions -Wno-incompatible-pointer-types', }) wamr = cmake.subproject('wamr', options: wamr_var) vmlib = wamr.dependency('vmlib') @@ -62,12 +63,17 @@ uncommon_shared_lib = shared_library('uncommon_shared', # Build the rustica-engine executable executable('rustica-engine', - 'main.c', + [ + 'src/rustica/main.c', + 'src/rustica/env.c', + 'src/rustica/moontest.c', + ], sources: pg.get_variable('post_export_backend_sources'), objects: [ postgres_pure_lib.extract_all_objects(recursive: false), uncommon_shared_lib.extract_all_objects(recursive: false), ], + include_directories: 'src', link_args: pg.get_variable('backend_link_args'), link_with: backend_link_with, link_depends: pg.get_variable('backend_link_depends'), diff --git a/src/rustica/env.c b/src/rustica/env.c new file mode 100644 index 0000000..2338922 --- /dev/null +++ b/src/rustica/env.c @@ -0,0 +1,227 @@ +#include +#include +#include + +#include "postgres.h" +#include "mb/pg_wchar.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); + if (val->owns_ptr) + pfree(val->ptr); + pfree(val); +} + +rustica_value_t +rustica_value_new(const uint8_t type, void *ptr, const size_t size) { + const rustica_value_t rv = + palloc(sizeof(RusticaValue) + + (size > sizeof(void *) ? size - sizeof(void *) : 0)); + rv->type = type; + rv->owns_ptr = false; + if (size == 0) { + rv->ptr = ptr; + rv->data_builtin = false; + } + else { + rv->data_builtin = true; + if (ptr == NULL) + memset(rv->data, 0, size); + else + 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, "exception thrown by stdc++"); +} + +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; + if (val->data_builtin) { + buf->size = strlen(val->data); + buf->data = val->data; + } + else { + buf->size = strlen(val->ptr); + buf->data = val->ptr; + } + 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; + if (val->data_builtin) + reader->arr = val->arr; + else + reader->arr = val->ptr; + 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 NativeSymbol time_symbols[] = { + { "now", time_now, "()I", NULL }, +}; + +void +rustica_register_natives() { + wasm_runtime_register_natives("spectest", + spectest_symbols, + sizeof(spectest_symbols) + / sizeof(NativeSymbol)); + wasm_runtime_register_natives("exception", + exception_symbols, + sizeof(exception_symbols) + / sizeof(NativeSymbol)); + wasm_runtime_register_natives("__moonbit_fs_unstable", + fs_symbols, + sizeof(fs_symbols) / sizeof(NativeSymbol)); + wasm_runtime_register_natives("__moonbit_time_unstable", + time_symbols, + sizeof(time_symbols) / sizeof(NativeSymbol)); +} diff --git a/src/rustica/env.h b/src/rustica/env.h new file mode 100644 index 0000000..2db54a6 --- /dev/null +++ b/src/rustica/env.h @@ -0,0 +1,53 @@ +#ifndef RUSTICA_ENV_H +#define RUSTICA_ENV_H + +#include "gc_export.h" + +#define RUSTICA_ENV_CSTRING 0x01 +#define RUSTICA_ENV_CSTRING_ARRAY 0x01 + +extern char **saved_argv; +extern int saved_argc; + +typedef struct RusticaPointerArray { + size_t size; + void *items[]; +} RusticaPointerArray; + +typedef struct RusticaValue { + uint8_t type; + bool data_builtin; + bool owns_ptr; + union { + void *ptr; + char data[]; + RusticaPointerArray arr[]; + }; +} 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/main.c b/src/rustica/main.c new file mode 100644 index 0000000..94f34ca --- /dev/null +++ b/src/rustica/main.c @@ -0,0 +1,227 @@ +#include "postgres.h" +#include "getopt_long.h" +#include "utils/memutils.h" +#include "utils/pg_locale.h" + +#include "bh_platform.h" +#include "bh_read_file.h" +#include "gc_export.h" + +#include "rustica/env.h" +#include "rustica/moontest.h" + +#define HEAP_M 512 +#define STACK_K 512 + +const char *progname; + +static void +init_locale(const char *categoryname, int category, const char *locale); + +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(_(" -h, --help show this help, then exit\n")); + printf(_(" -V, --version output version information, then exit\n")); +} + +int +main(int argc, char *argv[]) { + static struct option long_options[] = { + { "help", no_argument, NULL, 'h' }, + { "version", no_argument, NULL, 'V' }, + { NULL, 0, NULL, 0 } + }; + + int c; + int subcmd_index = 1; + char error_buf[128]; + uint32 size; + uint8_t *buffer; + const char *moontest_spec = NULL; + const char *wasm_file = NULL; + const char *dot = NULL; + 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_Interp, + }; + wasm_module_t module = NULL; + wasm_module_inst_t module_inst = NULL; + wasm_exec_env_t exec_env = NULL; + const char *exc = NULL; + + 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"); + + /* If no args, show help */ + if (argc < 2) { + help(); + exit(0); + } + + /* If the first non-program argument begins with '-', parse global options + (e.g. prog -h or prog --version). Otherwise treat argv[1] as subcommand. */ + if (argv[1][0] == '-') { + optind = 1; + while ((c = getopt_long(argc, argv, "hV", long_options, NULL)) != -1) { + switch (c) { + case 'h': + help(); + exit(0); + case 'V': + printf("%s (PostgreSQL %s)\n", progname, PG_VERSION); + exit(0); + default: + fprintf(stderr, + _("Try \"%s --help\" for more information.\n"), + progname); + exit(1); + } + } + if (optind >= argc) { + help(); + exit(0); + } + subcmd_index = optind; + } + + /* Support minimal subcommands: + - 'run ' (no options) + - 'moontest --spec ' (parse options starting after + subcommand) + */ + if (strcmp(argv[subcmd_index], "run") == 0) { + if (subcmd_index + 1 >= argc) { + fprintf(stderr, "Error: No wasm file specified for 'run'\n"); + return 1; + } + wasm_file = argv[subcmd_index + 1]; + } + else if (strcmp(argv[subcmd_index], "moontest") == 0) { + optind = subcmd_index + 1; /* start parsing after subcommand */ + if (moontest_parse_args(argc, argv, &moontest_spec, &wasm_file) != 0) { + return 1; + } + if (moontest_spec == NULL) { + // Help was already printed by moontest_parse_args + return 0; + } + Assert(wasm_file != NULL); + } + else { + /* Unknown subcommand -> show help */ + fprintf(stderr, "Unsupported command '%s'\n", argv[subcmd_index]); + help(); + return 1; + } + + // 检查文件扩展名是否为 .wasm + dot = strrchr(wasm_file, '.'); + if (!dot || strcmp(dot, ".wasm") != 0) { + fprintf(stderr, "Unsupported file type\n"); + return 1; + } + + // 初始化WASM运行时并加载文件 + if (!wasm_runtime_full_init(&init_args)) { + fprintf(stderr, "Error: Failed to initialize WASM runtime\n"); + return 1; + } + buffer = (uint8_t *)bh_read_file_to_buffer(wasm_file, &size); + if (!buffer) { + fprintf(stderr, "Error: Failed to read file: %s\n", argv[optind]); + return 1; + } + + rustica_register_natives(); + + module = wasm_runtime_load(buffer, size, error_buf, sizeof(error_buf)); + if (!module) { + fprintf(stderr, "Error loading wasm module: %s\n", error_buf); + return 1; + } + + module_inst = wasm_runtime_instantiate(module, + STACK_K * 1024, + (uint32_t)HEAP_M * 1024 * 1024, + error_buf, + sizeof(error_buf)); + if (!module_inst) { + fprintf(stderr, "Error instantiating wasm module: %s\n", error_buf); + return 1; + } + + exec_env = wasm_runtime_create_exec_env(module_inst, STACK_K * 1024); + if (!exec_env) { + fprintf(stderr, "Error creating execution environment\n"); + return 1; + } + + PG_TRY(); + { + if (moontest_spec) { + moontest_run(exec_env, moontest_spec); + } + else { + wasm_function_inst_t start_func = + wasm_runtime_lookup_function(module_inst, "_start"); + if (start_func) + wasm_runtime_call_wasm(exec_env, start_func, 0, NULL); + } + } + PG_CATCH(); + { + ErrorData *edata = CopyErrorData(); + fprintf(stderr, "Error: %s\n", edata->message); + FlushErrorState(); + FreeErrorData(edata); + } + PG_END_TRY(); + + exc = wasm_runtime_get_exception(module_inst); + if (exc) { + printf("Exception: %s\n", exc); + wasm_runtime_dump_call_stack(exec_env); + } + + wasm_runtime_destroy_exec_env(exec_env); + wasm_runtime_deinstantiate(module_inst); + wasm_runtime_unload(module); + wasm_runtime_destroy(); + + return 0; +} + +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/moontest.c b/src/rustica/moontest.c new file mode 100644 index 0000000..eced36b --- /dev/null +++ b/src/rustica/moontest.c @@ -0,0 +1,442 @@ +#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 } }; + +int +moontest_parse_args(int argc, + char *argv[], + const char **moontest_spec, + const char **wasm_file) { + int c; + while ((c = getopt_long(argc, argv, "s:h", moontest_options, NULL)) != -1) { + switch (c) { + case 's': + *moontest_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")); + return 0; + default: + fprintf(stderr, "Unknown option for 'moontest'\n"); + return 1; + } + } + if (optind < argc) + *wasm_file = argv[optind]; + if (!*moontest_spec) { + fprintf(stderr, "Error: --spec is required for 'moontest'\n"); + return 1; + } + if (!*wasm_file) { + fprintf(stderr, "Error: No wasm file specified for 'moontest'\n"); + return 1; + } + return 0; +} + +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..2378102 --- /dev/null +++ b/src/rustica/moontest.h @@ -0,0 +1,13 @@ +#ifndef RUSTICA_MOONTEST_H +#define RUSTICA_MOONTEST_H + +int +moontest_parse_args(int argc, + char *argv[], + const char **moontest_spec, + const char **wasm_file); + +void +moontest_run(wasm_exec_env_t exec_env, const char *moontest_spec); + +#endif /* RUSTICA_MOONTEST_H */ diff --git a/subprojects/packagefiles/meson-0.56.patch b/subprojects/packagefiles/postgresql/meson-0.56.patch similarity index 100% rename from subprojects/packagefiles/meson-0.56.patch rename to subprojects/packagefiles/postgresql/meson-0.56.patch diff --git a/subprojects/packagefiles/wamr/0001.patch b/subprojects/packagefiles/wamr/0001.patch new file mode 100644 index 0000000..9c683a8 --- /dev/null +++ b/subprojects/packagefiles/wamr/0001.patch @@ -0,0 +1,80 @@ +commit 8ff0666fc2cf81d4561ec277e75a0971260bea88 +Author: Xenia Lu +Date: Sun Sep 28 15:49:50 2025 +0800 + + Fix false OOB in array.fill + +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/tests/regression/ba-issues/issues/issue-4644/test.wasm b/tests/regression/ba-issues/issues/issue-4644/test.wasm +new file mode 100644 +index 00000000..21e0386d +Binary files /dev/null and b/tests/regression/ba-issues/issues/issue-4644/test.wasm differ +diff --git a/tests/regression/ba-issues/issues/issue-4644/test.wat b/tests/regression/ba-issues/issues/issue-4644/test.wat +new file mode 100644 +index 00000000..738d427c +--- /dev/null ++++ b/tests/regression/ba-issues/issues/issue-4644/test.wat +@@ -0,0 +1,24 @@ ++;; define array type - i32 array ++(type $i32_array (array (mut i32))) ++ ++;; main function ++(func $main ++ (local $arr (ref $i32_array)) ++ ++ ;; create an i32 array of size 10 with initial value 0 ++ (array.new $i32_array ++ (i32.const 0) ;; initial value ++ (i32.const 10)) ;; array size ++ (local.set $arr) ++ ++ ;; fill array using array.fill ++ (array.fill $i32_array ++ (local.get $arr) ;; array reference ++ (i32.const 0) ;; start index ++ (i32.const 42) ;; fill value ++ (i32.const 10)) ;; fill length - fill entire array ++) ++ ++(memory 1) ++(export "memory" (memory 0)) ++(export "_start" (func $main)) +diff --git a/tests/regression/ba-issues/running_config.json b/tests/regression/ba-issues/running_config.json +index 9288eb97..df8e32d2 100644 +--- a/tests/regression/ba-issues/running_config.json ++++ b/tests/regression/ba-issues/running_config.json +@@ -1754,6 +1754,22 @@ + "stdout content": "", + "description": "no sanitizer 'heap-buffer-overflow'" + } ++ }, ++ { ++ "deprecated": false, ++ "ids": [ ++ 4644 ++ ], ++ "runtime": "iwasm-default-gc-enabled", ++ "file": "test.wasm", ++ "mode": "classic-interp", ++ "options": "-f _start", ++ "argument": "", ++ "expected return": { ++ "ret code": 0, ++ "stdout content": "", ++ "description": "no out of bound exception" ++ } + } + ] + } diff --git a/subprojects/packagefiles/wamr/0002.patch b/subprojects/packagefiles/wamr/0002.patch new file mode 100644 index 0000000..ad32962 --- /dev/null +++ b/subprojects/packagefiles/wamr/0002.patch @@ -0,0 +1,125 @@ +commit f7ed6e1ef2ffabee0d3edd252ab47aff78b69b74 +Author: Xenia Lu +Date: Sun Sep 28 15:51:27 2025 +0800 + + loader: fix block/loop ref params type checking + +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]); +diff --git a/tests/regression/ba-issues/issues/issue-4646/test.wasm b/tests/regression/ba-issues/issues/issue-4646/test.wasm +new file mode 100644 +index 00000000..e163405e +Binary files /dev/null and b/tests/regression/ba-issues/issues/issue-4646/test.wasm differ +diff --git a/tests/regression/ba-issues/issues/issue-4646/test.wat b/tests/regression/ba-issues/issues/issue-4646/test.wat +new file mode 100644 +index 00000000..3fd503c5 +--- /dev/null ++++ b/tests/regression/ba-issues/issues/issue-4646/test.wat +@@ -0,0 +1,31 @@ ++;; define different reference types ++(type $struct_a (struct (field (mut i32)))) ++(type $struct_b (struct (field (mut i64)))) ++(type $struct_c (struct (field (mut i32)) (field (mut i32)))) ++ ++(func $main ++ ;; prepare parameters: i32, ref_a, i32, ref_b ++ (i32.const 10) ++ (struct.new $struct_a (i32.const 100)) ++ (i32.const 20) ++ (struct.new $struct_b (i64.const 200)) ++ ++ ;; block with interleaved parameters: i32, ref_a, i32, ref_b -> ref_c ++ (block (param i32 (ref $struct_a) i32 (ref $struct_b)) (result (ref $struct_c)) ++ ;; clean up parameters from stack ++ drop ;; drop ref_b ++ drop ;; drop i32 ++ drop ;; drop ref_a ++ drop ;; drop i32 ++ ++ ;; return new type reference struct_c ++ (struct.new $struct_c (i32.const 300) (i32.const 400)) ++ ) ++ ++ ;; drop return value ++ drop ++) ++ ++(memory 1) ++(export "memory" (memory 0)) ++(export "_start" (func $main)) +\ No newline at end of file +diff --git a/tests/regression/ba-issues/running_config.json b/tests/regression/ba-issues/running_config.json +index df8e32d2..9fe78c0e 100644 +--- a/tests/regression/ba-issues/running_config.json ++++ b/tests/regression/ba-issues/running_config.json +@@ -1770,6 +1770,22 @@ + "stdout content": "", + "description": "no out of bound exception" + } ++ }, ++ { ++ "deprecated": false, ++ "ids": [ ++ 4646 ++ ], ++ "runtime": "iwasm-default-gc-enabled", ++ "file": "test.wasm", ++ "mode": "classic-interp", ++ "options": "-f _start", ++ "argument": "", ++ "expected return": { ++ "ret code": 0, ++ "stdout content": "", ++ "description": "load successfully" ++ } + } + ] + } diff --git a/subprojects/packagefiles/wamr/0003.patch b/subprojects/packagefiles/wamr/0003.patch new file mode 100644 index 0000000..8b78402 --- /dev/null +++ b/subprojects/packagefiles/wamr/0003.patch @@ -0,0 +1,32 @@ +commit df7ab8d44e03dd74aee14a0a8b48dfbdcce22a9a +Author: Xenia Lu +Date: Sun Sep 28 15:52:17 2025 +0800 + + Don't print stack by default + +diff --git a/core/iwasm/interpreter/wasm_interp_classic.c b/core/iwasm/interpreter/wasm_interp_classic.c +index d0ac01bd..92bee750 100644 +--- a/core/iwasm/interpreter/wasm_interp_classic.c ++++ b/core/iwasm/interpreter/wasm_interp_classic.c +@@ -7547,7 +7547,7 @@ wasm_interp_call_wasm(WASMModuleInstance *module_inst, WASMExecEnv *exec_env, + else { + #if WASM_ENABLE_DUMP_CALL_STACK != 0 + if (wasm_interp_create_call_stack(exec_env)) { +- wasm_interp_dump_call_stack(exec_env, true, NULL, 0); ++ wasm_interp_dump_call_stack(exec_env, false, NULL, 0); + } + #endif + } +diff --git a/core/iwasm/interpreter/wasm_interp_fast.c b/core/iwasm/interpreter/wasm_interp_fast.c +index 36d4538f..7b17dfa7 100644 +--- a/core/iwasm/interpreter/wasm_interp_fast.c ++++ b/core/iwasm/interpreter/wasm_interp_fast.c +@@ -7982,7 +7982,7 @@ wasm_interp_call_wasm(WASMModuleInstance *module_inst, WASMExecEnv *exec_env, + else { + #if WASM_ENABLE_DUMP_CALL_STACK != 0 + if (wasm_interp_create_call_stack(exec_env)) { +- wasm_interp_dump_call_stack(exec_env, true, NULL, 0); ++ wasm_interp_dump_call_stack(exec_env, false, NULL, 0); + } + #endif + } diff --git a/subprojects/postgresql.wrap b/subprojects/postgresql.wrap index fee4b1f..002a949 100644 --- a/subprojects/postgresql.wrap +++ b/subprojects/postgresql.wrap @@ -3,4 +3,4 @@ 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 = meson-0.56.patch +diff_files = postgresql/meson-0.56.patch diff --git a/subprojects/wamr.wrap b/subprojects/wamr.wrap index 961a825..6ca08a9 100644 --- a/subprojects/wamr.wrap +++ b/subprojects/wamr.wrap @@ -3,3 +3,4 @@ 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/0003.patch From e265eb913b1f944d4ed5aa20e701275338918082 Mon Sep 17 00:00:00 2001 From: Xenia Lu Date: Mon, 29 Sep 2025 17:41:21 +0800 Subject: [PATCH 05/21] feat: add monotonic clock API for testing --- src/rustica/env.c | 21 +++++++++++++++++++++ src/rustica/env.h | 5 ++++- 2 files changed, 25 insertions(+), 1 deletion(-) diff --git a/src/rustica/env.c b/src/rustica/env.c index 2338922..81dabfb 100644 --- a/src/rustica/env.c +++ b/src/rustica/env.c @@ -4,6 +4,7 @@ #include "postgres.h" #include "mb/pg_wchar.h" +#include "portability/instr_time.h" #include "rustica/env.h" @@ -204,8 +205,28 @@ time_now(wasm_exec_env_t exec_env) { 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 diff --git a/src/rustica/env.h b/src/rustica/env.h index 2db54a6..71ed36b 100644 --- a/src/rustica/env.h +++ b/src/rustica/env.h @@ -1,10 +1,12 @@ #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 0x01 +#define RUSTICA_ENV_CSTRING_ARRAY 0x02 +#define RUSTICA_ENV_INSTR_TIME 0x03 extern char **saved_argv; extern int saved_argc; @@ -22,6 +24,7 @@ typedef struct RusticaValue { void *ptr; char data[]; RusticaPointerArray arr[]; + instr_time instr_time[]; }; } RusticaValue; From 76a9c9f095a14c050270ad379061ccf62a976bcc Mon Sep 17 00:00:00 2001 From: Xenia Lu Date: Sat, 4 Oct 2025 11:35:30 +0800 Subject: [PATCH 06/21] fix: sync WAMR patches and fix dump call stack --- meson.build | 1 + meson.py | 23 ++++ src/rustica/env.c | 2 +- src/rustica/main.c | 2 + subprojects/packagefiles/wamr/0001.patch | 89 ++++----------- subprojects/packagefiles/wamr/0002.patch | 83 ++------------ subprojects/packagefiles/wamr/0003.patch | 138 ++++++++++++++++++----- subprojects/packagefiles/wamr/0004.patch | 97 ++++++++++++++++ subprojects/wamr.wrap | 2 +- 9 files changed, 267 insertions(+), 170 deletions(-) create mode 100644 subprojects/packagefiles/wamr/0004.patch diff --git a/meson.build b/meson.build index d5187a9..ad51fe9 100644 --- a/meson.build +++ b/meson.build @@ -81,4 +81,5 @@ executable('rustica-engine', implib: 'postgres', dependencies: backend_build_deps + [vmlib], kwargs: pg.get_variable('default_bin_args'), + c_args: wamr.get_cmake_definitions('-DWASM'), ) diff --git a/meson.py b/meson.py index fadf4b1..7a4fc9b 100755 --- a/meson.py +++ b/meson.py @@ -6,6 +6,7 @@ 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 @@ -20,6 +21,7 @@ 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]) @@ -32,8 +34,29 @@ def get_cmake_variable( 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) + if __name__ == "__main__": cmake.CMakeSubproject = CMakeSubproject + interpreter.CMakeTraceParser = CMakeTraceParser sys.argv[0] = re.sub(r"(-script\.pyw|\.exe)?$", "", sys.argv[0]) sys.exit(main()) diff --git a/src/rustica/env.c b/src/rustica/env.c index 81dabfb..38b6318 100644 --- a/src/rustica/env.c +++ b/src/rustica/env.c @@ -76,7 +76,7 @@ static NativeSymbol spectest_symbols[] = { 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, "exception thrown by stdc++"); + wasm_runtime_set_exception(inst, "panic"); } static NativeSymbol exception_symbols[] = { diff --git a/src/rustica/main.c b/src/rustica/main.c index 94f34ca..ca325b7 100644 --- a/src/rustica/main.c +++ b/src/rustica/main.c @@ -6,6 +6,7 @@ #include "bh_platform.h" #include "bh_read_file.h" #include "gc_export.h" +#include "wasm_exec_env.h" #include "rustica/env.h" #include "rustica/moontest.h" @@ -180,6 +181,7 @@ main(int argc, char *argv[]) { fprintf(stderr, "Error creating execution environment\n"); return 1; } + exec_env->disable_dump_call_stack = true; PG_TRY(); { diff --git a/subprojects/packagefiles/wamr/0001.patch b/subprojects/packagefiles/wamr/0001.patch index 9c683a8..94389f3 100644 --- a/subprojects/packagefiles/wamr/0001.patch +++ b/subprojects/packagefiles/wamr/0001.patch @@ -1,8 +1,12 @@ -commit 8ff0666fc2cf81d4561ec277e75a0971260bea88 -Author: Xenia Lu -Date: Sun Sep 28 15:49:50 2025 +0800 +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 - Fix false OOB in array.fill +--- + 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 @@ -17,64 +21,19 @@ index edc473f2..d0ac01bd 100644 wasm_set_exception( module, "out of bounds array access"); goto got_exception; -diff --git a/tests/regression/ba-issues/issues/issue-4644/test.wasm b/tests/regression/ba-issues/issues/issue-4644/test.wasm -new file mode 100644 -index 00000000..21e0386d -Binary files /dev/null and b/tests/regression/ba-issues/issues/issue-4644/test.wasm differ -diff --git a/tests/regression/ba-issues/issues/issue-4644/test.wat b/tests/regression/ba-issues/issues/issue-4644/test.wat -new file mode 100644 -index 00000000..738d427c ---- /dev/null -+++ b/tests/regression/ba-issues/issues/issue-4644/test.wat -@@ -0,0 +1,24 @@ -+;; define array type - i32 array -+(type $i32_array (array (mut i32))) -+ -+;; main function -+(func $main -+ (local $arr (ref $i32_array)) -+ -+ ;; create an i32 array of size 10 with initial value 0 -+ (array.new $i32_array -+ (i32.const 0) ;; initial value -+ (i32.const 10)) ;; array size -+ (local.set $arr) -+ -+ ;; fill array using array.fill -+ (array.fill $i32_array -+ (local.get $arr) ;; array reference -+ (i32.const 0) ;; start index -+ (i32.const 42) ;; fill value -+ (i32.const 10)) ;; fill length - fill entire array -+) -+ -+(memory 1) -+(export "memory" (memory 0)) -+(export "_start" (func $main)) -diff --git a/tests/regression/ba-issues/running_config.json b/tests/regression/ba-issues/running_config.json -index 9288eb97..df8e32d2 100644 ---- a/tests/regression/ba-issues/running_config.json -+++ b/tests/regression/ba-issues/running_config.json -@@ -1754,6 +1754,22 @@ - "stdout content": "", - "description": "no sanitizer 'heap-buffer-overflow'" - } -+ }, -+ { -+ "deprecated": false, -+ "ids": [ -+ 4644 -+ ], -+ "runtime": "iwasm-default-gc-enabled", -+ "file": "test.wasm", -+ "mode": "classic-interp", -+ "options": "-f _start", -+ "argument": "", -+ "expected return": { -+ "ret code": 0, -+ "stdout content": "", -+ "description": "no out of bound 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/subprojects/packagefiles/wamr/0002.patch b/subprojects/packagefiles/wamr/0002.patch index ad32962..fb63c86 100644 --- a/subprojects/packagefiles/wamr/0002.patch +++ b/subprojects/packagefiles/wamr/0002.patch @@ -1,8 +1,11 @@ -commit f7ed6e1ef2ffabee0d3edd252ab47aff78b69b74 -Author: Xenia Lu -Date: Sun Sep 28 15:51:27 2025 +0800 +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 - 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 @@ -54,72 +57,6 @@ index 3f8c68db..b86c32d9 100644 POP_TYPE( wasm_type->types[wasm_type->param_count - i - 1]); -diff --git a/tests/regression/ba-issues/issues/issue-4646/test.wasm b/tests/regression/ba-issues/issues/issue-4646/test.wasm -new file mode 100644 -index 00000000..e163405e -Binary files /dev/null and b/tests/regression/ba-issues/issues/issue-4646/test.wasm differ -diff --git a/tests/regression/ba-issues/issues/issue-4646/test.wat b/tests/regression/ba-issues/issues/issue-4646/test.wat -new file mode 100644 -index 00000000..3fd503c5 ---- /dev/null -+++ b/tests/regression/ba-issues/issues/issue-4646/test.wat -@@ -0,0 +1,31 @@ -+;; define different reference types -+(type $struct_a (struct (field (mut i32)))) -+(type $struct_b (struct (field (mut i64)))) -+(type $struct_c (struct (field (mut i32)) (field (mut i32)))) -+ -+(func $main -+ ;; prepare parameters: i32, ref_a, i32, ref_b -+ (i32.const 10) -+ (struct.new $struct_a (i32.const 100)) -+ (i32.const 20) -+ (struct.new $struct_b (i64.const 200)) -+ -+ ;; block with interleaved parameters: i32, ref_a, i32, ref_b -> ref_c -+ (block (param i32 (ref $struct_a) i32 (ref $struct_b)) (result (ref $struct_c)) -+ ;; clean up parameters from stack -+ drop ;; drop ref_b -+ drop ;; drop i32 -+ drop ;; drop ref_a -+ drop ;; drop i32 -+ -+ ;; return new type reference struct_c -+ (struct.new $struct_c (i32.const 300) (i32.const 400)) -+ ) -+ -+ ;; drop return value -+ drop -+) -+ -+(memory 1) -+(export "memory" (memory 0)) -+(export "_start" (func $main)) -\ No newline at end of file -diff --git a/tests/regression/ba-issues/running_config.json b/tests/regression/ba-issues/running_config.json -index df8e32d2..9fe78c0e 100644 ---- a/tests/regression/ba-issues/running_config.json -+++ b/tests/regression/ba-issues/running_config.json -@@ -1770,6 +1770,22 @@ - "stdout content": "", - "description": "no out of bound exception" - } -+ }, -+ { -+ "deprecated": false, -+ "ids": [ -+ 4646 -+ ], -+ "runtime": "iwasm-default-gc-enabled", -+ "file": "test.wasm", -+ "mode": "classic-interp", -+ "options": "-f _start", -+ "argument": "", -+ "expected return": { -+ "ret code": 0, -+ "stdout content": "", -+ "description": "load successfully" -+ } - } - ] - } +-- +2.51.0 + diff --git a/subprojects/packagefiles/wamr/0003.patch b/subprojects/packagefiles/wamr/0003.patch index 8b78402..9997070 100644 --- a/subprojects/packagefiles/wamr/0003.patch +++ b/subprojects/packagefiles/wamr/0003.patch @@ -1,32 +1,110 @@ -commit df7ab8d44e03dd74aee14a0a8b48dfbdcce22a9a -Author: Xenia Lu -Date: Sun Sep 28 15:52:17 2025 +0800 +From 2bdde866b36ba0283b2120ab27e09339af69d7bc Mon Sep 17 00:00:00 2001 +From: Xenia Lu +Date: Fri, 3 Oct 2025 10:19:50 +0800 +Subject: [PATCH 3/4] build: fix LLVM 18 build on GCC 15 - Don't print stack by default +See also: referenced LLVM pull requests in patch files. +--- + build-scripts/build_llvm.py | 8 ++++- + ...01_Add_cstdint_to_SmallVector_101761.patch | 28 ++++++++++++++++ + ..._include_to_X86MCTargetDesc.h_123320.patch | 32 +++++++++++++++++++ + 3 files changed, 67 insertions(+), 1 deletion(-) + create mode 100644 build-scripts/llvm-patches/0001_Add_cstdint_to_SmallVector_101761.patch + create mode 100644 build-scripts/llvm-patches/0002_Add_missing_include_to_X86MCTargetDesc.h_123320.patch + +diff --git a/build-scripts/build_llvm.py b/build-scripts/build_llvm.py +index 3d241355..94e216ce 100755 +--- a/build-scripts/build_llvm.py ++++ b/build-scripts/build_llvm.py +@@ -23,9 +23,15 @@ def clone_llvm(dst_dir, llvm_repo, llvm_branch): + + if not llvm_dir.exists(): + GIT_CLONE_CMD = f"git clone --depth 1 --branch {llvm_branch} {llvm_repo} llvm" +- print(GIT_CLONE_CMD) ++ print(f"cd {dst_dir} && {GIT_CLONE_CMD}") + subprocess.check_output(shlex.split(GIT_CLONE_CMD), cwd=dst_dir) + ++ patch_dir = pathlib.Path(__file__).parent.joinpath("llvm-patches").resolve() ++ for patch_file in patch_dir.glob("*.patch"): ++ cmd = f"git apply {patch_file}" ++ print(f"cd {llvm_dir} && {cmd}") ++ subprocess.check_output(shlex.split(cmd), cwd=llvm_dir) ++ + return llvm_dir + + +diff --git a/build-scripts/llvm-patches/0001_Add_cstdint_to_SmallVector_101761.patch b/build-scripts/llvm-patches/0001_Add_cstdint_to_SmallVector_101761.patch +new file mode 100644 +index 00000000..c7ed0e16 +--- /dev/null ++++ b/build-scripts/llvm-patches/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/build-scripts/llvm-patches/0002_Add_missing_include_to_X86MCTargetDesc.h_123320.patch b/build-scripts/llvm-patches/0002_Add_missing_include_to_X86MCTargetDesc.h_123320.patch +new file mode 100644 +index 00000000..29c640cd +--- /dev/null ++++ b/build-scripts/llvm-patches/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 ++ +-- +2.51.0 -diff --git a/core/iwasm/interpreter/wasm_interp_classic.c b/core/iwasm/interpreter/wasm_interp_classic.c -index d0ac01bd..92bee750 100644 ---- a/core/iwasm/interpreter/wasm_interp_classic.c -+++ b/core/iwasm/interpreter/wasm_interp_classic.c -@@ -7547,7 +7547,7 @@ wasm_interp_call_wasm(WASMModuleInstance *module_inst, WASMExecEnv *exec_env, - else { - #if WASM_ENABLE_DUMP_CALL_STACK != 0 - if (wasm_interp_create_call_stack(exec_env)) { -- wasm_interp_dump_call_stack(exec_env, true, NULL, 0); -+ wasm_interp_dump_call_stack(exec_env, false, NULL, 0); - } - #endif - } -diff --git a/core/iwasm/interpreter/wasm_interp_fast.c b/core/iwasm/interpreter/wasm_interp_fast.c -index 36d4538f..7b17dfa7 100644 ---- a/core/iwasm/interpreter/wasm_interp_fast.c -+++ b/core/iwasm/interpreter/wasm_interp_fast.c -@@ -7982,7 +7982,7 @@ wasm_interp_call_wasm(WASMModuleInstance *module_inst, WASMExecEnv *exec_env, - else { - #if WASM_ENABLE_DUMP_CALL_STACK != 0 - if (wasm_interp_create_call_stack(exec_env)) { -- wasm_interp_dump_call_stack(exec_env, true, NULL, 0); -+ wasm_interp_dump_call_stack(exec_env, false, NULL, 0); - } - #endif - } diff --git a/subprojects/packagefiles/wamr/0004.patch b/subprojects/packagefiles/wamr/0004.patch new file mode 100644 index 0000000..00ae1d4 --- /dev/null +++ b/subprojects/packagefiles/wamr/0004.patch @@ -0,0 +1,97 @@ +From 18924258e08da63039046b6b293b30cee1592a2e Mon Sep 17 00:00:00 2001 +From: Xenia Lu +Date: Sun, 28 Sep 2025 03:52:17 +0800 +Subject: [PATCH 4/4] gate stack call dumping + +--- + core/iwasm/aot/aot_runtime.c | 6 ++++-- + core/iwasm/common/wasm_exec_env.h | 4 ++++ + core/iwasm/interpreter/wasm_interp_classic.c | 3 ++- + core/iwasm/interpreter/wasm_interp_fast.c | 3 ++- + core/iwasm/interpreter/wasm_runtime.c | 3 ++- + 5 files changed, 14 insertions(+), 5 deletions(-) + +diff --git a/core/iwasm/aot/aot_runtime.c b/core/iwasm/aot/aot_runtime.c +index d2621fb2..369e8eec 100644 +--- a/core/iwasm/aot/aot_runtime.c ++++ b/core/iwasm/aot/aot_runtime.c +@@ -2682,7 +2682,8 @@ aot_call_function(WASMExecEnv *exec_env, AOTFunctionInstance *function, + } + #endif + #if WASM_ENABLE_DUMP_CALL_STACK != 0 +- if (aot_create_call_stack(exec_env)) { ++ if (aot_create_call_stack(exec_env) ++ && !exec_env->disable_dump_call_stack) { + aot_dump_call_stack(exec_env, true, NULL, 0); + } + #endif +@@ -2755,7 +2756,8 @@ aot_call_function(WASMExecEnv *exec_env, AOTFunctionInstance *function, + } + #endif + #if WASM_ENABLE_DUMP_CALL_STACK != 0 +- if (aot_create_call_stack(exec_env)) { ++ if (aot_create_call_stack(exec_env) ++ && !exec_env->disable_dump_call_stack) { + aot_dump_call_stack(exec_env, true, NULL, 0); + } + #endif +diff --git a/core/iwasm/common/wasm_exec_env.h b/core/iwasm/common/wasm_exec_env.h +index 5d80312f..6494dcd1 100644 +--- a/core/iwasm/common/wasm_exec_env.h ++++ b/core/iwasm/common/wasm_exec_env.h +@@ -87,6 +87,10 @@ typedef struct WASMExecEnv { + uint8 *bottom; + } wasm_stack; + ++#if WASM_ENABLE_DUMP_CALL_STACK != 0 ++ bool disable_dump_call_stack; ++#endif ++ + #if WASM_ENABLE_INSTRUCTION_METERING != 0 + /* instructions to execute */ + int instructions_to_execute; +diff --git a/core/iwasm/interpreter/wasm_interp_classic.c b/core/iwasm/interpreter/wasm_interp_classic.c +index d0ac01bd..9d7b05a7 100644 +--- a/core/iwasm/interpreter/wasm_interp_classic.c ++++ b/core/iwasm/interpreter/wasm_interp_classic.c +@@ -7546,7 +7546,8 @@ wasm_interp_call_wasm(WASMModuleInstance *module_inst, WASMExecEnv *exec_env, + } + else { + #if WASM_ENABLE_DUMP_CALL_STACK != 0 +- if (wasm_interp_create_call_stack(exec_env)) { ++ if (wasm_interp_create_call_stack(exec_env) ++ && !exec_env->disable_dump_call_stack) { + wasm_interp_dump_call_stack(exec_env, true, NULL, 0); + } + #endif +diff --git a/core/iwasm/interpreter/wasm_interp_fast.c b/core/iwasm/interpreter/wasm_interp_fast.c +index 8f6bceb5..96fd2d19 100644 +--- a/core/iwasm/interpreter/wasm_interp_fast.c ++++ b/core/iwasm/interpreter/wasm_interp_fast.c +@@ -7981,7 +7981,8 @@ wasm_interp_call_wasm(WASMModuleInstance *module_inst, WASMExecEnv *exec_env, + } + else { + #if WASM_ENABLE_DUMP_CALL_STACK != 0 +- if (wasm_interp_create_call_stack(exec_env)) { ++ if (wasm_interp_create_call_stack(exec_env) ++ && !exec_env->disable_dump_call_stack) { + wasm_interp_dump_call_stack(exec_env, true, NULL, 0); + } + #endif +diff --git a/core/iwasm/interpreter/wasm_runtime.c b/core/iwasm/interpreter/wasm_runtime.c +index b4aa483d..8b2cbbf5 100644 +--- a/core/iwasm/interpreter/wasm_runtime.c ++++ b/core/iwasm/interpreter/wasm_runtime.c +@@ -3643,7 +3643,8 @@ call_wasm_with_hw_bound_check(WASMModuleInstance *module_inst, + * then the stack-frame is already freed inside wasm_interp_call_wasm */ + if (!ret) { + #if WASM_ENABLE_DUMP_CALL_STACK != 0 +- if (wasm_interp_create_call_stack(exec_env)) { ++ if (wasm_interp_create_call_stack(exec_env) ++ && !exec_env->disable_dump_call_stack) { + wasm_interp_dump_call_stack(exec_env, true, NULL, 0); + } + #endif +-- +2.51.0 + diff --git a/subprojects/wamr.wrap b/subprojects/wamr.wrap index 6ca08a9..0f3a1ac 100644 --- a/subprojects/wamr.wrap +++ b/subprojects/wamr.wrap @@ -3,4 +3,4 @@ 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/0003.patch +diff_files = wamr/0001.patch, wamr/0002.patch, wamr/0003.patch, wamr/0004.patch From 50538ae439b318d55971abef18d8615148163f3b Mon Sep 17 00:00:00 2001 From: Xenia Lu Date: Sun, 5 Oct 2025 12:08:39 +0800 Subject: [PATCH 07/21] I regreted. Just redirect os_printf to PG log --- meson.build | 1 + src/rustica/env.c | 29 +++++++ src/rustica/main.c | 2 - subprojects/packagefiles/wamr/0004.patch | 97 ------------------------ subprojects/wamr.wrap | 2 +- 5 files changed, 31 insertions(+), 100 deletions(-) delete mode 100644 subprojects/packagefiles/wamr/0004.patch diff --git a/meson.build b/meson.build index ad51fe9..1bb7ac2 100644 --- a/meson.build +++ b/meson.build @@ -51,6 +51,7 @@ wamr_var.add_cmake_defines({ # https://github.com/bytecodealliance/wasm-micro-runtime/issues/4640 'CMAKE_C_FLAGS': '-fzero-init-padding-bits=unions -Wno-incompatible-pointer-types', + 'WAMR_BH_VPRINTF': 'pg_log_vprintf', }) wamr = cmake.subproject('wamr', options: wamr_var) vmlib = wamr.dependency('vmlib') diff --git a/src/rustica/env.c b/src/rustica/env.c index 38b6318..85c9ec0 100644 --- a/src/rustica/env.c +++ b/src/rustica/env.c @@ -246,3 +246,32 @@ rustica_register_natives() { time_symbols, sizeof(time_symbols) / sizeof(NativeSymbol)); } + +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; +} diff --git a/src/rustica/main.c b/src/rustica/main.c index ca325b7..94f34ca 100644 --- a/src/rustica/main.c +++ b/src/rustica/main.c @@ -6,7 +6,6 @@ #include "bh_platform.h" #include "bh_read_file.h" #include "gc_export.h" -#include "wasm_exec_env.h" #include "rustica/env.h" #include "rustica/moontest.h" @@ -181,7 +180,6 @@ main(int argc, char *argv[]) { fprintf(stderr, "Error creating execution environment\n"); return 1; } - exec_env->disable_dump_call_stack = true; PG_TRY(); { diff --git a/subprojects/packagefiles/wamr/0004.patch b/subprojects/packagefiles/wamr/0004.patch deleted file mode 100644 index 00ae1d4..0000000 --- a/subprojects/packagefiles/wamr/0004.patch +++ /dev/null @@ -1,97 +0,0 @@ -From 18924258e08da63039046b6b293b30cee1592a2e Mon Sep 17 00:00:00 2001 -From: Xenia Lu -Date: Sun, 28 Sep 2025 03:52:17 +0800 -Subject: [PATCH 4/4] gate stack call dumping - ---- - core/iwasm/aot/aot_runtime.c | 6 ++++-- - core/iwasm/common/wasm_exec_env.h | 4 ++++ - core/iwasm/interpreter/wasm_interp_classic.c | 3 ++- - core/iwasm/interpreter/wasm_interp_fast.c | 3 ++- - core/iwasm/interpreter/wasm_runtime.c | 3 ++- - 5 files changed, 14 insertions(+), 5 deletions(-) - -diff --git a/core/iwasm/aot/aot_runtime.c b/core/iwasm/aot/aot_runtime.c -index d2621fb2..369e8eec 100644 ---- a/core/iwasm/aot/aot_runtime.c -+++ b/core/iwasm/aot/aot_runtime.c -@@ -2682,7 +2682,8 @@ aot_call_function(WASMExecEnv *exec_env, AOTFunctionInstance *function, - } - #endif - #if WASM_ENABLE_DUMP_CALL_STACK != 0 -- if (aot_create_call_stack(exec_env)) { -+ if (aot_create_call_stack(exec_env) -+ && !exec_env->disable_dump_call_stack) { - aot_dump_call_stack(exec_env, true, NULL, 0); - } - #endif -@@ -2755,7 +2756,8 @@ aot_call_function(WASMExecEnv *exec_env, AOTFunctionInstance *function, - } - #endif - #if WASM_ENABLE_DUMP_CALL_STACK != 0 -- if (aot_create_call_stack(exec_env)) { -+ if (aot_create_call_stack(exec_env) -+ && !exec_env->disable_dump_call_stack) { - aot_dump_call_stack(exec_env, true, NULL, 0); - } - #endif -diff --git a/core/iwasm/common/wasm_exec_env.h b/core/iwasm/common/wasm_exec_env.h -index 5d80312f..6494dcd1 100644 ---- a/core/iwasm/common/wasm_exec_env.h -+++ b/core/iwasm/common/wasm_exec_env.h -@@ -87,6 +87,10 @@ typedef struct WASMExecEnv { - uint8 *bottom; - } wasm_stack; - -+#if WASM_ENABLE_DUMP_CALL_STACK != 0 -+ bool disable_dump_call_stack; -+#endif -+ - #if WASM_ENABLE_INSTRUCTION_METERING != 0 - /* instructions to execute */ - int instructions_to_execute; -diff --git a/core/iwasm/interpreter/wasm_interp_classic.c b/core/iwasm/interpreter/wasm_interp_classic.c -index d0ac01bd..9d7b05a7 100644 ---- a/core/iwasm/interpreter/wasm_interp_classic.c -+++ b/core/iwasm/interpreter/wasm_interp_classic.c -@@ -7546,7 +7546,8 @@ wasm_interp_call_wasm(WASMModuleInstance *module_inst, WASMExecEnv *exec_env, - } - else { - #if WASM_ENABLE_DUMP_CALL_STACK != 0 -- if (wasm_interp_create_call_stack(exec_env)) { -+ if (wasm_interp_create_call_stack(exec_env) -+ && !exec_env->disable_dump_call_stack) { - wasm_interp_dump_call_stack(exec_env, true, NULL, 0); - } - #endif -diff --git a/core/iwasm/interpreter/wasm_interp_fast.c b/core/iwasm/interpreter/wasm_interp_fast.c -index 8f6bceb5..96fd2d19 100644 ---- a/core/iwasm/interpreter/wasm_interp_fast.c -+++ b/core/iwasm/interpreter/wasm_interp_fast.c -@@ -7981,7 +7981,8 @@ wasm_interp_call_wasm(WASMModuleInstance *module_inst, WASMExecEnv *exec_env, - } - else { - #if WASM_ENABLE_DUMP_CALL_STACK != 0 -- if (wasm_interp_create_call_stack(exec_env)) { -+ if (wasm_interp_create_call_stack(exec_env) -+ && !exec_env->disable_dump_call_stack) { - wasm_interp_dump_call_stack(exec_env, true, NULL, 0); - } - #endif -diff --git a/core/iwasm/interpreter/wasm_runtime.c b/core/iwasm/interpreter/wasm_runtime.c -index b4aa483d..8b2cbbf5 100644 ---- a/core/iwasm/interpreter/wasm_runtime.c -+++ b/core/iwasm/interpreter/wasm_runtime.c -@@ -3643,7 +3643,8 @@ call_wasm_with_hw_bound_check(WASMModuleInstance *module_inst, - * then the stack-frame is already freed inside wasm_interp_call_wasm */ - if (!ret) { - #if WASM_ENABLE_DUMP_CALL_STACK != 0 -- if (wasm_interp_create_call_stack(exec_env)) { -+ if (wasm_interp_create_call_stack(exec_env) -+ && !exec_env->disable_dump_call_stack) { - wasm_interp_dump_call_stack(exec_env, true, NULL, 0); - } - #endif --- -2.51.0 - diff --git a/subprojects/wamr.wrap b/subprojects/wamr.wrap index 0f3a1ac..6ca08a9 100644 --- a/subprojects/wamr.wrap +++ b/subprojects/wamr.wrap @@ -3,4 +3,4 @@ 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/0003.patch, wamr/0004.patch +diff_files = wamr/0001.patch, wamr/0002.patch, wamr/0003.patch From d2c1604b7e2bed0a63bba1ad0aaca4573d700bcc Mon Sep 17 00:00:00 2001 From: Xenia Lu Date: Sun, 5 Oct 2025 20:25:47 +0800 Subject: [PATCH 08/21] refactor: use PG exceptions and de-LLM --- meson.build | 1 + src/rustica/env.c | 87 ++++++----- src/rustica/main.c | 343 ++++++++++++++++++++++++----------------- src/rustica/moontest.c | 37 +++-- src/rustica/moontest.h | 6 +- 5 files changed, 272 insertions(+), 202 deletions(-) diff --git a/meson.build b/meson.build index 1bb7ac2..46ce503 100644 --- a/meson.build +++ b/meson.build @@ -59,6 +59,7 @@ 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 the rustica-engine executable diff --git a/src/rustica/env.c b/src/rustica/env.c index 85c9ec0..6be68c8 100644 --- a/src/rustica/env.c +++ b/src/rustica/env.c @@ -207,71 +207,74 @@ time_now(wasm_exec_env_t exec_env) { 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)); + 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); + 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 }, + { "instant_elapsed_as_secs_f64", + time_instant_elapsed_as_secs_f64, + "(r)F", + NULL }, }; void rustica_register_natives() { - wasm_runtime_register_natives("spectest", - spectest_symbols, - sizeof(spectest_symbols) - / sizeof(NativeSymbol)); - wasm_runtime_register_natives("exception", - exception_symbols, - sizeof(exception_symbols) - / sizeof(NativeSymbol)); - wasm_runtime_register_natives("__moonbit_fs_unstable", - fs_symbols, - sizeof(fs_symbols) / sizeof(NativeSymbol)); - wasm_runtime_register_natives("__moonbit_time_unstable", - time_symbols, - sizeof(time_symbols) / sizeof(NativeSymbol)); + 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); - } - ) - ); + 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; } diff --git a/src/rustica/main.c b/src/rustica/main.c index 94f34ca..0e7e75a 100644 --- a/src/rustica/main.c +++ b/src/rustica/main.c @@ -15,9 +15,26 @@ const char *progname; +static void +run_start(wasm_exec_env_t exec_env, va_list args); + +static void +run_moontest(wasm_exec_env_t exec_env, va_list args); + +static void +run_wasm_with(const char *wasm_file, 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"), @@ -30,34 +47,44 @@ help() { printf(_(" -V, --version output version information, then exit\n")); } -int -main(int argc, char *argv[]) { - static struct option long_options[] = { - { "help", no_argument, NULL, 'h' }, - { "version", no_argument, NULL, 'V' }, - { NULL, 0, NULL, 0 } - }; +static Subcommand +parse_args(int argc, char **argv) { + struct option long_options[] = { { "help", no_argument, NULL, 'h' }, + { "version", no_argument, NULL, 'V' }, + { NULL, 0, NULL, 0 } }; int c; - int subcmd_index = 1; - char error_buf[128]; - uint32 size; - uint8_t *buffer; - const char *moontest_spec = NULL; - const char *wasm_file = NULL; - const char *dot = NULL; - 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_Interp, - }; - wasm_module_t module = NULL; - wasm_module_inst_t module_inst = NULL; - wasm_exec_env_t exec_env = NULL; - const char *exc = NULL; + while ((c = getopt_long(argc, argv, "+m:hV", long_options, NULL)) != -1) { + switch (c) { + 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]))); +} + +int +main(int argc, char *argv[]) { + int rv = 0; saved_argc = argc; saved_argv = argv; @@ -77,143 +104,183 @@ main(int argc, char *argv[]) { unsetenv("LC_ALL"); - /* If no args, show help */ - if (argc < 2) { - help(); - exit(0); - } + PG_TRY(); + { + Subcommand subcmd = parse_args(argc, argv); + switch (subcmd) { + case RUN: + if (optind >= argc) + ereport(ERROR, errmsg("No wasm file specified for 'run'")); + run_wasm_with(argv[optind], run_start); + break; - /* If the first non-program argument begins with '-', parse global options - (e.g. prog -h or prog --version). Otherwise treat argv[1] as subcommand. */ - if (argv[1][0] == '-') { - optind = 1; - while ((c = getopt_long(argc, argv, "hV", long_options, NULL)) != -1) { - switch (c) { - case 'h': - help(); - exit(0); - case 'V': - printf("%s (PostgreSQL %s)\n", progname, PG_VERSION); - exit(0); - default: - fprintf(stderr, - _("Try \"%s --help\" for more information.\n"), - progname); - exit(1); - } - } - if (optind >= argc) { - help(); - exit(0); - } - subcmd_index = optind; - } + 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, run_moontest, moontest_spec); + } + else { + rv = 1; + } + } break; - /* Support minimal subcommands: - - 'run ' (no options) - - 'moontest --spec ' (parse options starting after - subcommand) - */ - if (strcmp(argv[subcmd_index], "run") == 0) { - if (subcmd_index + 1 >= argc) { - fprintf(stderr, "Error: No wasm file specified for 'run'\n"); - return 1; - } - wasm_file = argv[subcmd_index + 1]; - } - else if (strcmp(argv[subcmd_index], "moontest") == 0) { - optind = subcmd_index + 1; /* start parsing after subcommand */ - if (moontest_parse_args(argc, argv, &moontest_spec, &wasm_file) != 0) { - return 1; - } - if (moontest_spec == NULL) { - // Help was already printed by moontest_parse_args - return 0; + case HELP: + help(); + break; + + case VERSION: + printf("%s (PostgreSQL %s)\n", progname, PG_VERSION); + break; + + case BAD_ARGS: + rv = 1; + break; } - Assert(wasm_file != NULL); } - else { - /* Unknown subcommand -> show help */ - fprintf(stderr, "Unsupported command '%s'\n", argv[subcmd_index]); - help(); - return 1; + 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_Interp, + }; + + 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 || strcmp(dot, ".wasm") != 0) { - fprintf(stderr, "Unsupported file type\n"); - return 1; + ereport(ERROR, (errmsg("Unsupported file type: %s", wasm_file))); } - // 初始化WASM运行时并加载文件 - if (!wasm_runtime_full_init(&init_args)) { - fprintf(stderr, "Error: Failed to initialize WASM runtime\n"); - return 1; - } - buffer = (uint8_t *)bh_read_file_to_buffer(wasm_file, &size); + buffer = (uint8_t *)bh_read_file_to_buffer(wasm_file, out_size); if (!buffer) { - fprintf(stderr, "Error: Failed to read file: %s\n", argv[optind]); - return 1; + ereport(ERROR, (errmsg("Failed to read wasm file: %s", wasm_file))); } + return buffer; +} - rustica_register_natives(); +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; +} - module = wasm_runtime_load(buffer, size, error_buf, sizeof(error_buf)); - if (!module) { - fprintf(stderr, "Error loading wasm module: %s\n", error_buf); - return 1; - } +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); + })); + } +} - module_inst = wasm_runtime_instantiate(module, - STACK_K * 1024, - (uint32_t)HEAP_M * 1024 * 1024, - error_buf, - sizeof(error_buf)); - if (!module_inst) { - fprintf(stderr, "Error instantiating wasm module: %s\n", error_buf); - return 1; - } +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); +} - exec_env = wasm_runtime_create_exec_env(module_inst, STACK_K * 1024); - if (!exec_env) { - fprintf(stderr, "Error creating execution environment\n"); - return 1; - } +static void +run_wasm_with(const char *wasm_file, + 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(); { - if (moontest_spec) { - moontest_run(exec_env, moontest_spec); - } - else { - wasm_function_inst_t start_func = - wasm_runtime_lookup_function(module_inst, "_start"); - if (start_func) - wasm_runtime_call_wasm(exec_env, start_func, 0, NULL); + init_wamr(); + wamr_inited = true; + buffer = read_wasm_file(wasm_file, &size); + 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_CATCH(); + PG_FINALLY(); { - ErrorData *edata = CopyErrorData(); - fprintf(stderr, "Error: %s\n", edata->message); - FlushErrorState(); - FreeErrorData(edata); + 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(); - - exc = wasm_runtime_get_exception(module_inst); - if (exc) { - printf("Exception: %s\n", exc); - wasm_runtime_dump_call_stack(exec_env); - } - - wasm_runtime_destroy_exec_env(exec_env); - wasm_runtime_deinstantiate(module_inst); - wasm_runtime_unload(module); - wasm_runtime_destroy(); - - return 0; } static void diff --git a/src/rustica/moontest.c b/src/rustica/moontest.c index eced36b..81f4a33 100644 --- a/src/rustica/moontest.c +++ b/src/rustica/moontest.c @@ -14,16 +14,18 @@ struct option moontest_options[] = { { "spec", required_argument, NULL, 's' }, { "help", no_argument, NULL, 'h' }, { NULL, 0, NULL, 0 } }; -int +bool moontest_parse_args(int argc, char *argv[], - const char **moontest_spec, - const char **wasm_file) { + const char **out_spec, + const char **out_wasm_file) { int c; - while ((c = getopt_long(argc, argv, "s:h", moontest_options, NULL)) != -1) { + const char *spec = NULL; + while ((c = getopt_long(argc, argv, "+s:h", moontest_options, NULL)) + != -1) { switch (c) { case 's': - *moontest_spec = optarg; + spec = optarg; break; case 'h': printf(_("Usage:\n")); @@ -32,23 +34,20 @@ moontest_parse_args(int argc, printf(_( " --spec JSON spec describing tests to run\n")); printf(_(" -h, --help show this help, then exit\n")); - return 0; + *out_wasm_file = NULL; + *out_spec = spec; + return true; default: - fprintf(stderr, "Unknown option for 'moontest'\n"); - return 1; + return false; } } - if (optind < argc) - *wasm_file = argv[optind]; - if (!*moontest_spec) { - fprintf(stderr, "Error: --spec is required for 'moontest'\n"); - return 1; - } - if (!*wasm_file) { - fprintf(stderr, "Error: No wasm file specified for 'moontest'\n"); - return 1; - } - return 0; + 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 { diff --git a/src/rustica/moontest.h b/src/rustica/moontest.h index 2378102..0580cdc 100644 --- a/src/rustica/moontest.h +++ b/src/rustica/moontest.h @@ -1,11 +1,11 @@ #ifndef RUSTICA_MOONTEST_H #define RUSTICA_MOONTEST_H -int +bool moontest_parse_args(int argc, char *argv[], - const char **moontest_spec, - const char **wasm_file); + const char **out_spec, + const char **out_wasm_file); void moontest_run(wasm_exec_env_t exec_env, const char *moontest_spec); From 18fb2806dfeb064645240862f322b21ee1ce01f5 Mon Sep 17 00:00:00 2001 From: Xenia Lu Date: Sun, 5 Oct 2025 21:03:22 +0800 Subject: [PATCH 09/21] fix: support .WASM ext name --- src/rustica/main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/rustica/main.c b/src/rustica/main.c index 0e7e75a..31020fc 100644 --- a/src/rustica/main.c +++ b/src/rustica/main.c @@ -178,7 +178,7 @@ read_wasm_file(const char *wasm_file, uint32_t *out_size) { // 检查文件扩展名是否为 .wasm dot = strrchr(wasm_file, '.'); - if (!dot || strcmp(dot, ".wasm") != 0) { + if (!dot || strcasecmp(dot, ".wasm") != 0) { ereport(ERROR, (errmsg("Unsupported file type: %s", wasm_file))); } From 979cc0631d787069e0d6c608dd79f1107d6eb3df Mon Sep 17 00:00:00 2001 From: Xenia Lu Date: Sun, 5 Oct 2025 21:05:37 +0800 Subject: [PATCH 10/21] feat: use JIT/AOT runtime --- meson.build | 4 +- src/rustica/main.c | 116 +++++++++++++++++++++-- subprojects/packagefiles/wamr/0004.patch | 25 +++++ subprojects/wamr.wrap | 2 +- 4 files changed, 138 insertions(+), 9 deletions(-) create mode 100644 subprojects/packagefiles/wamr/0004.patch diff --git a/meson.build b/meson.build index 46ce503..bd7de6c 100644 --- a/meson.build +++ b/meson.build @@ -43,11 +43,13 @@ wamr_var.add_cmake_defines({ '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_FAST_INTERP': 0, + 'WAMR_BUILD_TAIL_CALL': 1, 'WAMR_BUILD_EXTENDED_CONST_EXPR': 1, 'WAMR_BUILD_EXCE_HANDLING': 1, + 'WAMR_BUILD_JIT': 1, # https://github.com/bytecodealliance/wasm-micro-runtime/issues/4640 'CMAKE_C_FLAGS': '-fzero-init-padding-bits=unions -Wno-incompatible-pointer-types', diff --git a/src/rustica/main.c b/src/rustica/main.c index 31020fc..ced60ad 100644 --- a/src/rustica/main.c +++ b/src/rustica/main.c @@ -6,6 +6,7 @@ #include "bh_platform.h" #include "bh_read_file.h" #include "gc_export.h" +#include "aot_export.h" #include "rustica/env.h" #include "rustica/moontest.h" @@ -22,7 +23,10 @@ static void run_moontest(wasm_exec_env_t exec_env, va_list args); static void -run_wasm_with(const char *wasm_file, void (*fn)(wasm_exec_env_t, va_list), ...); +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); @@ -43,19 +47,47 @@ help() { 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) { - struct option long_options[] = { { "help", no_argument, NULL, 'h' }, +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; @@ -84,6 +116,7 @@ parse_args(int argc, char **argv) { int main(int argc, char *argv[]) { + bool use_aot = true; int rv = 0; saved_argc = argc; @@ -106,12 +139,12 @@ main(int argc, char *argv[]) { PG_TRY(); { - Subcommand subcmd = parse_args(argc, argv); + 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], run_start); + run_wasm_with(argv[optind], use_aot, run_start); break; case MOONTEST: @@ -122,7 +155,10 @@ main(int argc, char *argv[]) { &moontest_spec, &wasm_file)) { if (wasm_file) - run_wasm_with(wasm_file, run_moontest, moontest_spec); + run_wasm_with(wasm_file, + use_aot, + run_moontest, + moontest_spec); } else { rv = 1; @@ -162,7 +198,7 @@ init_wamr() { .realloc_func = repalloc, .free_func = pfree } }, .gc_heap_size = (uint32_t)HEAP_M * 1024 * 1024, - .running_mode = Mode_Interp, + .running_mode = Mode_LLVM_JIT, }; if (!wasm_runtime_full_init(&init_args)) @@ -199,6 +235,66 @@ load_wasm_module(uint8_t *buffer, const uint32_t size) { 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); @@ -231,6 +327,7 @@ 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), ...) { bool wamr_inited = false; @@ -246,6 +343,11 @@ run_wasm_with(const char *wasm_file, 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]; 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/subprojects/wamr.wrap b/subprojects/wamr.wrap index 6ca08a9..0f3a1ac 100644 --- a/subprojects/wamr.wrap +++ b/subprojects/wamr.wrap @@ -3,4 +3,4 @@ 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/0003.patch +diff_files = wamr/0001.patch, wamr/0002.patch, wamr/0003.patch, wamr/0004.patch From 0a6bbde7b089032b6e45329a0f0aed33e8977166 Mon Sep 17 00:00:00 2001 From: Xenia Lu Date: Mon, 6 Oct 2025 09:32:09 +0800 Subject: [PATCH 11/21] feat: redirect bh_log to PG log --- meson.build | 1 + src/rustica/env.c | 46 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 47 insertions(+) diff --git a/meson.build b/meson.build index bd7de6c..9d2425a 100644 --- a/meson.build +++ b/meson.build @@ -54,6 +54,7 @@ wamr_var.add_cmake_defines({ # https://github.com/bytecodealliance/wasm-micro-runtime/issues/4640 'CMAKE_C_FLAGS': '-fzero-init-padding-bits=unions -Wno-incompatible-pointer-types', 'WAMR_BH_VPRINTF': 'pg_log_vprintf', + 'WAMR_BH_LOG': 'pg_bh_log', }) wamr = cmake.subproject('wamr', options: wamr_var) vmlib = wamr.dependency('vmlib') diff --git a/src/rustica/env.c b/src/rustica/env.c index 6be68c8..4f38bf8 100644 --- a/src/rustica/env.c +++ b/src/rustica/env.c @@ -6,6 +6,8 @@ #include "mb/pg_wchar.h" #include "portability/instr_time.h" +#include "bh_log.h" + #include "rustica/env.h" char **saved_argv; @@ -278,3 +280,47 @@ pg_log_vprintf(const char *format, va_list ap) { })); 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); +} From 60fdbd3caa5f83033d548adc149c3c0beb55078f Mon Sep 17 00:00:00 2001 From: Xenia Lu Date: Mon, 6 Oct 2025 09:50:10 +0800 Subject: [PATCH 12/21] misc: update README and LLVM build --- README.md | 14 ++++-- pyproject.toml | 1 + uv.lock | 123 ++++++++++++++++++++++++++++++++++++++++++++++++- 3 files changed, 132 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 7c80add..e699e4c 100644 --- a/README.md +++ b/README.md @@ -15,7 +15,6 @@ Rustica Engine 是一个将 WebAssembly 运行时 (WAMR) 与 PostgreSQL 后端 ### 依赖项 #### 构建工具 -- **Python** >= 3.13 - **Meson** >= 1.9.0 - **Ninja** (构建后端) - **uv** (Python 包管理器) @@ -69,7 +68,7 @@ sudo apt-get install -y \ libldap2-dev \ libsystemd-dev -# 安装 Python 和 uv +# 安装 uv curl -LsSf https://astral.sh/uv/install.sh | sh ``` @@ -120,7 +119,12 @@ uv sync uv run meson.py setup build ``` -4. 编译 rustica-engine: +4. 构建 LLVM: +```bash +uv run subprojects/wasm-*/build-scripts/build_llvm.py +``` + +5. 编译 rustica-engine: ```bash ninja -C build rustica-engine ``` @@ -129,7 +133,7 @@ ninja -C build rustica-engine 运行 WebAssembly 文件: ```bash -./build/rustica-engine +./build/rustica-engine run ``` 查看帮助信息: @@ -146,7 +150,7 @@ ninja -C build rustica-engine ```bash # 运行一个 WebAssembly 模块 -./build/rustica-engine example.wasm +./build/rustica-engine run example.wasm # 查看版本 ./build/rustica-engine -V diff --git a/pyproject.toml b/pyproject.toml index cf110de..18b6c42 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -6,4 +6,5 @@ readme = "README.md" requires-python = ">=3.9" dependencies = [ "meson>=1.9.0", + "requests>=2.32.5", ] diff --git a/uv.lock b/uv.lock index 255ae3c..5ecb207 100644 --- a/uv.lock +++ b/uv.lock @@ -2,6 +2,99 @@ 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" @@ -11,13 +104,41 @@ 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" }] +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" }, +] From afabb8d0f1a0b96c35074fae052226ef4ae7e0c8 Mon Sep 17 00:00:00 2001 From: Xenia Lu Date: Wed, 8 Oct 2025 14:00:50 +0800 Subject: [PATCH 13/21] feat: add option to embed all non-libc libs ...or dynamically link pre-built LLVM --- .gitignore | 2 + README.md | 7 +- meson.build | 64 ++++++++++++++++++- meson.py | 64 ++++++++++++++++++- meson_options.txt | 12 ++++ subprojects/.gitignore | 6 ++ subprojects/icu.wrap | 14 ++++ subprojects/lz4.wrap | 13 ++++ subprojects/openssl.wrap | 15 +++++ .../packagefiles/postgresql/embed-libs.patch | 47 ++++++++++++++ subprojects/packagefiles/wamr/0005.patch | 40 ++++++++++++ subprojects/postgresql.wrap | 2 +- subprojects/util-linux.wrap | 8 +++ subprojects/wamr.wrap | 2 +- subprojects/zlib.wrap | 13 ++++ 15 files changed, 297 insertions(+), 12 deletions(-) create mode 100644 meson_options.txt create mode 100644 subprojects/icu.wrap create mode 100644 subprojects/lz4.wrap create mode 100644 subprojects/openssl.wrap create mode 100644 subprojects/packagefiles/postgresql/embed-libs.patch create mode 100644 subprojects/packagefiles/wamr/0005.patch create mode 100644 subprojects/util-linux.wrap create mode 100644 subprojects/zlib.wrap diff --git a/.gitignore b/.gitignore index e1a2dea..ff54db9 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,4 @@ /.venv/ +/build/ +/build-staging/ /.python-version diff --git a/README.md b/README.md index e699e4c..29f93fb 100644 --- a/README.md +++ b/README.md @@ -119,12 +119,7 @@ uv sync uv run meson.py setup build ``` -4. 构建 LLVM: -```bash -uv run subprojects/wasm-*/build-scripts/build_llvm.py -``` - -5. 编译 rustica-engine: +4. 编译 rustica-engine: ```bash ninja -C build rustica-engine ``` diff --git a/meson.build b/meson.build index 9d2425a..9d2ae96 100644 --- a/meson.build +++ b/meson.build @@ -4,9 +4,45 @@ project( default_options : [] ) +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', + 'build-libblkid=disabled', + 'build-liblastlog2=disabled', + 'build-libsmartcols=disabled', + 'build-uuidd=disabled', + 'cryptsetup=disabled', + 'build-plymouth-support=disabled', + ], + ) + subproject('icu', default_options: ['default_library=static']) + subproject('openssl', default_options: ['default_library=static']) + zlib = subproject('zlib', default_options: ['default_library=static']) + zlib_a = zlib.build('zlib') +endif + # Include PostgreSQL subproject -pg = subproject('postgresql', default_options: ['uuid=e2fs']) +pg = subproject( + 'postgresql', + default_options: [ + '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 + 'uuid=e2fs', + ], +) add_project_arguments(pg.get_variable('cflags'), language: ['c']) add_project_arguments(pg.get_variable('cppflags'), language: ['c']) @@ -56,6 +92,28 @@ wamr_var.add_cmake_defines({ 'WAMR_BH_VPRINTF': 'pg_log_vprintf', 'WAMR_BH_LOG': 'pg_bh_log', }) +if get_option('llvm_dir') != '' + wamr_var.add_cmake_defines({ + 'LLVM_DIR': get_option('llvm_dir'), + }) +elif get_option('embed_libs') + # Tell WAMR to link LLVM with our static zlib + wamr_defines = { + 'LLVM_ENABLE_ZLIB:STRING': 'FORCE_ON', + 'ZLIB_LIBRARY': zlib_a, + 'ZLIB_INCLUDE_DIR': zlib.get_variable('depinc').to_list()[0], + 'ZLIB_USE_STATIC_LIBS': 'ON', + 'LLVM_ENABLE_ZSTD:STRING': 'OFF', + } + # Build LLVM with the right zlib too + llvm_cmake_flags = [] + foreach k, v : wamr_defines + llvm_cmake_flags += ['-D' + k + '=' + v] + endforeach + wamr_var.add_cmake_defines(wamr_defines + { + 'LLVM_CMAKE_FLAGS': ' '.join(llvm_cmake_flags), + }) +endif wamr = cmake.subproject('wamr', options: wamr_var) vmlib = wamr.dependency('vmlib') @@ -79,7 +137,9 @@ executable('rustica-engine', uncommon_shared_lib.extract_all_objects(recursive: false), ], include_directories: 'src', - link_args: pg.get_variable('backend_link_args'), + 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, diff --git a/meson.py b/meson.py index 7a4fc9b..e78ee9e 100755 --- a/meson.py +++ b/meson.py @@ -1,20 +1,26 @@ #!/usr/bin/env python3 # -*- coding: utf-8 -*- from __future__ import annotations +import copy +import pathlib import re import sys import typing as T -from mesonbuild.interpreterbase import noKwargs, typed_pos_args +from mesonbuild import mlog +from mesonbuild.interpreter import interpreter as ii +from mesonbuild.interpreter import interpreterobjects +from mesonbuild.interpreterbase import noKwargs, noPosargs, typed_pos_args, InterpreterObject from mesonbuild.cmake import interpreter from mesonbuild.mesonmain import main from mesonbuild.modules import cmake from mesonbuild.mesonlib import File +from mesonbuild.utils.universal import Popen_safe if T.TYPE_CHECKING: from mesonbuild.modules import ModuleState from mesonbuild.interpreter import SubprojectHolder - from mesonbuild.interpreterbase import TYPE_kwargs, TYPE_var, InterpreterObject + from mesonbuild.interpreterbase import TYPE_kwargs, TYPE_var class CMakeSubproject(cmake.CMakeSubproject): @@ -55,8 +61,62 @@ def add_definitions(self, tline: CMakeTraceLine) -> None: self.definitions.extend(tline.args) +class SubprojectHolder(ii.SubprojectHolder): + @noKwargs + @typed_pos_args("subproject.build", str) + @InterpreterObject.method('build') + def build_method(self, args: T.List[TYPE_var], kwargs: TYPE_kwargs) -> str: + backend = copy.copy(self.held_object.backend) + for k, v in list(backend.__dict__.items()): + try: + backend.__dict__[k] = copy.copy(v) + except Exception: + pass + env = backend.environment + builddir = pathlib.Path(env.build_dir).with_name("build-staging") + env.build_dir = str(builddir) + (builddir / 'meson-private').mkdir(parents=True, exist_ok=True) + mlog.log( + "Building subproject", + mlog.bold(self.held_object.subproject), + "for target", + mlog.bold(args[0]), + "in", + mlog.bold(str(builddir)), + ) + env.dump_coredata() + backend.generate(False, None) + rv = backend.get_target_filename_abs( + self.held_object.variables[args[0]]._target_object + ) + target = pathlib.Path(rv).relative_to(builddir) + p, o, e = Popen_safe(['ninja', target], cwd=builddir) + if p.returncode != 0: + mlog.error("Subproject build failed:") + mlog.log('--- stdout ---') + mlog.log(o) + mlog.log('--- stderr ---') + mlog.log(e) + mlog.log('') + raise RuntimeError("Subproject build failed") + else: + mlog.log("Subproject build successful") + return rv + + +class IncludeDirsHolder(interpreterobjects.IncludeDirsHolder): + @noKwargs + @noPosargs + @InterpreterObject.method('to_list') + def to_list_method(self, args: T.List[TYPE_var], kwargs: TYPE_kwargs) -> T.List[str]: + curdir = pathlib.Path(self.held_object.curdir) + return [str((curdir / inc).resolve()) for inc in self.held_object.incdirs] + + if __name__ == "__main__": cmake.CMakeSubproject = CMakeSubproject interpreter.CMakeTraceParser = CMakeTraceParser + ii.SubprojectHolder = SubprojectHolder + interpreterobjects.IncludeDirsHolder = IncludeDirsHolder 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..9ebbb4f --- /dev/null +++ b/meson_options.txt @@ -0,0 +1,12 @@ +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', +) diff --git a/subprojects/.gitignore b/subprojects/.gitignore index f8e6c44..099ccf7 100644 --- a/subprojects/.gitignore +++ b/subprojects/.gitignore @@ -2,3 +2,9 @@ .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/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/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/wamr/0005.patch b/subprojects/packagefiles/wamr/0005.patch new file mode 100644 index 0000000..86b9f5e --- /dev/null +++ b/subprojects/packagefiles/wamr/0005.patch @@ -0,0 +1,40 @@ +From 89ea88ff5754666322ae79b52abc83b9d9592dff Mon Sep 17 00:00:00 2001 +From: Xenia Lu +Date: Wed, 8 Oct 2025 10:48:59 +0800 +Subject: [PATCH 1/1] Build LLVM during setup + +--- + build-scripts/config_common.cmake | 10 +++++++++- + 1 file changed, 9 insertions(+), 1 deletion(-) + +diff --git a/build-scripts/config_common.cmake b/build-scripts/config_common.cmake +index 8cdce4a0..e86ec257 100644 +--- a/build-scripts/config_common.cmake ++++ b/build-scripts/config_common.cmake +@@ -103,7 +103,23 @@ if (WAMR_BUILD_JIT EQUAL 1) + set (LLVM_SRC_ROOT "${WAMR_ROOT_DIR}/core/deps/llvm") + set (LLVM_BUILD_ROOT "${LLVM_SRC_ROOT}/build") + if (NOT EXISTS "${LLVM_BUILD_ROOT}") +- message (FATAL_ERROR "Cannot find LLVM dir: ${LLVM_BUILD_ROOT}") ++ message(STATUS "LLVM build directory not found, attempting to build LLVM...") ++ if (DEFINED LLVM_CMAKE_FLAGS) ++ execute_process( ++ COMMAND python3 ${WAMR_ROOT_DIR}/build-scripts/build_llvm.py --extra-cmake-flags ${LLVM_CMAKE_FLAGS} ++ WORKING_DIRECTORY ${WAMR_ROOT_DIR} ++ RESULT_VARIABLE result ++ ) ++ else() ++ execute_process( ++ COMMAND python3 ${WAMR_ROOT_DIR}/build-scripts/build_llvm.py ++ WORKING_DIRECTORY ${WAMR_ROOT_DIR} ++ RESULT_VARIABLE result ++ ) ++ endif() ++ if (NOT result EQUAL 0) ++ message(FATAL_ERROR "Failed to build LLVM") ++ endif() + endif () + set (CMAKE_PREFIX_PATH "${LLVM_BUILD_ROOT};${CMAKE_PREFIX_PATH}") + set (LLVM_DIR ${LLVM_BUILD_ROOT}/lib/cmake/llvm) +-- +2.51.0 diff --git a/subprojects/postgresql.wrap b/subprojects/postgresql.wrap index 002a949..6f080bc 100644 --- a/subprojects/postgresql.wrap +++ b/subprojects/postgresql.wrap @@ -3,4 +3,4 @@ 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 +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..971a879 --- /dev/null +++ b/subprojects/util-linux.wrap @@ -0,0 +1,8 @@ +[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 + +[provide] +uuid = uuid_dep diff --git a/subprojects/wamr.wrap b/subprojects/wamr.wrap index 0f3a1ac..160de7a 100644 --- a/subprojects/wamr.wrap +++ b/subprojects/wamr.wrap @@ -3,4 +3,4 @@ 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/0003.patch, wamr/0004.patch +diff_files = wamr/0001.patch, wamr/0002.patch, wamr/0003.patch, wamr/0004.patch, wamr/0005.patch 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 From ae5a8eeb043749b48cf5ad6bceec59ee724bc81d Mon Sep 17 00:00:00 2001 From: Xenia Lu Date: Thu, 9 Oct 2025 08:42:06 +0800 Subject: [PATCH 14/21] feat: include the uuid-ossp extension by default --- meson.build | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/meson.build b/meson.build index 9d2ae96..b97b7e9 100644 --- a/meson.build +++ b/meson.build @@ -135,6 +135,7 @@ executable('rustica-engine', 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') + ( @@ -144,7 +145,7 @@ executable('rustica-engine', link_depends: pg.get_variable('backend_link_depends'), export_dynamic: true, implib: 'postgres', - dependencies: backend_build_deps + [vmlib], + dependencies: backend_build_deps + [vmlib, pg.get_variable('uuid')], kwargs: pg.get_variable('default_bin_args'), c_args: wamr.get_cmake_definitions('-DWASM'), ) From 58f3c098aa72ccd50e0e102b32e1ee50cbb69e26 Mon Sep 17 00:00:00 2001 From: Xenia Lu Date: Thu, 9 Oct 2025 10:01:18 +0800 Subject: [PATCH 15/21] feat: support building PG extension --- .gitignore | 3 ++ Makefile | 58 +++++++++++++++++++++++++++++++++++++ meson.build | 41 ++++++++++++++++++++++---- rustica-engine.control | 3 ++ sql/rustica-engine--1.0.sql | 0 src/rustica/extension.c | 9 ++++++ 6 files changed, 109 insertions(+), 5 deletions(-) create mode 100644 Makefile create mode 100644 rustica-engine.control create mode 100644 sql/rustica-engine--1.0.sql create mode 100644 src/rustica/extension.c diff --git a/.gitignore b/.gitignore index ff54db9..5a3e973 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,7 @@ /.venv/ /build/ /build-staging/ +/install/ +/data/ +/dist/ /.python-version diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..81776a7 --- /dev/null +++ b/Makefile @@ -0,0 +1,58 @@ +BUILD_DIR = $(shell pwd)/build +DIST_DIR = $(shell pwd)/dist +DEV_INSTALL_DIR = $(shell pwd)/install +DEV_DATA_DIR = $(shell pwd)/data +DEV_LLVM_DIR = /usr/lib/llvm18/lib/cmake/llvm + +# Default target: build for development +.PHONY: build +build: $(DEV_INSTALL_DIR) + +$(BUILD_DIR)/build.ninja: + uv run meson.py setup $(BUILD_DIR) --prefix=/ -Dllvm_dir=$(DEV_LLVM_DIR) + +$(DEV_INSTALL_DIR): $(BUILD_DIR)/build.ninja + uv run meson.py install -C $(BUILD_DIR) --destdir=$(DEV_INSTALL_DIR) + +# Run a development PostgreSQL instance +.PHONY: run +run: $(DEV_DATA_DIR) + $(DEV_INSTALL_DIR)/bin/postgres -D $(DEV_DATA_DIR) + +$(DEV_DATA_DIR): $(DEV_INSTALL_DIR) + $(DEV_INSTALL_DIR)/bin/initdb --auth=trust -D $(DEV_DATA_DIR) + +# 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: + uv run meson.py setup $(BUILD_DIR) --prefix=/usr -Dembed_libs=true --buildtype=release + uv run meson.py install -C $(BUILD_DIR) --destdir=$(DIST_DIR) --skip-subprojects --tags standalone + strip $(DIST_DIR)/usr/bin/rustica-engine + +# 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: + uv run meson.py setup $(BUILD_DIR) --prefix=/usr --buildtype=release + uv run meson.py install -C $(BUILD_DIR) --destdir=$(DIST_DIR) --skip-subprojects --tags extension + strip $(DIST_DIR)/usr/lib/postgresql/rustica-engine.so + +# Build both standalone binary and PostgreSQL extension for OS distribution packaging +.PHONY: dist +dist: + uv run meson.py setup $(BUILD_DIR) --prefix=/usr -Dllvm_dir=$(DEV_LLVM_DIR) --buildtype=release + uv run meson.py install -C $(BUILD_DIR) --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) $(shell dirname $(BUILD_DIR))/build-staging $(DEV_INSTALL_DIR) + +# Delete all build artifacts, development files, and distribution files +.PHONY: distclean +distclean: clean + rm -rf $(DIST_DIR) $(DEV_DATA_DIR) diff --git a/meson.build b/meson.build index b97b7e9..d60c7f5 100644 --- a/meson.build +++ b/meson.build @@ -30,6 +30,7 @@ endif pg = subproject( 'postgresql', default_options: [ + 'prefix=postgres', 'docs=disabled', # we don't need docs 'readline=disabled', # for psql 'zlib=disabled', # for pgdump/pgrestore @@ -40,6 +41,9 @@ pg = subproject( 'gssapi=disabled', # for GSSAPI auth 'ldap=disabled', # for LDAP lookup 'zstd=disabled', # for WAL compression + 'plperl=disabled', + 'plpython=disabled', + 'pltcl=disabled', 'uuid=e2fs', ], ) @@ -121,17 +125,24 @@ 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 executable +# 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/env.c', 'src/rustica/moontest.c', ], - sources: pg.get_variable('post_export_backend_sources'), + 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), @@ -145,7 +156,27 @@ executable('rustica-engine', link_depends: pg.get_variable('backend_link_depends'), export_dynamic: true, implib: 'postgres', - dependencies: backend_build_deps + [vmlib, pg.get_variable('uuid')], + dependencies: backend_build_deps + rustica_deps, kwargs: pg.get_variable('default_bin_args'), - c_args: wamr.get_cmake_definitions('-DWASM'), + 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/rustica-engine.control b/rustica-engine.control new file mode 100644 index 0000000..2972d9a --- /dev/null +++ b/rustica-engine.control @@ -0,0 +1,3 @@ +comment = 'Rustica Engine' +default_version = '1.0' +module_pathname = '$libdir/rustica-engine' diff --git a/sql/rustica-engine--1.0.sql b/sql/rustica-engine--1.0.sql new file mode 100644 index 0000000..e69de29 diff --git a/src/rustica/extension.c b/src/rustica/extension.c new file mode 100644 index 0000000..f8bbc3a --- /dev/null +++ b/src/rustica/extension.c @@ -0,0 +1,9 @@ +#include "postgres.h" +#include "utils/builtins.h" + +PG_MODULE_MAGIC; + +void +_PG_init(void) { + ereport(LOG, errmsg("Rustica Engine is now loaded")); +} From a56a2f52b2f938de0972aed6ff3abd552a84cf21 Mon Sep 17 00:00:00 2001 From: Xenia Lu Date: Thu, 9 Oct 2025 11:12:21 +0800 Subject: [PATCH 16/21] ci: test build standlone --- .github/workflows/ci.yml | 58 +++++++++++++++++++ meson.build | 10 +++- .../packagefiles/util-linux/3761.patch | 13 +++++ subprojects/util-linux.wrap | 1 + 4 files changed, 80 insertions(+), 2 deletions(-) create mode 100644 .github/workflows/ci.yml create mode 100644 subprojects/packagefiles/util-linux/3761.patch diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..af924d2 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,58 @@ +name: CI + +on: + push: + branches: [ master, ci ] + + pull_request: + branches: [ master ] + +jobs: + + build-standalone: + runs-on: ubuntu-22.04 + + steps: + + - uses: actions/checkout@v4 + + - name: Install uv + uses: astral-sh/setup-uv@v7 + + - uses: actions/cache@v4 + id: cache-standalone + with: + key: standalone-setup-${{ runner.os }}-${{ hashFiles('meson*', 'subprojects/*.wrap') }} + restore-keys: standalone-setup-${{ runner.os }}- + path: | + ./subprojects/packagecache + ./subprojects/wasm-micro-runtime-WAMR-*/core/deps/llvm/build/bin + ./subprojects/wasm-micro-runtime-WAMR-*/core/deps/llvm/build/include + ./subprojects/wasm-micro-runtime-WAMR-*/core/deps/llvm/build/lib + ./subprojects/wasm-micro-runtime-WAMR-*/core/deps/llvm/build/libexec + ./subprojects/wasm-micro-runtime-WAMR-*/core/deps/llvm/build/share + + - name: Install LLVM build dependencies + id: ccache-setup + if: steps.cache-standalone.outputs.cache-hit != 'true' + run: | + sudo apt-get update + sudo apt-get install -y ccache + echo "ccache_dir=$(ccache --get-config=cache_dir)" >> $GITHUB_OUTPUT + + - uses: actions/cache@v4 + if: steps.cache-standalone.outputs.cache-hit != 'true' + with: + key: llvm-ccache-${{ runner.os }}-${{ hashFiles('meson*', 'subprojects/*.wrap') }} + restore-keys: llvm-ccache-${{ runner.os }}- + path: ${{ steps.ccache-setup.outputs.ccache_dir }} + + - name: Build standalone + run: | + uv venv + make standalone + + - uses: actions/upload-artifact@v4 + with: + name: standalone + path: dist diff --git a/meson.build b/meson.build index d60c7f5..85a590e 100644 --- a/meson.build +++ b/meson.build @@ -76,6 +76,13 @@ postgres_pure_lib = static_library('postgres_lib', # Include WAMR subproject +cc = meson.get_compiler('c') +wamr_c_flags = ['-Wno-incompatible-pointer-types'] +# 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({ @@ -91,8 +98,7 @@ wamr_var.add_cmake_defines({ 'WAMR_BUILD_EXCE_HANDLING': 1, 'WAMR_BUILD_JIT': 1, - # https://github.com/bytecodealliance/wasm-micro-runtime/issues/4640 - 'CMAKE_C_FLAGS': '-fzero-init-padding-bits=unions -Wno-incompatible-pointer-types', + 'CMAKE_C_FLAGS': ' '.join(wamr_c_flags), 'WAMR_BH_VPRINTF': 'pg_log_vprintf', 'WAMR_BH_LOG': 'pg_bh_log', }) 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/util-linux.wrap b/subprojects/util-linux.wrap index 971a879..b66c4f7 100644 --- a/subprojects/util-linux.wrap +++ b/subprojects/util-linux.wrap @@ -3,6 +3,7 @@ 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 [provide] uuid = uuid_dep From 045fc1f53fc0b477c2a9df187a0e67d3bc4e144b Mon Sep 17 00:00:00 2001 From: Xenia Lu Date: Sat, 11 Oct 2025 09:42:23 +0800 Subject: [PATCH 17/21] fix: support old GCC --- src/rustica/env.c | 29 ++++++----------------------- src/rustica/env.h | 9 ++++----- 2 files changed, 10 insertions(+), 28 deletions(-) diff --git a/src/rustica/env.c b/src/rustica/env.c index 99480b5..332b947 100644 --- a/src/rustica/env.c +++ b/src/rustica/env.c @@ -20,27 +20,19 @@ 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); - if (val->owns_ptr) - pfree(val->ptr); pfree(val); } rustica_value_t rustica_value_new(const uint8_t type, void *ptr, const size_t size) { - const rustica_value_t rv = - palloc(sizeof(RusticaValue) - + (size > sizeof(void *) ? size - sizeof(void *) : 0)); + const rustica_value_t rv = palloc0(sizeof(RusticaValue) + size); rv->type = type; - rv->owns_ptr = false; if (size == 0) { rv->ptr = ptr; - rv->data_builtin = false; } else { - rv->data_builtin = true; - if (ptr == NULL) - memset(rv->data, 0, size); - else + rv->data = rv->vardata; + if (ptr != NULL) memcpy(rv->data, ptr, size); } return rv; @@ -93,14 +85,8 @@ 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; - if (val->data_builtin) { - buf->size = strlen(val->data); - buf->data = val->data; - } - else { - buf->size = strlen(val->ptr); - buf->data = val->ptr; - } + buf->size = strlen(val->data); + buf->data = val->data; return buf; } @@ -138,10 +124,7 @@ fs_begin_read_string_array(wasm_exec_env_t exec_env, wasm_obj_t ref) { rustica_value_from_wasm(ref, RUSTICA_ENV_CSTRING_ARRAY); ArrayReader *reader = palloc(sizeof(ArrayReader)); reader->offset = 0; - if (val->data_builtin) - reader->arr = val->arr; - else - reader->arr = val->ptr; + reader->arr = val->arr; return reader; } diff --git a/src/rustica/env.h b/src/rustica/env.h index 7bc62a1..40770f5 100644 --- a/src/rustica/env.h +++ b/src/rustica/env.h @@ -21,14 +21,13 @@ typedef struct RusticaPointerArray { typedef struct RusticaValue { uint8_t type; - bool data_builtin; - bool owns_ptr; union { void *ptr; - char data[]; - RusticaPointerArray arr[]; - instr_time instr_time[]; + char *data; + RusticaPointerArray *arr; + instr_time *instr_time; }; + char vardata[]; } RusticaValue; typedef RusticaValue *rustica_value_t; From f6ed97ad35a8f58ad88c8e894467e5a8ba8dd6ba Mon Sep 17 00:00:00 2001 From: Xenia Lu Date: Fri, 10 Oct 2025 15:26:52 +0800 Subject: [PATCH 18/21] ci: separate setup and build --- .github/workflows/ci.yml | 72 +++++++++++++++++++++++++++++----------- 1 file changed, 53 insertions(+), 19 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index af924d2..bfb0266 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -2,28 +2,72 @@ name: CI on: push: - branches: [ master, ci ] + branches: [ master ] pull_request: branches: [ master ] jobs: + setup-standalone: + runs-on: ubuntu-22.04 + + steps: + + - uses: actions/checkout@v4 + + - name: Install uv + uses: astral-sh/setup-uv@v7 + + - name: Cache setup artifacts + uses: actions/cache@v4 + id: cache-standalone + with: + key: standalone-setup-${{ runner.os }}-${{ hashFiles('meson*', 'subprojects/*.wrap') }} + restore-keys: standalone-setup-${{ runner.os }}- + path: | + ./subprojects/packagecache + ./subprojects/wasm-micro-runtime-WAMR-*/core/deps/llvm/build/bin + ./subprojects/wasm-micro-runtime-WAMR-*/core/deps/llvm/build/include + ./subprojects/wasm-micro-runtime-WAMR-*/core/deps/llvm/build/lib + ./subprojects/wasm-micro-runtime-WAMR-*/core/deps/llvm/build/libexec + ./subprojects/wasm-micro-runtime-WAMR-*/core/deps/llvm/build/share + + - name: Setup ccache + if: steps.cache-standalone.outputs.cache-hit != 'true' + uses: hendrikmuhs/ccache-action@v1.2 + with: + key: ccache-llvm-${{ runner.os }} + + - name: Setup standalone build + if: steps.cache-standalone.outputs.cache-hit != 'true' + run: | + uv venv + uv run meson.py setup build --prefix=/ -Dembed_libs=true --buildtype=release + build-standalone: runs-on: ubuntu-22.04 + needs: setup-standalone steps: - uses: actions/checkout@v4 + - name: Setup ccache + uses: hendrikmuhs/ccache-action@v1.2 + with: + key: ccache-standalone-${{ runner.os }} + - name: Install uv uses: astral-sh/setup-uv@v7 - - uses: actions/cache@v4 + - name: Retrieve setup artifacts + uses: actions/cache@v4 id: cache-standalone with: key: standalone-setup-${{ runner.os }}-${{ hashFiles('meson*', 'subprojects/*.wrap') }} restore-keys: standalone-setup-${{ runner.os }}- + fail-on-cache-miss: true path: | ./subprojects/packagecache ./subprojects/wasm-micro-runtime-WAMR-*/core/deps/llvm/build/bin @@ -32,27 +76,17 @@ jobs: ./subprojects/wasm-micro-runtime-WAMR-*/core/deps/llvm/build/libexec ./subprojects/wasm-micro-runtime-WAMR-*/core/deps/llvm/build/share - - name: Install LLVM build dependencies - id: ccache-setup - if: steps.cache-standalone.outputs.cache-hit != 'true' - run: | - sudo apt-get update - sudo apt-get install -y ccache - echo "ccache_dir=$(ccache --get-config=cache_dir)" >> $GITHUB_OUTPUT - - - uses: actions/cache@v4 - if: steps.cache-standalone.outputs.cache-hit != 'true' - with: - key: llvm-ccache-${{ runner.os }}-${{ hashFiles('meson*', 'subprojects/*.wrap') }} - restore-keys: llvm-ccache-${{ runner.os }}- - path: ${{ steps.ccache-setup.outputs.ccache_dir }} - - name: Build standalone run: | + mv subprojects/wasm-micro-runtime-WAMR-*/core/deps/llvm/build subprojects/llvm + rm -rf subprojects/wasm-micro-runtime-WAMR-* uv venv - make standalone + uv run meson.py setup build --prefix=/ -Dllvm_dir=subprojects/llvm/lib/cmake/llvm -Dembed_libs=true --buildtype=release + uv run meson.py install -C build --destdir=dist --skip-subprojects --tags standalone + strip dist/bin/rustica-engine - uses: actions/upload-artifact@v4 with: name: standalone - path: dist + path: dist/bin/rustica-engine + From ee6d128f249f0138be7bcdf995cea8acee78c7c1 Mon Sep 17 00:00:00 2001 From: Xenia Lu Date: Sat, 11 Oct 2025 11:33:57 +0800 Subject: [PATCH 19/21] fix: use proper deps_dir for LLVM --- .github/workflows/ci.yml | 26 +++++------ meson.build | 1 + subprojects/.gitignore | 1 + subprojects/packagefiles/wamr/0006.patch | 55 ++++++++++++++++++++++++ subprojects/wamr.wrap | 2 +- 5 files changed, 69 insertions(+), 16 deletions(-) create mode 100644 subprojects/packagefiles/wamr/0006.patch diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index bfb0266..b22f183 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -27,11 +27,11 @@ jobs: restore-keys: standalone-setup-${{ runner.os }}- path: | ./subprojects/packagecache - ./subprojects/wasm-micro-runtime-WAMR-*/core/deps/llvm/build/bin - ./subprojects/wasm-micro-runtime-WAMR-*/core/deps/llvm/build/include - ./subprojects/wasm-micro-runtime-WAMR-*/core/deps/llvm/build/lib - ./subprojects/wasm-micro-runtime-WAMR-*/core/deps/llvm/build/libexec - ./subprojects/wasm-micro-runtime-WAMR-*/core/deps/llvm/build/share + ./subprojects/llvm/build/bin + ./subprojects/llvm/build/include + ./subprojects/llvm/build/lib + ./subprojects/llvm/build/libexec + ./subprojects/llvm/build/share - name: Setup ccache if: steps.cache-standalone.outputs.cache-hit != 'true' @@ -70,20 +70,16 @@ jobs: fail-on-cache-miss: true path: | ./subprojects/packagecache - ./subprojects/wasm-micro-runtime-WAMR-*/core/deps/llvm/build/bin - ./subprojects/wasm-micro-runtime-WAMR-*/core/deps/llvm/build/include - ./subprojects/wasm-micro-runtime-WAMR-*/core/deps/llvm/build/lib - ./subprojects/wasm-micro-runtime-WAMR-*/core/deps/llvm/build/libexec - ./subprojects/wasm-micro-runtime-WAMR-*/core/deps/llvm/build/share + ./subprojects/llvm/build/bin + ./subprojects/llvm/build/include + ./subprojects/llvm/build/lib + ./subprojects/llvm/build/libexec + ./subprojects/llvm/build/share - name: Build standalone run: | - mv subprojects/wasm-micro-runtime-WAMR-*/core/deps/llvm/build subprojects/llvm - rm -rf subprojects/wasm-micro-runtime-WAMR-* uv venv - uv run meson.py setup build --prefix=/ -Dllvm_dir=subprojects/llvm/lib/cmake/llvm -Dembed_libs=true --buildtype=release - uv run meson.py install -C build --destdir=dist --skip-subprojects --tags standalone - strip dist/bin/rustica-engine + make standalone - uses: actions/upload-artifact@v4 with: diff --git a/meson.build b/meson.build index 3faae53..d92b434 100644 --- a/meson.build +++ b/meson.build @@ -101,6 +101,7 @@ wamr_var.add_cmake_defines({ 'WAMR_BUILD_EXCE_HANDLING': 1, 'WAMR_BUILD_JIT': 1, + 'DEPS_DIR': meson.project_source_root() / 'subprojects', 'CMAKE_C_FLAGS': ' '.join(wamr_c_flags), 'WAMR_BH_VPRINTF': 'pg_log_vprintf', 'WAMR_BH_LOG': 'pg_bh_log', diff --git a/subprojects/.gitignore b/subprojects/.gitignore index 099ccf7..3b40d99 100644 --- a/subprojects/.gitignore +++ b/subprojects/.gitignore @@ -8,3 +8,4 @@ /openssl-*/ /llvm-project-*.src/ /zlib-*/ +/llvm/ diff --git a/subprojects/packagefiles/wamr/0006.patch b/subprojects/packagefiles/wamr/0006.patch new file mode 100644 index 0000000..1cadc85 --- /dev/null +++ b/subprojects/packagefiles/wamr/0006.patch @@ -0,0 +1,55 @@ +diff -ru wasm-micro-runtime-WAMR-2.4.2.orig/build-scripts/build_llvm.py wasm-micro-runtime-WAMR-2.4.2/build-scripts/build_llvm.py +--- wasm-micro-runtime-WAMR-2.4.2.orig/build-scripts/build_llvm.py 2025-10-11 12:28:16.653222239 +0800 ++++ wasm-micro-runtime-WAMR-2.4.2/build-scripts/build_llvm.py 2025-10-11 12:28:48.276741632 +0800 +@@ -236,6 +236,11 @@ + def main(): + parser = argparse.ArgumentParser(description="build necessary LLVM libraries") + parser.add_argument( ++ "--deps-dir", ++ type=str, ++ default="", ++ ) ++ parser.add_argument( + "--platform", + type=str, + choices=["android", "arc", "darwin", "linux", "windows", "xtensa"], +@@ -319,8 +324,11 @@ + if current_file.is_symlink(): + current_file = pathlib.Path(os.readlink(current_file)) + +- current_dir = current_file.parent.resolve() +- deps_dir = current_dir.joinpath("../core/deps").resolve() ++ if options.deps_dir: ++ deps_dir = pathlib.Path(options.deps_dir) ++ else: ++ current_dir = current_file.parent.resolve() ++ deps_dir = current_dir.joinpath("../core/deps").resolve() + + try: + llvm_info = llvm_repo_and_branch.get(platform, llvm_repo_and_branch["default"]) +diff -ru wasm-micro-runtime-WAMR-2.4.2.orig/build-scripts/config_common.cmake wasm-micro-runtime-WAMR-2.4.2/build-scripts/config_common.cmake +--- wasm-micro-runtime-WAMR-2.4.2.orig/build-scripts/config_common.cmake 2025-10-11 12:28:16.656555593 +0800 ++++ wasm-micro-runtime-WAMR-2.4.2/build-scripts/config_common.cmake 2025-10-11 12:29:31.690330374 +0800 +@@ -100,19 +100,19 @@ + set (WAMR_BUILD_LAZY_JIT 1) + endif () + if (NOT DEFINED LLVM_DIR) +- set (LLVM_SRC_ROOT "${WAMR_ROOT_DIR}/core/deps/llvm") ++ set (LLVM_SRC_ROOT "${DEPS_DIR}/llvm") + set (LLVM_BUILD_ROOT "${LLVM_SRC_ROOT}/build") + if (NOT EXISTS "${LLVM_BUILD_ROOT}") + message(STATUS "LLVM build directory not found, attempting to build LLVM...") + if (DEFINED LLVM_CMAKE_FLAGS) + execute_process( +- COMMAND python3 ${WAMR_ROOT_DIR}/build-scripts/build_llvm.py --extra-cmake-flags ${LLVM_CMAKE_FLAGS} ++ COMMAND python3 ${WAMR_ROOT_DIR}/build-scripts/build_llvm.py --deps-dir ${DEPS_DIR} --extra-cmake-flags ${LLVM_CMAKE_FLAGS} + WORKING_DIRECTORY ${WAMR_ROOT_DIR} + RESULT_VARIABLE result + ) + else() + execute_process( +- COMMAND python3 ${WAMR_ROOT_DIR}/build-scripts/build_llvm.py ++ COMMAND python3 ${WAMR_ROOT_DIR}/build-scripts/build_llvm.py --deps-dir ${DEPS_DIR} + WORKING_DIRECTORY ${WAMR_ROOT_DIR} + RESULT_VARIABLE result + ) diff --git a/subprojects/wamr.wrap b/subprojects/wamr.wrap index 160de7a..831022c 100644 --- a/subprojects/wamr.wrap +++ b/subprojects/wamr.wrap @@ -3,4 +3,4 @@ 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/0003.patch, wamr/0004.patch, wamr/0005.patch +diff_files = wamr/0001.patch, wamr/0002.patch, wamr/0003.patch, wamr/0004.patch, wamr/0005.patch, wamr/0006.patch From 069258f40d38f588b5e911bd6978b597a0831a47 Mon Sep 17 00:00:00 2001 From: Xenia Lu Date: Sun, 12 Oct 2025 09:24:01 +0800 Subject: [PATCH 20/21] build: make zlib/LLVM as top-level deps --- .github/workflows/ci.yml | 133 +++++++++++++----- .gitignore | 2 - Makefile | 92 +++++++++--- meson.build | 47 +++---- meson.py | 89 ++++-------- meson_options.txt | 18 +++ subprojects/.gitignore | 1 - subprojects/llvm.wrap | 9 ++ ...01_Add_cstdint_to_SmallVector_101761.patch | 28 ++++ ..._include_to_X86MCTargetDesc.h_123320.patch | 32 +++++ .../llvm/0003_Add_Meson_Build.patch | 84 +++++++++++ subprojects/packagefiles/wamr/0003.patch | 110 --------------- subprojects/packagefiles/wamr/0005.patch | 40 ------ subprojects/packagefiles/wamr/0006.patch | 55 -------- subprojects/wamr.wrap | 3 +- 15 files changed, 392 insertions(+), 351 deletions(-) create mode 100644 subprojects/llvm.wrap create mode 100644 subprojects/packagefiles/llvm/0001_Add_cstdint_to_SmallVector_101761.patch create mode 100644 subprojects/packagefiles/llvm/0002_Add_missing_include_to_X86MCTargetDesc.h_123320.patch create mode 100644 subprojects/packagefiles/llvm/0003_Add_Meson_Build.patch delete mode 100644 subprojects/packagefiles/wamr/0003.patch delete mode 100644 subprojects/packagefiles/wamr/0005.patch delete mode 100644 subprojects/packagefiles/wamr/0006.patch diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index b22f183..8f34883 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -9,80 +9,141 @@ on: jobs: - setup-standalone: - runs-on: ubuntu-22.04 + download-subprojects: + runs-on: ubuntu-latest + container: + image: ubuntu:22.04 steps: - uses: actions/checkout@v4 - - name: Install uv + - 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 - - name: Cache setup artifacts + - 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: cache-standalone + id: llvm_cache with: - key: standalone-setup-${{ runner.os }}-${{ hashFiles('meson*', 'subprojects/*.wrap') }} - restore-keys: standalone-setup-${{ runner.os }}- + key: llvm-${{ runner.os }}-${{ hashFiles('subprojects/llvm.wrap', 'subprojects/packagefiles/llvm/*') }} + restore-keys: llvm-${{ runner.os }}- path: | - ./subprojects/packagecache - ./subprojects/llvm/build/bin - ./subprojects/llvm/build/include - ./subprojects/llvm/build/lib - ./subprojects/llvm/build/libexec - ./subprojects/llvm/build/share + ./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.cache-standalone.outputs.cache-hit != 'true' + if: steps.llvm_cache.outputs.cache-hit != 'true' uses: hendrikmuhs/ccache-action@v1.2 with: key: ccache-llvm-${{ runner.os }} - - name: Setup standalone build - if: steps.cache-standalone.outputs.cache-hit != 'true' + - if: steps.llvm_cache.outputs.cache-hit != 'true' + name: Build LLVM run: | uv venv - uv run meson.py setup build --prefix=/ -Dembed_libs=true --buildtype=release + make `pwd`/build/llvm/.stamp build-standalone: - runs-on: ubuntu-22.04 - needs: setup-standalone + runs-on: ubuntu-latest + needs: [ download-subprojects, build-llvm ] + container: + image: ubuntu:22.04 steps: - uses: actions/checkout@v4 - - name: Setup ccache - uses: hendrikmuhs/ccache-action@v1.2 + - name: Retrieve subproject downloads + uses: actions/cache/restore@v4 with: - key: ccache-standalone-${{ runner.os }} + 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: Retrieve setup artifacts - uses: actions/cache@v4 - id: cache-standalone + - name: Setup ccache + uses: hendrikmuhs/ccache-action@v1.2 with: - key: standalone-setup-${{ runner.os }}-${{ hashFiles('meson*', 'subprojects/*.wrap') }} - restore-keys: standalone-setup-${{ runner.os }}- - fail-on-cache-miss: true - path: | - ./subprojects/packagecache - ./subprojects/llvm/build/bin - ./subprojects/llvm/build/include - ./subprojects/llvm/build/lib - ./subprojects/llvm/build/libexec - ./subprojects/llvm/build/share + 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/bin/rustica-engine + path: dist/usr/bin/rustica-engine diff --git a/.gitignore b/.gitignore index 2bdbbd3..88d6dd9 100644 --- a/.gitignore +++ b/.gitignore @@ -1,8 +1,6 @@ /.idea/ /.venv/ /build/ -/build-staging/ -/install/ /data/ /dist/ /.python-version diff --git a/Makefile b/Makefile index 81776a7..5dbb790 100644 --- a/Makefile +++ b/Makefile @@ -1,58 +1,104 @@ BUILD_DIR = $(shell pwd)/build DIST_DIR = $(shell pwd)/dist -DEV_INSTALL_DIR = $(shell pwd)/install DEV_DATA_DIR = $(shell pwd)/data -DEV_LLVM_DIR = /usr/lib/llvm18/lib/cmake/llvm +DEV_LLVM_DIR = /usr/lib/llvm18 # Default target: build for development .PHONY: build -build: $(DEV_INSTALL_DIR) +build: $(BUILD_DIR)/install -$(BUILD_DIR)/build.ninja: - uv run meson.py setup $(BUILD_DIR) --prefix=/ -Dllvm_dir=$(DEV_LLVM_DIR) +$(BUILD_DIR)/build/.stamp: + uv run meson.py setup $(BUILD_DIR)/build --prefix=/ -Dllvm_dir=$(DEV_LLVM_DIR) + touch $@ -$(DEV_INSTALL_DIR): $(BUILD_DIR)/build.ninja - uv run meson.py install -C $(BUILD_DIR) --destdir=$(DEV_INSTALL_DIR) +$(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_DATA_DIR) - $(DEV_INSTALL_DIR)/bin/postgres -D $(DEV_DATA_DIR) +run: $(DEV_DATA_DIR)/.stamp + $(BUILD_DIR)/install/bin/postgres -D $(DEV_DATA_DIR) -$(DEV_DATA_DIR): $(DEV_INSTALL_DIR) - $(DEV_INSTALL_DIR)/bin/initdb --auth=trust -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: - uv run meson.py setup $(BUILD_DIR) --prefix=/usr -Dembed_libs=true --buildtype=release - uv run meson.py install -C $(BUILD_DIR) --destdir=$(DIST_DIR) --skip-subprojects --tags standalone - strip $(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: - uv run meson.py setup $(BUILD_DIR) --prefix=/usr --buildtype=release - uv run meson.py install -C $(BUILD_DIR) --destdir=$(DIST_DIR) --skip-subprojects --tags extension - strip $(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) --prefix=/usr -Dllvm_dir=$(DEV_LLVM_DIR) --buildtype=release - uv run meson.py install -C $(BUILD_DIR) --destdir=$(DIST_DIR) --skip-subprojects + 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) $(shell dirname $(BUILD_DIR))/build-staging $(DEV_INSTALL_DIR) + rm -rf $(BUILD_DIR)/build $(BUILD_DIR)/install # Delete all build artifacts, development files, and distribution files .PHONY: distclean distclean: clean - rm -rf $(DIST_DIR) $(DEV_DATA_DIR) + rm -rf $(BUILD_DIR) $(DIST_DIR) $(DEV_DATA_DIR) diff --git a/meson.build b/meson.build index d92b434..8912f9c 100644 --- a/meson.build +++ b/meson.build @@ -7,6 +7,16 @@ project( 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']) @@ -24,8 +34,6 @@ if get_option('embed_libs') ) subproject('icu', default_options: ['default_library=static']) subproject('openssl', default_options: ['default_library=static']) - zlib = subproject('zlib', default_options: ['default_library=static']) - zlib_a = zlib.build('zlib') endif # Include PostgreSQL subproject @@ -80,7 +88,8 @@ postgres_pure_lib = static_library('postgres_lib', # Include WAMR subproject cc = meson.get_compiler('c') -wamr_c_flags = ['-Wno-incompatible-pointer-types'] +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'] @@ -101,32 +110,20 @@ wamr_var.add_cmake_defines({ 'WAMR_BUILD_EXCE_HANDLING': 1, 'WAMR_BUILD_JIT': 1, - 'DEPS_DIR': meson.project_source_root() / 'subprojects', '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('llvm_dir') != '' - wamr_var.add_cmake_defines({ - 'LLVM_DIR': get_option('llvm_dir'), - }) -elif get_option('embed_libs') - # Tell WAMR to link LLVM with our static zlib - wamr_defines = { - 'LLVM_ENABLE_ZLIB:STRING': 'FORCE_ON', - 'ZLIB_LIBRARY': zlib_a, - 'ZLIB_INCLUDE_DIR': zlib.get_variable('depinc').to_list()[0], - 'ZLIB_USE_STATIC_LIBS': 'ON', - 'LLVM_ENABLE_ZSTD:STRING': 'OFF', - } - # Build LLVM with the right zlib too - llvm_cmake_flags = [] - foreach k, v : wamr_defines - llvm_cmake_flags += ['-D' + k + '=' + v] - endforeach - wamr_var.add_cmake_defines(wamr_defines + { - 'LLVM_CMAKE_FLAGS': ' '.join(llvm_cmake_flags), - }) +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') diff --git a/meson.py b/meson.py index 063906c..eb48596 100755 --- a/meson.py +++ b/meson.py @@ -4,26 +4,21 @@ # SPDX-License-Identifier: Apache-2.0 OR MulanPSL-2.0 from __future__ import annotations -import copy import pathlib import re import sys import typing as T -from mesonbuild import mlog -from mesonbuild.interpreter import interpreter as ii -from mesonbuild.interpreter import interpreterobjects -from mesonbuild.interpreterbase import noKwargs, noPosargs, typed_pos_args, InterpreterObject +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 -from mesonbuild.utils.universal import Popen_safe if T.TYPE_CHECKING: from mesonbuild.modules import ModuleState from mesonbuild.interpreter import SubprojectHolder - from mesonbuild.interpreterbase import TYPE_kwargs, TYPE_var + from mesonbuild.interpreterbase import InterpreterObject, TYPE_kwargs, TYPE_var class CMakeSubproject(cmake.CMakeSubproject): @@ -64,62 +59,40 @@ def add_definitions(self, tline: CMakeTraceLine) -> None: self.definitions.extend(tline.args) -class SubprojectHolder(ii.SubprojectHolder): - @noKwargs - @typed_pos_args("subproject.build", str) - @InterpreterObject.method('build') - def build_method(self, args: T.List[TYPE_var], kwargs: TYPE_kwargs) -> str: - backend = copy.copy(self.held_object.backend) - for k, v in list(backend.__dict__.items()): - try: - backend.__dict__[k] = copy.copy(v) - except Exception: - pass - env = backend.environment - builddir = pathlib.Path(env.build_dir).with_name("build-staging") - env.build_dir = str(builddir) - (builddir / 'meson-private').mkdir(parents=True, exist_ok=True) - mlog.log( - "Building subproject", - mlog.bold(self.held_object.subproject), - "for target", - mlog.bold(args[0]), - "in", - mlog.bold(str(builddir)), - ) - env.dump_coredata() - backend.generate(False, None) - rv = backend.get_target_filename_abs( - self.held_object.variables[args[0]]._target_object - ) - target = pathlib.Path(rv).relative_to(builddir) - p, o, e = Popen_safe(['ninja', target], cwd=builddir) - if p.returncode != 0: - mlog.error("Subproject build failed:") - mlog.log('--- stdout ---') - mlog.log(o) - mlog.log('--- stderr ---') - mlog.log(e) - mlog.log('') - raise RuntimeError("Subproject build failed") - else: - mlog.log("Subproject build successful") - return rv - - -class IncludeDirsHolder(interpreterobjects.IncludeDirsHolder): +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 - @noPosargs - @InterpreterObject.method('to_list') - def to_list_method(self, args: T.List[TYPE_var], kwargs: TYPE_kwargs) -> T.List[str]: - curdir = pathlib.Path(self.held_object.curdir) - return [str((curdir / inc).resolve()) for inc in self.held_object.incdirs] + 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 - ii.SubprojectHolder = SubprojectHolder - interpreterobjects.IncludeDirsHolder = IncludeDirsHolder 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 index 9ebbb4f..7db9b86 100644 --- a/meson_options.txt +++ b/meson_options.txt @@ -10,3 +10,21 @@ option( 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/subprojects/.gitignore b/subprojects/.gitignore index 3b40d99..099ccf7 100644 --- a/subprojects/.gitignore +++ b/subprojects/.gitignore @@ -8,4 +8,3 @@ /openssl-*/ /llvm-project-*.src/ /zlib-*/ -/llvm/ 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/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/wamr/0003.patch b/subprojects/packagefiles/wamr/0003.patch deleted file mode 100644 index 9997070..0000000 --- a/subprojects/packagefiles/wamr/0003.patch +++ /dev/null @@ -1,110 +0,0 @@ -From 2bdde866b36ba0283b2120ab27e09339af69d7bc Mon Sep 17 00:00:00 2001 -From: Xenia Lu -Date: Fri, 3 Oct 2025 10:19:50 +0800 -Subject: [PATCH 3/4] build: fix LLVM 18 build on GCC 15 - -See also: referenced LLVM pull requests in patch files. ---- - build-scripts/build_llvm.py | 8 ++++- - ...01_Add_cstdint_to_SmallVector_101761.patch | 28 ++++++++++++++++ - ..._include_to_X86MCTargetDesc.h_123320.patch | 32 +++++++++++++++++++ - 3 files changed, 67 insertions(+), 1 deletion(-) - create mode 100644 build-scripts/llvm-patches/0001_Add_cstdint_to_SmallVector_101761.patch - create mode 100644 build-scripts/llvm-patches/0002_Add_missing_include_to_X86MCTargetDesc.h_123320.patch - -diff --git a/build-scripts/build_llvm.py b/build-scripts/build_llvm.py -index 3d241355..94e216ce 100755 ---- a/build-scripts/build_llvm.py -+++ b/build-scripts/build_llvm.py -@@ -23,9 +23,15 @@ def clone_llvm(dst_dir, llvm_repo, llvm_branch): - - if not llvm_dir.exists(): - GIT_CLONE_CMD = f"git clone --depth 1 --branch {llvm_branch} {llvm_repo} llvm" -- print(GIT_CLONE_CMD) -+ print(f"cd {dst_dir} && {GIT_CLONE_CMD}") - subprocess.check_output(shlex.split(GIT_CLONE_CMD), cwd=dst_dir) - -+ patch_dir = pathlib.Path(__file__).parent.joinpath("llvm-patches").resolve() -+ for patch_file in patch_dir.glob("*.patch"): -+ cmd = f"git apply {patch_file}" -+ print(f"cd {llvm_dir} && {cmd}") -+ subprocess.check_output(shlex.split(cmd), cwd=llvm_dir) -+ - return llvm_dir - - -diff --git a/build-scripts/llvm-patches/0001_Add_cstdint_to_SmallVector_101761.patch b/build-scripts/llvm-patches/0001_Add_cstdint_to_SmallVector_101761.patch -new file mode 100644 -index 00000000..c7ed0e16 ---- /dev/null -+++ b/build-scripts/llvm-patches/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/build-scripts/llvm-patches/0002_Add_missing_include_to_X86MCTargetDesc.h_123320.patch b/build-scripts/llvm-patches/0002_Add_missing_include_to_X86MCTargetDesc.h_123320.patch -new file mode 100644 -index 00000000..29c640cd ---- /dev/null -+++ b/build-scripts/llvm-patches/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 -+ --- -2.51.0 - diff --git a/subprojects/packagefiles/wamr/0005.patch b/subprojects/packagefiles/wamr/0005.patch deleted file mode 100644 index 86b9f5e..0000000 --- a/subprojects/packagefiles/wamr/0005.patch +++ /dev/null @@ -1,40 +0,0 @@ -From 89ea88ff5754666322ae79b52abc83b9d9592dff Mon Sep 17 00:00:00 2001 -From: Xenia Lu -Date: Wed, 8 Oct 2025 10:48:59 +0800 -Subject: [PATCH 1/1] Build LLVM during setup - ---- - build-scripts/config_common.cmake | 10 +++++++++- - 1 file changed, 9 insertions(+), 1 deletion(-) - -diff --git a/build-scripts/config_common.cmake b/build-scripts/config_common.cmake -index 8cdce4a0..e86ec257 100644 ---- a/build-scripts/config_common.cmake -+++ b/build-scripts/config_common.cmake -@@ -103,7 +103,23 @@ if (WAMR_BUILD_JIT EQUAL 1) - set (LLVM_SRC_ROOT "${WAMR_ROOT_DIR}/core/deps/llvm") - set (LLVM_BUILD_ROOT "${LLVM_SRC_ROOT}/build") - if (NOT EXISTS "${LLVM_BUILD_ROOT}") -- message (FATAL_ERROR "Cannot find LLVM dir: ${LLVM_BUILD_ROOT}") -+ message(STATUS "LLVM build directory not found, attempting to build LLVM...") -+ if (DEFINED LLVM_CMAKE_FLAGS) -+ execute_process( -+ COMMAND python3 ${WAMR_ROOT_DIR}/build-scripts/build_llvm.py --extra-cmake-flags ${LLVM_CMAKE_FLAGS} -+ WORKING_DIRECTORY ${WAMR_ROOT_DIR} -+ RESULT_VARIABLE result -+ ) -+ else() -+ execute_process( -+ COMMAND python3 ${WAMR_ROOT_DIR}/build-scripts/build_llvm.py -+ WORKING_DIRECTORY ${WAMR_ROOT_DIR} -+ RESULT_VARIABLE result -+ ) -+ endif() -+ if (NOT result EQUAL 0) -+ message(FATAL_ERROR "Failed to build LLVM") -+ endif() - endif () - set (CMAKE_PREFIX_PATH "${LLVM_BUILD_ROOT};${CMAKE_PREFIX_PATH}") - set (LLVM_DIR ${LLVM_BUILD_ROOT}/lib/cmake/llvm) --- -2.51.0 diff --git a/subprojects/packagefiles/wamr/0006.patch b/subprojects/packagefiles/wamr/0006.patch deleted file mode 100644 index 1cadc85..0000000 --- a/subprojects/packagefiles/wamr/0006.patch +++ /dev/null @@ -1,55 +0,0 @@ -diff -ru wasm-micro-runtime-WAMR-2.4.2.orig/build-scripts/build_llvm.py wasm-micro-runtime-WAMR-2.4.2/build-scripts/build_llvm.py ---- wasm-micro-runtime-WAMR-2.4.2.orig/build-scripts/build_llvm.py 2025-10-11 12:28:16.653222239 +0800 -+++ wasm-micro-runtime-WAMR-2.4.2/build-scripts/build_llvm.py 2025-10-11 12:28:48.276741632 +0800 -@@ -236,6 +236,11 @@ - def main(): - parser = argparse.ArgumentParser(description="build necessary LLVM libraries") - parser.add_argument( -+ "--deps-dir", -+ type=str, -+ default="", -+ ) -+ parser.add_argument( - "--platform", - type=str, - choices=["android", "arc", "darwin", "linux", "windows", "xtensa"], -@@ -319,8 +324,11 @@ - if current_file.is_symlink(): - current_file = pathlib.Path(os.readlink(current_file)) - -- current_dir = current_file.parent.resolve() -- deps_dir = current_dir.joinpath("../core/deps").resolve() -+ if options.deps_dir: -+ deps_dir = pathlib.Path(options.deps_dir) -+ else: -+ current_dir = current_file.parent.resolve() -+ deps_dir = current_dir.joinpath("../core/deps").resolve() - - try: - llvm_info = llvm_repo_and_branch.get(platform, llvm_repo_and_branch["default"]) -diff -ru wasm-micro-runtime-WAMR-2.4.2.orig/build-scripts/config_common.cmake wasm-micro-runtime-WAMR-2.4.2/build-scripts/config_common.cmake ---- wasm-micro-runtime-WAMR-2.4.2.orig/build-scripts/config_common.cmake 2025-10-11 12:28:16.656555593 +0800 -+++ wasm-micro-runtime-WAMR-2.4.2/build-scripts/config_common.cmake 2025-10-11 12:29:31.690330374 +0800 -@@ -100,19 +100,19 @@ - set (WAMR_BUILD_LAZY_JIT 1) - endif () - if (NOT DEFINED LLVM_DIR) -- set (LLVM_SRC_ROOT "${WAMR_ROOT_DIR}/core/deps/llvm") -+ set (LLVM_SRC_ROOT "${DEPS_DIR}/llvm") - set (LLVM_BUILD_ROOT "${LLVM_SRC_ROOT}/build") - if (NOT EXISTS "${LLVM_BUILD_ROOT}") - message(STATUS "LLVM build directory not found, attempting to build LLVM...") - if (DEFINED LLVM_CMAKE_FLAGS) - execute_process( -- COMMAND python3 ${WAMR_ROOT_DIR}/build-scripts/build_llvm.py --extra-cmake-flags ${LLVM_CMAKE_FLAGS} -+ COMMAND python3 ${WAMR_ROOT_DIR}/build-scripts/build_llvm.py --deps-dir ${DEPS_DIR} --extra-cmake-flags ${LLVM_CMAKE_FLAGS} - WORKING_DIRECTORY ${WAMR_ROOT_DIR} - RESULT_VARIABLE result - ) - else() - execute_process( -- COMMAND python3 ${WAMR_ROOT_DIR}/build-scripts/build_llvm.py -+ COMMAND python3 ${WAMR_ROOT_DIR}/build-scripts/build_llvm.py --deps-dir ${DEPS_DIR} - WORKING_DIRECTORY ${WAMR_ROOT_DIR} - RESULT_VARIABLE result - ) diff --git a/subprojects/wamr.wrap b/subprojects/wamr.wrap index 831022c..3ceccd5 100644 --- a/subprojects/wamr.wrap +++ b/subprojects/wamr.wrap @@ -3,4 +3,5 @@ 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/0003.patch, wamr/0004.patch, wamr/0005.patch, wamr/0006.patch +diff_files = wamr/0001.patch, wamr/0002.patch, wamr/0004.patch +method = cmake From e6e6e2f62613f23a91230a213cffa5b761ef8aa8 Mon Sep 17 00:00:00 2001 From: Xenia Lu Date: Sun, 12 Oct 2025 22:10:54 +0800 Subject: [PATCH 21/21] dep: fix include uuid/uuid.h --- meson.build | 134 ++++++++++++++++- .../packagefiles/util-linux/uuid_h.patch | 135 ++++++++++++++++++ subprojects/util-linux.wrap | 2 +- 3 files changed, 268 insertions(+), 3 deletions(-) create mode 100644 subprojects/packagefiles/util-linux/uuid_h.patch diff --git a/meson.build b/meson.build index 8912f9c..a5effeb 100644 --- a/meson.build +++ b/meson.build @@ -24,12 +24,142 @@ if get_option('embed_libs') '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', - 'cryptsetup=disabled', - 'build-plymouth-support=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']) 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/subprojects/util-linux.wrap b/subprojects/util-linux.wrap index b66c4f7..7f9a7b1 100644 --- a/subprojects/util-linux.wrap +++ b/subprojects/util-linux.wrap @@ -3,7 +3,7 @@ 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 +diff_files = util-linux/3761.patch, util-linux/uuid_h.patch [provide] uuid = uuid_dep