跳至內容

DKMS 軟體包打包準則

出自 Arch Linux 中文维基
Arch 打包準則

32 位 – 安全 – CLR – CMake – DKMS – Eclipse – Electron – Free Pascal – GNOME – Go – Haskell – Java – 交叉編譯工具 – KDE – Lisp – Meson – MinGW – 內核模塊 – Node.js – Nonfree – OCaml – Perl – PHP – Python – R – Ruby – Rust – Shell – VCS – Web – Wine – 字體

創建一個新的 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 install 和 dkms remove 鉤子。

dkms install 會確保過程結束時執行 depmod。dkms 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