Installation of Spacemacs on Windows via WSL2

A step by step guided installation tutorial with context


Updated: 2022-06-29 Wed 02:14

Take advantage of the unparalleled, extensible, and powerful text editing capabilities of GNU Emacs from within Windows OS.


1. Introduction

Is it possible to judge whether or not a piece of music is objectively good, perfect and beautiful? The word "objectively" must sound a bit old fashioned, after all, every man is doing what is right in his own eyes in these times1. But we can be reasonably certain that a song which has been well loved generation after generation has a quality absent from a yet untested, recently released album. Yes, I'm talking about Emacs here. 40 odd years is a terribly long time in the world of software. We have reason to be grateful as Spacemacs has done its part in flattening the notorious Emacs learning curve. But enough evangelizing. This comprehensive tutorial can be said to be directed towards non-programmers who are comfortable with computing (as this write-up originally existed as personal notes of mine). I hope you take away something useful!

I feel obliged to point out that there exist multiple popular ways of installing Emacs on a Windows machine. You may compile Emacs source code and run it "natively" through Cygwin. Another option is to run a virtual linux machine and install Emacs from there. Because installing natively would mean more workarounds in the future when dealing with external software and also because Windows Subsystem for Linux (WSL) offers better system call compatibility, I elected to go down the more well trodden path of running Emacs on Ubuntu through WSL. In the simplest terms, WSL is a very lightweight virtual machine that allows you to use linux kernels to run linux applications in Windows without dual booting.

Originally there existed limitations around graphical linux applications. One of my first updates to this article was to note the coming of built-in graphical support without the need for an external X server. The future has come to pass, and the changes (in the form of WSLg) have landed in Windows 11. Those hoping for a backporting of WSLg to Windows 10 are being told to "wait one". A preview of WSL in the Microsoft store also states a Windows 11 requirement. Not feeling very optimistic about the time-frame for Windows 10 WSLg, I decided to go ahead and upgrade to Windows 11.

I have kept the old Windows 10 WSL installation walk through and have added my experience on setting up WSL on Windows 11.

Windows 10 Installation Windows 11 Installation

2. Windows 10 Installation

  1. Prerequisites

    Check that you meet the requirements for running WSL2. "Win + r", type in "winver" and hit enter. Open command prompt or powerhsell and enter:

    systeminfo | find "System Type"
    

    Compare your Windows version with the below

    • For x64 systems: Version 1903 or higher, with Build 18362 or higher.
    • For ARM64 systems: Version 2004 or higher, with Build 19041 or higher.

2.1. Install Microsoft Windows Subsystem for Linux (WSL) & Your Linux Distribution

First, install the Microsoft Windows Subsystem for Linux version 2. Unless explicitly mentioned as WSL1, WSL refers to WSL version 2. WSL2 is recommended over WSL1 Unless you plan on using Linux commandline on files stored in the Native Windows file system instead of the WSL filesystem. I will go into more detail later, but the WSL filesystem is accessible in Windows Explorer and shows up as a network drive. If you are unsure, go with WSL2. This process is already documented by Microsoft (includes troubleshooting guidelines). Repeated here for completion's sake:

Enable the windows feature called "Windows subsystem for Linux" by either checking the box in the GUI screen. You can get there by searching "Turn Windows features on or off" in the control panel search box. Do the same for the check box titled "virtual machine platform". you can enable these 2 features via the shell as well.

OR open the power shell as administrator and run:

dism.exe /online /enable-feature /featurename:Microsoft-Windows-Subsystem-Linux /all /norestart
dism.exe /online /enable-feature /featurename:VirtualMachinePlatform /all /norestart

now you have to download and run the Linux kernel update package from Microsoft. Again make sure you download the right one for your CPU architecture.

2.2. Install X Server

This is the software that allows Linux to display GUI elements. You have many options here:

  1. Xming
  2. Mobaxterm
  3. Vcxsrv

I have chosen Vcxsrv. Simple installation and configuration. Download and run the sourceforge installer and you can launch the program by the "Xlaunch" shortcut. No need to change any of the settings. Click next until the end and you should see a system tray icon. Feel free to add the "X Launch" shortcut to your Windows (Win + R) folder.

After installation, create a new desktop shortcut and use the following command. Add the following command in the properties → shortcut →target

"C:\Program Files\VcXsrv\vcxsrv.exe" :0 -ac -terminate -lesspointer -multiwindow -clipboard -wgl -dpi auto

The last step before launching is to configure your X Server correctly. In the WSL terminal, export the DISPLAY variable.

$ export DISPLAY=$(awk '/nameserver / {print $2; exit}' /etc/resolv.conf 2>/dev/null):0
$ export LIBGL_ALWAYS_INDIRECT=1

The reason for the above is because the internal IP address of the WSL (2) server changes on reboot. Don't worry, the team at WSL has ensured that connections to WSL from Windows (Ex. localhost:8000) require no extra configuration. The snippet above for is for WSL to Windows 10 GUI applications. You will probably want to put the two export commands into your .bashrc file, located in '~/home/$USER$/' folder. We can do this after completing the steps below.

2.3. Install Emacs

Spacemacs is a preset configuration of Emacs, so we must first make sure Emacs is installed properly. The default Emacs build that comes with Ubuntu 20.04 on WSL doesn't support XWindows (the X Server we just installed). To fix this we are going to add Kevin Kelley's builds of Emacs with XWindows supports, simply by adding Kevin's PPA to WSL. Enter the following in the WSL Terminal.

sudo apt update && sudo apt upgrade
sudo add-apt-repository ppa:kelleyk/emacs
sudo apt update
sudo apt install emacs27

Now we are ready to proceed to 4

3. Windows 11 Installation

If the Windows 10 installation process seems replete with hacks and workarounds, then let us rejoice at the new features added to WSL in the form of WSLg. WSLg has built-in support for graphical applications – both the Wayland protocol and the X window system – and pulseaudio. This simplifies the process considerably.

I am currently using a Thinkpad T470s that met all the Windows 11 requirements with the exception of a greater than 8th generation Intel CPU. Despite the official Windows 11 upgrade assistant refusing to allow an upgrade, using Rufus to create a Windows 11 installation media worked flawlessly. The usual caveats apply. Backup any personal data, backup your Windows 10 product key, and check that the OEM has Windows 11 drivers for your model etc. Here I'd like to take a moment to thank Intel and Lenovo's Thinkpad group for providing Windows 11 drivers for the 5 year old T470s with the Intel i5 6300-U. Support for your machine may vary. Please be careful.

3.1. Install Microsoft Windows Subsystem for Linux (WSL) & Your Linux Distribution

The following inside Windows Powershell (run as Admin) will enable WSL,

# Installs WSL and sets the default distribution to Debian.
# Use wsl --list --online to list available Linux distributions.
# See https://docs.microsoft.com/en-us/windows/wsl/install for more.
wsl --install -d Debian

Ubuntu 22.04 and above should work with WSLg out of the box. The beginner friendly Ubuntu is derived from Debian, so all commands ought to work the same. After restarting your machine and creating a new WSL user check the OS version in the WSL bash shell,

cat /etc/os-release

If VERSION is not equal to the latest Debain stable release (version = 11), we must upgrade. Debian VERSION=9 (stretch) is too old for WSLg.

3.2. Install Emacs from official Debian package distribution

No nonsense, no fuss. Inside your WSL bash shell,

sudo apt install emacs

3.3. Install Emacs from source

I wrote the initial tutorial for Windows 10, for Emacs was also my introduction into the world of UNIX and Lisp. That, combined with the desire to remind my future forgetful self was the reason for the surface-level depth and hand holding steps. Now if you count yourself comfortable in such an environment, I can think of a few good reasons to install Emacs from source at this point in time.

  1. When Emacs 28+ is configured with the flag --with-native-compilation Emacs Lisp bytecode is translated to C and then machine code, yielding performance benefits.
  2. WSLg uses Wayland and Emacs 29.0.50 master has the pure GTK feature instead of relying on the older X window system.
  3. Debian does not build emacs with the flag --with-xwidgets for security reasons. With this feature enabled, Emacs is able to embed a Webkit browser widget inside a buffer. Compared to Emacs EWW which has HTML and limited CSS support, xwidget-webkit renders HTML, CSS and Javascript. Currently the xwidgets-webkit browser crashes to desktop on websites like Reddit or Youtube.

Currently Debian bullseye packages Emacs 27.1. And for the record, I find such attention to stability perfectly reasonable. I am not familiar at all with the typical C build process, so Mr. Batsov's advice helped. Onto the build process,

sudo apt update
# Install build dependencies ./configure will tell you if a build dependency is missing.
sudo apt install git build-essential libgtk-3-dev libgnutls28-dev \
 libtiff5-dev libgif-dev libjpeg-dev libpng-dev libxpm-dev \
 libncurses-dev texinfo autoconf libxml2-dev libwebp-dev \
 librsvg2-dev libsqlite3-dev liblcms2-dev libgpm-dev libotf-dev \
 libacl1-dev libjansson4 libjansson-dev libgccjit0 libgccjit-10-dev \
 gcc-10 g++-10 libwebkit2gtk-4.0-dev
export CC=/usr/bin/gcc-10 CXX=/usr/bin/gcc-10
sudo git clone git://git.sv.gnu.org/emacs.git /usr/local/src/emacs
cd /usr/local/src/emacs
sudo ./autogen.sh
# See ./configure --help for more options. "C-h v"
# 'system-configuration-options' to see what your Emacs is built with.
sudo ./configure --with-mailutils --with-wide-int --with-pgtk \
            --with-native-compilation --with-json --with-xwidgets
# gconf is deprecated in favour of gsettings.
# I have 4 threads.
sudo make -j4
# Default install in /usr/local/ and emacs-29.0.50 binary under
# /usr/local/bin.
sudo make install
# If you keep your Emacs source folder around, it will know how to uninstall
# or to git pull from master and rebuild.
sudo make uninstall
# git clean -dfX in case of rebuild.

Installing with a utility like checkinstall does package a .deb, allowing you to remove the Emacs source folder and then at a later point in time call sudo apt purge emacs. However running sudo checkinstall inside M-x shell while compiling mu (while it worked fine for Emacs?) broke my old Windows 10/WSL2 Ubuntu 20.04 system badly. I did not press Ctrl-C or interrupt the install in any way, but the outcome was the same. I regret not being able to give a more detailed bug report, for it screwed my system good and proper. See

Perhaps a symptom of WSL system not having systemd?

4. Install Spacemacs

Enter the following in your WSL terminal to install Spacemacs from the develop branch. It is strongly recommended to use develop over master as bugs get fixed more quickly on develop. You have the option to change later on. Make sure git is installed on Ubuntu and clone the Spacemacs repo.

git clone -b develop https://github.com/syl20bnr/spacemacs ~/.emacs.d

Now for the moment of truth. Launch Spacemacs by the following command in the WSL terminal.

emacs &

On the initial startup, you will be presented with a few choices. Pick "All aboard the evil…..Vim" and then "Full Installation" for the second choice. Rest assured, you will be able to change the first option later on in your dotspacemacs (~/.spacemacs) file and if you are a beginner, the full installation is preferred over the base installation. In the first initial startup, you will have to wait for all the MELPA packages to download and install. MELPA is the package manager for all Emacs packages. After the download is completed, you will have successfully installed Spacemacs.

4.0.1. Fixing the Font

If you get a message informing you that "adobe source code pro" cannot be found, you can install it with the following WSL bash commands2, or manually after having consulted: Fonts - Debian Wiki

#!/bin/bash
set  -euo pipefail
I1FS=$'\n\t'
mkdir -p /tmp/adodefont
cd /tmp/adodefont
wget -q --show-progress -O source-code-pro.zip https://github.com/adobe-fonts/source-code-pro/archive/2.030R-ro/1.050R-it.zip
unzip -q source-code-pro.zip -d source-code-pro
fontpath="${XDG_DATA_HOME:-$HOME/.local/share}"/fonts
mkdir -p $fontpath
cp -v source-code-pro/*/OTF/*.otf $fontpath
fc-cache -f
rm -rf source-code-pro{,.zip}

5. How WSL (Ubuntu) files are treated by Windows

DO NOT access the WSL linux files under @appdata/canonical etc. in the Windows explorer. According to the WSL developers, this is due to differences in how file metadata is implemented in linux versus Windows. 2 methods of properly accessing your files:

  1. To access your linux files, in your WSL bash terminal enter in

    explorer.exe .
    
  2. WSL Filepath method. Location of these files is under "\\wsl$". Click on windows explorer address bar at the top to input this address.

6. Getting Comfortable with Spacemacs

A couple of first steps to get yourself grounded. Makre sure you take caution to avoid the dreaded Emacs pinkie. Repetitive strain injury and carpal tunnel are painful and debilitating. Personally, I have made the following changes to my keyboard layout to make it more ergonomic. The benefits spill over to applications outside of Emacs as well. To do so:

  1. Install Microsoft PowerToys
  2. Under the Keyboard Remapper, swap right ctrl and right alt.
  3. swap left ctrl and left alt.
  4. swap left alt (physically the left ctrl key) with the Windows key. This will retain comfortable alt-tabbing.
  5. swap esc with caps lock.

    Emacs is designed to be keyboard driven, although scrolling and mouse support works out of the box. Now let's get started.

6.1. Prerequisite: familiarity with basic vim operations

If are new or want a brushup, access the built in tutorial via "SPC h T v" in Spacemacs ("SPC h T e" for the emacs version). If you pause after hitting "SPC", you will see a popup. This package is called "emacs-which-key" and it frees you for remembering 1001 commands. Like memorizing a piano piece, you will pick up your most commonly used bindings soon enough. To extend this analogy further, Spacemacs bindings are not without reason, but are designed to be mnemonic. If you are new to vim's way of modal editing, here is some helpful reading: vi - What is your most productive shortcut with Vim? - Stack Overflow. Even more interactive vim tutorials are easily found online.

6.2. Watch and Learn

In terms of time efficiency, depth of content covered, and ease of understanding, nothing surpasses:Spacemacs: Installation, Configuration, and Navigation Tutorial - YouTube (20 min). I seriously and whole-heartedly recommend the rest of his videos. Definitely try following along.

Almost all configuration will be done in your ~/.spacemacs file. For a proper understanding of the ~/.spacemacs file, see Streaky Cobra's breakdown of the file. The only update to this information is the placement of custom user layers and snippets in the "private" directory of the ~/.emacs.d . But that is a worry for later.

6.3. Do and Explore

Spacemacs places it's help commands under "SPC h", so give those a try. A hint for new users, "SPC h d", opens up a plethora of information. I'm am proceeding under the assumption you have watched the video in 1) and so one of the topics only lightly discussed was the concept of major and minor modes. A buffer can have one major mode, and multiple minor modes. Of course, Emacs being Emacs, it's possible to have two major modes with the package Polymode. "SPC h d b" will pull up a buffer describing the currently active modes. You can access the Spacemacs beginner tutorial with "SPC h SPC", and then typing in "Beginner's Tutorial". Now you can navigate the tutorial with the movement keys you have just learned. The tutorial is also accessible here (or in Emacs, "SPC h r").

6.4. Customize

Lastly here is a step by step example to install the "helpful" package. This is just a concrete example of package installation & configuration process. This particular package was chosen simply because it extends the "self-documenting" aspect of Emacs.

If you have found a useful Emacs package, the installation differs slightly than vanilla Emacs. The first thing to do is check the spacemacs develop layers list to see if a layer has included your desired package. Lets do that with the "helpful" package. Huh. So it is already included in a layer! That makes life easier for us, we can follow the README installation instructions. Remember you can access your dotspacemacs configuration file with "SPC f e d". Don't forget to hit "SPC f e R" to reload your configuration after adding the layer to your ~/.spacemacs file.

Now if your package is not already pre-configured in a layer, it is most likely either on MELPA or Github. If it is a local package, I'm afraid you'll have to consult the README.md found in ~/.emacs.d/private/local . In fact, that README contains all the information we need for all three use cases above. Quoted below:

  1. For a local package:
    • Load the file explicitly, using the full path to the file, by placing a

      \`(load "~/.emacs.d/private/local/package-name")\` within the body of the \`dotspacemacs/user-config\` function of your dotspacemacs file.

      • Alternatively create a directory with the name of the package in the

      \`.emacs.d/private/local\` directory, and add that directory to the load-path variable by adding \`(some-package :location local)\` to the list \`dotspacemacs-additional-packages\` within the \`dotspacemacs/layers\` function of your dotspacemacs file. After placing your package file into this package-directory the file can be loaded, without requiring the full path, by placing a \`(require 'package-name)\` within the body of the \`dotspacemacs/user-config\` function of your dotspacemacs file.

  2. If the package is on (M)ELPA simply add the package name to the list \`dotspacemacs-additional-packages\` in your dotspacemacs file
  3. For a package hosted on github the recipe for github packages can be used i.e. add

    \`\`\` (some-package :location (recipe :fetcher github :repo "some/repo")) \`\`\`

    to the list \`dotspacemacs-additional-packages\` in your dotspacemacs file.

There is no substitute for reading the documentation of the package. Or the source code itself. Luckily, the package we are about to customize makes the latter task slightly easier. Let us pretend we want to customize a variable in our dotspacemacs file. Before we do that, let's switch to the previously opened ~/.spacemacs (dotspacemacs) file buffer with "SPC b b".

One important point to keep in mind is that all key bindings are simply calling a command. From the code and package docs we can see that "helpful-variable" is a command. To run any interactive function in Emacs, we will use M-x ("alt-x" or the Spacemacs way: "SPC SPC") and type in "helpful-variable". Before we run it by hitting RET (enter), we notice – thanks to helm, an emacs completion package – that the keybinding already set for that command is "C-h v". Good to know. Press ESC to exit.

"SPC b d", ESC, q and C-g are the common default bindings to close a buffer or window.

In our dotspacemacs file let's press "SPC s s" and type in "dotspacemacs-themes". Make sure our cursor is placed on the variable "dotspacemacs-themes" and use the keybind we learned earlier: "C-h v". The variable at our cursor is filled in and a helpful buffer is drawn up. Give it a quick read. If you are curious you can compare it to "SPC h d v" with the cursor on the same point. Try swapping the "dotspacemacs-themes" variable. Save, "SPC f s" and reload "SPC f e R".

dotspacemacs-themes '(spacemacs-light spacemacs-dark)

7. Conclusion

So there you have it. The universality and power of vim's modal editing combined with the endless flexibility of the emacs lisp interpreter. Made "modern" and accessible thanks to the blood, sweat, tears and smarts of open-source contributors. Where to go from here?

8. Bonus! Why is my GUI Spacemacs interrupted by Sleep?

# Allows us to open links in Spacemacs to our Windows 10 browser
fix_wsl2_interop() {
    for i in $(pstree -np -s $$ | grep -o -E '[0-9]+'); do
        if [[ -e "/run/WSL/${i}_interop" ]]; then
            export WSL_INTEROP=/run/WSL/${i}_interop
        fi
    done
}

#Call the function
export -f fix_wsl2_interop
fix_wsl2_interop

I have kept this for last because this adds quite a bit of complexity to the installation process. It's best to make sure the above is familiar before marching on. WSL2 networking is still very much a work in progress, and WSLg will be restricted to Windows 11 only. Therefore X server sessions are not kept alive after the computer goes to sleep. This can be a deal breaker for some. If that is the case, then here is the workaround I use: courtesy of Mr. Christian Koberl.

DO NOT uninstall or change your previous VCXSRV setup. I keep both X2Go and VCXSRV open as otherwise my clipboard will stop working. Hard to debug.

After each WSL/Windows restart

  • Launch ssh in Linux (if not started yet): sudo service ssh start
  • Launch “X2Go Client” on Windows ad connect to the server with WSL user/password
  • Now you can launch X11 apps via the tray icon (see X2Go Published Applications)

To get sound you can use this link, How To Get Sound (PulseAudio) To Work On WSL2 - Linux Uprising Blog

The reason I do not use this option is due to battery usage as indicated by the Windows task manager. X2go client uses pulseaudio server and the cpu usage for windows audio process will be stuck around 8-10% CPU. My elfeed-mpv function is also very slow. I will have to wait until Windows 11 with WSLg before managing my music with Emacs.

Under Options → Settings → Pulseaudio settings, you can now disable audio input (microphone support.) This itself is desirable for many users, but it also serves as a workaround for the issue of PulseAudio failing to do output simply because input is unavailable. – doc:release-notes-mswin:x2goclient-4.0.5.1 {X2Go - [email protected]}

9. Performance tips and tricks

In the Lisp programming language family, Emacs Lisp is a derivative of the Maclisp of the 1980's. For a general purpose programming language other lisp dialects are better suited, such as ANSI Common Lisp. Emacs Lisp however remains perfectly adequate as a Domain Specific Language (DSL) for editing text. As recently as 2020 has the Emacs Lisp implementation gained the ability to compile to native machine code with libgccgit.

That does not mean performance becomes less of a concern, as many Emacs configs are treated less like a software program (for which typical best practices apply) and more like a throwaway script hacked together by the worst of copy-paste programming. I have learned the hard way that when it comes to subpar Emacs performance, the culprit and resolution is not so different from performance problems in other languages: check for errors in your own code or the libraries you use. Performance comes from data structures, and efficiency from algorithms. Even (premature) optimization out the wazoo will not save you if those principles are ignored. However if we must optimize, then it would be wise to profile first.

Open the built-in Emacs Profiler with SPC h P s.

I have it on the authority of common sense and the Emacs maintainer that messing with Emacs garbage collector is not a good idea. But if you must, check out the gcmh melpa package.

To see what functions are running at set times, see the variables timer-list and timer-idle-list.

10. Sources and Credits

Footnotes:

1

Judges 21:24 DRA. What would medieval Thomists think of the word "self-actualization"? Can man remake himself in his own image anymore than a creature can be the first cause of itself, to reduce his potential to actual in such a manner?