summaryrefslogtreecommitdiffstats
path: root/dev/shlibdeps.mdwn
blob: e3003ed2e33a1647a2cbb84a6f9be9aa2f2e2fce (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
[[!meta title="Automatic Shared Library Dependency Substitution Variables"]]

Background
==========

Currently, binary packages' control files (`<binpkg>.pkg/control` in source
packages) must explicitly list library dependencies.  Package maintainers can
manually see ELF files' `DT_NEEDED` entries with tools like **readelf** or
**ldd** and figure out which binary packages provide each SONAME (usually just
dropping `.so` from the middle of the SONAME, e.g. `libz.1` provides
`libz.so.1`).  Being a manual process, this method is error-prone: it's an extra
step that can be forgotten when preparing a new package or updating to a new
upstream version, it's possible to miss some ELF files in binary packages, etc.
An automated solution is clearly desirable.

Debian achieves this with a tool called **dpkg-shlibdeps**, which:

 1. Finds all ELF files in each binary package,
 2. Finds all libraries against which each ELF file is linked (i.e.
    `DT_NEEDED`),
 3. Finds dependency libraries on the system (resolving SONAMEs to file names),
 4. Looks up the packages that provide each dependency library (with
    `dpkg -S <lib-file-name>`), and
 5. Checks whether each ELF file uses symbols from its library dependencies (and
    warns of any useless/avoidable dependencies).

ProteanOS should have a similar tool.  This document describes how this can be
implemented.

Implementation
==============

Changes need to be made in three places in ProteanOS: the Source Package Format
specification, opkbuild, and opkhelper.

SPF 2.0
-------

SPF 2.0 needs to be amended to specify `tmp/<binpkg>.substvars` files, like the
`substvars` file but generated during the build process (while commands from the
`build` makefile are run and before opkbuild tools complete the package
build) and specific to each binary package.

opkbuild
--------

opkbuild needs to read the `tmp/<binpkg>.substvars` files and use them when
generating binary packages' `control` files.

opkhelper
---------

opkhelper needs a new tool, which will be called **oh-shlibdeps**, to be run
after **oh-installfiles**.  This new tool will:

 1. Find all ELF files in each binary package (**oh-strip** already does
    something similar),
 2. Run the C library's **ldd** tool and parse its output (e.g. with
    `sed -n 's/^\t.* => \(.*\) (.*)$/\1/p;'`) to find the file names of all
    libraries against which each ELF file is linked (a combination of steps 2
    and 3 above), and
 3. Look up the packages that provide each dependency library (with
    `opkg search ${filename} | sed 's/ - .*$//;'`).

Detecting useless/avoidable dependencies is considered outside the scope of the
current proposed design and may be considered in the future.

ProteanOS's `opkhelper-3.0` binary package will need to ensure the existence of
the **ldd** tool.  **ldd** is provided by the `libc-bin` package on the
`any-any-glibc` architectures (currently all architectures in ProteanOS).
musl's RTLD (a.k.a. dynamic linker) has **ldd** functionality built-in and
enabled when executed as `ldd`, so no separate package will be required.  So the
needed dependencies will depend on the architecture, however `opkhelper-3.0` is
`Architecture: all`, which means it can't have architecture-dependent
dependencies (which would be solved at build time by opkbuild, not at run time
by opkg).  Therefore, `opkhelper-3.0` will likely have to depend on
`libc-bin | ldd`, which will work on either `any-any-glibc` or `any-any-musl`
architectures if the musl library binary package `Provides: ldd`.