diff --git a/.gitignore b/.gitignore index c895ca2..f504bdf 100644 --- a/.gitignore +++ b/.gitignore @@ -126,3 +126,4 @@ kmk/release_info.py kmk/release_info.mpy *.mpy .vscode +.dist diff --git a/Dockerfile b/Dockerfile index 80d094f..19ea82d 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,20 +1,39 @@ -FROM python:3.7-alpine +FROM python:3.9-slim-buster -RUN mkdir -p /app +ARG KMKPY_REF +ARG KMKPY_URL + +ENV KMKPY_REF ${KMKPY_REF} +ENV KMKPY_URL ${KMKPY_URL} + +RUN mkdir -p /app /dist WORKDIR /app -RUN apk update && apk add alpine-sdk coreutils curl gettext git git-lfs openssh rsync wget zip - +RUN apt-get update && apt-get install -y build-essential curl gettext git git-lfs rsync wget zip lbzip2 RUN pip install pipenv -### Get a local copy of CircuitPython and its dependencies -# Our absolute baseline is 4.0.0, which (as of writing) shares MPY compat -# with all future versions. Our baseline will need to update as MPY compat -# changes -RUN git clone --branch 4.0.0 --depth 1 https://github.com/adafruit/CircuitPython /opt/circuitpython -RUN git -C /opt/circuitpython submodule update --init +# Pull CircuitPython-designated ARM GCC to avoid mismatches/weird +# inconsistencies with upstream +RUN curl -L -o /tmp/gcc-arm.tar.bz2 https://adafruit-circuit-python.s3.amazonaws.com/gcc-arm-none-eabi-9-2019-q4-major-x86_64-linux.tar.bz2 && \ + tar -C /usr --strip-components=1 -xaf /tmp/gcc-arm.tar.bz2 && \ + rm -rf /tmp/gcc-arm.tar.bz2 -### Build the MPY compiler -RUN make -C /opt/circuitpython/mpy-cross +# Get a local copy of KMKPython and its dependencies. We don't provide MPY +# builds for kmkpython anymore, so we can get away with being opinionated +# here. +RUN git init /opt/kmkpython && \ + git -C /opt/kmkpython remote add origin ${KMKPY_URL} && \ + git -C /opt/kmkpython fetch --depth 1 origin ${KMKPY_REF} && \ + git -C /opt/kmkpython checkout FETCH_HEAD && \ + git -C /opt/kmkpython submodule update --init --recursive -ENV PATH=/opt/circuitpython/mpy-cross:${PATH} +# Build the MPY compiler +RUN make -C /opt/kmkpython/mpy-cross + +ENV PATH=/opt/kmkpython/mpy-cross:${PATH} + +RUN mkdir -p /opt/kmkpython/frozen/kmk/kmk +COPY ./build_kmkpython_release.sh /app/ +COPY ./kmk /opt/kmkpython/frozen/kmk/kmk + +CMD /app/build_kmkpython_release.sh diff --git a/Makefile b/Makefile index efe4ad4..eca9f1e 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,10 @@ .SILENT: .PHONY: \ + clean-dist \ devdeps \ + dist \ + dockerbase \ lint .DEFAULT: all @@ -23,6 +26,8 @@ MPY_TARGET_DIR ?= .compiled PY_KMK_TREE = $(shell find $(MPY_SOURCES) -name "*.py") DIST_DESCRIBE = $(shell $(DIST_DESCRIBE_CMD)) +TIMESTAMP := $(shell date +%s) + all: copy-kmk copy-bootpy copy-keymap copy-board compile: $(MPY_TARGET_DIR)/.mpy.compiled @@ -39,49 +44,6 @@ endif @rm -rf $(MPY_SOURCES)/release_info.py @touch $(MPY_TARGET_DIR)/.mpy.compiled -dist: dist/kmk-latest.zip dist/kmk-latest.unoptimized.zip dist/$(DIST_DESCRIBE).zip dist/$(DIST_DESCRIBE).unoptimized.zip - -dist-deploy: devdeps dist - @echo "===> Uploading artifacts to https://cdn.kmkfw.io/" - @$(PIPENV) run s3cmd -c .s3cfg put -P dist/kmk-$(DIST_DESCRIBE).zip dist/kmk-$(DIST_DESCRIBE).unoptimized.zip s3://kmk-releases/ >/dev/null - @[[ "$${CIRCLE_BRANCH}" == "master" ]] && echo "====> Uploading artifacts as 'latest' to https://cdn.kmkfw.io/" || true - @[[ "$${CIRCLE_BRANCH}" == "master" ]] && $(PIPENV) run s3cmd -c .s3cfg put -P dist/kmk-latest.zip dist/kmk-latest.unoptimized.zip s3://kmk-releases/ >/dev/null || true - @[[ -n "$${CIRCLE_TAG}" ]] && echo "====> Uploading artifacts as '$${CIRCLE_TAG}' to https://cdn.kmkfw.io/" || true - @[[ -n "$${CIRCLE_TAG}" ]] && $(PIPENV) run s3cmd -c .s3cfg put -P dist/kmk-latest.zip s3://kmk-releases/$${CIRCLE_TAG}.zip >/dev/null || true - @[[ -n "$${CIRCLE_TAG}" ]] && $(PIPENV) run s3cmd -c .s3cfg put -P dist/kmk-latest.unoptimized.zip s3://kmk-releases/$${CIRCLE_TAG}.unoptimized.zip >/dev/null || true - -dist/kmk-latest.zip: compile boot.py - @echo "===> Building optimized ZIP" - @mkdir -p dist - @cd $(MPY_TARGET_DIR) && zip -r ../dist/kmk-latest.zip kmk 2>&1 >/dev/null - @zip -r dist/kmk-latest.zip boot.py 2>&1 >/dev/null - -dist/$(DIST_DESCRIBE).zip: dist/kmk-latest.zip - @echo "===> Aliasing optimized ZIP" - @cp dist/kmk-latest.zip dist/kmk-$(DIST_DESCRIBE).zip - -dist/kmk-latest.unoptimized.zip: $(PY_KMK_TREE) boot.py - @echo "===> Building unoptimized ZIP" - @mkdir -p dist - @echo "KMK_RELEASE = '$(DIST_DESCRIBE)'" > kmk/release_info.py - @zip -r dist/kmk-latest.unoptimized.zip kmk boot.py 2>&1 >/dev/null - @rm -rf kmk/release_info.py - -dist/$(DIST_DESCRIBE).unoptimized.zip: dist/kmk-latest.unoptimized.zip - @echo "===> Aliasing unoptimized ZIP" - @cp dist/kmk-latest.unoptimized.zip dist/kmk-$(DIST_DESCRIBE).unoptimized.zip - -.docker_base: Dockerfile - @echo "===> Building Docker base image kmkfw/base:${DOCKER_BASE_TAG}" - @docker build -t kmkfw/base:${DOCKER_BASE_TAG} . - @touch .docker_base - -docker-base: .docker_base - -docker-base-deploy: docker-base - @echo "===> Pushing Docker base image kmkfw/base:${DOCKER_BASE_TAG} to Docker Hub" - @docker push kmkfw/base:${DOCKER_BASE_TAG} - .devdeps: Pipfile.lock @echo "===> Installing dependencies with pipenv" @$(PIPENV) sync --dev @@ -89,6 +51,16 @@ docker-base-deploy: docker-base devdeps: .devdeps +dist: clean-dist dockerbase + @mkdir -p .dist + @docker run --rm -it -v $$(pwd)/.dist:/dist kmkpy:$(TIMESTAMP) + +dockerbase: + docker build . \ + -t kmkpy:$(TIMESTAMP) \ + --build-arg KMKPY_URL=$$(cut -f1 < kmkpython_ref.tsv) \ + --build-arg KMKPY_REF=$$(cut -f2 < kmkpython_ref.tsv) + lint: devdeps @$(PIPENV) run flake8 @@ -98,10 +70,14 @@ fix-formatting: devdeps fix-isort: devdeps @find kmk/ user_keymaps/ boards/ -name "*.py" | xargs $(PIPENV) run isort -clean: +clean: clean-dist @echo "===> Cleaning build artifacts" @rm -rf .devdeps build dist $(MPY_TARGET_DIR) +clean-dist: + @echo "===> Cleaning KMKPython dists" + @rm -rf .dist + # This is mostly a leftover from the days we vendored stuff from # micropython-lib via submodules. Leaving this here mostly in case someone goes # exploring through the history of KMK's repo and manages to screw up their @@ -173,5 +149,4 @@ ifdef BOARD copy-board: $(MOUNTPOINT)/kb.py endif # BOARD - endif # MOUNTPOINT diff --git a/build_kmkpython_release.sh b/build_kmkpython_release.sh new file mode 100755 index 0000000..307da24 --- /dev/null +++ b/build_kmkpython_release.sh @@ -0,0 +1,10 @@ +#!/bin/sh + +TIMESTAMP=$(date +%s) +TARGETS=${TARGETS:-"nice_nano itsybitsy_nrf52840_express"} + +for TARGET in ${TARGETS}; do + make -C /opt/kmkpython/ports/nrf BOARD="${TARGET}" + cp "/opt/kmkpython/ports/nrf/build-${TARGET}/firmware.uf2" "/dist/${TARGET}-${TIMESTAMP}.uf2" + echo "===> Built /dist/${TARGET}-${TIMESTAMP}.uf2" +done diff --git a/kmkpython_ref.tsv b/kmkpython_ref.tsv new file mode 100644 index 0000000..9fb27e7 --- /dev/null +++ b/kmkpython_ref.tsv @@ -0,0 +1 @@ +https://github.com/kmkfw/kmkpython b55fe4abc344bf1f509e8ef036d2a4cf13d6be63