Using Long Paths in Windows and Rust
Tags: rust, windows, fnm
Published: 2021-04-06 17:23:27

---
title: Using Long Paths in Windows and Rust
published: true
date: 2020-08-17 00:00:00 UTC
tags: rust, windows, fnm
canonical_url: https://gal.hagever.com/posts/windows-long-paths-in-rust/
---

Lately, I’ve been working on a Rust clone of [fnm](../fnm). I like Rust and it is a great way to learn the language. Thanks to the Rust cross-platform tooling, I got a simple proof-of-concept for Windows support quickly.

The first thing I got to do was a `install_node_dist` method, which takes a borrowed `Version` struct and a path to install into. I wrote a simple test to install Node 12.0.0 and it seemed to work on Linux, MacOS and even Windows! I was excited, but since I don’t really use Windows and fnm works perfectly well for me, I dropped it (no pun intended.)

* * *

Not so long ago I saw some tweets by [@zkat\_\_](http://twitter.com/zkat__) regarding [a new package manager for Node written in Rust](https://github.com/orogene/orogene). It made me want to play with Rust again and I decided to copy the entire fnm end-to-end test suite into the Rust project. The E2E test suite was written in Bash (with some exception for Zsh and Fish), but I migrated it to a Rust DSL so I will be able to test the same code on Bash, Zsh and Fish — “write once, run everywhere”. Maybe I’ll write more about it in later posts.

When I started migrating the tests to PowerShell, I saw that there are some versions I fail to install, because of a “path too long” error. It was weird. But since I haven’t used Windows in years, I decided to install a dev Windows VM in order to make it work. After some debugging, it seemed that the deep directory structure of the Node modules that come with Node v8.11.3 were too deep for Windows to handle with its default configurations, and I had to make some changes.

I didn’t really know how to fix it, but while traversing the web (and [finding this tweet by @zkat\_\_](https://twitter.com/zkat__/status/1283223785592680449)) I saw a similar solution in a couple of repos, including Orogene — and applying it solved my issue.

## Solving the Long Paths Issue[<svg aria-hidden="true" focusable="false" height="16" version="1.1" viewbox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg>](#solving-the-long-paths-issue)

> A Windows executable can have [an embedded manifest](https://docs.microsoft.com/en-us/windows/win32/sbscs/application-manifests) that tells Windows how to handle the executable!

This is what I was missing. By embedding the following manifest to our binary we are able to use long paths freely. Let’s say this is `fnm.manifest`:

```xml
<?xml version='1.0' encoding='utf-8' standalone='yes'?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
  <application xmlns="urn:schemas-microsoft-com:asm.v3">
    <windowsSettings>
      <longPathAware xmlns="http://schemas.microsoft.com/SMI/2016/WindowsSettings">
        true
      </longPathAware>
    </windowsSettings>
  </application>
</assembly>
```

We now need to create a [resource file](https://docs.microsoft.com/en-us/cpp/windows/resource-files-visual-studio?view=vs-2019) (I don’t really know what it is) with the following contents:

```
#define RT_MANIFEST 24
1 RT_MANIFEST "fnm.manifest"
```

The last piece of the puzzle is to embed it into our Rust program. To do that, we need to install the following crate: [`embed-resource`](https://docs.rs/embed-resource) and create a [Cargo build script](https://doc.rust-lang.org/cargo/reference/build-scripts.html):

```rust
fn main() {
    embed_resource::compile("fnm-manifest.rc");
}
```

This should hopefully make your path issues disappear. But maybe in the future it will be embedded into every Rust program, who knows?

* * *

Again, thanks again for the code I copied from [Orogene](https://github.com/orogene/orogene). Speedy CLIs for Node development are making me excited: there’s no reason we have slow tools!