coding windows c/c++ on linux (update)

by on
3 minute read

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.

c, cpp, clang, clangd, completion, intellisense, vim, neovim, coc, windows, linux
Spotted a mistake in this article? Why not suggest an edit!