Emacs.app installed incorrectly via home-manager

Summary:

Emacs Application on darwin arm64 installed via home-manager 20.09:

  • is not executable
  • calls exec on bin/etags, not bin/emacs
  • sets load-path to itself
  • references vanilla emacs as opposed to emacs-with-deps

Details:

I’ve been using Emacs with home-manager for over a year, but after moving to a new machine, I can’t seem to install it properly with home-manager. Emacs installed via nix-env works (although it doesn’t load my home-manager configuration, of course).

I’ve tried removing my normal configuration and setting the minimal programs.emacs.enable = true;. I’ve run nix-store --verify --check-contents --repair and even disabled emacs, ran nix-collect-garbage --delete-old, ensured emacs was no longer in the nix store and then started again.

The first problem is that the macOS Application is not executable:

Permissions error via `open -a`
% open ~/Applications/Home\ Manager\ Apps/Emacs.app
The application cannot be opened for an unexpected reason, error=Error Domain=NSOSStatusErrorDomain Code=-10826 "kLSNoLaunchPermissionErr: User doesn't have permission to launch the app (managed networks)" UserInfo={_LSFunction=_LSLaunchWithRunningboard, _LSLine=2508, NSUnderlyingError=0x13f62cae0 {Error Domain=RBSRequestErrorDomain Code=5 "Launch failed." UserInfo={NSLocalizedFailureReason=Launch failed., NSUnderlyingError=0x13f62d460 {Error Domain=NSPOSIXErrorDomain Code=111 "Unknown error: 111" UserInfo={NSLocalizedDescription=Launchd job spawn failed with error: 111}}}}}
% ll ~/Applications/Home\ Manager\ Apps/Emacs.app/Contents/MacOS
total 8
-r--r--r--  1 root  wheel   836B  1 Jan  1970 Emacs

If I chmod +x that file, I no longer get the error, but the Emacs window doesn’t open if I double-click or use open -a on the .app bundle. If I execute Contents/MacOS/Emacs file directly in the terminal:

% ~/Applications/Home\ Manager\ Apps/Emacs.app/Contents/MacOS/Emacs
/nix/store/6sap8pb8r6dd7v8jawd8wyp9qyqqvdds-emacs-27.1/bin/etags: no input files specified.
	Try '/nix/store/6sap8pb8r6dd7v8jawd8wyp9qyqqvdds-emacs-27.1/bin/etags --help' for a complete list of options.

I edited the file and replaced the call to etags with emacs. Emacs launches with some warnings in the terminal.

Warning: Lisp directory '/nix/store/6sap8pb8r6dd7v8jawd8wyp9qyqqvdds-emacs-27.1/Applications/Emacs.app/Contents/MacOS/Emacs': Not a directory
2020-12-18 14:08:39.117 emacs[44136:687221] Error - planarGetBytes count (16) is less than bytesPerRow (32).  No data will be read.

In Emacs, the load-path is not set correctly, as emacs complains about not being able to find packages (even once I switch back to my normal configuration). This is presumably related to the first warning. The second warning gets repeated a few times.

Bizarrely, if I simply call emacs in the terminal, everything works as expected.

Looking at the contents of Emacs and comparing to emacs, it’s easy to see why

Emacs
#!/nix/store/pmmh1dl7kmxi2xpagknl9qqa4wr7vv9c-bash-4.4-p23/bin/bash

IFS=:

newLoadPath=()
added=

if [[ -n $EMACSLOADPATH ]]
then
    while read -rd: entry
    do
        if [[ -z $entry && -z $added ]]
        then
            newLoadPath+=(/nix/store/6sap8pb8r6dd7v8jawd8wyp9qyqqvdds-emacs-27.1/Applications/Emacs.app/Contents/MacOS/Emacs)
            added=1
        fi
        newLoadPath+=("$entry")
    done <<< "$EMACSLOADPATH:"
else
    newLoadPath+=(/nix/store/6sap8pb8r6dd7v8jawd8wyp9qyqqvdds-emacs-27.1/Applications/Emacs.app/Contents/MacOS/Emacs)
    newLoadPath+=("")
fi

export EMACSLOADPATH="${newLoadPath[*]}"
export emacsWithPackages_siteLisp=/nix/store/6sap8pb8r6dd7v8jawd8wyp9qyqqvdds-emacs-27.1/Applications/Emacs.app/Contents/MacOS/Emacs

exec /nix/store/6sap8pb8r6dd7v8jawd8wyp9qyqqvdds-emacs-27.1/bin/emacs "$@"
emacs

#!/nix/store/pmmh1dl7kmxi2xpagknl9qqa4wr7vv9c-bash-4.4-p23/bin/bash

IFS=:

newLoadPath=()
added=

if [[ -n $EMACSLOADPATH ]]
then
while read -rd: entry
do
if [[ -z $entry && -z $added ]]
then
newLoadPath+=(/nix/store/pbhxhswcyjz3xmjcd8lwy2r3lra0d1aj-emacs-packages-deps/share/emacs/site-lisp)
added=1
fi
newLoadPath+=("$entry")
done <<< “$EMACSLOADPATH:”
else
newLoadPath+=(/nix/store/pbhxhswcyjz3xmjcd8lwy2r3lra0d1aj-emacs-packages-deps/share/emacs/site-lisp)
newLoadPath+=("")
fi

export EMACSLOADPATH="${newLoadPath[*]}"
export emacsWithPackages_siteLisp=/nix/store/pbhxhswcyjz3xmjcd8lwy2r3lra0d1aj-emacs-packages-deps/share/emacs/site-lisp

exec /nix/store/6sap8pb8r6dd7v8jawd8wyp9qyqqvdds-emacs-27.1/bin/emacs “$@”

Emacs is adding its own binary path to newLoadPath and using the path to vanilla emacs in the nix store, whereas emacs correctly references the site-lisp folder of /nix/store/*-emacs-package-deps, which explains why the packages aren’t loading in the former.

If I copy emacs over Emacs, everything works. However, I don’t understand what’s going on here at all.

These are my channels:

darwin https://github.com/LnL7/nix-darwin/archive/master.tar.gz
home-manager https://github.com/nix-community/home-manager/archive/release-20.09.tar.gz
nixpkgs https://nixos.org/channels/nixpkgs-20.09-darwin
nixpkgs-unstable https://nixos.org/channels/nixpkgs-unstable

It might be somehow relevant that the new machine is is a MacBook with an ARM M1 processor, as I can’t seem to replicate the issue on Intel (both machines running Big Sur 11.1).

I think I was somehow bitten by https://github.com/NixOS/nix/issues/2033.

I had realised that my macOS installs were a bit outdated compared to NixOS. So I updated the channels with

sudo -i
nix-channel --update

I think this issue might have been caused by me mismatching home-manager/nixpkgs 20.09/unstable… When changing my channels after running into https://github.com/nix-community/home-manager/issues/1645 didn’t work, that’s when I realised that my local channels were still out of date.