├── dev-notes.md ├── codespaces ├── README.md ├── Dockerfile └── library-scripts │ └── common-debian.sh ├── .gitignore ├── .devcontainer └── devcontainer.json ├── requirements.txt ├── LICENSE ├── Dockerfile ├── .github └── workflows │ ├── release.yml │ └── deploy-test.yml └── README.md /dev-notes.md: -------------------------------------------------------------------------------- 1 | # Developer docs 2 | 3 | ## Publish image 4 | 5 | ``` 6 | docker login ghcr.io -u 7 | docker images 8 | docker tag IMAGE_ID ghcr.io/carlosperate/microbit-toolchain:VERSION 9 | docker push ghcr.io/carlosperate/microbit-toolchain:VERSION 10 | ``` 11 | -------------------------------------------------------------------------------- /codespaces/README.md: -------------------------------------------------------------------------------- 1 | # Codespaces image 2 | 3 | - Template based on 4 | https://github.com/microsoft/vscode-dev-containers/tree/v0.146.0/container-templates 5 | - common-debian.sh: 6 | https://github.com/microsoft/vscode-dev-containers/blob/v0.146.0/script-library/common-debian.sh 7 | 8 | 9 | ### Publish image 10 | 11 | ``` 12 | docker login ghcr.io -u 13 | docker images 14 | docker tag IMAGE_ID ghcr.io/OWNER/IMAGE_NAME:VERSION 15 | docker push ghcr.io/OWNER/IMAGE_NAME:VERSION 16 | ``` 17 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ########### 2 | # Project # 3 | ########### 4 | # Nothing yet 5 | 6 | ###################### 7 | # OS generated files # 8 | ###################### 9 | # macoOS 10 | .DS_Store 11 | .DS_Store? 12 | .AppleDouble 13 | .LSOverride 14 | ._* 15 | .Spotlight-V100 16 | .Trashes 17 | Icon? 18 | 19 | # Windows 20 | Thumbs.db 21 | ehthumbs.db 22 | ehthumbs_vista.db 23 | *.stackdump 24 | [Dd]esktop.ini 25 | $RECYCLE.BIN/ 26 | *.lnk 27 | 28 | # Linux 29 | *~ 30 | .fuse_hidden* 31 | .directory 32 | .Trash-* 33 | .nfs* 34 | -------------------------------------------------------------------------------- /.devcontainer/devcontainer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Dev Container for micro:bit", 3 | "image": "ghcr.io/carlosperate/devcontainer-microbit:latest", 4 | 5 | // Set *default* container specific settings.json values on container create. 6 | "settings": { 7 | "terminal.integrated.shell.linux": "/usr/bin/zsh" 8 | }, 9 | 10 | // Add the IDs of extensions you want installed when the container is created. 11 | "extensions": [ 12 | "ms-vscode.cpptools", 13 | "ms-vscode.cmake-tools", 14 | "marus25.cortex-debug", 15 | ], 16 | 17 | // Use 'forwardPorts' to make a list of ports inside the container available locally. 18 | // "forwardPorts": [], 19 | 20 | // Use 'postCreateCommand' to run commands after the container is created. 21 | // "postCreateCommand": "uname -a", 22 | 23 | // Uncomment when using a ptrace-based debugger like C++, Go, and Rust 24 | // "runArgs": [ "--cap-add=SYS_PTRACE", "--security-opt", "seccomp=unconfined" ], 25 | 26 | // Uncomment to connect as a non-root user. See https://aka.ms/vscode-remote/containers/non-root. 27 | "remoteUser": "vscode" 28 | } 29 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | appdirs==1.4.4 2 | argcomplete==1.12.2 3 | certifi==2020.12.5 4 | cffi==1.14.5 5 | chardet==4.0.0 6 | cmake==3.18.4.post1 7 | cmsis-pack-manager==0.2.10 8 | colorama==0.3.9 9 | cryptography==2.9.2 10 | Deprecated==1.2.11 11 | future==0.18.2 12 | hgapi==1.7.4 13 | idna==2.10 14 | importlib-metadata==3.7.0 15 | intelhex==2.3.0 16 | intervaltree==3.1.0 17 | Jinja2==2.11.3 18 | jsonpointer==1.14 19 | jsonschema==2.6.0 20 | MarkupSafe==1.1.1 21 | mbed-test-wrapper==1.0.0 22 | milksnake==0.1.5 23 | naturalsort==1.5.1 24 | ninja==1.10.0.post2 25 | pathlib==1.0.1 26 | prettytable==2.1.0 27 | project-generator==0.8.17 28 | project-generator-definitions==0.2.42 29 | psutil==5.8.0 30 | pycparser==2.20 31 | pyelftools==0.23 32 | PyGithub==1.54.1 33 | PyJWT==1.7.1 34 | pylink-square==0.8.2 35 | pyocd==0.29.0 36 | pyOpenSSL==19.1.0 37 | pyusb==1.1.1 38 | PyYAML==5.4.1 39 | requests==2.25.1 40 | semantic-version==2.8.5 41 | six==1.15.0 42 | sortedcontainers==2.3.0 43 | typing-extensions==3.7.4.3 44 | urllib3==1.26.3 45 | valinor==1.1.4 46 | wcwidth==0.2.5 47 | wrapt==1.12.1 48 | xmltodict==0.12.0 49 | yotta==0.20.5 50 | zipp==3.4.1 51 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 Carlos Pereira Atencio 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /codespaces/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM ghcr.io/carlosperate/microbit-toolchain:latest 2 | 3 | # Use the [Option] comment to specify true/false arguments that should appear in VS Code UX 4 | # 5 | # [Option] Install zsh 6 | ARG INSTALL_ZSH="true" 7 | # [Option] Upgrade OS packages to their latest versions 8 | ARG UPGRADE_PACKAGES="false" 9 | 10 | # Install needed packages and setup non-root user. Use a separate RUN statement to add your own dependencies. 11 | ARG USERNAME=vscode 12 | ARG USER_UID=1000 13 | ARG USER_GID=$USER_UID 14 | COPY library-scripts/*.sh /tmp/library-scripts/ 15 | RUN apt-get update && export DEBIAN_FRONTEND=noninteractive \ 16 | && /bin/bash /tmp/library-scripts/common-debian.sh "${INSTALL_ZSH}" "${USERNAME}" "${USER_UID}" "${USER_GID}" "${UPGRADE_PACKAGES}" \ 17 | # 18 | # **************************************************************************** 19 | # * TODO: Add any additional OS packages you want included in the definition * 20 | # * here. We want to do this before cleanup to keep the "layer" small. * 21 | # **************************************************************************** 22 | # && apt-get -y install --no-install-recommends \ 23 | # 24 | && apt-get autoremove -y && apt-get clean -y && rm -rf /var/lib/apt/lists/* /tmp/library-scripts 25 | 26 | # [Optional] Uncomment this section to install additional OS packages. 27 | # RUN apt-get update && export DEBIAN_FRONTEND=noninteractive \ 28 | # && apt-get -y install --no-install-recommends 29 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM ubuntu:focal 2 | 3 | LABEL org.opencontainers.image.title="micro:bit Toolchain" 4 | LABEL org.opencontainers.image.description="Docker image with the micro:bit toolchain." 5 | LABEL org.opencontainers.image.authors="Carlos Pereira Atencio " 6 | LABEL org.opencontainers.image.source="https://github.com/carlosperate/docker-microbit-toolchain" 7 | 8 | # Installing build tools, git, python3 and setting it as the default python 9 | ENV DEBIAN_FRONTEND=noninteractive 10 | RUN apt-get update -qq && \ 11 | apt-get install -y --no-install-recommends wget git build-essential srecord && \ 12 | apt-get install -y --no-install-recommends python3 python3-pip && \ 13 | update-alternatives --install /usr/bin/python python /usr/bin/python3 1 && \ 14 | apt-get autoremove -y && apt-get clean -y && rm -rf /var/lib/apt/lists/* 15 | 16 | # Installing Arm GCC 17 | WORKDIR /opt/ 18 | RUN cd /opt/ && \ 19 | wget -q https://developer.arm.com/-/media/Files/downloads/gnu-rm/10-2020q4/gcc-arm-none-eabi-10-2020-q4-major-x86_64-linux.tar.bz2 && \ 20 | echo "8312c4c91799885f222f663fc81f9a31 gcc-arm-none-eabi-10-2020-q4-major-x86_64-linux.tar.bz2" >> MD5SUM && \ 21 | md5sum -c MD5SUM && \ 22 | rm MD5SUM && \ 23 | tar -xf gcc-arm-none-eabi-10-2020-q4-major-x86_64-linux.tar.bz2 && \ 24 | rm gcc-arm-none-eabi-10-2020-q4-major-x86_64-linux.tar.bz2 25 | ENV PATH $PATH:/opt/gcc-arm-none-eabi-10-2020-q4-major/bin 26 | 27 | # Installing Yotta, Cmake, and Ninja 28 | COPY requirements.txt /home/ 29 | RUN python3 -m pip --no-cache-dir install --upgrade pip && \ 30 | python3 -m pip --no-cache-dir install -r /home/requirements.txt && \ 31 | rm /home/requirements.txt 32 | 33 | WORKDIR /home/ 34 | -------------------------------------------------------------------------------- /.github/workflows/release.yml: -------------------------------------------------------------------------------- 1 | name: Deploy versioned & latest 2 | 3 | on: 4 | release: 5 | types: [published] 6 | 7 | jobs: 8 | deploy-base: 9 | name: Deploy base image 10 | runs-on: ubuntu-latest 11 | steps: 12 | - uses: actions/checkout@v2 13 | - name: Get the version 14 | id: get_version 15 | run: echo ::set-output name=VERSION::${GITHUB_REF/refs\/tags\//} 16 | shell: bash 17 | - name: Login to GitHub Container Registry 18 | uses: docker/login-action@v1 19 | with: 20 | registry: ghcr.io 21 | username: ${{ github.actor }} 22 | password: ${{ secrets.GITHUB_TOKEN }} 23 | - name: Build base image 24 | run: docker build -t ghcr.io/${{ github.actor }}/microbit-toolchain:latest . 25 | - name: Tag same base image with the versioned tag 26 | run: docker tag ghcr.io/${{ github.actor }}/microbit-toolchain:latest ghcr.io/${{ github.actor }}/microbit-toolchain:${{ steps.get_version.outputs.VERSION }} 27 | - name: Push base images to ghcr.io 28 | run: | 29 | docker push ghcr.io/${{ github.actor }}/microbit-toolchain:${{ steps.get_version.outputs.VERSION }} 30 | docker push ghcr.io/${{ github.actor }}/microbit-toolchain:latest 31 | 32 | deploy-devcontainer: 33 | name: Deploy devcontainer 34 | needs: deploy-base 35 | runs-on: ubuntu-latest 36 | steps: 37 | - uses: actions/checkout@v2 38 | - name: Get the version 39 | id: get_version 40 | run: echo ::set-output name=VERSION::${GITHUB_REF/refs\/tags\//} 41 | shell: bash 42 | - name: Login to GitHub Container Registry 43 | uses: docker/login-action@v1 44 | with: 45 | registry: ghcr.io 46 | username: ${{ github.actor }} 47 | password: ${{ secrets.GITHUB_TOKEN }} 48 | - name: Build codespaces image 49 | run: docker build -t ghcr.io/${{ github.actor }}/devcontainer-microbit:latest codespaces 50 | - name: Tag same codespaces image with the versioned tag 51 | run: docker tag ghcr.io/${{ github.actor }}/devcontainer-microbit:latest ghcr.io/${{ github.actor }}/devcontainer-microbit:${{ steps.get_version.outputs.VERSION }} 52 | - name: Push codespaces images to ghcr.io 53 | run: | 54 | docker push ghcr.io/${{ github.actor }}/devcontainer-microbit:${{ steps.get_version.outputs.VERSION }} 55 | docker push ghcr.io/${{ github.actor }}/devcontainer-microbit:latest 56 | -------------------------------------------------------------------------------- /.github/workflows/deploy-test.yml: -------------------------------------------------------------------------------- 1 | name: Deploy master & test builds 2 | 3 | on: 4 | push: 5 | branches: [master, ci] 6 | 7 | jobs: 8 | deploy: 9 | name: Deploy master tag image 10 | runs-on: ubuntu-latest 11 | if: "!contains(github.event.head_commit.message, 'ci-skip') && !contains(github.event.head_commit.message, 'skip-ci')" 12 | steps: 13 | - uses: actions/checkout@v2 14 | - name: Login to GitHub Container Registry 15 | uses: docker/login-action@v1 16 | with: 17 | registry: ghcr.io 18 | username: ${{ github.actor }} 19 | password: ${{ secrets.GITHUB_TOKEN }} 20 | - name: Build image 21 | run: docker build -t ghcr.io/${{ github.actor }}/microbit-toolchain:master . 22 | - name: Push master tag to ghcr.io 23 | run: docker push ghcr.io/${{ github.actor }}/microbit-toolchain:master 24 | 25 | build-uPy-v1: 26 | name: MicroPython V1 test build with master tag image 27 | needs: deploy 28 | runs-on: ubuntu-latest 29 | container: ghcr.io/carlosperate/microbit-toolchain:master 30 | steps: 31 | - name: Check Versions 32 | run: | 33 | arm-none-eabi-gcc --version 34 | cmake --version 35 | ninja --version 36 | yotta --version 37 | srec_cat --version 38 | - name: Clone MicroPython 39 | run: git clone https://github.com/bbcmicrobit/micropython.git 40 | - name: Build MicroPython 41 | run: | 42 | cd micropython 43 | yt target bbc-microbit-classic-gcc-nosd@https://github.com/lancaster-university/yotta-target-bbc-microbit-classic-gcc-nosd 44 | yt up 45 | make all 46 | 47 | build-dal: 48 | name: DAL test build with master tag image 49 | needs: deploy 50 | runs-on: ubuntu-latest 51 | container: ghcr.io/carlosperate/microbit-toolchain:master 52 | steps: 53 | - name: Check Versions 54 | run: | 55 | arm-none-eabi-gcc --version 56 | cmake --version 57 | ninja --version 58 | yotta --version 59 | srec_cat --version 60 | - name: Clone microbit-samples 61 | run: git clone https://github.com/lancaster-university/microbit-samples.git 62 | - name: Build DAL samples 63 | run: | 64 | cd microbit-samples 65 | yt build 66 | 67 | build-uPy-v2: 68 | name: MicroPython V2 test build with master tag image 69 | needs: deploy 70 | runs-on: ubuntu-latest 71 | container: ghcr.io/carlosperate/microbit-toolchain:master 72 | steps: 73 | - name: Check Versions 74 | run: | 75 | arm-none-eabi-gcc --version 76 | cmake --version 77 | ninja --version 78 | yotta --version 79 | srec_cat --version 80 | - name: Clone MicroPython 81 | run: | 82 | git clone https://github.com/microbit-foundation/micropython-microbit-v2.git 83 | cd micropython-microbit-v2 84 | git submodule update --init 85 | cd .. 86 | - name: Build MicroPython 87 | run: | 88 | cd micropython-microbit-v2 89 | make -C lib/micropython/mpy-cross PYTHON=python3 90 | cd src 91 | make 92 | 93 | build-codal: 94 | name: CODAL test build with master tag image 95 | needs: deploy 96 | runs-on: ubuntu-latest 97 | container: ghcr.io/carlosperate/microbit-toolchain:master 98 | steps: 99 | - name: Check Versions 100 | run: | 101 | arm-none-eabi-gcc --version 102 | cmake --version 103 | ninja --version 104 | yotta --version 105 | srec_cat --version 106 | - name: Clone microbit-v2-samples 107 | run: git clone https://github.com/lancaster-university/microbit-v2-samples.git 108 | - name: Build CODAL samples 109 | run: | 110 | cd microbit-v2-samples 111 | python build.py 112 | 113 | build-daplink: 114 | name: DAPLink test build with master tag image 115 | needs: deploy 116 | runs-on: ubuntu-latest 117 | container: ghcr.io/carlosperate/microbit-toolchain:master 118 | steps: 119 | - name: Check Versions 120 | run: | 121 | arm-none-eabi-gcc --version 122 | cmake --version 123 | ninja --version 124 | yotta --version 125 | srec_cat --version 126 | - name: Clone DAPLink and checkout develop branch 127 | run: | 128 | git clone https://github.com/mbedmicro/DAPLink 129 | cd DAPLink 130 | git checkout -b develop origin/develop 131 | - name: Install Python dependencies 132 | working-directory: DAPLink 133 | run: pip install -r requirements.txt 134 | - name: Build all micro:bit DAPLink projects 135 | working-directory: DAPLink 136 | run: python tools/progen_compile.py -t make_gcc_arm kl26z_bl kl26z_microbit_if kl27z_microbit_bl kl27z_microbit_if nrf52820_microbit_bl nrf52820_microbit_if 137 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Docker micro:bit Toolchain 2 | 3 | Docker image with the micro:bit toolchain. 4 | 5 | ![docker-microbit](https://user-images.githubusercontent.com/4189262/99010611-3445f000-2542-11eb-90d8-0983d37de762.png) 6 | 7 | Useful to be able to compile C/C++ programmes using the DAL or CODAL micro:bit 8 | runtime, which includes projects like MicroPython. It can also be used to build 9 | the DAPLink project for the micro:bit interface chip. 10 | 11 | Also includes a Docker image ready to be used with 12 | [GitHub Codespaces](https://github.com/features/codespaces) and build your 13 | micro:bit projects on the cloud. 14 | 15 | ![codespaces](https://user-images.githubusercontent.com/4189262/99011128-48d6b800-2543-11eb-89a7-738ff64e379a.png) 16 | 17 | 18 | ## How to use this Docker image to build your micro:bit project 19 | 20 | The Docker image is hosted in the 21 | [GitHub Container Registry](https://github.blog/2020-09-01-introducing-github-container-registry/) 22 | and can be fetch with this command: 23 | 24 | ``` 25 | docker pull ghcr.io/carlosperate/microbit-toolchain:latest 26 | ``` 27 | 28 | You can find more info about the image here: 29 | https://github.com/carlosperate/docker-microbit-toolchain/pkgs/container/microbit-toolchain 30 | 31 | You can run this Docker image to build your project with a command like this: 32 | 33 | ``` 34 | docker run -v $(pwd):/home --rm ghcr.io/carlosperate/microbit-toolchain:latest 35 | ``` 36 | 37 | Where: 38 | - `-v $(pwd):/home` flag mounts your PC current working directory as a volume 39 | inside the docker container `/home` path, which is also the container default 40 | working directory 41 | - `--rm` flag will clean up the container created for the build 42 | - `` should be replaced with whatever build command is needed for 43 | your project. For example, for a CODAL project that would be `python build.py` 44 | ([info in their README](https://github.com/lancaster-university/microbit-v2-samples/tree/v0.2.11#building)) 45 | 46 | ### Example: DAL (V1 C++ Samples) 47 | 48 | The build steps from this example have been obtained from the 49 | [project README](https://github.com/lancaster-university/microbit-samples/blob/v2.1.1/README.md). 50 | 51 | ```bash 52 | # Clone the repository 53 | $ git clone https://github.com/lancaster-university/microbit-samples 54 | $ cd microbit-samples 55 | # Build it using this docker image 56 | $ docker run -v $(pwd):/home --rm ghcr.io/carlosperate/microbit-toolchain:latest yotta build 57 | ``` 58 | 59 | ### Example: CODAL (V2 C++ Samples) 60 | 61 | The build steps from this example have been obtained from the 62 | [project README](https://github.com/lancaster-university/microbit-v2-samples/blob/v0.2.11/README.md). 63 | 64 | ```bash 65 | # Clone the repository 66 | $ git clone https://github.com/lancaster-university/microbit-v2-samples.git 67 | $ cd microbit-v2-samples 68 | # Build it using this docker image 69 | $ docker run -v $(pwd):/home --rm ghcr.io/carlosperate/microbit-toolchain:latest python build.py 70 | ``` 71 | 72 | ### Example: MicroPython V1 73 | 74 | The build steps from this example have been obtained from the 75 | [project README](https://github.com/bbcmicrobit/micropython/blob/v1.0.1/README.md). 76 | 77 | ```bash 78 | # Clone the repository 79 | $ git clone https://github.com/bbcmicrobit/micropython.git 80 | $ cd micropython 81 | # First prepare the project, this initial docker command only has to be run once 82 | $ docker run -v $(pwd):/home --rm ghcr.io/carlosperate/microbit-toolchain:latest yt target bbc-microbit-classic-gcc-nosd@https://github.com/lancaster-university/yotta-target-bbc-microbit-classic-gcc-nosd 83 | # Now we are ready to build it 84 | $ docker run -v $(pwd):/home --rm ghcr.io/carlosperate/microbit-toolchain:latest make all 85 | ``` 86 | 87 | ### Example: MicroPython V2 88 | 89 | The build steps from this example have been obtained from the 90 | [project README](https://github.com/microbit-foundation/micropython-microbit-v2/blob/v2.0.0-beta.1/README.md). 91 | 92 | ```bash 93 | # Clone the repository 94 | $ git clone https://github.com/microbit-foundation/micropython-microbit-v2.git 95 | $ cd micropython-microbit-v2 96 | $ git submodule update --init 97 | # First we prepare the project, this initial docker command only has to be run once 98 | $ docker run -v $(pwd):/home --rm ghcr.io/carlosperate/microbit-toolchain:latest make -C lib/micropython/mpy-cross 99 | # Now we are ready to build using the Makefile in the src folder 100 | $ docker run -v $(pwd):/home --rm ghcr.io/carlosperate/microbit-toolchain:latest make -C src 101 | ``` 102 | 103 | ### Example: DAPLink for micro:bit V2 104 | 105 | The build steps from this example have been obtained from the 106 | [project developer's guide](https://github.com/ARMmbed/DAPLink/blob/develop/docs/DEVELOPERS-GUIDE.md). 107 | 108 | ```bash 109 | # Clone the repository 110 | $ git clone https://github.com/mbedmicro/DAPLink 111 | $ cd DAPLink 112 | # Install the Python dependencies in a venv saved in the project directory 113 | $ docker run -v $(pwd):/home --rm ghcr.io/carlosperate/microbit-toolchain:latest bash -c "pip install virtualenv && virtualenv venv && source venv/bin/activate && pip install -r requirements.txt" 114 | # Activate the Python virtual environment and run the build script 115 | $ docker run -v $(pwd):/home --rm ghcr.io/carlosperate/microbit-toolchain:latest bash -c "source venv/bin/activate && python tools/progen_compile.py -t make_gcc_arm kl27z_microbit_if" 116 | ``` 117 | 118 | 119 | ## How to use this Docker Image with GitHub Codespaces 120 | 121 | This section of the docs is still a WIP. 122 | 123 | 124 | ## Other General Docker Instructions 125 | 126 | ### Build docker image 127 | 128 | Build the docker image: 129 | 130 | ``` 131 | docker build -t "microbit-toolchain" . 132 | ``` 133 | 134 | ### Run a bash session 135 | 136 | Run a bash session (launches a new container) from an existing docker image: 137 | 138 | ``` 139 | docker run --name microbit-toolchain-container -it --entrypoint /bin/bash microbit-toolchain 140 | ``` 141 | 142 | ### Copy files from docker to host 143 | 144 | ``` 145 | docker cp microbit-toolchain-container:/home/artefacts . 146 | ``` 147 | -------------------------------------------------------------------------------- /codespaces/library-scripts/common-debian.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | #------------------------------------------------------------------------------------------------------------- 3 | # Copyright (c) Microsoft Corporation. All rights reserved. 4 | # Licensed under the MIT License. See https://go.microsoft.com/fwlink/?linkid=2090316 for license information. 5 | #------------------------------------------------------------------------------------------------------------- 6 | # 7 | # Docs: https://github.com/microsoft/vscode-dev-containers/blob/master/script-library/docs/common.md 8 | # 9 | # Syntax: ./common-debian.sh [install zsh flag] [username] [user UID] [user GID] [upgrade packages flag] [install Oh My *! flag] 10 | 11 | INSTALL_ZSH=${1:-"true"} 12 | USERNAME=${2:-"automatic"} 13 | USER_UID=${3:-"automatic"} 14 | USER_GID=${4:-"automatic"} 15 | UPGRADE_PACKAGES=${5:-"true"} 16 | INSTALL_OH_MYS=${6:-"true"} 17 | 18 | set -e 19 | 20 | if [ "$(id -u)" -ne 0 ]; then 21 | echo -e 'Script must be run as root. Use sudo, su, or add "USER root" to your Dockerfile before running this script.' 22 | exit 1 23 | fi 24 | 25 | # If in automatic mode, determine if a user already exists, if not use vscode 26 | if [ "${USERNAME}" = "auto" ] || [ "${USERNAME}" = "automatic" ]; then 27 | USERNAME="" 28 | POSSIBLE_USERS=("vscode" "node" "codespace" "$(awk -v val=1000 -F ":" '$3==val{print $1}' /etc/passwd)") 29 | for CURRENT_USER in ${POSSIBLE_USERS[@]}; do 30 | if id -u ${CURRENT_USER} > /dev/null 2>&1; then 31 | USERNAME=${CURRENT_USER} 32 | break 33 | fi 34 | done 35 | if [ "${USERNAME}" = "" ]; then 36 | USERNAME=vscode 37 | fi 38 | elif [ "${USERNAME}" = "none" ]; then 39 | USERNAME=root 40 | USER_UID=0 41 | USER_GID=0 42 | fi 43 | 44 | # Load markers to see which steps have already run 45 | MARKER_FILE="/usr/local/etc/vscode-dev-containers/common" 46 | if [ -f "${MARKER_FILE}" ]; then 47 | echo "Marker file found:" 48 | cat "${MARKER_FILE}" 49 | source "${MARKER_FILE}" 50 | fi 51 | 52 | # Ensure apt is in non-interactive to avoid prompts 53 | export DEBIAN_FRONTEND=noninteractive 54 | 55 | # Function to call apt-get if needed 56 | apt-get-update-if-needed() 57 | { 58 | if [ ! -d "/var/lib/apt/lists" ] || [ "$(ls /var/lib/apt/lists/ | wc -l)" = "0" ]; then 59 | echo "Running apt-get update..." 60 | apt-get update 61 | else 62 | echo "Skipping apt-get update." 63 | fi 64 | } 65 | 66 | # Run install apt-utils to avoid debconf warning then verify presence of other common developer tools and dependencies 67 | if [ "${PACKAGES_ALREADY_INSTALLED}" != "true" ]; then 68 | apt-get-update-if-needed 69 | 70 | PACKAGE_LIST="apt-utils \ 71 | git \ 72 | openssh-client \ 73 | gnupg2 \ 74 | iproute2 \ 75 | procps \ 76 | lsof \ 77 | htop \ 78 | net-tools \ 79 | psmisc \ 80 | curl \ 81 | wget \ 82 | rsync \ 83 | ca-certificates \ 84 | unzip \ 85 | zip \ 86 | nano \ 87 | vim-tiny \ 88 | less \ 89 | jq \ 90 | lsb-release \ 91 | apt-transport-https \ 92 | dialog \ 93 | libc6 \ 94 | libgcc1 \ 95 | libgssapi-krb5-2 \ 96 | libicu[0-9][0-9] \ 97 | liblttng-ust0 \ 98 | libstdc++6 \ 99 | zlib1g \ 100 | locales \ 101 | sudo \ 102 | ncdu \ 103 | man-db \ 104 | strace" 105 | 106 | # Install libssl1.1 if available 107 | if [[ ! -z $(apt-cache --names-only search ^libssl1.1$) ]]; then 108 | PACKAGE_LIST="${PACKAGE_LIST} libssl1.1" 109 | fi 110 | 111 | # Install appropriate version of libssl1.0.x if available 112 | LIBSSL=$(dpkg-query -f '${db:Status-Abbrev}\t${binary:Package}\n' -W 'libssl1\.0\.?' 2>&1 || echo '') 113 | if [ "$(echo "$LIBSSL" | grep -o 'libssl1\.0\.[0-9]:' | uniq | sort | wc -l)" -eq 0 ]; then 114 | if [[ ! -z $(apt-cache --names-only search ^libssl1.0.2$) ]]; then 115 | # Debian 9 116 | PACKAGE_LIST="${PACKAGE_LIST} libssl1.0.2" 117 | elif [[ ! -z $(apt-cache --names-only search ^libssl1.0.0$) ]]; then 118 | # Ubuntu 18.04, 16.04, earlier 119 | PACKAGE_LIST="${PACKAGE_LIST} libssl1.0.0" 120 | fi 121 | fi 122 | 123 | echo "Packages to verify are installed: ${PACKAGE_LIST}" 124 | apt-get -y install --no-install-recommends ${PACKAGE_LIST} 2> >( grep -v 'debconf: delaying package configuration, since apt-utils is not installed' >&2 ) 125 | 126 | PACKAGES_ALREADY_INSTALLED="true" 127 | fi 128 | 129 | # Get to latest versions of all packages 130 | if [ "${UPGRADE_PACKAGES}" = "true" ]; then 131 | apt-get-update-if-needed 132 | apt-get -y upgrade --no-install-recommends 133 | apt-get autoremove -y 134 | fi 135 | 136 | # Ensure at least the en_US.UTF-8 UTF-8 locale is available. 137 | # Common need for both applications and things like the agnoster ZSH theme. 138 | if [ "${LOCALE_ALREADY_SET}" != "true" ] && ! grep -o -E '^\s*en_US.UTF-8\s+UTF-8' /etc/locale.gen > /dev/null; then 139 | echo "en_US.UTF-8 UTF-8" >> /etc/locale.gen 140 | locale-gen 141 | LOCALE_ALREADY_SET="true" 142 | fi 143 | 144 | # Create or update a non-root user to match UID/GID. 145 | if id -u ${USERNAME} > /dev/null 2>&1; then 146 | # User exists, update if needed 147 | if [ "${USER_GID}" != "automatic" ] && [ "$USER_GID" != "$(id -G $USERNAME)" ]; then 148 | groupmod --gid $USER_GID $USERNAME 149 | usermod --gid $USER_GID $USERNAME 150 | fi 151 | if [ "${USER_UID}" != "automatic" ] && [ "$USER_UID" != "$(id -u $USERNAME)" ]; then 152 | usermod --uid $USER_UID $USERNAME 153 | fi 154 | else 155 | # Create user 156 | if [ "${USER_GID}" = "automatic" ]; then 157 | groupadd $USERNAME 158 | else 159 | groupadd --gid $USER_GID $USERNAME 160 | fi 161 | if [ "${USER_UID}" = "automatic" ]; then 162 | useradd -s /bin/bash --gid $USERNAME -m $USERNAME 163 | else 164 | useradd -s /bin/bash --uid $USER_UID --gid $USERNAME -m $USERNAME 165 | fi 166 | fi 167 | 168 | # Add add sudo support for non-root user 169 | if [ "${USERNAME}" != "root" ] && [ "${EXISTING_NON_ROOT_USER}" != "${USERNAME}" ]; then 170 | echo $USERNAME ALL=\(root\) NOPASSWD:ALL > /etc/sudoers.d/$USERNAME 171 | chmod 0440 /etc/sudoers.d/$USERNAME 172 | EXISTING_NON_ROOT_USER="${USERNAME}" 173 | fi 174 | 175 | # ** Shell customization section ** 176 | if [ "${USERNAME}" = "root" ]; then 177 | USER_RC_PATH="/root" 178 | else 179 | USER_RC_PATH="/home/${USERNAME}" 180 | fi 181 | 182 | # .bashrc/.zshrc snippet 183 | RC_SNIPPET="$(cat << EOF 184 | export USER=\$(whoami) 185 | 186 | export PATH=\$PATH:\$HOME/.local/bin 187 | EOF 188 | )" 189 | 190 | # code shim, it fallbacks to code-insiders if code is not available 191 | cat << 'EOF' > /usr/local/bin/code 192 | #!/bin/sh 193 | 194 | get_in_path_except_current() { 195 | which -a "$1" | grep -v "$0" | head -1 196 | } 197 | 198 | code="$(get_in_path_except_current code)" 199 | 200 | if [ -n "$code" ]; then 201 | exec "$code" "$@" 202 | elif [ "$(command -v code-insiders)" ]; then 203 | exec code-insiders "$@" 204 | else 205 | echo "code or code-insiders is not installed" >&2 206 | exit 127 207 | fi 208 | EOF 209 | chmod +x /usr/local/bin/code 210 | 211 | # Codespaces themes - partly inspired by https://github.com/ohmyzsh/ohmyzsh/blob/master/themes/robbyrussell.zsh-theme 212 | CODESPACES_BASH="$(cat \ 213 | <&1 279 | echo -e "$(cat "${TEMPLATE}")\nDISABLE_AUTO_UPDATE=true\nDISABLE_UPDATE_PROMPT=true" > ${USER_RC_FILE} 280 | if [ "${OH_MY}" = "bash" ]; then 281 | sed -i -e 's/OSH_THEME=.*/OSH_THEME="codespaces"/g' ${USER_RC_FILE} 282 | mkdir -p ${OH_MY_INSTALL_DIR}/custom/themes/codespaces 283 | echo "${CODESPACES_BASH}" > ${OH_MY_INSTALL_DIR}/custom/themes/codespaces/codespaces.theme.sh 284 | else 285 | sed -i -e 's/ZSH_THEME=.*/ZSH_THEME="codespaces"/g' ${USER_RC_FILE} 286 | mkdir -p ${OH_MY_INSTALL_DIR}/custom/themes 287 | echo "${CODESPACES_ZSH}" > ${OH_MY_INSTALL_DIR}/custom/themes/codespaces.zsh-theme 288 | fi 289 | # Shrink git while still enabling updates 290 | cd ${OH_MY_INSTALL_DIR} 291 | git repack -a -d -f --depth=1 --window=1 292 | 293 | if [ "${USERNAME}" != "root" ]; then 294 | cp -rf ${USER_RC_FILE} ${OH_MY_INSTALL_DIR} /root 295 | chown -R ${USERNAME}:${USERNAME} ${USER_RC_PATH} 296 | fi 297 | } 298 | 299 | if [ "${RC_SNIPPET_ALREADY_ADDED}" != "true" ]; then 300 | echo "${RC_SNIPPET}" >> /etc/bash.bashrc 301 | RC_SNIPPET_ALREADY_ADDED="true" 302 | fi 303 | install-oh-my bash bashrc.osh-template https://github.com/ohmybash/oh-my-bash 304 | 305 | # Optionally install and configure zsh and Oh My Zsh! 306 | if [ "${INSTALL_ZSH}" = "true" ]; then 307 | if ! type zsh > /dev/null 2>&1; then 308 | apt-get-update-if-needed 309 | apt-get install -y zsh 310 | fi 311 | if [ "${ZSH_ALREADY_INSTALLED}" != "true" ]; then 312 | echo "${RC_SNIPPET}" >> /etc/zsh/zshrc 313 | ZSH_ALREADY_INSTALLED="true" 314 | fi 315 | install-oh-my zsh zshrc.zsh-template https://github.com/ohmyzsh/ohmyzsh 316 | fi 317 | 318 | # Write marker file 319 | mkdir -p "$(dirname "${MARKER_FILE}")" 320 | echo -e "\ 321 | PACKAGES_ALREADY_INSTALLED=${PACKAGES_ALREADY_INSTALLED}\n\ 322 | LOCALE_ALREADY_SET=${LOCALE_ALREADY_SET}\n\ 323 | EXISTING_NON_ROOT_USER=${EXISTING_NON_ROOT_USER}\n\ 324 | RC_SNIPPET_ALREADY_ADDED=${RC_SNIPPET_ALREADY_ADDED}\n\ 325 | ZSH_ALREADY_INSTALLED=${ZSH_ALREADY_INSTALLED}" > "${MARKER_FILE}" 326 | 327 | echo "Done!" 328 | --------------------------------------------------------------------------------