Running joplin on Apple silicon

Managed to build an arm64 version of the app using this PR. The app appears to be working flawlessly on my system after some basic testing. Compared to the x64 version running under Rosetta 2, the native version is much more responsive especially when switching between notes and notebooks. The native version also only takes about a third of the time to launch and has considerably lower battery consumption.

I'm not a developer but I'm willing to help with testing in case this gets officially supported.

I think lot's of people with Apple Silicon chips would be more than happy to have a native solution (even when marked experimental) as opposed to the Rosetta workaround.

2 Likes

Today I got an apple silicon device and I'll look into it.

Seems to work OK, on a Macbook Air.

2 Likes

I've also been forced to switch to an apple arm64 computer. So far, Joplin x86 is running without errors, but not as well as on my old apple x86 computer. I have some graphical stutter and lag when navigating notes and folders, which was not a problem previously, and it's using >1 GB of RAM with ~200 notes, more than double the x86 computer memory. Certainly usable, but noticeably worse than on the x86 computer.

@Shamp0o, could you possibly provide some instruction on compiling to arm64, if it wouldn't be too much trouble? I am a novice programmer and I'm not sure how to get started learning how to do this, but your comment made it sound plausible.

Hello, I have exactly the same issue as you (stutter, lag ...).
I managed to build and test the arm64 native version but i could not succeed to have an executable (.dmg, .app).
To build and test it I installed some dependencies with HomeBrew
brew install cocoapods vips.

Then i went to /packages/app-desktop and ran the following
yarn install
yarn start.

Shamp0o I am also interested on how you managed to have a .app file.

1 Like

Okok, i'm so excited i finally did it, i have Joplin running natively, moreover, it kept all my previous configurations.

Disclaimer : I do not know Electron or Node, it's my first time experiencing with it.

So, after doing the yarn install, I stayed in the /packages/app-desktop directory and ran the following :
npx electron-builder.

It creates a dmg file in /packages/app-desktop/dist, you just have to open it and drag the Joplin icon in the Applications folder !

Then you'll be asked if you want to replace the old file (and ofc you say yes) and there you go. ENJOY

However, the normal command to use is npm run dist which is equivalent to yarn run electronRebuild && npx electron-builder and the yarn run electronRebuild did not work on my system, i get the following error :

[23:54:03] 'electronRebuild' errored after 1.98 s
[23:54:03] Error: Command failed: yarn run electron-rebuild --force-abi 89
- Searching dependency tree
gyp: name 'openssl_fips' is not defined while evaluating condition 'openssl_fips != ""' in binding.gyp while trying to load binding.gyp
✖ Rebuild Failed

An unhandled error occurred inside electron-rebuild
node-gyp failed to rebuild '/Users/[REDACTED]/Downloads/joplin/packages/lib/node_modules/sqlite3'.
For more information, rerun with the DEBUG environment variable set to "electron-rebuild".

Error: `gyp` failed with exit code: 1



Error: node-gyp failed to rebuild '/Users/[REDACTED]/Downloads/joplin/packages/lib/node_modules/sqlite3'.
For more information, rerun with the DEBUG environment variable set to "electron-rebuild".

Error: `gyp` failed with exit code: 1


    at NodeGyp.rebuildModule (/Users/[REDACTED]/Downloads/joplin/packages/app-desktop/node_modules/electron-rebuild/lib/src/module-type/node-gyp.js:117:19)
    at processTicksAndRejections (node:internal/process/task_queues:96:5)
    at async ModuleRebuilder.rebuildNodeGypModule (/Users/[REDACTED]/Downloads/joplin/packages/app-desktop/node_modules/electron-rebuild/lib/src/module-rebuilder.js:94:9)
    at async ModuleRebuilder.rebuild (/Users/[REDACTED]/Downloads/joplin/packages/app-desktop/node_modules/electron-rebuild/lib/src/module-rebuilder.js:124:14)
    at async Rebuilder.rebuildModuleAt (/Users/[REDACTED]/Downloads/joplin/packages/app-desktop/node_modules/electron-rebuild/lib/src/rebuild.js:145:13)
    at async Rebuilder.rebuild (/Users/[REDACTED]/Downloads/joplin/packages/app-desktop/node_modules/electron-rebuild/lib/src/rebuild.js:108:17)
    at async /Users/[REDACTED]/Downloads/joplin/packages/app-desktop/node_modules/electron-rebuild/lib/src/cli.js:154:9

    at ChildProcess.exithandler (node:child_process:399:12)
    at ChildProcess.emit (node:events:520:28)
    at ChildProcess.emit (node:domain:537:15)
    at maybeClose (node:internal/child_process:1090:16)
    at Socket.<anonymous> (node:internal/child_process:449:11)
    at Socket.emit (node:events:520:28)
    at Socket.emit (node:domain:537:15)
    at Pipe.<anonymous> (node:net:687:12)
    at Pipe.callbackTrampoline (node:internal/async_hooks:130:17)

If someone can figure this out, I will be happy to hear how and why.

2 Likes

Congratulations on getting so far. I wish I had your determination.

You're finding the dependencies that cause most people to give up. I let the individual component suppliers sort out their bits.

A year ago I placed an issue in the Electron project to build for ARM. And left it, because it was going to happen in version 11.

You have two other errors there; openssl-fips and sqlite3.

Openssl-fips has an issue that has a workaround.

I can't understand why there is a problem with sqlite3. Sqlite runs on android and iOS devices and they are all ARM processors. There a build for it done a month ago.

I'm still bemused how you have a working build for ARM. You might not be running Electron for ARM - look and see if LSRequiresNativeExecution is false in the plist file. In which case it's doing a binary translation using Rosetta2.

You can check builds in sites like DoesItArm or IsAppleSiliconReady. And you can submit your successes to them.

Whatever, I hope you've enjoyed your voyage of discovery. You're doing what every integration engineer does before new versions are released. They get paid well to do this.

2 Likes

Hello and thank you !

I don't know which plist file you are talking about, but when checking in Joplin.app/Content/Info.plist I do not find any LSRequiresNativeExecution key.
As I found they are mutlitple plist files in the application directory, I used a grep command and found nothing. (command I used : grep -R -i LSRequiresNativeExecution *)

Moreover, in the Activity monitor when I check for type it says "Apple" on every process as you can see here :

Tell me if you need any complementary information.

EDIT :

I uploaded my App file on DoesItArm and got the following

sorry for the late reply. From my personal notes:

Warning: The build only works with node v16 at the moment. Building on node v17 results in an error (see comments below)

Prerequisites

  1. Install Node: brew install node@16
  2. Install Yarn: brew install yarn
  3. Install Cocoapods - brew install cocoapods
  4. Install Vips - brew install vips

Clone and make changes to package.json

  1. Clone repo, e.g.
    git clone --depth 1 --branch v2.6.10 https://github.com/laurent22/joplin.git

  2. Change build target in /packages/app-desktop/package.json

Build

  1. yarn install
  2. cd packages/app-desktop
  3. Build executable: yarn run dist

So I just tried to build v2.7.13 and I ran into the exact same errors as @davack above when using npm run dist or yarn run dist.

Running npx electron-builder is successful and gives me a working executable but in that case yarn run electronRebuild (electron-rebuild) is not executed. This is also my first attempt of building an electron app so I'm not sure what the consequences of omitting the electron-rebuild command are but the app appears to be working just fine.

After doing some digging, the openssl_flips error seems to be related to the electron-rebuild version. Apparently this issue should be fixed in version 3.2.5 but I'm running v3.2.5 and still getting this same error. From my understanding the sqlite3 error might not be a separate error but might be caused by the openssl_flips error.

1 Like

Strange : following the instructions given above, I could build v.2.7.13 for M1 without difficulty. However, when trying to do the same with v2.7.15, I get the following error when running npx electron-builder :

• electron-builder  version=22.14.10 os=21.4.0
  • loaded configuration  file=package.json ("build" field)
  • electron-rebuild not required if you use electron-builder, please consider to remove excess dependency from devDependencies

To ensure your native dependencies are always matched electron version, simply add script `"postinstall": "electron-builder install-app-deps" to your `package.json`
  • writing effective config  file=dist/builder-effective-config.yaml
  • skipped dependencies rebuild  reason=npmRebuild is set to false
  • packaging       platform=darwin arch=arm64 electron=14.1.0 appOutDir=dist/mac-arm64
  • skipped macOS application code signing  reason=cannot find valid "Developer ID Application" identity or custom non-Apple code signing certificate, see https://electron.build/code-signing allIdentities=     0 identities found
                                                Valid identities only
     0 valid identities found
Checking if notarization should be done...
Either not running in CI or not processing a desktop app tag - skipping notarization. process.env.IS_CONTINUOUS_INTEGRATION = undefined; process.env.GIT_TAG_NAME = undefined
  • building        target=macOS zip arch=arm64 file=dist/Joplin-2.7.15-arm64-mac.zip
  • building        target=DMG arch=arm64 file=dist/Joplin-2.7.15-arm64.dmg
  • Detected arm64 process, HFS+ is unavailable. Creating dmg with APFS - supports Mac OSX 10.12+
  • building block map  blockMapFile=dist/Joplin-2.7.15-arm64-mac.zip.blockmap
  ⨯ Exit code: ENOENT. spawn /usr/bin/python ENOENT  failedTask=build stackTrace=Error: Exit code: ENOENT. spawn /usr/bin/python ENOENT
    at /Users/rafjaf/Downloads/joplin 09-44-14-839/packages/app-desktop/node_modules/builder-util/src/util.ts:133:18
    at exithandler (node:child_process:406:5)
    at ChildProcess.errorhandler (node:child_process:418:5)
    at ChildProcess.emit (node:events:527:28)
    at Process.ChildProcess._handle.onexit (node:internal/child_process:289:12)
    at onErrorNT (node:internal/child_process:476:16)
    at processTicksAndRejections (node:internal/process/task_queues:83:21)

Would anyone have a clue ?

I take this opportunity to insist that a M1 build represents a true added value : Joplin is much snappier than when running it on Rosetta.

Thank you for your help!

1 Like

All,

I just found Joplin today and happen to have a Mac with the M1, so I found this thread while hunting for an ARM build and decided to give things a go. I had failures and then a success, details below.

I checked out tag v2.7.15. Running Node 17 (following brew install node instructions from Shamp0o above) I ran into the openssl_fips and sqllite errors encountered by davack. I perused the web and found a few Github projects encountering this issue when using Node 17, so I downgraded to Node 16 (using brew install node@16 and following the brew hints to add node 16 to my PATH), cleared my node_modules, ran the Build instructions from Shamp0o again, and had immediate success. Looking at the Joplin interface for the first time right now!

Could be an issue in Node 17, or maybe a dependency that would need an update for compatibility with Apple Silicon. Either way I jumped right into the deep end on this one and I'm super excited to give the app a shot now.

Note - as a new user I can't mention other users, apologies. Hope my info is helpful, and I'll go ahead and put my vote in for official Apple Silicon support!

5 Likes

I've been using the normal desktop Joplin on an M1 MacBook air. Here's the latest version. It appears there's no need to build from source.

Joplin 2.7.15 (prod, darwin)

Client ID: 9aa1c4310c9a45ffbd5dbad00bdc7102
Sync Version: 3
Profile Version: 41
Keychain Supported: Yes

Revision: 8352e23

Unless I am mistaken, the file you are referring to, available on Joplin website for download, is the Intel version, not the Apple Silicon. It works thanks to Rosetta but is (much) slower than an Apple Silicon build.

I can confirm that node v16 works without issues. Thanks for looking into this. I updated my post above accordingly.

I finally understood why it was not working for me even with node 16. As it appears from the error message posted above, npx electron-builder could not call /usr/bin/python... because in the latest versions of Mac OS, Python 2 is not installed anymore by default (and cannot be installed in this directory without disabling some system-wide protection). Therefore, after installing Python 2, I had to modify joplin/packages/app-desktop/node_modules/dmg-builder/out/dmg.js where the path to usr/bin/python is for some unknown reason hard-coded. I finally resolved to write the following script to automate the process next time (and hopefully help other persons confronted with the same difficulties) :

#!/bin/zsh
if [ -z "$1" ]; then
	echo "$0 [version]"
	echo "Builds Joplin [version] in ARM64"
	echo
	echo "Before running for the first time, you should install dependancies by running"
	echo "brew install node node@16 yarn cocoapods vips jq jo macos-trash"
	if [ ! -e "/usr/bin/python" ]; then
		echo
		echo "You should also install Python2 from https://www.python.org/downloads/release/python-2718/"
	fi
	exit
fi

# Changing path to force the use of Node 16
export PATH="/opt/homebrew/opt/node@16/bin:$PATH"
export LDFLAGS="-L/opt/homebrew/opt/node@16/lib"
export CPPFLAGS="-I/opt/homebrew/opt/node@16/include"
echo "PATH: $PATH"

# Cloning the requested version of Joplin from Github
cd ~/Downloads
git clone --depth 1 --branch "v$1" https://github.com/laurent22/joplin.git

# Modifying the target for the build (Apple Silicon instead of Intel)
cd joplin
TMP=$(mktemp)
VALUE=$(jo target=default "arch[]=arm64")
jq ".build.mac.target=$VALUE" packages/app-desktop/package.json > $TMP
mv $TMP packages/app-desktop/package.json

# Downloading and building dependancies - takes about one hour on my Mac
yarn install
cd packages/app-desktop

# If Python 2 is not installed by default, change the path which is
# hard-coded in the build files with the actual path to Python 2
# (obviously won't work if Python 2 is not installed)
if [ ! -e "/usr/bin/python" ]; then
	sed -i '' "s|/usr/bin/python|$(which python2)|" node_modules/dmg-builder/out/dmg.js
fi

# Let's finally build Joplin!
npx electron-builder
EXIT=$?

# Joplin.app will be copied to the root of the Download folder
cp -R dist/mac-arm64/Joplin.app ~/Downloads
cd ~/Downloads

# Remove the files downloaded from Github if all went well
if [[ $EXIT -eq 0 ]]; then 
	trash joplin
fi

# Make a beep to signal it's over
tput bel

Any comment most welcome!

3 Likes

I also face a similar error while installing the node_modules (most of the time sqlite3), since apple changed its default python version to python3, there is no alias for python

I tried using alias in my .zshrc file but it didn't work (alias won't work in /bin/sh shell, no idea why)

I fixed it by creating a symbolic link of python3 to python

ln -sf /opt/homebrew/bin/python3 /usr/local/bin/python

Note: I installed python3 with homebrew

1 Like

I had tried something similar, but it didn't help for me because the Python script on which npx electron-builder stumbled was written for Python 2, not Python 3 (some dependencies did not work with a newer version of Python). However, if it works for you, good to know!

In case it's helpful to anyone, here is how I got Joplin running as a native Apple Silicon app on a 2020 MacBook Air (Apple Silicon M1, MacOS Monterey 12.3.1). I haven't noticed any problems so far in limited testing, but I make no warranties about the integrity of the binary below or what results you may encounter. It's working for me, but YMMV.

  1. I downloaded the prebuilt Apple Silicon binary from github .com/noah-nash/joplin-arm64-darwin-guide/releases. (Notes from the person who kindly created that binary and documented the process are in this blog post: noahnash .net/blog/joplin-apple-silicon/ .) Note: the system is not allowing me to include links, so you'll need to remove an extraneous space from each of those links.

  2. In terminal I ran the following command:
    xattr -d com.apple.quarantine /Applications/Joplin.app
    (Without this step, the application could not be launched because it was unsigned and produced an error stating that the the application was "damaged.")

  3. I then launched Joplin with no problems. (I believe the very first time I launched the application I control-clicked Joplin and selected "open" from the resulting contextual menu.)

5 Likes

Thank you!

I followed these instructions and am running arm64 Joplin on an M1 Max computer with webdav sync. It is much more responsive than the emulated official x86 build. I especially notice that there is no longer a delay when switching between notebooks, something that had bothered me before. I didn't need to re-setup the program at all; all settings were retained.

I would encourage other apple arm64 users to try this. I hope it becomes an official build eventually.

3 Likes