From 8c4f8343895199bb67f77f5fc17f39498c32f0af Mon Sep 17 00:00:00 2001 From: Caleb White Date: Tue, 3 Oct 2023 09:20:57 -0500 Subject: [PATCH 1/4] Add local Docker build option --- Dockerfile | 24 ++++++++++++++++++++++++ Makefile | 21 +++++++++++++++++++++ bin/build.sh | 40 ++++++++++++++++++++++++++++++++++++++++ firmware/.gitignore | 2 ++ 4 files changed, 87 insertions(+) create mode 100644 Dockerfile create mode 100644 Makefile create mode 100755 bin/build.sh create mode 100644 firmware/.gitignore diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..e4d48b6 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,24 @@ +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 west init -l config \ + && west update \ + && west zephyr-export + +COPY bin/build.sh ./ + +CMD ["./build.sh"] diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..5dba756 --- /dev/null +++ b/Makefile @@ -0,0 +1,21 @@ +DOCKER := $(shell { command -v podman || command -v docker; }) + +.PHONY: all clean distclean + +all: + $(DOCKER) build --tag zmk --build-arg USER_ID=$(shell id -u) . + $(DOCKER) volume create build + $(DOCKER) run --rm -it --name zmk \ + -v build:/app \ + -v $(PWD)/build.yaml:/app/build.yaml:ro \ + -v $(PWD)/config:/app/config:ro \ + -v $(PWD)/firmware:/app/firmware \ + -e OUTPUT_ZMK_CONFIG=$(OUTPUT_ZMK_CONFIG) \ + zmk + +clean: + rm -rf firmware/[^.]* + -$(DOCKER) volume rm build config firmware + +distclean: clean + -$(DOCKER) image rm zmk diff --git a/bin/build.sh b/bin/build.sh new file mode 100755 index 0000000..fb0bc9c --- /dev/null +++ b/bin/build.sh @@ -0,0 +1,40 @@ +#!/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="firmware/${timestamp}-${artifact_name}" + build_dir="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 + + cp ${build_dir}/zephyr/zmk.uf2 "${filename}.uf2" +done < <(yq ' + [{"board": .board[], "shield": .shield[] // ""}] + .include + | filter(.board) + | unique_by(.board + .shield).[] + | [.board, .shield // ""] + | @csv +' build.yaml) diff --git a/firmware/.gitignore b/firmware/.gitignore new file mode 100644 index 0000000..d6b7ef3 --- /dev/null +++ b/firmware/.gitignore @@ -0,0 +1,2 @@ +* +!.gitignore From 1579e50aefacc624dcf6f5c1e28139498b10e657 Mon Sep 17 00:00:00 2001 From: Caleb White Date: Tue, 3 Oct 2023 13:00:11 -0500 Subject: [PATCH 2/4] Add README --- README.md | 64 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 64 insertions(+) create mode 100644 README.md diff --git a/README.md b/README.md new file mode 100644 index 0000000..7ea28d3 --- /dev/null +++ b/README.md @@ -0,0 +1,64 @@ +# 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, this allows 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. + +## Flashing firmware + +Follow the ZMK instructions on [Flashing UF2 Files](https://zmk.dev/docs/user-setup#flashing-uf2-files) to flash the firmware. From e63586b8246d4ae4ecaebed9da79de4ce937ce3e Mon Sep 17 00:00:00 2001 From: Caleb White Date: Tue, 3 Oct 2023 14:38:41 -0500 Subject: [PATCH 3/4] Update docker image tag --- Makefile | 13 +++++++------ README.md | 2 ++ 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/Makefile b/Makefile index 5dba756..98a861f 100644 --- a/Makefile +++ b/Makefile @@ -3,19 +3,20 @@ DOCKER := $(shell { command -v podman || command -v docker; }) .PHONY: all clean distclean all: - $(DOCKER) build --tag zmk --build-arg USER_ID=$(shell id -u) . - $(DOCKER) volume create build - $(DOCKER) run --rm -it --name zmk \ - -v build:/app \ + $(DOCKER) zmk_build --tag zmk-config --build-arg USER_ID=$(shell id -u) . + $(DOCKER) volume create zmk_app + $(DOCKER) run --rm -it --name zmk-config -u zmk \ + -v zmk_app:/app \ -v $(PWD)/build.yaml:/app/build.yaml:ro \ -v $(PWD)/config:/app/config:ro \ -v $(PWD)/firmware:/app/firmware \ -e OUTPUT_ZMK_CONFIG=$(OUTPUT_ZMK_CONFIG) \ - zmk + zmk-config clean: rm -rf firmware/[^.]* -$(DOCKER) volume rm build config firmware + -$(DOCKER) volume rm zmk_app distclean: clean - -$(DOCKER) image rm zmk + -$(DOCKER) image rm zmk-config diff --git a/README.md b/README.md index 7ea28d3..aa3dec3 100644 --- a/README.md +++ b/README.md @@ -59,6 +59,8 @@ The compiled firmware files and docker volume build cache can be deleted with `m 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. From b736bdfe169f76591f627867e83fd3dc9ea73d43 Mon Sep 17 00:00:00 2001 From: Caleb White Date: Tue, 3 Oct 2023 15:32:35 -0500 Subject: [PATCH 4/4] Update build files --- Dockerfile | 3 ++- Makefile | 16 ++++++++-------- README.md | 2 +- bin/build.sh | 13 ++++++++++--- 4 files changed, 21 insertions(+), 13 deletions(-) diff --git a/Dockerfile b/Dockerfile index e4d48b6..be781d0 100644 --- a/Dockerfile +++ b/Dockerfile @@ -15,7 +15,8 @@ WORKDIR /app COPY config/west.yml config/west.yml -RUN west init -l config \ +RUN mkdir -p build \ + && west init -l config \ && west update \ && west zephyr-export diff --git a/Makefile b/Makefile index 98a861f..0cd3c26 100644 --- a/Makefile +++ b/Makefile @@ -3,20 +3,20 @@ DOCKER := $(shell { command -v podman || command -v docker; }) .PHONY: all clean distclean all: - $(DOCKER) zmk_build --tag zmk-config --build-arg USER_ID=$(shell id -u) . - $(DOCKER) volume create zmk_app - $(DOCKER) run --rm -it --name zmk-config -u zmk \ - -v zmk_app:/app \ + $(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 \ -e OUTPUT_ZMK_CONFIG=$(OUTPUT_ZMK_CONFIG) \ - zmk-config + zmk-build-user-config clean: rm -rf firmware/[^.]* - -$(DOCKER) volume rm build config firmware - -$(DOCKER) volume rm zmk_app + -$(DOCKER) volume rm zmk_build distclean: clean - -$(DOCKER) image rm zmk-config + -$(DOCKER) image rm zmk-build-user-config + -$(DOCKER) system prune diff --git a/README.md b/README.md index aa3dec3..084f7c9 100644 --- a/README.md +++ b/README.md @@ -48,7 +48,7 @@ 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, this allows subsequent builds to compile faster. +A docker volume is used to cache the build artifacts, allowing subsequent builds to compile faster. ### Cleanup diff --git a/bin/build.sh b/bin/build.sh index fb0bc9c..7814dd4 100755 --- a/bin/build.sh +++ b/bin/build.sh @@ -6,8 +6,8 @@ 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="firmware/${timestamp}-${artifact_name}" - build_dir="build/${artifact_name}" + filename="${PWD}/firmware/${timestamp}-${artifact_name}" + build_dir="${PWD}/build/${artifact_name}" echo "" echo "-----------------" @@ -30,7 +30,14 @@ while IFS=$',' read -r board shield; do | sort > "${filename}.config" fi - cp ${build_dir}/zephyr/zmk.uf2 "${filename}.uf2" + 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)