0

I develop c++ apps on linux and i use neovim with coc.nvim and coc-clangd plugins. I want to develop an app for windows but i comfort with linux and neovim so i want to use them for it. But i get some include errors with some windows headers (etc. "windows.h").

I use linux only for writing the code and i'll compile the program on windows. How can i prevent this errors and use windows headers with coc.nvim?

enter image description here

romainl
  • 186,200
  • 21
  • 280
  • 313
sabenburra
  • 93
  • 1
  • 3
  • 6

2 Answers2

2

i'll compile the program on windows

You can cross-compile it from Linux. It's only marginally more difficult than getting the code completion to work.

  1. Get the standard library headers (and libraries, if you want to cross-compile) from MinGW.

    Your package manager might have those, or you can get them from https://winlibs.com/.

    I prefer getting those from MSYS2, and made scripts to automate this (since MSYS2 is otherwise Windows-only):

    git clone https://github.com/holyblackcat/quasi-msys2
    cd quasi-msys2/
    make install _gcc
    
  2. Figure out the Clang flags needed to cross-compile.

    Unlike GCC, which for every target platform requires a separate compiler distribution, Clang is inherently a cross-compiler. You only need a single Clang distribution to compile for any supported platform.

    Download Clang from your package manager, and point it to the freshly downloaded headers and libraries.

    Following flags work for me: clang++-14 1.cpp --target=x86_64-w64-mingw32 --sysroot=/path/to/quasi-msys2/root/mingw64 -fuse-ld=lld-14 -pthread -stdlib=libstdc++ -femulated-tls -rtlib=libgcc.

    --target and --sysroot are crucial. The latter needs to point to the files you've downloaded. The remaining flags are less important.

    Running this should produce a.exe, runnable with wine a.exe.

  3. Feed the same flags to Clangd.

    There are several ways to set compiler flags for Clangd.

    The easiest one is to create a file named compile_flags.txt in your project directory, and put the flags into it, one per line:

    --target=x86_64-w64-mingw32
    --sysroot=/path/to/quasi-msys2/root/mingw64
    -fuse-ld=lld-14
    -pthread
    -stdlib=libstdc++
    -femulated-tls
    -rtlib=libgcc
    

    Then Clangd should do the right thing for any source files in this directory.


Apparently, my Quasi-MSYS2 can somewhat automate this.

After running the commands above (make install _gcc and others), run make env/shell.sh, and run your editor from this shell.

Replace compiler_flags.txt with compiler_commands.json with following contents:

[
    {
        "directory": "/your/sources",
        "file": "/your/sources/1.cpp",
        "command": "win-clang++ 1.cpp"
    }
]

Where win-clang++ is a Clang wrapper I ship, which automatically adds the flags I listed above.

Configure your editor to add following flag to Clangd: --query-driver=/path/to/win-clang++ (use which win-clang++ from quasi-msys2 shell to get the full path).

This makes Clangd obtain the right flags automatically from this wrapper.

HolyBlackCat
  • 78,603
  • 9
  • 131
  • 207
  • firstly, thanks for your answer. i tried compile my code with the flags that you write, i got this error: "clang-14: error: invalid linker name in argument '-fuse-ld=lld-14'". when i remove this flag, it compiled successfully. but when i try run the .exe file on windows, i get this error: "libstdc++-6.dll not found" – sabenburra Aug 25 '22 at 20:06
  • @g3n1u5 *"invalid linker name in argument"* LLD needs to be installed separately for it to work. Depending on how it's named, you might need to spell it as just `-fuse-ld=lld`. But if the stock linker works (if everything works without this flag), you can just skip it. – HolyBlackCat Aug 25 '22 at 20:08
  • @g3n1u5 *"libstdc++-6.dll not found"* Copy this file and place it next to your .exe. Quasi-MSYS2 installs it to `quasi-msys2/root/mingw64/bin`. Alternatively, add `-static` to statically link everything. – HolyBlackCat Aug 25 '22 at 20:09
  • .exe runs succcesfully. i write the flags to compile_flags.txt file but then, clangd can't found the iostream file. And shows error for it on neovim :( – sabenburra Aug 25 '22 at 20:39
  • @g3n1u5 Can you share Clangd logs? Not sure where neovim puts those. – HolyBlackCat Aug 25 '22 at 20:42
  • 1
    oh, i just enter a wrong path to compile_flags.txt for --sysroot flag. i fixed that and the problem solved now. thanks a lot for your answers. – sabenburra Aug 25 '22 at 20:53
0

You can't use windows.h while you're compiling a Linux native application. If want to make your application platform ready and you're using some kind of OS native cals, then you have to probably use defines like #if _WIN32/__linux__ and so on. At the end, you can cross-compile your application to Windows while you're running on Linux as well.

Andy
  • 74
  • 9