using CMake Part I – Build drivers

In order to satisfy our local team’s performance expectation, I have migrated our diskless system to all latest toolchains, for example, VC2015, Intel Compiler 2016, boost 1.60, etc.

It’s hard to set options for each individual projects inside this solution, CMake is a very good choice to control options across projects. Although we switched back to VC2015, because worse performance of Intel Compiler 2016. Some code/script pieces maybe usefull in everyday development.

function (set_ddk_options _target)
    FIND_FILE(NTDDKPATH “ntddk.h”)
    IF(NOT (“${NTDDKPATH}” STREQUAL “NTDDKPATH-NOTFOUND”))
        GET_FILENAME_COMPONENT(DDK_INC ${NTDDKPATH} DIRECTORY)
        INCLUDE_DIRECTORIES(${DDK_INC})
    ENDIF()

    FIND_LIBRARY(DDK_LIBPATH “ntoskrnl”)
    IF(NOT (“${DDK_LIBPATH}” STREQUAL “DDK_LIBPATH-NOTFOUND”))
        GET_FILENAME_COMPONENT(DDK_LIB ${DDK_LIBPATH} DIRECTORY)
        LINK_DIRECTORIES(${DDK_LIB})
    ENDIF()

endfunction()

macro (set_type_driver _target)
include(CheckTypeSize)
check_type_size(void* SIZEOF_VOID_PTR)
if(“${SIZEOF_VOID_PTR}” STREQUAL “4”)
    ADD_DEFINITIONS(-D_X86_=1)
    ADD_DEFINITIONS(-Di386=1)
elseif(“${SIZEOF_VOID_PTR}” STREQUAL “8”)
    ADD_DEFINITIONS(-D_WIN64)
    ADD_DEFINITIONS(-D_AMD64_)
    ADD_DEFINITIONS(-DAMD64)
else()
    message(FATAL_ERROR “Unsupported architecture”)
    return()
endif()

ADD_DEFINITIONS(-D_WIN32_WINNT=0x0501)

# adjust linker options
foreach(item _CMAKE_VS_LINK_DLL
    CMAKE_CXX_CREATE_SHARED_LIBRARY
    CMAKE_CXX_CREATE_SHARED_MODULE
    CMAKE_SHARED_LINKER_FLAGS_DEBUG)
STRING (REPLACE “–manifests <MANIFESTS>” “” ${item} ${${item}})
STRING (REPLACE “/INCREMENTAL:YES ” “” ${item} ${${item}})
STRING (REPLACE “/INCREMENTAL” “” ${item} ${${item}})
#STRING (REPLACE “/debug” “/release” ${item} ${${item}})
STRING (REPLACE “/dll” “/driver” ${item} ${${item}})
endforeach()
 
# adjust cl options
foreach(item CMAKE_CXX_FLAGS
    CMAKE_CXX_FLAGS_DEBUG
    CMAKE_CXX_FLAGS_RELEASE)
STRING (REGEX REPLACE “/RTC(su|[1su])” “” ${item} ${${item}})
STRING (REGEX REPLACE “/EH(sc|a)” “” ${item} ${${item}})
STRING (REGEX REPLACE “/GS” “” ${item} ${${item}})
STRING (REGEX REPLACE “/GR” “” ${item} ${${item}})
endforeach()

# remove default libraries
set(CMAKE_C_STANDARD_LIBRARIES “”)
set(CMAKE_CXX_STANDARD_LIBRARIES “”)
TARGET_LINK_LIBRARIES(${_target} ntoskrnl hal ntstrsafe)

SET_TARGET_PROPERTIES(${_target} PROPERTIES SUFFIX “.sys”)

# /Gz is x86 specified
check_type_size(void* SIZEOF_VOID_PTR)
if(“${SIZEOF_VOID_PTR}” STREQUAL “4”)
foreach(item CMAKE_CXX_FLAGS
    CMAKE_CXX_FLAGS_DEBUG
    CMAKE_CXX_FLAGS_RELEASE)
set(${item} “${${item}} /Gz”)
endforeach()
endif()

SET_TARGET_PROPERTIES (${_target} PROPERTIES COMPILE_FLAGS “/GS- /GR- /D_KERNEL_MODE /DNTSTRSAFE_LIB /GL” )

SET_TARGET_PROPERTIES (${_target} PROPERTIES LINK_FLAGS “/incremental:no /nodefaultlib /version:5.0 /manifest:no /subsystem:native /stack:262144,4096 /driver /entry:DriverEntry /base:0x10000 /integritycheck /ignore:4198,4010,4037,4039,4065,4070,4078,4087,4089,4099,4221,4210,4086 /release /LTCG” )

endmacro()

Let me explain one by one. CMake’s default options are prepared for console/GUI applications, DLL, static libraies, it doesnt work for drivers. Thanks to all variables, we can easily overide the default options.

First of all, set i386,AMD64 macros according current data width.

Secondly, set the mimum api to winxp, because our users are still using it.

Next, remove CL/LINK options which is not supported in kernel mode, also add options used in kernel mode.

Last but not least, set the extension to be .sys.

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s