[Libreoffice-commits] core.git: Branch 'feature/wasm' - 269 commits - accessibility/Library_acc.mk accessibility/source android/README autogen.sh basctl/source basegfx/test basic/source bean/native bin/find-can-be-private-symbols.classes.results bin/find-mergedlib-can-be-private.classes.results bin/gla11y bin/lint-ui.py bridges/Module_bridges.mk bridges/source canvas/Module_canvas.mk chart2/source cli_ure/source comphelper/source compilerplugins/clang compilerplugins/LICENSE.TXT config_host.mk.in configure.ac connectivity/source cppu/source cpputools/Module_cpputools.mk cui/inc cui/source cui/uiconfig dbaccess/source desktop/Library_sofficeapp.mk desktop/Module_desktop.mk desktop/source dictionaries download.lst drawinglayer/source editeng/inc editeng/source embeddedobj/source embeddedobj/test extensions/Module_extensions.mk extensions/source external/apr external/boost external/breakpad external/cairo external/clucene external/coinmp external/cppunit external/curl external/epm external/expat ext ernal/firebird external/fontconfig external/freetype external/gpgmepp external/harfbuzz external/hunspell external/hyphen external/icu external/lcms2 external/libabw external/libassuan external/libatomic_ops external/libcdr external/libebook external/libeot external/libepubgen external/libetonyek external/libexttextcat external/libffi external/libfreehand external/libgpg-error external/libjpeg-turbo external/liblangtag external/libmspub external/libmwaw external/libnumbertext external/libodfgen external/liborcus external/libpagemaker external/libqxp external/librevenge external/libstaroffice external/libvisio external/libwpd external/libwpg external/libwps external/libxml2 external/libxslt external/libzmf external/mythes external/neon external/nss external/openldap external/openssl external/poppler external/postgresql external/python3 external/redland external/serf external/skia external/xmlsec extras/source filter/CppunitTest_filter_tiff_test.mk filter/Library_gie.mk filter/Module_ filter.mk filter/qa filter/source filter/uiconfig forms/source fpicker/uiconfig framework/inc framework/source .gitignore helpcompiler/inc helpcompiler/source helpcontent2 i18nlangtag/source i18npool/Library_i18npool.mk i18npool/source i18nutil/source icon-themes/breeze icon-themes/breeze_dark icon-themes/breeze_dark_svg icon-themes/breeze_svg icon-themes/colibre icon-themes/colibre_svg icon-themes/elementary icon-themes/elementary_svg icon-themes/karasa_jaga icon-themes/karasa_jaga_svg icon-themes/sifr icon-themes/sifr_dark icon-themes/sifr_dark_svg icon-themes/sifr_svg icon-themes/sukapura icon-themes/sukapura_svg idl/source include/basegfx include/basic include/comphelper include/desktop include/editeng include/filter include/i18nlangtag include/jvmaccess include/jvmfwk include/LibreOfficeKit include/o3tl include/oox include/osl include/sal include/sfx2 include/svtools include/svx include/tools include/unotools include/vcl include/xmloff instsetoo_native/CustomTarget_install.mk i o/source io/test javaunohelper/source jurt/source jvmfwk/plugins jvmfwk/source lingucomponent/source lotuswordpro/source Makefile.gbuild odk/docs odk/examples odk/index.html odk/index_online.html officecfg/registry oox/source pyuno/source readlicense_oo/license README.md README.wasm registry/Module_registry.mk reportdesign/source RepositoryExternal.mk Repository.mk RepositoryModule_host.mk sal/osl scaddins/source sc/inc sc/Library_scui.mk sc/qa scripting/examples scripting/Module_scripting.mk scripting/source sc/source sc/uiconfig sdext/source sd/inc sd/Library_sdui.mk sd/qa sd/source sd/uiconfig setup_native/source sfx2/sdi sfx2/source sfx2/uiconfig shell/Module_shell.mk slideshow/source solenv/bin solenv/clang-format solenv/flatpak-manifest.in solenv/gbuild solenv/sanitizers starmath/source starmath/uiconfig stoc/source svgio/inc svgio/source svl/Library_svl.mk svl/source svl/unx svtools/source svx/inc svx/Library_svx.mk svx/qa svx/source svx/uiconfig svx/UIConfig_svx.mk svx/util sw/inc sw/Library_swui.mk sw/Module_sw.mk sw/qa sw/source sw/uiconfig sw/UIConfig_swriter.mk testtools/source toolkit/source tools/source ucb/source uitest/impress_tests unoidl/Executable_unoidl-read.mk unotools/source uui/source vbahelper/source vcl/CppunitTest_vcl_filters_test.mk vcl/Executable_ui-previewer.mk vcl/inc vcl/jsdialog vcl/Library_vcl.mk vcl/Library_vclplug_gen.mk vcl/Library_vclplug_gtk3_kde5.mk vcl/Library_vclplug_gtk3.mk vcl/Library_vclplug_kf5.mk vcl/Library_vclplug_osx.mk vcl/Library_vclplug_qt5.mk vcl/Library_vclplug_win.mk vcl/Module_vcl.mk vcl/qa vcl/qt5 vcl/quartz vcl/skia vcl/source vcl/unx vcl/wasm vcl/win vcl/workben wasm/CustomTarget_components.mk wasm/CustomTarget_wasm-qt5-mandelbrot_moc.mk wasm/Executable_wasm-qt5-mandelbrot.mk wasm/Library_components.mk wasm/Makefile wasm/Module_wasm.mk wasm/README wasm/source wizards/source writerfilter/source writerperfect/qa xmloff/source xmlscript/source xmlsecurity/Library_xmlsecurity.mk xmlsecurity/Library_xsec_xm lsec.mk xmlsecurity/Module_xmlsecurity.mk xmlsecurity/source

Jan-Marek Glogowski (via logerrit) logerrit at kemper.freedesktop.org
Mon Jan 11 11:16:20 UTC 2021


Rebased ref, commits from common ancestor:
commit d764527eaef282bd246707289669f77b8a6b3522
Author:     Jan-Marek Glogowski <glogow at fbihome.de>
AuthorDate: Sat Jan 9 13:41:18 2021 +0100
Commit:     Jan-Marek Glogowski <glogow at fbihome.de>
CommitDate: Sat Jan 9 15:08:40 2021 +0100

    Enable some more tests and demos for static builds
    
    Change-Id: I6372cd33db2fb72d417ca483d1324fca6947e077

diff --git a/Repository.mk b/Repository.mk
index 2b5d597fc01b..aedf890b8f85 100644
--- a/Repository.mk
+++ b/Repository.mk
@@ -67,7 +67,7 @@ $(eval $(call gb_Helper_register_executables,NONE, \
         svptest \
         svpclient ) \
 	$(if $(filter LINUX %BSD SOLARIS,$(OS)), tilebench) \
-	$(if $(filter LINUX MACOSX SOLARIS WNT %BSD,$(OS)),icontest) \
+    icontest \
 	vcldemo \
 	tiledrendering \
     mtfdemo \
diff --git a/registry/Module_registry.mk b/registry/Module_registry.mk
index 90f7833673d8..aa7ec1ab3ecc 100644
--- a/registry/Module_registry.mk
+++ b/registry/Module_registry.mk
@@ -11,7 +11,7 @@ $(eval $(call gb_Module_Module,registry))
 
 $(eval $(call gb_Module_add_targets,registry,\
 	Library_reg \
-	$(if $(filter-out $(OS),iOS), \
+	$(if $(DISABLE_DYNLOADING),, \
 		$(if $(ENABLE_MACOSX_SANDBOX),, \
 			Executable_regmerge \
 			Executable_regview \
@@ -20,9 +20,8 @@ $(eval $(call gb_Module_add_targets,registry,\
 	) \
 ))
 
-ifneq ($(OS),iOS) # missing regmerge (see above), needed within test
-
-ifeq ($(ENABLE_MACOSX_SANDBOX),) # ditto
+ifneq (,$(DISABLE_DYNLOADING))
+ifeq ($(ENABLE_MACOSX_SANDBOX),)
 
 $(eval $(call gb_Module_add_check_targets,registry, \
     CustomTarget_regcompare_test \
diff --git a/vcl/Module_vcl.mk b/vcl/Module_vcl.mk
index a45b43be22bd..fc38ed5b481a 100644
--- a/vcl/Module_vcl.mk
+++ b/vcl/Module_vcl.mk
@@ -34,7 +34,7 @@ $(eval $(call gb_Module_add_targets,vcl,\
         $(if $(ENABLE_MACOSX_SANDBOX),, \
             $(if $(DISABLE_GUI),, \
                 Executable_ui-previewer)) \
-        $(if $(filter LINUX MACOSX SOLARIS WNT %BSD,$(OS)), \
+        $(if $(filter EMSCRIPTEN LINUX MACOSX SOLARIS WNT %BSD,$(OS)), \
             $(if $(DISABLE_GUI),, \
                 Executable_vcldemo \
                 Executable_icontest \
@@ -42,8 +42,6 @@ $(eval $(call gb_Module_add_targets,vcl,\
                 Executable_mtfdemo ))) \
 ))
 
-ifeq ($(CROSS_COMPILING)$(DISABLE_DYNLOADING),)
-
 $(eval $(call gb_Module_add_targets,vcl,\
     $(if $(filter-out ANDROID iOS WNT,$(OS)), \
         Executable_svdemo \
@@ -52,8 +50,6 @@ $(eval $(call gb_Module_add_targets,vcl,\
         Executable_svpclient) \
 ))
 
-endif
-
 $(eval $(call gb_Module_add_l10n_targets,vcl,\
     AllLangMoTarget_vcl \
 ))
commit 1c34efae240f7edd1246ff8afe452d9f75b3bd33
Author:     Jan-Marek Glogowski <glogow at fbihome.de>
AuthorDate: Tue Dec 29 11:49:50 2020 +0100
Commit:     Jan-Marek Glogowski <glogow at fbihome.de>
CommitDate: Sat Jan 9 15:08:39 2021 +0100

    Add a static components library
    
    This adds all component implementing libraries as dependency to a
    new components library, which otherwise just contains the "native"
    code with the mapping of the component constructors.
    
    Since there is no way to know, which components are actually used,
    this has to include all build components.
    
    The components lbrary is automatically added to all users of
    cppuhelper, which contains the calls to the mapper functions of the
    generated "native" code.
    
    Change-Id: Ie78af06c3325c0f58226a4c4da85a1d64fb45dc6

diff --git a/Repository.mk b/Repository.mk
index 8d3fe5be50bd..2b5d597fc01b 100644
--- a/Repository.mk
+++ b/Repository.mk
@@ -345,6 +345,7 @@ $(eval $(call gb_Helper_register_libraries_for_install,OOOLIBS,ooo, \
 	$(call gb_Helper_optional,OPENCL,clew) \
 	$(if $(filter $(OS),WNT),,cmdmail) \
 	cppcanvas \
+	$(if $(filter $(OS),EMSCRIPTEN),components) \
 	configmgr \
 	ctl \
 	cui \
diff --git a/i18npool/Library_i18npool.mk b/i18npool/Library_i18npool.mk
index 6bbab747d462..da044da5b9b9 100644
--- a/i18npool/Library_i18npool.mk
+++ b/i18npool/Library_i18npool.mk
@@ -25,6 +25,17 @@ $(eval $(call gb_Library_use_libraries,i18npool,\
 	i18nlangtag \
 	i18nutil \
 	sal \
+    $(if $(DISABLE_DYNLOADING), \
+        collator_data \
+        dict_ja \
+        dict_zh \
+        index_data \
+        localedata_en \
+        localedata_es \
+        localedata_euro \
+        localedata_others \
+        textconv_dict \
+    ) \
 ))
 
 $(eval $(call gb_Library_use_externals,i18npool,\
diff --git a/i18nutil/source/utility/paper.cxx b/i18nutil/source/utility/paper.cxx
index 4e94f9b36a14..91b7bccb8376 100644
--- a/i18nutil/source/utility/paper.cxx
+++ b/i18nutil/source/utility/paper.cxx
@@ -233,7 +233,7 @@ PaperInfo PaperInfo::getSystemDefaultPaper()
         if (bInitialized)
             return aInstance;
 
-#ifndef MACOSX
+#if ! defined(MACOSX) && ! defined(EMSCRIPTEN)
         // try libpaper
         // #i78617# workaround missing paperconf command
         FILE* pPipe = popen( "paperconf 2>/dev/null", "r" );
diff --git a/idl/source/objects/types.cxx b/idl/source/objects/types.cxx
index 9cb1684caffc..52110127b842 100644
--- a/idl/source/objects/types.cxx
+++ b/idl/source/objects/types.cxx
@@ -251,7 +251,7 @@ void SvMetaType::WriteSfxItem(
 
     // write the implementation part
     rOutStm.WriteCharPtr( "#ifdef SFX_TYPEMAP" ) << endl;
-    rOutStm.WriteCharPtr( "#if !defined(_WIN32) && (defined(DISABLE_DYNLOADING) && (defined(ANDROID) || defined(IOS) || defined(LINUX)))" ) << endl;
+    rOutStm.WriteCharPtr( "#if !defined(_WIN32) && (defined(DISABLE_DYNLOADING) && (defined(ANDROID) || defined(IOS) || defined(EMSCRIPTEN) || defined(LINUX)))" ) << endl;
     rOutStm.WriteCharPtr( "__attribute__((__weak__))" ) << endl;
     rOutStm.WriteCharPtr( "#endif" ) << endl;
     rOutStm.WriteOString( aTypeName ).WriteOString( aVarName )
diff --git a/sd/source/core/typemap.cxx b/sd/source/core/typemap.cxx
index 046be764ba19..4378ad2d2f84 100644
--- a/sd/source/core/typemap.cxx
+++ b/sd/source/core/typemap.cxx
@@ -95,7 +95,49 @@
 #include <svx/galleryitem.hxx>
 #include <svx/sdangitm.hxx>
 
+#ifdef DISABLE_DYNLOADING
+/* Avoid clash with the ones from svx/source/form/typemap.cxx */
+#define aSfxBoolItem_Impl sd_source_core_typemap_aSfxBoolItem_Impl
+#define aSfxInt32Item_Impl sd_source_core_typemap_aSfxInt32Item_Impl
+#define aSfxStringItem_Impl sd_source_core_typemap_aSfxStringItem_Impl
+#define aSfxUInt16Item_Impl sd_source_core_typemap_aSfxUInt16Item_Impl
+#define aSfxUInt32Item_Impl sd_source_core_typemap_aSfxUInt32Item_Impl
+#define aSfxVoidItem_Impl sd_source_core_typemap_aSfxVoidItem_Impl
+#define aSvxClipboardFormatItem_Impl sd_source_core_typemap_aSvxClipboardFormatItem_Impl
+#define aSvxColorItem_Impl sd_source_core_typemap_aSvxColorItem_Impl
+#define aSvxContourItem_Impl sd_source_core_typemap_aSvxContourItem_Impl
+#define aSvxCrossedOutItem_Impl sd_source_core_typemap_aSvxCrossedOutItem_Impl
+#define aSvxFontHeightItem_Impl sd_source_core_typemap_aSvxFontHeightItem_Impl
+#define aSvxFontItem_Impl sd_source_core_typemap_aSvxFontItem_Impl
+#define aSvxLanguageItem_Impl sd_source_core_typemap_aSvxLanguageItem_Impl
+#define aSvxPostureItem_Impl sd_source_core_typemap_aSvxPostureItem_Impl
+#define aSvxShadowedItem_Impl sd_source_core_typemap_aSvxShadowedItem_Impl
+#define aSvxUnderlineItem_Impl sd_source_core_typemap_aSvxUnderlineItem_Impl
+#define aSvxOverlineItem_Impl sd_source_core_typemap_aSvxOverlineItem_Impl
+#define aSvxWeightItem_Impl sd_source_core_typemap_aSvxWeightItem_Impl
+#endif
+
 #define SFX_TYPEMAP
 #include <sdslots.hxx>
 
+#ifdef DISABLE_DYNLOADING
+#undef aSfxBoolItem_Impl
+#undef aSfxInt32Item_Impl
+#undef aSfxStringItem_Impl
+#undef aSfxUInt16Item_Impl
+#undef aSfxUInt32Item_Impl
+#undef aSfxVoidItem_Impl
+#undef aSvxClipboardFormatItem_Impl
+#undef aSvxColorItem_Impl
+#undef aSvxContourItem_Impl
+#undef aSvxCrossedOutItem_Impl
+#undef aSvxFontHeightItem_Impl
+#undef aSvxFontItem_Impl
+#undef aSvxLanguageItem_Impl
+#undef aSvxPostureItem_Impl
+#undef aSvxShadowedItem_Impl
+#undef aSvxTextLineItem_Impl
+#undef aSvxWeightItem_Impl
+#endif
+
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/solenv/gbuild/Library.mk b/solenv/gbuild/Library.mk
index 4f336cbb0007..685e5c249afc 100644
--- a/solenv/gbuild/Library.mk
+++ b/solenv/gbuild/Library.mk
@@ -119,6 +119,9 @@ $(if $(3),$(call gb_Output_error,gb_Library_set_soversion_script: too many argum
 $(call gb_Library__set_soversion_script_platform,$(1),$(2))
 endef
 
+gb_Library__get_component_var = $(call gb_Library__get_workdir_linktargetname,$(1))<>COMPONENTFILE
+gb_Library__get_component = $($(call gb_Library__get_component_var,$(1)))
+
 # The dependency from workdir component target to outdir library should ensure
 # that gb_CppunitTest_use_component can transitively depend on the library.
 # But the component target also must be delivered; use the target
@@ -134,6 +137,7 @@ $(call gb_ComponentTarget_get_target,$(2)) :| \
 	$(call gb_Library_get_target,$(gb_Library__get_name))
 $(call gb_Library_get_clean_target,$(gb_Library__get_name)) : \
 	$(call gb_ComponentTarget_get_clean_target,$(2))
+$(eval $(call gb_Library__get_component_var,$(1)) += $(2))
 endef
 
 gb_Library__get_name = $(if $(filter $(1),$(gb_MERGEDLIBS)),merged,$(1))
diff --git a/solenv/gbuild/platform/EMSCRIPTEN_INTEL_GCC.mk b/solenv/gbuild/platform/EMSCRIPTEN_INTEL_GCC.mk
index ba88eea92976..b0e26432f173 100644
--- a/solenv/gbuild/platform/EMSCRIPTEN_INTEL_GCC.mk
+++ b/solenv/gbuild/platform/EMSCRIPTEN_INTEL_GCC.mk
@@ -7,11 +7,7 @@
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 #
 
-ifeq ($(DISABLE_DYNLOADING),TRUE)
 gb_UnoApiHeadersTarget_select_variant = $(if $(filter udkapi,$(1)),comprehensive,$(2))
-else
-gb_UnoApiHeadersTarget_select_variant = $(2)
-endif
 
 include $(GBUILDDIR)/platform/unxgcc.mk
 
diff --git a/solenv/gbuild/static.mk b/solenv/gbuild/static.mk
index f71a042f7221..c2b359378eed 100644
--- a/solenv/gbuild/static.mk
+++ b/solenv/gbuild/static.mk
@@ -50,6 +50,13 @@
 # doesn't seem to happen in any breaking way and it works to link multiple Executable
 # with large and small expanded dependency lists.
 #
+# Then there is the special static "components" library, which simply depends on all build
+# components. In theory these could be limited per-module (Writer, Calc, etc.), but currently
+# this is not implemented and instead solenv/bin/native-code.py is used, so actually
+# everything is build and "cleaned up" at link time, which is especially expensive for WASM.
+# That library is currently just used for Emscripten, but could be used generally for
+# static builds.
+#
 # For WASM, this also serialize the linking, because the wasm-opt process is multi-threaded,
 # running on all available cores, using GB of memory. Extra parallelism is counterproductive.
 #
@@ -62,6 +69,10 @@
 ifeq ($(true),$(gb_FULLDEPS))
 ifeq (,$(gb_PARTIAL_BUILD))
 
+ifeq ($(OS),EMSCRIPTEN)
+$(foreach lib,$(gb_Library_KNOWNLIBS),$(if $(call gb_Library__get_component,$(lib)),$(eval $(call gb_Library_use_libraries,components,$(lib)))))
+endif
+
 define gb_Executable__add_x_template
 
 define gb_Executable__add_$(2)
@@ -173,6 +184,7 @@ gb_Executable__has_any_dependencies = $(if $(filter-out GBUILD_TOUCHED,$(call gb
 # * Expand all libraries. It's not strictly needed, as we only need the info for the executables,
 #   but this way we can implement updating single gbuild-module dependencies as needed.
 # * For all executables:
+#   * For EMSCRIPTEN, add components library to any cppuhelper user, as it contains the call to the mapper functions
 #   * Find any loader libraries and add the needed plugin dependences
 #   * Add all statics to the executables
 #   * Add icudata as needed (it should be a plugin somehow declared in RepositoryExternal.mk, but that didn't work)
@@ -180,6 +192,8 @@ gb_Executable__has_any_dependencies = $(if $(filter-out GBUILD_TOUCHED,$(call gb
 # * Remove "touch" mark from all touched targets
 $(foreach lib,$(gb_Library_KNOWNLIBS),$(eval $(call gb_LinkTarget__fill_all_libraries,$(lib))))
 $(foreach exec,$(gb_Executable_KNOWN), \
+	$(if $(and $(filter EMSCRIPTEN,$(OS)),$(filter cppuhelper,$(call gb_Executable__get_all_libraries,$(exec)))), \
+		$(eval $(call gb_Executable_use_libraries,$(exec),components))) \
 	$(eval $(call gb_LinkTarget__fill_all_executable,$(exec))) \
 	$(foreach loader,$(filter $(gb_Library_KNOWNLOADERS),$(call gb_Executable__get_all_libraries,$(exec))), \
 		$(eval $(call gb_Executable_use_libraries,$(exec),$(call gb_Library__get_plugins,$(loader)))) \
diff --git a/vcl/Executable_ui-previewer.mk b/vcl/Executable_ui-previewer.mk
index 87a63182a0de..f853ce40864e 100644
--- a/vcl/Executable_ui-previewer.mk
+++ b/vcl/Executable_ui-previewer.mk
@@ -30,119 +30,6 @@ $(eval $(call gb_Executable_use_libraries,ui-previewer,\
     tl \
     ucbhelper \
     vcl \
-    $(if $(filter TRUE,$(DISABLE_DYNLOADING)), \
-        acc \
-        avmedia \
-        basegfx \
-        bib \
-        bootstrap \
-        cairocanvas \
-        canvasfactory \
-        canvastools \
-        chartcontroller \
-        chartcore \
-        collator_data \
-        configmgr \
-        cppcanvas \
-        ctl \
-        cui \
-        dba \
-        dbtools \
-        dict_ja \
-        dict_zh \
-        drawinglayer \
-        editeng \
-        embobj \
-        emfio \
-        epoxy \
-        evtatt \
-        expwrap \
-        filterconfig \
-        frm \
-        fsstorage \
-        fwk \
-        gie \
-        gie \
-        graphicfilter \
-        graphicfilter \
-        guesslang \
-        hyphen \
-        i18nlangtag \
-        i18npool \
-        i18npool \
-        i18nsearch \
-        i18nutil \
-        icg \
-        index_data \
-        introspection \
-        invocadapt \
-        invocation \
-        lng \
-        lnth \
-        localebe1 \
-        localedata_en \
-        localedata_es \
-        localedata_euro \
-        localedata_others \
-        msfilter \
-        mtfrenderer \
-        namingservice \
-        numbertext \
-        odfflatxml \
-        oox \
-        package2 \
-        pdffilter \
-        proxyfac \
-        reflection \
-        reg \
-        salhelper \
-        sax \
-        sax \
-        sb \
-        sfx \
-        simplecanvas \
-        sot \
-        spell \
-        srtrs1 \
-        stocservices \
-        storagefd \
-        store \
-        svgfilter \
-        svgio \
-        svl \
-        svt \
-        svx \
-        svxcore \
-        t602filter \
-        textconv_dict \
-        textfd \
-        tl \
-        tk \
-        ucb1 \
-        ucbhelper \
-        ucpdav1 \
-        ucpfile1 \
-        ucphier1 \
-        ucppkg1 \
-        ucptdoc1 \
-        unoidl \
-        unordf \
-        unoxml \
-        utl \
-        uui \
-        vclcanvas \
-        xmlfa \
-        xmlfd \
-        xmlreader \
-        xmlscript \
-        xo \
-        xof \
-        xsltdlg \
-        xsltfilter \
-        xsltfilter \
-        xstor \
-        $(if $(filter EMSCRIPTEN,$(OS)),vclplug_qt5) \
-    ) \
 ))
 
 $(eval $(call gb_Executable_add_exception_objects,ui-previewer,\
diff --git a/vcl/Library_vcl.mk b/vcl/Library_vcl.mk
index 6900010fd731..d9f5e75f7e71 100644
--- a/vcl/Library_vcl.mk
+++ b/vcl/Library_vcl.mk
@@ -584,9 +584,6 @@ $(eval $(call gb_Library_add_exception_objects,vcl,\
     $(vcl_headless_freetype_code) \
 ))
 
-$(eval $(call gb_Library_add_generated_exception_objects,vcl,\
-    CustomTarget/vcl/wasm/native-code \
-))
 
 $(eval $(call gb_Library_use_externals,vcl,\
     cairo \
diff --git a/vcl/Module_vcl.mk b/vcl/Module_vcl.mk
index 34e0bd041583..a45b43be22bd 100644
--- a/vcl/Module_vcl.mk
+++ b/vcl/Module_vcl.mk
@@ -123,12 +123,6 @@ $(eval $(call gb_Module_add_targets,vcl,\
 ))
 endif
 
-ifeq ($(OS),EMSCRIPTEN)
-$(eval $(call gb_Module_add_targets,vcl,\
-    CustomTarget_wasm_native \
-))
-endif
-
 ifneq ($(ENABLE_FUZZERS),)
 $(eval $(call gb_Module_add_targets,vcl,\
     CustomTarget_nativecore \
diff --git a/vcl/CustomTarget_wasm_native.mk b/wasm/CustomTarget_components.mk
similarity index 71%
rename from vcl/CustomTarget_wasm_native.mk
rename to wasm/CustomTarget_components.mk
index a9f702388500..cb188166d894 100644
--- a/vcl/CustomTarget_wasm_native.mk
+++ b/wasm/CustomTarget_components.mk
@@ -8,14 +8,14 @@
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 #
 
-$(eval $(call gb_CustomTarget_CustomTarget,vcl/wasm))
+$(eval $(call gb_CustomTarget_CustomTarget,wasm/components))
 
-wasm_WORKDIR := $(call gb_CustomTarget_get_workdir,vcl/wasm)
+wasm_WORKDIR := $(call gb_CustomTarget_get_workdir,wasm)
 
-$(call gb_CustomTarget_get_target,vcl/wasm): \
-	$(wasm_WORKDIR)/native-code.cxx
+$(call gb_CustomTarget_get_target,wasm/components): \
+	$(wasm_WORKDIR)/component_maps.cxx
 
-$(wasm_WORKDIR)/native-code.cxx: \
+$(wasm_WORKDIR)/component_maps.cxx: \
 	    $(SRCDIR)/solenv/bin/native-code.py \
 	    | $(wasm_WORKDIR)/.dir
 	$(call gb_Output_announce,$(subst $(BUILDDIR)/,,$@),$(true),GEN,2)
diff --git a/wasm/Library_components.mk b/wasm/Library_components.mk
new file mode 100644
index 000000000000..128a3c12c2df
--- /dev/null
+++ b/wasm/Library_components.mk
@@ -0,0 +1,16 @@
+# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t; fill-column: 100 -*-
+#
+# This file is part of the LibreOffice project.
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+
+$(eval $(call gb_Library_Library,components))
+
+$(eval $(call gb_Library_add_generated_exception_objects,components,\
+    CustomTarget/wasm/component_maps \
+))
+
+# vim: set noet sw=4 ts=4:
diff --git a/wasm/Module_wasm.mk b/wasm/Module_wasm.mk
index 0ef8c4c6aaf4..d6f507a005df 100644
--- a/wasm/Module_wasm.mk
+++ b/wasm/Module_wasm.mk
@@ -13,6 +13,8 @@ ifeq ($(OS),EMSCRIPTEN)
 $(eval $(call gb_Module_add_targets,wasm,\
     CustomTarget_wasm-qt5-mandelbrot_moc \
     Executable_wasm-qt5-mandelbrot \
+    CustomTarget_components \
+    Library_components \
 ))
 
 endif
commit 660e4b7156e2ad9ba06e990488450208c810f5e2
Author:     Jan-Marek Glogowski <glogow at fbihome.de>
AuthorDate: Tue Dec 29 11:40:44 2020 +0100
Commit:     Jan-Marek Glogowski <glogow at fbihome.de>
CommitDate: Sat Jan 9 15:08:39 2021 +0100

    gbuild: handle Executable(s) for static build
    
    See the (large) comment in solenv/gbuild/static.mk trying to
    explain, why this implementation was chosen (spoiler: seems
    there is no other way) and what is actually implemented. Yes,
    I also think it's borderline maintainable (like gbuild in
    general; complexity clashing with make "restrictions"). Feel
    free to propose / implement anything easier, except expanding
    the bin/lo-all-static-libs "concept" ;-)
    
    Change-Id: Iceb73c05b163affc4385fd4f8f0f5a2ecb55b004

diff --git a/Makefile.gbuild b/Makefile.gbuild
index cd7fc973c287..f369c9e9fb4d 100644
--- a/Makefile.gbuild
+++ b/Makefile.gbuild
@@ -20,6 +20,10 @@ include $(SRCDIR)/solenv/gbuild/gbuild.mk
 
 $(eval $(call gb_Module_make_global_targets,$(SRCDIR)/RepositoryModule_$(gb_Side).mk))
 
+ifneq (,$(DISABLE_DYNLOADING))
+include $(SRCDIR)/solenv/gbuild/static.mk
+endif
+
 upload-symbols:
 	bin/upload_symbols.py $(WORKDIR)/symbols.zip $(BREAKPAD_SYMBOL_CONFIG) "$(LIBO_VERSION_MAJOR).$(LIBO_VERSION_MINOR).$(LIBO_VERSION_MICRO).$(LIBO_VERSION_PATCH)$(LIBO_VERSION_SUFFIX)$(LIBO_VERSION_SUFFIX_SUFFIX)"
 
diff --git a/solenv/gbuild/Library.mk b/solenv/gbuild/Library.mk
index 8883262025af..4f336cbb0007 100644
--- a/solenv/gbuild/Library.mk
+++ b/solenv/gbuild/Library.mk
@@ -171,7 +171,7 @@ endif
 
 $(call gb_LinkTarget_get_target,$(call gb_Library_get_linktarget,$(2))) : PLUGINS += $(1)
 $(eval $(call gb_LinkTarget__add_plugin,$(call gb_Library_get_linktarget,$(2)),$(1)))
-$(call gb_Library__forward_to_Linktarget,$(0),$(1),$(2),$(3))
+$(eval $(call gb_LinkTarget__set_plugin_for,$(call gb_Library_get_linktarget,$(1)),$(2),$(3)))
 endef
 
 # forward the call to the gb_LinkTarget implementation
diff --git a/solenv/gbuild/LinkTarget.mk b/solenv/gbuild/LinkTarget.mk
index fdd74c4887b8..185c2f55b283 100644
--- a/solenv/gbuild/LinkTarget.mk
+++ b/solenv/gbuild/LinkTarget.mk
@@ -597,6 +597,8 @@ $(WORKDIR)/Clean/LinkTarget/% :
 		$(foreach object,$(GENCXXCLROBJECTS),$(call gb_GenCxxClrObject_get_dwo_target,$(object))) \
 		$(call gb_LinkTarget_get_target,$(LINKTARGET)) \
 		$(call gb_LinkTarget_get_dep_target,$(LINKTARGET)) \
+		$(call gb_LinkTarget_get_dep_libraries_target,$(LINKTARGET)) \
+		$(call gb_LinkTarget_get_dep_externals_target,$(LINKTARGET)) \
 		$(call gb_LinkTarget_get_headers_target,$(LINKTARGET)) \
 		$(call gb_LinkTarget_get_objects_list,$(LINKTARGET)) \
 		$(call gb_LinkTarget_get_pch_timestamp,$(LINKTARGETMAKEFILENAME)) \
@@ -610,7 +612,7 @@ $(WORKDIR)/Clean/LinkTarget/% :
 # cat the deps of all objects in one file, then we need only open that one file
 # call gb_LinkTarget__command_dep,dep_target,linktargetname
 define gb_LinkTarget__command_dep
-$(call gb_Output_announce,LNK:$(2),$(true),DEP,1)
+$(call gb_Output_announce,LNK:$(2).d,$(true),DEP,1)
 	$(call gb_Trace_StartRange,LNK:$(2),DEP)
 $(call gb_Helper_abbreviate_dirs,\
 	mkdir -p $(dir $(1)) && \
@@ -673,12 +675,23 @@ $(call gb_LinkTarget_get_target,$(1)) : $(call gb_LinkTarget_get_headers_target,
 
 endef
 
+define gb_LinkTarget__add_linked_libs
+$(call gb_LinkTarget_get_target,$(1)) : LINKED_LIBS += $(2)
+
+endef
+
 # it's not possible to use a pattern rule for files in INSTDIR because
 # it would inevitably conflict with the pattern rule for Package
 # (especially since external libraries are delivered via Package)
 # call gb_LinkTarget__command_impl,linktargettarget,linktargetname
 define gb_LinkTarget__command_impl
 	$(if $(gb_FULLDEPS),
+		$(if $(DISABLE_DYNLOADING),
+			$(if $(gb_PARTIAL_BUILD),,
+	                        $(call gb_LinkTarget__command_dep_libraries,$(call gb_LinkTarget_get_dep_libraries_target,$(2)).tmp,$(2))
+	                        mv $(call gb_LinkTarget_get_dep_libraries_target,$(2)).tmp $(call gb_LinkTarget_get_dep_libraries_target,$(2))
+	                        $(call gb_LinkTarget__command_dep_externals,$(call gb_LinkTarget_get_dep_externals_target,$(2)).tmp,$(2))
+	                        mv $(call gb_LinkTarget_get_dep_externals_target,$(2)).tmp $(call gb_LinkTarget_get_dep_externals_target,$(2))))
 		$(if $(findstring concat-deps,$(2)),,
 			$(call gb_LinkTarget__command_dep,$(call gb_LinkTarget_get_dep_target,$(2)).tmp,$(2))
 			mv $(call gb_LinkTarget_get_dep_target,$(2)).tmp $(call gb_LinkTarget_get_dep_target,$(2))))
@@ -695,7 +708,37 @@ endef
 ifeq ($(gb_FULLDEPS),$(true))
 $(call gb_LinkTarget_get_dep_target,%) : $(call gb_Executable_get_runtime_dependencies,concat-deps)
 	$(call gb_LinkTarget__command_dep,$@,$*)
+
+ifneq (,$(DISABLE_DYNLOADING))
+ifeq (,$(gb_PARTIAL_BUILD))
+
+define gb_LinkTarget__statics_rules_template
+
+define gb_LinkTarget__command_dep_$(1)
+$$(call gb_Output_announce,LNK:$$(2).d.$(1),$$(true),DEP,1)
+mkdir -p $$(dir $$(1)) && \
+TEMPFILE=$$(call var2file,$$(shell $$(gb_MKTEMP)),200,\
+	$$(call gb_LinkTarget__get_all_$(1),$$(2))) && \
+mv $$$${TEMPFILE} $$(1)
+
+endef
+
+$$(call gb_LinkTarget_get_dep_target,%) : $$(call gb_LinkTarget_get_dep_$(1)_target,%)
+
+$$(call gb_LinkTarget_get_dep_$(1)_target,%) : | $$(dir $$(call gb_LinkTarget_get_dep_target,%)).dir
+	$$(call gb_LinkTarget__command_dep_$(1),$$@,$$*)
+
+endef # gb_LinkTarget__statics_rules_template
+
+$(dir $(call gb_LinkTarget_get_dep_target,%))/.dir :
+	$(if $(wildcard $(dir $@)),,mkdir -p $(dir $@))
+
+$(eval $(call gb_LinkTarget__statics_rules_template,libraries))
+$(eval $(call gb_LinkTarget__statics_rules_template,externals))
+
 endif
+endif
+endif # $(gb_FULLDEPS)
 
 # Ok, this is some dark voodoo: When declaring a linktarget with
 # gb_LinkTarget_LinkTarget we set SELF in the headertarget to name of the
@@ -851,7 +894,13 @@ $(call gb_LinkTarget_get_dep_target,$(1)) : GENCOBJECTS :=
 $(call gb_LinkTarget_get_dep_target,$(1)) : GENCXXOBJECTS :=
 $(call gb_LinkTarget_get_dep_target,$(1)) : GENCXXCLROBJECTS :=
 $(call gb_LinkTarget_get_dep_target,$(1)) : YACCOBJECTS :=
+ifneq (,$(DISABLE_DYNLOADING))
+ifeq (,$(gb_PARTIAL_BUILD))
+$(call gb_LinkTarget_get_dep_target,$(1)) : $(call gb_LinkTarget_get_dep_libraries_target,$(1))
+$(call gb_LinkTarget_get_dep_target,$(1)) : $(call gb_LinkTarget_get_dep_externals_target,$(1))
+endif
 endif
+endif # $(gb_FULLDEPS)
 
 gb_LinkTarget_CXX_SUFFIX_$(call gb_LinkTarget__get_workdir_linktargetname,$(1)) := cxx
 
@@ -860,7 +909,7 @@ $(if $(findstring $(INSTDIR),$(1)),$(call gb_LinkTarget__make_installed_rule,$(1
 
 $(call gb_PrecompiledHeader_generate_timestamp_rule,$(2))
 
-endef
+endef # gb_LinkTarget_LinkTarget
 
 # call gb_LinkTarget_set_soversion_script,linktarget,soversionscript
 define gb_LinkTarget_set_soversion_script
@@ -1022,6 +1071,19 @@ $(call gb_Library_get_target,$(1)) :| $(call gb_Library_get_headers_target,$(1))
 
 endef
 
+define gb_LinkTarget__all_x_accessors
+gb_LinkTarget__get_all_$(1)_var = $$(call gb_LinkTarget__get_workdir_linktargetname,$$(1))<>ALL_$(2)
+gb_LinkTarget__get_all_$(1) = $$($$(call gb_LinkTarget__get_all_$(1)_var,$$(1)))
+gb_Library__get_all_$(1) = $$($$(call gb_LinkTarget__get_all_$(1)_var,$$(call gb_Library_get_linktarget,$$(1))))
+gb_Executable__get_all_$(1) = $$($$(call gb_LinkTarget__get_all_$(1)_var,$$(call gb_Executable_get_linktarget,$$(1))))
+gb_ExternalProject__get_all_$(1) = $$($$(call gb_LinkTarget__get_all_$(1)_var,$$(call gb_ExternalProject__get_workdir_linktargetname,$$(1))))
+
+endef
+
+$(eval $(call gb_LinkTarget__all_x_accessors,libraries,LIBRARIES))
+$(eval $(call gb_LinkTarget__all_x_accessors,externals,EXTERNALS))
+$(eval $(call gb_LinkTarget__all_x_accessors,statics,STATICS))
+
 # call gb_LinkTarget__use_libraries,linktarget,requestedlibs,actuallibs,linktargetmakefilename
 define gb_LinkTarget__use_libraries
 
@@ -1040,6 +1102,9 @@ $(call gb_LinkTarget_get_target,$(1)) : LINKED_LIBS += $(3)
 ifeq ($(DISABLE_DYNLOADING),)
 $(call gb_LinkTarget_get_target,$(1)) : \
 	$(foreach lib,$(3),$(call gb_Library_get_exports_target,$(lib)))
+else
+$(if $(gb_DEBUG_STATIC),$(info $(call gb_LinkTarget__get_all_libraries_var,$(1)) += $(3)))
+$(call gb_LinkTarget__get_all_libraries_var,$(1)) += $(3)
 endif
 
 $(call gb_LinkTarget_get_headers_target,$(1)) : \
@@ -1130,6 +1195,9 @@ $(if $(call gb_LinkTarget__is_merged,$(1)),\
 
 ifeq ($(DISABLE_DYNLOADING),)
 $(call gb_LinkTarget_get_target,$(1)) : $(foreach lib,$(2),$(call gb_StaticLibrary_get_target,$(lib)))
+else
+$(if $(gb_DEBUG_STATIC),$(info $(call gb_LinkTarget__get_all_statics_var,$(1)) += $(2)))
+$(call gb_LinkTarget__get_all_statics_var,$(1)) += $(2)
 endif
 $(call gb_LinkTarget_get_headers_target,$(1)) : \
 	$(foreach lib,$(2),$(call gb_StaticLibrary_get_headers_target,$(lib)))
@@ -1741,6 +1809,11 @@ $(if $(filter undefined,$(origin gb_LinkTarget__use_$(2))),\
   $(if $(call gb_LinkTarget__is_merged,$(1)),$(call gb_LinkTarget__use_$(2),$(call gb_Library_get_linktarget,merged))) \
     $(call gb_LinkTarget__use_$(2),$(1)) \
 )
+ifneq (,$(DISABLE_DYNLOADING))
+$(if $(gb_DEBUG_STATIC),$(info $(call gb_LinkTarget__get_all_externals_var,$(1)) += $(2)))
+$(eval $(call gb_LinkTarget__get_all_externals_var,$(1)) += $(2))
+endif
+
 endef
 
 # $(call gb_LinkTarget_use_externals,library,externals)
@@ -1813,13 +1886,14 @@ endif
 ifeq (,$(filter $(1),$(foreach plugin,$(gb_Library_KNOWNPLUGINS),$(call gb_Library_get_linktarget,$(plugin)))))
 $$(eval $$(call gb_Output_error,Unknown plugin(s) '$(filter $(1),$(foreach plugin,$(gb_Library_KNOWNPLUGINS),$(call gb_Library_get_linktarget,$(plugin))))'. Plugins must be registered in Repository.mk or RepositoryExternal.mk))
 endif
-ifeq (,$(filter $(1),$(foreach lib,$(gb_MERGEDLIBS),$(call gb_Library_get_linktarget,$(lib)))))
+ifneq (,$(filter $(1),$(foreach lib,$(gb_MERGEDLIBS),$(call gb_Library_get_linktarget,$(lib)))))
 $$(eval $$(call gb_Output_error,Plugins can't be in mergelibs))
 endif
 ifeq ($(call gb_LinkTarget__is_build_tool,$(1)),$(true))
 $$(eval $$(call gb_Output_error,Plugin support for build tools not implemented))
 endif
 
+$(if $(filter $(2),$(gb_Library_KNOWNLOADERS)),,gb_Library_KNOWNLOADERS += $(2))
 $(call gb_LinkTarget__use_libraries,$(1),$(2),$(2))
 
 endef
diff --git a/solenv/gbuild/TargetLocations.mk b/solenv/gbuild/TargetLocations.mk
index 801d188be737..67b960747676 100644
--- a/solenv/gbuild/TargetLocations.mk
+++ b/solenv/gbuild/TargetLocations.mk
@@ -111,16 +111,26 @@ gb_JunitTest_get_classsetname = JunitTest/$(1)
 gb_JunitTest_get_target = $(WORKDIR)/JunitTest/$(1)/done
 gb_JunitTest_get_userdir = $(WORKDIR)/JunitTest/$(1)/user
 gb_PythonTest_get_target = $(WORKDIR)/PythonTest/$(1)/done
+
+# linktarget = class/object<>some_optional_target, like Library/libswlo.so<>/.../instdir/program/libswlo.so
+# while the target is optional, the workdir functions will always work correctly
 gb_LinkTarget__get_workdir_linktargetname = $(firstword $(subst <>,  ,$(1)))
+gb_LinkTarget__get_workdir_linktargetclass =  $(firstword $(subst /,  ,$(call gb_LinkTarget__get_workdir_linktargetname,$(1))))
+gb_LinkTarget__get_workdir_linktargetobject = $(lastword $(subst /,  ,$(call gb_LinkTarget__get_workdir_linktargetname,$(1))))
+gb_LinkTarget_get_target = $(lastword $(subst <>,  ,$(1)))
+
 gb_LinkTarget_get_headers_target = \
  $(WORKDIR)/Headers/$(call gb_LinkTarget__get_workdir_linktargetname,$(1))
 gb_LinkTarget_get_objects_list = \
  $(WORKDIR)/LinkTarget/$(call gb_LinkTarget__get_workdir_linktargetname,$(1)).objectlist
 gb_LinkTarget_get_dep_target = \
  $(WORKDIR)/Dep/LinkTarget/$(call gb_LinkTarget__get_workdir_linktargetname,$(1)).d
+gb_LinkTarget_get_dep_libraries_target = \
+ $(WORKDIR)/Dep/LinkTarget/$(call gb_LinkTarget__get_workdir_linktargetname,$(1)).d.libraries
+gb_LinkTarget_get_dep_externals_target = \
+ $(WORKDIR)/Dep/LinkTarget/$(call gb_LinkTarget__get_workdir_linktargetname,$(1)).d.externals
 gb_LinkTarget_get_clean_target = \
  $(WORKDIR)/Clean/LinkTarget/$(call gb_LinkTarget__get_workdir_linktargetname,$(1))
-gb_LinkTarget_get_target = $(lastword $(subst <>,  ,$(1)))
 gb_LinkTarget_get_pch_timestamp = $(WORKDIR)/PrecompiledHeader/$(call gb_PrecompiledHeader__get_debugdir,$(1))/Timestamps/$(1)
 gb_LinkTarget_get_pch_reuse_timestamp = $(WORKDIR)/PrecompiledHeader/$(call gb_PrecompiledHeader__get_debugdir,$(1))/Timestamps/$(1)_reuse
 gb_Module_get_nonl10n_target = $(WORKDIR)/Module/nonl10n/$(1)
@@ -387,6 +397,10 @@ define gb_Executable_get_linktarget
 $(call gb_Executable__get_workdir_linktargetname,$(1))<>$(call gb_Executable_get_target,$(1))
 endef
 
+define gb_ExternalProject__get_workdir_linktargetname
+ExternalProject/$(1)
+endef
+
 define gb_Library__get_workdir_linktargetname
 Library/$(call gb_Library_get_filename,$(1))
 endef
@@ -397,6 +411,9 @@ endef
 define gb_Library_get_linktarget
 $(call gb_Library__get_workdir_linktargetname,$(1))<>$(call gb_Library_get_target,$(1))
 endef
+define gb_Library_get_dep_libraries_target
+$(call gb_LinkTarget_get_dep_libraries_target,$(call gb_Library_get_linktarget,$(1)))
+endef
 
 define gb_StaticLibrary__get_workdir_linktargetname
 StaticLibrary/$(call gb_StaticLibrary_get_filename,$(1))
diff --git a/solenv/gbuild/static.mk b/solenv/gbuild/static.mk
new file mode 100644
index 000000000000..f71a042f7221
--- /dev/null
+++ b/solenv/gbuild/static.mk
@@ -0,0 +1,219 @@
+# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*-
+#
+# This file is part of the LibreOffice project.
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+
+# "spezialgelagerter Sonderfall" :-(
+#
+# *******************************************
+# Use gb_DEBUG_STATIC=t to dump variuos debug info for the static build preparation!
+# *******************************************
+#
+# "Generic" comment form the author:
+# My thought was: the dependency info is already there. Can't be too hard to use it for
+# correct static linkage... well it took more then two weeks to hopefully identify all
+# problems / edge cases. Now I can appreciate the usage bin/lo-all-static-libs even more.
+#
+# This code moved a few times to the various gbuild / make phases: Makefile / module
+# setup (in use_(libraries|externals)), post parsing (like now), make "dependency" tree
+# processing. It currently looks like this is the only working option.
+#
+# For static linking, we must collect all depending libraries, externals and statics to
+# be available at link time. And Libraries and externals can use each other. This could
+# be done "in-line", while make processes the dependency tree and would have the correct
+# order, so no separate tree-walking would be needed.
+# It can't be done while reading / processing the modules, as this happens in no order, so
+# depending modules will be missing.
+#
+# Then there is the (gbuild new) concept of plugin libraries. These depend on some loader
+# libraries, like vcl and vclplug_* or gie. For a shared library build, these plugins are
+# just dlopen'ed, but for a static build, any linked binary must also link the plugins, which
+# turns plugins + loaders into a dependency cycle. The implemented solution is to just add
+# plugins to executables, if these depend on a loader library. This results in the additional
+# rule: nothing non-plugin is allowed to depend on a plugins (see gb_Library_set_plugin_for).
+#
+# And we can't add these dependencies while make is already processing the Executables,
+# because these contain additional eval'ed targets, which we can't create in make recipes.
+# This is especially true for externals (see gb_LinkTarget__use_* in RepositoryExternal.mk).
+# We also can't add all plugins to all executables, as we have multiple helper
+# binaries, which are needed early and don't depend on plugins.
+#
+# So the only option left seems to be to walk the dependency tree ourself and expand all
+# the libraries and externals and then add the plugins to the executables. Statics are
+# handled after that, since these won't need extra dependencies not already known.
+# It's a bit fragile in theory, as you can add "gbuild-undetectable" dependencies to any
+# target in the modules, which would need some manual adjustment, but currently that
+# doesn't seem to happen in any breaking way and it works to link multiple Executable
+# with large and small expanded dependency lists.
+#
+# For WASM, this also serialize the linking, because the wasm-opt process is multi-threaded,
+# running on all available cores, using GB of memory. Extra parallelism is counterproductive.
+#
+# Best way to "debug" is to replace "eval" with "info" to see the expanded template, which
+# doesn't look that horrible (both do the same expansion internally).
+# There is already a lot of $(info ...) protected by the already mentioned $(gb_DEBUG_STATIC).
+#
+# P.S. remeber to keep the $(info ...) and $(eval ...) blocks in sync (maybe add a function?)
+#
+ifeq ($(true),$(gb_FULLDEPS))
+ifeq (,$(gb_PARTIAL_BUILD))
+
+define gb_Executable__add_x_template
+
+define gb_Executable__add_$(2)
+$$(foreach item,$$(2),
+	$$(foreach dep,$$(call gb_$(1)__get_all_$(2),$$(item)),
+		$$(if $$(filter $$(dep),GBUILD_TOUCHED $$(call gb_Executable__get_all_$(2),$$(1))),,
+			$$(eval $$(call gb_LinkTarget__add_$(2),$$(call gb_Executable__get_workdir_linktargetname,$$(1)),$$(dep)))))
+	$$(foreach dep,$$(call gb_$(1)__get_all_$(3),$$(item)),
+		$$(if $$(filter $$(dep),GBUILD_TOUCHED $$(call gb_Executable__get_all_$(3),$$(1))),,
+			$$(eval $$(call gb_LinkTarget__add_$(3),$$(call gb_Executable__get_workdir_linktargetname,$$(1)),$$(dep))))))
+
+endef
+
+endef # gb_Executable__add_x_template
+
+ifneq (,$(gb_DEBUG_STATIC))
+$(info $(call gb_Executable__add_x_template,ExternalProject,externals,libraries))
+$(info $(call gb_Executable__add_x_template,Library,libraries,externals))
+endif
+$(eval $(call gb_Executable__add_x_template,ExternalProject,externals,libraries))
+$(eval $(call gb_Executable__add_x_template,Library,libraries,externals))
+
+define gb_LinkTarget__add_x_template
+
+define gb_LinkTarget__add_$(1)
+$$(if $(gb_DEBUG_STATIC),$$(info $$(call gb_LinkTarget__get_all_$(1)_var,$$(call gb_LinkTarget__get_workdir_linktargetname,$$(1))) += $$(2)))
+$$(call gb_LinkTarget__get_all_$(1)_var,$$(call gb_LinkTarget__get_workdir_linktargetname,$$(1))) += $$(2)
+
+endef
+
+endef # gb_LinkTarget__add_x_template
+
+ifneq (,$(gb_DEBUG_STATIC))
+$(info $(call gb_LinkTarget__add_x_template,libraries))
+$(info $(call gb_LinkTarget__add_x_template,externals))
+$(info $(call gb_LinkTarget__add_x_template,statics))
+endif
+$(eval $(call gb_LinkTarget__add_x_template,libraries))
+$(eval $(call gb_LinkTarget__add_x_template,externals))
+$(eval $(call gb_LinkTarget__add_x_template,statics))
+
+# contains the list of all touched workdir_linktargetname(s)
+gb_LinkTarget__ALL_TOUCHED =
+
+define gb_LinkTarget__add_touch
+$(eval $(call gb_LinkTarget__add_libraries,$(1),GBUILD_TOUCHED))
+$(eval $(call gb_LinkTarget__add_externals,$(1),GBUILD_TOUCHED))
+gb_LinkTarget__ALL_TOUCHED += $(1)
+
+endef
+
+define gb_LinkTarget__remove_touch
+$(call gb_LinkTarget__get_all_libraries_var,$(1)) := $(filter-out GBUILD_TOUCHED,$(call gb_LinkTarget__get_all_libraries,$(1)))
+$(call gb_LinkTarget__get_all_externals_var,$(1)) := $(filter-out GBUILD_TOUCHED,$(call gb_LinkTarget__get_all_externals,$(1)))
+
+endef
+
+# The following code is a template, because libraries and externals can use each others.
+# It recursively walks the dependency tree for all libraries and externals, storing
+# the information in variables per workdir_linktargetname, filtered for uniqueness. In the end
+# all of them have two variables, which you can get with gb_LinkTarget__get_all_(libraries|externals).
+# Expanded lists have a GBUILD_TOUCHED entry to prevent processing them multiple times
+#
+# eval call gb_LinkTarget__fill_all_x_template,type,typeclassname,othertype,other typeclassname,override,override typeclassname
+define gb_LinkTarget__fill_all_x_template
+
+define gb_LinkTarget__fill_all_$(if $(5),$(5),$(1))
+$$(if $$(filter GBUILD_TOUCHED,$$(call gb_$(2)__get_all_$(1),$$(1))),,
+	$(if $(gb_DEBUG_STATIC),$$(info gb_LinkTarget__fill_all_$(if $(5),$(5),$(1)) $(1) for $$(1) in: $$(call gb_$(if $(6),$(6),$(2))__get_all_$(1),$$(1))))
+	$(if $(gb_DEBUG_STATIC),$$(info gb_LinkTarget__fill_all_$(if $(5),$(5),$(1)) $(3) for $$(1) in: $$(call gb_$(if $(6),$(6),$(2))__get_all_$(3),$$(1))))
+	$$(foreach item,$$(call gb_$(if $(6),$(6),$(2))__get_all_$(1),$$(1)),
+		$$(call gb_LinkTarget__fill_all_$(1),$$(item))
+		$$(foreach dep,$$(call gb_$(2)__get_all_$(1),$$(item)),
+			$$(if $$(filter $$(dep),GBUILD_TOUCHED $$(call gb_$(if $(6),$(6),$(2))__get_all_$(1),$$(1))),,
+				$$(eval $$(call gb_LinkTarget__add_$(1),$$(call gb_$(if $(6),$(6),$(2))__get_workdir_linktargetname,$$(1)),$$(dep)))))
+		$$(foreach dep,$$(call gb_$(2)__get_all_$(3),$$(item)),
+			$$(if $$(filter $$(dep),GBUILD_TOUCHED $$(call gb_$(if $(6),$(6),$(2))__get_all_$(3),$$(1))),,
+				$$(eval $$(call gb_LinkTarget__add_$(3),$$(call gb_$(if $(6),$(6),$(2))__get_workdir_linktargetname,$$(1)),$$(dep))))))
+	$$(foreach item,$$(call gb_$(if $(6),$(6),$(2))__get_all_$(3),$$(1)),
+		$$(call gb_LinkTarget__fill_all_$(3),$$(item))
+		$$(foreach dep,$$(call gb_$(4)__get_all_$(1),$$(item)),
+			$$(if $$(filter $$(dep),GBUILD_TOUCHED $$(call gb_$(if $(6),$(6),$(2))__get_all_$(1),$$(1))),,
+				$$(eval $$(call gb_LinkTarget__add_$(1),$$(call gb_$(if $(6),$(6),$(2))__get_workdir_linktargetname,$$(1)),$$(dep)))))
+		$$(foreach dep,$$(call gb_$(4)__get_all_$(3),$$(item)),
+			$$(if $$(filter $$(dep),GBUILD_TOUCHED $$(call gb_$(if $(6),$(6),$(2))__get_all_$(3),$$(1))),,
+				$$(eval $$(call gb_LinkTarget__add_$(3),$$(call gb_$(if $(6),$(6),$(2))__get_workdir_linktargetname,$$(1)),$$(dep))))))
+	$$(eval $$(call gb_LinkTarget__add_touch,$$(call gb_$(if $(6),$(6),$(2))__get_workdir_linktargetname,$$(1))))
+	$(if $(gb_DEBUG_STATIC),$$(info gb_LinkTarget__fill_all_$(if $(5),$(5),$(1)) $(1) for $$(1) out: $$(call gb_$(if $(6),$(6),$(2))__get_all_$(1),$$(1))))
+	$(if $(gb_DEBUG_STATIC),$$(info gb_LinkTarget__fill_all_$(if $(5),$(5),$(1)) $(3) for $$(1) out: $$(call gb_$(if $(6),$(6),$(2))__get_all_$(3),$$(1)))))
+
+endef
+
+endef # gb_LinkTarget__fill_all_x_template
+
+ifneq (,$(gb_DEBUG_STATIC))
+$(info $(call gb_LinkTarget__fill_all_x_template,libraries,Library,externals,ExternalProject))
+$(info $(call gb_LinkTarget__fill_all_x_template,externals,ExternalProject,libraries,Library))
+$(info $(call gb_LinkTarget__fill_all_x_template,libraries,Library,externals,ExternalProject,executable,Executable))
+endif
+$(eval $(call gb_LinkTarget__fill_all_x_template,libraries,Library,externals,ExternalProject))
+$(eval $(call gb_LinkTarget__fill_all_x_template,externals,ExternalProject,libraries,Library))
+$(eval $(call gb_LinkTarget__fill_all_x_template,libraries,Library,externals,ExternalProject,executable,Executable))
+
+gb_Executable__LAST_KNOWN =
+gb_Executable__has_any_dependencies = $(if $(filter-out GBUILD_TOUCHED,$(call gb_Executable__get_all_libraries,$(1)) $(call gb_Executable__get_all_externals,$(1))),$(1))
+
+# The comment exists To help decipering / verifying the following block. Most later items depends on previous one(s).
+#
+# * Expand all libraries. It's not strictly needed, as we only need the info for the executables,
+#   but this way we can implement updating single gbuild-module dependencies as needed.
+# * For all executables:
+#   * Find any loader libraries and add the needed plugin dependences
+#   * Add all statics to the executables
+#   * Add icudata as needed (it should be a plugin somehow declared in RepositoryExternal.mk, but that didn't work)
+#   * Serialize the linking of executables for EMSCRIPTEN, because wasm-opt is multi-threaded using all cores.
+# * Remove "touch" mark from all touched targets
+$(foreach lib,$(gb_Library_KNOWNLIBS),$(eval $(call gb_LinkTarget__fill_all_libraries,$(lib))))
+$(foreach exec,$(gb_Executable_KNOWN), \
+	$(eval $(call gb_LinkTarget__fill_all_executable,$(exec))) \
+	$(foreach loader,$(filter $(gb_Library_KNOWNLOADERS),$(call gb_Executable__get_all_libraries,$(exec))), \
+		$(eval $(call gb_Executable_use_libraries,$(exec),$(call gb_Library__get_plugins,$(loader)))) \
+		$(eval $(call gb_Executable__add_libraries,$(exec),$(call gb_Library__get_plugins,$(loader))))) \
+	$(if $(filter-out GBUILD_TOUCHED,$(call gb_Executable__get_all_libraries,$(exec))), \
+		$(foreach lib,$(filter-out GBUILD_TOUCHED,$(call gb_Executable__get_all_libraries,$(exec))), \
+			$(if $(call gb_Library__get_all_statics,$(lib)), \
+				$(eval $(call gb_Executable_use_static_libraries,$(exec),$(call gb_Library__get_all_statics,$(lib)))))) \
+		$(eval $(call gb_Executable_use_libraries,$(exec),$(filter-out GBUILD_TOUCHED,$(call gb_Executable__get_all_libraries,$(exec)))))) \
+	$(if $(filter-out GBUILD_TOUCHED,$(call gb_Executable__get_all_externals,$(exec))), \
+		$(eval $(call gb_Executable_use_externals,$(exec),$(filter-out GBUILD_TOUCHED,$(call gb_Executable__get_all_externals,$(exec)))))) \
+	$(if $(filter icui18n icuuc,$(call gb_Executable__get_all_externals,$(exec))), \
+		$(eval $(call gb_Executable_use_externals,$(exec),icudata))) \
+	$(if $(and $(filter EMSCRIPTEN,$(OS)),$(call gb_Executable__has_any_dependencies,$(exec))), \
+		$(if $(gb_Executable__LAST_KNOWN), \
+			$(if $(gb_DEBUG_STATIC),$(info $(call gb_Executable_get_target,$(exec)) => $(call gb_Executable_get_target,$(gb_Executable__LAST_KNOWN))))) \
+			$(eval $(call gb_Executable_get_target,$(exec)) : $(call gb_Executable_get_target,$(gb_Executable__LAST_KNOWN))) \
+		$(eval gb_Executable__LAST_KNOWN = $(exec))))
+$(foreach workdir_linktargetname,$(gb_LinkTarget__ALL_TOUCHED),$(eval $(call gb_LinkTarget__remove_touch,$(workdir_linktargetname))))
+
+else # $(gb_PARTIAL_BUILD)
+
+gb_Executable__get_dep_libraries_target = $(call gb_LinkTarget_get_dep_libraries_target,$(call gb_Executable__get_workdir_linktargetname,$(1)))
+gb_Executable__get_dep_externals_target = $(call gb_LinkTarget_get_dep_externals_target,$(call gb_Executable__get_workdir_linktargetname,$(1)))
+
+$(foreach exec,$(gb_Executable_KNOWN), \
+	$(if $(shell cat $(call gb_Executable__get_dep_libraries_target,$(exec)) 2>/dev/null), \
+		$(eval $(call gb_Executable_use_libraries,$(exec),$(shell cat $(call gb_Executable__get_dep_libraries_target,$(exec)))))) \
+	$(if $(shell cat $(call gb_Executable__get_dep_externals_target,$(exec)) 2>/dev/null), \
+		$(eval $(call gb_Executable_use_externals,$(exec),$(shell cat $(call gb_Executable__get_dep_externals_target,$(exec)))))) \
+	$(if $(shell cat $(call gb_Executable__get_dep_statics_target,$(exec)) 2>/dev/null), \
+		$(eval $(call gb_Executable_use_static_libraries,$(exec),$(shell cat $(call gb_Executable__get_dep_statics_target,$(exec)))))))
+
+endif # $(gb_PARTIAL_BUILD)
+endif # $(gb_FULLDEPS)
+
+# vim: set noet sw=4 ts=4:
diff --git a/vcl/Executable_ui-previewer.mk b/vcl/Executable_ui-previewer.mk
index 2fb4dcf87046..87a63182a0de 100644
--- a/vcl/Executable_ui-previewer.mk
+++ b/vcl/Executable_ui-previewer.mk
@@ -11,41 +11,6 @@ $(eval $(call gb_Executable_Executable,ui-previewer))
 
 $(eval $(call gb_Executable_use_externals,ui-previewer,\
     boost_headers \
-    $(if $(filter TRUE,$(DISABLE_DYNLOADING)),\
-        boost_filesystem \
-        boost_iostreams \
-        boost_system \
-        cairo \
-        dtoa \
-        epubgen \
-        expat \
-        fontconfig \
-        freetype \
-        graphite \
-        harfbuzz \
-        hunspell \
-        hyphen \
-        icudata \
-        icui18n \
-        icuuc \
-        lcms2 \
-        libexttextcat \
-        libjpeg \
-        liblangtag \
-        libnumbertext \
-        libpng \
-        librdf \
-        libxml2 \
-        libxslt \
-        mdds_headers \
-        mythes \
-        openssl \
-        orcus \
-        orcus-parser \
-        qrcodegen \
-        qt5 \
-        revenge \
-    ) \
 ))
 
 $(eval $(call gb_Executable_use_api,ui-previewer,\
@@ -54,10 +19,6 @@ $(eval $(call gb_Executable_use_api,ui-previewer,\
 ))
 
 $(eval $(call gb_Executable_use_static_libraries,ui-previewer,\
-    $(if $(filter TRUE,$(DISABLE_DYNLOADING)),\
-        boost_locale \
-        ulingu \
-    ) \
     vclmain \
 ))
 
commit f437b31d0afeab65ff9bceffbb989424d53dbca2
Author:     Jan-Marek Glogowski <glogow at fbihome.de>
AuthorDate: Tue Dec 29 11:42:30 2020 +0100
Commit:     Jan-Marek Glogowski <glogow at fbihome.de>
CommitDate: Sat Jan 9 15:08:39 2021 +0100

    gbuild: introduce plugin (loader) concept
    
    This introduces two concepts: a plugin and its loader (library)
    
    LO currrently has dependency cycles for some libraries. There is
    scui, which depends on sc, while sc dlopen's scui. There are the
    various vclplug_* and the filters/gie libraries, which depends on
    vcl and vcl dlopen's them. While the dependcies of the plugins on
    their loader works fine, for static builds you must add a
    dependency from the loader to the plugins, which introduces a
    dependency cycle.
    
    I codeified a few rules into the build system along with it:
    * just plugins are allowed to depend / link other plugins
    * plugins aren't allowed to be linked into the merge lib
    * plugin loaders are "limited" to libraries
    
    At the high level, this is implemented via two new gbuild calls:
    * gb_Library_set_plugin_for,lib,loader: declare a library to be a
      plugin of a loader library
    * gb_Helper_register_plugins_for_install: "plugin" replacement for
      gb_Helper_register_libraries_for_install to implement some
      additional checks in the build system
    
    For the shared build, nothing changes. gb_Library_set_plugin_for is
    just forwarded to gb_LinkTarget__use_libraries.
    
    P.S. Android and iOS don't build their "executables" using gbuild,
    but call bin/lo-all-static-libs to "let the linker figure it out".
    
    P.P.S. the static handling isn't implemented in this commit, as it
    turned out to be (very) much more complex.
    
    Change-Id: I7b01d9c384cbc5838bd2cc93aff18e4868939d6e

diff --git a/Repository.mk b/Repository.mk
index fbe24f3855bc..8d3fe5be50bd 100644
--- a/Repository.mk
+++ b/Repository.mk
@@ -252,12 +252,15 @@ $(eval $(call gb_Helper_register_libraries_for_install,OOOLIBS,calc, \
 	sc \
 	scd \
 	scfilt \
-	scui \
 	wpftcalc \
 	solver \
 	$(call gb_Helper_optional,SCRIPTING,vbaobj) \
 ))
 
+$(eval $(call gb_Helper_register_plugins_for_install,OOOLIBS,calc, \
+	scui \
+))
+
 $(eval $(call gb_Helper_register_libraries_for_install,OOOLIBS,graphicfilter, \
 	svgfilter \
 	wpftdraw \
@@ -280,19 +283,26 @@ $(eval $(call gb_Helper_register_libraries_for_install,OOOLIBS,onlineupdate, \
 
 $(eval $(call gb_Helper_register_libraries_for_install,OOOLIBS,gnome, \
 	$(if $(ENABLE_EVOAB2),evoab) \
-	$(if $(ENABLE_GTK3),vclplug_gtk3) \
 	$(if $(ENABLE_GIO),losessioninstall) \
 	$(if $(ENABLE_GIO),ucpgio1) \
 ))
 
+$(eval $(call gb_Helper_register_plugins_for_install,OOOLIBS,gnome, \
+    $(if $(ENABLE_GTK3),vclplug_gtk3) \
+))
+
 $(eval $(call gb_Helper_register_libraries_for_install,OOOLIBS,kde, \
 	$(if $(ENABLE_KF5),kf5be1) \
-	$(if $(USING_X11), \
-        $(if $(ENABLE_KF5),vclplug_kf5) \
-        $(if $(ENABLE_QT5),vclplug_qt5) \
-        $(if $(ENABLE_GTK3_KDE5),vclplug_gtk3_kde5) \
-	) \
 ))
+
+ifneq (,$(USING_X11))
+$(eval $(call gb_Helper_register_plugins_for_install,OOOLIBS,kde, \
+    $(if $(ENABLE_KF5),vclplug_kf5) \
+    $(if $(ENABLE_QT5),vclplug_qt5) \
+    $(if $(ENABLE_GTK3_KDE5),vclplug_gtk3_kde5) \
+))
+endif
+
 ifneq ($(ENABLE_GTK3_KDE5),)
 $(eval $(call gb_Helper_register_executables_for_install,OOO,kde, \
        lo_kde5filepicker \
@@ -300,7 +310,7 @@ $(eval $(call gb_Helper_register_executables_for_install,OOO,kde, \
 endif
 
 ifeq ($(OS),HAIKU)
-$(eval $(call gb_Helper_register_libraries_for_install,OOOLIBS,haiku, \
+$(eval $(call gb_Helper_register_plugins_for_install,OOOLIBS,haiku, \
     $(if $(ENABLE_QT5),vclplug_qt5) \
     $(if $(ENABLE_KF5),vclplug_kf5) \
 ))
@@ -370,7 +380,6 @@ $(eval $(call gb_Helper_register_libraries_for_install,OOOLIBS,ooo, \
 	$(if $(filter DESKTOP,$(BUILD_TYPE)),helplinker) \
 	i18npool \
 	i18nsearch \
-    gie \
 	hyphen \
     icg \
 	$(if $(ENABLE_JAVA),jdbc) \
@@ -406,7 +415,6 @@ $(eval $(call gb_Helper_register_libraries_for_install,OOOLIBS,ooo, \
 	sd \
 	sdd \
 	sdfilt \
-	sdui \
 	sfx \
 	simplecanvas \
 	slideshow \
@@ -451,14 +459,10 @@ $(eval $(call gb_Helper_register_libraries_for_install,OOOLIBS,ooo, \
 	xof \
 	xsltdlg \
 	xsltfilter \
-	$(if $(USING_X11), \
-		vclplug_gen \
-	) \
 	$(if $(filter $(OS),WNT), \
 		ado \
 		oleautobridge \
 		smplmail \
-		vclplug_win \
 		wininetbe1 \
 	) \
 	$(if $(filter $(OS),MACOSX), \
@@ -466,12 +470,19 @@ $(eval $(call gb_Helper_register_libraries_for_install,OOOLIBS,ooo, \
 			AppleRemote \
 		) \
 		fps_aqua \
-		vclplug_osx \
 	) \
 	$(if $(filter iOS MACOSX,$(OS)), \
 		MacOSXSpell \
 	) \
-	$(if $(filter EMSCRIPTEN,$(OS)),vclplug_qt5) \
+))
+
+$(eval $(call gb_Helper_register_plugins_for_install,OOOLIBS,ooo, \
+    gie \
+    sdui \
+    $(if $(USING_X11),vclplug_gen) \
+    $(if $(filter $(OS),WNT),vclplug_win) \
+    $(if $(filter $(OS),MACOSX),vclplug_osx) \
+    $(if $(filter EMSCRIPTEN,$(OS)),vclplug_qt5) \
 ))
 
 $(eval $(call gb_Helper_register_libraries_for_install,OOOLIBS,postgresqlsdbc, \
@@ -510,7 +521,6 @@ $(eval $(call gb_Helper_register_libraries_for_install,OOOLIBS,writer, \
 	$(if $(ENABLE_LWP),lwpft) \
 	msword \
 	swd \
-	swui \
 	t602filter \
 	$(call gb_Helper_optional,SCRIPTING,vbaswobj) \
 	wpftwriter \
@@ -518,6 +528,10 @@ $(eval $(call gb_Helper_register_libraries_for_install,OOOLIBS,writer, \
 	$(call gb_Helper_optional,DBCONNECTIVITY,writer) \
 ))
 
+$(eval $(call gb_Helper_register_plugins_for_install,OOOLIBS,writer, \
+	swui \
+))
+
 # cli_cppuhelper is NONE even though it is actually in URE because it is CliNativeLibrary
 $(eval $(call gb_Helper_register_libraries,PLAINLIBS_NONE, \
 	smoketest \
diff --git a/filter/Library_gie.mk b/filter/Library_gie.mk
index 8c0cbd46b9b9..492403331a16 100644
--- a/filter/Library_gie.mk
+++ b/filter/Library_gie.mk
@@ -24,6 +24,8 @@ $(eval $(call gb_Library_set_include,gie,\
     -I$(SRCDIR)/filter/inc \
 ))
 
+$(eval $(call gb_Library_set_plugin_for,gie,vcl))
+
 $(eval $(call gb_Library_use_external,gie,boost_headers))
 
 $(eval $(call gb_Library_use_sdk_api,gie))
@@ -39,7 +41,6 @@ $(eval $(call gb_Library_use_libraries,gie,\
     comphelper \
     i18nlangtag \
     svt \
-    vcl \
     utl \
     tl \
     tk \
diff --git a/sc/Library_scui.mk b/sc/Library_scui.mk
index 86605ab63a0d..4d4cffa12bd4 100644
--- a/sc/Library_scui.mk
+++ b/sc/Library_scui.mk
@@ -9,6 +9,8 @@
 
 $(eval $(call gb_Library_Library,scui))
 
+$(eval $(call gb_Library_set_plugin_for,scui,sc))
+
 $(eval $(call gb_Library_set_include,scui,\
 	-I$(SRCDIR)/sc/source/core/inc \
 	-I$(SRCDIR)/sc/source/filter/inc \
@@ -55,7 +57,6 @@ $(eval $(call gb_Library_use_libraries,scui,\
 	$(call gb_Helper_optional,OPENCL, \
 		opencl) \
 	sal \
-	sc \
 	sfx \
 	sot \
 	svl \
diff --git a/sd/Library_sdui.mk b/sd/Library_sdui.mk
index c776e2eed532..a774d0610cb4 100644
--- a/sd/Library_sdui.mk
+++ b/sd/Library_sdui.mk
@@ -9,6 +9,8 @@
 
 $(eval $(call gb_Library_Library,sdui))
 
+$(eval $(call gb_Library_set_plugin_for,sdui,sd))
+
 $(eval $(call gb_Library_set_include,sdui,\
     $$(INCLUDE) \
     -I$(SRCDIR)/sd/inc \
@@ -49,7 +51,6 @@ $(eval $(call gb_Library_use_libraries,sdui,\
     fwk \
     sal \
     salhelper \
-    sd \
     sfx \
     sot \
     svl \
diff --git a/solenv/gbuild/Helper.mk b/solenv/gbuild/Helper.mk
index 2aa0fc8d65b2..2367a8ba9a91 100644
--- a/solenv/gbuild/Helper.mk
+++ b/solenv/gbuild/Helper.mk
@@ -199,6 +199,13 @@ $(if $(filter UNOVERLIBS RTVERLIBS,$(1)),\
 
 endef
 
+# a plugin is a library, why can't be dynamically linked and must be dlopen'd, but must be linked static
+define gb_Helper_register_plugins_for_install
+$(call gb_Helper_register_libraries_for_install,$(1),$(2),$(3))
+gb_Library_KNOWNPLUGINS += $(3)
+
+endef
+
 define gb_Helper__register_jars
 $(foreach group,$(gb_Jar_VALIDGROUPS),\
  $(foreach target,$(2),\
diff --git a/solenv/gbuild/Library.mk b/solenv/gbuild/Library.mk
index 8c3c2207480d..8883262025af 100644
--- a/solenv/gbuild/Library.mk
+++ b/solenv/gbuild/Library.mk
@@ -162,6 +162,18 @@ gb_Library__COMPONENTPREFIXES := \
 
 gb_Library_get_runtime_filename = $(call gb_Library_get_filename,$(1))
 
+# call gb_Library_set_plugin_for,library,loader
+define gb_Library_set_plugin_for
+ifneq (,$$(filter-out $(gb_Library_KNOWNPLUGINS),$(1)))
+$$(eval $$(call gb_Output_info,currently known plugins are: $(sort $(gb_Library_KNOWNPLUGINS)),ALL))
+$$(eval $$(call gb_Output_error,Unknown plugin(s) '$$(filter-out $(gb_Library_KNOWNPLUGINS),$(1)))'. Plugins must be registered in Repository.mk or RepositoryExternal.mk))
+endif
+
+$(call gb_LinkTarget_get_target,$(call gb_Library_get_linktarget,$(2))) : PLUGINS += $(1)
+$(eval $(call gb_LinkTarget__add_plugin,$(call gb_Library_get_linktarget,$(2)),$(1)))
+$(call gb_Library__forward_to_Linktarget,$(0),$(1),$(2),$(3))
+endef
+
 # forward the call to the gb_LinkTarget implementation
 # (note: because the function name is in $(1), the other args are shifted by 1)
 define gb_Library__forward_to_Linktarget
diff --git a/solenv/gbuild/LinkTarget.mk b/solenv/gbuild/LinkTarget.mk
index 6cd8719f91b7..fdd74c4887b8 100644
--- a/solenv/gbuild/LinkTarget.mk
+++ b/solenv/gbuild/LinkTarget.mk
@@ -1041,6 +1041,7 @@ ifeq ($(DISABLE_DYNLOADING),)
 $(call gb_LinkTarget_get_target,$(1)) : \
 	$(foreach lib,$(3),$(call gb_Library_get_exports_target,$(lib)))
 endif
+
 $(call gb_LinkTarget_get_headers_target,$(1)) : \
 	$(foreach lib,$(2),$(call gb_Library_get_headers_target,$(lib)))
 $(foreach lib,$(2),$(call gb_LinkTarget__lib_dummy_depend,$(lib)))
@@ -1089,7 +1090,12 @@ endef
 define gb_LinkTarget_use_libraries
 ifneq (,$$(filter-out $(gb_Library_KNOWNLIBS),$(2)))
 $$(eval $$(call gb_Output_info,currently known libraries are: $(sort $(gb_Library_KNOWNLIBS)),ALL))
-$$(eval $$(call gb_Output_error,Cannot link against library/libraries $$(filter-out $(gb_Library_KNOWNLIBS),$(2)). Libraries must be registered in Repository.mk or RepositoryExternal.mk))
+$$(eval $$(call gb_Output_error,Cannot link against library/libraries '$$(filter-out $(gb_Library_KNOWNLIBS),$(2))'. Libraries must be registered in Repository.mk or RepositoryExternal.mk))
+endif
+ifneq (,$$(filter $(2),$(gb_Library_KNOWNPLUGINS)))
+ifneq (,$$(filter $(1),$$(foreach plugin,$(gb_Library_KNOWNPLUGINS),$(call gb_Library__get_workdir_linktargetname,$(plugin)))))
+$$(eval $$(call gb_Output_error,Cannot link against plugin library/libraries '$$(filter $(2),$(gb_Library_KNOWNPLUGINS))'. Only plugins are allowed to do that.))
+endif
 endif
 
 ifeq ($(call gb_LinkTarget__is_build_tool,$(1)),$(true))
@@ -1789,5 +1795,33 @@ $(call gb_LinkTarget_get_target,$(1)) : T_USE_LD := $(or $(CLANG_USE_LD),$(USE_L
 
 endef
 
+gb_LinkTarget__get_plugins_var = $(call gb_LinkTarget__get_workdir_linktargetname,$(1))<>PLUGINS
+gb_LinkTarget__get_plugins = $($(call gb_LinkTarget__get_plugins_var,$(1)))
+gb_Library__get_plugins = $($(call gb_LinkTarget__get_plugins_var,$(call gb_Library_get_linktarget,$(1))))
+
+define gb_LinkTarget__add_plugin
+$(call gb_LinkTarget__get_plugins_var,$(1)) += $(2)
+
+endef
+
+# call gb_LinkTarget__set_plugin_for,linktarget,loader
+define gb_LinkTarget__set_plugin_for
+ifneq (,$$(filter-out $(gb_Library_KNOWNLIBS),$(2)))
+$$(eval $$(call gb_Output_info,currently known libraries are: $(sort $(gb_Library_KNOWNLIBS)),ALL))
+$$(eval $$(call gb_Output_error,Cannot link against library/libraries $$(filter-out $(gb_Library_KNOWNLIBS),$(2)). Libraries must be registered in Repository.mk or RepositoryExternal.mk))
+endif
+ifeq (,$(filter $(1),$(foreach plugin,$(gb_Library_KNOWNPLUGINS),$(call gb_Library_get_linktarget,$(plugin)))))
+$$(eval $$(call gb_Output_error,Unknown plugin(s) '$(filter $(1),$(foreach plugin,$(gb_Library_KNOWNPLUGINS),$(call gb_Library_get_linktarget,$(plugin))))'. Plugins must be registered in Repository.mk or RepositoryExternal.mk))
+endif
+ifeq (,$(filter $(1),$(foreach lib,$(gb_MERGEDLIBS),$(call gb_Library_get_linktarget,$(lib)))))
+$$(eval $$(call gb_Output_error,Plugins can't be in mergelibs))
+endif
+ifeq ($(call gb_LinkTarget__is_build_tool,$(1)),$(true))
+$$(eval $$(call gb_Output_error,Plugin support for build tools not implemented))
+endif
+
+$(call gb_LinkTarget__use_libraries,$(1),$(2),$(2))
+
+endef
 
 # vim: set noet sw=4:
diff --git a/sw/Library_swui.mk b/sw/Library_swui.mk
index 99f1dd20ae3d..e643179d355f 100644
--- a/sw/Library_swui.mk
+++ b/sw/Library_swui.mk
@@ -19,6 +19,8 @@
 
 $(eval $(call gb_Library_Library,swui))
 
+$(eval $(call gb_Library_set_plugin_for,swui,sw))
+
 $(eval $(call gb_Library_set_include,swui,\
     -I$(SRCDIR)/sw/inc \
     -I$(SRCDIR)/sw/source/uibase/inc \
@@ -69,7 +71,6 @@ $(eval $(call gb_Library_use_libraries,swui,\
     svx \
     svx \
     svxcore \
-    sw \
     tk \
     tl \
     ucbhelper \
diff --git a/vcl/Library_vclplug_gen.mk b/vcl/Library_vclplug_gen.mk
index 0b9d23e40de5..126ae9ad8263 100644
--- a/vcl/Library_vclplug_gen.mk
+++ b/vcl/Library_vclplug_gen.mk
@@ -19,6 +19,8 @@
 
 $(eval $(call gb_Library_Library,vclplug_gen))
 
+$(eval $(call gb_Library_set_plugin_for,vclplug_gen,vcl))
+
 $(eval $(call gb_Library_set_include,vclplug_gen,\
     $$(INCLUDE) \
     -I$(SRCDIR)/vcl/inc \
@@ -33,7 +35,6 @@ $(eval $(call gb_Library_use_sdk_api,vclplug_gen))
 $(eval $(call gb_Library_use_common_precompiled_header,vclplug_gen))
 
 $(eval $(call gb_Library_use_libraries,vclplug_gen,\
-    vcl \
     tl \
     utl \
     sot \
diff --git a/vcl/Library_vclplug_gtk3.mk b/vcl/Library_vclplug_gtk3.mk
index afc85d224918..8fb5ddd474da 100644
--- a/vcl/Library_vclplug_gtk3.mk
+++ b/vcl/Library_vclplug_gtk3.mk
@@ -19,6 +19,8 @@
 
 $(eval $(call gb_Library_Library,vclplug_gtk3))
 
+$(eval $(call gb_Library_set_plugin_for,vclplug_gtk3,vcl))
+
 # Silence deprecation warnings wholesale as long as vcl/unx/gtk3/*.cxx just
 # forward to vcl/unx/gtk/*.cxx:
 $(eval $(call gb_Library_add_cxxflags,vclplug_gtk3, \
@@ -53,7 +55,6 @@ $(eval $(call gb_Library_add_libs,vclplug_gtk3,\
 ))
 
 $(eval $(call gb_Library_use_libraries,vclplug_gtk3,\
-    vcl \
     svl \
     tl \
     utl \
diff --git a/vcl/Library_vclplug_gtk3_kde5.mk b/vcl/Library_vclplug_gtk3_kde5.mk
index 8dffad18c9de..2bc2a6d5c480 100644
--- a/vcl/Library_vclplug_gtk3_kde5.mk
+++ b/vcl/Library_vclplug_gtk3_kde5.mk
@@ -19,6 +19,8 @@
 
 $(eval $(call gb_Library_Library,vclplug_gtk3_kde5))
 
+$(eval $(call gb_Library_set_plugin_for,vclplug_gtk3_kde5,vcl))
+
 # Silence deprecation warnings wholesale as long as vcl/unx/gtk3/*.cxx just
 # forward to vcl/unx/gtk/*.cxx:
 $(eval $(call gb_Library_add_cxxflags,vclplug_gtk3_kde5, \
@@ -59,7 +61,6 @@ $(eval $(call gb_Library_add_libs,vclplug_gtk3_kde5,\
 
 $(eval $(call gb_Library_use_libraries,vclplug_gtk3_kde5,\
     svl \
-    vcl \
     tl \
     utl \
     sot \
diff --git a/vcl/Library_vclplug_kf5.mk b/vcl/Library_vclplug_kf5.mk
index d10cecd167d5..1e7765a6d6ce 100644
--- a/vcl/Library_vclplug_kf5.mk
+++ b/vcl/Library_vclplug_kf5.mk
@@ -19,6 +19,8 @@
 
 $(eval $(call gb_Library_Library,vclplug_kf5))
 
+$(eval $(call gb_Library_set_plugin_for,vclplug_kf5,vcl))
+
 $(eval $(call gb_Library_use_custom_headers,vclplug_kf5,vcl/unx/kf5))
 
 $(eval $(call gb_Library_set_include,vclplug_kf5,\
@@ -35,7 +37,6 @@ $(eval $(call gb_Library_use_sdk_api,vclplug_kf5))
 
 $(eval $(call gb_Library_use_libraries,vclplug_kf5,\
     vclplug_qt5 \
-    vcl \
     tl \
     utl \
     sot \
diff --git a/vcl/Library_vclplug_osx.mk b/vcl/Library_vclplug_osx.mk
index f0d22298a0c8..f986f377a672 100644
--- a/vcl/Library_vclplug_osx.mk
+++ b/vcl/Library_vclplug_osx.mk
@@ -19,6 +19,8 @@
 
 $(eval $(call gb_Library_Library,vclplug_osx))
 
+$(eval $(call gb_Library_set_plugin_for,vclplug_osx,vcl))
+
 $(eval $(call gb_Library_set_include,vclplug_osx,\
     $$(INCLUDE) \
     -I$(SRCDIR)/vcl/inc \
@@ -51,7 +53,6 @@ $(eval $(call gb_Library_use_libraries,vclplug_osx,\
     sal \
     salhelper \
     tl \
-    vcl \
 ))
 
 $(eval $(call gb_Library_use_externals,vclplug_osx,\
diff --git a/vcl/Library_vclplug_qt5.mk b/vcl/Library_vclplug_qt5.mk
index 3aad76800ad6..58858bac6946 100644
--- a/vcl/Library_vclplug_qt5.mk
+++ b/vcl/Library_vclplug_qt5.mk
@@ -19,6 +19,8 @@
 
 $(eval $(call gb_Library_Library,vclplug_qt5))
 
+$(eval $(call gb_Library_set_plugin_for,vclplug_qt5,vcl))
+
 $(eval $(call gb_Library_use_custom_headers,vclplug_qt5,vcl/qt5))
 
 $(eval $(call gb_Library_set_include,vclplug_qt5,\
@@ -35,7 +37,6 @@ $(eval $(call gb_Library_add_defs,vclplug_qt5,\
 $(eval $(call gb_Library_use_sdk_api,vclplug_qt5))
 
 $(eval $(call gb_Library_use_libraries,vclplug_qt5,\
-    vcl \
     tl \
     utl \
     sot \
diff --git a/vcl/Library_vclplug_win.mk b/vcl/Library_vclplug_win.mk
index 38031387be4a..c386d1ff1397 100644
--- a/vcl/Library_vclplug_win.mk
+++ b/vcl/Library_vclplug_win.mk
@@ -19,6 +19,8 @@
 
 $(eval $(call gb_Library_Library,vclplug_win))
 
+$(eval $(call gb_Library_set_plugin_for,vclplug_win,vcl))
+
 $(eval $(call gb_Library_set_componentfile,vclplug_win,vcl/vclplug_win))
 
 $(eval $(call gb_Library_set_include,vclplug_win,\
@@ -52,7 +54,6 @@ $(eval $(call gb_Library_use_libraries,vclplug_win,\
     salhelper \
     tl \
     utl \
-    vcl \
 ))
 
 $(eval $(call gb_Library_use_externals,vclplug_win,\
commit 58639dc220097b22af13eedb8736e399fdef1953
Author:     Jan-Marek Glogowski <glogow at fbihome.de>
AuthorDate: Thu Dec 31 00:25:16 2020 +0100
Commit:     Jan-Marek Glogowski <glogow at fbihome.de>
CommitDate: Sat Jan 9 15:08:39 2021 +0100

    WASM: link Writer native-code
    
    Change-Id: Ic475e2a9c5c9f493eb1b897dc8356aed5523037d

diff --git a/vcl/CustomTarget_wasm_native.mk b/vcl/CustomTarget_wasm_native.mk
index 1bd829634030..a9f702388500 100644
--- a/vcl/CustomTarget_wasm_native.mk
+++ b/vcl/CustomTarget_wasm_native.mk
@@ -19,6 +19,6 @@ $(wasm_WORKDIR)/native-code.cxx: \
 	    $(SRCDIR)/solenv/bin/native-code.py \
 	    | $(wasm_WORKDIR)/.dir
 	$(call gb_Output_announce,$(subst $(BUILDDIR)/,,$@),$(true),GEN,2)
-	$(call gb_Helper_abbreviate_dirs,$(call gb_ExternalExecutable_get_command,python) $< -g core) > $@
+	$(call gb_Helper_abbreviate_dirs,$(call gb_ExternalExecutable_get_command,python) $< -g core -g writer) > $@
 
 # vim: set noet sw=4:
diff --git a/vcl/Executable_ui-previewer.mk b/vcl/Executable_ui-previewer.mk
index b26a5b1dae6d..2fb4dcf87046 100644
--- a/vcl/Executable_ui-previewer.mk
+++ b/vcl/Executable_ui-previewer.mk
@@ -17,6 +17,7 @@ $(eval $(call gb_Executable_use_externals,ui-previewer,\
         boost_system \
         cairo \
         dtoa \
+        epubgen \
         expat \
         fontconfig \
         freetype \
@@ -43,6 +44,7 @@ $(eval $(call gb_Executable_use_externals,ui-previewer,\
         orcus-parser \
         qrcodegen \
         qt5 \
+        revenge \
     ) \
 ))
 
commit 19491efe4328f809f170f3ec917fa5ec5341b753
Author:     Jan-Marek Glogowski <glogow at fbihome.de>
AuthorDate: Tue Dec 29 11:57:02 2020 +0100
Commit:     Jan-Marek Glogowski <glogow at fbihome.de>
CommitDate: Sat Jan 9 15:08:39 2021 +0100

    Drop some duplicate code
    
    Change-Id: Iff627d34774d495bec9ebe5c499dd0fd43a1d819

diff --git a/i18npool/source/localedata/localedata.cxx b/i18npool/source/localedata/localedata.cxx
index 273415d9461e..8bd23682bb5d 100644
--- a/i18npool/source/localedata/localedata.cxx
+++ b/i18npool/source/localedata/localedata.cxx
@@ -52,10 +52,6 @@ static const char *lcl_DATA_ES = "localedata_es";
 static const char *lcl_DATA_EURO = "localedata_euro";
 static const char *lcl_DATA_OTHERS = "localedata_others";
 
-#endif
-
-#ifndef DISABLE_DYNLOADING
-
 const struct {
     const char* pLocale;
     const char* pLib;
diff --git a/solenv/gbuild/Library.mk b/solenv/gbuild/Library.mk
index 1973249f5db4..8c3c2207480d 100644
--- a/solenv/gbuild/Library.mk
+++ b/solenv/gbuild/Library.mk
@@ -172,7 +172,6 @@ endef
 # copy pasta for forwarding: this could be (and was) done more elegantly, but
 # these here can be found by both git grep and ctags
 gb_Library_add_cobject = $(call gb_Library__forward_to_Linktarget,$(0),$(1),$(2),$(3))
-gb_Library_add_cobject = $(call gb_Library__forward_to_Linktarget,$(0),$(1),$(2),$(3))
 gb_Library_add_cobjects = $(call gb_Library__forward_to_Linktarget,$(0),$(1),$(2),$(3))
 gb_Library_add_cxxobject = $(call gb_Library__forward_to_Linktarget,$(0),$(1),$(2),$(3))
 gb_Library_add_cxxobjects = $(call gb_Library__forward_to_Linktarget,$(0),$(1),$(2),$(3))
commit 64eaa7710b227733ed0c4deb2066dcc25612e15d
Author:     Jan-Marek Glogowski <glogow at fbihome.de>
AuthorDate: Thu Dec 24 22:47:22 2020 +0100
Commit:     Jan-Marek Glogowski <glogow at fbihome.de>
CommitDate: Sat Jan 9 15:08:39 2021 +0100

    WASM encode some more fixed configure options
    
    ... and update README.wasm
    
    Change-Id: Id4b8499dc2154466036f39150386d575a348a3ef

diff --git a/README.wasm b/README.wasm
index 3e201737bd24..cbc08a40a490 100644
--- a/README.wasm
+++ b/README.wasm
@@ -47,12 +47,13 @@ make -j<CORES> module-qtbase module-qtdeclarative
 
 Building with examples will break with some of them, but at that point Qt already works.
 
-Checking for target architecture... Project ERROR: target architecture detection binary not found.
+At some point Qt configure failed for me with:
+"Checking for target architecture... Project ERROR: target architecture detection binary not found."
 
 What seems to have fixed this was to run "emsdk activate 1.39.8" again.
 
 Current Qt fails to start the demo webserver: https://bugreports.qt.io/browse/QTCREATORBUG-24072
-Use: emrun --serve_after_close to run Qt WASM demos
+Use "emrun --serve_after_close" to run Qt WASM demos
 
 Enabling multi-thread support in Firefox is a bit of work with older versions:
 - https://bugzilla.mozilla.org/show_bug.cgi?id=1477743#c7
@@ -62,7 +63,7 @@ Enabling multi-thread support in Firefox is a bit of work with older versions:
 
 == Setup LO ==
 
-Currently autogen.sh is patched to use emconfigure. That basically sets various environment vars,
+autogen.sh is patched to use emconfigure. That basically sets various environment vars,
 especially EMMAKEN_JUST_CONFIGURE, which will create the correct output file names, checked by
 configure (a.out).
 
@@ -80,7 +81,6 @@ QT5DIR=/dir/of/git_qt5/qtbase
 --disable-firebird-sdbc
 --disable-gio
 --disable-gstreamer-1-0
---disable-gtk3
 --disable-ldap
 --disable-lpsolve
 --disable-mariadb-sdbc
@@ -96,15 +96,14 @@ QT5DIR=/dir/of/git_qt5/qtbase
 --disable-scripting
 --disable-sdremote-bluetooth
 --enable-ccache
---enable-qt5
---without-fonts
 --without-helppack-integration
 --without-java
 --without-junit
 --without-system-dicts
+--with-fonts
 --with-theme=no
 
-Will also be encoded in configure.ac at some point, some already is.
+Many will also be encoded in configure.ac at some point, some already is.
 
 
 = Ideas for an UNO bridge implementation =
@@ -186,9 +185,6 @@ We're also using emconfigure at the moment. Originally I patched emscripten, bec
 woulden't create the correct a.out file for C++ configure tests. Later I found that
 the emconfigure sets EMMAKEN_JUST_CONFIGURE to work around the problem.
 
-But it sets many more environment variables with "em<tool>" variants. This can all be moved
-into LO configure later.
-
 ICU bug: https://github.com/emscripten-core/emscripten/issues/10129
 Alternative, probably: https://developer.mozilla.org/de/docs/Web/JavaScript/Reference/Global_Objects/Intl
 
diff --git a/configure.ac b/configure.ac
index d65bdc43a401..403c95977b4d 100644
--- a/configure.ac
+++ b/configure.ac
@@ -2916,7 +2916,7 @@ fi
 if test -z "$enable_scripting"; then
     # Disable scripting for iOS unless specifically overridden
     # with --enable-scripting.
-    if test $_os != iOS; then
+    if test $_os != iOS -o $_os = Emscripten; then
         enable_scripting=yes
     fi
 fi
@@ -2930,7 +2930,7 @@ else
     SCPDEFS="$SCPDEFS -DDISABLE_SCRIPTING"
 fi
 
-if test $_os = iOS -o $_os = Android; then
+if test $_os = iOS -o $_os = Android -o $_os = Emscripten; then
     # Disable dynamic_loading always for iOS and Android
     enable_dynamic_loading=no
 elif test -z "$enable_dynamic_loading"; then
@@ -5234,6 +5234,7 @@ if test "$cross_compiling" = "yes"; then
     test -n "$PKG_CONFIG_FOR_BUILD" && export PKG_CONFIG="$PKG_CONFIG_FOR_BUILD"
     cd CONF-FOR-BUILD
 
+    # Handle host configuration, which affects the cross-toolset too
     sub_conf_opts=""
     test -n "$enable_ccache" && sub_conf_opts="$sub_conf_opts --enable-ccache=$enable_ccache"
     test -n "$with_ant_home" && sub_conf_opts="$sub_conf_opts --with-ant-home=$with_ant_home"
@@ -5512,8 +5513,9 @@ if test "$USING_X11" != TRUE; then
 fi
 
 if test "$OS" = "EMSCRIPTEN"; then
-    enable_cairo_canvas=yes
     test_qt5=yes
+    enable_cairo_canvas=yes
+    enable_qt5=yes
 fi
 
 if test "$OS" = "HAIKU"; then
diff --git a/solenv/bin/run-configure b/solenv/bin/run-configure
index 9a0f2724f3a8..9758ff1d86c6 100755
--- a/solenv/bin/run-configure
+++ b/solenv/bin/run-configure
@@ -1,5 +1,9 @@
 #!/bin/sh
+
+# We could run emconfigure here, but LO's gbuild should have set up everything
+# correctly. If something breaks because of this, we likely have mre problems.
 if test "$OS" = "EMSCRIPTEN"; then
     export EMMAKEN_JUST_CONFIGURE=1
 fi
+
 exec "$@"
commit 7c6481cbdc5426ce8309f9dc2271589632883f8e
Author:     Jan-Marek Glogowski <glogow at fbihome.de>
AuthorDate: Fri Jan 8 12:37:06 2021 +0100
Commit:     Jan-Marek Glogowski <glogow at fbihome.de>
CommitDate: Sat Jan 9 15:08:38 2021 +0100

    WASM use Qt qtloader.js and html template
    
    The emscripten generated one doesn't work, probably because of
    qtloader.js.
    
    Change-Id: I402d20d0175130ce3b26a9d998661fd66f5806a1

diff --git a/config_host.mk.in b/config_host.mk.in
index 51635a8196b4..e758b25f509a 100644
--- a/config_host.mk.in
+++ b/config_host.mk.in
@@ -517,6 +517,7 @@ export QT5_LIBS=$(gb_SPACE)@QT5_LIBS@
 export QT5_GOBJECT_CFLAGS=$(gb_SPACE)@QT5_GOBJECT_CFLAGS@
 export QT5_GOBJECT_LIBS=$(gb_SPACE)@QT5_GOBJECT_LIBS@
 export QT5_HAVE_GOBJECT=@QT5_HAVE_GOBJECT@
+export QT5_PLATFORMS_SRCDIR=@QT5_PLATFORMS_SRCDIR@
 export QXP_CFLAGS=$(gb_SPACE)@QXP_CFLAGS@
 export QXP_LIBS=$(gb_SPACE)@QXP_LIBS@
 export RANLIB=@RANLIB@
diff --git a/configure.ac b/configure.ac
index 81ddcc15f43a..d65bdc43a401 100644
--- a/configure.ac
+++ b/configure.ac
@@ -12408,6 +12408,7 @@ MOC5="moc"
 QT5_GOBJECT_CFLAGS=""
 QT5_GOBJECT_LIBS=""
 QT5_HAVE_GOBJECT=""
+QT5_PLATFORMS_SRCDIR=""
 if test \( "$test_kf5" = "yes" -a "$ENABLE_KF5" = "TRUE" \) -o \
         \( "$test_qt5" = "yes" -a "$ENABLE_QT5" = "TRUE" \) -o \
         \( "$test_gtk3_kde5" = "yes" -a "$ENABLE_GTK3_KDE5" = "TRUE" \)
@@ -12447,6 +12448,7 @@ then
     qt5_incdirs="`$QMAKE5 -query QT_INSTALL_HEADERS` $qt5_incdirs"
     qt5_libdirs="`$QMAKE5 -query QT_INSTALL_LIBS` $qt5_libdirs"
     qt5_platformsdir="`$QMAKE5 -query QT_INSTALL_PLUGINS`/platforms"
+    QT5_PLATFORMS_SRCDIR="$qt5_platformsdir"
 
     AC_MSG_CHECKING([for Qt5 headers])
     qt5_incdir="no"
@@ -12482,8 +12484,13 @@ then
         AC_MSG_ERROR([Qt5 libraries not found.  Please specify the root of your Qt5 installation by exporting QT5DIR before running "configure".])
     fi
 
-    if test "$_os" = "Emscripten" -a ! -f "${qt5_platformsdir}"/libqwasm.a; then
-        AC_MSG_ERROR([No Qt5 WASM QPA plugin found in ${qt5_platformsdir}])
+    if test "$_os" = "Emscripten"; then
+        if test ! -f "$QT5_PLATFORMS_SRCDIR"/wasm_shell.html ; then
+            QT5_PLATFORMS_SRCDIR="${QT5_PLATFORMS_SRCDIR/plugins/src\/plugins}/wasm"
+        fi
+	if test ! -f "${qt5_platformsdir}"/libqwasm.a -o ! -f "$QT5_PLATFORMS_SRCDIR"/wasm_shell.html; then
+            AC_MSG_ERROR([No Qt5 WASM QPA plugin found in ${qt5_platformsdir} or ${QT5_PLATFORMS_SRCDIR}])
+        fi
     fi
 
     QT5_CFLAGS="-I$qt5_incdir -DQT_CLEAN_NAMESPACE -DQT_THREAD_SUPPORT -DQT_NO_VERSION_TAGGING"
@@ -12531,6 +12538,7 @@ AC_SUBST(MOC5)
 AC_SUBST(QT5_GOBJECT_CFLAGS)
 AC_SUBST(QT5_GOBJECT_LIBS)
 AC_SUBST(QT5_HAVE_GOBJECT)
+AC_SUBST(QT5_PLATFORMS_SRCDIR)
 
 dnl ===================================================================
 dnl KF5 Integration
diff --git a/solenv/gbuild/platform/EMSCRIPTEN_INTEL_GCC.mk b/solenv/gbuild/platform/EMSCRIPTEN_INTEL_GCC.mk
index 941081614291..ba88eea92976 100644
--- a/solenv/gbuild/platform/EMSCRIPTEN_INTEL_GCC.mk
+++ b/solenv/gbuild/platform/EMSCRIPTEN_INTEL_GCC.mk
@@ -17,7 +17,7 @@ include $(GBUILDDIR)/platform/unxgcc.mk
 
 gb_RUN_CONFIGURE := $(SRCDIR)/solenv/bin/run-configure
 gb_EMSCRIPTEN_CPPFLAGS := -pthread -s TOTAL_MEMORY=1GB -s USE_PTHREADS=1 -s PTHREAD_POOL_SIZE=4 -s SAFE_HEAP=1
-gb_EMSCRIPTEN_LDFLAGS := $(gb_EMSCRIPTEN_CPPFLAGS) --bind -s ERROR_ON_UNDEFINED_SYMBOLS=1 -s FETCH=1 -s ASSERTIONS=1 -s EXIT_RUNTIME=1 -s EXTRA_EXPORTED_RUNTIME_METHODS=["UTF16ToString","stringToUTF16"]
+gb_EMSCRIPTEN_LDFLAGS := $(gb_EMSCRIPTEN_CPPFLAGS) --bind -s ERROR_ON_UNDEFINED_SYMBOLS=1 -s FETCH=1 -s ASSERTIONS=2 -s EXIT_RUNTIME=1 -s EXTRA_EXPORTED_RUNTIME_METHODS=["UTF16ToString","stringToUTF16"]
 gb_EMSCRIPTEN_QTDEFS := -DQT_NO_LINKED_LIST -DQT_NO_JAVA_STYLE_ITERATORS -DQT_NO_EXCEPTIONS -D_LARGEFILE64_SOURCE -D_LARGEFILE_SOURCE -DQT_NO_DEBUG -DQT_WIDGETS_LIB -DQT_GUI_LIB -DQT_CORE_LIB
 
 gb_Executable_EXT := .html
diff --git a/solenv/gbuild/platform/unxgcc.mk b/solenv/gbuild/platform/unxgcc.mk
index 616f7ac69af9..771f6ef6264a 100644
--- a/solenv/gbuild/platform/unxgcc.mk
+++ b/solenv/gbuild/platform/unxgcc.mk
@@ -156,6 +156,9 @@ $(call gb_Helper_abbreviate_dirs,\
 			>> $(WORKDIR)/LinkTarget/$(2).exports.tmp && \
 		$(call gb_Helper_replace_if_different_and_touch,$(WORKDIR)/LinkTarget/$(2).exports.tmp, \
 			$(WORKDIR)/LinkTarget/$(2).exports,$(1))))
+	$(if $(and $(filter CppunitTest Executable,$(TARGETTYPE)),$(filter EMSCRIPTEN,$(OS)),$(filter TRUE,$(ENABLE_QT5))), \
+		cp $(QT5_PLATFORMS_SRCDIR)/qtlogo.svg $(QT5_PLATFORMS_SRCDIR)/qtloader.js $(dir $(1)) ; \
+		sed -e 's/@APPNAME@/$(subst $(gb_Executable_EXT),,$(notdir $(1)))/' $(QT5_PLATFORMS_SRCDIR)/wasm_shell.html > $(1))
 endef
 
 define gb_LinkTarget__command_staticlink
commit cd74b0ef52957e7b55c4d19cea593ad55f29261c
Author:     Jan-Marek Glogowski <glogow at fbihome.de>
AuthorDate: Tue Dec 22 12:47:03 2020 +0100
Commit:     Jan-Marek Glogowski <glogow at fbihome.de>
CommitDate: Sat Jan 9 15:08:38 2021 +0100

    WASM build mandelbrot Qt example via gbuild
    
    All the flags are copied directly from the qmake example. The
    emscripten HTML doesn't work, but copying the Qt HTML and the
    qtloader.js correctly runs the example in the browser.
    
    This is all a bit messy, but it is mainly a know working app
    to verify any WASM development at this point, so we know the
    Gbuild configuration can build a WASM application.
    
    Change-Id: I1e5fcc64f452d524192f4ea6d975aafafbb9f5bb

diff --git a/README.wasm b/README.wasm
index 012d8c981539..3e201737bd24 100644
--- a/README.wasm
+++ b/README.wasm
@@ -5,6 +5,13 @@ $ emrun --serve_after_close instdir/program/ui-previewer.html
 
 The ui-previewer "binary" will "crash" with memory alignment problems.
 
+You can run the WASM mandelbrot Qt example, if you copy it's HTML
+and the qtloader.js from the Qt's example folder after build with:
+
+$ emrun --serve_after_close workdir/LinkTarget/Executable/mandelbrot.html
+
+REMINDER: always start new tabs in the browser, reload might fail / cache!
+
 
 = Setup for the LO WASM build (with Qt) =
 
diff --git a/Repository.mk b/Repository.mk
index 09e873eb3bc7..fbe24f3855bc 100644
--- a/Repository.mk
+++ b/Repository.mk
@@ -73,6 +73,7 @@ $(eval $(call gb_Helper_register_executables,NONE, \
     mtfdemo \
     visualbackendtest \
 	$(if $(and $(ENABLE_GTK3), $(filter LINUX %BSD SOLARIS,$(OS))), gtktiledviewer) \
+    $(if $(filter EMSCRIPTEN,$(OS)),wasm-qt5-mandelbrot) \
 ))
 
 $(eval $(call gb_Helper_register_executables_for_install,SDK,sdk, \
diff --git a/RepositoryModule_host.mk b/RepositoryModule_host.mk
index dc9725700903..d25f3dd67e22 100644
--- a/RepositoryModule_host.mk
+++ b/RepositoryModule_host.mk
@@ -148,6 +148,7 @@ $(eval $(call gb_Module_add_moduledirs,libreoffice,\
 	uui \
 	vbahelper \
 	vcl \
+	wasm \
 	winaccessibility \
 	wizards \
 	writerfilter \
diff --git a/configure.ac b/configure.ac
index 06887bfc0678..81ddcc15f43a 100644
--- a/configure.ac
+++ b/configure.ac
@@ -12446,6 +12446,7 @@ then
 
     qt5_incdirs="`$QMAKE5 -query QT_INSTALL_HEADERS` $qt5_incdirs"
     qt5_libdirs="`$QMAKE5 -query QT_INSTALL_LIBS` $qt5_libdirs"
+    qt5_platformsdir="`$QMAKE5 -query QT_INSTALL_PLUGINS`/platforms"
 
     AC_MSG_CHECKING([for Qt5 headers])
     qt5_incdir="no"
@@ -12481,11 +12482,15 @@ then
         AC_MSG_ERROR([Qt5 libraries not found.  Please specify the root of your Qt5 installation by exporting QT5DIR before running "configure".])
     fi
 
+    if test "$_os" = "Emscripten" -a ! -f "${qt5_platformsdir}"/libqwasm.a; then
+        AC_MSG_ERROR([No Qt5 WASM QPA plugin found in ${qt5_platformsdir}])
+    fi
+
     QT5_CFLAGS="-I$qt5_incdir -DQT_CLEAN_NAMESPACE -DQT_THREAD_SUPPORT -DQT_NO_VERSION_TAGGING"
     QT5_CFLAGS=$(printf '%s' "$QT5_CFLAGS" | sed -e "s/-I/${ISYSTEM?}/g")
     QT5_LIBS="-L$qt5_libdir -lQt5Core -lQt5Gui -lQt5Widgets -lQt5Network"
     if test "$_os" = "Emscripten"; then
-        QT5_LIBS="$QT5_LIBS -lqtpcre2"
+        QT5_LIBS="$QT5_LIBS -lqtpcre2 -lQt5EventDispatcherSupport -lQt5FontDatabaseSupport -L${qt5_platformsdir} -lqwasm"
     fi
 
     if test "$USING_X11" = TRUE; then
diff --git a/solenv/gbuild/platform/EMSCRIPTEN_INTEL_GCC.mk b/solenv/gbuild/platform/EMSCRIPTEN_INTEL_GCC.mk
index 1c0456c646ec..941081614291 100644
--- a/solenv/gbuild/platform/EMSCRIPTEN_INTEL_GCC.mk
+++ b/solenv/gbuild/platform/EMSCRIPTEN_INTEL_GCC.mk
@@ -17,12 +17,19 @@ include $(GBUILDDIR)/platform/unxgcc.mk
 
 gb_RUN_CONFIGURE := $(SRCDIR)/solenv/bin/run-configure
 gb_EMSCRIPTEN_CPPFLAGS := -pthread -s TOTAL_MEMORY=1GB -s USE_PTHREADS=1 -s PTHREAD_POOL_SIZE=4 -s SAFE_HEAP=1
+gb_EMSCRIPTEN_LDFLAGS := $(gb_EMSCRIPTEN_CPPFLAGS) --bind -s ERROR_ON_UNDEFINED_SYMBOLS=1 -s FETCH=1 -s ASSERTIONS=1 -s EXIT_RUNTIME=1 -s EXTRA_EXPORTED_RUNTIME_METHODS=["UTF16ToString","stringToUTF16"]
+gb_EMSCRIPTEN_QTDEFS := -DQT_NO_LINKED_LIST -DQT_NO_JAVA_STYLE_ITERATORS -DQT_NO_EXCEPTIONS -D_LARGEFILE64_SOURCE -D_LARGEFILE_SOURCE -DQT_NO_DEBUG -DQT_WIDGETS_LIB -DQT_GUI_LIB -DQT_CORE_LIB
 
 gb_Executable_EXT := .html
+gb_EMSCRIPTEN_EXCEPT := -s DISABLE_EXCEPTION_CATCHING=0
 
-gb_CFLAGS += $(gb_EMSCRIPTEN_CPPFLAGS)
-gb_CXXFLAGS += $(gb_EMSCRIPTEN_CPPFLAGS) -s DISABLE_EXCEPTION_CATCHING=0
-gb_LinkTarget_LDFLAGS += $(gb_EMSCRIPTEN_CPPFLAGS) --bind
+gb_LinkTarget_CFLAGS += $(gb_EMSCRIPTEN_CPPFLAGS) $(gb_EMSCRIPTEN_QTDEFS)
+gb_LinkTarget_CXXFLAGS += $(gb_EMSCRIPTEN_CPPFLAGS) $(gb_EMSCRIPTEN_QTDEFS) $(gb_EMSCRIPTEN_EXCEPT)
+
+# WASM is also optimized at link time, but ignores linker flags, so wants $(gb_COMPILEROPTFLAGS)
+gb_LINKEROPTFLAGS :=
+gb_LINKERSTRIPDEBUGFLAGS :=
+gb_LinkTarget_LDFLAGS += $(gb_EMSCRIPTEN_LDFLAGS) $(gb_EMSCRIPTEN_CPPFLAGS) $(gb_EMSCRIPTEN_EXCEPT) $(gb_COMPILEROPTFLAGS)
 
 define gb_Library_get_rpath
 endef
@@ -30,9 +37,4 @@ endef
 define gb_Executable_get_rpath
 endef
 
-gb_LINKEROPTFLAGS :=
-gb_LINKERSTRIPDEBUGFLAGS :=
-
-#gb_CXX_LINKFLAGS += -pthread -s TOTAL_MEMORY=1GB -s USE_PTHREADS=1 -s PTHREAD_POOL_SIZE=4
-
 # vim: set noet sw=4 ts=4
diff --git a/wasm/CustomTarget_wasm-qt5-mandelbrot_moc.mk b/wasm/CustomTarget_wasm-qt5-mandelbrot_moc.mk
new file mode 100644
index 000000000000..52b7447d22e9
--- /dev/null
+++ b/wasm/CustomTarget_wasm-qt5-mandelbrot_moc.mk
@@ -0,0 +1,37 @@
+# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*-
+#
+# This file is part of the LibreOffice project.
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+
+$(eval $(call gb_CustomTarget_CustomTarget,wasm/qt5-mandelbrot))
+
+$(call gb_CustomTarget_get_target,wasm/qt5-mandelbrot) : \
+	$(call gb_CustomTarget_get_workdir,wasm/qt5-mandelbrot)/renderthread.moc \
+	$(call gb_CustomTarget_get_workdir,wasm/qt5-mandelbrot)/mandelbrotwidget.moc \
+
+qt5_mandelbrot_MOCDEFS_H := $(call gb_CustomTarget_get_workdir,wasm/qt5-mandelbrot)/moc_predefs.h
+qt5_mandelbrot_MOCDEFS_CXX := $(call gb_CustomTarget_get_workdir,wasm/qt5-mandelbrot)/moc_dummy.cxx
+qt5_mandelbrot_WORKDIR :=  $(call gb_CustomTarget_get_workdir,wasm/qt5-mandelbrot)/.dir
+
+$(qt5_mandelbrot_MOCDEFS_CXX): | $(qt5_mandelbrot_WORKDIR)
+	touch $@
+
+$(qt5_mandelbrot_MOCDEFS_H): $(qt5_mandelbrot_MOCDEFS_CXX) | $(qt5_mandelbrot_WORKDIR)
+	$(call gb_Output_announce,$(subst $(WORKDIR)/,,$@),$(true),CXX,1)
+	$(call gb_Trace_StartRange,$(subst $(WORKDIR)/,,$@),CXX)
+	$(CXX) -pipe -O2 -std=gnu++11 -fno-exceptions $(gb_EMSCRIPTEN_CPPFLAGS) -dM -E -o $@ $<
+	$(call gb_Trace_EndRange,$(subst $(WORKDIR)/,,$@),MOC)
+
+$(call gb_CustomTarget_get_workdir,wasm/qt5-mandelbrot)/%.moc : \
+		$(SRCDIR)/wasm/source/qt5-mandelbrot/%.h \
+		$(qt5_mandelbrot_MOCDEFS_H) | $(qt5_mandelbrot_WORKDIR)
+	$(call gb_Output_announce,$(subst $(WORKDIR)/,,$@),$(true),MOC,1)
+	$(call gb_Trace_StartRange,$(subst $(WORKDIR)/,,$@),MOC)
+	$(MOC5) --include $(qt5_mandelbrot_MOCDEFS_H) $(gb_EMSCRIPTEN_QTDEFS) $< -o $@
+	$(call gb_Trace_EndRange,$(subst $(WORKDIR)/,,$@),MOC)
+
+# vim: set noet sw=4:
diff --git a/wasm/Executable_wasm-qt5-mandelbrot.mk b/wasm/Executable_wasm-qt5-mandelbrot.mk
new file mode 100644
index 000000000000..7afaa81c0dc4
--- /dev/null
+++ b/wasm/Executable_wasm-qt5-mandelbrot.mk
@@ -0,0 +1,32 @@
+# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*-
+#
+# This file is part of the LibreOffice project.
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+
+$(eval $(call gb_Executable_Executable,wasm-qt5-mandelbrot))
+
+$(eval $(call gb_Executable_use_custom_headers,wasm-qt5-mandelbrot,wasm/qt5-mandelbrot))
+
+$(eval $(call gb_Executable_use_externals,wasm-qt5-mandelbrot,\
+    graphite \
+    freetype \
+    harfbuzz \
+    libpng \
+    qt5 \
+))
+
+$(eval $(call gb_Executable_add_exception_objects,wasm-qt5-mandelbrot,\
+    wasm/source/qt5-mandelbrot/main \
+    wasm/source/qt5-mandelbrot/mandelbrotwidget \
+    wasm/source/qt5-mandelbrot/renderthread \
+))
+
+$(eval $(call gb_Executable_add_defs,wasm-qt5-mandelbrot,\
+    -DVCL_INTERNALS \
+))
+
+# vim: set noet sw=4 ts=4:
diff --git a/wasm/Makefile b/wasm/Makefile
new file mode 100644
index 000000000000..0c6f47b1790f
--- /dev/null
+++ b/wasm/Makefile
@@ -0,0 +1,13 @@
+# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*-
+#
+# This file is part of the LibreOffice project.
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+module_directory:=$(dir $(realpath $(firstword $(MAKEFILE_LIST))))
+
+include $(module_directory)/../solenv/gbuild/partial_build.mk
+
+# vim: set noet sw=4 ts=4:
diff --git a/wasm/Module_wasm.mk b/wasm/Module_wasm.mk
new file mode 100644
index 000000000000..0ef8c4c6aaf4
--- /dev/null
+++ b/wasm/Module_wasm.mk
@@ -0,0 +1,20 @@
+# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*-
+#
+# This file is part of the LibreOffice project.
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+$(eval $(call gb_Module_Module,wasm))
+
+ifeq ($(OS),EMSCRIPTEN)
+
+$(eval $(call gb_Module_add_targets,wasm,\
+    CustomTarget_wasm-qt5-mandelbrot_moc \
+    Executable_wasm-qt5-mandelbrot \
+))
+
+endif
+
+# vim: set noet sw=4 ts=4:
diff --git a/wasm/README b/wasm/README
new file mode 100644
index 000000000000..a23bd6a45ea9
--- /dev/null
+++ b/wasm/README
@@ -0,0 +1 @@
+See /README.wasm
diff --git a/wasm/source/qt5-mandelbrot/main.cxx b/wasm/source/qt5-mandelbrot/main.cxx
new file mode 100644
index 000000000000..037c63153cf2
--- /dev/null
+++ b/wasm/source/qt5-mandelbrot/main.cxx
@@ -0,0 +1,66 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+**   * Redistributions of source code must retain the above copyright
+**     notice, this list of conditions and the following disclaimer.
+**   * 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.
+**   * Neither the name of The Qt Company Ltd nor the names of its
+**     contributors may be used to endorse or promote products derived
+**     from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS 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 ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "mandelbrotwidget.h"
+
+#include <QtWidgets/QApplication>
+#include <QtCore/QtPlugin>
+
+Q_IMPORT_PLUGIN(QWasmIntegrationPlugin)
+
+int main(int argc, char* argv[])
+{
+    QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
+    QCoreApplication::setAttribute(Qt::AA_UseHighDpiPixmaps);
+    QApplication app(argc, argv);
+    MandelbrotWidget widget;
+    widget.show();
+    return app.exec();
+}
diff --git a/wasm/source/qt5-mandelbrot/mandelbrotwidget.cxx b/wasm/source/qt5-mandelbrot/mandelbrotwidget.cxx
new file mode 100644
index 000000000000..5886dd2664c0
--- /dev/null
+++ b/wasm/source/qt5-mandelbrot/mandelbrotwidget.cxx
@@ -0,0 +1,228 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+**   * Redistributions of source code must retain the above copyright
+**     notice, this list of conditions and the following disclaimer.
+**   * 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.
+**   * Neither the name of The Qt Company Ltd nor the names of its
+**     contributors may be used to endorse or promote products derived
+**     from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS 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 ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "mandelbrotwidget.h"
+#include "mandelbrotwidget.moc"
+
+#include <QtGui/QPainter>
+#include <QtGui/QKeyEvent>
+
+#include <math.h>
+
+const double DefaultCenterX = -0.637011;
+const double DefaultCenterY = -0.0395159;
+const double DefaultScale = 0.00403897;
+
+const double ZoomInFactor = 0.8;
+const double ZoomOutFactor = 1 / ZoomInFactor;
+const int ScrollStep = 20;
+
+MandelbrotWidget::MandelbrotWidget(QWidget* parent)
+    : QWidget(parent)
+    , centerX(DefaultCenterX)
+    , centerY(DefaultCenterY)
+    , pixmapScale(DefaultScale)
+    , curScale(DefaultScale)
+{
+    connect(&thread, &RenderThread::renderedImage, this, &MandelbrotWidget::updatePixmap);
+
+    setWindowTitle(tr("Mandelbrot"));
+#if QT_CONFIG(cursor)
+    setCursor(Qt::CrossCursor);
+#endif
+    resize(550, 400);
+}
+
+void MandelbrotWidget::paintEvent(QPaintEvent* /* event */)
+{
+    QPainter painter(this);
+    painter.fillRect(rect(), Qt::black);
+
+    if (pixmap.isNull())
+    {
+        painter.setPen(Qt::white);
+        painter.drawText(rect(), Qt::AlignCenter, tr("Rendering initial image, please wait..."));
+        return;
+    }
+
+    if (qFuzzyCompare(curScale, pixmapScale))
+    {
+        painter.drawPixmap(pixmapOffset, pixmap);
+    }
+    else
+    {
+        auto previewPixmap = qFuzzyCompare(pixmap.devicePixelRatioF(), qreal(1))
+                                 ? pixmap
+                                 : pixmap.scaled(pixmap.size() / pixmap.devicePixelRatioF(),
+                                                 Qt::KeepAspectRatio, Qt::SmoothTransformation);
+        double scaleFactor = pixmapScale / curScale;
+        int newWidth = int(previewPixmap.width() * scaleFactor);
+        int newHeight = int(previewPixmap.height() * scaleFactor);
+        int newX = pixmapOffset.x() + (previewPixmap.width() - newWidth) / 2;
+        int newY = pixmapOffset.y() + (previewPixmap.height() - newHeight) / 2;
+
+        painter.save();
+        painter.translate(newX, newY);
+        painter.scale(scaleFactor, scaleFactor);
+
+        QRectF exposed = painter.transform().inverted().mapRect(rect()).adjusted(-1, -1, 1, 1);
+        painter.drawPixmap(exposed, previewPixmap, exposed);
+        painter.restore();
+    }
+
+    QString text = tr("Use mouse wheel or the '+' and '-' keys to zoom. "
+                      "Press and hold left mouse button to scroll.");
+    QFontMetrics metrics = painter.fontMetrics();
+    int textWidth = metrics.horizontalAdvance(text);
+
+    painter.setPen(Qt::NoPen);
+    painter.setBrush(QColor(0, 0, 0, 127));
+    painter.drawRect((width() - textWidth) / 2 - 5, 0, textWidth + 10, metrics.lineSpacing() + 5);
+    painter.setPen(Qt::white);
+    painter.drawText((width() - textWidth) / 2, metrics.leading() + metrics.ascent(), text);
+}
+
+void MandelbrotWidget::resizeEvent(QResizeEvent* /* event */)
+{
+    thread.render(centerX, centerY, curScale, size(), devicePixelRatioF());
+}
+
+void MandelbrotWidget::keyPressEvent(QKeyEvent* event)
+{
+    switch (event->key())
+    {
+        case Qt::Key_Plus:
+            zoom(ZoomInFactor);
+            break;
+        case Qt::Key_Minus:
+            zoom(ZoomOutFactor);
+            break;
+        case Qt::Key_Left:
+            scroll(-ScrollStep, 0);
+            break;
+        case Qt::Key_Right:
+            scroll(+ScrollStep, 0);
+            break;
+        case Qt::Key_Down:
+            scroll(0, -ScrollStep);
+            break;
+        case Qt::Key_Up:
+            scroll(0, +ScrollStep);
+            break;
+        default:
+            QWidget::keyPressEvent(event);
+    }
+}
+
+#if QT_CONFIG(wheelevent)
+void MandelbrotWidget::wheelEvent(QWheelEvent* event)
+{
+    const int numDegrees = event->angleDelta().y() / 8;
+    const double numSteps = numDegrees / double(15);
+    zoom(pow(ZoomInFactor, numSteps));
+}
+#endif
+
+void MandelbrotWidget::mousePressEvent(QMouseEvent* event)
+{
+    if (event->button() == Qt::LeftButton)
+        lastDragPos = event->pos();
+}
+
+void MandelbrotWidget::mouseMoveEvent(QMouseEvent* event)
+{
+    if (event->buttons() & Qt::LeftButton)
+    {
+        pixmapOffset += event->pos() - lastDragPos;
+        lastDragPos = event->pos();
+        update();
+    }
+}
+
+void MandelbrotWidget::mouseReleaseEvent(QMouseEvent* event)
+{
+    if (event->button() == Qt::LeftButton)
+    {
+        pixmapOffset += event->pos() - lastDragPos;
+        lastDragPos = QPoint();
+
+        const auto pixmapSize = pixmap.size() / pixmap.devicePixelRatioF();
+        int deltaX = (width() - pixmapSize.width()) / 2 - pixmapOffset.x();
+        int deltaY = (height() - pixmapSize.height()) / 2 - pixmapOffset.y();
+        scroll(deltaX, deltaY);
+    }
+}
+
+void MandelbrotWidget::updatePixmap(const QImage& image, double scaleFactor)
+{
+    if (!lastDragPos.isNull())
+        return;
+
+    pixmap = QPixmap::fromImage(image);
+    pixmapOffset = QPoint();
+    lastDragPos = QPoint();
+    pixmapScale = scaleFactor;
+    update();
+}
+
+void MandelbrotWidget::zoom(double zoomFactor)
+{
+    curScale *= zoomFactor;
+    update();
+    thread.render(centerX, centerY, curScale, size(), devicePixelRatioF());
+}
+
+void MandelbrotWidget::scroll(int deltaX, int deltaY)
+{
+    centerX += deltaX * curScale;
+    centerY += deltaY * curScale;
+    update();
+    thread.render(centerX, centerY, curScale, size(), devicePixelRatioF());
+}
diff --git a/wasm/source/qt5-mandelbrot/mandelbrotwidget.h b/wasm/source/qt5-mandelbrot/mandelbrotwidget.h
new file mode 100644
index 000000000000..72e95568b522
--- /dev/null
+++ b/wasm/source/qt5-mandelbrot/mandelbrotwidget.h
@@ -0,0 +1,91 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+**   * Redistributions of source code must retain the above copyright
+**     notice, this list of conditions and the following disclaimer.
+**   * 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.
+**   * Neither the name of The Qt Company Ltd nor the names of its
+**     contributors may be used to endorse or promote products derived

... etc. - the rest is truncated


More information about the Libreoffice-commits mailing list