跳转到内容

DKMS 软件包打包准则

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

32 位安全CLRCMakeDKMSEclipseElectronFree PascalGNOMEGoHaskellJava交叉编译工具KDELispMesonMinGW内核模块Node.jsNonfreeOCamlPerlPHPPythonRRubyRustShellVCSWebWine字体

创建一个新的 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 installdkms remove 钩子。

dkms install 会确保过程结束时执行 depmoddkms 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