__          __             __
\ \_________\ \____________\ \___
 \  _ \  _\ _  \  _\ __ \ __\   /
  \___/\__/\__/ \_\ \___/\__/\_\_\
                      Bedrock Linux

Introductory Material

Limitations

Reference Material

Extending Bedrock

Miscellaneous


© Bedrock Linux 2012-2020
Linux® is a registered
trademark of Linus Torvalds

Bedrock Linux 0.7 Poki Extension

Bedrock Linux's core functionality is largely distro and package manager agnostic. However, Bedrock does provide distro and package manager specific quality-of-life utilities. This page documents expanding this functionality.

Before attempting to usptream anything to Bedrock, run make check and resolve any complaints it may raise with your changes.

brl fetch New Distros

brl fetch bootstraps a minimal set of files from a given distribution for use as a Bedrock stratum. This should be enough for the user to bootstrap whatever else he/she needs, such as a package manager and its (both explicitly configured and assumed) dependencies.

Support for a new distro may be added by creating a file at:

See surrounding files for examples.

Allowed commands

brl fetch is used to gather files from other distros. Care must be taken to avoid the catch-22 which results from brl fetch depending on functionality from those distros.

brl fetch per-distro scripts only may use:

Prelude

The per-distro brl fetch file should start with a fixed pattern of:

#!/bedrock/libexec/busybox sh
#
# distro bootstrap support
#
# copyright message
#

# shellcheck source=src/slash-bedrock/libexec/brl-fetch
. /bedrock/share/common-code
trap 'fetch_abort "Unexpected error occurred."' EXIT

Variables

brl fetch sources the discussed file. The following variables will be set before brl fetch calls most per-distro functions are called and are safe to utilize in most of the functions described below:

Target Functions

The file should populate the following functions:

Helper Functions

brl fetch provides a number of functions which may assist in implementing fetch():

Fetch Strategies

Below are some strategies developed to implement fetch() for various distros.

Portable Bootstrap Utility

Some distros provide a portable utility which can bootstrap the distro. For example, Alpine and Void both provide a static, stand-alone version of their respective package managers. These can bootstrap the rest of their distros without many assumed dependencies.

For such distros, the general strategy is to:

Double Bootstrap

Some distros provide a non-portable utility to bootstrap the distro. For brl fetch to use it, this must itself be bootstrapped. For example, Arch provides pacstrap, Debian provides debootstrap, and Fedora provides dnf.

For such distros, the general strategy is to:

Rootfs provided

Some distros provide essentially exactly the files which are needed, such as in a single compressed tarball file. For example, Gentoo, KISS, and OpenWRT all provide suitable tarballs of their userland as part of their normal distribution method. These just need to be downloaded and extracted into ${target_dir}.

pmm New Package Managers

pmm is a Bedrock-aware tool which abstracts cross- and multi-package-manager operations.

Support for a new package manager may be added by creating a file at:

See surrounding files for examples.

These files are predominantly awk array definitions which pmm sources.

After adding a package manager to pmm on a Bedrock system, run

pmm --check-pmm-configuration

to have pmm self-sanity check and ensure you are not missing a required field.

system_package_managers[]

Many distros are built around specific package managers. For example, apt, dnf, and pacman. pmm considers these system package managers. They are contrasted against auxiliary package managers such as pip or yay.

If the package manager you are adding is a system package manager, indicate so by adding it to system_package_managers[]:

system_package_managers["package-manager"]

package_manager_canary_executables[]

pmm detects if a given stratum provides a package manager by searching its common $PATH locations for a canary executable. These are often one-to-one with the package manager name, e.g. apt, dnf, and pacman. However, this is not always the case. For example, xbps does not provide a xbps package manager, but rather uses xbps-install, xbps-remove, et al.

Tell pmm what executable to look for to detect a given package manager with package_manager_canary_executable[]:

package_manager_canary_executables["package-manager"] = "canary-executable"

supersedes[]

Some package managers wrap another package manager. For example, yay effectively supersedes pacman. pmm must be aware of this to avoid double-counting package ownership.

If the package manager you are adding supersedes another package manager, indicate so with supersedes[]:

supersedes["new-package-manager"] = "old-package-manager"

user_interfaces[]

Rather than introduce a new user interface, pmm mimics that of other package managers. Any given package manager's interface is defined with the user_interfaces[] array.

The expected format is:

user_interfaces["package-manager", "interface-item"] = "pattern"

For example:

user_interfaces["apk", "upgrade-packages-full"] = "pmm upgrade"

tells pmm that if it is configured to mimic apk and sees an input in the form pmm upgrade the request is to upgrade all packages.

There are two types of interface items for second field:

These must match pmm's name for the flag or operation.

See /bedrock/share/pmm/help for the list of interface items expected. Note the comments; some help[] entries are for package-manager-agnostic operations which do not correspond to a given per-package-manager support file.

A pattern may contain / to indicate multiple legal values for the given field. For example:

user_interfaces["apk", "quiet"] = "-q/--quiet"

indicates that either -q or --quiet indicates the user provided the quiet flag.

A pattern may contain .... This indicates one or more terms with varying contents is expected at that position. For example:

user_interfaces["apk", "install-packages"] = "pmm add <pkgs>"

tells pmm that if it is configured to mimic apk and sees pmm add followed by at least one more term, the user requested is to install one or more packages.

The exact contents of ... for a given interface item must match the help[] description output in /bedrock/share/pmm/help. Otherwise, pmm --check-pmm-configuration will raise concern that you populated the wrong entry.

If a package manager does not surface a given flag or operation, populate its value as an empty string. Otherwise, pmm --check-pmm-configuration will raise concern that you might have failed to implement a given entry.

implementations[]

A package manager's implementation of a given operation is indicated with implementations[] The expected format is:

implementations["package-manager", "operation"] = "shell command"

For example:

implementations["apk", "install-packages"] = "strat -r ${stratum} apk ${flags} add ${items}"

tells pmm how to instruct a given stratum's apk to install a package.

Before running shell command, pmm populates the following shell variables for use in implementations[] commands:

Some pmm operations are combinations of primitive operations. For example, the operation update-package-database,upgrade-packages-full first updates the package database then upgrades all packages. Only implement these if the given package manager can do so with a single command; otherwise, leave it an empty string. pmm will queue independent primitive operations automatically if a combine operation is unimplemented.

Some pmm operation concepts do not align perfectly with the package manager concepts. When populating such implementations[], if the concept does not align perfectly, populate broadly. For example, apt differentiates between apt upgrade and apt full-upgrade, but pacman does not carry this difference. If pmm is mimicking apt and either of these upgrade variations are passed to pacman, pacman should perform its singular upgrade concept. Thus, pacman's implementations[] include both

implementations["pacman", "upgrade-packages-limited"] = "strat -r ${stratum} pacman ${flags} -Su"

and

implementations["pacman", "upgrade-packages-full"] = "strat -r ${stratum} pacman ${flags} -Su"

Some implementations[] are consumed by pmm, either for use internally within pmm or to be altered before being provided to the end user. These commands should always be run in a non-interactive mode; they should never prompt for input. Moreover, these should have their output standardized. See /bedrock/share/pmm/help comments.

pmm New Operations

pmm is a Bedrock-aware tool which abstracts cross- and multi-package-manager operations.

To add a new pmm operation, add an operations[] line to:

The expected format is:

operations["operation-name"] = "applicability-type, applicability-check, argument-count, pre-process, post-process"

where:

Additionally, add --help output for it to:

and add user_interfaces[] and implementations[] entries for each existing package manager per the pmm new package manager documentation.

After adding an operation to pmm on a Bedrock system, run

pmm --check-pmm-configuration

to have pmm self-sanity check and ensure you are not missing a required field.