This guide is for users who are developing systems using Baserock tooling for an ARM device. It assumes you have a Trove and an ARM distbuild network set up already.
It assumes you have a project definitions in your Trove that has been forked from the Baserock reference system definitions.
Placeholders that are used in this guide:
- $trove -- hostname and trove-id of your Trove
- $project -- name of your project
- $project/definitions -- your project definitions repo
All commands should be run in your Baserock chroot unless otherwise noted.
Preparation
Set up a Baserock chroot (or VM) on your main development machine.
Configure Git user.name
and user.email
.
git config --global user.name "John Doe"
git config --global user.email johndoe@example.com
Create a morph.conf
file in /src
[config]
log = /src/morph.log
log-max = 200M
cachedir = /src/cache
tempdir = /src/tmp
trove-host = hostname-of-trove
trove-id = trove-id-of-your-trove
controller-initiator-address = hostname-of-your-controller-initiator
Then create a symlink to it from /etc
:
ln -sv /src/morph.conf /etc/morph.conf
This way if you replace your chroot (or VM's root disk) you only need to re-create the symlink, as the contents of /src are shared between all versions.
Building a system
# Clone the definitions repository
git clone git://$trove/$projects/definitions /src/
# build the ARMv7 LHF base system
cd /src/definitions
morph distbuild systems/base-system-armv7lhf-generic.morph
Deploying a system to .tar file
# Work in your checked out definitions directory
cd /src/definitions
# Create the cluster definition file for the tarball
cat > tar.morph <<EOF
name: tar
kind: cluster
systems:
- morph: systems/base-system-armv7lhf-generic.morph
deploy:
tar:
type: extensions/tar
location: rootfs.tar
EOF
# Deploy the built system using the cluster definition file
morph deploy tar.morph
# rootfs.tar now exists and you can unpack it to an SD card and boot
# your device.
Partial deployment
NOTE: This should not be used when deploying production systems, as it has a number of limitations.
It may be useful during development to be able to deploy just a chunk and its dependencies, rather than the whole system.
# Work in your checked out definitions directory
cd /src/definitions
# Create the cluster definition file for the partial deployment
cat > partial-tar.morph <<EOF
name: partial-tar
kind: cluster
systems:
- morph: systems/base-system-armv7lhf-generic.morph
deploy:
tar:
type: extensions/tar
location: deployed-chunks.tar
partial-deploy-components:
- strata/build-essential/busybox.morph
# Deploy using --partial
morph deploy --partial partial-tar.morph
deployed-chunks.tar
now exists, containing busybox and its dependencies.
This can now be extracted on top of an existing rootfs. Note that the
components listed in partial-deploy-components
must be in the system
defined above (in the morph
field), and can be chunks or strata. This
only works for deployments with type: extensions/tar
or
type: extensions/sysroot
.
If morph deploy
is run without --partial
, then partial-deploy-components
is simply ignored and the full system is deployed.
Adding a chunk
To import open source projects into your Trove, see: http://wiki.baserock.org/Trove/reference/#index12h3
To add or change chunks in your systems, see:
http://wiki.baserock.org/devel-with/#index9h2 and
http://wiki.baserock.org/devel-with/#index10h2 (but use morph
distbuild
in place of morph build
and $trove:$project/definitions in
place of baserock:baserock/definitions).
Modifying a chunk
To modify a chunk, libpng in the example, do the following:
# Move to your checked out definitions directory
cd /src/definitions
morph get-chunk-details libpng
You should see the following output from morph get-chunk-details libpng
:
In stratum graphics-common:
Chunk: libpng
Repo: git://git.baserock.org/delta/libpng
Ref: 259fb7761d747655c607efcec7a12ff1f3c24561
This provides the details needed to modify the chunk.
# Move to somewhere you can clone the chunk repo.
cd /src/
# Clone the repo URL from the earlier `morph get-chunk-details` output
git clone git://git.baserock.org/delta/libpng
# <Make your changes to the chunk>
git commit
git push
NOTE: you can also use the morph get-repo
command.
Now you can update your definitions to reference the updated chunk:
# Move back to your checked out definitions directory
cd /src/definitions
The earlier morph get-chunk-details libpng
output showed that libpng was in the graphics-common stratum. Edit stratum/graphics-common.morph
and update the libpng chunk's ref field.
Checking definitions reproducibility
Before producing a release, we should ensure that what we release is reproducible. We can use the morph certify
tool to do this. In your definitions repo:
# Run the reproducibility certification tool.
morph certify . HEAD systems/base-system-armv7lhf-generic.morph
If it produces any warnings, the current state of definitions cannot be certified as reproducible and it will report FAILED. Otherwise you will see:
=> Reproducibility certification PASSED for
systems/base-system-armv7lhf-generic.morph
If certification passes, proceed to building the release:
# Build the system
morph distbuild --local-changes=ignore systems/base-system-armv7lhf-generic.morph
Working with binaries in Git repos
Trove allows you to use git-fat to manage binary content that needs to go in your Baserock system. This lets you track the history of the binary files in a Git repo while storing the actual content outside the repo, which stops the repo becoming enormous.
To add a binary file to a chunk repo:
morph add-binary ./large-binary-file
This will run git-fat init
for you if needed, and will update and
commit the .gitfat
and .gitattributes
files, in a way that
causes large-binary-file
to be stored in a special $repo/.gitfat
directory on the Trove.
The binary files are not transferred as part of a normal git push
operation. You can either use morph push
in place of git push
, OR
use git push && git fat push
to push.
Creating a cross-compile SDK
You can use Morph to generate a cross-compile 'SDK' for your rootfs. The SDK is treated as another Baserock system, built for x86_32 or x86_64 and containing your rootfs as a 'nested' system so that the headers and libraries are available. (This can make it rather large; including only the headers and libraries would be a nice improvement).
There are SDK systems in definitions.git for x86_32 and x86_64 hosts, both targetting armv7lhf:
It should be simple to adapt these for other host and/or target platforms.
To build one of these systems, use morph
inside your x86_32 chroot (or
whatever the host platform is):
# Work in your checked out definitions directory
cd master/$trove/$project/definitions/
morph build systems/armv7lhf-cross-toolchain-system-x86_32.morph
Make sure you have an up-to-date build of your target rootfs in your shared artifact cache, too. (See 'Building a system' section, above).
Now create a cluster (deployment) morph for your SDK system. Below is an example; see the sdk-example-cluster.morph file for further guidance.
name: sdk
kind: cluster
description: Cross-compile SDK for $project
systems:
- morph: systems/armv7lhf-cross-toolchain-system-x86_32.morph
deploy:
sdk:
type: extensions/sdk
location: $project-sdk-v1.sh
PREFIX: /usr
TARGET: armv7lhf-baserock-linux-gnueabi
subsystems:
- morph: systems/$project-system-armv7lhf.morph
deploy:
sysroot:
type: extensions/sysroot
location: usr/armv7lhf-baserock-linux-gnueabi/sys-root
Replace the $project placeholders in this, save it as sdk.morph
and run:
morph deploy sdk.morph
You should get a self-extracting shell script output written to $project-sdk-v1