Upstream-side: ABI version numbers
The X server defines several
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 replacesxserver-xorg-corewithxserver-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 appendsxinpdriver:Depends=…andxinpdriver:Provides=…to this package’s substvars file. - 
If a package name starts with
xserver-xorg-video-, it appendsxviddriver:Depends=…andxviddriver: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
autoreconfat build time. - 
It is a
videodriver. For aninputdriver, replace bothxviddriveroccurrences withxinpdriver. 
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 underdebian/PACKAGEinstead ofdebian/tmp), so make it usedebian/tmpin all cases. This way,dh_installhas 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.lafiles. Also, using--fail-missingmakes 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 (bothquiltandautoreconfinsert commands beforedh_auto_configure, and afterdh_clean). Also, we build out-of-tree. Thexsfsequence is explained in the previous part. 
If one needs to build several flavours,
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.