Wednesday, July 22, 2020

'wasm memory too small' Qt for WebAssembly

Sometimes when I am building a larger project with Qt for WebAssembly, I get this type of message:

wasm-ld: error: initial memory too small, 17553264 bytes needed

and the build fails.

This means that you need to tell Emscripten compiler to allocate more than the standard 1GB initial memory.
Qt allows you to specify to add more initial memory by using QMAKE_TOTAL_MEMORY in your pro file.

So it makes sense to add something like this:

QMAKE_TOTAL_MEMORY=17553264

BUT the result is:

shared:ERROR: For wasm, TOTAL_MEMORY must be a multiple of 64KB, was 17553264

grrrr...  ok, what if we find a multiple of 64?

17553264 / 64 = 274,269.95

We need a whole number, so lets round up to the next whole number.

274270 * 64 = 17553280

But no. That doesn't work either:

shared:ERROR: For wasm, TOTAL_MEMORY must be a multiple of 64KB, was 17553280

WTH?!?

The answer is that a KB is 1024 bytes, so 64 * 1024 = 65536 bytes

So let's find the closest whole number multiple of 64 KB (65536)

17553264 / 65536 = 267.841...

so let's try 268

268 * 65536 = 17563648

QMAKE_TOTAL_MEMORY=17563648

and this now builds, and hopefully runs!


You can also read more about Mobile and Embedded development and Qt for WebAssembly in the book Hands-On Mobile and Embedded Development with Qt 5

Friday, May 29, 2020

Debugging Qt for WebAssembly


Debugging is often difficult in the best of times. Debugging Qt webassembly apps in the web browser is not something I want to do on a nice summer day, and certainly makes a person more appreciative of mature, gui based debugging. But sometimes you have to do what you have to do.

If you have a crash on your Qt for WebAssembly app, you would see a not very human readable backtrace in the console output. You can start by recompiling your app with CONFIG+=debug, which allows nice symbol names in the backtrace that appears in the dev console of the browser when an exception or crash happens. Many times this can lead you to find your bug fairly quickly.

NOTE: The Qt libraries do not need to be compiled in debug mode for you to just see symbols while debugging. Although, if you want to step through C++ source code using sourcemaps, you will need to compile Qt and your application in debug mode.

The easy way is to add qDebug output, run it and see what happens. I do this quite often. But just as often, it is not enough to find a particular bug.

One issue with that is linking emscripten based wasm files takes a long time (because that is where all the magic happen), so this method is rather time consuming. Thankfully, with Qt 5.15, we use Emscripten 1.39.8 which is based on upstream clang, transpiles directly to wasm binaries and skips the internediate step of outputting javascript, so link time is greatly reduced.

What if you need to step through the source code like a desktop debugger? QtCreator does not at this time, have support for debugging Qt WebAssembly apps. I suppose it could be implemented using the browsers remote debugging interface API 

Emscripten can be used to generate source maps for the browser debugger to utilize for debugging. In Qt, we use qmake to add the necessary linker lines to allow emscripten to generate these source maps. Qt should do this by default when you use CONFIG+=debug

There is a bug that was recently fixed regarding this. If you do not find any source maps files (.map), the workaround is to add QMAKE_LFLAGS_DEBUG += -g4 in your pro file.

By default, the source base in Qt is set to use http://localhost:8000/

You can change this by adding into your .pro file, something like:
QMAKE_WASM_SOURCE_MAP_BASE = http://myip:6931 /

Emrun by default uses port 6931.

If you are running a server of some sort, you can use the ip for that. 

Sources need to be in the directory tree seen by the server, so an in-source build is the easiest. In my experience, Chrome browser seems to be able to debug with sourcemaps better. If you are using Mac or Linux, you can simply symlink the source file path into the web server base.

This is what happens when you do not have this set up correctly:

Error while fetching an original source: request failed with status 404
Source URL: http://192.168.0.21:6931/src/wasm-windows/main.cpp

Or pehaps you see a message in the sources tab of the browser console such as:
Could not load content for http://localhost:8000/depot/qt/qt5/qtbase/examples/widgets/richtext/textedit/textedit.cpp (HTTP error: status code 404, net::ERR_HTTP_RESPONSE_CODE_FAILURE)

It means it would not find the specific source file. You can symlink the sources directory.
I am using chrome, as I had better luck with it utilizing the sourcemaps. The actual procedure for firefox might be a bit different. It isn't working for me at this time.
  • emrun --browser chrome --port 8000 --hostname localhost --serve_after_close textedit.html 
    • (or wasmsourceserver.py as below)
  • open the web console
  • [chrome] Go into the debugger by clicking on 'sources'
  • [firefox] Uses the 'Debugger' tab
You should now see some entries to source files, including our main.cpp


You can now step in, step out, step over and even set breakpoints, just like a desktop gui debugger like QtCreator.



Note that these file paths are relative, and will create an error when you try debugging it, when it tries to step into a source file not local. This defeats the purpose of steping into code for the most part.

Morten has a work around on the QTBUG https://bugreports.qt.io/browse/QTBUG-72002 with a python web server named:
wasmsourceserver.py

By running this custom server, it will build a file map of all the files in the current directly reursively.


Another way to add a type of breakpoint, if you want to stop execution on a certain line and popup the browser debugger programmatically, you can add
 emscripten_debugger(); 
on the line you want it to stop and pop up. This is in the header emscripten.h, and recompile.




You can also read more about Mobile and Embedded development and Qt for WebAssembly in the book Hands-On Mobile and Embedded Development with Qt 5


Thursday, March 26, 2020

Qt on RaspberryPi

Qt on RaspberryPi is really easy, but can be rather time consuming to build an image to run on raspberry pi with Qt 5. You can either do it up yourself manually grabbing the sources, tool chains, etc. You could also buy the Qt for device creation package which comes with great support, bells, whistles and commercial licensing, or build it yourself and use open source GPL licensing. To get started using the open sourced parts, you clone one git repo:
  • meta-boot2qt 
git clone git://code.qt.io/yocto/meta-boot2qt.git

 You then need to decide which device to target. I have a fancy new raspberry pi 4 hooked up to a touch screen, so I will choose that.

To get a list of the Boot2Qt targets run the command:

  meta-boot2qt/b2qt-init-build-env list-devices

To initialize the build environment for a raspberry pi:

 meta-boot2qt/b2qt-init-build-env init --device raspberrypi4

This will clone needed repo's.

You will then need to set up the environment specifically for your device by setting MACHINE
and then source the setup-environment.sh script:

 export MACHINE=raspberrypi4 
 source ./setup-environment.sh

Now, if you just want an image to run:

 bitbake b2qt-embedded-qt5-image

Sit back, enjoy a cuppa and a pizza on this fine day... Don't let the computer sleep, or you will kick yourself in a few hours when you check on the progress. My final image to be dd'd onto the sd card was found in

   tmp/deploy/images/raspberrypi4

This is what you will be presented with when you boot your device:

To build the sdk/sysroot the command would be:

 bitbake meta-toolchain-b2qt-embedded-qt5-sdk 

You can build other targets including qemu, which will give you an image that runs in the qemu emulator.

You can then also set up target kits in Qt Creator to target the raspberry pi, set up the device kit so you can run and debug on the device. More fun for all that time on your hands right now!

I write about creating device OS images using Qt's Boot To Qt and Bitbake for the Raspeberry Pi in my book, Hands-On Mobile and Embedded Development with Qt 5


Tuesday, March 24, 2020

QtWebAssembly updates Emscripten Requirement

In the just released Qt 5.15-beta2 version, Qt for WebAssembly will require an Emscripten update from 1.38.27 to 1.39.8. Require because there are a few incompatible changes we needed in Qt.

The update includes several improvements, including faster linking times, as Emscripten no longer has to transpile to javascript before it outputs wasm. It can build directly to wasm thanks to upstream wasm support in clang.

Users will notice app build times are greatly improved on all platforms, since Emscripten no longer has a two pass linker procedure.

To update Emscripten, I usually do this from the commandline:

cd ~/emsdk
git pull
./emsdk update-tags
./emsdk install 1.39.8
./emsdk activate --embedded 1.39.8

and finally

source ~/emsdk/emsdk_env.sh


Of course, you will need to rebuild Qt, all other modules and apps.

You can read more about Qt for WebAssembly and Embedded Qt development in the book Hands-On Mobile and Embedded Development with Qt 5

Wednesday, January 8, 2020

Qt WebAssembly faster builds

Admittedly, building Qt WebAssembly apps takes what seems like forever. Technically, it is the linking part that takes a huge amount of time, as that is where the magic happens.

You may have missed my first blog regarding faster build times for Qt WebAssembly apps:
http://qtandeverything.blogspot.com/2019/06/faster-link-time-for-qt-webassembly.html

Here is how to get set up to use this now integrated feature.

1. You need emscripten with upstream clang, which has support for transpiling directly to wasm, instead of taking the intermediary step of building javascript, then outputting wasm binary with that. Starting with version 1.39.0, upstream clang is the default. You can use "latest" to get 1.39.x or something like "sdk-upstream-1.38.43-64bit" to get an earlier version.

./emsdk install latest
./emsdk activate --embedded latest
source ./emsdk_env.sh

You can then configure and rebuild Qt with  -device-option WASM_OBJECT_FILES=1

configure -xplatform wasm-emscripten -developer-build -nomake tests -nomake examples -opensource -confirm-license -verbose -compile-examples -no-warnings-are-errors -release -device-option WASM_OBJECT_FILES=1

Then you can build your Qt app as normal using the qmake from that build, and watch the build time speed up!

*NOTE* Using  WASM_OBJECT_FILES with a multi-threaded build is still experimental, as both threads and using wasm object files in emscriptem/wasm and Qt are experimental. I have not seen any real issues regarding the use of both of these at the same time.

You can read more about Qt for WebAssembly, mobile and embedded development in the book Hands-On Mobile and Embedded Development with Qt 5

Tuesday, January 7, 2020

Aussie firestorms

As some may know, I currently reside in Australia, which is undergoing an unprecedented bush fire season. Total burnt area is about the size of Demark, with no end in sight. Whole forests and towns are being incinerated. Millions of animals, both wild and farm are being killed and injured by the swiftly moving crown fire being whipped up by high dry winds.

There are people that need help, and people that rescue animal need help as well.
https://www.news.com.au/technology/environment/bushfire-relief-how-you-can-help-those-in-need/news-story/a0476ac3538b8c373f281ea6be204421

Some of you may have seen that I authored a book that was published by Packt this last year
Hands on Mobile and Embedded Development with Qt 5

I have decided the donate all my last quarters royalties to the WIRES Emergency Fund for Wildlife. It's not much, but I wanted to help out creatures that cannot help themselves or cannot seek out help. If there is any interest, I will donate the next quarters royalties as well.