Building Qt Apps to Wasm

• I'm having difficulties building the Notepad app described in the Getting Started Tutorial to Wasm. I've managed to get it to work fine when using the MSVC compiler through Qt Creator, but I just can't get it to compile with Emscripten. I opened an issue on the Emscripten GitHub and thought I should open this thread here as well.

I redirected the build output to a file. That's on Gist; here's a link to it.

The Emscripten GitHub issue also has the code posted. For some reason the "Select Font" dialog box comes up twice whenever I click on that button. I'd like some help on that as well.

• Currently, Qt for WebAssembly only builds using mingw32 on windows.

• What do I do after installing Mingw and sed and adding them to my system PATH variable? I did that and tried running this command again:

em++ -std=c++17 -Wall -pedantic -I "C:/Qt/5.13.1/wasm_32/include" -I "C:/Qt/5.13.1/wasm_32/include/QtCore" -I "C:/Qt/5.13.1/wasm_32/include/QtPrintSupport" -I "C:/Qt/5.13.1/wasm_32/include/QtWidgets" -L "C:/Qt/5.13.1/wasm_32/lib" main.cpp notepad.cpp -s WASM=1 -s EXPORT_ALL=1 -o notepad.js


but it still fails with the same message.

Edit: I ran qmake and nmake, but got this error:

shared:ERROR: BINARYEN_TRAP_MODE is not supported by the LLVM wasm backend
NMAKE : fatal error U1077: 'C:\emsdk\upstream\emscripten\em++.BAT' : return code '0x1'
Stop.


Do you guys know how to make it work with the Wasm backend, or should I try asking at the Emscripten GitHub page? The LLVM Wasm backend is the latest, tip-of-the-tree build of vanilla LLVM. It can be installed with the latest-upstream package (emsdk install latest-upstream).

• What do I do after installing Mingw and sed and adding them to my system PATH variable? I did that and tried running this command again:

em++ -std=c++17 -Wall -pedantic -I "C:/Qt/5.13.1/wasm_32/include" -I "C:/Qt/5.13.1/wasm_32/include/QtCore" -I "C:/Qt/5.13.1/wasm_32/include/QtPrintSupport" -I "C:/Qt/5.13.1/wasm_32/include/QtWidgets" -L "C:/Qt/5.13.1/wasm_32/lib" main.cpp notepad.cpp -s WASM=1 -s EXPORT_ALL=1 -o notepad.js


but it still fails with the same message.

Edit: I ran qmake and nmake, but got this error:

It will not work using nmake either, for various reasons. You must use mingw32-make

shared:ERROR: BINARYEN_TRAP_MODE is not supported by the LLVM wasm backend
NMAKE : fatal error U1077: 'C:\emsdk\upstream\emscripten\em++.BAT' : return code '0x1'
Stop.


What version of Qt are you trying to build?

https://wiki.qt.io/Qt_for_WebAssembly
Qt 5.12: 1.38.16

Do you guys know how to make it work with the Wasm backend, or should I try asking at the Emscripten GitHub page?  The LLVM Wasm backend is the latest, tip-of-the-tree build of vanilla LLVM.  It can be installed with the latest-upstream package (emsdk install latest-upstream).

• What do I do after installing Mingw and sed and adding them to my system PATH variable? I did that and tried running this command again:

em++ -std=c++17 -Wall -pedantic -I "C:/Qt/5.13.1/wasm_32/include" -I "C:/Qt/5.13.1/wasm_32/include/QtCore" -I "C:/Qt/5.13.1/wasm_32/include/QtPrintSupport" -I "C:/Qt/5.13.1/wasm_32/include/QtWidgets" -L "C:/Qt/5.13.1/wasm_32/lib" main.cpp notepad.cpp -s WASM=1 -s EXPORT_ALL=1 -o notepad.js


but it still fails with the same message.

Edit: I ran qmake and nmake, but got this error:

It will not work using nmake either, for various reasons. You must use mingw32-make

shared:ERROR: BINARYEN_TRAP_MODE is not supported by the LLVM wasm backend
NMAKE : fatal error U1077: 'C:\emsdk\upstream\emscripten\em++.BAT' : return code '0x1'
Stop.


What version of Qt are you trying to build?

https://wiki.qt.io/Qt_for_WebAssembly
Qt 5.12: 1.38.16

Do you guys know how to make it work with the Wasm backend, or should I try asking at the Emscripten GitHub page?  The LLVM Wasm backend is the latest, tip-of-the-tree build of vanilla LLVM.  It can be installed with the latest-upstream package (emsdk install latest-upstream).


I'm not building Qt. I installed Qt 5.13.1 binaries. I'm trying to build the Notepad App to Wasm (from the Getting Started Guide (I already built it natively in Qt Creator)).

The problem I'm having right now is that the Makefile that the qmake program generated for the Notepad app has BINARYEN_TRAP_MODE set which for the Emscripten Wasm backend is bad. But even after removing that I still get errors.

• What do I do after installing Mingw and sed and adding them to my system PATH variable? I did that and tried running this command again:

em++ -std=c++17 -Wall -pedantic -I "C:/Qt/5.13.1/wasm_32/include" -I "C:/Qt/5.13.1/wasm_32/include/QtCore" -I "C:/Qt/5.13.1/wasm_32/include/QtPrintSupport" -I "C:/Qt/5.13.1/wasm_32/include/QtWidgets" -L "C:/Qt/5.13.1/wasm_32/lib" main.cpp notepad.cpp -s WASM=1 -s EXPORT_ALL=1 -o notepad.js


but it still fails with the same message.

Edit: I ran qmake and nmake, but got this error:

It will not work using nmake either, for various reasons. You must use mingw32-make

shared:ERROR: BINARYEN_TRAP_MODE is not supported by the LLVM wasm backend
NMAKE : fatal error U1077: 'C:\emsdk\upstream\emscripten\em++.BAT' : return code '0x1'
Stop.


What version of Qt are you trying to build?

https://wiki.qt.io/Qt_for_WebAssembly
Qt 5.12: 1.38.16

Do you guys know how to make it work with the Wasm backend, or should I try asking at the Emscripten GitHub page?  The LLVM Wasm backend is the latest, tip-of-the-tree build of vanilla LLVM.  It can be installed with the latest-upstream package (emsdk install latest-upstream).


I'm not building Qt. I installed Qt 5.13.1 binaries. I'm trying to build the Notepad App to Wasm (from the Getting Started Guide (I already built it natively in Qt Creator)).

The problem I'm having right now is that the Makefile that the qmake program generated for the Notepad app has BINARYEN_TRAP_MODE set which for the Emscripten Wasm backend is bad. But even after removing that I still get errors.

That is because 5.13 needs emscripten 1.38.27 or 1.38.30.
Thats said, if you apply this patch https://codereview.qt-project.org/c/qt/qtbase/+/266814/2/mkspecs/wasm-emscripten/qmake.conf

To the mkspec/wasm-emscripten/qmake.conf file for the Qt you are using, it should compile.
Or you can just remove that line too.

• I installed the latest version of Emscripten. I did need to execute git pull just now though. But it could be that the version I have is too new for Qt (could that be the case?).

By the way. Do you understand what I mean when I say "Emscripten Wasm backend"? That's the backend I'm using. It's the one using LLVM without the Emscripten changes to LLVM. Basically "vanilla" LLVM which you need the latest tip-of-the-tree version of. Later than the current stable version. The regular backend is called the Fastcomp backend. I heard they're going to make the Wasm backend the default backend. And the BINARYEN_TRAP_MODE setting being used is bad for the Wasm backend. (I don't mean to look down on you or anything. I'm really just checking to make sure we're on the same page here.)

I don't understand what the condition is in the Makefile that has to be false for the EMCC_COMMON_LFLAGS += -s \"BINARYEN_TRAP_MODE=\'clamp\'\" line to be added in its else clause. What kind of object files is it looking for?

• I installed the latest version of Emscripten. I did need to execute git pull just now though. But it could be that the version I have is too new for Qt (could that be the case?).

By the way. Do you understand what I mean when I say "Emscripten Wasm backend"? That's the backend I'm using. It's the one using LLVM without the Emscripten changes to LLVM. Basically "vanilla" LLVM which you need the latest tip-of-the-tree version of. Later than the current stable version. The regular backend is called the Fastcomp backend. I heard they're going to make the Wasm backend the default backend. And the BINARYEN_TRAP_MODE setting being used is bad for the Wasm backend. (I don't mean to look down on you or anything. I'm really just checking to make sure we're on the same page here.)

I don't understand what the condition is in the Makefile that has to be false for the EMCC_COMMON_LFLAGS += -s \"BINARYEN_TRAP_MODE=\'clamp\'\" line to be added in its else clause. What kind of object files is it looking for?

Yes, I am well aware of emscripten/wasm issues.

To use wasm object files, you need to have a Qt built using -device-option=WASM_OBJECT_FILES=1, which will use emscripten upstream to bypass creating the intermediate javascript file when transpiling to wasm. This speeds up linking time.

The Qt released binaries were not built using the new upstream backend.

Apparently we need another check to detect when using the upstream emscripten and not apply the clamp mode.

You can either:

• install and use emscripten 1.38.27 without the benefit of wasm object files, and will work correctly with Qt webassembly binaries.
• edit the wasm-emscripten/qmake.conf file and simply remove the clamp mode line, and hope things work correctly due to mis-matched emscripten versions

• If I apply the patch, will I not get the JavaScript glue code? Because I do want that along with the .wasm file.

What part of the Makefile should the patch go in? Is there a way to directly install the patch so that whenever I generate a Makefile the patch will be in it?

• @DragonOsman
You will still get glue code. The clamp mode only tells emscripten what to do in case of a javascript overflow, which the wasm binaries does not have an issue with.

Remove the clamp line from ~/Qt/<version>/wasm_32/mkspecs/wasm-emscripten/qmake.conf
or whereever you installed Qt

• Is there something I need to add in place of the clamp mode line? Because I do get a whole bunch of errors and exceptions from Python when I run nmake after removing the clamp mode line from the Makefile. Is it okay to assume that it'll work fine if I change the .conf file instead of the Makefile?

Edit: This is my qmake.conf file now:

# qmake configuration for building with emscripten
MAKEFILE_GENERATOR      = UNIX
QMAKE_PLATFORM          = wasm unix

include(../common/gcc-base.conf)
include(../common/clang.conf)

# Support setting WASM_OBJECT_FILES with -device-option WASM_OBJECT_FILES=1
!isEmpty(WASM_OBJECT_FILES): {
!equals(WASM_OBJECT_FILES, 1):!equals(WASM_OBJECT_FILES, 0): \
message(Error: The value for WASM_OBJECT_FILES must be 0 or 1)
QMAKE_CFLAGS += -s WASM_OBJECT_FILES=$$WASM_OBJECT_FILES QMAKE_CXXFLAGS += -s WASM_OBJECT_FILES=$$WASM_OBJECT_FILES
QMAKE_LFLAGS += -s WASM_OBJECT_FILES=$$WASM_OBJECT_FILES } else { EMCC_COMMON_LFLAGS += -s \"BINARYEN_TRAP_MODE=\'clamp\'\" } EMTERP_FLAGS = \ -s EMTERPRETIFY=1 \ -s EMTERPRETIFY_ASYNC=1 \ -s \"EMTERPRETIFY_FILE=\'data.binary\'\" \ -s ASSERTIONS=1 \ --profiling-funcs EMCC_COMMON_LFLAGS = \ -s WASM=1 \ -s FULL_ES2=1 \ -s USE_WEBGL2=1 \ -s NO_EXIT_RUNTIME=0 \ -s ERROR_ON_UNDEFINED_SYMBOLS=1 \ --bind # The -s arguments can also be used with release builds, # but are here in debug for clarity. EMCC_COMMON_LFLAGS_DEBUG = \$$EMCC_COMMON_LFLAGS \
-s ASSERTIONS=2 \
-s DEMANGLE_SUPPORT=1 \
# -s LIBRARY_DEBUG=1 \ #print out library calls, verbose
# -s SYSCALL_DEBUG=1 \ #print out sys calls, verbose
# -s FS_LOG=1 \ #print out filesystem ops, verbose
# -s SOCKET_DEBUG \ #print out socket,network data transfer
-s GL_DEBUG=1

# Set up debug/optimization flags
QMAKE_CXXFLAGS_RELEASE -= -O2
QMAKE_CFLAGS_RELEASE   -= -O2
equals(WASM_OBJECT_FILES, 1) {
QMAKE_LFLAGS_DEBUG     += -g

QMAKE_CXXFLAGS_RELEASE += -O3
QMAKE_CFLAGS_RELEASE   += -O3
QMAKE_LFLAGS_RELEASE   += -O3
QMAKE_CFLAGS_OPTIMIZE  += -O3
QMAKE_CFLAGS_OPTIMIZE_FULL += -Oz
} else {
# Practical debugging setup:
#    "-g4" preserves function names for stack traces
#    "-Os" produces reasonably sized binaries
QMAKE_CFLAGS_DEBUG     -= -g
QMAKE_CXXFLAGS_DEBUG   -= -g
QMAKE_CFLAGS_DEBUG     += -Os -g4
QMAKE_CXXFLAGS_DEBUG   += -Os -g4
QMAKE_LFLAGS_DEBUG     += -Os -g4

QMAKE_CXXFLAGS_RELEASE += -O3
QMAKE_CFLAGS_RELEASE   += -O3
QMAKE_LFLAGS_RELEASE   += -O3
QMAKE_CFLAGS_OPTIMIZE  += -O3
QMAKE_CFLAGS_OPTIMIZE_FULL += -Oz
}

QMAKE_COMPILER         += emscripten

QMAKE_CC                = emcc
QMAKE_CXX               = em++

QMAKE_LINK              = $$QMAKE_CXX QMAKE_LINK_SHLIB =$$QMAKE_CXX
QMAKE_LINK_C            = $$QMAKE_CC QMAKE_LINK_C_SHLIB =$$QMAKE_CC

QMAKE_LIBS_THREAD       = $$QMAKE_CFLAGS_THREAD QMAKE_LFLAGS +=$$EMCC_COMMON_LFLAGS
QMAKE_LFLAGS_DEBUG     += $$EMCC_COMMON_LFLAGS_DEBUG QMAKE_PREFIX_SHLIB = lib QMAKE_EXTENSION_SHLIB = so # llvm bitcode, linked to js in post_link QMAKE_PREFIX_STATICLIB = lib QMAKE_EXTENSION_STATICLIB = a # llvm bitcode QMAKE_AR = emar cqs equals(QMAKE_HOST.os, Windows) { QMAKE_AR_CMD = \ "(file >(OBJECTS_DIR)/(TARGET).rsp, (subst \\,/,(OBJECTS)))$$escape_expand(\\n\\t)" \
"$(AR)$(DESTDIR)$(TARGET) @$(OBJECTS_DIR)/\$(TARGET).rsp"
}

QMAKE_DISTCLEAN            += *.html *.js *.wasm



• Just place a # in front of that line EMCC_COMMON_LFLAGS += -s "BINARYEN_TRAP_MODE='clamp'" and run qmake again - that will recreate the Makefile

• I took out that line completely, added the patch, and then ran qmake and nmake again but have the same error as before. A whole bunch of red lines with "unknown warning option" and other stuff in it. And I don't know why the -Werror option is being passed to the compiler backend.

I also have to forcibly close the window using the red button because just giving it the keyboard interrupt isn't enough.

Note: This is one part of the stream of errors:

error: unknown warning option '-Wno-int-in-bool-context'; did you mean '-Wno-gnu-include-next'?
[-Werror,-Wunknown-warning-option]
error: unknown warning option '-Wno-int-in-bool-context'; did you mean '-Wno-gnu-include-next'?
[-Werror,-Wunknown-warning-option]
shared:ERROR: 'C:/emsdk/upstream/bin\clang.exe -target wasm32-unknown-emscripten -D__EMSCRIPTEN_major__=1 -D__EMSCRIPTEN_minor__=38 -D__EMSCRIPTEN_tiny__=46 -D_LIBCPP_ABI_VERSION=2 -Dunix -D__unix -D__unix__ -Werror=implicit-function-declaration -Xclang -nostdsysteminc -Xclang -isystemC:\emsdk\upstream\emscripten\system\include\libcxx -Xclang -isystemC:\emsdk\upstream\emscripten\system\lib\libcxxabi\include -Xclang -isystemC:\emsdk\upstream\emscripten\system\include\compat -Xclang -isystemC:\emsdk\upstream\emscripten\system\include -Xclang -isystemC:\emsdk\upstream\emscripten\system\include\libc -Xclang -isystemC:\emsdk\upstream\emscripten\system\lib\libc\musl\arch\emscripten -Xclang -isystemC:\emsdk\upstream\emscripten\system\local\include -Wno-int-in-bool-context -c -Werror -Os -fno-builtin -Wno-return-type -Wno-parentheses -Wno-ignored-attributes -Wno-shift-count-overflow -Wno-shift-negative-value -Wno-dangling-else -Wno-unknown-pragmas -Wno-shift-op-parentheses -Wno-string-plus-int -Wno-logical-op-parentheses -Wno-bitwise-op-parentheses -Wno-visibility -Wno-pointer-sign -Wno-absolute-value -Wno-empty-body -Wno-int-in-bool-context -IC:\emsdk\upstream\emscripten\system\lib\libc\musl\src\internal -IC:\emsdk\upstream\emscripten\system\lib\libc\musl\arch\js -DEMSCRIPTEN C:\emsdk\upstream\emscripten\system\lib\libc\musl\src\stdlib\qsort.c -fno-inline-functions -Xclang -isystemC:\emsdk\upstream\emscripten\system\include\SDL -c -o C:\Users\Osman\AppData\Local\Temp\emscripten_temp_bduibeac\qsort.c.o -mllvm -combiner-global-alias-analysis=false -mllvm -enable-emscripten-sjlj -mllvm -disable-lsr' failed (1)


Actually it did end on its own this time. I'll be able to give you a log file after running nmake 2> build.log now. Here's a link.

• You need to use mingw32-make and not nmake.

• The reason for the unknown warning error was a mismatch between the Clang version and the Emscripten version. But after fixing that I have an error from wasm-ld.exe saying that the machine type of library files needs to be wasm32. I don't know what I need to do here so some help would be good. I mentioned this in the Emscripten GitHub as well.

And whether I run nmake or mingw32-make, the result is still pretty much the same: https://gist.github.com/DragonOsman/4b5a04e0546d3ccc21c67cc978510e70

• There are errors from wasm-ld.exe saying that there are object files that don't have the machine-type wasm32. The object files generated by running nmake definitely hve wasm code in them, even though wasm-ld is flagging them as well. Which is really weird. I see that the object files that come from the Qt library itself are also getting flagged though. Could you guys verify using wasm-dis if those are also wasm object files? Although there's still a problem there because wasm object files shouldn't even have a machine type--only bitcode files should which these aren't. This is really confusing.

• Did you install Emscripten 1.38.27 ? That would be needed for Qt 5.13

• @lorn-potter Do I need to do a complete downgrade? I have version 1.39.0 right now. Could that be what's causing the problem with the wasm-ld error saying that my object files aren't of machine-type wasm32?

• @lorn-potter Do I need to do a complete downgrade? I have version 1.39.0 right now. Could that be what's causing the problem with the wasm-ld error saying that my object files aren't of machine-type wasm32?

Yes, because 1.39.0 switched to wasm object files by default, where as the older version used fastcomp to build.

You can install a different version alongside 1.39.0:
./emsdk install sdk-1.38.27-64bit

and then to switch to the newly installed version:
./emsdk activate --embedded sdk-1.38.27-64bit

When you want ot use a different version just use the activate line with the correct installed version.

• Is the default backend being switched to the Wasm one the only reason? I don't think that would be enough to give those machine-type errors.

I hope Qt 5 will eventually support version 1.38.48 and newer of Emscripten at some point as well.

• @lorn-potter Would it be a good idea to get version 1.38.30 instead?

• @lorn-potter What's the use of the patch if Qt 5 still can't handle the Wasm backend? The reason for the machine type error from wasm-ld is something else: in later versions of Emscripten, it doesn't generate bitcode for Wasm object files. But for some weird reason wasm-ld still gives an error saying that the machine type of the object files isn't wasm32. That's very strange. Please read my conversation with this LLVM developer on this Emscripten GitHub issue I've opened. It would be good if these problems are fixed so that the Wasm backend on the latest version of Emscripten works well with Qt 5.

And right now I can't install the 1.38.27 SDK itself directly using the Emsdk; I have to install Emscripten, Clang and Binaryen separately through Emsdk and since I want to use my own Node, Python and Java anyway, I don't also get those. I had to use CMake to build and install Binaryen on my own though because what Emsdk did failed for me. When I try to install the SDK through Emsdk directly, I get a System Error Access denied when it unzips the Python zip file and gets to trying to add DLLs to the Emsdk Python installation directory.

Edit: I deleted the old files and tried to configure and build again, but now I have this error: shared:ERROR: fastcomp is not compatible with wasm object files:main.obj. I have Emscripten 1.38.27 now with the asm.js backend, so what's going on now? Why is it generating a Wasm object file? Do I still need to add something to the .conf file so that it won't generate Wasm object files when the asm.js backend is being used?

Also, it probably shouldn't generate Wasm object files with the Wasm backend anyway. Wasm object files aren't standard Wasm files.

Edit: Actually, I should be able to make it work if I build Qt for WebAssembly myself. I just need to know what modules are usually built for Qt 5 for Windows. I'll build those same modules. Except if threading support isn't included in there, then I want to include that as well in addition to the rest of it. What module do I need for threading support?

• I want to try to building Qt for WebAssebly again since I think if I had Qt built using the latest version of Emscripten, it may not do what it's not supposed to when using that version of Emscripten. So I want to know how to have it use LLVM 10 installed through the EMSDK and have it generate LLVM bitcode targeting the wasm32 machine type (for that I probably need to know how to pass (multiple) command line arguments to the Clang compiler itself when building Qt). Also, if I want to have it use C++17 rules when building Qt, what should I do? I tried passing the -c++std c++17 argument to configure.bat but it didn't work. Internally it was still using C++11.

I hope someone will help me with that. Thanks in advance.

• @DragonOsman If you install emsdk latest (1.39.0), and build Qt, you can get the new wasm object file format by passing -device-option WASM_OBJECT_FILES=1 to Qt configure.

As far as the c++17 support, see this bug I just reported:
https://bugreports.qt.io/browse/QTBUG-79552

• Okay, but how can I pass the option to emit LLVM bitcode with machine-type wasm32? Will passing -device-option WASM_OBJECT_FILES=1 to Qt configure like you said be enough? I do want to know where to pass the --emit-llvm and --target=wasm32 flags to Clang.

Also, I heard on the Emscripten GitHub that .obj files with wasm in them aren't standard wasm files. And that Emscripten version 1.38.38 and above isn't supposed to generate it in the first place, especially with the new Wasm backend. The error I was before where wasm-ld.exe was saying that the .obj files don't have machine-type wasm32 was strange for that reason. Also because those object files all had Wasm code in them. wasm-ld.exe was also saying it about object files from the Qt library itself, though, and I don't know where to find them to check if they have Wasm code in them or not. They most likely have it as well though.

Also I've added this line to qmake.conf along with the recommended patch: QMAKE_CXXFLAGS_RELEASE += -Xclang --emit-llvm -Xclang --target=wasm32, but is that okay? Or did I make a mistake here? Also, if I add this patch to the Qt I build from source, and then I want to execute git pull, would it be okay to push my changes to the repository? Note: I'll keep the prebuilt binaries too and I try with both. Maybe I can still get this to work.

Edit: One more question: do I need the Qt Web module when targeting Wasm? The one that's takes too long and the documentation says to consider not building it.

• This is the error I get now when using prebuilt Qt to build the Notepad project:

wasm-ld: error: notepad.obj: machine type must be wasm32
wasm-ld: error: notepad.js_plugin_import.obj: machine type must be wasm32
wasm-ld: error: moc_notepad.obj: machine type must be wasm32
wasm-ld: error: qapplication.obj: machine type must be wasm32
wasm-ld: error: qwidget.obj: machine type must be wasm32
wasm-ld: error: qwasmlocalfileaccess.obj: machine type must be wasm32
shared:ERROR: 'C:/emsdk/upstream/bin\wasm-ld.exe -o c:\users\osman\appdata\local\temp\emscripten_temp\notepad.wasm --allow-undefined --lto-O0 main.obj notepad.obj -LC:\emsdk\upstream\emscripten\system\local\lib notepad.js_plugin_import.obj -LC:\emsdk\upstream\emscripten\system\lib moc_notepad.obj -LC:\Users\Osman\.emscripten_cache\wasm-obj C:/Qt/5.13.1/wasm_32/plugins/platforms/libqwasm.a C:/Qt/5.13.1/wasm_32/lib/libQt5EventDispatcherSupport.a C:/Qt/5.13.1/wasm_32/lib/libQt5FontDatabaseSupport.a C:/Qt/5.13.1/wasm_32/lib/libqtfreetype.a C:/Qt/5.13.1/wasm_32/lib/libQt5EglSupport.a C:/Qt/5.13.1/wasm_32/plugins/imageformats/libqgif.a C:/Qt/5.13.1/wasm_32/plugins/imageformats/libqicns.a C:/Qt/5.13.1/wasm_32/plugins/imageformats/libqico.a C:/Qt/5.13.1/wasm_32/plugins/imageformats/libqjpeg.a C:/Qt/5.13.1/wasm_32/plugins/imageformats/libqtga.a C:/Qt/5.13.1/wasm_32/plugins/imageformats/libqtiff.a C:/Qt/5.13.1/wasm_32/plugins/imageformats/libqwbmp.a C:/Qt/5.13.1/wasm_32/plugins/imageformats/libqwebp.a C:/Qt/5.13.1/wasm_32/lib/libQt5PrintSupport.a C:/Qt/5.13.1/wasm_32/lib/libQt5Widgets.a C:/Qt/5.13.1/wasm_32/lib/libQt5Gui.a C:/Qt/5.13.1/wasm_32/lib/libqtlibpng.a C:/Qt/5.13.1/wasm_32/lib/libqtharfbuzz.a C:/Qt/5.13.1/wasm_32/lib/libQt5Core.a C:/Qt/5.13.1/wasm_32/lib/libqtpcre2.a C:\Users\Osman\.emscripten_cache\wasm-obj\libc.a C:\Users\Osman\.emscripten_cache\wasm-obj\libcompiler_rt.a C:\Users\Osman\.emscripten_cache\wasm-obj\libc-wasm.a C:\Users\Osman\.emscripten_cache\wasm-obj\libc++-noexcept.a C:\Users\Osman\.emscripten_cache\wasm-obj\libc++abi-noexcept.a --whole-archive C:\Users\Osman\.emscripten_cache\wasm-obj\libembind-rtti.a --no-whole-archive C:\Users\Osman\.emscripten_cache\wasm-obj\libgl-webgl2.a C:\Users\Osman\.emscripten_cache\wasm-obj\libdlmalloc.a C:\Users\Osman\.emscripten_cache\wasm-obj\libpthread_stub.a C:\Users\Osman\.emscripten_cache\wasm-obj\libc_rt_wasm.a --import-memory --import-table -mllvm -combiner-global-alias-analysis=false -mllvm -enable-emscripten-sjlj -mllvm -disable-lsr --export __wasm_call_ctors --export __data_end --export main --export malloc --export free --export setThrew --export __errno_location --export fflush --export _ZSt18uncaught_exceptionv --export __cxa_find_matching_catch --export __cxa_is_pointer_type --export __cxa_can_catch --export emscripten_GetProcAddress --export emscripten_webgl_make_context_current --export emscripten_webgl_get_current_context --export strstr --export emscripten_builtin_memalign --export memalign --export emscripten_builtin_free --export _get_environ --export realloc --export _get_tzname --export _get_daylight --export _get_timezone --export strlen -z stack-size=5242880 --initial-memory=16777216 --no-entry --global-base=1024' failed (1)


If I pass -device-option WASM_OBJECT_FILES=1 to Qt configure when building Qt, will that fix this?

I checked notepad.obj and notepad.js_plugin_import.obj with wasm-dis.exe before and found that they were Wasm object files. But now when I check again, main.obj does have Wasm code in it but this is what I get for notepad.obj:

[parse exception: surprising value (at 0:4)]
Fatal: error in parsing wasm binary


All three of the ones from my code give the same error. How can I find those three object files from the Qt library so I can check them too?

• I finally managed to build the Notepad example app to Wasm, but I don't know how to run it. I tried opening notepad.html, but that brought me to a page with the Qt logo that says:

Qt for WebAssembly: notepad


So what should I do?

Thanks in advance for any help.

• You can either put the resulting .js, .wasm, .html files on a web server, or emscripten comes with emrun which will start a server and open the html file in a browser.

• Thanks, I'll try that.

• I launched Python's web server by running python -m http.server, but I get the same exact HTML page as before when I go to notepad.html. It still has that same error on it.

• I get the exact same result with emrun. The error "TypeError: Body has already been read". How do I fix this? Someone please help. This seems like a JavaScript error so maybe I should also consult the Emscripten developers. But it's also something related to Qt and there may be something I need to know about how to run a Wasm module compiled from Qt code.

• The error "TypeError: Body has already been read". How do I fix this?

I have seen that when I configure qt for threads and have forgotten to enable shared memory in the browsers.

Chrome: chrome://flags "WebAssembly threads support"
FireFox: about:config "javascript.options.shared_memory"

• Okay, thanks. I'll have to see how to do that for MS Edge. Thanks for the info on Chrome.

• Okay, thanks. I'll have to see how to do that for MS Edge. Thanks for the info on Chrome.

I do not think Edge has re-enabled shared memory:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/SharedArrayBuffer

• I used it in Chrome. The functionality of saving a file doesn't seem to work (may need to let WebAssembly use the filesystem) and the "Select Font" feature is giving me trouble. It opens up two dialogue boxes so I have cancel the second one. On the first one then, the font size selector goes crazy when I try to use it; it keeps going between different sets of two options in really fast succession and I can't choose one at all. Is there a special way to get the Notepad example to work as a Wasm app? These problems only appear in the Wasm app.

• This is the error I get now when using prebuilt Qt to build the Notepad project:

wasm-ld: error: notepad.obj: machine type must be wasm32
wasm-ld: error: notepad.js_plugin_import.obj: machine type must be wasm32
wasm-ld: error: moc_notepad.obj: machine type must be wasm32
wasm-ld: error: qapplication.obj: machine type must be wasm32
wasm-ld: error: qwidget.obj: machine type must be wasm32
wasm-ld: error: qwasmlocalfileaccess.obj: machine type must be wasm32
shared:ERROR: 'C:/emsdk/upstream/bin\wasm-ld.exe -o c:\users\osman\appdata\local\temp\emscripten_temp\notepad.wasm --allow-undefined --lto-O0 main.obj notepad.obj -LC:\emsdk\upstream\emscripten\system\local\lib notepad.js_plugin_import.obj -LC:\emsdk\upstream\emscripten\system\lib moc_notepad.obj -LC:\Users\Osman\.emscripten_cache\wasm-obj C:/Qt/5.13.1/wasm_32/plugins/platforms/libqwasm.a C:/Qt/5.13.1/wasm_32/lib/libQt5EventDispatcherSupport.a C:/Qt/5.13.1/wasm_32/lib/libQt5FontDatabaseSupport.a C:/Qt/5.13.1/wasm_32/lib/libqtfreetype.a C:/Qt/5.13.1/wasm_32/lib/libQt5EglSupport.a C:/Qt/5.13.1/wasm_32/plugins/imageformats/libqgif.a C:/Qt/5.13.1/wasm_32/plugins/imageformats/libqicns.a C:/Qt/5.13.1/wasm_32/plugins/imageformats/libqico.a C:/Qt/5.13.1/wasm_32/plugins/imageformats/libqjpeg.a C:/Qt/5.13.1/wasm_32/plugins/imageformats/libqtga.a C:/Qt/5.13.1/wasm_32/plugins/imageformats/libqtiff.a C:/Qt/5.13.1/wasm_32/plugins/imageformats/libqwbmp.a C:/Qt/5.13.1/wasm_32/plugins/imageformats/libqwebp.a C:/Qt/5.13.1/wasm_32/lib/libQt5PrintSupport.a C:/Qt/5.13.1/wasm_32/lib/libQt5Widgets.a C:/Qt/5.13.1/wasm_32/lib/libQt5Gui.a C:/Qt/5.13.1/wasm_32/lib/libqtlibpng.a C:/Qt/5.13.1/wasm_32/lib/libqtharfbuzz.a C:/Qt/5.13.1/wasm_32/lib/libQt5Core.a C:/Qt/5.13.1/wasm_32/lib/libqtpcre2.a C:\Users\Osman\.emscripten_cache\wasm-obj\libc.a C:\Users\Osman\.emscripten_cache\wasm-obj\libcompiler_rt.a C:\Users\Osman\.emscripten_cache\wasm-obj\libc-wasm.a C:\Users\Osman\.emscripten_cache\wasm-obj\libc++-noexcept.a C:\Users\Osman\.emscripten_cache\wasm-obj\libc++abi-noexcept.a --whole-archive C:\Users\Osman\.emscripten_cache\wasm-obj\libembind-rtti.a --no-whole-archive C:\Users\Osman\.emscripten_cache\wasm-obj\libgl-webgl2.a C:\Users\Osman\.emscripten_cache\wasm-obj\libdlmalloc.a C:\Users\Osman\.emscripten_cache\wasm-obj\libpthread_stub.a C:\Users\Osman\.emscripten_cache\wasm-obj\libc_rt_wasm.a --import-memory --import-table -mllvm -combiner-global-alias-analysis=false -mllvm -enable-emscripten-sjlj -mllvm -disable-lsr --export __wasm_call_ctors --export __data_end --export main --export malloc --export free --export setThrew --export __errno_location --export fflush --export _ZSt18uncaught_exceptionv --export __cxa_find_matching_catch --export __cxa_is_pointer_type --export __cxa_can_catch --export emscripten_GetProcAddress --export emscripten_webgl_make_context_current --export emscripten_webgl_get_current_context --export strstr --export emscripten_builtin_memalign --export memalign --export emscripten_builtin_free --export _get_environ --export realloc --export _get_tzname --export _get_daylight --export _get_timezone --export strlen -z stack-size=5242880 --initial-memory=16777216 --no-entry --global-base=1024' failed (1)


If I pass -device-option WASM_OBJECT_FILES=1 to Qt configure when building Qt, will that fix this?

I checked notepad.obj and notepad.js_plugin_import.obj with wasm-dis.exe before and found that they were Wasm object files. But now when I check again, main.obj does have Wasm code in it but this is what I get for notepad.obj:

[parse exception: surprising value (at 0:4)]
Fatal: error in parsing wasm binary


All three of the ones from my code give the same error. How can I find those three object files from the Qt library so I can check them too?

What was your solution for machine type must be wasm32? I have been seeing this as well.

• @steno said in Building Qt Apps to Wasm:

What was your solution for machine type must be wasm32? I have been seeing this as well.

If you use the prebuilt binaries, you need to use emscripten version 1.38.27 or 1.38.30 for threaded.

./emsdk install sdk-fastcomp-1.38.27-64bit
./emsdk activate sdk-fastcomp-1.38.27-64bit