CLion: add WSL Legacy support (for Windows builds < 1709)

Windows

CLion, the JetBrains C/C++ editor, supports WSL (Windows Subsystem for Linux), which allows you to build your code with a Linux compiler (gcc / clang) using an IDE on Windows. Unfortunately, the support is now officially limited to Windows builds starting 1709, where Linux distributions can be directly installed from the Windows Store. Let’s see how add the support legacy WSL (the one you can manage using lxrun). Please understand that this method is obviously not officially supported, and all CLion WSL-related features may not work.

Why it doesn’t work as-is

Part of the source code of CLion is public: the IntelliJ platform (all JetBrains IDE shares a common source-code part which uses to be foundations of IntelliJ). The platform source code can be found on GitHub, in IntelliJ community edition repository. Let’s take a look at WSL handling code (in the platform because used by many JetBrains IDE).

At first sight, we may think that WSL legacy is supported when we see the WSLDistributionLegacy class, because WSL legacy is actually supported by the IntelliJ platform (supported by some others JetBrains IDE, see this ticket). However, we can note that this features is experimental and requires a special config key to be activated, as we can see in this snippet of code (can be found here):

// add legacy WSL if it's available and enabled
if (Experiments.isFeatureEnabled("wsl.legacy.distribution")) {
  ContainerUtil.addIfNotNull(result, WSLDistributionLegacy.getInstance());
}

The fact is, even if we enable this experimental feature, it still does not work, probably because of the second line of the code below (found in WSLCidrUtil.java, decompiled from CLion 2018.2.3) :

for (WSLDistribution distro : wslDistros) {
  if (distr oinstanceof WSLDistributionLegacy) continue;
  validWslDistros.add(new CidrWSLDistribution(distro));
}

We can see that support has been explicitly disabled in CLion.

Why it can work

CLion make a basic usage of WSL: it runs commands on the Linux subsystem directly thanks to wsl.exe (c.f. CLion logs), which is not present in pre-1709 Windows builds. However, it only uses one command from the executable: run (commands, obviously).

2 solutions offer to us:

  • Recompile the WSLCidrUtil class without the continue condition.
  • Find a way to make CLion detecting our WSL as non-legacy.

Even if both solutions seems bad, I still chose the second solution for multiple reasons:

  • This condition is probably here for a good reason.
  • Recompiling a class is annoying for updates.
  • Decompilation legality can be questioned (even if as a EU citizen, article 6 of the 1991 Software Directive permits me to decompile CLion in this very specific case: interoperability reasons).

Let’s explore the second solution. We can notice that defaults distributions are hardcoded here, but can be customized thanks to wsl.distributions.xml configuration file (you can find it in %HOMEPATH%\.CLion2018.x\config\options\).

As we can see, distributions are identified by an internal ID, a Microsoft ID and an executable path. After some time looking at the code, we can deduce that CLion runs through all available distributions and do the following:

  • Checks if executable path is absolute, and if not 
    appends it to default WSL executables root
  • Uses distribution Microsoft ID to find it from available registry keys in HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Lxss\ (matches the correct key using DistributionName value)
  • It deduces WSL root path using BasePath value: BasePath\rootfs\

CLion uses the WSL executable (let’s call it wsl.exe) as follows: wsl.exe run command, and it runs the specified shell command in WSL.

Now let’s add a new entry in wsl.distributions.xml (do not forget to replace user1 by your username).

<descriptor>
  <id>UBUNTU2</id>
  <microsoft-id>ubuntu_bash_2</microsoft-id>
  <executable-path>C:\Users\user1\AppData\Local\Microsoft\WindowsApps\my_wsl.exe</executable-path>
  <presentable-name>Ubuntu (pre 1709)</presentable-name>
</descriptor>

We just need a custom my_wsl.exe binary which respects the new wsl.exe API. You can download directly the executable or find the code here and compile it directly.

Leave a Reply

Your email address will not be published. Required fields are marked *