Setup Windows 10 Development Environment
hack wslAfter several weeks research, I pulled the trigger for a new Windows laptop, and started the journey to build the development environment in Windows. Arguably, the MacBook Pro is still a better choice thanks to the native Unix environment; but the Windows Subsystem for Linux, aka WSL and Docker Desktop for Windows helped to close the gap.
Hardware
The spec of the Windows laptop, HP Envy 13-aq0011ms is not top of the line, but strikes a good balance between the performance and portability:
- Intel Core i5-8265U 1.60 GHz with Turbo Boost Technology up to 3.90 GHz
- 8GB DDR4 2400 SDRAM1
- 256GB PCIe NVMe M.2 SSD
- 13.3-inch FHD(1920 x 1080) IPS touchscreen, 10-finger multi-touch support
- 2.92 lbs (1.27 kg)
And the price too, $499; — it is quite rare to get all three out of three in this industry.
The build quality is impressive: the aluminum body is really a joy to work with; the privacy camera kill switch is a nice touch. The USB Type-C port with Power Delivery is a nice surprise, — I can charge the laptop with the MacBook Pro charger. Though the charge won’t go through the USB-C AV multiport adapter.
On the flip side, the touchpad is subpar: it’s too sensitive when typing, and too insensitive for drag-and-drop. The keyboard is as flaky as the notorious butterfly keyboard in MacBook Pro. The Ctrl, Fn, Win, Alt keys are really hard to work with: the Ctrl key is too far and too small for the pinkie to reach. We will fix it in the Keyboard shortcuts.
Prerequisites and Scopes
I learned my lessons when tweaking the linux desktops in my earlier days. The scopes of the initiative are limited as:
- I will use vscode(with vim plugin) as the main editor.
- I will use firefox as the main browser.
- All interpreters, libraries, compilers, terminal applications will stay in WSL
land, except
git
as the vscode source control depends on the native git executable. - I will use
wsltty
as the main terminal for WSL. - I will not attempt to automate the setup as I am still exploring.
In Windows, I use the Chocalatey package manager to manage softwares packages, such as:
choco install firefox vscode autohotkey microsoft-windows-terminal nodejs-lts docker-desktop wsltty git
Windows Subsystem for Linux
The Windows Subsystem for Linux, aka WSL, provides a good enough emulation of
Linux runtime. It is not a full-fledged linux distro: the underlying file system
is case-insensitive, the systemd
init is partially supported, etc2; but
good enough for dependency management.
I followed this guide to install the WSL2:
dism.exe /online /enable-feature /featurename:Microsoft-Windows-Subsystem-Linux /all /norestart
dism.exe /online /enable-feature /featurename:VirtualMachinePlatform /all /norestart
With build 17093, we can configure wsl’s DrvFS to store metadata for Linux’s
ACL. Add this to /etc/wsl.conf
:
[automount]
enabled = true
root = /
options = "metadata,umask=22,fmask=11"
mountFsTab = false
- the
root
configures ALL disks are mounted in/
, instead of the default/mnt
. This is required by the docker desktop, see WSL bug. - the
options
enable the metadata, and the umask improvement.
The update of /etc/wsl.conf
requires a WSL restart, with build 17046 we can
terminate WSL without reboot:
wsl -l
Windows Subsystem for Linux Distributions:
Ubuntu-18.04 (Default)
wsl -t Ubuntu-18.04
Customization
I have to keep reminding myself to timebox this process as it is a never-ending
journey. The configuration, or dotfiles
are grouped under the manydots
umbrella, feel free to cherry pick for your convenience.
In WSL, I use vcsh
to manage dotfiles, — it solves the problems that
multiple repositories are mounted in the same directory, $HOME
. See
this post for more details.
Keyboard shortcuts
I have been using MacBook Pro at work for several years, the muscle memory does not serve me well in Windows shortcuts. I prefer to customize the keyboard shortcuts in Windows just similar to macOS shortcuts.
More concretely, we will map Alt in Windows to Command in macOS, — as they are roughly the same size and in the same spot. We will use the Alt+C to replicate the Command+C for copy to clipboard shortcut. Thus we need to map Alt+C to Ctrl+Insert in the terminal, and Ctrl+C in the remaining applications.
The awesome AutoHotKey, aka AHK, can customize the key mapping in Windows. I slowly built my AutoHotKey.ahk from this gist for my personal habit. You can follow this guide to auto load the script when Windows boots.
Touchpad Gestures
The HP Envy 13 laptop is equipped with Precision Touchpad, which means it supports multi-finger gesture. Unfortunately, two-finger gestures can only scroll vertically or horizontally, no swipe. The TouchpadSwipe addon tried to simulate the swipe gesture in the software side, but did not work reliably.
Terminal
I use wsltty
as the default WSL terminal. It is built upon the mintty
code
base with wslbridge
library, so we can reuse the mintty configuration, in
%APPDATA%
:
git clone [email protected]:manydots/minttyrc.git mintty
You can install the powerline fonts for better look and feel for tmux and vim.
ZSH
I use zplug prezto to manage zsh plugins for better loading performance,
see zplug bug.
git clone --recursive https://github.com/sorin-ionescu/prezto.git "${ZDOTDIR:-$HOME}/.zprezto"
This will install the prezto
in $HOME/.zprezto
. I then sync the my zsh
configuration:
vcsh clone [email protected]:manydots/zshrc.git 'zshrc'
chsh -s /usr/bin/zsh
Restart WSL.
TMUX
I use tpm to manage the tmux plugins:
mkdir -p ~/.tmux/plugins
git clone https://github.com/tmux-plugins/tpm ~/.tmux/plugins/tpm
Checkout this repository for my
.tmux.conf
.
vcsh clone [email protected]:manydots/tmuxrc.git 'tmuxrc'
It is worthy mentioning to setup the $TERM
to leverage mintty’s 256-color
support:
set -g default-terminal "screen-256color"
Remote Development
The vscode remote development makes this configuration possible and usable.
Launch code
in the WSL environment, vscode will install the Remote - WSL
extension, and bridge the local UI and remote development. Therefore, we can
benefit from the Windows’ graphic experience and Linux’s package management.
Nodejs in WSL
Install latest nodejs in the WSL.
curl -sL https://deb.nodesource.com/setup_13.x | sudo -E bash -
sudo apt-get install -y nodejs
sudo npm install -g yarn
Launch the gatsby
for this blog:
yarn develop
... ...
You can now view silversmith in the browser.
http://localhost:8000/
You can navigate to http://localhost:8000/
to access the site, — not port
remap needed.
Python in WSL
You might consider to install native Windows distribution to leverage CUDA acceleration since GPU is not accessible in the WSL environment. I would install the latest miniconda since the MKL optimization is included, and the HP Envy is not equipped with dedicated video adapter.
First install the pyenv
to manage multiple python runtimes.
git clone https://github.com/pyenv/pyenv.git ~/.pyenv
I don’t use virtualenvwrapper
, and prefer dedicated virtual environment venv
for each project. Add the two lines in the .zshrc
to enable the virtualenv
auto-switch:
zstyle ':prezto:module:python' skip-virtualenvwrapper-init 'on'
zstyle ':prezto:module:python:virtualenv' initialize 'yes'
zstyle ':prezto:module:python:virtualenv' auto-switch 'yes'
Install the following packages via pyenv and conda
:
pyenv install miniconda3-latest
conda install numpy scipy panda matplotlib scikit-learn
You can also verify the mkl is supported as suggested here:
conda install pytest
python -c 'import scipy; scipy.test()'
Docker Desktop
Container has become the de-facto standard in the state-of-art deployment pipeline. It is quite common that the infrastructure component is packed in the docker container format. I take the middle ground:
- the infrastructure, such as RDBMS, ElasticSearch will be managed by the docker stack.
- the web application with business logic run in WSL for better introspect, debug support.
After the Docker Desktop for Windows3 installed, I enabled the
Expose daemon on tcp://localhost:2375 without TLS
option in settings, then
restarted the docker engine. This allows the docker client in WSL to talk to the
docker engine.
In WSL, install the docker, and run the docker command with DOCKER_HOST
configured to the port we just exposed:
sudo apt-get install docker.io
DOCKER_HOST=tcp://127.0.0.1:2375 docker run hello-world
I hesitated to take the advantage of the WSL backend as I felt the software stacks kind of shaky with so many experimental features built upon each other. Also the VM-based container runtime is more close to the production environment, a good candidate for staging environment.
Close Thoughts
The remote programming seems odd in the first sight, but essentially quite common in the software industry. Simply because the application is too big, or too complicated to fit into the MacBook Pro, or DevOps has no appetite to maintain two runtimes. From this point of view, macOS has only marginal advantage than the Windows, the developers will use Linux anyway.
Footnotes
-
Soldered in the motherboard unfortunately. It is a stretch to run docker, android emulator simultaneously in 8G memory just fyi. ↩
-
That is why I am hesitant to adopt the
nix
in WSL. ↩ -
Docker Desktop for Windows requires the Windows Professional or Windows Enterprise due to the Hyper-V feature, even though the WSL backend does not depend on Hyper-V. ↩