Cargo: Add longPathAware to the app manifest on Windows

Created on 11 Mar 2020  路  5Comments  路  Source: rust-lang/cargo

Describe the problem you are trying to solve

On Windows, when the directory where the project files are located is too long, cargo fails with various file-related errors.

Describe the solution you'd like

Rust should handle long path ok. We just have to add a longPathAware to the app manifest:
https://docs.microsoft.com/en-us/windows/win32/fileio/naming-a-file

<application xmlns="urn:schemas-microsoft-com:asm.v3">
    <windowsSettings xmlns:ws2="http://schemas.microsoft.com/SMI/2016/WindowsSettings">
        <ws2:longPathAware>true</ws2:longPathAware>
    </windowsSettings>
</application>

Notes

This issue only occurs if the file paths cargo wants to touch are too long.
This happens with paths like these:

C:\Users\User\AppData\Local\Yarn\Cache\v6\.tmp\19aa03367eb9c4791798fcfbbdd8d7d4.e2c16fa02b2d9250fe13c2054c37a11aef5c0da3.prepare\native\target\x86_64-pc-windows-msvc\release\.fingerprint\semver-parser-dc26c18a352c24f5\lib-semver_parser-dc26c18a352c24f5.json
C-feature-request O-windows

Most helpful comment

Rust doesn't have a way to embed the app manifest AFAIK.

If your CI has the MSVC toolsets installed, you have all that you need. Don't have them? Here is the direct download link.

The default registry key needed for that is OFF, so I don't think it would help most people

But for the people who DO have it on, it would help. In my opinion, that's a pretty good start! And when developers start seeing that their colleague got it working, they will ask "hey dude, what did you do?", and soon their IT department will turn the switch on for all new dev computers.

All the windows-interfacing APIs (in C and Rust) would need to be audited/updated for the larger constant.

If your windows-interfacing APIs are still using a static 260-char buffer, it's past time to fix that code. All Windows APIs have a way to query the required buffer length. The typical way is calling the function with a 0-length buffer, and the return code is the required length. Any skilled Windows developer should know that.

All of rustc and cargo would need to handle this.

Yep. Let's start with this tool (this issue is about Cargo, right?). When it's done, other executables will copy the solution. Lead by example!

IIRC, MSVC's linker can't handle long filenames, so it probably wouldn't work even if we tried.

Have you tried? Or are you assuming other tools might not work as an excuse not to try? How will the situation improve if every maintainer used the argument "tool X is not updated, so I'm not updating tool Y" ? I strongly believe that if everyone does their part, the ecosystem will quickly improve for everybody.

Many other tools would not be able to handle these paths

Maybe they already do, but unless cargo is updated, we'll never know. And what's the worst-case here? That cargo supports it, and we find out that a downstream tool gives an error. Then we can create an issue and a PR for that downstream tool, and keep making progress.

We could maybe try to use canonicalized UNC paths everywhere

Good point, excellent explanation. This is not a very good solution. The manifest solution seems a better approach.

All 5 comments

I think this would be a very hard problem to solve, if not impossible. Some issues I can think of:

  • Rust doesn't have a way to embed the app manifest AFAIK.
  • The default registry key needed for that is OFF, so I don't think it would help most people.
  • All the windows-interfacing APIs (in C and Rust) would need to be audited/updated for the larger constant.
  • All of rustc and cargo would need to handle this.
  • IIRC, MSVC's linker can't handle long filenames, so it probably wouldn't work even if we tried.
  • Many other tools would not be able to handle these paths.
  • We could maybe try to use canonicalized device paths (\\?\) everywhere, but I think that would be very difficult and problematic. We already have problems with device paths on various filesystems. They are also not user-friendly, so would probably need some abstraction that could show different representations.

Thanks for the response! Maybe there's a workaround I could apply to handle this? Like setting a custom CARGO_TARGET_DIR - would that work? I think it should work...

It could be disable by the regedit.msc. so just stopping checking it in the cargo for windows'll be fine.

Rust doesn't have a way to embed the app manifest AFAIK.

If your CI has the MSVC toolsets installed, you have all that you need. Don't have them? Here is the direct download link.

The default registry key needed for that is OFF, so I don't think it would help most people

But for the people who DO have it on, it would help. In my opinion, that's a pretty good start! And when developers start seeing that their colleague got it working, they will ask "hey dude, what did you do?", and soon their IT department will turn the switch on for all new dev computers.

All the windows-interfacing APIs (in C and Rust) would need to be audited/updated for the larger constant.

If your windows-interfacing APIs are still using a static 260-char buffer, it's past time to fix that code. All Windows APIs have a way to query the required buffer length. The typical way is calling the function with a 0-length buffer, and the return code is the required length. Any skilled Windows developer should know that.

All of rustc and cargo would need to handle this.

Yep. Let's start with this tool (this issue is about Cargo, right?). When it's done, other executables will copy the solution. Lead by example!

IIRC, MSVC's linker can't handle long filenames, so it probably wouldn't work even if we tried.

Have you tried? Or are you assuming other tools might not work as an excuse not to try? How will the situation improve if every maintainer used the argument "tool X is not updated, so I'm not updating tool Y" ? I strongly believe that if everyone does their part, the ecosystem will quickly improve for everybody.

Many other tools would not be able to handle these paths

Maybe they already do, but unless cargo is updated, we'll never know. And what's the worst-case here? That cargo supports it, and we find out that a downstream tool gives an error. Then we can create an issue and a PR for that downstream tool, and keep making progress.

We could maybe try to use canonicalized UNC paths everywhere

Good point, excellent explanation. This is not a very good solution. The manifest solution seems a better approach.

I just ran into this issue because I have a crate with a long name, over 100 characters each, so the path to the crate's location in the target folder exceeds the 260 character limit. Because of this, even cargo build fails. Does anyone following this issue know of any workarounds?

Was this page helpful?
0 / 5 - 0 ratings