đŸ Archived View for lofi.haiku-os.org âș docs âș develop âș packages âș Infrastructure.gmi captured on 2024-03-21 at 15:05:33. Gemini links have been rewritten to link to archived content
âŹ ïž Previous capture (2023-09-28)
-=-=-=-=-=-=-
This pages gives an overview of what components belong to Haikuâs package management infrastructure and how they work and interact.
.
package-management-infrastructure.png
In Haiku there are two main locations where software is installed. â/boot/systemâ and â/boot/home/configâ. â/boot/systemâ is where system-wide software (i.e. software for all users), including the base system, is installed, while â/boot/home/configâ is only for the userâs software. The discrimination between those two doesnât make that much sense yet, but when Haiku supports multi-user it will (obviously each user will need their own home directory then, e.g. â/boot/home/<user>â).
At both main installation locations a packagefs instance is mounted. Each instance presents a virtually extracted union of the contents of all packages in the subdirectory âpackagesâ of that location. E.g. if one would extract the contents of all package files in â/boot/system/packagesâ to an actual directory, that would match exactly what is presented by packagefs in â/boot/systemâ. With a few exceptions â packagefs provides several additional directories.
There are so-called shine-through directories which live on the underlying BFS volume. Normally a file system mounted at a directory would completely hide anything that is in that directory. These shine-through directories are handled specially, though; packagefs shows them just like they are on the BFS volume. One of those directories is âpackagesâ. This is necessary since otherwise it wouldnât be possible to add, remove, or update any packages. Further shine-through directories are âsettingsâ, âcacheâ, âvarâ, and ânon-packagedâ. The latter is a place where software can be installed the âtraditionalâ, i.e. unpackaged, way.
At the lowest level software can be installed by simply dropping a respective package file in a âpackagesâ subdirectory of one of â/boot/systemâ or â/boot/home/configâ. The package daemon, a background process that sleeps most of the time, monitors the directory and, when happy with the newly added package, it asks packagefs to presents its contents on the fly in the directory structure. The package is said to be activated. Removing a package has the opposite effect.
Things are a bit more complicated due to the fact that packages usually have dependencies. E.g. when adding a package that has an unsatisfied dependency (e.g. needs a certain library that is not installed) it is not a good idea to activate the package nonetheless. The package contents (programs, libraries,âŠ) might not work correctly, and, e.g. when shadowing other installed software, might even break things that worked before.
Thatâs why the package daemon doesnât just activate any well-formed packages. Instead it examines the new situation and checks whether all dependencies are fulfilled and whether there are any conflicts. If they arenât any problems, it tells packagefs to activate/deactivate the packages as requested. In case there are issues with the dependencies, according to how it has been configured via settings, the daemon prompts the user immediately, checks remote repositories for solutions to the problem and presents the user with the possible options, or it even performs all necessary actions without bothering the user, if possible. In the end, if the problems could be solved (e.g. by downloading additional packages), the respective packages will be de-/activated, or, otherwise, nothing will be changed.
To avoid always having to check all dependencies when booting, the package daemon writes the last consistent state of package activations to the file âpackages/administrative/activated-packagesâ. When being mounted packagefs, reads that file and only activates the packages specified by it. If the file is missing or packages it refers to cannot be found or loaded, packagefs falls back to activating all packages in the âpackagesâ directory. The package daemon, once started, checks the state.
While manual software installation is possible, the more comfortable way is to use the package manager. The package manager has a configurable list of remote software repositories. It knows what software is available in those repositories and what is installed locally. After the user has selected software packages to be installed/deinstalled, package dependencies are resolved, and packages are downloaded and moved to their installation location.
The package manager prepares a transaction directory, a subdirectory in the âpackages/administrativeâ directory, which contains the new packages. It then contacts the package management daemon (via the package kit) to perform the package activation changes. The daemon moves the new packages to the âpackagesâ directory, moves obsolete packages to an old state directory (also a subdirectory in the âpackages/administrativeâ directory, with the current date and time encoded in its name) and asks packagefs to activate/deactivate the respective packages. The old state directories allow recovery of old states. That is particularly interesting for the system installation location. As as safe mode/recovery option, the boot loader offers the user to select an old installation state which can then be booted into, instead of the latest state.
Haiku also supports a concept that is commonly referred to as application bundles. An application bundle is a fully self-contained package that doesnât need to be installed anywhere. The implementation details have not yet been decided on. The basic idea is to either mount a dedicated packagefs with the content of such a package or have a special location where one of the three already mounted packagefs instances (likely the â/boot/home/configâ one) shows that content. With a bit of Tracker (or even libbe) integration that will allow the mounted directory to be opened or the application to be started when such a package file has been double-clicked.
Having two separate installation locations for software requires some considerations regarding their consistency and interactions. Thereâs a well-defined order of the installation locations: â/boot/home/configâ, â/boot/systemâ. This has already been the order in which on BeOS commands, libraries, and add-ons where searched (according to the environmental variables "PATH", "LIBRARY_PATH", and "ADDON_PATH"). That e.g. allows a user to install a new/different version of a program in â/boot/home/configâ and have it override the version in â/boot/systemâ.
This order also needs to be the order in which package dependencies are directed. While it shall be possible to have a library in â/boot/home/configâ override one in â/boot/systemâ and have programs installed in the latter location use the overriding library, packages in an installation location must not have dependencies that can only be resolved to packages installed in a location that is prior according to the order. E.g. a program installed in â/boot/systemâ must not depend on a library that is only installed in â/boot/home/configâ. When going multi-user that would mean the program would work for one user, but not for another one who hasnât installed the library. Consequently â/boot/systemâ is fully self-contained. All dependencies must be resolved within it. A safe-mode boot should be possible with only the â/boot/systemâ packagefs being mounted. As a consequence these constraints have to be respected when software is installed or uninstalled.
Another challenge that comes with having two installation locations is that some packages have compiled-in absolute paths to their own files (e.g. data files) or to their dependencies. The former could be solved by building two different versions of a package, but that wouldnât work with the latter and would be tedious anyway. The solution are dynamically generated symbolic links in a fixed location, â/boot/system/package-linksâ (symlinked to â/packagesâ), that for each installed package and its dependencies refer to the respective installation location.
For each installed package a subdirectory named like the package (package name plus version) will be generated automatically. That subdirectory contains a symlink â.selfâ which refers to the installation location of the package itself as well as a symlink for each of its dependencies pointing to their installation locations. Furthermore thereâs a symlink â.settingsâ which points to the installation locationâs directory for global settings. E.g. for an OpenSSH package installed in â/boot/home/configâ and OpenSSL installed in â/boot/systemâ the directory could look like this:
/boot/system/package-links/openssh-5.8p2-1/ .self -> ../../../home/config .settings -> ../../../home/config/settings/global haiku -> ../.. lib:libssl -> ../..
Installing a different, compatible version of OpenSSL in â/boot/home/configâ would automatically change the respective dependency symlink. Once supporting multi-user fully, the symlinks targets would also depend on the user ID of the process that checks them, so software installed only for the user is handled correctly.
While it depends on the location the package has been installed in where the paths refer to, the absolute paths of the package links themselves remain stable. So they can be compiled in, when a package is built, and will work regardless of where the package is installed.
Another problem the package links can solve are incompatible versions of the same package being installed in different locations. E.g. when a program and another program it depends on are installed in â/boot/systemâ, installing an incompatible version of the latter in â/boot/home/configâ will not break the former, since the dependency link will continue to point to the compatible version. With a bit of help from the runtime loader the same would work for libraries. In practice thatâs less of a problem, though, since libraries usually have a naming scheme and matching shared object names that already prevent mismatches.
A software repository is a collection of packages, usually accessible via the internet. Haikuâs package management solution allows to refer to any number of software repositories from which packages can be downloaded and installed. The structure of the respository is very simple. Itâs just a set of files which can be downloaded via a common protocol (HTTP or FTP). One file is the repository index file in
. It lists all packages that are available in the repository together with their descriptions and dependency information. It is downloaded and cached, allowing user interfaces to show the information and the dependency solver to do the computation locally. The other files are the individual package files.
There are two standard repositories for Haiku:
For the different builds and releases there are different instances of those two repositories:
The repositories are maintained via files in the Haiku git repository. For each architecture and each repository the Haiku git repository contains a file listing the packages for that repository. For the HaikuPorts repositories the packages are listed with the respective version. For the Haiku repositories the version is implied.
Whenever a developer wants to update or add a HaikuPorts package, the new package file has to be uploaded to their git.haiku-os.org account and the package list file for the repository has to be adjusted accordingly. "jam upload-packages <packages-list>" can be used in order to upload the package(s) or the packages could just be "scp"âed into the âhpkg-uploadâ folder in the developer home directory on git.haiku-os.org. When that is done, the change can be pushed to git.haiku-os.org, where a push hook will analyze the change, move the new package file(s) from the developerâs account to the repository directory, and build a new repository snapshot. If a package file is missing or broken, the push will be rejected with a message notifying the developer about the problem.
The creation and update of repositories for official releases has to be triggered explicitly on the server. In either case the Haiku repository is built by the build service.
The package kit provides an API for all package management related tasks, including:
Package files and repository index files contain text strings â e.g. the package short and long description â that are presented to the user. Therefore translations for these strings must be available. Since it is impractical to include the translations in the package and repository index files, they must be provided in separate files. How exactly has not been decided on yet.