diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 09425a089b..e4ef85a3bb 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -20,155 +20,35 @@ on: # Steps to run for the Workflow jobs: build: - - # Run these steps on Ubuntu runs-on: ubuntu-latest - + container: + image: infinitime/infinitime-build steps: - - ######################################################################################### - # Download and Cache Dependencies - - - name: Install cmake - uses: lukka/get-cmake@v3.18.3 - - - name: Check cache for Embedded Arm Toolchain arm-none-eabi-gcc - id: cache-toolchain - uses: actions/cache@v2 - env: - cache-name: cache-toolchain-9-2020-q2 - with: - path: ${{ runner.temp }}/arm-none-eabi - key: ${{ runner.os }}-build-${{ env.cache-name }} - restore-keys: ${{ runner.os }}-build-${{ env.cache-name }} - - - name: Install Embedded Arm Toolchain arm-none-eabi-gcc - if: steps.cache-toolchain.outputs.cache-hit != 'true' # Install toolchain if not found in cache - uses: fiam/arm-none-eabi-gcc@v1.0.4 - with: - # GNU Embedded Toolchain for Arm release name, in the V-YYYY-qZ format (e.g. "9-2019-q4") - release: 9-2020-q2 - # Directory to unpack GCC to. Defaults to a temporary directory. - directory: ${{ runner.temp }}/arm-none-eabi - - - name: Check cache for nRF5 SDK - id: cache-nrf5sdk - uses: actions/cache@v2 - env: - cache-name: cache-nrf5sdk - with: - path: ${{ runner.temp }}/nrf5_sdk - key: ${{ runner.os }}-build-${{ env.cache-name }} - restore-keys: ${{ runner.os }}-build-${{ env.cache-name }} - - - name: Install nRF5 SDK - if: steps.cache-nrf5sdk.outputs.cache-hit != 'true' # Install SDK if not found in cache - run: | - cd ${{ runner.temp }} - curl https://developer.nordicsemi.com/nRF5_SDK/nRF5_SDK_v15.x.x/nRF5_SDK_15.3.0_59ac345.zip -o nrf5_sdk.zip - unzip nrf5_sdk.zip - mv nRF5_SDK_15.3.0_59ac345 nrf5_sdk - - - name: Check cache for MCUBoot - id: cache-mcuboot - uses: actions/cache@v2 - env: - cache-name: cache-mcuboot - with: - path: ${{ runner.temp }}/mcuboot - key: ${{ runner.os }}-build-${{ env.cache-name }} - restore-keys: ${{ runner.os }}-build-${{ env.cache-name }} - - - name: Install MCUBoot - if: steps.cache-mcuboot.outputs.cache-hit != 'true' # Install MCUBoot if not found in cache - run: | - cd ${{ runner.temp }} - git clone --branch v1.7.2 https://github.com/mcu-tools/mcuboot - - - name: Install imgtool dependencies - run: | - pip3 install --user -r ${{ runner.temp }}/mcuboot/scripts/requirements.txt - - - name: Install adafruit-nrfutil - run: | - pip3 install --user wheel - pip3 install --user setuptools - pip3 install --user adafruit-nrfutil - - - name: Install lv_font_conv - run: - npm i -g lv_font_conv@1.5.2 - - ######################################################################################### - # Checkout - + # This workaround fixes the error "unsafe repository (REPO is owned by someone else)". + # See https://github.com/actions/checkout/issues/760 and https://github.com/actions/checkout/issues/766 + # The fix in "actions/checkout@v2" was not sufficient as the build process also uses git (to get the current + # commit hash, for example). + - name: Workaround permission issues + run: git config --global --add safe.directory "$GITHUB_WORKSPACE" - name: Checkout source files uses: actions/checkout@v2 with: submodules: recursive - - - name: Show files - run: set ; pwd ; ls -l - - ######################################################################################### - # CMake - - - name: CMake - run: | - mkdir -p build - cd build - cmake -G Ninja -DARM_NONE_EABI_TOOLCHAIN_PATH=${{ runner.temp }}/arm-none-eabi -DNRF5_SDK_PATH=${{ runner.temp }}/nrf5_sdk -DUSE_OPENOCD=1 -DBUILD_DFU=1 ../ - - ######################################################################################### - # Make and Upload DFU Package - # pinetime-mcuboot-app.img must be flashed at address 0x8000 in the internal flash memory with OpenOCD: - # program image.bin 0x8000 - - # For Debugging Builds: Remove "make" option "-j" for clearer output. Add "--trace" to see details. - # For Faster Builds: Add "make" option "-j" - - - name: Make pinetime-mcuboot-app - run: | - cmake --build build --target pinetime-mcuboot-app - - - name: Unzip DFU package - run: | - # Unzip the package because Upload Artifact will zip up the files - unzip build/src/pinetime-mcuboot-app-dfu*.zip -d build/src/pinetime-mcuboot-app-dfu - - - name: Upload DFU package + - name: Build + shell: bash + env: + SOURCES_DIR: . + run: | + /opt/build.sh all + - name: Upload DFU artifacts uses: actions/upload-artifact@v2 with: - name: pinetime-mcuboot-app-dfu - path: build/src/pinetime-mcuboot-app-dfu/* - - ######################################################################################### - # Make and Upload Standalone Firmware - - - name: Make pinetime-app - run: | - cmake --build build --target pinetime-app - - - name: Upload standalone firmware + name: InfiniTime DFU file + path: | + ./build/output/pinetime-mcuboot-app-dfu-*.zip + - name: Upload MCUBoot image artifacts uses: actions/upload-artifact@v2 with: - name: pinetime-app.out - path: build/src/pinetime-app*.out - - ######################################################################################### - # Make but don't Upload the Recovery Firmware to be sure it builds correctly - - - name: Make pinetime-recovery - run: | - cmake --build build --target pinetime-recovery - - ######################################################################################### - # Finish - - - name: Find output - run: | - find . -name "pinetime-app.*" -ls - find . -name "pinetime-mcuboot-app.*" -ls - -# Embedded Arm Toolchain and nRF5 SDK will only be cached if the build succeeds. -# So make sure that the first build always succeeds, e.g. comment out the "Make" step. + name: InfiniTime MCUBoot image file + path: | + ./build/output/pinetime-mcuboot-app-image-*.bin diff --git a/doc/buildWithDocker.md b/doc/buildWithDocker.md index a57893c94c..1bea838025 100644 --- a/doc/buildWithDocker.md +++ b/doc/buildWithDocker.md @@ -1,62 +1,58 @@ # Build the project using Docker -A [Docker image (Dockerfile)](../docker) containing all the build environment is available for X86_64 and AMD64 architectures. These images make the build of the firmware and the generation of the DFU file for OTA quite easy, as well as preventing clashes with any other toolchains or development environments you may have installed. +A [Docker image (Dockerfile)](../docker) containing all the build environment is available for X86_64 and AMD64 architectures. +These images make the build of the firmware and the generation of the DFU file for OTA quite easy, as well as preventing clashes with any other toolchains or development environments you may have installed. -Based on Ubuntu 18.04 with the following build dependencies: +Based on Ubuntu 22.04 with the following build dependencies: * ARM GCC Toolchain * nRF SDK * MCUBoot * adafruit-nrfutil +* lv_font_conv ## Run a container to build the project -The `infinitime-build` image contains all the dependencies you need. The default `CMD` will compile sources found in `/sources`, so you need only mount your code. +The `infinitime-build` image contains all the dependencies you need. +The default `CMD` will compile sources found in `/sources`, so you need only mount your code. Before continuing, make sure you first build the image as indicated in the [Build the image](#build-the-image) section, or check the [Using the image from Docker Hub](#using-the-image-from-docker-hub) section if you prefer to use a pre-made image. -This example will build the firmware, generate the MCUBoot image and generate the DFU file. For cloning the repo, see [these instructions](../doc/buildAndProgram.md#clone-the-repo). Outputs will be written to **/build/output**: +This example will build the firmware, generate the MCUBoot image and generate the DFU file. +For cloning the repo, see [these instructions](../doc/buildAndProgram.md#clone-the-repo). Outputs will be written to **/build/output**: ```bash cd # e.g. cd ./work/Pinetime -docker run --rm -it -v $(pwd):/sources infinitime-build +docker run --rm -it -v ${PWD}:/sources --user $(id -u):$(id -g) infinitime-build ``` -If you only want to build a single CMake target, you can pass it in as the first parameter to the build script. This means calling the script explicitly as it will override the `CMD`. Here's an example For `pinetime-app`: +By default, the container runs as `root`, which is not convenient as all the files generated by the build will also belong to `root`. +The parameter `--user` overrides that default behavior. +The command above will run as your current user. -```bash -docker run --rm -it -v $(pwd):/sources infinitime-build /opt/build.sh pinetime-app -``` - -The image is built using 1000:1000 for the user id and group id. If this is different to your user or group ids (run `id -u` and `id -g` to find out what your id values are if you are unsure), you will need to override them via the `--user` parameter in order to prevent permission errors with the output files (and the cmake build cache). - -Running with this image is the same as above, you just specify the ids to `docker run`: +If you only want to build a single CMake target, you can pass it in as the first parameter to the build script. +This means calling the script explicitly as it will override the `CMD`. +Here's an example for `pinetime-app`: ```bash -docker run --rm -it -v $(pwd):/sources --user $(id -u):$(id -g) infinitime-build -``` - -Or you can specify your user id and group id (by number, not by name) directly: - -```bash -docker run --rm -it -v $(pwd):/sources --user 1234:1234 infinitime-build +docker run --rm -it -v ${PWD}:/sources --user $(id -u):$(id -g) infinitime-build /opt/build.sh pinetime-app ``` ## Using the image from Docker Hub -The image is available via Docker Hub for both the amd64 and arm64v8 architectures at [pfeerick/infinitime-build](https://hub.docker.com/r/pfeerick/infinitime-build). +The image is available via Docker Hub for both the amd64 and arm64v8 architectures at [infinitime/infinitime-build](https://hub.docker.com/repository/docker/infinitime/infinitime-build). -It can be pulled (downloaded) using the following command: +You can run it using the following command: ```bash -docker pull pfeerick/infinitime-build +docker run --rm -it -v ${PWD}:/sources --user $(id -u):$(id -g) infinitime/infinitime-build ``` The default `latest` tag *should* automatically identify the correct image architecture, but if for some reason Docker does not, you can specify it manually: -* For AMD64 (x86_64) systems: `docker pull pfeerick/infinitime-build:amd64` +* For AMD64 (x86_64) systems: `docker pull --platform linux/amd64 infinitime/infinitime-build` -* For ARM64v8 (ARM64/aarch64) systems: `docker pull pfeerick/infinitime-build:arm64v8` +* For ARM64v8 (ARM64/aarch64) systems: `docker pull --platform linux/arm64 infinitime/infinitime-build` ## Build the image @@ -65,11 +61,5 @@ You can build the image yourself if you like! The following commands must be run from the root of the project. This operation will take some time but, when done, a new image named *infinitime-build* is available. ```bash -docker image build -t infinitime-build ./docker -``` - -The `PUID` and `PGID` build arguments are used to set the user and group ids used in the container, meaning you will not need to specify it later unless they change for some reason. Specifying them is not mandatory, as this can be over-ridden at build time via the `--user` flag, but doing so will make the command you need to run later a bit shorter. In the below examples, they are set to your current user id and group id automatically. You can specify them manually, but they must be specified by number, not by name. - -```bash -docker image build -t infinitime-build --build-arg PUID=$(id -u) --build-arg PGID=$(id -g) ./docker -``` +docker build -t infinitime-build ./docker +``` \ No newline at end of file diff --git a/docker/Dockerfile b/docker/Dockerfile index 10bed55f64..f2d187d048 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -44,10 +44,5 @@ RUN bash -c "source /opt/build.sh; GetNrfSdk;" # McuBoot RUN bash -c "source /opt/build.sh; GetMcuBoot;" -ARG PUID=1000 -ARG PGID=1000 -RUN groupadd --system --gid $PGID infinitime && useradd --system --uid $PUID --gid $PGID infinitime - -USER infinitime:infinitime ENV SOURCES_DIR /sources CMD ["/opt/build.sh"] diff --git a/docker/build.sh b/docker/build.sh index d86e7c21d6..878d9ec619 100755 --- a/docker/build.sh +++ b/docker/build.sh @@ -9,7 +9,7 @@ set -e export TOOLS_DIR="${TOOLS_DIR:=/opt}" export SOURCES_DIR="${SOURCES_DIR:=/sources}" export BUILD_DIR="${BUILD_DIR:=$SOURCES_DIR/build}" -export OUTPUT_DIR="${OUTPUT_DIR:=$BUILD_DIR/output}" +export OUTPUT_DIR="${OUTPUT_DIR:=$SOURCES_DIR/build/output}" export BUILD_TYPE=${BUILD_TYPE:=Release} export GCC_ARM_VER=${GCC_ARM_VER:="gcc-arm-none-eabi-9-2020-q2-update"} @@ -22,7 +22,7 @@ main() { local target="$1" mkdir -p "$TOOLS_DIR" - + [[ ! -d "$TOOLS_DIR/$GCC_ARM_VER" ]] && GetGcc [[ ! -d "$TOOLS_DIR/$NRF_SDK_VER" ]] && GetNrfSdk [[ ! -d "$TOOLS_DIR/mcuboot" ]] && GetMcuBoot @@ -31,7 +31,7 @@ main() { CmakeGenerate CmakeBuild $target - BUILD_RESULT=$? + BUILD_RESULT=$? if [ "$DISABLE_POSTBUILD" != "true" -a "$BUILD_RESULT" == 0 ]; then source "$BUILD_DIR/post_build.sh" fi @@ -54,18 +54,14 @@ GetNrfSdk() { } CmakeGenerate() { - # We can swap the CD and trailing SOURCES_DIR for -B and -S respectively - # once we go to newer CMake (Ubuntu 18.10 gives us CMake 3.10) - cd "$BUILD_DIR" - cmake -G "Unix Makefiles" \ + -S "$SOURCES_DIR" \ + -B "$BUILD_DIR" \ -DCMAKE_BUILD_TYPE=$BUILD_TYPE \ -DUSE_OPENOCD=1 \ -DARM_NONE_EABI_TOOLCHAIN_PATH="$TOOLS_DIR/$GCC_ARM_VER" \ -DNRF5_SDK_PATH="$TOOLS_DIR/$NRF_SDK_VER" \ - -DBUILD_DFU=1 \ - "$SOURCES_DIR" - cmake -L -N . + -DBUILD_DFU=1 } CmakeBuild() { diff --git a/docker/post_build.sh.in b/docker/post_build.sh.in index db6e7a94d0..8c94471a38 100755 --- a/docker/post_build.sh.in +++ b/docker/post_build.sh.in @@ -15,12 +15,10 @@ cp "$BUILD_DIR/src/pinetime-mcuboot-app-dfu-$PROJECT_VERSION.zip" "$OUTPUT_DIR/p cp "$BUILD_DIR/src/pinetime-mcuboot-recovery-loader-image-$PROJECT_VERSION.bin" "$OUTPUT_DIR/pinetime-mcuboot-recovery-loader-image-$PROJECT_VERSION.bin" cp "$BUILD_DIR/src/pinetime-mcuboot-recovery-loader-dfu-$PROJECT_VERSION.zip" "$OUTPUT_DIR/pinetime-mcuboot-recovery-loader-dfu-$PROJECT_VERSION.zip" - mkdir -p "$OUTPUT_DIR/src" -cd "$BUILD_DIR" -cp src/*.bin "$OUTPUT_DIR/src" -cp src/*.hex "$OUTPUT_DIR/src" -cp src/*.out "$OUTPUT_DIR/src" -cp src/*.map "$OUTPUT_DIR/src" +cp $BUILD_DIR/src/*.bin "$OUTPUT_DIR/src/" +cp $BUILD_DIR/src/*.hex "$OUTPUT_DIR/src/" +cp $BUILD_DIR/src/*.out "$OUTPUT_DIR/src/" +cp $BUILD_DIR/src/*.map "$OUTPUT_DIR/src/" ls -RUv1 "$OUTPUT_DIR" | sed 's;^\([^/]\); \1;g' \ No newline at end of file