DKMS 软件包指南

来自 ArchWiki
Arch 软件包指南

32 位CLRCMake交叉编译DKMSEclipseElectron字体Free PascalGNOMEGoHaskellJavaKDE内核模块LispMesonMinGWNode.js非自由软件OCamlPerlPHPPythonRRubyRust - 安全ShellVCSWeb 应用Wine

这里是在创建 DKMS 软件包时需要遵循的一些指南。

软件包名称

DKMS 软件包的命名方式是在原始软件包名称后附加 "-dkms"。

变量 $_pkgname 通常在 $pkgname 之后使用,以描述不包含 "-dkms" 后缀的软件包名称 (例如 _pkgname="${pkgname%-*}")。

依赖关系

dkms 添加到 depends 数组中。这非常重要,因为它将提供工具和钩子,以便在内核更新时重建 -dkms 软件包提供的内核驱动程序。

不要在 PKGBUILD 中包含 linux-headers – 或任何其他 Linux 头文件软件包。这些头文件已经列为 dkms 的可选依赖项,并且每个内核软件包都有自己的头文件软件包,因此在 -dkms 软件包中包含头文件软件包依赖项既是不必要的冗余,也是限制性的。

源代码位置

软件包应将内核模块的源文件安装到

/usr/src/PACKAGE_NAME-PACKAGE_VERSION

其中 PACKAGE_NAMEPACKAGE_VERSION 是内核模块的名称和版本。

强烈建议将 PACKAGE_NAME 设置为 $_pkgname 的值(参见 #软件包名称),并将 PACKAGE_VERSION 设置为 $pkgver

注意: 无需构建内核模块的源文件或安装它们;当 Linux 内核更新时,由于 dkms 中的 pacman 钩子,这将自动完成。

打补丁

源代码可以直接在 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 钩子 自动完成。此钩子运行 dkms installdkms remove,软件包维护者无需手动操作。

注意: dkms install 确保在其过程结束时调用 depmoddkms install 依赖于 dkms build(针对当前内核构建源代码),而 dkms build 本身又依赖于 dkms add(添加从 /var/lib/dkms/PACKAGE_NAME/PACKAGE_VERSION/source/usr/src/PACKAGE_NAME-PACKAGE_VERSION 的符号链接)。

示例

这是一个示例软件包,它根据软件包名称和版本编辑 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 "${pkgdir}/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
}

模块黑名单配置

当已知 example-conflicting-module 与此软件包的 example 模块冲突时,应将其列入黑名单

example-dkms.conf
blacklist example-conflicting-module