From 54bbdf860f99908cdb42067662ac98fcf9c578c3 Mon Sep 17 00:00:00 2001 From: Michael Stoops Date: Wed, 31 Mar 2021 20:16:51 -0700 Subject: [PATCH 1/6] Major rewrite. Added support for macOS, Debian, Ubuntu. Added test/validation script. --- LICENSE.txt | 21 ++ README.md | 28 +++ pico_setup.sh | 520 ++++++++++++++++++++++++++++++++++--------------- test/README.md | 106 ++++++++++ test/test | 125 ++++++++++++ 5 files changed, 645 insertions(+), 155 deletions(-) create mode 100644 LICENSE.txt create mode 100644 README.md create mode 100644 test/README.md create mode 100755 test/test diff --git a/LICENSE.txt b/LICENSE.txt new file mode 100644 index 0000000..1d2dc0d --- /dev/null +++ b/LICENSE.txt @@ -0,0 +1,21 @@ +Copyright 2020 (c) 2020 Raspberry Pi (Trading) Ltd. + +Redistribution and use in source and binary forms, with or without modification, are permitted provided that the +following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following + disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided with the distribution. + +3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, +INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/README.md b/README.md new file mode 100644 index 0000000..e8d0684 --- /dev/null +++ b/README.md @@ -0,0 +1,28 @@ +# Raspberry Pi Pico Setup + +Raspberry Pi Pico Setup provides a script for installing the Pico SDK and toolchain. + +# How-To + +Download and run `pico_setup.sh`. + +If you want the testing script and documentation, you can clone the git repo too. + +# Support + +Operating systems: +* Raspberry Pi OS (32-bit) +* Debian 10 (Buster) +* Ubuntu 20.10 (Groovy) +* macOS 11 (Big Sur) + +Hardware: +* Raspberry Pi 2/3/4/400 +* PC (x86_64) +* Mac (both Intel and Apple Silicon) + +Other versions may work, but haven't been tested. Use at your own risk. + +# Testing + +See [test/README.md](test/README.md) diff --git a/pico_setup.sh b/pico_setup.sh index 4a928d7..1c20a78 100755 --- a/pico_setup.sh +++ b/pico_setup.sh @@ -1,186 +1,396 @@ -#!/bin/bash +#!/usr/bin/env bash + +# Phase 0: Preflight check +# Verify baseline dependencies + +# Phase 1: Setup minimum dev environment +# Install the toolchain +# Create a directory called pico +# Download the pico-sdk repository and submodules +# Define env variables for repo: PICO_SDK_PATH +# Configure the Raspberry Pi UART for use with Raspberry Pi Pico + +# Phase 2: Setting up tutorial repos +# Download pico-examples, pico-extras, pico-playground repositories, and submodules +# Build the blink and hello_world examples + +# Phase 3: Recommended tools +# Download and build picotool (see Appendix B), and copy it to /usr/local/bin. +# Download and build picoprobe (see Appendix A) and OpenOCD +# Download and install Visual Studio Code and required extensions + + # Exit on error set -e +# Show all commands +set -x -if grep -q Raspberry /proc/cpuinfo; then - echo "Running on a Raspberry Pi" -else - echo "Not running on a Raspberry Pi. Use at your own risk!" -fi # Number of cores when running make JNUM=4 # Where will the output go? -OUTDIR="$(pwd)/pico" - -# Install dependencies -GIT_DEPS="git" -SDK_DEPS="cmake gcc-arm-none-eabi gcc g++" -OPENOCD_DEPS="gdb-multiarch automake autoconf build-essential texinfo libtool libftdi-dev libusb-1.0-0-dev" -# Wget to download the deb -VSCODE_DEPS="wget" -UART_DEPS="minicom" - -# Build full list of dependencies -DEPS="$GIT_DEPS $SDK_DEPS" - -if [[ "$SKIP_OPENOCD" == 1 ]]; then - echo "Skipping OpenOCD (debug support)" -else - DEPS="$DEPS $OPENOCD_DEPS" -fi - -if [[ "$SKIP_VSCODE" == 1 ]]; then - echo "Skipping VSCODE" -else - DEPS="$DEPS $VSCODE_DEPS" -fi - -echo "Installing Dependencies" -sudo apt update -sudo apt install -y $DEPS - -echo "Creating $OUTDIR" -# Create pico directory to put everything in -mkdir -p $OUTDIR -cd $OUTDIR - -# Clone sw repos -GITHUB_PREFIX="https://github.com/raspberrypi/" -GITHUB_SUFFIX=".git" -SDK_BRANCH="master" - -for REPO in sdk examples extras playground -do - DEST="$OUTDIR/pico-$REPO" - - if [ -d $DEST ]; then - echo "$DEST already exists so skipping" +WORKING_DIR="$(pwd)/pico" + + +linux() { + # Returns true iff this is running on Linux + uname | grep -q "^Linux$" + return ${?} +} + +raspbian() { + # Returns true iff this is running on Raspbian or close derivative such as Raspberry Pi OS, but not necessarily on a Raspberry Pi computer + grep -q '^NAME="Raspbian GNU/Linux"$' /etc/os-release + return ${?} +} + +debian() { + # Returns true iff this is running on Debian + grep -q '^NAME="Debian GNU/Linux"$' /etc/os-release + return ${?} +} + +ubuntu() { + # Returns true iff this is running on Ubuntu + grep -q '^NAME="Ubuntu"$' /etc/os-release + return ${?} +} + +mac() { + # Returns true iff this is running on macOS and presumably Apple hardware + uname | grep -q "^Darwin$" + return ${?} +} + +raspberry_pi() { + # Returns true iff this is running on a Raspberry Pi computer, regardless of the OS + if [ -f /proc/cpuinfo ]; then + grep -q "^Model\s*: Raspberry Pi" /proc/cpuinfo + return ${?} + fi + return 1 +} + +phase_0() { + # Preflight the check + # Checks the baseline dependencies. If you don't have these, this script won't work. + echo "Entering phase 0: Preflight check" + + echo "Verifying sudo access" + sudo -v + + if mac; then + echo "Running on macOS" + if which brew >> /dev/null; then + echo "Found brew" + brew update + else + echo -e 'This script requires Homebrew, the missing package manager for macOS. See https://docs.brew.sh/Installation. For quick install, run:\n/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install.sh)"' + echo "Stopping." + exit 1 + fi + else + if linux; then + echo "Running on Linux" + else + echo "Platform $(uname) not recognized. Use at your own risk. Continuing as though this were Linux." + fi + + if which apt >> /dev/null; then + echo "Found apt" + sudo apt update + else + echo 'This script requires apt, the default package manager for Debian and Debian-derived distros such as Ubuntu, and Raspberry Pi OS.' + echo "Stopping." + exit 1 + fi + fi +} + +install_toolchain_linux() { + # Install toolchain for Linux + + DEPS="git cmake gcc-arm-none-eabi build-essential gdb-multiarch automake autoconf build-essential texinfo libtool libftdi-dev libusb-1.0-0-dev" + if debian || ubuntu; then + DEPS="${DEPS} pkg-config libstdc++-arm-none-eabi-newlib" + fi + sudo apt install -y ${DEPS} +} + +brew_install_idempotent() { + # For some reason, brew install is not idempotent. This function succeeds even when the package is already installed. + brew list ${*} || brew install ${*} + return ${?} +} + +install_toolchain_mac() { + # Install dependencies for mac + + brew_install_idempotent git cmake pkg-config libtool automake libusb wget pkg-config gcc texinfo + brew tap ArmMbed/homebrew-formulae + brew_install_idempotent arm-none-eabi-gcc +} + +create_working_dir() { + # Creates ./pico directory if necessary + + mkdir -p "${WORKING_DIR}" +} + +clone_repo() { + # Clones the given repo name from GitHub and inits any submodules + # $1 should be the full name of the repo, ex: pico-sdk + # $2 should be the branch name. Defaults to master. + # all other args are passed to git clone + REPO_NAME="${1}" + if shift && [ "${1}" ]; then + BRANCH="${1}" + else + BRANCH=master + fi + if shift; then + # $* contains more args + true + fi + + cd "${WORKING_DIR}" + + REPO_URL="https://github.com/raspberrypi/${REPO_NAME}.git" + DEST="${WORKING_DIR}/${REPO_NAME}" + + if [ -d "${DEST}" ]; then + echo "Not cloning $DEST because it already exists" else - REPO_URL="${GITHUB_PREFIX}pico-${REPO}${GITHUB_SUFFIX}" echo "Cloning $REPO_URL" - git clone -b $SDK_BRANCH $REPO_URL + git clone -b "$BRANCH" "$REPO_URL" ${*} # Any submodules - cd $DEST + cd "$DEST" git submodule update --init - cd $OUTDIR + fi +} - # Define PICO_SDK_PATH in ~/.bashrc - VARNAME="PICO_${REPO^^}_PATH" - echo "Adding $VARNAME to ~/.bashrc" - echo "export $VARNAME=$DEST" >> ~/.bashrc - export ${VARNAME}=$DEST +set_envs() { + # Permanently sets environment variables by adding them to the current user's profile script + # arguments should be in the form of FOO=foo BAR=bar + + # detect appropriate file for setting env vars + if echo "${SHELL}" | grep -q zsh; then + # zsh detected + FILE=~/.zprofile + else + # sh, bash and others + FILE=~/.profile fi -done - -cd $OUTDIR - -# Pick up new variables we just defined -source ~/.bashrc - -# Build a couple of examples -cd "$OUTDIR/pico-examples" -mkdir build -cd build -cmake ../ -DCMAKE_BUILD_TYPE=Debug - -for e in blink hello_world -do - echo "Building $e" - cd $e - make -j$JNUM - cd .. -done - -cd $OUTDIR - -# Picoprobe and picotool -for REPO in picoprobe picotool -do - DEST="$OUTDIR/$REPO" - REPO_URL="${GITHUB_PREFIX}${REPO}${GITHUB_SUFFIX}" - git clone $REPO_URL - - # Build both - cd $DEST - mkdir build - cd build - cmake ../ - make -j$JNUM - if [[ "$REPO" == "picotool" ]]; then - echo "Installing picotool to /usr/local/bin/picotool" - sudo cp picotool /usr/local/bin/ + # ensure that appends go to a new line + if [ -f ${FILE} ]; then + if tail -n 1 ${FILE} | grep -q "^$"; then + echo "${FILE} exists and has trailing newline." + else + echo "${FILE} exists but has no trailing newline. Adding newline." + echo >> ${FILE} + fi fi - cd $OUTDIR -done - -if [ -d openocd ]; then - echo "openocd already exists so skipping" - SKIP_OPENOCD=1 -fi - -if [[ "$SKIP_OPENOCD" == 1 ]]; then - echo "Won't build OpenOCD" -else - # Build OpenOCD - echo "Building OpenOCD" - cd $OUTDIR - # Should we include picoprobe support (which is a Pico acting as a debugger for another Pico) - INCLUDE_PICOPROBE=1 - OPENOCD_BRANCH="rp2040" - OPENOCD_CONFIGURE_ARGS="--enable-ftdi --enable-sysfsgpio --enable-bcm2835gpio" - if [[ "$INCLUDE_PICOPROBE" == 1 ]]; then - OPENOCD_BRANCH="picoprobe" - OPENOCD_CONFIGURE_ARGS="$OPENOCD_CONFIGURE_ARGS --enable-picoprobe" + for EXPR in ${*}; do + # set for now + export "${EXPR}" + + # set for later + set_env "${FILE}" "${EXPR}" + done +} + +set_env() { + # Permanently sets one environment variable for bash + # $1 must be the file where the env is stored + # $2 should be in the form of VAR=value + FILE="${1}" + EXPR="${2}" + + if ! grep -q "^export ${EXPR}$" ${FILE}; then + echo "Setting env variable ${EXPR} in ${FILE}" + echo "export ${EXPR}" >> ${FILE} fi +} + +setup_sdk() { + # Downloads and builds the SDK + cd "${WORKING_DIR}" + + clone_repo pico-sdk + + # Set env var PICO_SDK_PATH + REPO_UPPER=$(echo ${REPO_NAME} | tr "[:lower:]" "[:upper:]") + REPO_UPPER=$(echo ${REPO_UPPER} | tr "-" "_") + set_envs "${REPO_UPPER}_PATH=$DEST" +} + +enable_uart() { + # Enable UART + sudo apt install -y minicom + echo "Disabling Linux serial console (UART) so we can use it for pico" + sudo raspi-config nonint do_serial 2 + echo "You must run sudo reboot to finish UART setup" +} - git clone "${GITHUB_PREFIX}openocd${GITHUB_SUFFIX}" -b $OPENOCD_BRANCH --depth=1 - cd openocd +phase_1() { + # Setup minimum dev environment + echo "Entering phase 1: Setup minimum dev environment" + + if mac; then + install_toolchain_mac + else + install_toolchain_linux + fi + + create_working_dir + setup_sdk + + if linux && pi; then + if [[ "$SKIP_UART" == 1 ]]; then + echo "Skipping UART configuration" + else + enable_uart + fi + else + echo "Not configuring UART because this is not running Raspberry Pi OS on a Raspberry Pi computer" + fi +} + +build_examples() { + # Build a couple of examples + echo "Building selected examples" + + cd "$WORKING_DIR/pico-examples" + mkdir -p build + cd build + cmake ../ -DCMAKE_BUILD_TYPE=Debug + + for EXAMPLE in blink hello_world; do + echo "Building $EXAMPLE" + cd "$EXAMPLE" + make -j${JNUM} + cd .. + done +} + +phase_2() { + # Setup tutorial repos + echo "Entering phase 2: Setting up tutorial repos" + + for REPO_NAME in pico-examples pico-extras pico-playground; do + clone_repo "${REPO_NAME}" + done + + build_examples +} + +setup_picotool() { + # Downloads, builds, and installs picotool + echo "Setting up picotool" + + cd "${WORKING_DIR}" + + clone_repo picotool + cd "${WORKING_DIR}/picotool" + mkdir -p build + cd build + cmake ../ + make -j${JNUM} + + echo "Installing picotool to /usr/local/bin/picotool" + sudo cp picotool /usr/local/bin/ +} + +setup_openocd() { + # Download, build, and install OpenOCD for picoprobe and bit-banging without picoprobe + echo "Setting up OpenOCD" + + cd "${WORKING_DIR}" + + clone_repo openocd picoprobe --depth=1 + cd "${WORKING_DIR}/openocd" ./bootstrap - ./configure $OPENOCD_CONFIGURE_ARGS - make -j$JNUM + OPTS="--enable-ftdi --enable-bcm2835gpio --enable-picoprobe" + if linux; then + # sysfsgpio is only available on linux + OPTS="${OPTS} --enable-sysfsgpio" + fi + ./configure ${OPTS} + make -j${JNUM} sudo make install -fi +} + +setup_picoprobe() { + # Download and build picoprobe. Requires that OpenOCD is already setup + echo "Setting up picoprobe" + + cd "${WORKING_DIR}" + + clone_repo picoprobe + cd "${WORKING_DIR}/picoprobe" + mkdir -p build + cd build + cmake .. + make -j${JNUM} +} + +install_vscode_linux() { + # Install Visual Studio Code + + # VS Code is specially added to Raspberry Pi OS repos. Need to add the right repos to make it work on Debian/Ubuntu. + if debian || ubuntu; then + echo "Visual Studio Code installation currently doesn't work on Debian and Ubuntu" + return + fi + + echo "Installing Visual Studio Code" -cd $OUTDIR + cd "${WORKING_DIR}" -# Liam needed to install these to get it working -EXTRA_VSCODE_DEPS="libx11-xcb1 libxcb-dri3-0 libdrm2 libgbm1 libegl-mesa0" -if [[ "$SKIP_VSCODE" == 1 ]]; then - echo "Won't include VSCODE" -else - if [ -f vscode.deb ]; then - echo "Skipping vscode as vscode.deb exists" + sudo apt install -y code + + # Get extensions + code --install-extension marus25.cortex-debug + code --install-extension ms-vscode.cmake-tools + code --install-extension ms-vscode.cpptools +} + +install_vscode_mac() { + echo "This script cannot install Visual Studio Code on macOS" +} + +phase_3() { + # Setup recommended tools + echo "Setting up recommended tools" + + setup_picotool + setup_openocd + setup_picoprobe + + # Install Visual Studio Code + if mac; then + install_vscode_mac else - echo "Installing VSCODE" - if uname -m | grep -q aarch64; then - VSCODE_DEB="https://aka.ms/linux-arm64-deb" + if dpkg-query -s libx11-6; then + install_vscode_linux else - VSCODE_DEB="https://aka.ms/linux-armhf-deb" + echo "Not installing Visual Studio Code because it looks like XWindows is not installed." fi + fi +} - wget -O vscode.deb $VSCODE_DEB - sudo apt install -y ./vscode.deb - sudo apt install -y $EXTRA_VSCODE_DEPS +main() { + phase_0 + phase_1 + phase_2 + phase_3 - # Get extensions - code --install-extension marus25.cortex-debug - code --install-extension ms-vscode.cmake-tools - code --install-extension ms-vscode.cpptools - fi -fi + echo "Congratulations, installation is complete. 😁" +} -# Enable UART -if [[ "$SKIP_UART" == 1 ]]; then - echo "Skipping uart configuration" -else - sudo apt install -y $UART_DEPS - echo "Disabling Linux serial console (UART) so we can use it for pico" - sudo raspi-config nonint do_serial 2 - echo "You must run sudo reboot to finish UART setup" -fi +main \ No newline at end of file diff --git a/test/README.md b/test/README.md new file mode 100644 index 0000000..dcf3590 --- /dev/null +++ b/test/README.md @@ -0,0 +1,106 @@ +# Testing pico-setup + +The tests validate that `pico_setup.sh` _seems_ to setup your system correctly. It can be fooled. It does not test that the SDK or tools themselves work correctly, just that the setup script did its thing. + +To execute the tests, first run `pico_setup.sh` from wherever you want to install the pico dev environment: +```shell +./pico_setup.sh +``` +Logout and back in, so that your shell will pick up its environment variables. Then run the test from the same location as you ran `pico_setup.sh`: +```shell +./test/test +``` + +# What to test + +## Platform support +Test support for the following platforms. The general process is: +1. Start from a fresh OS image. +1. Start the SSH service if necessary: `sudo /sbin/service ssh start` +1. Push down the contents of the pico-setup repo from your dev host: `scp -r ~/git/raspberrypi/pico-setup/ pi@pi4:` +1. SSH to the test host and execute the setup: `pico-setup/pico_setup.sh` +1. Test the setup: "ssh pi@pi4 pico-setup/test/test" + +### Raspberry Pi OS Full (32-bit) on Raspberry Pi 4B +This is the baseline platform, what most users will have. + +Write fresh SD card with Raspberry Pi Imager. + +### Raspberry Pi OS Full (64-bit) on Raspberry Pi 4B +If all of the dependencies (APT repo, etc) are in good shape, this should work the same as the 32-bit OS, since we don't do anything explicitly for one or the other. + +Write fresh SD card with Raspberry Pi Imager. + +### Raspberry Pi OS Lite (32-bit) on Raspberry Pi 4B +Should be the same as the full OS, but doesn't attempt to install VS Code, because there will be no XWindows. + +Write fresh SD card with Raspberry Pi Imager. + +### Ubuntu Desktop 20.10 (64-bit) on Raspberry Pi 4B +Less common. Should work a lot like Raspberry Pi OS, but with a couple different package dependencies. + +Write fresh SD card with Raspberry Pi Imager. + +### Debian 10 (Buster) on Raspberry Pi 4B +Less common. Should work a lot like Raspberry Pi OS, but with a couple different package dependencies. + +Write fresh SD card with Raspberry Pi Imager. + +### macOS Big Sur on Mac mini Intel +Can be rented on EC2, but not as cheaply as the other platforms. You have to get a dedicated host, which currently costs $1.083/hour in us-west-2, with a minimum of 24 hours. You can launch and terminate instances all day on that dedicated host without extra cost, which is good for testing installers. Comes with Homebrew installed, which is nice. + +Default user is `ec2-user`. You will have to use sudo to set the user's password: +```shell +sudo -i +passwd ec2-user +``` + +### Raspberry Pi Desktop on x86_64 +Not yet tested. + +### Ubuntu 20.10 on x86_64 +Can be rented on [EC2](https://aws.amazon.com/marketplace/pp/B08LQMCZGC?ref_=beagle&applicationId=AWS-Marketplace-Console) for pennies/hour. Recommend t3.micro with 8 GiB EBS volume. Default user is `ubuntu`. You will have to use sudo to set the user's password: +```shell +sudo -i +passwd ubuntu +``` + +### Debian 10 (Buster) on x86_64 +Can be rented on [EC2](https://aws.amazon.com/marketplace/pp/B0859NK4HC?ref_=aws-mp-console-subscription-detail) for pennies/hour. Recommend t3.micro with 8 GiB EBS volume. Default user is `admin`. You will have to use sudo to set the user's password: +```shell +sudo -i +passwd admin +``` + +### Ubuntu 20.10 on Graviton2 +Can be rented on [EC2](https://aws.amazon.com/marketplace/pp/B08LQMCZGC?ref_=beagle&applicationId=AWS-Marketplace-Console) for pennies/hour. Recommend t4g.micro with 8 GiB EBS volume. Default user is `ubuntu`. You will have to use sudo to set the user's password: +```shell +sudo -i +passwd ubuntu +``` + +### Debian 10 (Buster) on Graviton2 +Can be rented on [EC2](https://aws.amazon.com/marketplace/pp/B0859NK4HC?ref_=aws-mp-console-subscription-detail) for pennies/hour. Recommend t3.micro with 8 GiB EBS volume. Default user is `admin`. You will have to use sudo to set the user's password: +```shell +sudo -i +passwd admin +``` + +### Windows Server 2016 Base on x86_64 +https://aws.amazon.com/marketplace/server/procurement?productId=13c2dbc9-57fc-4958-922e-a1ba7e223b0d + +### Windows Server 2016 Base on x86_64 +https://aws.amazon.com/marketplace/server/procurement?productId=ef297a90-3ad0-4674-83b4-7f0ec07c39bb + +### Ubuntu on WSL2 on Windows Server 2016 Base on x86_64 +Not yet tested. + +### Debian 10 (Buster) on WSL2 on Windows Server 2016 Base on x86_64 +Not yet tested. + +## Scenarios +Test some scenarios: +* Shells: bash, zsh. It should be enough to switch shells and rerun the installer and test. You don't have to wipe the SD card/disk. +* .profile or .zprofile doesn't end in newline +* PWD containing space +* Raspberry Pi OS Lite (32-bit) shouldn't install VS Code diff --git a/test/test b/test/test new file mode 100755 index 0000000..74d4041 --- /dev/null +++ b/test/test @@ -0,0 +1,125 @@ +#!/usr/bin/env bash + +# Executes the full test suite on the local host +# +# Configurations env vars: + +set -ex + +WORKING_DIR="$(pwd)/pico" + +mac() { + # Returns true iff this is running on macOS and presumably Apple hardware + uname | grep -q "^Darwin$" + return ${?} +} + +fail() { + # Outputs a failure message and exits with the error code output by the previous call. + # All args are echoed as a failure message. + + R="${?}" + echo "Tests failed! 😢" + if [ ${*} ]; then + echo "${*}" + fi + exit ${R} +} + +test_git_repo() { + # tests that the given relative path exists and is a git repo + git -C ${WORKING_DIR}/${1} status || fail +} + +test_toolchain_linux() { + # test that the expected packages are installed + dpkg-query -s git cmake gcc-arm-none-eabi build-essential gdb-multiarch automake autoconf build-essential texinfo libtool libftdi-dev libusb-1.0-0-dev || fail +} + +test_toolchain_mac() { + # test that the expected packages are installed + brew list git cmake pkg-config libtool automake libusb wget pkg-config gcc texinfo arm-none-eabi-gcc +} + +test_pico_sdk() { + test_git_repo pico-sdk + + # test that the SDK env var is set and correct + test "${PICO_SDK_PATH}" = "${WORKING_DIR}/pico-sdk" || fail +} + +test_pico_examples() { + test_git_repo pico-examples + + # test that blink is built + test -f ${WORKING_DIR}/pico-examples/build/blink/blink.uf2 || fail + + # test that hello_serial is built + test -f ${WORKING_DIR}/pico-examples/build/hello_world/serial/hello_serial.uf2 || fail + + # test that hello_usb is built + test -f ${WORKING_DIR}/pico-examples/build/hello_world/usb/hello_usb.uf2 || fail +} + +test_pico_extras() { + test_git_repo pico-extras +} + +test_pico_playground() { + test_git_repo pico-playground +} + +test_picotool() { + test_git_repo picotool + + # test that the binary is built + test -x ${WORKING_DIR}/picotool/build/picotool || fail + + # test that picotool is installed in the expected location + test -x /usr/local/bin/picotool || fail +} + +test_openocd() { + test_git_repo openocd + + # test that the binary is built + test -x ${WORKING_DIR}/openocd/src/openocd || fail +} + +test_picoprobe() { + test_git_repo picoprobe || fail + + # test that the binary is built + test -f ${WORKING_DIR}/picoprobe/build/picoprobe.uf2 || fail +} + +test_vscode_linux() { + dpkg-query -s code || fail +} + +test_vscode_mac() { + echo "This script can't tell whether Visual Studio Code is installed on macOS" +} + +# execute tests +if mac; then + test_toolchain_mac +else + test_toolchain_linux +fi + +test_pico_sdk + +test_pico_examples +test_pico_extras +test_pico_playground +test_openocd +test_picoprobe +test_picotool +if mac; then + test_vscode_mac +else + test_vscode_mac +fi + +echo "Tests passed! 😁" From 1858d3385f86149123b7b02e5056995c5a392074 Mon Sep 17 00:00:00 2001 From: Michael Stoops Date: Wed, 31 Mar 2021 20:16:51 -0700 Subject: [PATCH 2/6] Bug fixes. --- README.md | 24 ++++++++ pico_setup.sh | 145 ++++++++++++++++++++++++++++++++++++++++++++++++- test/README.md | 29 ++++++---- test/test | 65 ++++++++++++++++++++++ 4 files changed, 251 insertions(+), 12 deletions(-) diff --git a/README.md b/README.md index e8d0684..7d1f4be 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,19 @@ Raspberry Pi Pico Setup provides a script for installing the Pico SDK and toolch # How-To +<<<<<<< HEAD Download and run `pico_setup.sh`. +======= +Download and run `pico_setup.sh`: +```shell +wget https://raw.githubusercontent.com/raspberrypi/pico-setup/master/pico_setup.sh +chmod +x pico_setup +./pico_setup +``` +The script uses sudo, so you may need to enter your password. + +After the script is complete, reboot to ensure that all changes take effect, such as the UART settings and environment variables. +>>>>>>> 4f2c6f4... Major rewrite. Added support for macOS, Debian, Ubuntu. Added test/validation script. If you want the testing script and documentation, you can clone the git repo too. @@ -17,6 +29,7 @@ Operating systems: * macOS 11 (Big Sur) Hardware: +<<<<<<< HEAD * Raspberry Pi 2/3/4/400 * PC (x86_64) * Mac (both Intel and Apple Silicon) @@ -26,3 +39,14 @@ Other versions may work, but haven't been tested. Use at your own risk. # Testing See [test/README.md](test/README.md) +======= +* Raspberry Pi 2/3/4/400/CM3/CM4 +* PC (x86_64) +* Mac (both Intel and Apple Silicon) + +Other OSes and hardware may work, but haven't been tested. Use at your own risk. + +# Testing + +See [test/README.md](test/README.md). +>>>>>>> 4f2c6f4... Major rewrite. Added support for macOS, Debian, Ubuntu. Added test/validation script. diff --git a/pico_setup.sh b/pico_setup.sh index 1c20a78..8e18f5c 100755 --- a/pico_setup.sh +++ b/pico_setup.sh @@ -161,6 +161,7 @@ clone_repo() { DEST="${WORKING_DIR}/${REPO_NAME}" if [ -d "${DEST}" ]; then +<<<<<<< HEAD echo "Not cloning $DEST because it already exists" else echo "Cloning $REPO_URL" @@ -176,6 +177,23 @@ set_envs() { # Permanently sets environment variables by adding them to the current user's profile script # arguments should be in the form of FOO=foo BAR=bar +======= + echo "Not cloning ${DEST} because it already exists. If you really want to start over, delete it: rm -rf ${DEST}" + else + echo "Cloning ${REPO_URL}" + git clone -b "${BRANCH}" "${REPO_URL}" ${*} + + # Any submodules + cd "${DEST}" + git submodule update --init + fi +} + +set_envs() { + # Permanently sets environment variables by adding them to the current user's profile script + # arguments should be in the form of FOO=foo BAR=bar + +>>>>>>> 4f2c6f4... Major rewrite. Added support for macOS, Debian, Ubuntu. Added test/validation script. # detect appropriate file for setting env vars if echo "${SHELL}" | grep -q zsh; then # zsh detected @@ -200,6 +218,7 @@ set_envs() { export "${EXPR}" # set for later +<<<<<<< HEAD set_env "${FILE}" "${EXPR}" done } @@ -312,6 +331,106 @@ setup_openocd() { cd "${WORKING_DIR}" +======= + if ! grep -q "^export ${EXPR}$" ${FILE}; then + echo "Setting env variable ${EXPR} in ${FILE}" + echo "export ${EXPR}" >> ${FILE} + fi + done +} + +setup_sdk() { + # Downloads and builds the SDK + cd "${WORKING_DIR}" + + clone_repo pico-sdk + + # Set env var PICO_SDK_PATH + REPO_UPPER=$(echo ${REPO_NAME} | tr "[:lower:]" "[:upper:]") + REPO_UPPER=$(echo ${REPO_UPPER} | tr "-" "_") + set_envs "${REPO_UPPER}_PATH=$DEST" +} + +enable_uart() { + # Enable UART + sudo apt install -y minicom + echo "Disabling Linux serial console (UART) so we can use it for pico" + sudo raspi-config nonint do_serial 2 + echo "You must run sudo reboot to finish UART setup" +} + +phase_1() { + # Setup minimum dev environment + echo "Entering phase 1: Setup minimum dev environment" + + if mac; then + install_toolchain_mac + else + install_toolchain_linux + fi + + create_working_dir + setup_sdk + + if raspbian && raspberry_pi; then + enable_uart + else + echo "Not configuring UART because this is not running Raspberry Pi OS on a Raspberry Pi computer" + fi +} + +build_examples() { + # Build a couple of examples + echo "Building selected examples" + + cd "$WORKING_DIR/pico-examples" + mkdir -p build + cd build + cmake ../ -DCMAKE_BUILD_TYPE=Debug + + for EXAMPLE in blink hello_world; do + echo "Building $EXAMPLE" + cd "$EXAMPLE" + make -j${JNUM} + cd .. + done +} + +phase_2() { + # Setup tutorial repos + echo "Entering phase 2: Setting up tutorial repos" + + for REPO_NAME in pico-examples pico-extras pico-playground; do + clone_repo "${REPO_NAME}" + done + + build_examples +} + +setup_picotool() { + # Downloads, builds, and installs picotool + echo "Setting up picotool" + + cd "${WORKING_DIR}" + + clone_repo picotool + cd "${WORKING_DIR}/picotool" + mkdir -p build + cd build + cmake ../ + make -j${JNUM} + + echo "Installing picotool to /usr/local/bin/picotool" + sudo cp picotool /usr/local/bin/ +} + +setup_openocd() { + # Download, build, and install OpenOCD for picoprobe and bit-banging without picoprobe + echo "Setting up OpenOCD" + + cd "${WORKING_DIR}" + +>>>>>>> 4f2c6f4... Major rewrite. Added support for macOS, Debian, Ubuntu. Added test/validation script. clone_repo openocd picoprobe --depth=1 cd "${WORKING_DIR}/openocd" ./bootstrap @@ -344,16 +463,28 @@ install_vscode_linux() { # VS Code is specially added to Raspberry Pi OS repos. Need to add the right repos to make it work on Debian/Ubuntu. if debian || ubuntu; then +<<<<<<< HEAD echo "Visual Studio Code installation currently doesn't work on Debian and Ubuntu" +======= + echo "Not yet implemented: testing Visual Studio Code on Debian/Ubuntu" +>>>>>>> 4f2c6f4... Major rewrite. Added support for macOS, Debian, Ubuntu. Added test/validation script. return fi echo "Installing Visual Studio Code" +<<<<<<< HEAD + + cd "${WORKING_DIR}" + + sudo apt install -y code + +======= cd "${WORKING_DIR}" sudo apt install -y code +>>>>>>> 4f2c6f4... Major rewrite. Added support for macOS, Debian, Ubuntu. Added test/validation script. # Get extensions code --install-extension marus25.cortex-debug code --install-extension ms-vscode.cmake-tools @@ -361,7 +492,11 @@ install_vscode_linux() { } install_vscode_mac() { +<<<<<<< HEAD echo "This script cannot install Visual Studio Code on macOS" +======= + echo "Not yet implemented: installing Visual Studio Code on macOS" +>>>>>>> 4f2c6f4... Major rewrite. Added support for macOS, Debian, Ubuntu. Added test/validation script. } phase_3() { @@ -376,7 +511,11 @@ phase_3() { if mac; then install_vscode_mac else +<<<<<<< HEAD if dpkg-query -s libx11-6; then +======= + if dpkg-query -s xserver-xorg >> /dev/null; then +>>>>>>> 4f2c6f4... Major rewrite. Added support for macOS, Debian, Ubuntu. Added test/validation script. install_vscode_linux else echo "Not installing Visual Studio Code because it looks like XWindows is not installed." @@ -393,4 +532,8 @@ main() { echo "Congratulations, installation is complete. 😁" } -main \ No newline at end of file +<<<<<<< HEAD +main +======= +main +>>>>>>> 4f2c6f4... Major rewrite. Added support for macOS, Debian, Ubuntu. Added test/validation script. diff --git a/test/README.md b/test/README.md index dcf3590..3e5c18a 100644 --- a/test/README.md +++ b/test/README.md @@ -18,21 +18,21 @@ Test support for the following platforms. The general process is: 1. Start from a fresh OS image. 1. Start the SSH service if necessary: `sudo /sbin/service ssh start` 1. Push down the contents of the pico-setup repo from your dev host: `scp -r ~/git/raspberrypi/pico-setup/ pi@pi4:` -1. SSH to the test host and execute the setup: `pico-setup/pico_setup.sh` -1. Test the setup: "ssh pi@pi4 pico-setup/test/test" +1. SSH to the test host and execute the setup: `ssh pi@pi4 pico-setup/pico_setup.sh` +1. Logout to pick up env variables and test the setup: `ssh pi@pi4 pico-setup/test/test` -### Raspberry Pi OS Full (32-bit) on Raspberry Pi 4B +### Raspberry Pi OS (32-bit) on Raspberry Pi 4B This is the baseline platform, what most users will have. Write fresh SD card with Raspberry Pi Imager. -### Raspberry Pi OS Full (64-bit) on Raspberry Pi 4B +### Raspberry Pi OS (64-bit) on Raspberry Pi 4B If all of the dependencies (APT repo, etc) are in good shape, this should work the same as the 32-bit OS, since we don't do anything explicitly for one or the other. Write fresh SD card with Raspberry Pi Imager. ### Raspberry Pi OS Lite (32-bit) on Raspberry Pi 4B -Should be the same as the full OS, but doesn't attempt to install VS Code, because there will be no XWindows. +Should be the same as the full OS. Currently, this will install Visual Studio Code, but that may change. Write fresh SD card with Raspberry Pi Imager. @@ -80,20 +80,27 @@ passwd ubuntu ``` ### Debian 10 (Buster) on Graviton2 -Can be rented on [EC2](https://aws.amazon.com/marketplace/pp/B0859NK4HC?ref_=aws-mp-console-subscription-detail) for pennies/hour. Recommend t3.micro with 8 GiB EBS volume. Default user is `admin`. You will have to use sudo to set the user's password: +Can be rented on [EC2](https://aws.amazon.com/marketplace/pp/B0859NK4HC?ref_=aws-mp-console-subscription-detail) for pennies/hour. Recommend t4g.micro with 8 GiB EBS volume. Default user is `admin`. You will have to use sudo to set the user's password: ```shell sudo -i passwd admin ``` ### Windows Server 2016 Base on x86_64 -https://aws.amazon.com/marketplace/server/procurement?productId=13c2dbc9-57fc-4958-922e-a1ba7e223b0d +Not yet tested. See https://aws.amazon.com/marketplace/server/procurement?productId=13c2dbc9-57fc-4958-922e-a1ba7e223b0d. -### Windows Server 2016 Base on x86_64 -https://aws.amazon.com/marketplace/server/procurement?productId=ef297a90-3ad0-4674-83b4-7f0ec07c39bb +### Ubuntu 20.04 on WSL2 on Windows Server 2019 Base on x86_64 +Not yet tested. https://aws.amazon.com/marketplace/server/procurement?productId=ef297a90-3ad0-4674-83b4-7f0ec07c39bb. + +t3.large + +https://docs.microsoft.com/en-us/windows/wsl/install-on-server + +Download Linux archive + +Find archive and extract all +Run the program. -### Ubuntu on WSL2 on Windows Server 2016 Base on x86_64 -Not yet tested. ### Debian 10 (Buster) on WSL2 on Windows Server 2016 Base on x86_64 Not yet tested. diff --git a/test/test b/test/test index 74d4041..7b4dc3d 100755 --- a/test/test +++ b/test/test @@ -8,12 +8,46 @@ set -ex WORKING_DIR="$(pwd)/pico" +<<<<<<< HEAD +======= +linux() { + # Returns true iff this is running on Linux + uname | grep -q "^Linux$" + return ${?} +} + +debian() { + # Returns true iff this is running on Debian + grep -q '^NAME="Debian GNU/Linux"$' /etc/os-release + return ${?} +} + +ubuntu() { + # Returns true iff this is running on Ubuntu + grep -q '^NAME="Ubuntu"$' /etc/os-release + return ${?} +} + +>>>>>>> 4f2c6f4... Major rewrite. Added support for macOS, Debian, Ubuntu. Added test/validation script. mac() { # Returns true iff this is running on macOS and presumably Apple hardware uname | grep -q "^Darwin$" return ${?} } +<<<<<<< HEAD +======= +raspberry_pi() { + # Returns true iff this is running on a Raspberry Pi computer, regardless of the OS + if [ -f /proc/cpuinfo ]; then + grep -q "^Model\s*: Raspberry Pi" /proc/cpuinfo + return ${?} + fi + return 1 +} + + +>>>>>>> 4f2c6f4... Major rewrite. Added support for macOS, Debian, Ubuntu. Added test/validation script. fail() { # Outputs a failure message and exits with the error code output by the previous call. # All args are echoed as a failure message. @@ -48,6 +82,17 @@ test_pico_sdk() { test "${PICO_SDK_PATH}" = "${WORKING_DIR}/pico-sdk" || fail } +<<<<<<< HEAD +======= +test_uart() { + # test that the UART is configured. Only works on Raspberry Pi OS on Raspberry Pi hardware. + dpkg-query -s minicom || fail + grep -q "enable_uart=1" /boot/config.txt || fail + # note that the test for console=serial0 tests for the absence of a string + grep -q "console=serial0" /boot/cmdline.txt && fail +} + +>>>>>>> 4f2c6f4... Major rewrite. Added support for macOS, Debian, Ubuntu. Added test/validation script. test_pico_examples() { test_git_repo pico-examples @@ -98,9 +143,16 @@ test_vscode_linux() { } test_vscode_mac() { +<<<<<<< HEAD echo "This script can't tell whether Visual Studio Code is installed on macOS" } +======= + echo "Not yet implemented: testing Visual Studio Code on macOS" +} + + +>>>>>>> 4f2c6f4... Major rewrite. Added support for macOS, Debian, Ubuntu. Added test/validation script. # execute tests if mac; then test_toolchain_mac @@ -110,6 +162,13 @@ fi test_pico_sdk +<<<<<<< HEAD +======= +if raspbian && raspberry_pi; then + test_uart +fi + +>>>>>>> 4f2c6f4... Major rewrite. Added support for macOS, Debian, Ubuntu. Added test/validation script. test_pico_examples test_pico_extras test_pico_playground @@ -119,7 +178,13 @@ test_picotool if mac; then test_vscode_mac else +<<<<<<< HEAD test_vscode_mac +======= + if dpkg-query -s xserver-xorg >> /dev/null && ! (debian || ubuntu); then + test_vscode_linux + fi +>>>>>>> 4f2c6f4... Major rewrite. Added support for macOS, Debian, Ubuntu. Added test/validation script. fi echo "Tests passed! 😁" From 2d1dafe8705f319bc26530cf930aa29c4403a83d Mon Sep 17 00:00:00 2001 From: Michael Stoops Date: Fri, 2 Apr 2021 13:21:44 -0700 Subject: [PATCH 3/6] Adding file missed in previous commit --- pico_setup.sh | 157 -------------------------------------------------- 1 file changed, 157 deletions(-) diff --git a/pico_setup.sh b/pico_setup.sh index 8e18f5c..66c647f 100755 --- a/pico_setup.sh +++ b/pico_setup.sh @@ -161,23 +161,6 @@ clone_repo() { DEST="${WORKING_DIR}/${REPO_NAME}" if [ -d "${DEST}" ]; then -<<<<<<< HEAD - echo "Not cloning $DEST because it already exists" - else - echo "Cloning $REPO_URL" - git clone -b "$BRANCH" "$REPO_URL" ${*} - - # Any submodules - cd "$DEST" - git submodule update --init - fi -} - -set_envs() { - # Permanently sets environment variables by adding them to the current user's profile script - # arguments should be in the form of FOO=foo BAR=bar - -======= echo "Not cloning ${DEST} because it already exists. If you really want to start over, delete it: rm -rf ${DEST}" else echo "Cloning ${REPO_URL}" @@ -193,7 +176,6 @@ set_envs() { # Permanently sets environment variables by adding them to the current user's profile script # arguments should be in the form of FOO=foo BAR=bar ->>>>>>> 4f2c6f4... Major rewrite. Added support for macOS, Debian, Ubuntu. Added test/validation script. # detect appropriate file for setting env vars if echo "${SHELL}" | grep -q zsh; then # zsh detected @@ -218,120 +200,6 @@ set_envs() { export "${EXPR}" # set for later -<<<<<<< HEAD - set_env "${FILE}" "${EXPR}" - done -} - -set_env() { - # Permanently sets one environment variable for bash - # $1 must be the file where the env is stored - # $2 should be in the form of VAR=value - FILE="${1}" - EXPR="${2}" - - if ! grep -q "^export ${EXPR}$" ${FILE}; then - echo "Setting env variable ${EXPR} in ${FILE}" - echo "export ${EXPR}" >> ${FILE} - fi -} - -setup_sdk() { - # Downloads and builds the SDK - cd "${WORKING_DIR}" - - clone_repo pico-sdk - - # Set env var PICO_SDK_PATH - REPO_UPPER=$(echo ${REPO_NAME} | tr "[:lower:]" "[:upper:]") - REPO_UPPER=$(echo ${REPO_UPPER} | tr "-" "_") - set_envs "${REPO_UPPER}_PATH=$DEST" -} - -enable_uart() { - # Enable UART - sudo apt install -y minicom - echo "Disabling Linux serial console (UART) so we can use it for pico" - sudo raspi-config nonint do_serial 2 - echo "You must run sudo reboot to finish UART setup" -} - -phase_1() { - # Setup minimum dev environment - echo "Entering phase 1: Setup minimum dev environment" - - if mac; then - install_toolchain_mac - else - install_toolchain_linux - fi - - create_working_dir - setup_sdk - - if linux && pi; then - if [[ "$SKIP_UART" == 1 ]]; then - echo "Skipping UART configuration" - else - enable_uart - fi - else - echo "Not configuring UART because this is not running Raspberry Pi OS on a Raspberry Pi computer" - fi -} - -build_examples() { - # Build a couple of examples - echo "Building selected examples" - - cd "$WORKING_DIR/pico-examples" - mkdir -p build - cd build - cmake ../ -DCMAKE_BUILD_TYPE=Debug - - for EXAMPLE in blink hello_world; do - echo "Building $EXAMPLE" - cd "$EXAMPLE" - make -j${JNUM} - cd .. - done -} - -phase_2() { - # Setup tutorial repos - echo "Entering phase 2: Setting up tutorial repos" - - for REPO_NAME in pico-examples pico-extras pico-playground; do - clone_repo "${REPO_NAME}" - done - - build_examples -} - -setup_picotool() { - # Downloads, builds, and installs picotool - echo "Setting up picotool" - - cd "${WORKING_DIR}" - - clone_repo picotool - cd "${WORKING_DIR}/picotool" - mkdir -p build - cd build - cmake ../ - make -j${JNUM} - - echo "Installing picotool to /usr/local/bin/picotool" - sudo cp picotool /usr/local/bin/ -} - -setup_openocd() { - # Download, build, and install OpenOCD for picoprobe and bit-banging without picoprobe - echo "Setting up OpenOCD" - - cd "${WORKING_DIR}" - -======= if ! grep -q "^export ${EXPR}$" ${FILE}; then echo "Setting env variable ${EXPR} in ${FILE}" echo "export ${EXPR}" >> ${FILE} @@ -430,7 +298,6 @@ setup_openocd() { cd "${WORKING_DIR}" ->>>>>>> 4f2c6f4... Major rewrite. Added support for macOS, Debian, Ubuntu. Added test/validation script. clone_repo openocd picoprobe --depth=1 cd "${WORKING_DIR}/openocd" ./bootstrap @@ -463,28 +330,16 @@ install_vscode_linux() { # VS Code is specially added to Raspberry Pi OS repos. Need to add the right repos to make it work on Debian/Ubuntu. if debian || ubuntu; then -<<<<<<< HEAD - echo "Visual Studio Code installation currently doesn't work on Debian and Ubuntu" -======= echo "Not yet implemented: testing Visual Studio Code on Debian/Ubuntu" ->>>>>>> 4f2c6f4... Major rewrite. Added support for macOS, Debian, Ubuntu. Added test/validation script. return fi echo "Installing Visual Studio Code" -<<<<<<< HEAD cd "${WORKING_DIR}" sudo apt install -y code -======= - - cd "${WORKING_DIR}" - - sudo apt install -y code - ->>>>>>> 4f2c6f4... Major rewrite. Added support for macOS, Debian, Ubuntu. Added test/validation script. # Get extensions code --install-extension marus25.cortex-debug code --install-extension ms-vscode.cmake-tools @@ -492,11 +347,7 @@ install_vscode_linux() { } install_vscode_mac() { -<<<<<<< HEAD - echo "This script cannot install Visual Studio Code on macOS" -======= echo "Not yet implemented: installing Visual Studio Code on macOS" ->>>>>>> 4f2c6f4... Major rewrite. Added support for macOS, Debian, Ubuntu. Added test/validation script. } phase_3() { @@ -511,11 +362,7 @@ phase_3() { if mac; then install_vscode_mac else -<<<<<<< HEAD - if dpkg-query -s libx11-6; then -======= if dpkg-query -s xserver-xorg >> /dev/null; then ->>>>>>> 4f2c6f4... Major rewrite. Added support for macOS, Debian, Ubuntu. Added test/validation script. install_vscode_linux else echo "Not installing Visual Studio Code because it looks like XWindows is not installed." @@ -532,8 +379,4 @@ main() { echo "Congratulations, installation is complete. 😁" } -<<<<<<< HEAD -main -======= main ->>>>>>> 4f2c6f4... Major rewrite. Added support for macOS, Debian, Ubuntu. Added test/validation script. From 9fbed81df7dc8340e3b9f8a6cb68ca4fcf6d9f58 Mon Sep 17 00:00:00 2001 From: Michael Stoops Date: Fri, 2 Apr 2021 16:04:24 -0700 Subject: [PATCH 4/6] Bug fixes and improved compatibility. --- README.md | 22 ++++++---------------- pico_setup.sh | 36 +++++++++++++++++------------------- test/README.md | 39 +++++++++++++++++++++++++-------------- test/test | 22 ---------------------- 4 files changed, 48 insertions(+), 71 deletions(-) diff --git a/README.md b/README.md index 7d1f4be..4b030cc 100644 --- a/README.md +++ b/README.md @@ -4,9 +4,6 @@ Raspberry Pi Pico Setup provides a script for installing the Pico SDK and toolch # How-To -<<<<<<< HEAD -Download and run `pico_setup.sh`. -======= Download and run `pico_setup.sh`: ```shell wget https://raw.githubusercontent.com/raspberrypi/pico-setup/master/pico_setup.sh @@ -16,30 +13,24 @@ chmod +x pico_setup The script uses sudo, so you may need to enter your password. After the script is complete, reboot to ensure that all changes take effect, such as the UART settings and environment variables. ->>>>>>> 4f2c6f4... Major rewrite. Added support for macOS, Debian, Ubuntu. Added test/validation script. If you want the testing script and documentation, you can clone the git repo too. # Support +This script works on most Debian-derived Linux distros and macOS, running on common Raspberry Pi, PC, and Mac hardware. This ***DOESN'T*** mean that all of the pico tools work properly on these platforms. It just means that this script runs and passes its own tests. + Operating systems: * Raspberry Pi OS (32-bit) * Debian 10 (Buster) * Ubuntu 20.10 (Groovy) * macOS 11 (Big Sur) +* Ubuntu 20.04 on Windows Subsystem for Linux on Windows Server 2019 Base +* Debian GNU/Linux 1.3.0.0 on Windows Subsystem for Linux on Windows Server 2019 Base -Hardware: -<<<<<<< HEAD -* Raspberry Pi 2/3/4/400 -* PC (x86_64) -* Mac (both Intel and Apple Silicon) - -Other versions may work, but haven't been tested. Use at your own risk. - -# Testing +This script does not support Windows natively, only Windows Subsystem for Linux. -See [test/README.md](test/README.md) -======= +Hardware: * Raspberry Pi 2/3/4/400/CM3/CM4 * PC (x86_64) * Mac (both Intel and Apple Silicon) @@ -49,4 +40,3 @@ Other OSes and hardware may work, but haven't been tested. Use at your own risk. # Testing See [test/README.md](test/README.md). ->>>>>>> 4f2c6f4... Major rewrite. Added support for macOS, Debian, Ubuntu. Added test/validation script. diff --git a/pico_setup.sh b/pico_setup.sh index 66c647f..a525b23 100755 --- a/pico_setup.sh +++ b/pico_setup.sh @@ -20,7 +20,6 @@ # Download and install Visual Studio Code and required extensions - # Exit on error set -e # Show all commands @@ -112,7 +111,7 @@ phase_0() { install_toolchain_linux() { # Install toolchain for Linux - DEPS="git cmake gcc-arm-none-eabi build-essential gdb-multiarch automake autoconf build-essential texinfo libtool libftdi-dev libusb-1.0-0-dev" + DEPS="python3 git cmake gcc-arm-none-eabi build-essential gdb-multiarch automake autoconf build-essential texinfo libtool libftdi-dev libusb-1.0-0-dev" if debian || ubuntu; then DEPS="${DEPS} pkg-config libstdc++-arm-none-eabi-newlib" fi @@ -172,9 +171,10 @@ clone_repo() { fi } -set_envs() { - # Permanently sets environment variables by adding them to the current user's profile script - # arguments should be in the form of FOO=foo BAR=bar +set_env() { + # Permanently sets an environment variable by adding it to the current user's profile script + # $1 should be in the form of FOO=foo + EXPR="${1}" # detect appropriate file for setting env vars if echo "${SHELL}" | grep -q zsh; then @@ -186,25 +186,23 @@ set_envs() { fi # ensure that appends go to a new line - if [ -f ${FILE} ]; then - if tail -n 1 ${FILE} | grep -q "^$"; then + if [ -f "${FILE}" ]; then + if tail -n 1 "${FILE}" | grep -q "^$"; then echo "${FILE} exists and has trailing newline." else echo "${FILE} exists but has no trailing newline. Adding newline." - echo >> ${FILE} + echo >> "${FILE}" fi fi - for EXPR in ${*}; do - # set for now - export "${EXPR}" - - # set for later - if ! grep -q "^export ${EXPR}$" ${FILE}; then - echo "Setting env variable ${EXPR} in ${FILE}" - echo "export ${EXPR}" >> ${FILE} - fi - done + # set for now + export "${EXPR}" + + # set for later + if ! grep -q "^export ${EXPR}$" "${FILE}"; then + echo "Setting env variable ${EXPR} in ${FILE}" + echo "export \"${EXPR}\"" >> "${FILE}" + fi } setup_sdk() { @@ -216,7 +214,7 @@ setup_sdk() { # Set env var PICO_SDK_PATH REPO_UPPER=$(echo ${REPO_NAME} | tr "[:lower:]" "[:upper:]") REPO_UPPER=$(echo ${REPO_UPPER} | tr "-" "_") - set_envs "${REPO_UPPER}_PATH=$DEST" + set_env "${REPO_UPPER}_PATH=$DEST" } enable_uart() { diff --git a/test/README.md b/test/README.md index 3e5c18a..d31ab5f 100644 --- a/test/README.md +++ b/test/README.md @@ -32,11 +32,18 @@ If all of the dependencies (APT repo, etc) are in good shape, this should work t Write fresh SD card with Raspberry Pi Imager. ### Raspberry Pi OS Lite (32-bit) on Raspberry Pi 4B -Should be the same as the full OS. Currently, this will install Visual Studio Code, but that may change. +Should be the same as the full OS, but doesn't install Visual Studio Code because there's no XWindows. Write fresh SD card with Raspberry Pi Imager. ### Ubuntu Desktop 20.10 (64-bit) on Raspberry Pi 4B +Not yet tested. + +Less common. Should work a lot like Raspberry Pi OS, but with a couple different package dependencies. + +Write fresh SD card with Raspberry Pi Imager. + +### Ubuntu Server 20.10 (32-bit) on Raspberry Pi 4B Less common. Should work a lot like Raspberry Pi OS, but with a couple different package dependencies. Write fresh SD card with Raspberry Pi Imager. @@ -89,25 +96,29 @@ passwd admin ### Windows Server 2016 Base on x86_64 Not yet tested. See https://aws.amazon.com/marketplace/server/procurement?productId=13c2dbc9-57fc-4958-922e-a1ba7e223b0d. -### Ubuntu 20.04 on WSL2 on Windows Server 2019 Base on x86_64 -Not yet tested. https://aws.amazon.com/marketplace/server/procurement?productId=ef297a90-3ad0-4674-83b4-7f0ec07c39bb. - -t3.large +### Ubuntu 20.04 on WSL1 on Windows Server 2019 Base on x86_64 +Can be rented on [EC2](https://aws.amazon.com/marketplace/server/procurement?productId=ef297a90-3ad0-4674-83b4-7f0ec07c39bb) for pennies/hour. Recommend t3.large. Default user is `ec2-user`. Connect with Microsoft Remote Desktop. -https://docs.microsoft.com/en-us/windows/wsl/install-on-server +Install WSL according to https://docs.microsoft.com/en-us/windows/wsl/install-on-server. Install Ubuntu for WSL -Download Linux archive - -Find archive and extract all -Run the program. +In the Linux shell: +```shell +wget https://raw.githubusercontent.com/raspberrypi/pico-setup/master/pico_setup.sh +chmod +x pico_setup.sh +./pico_setup.sh +``` +### Debian GNU/Linux 1.3.0.0 on WSL1 on Windows Server 2019 Base on x86_64 +Similar instructions as Ubuntu, but using the Debian WSL package and you'll have to explicitly install wget: +```shell +sudo apt update +sudo apt install -y wget +``` -### Debian 10 (Buster) on WSL2 on Windows Server 2016 Base on x86_64 -Not yet tested. +Currently fails due to lack of python3. ## Scenarios Test some scenarios: * Shells: bash, zsh. It should be enough to switch shells and rerun the installer and test. You don't have to wipe the SD card/disk. * .profile or .zprofile doesn't end in newline -* PWD containing space -* Raspberry Pi OS Lite (32-bit) shouldn't install VS Code +* PWD containing space. The script seems to handle it but a OpenOCD submodule, jimctl, doesn't. diff --git a/test/test b/test/test index 7b4dc3d..af957df 100755 --- a/test/test +++ b/test/test @@ -8,8 +8,6 @@ set -ex WORKING_DIR="$(pwd)/pico" -<<<<<<< HEAD -======= linux() { # Returns true iff this is running on Linux uname | grep -q "^Linux$" @@ -28,15 +26,12 @@ ubuntu() { return ${?} } ->>>>>>> 4f2c6f4... Major rewrite. Added support for macOS, Debian, Ubuntu. Added test/validation script. mac() { # Returns true iff this is running on macOS and presumably Apple hardware uname | grep -q "^Darwin$" return ${?} } -<<<<<<< HEAD -======= raspberry_pi() { # Returns true iff this is running on a Raspberry Pi computer, regardless of the OS if [ -f /proc/cpuinfo ]; then @@ -47,7 +42,6 @@ raspberry_pi() { } ->>>>>>> 4f2c6f4... Major rewrite. Added support for macOS, Debian, Ubuntu. Added test/validation script. fail() { # Outputs a failure message and exits with the error code output by the previous call. # All args are echoed as a failure message. @@ -82,8 +76,6 @@ test_pico_sdk() { test "${PICO_SDK_PATH}" = "${WORKING_DIR}/pico-sdk" || fail } -<<<<<<< HEAD -======= test_uart() { # test that the UART is configured. Only works on Raspberry Pi OS on Raspberry Pi hardware. dpkg-query -s minicom || fail @@ -92,7 +84,6 @@ test_uart() { grep -q "console=serial0" /boot/cmdline.txt && fail } ->>>>>>> 4f2c6f4... Major rewrite. Added support for macOS, Debian, Ubuntu. Added test/validation script. test_pico_examples() { test_git_repo pico-examples @@ -143,16 +134,10 @@ test_vscode_linux() { } test_vscode_mac() { -<<<<<<< HEAD - echo "This script can't tell whether Visual Studio Code is installed on macOS" -} - -======= echo "Not yet implemented: testing Visual Studio Code on macOS" } ->>>>>>> 4f2c6f4... Major rewrite. Added support for macOS, Debian, Ubuntu. Added test/validation script. # execute tests if mac; then test_toolchain_mac @@ -162,13 +147,10 @@ fi test_pico_sdk -<<<<<<< HEAD -======= if raspbian && raspberry_pi; then test_uart fi ->>>>>>> 4f2c6f4... Major rewrite. Added support for macOS, Debian, Ubuntu. Added test/validation script. test_pico_examples test_pico_extras test_pico_playground @@ -178,13 +160,9 @@ test_picotool if mac; then test_vscode_mac else -<<<<<<< HEAD - test_vscode_mac -======= if dpkg-query -s xserver-xorg >> /dev/null && ! (debian || ubuntu); then test_vscode_linux fi ->>>>>>> 4f2c6f4... Major rewrite. Added support for macOS, Debian, Ubuntu. Added test/validation script. fi echo "Tests passed! 😁" From 049289a4190aab46bd0ecbb09a13fe7f11194ffb Mon Sep 17 00:00:00 2001 From: Michael Stoops Date: Wed, 7 Apr 2021 01:19:25 -0700 Subject: [PATCH 5/6] Numerous changes coming from code review --- README.md | 27 +++++----- pico_setup.sh | 119 +++++++++++++++++++++--------------------- test/README.md | 138 ++++++++++++++++++++----------------------------- test/test | 4 +- 4 files changed, 133 insertions(+), 155 deletions(-) diff --git a/README.md b/README.md index 4b030cc..251d306 100644 --- a/README.md +++ b/README.md @@ -2,41 +2,44 @@ Raspberry Pi Pico Setup provides a script for installing the Pico SDK and toolchain. -# How-To +## How-To Download and run `pico_setup.sh`: + ```shell wget https://raw.githubusercontent.com/raspberrypi/pico-setup/master/pico_setup.sh -chmod +x pico_setup -./pico_setup +chmod +x pico_setup.sh +./pico_setup.sh ``` + The script uses sudo, so you may need to enter your password. After the script is complete, reboot to ensure that all changes take effect, such as the UART settings and environment variables. If you want the testing script and documentation, you can clone the git repo too. -# Support +## Support This script works on most Debian-derived Linux distros and macOS, running on common Raspberry Pi, PC, and Mac hardware. This ***DOESN'T*** mean that all of the pico tools work properly on these platforms. It just means that this script runs and passes its own tests. Operating systems: + * Raspberry Pi OS (32-bit) * Debian 10 (Buster) -* Ubuntu 20.10 (Groovy) +* Ubuntu 20.04 or later * macOS 11 (Big Sur) -* Ubuntu 20.04 on Windows Subsystem for Linux on Windows Server 2019 Base -* Debian GNU/Linux 1.3.0.0 on Windows Subsystem for Linux on Windows Server 2019 Base - -This script does not support Windows natively, only Windows Subsystem for Linux. +* Windows Subsystem for Linux Hardware: -* Raspberry Pi 2/3/4/400/CM3/CM4 + +* Any model of Raspberry Pi * PC (x86_64) * Mac (both Intel and Apple Silicon) -Other OSes and hardware may work, but haven't been tested. Use at your own risk. +Visual Studio Code may not run well on Raspberry Pi 1 and Zero because of their smaller RAM capacity, but the rest of the toolkit works fine. + +Other OSes and hardware _may_ work, but haven't been tested. Use at your own risk. -# Testing +## Testing See [test/README.md](test/README.md). diff --git a/pico_setup.sh b/pico_setup.sh index a525b23..85398a0 100755 --- a/pico_setup.sh +++ b/pico_setup.sh @@ -3,12 +3,12 @@ # Phase 0: Preflight check # Verify baseline dependencies -# Phase 1: Setup minimum dev environment -# Install the toolchain +# Phase 1: Setup dev environment +# Install the software packages from APT or Homebrew # Create a directory called pico # Download the pico-sdk repository and submodules -# Define env variables for repo: PICO_SDK_PATH -# Configure the Raspberry Pi UART for use with Raspberry Pi Pico +# Define env variables: PICO_SDK_PATH +# On Raspberry Pi only: configure the UART for use with Raspberry Pi Pico # Phase 2: Setting up tutorial repos # Download pico-examples, pico-extras, pico-playground repositories, and submodules @@ -24,13 +24,19 @@ set -e # Show all commands set -x - +# Trying to use an non-existent variable is an error +set -u # Number of cores when running make JNUM=4 # Where will the output go? -WORKING_DIR="$(pwd)/pico" +if printenv TARGET_DIR; then + echo "Using target dir from \$TARGET_DIR: ${TARGET_DIR}" +else + TARGET_DIR="$(pwd)/pico" + echo "Using target dir: ${TARGET_DIR}" +fi linux() { @@ -73,7 +79,7 @@ raspberry_pi() { } phase_0() { - # Preflight the check + # Preflight check # Checks the baseline dependencies. If you don't have these, this script won't work. echo "Entering phase 0: Preflight check" @@ -108,12 +114,12 @@ phase_0() { fi } -install_toolchain_linux() { - # Install toolchain for Linux +install_dev_env_deps_linux() { + # Install development environment dependencies for Linux - DEPS="python3 git cmake gcc-arm-none-eabi build-essential gdb-multiarch automake autoconf build-essential texinfo libtool libftdi-dev libusb-1.0-0-dev" + DEPS="python3 git cmake gcc-arm-none-eabi build-essential gdb-multiarch automake autoconf build-essential texinfo libtool libftdi-dev libusb-1.0-0-dev minicom pkg-config" if debian || ubuntu; then - DEPS="${DEPS} pkg-config libstdc++-arm-none-eabi-newlib" + DEPS="${DEPS} libstdc++-arm-none-eabi-newlib" fi sudo apt install -y ${DEPS} } @@ -124,51 +130,55 @@ brew_install_idempotent() { return ${?} } -install_toolchain_mac() { - # Install dependencies for mac +install_dev_env_deps_mac() { + # Install development environment dependencies for mac - brew_install_idempotent git cmake pkg-config libtool automake libusb wget pkg-config gcc texinfo - brew tap ArmMbed/homebrew-formulae - brew_install_idempotent arm-none-eabi-gcc + brew_install_idempotent git cmake pkg-config libtool automake libusb wget pkg-config gcc texinfo minicom ArmMbed/homebrew-formulae/arm-none-eabi-gcc } create_working_dir() { # Creates ./pico directory if necessary - mkdir -p "${WORKING_DIR}" + mkdir -p "${TARGET_DIR}" } -clone_repo() { +clone_raspberrypi_repo() { # Clones the given repo name from GitHub and inits any submodules # $1 should be the full name of the repo, ex: pico-sdk # $2 should be the branch name. Defaults to master. # all other args are passed to git clone REPO_NAME="${1}" - if shift && [ "${1}" ]; then + if shift && [ ${#} -gt 0 ]; then BRANCH="${1}" + # Can't just say `shift` because `set -e` will think it's an error and terminate the script. + shift || true else BRANCH=master fi - if shift; then - # $* contains more args - true - fi - cd "${WORKING_DIR}" + # Save the working directory + pushd "${TARGET_DIR}" >> /dev/null REPO_URL="https://github.com/raspberrypi/${REPO_NAME}.git" - DEST="${WORKING_DIR}/${REPO_NAME}" + DEST="${TARGET_DIR}/${REPO_NAME}" if [ -d "${DEST}" ]; then echo "Not cloning ${DEST} because it already exists. If you really want to start over, delete it: rm -rf ${DEST}" else echo "Cloning ${REPO_URL}" - git clone -b "${BRANCH}" "${REPO_URL}" ${*} + if [ ${#} -gt 0 ]; then + git clone -b "${BRANCH}" "${REPO_URL}" ${*} + else + git clone -b "${BRANCH}" "${REPO_URL}" + fi # Any submodules cd "${DEST}" git submodule update --init fi + + # Restore working directory + popd >> /dev/null } set_env() { @@ -187,10 +197,8 @@ set_env() { # ensure that appends go to a new line if [ -f "${FILE}" ]; then - if tail -n 1 "${FILE}" | grep -q "^$"; then - echo "${FILE} exists and has trailing newline." - else - echo "${FILE} exists but has no trailing newline. Adding newline." + if ! ( tail -n 1 "${FILE}" | grep -q "^$" ); then + # FILE exists but has no trailing newline. Adding newline. echo >> "${FILE}" fi fi @@ -206,20 +214,15 @@ set_env() { } setup_sdk() { - # Downloads and builds the SDK - cd "${WORKING_DIR}" - - clone_repo pico-sdk + # Download the SDK + clone_raspberrypi_repo pico-sdk # Set env var PICO_SDK_PATH - REPO_UPPER=$(echo ${REPO_NAME} | tr "[:lower:]" "[:upper:]") - REPO_UPPER=$(echo ${REPO_UPPER} | tr "-" "_") - set_env "${REPO_UPPER}_PATH=$DEST" + set_env "PICO_SDK_PATH=${TARGET_DIR}/pico-sdk" } enable_uart() { # Enable UART - sudo apt install -y minicom echo "Disabling Linux serial console (UART) so we can use it for pico" sudo raspi-config nonint do_serial 2 echo "You must run sudo reboot to finish UART setup" @@ -230,18 +233,18 @@ phase_1() { echo "Entering phase 1: Setup minimum dev environment" if mac; then - install_toolchain_mac + install_dev_env_deps_mac else - install_toolchain_linux + install_dev_env_deps_linux fi create_working_dir setup_sdk - if raspbian && raspberry_pi; then + if raspberry_pi && which raspi-config >> /dev/null; then enable_uart else - echo "Not configuring UART because this is not running Raspberry Pi OS on a Raspberry Pi computer" + echo "Not configuring UART because this is not a Raspberry Pi computer, or raspi-config is unavailable." fi } @@ -249,7 +252,7 @@ build_examples() { # Build a couple of examples echo "Building selected examples" - cd "$WORKING_DIR/pico-examples" + cd "$TARGET_DIR/pico-examples" mkdir -p build cd build cmake ../ -DCMAKE_BUILD_TYPE=Debug @@ -267,7 +270,7 @@ phase_2() { echo "Entering phase 2: Setting up tutorial repos" for REPO_NAME in pico-examples pico-extras pico-playground; do - clone_repo "${REPO_NAME}" + clone_raspberrypi_repo "${REPO_NAME}" done build_examples @@ -277,10 +280,10 @@ setup_picotool() { # Downloads, builds, and installs picotool echo "Setting up picotool" - cd "${WORKING_DIR}" + cd "${TARGET_DIR}" - clone_repo picotool - cd "${WORKING_DIR}/picotool" + clone_raspberrypi_repo picotool + cd "${TARGET_DIR}/picotool" mkdir -p build cd build cmake ../ @@ -294,10 +297,10 @@ setup_openocd() { # Download, build, and install OpenOCD for picoprobe and bit-banging without picoprobe echo "Setting up OpenOCD" - cd "${WORKING_DIR}" + cd "${TARGET_DIR}" - clone_repo openocd picoprobe --depth=1 - cd "${WORKING_DIR}/openocd" + clone_raspberrypi_repo openocd picoprobe --depth=1 + cd "${TARGET_DIR}/openocd" ./bootstrap OPTS="--enable-ftdi --enable-bcm2835gpio --enable-picoprobe" if linux; then @@ -313,10 +316,10 @@ setup_picoprobe() { # Download and build picoprobe. Requires that OpenOCD is already setup echo "Setting up picoprobe" - cd "${WORKING_DIR}" + cd "${TARGET_DIR}" - clone_repo picoprobe - cd "${WORKING_DIR}/picoprobe" + clone_raspberrypi_repo picoprobe + cd "${TARGET_DIR}/picoprobe" mkdir -p build cd build cmake .. @@ -326,16 +329,14 @@ setup_picoprobe() { install_vscode_linux() { # Install Visual Studio Code - # VS Code is specially added to Raspberry Pi OS repos. Need to add the right repos to make it work on Debian/Ubuntu. - if debian || ubuntu; then - echo "Not yet implemented: testing Visual Studio Code on Debian/Ubuntu" + # VS Code is specially added to Raspberry Pi OS repos, but might not be present on Debian/Ubuntu. So we check first. + if ! apt list code; then + echo "It appears that your APT repos do not offer Visual Studio Code. Skipping." return fi echo "Installing Visual Studio Code" - cd "${WORKING_DIR}" - sudo apt install -y code # Get extensions @@ -374,7 +375,7 @@ main() { phase_2 phase_3 - echo "Congratulations, installation is complete. 😁" + echo "Congratulations, installation is complete. :D" } main diff --git a/test/README.md b/test/README.md index d31ab5f..fde2e66 100644 --- a/test/README.md +++ b/test/README.md @@ -3,122 +3,96 @@ The tests validate that `pico_setup.sh` _seems_ to setup your system correctly. It can be fooled. It does not test that the SDK or tools themselves work correctly, just that the setup script did its thing. To execute the tests, first run `pico_setup.sh` from wherever you want to install the pico dev environment: + ```shell ./pico_setup.sh ``` + Logout and back in, so that your shell will pick up its environment variables. Then run the test from the same location as you ran `pico_setup.sh`: + ```shell ./test/test ``` -# What to test - -## Platform support -Test support for the following platforms. The general process is: -1. Start from a fresh OS image. -1. Start the SSH service if necessary: `sudo /sbin/service ssh start` -1. Push down the contents of the pico-setup repo from your dev host: `scp -r ~/git/raspberrypi/pico-setup/ pi@pi4:` -1. SSH to the test host and execute the setup: `ssh pi@pi4 pico-setup/pico_setup.sh` -1. Logout to pick up env variables and test the setup: `ssh pi@pi4 pico-setup/test/test` +## What to test -### Raspberry Pi OS (32-bit) on Raspberry Pi 4B -This is the baseline platform, what most users will have. +### Platform support -Write fresh SD card with Raspberry Pi Imager. +We can test platform support by getting the platforms and verifying the script on each. The general process is: -### Raspberry Pi OS (64-bit) on Raspberry Pi 4B -If all of the dependencies (APT repo, etc) are in good shape, this should work the same as the 32-bit OS, since we don't do anything explicitly for one or the other. +1. Start from a fresh OS image. +1. Do any necessary setup. +1.1. On Raspberry Pi OS, you'll need to start the SSH service if necessary: `sudo /sbin/service ssh start` +1.1. On EC2, you'll need to set a password: `sudo -i passwd $USER` +1. Push the contents of the pico-setup repo from your dev host: `scp -r ~/git/raspberrypi/pico-setup/ pi@${TESTING_HOST}:` +1. SSH to the test host and execute the setup: `ssh pi@${TESTING_HOST} pico-setup/pico_setup.sh` +1. Logout to pick up env variables and test the setup: `ssh pi@${TESTING_HOST} pico-setup/test/test` -Write fresh SD card with Raspberry Pi Imager. +For all tests on Raspberry Pi computers, start with a pristine image written by Raspberry Pi Imager. The focus is on more recent hardware such as Raspberry Pi 4, but this installer's dependencies are more about software than hardware, so it should work with any version of the hardware. -### Raspberry Pi OS Lite (32-bit) on Raspberry Pi 4B -Should be the same as the full OS, but doesn't install Visual Studio Code because there's no XWindows. +The tests on non-Raspberry Pi computers can be executed on EC2 instances. The recommended EC2 instance sizes cost pennies/hour, except for mac1. mac1 costs 1.083 USD/hour in us-west-2, and requires dedicated host with minimum charge of 24 hours. You can launch and terminate instances all day on that dedicated host without cost, other than the hour it takes to clean up a terminated instance and launch a new one. -Write fresh SD card with Raspberry Pi Imager. +Notes on EC2: -### Ubuntu Desktop 20.10 (64-bit) on Raspberry Pi 4B -Not yet tested. +* For the Linux x86_64 tests, t3.micro with standard 8 GiB EBS volume are sufficient. +* For the AArch64 tests, t4g.micro with standard 8 GiB EBS volume are sufficient. +* For the Windows Subsystem for Linux tests, t3.large with standard 30 GiB EBS volume are sufficient. +* For the official Ubuntu AMIs from Canonical, the default username is `ubuntu`. +* For the official Debian AMIs from Debian, the default username is `admin`. +* For the macOS and Windows AMIs from Amazon, the default username is `ec2-user`. -Less common. Should work a lot like Raspberry Pi OS, but with a couple different package dependencies. +#### Summary -Write fresh SD card with Raspberry Pi Imager. +TODO: update this +| | Raspberry Pi | x86_64 | AArch64 | +|-|-|-|-| +| Raspberry Pi OS (32-bit) | ✅ | Not tested | Not tested | +| Raspberry Pi OS (64-bit) | ✅ | Not tested | Not tested | +| Raspberry Pi OS Lite (32-bit) | ✅ | Not tested | Not tested | +| Ubuntu Desktop (64-bit) | ? | ✅ [EC2](https://aws.amazon.com/marketplace/pp/B08LQMCZGC) | ✅ [EC2](https://aws.amazon.com/marketplace/pp/B08LQMCZGC) | +| Ubuntu Server (32-bit) | ✅ | ? | ? | +| Debian 10 (Buster) | ✅ | ? | ? | +| macOS 11 Big Sur | - | ✅ | ✅ | +| Ubuntu on WSL | - | ✅ | - | +| Debian on WSL | - | ✅ | - | -### Ubuntu Server 20.10 (32-bit) on Raspberry Pi 4B -Less common. Should work a lot like Raspberry Pi OS, but with a couple different package dependencies. +#### Links to EC2 for convenience -Write fresh SD card with Raspberry Pi Imager. +TODO: update this -### Debian 10 (Buster) on Raspberry Pi 4B -Less common. Should work a lot like Raspberry Pi OS, but with a couple different package dependencies. +| | x86_64 | AArch64 | +|-|-|-|-| +| Ubuntu Desktop (64-bit) | [EC2](https://aws.amazon.com/marketplace/pp/B08LQMCZGC) | [EC2](https://aws.amazon.com/marketplace/pp/B08LQMCZGC) | +| Ubuntu Server (32-bit) | +| Debian 10 (Buster) | [EC2](https://aws.amazon.com/marketplace/pp/B0859NK4HC) | [EC2](https://aws.amazon.com/marketplace/pp/B0859NK4HC) | +| macOS 11 Big Sur | +| Windows Subsustem for Linux | -Write fresh SD card with Raspberry Pi Imager. +#### Windows Subsystem for Linux -### macOS Big Sur on Mac mini Intel -Can be rented on EC2, but not as cheaply as the other platforms. You have to get a dedicated host, which currently costs $1.083/hour in us-west-2, with a minimum of 24 hours. You can launch and terminate instances all day on that dedicated host without extra cost, which is good for testing installers. Comes with Homebrew installed, which is nice. +Install WSL according to https://docs.microsoft.com/en-us/windows/wsl/install-on-server. -Default user is `ec2-user`. You will have to use sudo to set the user's password: -```shell -sudo -i -passwd ec2-user -``` +Get your Linux distro here: https://docs.microsoft.com/en-us/windows/wsl/install-manual#downloading-distributions -### Raspberry Pi Desktop on x86_64 -Not yet tested. +The Debian build apparently doesn't contain wget: -### Ubuntu 20.10 on x86_64 -Can be rented on [EC2](https://aws.amazon.com/marketplace/pp/B08LQMCZGC?ref_=beagle&applicationId=AWS-Marketplace-Console) for pennies/hour. Recommend t3.micro with 8 GiB EBS volume. Default user is `ubuntu`. You will have to use sudo to set the user's password: ```shell -sudo -i -passwd ubuntu -``` - -### Debian 10 (Buster) on x86_64 -Can be rented on [EC2](https://aws.amazon.com/marketplace/pp/B0859NK4HC?ref_=aws-mp-console-subscription-detail) for pennies/hour. Recommend t3.micro with 8 GiB EBS volume. Default user is `admin`. You will have to use sudo to set the user's password: -```shell -sudo -i -passwd admin -``` - -### Ubuntu 20.10 on Graviton2 -Can be rented on [EC2](https://aws.amazon.com/marketplace/pp/B08LQMCZGC?ref_=beagle&applicationId=AWS-Marketplace-Console) for pennies/hour. Recommend t4g.micro with 8 GiB EBS volume. Default user is `ubuntu`. You will have to use sudo to set the user's password: -```shell -sudo -i -passwd ubuntu -``` - -### Debian 10 (Buster) on Graviton2 -Can be rented on [EC2](https://aws.amazon.com/marketplace/pp/B0859NK4HC?ref_=aws-mp-console-subscription-detail) for pennies/hour. Recommend t4g.micro with 8 GiB EBS volume. Default user is `admin`. You will have to use sudo to set the user's password: -```shell -sudo -i -passwd admin +sudo apt update +sudo apt install -y wget ``` -### Windows Server 2016 Base on x86_64 -Not yet tested. See https://aws.amazon.com/marketplace/server/procurement?productId=13c2dbc9-57fc-4958-922e-a1ba7e223b0d. - -### Ubuntu 20.04 on WSL1 on Windows Server 2019 Base on x86_64 -Can be rented on [EC2](https://aws.amazon.com/marketplace/server/procurement?productId=ef297a90-3ad0-4674-83b4-7f0ec07c39bb) for pennies/hour. Recommend t3.large. Default user is `ec2-user`. Connect with Microsoft Remote Desktop. - -Install WSL according to https://docs.microsoft.com/en-us/windows/wsl/install-on-server. Install Ubuntu for WSL - In the Linux shell: + ```shell wget https://raw.githubusercontent.com/raspberrypi/pico-setup/master/pico_setup.sh chmod +x pico_setup.sh ./pico_setup.sh ``` -### Debian GNU/Linux 1.3.0.0 on WSL1 on Windows Server 2019 Base on x86_64 -Similar instructions as Ubuntu, but using the Debian WSL package and you'll have to explicitly install wget: -```shell -sudo apt update -sudo apt install -y wget -``` +## Scenarios -Currently fails due to lack of python3. +Here are some scenarios worth testing: -## Scenarios -Test some scenarios: -* Shells: bash, zsh. It should be enough to switch shells and rerun the installer and test. You don't have to wipe the SD card/disk. -* .profile or .zprofile doesn't end in newline -* PWD containing space. The script seems to handle it but a OpenOCD submodule, jimctl, doesn't. +* Shells: bash, zsh. It should be enough to switch shells and rerun the installer and test scripts. You don't have to wipe the SD card/disk. Note that bash is default on Raspberry Pi OS and most other Linux distros. On macOS, the default is zsh. +* .profile or .zprofile does/doesn't end in newline +* PWD containing space. The installer script seems to handle it but an OpenOCD submodule, jimctl, doesn't. I think that jimctl is an alternative to picoprobe, so maybe we shouldn't try to build (or init) it at all. Or maybe we could do everyone a favor and send them a PR fixing it. diff --git a/test/test b/test/test index af957df..a89b684 100755 --- a/test/test +++ b/test/test @@ -47,7 +47,7 @@ fail() { # All args are echoed as a failure message. R="${?}" - echo "Tests failed! 😢" + echo "Tests failed! :'-(" if [ ${*} ]; then echo "${*}" fi @@ -165,4 +165,4 @@ else fi fi -echo "Tests passed! 😁" +echo "Tests passed! :D" From 1ff656cc929f05015cfeed653ae2bb7f8976cc9e Mon Sep 17 00:00:00 2001 From: Michael Stoops Date: Mon, 12 Apr 2021 20:14:03 -0700 Subject: [PATCH 6/6] Redesigned the tests --- pico_setup.sh | 252 ++++++++++++++++++++++++++++++++------- test/README.md | 81 ++++--------- test/test | 168 -------------------------- test/test_local.sh | 288 +++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 524 insertions(+), 265 deletions(-) delete mode 100755 test/test create mode 100755 test/test_local.sh diff --git a/pico_setup.sh b/pico_setup.sh index 85398a0..853a08c 100755 --- a/pico_setup.sh +++ b/pico_setup.sh @@ -22,11 +22,17 @@ # Exit on error set -e -# Show all commands -set -x -# Trying to use an non-existent variable is an error + +# Trying to use a non-existent variable is an error set -u +# if printenv DEBUG >& /dev/null; then + # Show all commands + set -x + + env +# fi + # Number of cores when running make JNUM=4 @@ -38,7 +44,6 @@ else echo "Using target dir: ${TARGET_DIR}" fi - linux() { # Returns true iff this is running on Linux uname | grep -q "^Linux$" @@ -78,14 +83,28 @@ raspberry_pi() { return 1 } +sudo_wrapper() { + # Some platforms have different needs for invoking sudo. This wrapper encapsulates that complexity. + # The output of this function should be a string on stdout, which will be used as a command. Example: + # `$(sudo_wrapper) whoami` + # The above may equate to: + # `sudo -i whoami` + + if [ "${USER}" = root ]; then + # if we're already root, don't sudo at all. Relevant to some Docker images that don't have sudo but already run as root. + return + fi + + # EC2 AMIs tend to have the user password unset, so you can't sudo without -i. It will cd /root, so you have to be + # careful with relative paths in the command. + echo sudo -i +} + phase_0() { # Preflight check # Checks the baseline dependencies. If you don't have these, this script won't work. echo "Entering phase 0: Preflight check" - echo "Verifying sudo access" - sudo -v - if mac; then echo "Running on macOS" if which brew >> /dev/null; then @@ -105,23 +124,49 @@ phase_0() { if which apt >> /dev/null; then echo "Found apt" - sudo apt update + $(sudo_wrapper) apt update else - echo 'This script requires apt, the default package manager for Debian and Debian-derived distros such as Ubuntu, and Raspberry Pi OS.' + echo 'This script requires apt, the default package manager for Debian and Debian-derived distros such as Ubuntu and Raspberry Pi OS.' echo "Stopping." exit 1 fi fi } +fail() { + # Outputs a failure message and exits with the error code output by the previous call. + # All args are echoed as a failure message. + + R="${?}" + echo "Validation failed! :'-(" + if [ ${*} ]; then + echo "${*}" + fi + exit ${R} +} + +validate_git_repo() { + # tests that the given relative path exists and is a git repo + git -C ${TARGET_DIR}/${1} status >& /dev/null || fail +} + +validate_toolchain_linux() { + # test that the expected packages are installed + dpkg-query -s git cmake gcc-arm-none-eabi build-essential gdb-multiarch automake autoconf build-essential texinfo libtool libftdi-dev libusb-1.0-0-dev >& /dev/null || fail +} + install_dev_env_deps_linux() { # Install development environment dependencies for Linux - DEPS="python3 git cmake gcc-arm-none-eabi build-essential gdb-multiarch automake autoconf build-essential texinfo libtool libftdi-dev libusb-1.0-0-dev minicom pkg-config" + # Avoid a certain dependency by installing ssh-client without recommends. See + # https://github.com/raspberrypi/pico-setup/pull/20#discussion_r608793993 for details. + $(sudo_wrapper) apt install -y --no-install-recommends ssh-client + + DEPS="autoconf automake build-essential cmake gcc-arm-none-eabi gdb-multiarch git libftdi-dev libtool libusb-1.0-0-dev minicom pkg-config python3 texinfo" if debian || ubuntu; then DEPS="${DEPS} libstdc++-arm-none-eabi-newlib" fi - sudo apt install -y ${DEPS} + $(sudo_wrapper) apt install -y ${DEPS} } brew_install_idempotent() { @@ -130,13 +175,18 @@ brew_install_idempotent() { return ${?} } +validate_toolchain_mac() { + # test that the expected packages are installed + brew list git cmake pkg-config libtool automake libusb wget pkg-config gcc texinfo arm-none-eabi-gcc >& /dev/null +} + install_dev_env_deps_mac() { # Install development environment dependencies for mac - brew_install_idempotent git cmake pkg-config libtool automake libusb wget pkg-config gcc texinfo minicom ArmMbed/homebrew-formulae/arm-none-eabi-gcc + brew_install_idempotent ArmMbed/homebrew-formulae/arm-none-eabi-gcc automake cmake git libtool libusb gcc minicom pkg-config texinfo wget } -create_working_dir() { +create_TARGET_DIR() { # Creates ./pico directory if necessary mkdir -p "${TARGET_DIR}" @@ -156,35 +206,43 @@ clone_raspberrypi_repo() { BRANCH=master fi - # Save the working directory - pushd "${TARGET_DIR}" >> /dev/null - REPO_URL="https://github.com/raspberrypi/${REPO_NAME}.git" - DEST="${TARGET_DIR}/${REPO_NAME}" + REPO_DIR="${TARGET_DIR}/${REPO_NAME}" - if [ -d "${DEST}" ]; then - echo "Not cloning ${DEST} because it already exists. If you really want to start over, delete it: rm -rf ${DEST}" + if [ -d "${REPO_DIR}" ]; then + echo "${REPO_DIR} already exists. Updating." + git -C "${REPO_DIR}" pull --ff-only else echo "Cloning ${REPO_URL}" if [ ${#} -gt 0 ]; then - git clone -b "${BRANCH}" "${REPO_URL}" ${*} + git -C "${TARGET_DIR}" clone -b "${BRANCH}" "${REPO_URL}" ${*} else - git clone -b "${BRANCH}" "${REPO_URL}" + git -C "${TARGET_DIR}" clone -b "${BRANCH}" "${REPO_URL}" fi # Any submodules - cd "${DEST}" - git submodule update --init + git -C "${REPO_DIR}" submodule update --init fi +} - # Restore working directory - popd >> /dev/null +warn_for_bashrc() { + # Earlier versions of this script set environment variables in .bashrc. The location has moved to .profile or + # .zprofile. If the user has a .bashrc defining any pico dev env variables, they could conflict with the settings + # in the other files. This function raises a warning for the user. + + REGEX="^\s*export\s+\"?PICO_SDK_PATH=" + if grep -q "${REGEX}" ~/.bashrc; then + echo "Your ~/.bashrc file contains the following line, which may conflict with this script's settings. We recommend removing it to prevent possible issues." + echo -n " "; grep "${REGEX}" ~/.bashrc + fi } set_env() { # Permanently sets an environment variable by adding it to the current user's profile script - # $1 should be in the form of FOO=foo - EXPR="${1}" + # The form of the arguments should be `FOO foo`, which sets the environment variable `FOO=foo` + NAME="${1}" + VALUE="${2}" + EXPR="${NAME}=${VALUE}" # detect appropriate file for setting env vars if echo "${SHELL}" | grep -q zsh; then @@ -205,26 +263,51 @@ set_env() { # set for now export "${EXPR}" - + # set for later - if ! grep -q "^export ${EXPR}$" "${FILE}"; then + REGEX="^\s*export\s+\"?${NAME}=" + if grep -q "${REGEX}" "${FILE}"; then + # Warn the user + echo "Your ${FILE} already contains the following environment variable definition(s):" + grep "${REGEX}" "${FILE}" + echo "This script would normally set the following line. We're adding it, but commented out, so that you can choose which you want." + echo "export \"${EXPR}\"" + # Write to file + echo "# pico_setup.sh commented out the following line because it conflicts with another line in this file. You should choose one or the other." >> "${FILE}" + echo "# export \"${EXPR}\"" >> "${FILE}" + else echo "Setting env variable ${EXPR} in ${FILE}" echo "export \"${EXPR}\"" >> "${FILE}" fi } +validate_pico_sdk() { + validate_git_repo pico-sdk + + # test that the SDK env var is set and correct + test "${PICO_SDK_PATH}" = "${TARGET_DIR}/pico-sdk" || fail +} + setup_sdk() { # Download the SDK clone_raspberrypi_repo pico-sdk # Set env var PICO_SDK_PATH - set_env "PICO_SDK_PATH=${TARGET_DIR}/pico-sdk" + set_env PICO_SDK_PATH "${TARGET_DIR}/pico-sdk" +} + +validate_uart() { + # test that the UART is configured. Only works on Raspberry Pi OS on Raspberry Pi hardware. + dpkg-query -s minicom >& /dev/null || fail + grep -q "enable_uart=1" /boot/config.txt || fail + # note that the test for console=serial0 tests for the absence of a string + grep -q "console=serial0" /boot/cmdline.txt && fail } enable_uart() { # Enable UART echo "Disabling Linux serial console (UART) so we can use it for pico" - sudo raspi-config nonint do_serial 2 + $(sudo_wrapper) raspi-config nonint do_serial 2 echo "You must run sudo reboot to finish UART setup" } @@ -234,17 +317,21 @@ phase_1() { if mac; then install_dev_env_deps_mac + validate_toolchain_mac else install_dev_env_deps_linux + validate_toolchain_linux fi - create_working_dir + create_TARGET_DIR setup_sdk + validate_pico_sdk if raspberry_pi && which raspi-config >> /dev/null; then enable_uart + validate_uart else - echo "Not configuring UART because this is not a Raspberry Pi computer, or raspi-config is unavailable." + echo "Not configuring UART, because either this is not a Raspberry Pi computer, or raspi-config is not available." fi } @@ -252,7 +339,9 @@ build_examples() { # Build a couple of examples echo "Building selected examples" - cd "$TARGET_DIR/pico-examples" + # Save the working directory + pushd "${TARGET_DIR}/pico-examples" >> /dev/null + mkdir -p build cd build cmake ../ -DCMAKE_BUILD_TYPE=Debug @@ -263,6 +352,30 @@ build_examples() { make -j${JNUM} cd .. done + + # Restore the working directory + popd >> /dev/null +} + +validate_pico_extras() { + validate_git_repo pico-extras +} + +validate_pico_examples() { + validate_git_repo pico-examples + + # test that blink is built + test -f ${TARGET_DIR}/pico-examples/build/blink/blink.uf2 || fail + + # test that hello_serial is built + test -f ${TARGET_DIR}/pico-examples/build/hello_world/serial/hello_serial.uf2 || fail + + # test that hello_usb is built + test -f ${TARGET_DIR}/pico-examples/build/hello_world/usb/hello_usb.uf2 || fail +} + +validate_pico_playground() { + validate_git_repo pico-playground } phase_2() { @@ -274,13 +387,28 @@ phase_2() { done build_examples + + validate_pico_examples + validate_pico_extras + validate_pico_playground +} + +validate_picotool() { + validate_git_repo picotool + + # test that the binary is built + test -x ${TARGET_DIR}/picotool/build/picotool || fail + + # test that picotool is installed in the expected location + test -x /usr/local/bin/picotool || fail } setup_picotool() { # Downloads, builds, and installs picotool echo "Setting up picotool" - cd "${TARGET_DIR}" + # Save the working directory + pushd "${TARGET_DIR}" >> /dev/null clone_raspberrypi_repo picotool cd "${TARGET_DIR}/picotool" @@ -290,14 +418,25 @@ setup_picotool() { make -j${JNUM} echo "Installing picotool to /usr/local/bin/picotool" - sudo cp picotool /usr/local/bin/ + $(sudo_wrapper) cp "${TARGET_DIR}/picotool/build/picotool" /usr/local/bin/ + + # Restore the working directory + popd >> /dev/null +} + +validate_openocd() { + validate_git_repo openocd + + # test that the binary is built + test -x ${TARGET_DIR}/openocd/src/openocd || fail } setup_openocd() { # Download, build, and install OpenOCD for picoprobe and bit-banging without picoprobe echo "Setting up OpenOCD" - cd "${TARGET_DIR}" + # Save the working directory + pushd "${TARGET_DIR}" >> /dev/null clone_raspberrypi_repo openocd picoprobe --depth=1 cd "${TARGET_DIR}/openocd" @@ -309,14 +448,25 @@ setup_openocd() { fi ./configure ${OPTS} make -j${JNUM} - sudo make install + $(sudo_wrapper) make -C "${TARGET_DIR}/openocd" install + + # Restore the working directory + popd >> /dev/null +} + +validate_picoprobe() { + validate_git_repo picoprobe || fail + + # test that the binary is built + test -f ${TARGET_DIR}/picoprobe/build/picoprobe.uf2 || fail } setup_picoprobe() { # Download and build picoprobe. Requires that OpenOCD is already setup echo "Setting up picoprobe" - cd "${TARGET_DIR}" + # Save the working directory + pushd "${TARGET_DIR}" >> /dev/null clone_raspberrypi_repo picoprobe cd "${TARGET_DIR}/picoprobe" @@ -324,20 +474,27 @@ setup_picoprobe() { cd build cmake .. make -j${JNUM} + + # Restore the working directory + popd >> /dev/null +} + +validate_vscode_linux() { + dpkg-query -s code >& /dev/null || fail } install_vscode_linux() { # Install Visual Studio Code # VS Code is specially added to Raspberry Pi OS repos, but might not be present on Debian/Ubuntu. So we check first. - if ! apt list code; then + if ! apt-cache show code >& /dev/null; then echo "It appears that your APT repos do not offer Visual Studio Code. Skipping." return fi echo "Installing Visual Studio Code" - sudo apt install -y code + $(sudo_wrapper) apt install -y code # Get extensions code --install-extension marus25.cortex-debug @@ -345,6 +502,10 @@ install_vscode_linux() { code --install-extension ms-vscode.cpptools } +validate_vscode_mac() { + echo "Not yet implemented: testing Visual Studio Code on macOS" +} + install_vscode_mac() { echo "Not yet implemented: installing Visual Studio Code on macOS" } @@ -354,15 +515,22 @@ phase_3() { echo "Setting up recommended tools" setup_picotool + validate_picotool + setup_openocd + validate_openocd + setup_picoprobe + validate_picoprobe # Install Visual Studio Code if mac; then install_vscode_mac + validate_vscode_mac else - if dpkg-query -s xserver-xorg >> /dev/null; then + if dpkg-query -s xserver-xorg >& /dev/null; then install_vscode_linux + validate_vscode_linux else echo "Not installing Visual Studio Code because it looks like XWindows is not installed." fi diff --git a/test/README.md b/test/README.md index fde2e66..1873290 100644 --- a/test/README.md +++ b/test/README.md @@ -1,74 +1,53 @@ # Testing pico-setup -The tests validate that `pico_setup.sh` _seems_ to setup your system correctly. It can be fooled. It does not test that the SDK or tools themselves work correctly, just that the setup script did its thing. +`pico_setup.sh` validates that it has the expected effect for your specific setup. However, the script needs to work on a variety of platforms, so we test a variety. -To execute the tests, first run `pico_setup.sh` from wherever you want to install the pico dev environment: +***Be warned: the testing script is destructive.*** It configures the system in all kinds of ways to see if the script can handle it, and makes little attempt to put things back where they were before. These tests are expected to be run on a single-use system. You start with a fresh image at the beginning, and discard it at the end. -```shell -./pico_setup.sh -``` +The general testing process is: -Logout and back in, so that your shell will pick up its environment variables. Then run the test from the same location as you ran `pico_setup.sh`: - -```shell -./test/test -``` - -## What to test +1. Start from a fresh OS image. +1.1. On Raspberry Pi OS, you'll need to start the SSH service if necessary: `sudo /sbin/service ssh start` +1. Push the contents of the pico-setup repo from your dev host: `scp -r ~/git/raspberrypi/pico-setup/ ${TEST_USER}@${TEST_HOST}:` +1. SSH to the test host and execute the test suite: `ssh ${TEST_USER}@${TEST_HOST} "export WRECK_THIS_COMPUTER=PLEASE_I_DESERVE_IT && pico-setup/test/test_local.sh" |& tee ${TEST_HOST}.log` -### Platform support +The `tee` part captures all output and dumps it to a log file on the local host so you can investigate anything that went wrong. Additionally, logs for each test should be on the testing host, at `/tmp/test_*` -We can test platform support by getting the platforms and verifying the script on each. The general process is: +If the test completes successfully, it will say that it's complete and return 0. If it fails, it will return non-zero. -1. Start from a fresh OS image. -1. Do any necessary setup. -1.1. On Raspberry Pi OS, you'll need to start the SSH service if necessary: `sudo /sbin/service ssh start` -1.1. On EC2, you'll need to set a password: `sudo -i passwd $USER` -1. Push the contents of the pico-setup repo from your dev host: `scp -r ~/git/raspberrypi/pico-setup/ pi@${TESTING_HOST}:` -1. SSH to the test host and execute the setup: `ssh pi@${TESTING_HOST} pico-setup/pico_setup.sh` -1. Logout to pick up env variables and test the setup: `ssh pi@${TESTING_HOST} pico-setup/test/test` +## Preparations For all tests on Raspberry Pi computers, start with a pristine image written by Raspberry Pi Imager. The focus is on more recent hardware such as Raspberry Pi 4, but this installer's dependencies are more about software than hardware, so it should work with any version of the hardware. +Raspberry Pi is an ARM platform, so testing Raspberry Pi hardware technically covers ARM tests. However, the Linux distros built for Raspberry Pi hardware tend to be customized, so testing the mainline build is nonetheless relevant. + The tests on non-Raspberry Pi computers can be executed on EC2 instances. The recommended EC2 instance sizes cost pennies/hour, except for mac1. mac1 costs 1.083 USD/hour in us-west-2, and requires dedicated host with minimum charge of 24 hours. You can launch and terminate instances all day on that dedicated host without cost, other than the hour it takes to clean up a terminated instance and launch a new one. Notes on EC2: -* For the Linux x86_64 tests, t3.micro with standard 8 GiB EBS volume are sufficient. -* For the AArch64 tests, t4g.micro with standard 8 GiB EBS volume are sufficient. +* For the Linux x86 tests, t3.micro with standard 8 GiB EBS volume are sufficient. +* For the ARM tests, t4g.micro with standard 8 GiB EBS volume are sufficient. * For the Windows Subsystem for Linux tests, t3.large with standard 30 GiB EBS volume are sufficient. * For the official Ubuntu AMIs from Canonical, the default username is `ubuntu`. * For the official Debian AMIs from Debian, the default username is `admin`. * For the macOS and Windows AMIs from Amazon, the default username is `ec2-user`. -#### Summary - -TODO: update this -| | Raspberry Pi | x86_64 | AArch64 | -|-|-|-|-| -| Raspberry Pi OS (32-bit) | ✅ | Not tested | Not tested | -| Raspberry Pi OS (64-bit) | ✅ | Not tested | Not tested | -| Raspberry Pi OS Lite (32-bit) | ✅ | Not tested | Not tested | -| Ubuntu Desktop (64-bit) | ? | ✅ [EC2](https://aws.amazon.com/marketplace/pp/B08LQMCZGC) | ✅ [EC2](https://aws.amazon.com/marketplace/pp/B08LQMCZGC) | -| Ubuntu Server (32-bit) | ✅ | ? | ? | -| Debian 10 (Buster) | ✅ | ? | ? | -| macOS 11 Big Sur | - | ✅ | ✅ | -| Ubuntu on WSL | - | ✅ | - | -| Debian on WSL | - | ✅ | - | +## Summary -#### Links to EC2 for convenience +* ✅ Means this version is tested and works on this platform. +* ? Means this version hasn't been tested on this platform. +* (blank) Means this platform isn't relevant. -TODO: update this - -| | x86_64 | AArch64 | +| | Raspberry Pi | x86 | ARM | |-|-|-|-| -| Ubuntu Desktop (64-bit) | [EC2](https://aws.amazon.com/marketplace/pp/B08LQMCZGC) | [EC2](https://aws.amazon.com/marketplace/pp/B08LQMCZGC) | -| Ubuntu Server (32-bit) | -| Debian 10 (Buster) | [EC2](https://aws.amazon.com/marketplace/pp/B0859NK4HC) | [EC2](https://aws.amazon.com/marketplace/pp/B0859NK4HC) | -| macOS 11 Big Sur | -| Windows Subsustem for Linux | +| Raspberry Pi OS | ✅ | ? | | +| Ubuntu 20 | ? | ✅ | ✅ | +| Debian 10 | ? | ✅ | ✅ | +| macOS 11 Big Sur | | ? | ? | +| Ubuntu on WSL | | ? | | +| Debian on WSL | | ? | | -#### Windows Subsystem for Linux +## Windows Subsystem for Linux Install WSL according to https://docs.microsoft.com/en-us/windows/wsl/install-on-server. @@ -88,11 +67,3 @@ wget https://raw.githubusercontent.com/raspberrypi/pico-setup/master/pico_setup. chmod +x pico_setup.sh ./pico_setup.sh ``` - -## Scenarios - -Here are some scenarios worth testing: - -* Shells: bash, zsh. It should be enough to switch shells and rerun the installer and test scripts. You don't have to wipe the SD card/disk. Note that bash is default on Raspberry Pi OS and most other Linux distros. On macOS, the default is zsh. -* .profile or .zprofile does/doesn't end in newline -* PWD containing space. The installer script seems to handle it but an OpenOCD submodule, jimctl, doesn't. I think that jimctl is an alternative to picoprobe, so maybe we shouldn't try to build (or init) it at all. Or maybe we could do everyone a favor and send them a PR fixing it. diff --git a/test/test b/test/test deleted file mode 100755 index a89b684..0000000 --- a/test/test +++ /dev/null @@ -1,168 +0,0 @@ -#!/usr/bin/env bash - -# Executes the full test suite on the local host -# -# Configurations env vars: - -set -ex - -WORKING_DIR="$(pwd)/pico" - -linux() { - # Returns true iff this is running on Linux - uname | grep -q "^Linux$" - return ${?} -} - -debian() { - # Returns true iff this is running on Debian - grep -q '^NAME="Debian GNU/Linux"$' /etc/os-release - return ${?} -} - -ubuntu() { - # Returns true iff this is running on Ubuntu - grep -q '^NAME="Ubuntu"$' /etc/os-release - return ${?} -} - -mac() { - # Returns true iff this is running on macOS and presumably Apple hardware - uname | grep -q "^Darwin$" - return ${?} -} - -raspberry_pi() { - # Returns true iff this is running on a Raspberry Pi computer, regardless of the OS - if [ -f /proc/cpuinfo ]; then - grep -q "^Model\s*: Raspberry Pi" /proc/cpuinfo - return ${?} - fi - return 1 -} - - -fail() { - # Outputs a failure message and exits with the error code output by the previous call. - # All args are echoed as a failure message. - - R="${?}" - echo "Tests failed! :'-(" - if [ ${*} ]; then - echo "${*}" - fi - exit ${R} -} - -test_git_repo() { - # tests that the given relative path exists and is a git repo - git -C ${WORKING_DIR}/${1} status || fail -} - -test_toolchain_linux() { - # test that the expected packages are installed - dpkg-query -s git cmake gcc-arm-none-eabi build-essential gdb-multiarch automake autoconf build-essential texinfo libtool libftdi-dev libusb-1.0-0-dev || fail -} - -test_toolchain_mac() { - # test that the expected packages are installed - brew list git cmake pkg-config libtool automake libusb wget pkg-config gcc texinfo arm-none-eabi-gcc -} - -test_pico_sdk() { - test_git_repo pico-sdk - - # test that the SDK env var is set and correct - test "${PICO_SDK_PATH}" = "${WORKING_DIR}/pico-sdk" || fail -} - -test_uart() { - # test that the UART is configured. Only works on Raspberry Pi OS on Raspberry Pi hardware. - dpkg-query -s minicom || fail - grep -q "enable_uart=1" /boot/config.txt || fail - # note that the test for console=serial0 tests for the absence of a string - grep -q "console=serial0" /boot/cmdline.txt && fail -} - -test_pico_examples() { - test_git_repo pico-examples - - # test that blink is built - test -f ${WORKING_DIR}/pico-examples/build/blink/blink.uf2 || fail - - # test that hello_serial is built - test -f ${WORKING_DIR}/pico-examples/build/hello_world/serial/hello_serial.uf2 || fail - - # test that hello_usb is built - test -f ${WORKING_DIR}/pico-examples/build/hello_world/usb/hello_usb.uf2 || fail -} - -test_pico_extras() { - test_git_repo pico-extras -} - -test_pico_playground() { - test_git_repo pico-playground -} - -test_picotool() { - test_git_repo picotool - - # test that the binary is built - test -x ${WORKING_DIR}/picotool/build/picotool || fail - - # test that picotool is installed in the expected location - test -x /usr/local/bin/picotool || fail -} - -test_openocd() { - test_git_repo openocd - - # test that the binary is built - test -x ${WORKING_DIR}/openocd/src/openocd || fail -} - -test_picoprobe() { - test_git_repo picoprobe || fail - - # test that the binary is built - test -f ${WORKING_DIR}/picoprobe/build/picoprobe.uf2 || fail -} - -test_vscode_linux() { - dpkg-query -s code || fail -} - -test_vscode_mac() { - echo "Not yet implemented: testing Visual Studio Code on macOS" -} - - -# execute tests -if mac; then - test_toolchain_mac -else - test_toolchain_linux -fi - -test_pico_sdk - -if raspbian && raspberry_pi; then - test_uart -fi - -test_pico_examples -test_pico_extras -test_pico_playground -test_openocd -test_picoprobe -test_picotool -if mac; then - test_vscode_mac -else - if dpkg-query -s xserver-xorg >> /dev/null && ! (debian || ubuntu); then - test_vscode_linux - fi -fi - -echo "Tests passed! :D" diff --git a/test/test_local.sh b/test/test_local.sh new file mode 100755 index 0000000..f6bc320 --- /dev/null +++ b/test/test_local.sh @@ -0,0 +1,288 @@ +#!/usr/bin/env bash +# +# Executes the full test suite on the local host. +# +# WARNING!!! WARNING!!! WARNING!!! WARNING!!! WARNING!!! WARNING!!! WARNING!!! +# DO NOT RUN THIS SCRIPT ON A COMPUTER YOU AREN'T WILLING TO SACRIFICE. +# Running this script may result in undesired changes to this computer, such as: +# * installation of packages you don't want +# * broken or partial installations +# * broken build outputs overwriting working ones on the root filesystem +# * leaving files and data where you don't want them +# * messing with your shell and profiles +# * deleting files and directories wherever it wants to +# +# If you really want to sacrifice this computer, run with this env variable set: +# WRECK_THIS_COMPUTER="PLEASE_I_DESERVE_IT" + +echo "WARNING!!! WARNING!!! WARNING!!! WARNING!!! WARNING!!! WARNING!!! WARNING!!!" +echo "DO NOT RUN THIS SCRIPT ON A COMPUTER YOU AREN'T WILLING TO SACRIFICE." +echo "Running this script may result in undesired changes to this computer, such as:" +echo "* installation of packages you don't want" +echo "* broken or partial installations" +echo "* broken build outputs overwriting working ones on the root filesystem" +echo "* leaving files and data where you don't want them" +echo "* messing with your shell and profiles" +echo "* deleting files and directories wherever it wants to" +echo + +if [ "${WRECK_THIS_COMPUTER}" == "PLEASE_I_DESERVE_IT" ]; then + env | grep "WRECK_THIS_COMPUTER" + echo "Wrecking this computer, per request..." + echo + echo "Waiting five seconds..." + sleep 5 + echo +else + echo "If you really want to sacrifice this computer, run with this env variable set:" + echo 'WRECK_THIS_COMPUTER="PLEASE_I_DESERVE_IT"' + exit 1 +fi + +# Set this after the warning, so that the debug output doesn't confuse people +set -ex + +# set the debug flag for the installer script +export DEBUG=1 + +# Save path to the setup script, which is above this script. +SETUP_SCRIPT_PATH="$(pwd)/$(dirname "${0}")/../pico_setup.sh" + +backup() { + FILE="${1}" + if [ -f "${FILE}" ]; then + cp "${FILE}" "${FILE}.$(date +"%Y%m%d-%H%M%S")" + fi +} + +setup() { + backup ~/.profile + backup ~/.zprofile +} + +start_test() { + # Does the standard setup for a test + TEST_NAME="${1}" + echo "Starting ${TEST_NAME}" + + # Cleanse and change into test dir + TEST_DIR="/tmp/${TEST_NAME}" + rm -rf "${TEST_DIR}" || true + mkdir -p "${TEST_DIR}" + pushd "${TEST_DIR}" > /dev/null + + # should always start with this unset + unset TARGET_DIR +} + +execute_and_log() { + # Executes the given args, and captures output to a log file. + # Outputs the variable LOG_FILE, containing the path of file. + LOG_FILE="${TEST_DIR}/$(basename ${1}).$(date +"%Y%m%d-%H%M%S.%N").log" + echo execute_and_log: ${*} + echo logging to: ${LOG_FILE} + # Appending to this file is a bit of a gamble. The nanosecond-precision name should be unique, but in case it + # isn't, I'd rather append than lose data. + ${*} |& tee -a ${LOG_FILE} +} + +complete_test() { + popd > /dev/null + + echo "Completed ${TEST_NAME}" + unset TEST_NAME +} + +test_with_target_dir_unset() { + start_test test_with_target_dir_unset + + # just to be sure + unset TARGET_DIR + + execute_and_log "${SETUP_SCRIPT_PATH}" + + complete_test +} + +test_with_target_dir_set() { + start_test test_with_target_dir_set + + # Set the target dir to be something below the test dir + export TARGET_DIR="${TEST_DIR}/target_dir" + execute_and_log "${SETUP_SCRIPT_PATH}" + + # verify that at least one expected git repo exists + git -C "${TARGET_DIR}/pico-sdk" status + + unset TARGET_DIR + + complete_test +} + +test_update() { + start_test test_update + + # run the first time + execute_and_log "${SETUP_SCRIPT_PATH}" + + + # run a second time, watching for the indicator that we're doing the git pull. + execute_and_log "${SETUP_SCRIPT_PATH}" + COUNT=$(grep -c "git .* pull --ff-only" ${LOG_FILE}) + if [ 7 -ne "${COUNT}" ]; then + echo "Didn't see the expected number of git pulls" + exit 1 + fi + + complete_test +} + +test_with_space_in_target_dir() { + start_test test_with_space_in_target_dir + + # Set the target dir to be something below the test dir + export TARGET_DIR="${TEST_DIR}/target_dir_WITH SPACE" + execute_and_log "${SETUP_SCRIPT_PATH}" + + # verify that at least one expected git repo exists + git -C "${TARGET_DIR}/pico-sdk" status + + unset TARGET_DIR + + complete_test +} + +test_with_specific_shell() { + # Execute a test in the case that the user has a certain shell. Warning: this does not attempt to change the shell + # back. + # $1 must be the new shell + NEW_SHELL="${1}" + + # sudo to change shell, so it won't prompt for password + sudo chsh -s "${NEW_SHELL}" "${USER}" + + # try to verify that the user is, in fact, using the new shell: + sudo -i -u "${USER}" printenv SHELL | grep ${NEW_SHELL} + + execute_and_log sudo -i -u "${USER}" "${SETUP_SCRIPT_PATH}" +} + +test_with_bash_user() { + start_test test_with_bash_user + + # Setup the expected scenario + rm ~/.zprofile || true + cp /etc/skel/.profile ~ + + # This is a hack so that this test works. The problem is that the method of calling the installer doesn't + # pass the TARGET_DIR env var, so we really can't install it to anywhere in particular. It goes to the ~/pico + # whether you want it to or not. Setting the target dir with a command line switch should allow this to be fixed. + TARGET_DIR="${HOME}/pico" + # clean it out + rm -rf "${TARGET_DIR}" + + test_with_specific_shell "$(which bash)" + + # verify the change + test "$(tail -n 1 ~/.profile)" == "export \"PICO_SDK_PATH=${TARGET_DIR}/pico-sdk\"" + # and a non-change + test ! -f ~/.zprofile + + complete_test +} + +test_with_sh_user() { + start_test test_with_sh_user + + # Setup the expected scenario + rm ~/.zprofile || true + cp /etc/skel/.profile ~ + + # This is a hack so that this test works. The problem is that the method of calling the installer doesn't + # pass the TARGET_DIR env var, so we really can't install it to anywhere in particular. It goes to the ~/pico + # whether you want it to or not. Setting the target dir with a command line switch should allow this to be fixed. + TARGET_DIR="${HOME}/pico" + # clean it out + rm -rf "${TARGET_DIR}" + + test_with_specific_shell "$(which sh)" + + # verify the change + test "$(tail -n 1 ~/.profile)" == "export \"PICO_SDK_PATH=${TARGET_DIR}/pico-sdk\"" + # and a non-change + test ! -f ~/.zprofile + + complete_test +} + +test_with_zsh_user() { + start_test test_with_zsh_user + + # attempt to ensure zsh is installed + sudo apt -y install zsh + if [ ! -x "$(which zsh)" ]; then + echo "Can't find zsh" + exit 1 + fi + + # Setup the expected scenario + rm ~/.profile || true + rm ~/.zprofile || true + + # This is a hack so that this test works. The problem is that the method of calling the installer doesn't + # pass the TARGET_DIR env var, so we really can't install it to anywhere in particular. It goes to the ~/pico + # whether you want it to or not. Setting the target dir with a command line switch should allow this to be fixed. + TARGET_DIR="${HOME}/pico" + # clean it out + rm -rf "${TARGET_DIR}" + + test_with_specific_shell "$(which zsh)" + + # verify the change + test "$(tail -n 1 ~/.zprofile)" == "export \"PICO_SDK_PATH=${TARGET_DIR}/pico-sdk\"" + # and a non-change + test ! -f ~/.profile + + complete_test +} + +test_with_naked_tail_dot_profile() { + start_test test_with_naked_tail_dot_profile + + # Setup the expected scenario + echo -n "# no newline!" > ~/.profile + xxd ~/.profile + + # This is a hack so that this test works. The problem is that the method of calling the installer doesn't + # pass the TARGET_DIR env var, so we really can't install it to anywhere in particular. It goes to the ~/pico + # whether you want it to or not. Setting the target dir with a command line switch should allow this to be fixed. + TARGET_DIR="${HOME}/pico" + # clean it out + rm -rf "${TARGET_DIR}" + + test_with_specific_shell "$(which bash)" + + # verify the change + test "$(tail -n 1 ~/.profile)" == "export \"PICO_SDK_PATH=${TARGET_DIR}/pico-sdk\"" + + complete_test +} + +execute_all_tests() { + # Execute all the (enabled) tests + + setup + + test_with_target_dir_unset + test_with_target_dir_set + test_update + # Doesn't work because of jimtcl + # test_with_space_in_target_dir + test_with_bash_user + test_with_sh_user + test_with_zsh_user + test_with_naked_tail_dot_profile +} + + +execute_all_tests