summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMikolaj Boc <mikolaj.boc@qt.io>2022-12-29 17:54:29 +0100
committerMikolaj Boc <mikolaj.boc@qt.io>2023-06-20 09:08:03 +0200
commit1f6cac0da9c31b67f5cb5850ce52a4622e57b4d5 (patch)
treec053e1b0e4d39c2436c150eb4208ecab6023bad3
parentdb9e206deecab7b78dd2177d4bcaf6415fb84c94 (diff)
Make WASM export names different across modules
The export name is now ${TARGET_NAME}Entry. This can also be overridden by using QT_WASM_EXPORT_NAME, both in CMake and qmake Change-Id: I59c97ae6e22f0b2720716e9d7eff7b6b13d37ab5 Reviewed-by: Morten Johan Sørvig <morten.sorvig@qt.io>
-rw-r--r--cmake/QtWasmHelpers.cmake12
-rw-r--r--mkspecs/common/wasm/wasm.conf1
-rw-r--r--mkspecs/features/wasm/wasm.prf7
-rw-r--r--src/corelib/Qt6CoreMacros.cmake1
-rw-r--r--src/corelib/Qt6WasmMacros.cmake9
-rw-r--r--src/plugins/platforms/wasm/qtloader.js2
-rw-r--r--src/plugins/platforms/wasm/wasm_shell.html2
-rw-r--r--tests/manual/wasm/a11y/basic_widgets/basic_widgets.html2
-rw-r--r--tests/manual/wasm/eventloop/eventloop_auto/eventloop_auto.html2
-rw-r--r--tests/manual/wasm/eventloop/eventloop_auto/eventloop_auto_asyncify.html2
-rw-r--r--tests/manual/wasm/network/sockify_sockets_auto/sockify_sockets_auto.html2
-rw-r--r--tests/manual/wasm/qstdweb/files_auto.html2
-rw-r--r--tests/manual/wasm/qstdweb/promise_auto.html2
-rw-r--r--tests/manual/wasm/qstdweb/qwasmcompositor_auto.html2
-rw-r--r--tests/manual/wasm/qtloader_integration/test_body.js56
-rw-r--r--tests/manual/wasm/qtwasmtestlib/README.md4
-rw-r--r--tests/manual/wasm/qtwasmtestlib/qtwasmtestlib.js10
-rw-r--r--util/wasm/batchedtestrunner/qwasmjsruntime.js10
18 files changed, 82 insertions, 46 deletions
diff --git a/cmake/QtWasmHelpers.cmake b/cmake/QtWasmHelpers.cmake
index 3eb97fa3cb..2b3a97987f 100644
--- a/cmake/QtWasmHelpers.cmake
+++ b/cmake/QtWasmHelpers.cmake
@@ -18,14 +18,9 @@ function (qt_internal_setup_wasm_target_properties wasmTarget)
target_compile_options("${wasmTarget}" INTERFACE "SHELL:-s MEMORY64=1" )
target_link_options("${wasmTarget}" INTERFACE "SHELL:-s MEMORY64=1" -mwasm64)
endif()
- # Enable MODULARIZE and set EXPORT_NAME, which makes it possible to
- # create application instances using a global constructor function,
- # e.g. let app_instance = await createQtAppInstance().
- # (as opposed to MODULARIZE=0, where Emscripten creates a global app
- # instance object at Javascript eval time)
- target_link_options("${wasmTarget}" INTERFACE
- "SHELL:-s MODULARIZE=1"
- "SHELL:-s EXPORT_NAME=createQtAppInstance")
+ # Enable MODULARIZE so that we are able to set EXPORT_NAME later and instantiate on demand (with
+ # MODULARIZE=0, emscripten creates a global app instance object at Javascript eval time)
+ target_link_options("${wasmTarget}" INTERFACE "SHELL:-s MODULARIZE=1")
#simd
if (QT_FEATURE_wasm_simd128)
@@ -126,6 +121,7 @@ function (qt_internal_setup_wasm_target_properties wasmTarget)
endfunction()
function(qt_internal_wasm_add_finalizers target)
+ qt_add_list_file_finalizer(_qt_internal_set_wasm_export_name ${target})
qt_add_list_file_finalizer(_qt_internal_add_wasm_extra_exported_methods ${target})
qt_add_list_file_finalizer(_qt_internal_wasm_add_target_helpers ${target})
endfunction()
diff --git a/mkspecs/common/wasm/wasm.conf b/mkspecs/common/wasm/wasm.conf
index b67d721352..adad999200 100644
--- a/mkspecs/common/wasm/wasm.conf
+++ b/mkspecs/common/wasm/wasm.conf
@@ -35,7 +35,6 @@ EMCC_COMMON_LFLAGS += \
--bind \
-s FETCH=1 \
-s MODULARIZE=1 \
- -s EXPORT_NAME=createQtAppInstance \
-s WASM_BIGINT=1 \
-s STACK_SIZE=5MB
diff --git a/mkspecs/features/wasm/wasm.prf b/mkspecs/features/wasm/wasm.prf
index 0256fc2e49..72007fe863 100644
--- a/mkspecs/features/wasm/wasm.prf
+++ b/mkspecs/features/wasm/wasm.prf
@@ -15,6 +15,13 @@ exists($$QMAKE_QT_CONFIG) {
}
EMCC_LFLAGS += -s EXPORTED_RUNTIME_METHODS=$$EXPORTED_METHODS
+ !isEmpty(QT_WASM_EXPORT_NAME): {
+ EXPORT_NAME = $$QT_WASM_EXPORT_NAME
+ } else {
+ EXPORT_NAME = $${TARGET}_entry
+ }
+ EMCC_LFLAGS += -s EXPORT_NAME=$$EXPORT_NAME
+
qtConfig(thread) {
EMCC_LFLAGS += -pthread
diff --git a/src/corelib/Qt6CoreMacros.cmake b/src/corelib/Qt6CoreMacros.cmake
index abffd2026e..3347f39829 100644
--- a/src/corelib/Qt6CoreMacros.cmake
+++ b/src/corelib/Qt6CoreMacros.cmake
@@ -656,6 +656,7 @@ function(_qt_internal_finalize_executable target)
if(EMSCRIPTEN)
_qt_internal_wasm_add_target_helpers("${target}")
_qt_internal_add_wasm_extra_exported_methods("${target}")
+ _qt_internal_set_wasm_export_name("${target}")
endif()
if(IOS)
_qt_internal_finalize_ios_app("${target}")
diff --git a/src/corelib/Qt6WasmMacros.cmake b/src/corelib/Qt6WasmMacros.cmake
index 6e004dc862..188ed28fe4 100644
--- a/src/corelib/Qt6WasmMacros.cmake
+++ b/src/corelib/Qt6WasmMacros.cmake
@@ -104,3 +104,12 @@ function(_qt_internal_add_wasm_extra_exported_methods target)
)
endif()
endfunction()
+
+function(_qt_internal_set_wasm_export_name target)
+ get_target_property(export_name "${target}" QT_WASM_EXPORT_NAME)
+ if(export_name)
+ target_link_options("${target}" PRIVATE "SHELL:-s EXPORT_NAME=${export_name}")
+ else()
+ target_link_options("${target}" PRIVATE "SHELL:-s EXPORT_NAME=${target}_entry")
+ endif()
+endfunction()
diff --git a/src/plugins/platforms/wasm/qtloader.js b/src/plugins/platforms/wasm/qtloader.js
index c62b3f8823..1d1e7fb6d1 100644
--- a/src/plugins/platforms/wasm/qtloader.js
+++ b/src/plugins/platforms/wasm/qtloader.js
@@ -49,7 +49,7 @@ async function qtLoad(config)
if (typeof config.qt !== 'object')
throw new Error('config.qt is required, expected an object');
if (typeof config.qt.entryFunction !== 'function')
- config.qt.entryFunction = window.createQtAppInstance;
+ throw new Error('config.qt.entryFunction is required, expected a function');
config.qtContainerElements = config.qt.containerElements;
delete config.qt.containerElements;
diff --git a/src/plugins/platforms/wasm/wasm_shell.html b/src/plugins/platforms/wasm/wasm_shell.html
index 9924890122..2287e3fad2 100644
--- a/src/plugins/platforms/wasm/wasm_shell.html
+++ b/src/plugins/platforms/wasm/wasm_shell.html
@@ -57,7 +57,7 @@
exitData.text !== undefined ? ` (${exitData.text})` : '';
showUi(spinner);
},
- entryFunction: window.createQtAppInstance,
+ entryFunction: window.@APPNAME@_entry,
containerElements: [screen],
}
});
diff --git a/tests/manual/wasm/a11y/basic_widgets/basic_widgets.html b/tests/manual/wasm/a11y/basic_widgets/basic_widgets.html
index 899e72bb00..091809be5c 100644
--- a/tests/manual/wasm/a11y/basic_widgets/basic_widgets.html
+++ b/tests/manual/wasm/a11y/basic_widgets/basic_widgets.html
@@ -7,7 +7,7 @@
<script>
window.onload = async () => {
- let qt_instance = await createQtAppInstance({
+ let qt_instance = await a11y_basic_widgets_entry({
qtContainerElements: [document.getElementById("qt_container")],
});
}
diff --git a/tests/manual/wasm/eventloop/eventloop_auto/eventloop_auto.html b/tests/manual/wasm/eventloop/eventloop_auto/eventloop_auto.html
index 7ff9d8e7f2..e8e35abcbb 100644
--- a/tests/manual/wasm/eventloop/eventloop_auto/eventloop_auto.html
+++ b/tests/manual/wasm/eventloop/eventloop_auto/eventloop_auto.html
@@ -3,7 +3,7 @@
<script type="text/javascript" src="eventloop_auto.js"></script>
<script>
window.onload = () => {
- runTestCase(document.getElementById("log"));
+ runTestCase(eventloop_auto_entry, document.getElementById("log"));
};
</script>
<p>Running event dispatcher auto test.</p>
diff --git a/tests/manual/wasm/eventloop/eventloop_auto/eventloop_auto_asyncify.html b/tests/manual/wasm/eventloop/eventloop_auto/eventloop_auto_asyncify.html
index a277c9b9e0..f09b29d85b 100644
--- a/tests/manual/wasm/eventloop/eventloop_auto/eventloop_auto_asyncify.html
+++ b/tests/manual/wasm/eventloop/eventloop_auto/eventloop_auto_asyncify.html
@@ -3,7 +3,7 @@
<script type="text/javascript" src="eventloop_auto_asyncify.js"></script>
<script>
window.onload = () => {
- runTestCase(document.getElementById("log"));
+ runTestCase(eventloop_auto_asyncify_entry, document.getElementById("log"));
};
</script>
<p>Running event dispatcher auto test.</p>
diff --git a/tests/manual/wasm/network/sockify_sockets_auto/sockify_sockets_auto.html b/tests/manual/wasm/network/sockify_sockets_auto/sockify_sockets_auto.html
index 5376249a71..080ada94e7 100644
--- a/tests/manual/wasm/network/sockify_sockets_auto/sockify_sockets_auto.html
+++ b/tests/manual/wasm/network/sockify_sockets_auto/sockify_sockets_auto.html
@@ -3,7 +3,7 @@
<script type="text/javascript" src="sockify_sockets_auto.js"></script>
<script>
window.onload = async () => {
- runTestCase(document.getElementById("log"));
+ runTestCase(sockify_sockets_auto_entry, document.getElementById("log"));
};
</script>
<p> Sockify tunneled sockets auto test.
diff --git a/tests/manual/wasm/qstdweb/files_auto.html b/tests/manual/wasm/qstdweb/files_auto.html
index 71e8088dfb..9027fdc660 100644
--- a/tests/manual/wasm/qstdweb/files_auto.html
+++ b/tests/manual/wasm/qstdweb/files_auto.html
@@ -6,7 +6,7 @@
<script type="text/javascript" src="files_auto.js"></script>
<script>
window.onload = () => {
- runTestCase(document.getElementById("log"));
+ runTestCase(files_auto_entry, document.getElementById("log"));
};
</script>
<p>Running files auto test.</p>
diff --git a/tests/manual/wasm/qstdweb/promise_auto.html b/tests/manual/wasm/qstdweb/promise_auto.html
index 786145419f..94a8dbb88a 100644
--- a/tests/manual/wasm/qstdweb/promise_auto.html
+++ b/tests/manual/wasm/qstdweb/promise_auto.html
@@ -3,7 +3,7 @@
<script type="text/javascript" src="promise_auto.js"></script>
<script>
window.onload = () => {
- runTestCase(document.getElementById("log"));
+ runTestCase(promise_auto_entry, document.getElementById("log"));
};
</script>
<p>Running promise auto test.</p>
diff --git a/tests/manual/wasm/qstdweb/qwasmcompositor_auto.html b/tests/manual/wasm/qstdweb/qwasmcompositor_auto.html
index 26daecdf41..f33aab0b9c 100644
--- a/tests/manual/wasm/qstdweb/qwasmcompositor_auto.html
+++ b/tests/manual/wasm/qstdweb/qwasmcompositor_auto.html
@@ -3,7 +3,7 @@
<script type="text/javascript" src="qwasmcompositor_auto.js"></script>
<script>
window.onload = () => {
- runTestCase(document.getElementById("log"));
+ runTestCase(qwasmcompositor_auto_entry, document.getElementById("log"));
};
</script>
<p>Running files auto test.</p>
diff --git a/tests/manual/wasm/qtloader_integration/test_body.js b/tests/manual/wasm/qtloader_integration/test_body.js
index d68c6ba8cc..385a3816d3 100644
--- a/tests/manual/wasm/qtloader_integration/test_body.js
+++ b/tests/manual/wasm/qtloader_integration/test_body.js
@@ -48,10 +48,32 @@ export class QtLoaderIntegrationTests
'config.qt is required, expected an object', caughtException.message);
}
- async useDefaultOnMissingEntryFunction()
+ async missingEntryFunction()
{
- const instance = await qtLoad({ arguments: ['--no-gui'], qt: {}});
- assert.isNotUndefined(instance);
+ let caughtException;
+ try {
+ await qtLoad({ qt: {}});
+ } catch (e) {
+ caughtException = e;
+ }
+
+ assert.isNotUndefined(caughtException);
+ assert.equal(
+ 'config.qt.entryFunction is required, expected a function', caughtException.message);
+ }
+
+ async badEntryFunction()
+ {
+ let caughtException;
+ try {
+ await qtLoad({ qt: { entryFunction: 'invalid' }});
+ } catch (e) {
+ caughtException = e;
+ }
+
+ assert.isNotUndefined(caughtException);
+ assert.equal(
+ 'config.qt.entryFunction is required, expected a function', caughtException.message);
}
async environmentVariables()
@@ -62,7 +84,7 @@ export class QtLoaderIntegrationTests
variable1: 'value1',
variable2: 'value2'
},
- entryFunction: createQtAppInstance,
+ entryFunction: tst_qtloader_integration_entry,
containerElements: [this.#testScreenContainers[0]]
}
});
@@ -79,7 +101,7 @@ export class QtLoaderIntegrationTests
const instance = await qtLoad({
qt: {
- entryFunction: createQtAppInstance,
+ entryFunction: tst_qtloader_integration_entry,
containerElements: this.#testScreenContainers
}
});
@@ -125,7 +147,7 @@ export class QtLoaderIntegrationTests
{
const instance = await qtLoad({
qt: {
- entryFunction: createQtAppInstance,
+ entryFunction: tst_qtloader_integration_entry,
containerElements: this.#testScreenContainers,
}
});
@@ -181,7 +203,7 @@ export class QtLoaderIntegrationTests
const instances = await Promise.all([1, 2, 3].map(i => qtLoad({
qt: {
- entryFunction: createQtAppInstance,
+ entryFunction: tst_qtloader_integration_entry,
containerElements: [this.#addScreenContainer(`screen-container-${i}`, {
width: `${i * 10}px`,
height: `${i * 10}px`,
@@ -222,7 +244,7 @@ export class QtLoaderIntegrationTests
accumulatedStdout += output;
},
qt: {
- entryFunction: createQtAppInstance,
+ entryFunction: tst_qtloader_integration_entry,
}
});
@@ -246,7 +268,7 @@ export class QtLoaderIntegrationTests
{
await qtLoad({
qt: {
- entryFunction: createQtAppInstance,
+ entryFunction: tst_qtloader_integration_entry,
containerElements: [this.#testScreenContainers[0]],
module: await WebAssembly.compileStreaming(
fetch('tst_qtloader_integration.wasm'))
@@ -259,7 +281,7 @@ export class QtLoaderIntegrationTests
const instance = await qtLoad({
arguments: ['--no-gui', 'arg1', 'other', 'yetanotherarg'],
qt: {
- entryFunction: createQtAppInstance,
+ entryFunction: tst_qtloader_integration_entry,
}
});
const args = this.#callTestInstanceApi(instance, 'retrieveArguments');
@@ -275,7 +297,7 @@ export class QtLoaderIntegrationTests
try {
await qtLoad({
qt: {
- entryFunction: createQtAppInstance,
+ entryFunction: tst_qtloader_integration_entry,
containerElements: [this.#testScreenContainers[0]],
module: Promise.reject(new Error('Failed to load')),
}
@@ -294,7 +316,7 @@ export class QtLoaderIntegrationTests
arguments: ['--no-gui'],
qt: {
onExit: onExitMock,
- entryFunction: createQtAppInstance,
+ entryFunction: tst_qtloader_integration_entry,
}
});
try {
@@ -316,7 +338,7 @@ export class QtLoaderIntegrationTests
arguments: ['--no-gui', '--crash-immediately'],
qt: {
onExit: onExitMock,
- entryFunction: createQtAppInstance,
+ entryFunction: tst_qtloader_integration_entry,
}
});
} catch (e) {
@@ -340,7 +362,7 @@ export class QtLoaderIntegrationTests
arguments: ['--no-gui'],
onAbort: onAbortMock,
qt: {
- entryFunction: createQtAppInstance,
+ entryFunction: tst_qtloader_integration_entry,
}
});
try {
@@ -358,7 +380,7 @@ export class QtLoaderIntegrationTests
arguments: ['--no-gui'],
qt: {
onExit: onExitMock,
- entryFunction: createQtAppInstance,
+ entryFunction: tst_qtloader_integration_entry,
}
});
// The module is running. onExit should not have been called.
@@ -383,7 +405,7 @@ export class QtLoaderIntegrationTests
arguments: ['--no-gui', '--exit-immediately'],
qt: {
onExit: onExitMock,
- entryFunction: createQtAppInstance,
+ entryFunction: tst_qtloader_integration_entry,
}
});
assert.equal(1, onExitMock.calls.length);
@@ -402,7 +424,7 @@ export class QtLoaderIntegrationTests
arguments: ['--no-gui'],
quit: quitMock,
qt: {
- entryFunction: createQtAppInstance,
+ entryFunction: tst_qtloader_integration_entry,
}
});
try {
diff --git a/tests/manual/wasm/qtwasmtestlib/README.md b/tests/manual/wasm/qtwasmtestlib/README.md
index 515c33ae6a..6de81fe8b4 100644
--- a/tests/manual/wasm/qtwasmtestlib/README.md
+++ b/tests/manual/wasm/qtwasmtestlib/README.md
@@ -48,7 +48,7 @@ Finally provide an html file which hosts the test runner and calls runTestCase()
<script type="text/javascript" src="test_case.js"></script>
<script>
window.onload = async () => {
- runTestCase(document.getElementById("log"));
+ runTestCase(entryFunction, document.getElementById("log"));
};
</script>
<p>Running Foo auto test.</p>
@@ -67,7 +67,7 @@ html file provides container elements which becomes QScreens for the test code.
window.onload = async () => {
let log = document.getElementById("log")
let containers = [document.getElementById("container")];
- runTestCase(log, containers);
+ runTestCase(entryFunction, log, containers);
};
</script>
<p>Running Foo auto test.</p>
diff --git a/tests/manual/wasm/qtwasmtestlib/qtwasmtestlib.js b/tests/manual/wasm/qtwasmtestlib/qtwasmtestlib.js
index eaf518d1ef..01003f30f9 100644
--- a/tests/manual/wasm/qtwasmtestlib/qtwasmtestlib.js
+++ b/tests/manual/wasm/qtwasmtestlib/qtwasmtestlib.js
@@ -77,12 +77,13 @@ async function runTestFunction(instance, name) {
}
}
-async function runTestCaseImpl(testFunctionStarted, testFunctionCompleted, qtContainers) {
+async function runTestCaseImpl(entryFunction, testFunctionStarted, testFunctionCompleted, qtContainers)
+{
// Create test case instance
const config = {
qtContainerElements: qtContainers || []
}
- const instance = await createQtAppInstance(config);
+ const instance = await entryFunction(config);
// Run all test functions
const functionsString = instance.getTestFunctions();
@@ -124,10 +125,11 @@ function testFunctionCompleted(status) {
g_htmlLogElement.innerHTML += line;
}
-async function runTestCase(htmlLogElement, qtContainers) {
+async function runTestCase(entryFunction, htmlLogElement, qtContainers)
+{
g_htmlLogElement = htmlLogElement;
try {
- await runTestCaseImpl(testFunctionStarted, testFunctionCompleted, qtContainers);
+ await runTestCaseImpl(entryFunction, testFunctionStarted, testFunctionCompleted, qtContainers);
g_htmlLogElement.innerHTML += "<br> DONE"
} catch (err) {
g_htmlLogElement.innerHTML += err
diff --git a/util/wasm/batchedtestrunner/qwasmjsruntime.js b/util/wasm/batchedtestrunner/qwasmjsruntime.js
index b8603f2618..d973914cd3 100644
--- a/util/wasm/batchedtestrunner/qwasmjsruntime.js
+++ b/util/wasm/batchedtestrunner/qwasmjsruntime.js
@@ -109,18 +109,18 @@ export class CompiledModule {
this.#resourceLocator = resourceLocator;
}
- static make(js, wasm, resourceLocator
+ static make(js, wasm, entryFunctionName, resourceLocator
) {
const exports = {};
eval(js);
- if (!exports.createQtAppInstance) {
+ if (!exports[entryFunctionName]) {
throw new Error(
- 'createQtAppInstance has not been exported by the main script'
+ '${entryFunctionName} has not been exported by the main script'
);
}
return new CompiledModule(
- exports.createQtAppInstance, js, wasm, resourceLocator
+ exports[entryFunctionName], js, wasm, resourceLocator
);
}
@@ -218,6 +218,6 @@ export class ModuleLoader {
);
const [js, wasm] = await Promise.all([jsLoadPromise, wasmLoadPromise]);
- return CompiledModule.make(js, wasm, this.#resourceLocator);
+ return CompiledModule.make(js, wasm, `${moduleName}_entry`, this.#resourceLocator);
}
}