跳转到内容

DKMS 软件包打包准则

来自 Arch Linux 中文维基
Arch 打包准则

32 位 – 安全 – CLR – CMake – DKMS – Eclipse – Electron – Free Pascal – GNOME – Go – Haskell – Java – 交叉编译工具 – KDE – Lisp – Meson – MinGW – 内核模块 – Node.js – Nonfree – OCaml – Perl – PHP – Python – R – Ruby – Rust – Shell – VCS – Web – Wine – 字体

创建一个新的 DKMS 包时,可以参考下面的指导方针。

包名

DKMS 包的命名方式是:原始包名加"-dkms"后缀。

通常在 $pkgname 后面使用 $_pkgname 记录不包含 "-dkms" 后缀的软件包名 (例如 _pkgname=${pkgname%-*}). 这样可以在原始的软件包 PKGBUILD 和 DKMS 编译文件之间保持相似性。

依赖

依赖的包应该是原来软件包的基础上,加上 dkms包。这一点很重要,因为它将提供工具和 Hook 文件,在内核更新时重建由 -dkms 软件包提供的内核驱动程序。

不要在 PKGBUILD 包含 linux-headers包 或任何其他的Linux头文件包。这些头文件已经作为 dkms包 的可选依赖,同时每个内核包都有自己的头文件包,因此在 -dkms 软件包包含这些头文件包是不必要的重复和限制的。

源代码构建位置

构建模块所需源代码需要放在(这是DKMS构建模块时使用的默认目录):

/usr/src/PACKAGE_NAME-PACKAGE_VERSION

在软件包目录,要包含一个 dkms.conf 配置文件,告诉 DKMS 如何编译。这个配置文件需要包含:

  • PACKAGE_NAME - 实际的项目名称,通常使用 $_pkgname (见#包名)或 $_pkgbase.
  • PACKAGE_VERSION - 通常使用 $pkgver.
注意:不需要编译内核模块的源文件,也不需要安装它们;由于 dkms包 中的 pacman#钩子,每当 Linux 内核更新时,这些工作都会自动完成。

打补丁

为内核模块源代码打补丁既可以直接在 PKGBUILD 中进行,也可以通过dkms.conf来进行。

若通过 dkms.conf 打补丁,请确保将补丁安装在 /usr/src/PACKAGE_NAME-PACKAGE_VERSION/patches/ 目录下,并为每个补丁添加 PATCH[number]=patch_filename 条目,记得将 number 替换为以0起始的数字。查阅 dkms(8) § DKMS.CONF 以获取相关信息

.install 中模块的自动加载

模块的加载和卸载必须由用户自己来执行,设想一下,某个模块可能在加载的时候崩溃。

另外,不要在 .install 中调用 dkms ,该操作会由 dkms包 提供的 Pacman 钩子 自动完成。Pacman 会自动执行 dkms install 和 dkms remove 钩子。

dkms install 会确保过程结束时执行 depmod。dkms install 依赖 dkms build (针对当前内核编译源码),build 依赖 dkms add (添加从 /var/lib/dkms/<package>/<version>/source 到 /usr/src/<package> 的链接)。

例子

这儿有个根据包名字和版本来对dkms.conf进行编辑,并安装模块黑名单配置文件的例子。

其它示例请参考官方软件仓库中的 -dkms 软件包和 AUR 中的 -dkms 包。

PKGBUILD

PKGBUILD
# Maintainer: foo <foo(at)example(dot)org>
# Contributor: bar <bar(at)example(dot)org>

_pkgbase=example
pkgname=example-dkms
pkgver=1
pkgrel=1
pkgdesc="The Example kernel modules (DKMS)"
arch=('x86_64')
url="https://www.example.org/"
license=('GPL2')
depends=('dkms')
conflicts=("${_pkgbase}")
install=${pkgname}.install
source=("${url}/files/tarball.tar.gz"
        'dkms.conf'
        "${pkgname}.conf"
        'linux-3.14.patch')
md5sums=(use 'updpkgsums')

prepare() {
  cd ${_pkgbase}-${pkgver}

  # Patch
  patch -p1 -i "${srcdir}"/linux-3.14.patch
}

package() {
  # Copy dkms.conf
  install -Dm644 dkms.conf "${pkgdir}"/usr/src/${_pkgbase}-${pkgver}/dkms.conf

  # Set name and version
  sed -e "s/@_PKGBASE@/${_pkgbase}/" \
      -e "s/@PKGVER@/${pkgver}/" \
      -i "${pkgdir}"/usr/src/${_pkgbase}-${pkgver}/dkms.conf

  # Copy sources (including Makefile)
  cp -r ${_pkgbase}/* "${pkgdir}"/usr/src/${_pkgbase}-${pkgver}/

  # Blacklists conflicting module
  install -Dm644 ${pkgname}.conf "${srcdir}/usr/lib/modprobe.d/${pkgname}.conf"
}

dkms.conf

dkms.conf
PACKAGE_NAME="@_PKGBASE@"
PACKAGE_VERSION="@PKGVER@"
MAKE[0]="make --uname_r=$kernelver"
CLEAN="make clean"
BUILT_MODULE_NAME[0]="@_PKGBASE@"
DEST_MODULE_LOCATION[0]="/kernel/drivers/misc"
AUTOINSTALL="yes"

.install

该示例会在安装或升级后显示一条信息,建议用户在不想立即重启系统时,卸载冲突模块(example-conflicting-module)并加载该包提供的模块(example)。

example.install
post_install() {
  cat<<EOF

Unload and load kernel modules:

  rmmod example-conflicting-module
  modprobe example

EOF
}

post_upgrade() {
  post_install
}

Module blacklist conf

已知模块 example-conflicting-module 会与模块 example 冲突时,应将其加入模块黑名单:

example-dkms.conf
blacklist example-conflicting-module