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>
This commit is contained in:
parent
db9e206dee
commit
1f6cac0da9
@ -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()
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
@ -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}")
|
||||
|
@ -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()
|
||||
|
@ -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;
|
||||
|
@ -57,7 +57,7 @@
|
||||
exitData.text !== undefined ? ` (${exitData.text})` : '';
|
||||
showUi(spinner);
|
||||
},
|
||||
entryFunction: window.createQtAppInstance,
|
||||
entryFunction: window.@APPNAME@_entry,
|
||||
containerElements: [screen],
|
||||
}
|
||||
});
|
||||
|
@ -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")],
|
||||
});
|
||||
}
|
||||
|
@ -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>
|
||||
|
@ -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>
|
||||
|
@ -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.
|
||||
|
@ -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>
|
||||
|
@ -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>
|
||||
|
@ -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>
|
||||
|
@ -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 {
|
||||
|
@ -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>
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user