The repo bootstrap logic has worked well enough in the initial systemd
bringup. But we have decided to replace the approach of building
packages multiple times during the repo_bootstrap with building each
package only once and adding -stage0 packages where necessary (currently
only a systemd-stage0 package).
Advantages:
* Replace the often breaking repo_bootstrap logic with something less
fragile (repo_bootstrap is currently broken again).
* Can get rid of the whole bootstrap logic in pmaports.cfg, pmbootstrap,
build.postmarketos.org. This will make pmbootstrap and bpo easier to
maintain.
* Fix problems we have seen when upgrading two or more of (systemd,
dbus, linux-pam-pmos) at once: it doesn't pass in CI and it doesn't
pass in BPO
* You don't need to do a whole bootstrap at once, it is again broken
down by package. This means if building one package fails (locally or
in bpo), we don't need to do the whole thing again, just start at the
package that failed. This also means it is much easier to optimize
e.g. the stage0 packages to build faster.
* Fixes some specific bugs we currently have (abuild twice in pmaports,
bpo tests disabled because of that, ...)
Part-of: https://gitlab.postmarketos.org/postmarketOS/pmbootstrap/-/merge_requests/2588
Previously, it would only fall back to parsing all APKBUILDs if a main
package was guessed for this potential subpackage. We do however want to
scan all APKBUILDs in case the package is provided by one of the
packages in pmaports.
Signed-off-by: Jens Reidel <adrian@travitia.xyz>
g++ is a subpackage of gcc, but cannot be detected as such easily by
pmbootstrap. This is because g++ is not gcc-g++ or any other variant of
such package names. Similarly, the detection for musl-dev-ppc64le and
other architectures is broken, since the -dev suffix detection does not
work if there is an architecture suffix.
To fix it, add special case handling for cross toolchain and packages
and have that fixup the -dev cases and hardcode g++ as a subpackage of
gcc.
To reproduce:
- Generate ppc64le cross packages:
pmbootstrap aportgen gcc-ppc64le musl-ppc64le
- Build a package (to trigger building cross compilers):
pmbootstrap build hello-world --arch=ppc64le
Signed-off-by: Jens Reidel <adrian@travitia.xyz>
Replace aports -> pmaports in these messages.
$ pmbootstrap build systemd
[17:37:02] NOTE: The package 'systemd' exists in extra-repos/systemd, but systemd is currently disabled
[17:37:02] ERROR: Could not find package 'systemd' in pmaports
If the user tries to build a package, but it can't be found: check if
systemd is disabled and the package is in extra-repos/systemd, display a
hint about it.
$ pmbootstrap build systemd
[17:33:53] NOTE: The package 'systemd' exists in extra-repos/systemd, but systemd is currently disabled
[17:33:53] ERROR: Could not find aport for package: systemd
Fixes: issue 2398
Replace the boolean skip_extra_repos with a new with_extra_repos
argument that can be default, enabled or disabled.
This will be used to explicitly enable extra repos in a package search
even if systemd is currently disabled, so we can display a hint when a
package was not found because systemd is disabled in a follow-up patch.
I'm not sure why this was annotated as a Sequence rather than list. The
function clearly returns a list, not a Sequence, and the commit that
originally did it[1] provides no justification. This causes problems
with mypy checks in other places, so let's just annotate this as
returning a list.
[1]: 198f302a36
For packages selected by the user (see last commit), set the
provider_priority to 999999 instead of 999. The previous number seems
not high enough, we might set this in the APKBUILDs.
This function is used by "pmbootstrap repo_missing", which is only used
by bpo. In order to support building the split repository in bpo, this
patch is required.
Return "systemd" for the packages that are in extra-repos/systemd, and
None for all other packages (indicating that they don't get split into a
separate repository).
Checking the parent-parent dir of the APKBUILD is a bit fragile
(assuming we don't have subdirs in the systemd repository), but that
assumption was made with the previous implementation as well (would only
return "systemd" in that case). I don't see a better solution with
reasonable effort right now, given that we also support multiple
pmaports dirs. We can improve this in the future, meanwhile let's just
not use subdirs in the systemd repository.
Now that we have target-version = "py310" in [tool.ruff] in
pyproject.toml, ruff check complains about using typing.Optional and
typing.Union instead of newer syntax. Run the tool to fix it.
Generalise pmb.helpers.other.cache with a more python decorator.
The Cache decorator takes a list of function arguments to use as cache
keys, keyword args can be used to restrict caching so that it is skipped
entirely unless the attribute has a specific value.
For example, pmb.helpers.pmaports.get() has the decorator:
@Cache("pkgname", subpackages=True)
This means the return value will be cached only when subpackages is
True, otherwise it will always miss.
Signed-off-by: Caleb Connolly <caleb@postmarketos.org>
Move pmb/parse/arch.py over to core and refactor it as an Arch type,
similar to how Chroot was done. Fix all the uses (that I can find) of
arch in the codebase that need adjusting.
The new Arch type is an Enum, making it clear what architectures can be
represented and making it much easier to reason about. Since we support
~5 (kinda) different representations of an Architecture (Alpine, Kernel,
target triple, platform, and QEMU), we now formalise that the Alpine
format is what we represent internally, with methods to convert to any
of the others as-needed.
Signed-off-by: Caleb Connolly <caleb@postmarketos.org>
find() gets the pmaports directory of a package, get() parses the
APKBUILD inside that directory.
Instead of having the extra code path in get() for not searching
subpackages, which duplicated part of find(), add a subpackages
parameter to get().
Besides the deduplication done now, this is in preparation for code that
will extend get() to handle the extra-repos/systemd directory - without
this patch, the changes would need to be duplicated in both functions.
The repo_bootstrap command is totally standalone and has it's own state,
making it a good candidate for the pmb.commands submodule. Port it over
and move the require_bootstrap() helper function over to
pmb/helpers/pmaports.py
We also fix the call to pmb.build.package() which broke during rework.
Signed-off-by: Caleb Connolly <caleb@postmarketos.org>
Cease merging pmbootstrap.cfg into args, implement a Context type to let
us pull globals out of thin air (as an intermediate workaround) and rip
args out of a lot of the codebase.
This is just a first pass, after this we can split all the state that
leaked over into Context into types with narrower scopes (like a
BuildContext(), etc).
Signed-off-by: Caleb Connolly <caleb@postmarketos.org>
With the new chroot type, we can now write fancy paths in the pythonic
way. Convert most of the codebase over, as well as adding various other
type hints.
Signed-off-by: Caleb Connolly <caleb@postmarketos.org>
We use a custom verbose log level in pmbootstrap, unfortunately it isn't
possible to correctly type this due to some limitations in the logging
library [1], [2].
Given that our usecase is fairly simple, we can just wrap the module
with our own so we only have to tell mypy to ignore the error once
instead of at every callsite.
[1]: https://github.com/cryptax/droidlysis/issues/15
[2]: https://github.com/python/typing/discussions/980
Signed-off-by: Caleb Connolly <caleb@postmarketos.org>
Introduce a new module: pmb.core to contain explicitly typed pmbootstrap
API. The first component being Suffix and SuffixType. This explicitly
defines what suffixes are possible, future changes should aim to further
constrain this API (e.g. by validating against available device
codenames or architectures for buildroot suffixes).
Additionally, migrate the entire codebase over to using pathlib.Path.
This is a relatively new part of the Python standard library that uses a
more object oriented model for path handling. It also uses strong type
hinting and has other features that make it much cleaner and easier to
work with than pure f-strings. The Chroot class overloads the "/"
operator the same way the Path object does, allowing one to write paths
relative to a given chroot as:
builddir = chroot / "home/pmos/build"
The Chroot class also has a string representation ("native", or
"rootfs_valve-jupiter"), and a .path property for directly accessing the
absolute path (as a Path object).
The general idea here is to encapsulate common patterns into type hinted
code, and gradually reduce the amount of assumptions made around the
codebase so that future changes are easier to implement.
As the chroot suffixes are now part of the Chroot class, we also
implement validation for them, this encodes the rules on suffix naming
and will cause a runtime exception if a suffix doesn't follow the rules.
If we found an APKBUILD already, with the exact name of the package we
are looking for, then don't also guess what other package could contain
the package as subpackage.
The guess was thrown away with the previous logic, but it caused
misleading verbose logs like:
lomiri-history-service: guessed to be a subpackage of lomiri
Also this is slightly faster. While at it, tweak the related comments
to make this easier to understand.
Link: https://lists.sr.ht/~postmarketos/pmbootstrap-devel/%3C20231121222457.2871-1-ollieparanoid@postmarketos.org%3E
Fix that APKBUILDs mentioning other packages with an operator could not
be found. As we are building the initial branch of v23.12, this
currently happens with postmarketos-mkinitfs: it depends on
devicepkg-utils>=0.2.0 and currently pmbootstrap will only remove the
>=0.2.0 when looking for the pkgname in the APKINDEX of binary packages
(which is why it works on master). But it does not yet do that when
looking for the pkgname in pmaports.
Move the code for stripping the operator to a common place and use it
for getting packages from pmaports too.
Change the order of operators while at it, try to find <= before =, as
otherwise it would cut off example<=1.2.3 as "example<" instead of
"example".
Reviewed-by: Caleb Connolly <kc@postmarketos.org> (via chat)
Replace "args.cache" with a global variable in order to
avoid passing "args" to all functions. This is a step to get rid of this
args-passed-to-all-functions pattern in pmbootstrap.
The provider selection for "pmbootstrap init" added in this commit
is a flexible way to offer UI/device-specific configuration options
in "pmbootstrap init", without hardcoding them in pmbootstrap.
Instead, the options are defined entirely in pmaports using APK's
virtual package provider mechanism. The code in pmbootstrap searches
for available providers and displays them together with their pkgdesc.
There are many possible use cases for this but I have tested two so far:
1. Selecting root provider (sudo vs doas). This can be defined entirely
in postmarketos-base, without having to handle this specifically in
pmbootstrap.
$ pmbootstrap init
[...]
Available providers for postmarketos-root (2):
* sudo: Use sudo to run root commands (**default**)
* doas: Use doas (minimal replacement for sudo) to run root commands
(Note: Does not support all functionality of sudo)
Provider [default]: doas
2. Device-specific options. My main motivation for working on this
feature is a new configuration option for the MSM8916-based devices.
It allows more control about which firmware to enable:
$ pmbootstrap init
[...]
Available providers for soc-qcom-msm8916-rproc (3):
* all: Enable all remote processors (audio goes through modem) (default)
* no-modem: Disable only modem (audio bypasses modem, ~80 MiB more RAM)
* none: Disable all remote processors (no WiFi/BT/modem, ~90 MiB more RAM)
Provider [default]: no-modem
The configuration prompts show up dynamically by defining
_pmb_select="<virtual packages>" in postmarketos-base, a UI PKGBUILD
or the device APKBUILD. Selecting "default" (just pressing enter)
means that no provider is selected. This allows APK to choose it
automatically based on the "provider_priority". It also provides
compatibility with existing installation; APK will just choose the
default provider when upgrading. The selection can still be changed
after installation by installing another provider using "apk".
Note that at the end this is just a more convenient interface for the
already existing "extra packages" prompt. When using pmbootstrap in
automated scripts the providers (e.g. "postmarketos-root-doas") can be
simply selected through the existing "extra_packages" option.
At the moment, "provides" are only checked in the root package and not
in subpackages of APKBUILDs. Fix this by looking through the subpackages
as well.
At the moment we have to parse all APKBUILDs to find subpackages,
even if they are guessed easily shortly after. To speed this up,
let's guess first but verify the guess by only parsing that particular
APKBUILD. If the subpackage/provides is in there we seem to have found it.