[Build-common-hackers] Adding kernel modules packaging support to CDBS (long)

Frédéric Brière fbriere at fbriere.net
Wed Mar 25 01:35:18 UTC 2009


Hi everyone,

As I mentioned in #377390, I have been working on adding support for
kernel modules packages to CDBS.  I think I've finally got it all nailed
down, so now I'm looking for feedback from the CDBS community, and from
maintainers of kernel modules packages.  (There are seven such packages
currently using CDBS; I'll be contacting their maintainers shortly to
point them to this discussion.)

The source can be viewed here:
<http://git.fbriere.net/cdbs-kernel-module.git/?a=tree>.

In working on these, I drew from my own experience (I've worked on two
out-of-Debian kernel modules packages), and looked through the 70 kernel
modules packages found in Debian for inspiration.  I hope I've come up
with something that will prove to be both useful and versatile enough
for everybody.

In this email, I'll be laying down sort of a rough draft of an attempt
at documentation.  (Bear with me, because I suck at writing good
documentation.)  Comments inviting answers/discussion are included in
[[ brackets ]] -- although feedback is obviously welcome everywhere.
(It's much better to get things right the first time than to be stuck
with a half-assed implementation forever.  So, don't hold back.)


But first, here's an (optional) crash course for those of you who are
unfamiliar with the way kernel modules packages work:

----- BEGIN MODULES PACKAGING PRIMER -----

The source for the out-of-kernel "foo" module is provided by a package
(typically called foo-source -- a binary package, despite the name)
containing mostly a single tarball at /usr/src/foo.tar.bz2.  The user is
expected to untar it and run a specific command, which will then compile
the module and generate a binary package (typically called
foo-modules-2.6.xx, version <kernel_version>+<upstream_version>[*]) for
the user to install.

 [*] Or not, depending on bug #402811

While there is no policy over how this must be implemented by the
contents of the tarball, common usage is to mimic source packages, with
a debian/rules makefile and such.  This has in turn been made
semi-official by tools like kernel-package and module-assitant, which
expect a debian/rules that provides specific targets for this purpose.
(Namely, "kdist*" for kpkg, and "binary-modules" for m-a.)

As there is no conflict between the target names expected from the
tarball's debian/rules and those from the source package's debian/rules,
it is common to see them merged into a single file.

Finally, do note that the name of the foo-modules-2.6.xx package (as
well as its version) can only be determined at build time, meaning that
the tarball's debian/control needs to be generated/modified by
debian/rules.

----- END MODULES PACKAGING PRIMER -----


The classes and rules that follow are meant to adhere as much as
possible to the CDBS philosophy: be modular, automate the common/boring
stuff, and don't get in the way.  In particular, most variable and
target names are kept deliberately distinct from those found elsewhere
in CDBS, in order to allow for the sharing of debian/rules between the
source package and the *-source tarball.  (I'll admit it may look
convoluted at first, but I believe it was the best solution.)

[[ One small remark beforehand: the pathnames I've chosen are somewhat
screwed up.  Maybe something like "(class|rules)/modules-foo.mk" would
be appropriate?  Not to mention that my selection of rules vs. class is
murky at best. ]]


Well, here we go!


----- BEGIN KERNEL MODULES CLASSES -----

 == core.mk ==

<http://git.fbriere.net/cdbs-kernel-module.git/?a=blob;f=core.mk>

Similar to buildcore.mk, this provides a flavorless basic support for
kernel modules.  The $(DEB_MODULES_SRCDIR) and $(DEB_MODULES_BUILDDIR)
play the same role as their non-MODULES counterpart.  All the usual
variables are available, with the possible exception of *_PACKAGES noted
below.

The following rules are there for you to fill at your leasure:

  - clean-modules
  - pre-build-modules
  - configure-modules
  - build-modules
  - post-build-modules
  - install-modules
  - binary-modules
  - sign-modules

They serve the same purpose as their non-modules counterpart.  The
sign-modules target is meant to generate a .changes file and sign it;
see the kernel-package documentation for more details.

All kdist* targets required by kernel-package will be correctly defined,
based on the targets listed above.  (This means you should not include
module-assistant's common-rules.make, which you do not need anyway.)

Take note that if your tarball does not ship with a debian/control file,
you will see a couple of "debian/control: No such file or directory"
error messages at first.  Do not be alarmed, these are harmless.  This
does mean, however, that the $(DEB_SOURCE_PACKAGE) and $(DEB_*_PACKAGES)
variables will have undefined contents, as well as $(DEB_DESTDIR).  This
has no incidence on CDBS, but it does mean that you cannot rely on them.

Also note that $(DEB_AUTO_UPDATE_DEBIAN_CONTROL) is incompatible with
this class.

Finally, $(DEB_MODULES_DEB_DESTDIR) is provided as a suggestion to where
you should leave the final .deb package.

[[ The kdist and kdist_image targets currently run the whole
build+install as root, which is far from ideal.  I initially balked at
the idea of calling make twice (build as user, then install as root),
but then I noticed this is exactly what dpkg-buildpackage does.  So, I'm
now leaning towards this, and will proceed if there are no objections. ]]


 == debhelper.mk ==

<http://git.fbriere.net/cdbs-kernel-module.git/?a=blob;f=debhelper.mk>

Adds debhelper support to core.mk.  This will pull in CDBS'
debhelper.mk, and is conversely automatically pulled in by core.mk if
CDBS' debhelper.mk was included before.  (In other words, when sharing
debian/rules, the modules and non-modules halves will either both or
neither use debhelper.)

Like debhelper.mk, this invokes most dh_* commands, save for those which
wouldn't make much sense for kernel modules (dh_strip, dh_shlibdeps,
etc).  binary-*-modules targets are defined corresponding to those in
debhelper.mk (save for binary-strip).

Variables of the type $(DEB_*_<package>) are replaced by
$(DEB_*_MODULES); the corresponding $(DEB_*_ALL) variables do *not* take
effect.  Variables of the type $(DEB_*_ARGS) and $(DEB_*_EXCLUDE) are
applied, though.

[[ This is far from ideal, but it's the best I could manage, since
*_ARGS and *_EXCLUDE cannot be managed on a per-package basis.  I'm also
not sure what to do with DEB_DH_GENCONTROL_ARGS, which involves both. ]]

$(DEB_INSTALL_{DIRS,CHANGELOGS,DOCS}_MODULES) get the same default
values as the corresponding $(DEB_INSTALL_*_ALL), which often make
sense.  Note that these defaults are based on $(DEB_SRCDIR), and not
$(DEB_SRCDIR_MODULES).  [[ This could be avoiding by cut&pasting the
definition, but I don't like the idea. ]]

Finally, $(DEB_DH_INSTALL_SOURCEDIR_MODULES) replaces
$(DEB_DH_INSTALL_SOURCEDIR).

$(DEB_MODULES_VERSION) can be used to provide the version of the
package, in case it wasn't added to the changelog.


 == makefile.mk ==

<http://git.fbriere.net/cdbs-kernel-module.git/?a=blob;f=makefile.mk>

Similar to CDBS' makefile.mk, but for modules, and without $(CXXFLAGS),
$(LDFLAGS), or the "check" target.

All $(DEB_MAKE_*) variables are replaced with $(DEB_MODULES_MAKE_*).
$(CFLAGS_MODULES) and $(CPPFLAGS_MODULES) are initialized from $(CFLAGS)
and $(CPPFLAGS), and thus behave in the same way regarding
$(DEB_BUILD_OPTIONS).

[[ I blindly copied the makefile-clean rule, but its purpose escapes me.
Can anyone shed some light? ]]


 == module-assistant.mk ==

<http://git.fbriere.net/cdbs-kernel-module.git/?a=blob;f=module-assistant.mk>

Hooks into module-assistant.  (See the module-assistant documentation
for more information.)

module-assistant's "prep-deb-files" and "genchanges" targets will be
invoked as part of the "pre-build-modules" and "sign-modules" targets.

module-assistant requires $(PACKAGE) to be defined *before* inclusion.
If needed, this class will attempt to provide a sensible default, by
scanning debian/control[.modules.in] and returning the first package
name matching *-module[s]-X*, where X is not a letter/digit.  (This will
thus match foo-modules-_KVERS_ or foo-modules-${kpkg:Kernel-Version},
but not foo-modules-source.)

$(DEB_MODULES_VERSION) and $(DEB_MODULES_DEB_DESTDIR) are automatically
set from module-assistant's $(VERSION) and $(DEB_DESTDIR).  Afterwards,
$(DEB_DESTDIR) will be restored to its previous value, to avoid any
conflict when sharing the same debian/rules.

In addition, $(DEB_MODULES_DESTDIR) is provided as a convenient
equivalent to $(DEB_DESTDIR), pointing to "$(CURDIR)/debian/$(PKGNAME)".

Non-modules builds will not fail if module-assistant is not installed,
so no build-dependency is needed even when sharing the same
debian/rules.  (But do remember to have the *-source binary package
depend on it.)


 == source.mk ==

<http://git.fbriere.net/cdbs-kernel-module.git/?a=blob;f=source.mk>

Provides support for building kernel module source packages.  Unlike the
previous classes, this one is a regular class, meant to hook into the
foo-source build.  It supports building multiple *-source packages, but
tries to make the almost-universal single-source-package case as easy as
possible.

(This class pulls in debhelper.mk.)

$(DEB_MODULES_SRC_PACKAGES) holds the list of kernel module source
packages, defaulting to all *-source and *-src packages.  If overridden,
this must be done *before* inclusion.

By default, the "foo" part of the foo.tar.bz2 tarball and
/usr/src/modules/foo directory is obtained by stripping out
[-module[s]]-(source|src) from the package's name.  This can be
overridden with $(DEB_MODULES_SRC_BASENAME_<package>), or
$(DEB_MODULES_SRC_BASENAME) for convenience if there is only one package
in $(DEB_MODULES_SRC_PACKAGES).

Still for convenience, $(DEB_MODULES_SRC_DESTDIR) is provided, pointing
to debian/foo-source/usr/src/modules/foo for the first package in
$(DEB_MODULES_SRC_PACKAGES).

At the beginning of the install target, this class will create the
usr/src/modules/foo/debian directory, and populate it with any of the
following files found in the source package's debian directory:

  - rules
  - changelog
  - copyright
  - compat
  - *.modules.in
  - *KVERS*
  - Any file in $(DEB_MODULES_SRC_DEBFILES_<package>)
  - Any file in $(DEB_MODULES_SRC_DEBFILES)

(Note that this does not include debian/control.)

In addition, if debian/rules.modules or debian/foo-source.rules exists,
this file will be copied as debian/rules.

At the end of the install target, this class will fix the permissions of
the usr/src/modules/foo tree, and create the tarball.  (The source
package should build-depend on bzip2.)

[[ I'm not sure about the permissions I chose, but they seemed the most
appropriate. ]]

[[ One snag I hit is that when building foo-source as part of several
packages, you often want to use dh_install with a different --sourcedir
(typically ".") but there is no mechanism for a per-package
$(DEB_DH_INSTALL_SOURCEDIR).  I solved it with a single $(if), but I was
wondering if I should open a wishlist for
$(DEB_DH_INSTALL_SOURCEDIR_<package>). ]]

----- END KERNEL MODULES CLASSES -----


Whew!

As an addendum, I'd like to offer an example for comparison purposes.
You can see the debian/rules I've written for my ITP on opencbm:

<http://git.debian.org/?p=collab-maint/opencbm.git;a=blob;f=debian/rules>

Here's how it would look like with the help of the new classes (and a
small opencbm-source.install):


----- BEGIN DEBIAN/RULES EXAMPLE -----

  include /usr/share/cdbs/1/rules/debhelper.mk
  include /usr/share/cdbs/1/rules/patchsys-quilt.mk
  include /usr/share/cdbs/1/class/makefile.mk
  include /usr/share/cdbs/1/class/kernel-module/source.mk

  DEB_MAKE_MAKEFILE = LINUX/Makefile
  DEB_MAKE_INSTALL_TARGET = PREFIX=$(CURDIR)/debian/tmp/usr install

  # Set dh_install --sourcedir=. for opencbm-source
  DEB_DH_INSTALL_SOURCEDIR = $(if $(call cdbs_streq,$(cdbs_curpkg),opencbm-source),$(DEB_SRCDIR),$(DEB_DESTDIR))
  # Only keep debug symbols for the library
  DEB_DBG_PACKAGE_libopencbm0 = libopencbm0-dbg
  # Override the default -- README and NEWS are of little consequence
  DEB_INSTALL_DOCS_ALL =


  binary-install/opencbm::
	  dh_installmodules -p opencbm


  ### KERNEL SETUP

  include /usr/share/cdbs/1/class/kernel-module/makefile.mk
  include /usr/share/cdbs/1/rules/kernel-module/module-assistant.mk


  DEB_MODULES_BUILDDIR = sys/linux
  DEB_MODULES_MAKE_MAKEFILE = LINUX/Makefile
  DEB_MODULES_MAKE_INSTALL_TARGET = install-files
  # Makefile expects us to override all variables
  DEB_MODULES_MAKE_INVOKE += KERNEL_SOURCE=$(KSRC) MODDIR=$(DEB_MODULES_DESTDIR)/lib/modules/$(KVERS)/misc UDEV_RULES=

  clean-modules::
	  rm -f sys/linux/Module.symvers

  DEB_INSTALL_DIRS_MODULES = lib/modules/$(KVERS)/misc

----- END DEBIAN/RULES EXAMPLE -----


Much better, isn't it?  (And that's a somewhat convoluted package --
most would look much cleaner than this.)


So, I'd like to hear your thoughts and comments on this.  I'm also
looking forward to maintainters giving it a try, rewriting their
debian/rules, and raising any issue they may have encountered.  (I'd be
glad to lend a hand -- just let me know.)

Thank you all, you've been a terrific audience.  :)


-- 
I was attacked by dselect as a small child and have since avoided
debian.
		-- Andrew Morton



More information about the Build-common-hackers mailing list