.TH "alpm-sonamev1" 7 .SH "NAME" .PP soname \- representation and use of soname data in ALPM based packaging\. .SH "DESCRIPTION" .PP \fBSonames\fP[1] are a mechanism to ensure binary compatibility between \fIshared objects\fP and their consumers (i\.e\. other \fBELF\fP[2] files)\. More specifically, \fBsoname\fP[1] data is encoded in the `\f[CR]SONAME\fP` field of the `\f[CR]dynamic section\fP` in \fIshared object\fP files and usually denotes specific information on the version of the object file\. \fBELF\fP[2] files may dynamically link against specific versions of \fIshared objects\fP and declare this dependency with the help of the `\f[CR]NEEDED\fP` field in their \fIdynamic section\fP\. .PP Strings representing \fBsoname\fP information can be used in \fBalpm\-package\-relations\fP of type \fBprovision\fP and \fBrun\-time dependency\fP to allow for strict package dependency setups based on ABI compatibility\. .PP The \fBalpm\-soname\fP format exists in multiple versions\. This document describes version 1, which is a legacy version and has been removed with the release of pacman 6\.1 on 2024\-03\-04\. For the latest specification, refer to \fBalpm\-soname\fP\. .SH "FORMAT" .PP The representation of \fBsoname\fP information depends on in which ALPM file format they occur in\. .PP File formats, that represent static package source data (i\.e\. \fBPKGBUILD\fP and \fBSRCINFO\fP) are distinguished from those that represent dynamic package build environment data (i\.e\. \fBPKGINFO\fP)\. .PP The \fBSRCINFO\fP (and by extension also the \fBPKGBUILD\fP) file format is used to represent static data about package sources and should therefore only refer to the \fIbasic form\fP of \fBalpm\-sonamev1\fP\. The \fIbasic form\fP is defined as the name of the \fIshared object\fP file in which \fBsoname\fP data is encoded (e\.g\. `\f[CR]libexample\.so\fP`)\. .PP The \fBPKGINFO\fP file format may contain dynamic, build environment specific data\. In these files \fBsoname\fP data may be referred to using the \fIunversioned\fP or the \fIexplicit form\fP (both contain information derived from the targeted \fIshared object\fP file)\. .PP The \fIunversioned form\fP is defined as the name of a \fIshared object\fP file, directly followed by an '=' sign, directly followed by a \fIshared object\fP's (unversioned) \fBsoname\fP string, directly followed by a '\-' sign, directly followed by the \fIELF architecture format\fP of the \fIshared object\fP file (e\.g\. `\f[CR]libexample\.so=libexample\.so\-64\fP`)\. Refer to \fBreadelf\fP for further information on how to extract relevant fields such as `\f[CR]SONAME\fP` or `\f[CR]NEEDED\fP` from the \fIdynamic section\fP of an \fBELF\fP[2] file\. .PP The \fIexplicit form\fP is defined as the name of a \fIshared object\fP file, directly followed by an '=' sign, directly followed by a \fIversion\fP string, directly followed by a '\-' sign, directly followed by the \fIELF architecture format\fP (e\.g\. `\f[CR]libexample\.so=1\-64\fP`)\. The \fIversion\fP string represents the `\f[CR]current\fP` interface number of the \fBlibrary interface version\fP[3] that is encoded as part of the \fBsoname\fP by the developer of the \fIshared object\fP (e\.g\. `\f[CR]1\fP` in `\f[CR]libexample\.so\.1\fP`)\. Refer to \fBreadelf\fP for further information on how to extract relevant fields such as `\f[CR]SONAME\fP` or `\f[CR]NEEDED\fP` from the \fIdynamic section\fP of an \fBELF\fP[2] file\. .PP The \fIELF architecture format\fP is a number derived from the `\f[CR]Class\fP` field of the \fIELF header\fP of an \fBELF\fP[2] file\. For the 32\-bit format it is `\f[CR]32\fP`, for the 64\-bit format it is `\f[CR]64\fP`\. Refer to \fBreadelf\fP for further information on how to extract the \fIELF header\fP from an \fBELF\fP[2] file\. .PP When using the name of a \fIshared object\fP file, this always refers to the least specific file name\. If for example the following files exist on a system: .RS .PP .nf /usr/lib/libexample\.so \-> libexample\.so\.1 /usr/lib/libexample\.so\.1 \-> libexample\.so\.1\.0\.0 /usr/lib/libexample\.so\.1\.0\.0 .fi .RE .PP Then the symlink `\f[CR]libexample\.so\fP` is the least specific file name, while `\f[CR]libexample\.so\.1\.0\.0\fP` would refer to the actual \fBELF\fP[2] file\. .PP \fBNote\fP: While technically possible, it is strongly discouraged to use \fIunversioned\fP or \fIexplicit form\fP in \fBPKGBUILD\fP or \fBSRCINFO\fP! This is because it requires manual handling of dynamically changing \fBsoname\fP data in the static package source file formats and those may be out of sync with the actual, explicit data derived from the build environment\. .PP \fBNote\fP: Both \fIbasic\fP and \fIexplicit forms\fP of the \fBalpm\-sonamev1\fP format overlap with the \fBalpm\-package\-name\fP and \fBcomposite comparison expressions\fP as defined in the \fBalpm\-comparison\fP format, respectively\. Due to this ambiguity it is essential to use the \fBalpm\-sonamev1\fP forms in the respective correct file formats or ideally switch to a later version of the \fBalpm\-soname\fP format altogether\. .SH "USAGE" .PP A package can depend on a specific \fBsoname\fP with the help of an \fBalpm\-package\-relation\fP of type \fBrun\-time dependency\fP, if another package provides this exact \fBsoname\fP in their \fBalpm\-package\-relation\fP of type \fBprovision\fP\. .PP More specifically, a \fBsoname\fP dependency of one package is based on the \fBsoname\fP data of a \fIshared object\fP file provided by one of its dependency packages\. .PP A package build tool (e\.g\. \fBmakepkg\fP) automatically derives \fBsoname\fP information for \fBELF\fP[2] files in the build environment based on the following rules: .RS .Bl .IP \(bu 4 If the package that is built contains a \fIshared object\fP file and the name of that \fIshared object\fP file (i\.e\. the \fIbasic form\fP) is present as an \fBalpm\-package\-relation\fP of type \fBprovision\fP in the package's \fBPKGBUILD\fP file (e\.g\. `\f[CR]provides=(libexample\.so)\fP`), then relevant data from the `\f[CR]SONAME\fP` field in the \fIdynamic section\fP of the targeted \fBELF\fP[2] file is extracted\. .RS .Bl .IP \(bu 4 If the \fBsoname\fP data contains a version, it is extracted together with the \fIELF architecture format\fP of the file to construct the \fIexplicit form\fP\. It is added instead of the \fIbasic form\fP to the \fBalpm\-package\-relation\fP of type \fBprovision\fP in the \fBPKGINFO\fP file of the package (e\.g\. `\f[CR]provides = libexample\.so=1\-64\fP`)\. .El .Bl .IP \(bu 4 If the \fBsoname\fP data does not contain a version, the entire \fBsoname\fP together with the \fIELF architecture format\fP of the file is used to construct the \fIunversioned form\fP\. It is added instead of the \fIbasic form\fP to the \fBalpm\-package\-relation\fP of type \fBprovision\fP in the \fBPKGINFO\fP file of the package (e\.g\. `\f[CR]provides = libexample\.so=libexample\.so\-64\fP`)\. .El .RE .El .Bl .IP \(bu 4 If the package that is built contains an \fBELF\fP[2] file that dynamically links against a \fIshared object\fP available in the build environment and the name of that \fIshared object\fP file (i\.e\. the \fIbasic form\fP) is present as an \fBalpm\-package\-relation\fP of type \fBrun\-time dependency\fP in the package's \fBPKGBUILD\fP file (e\.g\. `\f[CR]depends=(libexample\.so)\fP`), then relevant \fBsoname\fP data from the `\f[CR]NEEDED\fP` fields in the \fIdynamic section\fP of the \fBELF\fP[2] file is extracted for those specific \fIshared objects\fP\. .RS .Bl .IP \(bu 4 All \fBsoname\fP data that contains a version is extracted together with the \fIELF architecture format\fP of the \fBELF\fP[2] file and is used to construct the \fIexplicit form\fP\. It is matched against the \fBalpm\-package\-relation\fP of type \fBprovision\fP in the \fBPKGINFO\fP data of the packages available in the build environment\. If one matches, the \fIexplicit form\fP instead of the \fIbasic form\fP is added to the \fBalpm\-package\-relation\fP of type \fBrun\-time dependency\fP in the \fBPKGINFO\fP file of the package that is being built (e\.g\. `\f[CR]depend = libexample\.so=1\-64\fP`)\. .El .Bl .IP \(bu 4 All \fBsoname\fP data that does not contain a version is extracted in its entirety, together with the \fIELF architecture format\fP of the \fBELF\fP[2] file and is used to construct the \fIunversioned form\fP\. It is matched against the \fBalpm\-package\-relation\fP of type \fBprovision\fP in the \fBPKGINFO\fP data of the packages available in the build environment\. If one matches, the \fIunversioned form\fP instead of the \fIbasic form\fP is added to the \fBalpm\-package\-relation\fP of type \fBrun\-time dependency\fP in the \fBPKGINFO\fP file of the package that is being built (e\.g\. `\f[CR]depend = libexample\.so=1\-64\fP`)\. .El .RE .El .RE .SH "EXAMPLES" .SS "Providing a soname" .PP The following example \fBPKGBUILD\fP for a package named `\f[CR]example\fP` is used to build and install an upstream project, which provides a shared object named `\f[CR]libexample\.so\fP`\. .RS .PP .nf pkgname=example pkgver=1\.0\.0 pkgrel=1 pkgdesc="An example library" arch=(x86_64) url="https://example\.org/library\.html" license=(MIT) depends=(glibc) provides=(libexample\.so) source=("https://example\.org/$pkgname\-$pkgver\.tar\.gz") sha256sums=(7d865e959b2466918c9863afca942d0fb89d7c9ac0c99bafc3749504ded97730) build() { make \-C $pkgname\-$pkgver } package() { make DESTDIR="$pkgdir" install \-C $pkgname\-$pkgver } .fi .RE .PP The following \fBSRCINFO\fP file can be generated from the above \fBPKGBUILD\fP file: .RS .PP .nf pkgbase = example pkgdesc = An example library pkgver = 1\.0\.0 pkgrel = 1 arch = x86_64 url = https://example\.org/library\.html license = MIT depends = glibc provides = libexample\.so source = https://example\.org/example\-1\.0\.0\.tar\.gz sha256sums = 7d865e959b2466918c9863afca942d0fb89d7c9ac0c99bafc3749504ded97730 pkgname = example .fi .RE .PP This example assumes that the project results in installing the following files to the filesystem: .RS .PP .nf /usr/lib/libexample\.so \-> libexample\.so\.1 /usr/lib/libexample\.so\.1 \-> libexample\.so\.1\.0\.0 /usr/lib/libexample\.so\.1\.0\.0 .fi .RE .PP Here, the file `\f[CR]/usr/lib/libexample\.so\.1\.0\.0\fP` encodes the \fBsoname\fP `\f[CR]libexample\.so\.1\fP`\. .PP After building from source, the resulting package file for `\f[CR]example\fP` contains the following \fBPKGINFO\fP file: .RS .PP .nf pkgname = example pkgver = 1\.0\.0\-1 pkgdesc = An example library url = https://example\.org/library\.html builddate = 1729181726 packager = Your Name size = 181849963 arch = x86_64 license = MIT provides = libexample\.so=1\-64 depend = glibc .fi .RE .SS "Depending on a soname" .PP The following \fBPKGBUILD\fP for a package named `\f[CR]application\fP` is used to build an upstream project that depends on the `\f[CR]example\fP` package from the previous example\. More specifically, the resulting package depends on the \fIshared object\fP `\f[CR]libexample\.so\fP` which is provided by the `\f[CR]example\fP` package\. .PP In the \fBPKGBUILD\fP the \fBrun\-time dependency\fP on the `\f[CR]libexample\.so\fP` \fIshared object\fP is added in the `\f[CR]package\fP` function instead of in the global \fBrun\-time dependency\fP declaration, while the `\f[CR]example\fP` package is declared as global \fBbuild dependency\fP\. This is because multiple \fBsonames\fP of the same name but of different \fIELF architecture format\fP may exist (consider e\.g\. the explicit forms `\f[CR]libexample\.so=1\-32\fP` and `\f[CR]libexample\.so=1\-64\fP`)\. If `\f[CR]libexample\.so\fP` was exposed as global \fBrun\-time dependency\fP, a build tool may accidentally pull in the wrong package containing a `\f[CR]libexample\.so\fP` due to the existing structural overlap between \fBalpm\-sonamev1\fP and \fBalpm\-package\-relation\fP! .RS .PP .nf pkgname=application pkgver=1\.0\.0 pkgrel=1 pkgdesc="An example application" arch=(x86_64) url="https://example\.org/application\.html" license=(MIT) depends=(glibc) makedepends=(example) source=("https://example\.org/$pkgname\-$pkgver\.tar\.gz") sha256sums=(b5bb9d8014a0f9b1d61e21e796d78dccdf1352f23cd32812f4850b878ae4944c) build() { make \-C $pkgname\-$pkgver } package() { depends+=(example libexample\.so) make DESTDIR="$pkgdir" install \-C $pkgname\-$pkgver } .fi .RE .PP The following \fBSRCINFO\fP file can be generated from the above \fBPKGBUILD\fP file: .RS .PP .nf pkgbase = application pkgdesc = An example application pkgver = 1\.0\.0 pkgrel = 1 arch = x86_64 url = https://example\.org/application\.html license = MIT depends = glibc depends = example depends = libexample\.so makedepends = example source = https://example\.org/application\-1\.0\.0\.tar\.gz sha256sums = b5bb9d8014a0f9b1d61e21e796d78dccdf1352f23cd32812f4850b878ae4944c pkgname = application .fi .RE .PP After building from source, the resulting package file for `\f[CR]application\fP` contains the following \fBPKGINFO\fP file: .RS .PP .nf pkgname = application pkgver = 1\.0\.0\-1 pkgdesc = An example application url = https://example\.org/application\.html builddate = 1729181726 packager = Your Name size = 181849963 arch = x86_64 license = MIT depend = glibc depend = example depend = libexample\.so=1\-64 .fi .RE .SH "SEE ALSO" .PP \fBreadelf\fP(1), \fBPKGBUILD\fP(5), \fBPKGINFO\fP(5), \fBSRCINFO\fP(5), \fBmakepkg\.conf\fP(5), \fBalpm\-comparison\fP(7), \fBalpm\-package\-name\fP(7), \fBalpm\-package\-relation\fP(7), \fBmakepkg\fP(8) .SH "NOTES" .RS .Bl .IP 1. 4 \fBsoname\fP .sp https://en\.wikipedia\.org/wiki/Soname .El .Bl .IP 2. 4 \fBELF\fP .sp https://en\.wikipedia\.org/wiki/Executable_and_Linkable_Format .El .Bl .IP 3. 4 \fBlibrary interface version\fP .sp https://www\.gnu\.org/software/libtool/manual/html_node/Versioning\.html .El .RE