Files
v/doc/windows_long_paths.md

59 lines
3.2 KiB
Markdown

# Long paths on Windows
Windows limits most paths to 260 characters (`MAX_PATH`). The system setting
`LongPathsEnabled` lifts that limit only for executables that declare themselves
`longPathAware` in their manifest, or for calls that use `\\?\` paths.
## Executables built by V
On a Windows host, V gives a Windows executable a manifest that declares `longPathAware`
right after linking it, the way `-icon` adds an icon. With `LongPathsEnabled` turned on,
such an executable can create, check and open files past `MAX_PATH`.
* An executable that its linker already gave a manifest keeps that manifest unchanged.
MinGW GCC links one that declares `longPathAware` already.
* If `<output>.manifest` exists beside the final executable, V leaves that external manifest
in control. Include `longPathAware` there if the program also needs long paths.
* Executables linked by MSVC get no manifest: they load `dbghelp.dll` at startup, and its
initialization would hang on a long `TMP` (see below) before any V code runs.
* Executables built with the FastC backend (`-b fastc`), shared libraries, and Windows
executables cross-compiled on another system get no manifest either.
* If the manifest cannot be added, the build still succeeds. V then prints a warning with
`-v` or `-showcc`, or when the build directory had to move (see below).
`os.exists` uses `GetFileAttributesW`, so it follows the manifest. The compiler starts a tool
whose path is 260 characters or longer through its `\\?\` form, which `CreateProcessW`
accepts; `os.Process` also takes a `\\?\` path as it is.
## Long TMP and TEMP values
In a `longPathAware` process, Windows' own `GetTempPathW` loops forever when `TMP` is 261
characters or longer (or `TEMP`, or `USERPROFILE`, when the variables before it are unset).
`CreateProcessW` calls it for every program it starts, so such a process would hang at
100% CPU. Programs like `cmd.exe` are `longPathAware` as well.
Before a V program starts another program on Windows (`os.exec`, `os.execute`,
`os.Process`, `os.Command`, `os.system`, `os.execvp`, `os.execve`, `os.open_uri`), it replaces
a temporary folder variable that is too long with a short one, best first:
1. the 8.3 short name of the same folder,
2. `%LOCALAPPDATA%\Temp`,
3. `%SystemRoot%\Temp`.
The program's own environment changes, so child programs inherit the short value. An
environment given to a child explicitly (`os.Process.set_environment`, `os.execve`) gets
the same fix.
## Build directories
`tcc.exe` is not long-path aware, and `CreateProcessW` cannot start a program whose working folder
is past `MAX_PATH`. When the C build directory next to the output (also the one of
`-b fastc`), or the TinyCC preflight directory under the temporary folder, would be 240
characters or longer, V uses a short name
for it under `%LOCALAPPDATA%\v3cc`, which only the user can write to. That per-build directory
is removed after the build; the `v3cc` folder itself stays. Shorter directories keep their
usual place, and other operating systems never move them.
The C build directory stays where it is when a C or linker flag holds a relative path that
leaves it, such as `-L../libs`, since such a path names a file beside the output.