From 6ce438420ae4db1a3eb178a9f1b5e45a9b1cce60 Mon Sep 17 00:00:00 2001 From: Sam Clegg Date: Sun, 19 Mar 2023 12:42:53 -0700 Subject: [PATCH] Fix libpng and libfreetype port with wasm exceptions are enabled Sadly, even though libpng can be compiled with setjmp/longjmp support some libraries such as openjpeg assume that setjmp support is included. Fixes: #19001 --- test/common.py | 25 +++++++++++++++++++++++++ test/test_core.py | 26 +------------------------- test/test_other.py | 3 ++- tools/ports/freetype.py | 16 ++++++++++++++-- tools/ports/libpng.py | 15 +++++++++++++-- 5 files changed, 55 insertions(+), 30 deletions(-) diff --git a/test/common.py b/test/common.py index c5b258e0298f9..ae1564a6aa0b0 100644 --- a/test/common.py +++ b/test/common.py @@ -294,6 +294,31 @@ def metafunc(self, with_bigint): return metafunc +# This works just like `with_both_eh_sjlj` above but doesn't enable exceptions. +# Use this for tests that use setjmp/longjmp but not exceptions handling. +def with_both_sjlj(f): + assert callable(f) + + def metafunc(self, is_native): + if is_native: + # Wasm SjLj is currently supported only in wasm backend and V8 + if not self.is_wasm(): + self.skipTest('wasm2js does not support wasm SjLj') + self.require_wasm_eh() + # FIXME Temporarily disabled. Enable this later when the bug is fixed. + if '-fsanitize=address' in self.emcc_args: + self.skipTest('Wasm EH does not work with asan yet') + self.set_setting('SUPPORT_LONGJMP', 'wasm') + f(self) + else: + self.set_setting('SUPPORT_LONGJMP', 'emscripten') + f(self) + + metafunc._parameterize = {'': (False,), + 'wasm_sjlj': (True,)} + return metafunc + + def ensure_dir(dirname): dirname = Path(dirname) dirname.mkdir(parents=True, exist_ok=True) diff --git a/test/test_core.py b/test/test_core.py index 35d2019740868..e51021e5619d3 100644 --- a/test/test_core.py +++ b/test/test_core.py @@ -28,6 +28,7 @@ from common import skip_if, needs_dylink, no_windows, no_mac, is_slow_test, parameterized from common import env_modify, with_env_modify, disabled, node_pthreads, also_with_wasm_bigint from common import read_file, read_binary, requires_v8, requires_node, compiler_for, crossplatform +from common import with_both_sjlj from common import NON_ZERO, WEBIDL_BINDER, EMBUILDER, PYTHON import clang_native @@ -124,31 +125,6 @@ def metafunc(self, is_native): return metafunc -# This works just like `with_both_eh_sjlj` above but doesn't enable exceptions. -# Use this for tests that use setjmp/longjmp but not exceptions handling. -def with_both_sjlj(f): - assert callable(f) - - def metafunc(self, is_native): - if is_native: - # Wasm SjLj is currently supported only in wasm backend and V8 - if not self.is_wasm(): - self.skipTest('wasm2js does not support wasm SjLj') - self.require_wasm_eh() - # FIXME Temporarily disabled. Enable this later when the bug is fixed. - if '-fsanitize=address' in self.emcc_args: - self.skipTest('Wasm EH does not work with asan yet') - self.set_setting('SUPPORT_LONGJMP', 'wasm') - f(self) - else: - self.set_setting('SUPPORT_LONGJMP', 'emscripten') - f(self) - - metafunc._parameterize = {'': (False,), - 'wasm': (True,)} - return metafunc - - def no_wasm2js(note=''): assert not callable(note) diff --git a/test/test_other.py b/test/test_other.py index 59db4ace7ee19..0f9d748aff5a1 100644 --- a/test/test_other.py +++ b/test/test_other.py @@ -33,7 +33,7 @@ from common import env_modify, no_mac, no_windows, requires_native_clang, with_env_modify from common import create_file, parameterized, NON_ZERO, node_pthreads, TEST_ROOT, test_file from common import compiler_for, EMBUILDER, requires_v8, requires_node, requires_wasm64 -from common import requires_wasm_eh, crossplatform +from common import requires_wasm_eh, crossplatform, with_both_sjlj from common import also_with_minimal_runtime, also_with_wasm_bigint, EMTEST_BUILD_VERBOSE, PYTHON from tools import shared, building, utils, deps_info, response_file, cache from tools.utils import read_file, write_file, delete_file, read_binary @@ -2205,6 +2205,7 @@ def test_bzip2(self): self.do_runf(test_file('bzip2_test.c'), 'usage: unzcrash filename', emcc_args=['-sUSE_BZIP2', '-Wno-pointer-sign']) + @with_both_sjlj def test_freetype(self): # copy the Liberation Sans Bold truetype file located in the # /test/freetype to the compilation folder diff --git a/tools/ports/freetype.py b/tools/ports/freetype.py index c7fe77e92b598..83ef166a91cd7 100644 --- a/tools/ports/freetype.py +++ b/tools/ports/freetype.py @@ -8,11 +8,20 @@ TAG = 'version_1' HASH = '0d0b1280ba0501ad0a23cf1daa1f86821c722218b59432734d3087a89acd22aabd5c3e5e1269700dcd41e87073046e906060f167c032eb91a3ac8c5808a02783' +variants = {'freetype-wasm-sjlj': {'SUPPORT_LONGJMP': 'wasm'}} + def needed(settings): return settings.USE_FREETYPE +def get_lib_name(settings): + if settings.SUPPORT_LONGJMP == 'wasm': + return 'libfreetype-wasm-sjlj.a' + else: + return 'libfreetype.a' + + def get(ports, settings, shared): ports.fetch_project('freetype', f'https://github.com/emscripten-ports/FreeType/archive/{TAG}.zip', sha512hash=HASH) @@ -90,13 +99,16 @@ def create(final): '-pthread' ] + if settings.SUPPORT_LONGJMP == 'wasm': + flags.append('-sSUPPORT_LONGJMP=wasm') + ports.build_port(source_path, final, 'freetype', flags=flags, srcs=srcs) - return [shared.cache.get_lib('libfreetype.a', create, what='port')] + return [shared.cache.get_lib(get_lib_name(settings), create, what='port')] def clear(ports, settings, shared): - shared.cache.erase_lib('libfreetype.a') + shared.cache.erase_lib(get_lib_name(settings)) def process_args(ports): diff --git a/tools/ports/libpng.py b/tools/ports/libpng.py index 1e9c91b3670a6..19d30d1805666 100644 --- a/tools/ports/libpng.py +++ b/tools/ports/libpng.py @@ -10,7 +10,11 @@ HASH = '2ce2b855af307ca92a6e053f521f5d262c36eb836b4810cb53c809aa3ea2dcc08f834aee0ffd66137768a54397e28e92804534a74abb6fc9f6f3127f14c9c338' deps = ['zlib'] -variants = {'libpng-mt': {'PTHREADS': 1}} +variants = { + 'libpng-mt': {'PTHREADS': 1}, + 'libpng-wasm-sjlj': {'SUPPORT_LONGJMP': 'wasm'}, + 'libpng-mt-wasm-sjlj': {'PTHREADS': 1, 'SUPPORT_LONGJMP': 'wasm'}, +} def needed(settings): @@ -18,7 +22,12 @@ def needed(settings): def get_lib_name(settings): - return 'libpng' + ('-mt' if settings.PTHREADS else '') + '.a' + suffix = '' + if settings.PTHREADS: + suffix += '-mt' + if settings.SUPPORT_LONGJMP == 'wasm': + suffix += '-wasm-sjlj' + return f'libpng{suffix}.a' def get(ports, settings, shared): @@ -35,6 +44,8 @@ def create(final): flags = ['-sUSE_ZLIB'] if settings.PTHREADS: flags += ['-pthread'] + if settings.SUPPORT_LONGJMP == 'wasm': + flags.append('-sSUPPORT_LONGJMP=wasm') ports.build_port(source_path, final, 'libpng', flags=flags, exclude_files=['pngtest'], exclude_dirs=['scripts', 'contrib'])