From 8414697ed3ba854a3a0b0d44954cd4836f796fd3 Mon Sep 17 00:00:00 2001 From: Tobiasz Laskowski Date: Tue, 3 Mar 2026 00:46:44 +0000 Subject: [PATCH 1/9] [ci] Add check to preserve 1.15 abi compat --- .github/workflows/build.yml | 26 ++++++++++++++++++++++++-- 1 file changed, 24 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 468a5a7bf..f09796abe 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -423,12 +423,34 @@ jobs: -DANDROID_PLATFORM=24 -DANDROID_ABI=arm64-v8a -DBUILD_SHARED_LIBS=OFF -DWITH_VM=OFF cmake --build build + check-abi: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v6 + name: Checkout current + - uses: actions/checkout@v6 + name: Checkout 1.15 + with: + path: hashlink_1.15 + ref: 1.15 + - run: | + sudo apt-get update + sudo apt-get install abigail-tools + name: Setup abi tools + - run: | + make DEBUG=1 -j8 libhl.so + name: Build current + - run: | + make -C hashlink_1.15 DEBUG=1 -j8 libhl + name: Build 1.15 + - run: | + abidiff hashlink_1.15/libhl.so libhl.so --no-added-syms + ########################################################### publish-latest-release: ########################################################### runs-on: ubuntu-latest - needs: - - build + needs: [build, check-abi] if: github.ref == 'refs/heads/master' concurrency: publish-latest-release # https://docs.github.com/en/actions/reference/workflow-syntax-for-github-actions#jobsjob_idconcurrency From 3efa9155be89245e2aaf4611720f905a89f156c2 Mon Sep 17 00:00:00 2001 From: Tobiasz Laskowski Date: Tue, 3 Mar 2026 00:54:23 +0000 Subject: [PATCH 2/9] Restore setup functions for abi compat This was broken in: 043fc84db5259885325d0d431bc2481ecad9ed58 e33d5f10d612a2726820c2344ed68964b6b5e368 --- src/hl.h | 11 ++++++++++- src/hlc_main.c | 2 +- src/main.c | 2 +- src/std/error.c | 15 +++++++++++++++ src/std/fun.c | 14 ++++++++++++++ src/std/sys.c | 37 ++++++++++++++++++++++++++++++++++++- 6 files changed, 77 insertions(+), 4 deletions(-) diff --git a/src/hl.h b/src/hl.h index 2da71da81..f5be95ebd 100644 --- a/src/hl.h +++ b/src/hl.h @@ -630,7 +630,7 @@ typedef struct { } hl_setup_t; HL_API hl_setup_t hl_setup; -HL_API void hl_sys_init(); +HL_API void hl_sys_init( void **args, int nargs, void *hlfile ); HL_API double hl_nan( void ); HL_API bool hl_is_dynamic( hl_type *t ); @@ -1020,6 +1020,15 @@ HL_API hl_track_info hl_track; #endif +// -------------- COMPAT ------------------------------------ + +HL_API void hl_setup_longjump( void *j ); +HL_API void hl_setup_exception( void *resolve_symbol, void *capture_stack ); +HL_API void hl_set_debug_mode( bool b ); +HL_API void hl_setup_callbacks(void* sc, void* gw); +HL_API void hl_setup_callbacks2(void* sc, void* gw, int flags); +HL_API void hl_setup_reload_check( void *freload, void *param ); + C_FUNCTION_END #endif diff --git a/src/hlc_main.c b/src/hlc_main.c index e69a39a83..21cc5948e 100644 --- a/src/hlc_main.c +++ b/src/hlc_main.c @@ -160,7 +160,7 @@ int main(int argc, char *argv[]) { hl_setup.get_wrapper = hlc_get_wrapper; hl_setup.sys_args = (pchar**)(argv + 1); hl_setup.sys_nargs = argc - 1; - hl_sys_init(); + hl_sys_init(NULL, 0, NULL); tf.ret = &hlt_void; clt.kind = HFUN; clt.fun = &tf; diff --git a/src/main.c b/src/main.c index a25b673cc..8c00041ab 100644 --- a/src/main.c +++ b/src/main.c @@ -272,7 +272,7 @@ int main(int argc, pchar *argv[]) { hl_setup.file_path = file; hl_setup.sys_args = (pchar**)argv; hl_setup.sys_nargs = argc; - hl_sys_init(); + hl_sys_init(NULL, 0, NULL); hl_register_thread(&ctx); main_ctx = &ctx; ctx.file = file; diff --git a/src/std/error.c b/src/std/error.c index 8849cf2ab..e27100396 100644 --- a/src/std/error.c +++ b/src/std/error.c @@ -52,12 +52,27 @@ HL_PRIM uchar *hl_resolve_symbol( void *addr, uchar *out, int *outSize ) { return hl_setup.resolve_symbol(addr, out, outSize); } +static void (*throw_jump)( jmp_buf, int ) = NULL; + +HL_PRIM void hl_setup_longjump( void *j ) { + throw_jump = j; +} + +HL_PRIM void hl_setup_exception( void *resolve_symbol, void *capture_stack ) { + hl_setup.resolve_symbol = resolve_symbol; + hl_setup.capture_stack = capture_stack; +} + HL_PRIM void hl_set_error_handler( vclosure *d ) { hl_thread_info *t = hl_get_thread(); t->trap_uncaught = t->trap_current; t->exc_handler = d; } +HL_PRIM void hl_set_debug_mode( bool b ) { + hl_setup.is_debugger_enabled = b; +} + static bool break_on_trap( hl_thread_info *t, hl_trap_ctx *trap, vdynamic *v ) { bool unwrapped = false; vdynamic *vvalue = NULL; diff --git a/src/std/fun.c b/src/std/fun.c index fafa8177e..4ec5ad22e 100644 --- a/src/std/fun.c +++ b/src/std/fun.c @@ -113,6 +113,20 @@ HL_PRIM bool hl_fun_compare( vdynamic *a, vdynamic *b ) { // ------------ DYNAMIC CALLS +typedef void *(*fptr_static_call)(void *fun, hl_type *t, void **args, vdynamic *out); +typedef void *(*fptr_get_wrapper)(hl_type *t); + +HL_PRIM void hl_setup_callbacks2( void *c, void *w, int flags ) { + hl_setup.static_call = (fptr_static_call)c; + hl_setup.get_wrapper = (fptr_get_wrapper)w; + hl_setup.static_call_ref = flags & 1; +} + +HL_PRIM void hl_setup_callbacks( void *c, void *w ) { + hl_setup.static_call = (fptr_static_call)c; + hl_setup.get_wrapper = (fptr_get_wrapper)w; +} + #define HL_MAX_ARGS 9 HL_PRIM vdynamic* hl_call_method( vdynamic *c, varray *args ) { diff --git a/src/std/sys.c b/src/std/sys.c index 7cfeb0d7d..a3d285eb5 100644 --- a/src/std/sys.c +++ b/src/std/sys.c @@ -159,6 +159,11 @@ HL_PRIM void hl_sys_print( vbyte *msg ) { hl_blocking(false); } +HL_PRIM void hl_setup_profiler( void *profile_event, void *before_exit ) { + hl_setup.before_exit = before_exit; + hl_setup.profile_event = profile_event; +} + HL_PRIM void hl_sys_profile_event( int code, vbyte *data, int dataLen ) { if( hl_setup.profile_event ) hl_setup.profile_event(code, data, dataLen); } @@ -168,6 +173,18 @@ HL_PRIM void hl_sys_exit( int code ) { exit(code); } +static void *f_vtune_init = NULL; +static void *g_vtune_module = NULL; +static void setup_vtune_wrapper() { + ((void(*)(void*))f_vtune_init)(g_vtune_module); +} + +HL_PRIM void hl_setup_vtune( void *vtune_init, void *m ) { + f_vtune_init = vtune_init; + g_vtune_module = m; + hl_setup.vtune_init = setup_vtune_wrapper; +} + HL_PRIM void hl_sys_vtune_init() { if( hl_setup.vtune_init ) hl_setup.vtune_init(); } @@ -674,10 +691,16 @@ HL_PRIM varray *hl_sys_args() { return a; } -HL_PRIM void hl_sys_init() { +HL_PRIM void hl_sys_init(void **args, int nargs, void *hlfile) { #ifdef HL_WIN QueryPerformanceFrequency(&qpcFrequency); #endif + if (hlfile) + hl_setup.file_path = (pchar*)hlfile; + if (args) + hl_setup.sys_args = (pchar**)args; + if (nargs) + hl_setup.sys_nargs = nargs; # ifdef HL_WIN_DESKTOP setlocale(LC_CTYPE, ""); // printf to current locale # endif @@ -687,6 +710,18 @@ HL_PRIM vbyte *hl_sys_hl_file() { return (vbyte*)hl_setup.file_path; } +static void *compat_reload_fun = NULL; +static void *compat_reload_param = NULL; +static bool reload_wrapper() { + return ((bool(*)(void*))compat_reload_fun)(compat_reload_param); +} + +HL_PRIM void hl_setup_reload_check( void *freload, void *param ) { + compat_reload_fun = freload; + compat_reload_param = param; + hl_setup.reload_check = reload_wrapper; +} + HL_PRIM bool hl_sys_check_reload( vbyte *debug_alt_file ) { return hl_setup.reload_check != NULL && hl_setup.reload_check(debug_alt_file); } From f341f90bce02af55a10ad0ffd7baf79b1c45c593 Mon Sep 17 00:00:00 2001 From: Tobiasz Laskowski Date: Tue, 3 Mar 2026 00:55:14 +0000 Subject: [PATCH 3/9] Add missing HL_PRIM to hl_sys_special Without this, the symbol may be hidden with some compilers and therefore cannot be loaded. --- src/std/sys.c | 2 +- src/std/sys_android.c | 4 ++-- src/std/sys_ios.m | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/std/sys.c b/src/std/sys.c index a3d285eb5..e8217e91b 100644 --- a/src/std/sys.c +++ b/src/std/sys.c @@ -731,7 +731,7 @@ HL_PRIM bool hl_sys_has_debugger() { } #ifndef HL_MOBILE -const char *hl_sys_special( const char *key ) { +HL_PRIM const char *hl_sys_special( const char *key ) { hl_error("Unknown sys_special key"); return NULL; } diff --git a/src/std/sys_android.c b/src/std/sys_android.c index df9519539..469685793 100644 --- a/src/std/sys_android.c +++ b/src/std/sys_android.c @@ -227,7 +227,7 @@ static const char* hl_sys_android_get_internal_storage_path(void) return hl_android_internal_files_path; } -const char *hl_sys_special( const char *key ) { +HL_PRIM const char *hl_sys_special( const char *key ) { if (strcmp(key, "android_external_storage_path")==0) return hl_sys_android_get_external_storage_path(); else if (strcmp(key, "android_internal_storage_path")==0) @@ -239,4 +239,4 @@ const char *hl_sys_special( const char *key ) { DEFINE_PRIM(_BYTES, sys_special, _BYTES); -#endif \ No newline at end of file +#endif diff --git a/src/std/sys_ios.m b/src/std/sys_ios.m index 602d0453e..7cae88686 100644 --- a/src/std/sys_ios.m +++ b/src/std/sys_ios.m @@ -54,7 +54,7 @@ static int ios_get_retina_scale_factor() return [[UIScreen mainScreen] scale]; } -const char *hl_sys_special( const char *key ) { +HL_PRIM const char *hl_sys_special( const char *key ) { if (strcmp(key, "ios_resource_path")==0) return ios_get_resource_path(); else if (strcmp(key, "ios_document_path")==0) From 394211ed76ad08dea99eb165a9344d9c7434e811 Mon Sep 17 00:00:00 2001 From: Tobiasz Laskowski Date: Tue, 3 Mar 2026 00:58:13 +0000 Subject: [PATCH 4/9] Avoid error about accidental exports in 1.15 These were never meant to be part of the public api, but were exported by mistake due to default symbol visibility. --- .github/workflows/build.yml | 2 +- other/abidiff.suppr | 13 +++++++++++++ 2 files changed, 14 insertions(+), 1 deletion(-) create mode 100644 other/abidiff.suppr diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index f09796abe..b19d8ec3c 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -444,7 +444,7 @@ jobs: make -C hashlink_1.15 DEBUG=1 -j8 libhl name: Build 1.15 - run: | - abidiff hashlink_1.15/libhl.so libhl.so --no-added-syms + abidiff hashlink_1.15/libhl.so libhl.so --no-added-syms --suppr other/abidiff.suppr ########################################################### publish-latest-release: diff --git a/other/abidiff.suppr b/other/abidiff.suppr new file mode 100644 index 000000000..fda524546 --- /dev/null +++ b/other/abidiff.suppr @@ -0,0 +1,13 @@ +# pcre2 was accidentally exported by libhl.so +[suppress_function] + symbol_name_regexp = ^_?pcre2_ + drop = yes + +[suppress_variable] + symbol_name_regexp = ^_?pcre2_ + drop = yes + +# accidentally exported, but never part of hl.h +[suppress_function] + symbol_name_regexp = hl_(cache_init|internal_capture_stack|mlookup_alloc|mlookup_find|mlookup_set_impl) + drop = yes From 94dc9eb6cee79c36fe1c95f1c1203fb7f45bd520 Mon Sep 17 00:00:00 2001 From: Tobiasz Laskowski Date: Tue, 3 Mar 2026 14:25:15 +0000 Subject: [PATCH 5/9] Ignore check for hl_closure_stack_capture symbol This was never part of hl.h, so its removal is safe. --- other/abidiff.suppr | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/other/abidiff.suppr b/other/abidiff.suppr index fda524546..528926983 100644 --- a/other/abidiff.suppr +++ b/other/abidiff.suppr @@ -11,3 +11,8 @@ [suppress_function] symbol_name_regexp = hl_(cache_init|internal_capture_stack|mlookup_alloc|mlookup_find|mlookup_set_impl) drop = yes + +# exported explicitly, but never part of hl.h +[suppress_variable] + symbol_name_regexp = hl_closure_stack_capture + drop = yes From 0499037a078243f2916253a2e0212eb7f59b484c Mon Sep 17 00:00:00 2001 From: Tobiasz Laskowski Date: Tue, 3 Mar 2026 10:03:12 +0000 Subject: [PATCH 6/9] Ignore gc_get_mark_threads missing from abi This was also never exposed in a header, and not exported explicitly --- other/abidiff.suppr | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/other/abidiff.suppr b/other/abidiff.suppr index 528926983..0013ee27d 100644 --- a/other/abidiff.suppr +++ b/other/abidiff.suppr @@ -12,6 +12,10 @@ symbol_name_regexp = hl_(cache_init|internal_capture_stack|mlookup_alloc|mlookup_find|mlookup_set_impl) drop = yes +[suppress_function] + symbol_name_regexp = gc_get_mark_threads + drop = yes + # exported explicitly, but never part of hl.h [suppress_variable] symbol_name_regexp = hl_closure_stack_capture From 3b5d4b4f186454390d2c0363d9d22a3b9c823d1a Mon Sep 17 00:00:00 2001 From: Tobiasz Laskowski Date: Tue, 3 Mar 2026 10:55:48 +0000 Subject: [PATCH 7/9] Fix false positive abi change for HLAST enum value The purpose of this value is to change, so it does not consistitute an ABI breakage. Based on: https://developers.redhat.com/articles/2025/02/04/how-analyze-changes-enum-types-using-abidiff#detecting_and_categorizing_enum_changes --- other/abidiff.suppr | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/other/abidiff.suppr b/other/abidiff.suppr index 0013ee27d..8bcf24fe3 100644 --- a/other/abidiff.suppr +++ b/other/abidiff.suppr @@ -1,3 +1,8 @@ +[suppress_type] + type_kind = enum + name = hl_type_kind + changed_enumerators = HLAST + # pcre2 was accidentally exported by libhl.so [suppress_function] symbol_name_regexp = ^_?pcre2_ From 887c316401d42b37865d740707d38299e5da9f84 Mon Sep 17 00:00:00 2001 From: Tobiasz Laskowski Date: Tue, 3 Mar 2026 11:51:44 +0000 Subject: [PATCH 8/9] [ci] Use header files to filter abi type changes This way we do not see errors related to opaque pointers, which are opaque so that it is safe to change them. --- .github/workflows/build.yml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index b19d8ec3c..be98f5d3a 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -444,7 +444,10 @@ jobs: make -C hashlink_1.15 DEBUG=1 -j8 libhl name: Build 1.15 - run: | - abidiff hashlink_1.15/libhl.so libhl.so --no-added-syms --suppr other/abidiff.suppr + (cd hashlink_1.15 && abidw --header-file src/hl.h libhl.so > libhl.abi) + abidw --header-file src/hl.h libhl.so > libhl.abi + + abidiff hashlink_1.15/libhl.abi libhl.abi --no-added-syms --suppr other/abidiff.suppr ########################################################### publish-latest-release: From 44c49c52eaa03018244d678d718bdb4e70c66a51 Mon Sep 17 00:00:00 2001 From: Tobiasz Laskowski Date: Tue, 3 Mar 2026 14:13:29 +0000 Subject: [PATCH 9/9] Ignore pcre16_* symbols in abidiff suppression This is what the symbols were in 1.13 and older --- other/abidiff.suppr | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/other/abidiff.suppr b/other/abidiff.suppr index 8bcf24fe3..882dc60a9 100644 --- a/other/abidiff.suppr +++ b/other/abidiff.suppr @@ -5,11 +5,11 @@ # pcre2 was accidentally exported by libhl.so [suppress_function] - symbol_name_regexp = ^_?pcre2_ + symbol_name_regexp = ^_?pcre(2|16)_ drop = yes [suppress_variable] - symbol_name_regexp = ^_?pcre2_ + symbol_name_regexp = ^_?pcre(2|16)_ drop = yes # accidentally exported, but never part of hl.h