llvm-mingw icon indicating copy to clipboard operation
llvm-mingw copied to clipboard

Spurious issues with accessing files on network mounts

Open falhumai96 opened this issue 2 years ago • 62 comments

I have tested a code of my own in the following options:

  • X64 VC++ MSVC
  • X64 MinGW GCC
  • X64 Linux
  • X64 MinGW Clang

and my project compiled successfully in all the above targets except the latter. I am getting a bunch of the following errors:

In file included from <some HPP file>.HPP:<some file line number>:
In file included from <some HPP file>.HPP:<some file line number>:
In file included from <some HPP file>.HPP:<some file line number>:
In file included from <some HPP file>.HPP:<some file line number>:
...
<some HPP file>.HPP:<some file line number>:<some column number>: error: #include nested too deeply.

My project is a CMake project. Sometimes running parallel builds many times results in a successful build. Also, I am using a Ninja generator, and I am building directly on Windows.

As this is a private code, I cannot share code snippets here, but I am happy to have a private chat with you in a different chat channel regarding this matter.

falhumai96 avatar Mar 05 '23 07:03 falhumai96

Could you provide any minimal sample code or project to reproduce the issue?

Biswa96 avatar Mar 05 '23 07:03 Biswa96

let me try to create a sample project that can repro the same problem, and ill link you to it

falhumai96 avatar Mar 05 '23 07:03 falhumai96

For the time being, I have added @Biswa96 and @mstorsjo to my private repo for investigation.

falhumai96 avatar Mar 05 '23 07:03 falhumai96

Try to rebuild with GCC/G++ MinGW as CC/CXX vs Clang/Clang++ (e.g. both either from MSYS2 or clang/clang++ from release of llvm-mingw ... I tried both). Also, I noticed that Clang does not respect _setmode(_fileno(stdout), _O_U16TEXT); to set the output to unicode (I can't print using std::wcout for e.g.).

falhumai96 avatar Mar 05 '23 07:03 falhumai96

I can not reproduce your original issue with llvm-mingw. I have used the llvm-mingw-20230130-ucrt-x86_64.zip file, extract it in a directory, add that to PATH environment variable. Then compiled it with cmake + ninja + llvm-mingw without any problem.

Biswa96 avatar Mar 05 '23 07:03 Biswa96

Hmm weird. By the way, I am running the build from SSH to a Windows VM. Could this be a problem?

falhumai96 avatar Mar 05 '23 07:03 falhumai96

Also, what are your versions of CMake and Ninja?

falhumai96 avatar Mar 05 '23 07:03 falhumai96

My CMake is 3.26.0-rc3 My Ninja is 1.11.1

falhumai96 avatar Mar 05 '23 07:03 falhumai96

I'm using it in msys2 mingw environment in bare metal Windows 10.

  • cmake: https://packages.msys2.org/base/mingw-w64-cmake
  • ninja: https://packages.msys2.org/base/mingw-w64-ninja

I'm not sure if the environment have any effect on preprocessing CPP files.

Biswa96 avatar Mar 05 '23 08:03 Biswa96

Can you also try to change some simple logic in any of the files and try to rebuild? For some reason the build errors seems to be intermittent. Sometimes the build goes through, sometimes I see aforementioned bug above.

falhumai96 avatar Mar 05 '23 09:03 falhumai96

Tried it, can't reproduce any issue. If you want clean build environment the Docker image may help. Docker Hub link is in README file.

Biswa96 avatar Mar 05 '23 09:03 Biswa96

@Biswa96 If possible, can you try to build on Win 11 as well? I am using Win 11 pro VM btw.

falhumai96 avatar Mar 06 '23 07:03 falhumai96

I have tried in bare metal Windows 11 installation as well. Same result, no issue or compiler error.

Biswa96 avatar Mar 06 '23 07:03 Biswa96

I have just tried a Windows 10 Pro installation and same problem happens. Here is what I did:

  • I download CMake 3.25.2 from official site: https://cmake.org/download/.
  • I downloaded Ninja from official github release site from: https://github.com/ninja-build/ninja/releases/tag/v1.11.1.
  • I download LLVM-MinGW from: https://github.com/mstorsjo/llvm-mingw/releases/tag/20220906.
  • I installed CMake and set the path for all users.
  • I put ninja somewhere and set path to it.
  • Same thing for LLVM-MinGW's top bin folder.
  • I set CC = x86_64-w64-mingw32-clang and CXX = x86_64-w64-mingw32-clang++.
  • I did cmake <project full path dir> -DCMAKE_INSTALL_PREFIX=<some custom install dir full path> -GNinja
  • I did "ninja install".

and same problem I see in my Win 10 pure installation.

falhumai96 avatar Mar 06 '23 08:03 falhumai96

@Biswa96 what do you mean by bare metal windows btw here? like IoT windows version?

falhumai96 avatar Mar 06 '23 08:03 falhumai96

can you please describe all the steps you have taken perform a clean build (also including how did you setup ur environment)? maybe I am missing something here.

falhumai96 avatar Mar 06 '23 08:03 falhumai96

bare metal means like normal installation on actual drive, no VM, no hypervisor. I am using msys2 (https://www.msys2.org/) project. But discussing about that would be off-topic here. You can use CI or container image to build your project with llvm-mingw.

Biswa96 avatar Mar 06 '23 08:03 Biswa96

I cannot reproduce any such build problem with the repo you provided.

To get a third party reproducible setup, I would recommend trying to reproduce the issue in e.g. GitHub Actions builds. If you manage to show a failure there, anybody else with a copy of the same repo should be able to reproduce the bug in the same way.

mstorsjo avatar Mar 06 '23 12:03 mstorsjo

I am getting different results in VirtualBox VM (above results) and bare metal Windows 11. On bare metal, I am now getting the following output:

cmd.exe /C "cd . && "C:\Program Files\CMake\bin\cmake.exe" -E rm -f lib\lib<Some Lib>.a && C:\PROGRA~1\LLVMMI~1\20230130\msvcrt\bin\X8FE23~1.EXE qc lib\lib<Some Lib>.a  lib/CMakeFiles/<Some Dir>.dir/__/common/LongPathSupport.rc.res lib/CMakeFiles/<Some Dir>.dir/Common.cpp.obj lib/CMakeFiles/<Some Dir>.dir/<Some File>.cpp.obj lib/CMakeFiles/<Some Dir>.dir/<Some File>.cpp.obj lib/CMakeFiles/<Some Dir>.dir/<Some File>.cpp.obj && C:\PROGRA~1\LLVMMI~1\20230130\msvcrt\bin\X8396E~1.EXE lib\lib<Some Lib>.a && cd ."
C:\PROGRA~1\LLVMMI~1\20230130\msvcrt\bin\llvm-X8FE23~1: Invalid argument
ninja: build stopped: subcommand failed.

This is how I set the environment before calling CMake build and install (testing on release 20220906 (I found the same issue with Clang-15 and Clang-16) with msvcrt) [testing on PowerShell Core]:

$env:Path = "C:\Program Files\LLVM MinGW\20220906\msvcrt\bin;$env:Path"; $env:CC = "x86_64-w64-mingw32uwp-clang.exe"; $env:CXX = "x86_64-w64-mingw32uwp-clang++.exe".

Then, I do cmake <Project full path> -DCMAKE_INSTALL_PREFIX=<Install full path> -GNinja and ninja install on the build directory.

It is weird why I am getting different outputs on different setups (same Windows setup, just different way of running it (bare metal/VM)).

falhumai96 avatar Mar 10 '23 07:03 falhumai96

Don't put anything in a path containing space characters. It is often a source of all kinds of weird issues.

alvinhochun avatar Mar 10 '23 08:03 alvinhochun

But, C:\Program Files is by default having spaces, which is where more most binaries reside (e.g. default install path for CMake). Not handling spaces in my opinion is a bug (a bug that I did not find earlier when playing around with the toolchain like 2-3 years ago).

falhumai96 avatar Mar 10 '23 08:03 falhumai96

Hmm, having ninja and the LLVM MinGW toolchain in a path no spaces has no errors.

falhumai96 avatar Mar 10 '23 08:03 falhumai96

What happens if you use the 8.3 name in your powershell script?

Instead of:

$env:Path = "C:\Program Files\LLVM MinGW\20220906\msvcrt\bin;$env:Path";

use

$env:Path = "C:\PROGRA~1\LLVMMI~1\20230130\msvcrt\bin;$env:Path";

CMake uses 8.3 old dos naming for Ninja files in order to overcome any space issues.

Edit: I've noticed that there are two dates here in the LLVM MinGW paths, make sure you have the same version for the 8.3 test.

cristianadam avatar Mar 10 '23 09:03 cristianadam

If I am to guess, it is possible that the llvm-mingw wrapper doesn't know how to handle 8.3 module names.

alvinhochun avatar Mar 10 '23 09:03 alvinhochun

With the tools placed in a path with spaces, I can indeed reproduce issues. And the issues are most probably caused by the wrapper executables indeed.

If I am to guess, it is possible that the llvm-mingw wrapper doesn't know how to handle 8.3 module names.

Yeah, that looks like it. Or more precisely - when the tool has been executed as C:\PROGRA~1\LLVMMI~1\20230130\msvcrt\bin\X8FE23~1.EXE, the tool tries to inspect X8FE23~1.EXE to see what executable to invoke, but can't figure it out - while it would have expected something like x86_64-w64-mingw32-ar.exe (which it parses and then invokes llvm-ar.exe).

When I try it out, I run into a case where it fails to link, since it executes C:\code\16rc1\PATHWI~1\bin\C__~1.EXE, and the wrapper doesn't detect that C__~1.EXE is meant to be another name for c++.exe, i.e. it should link in C++ mode.

I guess some step that doesn't look at argv[0] but instead resolves the name of the executable, would be necessary. (The LLVM based tools do this internally.)

The current approach of using argv[0] would be better, though, if we would be using symlinks. E.g. it would allow us to have both clang.exe and clang++.exe be symlinks to clang-target-wrapper.exe; by looking at argv[0], we should be able to figure out which name the user used for the symlink. If we resolve it to the actual name of the exe, we'd only see clang-target-wrapper.exe.

Or are there other ways to ask the filesystem to reverse-map the mangled file name in argv[0] into a full pathname?

mstorsjo avatar Mar 10 '23 11:03 mstorsjo

(Or as a separate sidetrack - is there any way to ask the CMake generator to not flatten paths to 8.3 paths, trusting that the tools themselves can handle arguments/paths with spaces correctly?)

mstorsjo avatar Mar 10 '23 11:03 mstorsjo

One can disable the 8.3 file naming on NTFS as seen at https://learn.microsoft.com/en-US/troubleshoot/windows-server/performance/stop-error-code-0x00000019

fsutil behavior set disable8dot3 1

If CMake and Ninja doesn't work afterwards then it's a valid CMake bug 🙂

cristianadam avatar Mar 10 '23 11:03 cristianadam

I think it would be easier to use something like GetLongPathName and / or GetShortPathName.

cristianadam avatar Mar 10 '23 11:03 cristianadam

The current approach of using argv[0] would be better, though, if we would be using symlinks. E.g. it would allow us to have both clang.exe and clang++.exe be symlinks to clang-target-wrapper.exe; by looking at argv[0], we should be able to figure out which name the user used for the symlink. If we resolve it to the actual name of the exe, we'd only see clang-target-wrapper.exe.

It seems like I misremembered about this; we do see the name of the symlink instead of the main executable from GetModuleFileName.

The usecase I thought about was to fake the behaviour of symlinks without having them; you could do the equivalent of execl(/*file*/ "actual-executable.exe", /*argv[0]*/ "<triple-prefix>-toolname.exe", /*other-args*/...), where you pass a fake executable name in argv[0] - that would essentially get the effect of having symlinks, without needing to have physical files corresponding to that file name (which would be nice on Windows, where symlinks still are a bit problematic.) I don't think anything relies on that though. (And if it does, it'd be simple to add support for it, in the form of dirname(GetModuleFileName())/basename(argv[0]).)

I think it would be easier to use something like GetLongPathName and / or GetShortPathName.

Thanks, that seems to do the trick - see https://github.com/mstorsjo/llvm-mingw/commit/829aad161faea2f357ef840c130837a34e90d53b. (I'm currently test running this a bit; I'll push it to the master branch once it looks good. Freel free to comment on it!) I see that LLVM already was doing pretty much exactly the same too: https://github.com/llvm/llvm-project/blob/llvmorg-16.0.0-rc3/llvm/lib/Support/Windows/Process.inc#L209-L219

mstorsjo avatar Mar 10 '23 17:03 mstorsjo

@mstorsjo if possible, can you also try the current LLVM MinGW wrappers in Windows inside VirtualBox? I have seen different results there. Not sure if it also applies o other VMs.

falhumai96 avatar Mar 10 '23 20:03 falhumai96