Dependencies between server and drivers
=======================================
:toc:
Cyril Brulebois <kibi@debian.org>


Upstream-side: ABI version numbers
----------------------------------

The X server defines several
https://en.wikipedia.org/wiki/Application_binary_interface[ABI] version numbers in the
`hw/xfree86/common/xf86Module.h` header, through the
`SET_ABI_VERSION(maj,min)` macro. In this document, the focus is on
`ABI_VIDEODRV_VERSION` and `ABI_XINPUT_VERSION`, which are
respectively about `video` drivers and `input` drivers.

An example of input ABI is `12.1`, `12` being the `major`, `1` being
the `minor`.

Like in usual shared libraries, the major is bumped when interfaces
are broken. There’s no compatibility at all in that case.

The minor gets bumped when interfaces are added. In other words, if a
driver is working with `x.y`, it should also work with higher minors:
`x.z`; `z>y`. The converse is not true, if a driver requires a given
minor (for example because it needs a new feature, like MultiTouch),
it won’t work with lower minors (which didn’t provide the needed
feature). Put another way: we have ascending compatibility with the
minors.

Conclusion: We need to keep track of both major and minor.

Thanks to `pkg-config` we can query them:

----
$ pkg-config --variable=abi_videodrv xorg-server
9.0
$ pkg-config --variable=abi_xinput xorg-server
12.1
----

<<<
Debian-side: Using virtual packages
-----------------------------------

Server’s build system
~~~~~~~~~~~~~~~~~~~~~

When `xorg-server` gets built, we use ++pkg-config++’s output to
determine the current major. Through substitution variables, we add
two virtual packages in the `Provides` field of the server (for both
`xserver-xorg-core` and `xserver-xorg-core-udeb`): `xorg-input-abi-$x`
and `xorg-video-abi-$y`, where `$x` and `$y` are the major part of the
version queried through `pkg-config` variables.

To handle ascending compatibility for minors, we maintain in
`debian/serverminver` the minimal version of `xserver-xorg-core` which
is needed. When a minor is bumped, we store the server version in that
file. This way, drivers built afterwards will depend on a *minimal*
version of the driver, the last which saw a minor version bump. In
other words: they will “depend on the server version they were built
against, or a higher/compatible one”.

Both ABI and minimal server version are recorded in two files shipped
in `xserver-xorg-dev`, to be used while building drivers:

   * `/usr/share/xserver-xorg/xinputdep`
   * `/usr/share/xserver-xorg/videodrvdep`

Example for `xinputdep`:

----
xorg-input-abi-11, xserver-xorg-core (>= 2:1.8.99.904)
----
To make sure we bump the `debian/serverminver` when there’s a minor
ABI change, there’s a `abibumpcheck` target (on which `clean`
depends), which extracts input and video ABI from the upstream header,
and compares them to the previous ones stored in
`debian/serverminver`, failing and diffing is something changed.


Driver’s control file
~~~~~~~~~~~~~~~~~~~~~

Drivers also use substitution variables in their control file,
replaced at build time.

----
# Input driver:
Depends: ${xinpdriver:Depends}, …
Provides: ${xinpdriver:Provides}

# Video driver:
Depends: ${xviddriver:Depends}, …
Provides: ${xviddriver:Provides}
----

For now, `${xinpdriver:Provides}` is always replaced with
`xorg-driver-input`, and `${xviddriver:Provides}` is always replaced
with `xorg-driver-video`. Hopefully provided packages will not change,
but using substitution variables is cheap, and makes it easy to add
tweaks afterwards if needed.


Driver’s build system
~~~~~~~~~~~~~~~~~~~~~

To set those variables, we ship a `dh_xsf_substvars` script in
`xserver-xorg-dev` starting with `2:1.9.4`, to be run before
`dh_gencontrol`. It iterates on the packages listed by
`dh_listpackages` (very old `debhelper` command) and does the
following work:

 * It reads variables from the files mentioned above.
 * If a package name ends with `-udeb`, it replaces
   `xserver-xorg-core` with `xserver-xorg-core-udeb`.
 * If a package name ends with `-dbg`, it does nothing for this
   package. Debug packages usually depend strictly on the non-debug
   packages, which in turn have appropriate dependencies.
 * If a package name starts with `xserver-xorg-input-`, it appends
   `xinpdriver:Depends=…` and `xinpdriver:Provides=…` to this
   package’s substvars file.
 * If a package name starts with `xserver-xorg-video-`, it appends
   `xviddriver:Depends=…` and `xviddriver:Provides=…` to this
   package’s substvars file.

Why such heuristics? The idea is to avoid getting “unused substitution
variable” warning messages while building. And since there’s a clear
`xserver-xorg-{input,video}-*` namespace, we can use that to specify
only input-related variables for input drivers, and only video-related
variables for video drivers.

To make it easy to compute substvars when using `dh`, a `dh` sequence
(`xsf.pm`) is shipped. As of `2:1.9.4-1`, it inserts
`dh_xsf_substvars` right before the `dh_gencontrol` call. Other
repetitive tasks could also be automated this way.


<<<
Sample driver packaging
-----------------------

The following assumes:

 * The upstream build system is sane enough, which lets us run
   `autoreconf` at build time.
 * It is a `video` driver. For an `input` driver, replace both
   `xviddriver` occurrences with `xinpdriver`.

Sample debian/control file
~~~~~~~~~~~~~~~~~~~~~~~~~~

----
Build-Depends:
 debhelper (>= 8),
 dh-autoreconf,
 quilt,
 xserver-xorg-dev (>= 2:1.9.4),
----

----
Depends:
 ${shlibs:Depends},
 ${misc:Depends},
 ${xviddriver:Depends},
Provides:
 ${xviddriver:Provides}
----

Sample debian/rules file
~~~~~~~~~~~~~~~~~~~~~~~~

----
#!/usr/bin/make -f

# Configuration:
#override_dh_auto_configure:
#        dh_auto_configure -- --with-FOO --without-BAR

# Install in debian/tmp to retain control through dh_install:
override_dh_auto_install:
        dh_auto_install --destdir=debian/tmp

# Kill *.la files, and forget no-one:
override_dh_install:
        find debian/tmp -name '*.la' -delete
        dh_install --fail-missing

## Debug package:
#override_dh_strip:
#        dh_strip --dbg-package=xserver-xorg-video-DRIVER-dbg

# That's a plugin, use appropriate warning level:
override_dh_shlibdeps:
        dh_shlibdeps -- --warnings=6

%:
        dh $@ --with quilt,autoreconf,xsf --builddirectory=build/
----

Some comments:

 * `dh_auto_configure`: Commented out since there’s usually no
   specific option to pass when building drivers. Sometimes needed to
   get a related utility built.
 * `dh_auto_install`: It behaves differently when operating on a
   single package (it installs under `debian/PACKAGE` instead of
   `debian/tmp`), so make it use `debian/tmp` in all cases. This way,
   `dh_install` has to be used (see below). That also means that a
   binary package (_e.g._ a debug package) can be added without
   changing this part.
 * `dh_install`: No point in keeping the `.la` files. Also, using
   `--fail-missing` makes sure every file installed by upstream is
   installed in some package, or explicitly ignored.
 * `dh_strip`: Commented out, there’s only a few drivers shipping a
   debug package.
 * `dh_shlibdeps`: The comment really says it all.
 * `dh`: The order is important! We want patching to happen before
   autoreconfiguring (both `quilt` and `autoreconf` insert commands
   before `dh_auto_configure`, and after `dh_clean`). Also, we build
   out-of-tree. The `xsf` sequence is explained in the previous part.

If one needs to build several flavours,
https://salsa.debian.org/xorg-team/driver/xserver-xorg-video-fbdev/blob/debian-unstable/debian/rules[++fbdev++'s rules file]
can be used as an example.


<<<
Handling a transition
---------------------

When a new major version of the server comes up, it can be updated
following its `README.source`. Usually, drivers can be rebuilt using
binNMUs. Be sure `xorg-server` is marked as `Installed` on all
buildds, or set a `dep-wait`.

On the release team side, a transition page can be asked for, to track
fully rebuilt drivers. For the input 12→13 and video 10→11
transitions, the settings are:

 * Affected: `.build-depends ~ /xserver-xorg-dev/`
 * Good: `.depends ~ /xorg-input-abi-13/ | .depends ~ /xorg-video-abi-11/`
 * Bad: `.depends ~ /xorg-input-abi-12/ | .depends ~ /xorg-video-abi-10/`


<<<
Staying tuned
-------------

Staying informed of driver-related changes can be a bit difficult in
the following cases:

 * If one maintains a single driver within the X Strike Force, one
   might not notice the few mails about drivers in the heavy mail flow
   on `debian-x@`.
 * If one maintains a driver outside the X Strike Force, one is
   probably not subscribed to the mailing list at all.

For those reasons, a mail alias is being set up to gather all
maintainers interested in receiving driver-related mails.
