From 75d209965531d7bad327a26ced76eca5228bb4b4 Mon Sep 17 00:00:00 2001 From: alvinlollo Date: Fri, 25 Sep 2026 21:02:44 +1000 Subject: [PATCH] Fix Studuino setup reproducibility --- .gitignore | 7 + Arduino.ino | 12 +- README.md | 66 +-- Resources/nvim/README.md | 12 +- compile_commands.json | 684 ------------------------------- hardware/studuino/avr/boards.txt | 5 +- setup.sh | 230 ++++++----- 7 files changed, 178 insertions(+), 838 deletions(-) create mode 100644 .gitignore delete mode 100644 compile_commands.json diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..518fc1f --- /dev/null +++ b/.gitignore @@ -0,0 +1,7 @@ +# Generated editor and Arduino CLI files +/compile_commands.json +/.arduino/ +*.bin +*.eep +*.elf +*.hex diff --git a/Arduino.ino b/Arduino.ino index 036cb09..fcff12e 100644 --- a/Arduino.ino +++ b/Arduino.ino @@ -1,9 +1,15 @@ -#include +#include +#include // Keep the complete smoke-test dependency set in clangd's database. + +Studuino board; void setup() { - // Add Studuino initialization here. + board.InitSensorPort(PORT_A0, PIDLED); } void loop() { - // Add Studuino code here. + board.LED(PORT_A0, ON); + board.Timer(1); + board.LED(PORT_A0, OFF); + board.Timer(1); } diff --git a/README.md b/README.md index b33320d..05e4c0a 100644 --- a/README.md +++ b/README.md @@ -1,16 +1,18 @@ # Studuino on Linux with Neovim -A development template for using the Artec Studuino (ATmega168/328, 3.3 V, 8 MHz) on Arch Linux with `arduino-cli`, `clangd`, and Neovim. +A development template for using the Artec Studuino (ATmega168/328, 3.3 V, 8 MHz) on Arch Linux with `arduino-cli` and optional `clangd`/Neovim tooling. This repository contains the Studuino hardware definition, the legacy Studuino libraries, an Arduino CLI setup script, and optional Neovim integration resources. ## Features -- Manual installation of the legacy Studuino hardware platform. +- Manual installation of the checked-in legacy Studuino hardware platform. - Arduino CLI project defaults for `studuino:avr:studuino`. -- Installation of the required `Servo` library. +- Installation of the checked-in Studuino libraries, including `Servo`. - Optional cleanup of unrelated user libraries. -- A generated `compile_commands.json` for `clangd` and Neovim. +- A generated, git-ignored `compile_commands.json` for `clangd` and Neovim. +- A real Studuino Blink smoke-test build during setup. +- Optional Neovim/Arduino language-server tooling. - Optional `picocom` serial-monitor support. - A LazyVim/Arduino-Nvim configuration template. @@ -21,16 +23,13 @@ This repository contains the Studuino hardware definition, the legacy Studuino l - A user account with permission to use serial devices. - Internet access for the initial Arduino CLI core/library installation. -The setup script installs these Arch packages by default: +The setup script installs `arduino-cli` by default. On Arch Linux, it can also install editor tooling with `--with-editor`: -- `arduino-cli` -- `clangd` -- `make` +- `clang` (provides `clangd`) - `neovim` -- `python` -- `unzip` +- `arduino-language-server` -It can optionally install `picocom` with `--with-monitor`. +It can optionally install `picocom` with `--with-monitor`. On other distributions, use `--skip-packages` and install the required commands through the distribution's package manager. ## Quick start @@ -38,21 +37,21 @@ From the repository root: ```bash cd /path/to/this/repository -./setup.sh +./setup.sh --with-editor ``` The script performs the following tasks: -1. Installs required Arch packages. +1. Installs the required packages for the selected options. 2. Adds the current user to `uucp` and `dialout`. 3. Initializes the Arduino CLI configuration if necessary. -4. Installs the AVR core when it is missing. -5. Installs the Studuino hardware definition. -6. Installs the libraries from `Resources/studuino_v1_lib.zip`. -7. Installs `Servo`, which is required by `Studuino.h`. -8. Ensures the sketch and default FQBN are configured. -9. Generates `compile_commands.json` for `clangd`. -10. Verifies board discovery and compilation. +4. Installs or upgrades the Arduino AVR core to a supported version. +5. Installs the checked-in Studuino hardware definition. +6. Installs the checked-in Studuino libraries, including `Servo`. +7. Ensures the sketch and default FQBN are configured. +8. Generates `compile_commands.json` for `clangd`. +9. Compiles the bundled Studuino Blink smoke test. +10. Compiles the project and verifies board/library discovery. Log out and back in after the first run if the script adds you to a new serial-port group. Group changes do not affect the current login session immediately. @@ -70,22 +69,25 @@ Useful options: # Do not install Arch packages or modify group membership ./setup.sh --skip-packages --skip-permissions +# Install Neovim, clangd, and Arduino language-server tooling +./setup.sh --with-editor + # Install picocom for a serial monitor ./setup.sh --with-monitor -# Remove user libraries not supplied by the Studuino bundle +# Remove user libraries not present in this repository ./setup.sh --clean -# Replace existing Studuino library and hardware files +# Replace existing hardware/libraries with the checked-in versions ./setup.sh --force # Skip regeneration of compile_commands.json ./setup.sh --skip-compile-db ``` -`--clean` is destructive. It preserves the libraries supplied in the Studuino ZIP and `Servo`, but removes other directories under the configured Arduino `libraries` directory. Back up any libraries you want to keep. +`--clean` is destructive. It preserves the libraries checked into this repository, including `Servo`, but removes other directories under the configured Arduino `libraries` directory. Back up any libraries you want to keep. -`--force` overwrites existing Studuino library and hardware files. Use it only when intentionally refreshing the Studuino installation. +`--force` overwrites existing Studuino hardware and library files with the checked-in versions. Use it after updating this repository or when intentionally refreshing the Studuino installation. ## Project layout @@ -95,7 +97,7 @@ Useful options: ├── sketch.yaml # arduino-cli project defaults ├── .arduino_config.lua # Arduino-Nvim board/port configuration ├── setup.sh # Idempotent setup script -├── compile_commands.json # clangd compilation database +├── compile_commands.json # Generated locally; not tracked ├── hardware/ │ └── studuino/ │ └── avr/ @@ -109,7 +111,7 @@ Useful options: └── nvim/ ``` -The Studuino platform is manually installed because it predates the modern Boards Manager package format. +The Studuino platform is manually installed because it predates the modern Boards Manager package format. The checked-in `hardware/` and `libraries/` trees are the canonical installation sources; the ZIP files under `Resources/` are retained as upstream source material and provenance. ## Board and port configuration @@ -181,7 +183,7 @@ arduino-cli upload \ --port /dev/ttyUSB0 ``` -The setup script verifies the project with a clean build. The Studuino target is an ATmega168 target, so the available program storage is smaller than a default Arduino Uno/ATmega328 build. +The setup script verifies the project with a clean build and also compiles `libraries/Studuino/example/Blink` as a smoke test. The Studuino target is an ATmega168 target, so the available program storage is 14,336 bytes and static data is limited to 1,024 bytes. ### Compile the bundled Blink example @@ -195,9 +197,9 @@ arduino-cli compile \ ## Neovim and clangd -The setup script installs `clangd` and generates `compile_commands.json` in the project root. `clangd` automatically searches the project directory for this file. +With `--with-editor`, the setup script installs the `clang` package (which provides `clangd`), Neovim, and `arduino-language-server`. It generates `compile_commands.json` in the project root; the file is ignored by Git because its paths are specific to the local Arduino CLI installation. -The initial database is generated from the minimal sketch, so it may not contain the Studuino library include paths. If clangd reports `Studuino.h file not found` after adding `#include `, refresh the database with the setup script after changing the sketch. +The initial database is generated from `Arduino.ino`, which includes `` and ``, so the complete bundled smoke-test dependency set is available to `clangd`. If you add a new library or change the FQBN, refresh the database with the setup script. If you add a new library or change the FQBN, refresh the database with: @@ -344,7 +346,7 @@ The supported path is: ### `Servo.h` not found -`Studuino.h` includes the Servo library, but Servo is distributed separately from the Studuino ZIP. Install it with: +`Studuino.h` includes the Servo library. It is checked into this repository and is installed by the setup script. If it is missing, install it with: ```bash arduino-cli lib install Servo @@ -400,7 +402,7 @@ The key must be `default_fqbn`; a top-level `fqbn` key is not used as the defaul ## Re-running setup -The setup script is designed to be rerun. It skips existing packages, libraries, and core installations unless `--force` is supplied. It always verifies the final board, libraries, and project compilation. +The setup script is designed to be rerun. It preserves existing user installations unless `--force` is supplied, verifies that the Arduino AVR core is at least version 1.8.8, and always verifies the board, libraries, Studuino smoke test, and project compilation. To inspect all available options: @@ -410,4 +412,4 @@ To inspect all available options: ## License and source materials -The Studuino hardware archive and Studuino library archive are kept in `Resources/` because they use a legacy/manual Arduino hardware layout. Keep the archives with the project so the setup can be recreated on another Linux machine. +The hardware and library ZIP files are retained in `Resources/` as upstream source archives. The active, maintained definitions are the checked-in `hardware/studuino/avr/` and `libraries/` directories; the setup script installs from those directories. diff --git a/Resources/nvim/README.md b/Resources/nvim/README.md index f3dc441..aa558db 100644 --- a/Resources/nvim/README.md +++ b/Resources/nvim/README.md @@ -35,7 +35,13 @@ return { ## Requirements -- [arduino-cli](https://arduino.github.io/arduino-cli/latest/installation/) -- [arduino-language-server](https://github.com/arduino/arduino-language-server) +The repository setup script can install the command-line prerequisites with: + +```bash +./setup.sh --with-editor +``` + +This installs `arduino-cli`, the `clang` package that provides `clangd`, `neovim`, and `arduino-language-server` on Arch Linux. The Neovim plugin dependencies are: + - [Telescope.nvim](https://github.com/nvim-telescope/telescope.nvim) -- [nvim-lspconfig](https://github.com/neovim/nvim-lspconfig) +- [nvim-lspconfig](https://github.com/neovim/nvim-lspconfig) for Neovim versions older than 0.11 diff --git a/compile_commands.json b/compile_commands.json deleted file mode 100644 index 865ce12..0000000 --- a/compile_commands.json +++ /dev/null @@ -1,684 +0,0 @@ -[ - { - "directory": "/home/alvin/Arduino", - "arguments": [ - "/home/alvin/.arduino15/packages/arduino/tools/avr-gcc/7.3.0-atmel3.6.1-arduino7/bin/avr-g++", - "-c", - "-g", - "-Os", - "-w", - "-std=gnu++11", - "-fno-exceptions", - "-ffunction-sections", - "-fdata-sections", - "-fno-threadsafe-statics", - "-MMD", - "-mmcu=atmega168", - "-DF_CPU=8000000L", - "-DARDUINO=10607", - "-DARDUINO_AVR_PRO", - "-DARDUINO_ARCH_AVR", - "-I/home/alvin/.arduino15/packages/arduino/hardware/avr/1.8.8/cores/arduino", - "-I/home/alvin/.arduino15/packages/arduino/hardware/avr/1.8.8/variants/standard", - "/home/alvin/.cache/arduino/studuino-compile-db/sketch/Arduino.ino.cpp", - "-o", - "/home/alvin/.cache/arduino/studuino-compile-db/sketch/Arduino.ino.cpp.o" - ], - "file": "/home/alvin/.cache/arduino/studuino-compile-db/sketch/Arduino.ino.cpp" - }, - { - "directory": "/home/alvin/Arduino", - "arguments": [ - "/home/alvin/.arduino15/packages/arduino/tools/avr-gcc/7.3.0-atmel3.6.1-arduino7/bin/avr-g++", - "-c", - "-g", - "-Os", - "-w", - "-std=gnu++11", - "-fno-exceptions", - "-ffunction-sections", - "-fdata-sections", - "-fno-threadsafe-statics", - "-MMD", - "-mmcu=atmega168", - "-DF_CPU=8000000L", - "-DARDUINO=10607", - "-DARDUINO_AVR_PRO", - "-DARDUINO_ARCH_AVR", - "-I/home/alvin/.arduino15/packages/arduino/hardware/avr/1.8.8/cores/arduino", - "-I/home/alvin/.arduino15/packages/arduino/hardware/avr/1.8.8/variants/standard", - "/home/alvin/.arduino15/packages/arduino/hardware/avr/1.8.8/cores/arduino/CDC.cpp", - "-o", - "/home/alvin/.cache/arduino/studuino-compile-db/core/CDC.cpp.o" - ], - "file": "/home/alvin/.arduino15/packages/arduino/hardware/avr/1.8.8/cores/arduino/CDC.cpp" - }, - { - "directory": "/home/alvin/Arduino", - "arguments": [ - "/home/alvin/.arduino15/packages/arduino/tools/avr-gcc/7.3.0-atmel3.6.1-arduino7/bin/avr-g++", - "-c", - "-g", - "-Os", - "-w", - "-std=gnu++11", - "-fno-exceptions", - "-ffunction-sections", - "-fdata-sections", - "-fno-threadsafe-statics", - "-MMD", - "-mmcu=atmega168", - "-DF_CPU=8000000L", - "-DARDUINO=10607", - "-DARDUINO_AVR_PRO", - "-DARDUINO_ARCH_AVR", - "-I/home/alvin/.arduino15/packages/arduino/hardware/avr/1.8.8/cores/arduino", - "-I/home/alvin/.arduino15/packages/arduino/hardware/avr/1.8.8/variants/standard", - "/home/alvin/.arduino15/packages/arduino/hardware/avr/1.8.8/cores/arduino/HardwareSerial1.cpp", - "-o", - "/home/alvin/.cache/arduino/studuino-compile-db/core/HardwareSerial1.cpp.o" - ], - "file": "/home/alvin/.arduino15/packages/arduino/hardware/avr/1.8.8/cores/arduino/HardwareSerial1.cpp" - }, - { - "directory": "/home/alvin/Arduino", - "arguments": [ - "/home/alvin/.arduino15/packages/arduino/tools/avr-gcc/7.3.0-atmel3.6.1-arduino7/bin/avr-g++", - "-c", - "-g", - "-Os", - "-w", - "-std=gnu++11", - "-fno-exceptions", - "-ffunction-sections", - "-fdata-sections", - "-fno-threadsafe-statics", - "-MMD", - "-mmcu=atmega168", - "-DF_CPU=8000000L", - "-DARDUINO=10607", - "-DARDUINO_AVR_PRO", - "-DARDUINO_ARCH_AVR", - "-I/home/alvin/.arduino15/packages/arduino/hardware/avr/1.8.8/cores/arduino", - "-I/home/alvin/.arduino15/packages/arduino/hardware/avr/1.8.8/variants/standard", - "/home/alvin/.arduino15/packages/arduino/hardware/avr/1.8.8/cores/arduino/HardwareSerial.cpp", - "-o", - "/home/alvin/.cache/arduino/studuino-compile-db/core/HardwareSerial.cpp.o" - ], - "file": "/home/alvin/.arduino15/packages/arduino/hardware/avr/1.8.8/cores/arduino/HardwareSerial.cpp" - }, - { - "directory": "/home/alvin/Arduino", - "arguments": [ - "/home/alvin/.arduino15/packages/arduino/tools/avr-gcc/7.3.0-atmel3.6.1-arduino7/bin/avr-g++", - "-c", - "-g", - "-Os", - "-w", - "-std=gnu++11", - "-fno-exceptions", - "-ffunction-sections", - "-fdata-sections", - "-fno-threadsafe-statics", - "-MMD", - "-mmcu=atmega168", - "-DF_CPU=8000000L", - "-DARDUINO=10607", - "-DARDUINO_AVR_PRO", - "-DARDUINO_ARCH_AVR", - "-I/home/alvin/.arduino15/packages/arduino/hardware/avr/1.8.8/cores/arduino", - "-I/home/alvin/.arduino15/packages/arduino/hardware/avr/1.8.8/variants/standard", - "/home/alvin/.arduino15/packages/arduino/hardware/avr/1.8.8/cores/arduino/HardwareSerial3.cpp", - "-o", - "/home/alvin/.cache/arduino/studuino-compile-db/core/HardwareSerial3.cpp.o" - ], - "file": "/home/alvin/.arduino15/packages/arduino/hardware/avr/1.8.8/cores/arduino/HardwareSerial3.cpp" - }, - { - "directory": "/home/alvin/Arduino", - "arguments": [ - "/home/alvin/.arduino15/packages/arduino/tools/avr-gcc/7.3.0-atmel3.6.1-arduino7/bin/avr-g++", - "-c", - "-g", - "-Os", - "-w", - "-std=gnu++11", - "-fno-exceptions", - "-ffunction-sections", - "-fdata-sections", - "-fno-threadsafe-statics", - "-MMD", - "-mmcu=atmega168", - "-DF_CPU=8000000L", - "-DARDUINO=10607", - "-DARDUINO_AVR_PRO", - "-DARDUINO_ARCH_AVR", - "-I/home/alvin/.arduino15/packages/arduino/hardware/avr/1.8.8/cores/arduino", - "-I/home/alvin/.arduino15/packages/arduino/hardware/avr/1.8.8/variants/standard", - "/home/alvin/.arduino15/packages/arduino/hardware/avr/1.8.8/cores/arduino/Print.cpp", - "-o", - "/home/alvin/.cache/arduino/studuino-compile-db/core/Print.cpp.o" - ], - "file": "/home/alvin/.arduino15/packages/arduino/hardware/avr/1.8.8/cores/arduino/Print.cpp" - }, - { - "directory": "/home/alvin/Arduino", - "arguments": [ - "/home/alvin/.arduino15/packages/arduino/tools/avr-gcc/7.3.0-atmel3.6.1-arduino7/bin/avr-g++", - "-c", - "-g", - "-Os", - "-w", - "-std=gnu++11", - "-fno-exceptions", - "-ffunction-sections", - "-fdata-sections", - "-fno-threadsafe-statics", - "-MMD", - "-mmcu=atmega168", - "-DF_CPU=8000000L", - "-DARDUINO=10607", - "-DARDUINO_AVR_PRO", - "-DARDUINO_ARCH_AVR", - "-I/home/alvin/.arduino15/packages/arduino/hardware/avr/1.8.8/cores/arduino", - "-I/home/alvin/.arduino15/packages/arduino/hardware/avr/1.8.8/variants/standard", - "/home/alvin/.arduino15/packages/arduino/hardware/avr/1.8.8/cores/arduino/HardwareSerial2.cpp", - "-o", - "/home/alvin/.cache/arduino/studuino-compile-db/core/HardwareSerial2.cpp.o" - ], - "file": "/home/alvin/.arduino15/packages/arduino/hardware/avr/1.8.8/cores/arduino/HardwareSerial2.cpp" - }, - { - "directory": "/home/alvin/Arduino", - "arguments": [ - "/home/alvin/.arduino15/packages/arduino/tools/avr-gcc/7.3.0-atmel3.6.1-arduino7/bin/avr-g++", - "-c", - "-g", - "-Os", - "-w", - "-std=gnu++11", - "-fno-exceptions", - "-ffunction-sections", - "-fdata-sections", - "-fno-threadsafe-statics", - "-MMD", - "-mmcu=atmega168", - "-DF_CPU=8000000L", - "-DARDUINO=10607", - "-DARDUINO_AVR_PRO", - "-DARDUINO_ARCH_AVR", - "-I/home/alvin/.arduino15/packages/arduino/hardware/avr/1.8.8/cores/arduino", - "-I/home/alvin/.arduino15/packages/arduino/hardware/avr/1.8.8/variants/standard", - "/home/alvin/.arduino15/packages/arduino/hardware/avr/1.8.8/cores/arduino/IPAddress.cpp", - "-o", - "/home/alvin/.cache/arduino/studuino-compile-db/core/IPAddress.cpp.o" - ], - "file": "/home/alvin/.arduino15/packages/arduino/hardware/avr/1.8.8/cores/arduino/IPAddress.cpp" - }, - { - "directory": "/home/alvin/Arduino", - "arguments": [ - "/home/alvin/.arduino15/packages/arduino/tools/avr-gcc/7.3.0-atmel3.6.1-arduino7/bin/avr-g++", - "-c", - "-g", - "-Os", - "-w", - "-std=gnu++11", - "-fno-exceptions", - "-ffunction-sections", - "-fdata-sections", - "-fno-threadsafe-statics", - "-MMD", - "-mmcu=atmega168", - "-DF_CPU=8000000L", - "-DARDUINO=10607", - "-DARDUINO_AVR_PRO", - "-DARDUINO_ARCH_AVR", - "-I/home/alvin/.arduino15/packages/arduino/hardware/avr/1.8.8/cores/arduino", - "-I/home/alvin/.arduino15/packages/arduino/hardware/avr/1.8.8/variants/standard", - "/home/alvin/.arduino15/packages/arduino/hardware/avr/1.8.8/cores/arduino/Tone.cpp", - "-o", - "/home/alvin/.cache/arduino/studuino-compile-db/core/Tone.cpp.o" - ], - "file": "/home/alvin/.arduino15/packages/arduino/hardware/avr/1.8.8/cores/arduino/Tone.cpp" - }, - { - "directory": "/home/alvin/Arduino", - "arguments": [ - "/home/alvin/.arduino15/packages/arduino/tools/avr-gcc/7.3.0-atmel3.6.1-arduino7/bin/avr-g++", - "-c", - "-g", - "-Os", - "-w", - "-std=gnu++11", - "-fno-exceptions", - "-ffunction-sections", - "-fdata-sections", - "-fno-threadsafe-statics", - "-MMD", - "-mmcu=atmega168", - "-DF_CPU=8000000L", - "-DARDUINO=10607", - "-DARDUINO_AVR_PRO", - "-DARDUINO_ARCH_AVR", - "-I/home/alvin/.arduino15/packages/arduino/hardware/avr/1.8.8/cores/arduino", - "-I/home/alvin/.arduino15/packages/arduino/hardware/avr/1.8.8/variants/standard", - "/home/alvin/.arduino15/packages/arduino/hardware/avr/1.8.8/cores/arduino/HardwareSerial0.cpp", - "-o", - "/home/alvin/.cache/arduino/studuino-compile-db/core/HardwareSerial0.cpp.o" - ], - "file": "/home/alvin/.arduino15/packages/arduino/hardware/avr/1.8.8/cores/arduino/HardwareSerial0.cpp" - }, - { - "directory": "/home/alvin/Arduino", - "arguments": [ - "/home/alvin/.arduino15/packages/arduino/tools/avr-gcc/7.3.0-atmel3.6.1-arduino7/bin/avr-gcc", - "-c", - "-g", - "-Os", - "-w", - "-std=gnu11", - "-ffunction-sections", - "-fdata-sections", - "-MMD", - "-mmcu=atmega168", - "-DF_CPU=8000000L", - "-DARDUINO=10607", - "-DARDUINO_AVR_PRO", - "-DARDUINO_ARCH_AVR", - "-I/home/alvin/.arduino15/packages/arduino/hardware/avr/1.8.8/cores/arduino", - "-I/home/alvin/.arduino15/packages/arduino/hardware/avr/1.8.8/variants/standard", - "/home/alvin/.arduino15/packages/arduino/hardware/avr/1.8.8/cores/arduino/WInterrupts.c", - "-o", - "/home/alvin/.cache/arduino/studuino-compile-db/core/WInterrupts.c.o" - ], - "file": "/home/alvin/.arduino15/packages/arduino/hardware/avr/1.8.8/cores/arduino/WInterrupts.c" - }, - { - "directory": "/home/alvin/Arduino", - "arguments": [ - "/home/alvin/.arduino15/packages/arduino/tools/avr-gcc/7.3.0-atmel3.6.1-arduino7/bin/avr-g++", - "-c", - "-g", - "-Os", - "-w", - "-std=gnu++11", - "-fno-exceptions", - "-ffunction-sections", - "-fdata-sections", - "-fno-threadsafe-statics", - "-MMD", - "-mmcu=atmega168", - "-DF_CPU=8000000L", - "-DARDUINO=10607", - "-DARDUINO_AVR_PRO", - "-DARDUINO_ARCH_AVR", - "-I/home/alvin/.arduino15/packages/arduino/hardware/avr/1.8.8/cores/arduino", - "-I/home/alvin/.arduino15/packages/arduino/hardware/avr/1.8.8/variants/standard", - "/home/alvin/.arduino15/packages/arduino/hardware/avr/1.8.8/cores/arduino/WMath.cpp", - "-o", - "/home/alvin/.cache/arduino/studuino-compile-db/core/WMath.cpp.o" - ], - "file": "/home/alvin/.arduino15/packages/arduino/hardware/avr/1.8.8/cores/arduino/WMath.cpp" - }, - { - "directory": "/home/alvin/Arduino", - "arguments": [ - "/home/alvin/.arduino15/packages/arduino/tools/avr-gcc/7.3.0-atmel3.6.1-arduino7/bin/avr-g++", - "-c", - "-g", - "-Os", - "-w", - "-std=gnu++11", - "-fno-exceptions", - "-ffunction-sections", - "-fdata-sections", - "-fno-threadsafe-statics", - "-MMD", - "-mmcu=atmega168", - "-DF_CPU=8000000L", - "-DARDUINO=10607", - "-DARDUINO_AVR_PRO", - "-DARDUINO_ARCH_AVR", - "-I/home/alvin/.arduino15/packages/arduino/hardware/avr/1.8.8/cores/arduino", - "-I/home/alvin/.arduino15/packages/arduino/hardware/avr/1.8.8/variants/standard", - "/home/alvin/.arduino15/packages/arduino/hardware/avr/1.8.8/cores/arduino/Stream.cpp", - "-o", - "/home/alvin/.cache/arduino/studuino-compile-db/core/Stream.cpp.o" - ], - "file": "/home/alvin/.arduino15/packages/arduino/hardware/avr/1.8.8/cores/arduino/Stream.cpp" - }, - { - "directory": "/home/alvin/Arduino", - "arguments": [ - "/home/alvin/.arduino15/packages/arduino/tools/avr-gcc/7.3.0-atmel3.6.1-arduino7/bin/avr-g++", - "-c", - "-g", - "-Os", - "-w", - "-std=gnu++11", - "-fno-exceptions", - "-ffunction-sections", - "-fdata-sections", - "-fno-threadsafe-statics", - "-MMD", - "-mmcu=atmega168", - "-DF_CPU=8000000L", - "-DARDUINO=10607", - "-DARDUINO_AVR_PRO", - "-DARDUINO_ARCH_AVR", - "-I/home/alvin/.arduino15/packages/arduino/hardware/avr/1.8.8/cores/arduino", - "-I/home/alvin/.arduino15/packages/arduino/hardware/avr/1.8.8/variants/standard", - "/home/alvin/.arduino15/packages/arduino/hardware/avr/1.8.8/cores/arduino/PluggableUSB.cpp", - "-o", - "/home/alvin/.cache/arduino/studuino-compile-db/core/PluggableUSB.cpp.o" - ], - "file": "/home/alvin/.arduino15/packages/arduino/hardware/avr/1.8.8/cores/arduino/PluggableUSB.cpp" - }, - { - "directory": "/home/alvin/Arduino", - "arguments": [ - "/home/alvin/.arduino15/packages/arduino/tools/avr-gcc/7.3.0-atmel3.6.1-arduino7/bin/avr-g++", - "-c", - "-g", - "-Os", - "-w", - "-std=gnu++11", - "-fno-exceptions", - "-ffunction-sections", - "-fdata-sections", - "-fno-threadsafe-statics", - "-MMD", - "-mmcu=atmega168", - "-DF_CPU=8000000L", - "-DARDUINO=10607", - "-DARDUINO_AVR_PRO", - "-DARDUINO_ARCH_AVR", - "-I/home/alvin/.arduino15/packages/arduino/hardware/avr/1.8.8/cores/arduino", - "-I/home/alvin/.arduino15/packages/arduino/hardware/avr/1.8.8/variants/standard", - "/home/alvin/.arduino15/packages/arduino/hardware/avr/1.8.8/cores/arduino/USBCore.cpp", - "-o", - "/home/alvin/.cache/arduino/studuino-compile-db/core/USBCore.cpp.o" - ], - "file": "/home/alvin/.arduino15/packages/arduino/hardware/avr/1.8.8/cores/arduino/USBCore.cpp" - }, - { - "directory": "/home/alvin/Arduino", - "arguments": [ - "/home/alvin/.arduino15/packages/arduino/tools/avr-gcc/7.3.0-atmel3.6.1-arduino7/bin/avr-g++", - "-c", - "-g", - "-Os", - "-w", - "-std=gnu++11", - "-fno-exceptions", - "-ffunction-sections", - "-fdata-sections", - "-fno-threadsafe-statics", - "-MMD", - "-mmcu=atmega168", - "-DF_CPU=8000000L", - "-DARDUINO=10607", - "-DARDUINO_AVR_PRO", - "-DARDUINO_ARCH_AVR", - "-I/home/alvin/.arduino15/packages/arduino/hardware/avr/1.8.8/cores/arduino", - "-I/home/alvin/.arduino15/packages/arduino/hardware/avr/1.8.8/variants/standard", - "/home/alvin/.arduino15/packages/arduino/hardware/avr/1.8.8/cores/arduino/new.cpp", - "-o", - "/home/alvin/.cache/arduino/studuino-compile-db/core/new.cpp.o" - ], - "file": "/home/alvin/.arduino15/packages/arduino/hardware/avr/1.8.8/cores/arduino/new.cpp" - }, - { - "directory": "/home/alvin/Arduino", - "arguments": [ - "/home/alvin/.arduino15/packages/arduino/tools/avr-gcc/7.3.0-atmel3.6.1-arduino7/bin/avr-gcc", - "-c", - "-g", - "-Os", - "-w", - "-std=gnu11", - "-ffunction-sections", - "-fdata-sections", - "-MMD", - "-mmcu=atmega168", - "-DF_CPU=8000000L", - "-DARDUINO=10607", - "-DARDUINO_AVR_PRO", - "-DARDUINO_ARCH_AVR", - "-I/home/alvin/.arduino15/packages/arduino/hardware/avr/1.8.8/cores/arduino", - "-I/home/alvin/.arduino15/packages/arduino/hardware/avr/1.8.8/variants/standard", - "/home/alvin/.arduino15/packages/arduino/hardware/avr/1.8.8/cores/arduino/wiring.c", - "-o", - "/home/alvin/.cache/arduino/studuino-compile-db/core/wiring.c.o" - ], - "file": "/home/alvin/.arduino15/packages/arduino/hardware/avr/1.8.8/cores/arduino/wiring.c" - }, - { - "directory": "/home/alvin/Arduino", - "arguments": [ - "/home/alvin/.arduino15/packages/arduino/tools/avr-gcc/7.3.0-atmel3.6.1-arduino7/bin/avr-g++", - "-c", - "-g", - "-Os", - "-w", - "-std=gnu++11", - "-fno-exceptions", - "-ffunction-sections", - "-fdata-sections", - "-fno-threadsafe-statics", - "-MMD", - "-mmcu=atmega168", - "-DF_CPU=8000000L", - "-DARDUINO=10607", - "-DARDUINO_AVR_PRO", - "-DARDUINO_ARCH_AVR", - "-I/home/alvin/.arduino15/packages/arduino/hardware/avr/1.8.8/cores/arduino", - "-I/home/alvin/.arduino15/packages/arduino/hardware/avr/1.8.8/variants/standard", - "/home/alvin/.arduino15/packages/arduino/hardware/avr/1.8.8/cores/arduino/abi.cpp", - "-o", - "/home/alvin/.cache/arduino/studuino-compile-db/core/abi.cpp.o" - ], - "file": "/home/alvin/.arduino15/packages/arduino/hardware/avr/1.8.8/cores/arduino/abi.cpp" - }, - { - "directory": "/home/alvin/Arduino", - "arguments": [ - "/home/alvin/.arduino15/packages/arduino/tools/avr-gcc/7.3.0-atmel3.6.1-arduino7/bin/avr-g++", - "-c", - "-g", - "-Os", - "-w", - "-std=gnu++11", - "-fno-exceptions", - "-ffunction-sections", - "-fdata-sections", - "-fno-threadsafe-statics", - "-MMD", - "-mmcu=atmega168", - "-DF_CPU=8000000L", - "-DARDUINO=10607", - "-DARDUINO_AVR_PRO", - "-DARDUINO_ARCH_AVR", - "-I/home/alvin/.arduino15/packages/arduino/hardware/avr/1.8.8/cores/arduino", - "-I/home/alvin/.arduino15/packages/arduino/hardware/avr/1.8.8/variants/standard", - "/home/alvin/.arduino15/packages/arduino/hardware/avr/1.8.8/cores/arduino/WString.cpp", - "-o", - "/home/alvin/.cache/arduino/studuino-compile-db/core/WString.cpp.o" - ], - "file": "/home/alvin/.arduino15/packages/arduino/hardware/avr/1.8.8/cores/arduino/WString.cpp" - }, - { - "directory": "/home/alvin/Arduino", - "arguments": [ - "/home/alvin/.arduino15/packages/arduino/tools/avr-gcc/7.3.0-atmel3.6.1-arduino7/bin/avr-gcc", - "-c", - "-g", - "-Os", - "-w", - "-std=gnu11", - "-ffunction-sections", - "-fdata-sections", - "-MMD", - "-mmcu=atmega168", - "-DF_CPU=8000000L", - "-DARDUINO=10607", - "-DARDUINO_AVR_PRO", - "-DARDUINO_ARCH_AVR", - "-I/home/alvin/.arduino15/packages/arduino/hardware/avr/1.8.8/cores/arduino", - "-I/home/alvin/.arduino15/packages/arduino/hardware/avr/1.8.8/variants/standard", - "/home/alvin/.arduino15/packages/arduino/hardware/avr/1.8.8/cores/arduino/wiring_pulse.c", - "-o", - "/home/alvin/.cache/arduino/studuino-compile-db/core/wiring_pulse.c.o" - ], - "file": "/home/alvin/.arduino15/packages/arduino/hardware/avr/1.8.8/cores/arduino/wiring_pulse.c" - }, - { - "directory": "/home/alvin/Arduino", - "arguments": [ - "/home/alvin/.arduino15/packages/arduino/tools/avr-gcc/7.3.0-atmel3.6.1-arduino7/bin/avr-gcc", - "-c", - "-g", - "-Os", - "-w", - "-std=gnu11", - "-ffunction-sections", - "-fdata-sections", - "-MMD", - "-mmcu=atmega168", - "-DF_CPU=8000000L", - "-DARDUINO=10607", - "-DARDUINO_AVR_PRO", - "-DARDUINO_ARCH_AVR", - "-I/home/alvin/.arduino15/packages/arduino/hardware/avr/1.8.8/cores/arduino", - "-I/home/alvin/.arduino15/packages/arduino/hardware/avr/1.8.8/variants/standard", - "/home/alvin/.arduino15/packages/arduino/hardware/avr/1.8.8/cores/arduino/hooks.c", - "-o", - "/home/alvin/.cache/arduino/studuino-compile-db/core/hooks.c.o" - ], - "file": "/home/alvin/.arduino15/packages/arduino/hardware/avr/1.8.8/cores/arduino/hooks.c" - }, - { - "directory": "/home/alvin/Arduino", - "arguments": [ - "/home/alvin/.arduino15/packages/arduino/tools/avr-gcc/7.3.0-atmel3.6.1-arduino7/bin/avr-gcc", - "-c", - "-g", - "-x", - "assembler-with-cpp", - "-mmcu=atmega168", - "-DF_CPU=8000000L", - "-DARDUINO=10607", - "-DARDUINO_AVR_PRO", - "-DARDUINO_ARCH_AVR", - "-I/home/alvin/.arduino15/packages/arduino/hardware/avr/1.8.8/cores/arduino", - "-I/home/alvin/.arduino15/packages/arduino/hardware/avr/1.8.8/variants/standard", - "/home/alvin/.arduino15/packages/arduino/hardware/avr/1.8.8/cores/arduino/wiring_pulse.S", - "-o", - "/home/alvin/.cache/arduino/studuino-compile-db/core/wiring_pulse.S.o" - ], - "file": "/home/alvin/.arduino15/packages/arduino/hardware/avr/1.8.8/cores/arduino/wiring_pulse.S" - }, - { - "directory": "/home/alvin/Arduino", - "arguments": [ - "/home/alvin/.arduino15/packages/arduino/tools/avr-gcc/7.3.0-atmel3.6.1-arduino7/bin/avr-gcc", - "-c", - "-g", - "-Os", - "-w", - "-std=gnu11", - "-ffunction-sections", - "-fdata-sections", - "-MMD", - "-mmcu=atmega168", - "-DF_CPU=8000000L", - "-DARDUINO=10607", - "-DARDUINO_AVR_PRO", - "-DARDUINO_ARCH_AVR", - "-I/home/alvin/.arduino15/packages/arduino/hardware/avr/1.8.8/cores/arduino", - "-I/home/alvin/.arduino15/packages/arduino/hardware/avr/1.8.8/variants/standard", - "/home/alvin/.arduino15/packages/arduino/hardware/avr/1.8.8/cores/arduino/wiring_digital.c", - "-o", - "/home/alvin/.cache/arduino/studuino-compile-db/core/wiring_digital.c.o" - ], - "file": "/home/alvin/.arduino15/packages/arduino/hardware/avr/1.8.8/cores/arduino/wiring_digital.c" - }, - { - "directory": "/home/alvin/Arduino", - "arguments": [ - "/home/alvin/.arduino15/packages/arduino/tools/avr-gcc/7.3.0-atmel3.6.1-arduino7/bin/avr-gcc", - "-c", - "-g", - "-Os", - "-w", - "-std=gnu11", - "-ffunction-sections", - "-fdata-sections", - "-MMD", - "-mmcu=atmega168", - "-DF_CPU=8000000L", - "-DARDUINO=10607", - "-DARDUINO_AVR_PRO", - "-DARDUINO_ARCH_AVR", - "-I/home/alvin/.arduino15/packages/arduino/hardware/avr/1.8.8/cores/arduino", - "-I/home/alvin/.arduino15/packages/arduino/hardware/avr/1.8.8/variants/standard", - "/home/alvin/.arduino15/packages/arduino/hardware/avr/1.8.8/cores/arduino/wiring_shift.c", - "-o", - "/home/alvin/.cache/arduino/studuino-compile-db/core/wiring_shift.c.o" - ], - "file": "/home/alvin/.arduino15/packages/arduino/hardware/avr/1.8.8/cores/arduino/wiring_shift.c" - }, - { - "directory": "/home/alvin/Arduino", - "arguments": [ - "/home/alvin/.arduino15/packages/arduino/tools/avr-gcc/7.3.0-atmel3.6.1-arduino7/bin/avr-gcc", - "-c", - "-g", - "-Os", - "-w", - "-std=gnu11", - "-ffunction-sections", - "-fdata-sections", - "-MMD", - "-mmcu=atmega168", - "-DF_CPU=8000000L", - "-DARDUINO=10607", - "-DARDUINO_AVR_PRO", - "-DARDUINO_ARCH_AVR", - "-I/home/alvin/.arduino15/packages/arduino/hardware/avr/1.8.8/cores/arduino", - "-I/home/alvin/.arduino15/packages/arduino/hardware/avr/1.8.8/variants/standard", - "/home/alvin/.arduino15/packages/arduino/hardware/avr/1.8.8/cores/arduino/wiring_analog.c", - "-o", - "/home/alvin/.cache/arduino/studuino-compile-db/core/wiring_analog.c.o" - ], - "file": "/home/alvin/.arduino15/packages/arduino/hardware/avr/1.8.8/cores/arduino/wiring_analog.c" - }, - { - "directory": "/home/alvin/Arduino", - "arguments": [ - "/home/alvin/.arduino15/packages/arduino/tools/avr-gcc/7.3.0-atmel3.6.1-arduino7/bin/avr-g++", - "-c", - "-g", - "-Os", - "-w", - "-std=gnu++11", - "-fno-exceptions", - "-ffunction-sections", - "-fdata-sections", - "-fno-threadsafe-statics", - "-MMD", - "-mmcu=atmega168", - "-DF_CPU=8000000L", - "-DARDUINO=10607", - "-DARDUINO_AVR_PRO", - "-DARDUINO_ARCH_AVR", - "-I/home/alvin/.arduino15/packages/arduino/hardware/avr/1.8.8/cores/arduino", - "-I/home/alvin/.arduino15/packages/arduino/hardware/avr/1.8.8/variants/standard", - "/home/alvin/.arduino15/packages/arduino/hardware/avr/1.8.8/cores/arduino/main.cpp", - "-o", - "/home/alvin/.cache/arduino/studuino-compile-db/core/main.cpp.o" - ], - "file": "/home/alvin/.arduino15/packages/arduino/hardware/avr/1.8.8/cores/arduino/main.cpp" - } -] \ No newline at end of file diff --git a/hardware/studuino/avr/boards.txt b/hardware/studuino/avr/boards.txt index ccad612..cb8d088 100755 --- a/hardware/studuino/avr/boards.txt +++ b/hardware/studuino/avr/boards.txt @@ -7,7 +7,8 @@ menu.cpu=Processor studuino.name=Studuino (3.3V, 8 MHz) w/ ATmega168 studuino.upload.tool=avrdude studuino.upload.protocol=arduino -studuino.upload.maximum_size=15872 +studuino.upload.maximum_size=14336 +studuino.upload.maximum_data_size=1024 studuino.upload.speed=115200 studuino.bootloader.tool=avrdude @@ -22,7 +23,5 @@ studuino.bootloader.lock_bits=0x0F studuino.build.mcu=atmega168 studuino.build.f_cpu=8000000L studuino.build.board=AVR_PRO -studuino.build.core=arduino -studuino.build.variant=standard studuino.build.core=arduino:arduino studuino.build.variant=arduino:standard diff --git a/setup.sh b/setup.sh index e7ae3cf..bff5b2d 100755 --- a/setup.sh +++ b/setup.sh @@ -6,40 +6,35 @@ set -Eeuo pipefail SCRIPT_DIR="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)" ARDUINO_USER_OVERRIDE="${ARDUINO_USER:-}" ARDUINO_USER="${ARDUINO_USER:-$HOME/Arduino}" -RESOURCE_DIR="$SCRIPT_DIR/Resources" -LIBRARY_ARCHIVE="$RESOURCE_DIR/studuino_v1_lib.zip" -HARDWARE_ARCHIVE="$RESOURCE_DIR/arduino_IDE_hardware_settings_ver17x.zip" +HARDWARE_SOURCE_DIR="$SCRIPT_DIR/hardware/studuino/avr" +LIBRARY_SOURCE_DIR="$SCRIPT_DIR/libraries" FQBN="studuino:avr:studuino" +MIN_AVR_CORE_VERSION="1.8.8" BUILD_DIR="${XDG_CACHE_HOME:-$HOME/.cache}/arduino/studuino-compile-db" VERIFY_BUILD_DIR="$BUILD_DIR/verify" +SMOKE_VERIFY_BUILD_DIR="$BUILD_DIR/verify-studuino-blink" +SMOKE_SKETCH_DIR="$LIBRARY_SOURCE_DIR/Studuino/example/Blink" FORCE=0 CLEAN_LIBRARIES=0 SKIP_PACKAGES=0 SKIP_PERMISSIONS=0 SKIP_COMPILE_DB=0 +WITH_EDITOR=0 WITH_MONITOR=0 CONFIG_FILE="${ARDUINO_CONFIG_FILE:-}" -TEMP_DIRS=() - -cleanup() { - local temporary - for temporary in "${TEMP_DIRS[@]}"; do - [[ -d "$temporary" ]] && rm -rf -- "$temporary" - done -} -trap cleanup EXIT usage() { cat <<'EOF' Usage: ./setup.sh [options] Options: - --force Replace existing Studuino library/hardware files. - --clean Remove user libraries not supplied by the Studuino bundle. + --force Replace hardware/libraries with checked-in versions. + --clean Remove user libraries absent from this repository. --skip-packages Do not install Arch packages. --skip-permissions Do not modify serial-port group membership. --skip-compile-db Do not generate compile_commands.json. + --with-editor Install Neovim, clang, and Arduino language-server tools. --with-monitor Also install picocom for a serial monitor. -h, --help Show this help. @@ -66,6 +61,9 @@ while (($# > 0)); do --skip-compile-db) SKIP_COMPILE_DB=1 ;; + --with-editor) + WITH_EDITOR=1 + ;; --with-monitor) WITH_MONITOR=1 ;; @@ -129,24 +127,28 @@ install_packages() { info "Skipping Arch package installation." else require_command pacman - local -a packages=( - arduino-cli - clangd - make - neovim - python - unzip - ) + local -a packages=(arduino-cli) + + if ((WITH_EDITOR)); then + packages+=(clang neovim arduino-language-server) + fi if ((WITH_MONITOR)); then packages+=(picocom) fi + info "Installing required Arch packages." as_root pacman -S --needed "${packages[@]}" fi require_command arduino-cli - require_command python3 - require_command unzip + if ((WITH_EDITOR)); then + require_command clangd + require_command nvim + require_command arduino-language-server + fi + if ((WITH_MONITOR)); then + require_command picocom + fi } ensure_serial_permissions() { @@ -207,7 +209,29 @@ resolve_arduino_user() { fi } +validate_hardware_files() { + local directory="$1" + + [[ -f "$directory/boards.txt" ]] || die "Missing Studuino board definition: $directory/boards.txt" + [[ -f "$directory/platform.txt" ]] || die "Missing Studuino platform definition: $directory/platform.txt" + [[ -f "$directory/platform.local.txt" ]] || die "Missing Studuino CLI overrides: $directory/platform.local.txt" + grep -q '^studuino.name=' "$directory/boards.txt" \ + || die "The Studuino board definition is missing its board entry." + grep -q '^name=' "$directory/platform.txt" \ + || die "The Studuino platform definition is missing its platform name." +} + +hardware_matches_source() { + local file + for file in boards.txt platform.txt platform.local.txt; do + cmp -s -- "$HARDWARE_SOURCE_DIR/$file" "$ARDUINO_USER/hardware/studuino/avr/$file" || return 1 + done +} + ensure_hardware_layout() { + [[ -d "$HARDWARE_SOURCE_DIR" ]] || die "Checked-in hardware directory not found: $HARDWARE_SOURCE_DIR" + validate_hardware_files "$HARDWARE_SOURCE_DIR" + local vendor_dir="$ARDUINO_USER/hardware/studuino" local hardware_dir="$vendor_dir/avr" local nested_dir="$vendor_dir/studuino/avr" @@ -227,120 +251,88 @@ ensure_hardware_layout() { fi fi - if [[ -f "$hardware_dir/boards.txt" && -f "$hardware_dir/platform.txt" ]] && (( FORCE == 0 )); then - info "Studuino hardware files are already installed; keeping them." + if [[ "$HARDWARE_SOURCE_DIR" -ef "$hardware_dir" ]]; then + info "Using the checked-in Studuino hardware definition." + elif [[ -L "$hardware_dir" ]]; then + die "Refusing to replace symlinked hardware directory: $hardware_dir" + elif [[ -e "$hardware_dir" ]] && ((FORCE == 0)); then + if hardware_matches_source; then + info "Studuino hardware files are already installed; keeping them." + else + warn "Installed Studuino hardware differs from this repository; keeping it. Re-run with --force to replace it." + fi else - [[ -f "$HARDWARE_ARCHIVE" ]] || die "Hardware archive not found: $HARDWARE_ARCHIVE" mkdir -p -- "$hardware_dir" - - # The official archive was created on Windows and uses backslashes in ZIP - # entry names. Extract only the Linux/other Studuino platform files. - python3 - "$HARDWARE_ARCHIVE" "$hardware_dir" "$FORCE" <<'PY' -from pathlib import Path -import sys -from zipfile import ZipFile - -archive = Path(sys.argv[1]) -destination = Path(sys.argv[2]) -force = sys.argv[3] == "1" - -wanted = { - "arduino_ide_settings_ver17x/other/hardware/studuino/avr/boards.txt": "boards.txt", - "arduino_ide_settings_ver17x/other/hardware/studuino/avr/platform.txt": "platform.txt", -} -found = set() - -with ZipFile(archive) as zipped: - for info in zipped.infolist(): - normalized = info.filename.replace("\\", "/") - target_name = wanted.get(normalized) - if target_name is None: - continue - target = destination / target_name - if target.exists() and not force: - print(f"[studuino] Keeping existing {target}") - else: - target.write_bytes(zipped.read(info)) - print(f"[studuino] Installed {target}") - found.add(target_name) - -missing = set(wanted.values()) - found -if missing: - raise SystemExit("Missing hardware files in archive: " + ", ".join(sorted(missing))) -PY + if ((FORCE)) && [[ -e "$hardware_dir" ]]; then + rm -rf -- "$hardware_dir" + mkdir -p -- "$hardware_dir" + fi + cp -a -- "$HARDWARE_SOURCE_DIR/." "$hardware_dir/" + info "Installed checked-in Studuino hardware files: $hardware_dir" fi +} - # The archive targets the legacy IDE's tool paths. These overrides make it - # work with the AVR tools installed by arduino-cli. - local local_properties="$hardware_dir/platform.local.txt" - cat >"$local_properties" <<'EOF' -# Generated by setup.sh for modern arduino-cli AVR tool paths. -compiler.path={runtime.tools.avr-gcc.path}/bin/ -archive_file_path={build.path}/{archive_file} -recipe.ar.pattern="{compiler.path}{compiler.ar.cmd}" {compiler.ar.flags} {compiler.ar.extra_flags} "{archive_file_path}" "{object_file}" -tools.avrdude.path={runtime.tools.avrdude.path} -tools.avrdude.cmd.path={path}/bin/avrdude -tools.avrdude.config.path={path}/etc/avrdude.conf -EOF - info "Wrote modern CLI compatibility overrides: $local_properties" +version_at_least() { + local current="$1" + local minimum="$2" - grep -q '^studuino.name=' "$hardware_dir/boards.txt" \ - || die "The installed Studuino boards.txt is missing its board definition." - grep -q '^name=' "$hardware_dir/platform.txt" \ - || die "The installed Studuino platform.txt is missing its platform name." + [[ "$current" == "$minimum" ]] && return 0 + [[ "$(printf '%s\n%s\n' "$minimum" "$current" | sort -V | head -n 1)" == "$minimum" ]] } ensure_avr_core() { - if run_cli core list | awk '$1 == "arduino:avr" { found = 1 } END { exit !found }'; then - info "AVR core is already installed." + local installed + installed="$(run_cli core list | awk '$1 == "arduino:avr" { print $2; exit }')" + + if [[ -z "$installed" ]]; then + info "Installing Arduino AVR core $MIN_AVR_CORE_VERSION." + run_cli core update-index + run_cli core install "arduino:avr@$MIN_AVR_CORE_VERSION" return fi - info "Installing the Arduino AVR core." + if version_at_least "$installed" "$MIN_AVR_CORE_VERSION"; then + info "Arduino AVR core $installed is installed." + return + fi + + warn "Arduino AVR core $installed is older than $MIN_AVR_CORE_VERSION; upgrading." run_cli core update-index - run_cli core install arduino:avr + run_cli core install "arduino:avr@$MIN_AVR_CORE_VERSION" } install_studuino_libraries() { - [[ -f "$LIBRARY_ARCHIVE" ]] || die "Library archive not found: $LIBRARY_ARCHIVE" - - local temporary - temporary="$(mktemp -d)" - TEMP_DIRS+=("$temporary") - - unzip -q "$LIBRARY_ARCHIVE" -d "$temporary" - local bundle_dir="$temporary/studuino_v1_lib" - [[ -d "$bundle_dir/Studuino" ]] || die "Unexpected Studuino library archive layout." + [[ -d "$LIBRARY_SOURCE_DIR/Studuino" ]] \ + || die "Checked-in Studuino library not found: $LIBRARY_SOURCE_DIR/Studuino" mkdir -p -- "$ARDUINO_USER/libraries" local source_dir destination name - for source_dir in "$bundle_dir"/*; do - [[ -d "$source_dir" ]] || continue + for source_dir in "$LIBRARY_SOURCE_DIR"/*; do + [[ -d "$source_dir" && ! -L "$source_dir" ]] || continue name="${source_dir##*/}" destination="$ARDUINO_USER/libraries/$name" - if [[ -L "$destination" ]]; then + if [[ "$source_dir" -ef "$destination" ]]; then + info "Using checked-in library: $name" + elif [[ -L "$destination" ]]; then die "Refusing to replace symlinked library: $destination" - fi - if [[ -e "$destination" ]] && ((FORCE == 0)); then + elif [[ -e "$destination" ]] && ((FORCE == 0)); then info "Keeping existing Studuino library: $destination" else if [[ -e "$destination" ]]; then rm -rf -- "$destination" fi cp -a -- "$source_dir" "$destination" - info "Installed Studuino library: $destination" + info "Installed checked-in Studuino library: $destination" fi done if ((CLEAN_LIBRARIES)); then local -A keep=() - for source_dir in "$bundle_dir"/*; do - [[ -d "$source_dir" ]] || continue + for source_dir in "$LIBRARY_SOURCE_DIR"/*; do + [[ -d "$source_dir" && ! -L "$source_dir" ]] || continue keep["${source_dir##*/}"]=1 done - # Servo is required by Studuino even though it is not in the ZIP. - keep[Servo]=1 local installed_dir installed_name for installed_dir in "$ARDUINO_USER/libraries"/*; do @@ -348,7 +340,7 @@ install_studuino_libraries() { installed_name="${installed_dir##*/}" if [[ -z "${keep[$installed_name]+present}" ]]; then rm -rf -- "$installed_dir" - info "Removed non-Studuino library: $installed_dir" + info "Removed library not supplied by this repository: $installed_dir" fi done fi @@ -391,17 +383,23 @@ EOF mv -- "$SCRIPT_DIR/sketch.ino" "$sketch" else cat >"$sketch" <<'EOF' -#include +#include +#include // Keep the complete smoke-test dependency set in clangd's database. + +Studuino board; void setup() { - // Add Studuino initialization here. + board.InitSensorPort(PORT_A0, PIDLED); } void loop() { - // Add Studuino code here. + board.LED(PORT_A0, ON); + board.Timer(1); + board.LED(PORT_A0, OFF); + board.Timer(1); } EOF - info "Created a minimal sketch at $sketch" + info "Created a Studuino smoke-test sketch at $sketch" fi elif [[ -f "$SCRIPT_DIR/sketch.ino" ]]; then warn "Both Arduino.ino and sketch.ino exist; leaving sketch.ino untouched." @@ -416,13 +414,13 @@ generate_compile_database() { mkdir -p -- "$BUILD_DIR" info "Generating the Neovim/clangd compilation database." - if run_cli compile --clean --fqbn "$FQBN" --only-compilation-database \ + if ! run_cli compile --clean --fqbn "$FQBN" --only-compilation-database \ --build-path "$BUILD_DIR" "$SCRIPT_DIR"; then - cp -- "$BUILD_DIR/compile_commands.json" "$SCRIPT_DIR/compile_commands.json" - info "Wrote $SCRIPT_DIR/compile_commands.json" - else - warn "Could not generate compile_commands.json; the Studuino setup is otherwise complete." + die "Could not generate compile_commands.json." fi + + cp -- "$BUILD_DIR/compile_commands.json" "$SCRIPT_DIR/compile_commands.json" + info "Wrote $SCRIPT_DIR/compile_commands.json" } verify_setup() { @@ -436,6 +434,12 @@ verify_setup() { run_cli lib list | grep -E '^Servo[[:space:]]' >/dev/null \ || die "The Servo library is not visible to arduino-cli." + [[ -f "$SMOKE_SKETCH_DIR/Blink.ino" ]] \ + || die "Studuino smoke-test sketch not found: $SMOKE_SKETCH_DIR/Blink.ino" + info "Compiling the Studuino Blink smoke test for $FQBN..." + run_cli compile --clean --fqbn "$FQBN" \ + --build-path "$SMOKE_VERIFY_BUILD_DIR" "$SMOKE_SKETCH_DIR" + info "Compiling the project for $FQBN..." run_cli compile --clean --fqbn "$FQBN" \ --build-path "$VERIFY_BUILD_DIR" "$SCRIPT_DIR"