#!/usr/bin/make -f

include /usr/share/dpkg/pkg-info.mk

# resolve if release is experimental
EXP_RELEASE = $(filter experimental% UNRELEASED,$(DEB_DISTRIBUTION))

DEB_VERSION_UPSTREAM_ORIG = $(firstword $(subst ~,$() ,$(DEB_VERSION_UPSTREAM)))

ifneq (,$(filter parallel=%,$(DEB_BUILD_OPTIONS)))
NUMJOBS = $(patsubst parallel=%,%,$(filter parallel=%,$(DEB_BUILD_OPTIONS)))
export EMCC_CORES=$(NUMJOBS)
endif

EM_OPTS = PATH="$(CURDIR):$$PATH" EM_CACHE="$(CURDIR)/debian/em_cache"
EMCC = $(EM_OPTS) emcc
TESTS_RUNNER = $(EM_OPTS) EMTEST_SKIP_SLOW=1 tests/runner.py
# use ccache when available
ifneq (,$(wildcard /usr/bin/ccache))
override_dh_auto_test: export EM_COMPILER_WRAPPER=ccache
endif

# files generated during build
SOURCE_MAP_MIN_JS = src/emscripten-source-map.min.js
NEON_H = system/include/neon/arm_neon.h

#  * test_poppler reauires tests.poppler.paper.pdf
ERRORS_wasm += \
 test_freetype \
 test_lua \
 test_poppler

ERRORS_other += \
 test_minimal_dynamic

# requires closure-compiler
ERRORS_other += \
 test_stdin
FAILS_CERTAIN_other += \
 test_EM_ASM_ES6_closure \
 test_EM_ASM_ES6_closure_O3 \
 test_IGNORE_CLOSURE_COMPILER_ERRORS \
 test_INCOMING_MODULE_JS_API \
 test_binaryen_debug \
 test_closure_externs \
 test_closure_full_js_library \
 test_closure_warnings \
 test_embind \
 test_emscripten_license_O2_closure \
 test_emscripten_license_O2_closure_emit \
 test_emscripten_license_O2_closure_js_emit \
 test_js_function_names_are_minified \
 test_minimal_runtime_code_size \
 test_module_exports_with_closure \
 test_no_nuthin \
 test_single_file \
 test_sixtyfour_bit_return_value_bigint \
 test_sixtyfour_bit_return_value_normal \

# requires Emscripten Ports
ERRORS_other += \
 test_bullet \
 test_bzip2 \
 test_freetype \
 test_libjpeg \
 test_libpng \
 test_sdl2_mixer_wav \
 test_vorbis
FAILS_CERTAIN_other += \
 test_boost_graph

# avoid modes requiring closure-compiler: wasm2 wasms wasm2js2 wasm2jss
# avoid unimportant mode causing multiple failures: strict
CHECK_MODES_WASMX = wasm0 wasm1 wasm3 wasmz
CHECK_MODES_WASMJS = wasm2js1 wasm2js3 wasm2jsz

# TODO: skip test_indirectbr_many only on armhf
FAILS_wasm += \
 test_bad_typeid \
 test_bullet_autoconf \
 test_bullet_cmake \
 test_dlfcn_alignment_and_zeroing \
 test_dlfcn_basic \
 test_dlfcn_data_and_fptr \
 test_dlfcn_funcs \
 test_dlfcn_handle_alloc \
 test_dlfcn_i64 \
 test_dlfcn_info \
 test_dlfcn_longjmp \
 test_dlfcn_mallocs \
 test_dlfcn_missing \
 test_dlfcn_qsort \
 test_dlfcn_self \
 test_dlfcn_stacks \
 test_dlfcn_unique_sig \
 test_dlfcn_varargs \
 test_dylink_basics \
 test_dylink_class \
 test_dylink_dot_a \
 test_dylink_dso_needed \
 test_dylink_dynamic_cast \
 test_dylink_floats \
 test_dylink_funcpointer \
 test_dylink_funcpointers_wrapper \
 test_dylink_function_pointer_equality \
 test_dylink_global_init \
 test_dylink_global_inits \
 test_dylink_global_var \
 test_dylink_global_var_modded \
 test_dylink_i64 \
 test_dylink_i64_b \
 test_dylink_i64_c \
 test_dylink_i64_invoke \
 test_dylink_iostream \
 test_dylink_jslib \
 test_dylink_many_postsets \
 test_dylink_memory_growth \
 test_dylink_no_export \
 test_dylink_postsets_chunking \
 test_dylink_printfs \
 test_dylink_raii_exceptions \
 test_dylink_rtti \
 test_dylink_safe_heap \
 test_dylink_spaghetti \
 test_dylink_static_funcpointer_float \
 test_dylink_static_funcpointers \
 test_dylink_stdlib \
 test_dylink_zlib \
 test_em_js_linked \
 test_emscripten_log \
 test_exceptions \
 test_exceptions_2 \
 test_exceptions_3 \
 test_exceptions_alias \
 test_exceptions_allowed \
 test_exceptions_allowed_2 \
 test_exceptions_allowed_uncaught \
 test_exceptions_convert \
 test_exceptions_custom \
 test_exceptions_destroy_virtual \
 test_exceptions_libcxx \
 test_exceptions_minimal_runtime \
 test_exceptions_multi \
 test_exceptions_multiple_inherit \
 test_exceptions_multiple_inherit_rethrow \
 test_exceptions_primary \
 test_exceptions_resume \
 test_exceptions_rethrow \
 test_exceptions_simplify_cfg \
 test_exceptions_std \
 test_exceptions_typed \
 test_exceptions_uncaught_2 \
 test_exceptions_uncaught \
 test_exceptions_uncaught_count \
 test_exceptions_virtual_inheritance \
 test_fs_nodefs_home \
 test_fs_nodefs_rw \
 test_i64_invoke_bigint \
 test_longjmp \
 test_longjmp2 \
 test_longjmp2_main_module \
 test_longjmp3 \
 test_longjmp4 \
 test_longjmp_exc \
 test_longjmp_funcptr \
 test_longjmp_i64 \
 test_longjmp_repeat \
 test_longjmp_stacked \
 test_longjmp_throw \
 test_longjmp_unwind \
 test_main_module_static_align \
 test_modularize_closure_pre \
 test_pthread_exceptions \
 test_relocatable_void_function \
 test_safe_stack_dylink \
 test_setjmp_many \
 test_setjmp_many_2 \
 test_setjmp_noleak \
 test_siglongjmp \
 test_stack_placement_pic

FAILS_wasm0 += \
 test_exceptions_refcount

# expects smaller output
FAILS_wasm1 += \
 test_emscripten_lazy_load_code_unconditional

# needs node module wasm2c
FAILS_wasmX_wasm2c += \
 test_autodebug_wasm_standalone \
 test_cube2hash_standalone \
 test_longjmp_standalone \
 test_posixtime_standalone

FAILS_other += \
 test_bad_function_pointer_cast \
 test_binaryen_ctors \
 test_clear_error_on_massive_static_data \
 test_cmake_stdproperty \
 test_dlopen_rtld_global \
 test_dlsym_rtld_default \
 test_error_on_missing_libraries \
 test_exception_settings \
 test_export_aliasee \
 test_extern_weak \
 test_f_exception \
 test_fignore_exceptions \
 test_function_exports_are_small \
 test_ld_library_path \
 test_linker_flags_pass_through \
 test_lld_report_undefined \
 test_locale_wrong \
 test_main_module_without_exceptions_message \
 test_main_module_without_main \
 test_metadce_cxx_except \
 test_metadce_cxx_mangle \
 test_metadce_hello_main_module_2 \
 test_no_legalize_js_ffi \
 test_only_force_stdlibs_2 \
 test_supported_linker_flags \
 test_wasm2c_reactor \
 test_wasm_backend_lto_libcxx_noexcept \

NONSCRIPT_EXECUTABLE = \
 system/include/libcxx/readme.txt \
 system/lib/libcxx/readme.txt \
 tests/other/wasm_sourcemap/foo.wasm \
 tests/other/wasm_sourcemap_dead/t.wasm \
 tools/system_libs.py

SCRIPT_NOT_EXECUTABLE = \
 src/compiler.js \
 tests/embind/build_benchmark \
 third_party/uglify-js/test/beautify.js \
 third_party/uglify-js/test/testparser.js \
 third_party/uglify-js/tmp/test.js \
 tools/js-optimizer.js \
 tools/preprocessor.js \
 tools/source-maps/sourcemap2json.js \
 tools/source-maps/sourcemapper.js

%:
	dh $@

# refresh upstream version hints from Debian package
override_dh_auto_configure: $(SOURCE_MAP_MIN_JS) $(NEON_H)
	cp -f emscripten-version.txt emscripten-version.txt.orig
	echo $(DEB_VERSION_UPSTREAM_ORIG) > emscripten-version.txt
	echo $(patsubst $(DEB_VERSION_UPSTREAM_ORIG)-%,%,$(DEB_VERSION_UPSTREAM_ORIG_REVISION)) \
		> emscripten-revision.txt
	tools/create_dom_pk_codes.py
	mkdir -p debian/em_cache

override_dh_auto_build:

ifeq (,$(filter nocheck,$(DEB_BUILD_OPTIONS)))
override_dh_auto_test:
	$(EMCC) -v 2>&1
	$(EMCC) tests/hello_world.c
	eslint --no-eslintrc --quiet --env browser --format unix a.out.js
	$(EMCC) -O3 tests/hello_world.c
	eslint --no-eslintrc --quiet --env browser --format unix a.out.js
	rm a.out.js a.out.wasm
	ln -sT /usr/share/fonts/truetype/liberation/LiberationSans-Bold.ttf \
		tests/freetype/LiberationSansBold.ttf
	$(TESTS_RUNNER) \
		$(CHECK_MODES_WASMX) \
		$(addprefix skip:wasm*.,$(ERRORS_wasm) $(FAILS_wasm)) \
		$(addprefix skip:wasm0.,$(FAILS_wasm0)) \
		$(addprefix skip:wasm1.,$(FAILS_wasm1)) \
		$(foreach wasm,$(CHECK_MODES_WASMX),\
			$(addprefix skip:$(wasm).,$(FAILS_wasmX_wasm2c))) \
		$(if $(EXP_RELEASE),|| true)
	$(TESTS_RUNNER) other \
		$(addprefix skip:other.,$(ERRORS_other) $(FAILS_CERTAIN_other) $(FAILS_other)) \
		$(if $(EXP_RELEASE),|| true)
ifneq (,$(EXP_RELEASE))
# TODO: always check CHECK_MODES_WASMJS when handling its output:
#  BlockingIOError: [Errno 11] write could not complete without blocking
	EMCC_CORES=1 $(TESTS_RUNNER) \
		$(CHECK_MODES_WASMJS) \
		$(addprefix skip:wasm*.,$(ERRORS_wasm) $(FAILS_wasm)) \
		|| true
	EMCC_CORES=1 $(TESTS_RUNNER) \
		$(foreach wasm,$(CHECK_MODES_WASMX),\
			$(addprefix $(wasm).,$(FAILS_wasm) $(FAILS_wasmX_wasm2c))) \
		$(addprefix wasm1.,$(FAILS_wasm1)) \
		|| true
	EMCC_CORES=1 $(TESTS_RUNNER) \
		$(foreach wasm,$(CHECK_MODES_WASMJS),\
			$(addprefix $(wasm).,$(FAILS_wasm))) \
		|| true
	EMCC_CORES=1 $(TESTS_RUNNER) \
		$(addprefix other.,$(FAILS_other)) \
		|| true
endif
	rm -f tests/freetype/LiberationSansBold.ttf
endif

# avoid license and Visual Studio files
override_dh_install:
	dh_install $(addprefix --exclude=,\
		COPYING GPL LICENSE License.txt license.dox \
		.dsp .dsw .sln .vcproj)

# webassembly code is alien to dh_strip
override_dh_strip:
	dh_strip --exclude=/usr/share/emscripten/cache

override_dh_fixperms:
	dh_fixperms
	chmod -x $(addprefix debian/emscripten/usr/share/emscripten/,\
		$(NONSCRIPT_EXECUTABLE))
	chmod +x $(addprefix debian/emscripten/usr/share/emscripten/,\
		$(SCRIPT_NOT_EXECUTABLE))

override_dh_missing:
	dh_missing --fail-missing

# restore maybe-outdated upstream version hint
override_dh_auto_clean:
	[ ! -e emscripten-version.txt.orig ] \
		|| mv -f emscripten-version.txt.orig emscripten-version.txt
	rm -rf debian/em_cache
	rm -f .emscripten $(SOURCE_MAP_MIN_JS) $(NEON_H)

# generate header file from SIMDe source
$(NEON_H): /usr/include/simde/arm/neon.h
	echo '#define SIMDE_ARM_NEON_A32V7_ENABLE_NATIVE_ALIASES' > $@
	echo '#define SIMDE_ARM_NEON_A64V8_ENABLE_NATIVE_ALIASES' >> $@
	cat $< >> $@
	echo '#undef SIMDE_ARM_NEON_A32V7_ENABLE_NATIVE_ALIASES' >> $@
	echo '#undef SIMDE_ARM_NEON_A64V8_ENABLE_NATIVE_ALIASES' >> $@

# join source-less and source-only parts of upstream source-map script
$(SOURCE_MAP_MIN_JS): \
 /usr/share/javascript/source-map/source-map.min.js \
 debian/missing-sources/source-map-footer_$(DEB_VERSION_UPSTREAM_ORIG).js
	cat $^ > $@

# custom rule: get source-only part of upstream source-map script
# (see README.source)
get-source-map-footer:
	wget -O- https://github.com/emscripten-core/emscripten/raw/$(DEB_VERSION_UPSTREAM_ORIG)/src/emscripten-source-map.min.js \
		| tail -n +2 \
		> debian/missing-sources/source-map-footer_$(DEB_VERSION_UPSTREAM_ORIG).js
