跳转到内容

为应对本站因各种原因无法访问,建议用户安装 arch-wiki-docs-zh-cnCNRepo 或者 arch-wiki-docs-zh-twCNRepo 离线文档包备用,也可尝试使用经由Cloudflare CDN的替代版本aw.lilydjwg.me

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
# 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"

该示例会在安装或升级后显示一条信息,建议用户在不想立即重启系统时,卸载冲突模块(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