flypig.co.uk

Gecko-dev Diary

Between August 2023 and September 2024 I upgrading the Sailfish OS browser from Gecko version ESR 78 to ESR 91, writing a daily blog as I went along. This page catalogues my progress, alongside the other browser-related topics I've looked in to since.

Latest code changes are in the gecko-dev sailfishos-esr91 branch.

There is an index of all posts in case you want to jump to a particular day.

Gecko RSS feed Click the icon for the Gecko-dev Diary RSS feed.

Gecko

5 most recent items

17 Aug 2024 : Day 322 #
It's a bit of a strange one today. I've not managed to spend any time coding and yet, the tasks I've done today are just as important as any coding I might have done. If you've been following along you'll know my current task is getting ESR 91 working on Sailfish OS 4.6. Up until now I've been developing on Sailfish OS 4.5, which was the latest version available when I started this process.

Until now I've chosen not to switch to the newer version to avoid complicating matters. Getting the browser working has been challenging enough without also having to worry about whether the difficulties are down to the gecko code or the underlying build target.

Now that the gecko code is feeling pretty stable, it feels like the right time to update and get it working on 4.6. Not least because, according to reports I've received from the Jolla team, it doesn't currently work on 4.6.

In order to shift to 4.6 I have to perform two upgrades: I have to upgrade my SDK and I have to upgrade my development phone. Both are currently on version 4.5. Upgrading the SDK is less of an issue because it's entirely possible, in fact normal, to install multiple target versions within the same SDK. I already have the aarch64, armv7hl and i486 variants of 3.4.0.24 and 4.5.0.18 installed as targets in my SDK and adding another one isn't going to affect any of those already installed.

On the other hand the target installed on my phone for testing purposes is more complex. I'm typically using three phones. My main daily phone is already running Sailfish OS 4.6, but I prefer not to use it for gecko development because I need it in a usable state at all times. Besides this I have two development phones. One has a debug version of ESR 78 installed (it's my own build, but largely identical to the version available from the Jolla repositories). The other has the latest test build of ESR 91.

I'm apprehensive about upgrading my ESR 91 testing phone because I know it'll cause breakage. So I've decided to upgrade my ESR 78 testing phone instead. This approaches has merit, first because it means I can continue testing ESR 78 on it, which I know will work because it comes preinstalled; second because it'll allow me to test ESR 91 on it as well without causing breakage of my other two phones.

That all sounds great, except that I'm currently travelling with a very poor mobile roaming signal.

So I'm performing the upgrade while eating lunch in a café that also offers free customer WiFi.

It's turned out to be s surprisingly effective approach. I now have a dev phone running 4.6 ready to try out ESR 91 on it just as soon as I've got a completed build.

Upgrading the SDK might be less risky, but it's more effort. For this I'm going to be using my temperamental mobile data connection. The upgrader claims it's a 429.89 MiB download which is well within my allowance, but it's going to take a little time. The installer claims it'll be a 30 minute download, which is a bit of a wait, but manageable.
 
The Sailfish SDK upgrader dialogue running on Linux showing the download progress (308.23 of 429.89 MB - minutes remaining) for 4.6.0.11.

Having installed Sailfish OS SDK 4.6.0.11EA-aarch64 I now have to set things up. This is more complicated than it might sound because, thinking all the way back to the start of this process, it's not just gecko that needs to be built. There are a collection of prerequisites that I'll need to build as well. These will need to be built and installed installed into a snapshot of the SDK so that gecko can be built against them.

So, first the build engine needs configuring.
$ sfdk config
# ---- command scope ---------
# <clear>

# ---- session scope ---------
# <clear>

# ---- global scope ---------
output-prefix = ~/RPMS
device = kolbe
target = SailfishOS-devel-aarch64

$ sfdk config --global --push target SailfishOS-4.6.0.11EA-aarch64
$ sfdk config --session --push no-fix-version
$ sfdk config --session --push snapshot esr91
$ sfdk config
# ---- command scope ---------
# <clear>

# ---- session scope ---------
no-fix-version
snapshot = esr91

# ---- global scope ---------
target = SailfishOS-4.6.0.11EA-aarch64
output-prefix = ~/RPMS
device = kolbe
These configuration changes are important for a number of reasons. The target setting ensures the build is performed against the correct target. The no-fix-version setting ensures the package version is taken from the spec file rather than the latest git tag. Finally the snapshot setting will make a copy of the build target with the given name so we can keep the packages installed ready for any future builds.

So, let's build!
$ sfdk build -p -d --with git_workaround
[...]
'cbindgen >= 0.19.0' not found in package names. Trying capabilities.
No provider of 'cbindgen >= 0.19.0' found.
'pkgconfig(nspr) >= 4.32.0' not found in package names. Trying capabilities.
No provider of 'pkgconfig(nspr) >= 4.32.0' found.
Obviously this didn't go quite to plan, but it has highlighted that I'll need to build cbindgen and nspr before I an build gecko. So let's create those two packages first. Because we've set up the build engine correctly, they'll be stored in the ~/RPMS directory and then installed from there when the gecko-dev spec file is read and the build engine identifies that they're needed.

One of the great things about having done all this before and having kept a careful record of it all is that I can just refer back to my previous notes to figure out the correct way to do all this.
$ cd rust-cbindgen/
$ sfdk build -d -p
[...]
$ cd ../nspr/
$ sfdk build -d -p
[...]
$ cd ../nspr/
$ mkdir rpm
$ mv *.patch *.spec *.changes rpm
$ sed -i -e 's/&quot;@${SOURCE_DATE_EPOCH}&quot;/
    &quot;${SOURCE_DATE_EPOCH}&quot;/g' rpm/nspr.spec 
$ tar -xvf nspr-4.35.tar.gz --strip-components=1
$ SOURCE_DATE_EPOCH=$(git log -1 --pretty=%ct)
$ git checkout -b update-4.35-temp
$ git add -u .
$ git add nspr rpm
$ git commit -m &quot;temp&quot;
$ sfdk build -d -p
[...]
$ git checkout update-4.35
$ git branch -D update-4.35-temp
$ cd ../gecko-dev-esr91/gecko-dev/
$ sfdk build -p -d --with git_workaround
[...]
This leaves me with a bunch of packages ready to be used as part of the gecko build:
$ ls -1
cbindgen-0.19.0-0.aarch64.rpm
nspr-4.35.0+git1-1.aarch64.rpm
nspr-debuginfo-4.35.0+git1-1.aarch64.rpm
nspr-debugsource-4.35.0+git1-1.aarch64.rpm
nspr-devel-4.35.0+git1-1.aarch64.rpm
rust-cbindgen-debuginfo-0.19.0-0.aarch64.rpm
rust-cbindgen-debugsource-0.19.0-0.aarch64.rpm
Now that I have these I've kicked off the build again. Things get past the initial prepare stage of the rpm build process. That's progress, certainly better than previously, but soon after I had an issue with compilation of one of the Rust packages:
25:56.21 error[E0597]: `desc_set` does not live long enough
25:56.21     --> gfx/wgpu/wgpu-core/src/device/mod.rs:1795:26
25:56.21      |
25:56.21 1782 |         let mut desc_set = desc_sets.pop().unwrap();
25:56.21      |             ------------ binding `desc_set` declared here
25:56.21 ...
25:56.21 1795 |                     set: desc_set.raw_mut(),
25:56.21      |                          ^^^^^^^^ borrowed value does not live 
    long enough
25:56.21 ...
25:56.21 1816 |     }
25:56.21      |     -
25:56.21      |     |
25:56.21      |     `desc_set` dropped here while still borrowed
25:56.22      |     borrow might be used here, when `write_map` is dropped and 
    runs the `Drop` code for type `BTreeMap`
25:56.22      |
25:56.22      = note: values in a scope are dropped in the opposite order they 
    are defined
25:57.25 For more information about this error, try `rustc --explain E0597`.
25:57.26 warning: `wgpu-core` (lib) generated 1 warning
25:57.26 error: could not compile `wgpu-core` (lib) due to previous error; 1 
    warning emitted
This is interesting. The "lifetime" error being thrown up suggests that a variable is potentially being used after it's been freed. Rust can be really picky about this kind of thing. Of course, the interesting thing is that this is upstream code that I've not made any changes too, so why is it failing here? The likely answer is that we're using a version of Rust that's different from the one expected by the upstream build.

Given that the difference is due to the newer build target, we can infer that the problem is down to a Rust version that's too new. That is, either something has changed in the libraries, or the compiler has started approaching lifetimes in a slightly different way. Breakages like this aren't unheard of in the Rust world; the compiler isn't as stable or backwards-compatible as some other languages.

Unfortunately the fix isn't immediately clear to me and, having spent most of the day performing upgrades, it's too late for me now to start trying to figure out a fix. I'll have to return to this tomorrow.

If you'd like to read any of my other gecko diary entries, they're all available on my Gecko-dev Diary page.

Comments

Uncover Disqus comments