Getting started with Akku package manager for Scheme
Akku is a package manager for Scheme that currently supports numerous R6RS and R7RS Scheme implementations [1]. I was slow to embrace Akku because I encountered some initial friction with installation and setup. Moreover, coming from R, I was more familiar with a global package management model than Akku's project-based workflow. In the meantime, I was content to manually manage the few libraries that I had downloaded from different repos and placed in a directory found by Chez's (library-directories)
.
Recently, though, I spent part of a weekend playing with Janet and was seriously considering shifting my attention from Chez to Janet. At the end of the weekend, when I was taking stock of why I found Janet so appealing, it boiled down to lisp-like syntax with modern affordances and a built-in package manager. I decided that convenient syntax didn't trump Chez's solidity and stability, which left the package manager as the primary attraction. I came away from that experience with a renewed appreciation for Chez Scheme and resolved to push past my previous pain points and get up and running with Akku. The friction was related to trying to install on Windows and macOS and my unfamiliarity with GnuPG keys. I subsequently switched to using Akku exclusively on Linux where it works seamlessly. In 2024, I revisited installing on macOS and updated this post to reflect my experience.
In this post, I will walk through the basics of installing Akku and setting up projects (Linux and macOS) and publishing packages (Linux only).
Installing Akku
There are several installation options, but I recommend first trying the pre-built options available here. Download akku-1.1.0.amd64-linux.tar.xz
for GNU/Linux amd64 and akku-1.1.0.src.tar.xz
for other architectures. After downloading, extract and install with the following commands.
$ tar -xf akku-1.1.0.src.tar.xz
$ cd akku-1.1.0.src
$ ./install.sh
This approach installs to ~/.local
. If ~/.local/bin
is not already on your path (check with echo $PATH
), then add the following line to .zshrc
(or wherever you keep your shell configuration commands). Make sure to replace username
with the your actual username and replace home
with Users
on macOS.
export PATH="/home/username/.local/bin:$PATH"
If the pre-built versions don't work for you, then the next step is to try the release tarball (akku-1.1.0.tar.gz
), which requires Guile.
$ tar -xf akku-1.1.0.tar.gz
$ cd akku-1.1.0
$ ./configure
$ make
$ sudo make install
If you receive errors about not being able to find Scheme libraries, and you previously added a line to export CHEZSCHEMELIBDIRS
in .zshrc
, then you can replace that line with the following conditional logic (which is also necessary for using Akku after installation). Akku sets a local library directory that will be overridden by the export in .zshrc
without adding this condition.
if [[ -v AKKU_ENV ]]; then
echo "AKKU_ENV is set"
else
export CHEZSCHEMELIBDIRS="/home/username/scheme/lib:"
fi
On macOS, if you use Homebrew, you could first try installing with brew install akku
, but that didn't work for me. I resorted to cloning the repository and building from there.
$ git clone https://gitlab.com/akkuscm/akku.git
$ cd akku
$ ./configure
$ make
$ sudo make install
This approach installs to /usr/local/bin
, which should generally already be on your path. In hindsight, I'm not sure if I had Xcode installed when I tried the first installation option listed above, which might explain why it failed, but I didn't want to mess with my working Akku installation to test that explanation.
Setting up a project
If you are starting a new project, the command akku init
will initialize "a new project with a simple template that demonstrates a program, a library and a test."
akku init example-project
You should manually update the version, synopsis, authors, and license in Akku.manifest
. If you are using Akku to install packages, then you will not need to manually update the depends field. However, Akku provides the option to include direct dependencies from Git repositories, local directories, and URLs, which does require manually updating the depends field. If you using direct dependencies, be advised...
Packages with direct dependencies will not be accepted into the Akku.scm archive. The archive is a self-sufficient set of packages.
It is not necessary to first use akku init
. You can start using Akku in an existing project. Let's pretend we have an existing project.
$ mkdir existing-project
$ cd existing-project
$ akku update
$ akku install
akku update
updates the local package index. It is a global command, not specific to a project. If you are having trouble installing a package, this is the first thing to try. akku install
creates the hidden .akku
directory [2]. When you install packages with akku install pkgname
, the library files are placed in .akku/lib
and the full source code is installed in .akku/src
.
Let's install my chez-stats
library.
akku install chez-stats
Now, if you take in a peak in .akku/lib
, you will find chez-stats
and the srfi
library. chez-stats
only has a dependency on srfi
for testing [3].
Installing chez-stats
creates the following Akku.manifest
file, which indicates a dependency on the current version of chez-stats
.
#!r6rs ; -*- mode: scheme; coding: utf-8 -*-
(import (akku format manifest))
(akku-package ("existing-project" "0.0.0-alpha.0")
(synopsis "I did not edit Akku.manifest")
(authors "Guy Q. Schemer")
(license "NOASSERTION")
(depends ("chez-stats" "^0.1.6"))
)
To upgrade the version of a dependency, I run akku update
, edit Akku.manifest
with the new version number, delete Akku.lock
, delete hidden .akku
folder, and run akku install
, which creates a new Akku.lock
file and .akku
folder. Presumably, the intended workflow is instead to remove the package that you are upgrading with akku uninstall pkgname
, akku update
, and akku install pkgname
.
Let's now illustrate how .akku/env
sets the environment to find the installed libraries. If we launch Chez (with scheme
or chez
) from the existing-project
directory, and try to load chez-stats
, we will be out of luck.
> (import (chez-stats))
Exception: library (chez-stats) not found
Calling library-directories
illustrates the problem [4].
> (library-directories)
(("/home/username/scheme/lib"
.
"/home/username/scheme/lib")
("." . "."))
If we load the Akku environment [5] before launcing Chez,
$ .akku/env
$ scheme
then Chez knows where to look for the libraries used in this project.
> (library-directories)
(("/home/username/existing-project/.akku/lib"
.
"/home/username/existing-project/.akku/libobj"))
> (import (chez-stats))
> (mean (random-sample 1e6 'normal))
0.003722857359421433
So far all of the examples assume that you are working from the Terminal, but Akku also provides examples of .chez-geiser
files that allow for integration with Emacs and Geiser. If Geiser is not picking up the .chez-geiser
file, then you might need to update Geiser.
Publishing a package
In preparation for publishing a package, we need to prepare and publish a GnuPG key (if you don't already have one).
$ sudo apt install gnupg
Generate a key and answer the subsequent prompts.
$ gpg --generate-key
Publish your key to a public key server with the following command (where keyid
is replaced with your new public key, a long string of numbers and letters).
$ gpg --keyserver pgp.mit.edu --send-keys keyid
When you tag your repo, it will prompt you for your GnuPG credentials. I'm not sure if the message is necessary, but the first time I tried to tag the repo (on macOS), git automatically opened vi
. Including a message with -m
will spare you from that fate.
$ git tag -s v0.1.0 -m "initial release"
Next you need to push the tagged release.
$ git push --tags
Because I use two-factor authentication for GitHub, I needed to set up a personal access token to use as the password when pushing the tags. Alternatively, you could set up git to authenticate with an ssh key.
The last step is to publish with Akku.
$ akku publish
In my experience, published packages appear in the Akku package list within 24-48 hours after submission.
[1] Chez Scheme, Chibi Scheme, GNU Guile, Gauche Scheme, Ikarus Scheme, IronScheme, Larceny Scheme, Loko Scheme, Mosh Scheme, Racket (plt-r6rs), Sagittarius Scheme, Vicare Scheme, Ypsilon Scheme
[2] To toggle the visibility of files on macOS, use the keyboard shortcut shift+command+period
. On Linux, use control+H
.
[3] You can run the tests for chez-stats
from the Terminal by first running .akku/env
and then scheme .akku/src/chez-stats/tests/test-chez-stats.sps
.
[4] /home/username/scheme/lib
is where I put libraries that I want to make globally available.
[5] If .akku/env
is not loading the environment, try eval $(.akku/env -s)
.