# XSF / Dependencies between server and drivers

Cyril Brulebois
`<kibi@debian.org>`

## 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 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, `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.