Add WindowsKernel platform support

I’m utilizing CMake to build Windows kernel drivers, but currently I have to drop a WindowsKernel.cmake into the Modules/Platforms dir to make it work. Could the following be added to CMake to support his natively?

Modules/Platforms/WindowsKernel.cmake:

set(WIN32 1)

if(CMAKE_VERBOSE_MAKEFILE)
  set(CMAKE_CL_NOLOGO)
else()
  set(CMAKE_CL_NOLOGO "/nologo")
endif()

set(WINDOWS_KERNEL 1)

set(CMAKE_STATIC_LIBRARY_PREFIX "")
set(CMAKE_STATIC_LIBRARY_SUFFIX ".lib")
set(CMAKE_SHARED_LIBRARY_PREFIX "")
set(CMAKE_SHARED_LIBRARY_SUFFIX ".dll")
set(CMAKE_IMPORT_LIBRARY_PREFIX "")
set(CMAKE_IMPORT_LIBRARY_SUFFIX ".lib")
set(CMAKE_EXECUTABLE_SUFFIX     ".sys")
set(CMAKE_LINK_LIBRARY_SUFFIX   ".lib")
set(CMAKE_DL_LIBS               "")
set(CMAKE_EXTRA_LINK_EXTENSIONS ".targets")

set(CMAKE_FIND_LIBRARY_PREFIXES "")
set(CMAKE_FIND_LIBRARY_SUFFIXES ".lib")

set(CMAKE_SHARED_LIBRARY_LINK_C_FLAGS "/LIB")
set(CMAKE_LIBRARY_PATH_FLAG     "-LIBPATH:")
set(CMAKE_LINK_LIBRARY_FLAG)

set(CMAKE_C_STANDARD_LIBRARIES_INIT "BufferOverflowK.lib ntoskrnl.lib hal.lib wmilib.lib")
set(CMAKE_CXX_STANDARD_LIBRARIES_INIT "${CMAKE_C_STANDARD_LIBRARIES_INIT}")

set(CMAKE_C_CREATE_SHARED_MODULE
    "<CMAKE_C_COMPILER> ${CMAKE_CL_NOLOGO} <CMAKE_SHARED_LIBRARY_C_FLAGS> <LANGUAGE_COMPILE_FLAGS> <LINK_FLAGS> <CMAKE_SHARED_LIBRARY_CREATE_C_FLAGS> <SONAME_FLAG><TARGET_SONAME> /OUT:<TARGET> <OBJECTS> <LINK_LIBRARIES>")

set(CMAKE_C_CREATE_SHARED_LIBRARY
    "<CMAKE_LINKER> ${CMAKE_CL_NOLOGO} <OBJECTS> /OUT:<TARGET> /IMPLIB:<TARGET_IMPLIB> /PDB:<TARGET_PDB> /VERSION:<TARGET_VERSION_MAJOR>.<TARGET_VERSION_MINOR> <LINK_FLAGS> <LINK_LIBRARIES>")

set(CMAKE_C_CREATE_STATIC_LIBRARY
    "<CMAKE_LINKER> /LIB ${CMAKE_CL_NOLOGO} <LINK_FLAGS> /OUT:<TARGET> <OBJECTS>")

set(CMAKE_C_COMPILE_OBJECT
    "<CMAKE_C_COMPILER> ${CMAKE_CL_NOLOGO} /Fo<OBJECT> /c <SOURCE> <DEFINES> <INCLUDES> <FLAGS>")

set(CMAKE_C_LINK_EXECUTABLE
    "<CMAKE_LINKER> ${CMAKE_CL_NOLOGO} <CMAKE_C_LINK_FLAGS> <LINK_FLAGS> <OBJECTS> /OUT:<TARGET> <LINK_LIBRARIES>")

include(Platform/WindowsPaths)

I think the fundamental problem is I don’t believe CMake doesn’t registers WDK like it does with the SDK.

I’m not really sure what your code is even trying to address.

WDK = Windows Driver Kit

I decouple toolchain specs in my projects. For example, this is a platform toolchain spec for x64-winkernel:

# Platform
set(CMAKE_SYSTEM_PROCESSOR x86_64)
set(CMAKE_SYSTEM_NAME      WindowsKernel)

# WDK path
set(WINDOWS_WDK_PATH "C:/path/to/toolchains/WDK/7.1")

# Tools
set(CMAKE_C_COMPILER   "${WINDOWS_WDK_PATH}/bin/x86/amd64/cl.exe" CACHE PATH "")
set(CMAKE_CXX_COMPILER "${WINDOWS_WDK_PATH}/bin/x86/amd64/cl.exe" CACHE PATH "")
set(CMAKE_ASM_COMPILER "${WINDOWS_WDK_PATH}/bin/x86/amd64/ml64.exe" CACHE PATH "")
set(CMAKE_LINKER       "${WINDOWS_WDK_PATH}/bin/x86/amd64/link.exe" CACHE PATH "")

set(CMAKE_C_COMPILER_WORKS   True)
set(CMAKE_CXX_COMPILER_WORKS True)

# Clear envar that influence toolchain behaviour
set(ENV{INCLUDE})
set(ENV{LIB})
set(ENV{LIBPATH})

# Include paths
include_directories(
    "${WINDOWS_WDK_PATH}/inc/api"
    "${WINDOWS_WDK_PATH}/inc/mfc42"
    "${WINDOWS_WDK_PATH}/inc/ddk"
    "${WINDOWS_WDK_PATH}/inc/crt"
    "${WINDOWS_WDK_PATH}/inc/win7"
    )

# Lib paths
link_directories(
    "${WINDOWS_WDK_PATH}/lib/crt/amd64"
    "${WINDOWS_WDK_PATH}/lib/win7/amd64"
    )

The compiler and linker flags are further decoupled, but above provides the interface you noted.

To answer this: I may be wrong, but as you said CMake does not have any inbuilt registration for WDK like it does the SDK. Extrapolate this, ignoring my toolchain spec to make this work, to how CMake handles platform types. Unless you explicitly add a WindowsKernel.cmake file to Modules/Platform there is no way to specify a platform target. This will result in what ultimately led me here:

System is unknown to cmake, create:
Platform/WindowsKernel to use this system, please post your config file on discourse.cmake.org so it can be added to cmake

I’ve been manually patching WindowsKernel.cmake into Modules/Platform but this is cumbersome as we have multiple users and it often gets forgotten.

Alternatively, is there any way to specify platform systems outside of CMake? I tried multiple approaches, but it seems CMake is hardcoded to only consider Modules/Platform.

This should probably be filed as an issue for consideration of integration and testing. This discussion is probably relevant too.

Sorry @ben.boeckel I wasn’t sure where to post this.

Thanks for posting the UMDF discussion. This would effectively be covered by adding inc/wdf/kmdf and inc/wdf/umdf to the include_directories and lib/wdf/kmdf/amd64/1.9 to the link_directories in my example above, or alternatively using the i386/ia64 targets if a non-amd64 target is desired.

The FindWDK.cmake from that discussion is relevant as well, it handles UMDF includes if WDK_KMDF is defined in a similar fashion to what I described above. I’m specifically using WDK 7.1 for legacy OS coverage, there have been changes to the directory layout of newer WDKs.

At our workplace we have custom toolchain files as well in order to build against the WDK.

And we don’t build for legacy OS coverage we always need to be using latest or close to latest.