Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add local Docker/Podman build option #6

Open
wants to merge 4 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 25 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
FROM docker.io/zmkfirmware/zmk-build-arm:stable

RUN apt-get update \
&& apt-get install -y wget \
&& wget https://github.com/mikefarah/yq/releases/latest/download/yq_linux_amd64 -O /usr/bin/yq \
&& chmod +x /usr/bin/yq

ARG USER_ID=1000

RUN adduser --disabled-password --gecos '' --uid ${USER_ID} zmk

USER zmk

WORKDIR /app

COPY config/west.yml config/west.yml

RUN mkdir -p build \
&& west init -l config \
&& west update \
&& west zephyr-export

COPY bin/build.sh ./

CMD ["./build.sh"]
22 changes: 22 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
DOCKER := $(shell { command -v podman || command -v docker; })
calebdw marked this conversation as resolved.
Show resolved Hide resolved

.PHONY: all clean distclean

all:
$(DOCKER) build --tag zmk-build-user-config --build-arg USER_ID=$(shell id -u) .
$(DOCKER) volume create zmk_build
$(DOCKER) run --rm -it --name zmk-build-user-config -u zmk \
-v zmk_build:/app/build \
-v $(PWD)/build.yaml:/app/build.yaml:ro \
-v $(PWD)/config:/app/config:ro \
-v $(PWD)/firmware:/app/firmware \
calebdw marked this conversation as resolved.
Show resolved Hide resolved
-e OUTPUT_ZMK_CONFIG=$(OUTPUT_ZMK_CONFIG) \
zmk-build-user-config

clean:
rm -rf firmware/[^.]*
-$(DOCKER) volume rm zmk_build

distclean: clean
-$(DOCKER) image rm zmk-build-user-config
-$(DOCKER) system prune
66 changes: 66 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
# Unified ZMK Config

## Modifying the keymap

[The ZMK documentation](https://zmk.dev/docs) covers both basic and advanced functionality and has a table of OS compatibility for keycodes.

## Building the Firmware with GitHub Actions

### Setup

1. Fork this repo.
2. Enable GitHub Actions on your fork.

### Build firmware

1. Push a commit to trigger the build.
2. Download the artifact.

## Building the Firmware in a local container

### Setup

#### Software

* Either Podman or Docker is required, Podman is preferred if both are present.
* `make` is also required

#### Windows specific

* If compiling on Windows use WSL2 and Docker [Docker Setup Guide](https://docs.docker.com/desktop/windows/wsl/).
* Install `make` using
```bash
sudo apt-get install make
```.
* The repository can be cloned directly into the WSL2 instance or accessed through the C: mount point WSL provides by default (`/mnt/c/path-to-repo`).

### Build firmware

1. Execute `make`.
2. Check the `firmware` directory for the latest firmware build.

#### Output ZMK Configs
Sometimes it can be useful to output the full ZMK configs for a build. This can be achieved by executing the following:
```bash
OUTPUT_ZMK_CONFIG=1 make
```

The configs with then be outputted to the `firmware` directory along with the firmware files.

#### Build Cache
A docker volume is used to cache the build artifacts, allowing subsequent builds to compile faster.

### Cleanup

#### Partial Cleanup
The compiled firmware files and docker volume build cache can be deleted with `make clean`. This might be necessary if you want a pristine build or to cleanup the `firmware` directory.

### Full Cleanup

The built docker container can be deleted with `make distclean`. This might be necessary if you want to rebuild the docker container or update the ZMK version used to compile your firmware.

Of course, you can also use regular Docker commands to manage the image/build cache.

## Flashing firmware

Follow the ZMK instructions on [Flashing UF2 Files](https://zmk.dev/docs/user-setup#flashing-uf2-files) to flash the firmware.
47 changes: 47 additions & 0 deletions bin/build.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
#!/usr/bin/env bash

config_dir="${PWD}/config"
timestamp=$(date -u +"%Y%m%d%H%M%S")

while IFS=$',' read -r board shield; do
extra_cmake_args=${shield:+-DSHIELD="$shield"}
artifact_name=${shield:+${shield// /-}-}${board}-zmk
filename="${PWD}/firmware/${timestamp}-${artifact_name}"
build_dir="${PWD}/build/${artifact_name}"

echo ""
echo "-----------------"
echo "BUILDING FIRMWARE"
echo "-----------------"
echo "Zephyr: ${ZEPHYR_VERSION}"
echo "Board: ${board}"
echo "Shield: ${shield}"
echo ""

if [[ ! -d "$build_dir" ]]; then
west build -s zmk/app -b "$board" -d ${build_dir} -- \
-DZMK_CONFIG="$config_dir" "${extra_cmake_args}"
else
west build -d ${build_dir} -- -DZMK_CONFIG="$config_dir"
fi

if [[ ! -z $OUTPUT_ZMK_CONFIG ]]; then
grep -v -e "^#" -e "^$" ${build_dir}/zephyr/.config \
| sort > "${filename}.config"
fi

extensions="uf2 hex bin"
for extension in $extensions; do
artifact=${build_dir}/zephyr/zmk.$extension
if [[ -f $artifact ]]; then
cp $artifact "${filename}.$extension"
break
fi
done
done < <(yq '
[{"board": .board[], "shield": .shield[] // ""}] + .include
| filter(.board)
| unique_by(.board + .shield).[]
| [.board, .shield // ""]
| @csv
' build.yaml)
2 changes: 2 additions & 0 deletions firmware/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
*
!.gitignore