跳转到内容
来自 Arch Linux 中文维基
Arch 打包准则

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

创建一个新的 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来进行。

If patching through dkms.conf, make sure to install the patches into /usr/src/PACKAGE_NAME-PACKAGE_VERSION/patches/ directory and to add a PATCH[number]=patch_filename for each patch to be applied, replacing number with a incremental value starting at 0. See dkms(8) § DKMS.CONF for more information.

.install 中模块的自动加载

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

Also do not call dkms as it is automatically done via pacman hook provided by dkms. 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

This example shows a message on post-install and post-upgrade that suggests unloading a conflicting module (example-conflicting-module) and then loading this package's module (example) for immediate use, when the user do not want to reboot the system at this moment.

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

When it is known that example-conflicting-module conflicts with this package's example module, it should be blacklisted:

example-dkms.conf
blacklist example-conflicting-module