乐趣区

关于c++:xmake-v262-发布新增-Linux-内核驱动模块构建支持

Xmake 是一个基于 Lua 的轻量级跨平台构建工具。

它十分的轻量,没有任何依赖,因为它内置了 Lua 运行时。

它应用 xmake.lua 保护我的项目构建,相比 makefile/CMakeLists.txt,配置语法更加简洁直观,对老手十分敌对,短时间内就能疾速入门,可能让用户把更多的精力集中在理论的我的项目开发上。

咱们可能应用它像 Make/Ninja 那样能够间接编译我的项目,也能够像 CMake/Meson 那样生成工程文件,另外它还有内置的包管理系统来帮忙用户解决 C/C++ 依赖库的集成应用问题。

目前,Xmake 次要用于 C/C++ 我的项目的构建,然而同时也反对其余 native 语言的构建,能够实现跟 C/C++ 进行混合编译,同时编译速度也是十分的快,能够跟 Ninja 持平。

Xmake = Build backend + Project Generator + Package Manager
  • 我的项目源码
  • 官网文档
  • 入门课程

<img src=”https://tboox.org/static/img/xmake/xmake-cmake.jpeg” width=”30%” />

新版本改变

这个版本次要新增两大个性:

  1. Linux 内核驱动模块的构建反对
  2. 分组构建和批量运行反对,可用于实现 Run all tests 性能

剩下的次要是一些零散的性能改良和 Bugs 修复,能够看下文末的更新内容明细,一些比拟大的改变,上面也会逐个阐明。

新个性介绍

构建 Linux 内核驱动模块

Xmake 兴许是首个提供 Linux 内核驱动开发 内置反对的第三方构建工具了。

只管网上也有介绍 CMake 如何去配置构建 linux 驱动,然而大都是通过 add_custom_command 形式自定义各种命令,而后执行 echo 去本人拼接生成 Linux 的 Makefile 文件。

也就是说,其实还是依赖 Linux 内核源码的 Makefile 来执行的构建,因而如果想本人追加一些编译配置和宏定义都会十分麻烦。

而应用 Xmake,咱们能够提供更加灵便的可配置性,更加简略的配置文件,以及一键编译、主动依赖拉取集成、Linux kernel 源码主动下载集成,内核驱动穿插编译等个性。

Hello World

咱们通过一个最简略的字符驱动来直观感触下。

首先,咱们筹备一个 Hello World 驱动代码,例如:

add_requires("linux-headers", {configs = {driver_modules = true}})

target("hello")
    add_rules("platform.linux.driver")
    add_files("src/*.c")
    add_packages("linux-headers")
    set_license("GPL-2.0")

它的配置非常简单,只须要配置上反对模块的 linux-headers 包,而后利用 platform.linux.driver 构建规定就行了。

而后间接执行 xmake 命令,一键编译,生成内核驱动模块 hello.ko。

$ xmake
[20%]: ccache compiling.release src/add.c
[20%]: ccache compiling.release src/hello.c
[60%]: linking.release build/linux/x86_64/release/hello.ko
[100%]: build ok!

简略么,兴许你会说,这跟间接用 Makefile 配置,而后 make 编译也没啥太大区别么。

那么重点来了,Xmake 是会主动帮你拉取指定版本依赖内核源码,make 不会,CMake 也不会,用户必须通过 sudo apt install linux-headers-generic 本人装置它们。

然而 Xmake 不须要,下面的一键编译,我其实省略了局部输入,实际上是这样的。

$ xmake
note: install or modify (m) these packages (pass -y to skip confirm)?
in xmake-repo:
  -> m4 1.4.19 [from:linux-headers,bison,flex,elfutils]
  -> flex 2.6.4 [from:bc,linux-headers]
  -> bison 3.8.2 [from:bc,linux-headers]
  -> ed 1.17 [from:bc,linux-headers]
  -> texinfo 6.7 [from:bc,linux-headers]
  -> bc 1.07.1 [from:linux-headers]
  -> pkg-config 0.29.2 [from:linux-headers]
  -> openssl 1.1.1l [private, from:linux-headers]
  -> elfutils 0.183 [private, from:linux-headers]
  -> linux-headers 5.10.46 [driver_modules:y]
please input: y (y/n/m)

  => download https://github.com/xmake-mirror/ed/archive/refs/tags/1.17.tar.gz .. ok
  => install ed 1.17 .. ok
  => download https://ftp.gnu.org/gnu/m4/m4-1.4.19.tar.xz .. ok
  => download https://ftp.gnu.org/gnu/texinfo/texinfo-6.7.tar.xz .. ok
  => download https://pkgconfig.freedesktop.org/releases/pkg-config-0.29.2.tar.gz .. ok
  => download https://github.com/openssl/openssl/archive/OpenSSL_1_1_1l.zip .. ok
  => install m4 1.4.19 .. ok
  => download https://github.com/westes/flex/releases/download/v2.6.4/flex-2.6.4.tar.gz .. ok
  => install texinfo 6.7 .. ok
  => install pkg-config 0.29.2 .. ok
  => download http://ftp.gnu.org/gnu/bison/bison-3.8.2.tar.gz .. ok
  => install flex 2.6.4 .. ok
  => download https://sourceware.org/elfutils/ftp/0.183/elfutils-0.183.tar.bz2 .. ok
  => install elfutils 0.183 .. ok
  => install bison 3.8.2 .. ok
  => download https://ftp.gnu.org/gnu/bc/bc-1.07.1.tar.gz .. ok
  => install bc 1.07.1 .. ok
  => install openssl 1.1.1l .. ok
  => download https://cdn.kernel.org/pub/linux/kernel/v5.x/linux-5.10.46.tar.xz .. ok
  => install linux-headers 5.10.46 .. ok
[16%]: ccache compiling.release src/add.c
[16%]: ccache compiling.release src/hello.c
[16%]: ccache compiling.release src/hello.mod.c
[66%]: linking.release build/linux/x86_64/release/hello.ko
[100%]: build ok!

首次编译,Xmake 会拉取所有依赖,如果用户本人曾经通过 apt 等第三方包治理装置了它们,Xmake 也会优先用零碎曾经装置的版本,省去下载安装过程。

也就是说,不论在哪个环境,用户都不须要关怀如何去搭建内核驱动开发环境,仅仅只须要一个 xmake 命令,就能搞定所有。

而这些依赖拉取,都是通过 add_requires("linux-headers", {configs = {driver_modules = true}}) 配置包来实现的。

另外,咱们也能够看残缺构建命令参数。

$ xmake -v
[20%]: ccache compiling.release src/add.c
/usr/bin/ccache /usr/bin/gcc -c -m64 -O2 -std=gnu89 -I/usr/src/linux-headers-5.11.0-41-generic/arch/x86/include -I/usr/src/linux-headers-5.11.0-41-generic/arch/x86/include/generated -I/usr/src/linux-headers-5.11.0-41-generic/include -I/usr/src/linux-headers-5.11.0-41-generic/arch/x86/include/uapi -I/usr/src/linux-headers-5.11.0-41-generic/arch/x86/include/generated/uapi -I/usr/src/linux-headers-5.11.0-41-generic/include/uapi -I/usr/src/linux-headers-5.11.0-41-generic/include/generated/uapi -D__KERNEL__ -DMODULE -DKBUILD_MODNAME=\"hello\" -DCONFIG_X86_X32_ABI -isystem /usr/lib/gcc/x86_64-linux-gnu/10/include -include /usr/src/linux-headers-5.11.0-41-generic/include/linux/kconfig.h -include /usr/src/linux-headers-5.11.0-41-generic/include/linux/compiler_types.h -nostdinc -mno-sse -mno-mmx -mno-sse2 -mno-3dnow -mno-avx -mno-80387 -mno-fp-ret-in-387 -mpreferred-stack-boundary=3 -mskip-rax-setup -mtune=generic -mno-red-zone -mcmodel=kernel -mindirect-branch=thunk-extern -mindirect-branch-register -mrecord-mcount -fmacro-prefix-map=./= -fno-strict-aliasing -fno-common -fshort-wchar -fno-PIE -fcf-protection=none -falign-jumps=1 -falign-loops=1 -fno-asynchronous-unwind-tables -fno-jump-tables -fno-delete-null-pointer-checks -fno-allow-store-data-races -fno-reorder-blocks -fno-ipa-cp-clone -fno-partial-inlining -fstack-protector-strong -fno-inline-functions-called-once -falign-functions=32 -fno-strict-overflow -fno-stack-check -fconserve-stack -DKBUILD_BASENAME=\"add\" -o build/.objs/hello/linux/x86_64/release/src/add.c.o src/add.c
[20%]: ccache compiling.release src/hello.c
/usr/bin/ccache /usr/bin/gcc -c -m64 -O2 -std=gnu89 -I/usr/src/linux-headers-5.11.0-41-generic/arch/x86/include -I/usr/src/linux-headers-5.11.0-41-generic/arch/x86/include/generated -I/usr/src/linux-headers-5.11.0-41-generic/include -I/usr/src/linux-headers-5.11.0-41-generic/arch/x86/include/uapi -I/usr/src/linux-headers-5.11.0-41-generic/arch/x86/include/generated/uapi -I/usr/src/linux-headers-5.11.0-41-generic/include/uapi -I/usr/src/linux-headers-5.11.0-41-generic/include/generated/uapi -D__KERNEL__ -DMODULE -DKBUILD_MODNAME=\"hello\" -DCONFIG_X86_X32_ABI -isystem /usr/lib/gcc/x86_64-linux-gnu/10/include -include /usr/src/linux-headers-5.11.0-41-generic/include/linux/kconfig.h -include /usr/src/linux-headers-5.11.0-41-generic/include/linux/compiler_types.h -nostdinc -mno-sse -mno-mmx -mno-sse2 -mno-3dnow -mno-avx -mno-80387 -mno-fp-ret-in-387 -mpreferred-stack-boundary=3 -mskip-rax-setup -mtune=generic -mno-red-zone -mcmodel=kernel -mindirect-branch=thunk-extern -mindirect-branch-register -mrecord-mcount -fmacro-prefix-map=./= -fno-strict-aliasing -fno-common -fshort-wchar -fno-PIE -fcf-protection=none -falign-jumps=1 -falign-loops=1 -fno-asynchronous-unwind-tables -fno-jump-tables -fno-delete-null-pointer-checks -fno-allow-store-data-races -fno-reorder-blocks -fno-ipa-cp-clone -fno-partial-inlining -fstack-protector-strong -fno-inline-functions-called-once -falign-functions=32 -fno-strict-overflow -fno-stack-check -fconserve-stack -DKBUILD_BASENAME=\"hello\" -o build/.objs/hello/linux/x86_64/release/src/hello.c.o src/hello.c
[60%]: linking.release build/linux/x86_64/release/hello.ko
/usr/bin/ld -m elf_x86_64 -r -o build/.objs/hello/linux/x86_64/release/build/linux/x86_64/release/hello.ko.o build/.objs/hello/linux/x86_64/release/src/add.c.o build/.objs/hello/linux/x86_64/release/src/hello.c.o
/usr/src/linux-headers-5.11.0-41-generic/scripts/mod/modpost -m -a -o build/.objs/hello/linux/x86_64/release/build/linux/x86_64/release/Module.symvers -e -N -T -
WARNING: modpost: Symbol info of vmlinux is missing. Unresolved symbol check will be entirely skipped.
/usr/bin/ccache /usr/bin/gcc -c -m64 -O2 -std=gnu89 -I/usr/src/linux-headers-5.11.0-41-generic/arch/x86/include -I/usr/src/linux-headers-5.11.0-41-generic/arch/x86/include/generated -I/usr/src/linux-headers-5.11.0-41-generic/include -I/usr/src/linux-headers-5.11.0-41-generic/arch/x86/include/uapi -I/usr/src/linux-headers-5.11.0-41-generic/arch/x86/include/generated/uapi -I/usr/src/linux-headers-5.11.0-41-generic/include/uapi -I/usr/src/linux-headers-5.11.0-41-generic/include/generated/uapi -D__KERNEL__ -DMODULE -DKBUILD_MODNAME=\"hello\" -DCONFIG_X86_X32_ABI -isystem /usr/lib/gcc/x86_64-linux-gnu/10/include -include /usr/src/linux-headers-5.11.0-41-generic/include/linux/kconfig.h -include /usr/src/linux-headers-5.11.0-41-generic/include/linux/compiler_types.h -nostdinc -mno-sse -mno-mmx -mno-sse2 -mno-3dnow -mno-avx -mno-80387 -mno-fp-ret-in-387 -mpreferred-stack-boundary=3 -mskip-rax-setup -mtune=generic -mno-red-zone -mcmodel=kernel -mindirect-branch=thunk-extern -mindirect-branch-register -mrecord-mcount -fmacro-prefix-map=./= -fno-strict-aliasing -fno-common -fshort-wchar -fno-PIE -fcf-protection=none -falign-jumps=1 -falign-loops=1 -fno-asynchronous-unwind-tables -fno-jump-tables -fno-delete-null-pointer-checks -fno-allow-store-data-races -fno-reorder-blocks -fno-ipa-cp-clone -fno-partial-inlining -fstack-protector-strong -fno-inline-functions-called-once -falign-functions=32 -fno-strict-overflow -fno-stack-check -fconserve-stack -o build/.objs/hello/linux/x86_64/release/build/linux/x86_64/release/hello.ko.mod.o build/.objs/hello/linux/x86_64/release/build/linux/x86_64/release/hello.ko.mod.c
/usr/bin/ld -m elf_x86_64 -r --build-id=sha1 -T /usr/src/linux-headers-5.11.0-41-generic/scripts/module.lds -o build/linux/x86_64/release/hello.ko build/.objs/hello/linux/x86_64/release/build/linux/x86_64/release/hello.ko.o build/.objs/hello/linux/x86_64/release/build/linux/x86_64/release/hello.ko.mod.o

应用特定版本的内核源码

咱们也能够指定版本语义规定,选取本人须要的内核源码作为构建源。

add_requires("linux-headers 5.9.x", {configs = {driver_modules = true}})

穿插编译

咱们也反对内核驱动模块的穿插编译,比方在 Linux x86_64 上应用穿插编译工具链来构建 Linux Arm/Arm64 的驱动模块。

咱们只须要筹备好本人的穿插编译工具链,通过 --sdk= 指定它的根目录,而后配置切换到 -p cross 平台,最初指定须要构建的架构 arm/arm64 即可。

同样的,咱们不必关怀如何筹备 linux-headers 去反对穿插编译,Xmake 的依赖包治理会帮你准本好所有,拉取构建反对对应架构的内核源码。

这里用到的穿插工具链,能够从这里下载: Download toolchains

更多,穿插编译配置文档,见:配置穿插编译

注:目前仅仅反对 arm/arm64 穿插编译架构,后续会反对更多的平台架构。

构建 Arm 驱动模块
$ xmake f -p cross -a arm --sdk=/mnt/gcc-linaro-7.5.0-2019.12-x86_64_arm-linux-gnueabihf -c
$ xmake
[20%]: ccache compiling.release src/add.c
[20%]: ccache compiling.release src/hello.c
[60%]: linking.release build/cross/arm/release/hello.ko
[100%]: build ok!
构建 Arm64 驱动模块
$ xmake f -p cross -a arm64 --sdk=/mnt/gcc-linaro-7.5.0-2019.12-x86_64_aarch64-linux-gnu -c
$ xmake
[20%]: ccache compiling.release src/add.c
[20%]: ccache compiling.release src/hello.c
[60%]: linking.release build/cross/arm64/release/hello.ko
[100%]: build ok!

分组批量构建和运行反对

晚期,咱们曾经反对了通过 set_group 设置指标分组,实现 vs/vsxmake 工程在 vs 下的源文件分组治理展现。

然而,这个分组仅限于这个个性,没有用于其余中央,而新版本中,咱们持续改良利用分组个性,实现指定构建一批目标程序,以及批量运行一批目标程序。

这通常有什么用呢,比方能够用来提供 Run all testsRun all benchmarks 等性能。

编译指定一批目标程序

咱们能够应用 set_group() 将给定的指标标记为 test/benchmark/... 并应用 set_default(false) 禁用来默认构建它。

这样,默认状况下 Xmake 不会去构建它们,然而咱们能够通过 xmake -g xxx 命令就能指定构建一批目标程序了。

比方,咱们能够应用此性能来构建所有测试。

target("test1")
    set_kind("binary")
    set_default(false)
    set_group("test")
    add_files("src/*.cpp")

target("test2")
    set_kind("binary")
    set_default(false)
    set_group("test")
    add_files("src/*.cpp")
$ xmake -g test
$ xmake --group=test

运行指定一批目标程序

咱们也能够通过设置分组,来指定运行所有带有 test 分组的测试程序。

这通常十分有用,在此之前想要实现 Run all tests 性能,咱们只能通过定义一个 task("tests") 在外面调用 os.exec 去挨个执行测试指标,配置比拟繁琐,对用户要求比拟高。

而当初,咱们只须要对须要执行的测试目标程序标记为 set_group("test"),而后就能够批量运行它们了。

$ xmake run -g test
$ xmake run --group=test

反对分组模式匹配

另外,咱们还能够反对分组的模式匹配,十分的灵便:

$ xmake build -g test_*
$ xmake run -g test/foo_*
$ xmake build -g bench*
$ xmake run -g bench*

更多信息见:#1913

改良 CMake 包源的查找和集成

之前的版本中,咱们提供了 find_package("cmake::xxx") 来查找 cmake 外部的包,然而这种形式对于用户集成应用还是很繁琐。

因而,新版本中,咱们进一步改良它,通过 add_requires 来实现对立疾速的 cmake 包集成。

add_requires("cmake::ZLIB", {alias = "zlib", system = true})
target("test")
    set_kind("binary")
    add_files("src/*.c")
    add_packages("zlib")

咱们指定 system = true 通知 xmake 强制从零碎中调用 cmake 查找包,如果找不到,不再走装置逻辑,因为 cmake 没有提供相似 vcpkg/conan 等包管理器的装置性能,
只提供了包查找个性。

指定版本

add_requires("cmake::OpenCV 4.1.1", {system = true})

指定组件

add_requires("cmake::Boost", {system = true, configs = {components = {"regex", "system"}})}

预设开关

add_requires("cmake::Boost", {system = true, configs = {components = {"regex", "system"},
                                             presets = {Boost_USE_STATIC_LIB = true}}})

相当于外部调用 find_package 查找包之前,在 CMakeLists.txt 中预约义一些配置,管制 find_package 的查找策略和状态。

set(Boost_USE_STATIC_LIB ON) -- will be used in FindBoost.cmake
find_package(Boost REQUIRED COMPONENTS regex system)

设置环境变量

add_requires("cmake::OpenCV", {system = true, configs = {envs = {CMAKE_PREFIX_PATH = "xxx"}}})

指定自定义 FindFoo.cmake 模块脚本目录

mydir/cmake_modules/FindFoo.cmake

add_requires("cmake::Foo", {system = true, configs = {moduledirs = "mydir/cmake_modules"}})

相干 issues: #1632

xmake-idea 插件更新

xmake-idea 这个插件因为集体工夫和精力的关系,始终没有花工夫去保护更新,而 IDEA 插件的兼容性问题有十分多,只有一段时间不必,就无奈在新的 Idea/Clion 上失常应用。

最近,我花了点工夫,修复了一些兼容性问题,比方 Windows 上创立工程会卡死的问题,新版本 Clion 无奈装置等问题。

目前,最新版本应该能够在全平台失常应用了。

<img src=”https://tboox.org/static/img/xmake/xmake-idea-output_panel.png” width=”50%” />

另外一些值得提起的事件

年终总结

这是 2021 年我公布的最初一个版本,这一年下来,经验了很多,Xmake 也在逐步成长为一个更加弱小的构建工具。

到今年年底,Xmake 总共播种了 4.2k stars,解决了 1.9k 的 issues/pr,超过 8k 屡次 commits。

<img src=”https://tboox.org/static/img/xmake/xmake-star-history.png” width=”50%” />

而官网的包治理仓库 xmake-repo 也曾经收录了近 500+ 的罕用依赖包。

感激

感激各位贡献者对 xmake-repo 仓库 和 Xmake 的奉献,残缺贡献者列表见:Contributors。

也非常感谢大家对 Xmake 的资助的反对,使得我可能有足够的能源去继续保护,残缺捐助列表见:Sponsors。

更新内容

新个性

  • #1902: 反对构建 linux 内核驱动模块
  • #1913: 通过 group 模式匹配,指定构建和运行一批目标程序

改良

  • #1872: 反对本义 set_configvar 中字符串值
  • #1888: 改良 windows 装置器,防止谬误删除其余装置目录下的文件
  • #1895: 改良 plugin.vsxmake.autoupdate 规定
  • #1893: 改良探测 icc 和 ifort 工具链
  • #1905: 改良 msvc 对 external 头文件搜寻探测反对
  • #1904: 改良 vs201x 工程生成器
  • 增加 XMAKE_THEME 环境变量去切换主题配置
  • #1907: 增加 -f/--force 参数使得 xmake create 能够在费控目录被强制创立
  • #1917: 改良 find_package 和配置

Bugs 修复

  • #1885: 修复 package:fetch_linkdeps 链接程序问题
  • #1903: 修复包链接程序
退出移动版