mirror of
https://github.com/ostreedev/ostree.git
synced 2025-01-09 01:18:35 +03:00
docs: Add a section on writing buildsystems
And add a test that is a demo buildsystem.
This commit is contained in:
parent
0b068c668a
commit
f51d651b10
@ -67,6 +67,7 @@ test_scripts = \
|
||||
tests/test-auto-summary.sh \
|
||||
tests/test-prune.sh \
|
||||
tests/test-refs.sh \
|
||||
tests/test-demo-buildsystem.sh \
|
||||
$(NULL)
|
||||
|
||||
if BUILDOPT_FUSE
|
||||
|
180
docs/manual/buildsystem-and-repos.md
Normal file
180
docs/manual/buildsystem-and-repos.md
Normal file
@ -0,0 +1,180 @@
|
||||
# Writing a buildsystem and managing repositories
|
||||
|
||||
OSTree is not a package system. It does not directly support building
|
||||
source code. Rather, it is a tool for transporting and managing
|
||||
content, along with package-system independent aspects like bootloader
|
||||
management for updates.
|
||||
|
||||
We'll assume here that we're planning to generate commits on a build
|
||||
server, then have client systems replicate it. Doing client-side
|
||||
assembly is also possible of course, but this discussion will focus
|
||||
primarily on server-side concerns.
|
||||
|
||||
## Build vs buy
|
||||
|
||||
Therefore, you need to either pick an existing tool for writing
|
||||
content into an OSTree repository, or to write your own. An example
|
||||
tool is [rpm-ostree](https://github.com/projectatomic/rpm-ostree) - it
|
||||
takes as input RPMs, and commits them (currently oriented for a server
|
||||
side, but aiming to do client side too).
|
||||
|
||||
## Initializing
|
||||
|
||||
For this initial discussion, we're assuming you have a single
|
||||
`archive-z2` repository:
|
||||
|
||||
```
|
||||
mkdir repo
|
||||
ostree --repo=repo init --mode=archive-z2
|
||||
```
|
||||
|
||||
You can export this via a static webserver, and configure clients to
|
||||
pull from it.
|
||||
|
||||
## Writing your own OSTree buildsystem
|
||||
|
||||
There exist many, many systems that basically follow this pattern:
|
||||
|
||||
```
|
||||
$pkg --installroot=/path/to/tmpdir install foo bar baz
|
||||
$imagesystem commit --root=/path/to/tmpdir
|
||||
```
|
||||
|
||||
For various values of `$pkg` such as `yum`, `apt-get`, etc., and
|
||||
values of `$imagesystem` could be simple tarballs, Amazon Machine
|
||||
Images, ISOs, etc.
|
||||
|
||||
Now obviously in this document, we're going to talk about the
|
||||
situation where `$imagesystem` is OSTree. The general idea with
|
||||
OSTree is that wherever you might store a series of tarballs for
|
||||
applications or OS images, OSTree is likely going to be better. For
|
||||
example, it supports GPG signatures, binary deltas, writing bootloader
|
||||
configuration, etc.
|
||||
|
||||
OSTree does not include a package/component build system simply
|
||||
because there already exist plenty of good ones - rather, it is
|
||||
intended to provide an infrastructure layer.
|
||||
|
||||
The above mentioned `rpm-ostree compose tree` chooses RPM as the value
|
||||
of `$pkg` - so binaries are built as RPMs, then committed as a whole
|
||||
into an OSTree commit.
|
||||
|
||||
But let's discuss building our own. If you're just experimenting,
|
||||
it's quite easy to start with the command line. We'll assume for this
|
||||
purpose that you have a build process that outputs a directory tree -
|
||||
we'll call this tool `$pkginstallroot` (which could be `yum
|
||||
--installroot` or `dbootstrap`, etc.).
|
||||
|
||||
Your initial prototype is going to look like:
|
||||
|
||||
```
|
||||
$pkginstallroot /path/to/tmpdir
|
||||
ostree --repo=repo commit -s 'build' -b exampleos/x86_64/standard --tree=dir=/path/to/tmpdir
|
||||
```
|
||||
|
||||
Alternatively, if your build system can generate a tarball, you can
|
||||
commit that tarball into OSTree. For example,
|
||||
[OpenEmbedded](http://www.openembedded.org/) can output a tarball, and
|
||||
one can commit it via:
|
||||
|
||||
```
|
||||
ostree commit -s 'build' -b exampleos/x86_64/standard --tree=tar=myos.tar
|
||||
```
|
||||
|
||||
## Constructing trees from unions
|
||||
|
||||
The above is a very simplistic model, and you will quickly notice that
|
||||
it's slow. This is because OSTree has to re-checksum and recompress
|
||||
the content each time it's committed. (Most of the CPU time is spent
|
||||
in compression which gets thrown away if the content turns out to be
|
||||
already stored).
|
||||
|
||||
A more advanced approach is to store components in OSTree itself, then
|
||||
union them, and recommit them. At this point, we recommend taking a
|
||||
look at the OSTree API, and choose a programming language supported by
|
||||
[GObject Introspection](https://wiki.gnome.org/Projects/GObjectIntrospection)
|
||||
to write your buildsystem scripts. Python may be a good choice, or
|
||||
you could choose custom C code, etc.
|
||||
|
||||
For the purposes of this tutorial we will use shell script, but it's
|
||||
strongly recommended to choose a real programming language for your
|
||||
build system.
|
||||
|
||||
Let's say that your build system produces separate artifacts (whether
|
||||
those are RPMs, zip files, or whatever). These artifacts should be
|
||||
the result of `make install DESTDIR=` or similar. Basically
|
||||
equivalent to RPMs/debs.
|
||||
|
||||
Further, in order to make things fast, we will need a separate
|
||||
`bare-user` repository in order to perform checkouts quickly via
|
||||
hardlinks. We'll then export content into the `archive-z2` repository
|
||||
for use by client systems.
|
||||
|
||||
```
|
||||
mkdir build-repo
|
||||
ostree --repo=build-repo init --mode=bare-user
|
||||
```
|
||||
|
||||
You can begin committing those as individual branches:
|
||||
|
||||
```
|
||||
ostree --repo=build-repo commit -b exampleos/x86_64/bash --tree=tar=bash-4.2-bin.tar.gz
|
||||
ostree --repo=build-repo commit -b exampleos/x86_64/systemd --tree=tar=systemd-224-bin.tar.gz
|
||||
```
|
||||
|
||||
Set things up so that whenever a package changes, you redo the
|
||||
`commit` with the new package version - conceptually, the branch
|
||||
tracks the individual package versions over time, and defaults to
|
||||
"latest". This isn't required - one could also include the version in
|
||||
the branch name, and have metadata outside to determine "latest" (or
|
||||
the desired version).
|
||||
|
||||
Now, to construct our final tree:
|
||||
|
||||
```
|
||||
rm exampleos-build -rf
|
||||
for package in bash systemd; do
|
||||
ostree --repo=build-repo checkout -U --union exampleos/x86_64/${package} exampleos-build
|
||||
done
|
||||
# Set up a "rofiles-fuse" mount point; this ensures that any processes
|
||||
# we run for post-processing of the tree don't corrupt the hardlinks.
|
||||
mkdir -p mnt
|
||||
rofiles-fuse exampleos-build mnt
|
||||
# Now run global "triggers", generate cache files:
|
||||
ldconfig -r mnt
|
||||
(Insert other programs here)
|
||||
fusermount -u mnt
|
||||
ostree --repo=build-repo commit -b exampleos/x86_64/standard --link-checkout-speedup exampleos-build
|
||||
```
|
||||
|
||||
There are a number of interesting things going on here. The major
|
||||
architectural change is that we're using `--link-checkout-speedup`.
|
||||
This is a way to tell OSTree that our checkout is made via hardlinks,
|
||||
and to scan the repository in order to build up a reverse `(device,
|
||||
inode) -> checksum` mapping.
|
||||
|
||||
In order for this mapping to be accurate, we needed the `rofiles-fuse`
|
||||
to ensure that any changed files had new inodes (and hence a new
|
||||
checksum).
|
||||
|
||||
## Migrating content between repositories
|
||||
|
||||
Now that we have content in our `build-repo` repository (in
|
||||
`bare-user` mode), we need to move the `exampleos/x86_64/standard`
|
||||
branch content into the repository just named `repo` (in `archive-z2`
|
||||
mode) for export, which will involve zlib compression of new objects.
|
||||
We likely want to generate static deltas after that as well.
|
||||
|
||||
Let's copy the content:
|
||||
|
||||
```
|
||||
ostree --repo=repo pull-local build-repo exampleos/x86_64/standard
|
||||
```
|
||||
|
||||
Clients can now incrementally download new objects - however, this
|
||||
would also be a good time to generate a delta from the previous
|
||||
commit.
|
||||
|
||||
```
|
||||
ostree --repo=repo static-delta generate exampleos/x86_64/standard
|
||||
```
|
@ -9,3 +9,4 @@ pages:
|
||||
- Atomic Upgrades: 'manual/atomic-upgrades.md'
|
||||
- Adapting Existing Systems: 'manual/adapting-existing.md'
|
||||
- Formats: 'manual/formats.md'
|
||||
- Build Systems and Repos: 'manual/buildsystem-and-repos.md'
|
||||
|
104
tests/test-demo-buildsystem.sh
Executable file
104
tests/test-demo-buildsystem.sh
Executable file
@ -0,0 +1,104 @@
|
||||
#!/bin/bash
|
||||
#
|
||||
# Copyright (C) 2016 Colin Walters <walters@verbum.org>
|
||||
#
|
||||
# This library is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU Lesser General Public
|
||||
# License as published by the Free Software Foundation; either
|
||||
# version 2 of the License, or (at your option) any later version.
|
||||
#
|
||||
# This library is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
# Lesser General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public
|
||||
# License along with this library; if not, write to the
|
||||
# Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
# Boston, MA 02111-1307, USA.
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
if ! fusermount --version >/dev/null 2>&1; then
|
||||
echo "1..0 # SKIP no fusermount"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
. $(dirname $0)/libtest.sh
|
||||
|
||||
echo "1..1"
|
||||
|
||||
# Run "triggers" like ldconfig, gtk-update-icon-cache, etc.
|
||||
demo_triggers() {
|
||||
root=$1
|
||||
shift
|
||||
mkdir -p ${root}/usr/lib
|
||||
echo updated ldconfig at $(date) > ${root}/usr/lib/ld.so.cache.new
|
||||
mv ${root}/usr/lib/ld.so.cache{.new,}
|
||||
}
|
||||
|
||||
# Make a binary in /usr/bin/$pkg which contains $version
|
||||
exampleos_build_commit_package() {
|
||||
pkg=$1
|
||||
version=$2
|
||||
mkdir -p ${pkg}-package/usr/bin/
|
||||
echo "${pkg}-content ${version}" > ${pkg}-package/usr/bin/${pkg}
|
||||
# Use a dummy subject for this.
|
||||
ostree --repo=build-repo commit -b exampleos/x86_64/${pkg} -s '' --tree=dir=${pkg}-package
|
||||
rm ${pkg}-package -rf
|
||||
}
|
||||
|
||||
exampleos_recompose() {
|
||||
rm exampleos-build -rf
|
||||
for pkg in ${packages}; do
|
||||
ostree --repo=build-repo checkout -U --union exampleos/x86_64/${pkg} exampleos-build
|
||||
done
|
||||
|
||||
# Now that we have our rootfs, run triggers
|
||||
rofiles-fuse exampleos-build mnt
|
||||
demo_triggers mnt/
|
||||
fusermount -u mnt
|
||||
|
||||
# Then we commit it, using --link-checkout-speedup to effectively
|
||||
# only re-checksum the ldconfig file. We also have dummy commit
|
||||
# message here.
|
||||
ostree --repo=build-repo commit -b exampleos/x86_64/standard -s 'exampleos build' --link-checkout-speedup exampleos-build
|
||||
}
|
||||
|
||||
packages="bash systemd"
|
||||
|
||||
mkdir build-repo
|
||||
ostree --repo=build-repo init --mode=bare-user
|
||||
mkdir repo
|
||||
ostree --repo=repo init --mode=archive-z2
|
||||
# Our FUSE mount point
|
||||
mkdir mnt
|
||||
|
||||
# "Build" some packages which are really just files with
|
||||
# the version number inside.
|
||||
exampleos_build_commit_package bash 0.4.7
|
||||
exampleos_build_commit_package systemd 224
|
||||
|
||||
# Now union the packages and commit
|
||||
exampleos_recompose
|
||||
|
||||
# This is our first commit - let's publish it.
|
||||
ostree --repo=repo pull-local build-repo exampleos/x86_64/standard
|
||||
|
||||
# Now, update the bash package - this is a new commit on the branch
|
||||
# exampleos/x86_64/bash.
|
||||
exampleos_build_commit_package bash 0.5.0
|
||||
|
||||
# We now have two commits
|
||||
exampleos_recompose
|
||||
|
||||
# Publish again:
|
||||
ostree --repo=repo pull-local build-repo exampleos/x86_64/standard
|
||||
# Optional: Generate a static delta vs the previous build
|
||||
ostree --repo=repo static-delta generate exampleos/x86_64/standard
|
||||
# Optional: Regenerate the summary file
|
||||
ostree --repo=repo summary -u
|
||||
|
||||
# Try: ostree --repo=demo-repo ls -R exampleos/x86_64/standard
|
||||
|
||||
echo "ok demo buildsystem"
|
Loading…
Reference in New Issue
Block a user