xmake 新增对 WDK 驱动开发环境支持 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
请不要在回答技术问题时复制粘贴 AI 生成的内容

xmake 新增对 WDK 驱动开发环境支持

  •  
  •   waruqi
    waruqi 2018 年 6 月 15 日 2658 次点击
    这是一个创建于 2869 天前的主题,其中的信息可能已经有所发展或是发生改变。

    xmake v2.2.1 新版本现已支持 WDK 驱动编译环境,我们可以直接在系统原生 cmd 终端下,执行 xmake 进行驱动编译,甚至配合 vscode, sublime text, IDEA 等编辑器+xmake 插件去开发 WDK 驱动。

    下面是 xmake 支持的一些编辑器插件,用户可以挑选自己喜欢的编辑器配合 xmake 来使用:

    WDK 环境介绍

    首先,我们先简单介绍下 WDK10 的编译环境的安装方式,我们可以看下微软的官方文档:Download the Windows Driver Kit (WDK)

    里面介绍了两种环境:

    1. 下载 WDK 开发包,直接安装到系统并集成到 VS 的开发环境中
    2. 下载 EWDK iso 镜像(内含完整 WDK 开发环境),直接挂载后,运行 LaunchBuildEnv 进入 cmd 环境

    xmake 对于这两种环境都是完全支持的,如果用户直接下载安装 WDK 环境到本地系统,那么不需要任何配置,只需要执行:

    $ xmake 

    xmake 会自动检测到 WDK 的安装环境,然后编译相关驱动项目,如果用户是直接挂载的 EWDK iso 开发镜像,那么编译前配置下 WDK 所在路径即可:

    $ xmake f --wdk="G:\Program Files\Windows Kits\10" $ xmake 

    更多详情可以参考:#159

    WDK 驱动实例

    xmake 支持 umdf, kmdf, wdm 驱动项目的维护,也是采用一系列扩展的 WDK rule 规则来实现,类似:Qt 编译环境的支持

    目前支持的规则有如下这些:

    • rule("wdk.driver")

    • rule("wdk.binary")

    • rule("wdk.static")

    • rule("wdk.shared")

    • rule("wdk.env.kmdf")

    • rule("wdk.env.umdf")

    • rule("wdk.env.wdm")

    其中,wdk.env.*规则描述驱动编译的环境,wdk.driver, wdk.static描述编译的目标类型,两者可以互相结合使用,我们既可以用来编译驱动程序,也可以用来编译基于 wdk 环境的静态库、可执行程序。

    下面,通过一些例子可以简单看下使用方式,具体例子代码见wdk-examples,其中的项目代码是从Windows-driver-samples移植过来的。

    umdf 驱动程序

    我们通过同时应用wdk.driver, wdk.env.umdf规则,来描述这个 target 作为 umdf 驱动程序来编译:

    target("echo") add_rules("wdk.driver", "wdk.env.umdf") add_files("driver/*.c") add_files("driver/*.inx") add_includedirs("exe") 

    我们也可以通过wdk.binary, wdk.env.umdf规则,来描述一个基于 wdk/umdf 编译环境的上层可执行程序:

    target("app") add_rules("wdk.binary", "wdk.env.umdf") add_files("exe/*.cpp") 

    kmdf 驱动程序

    kmdf 的项目描述跟刚才的 umdf 类似,只需要把wdk.env.umdf换成wdk.env.kmdf的环境规则就行了。

    target("nonpnp") add_rules("wdk.driver", "wdk.env.kmdf") add_values("wdk.tracewpp.flags", "-func:TraceEvents(LEVEL,FLAGS,MSG,...)") add_values("wdk.tracewpp.flags", "-func:Hexdump((LEVEL,FLAGS,MSG,...))") add_files("driver/*.c", {rule = "wdk.tracewpp"}) add_files("driver/*.rc") target("app") add_rules("wdk.binary", "wdk.env.kmdf") add_files("exe/*.c") add_files("exe/*.inf") 

    这个项目里面,需要特别注意的是,我们还用到了 tracewpp 对一些源文件的预处理,对于 tracewpp 任务的介绍,可以看下官方文档tracewpp-task,这里就不多做说明了。

    我们直接说下,如何在 xmake 的项目里应用 tracewpp 规则吧,由于这个规则并不是对当前 target 所有源文件都去处理的,因此我们只对需要的源文件进行应用这个规则,例如:

    add_files("driver/*.c", {rule = "wdk.tracewpp"}) add_files("driver/dir/test.c", {rule = "wdk.tracewpp"}) 

    当然 tracewpp 还会有一些自己的特殊选项,用户有时候需要自己根据需要来设置,例如:

    add_values("wdk.tracewpp.flags", "-func:TraceEvents(LEVEL,FLAGS,MSG,...)") add_values("wdk.tracewpp.flags", "-func:Hexdump((LEVEL,FLAGS,MSG,...))") 

    关于add_values的使用说明,可以看下文档:add_values 和 set_values 的使用说明,简单来说,就是用来给对应规则传递扩展参数设置的。

    wdm 驱动程序

    wdm 的项目描述也跟 umdf 类似,只需要把wdk.env.umdf换成wdk.env.wdm的环境规则就行了。

    target("kcs") add_rules("wdk.driver", "wdk.env.wdm") add_values("wdk.man.flags", "-prefix Kcs") add_values("wdk.man.resource", "kcsCounters.rc") add_values("wdk.man.header", "kcsCounters.h") add_values("wdk.man.counter_header", "kcsCounters_counters.h") add_files("*.c", "*.rc", "*.man") 

    上述代码,还添加了一些.man 文件用来预处理一些 manifest,具体相关的任务藐视,可以参考官方文档说明:ctrpp-task。 里面也有相关的一些特殊配置选项,目前 xmake 支持的配置有:

    add_values("wdk.man.flags", "-prefix Kcs") add_values("wdk.man.prefix", "Kcs") add_values("wdk.man.resource", "kcsCounters.rc") add_values("wdk.man.header", "kcsCounters.h") add_values("wdk.man.counter_header", "kcsCounters_counters.h") 

    下面再贴个 wdm 驱动的例子,这个例子中,除了之前讲的 tracewpp,我们还加了.mof 的文件处理,对于.mof 文件,xmake 会自动应用内置的wdk.mof规则,详细说明见:mofcomp-task

    target("msdsm") add_rules("wdk.driver", "wdk.env.wdm") add_values("wdk.tracewpp.flags", "-func:TracePrint((LEVEL,FLAGS,MSG,...))") add_files("*.c", {rule = "wdk.tracewpp"}) add_files("*.rc", "*.inf") add_files("*.mof|msdsm.mof") add_files("msdsm.mof", {values = {wdk_mof_header = "msdsmwmi.h"}}) 

    对于.mof 的配置选项,有些配置并不是全局应用于 target 的,对每个文件需要单独配置,这个时候,就不能直接使用set_valuesadd_values了,需要在add_files中设置相关 values。

    add_files("msdsm.mof", {values = {wdk_mof_header = "msdsmwmi.h"}}) add_files("msdsm.mof", {values = {["wdk.mof.header"] = "msdsmwmi.h"}}) 

    上面两种设置方式都是有效的,由于受限于 lua 的语法,为了考虑可读性,xmake 通过_下划线来简化 key 的设置,这个设置相当于单独对 msdsm.mof 文件设置了set_values("wdk.mof.header", "msdsmwmi.h")

    生成驱动包

    如果平常开发调试通过后,我们也可以通过以下命令生成.cab 驱动包来发布驱动程序:

    $ xmake [p|package] $ xmake [p|package] -o outputdir 

    输出的目录结构如下:

     - drivers - sampledsm - debug/x86/sampledsm.cab - release/x64/sampledsm.cab - debug/x86/sampledsm.cab - release/x64/sampledsm.cab 

    驱动签名

    默认编译我们是禁用签名的,如果想要在编译的同时,启用签名,可以通过set_values("wdk.sign.mode", ...)设置签名模式来启用。 只要启用了签名,那么平常的驱动构建、包括打包生成的.cab 文件,都会自动对其进行签名。

    测试签名

    测试签名一般本机调试时候用,可以使用 xmake 自带的 test 证书来进行签名,例如:

    target("msdsm") add_rules("wdk.driver", "wdk.env.wdm") set_values("wdk.sign.mode", "test") add_files("src/*.c") 

    不过这种情况下,需要用户手动在管理员模式下,执行一遍:$xmake l utils.wdk.testcert install,来生成和注册 test 证书到本机环境。 这个只需要执行一次就行了,后续就可以正常编译和签名了。

    当然也可以使用本机已有的有效证书去签名,例如直接从 sh1 来选择合适的证书进行签名:

    target("msdsm") add_rules("wdk.driver", "wdk.env.wdm") set_values("wdk.sign.mode", "test") set_values("wdk.sign.thumbprint", "032122545DCAA6167B1ADBE5F7FDF07AE2234AAA") add_files("src/*.c") 

    或者从 store/company 来选择合适的证书进行签名:

    target("msdsm") add_rules("wdk.driver", "wdk.env.wdm") set_values("wdk.sign.mode", "test") set_values("wdk.sign.store", "PrivateCertStore") set_values("wdk.sign.company", "tboox.org(test)") add_files("src/*.c") 

    正式签名

    对于正式签名,我们可以通过指定对应的正式签名证书文件进行签名:

    target("msdsm") add_rules("wdk.driver", "wdk.env.wdm") set_values("wdk.sign.mode", "release") set_values("wdk.sign.company", "xxxx") set_values("wdk.sign.certfile", path.join(os.projectdir(), "xxxx.cer")) 

    生成低版本驱动

    如果想在 wdk10 环境编译生成 win7, win8 等低版本系统支持的驱动,我们可以通过设置wdk.env.winver来切换系统版本:

    set_values("wdk.env.winver", "win10") set_values("wdk.env.winver", "win10_rs3") set_values("wdk.env.winver", "win81") set_values("wdk.env.winver", "win8") set_values("wdk.env.winver", "win7") set_values("wdk.env.winver", "win7_sp1") set_values("wdk.env.winver", "win7_sp2") set_values("wdk.env.winver", "win7_sp3") 

    如果觉得每次修改 xmake.lua 去切换编译非常繁琐,我们也可以手动指定编译的目标程序支持的 windows 版本,来快速切换到对应的版本进行编译:

    $ xmake f --wdk_winver=[win10_rs3|win8|win7|win7_sp1] $ xmake 

    目前支持的一些版本有:nt4, win2k, winxp, ws03, win6, vista, ws08, longhorn, win7, win8, win81, winblue, win10

    然后通过_下划线,组合指定子版本:sp1, sp2, sp3, th2, rs1, rs2, rs3

    xmake 还提供了一些内置的版本值,在切换 winver 版本是,会自动改变,用于一些更加定制化的配置需求,例如:

    target("test") on_load(function (target) local winnt_version = target:values("wdk.env.winnt_version") if winnt_version > "0x0A000000" then target:add("defines", "TEST") end end) 

    上述代码通过判断 WIN32_WINNT 的版本值,来定制添加一些相关配置,这个版本值会根据wdk.env.winver的配置自动适配更新,目前提供的这些内置版本值还有:

    target:values("wdk.env.winnt_version"): WIN32_WINNT target:values("wdk.env.ntddi_version"): NTDDI_VERSION target:values("wdk.env.winver_version"): WINVER 

    关于更多 xmake 下 WDK 开发相关介绍,请参考文档:WDK 驱动程序开发

    2 条回复    2018-06-15 17:40:48 +08:00
    Mapleaph
        1
    Mapleaph  
       2018 年 6 月 15 日
    是否支持 WDK7.1 ?
    waruqi
        2
    waruqi  
    OP
       2018 年 6 月 15 日
    @Mapleaph 暂时只支持 WDK10,其他版本等有时间可以考虑加上
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     5176 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 56ms UTC 05:47 PVG 13:47 LAX 22:47 JFK 01:47
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86