跳至內容
出自 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