coding windows c/c++ on linux (update)
This is a refresh to my old post regarding tips for coding Windows code from Linux with the help of Clang for code authoring. The previous post is now almost wholly deprecated.
Get the Enterprise WDK
The EWDK now comes as a large UDF disk image which can be used right away after mounting, contrary to previous ZIP format, which required extraction, or old WDK ISOs, which required installation. It's now an entire build environment in a single image, to compile either kernel-mode, as well as user-mode Windows code.
This is how it can be mounted:
mkdir EWDK_co_release_22000_210604-1628
sudo mount -o ro,loop EWDK_co_release_22000_210604-1628.iso EWDK_co_release_22000_210604-1628
Case-insensitive access
A lot of code developed on Windows rely on non portable extensions, and a
critical one that requires proper handling while on Linux regards the case
sensitiveness of access to source files, because, even though NTFS is actually
a case-sensitive file system, it's in general accessed in a case-insensitive
way by Windows applications, this allows for non portable header inclusion to
work, and it happens a lot (e.g. #include <windows.h>
while the file is
actually named Windows.h
in the file system).
To cope with that it's necessary to create a case-insensitive mount using cicpoffs, which at the moment is a little unknown tool but that works awesomely:
mkdir EWDK
cicpoffs -o use_ino EWDK_co_release_22000_210604-1628 EWDK
Note that the use_ino
option is mandatory.
clangd
settings
This is a sample set of clangd flags I use for kernel-mode coding:
--target=x86_64-pc-windows-msvc
-ferror-limit=64
-fms-compatibility-version=19.29
-Wall
-Wextra
-Wno-unknown-pragmas
-Wno-sizeof-array-div
-U__clang__
-U__clang_version__
-U__clang_major__
-U__clang_minor__
-U__clang_patchlevel__
-DNDEBUG
-D_MT=1
-D_AMD64_=1
-D_M_X64=100
-D_M_AMD64=100
-DWIN32
-D_WIN32=1
-D_WIN64=1
-D_WINDOWS
-DWINVER=0x0501
-D_WIN32_WINNT=0x0501
-D_MSC_VER=1929
-D_MSC_FULL_VER=192930100
-D_KERNEL_MODE=1
-DNOMINMAX
-DWIN32_LEAN_AND_MEAN=1
-D_CRT_SECURE_NO_WARNINGS=1
-D__INTELLISENSE__=1
-nostdinc
-isystem
/mnt/EWDK/Program Files/Windows Kits/10/Include/10.0.22000.0/shared
-isystem
/mnt/EWDK/Program Files/Windows Kits/10/Include/10.0.22000.0/km/crt
-isystem
/mnt/EWDK/Program Files/Windows Kits/10/Include/10.0.22000.0/km
For user-mode I use:
--target=x86_64-pc-windows-msvc
-ferror-limit=64
-fms-compatibility-version=19.29
-Wall
-Wextra
-Wno-unknown-pragmas
-U__clang__
-U__clang_version__
-U__clang_major__
-U__clang_minor__
-U__clang_patchlevel__
-DNDEBUG
-D_MT=1
-D_AMD64_=1
-D_M_X64=100
-D_M_AMD64=100
-DWIN32
-D_WIN32=1
-D_WIN64=1
-D_WINDOWS
-DWINVER=0x0501
-D_WIN32_WINNT=0x0501
-D_MSC_VER=1929
-D_MSC_FULL_VER=192930100
-DNOMINMAX
-DWIN32_LEAN_AND_MEAN=1
-D_CRT_SECURE_NO_WARNINGS=1
-D__INTELLISENSE__=1
-D__EDG__=1
-nostdinc
-isystem
/mnt/EWDK/Program Files/Windows Kits/10/Include/10.0.22000.0/shared
-isystem
/mnt/EWDK/Program Files/Windows Kits/10/Include/10.0.22000.0/ucrt
-isystem
/mnt/EWDK/Program Files/Windows Kits/10/Include/10.0.22000.0/um
-isystem
/mnt/EWDK/Program Files/Microsoft Visual Studio/2019/BuildTools/VC/Tools/MSVC/14.28.29910/include
As explained in my former post, the general idea of such set of flags is so that header logic in general will assume you're using a Microsoft compiler while in IntelliSense mode. Documentation for Microsoft's predefined macros can be found here.
I copy these flags to a compile_flags.txt
file that's put in some base
directory or subdirectory of the project's directory structure. At the moment
I use clangd
through coc-clangd on NeoVim.
Fast file shares on KVM/QEMU with Virtio-FS
Instead of Samba or NFS for file sharing between Linux host and Windows guest,
I now use Virtio-FS configured on the host, with WinFsp and VirtIO
drivers installed on the guest. I use the “memfd memory” approach for
Virtio-FS, which is the most straightforward to set up, requiring just sudo
virsh edit <some-virtual-machine>
and pasting two text sections (steps 2 and 3)
as the Virtio-FS documentation describes for setting up
guests. On guest's side, I start the VirtioFSService
in the
Windows Services Manager to end up with a Z:
volume for the host's folder
that was configured on virsh edit
.