Building Pebble Watchfaces on Modern Systems

How I got the Pebble command line tools, emulator, etc. to work on my Apple Silicon Mac, and Linux machine
6 min read 1

Way back when (circa 2015), I made some watchfaces for Pebble Watches. You can still access them today thanks to the Rebble project. It’s recently been announced that the original creators will launch a new device that will run the recently open-sourced version of Pebble OS.

However, the SDK has not been updated in about 10 years. It relies on Python 2, and the code doesn’t work on Python 3. You typically would need an emulator, or some other tool to allow you to install and build the old dependencies to develop watchfaces and apps.

That is… until now! I’ve been hacking on this for the past week and it seems to be in a very good place, I have tested it on my Apple Silicon Mac, My Arch Linux machine, and my old x86 Mac. I can build and install my old watchfaces and make upgrades.

If you’re looking to install rebbletool - visit the README on Github - the setup section will walk you through getting started.

Disclaimer: This tool is very experimental. Although I have tested it to work on my devices and it works well for me, it might not work on yours or could break things. Use at your own risk!

Running the CLI

Now, onto the fun part.

The first thing, was to get the pebble (renamed to rebble) command line tool to run, and install the last available SDK. This was actually pretty easy, just migrating Python 2 code to Python 3. Since I wanted to make this something you could clone + install, I also modified it to download the correct SDK containing the toolchain and set those up locally. On macOS, this process also makes gatekeeper not complain about all the files.

Then, I ran rebble build. And, it crashed. It became apparent this was not going to be as easy as I thought it would be.

version info

Getting it to build

Most of this is boring. But, in short - we’ve got a small set of patches that will allow things to build, and the command line tool will automatically detect this and apply them on top of the installed SDK to allow it to run using Python 3.

One important note - all of the binaries provided with the SDK were made before Apple Silicon, so you will need to make sure Rosetta 2 is installed. You can do so via running softwareupdate --install-rosetta.

Installing to Phone

This part, was pretty easy! I enabled the developer connection on my phone, fixed a couple more crashes in the CLI tool, and it installed!

This shows a full SDK install, patch, and build of a watchface, which I then installed to my phone!:

Installing to my phone!

Getting the emulator to run

On my Mac, I tried to run rebble install --emulator basalt next. No luck.

On Linux, it started but would crash because we had disabled pypkjs (which fails to build at this point in the adventure).

Since We have Rosetta 2 on the Mac, so it should work and fail in the same manner as on Linux, but upon further inspection it’s looking for some dylibs we don’t have the proper versions of.

Emulator crash

If you try to brew install these, like the original instructions suggest, this will still fail, instead complaining it’s not x86 (our Apple Silicon Mac is arm, not x86_64). I decided to fire up my (2012) Macbook pro, and install the libraries on there. The hope was, I can get those built & installed, then bundle them up and put them somewhere the system would look for them.

I bundled them up, and modified the SDK install to detect an Apple Silicon Mac, then it puts them in the rebbletool project directory alongside lib/. Then, I updated it to include the correct PATH to the emulator, and the DYLD_FALLBACK_LIBRARY_PATH pointing to our lib file with the x86 dylibs.

These are the libraries needed:

  • libglib-2.0.0.dylib
  • libintl.8.dylib
  • libpixman-1.0.dylib
  • libgthread-2.0.0.dylib
  • libpcre2-8.0.dylib

This worked!

Installing faces & apps on the emulator

From here, I turned to look into the next part. Upon emulator start, it informs us pypkjs is not able to be found. I disabled this when originally getting the cli tool to run, since it would not build.

I forked pypkjs, and disabled everything v8 related - it depended on PYv8 which has not been maintained, and the fork STPYv8, doesn’t support the JSExtension mechanism that pypkjs uses.

Upon disabling that, and after patching a single line of byte handling code in libpebble2, I was greeted with this on my mac:

Installing one of my watchfaces on the emulator.

Success! 💯

Emulator GDB

Unfortunately, the gdb provided by the SDK on macOS is linked to the old Python2 framework. Thankfully, this isn’t a huge problem - homebrew actually has a compatible arm version ready to go! After running brew install arm-none-eabi-gdb, and altering the CLI tool to find it - gdb works!

Debugging my watchface with GDB

What about PKJS?

This is where it gets more “fun”. And by that, I mean writing a bit more code than I thought I would. It turns out the best way to get this to work was to figure a way to make pypkjs run under STPYv8. There’s likely no porting PYv8 to modern systems, and we should use the latest fork.

It looked like I could pretty easily call functions/return data from js -> python, so I built a table of external functions, and provided a mechanism within the JS vm to call them. I then refactored the code to use that instead of the native methods JSExtension uses.

This plus-side of doing it this way, is that we can also log all of the back & forth between pypkjs and the js code the user writes!

This also enables the rebble emu-app-config command to work, provided your page implements the return_to query param as described in the docs

pypkjs running and running things like GeoLocation, XHR

The future

That’s all for now! I’ll be slowly refining things. There’s a few parts that aren’t working fully yet, including localStorage persistence and the Websockets APIs in pypkjs, but those are a work in progress!

I’m looking into seeing if we can rebuild the tools and/or make some of the homebrew versions of the cross-compiler work, so that we don’t need to rely on Rosetta. There’s other people on the Rebble Discord already looking into rebuilding the emulator to work on macOS natively, so good things might be coming!

Feedback & Mentions

Found a typo or technical problem? report an issue!

Some places around the web that this article is linked from:

Subscribe to my Newsletter

Like this post? Subscribe to get notified for future posts like this.