WSL2で快適なプログラミング環境を用意する
2020/08/08
#wsl
C++, Python, Webの開発環境をWSL2で整えてみる

最近PCを新しくしたのでプログラミング環境を一から整えることになりました。最初はLinux側で環境を整えるつもりだったのですが、WSL2がどんな感じなのか気になったのでWSL2で環境を整えてみました。結論から言うと大抵のことは出来て、とても良いです。

WSLで何ができるか?

WSLは超ざっくり言うと、Windowsの中でLinuxを動かせるようにするものです。Linuxのコマンドやツール群をWindows上で使うことができるようになります。Virtual Boxでも同じことはできますが、WSLはWindows上でネイティブに動作する点が異なるそうです。

具体的には次のようなことが行えるようになります。

  • Linuxコマンドの使用
  • Linux側でのCUIアプリケーションの利用
  • Linux側でのGUIアプリケーションの利用(設定が必要)
  • Windows, Linux間でのファイルのやり取り

本当にWindowsの中にLinuxがそのまま入ってしまうという感じです。

ここでGUIアプリケーションの利用と書いてあるのですが、これは最初から使えるわけではなく、色々と設定が必要となります。基本的にはCUIベースでの利用を想定していると思われます。従ってWSLでUbuntuを導入しても最初に見るのはTerminalの黒い画面だけです。

WSL1とWSL2

WSLには現在WSL1とWSL2の2つが存在します。WSL2は最近出たばかりのもので、WSL1と違ってLinux Kernelをフルサポートしている点が異なるそうです。また、ファイルシステムのパフォーマンスも改善されているそうです。これについては公式の次の記事が参考になるかと思います。

今回はWSL2を導入してみることにしました。

WSL2の導入

Windows側で色々とやる必要があります。導入手順もどんどん変わっていくと思われるので、ここでは導入で参考にした記事を紹介するのに留めたいと思います。

今回はLinuxディストリビューションとしてUbuntu 20.04を選びました。

Windows側でのTerminal選び

WSLを導入すると、導入したLinuxディストリビューションの名前で起動できるダサいターミナルがついてきます。流石にダサすぎるので、元々Linux側で使っていたHyper Terminalを使うことにしました。

導入してテーマとか整えるとこんな感じです。かわいい。

Hyperの様子
Hyperの様子

WSLでVS Codeを使う

WSLにはGUI環境がデフォルトで存在しないわけですが、Windows側のVS CodeにRemote - WSL Extensionを導入することで、Windows側のVS CodeをWSL上で起動することができるようになります。これによってWindows側のVS CodeからWSL上のコード編集、デバッグなどが行えるようになります。とても便利です。

GUIを必要としないアプリケーションの開発はこれで全部済んでしまいそうです。

以下はWindows側のVS CodeでWSL上のREADME.mdを編集している様子。

VS Codeの様子
VS Codeの様子

WSL2上でのWeb開発

WSL2上でサーバーを立ち上げて、Windows側からアクセスしたいとします。これはすごく簡単にできて、単純にWindows側でlocalhostにアクセスするだけです。Web開発も普通にできそうですね。

以下はWSL2上でサーバーを立ち上げて、Windows側からアクセスしている様子。

WSLでのWeb開発
WSLでのWeb開発

なおWSL2ではWindows側と別IPアドレスを持っているため、以前はWSL側のIPアドレスを指定しないとアクセスできなかったようです。これがアップデートによって改善されました。良いですね。

WSL側からWindowsのファイルにアクセスしたいとき

Windows側のファイルはWSLでは/mnt/cからアクセスできます。Windows側のファイルもLinuxのコマンドで操作できるので嬉しいです。

GUIアプリケーションの利用

WSL上でGUIアプリケーションも使えると嬉しいですが、これはWindows側にXサーバーを導入し、WSL側からWindows側のXサーバーに接続することで可能になります。

Windows側でのXサーバーの導入

Windowsで使えるXサーバーには次のようなものがあります。

  • Xming
  • VcXsrv

Xmingは最新のものは有償となっており、無料で使えるのは少し前のバージョンのものになります。今回はVcXsrvを使うことにしました。

まずはVcXsrvをダウンロードして、Windows側にインストールします。

インストールできたらVcXsrvを起動し、設定を行っていきます。

最初に表示されるDisplay SettingsではMultiple windowsを選択し、Display numberにはデフォルトの-1を入力して次に行きます。

次のClient startupではデフォルトのStart no clientを選択して次に。

最後のExtra Settingsは重要です。Disable access controlの箇所にチェックします。こうしないとWSL側からVcXsrvへのアクセスが拒否されます。もちろんセキュリティをちゃんと考えるならアクセスコントロールの設定をやったほうが良いと思いますが、面倒くさいので自分はそうしちゃいました。

これでVcXsrvの設定は完了です。最後に出るSave configurationをクリックすれば設定を保存することができます。保存した設定ファイルをクリックすれば、保存した設定でVcXsrvが起動するようになります。

ファイアウォールの設定

次にWindows側でVcXsrvのファイアウォールの設定をする必要があります。

Windowsのファイアウォールの設定を開き、受信の規則でパブリック, TCP 6000番の受信を許可します。

このままだとセキュリティ的にアレなので(一応ルーター側でTCP 6000番を許可しなければ外部からのアクセスは遮断できますが、内部からは接続し放題です)、WSLに割り当てられるIPアドレスの範囲だけからの通信を許可するようにします。プライベートIPのクラスB(172.16.0.0/12)に制限すれば良いです。

WSL側の設定

最後にWSL側でDISPLAY環境変数の設定が必要になります。

WSL2では単純にDISPLAY=:0.0とするとうまくWindows側のXサーバーに接続できません。WindowsとWSLでIPアドレスが異なるためです。従ってWindows側のIPアドレスを指定する必要がありますが、これは次のようにしてできます。

export DISPLAY=$(cat /etc/resolv.conf | grep nameserver | awk '{print $2}'):0

.bashrc.zshrcなどにこれを書いておくと良いでしょう。

以下を参考にしました。

動かしてみる

試しにxeyesを動かしてみます。xeyesのインストールはUbuntu 20.04ではapt install x11-appsで行えました。

Terminalにxeyesと入力して動かしてみるとWindows側で以下のようなWindowsが出ます。

matplotlibを試す

次にPythonでmatplotlibの表示を試してみます。以下のPythonコードをWSL側で実行してみます。

  1 import numpy as np
  2 import matplotlib.pyplot as plt
  3 
  4 x = np.linspace(0, 1)
  5 y = np.sin(x)
  6 plt.plot(x, y)
  7 plt.show()

実行するとWindows側でグラフが表示されます。

OpenGLアプリケーション

OpenGLアプリケーションも使用することができます。ただデフォルトではレンダリングはllvmpipeを使って行われるため、CPUを利用しています。

mesa-utilsapt installしてglxinfo -BすればデバイスやOpenGLのバージョンについて見れます。

Extended renderer info (GLX_MESA_query_renderer):
    Vendor: VMware, Inc. (0xffffffff)
    Device: llvmpipe (LLVM 10.0.0, 128 bits) (0xffffffff)
    Version: 20.0.8
    Accelerated: no
    Video memory: 7958MB
    Unified memory: no
    Preferred profile: core (0x1)
    Max core profile version: 3.3
    Max compat profile version: 3.1
    Max GLES1 profile version: 1.1
    Max GLES[23] profile version: 3.1
OpenGL vendor string: VMware, Inc.
OpenGL renderer string: llvmpipe (LLVM 10.0.0, 128 bits)
OpenGL core profile version string: 3.3 (Core Profile) Mesa 20.0.8
OpenGL core profile shading language version string: 3.30
OpenGL core profile context flags: (none)
OpenGL core profile profile mask: core profile

OpenGL version string: 3.1 Mesa 20.0.8
OpenGL shading language version string: 1.40
OpenGL context flags: (none)

OpenGL ES profile version string: OpenGL ES 3.1 Mesa 20.0.8
OpenGL ES profile shading language version string: OpenGL ES GLSL ES 3.10

Deviceがllvmpipeになっていることが分かると思います。また、OpenGLのバージョンを見ると3.3となっています。

試しにDear ImGuiのexample_glfw_opengl3を実行してみると、Windows側にちゃんと表示されました。

GPUを使ってレンダリングしたい場合は幾つか設定が必要です。まずVcXsrvの設定でNative openglにチェックします。

また、WSL側で環境変数LIBGL_ALWAYS_INDIRECTをセットします。

export LIBGL_ALWAYS_INDIRECT=1

これによってGPUでのレンダリングが可能になります。glxinfo -Bしてみると次のようになりました。

direct rendering: No (If you want to find out why, try setting LIBGL_DEBUG=verbose)
OpenGL vendor string: NVIDIA Corporation
OpenGL renderer string: GeForce RTX 2060 SUPER/PCIe/SSE2
OpenGL version string: 1.4 (4.6.0 NVIDIA 456.38)

rendererがGPUになっていることが分かります。この状態でDear ImGuiのexample_glfw_opengl2を動かしてみましたが、動作しました。一方でexample_glfw_opengl3は動かなかったため、OpenGL3には対応していないようです。個人的にはOpenGL3でシェーダー使って遊びたかったので残念です。

公式の発表によるとWSL2は今後GUIアプリケーションに対応していくことがアナウンスされています。近いうちにここで紹介したようなことは行わなくて良くなるかもしれません。

GPUの利用について

現在のところWSL2はGPUの利用に完全対応していませんが、CUDAとDirectMLについては最近のアップデートで対応しました。

個人的にはOpenGLやVulkanが自由に使えるようになると嬉しいのですが・・

公式によると今後GPUへの対応を進めていく方針だそうです。その中にはOpenGLやVulkanも含まれていて、今後に期待です。

メモリ枯渇問題

WSL2かなり良いのですが、使っていて唯一これはという問題があります。それはメモリがVmmemというWSLのプロセスに食い尽くされてしまうという問題です。

なぜそうなってしまうかについては次のページが参考になります。

対策としては上のページにも書いてあるとおり、WSL2に割り当てるメモリサイズを制限する必要があります。

総評

CUIアプリケーションやWeb開発はWSL2で十分に行えると感じました。特にVS CodeのRemote Extensionのおかげで開発がかなり楽になっていると思います。

また、GUIアプリケーションの開発も限定的ではありますが行えます。一方でGPUを使ったアプリケーションの開発はまだ無理な感じがあります。これについては今後に期待です。

参考文献