diff --git a/.cargo/config.toml b/.cargo/config.toml new file mode 100644 index 0000000..c6536eb --- /dev/null +++ b/.cargo/config.toml @@ -0,0 +1,2 @@ +[alias] +xtask = "run --quiet --release --package xtask --" diff --git a/Cargo.toml b/Cargo.toml index 000e5b5..3bc5f08 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,3 +1,8 @@ +[workspace] +members = [".", "xtask"] +default-members = ["."] +resolver = "2" + [package] name = "layers" version = "0.1.0-dev" diff --git a/README.md b/README.md index efc4fd7..ff77596 100644 --- a/README.md +++ b/README.md @@ -11,7 +11,9 @@ a pure-Rust KiCad-board-to-vectors crate. You would not technically need KiCad i ## Install -Every platform installs into KiCad 10's *10.0/plugin* directory. I'm 90% sure that's where they are supposed to go. +Every platform installs into KiCad 10's *10.0/plugins* directory (on Linux it'll also drop into 11.0, 12.0, etc. if you've already got those, native or flatpak, both). I'm 90% sure that's where they are supposed to go. + +`cargo xtask install` picks the right script and runs it. `cargo xtask build` stages without installing. `install-linux` / `install-macos` / `install-windows` force a specific platform if you ever need that. Close KiCad completely prior to running the install script or KiCad might crash, and you might lose work. Close KiCad completely when you update the plugin too. Turns out there's a lot of differences between python and Rust plugins, though maybe the better distiction is IPC plugins in general. I am yet to make a python IPC plugin though, so I can't say for certain. @@ -23,7 +25,7 @@ to regenerate icons from `resources/Layers.svg`). ```sh git clone https://git.else-if.org/jess/Layers cd Layers -./scripts/install.sh +cargo xtask install ``` Installs to `~/Documents/KiCad/10.0/plugins/com.jesshunter.layers/`. @@ -42,7 +44,7 @@ Download and run the installer from . Accept the defaults In the MSYS2 shell: ```sh -# ARM64 (Snapdragon X, Surface Pro 11, etc.) +# ARM64 (Apple M[x], Snapdragon X, Surface Pro 11, etc.) pacman -Syu pacman -S --needed \ mingw-w64-clang-aarch64-toolchain \ @@ -107,7 +109,7 @@ Close and reopen every PowerShell / cmd window after this so they pick up the ch ```bat git clone https://git.else-if.org/jess/Layers cd Layers -install.bat +cargo xtask install ``` Installs to `%USERPROFILE%\Documents\KiCad\10.0\plugins\com.jesshunter.layers\` @@ -128,10 +130,10 @@ source "$HOME/.cargo/env" git clone https://git.else-if.org/jess/Layers cd Layers -./scripts/install-linux.sh +cargo xtask install ``` -Installs to `~/.local/share/kicad/10.0/plugins/com.jesshunter.layers/`. +Installs to `~/.local/share/kicad/10.0/plugins/com.jesshunter.layers/` ### Linux — Arch / Manjaro (pacman) @@ -146,11 +148,15 @@ source "$HOME/.cargo/env" git clone https://git.else-if.org/jess/Layers cd Layers -./scripts/install-linux.sh +cargo xtask install ``` Installs to `~/.local/share/kicad/10.0/plugins/com.jesshunter.layers/`. +In both cases, it checks both the standard directory and the Flatpak directory. If you for some reason have both, it places it in both. If for some reason you have both but only want it in one of them, you can just delete it from the one you don't want it in. + +The Flatpak plugins dir is ` ~/.var/app/org.kicad.KiCad/data/kicad/10.0/plugins/com.jesshunter.layers/` + ## Configuration `resources/colors.toml` in the installed plugin directory controls every UI colour and the diff --git a/build-linux.sh b/build-linux.sh deleted file mode 100755 index f53256c..0000000 --- a/build-linux.sh +++ /dev/null @@ -1,42 +0,0 @@ -#!/usr/bin/env bash -set -euo pipefail - -ROOT="$(cd "$(dirname "$0")" && pwd)" -cd "$ROOT" - -render_plugin_json() { - local entrypoint="$1" - local out="$2" - local in="$ROOT/plugin.json.in" - if [ ! -f "$in" ]; then - echo "ERROR: $in not found" >&2 - exit 1 - fi - sed "s|@ENTRYPOINT@|$entrypoint|g" "$in" | sudo tee "$out" > /dev/null -} - -STAGE="$ROOT/build/bin/com.jesshunter.layers" -APPDIR="$STAGE/bin" - -sudo rm -rf "$STAGE" -sudo mkdir -p "$APPDIR" "$STAGE/resources" - -if command -v sudo rsvg-convert >/dev/null 2>&1 && [ -f "$ROOT/resources/Layers.svg" ]; then - for size in 24 48 128 256; do - if [ ! -f "$ROOT/resources/icon-${size}.png" ]; then - sudo rsvg-convert --width "$size" --height "$size" \ - "$ROOT/resources/Layers.svg" -o "$ROOT/resources/icon-${size}.png" - fi - done -fi - -cargo build --release --bin layers - -sudo cp "$ROOT/target/release/layers" "$APPDIR/Layers" -sudo chmod +x "$APPDIR/Layers" -render_plugin_json "bin/Layers" "$STAGE/plugin.json" -[ -f "$ROOT/LICENCE" ] && sudo cp "$ROOT/LICENCE" "$STAGE/LICENCE" -sudo cp -r "$ROOT/resources/." "$STAGE/resources/" - -echo "staged: $STAGE" -echo "bin: $APPDIR/Layers" diff --git a/resources/icon-128.png b/resources/icon-128.png new file mode 100644 index 0000000..c7e1f69 Binary files /dev/null and b/resources/icon-128.png differ diff --git a/resources/icon-256.png b/resources/icon-256.png new file mode 100644 index 0000000..6887dc1 Binary files /dev/null and b/resources/icon-256.png differ diff --git a/scripts/install-linux.sh b/scripts/install-linux.sh deleted file mode 100755 index 4a75cbc..0000000 --- a/scripts/install-linux.sh +++ /dev/null @@ -1,28 +0,0 @@ -#!/usr/bin/env bash -set -euo pipefail - -ROOT="$(cd "$(dirname "$0")/.." && pwd)" -cd "$ROOT" - -case "$(uname -s)" in - Linux) : ;; - *) echo "use scripts/install.sh on macOS or install.bat on Windows" >&2; exit 1;; -esac - -bash "$ROOT/build-linux.sh" - -INSTALL_ROOT="${XDG_DATA_HOME:-$HOME/.local/share}/kicad/10.0/3rdparty/plugins" -INSTALL_DIR="$INSTALL_ROOT/com.jesshunter.layers" -mkdir -p "$INSTALL_ROOT" - -# Preserve user state (state/, cache/, logs/, settings.json) across reinstall. -rm -rf "$INSTALL_DIR/bin" "$INSTALL_DIR/resources" "$INSTALL_DIR/plugin.json" "$INSTALL_DIR/LICENCE" -mkdir -p "$INSTALL_DIR/bin" "$INSTALL_DIR/resources" - -STAGE="$ROOT/build/bin/com.jesshunter.layers" -cp -R "$STAGE/bin/." "$INSTALL_DIR/bin/" -[ -f "$STAGE/plugin.json" ] && cp "$STAGE/plugin.json" "$INSTALL_DIR/plugin.json" -[ -f "$STAGE/LICENCE" ] && cp "$STAGE/LICENCE" "$INSTALL_DIR/LICENCE" -cp -R "$STAGE/resources/." "$INSTALL_DIR/resources/" - -echo "installed: $INSTALL_DIR" diff --git a/build.bat b/scripts/windows/build.bat similarity index 99% rename from build.bat rename to scripts/windows/build.bat index 00e14a2..87dae2d 100644 --- a/build.bat +++ b/scripts/windows/build.bat @@ -6,7 +6,7 @@ rem ARM64 -> aarch64-pc-windows-gnullvm (clangarm64 llvm-mingw toolchain) rem x86_64 -> x86_64-pc-windows-gnu (ucrt64 gcc-mingw toolchain) rem LAYERS_RUST_TARGET overrides. -pushd %~dp0 +pushd %~dp0..\.. set "ROOT=%CD%" if defined LAYERS_RUST_TARGET ( diff --git a/install.bat b/scripts/windows/install.bat similarity index 56% rename from install.bat rename to scripts/windows/install.bat index 32e7c98..49a7b8d 100644 --- a/install.bat +++ b/scripts/windows/install.bat @@ -1,10 +1,10 @@ @echo off setlocal enabledelayedexpansion -pushd %~dp0 +pushd %~dp0..\.. set "ROOT=%CD%" -call "%ROOT%\build.bat" +call "%ROOT%\scripts\windows\build.bat" if %ERRORLEVEL% neq 0 ( echo build failed popd @@ -15,21 +15,16 @@ rem Resolve the real Documents folder (respects OneDrive / folder redirection). for /f "usebackq delims=" %%i in (`powershell -NoProfile -Command "[Environment]::GetFolderPath('MyDocuments')"`) do set "DOCS=%%i" if not defined DOCS set "DOCS=%USERPROFILE%\Documents" -set "INSTALL_ROOT=%DOCS%\KiCad\10.0\plugins" -set "INSTALL_DIR=%INSTALL_ROOT%\com.jesshunter.layers" -if not exist "%INSTALL_ROOT%" mkdir "%INSTALL_ROOT%" >nul 2>&1 +set "INSTALL_DIR=%DOCS%\KiCad\10.0\plugins\com.jesshunter.layers" -rem Preserve user state (state/, cache/, logs/, settings.json) across reinstall. -if exist "%INSTALL_DIR%\bin" rmdir /s /q "%INSTALL_DIR%\bin" -if exist "%INSTALL_DIR%\resources" rmdir /s /q "%INSTALL_DIR%\resources" +if exist "%INSTALL_DIR%\bin" rmdir /s /q "%INSTALL_DIR%\bin" +if exist "%INSTALL_DIR%\resources" rmdir /s /q "%INSTALL_DIR%\resources" if exist "%INSTALL_DIR%\plugin.json" del /q "%INSTALL_DIR%\plugin.json" if exist "%INSTALL_DIR%\LICENCE" del /q "%INSTALL_DIR%\LICENCE" set "STAGE=%ROOT%\build\bin\com.jesshunter.layers" -xcopy /e /i /y /q "%STAGE%" "%INSTALL_DIR%" >nul +xcopy /e /i /y /q "%STAGE%" "%INSTALL_DIR%" >nul -echo. echo installed: %INSTALL_DIR% -echo. popd endlocal diff --git a/xtask/Cargo.toml b/xtask/Cargo.toml new file mode 100644 index 0000000..f706b5b --- /dev/null +++ b/xtask/Cargo.toml @@ -0,0 +1,9 @@ +[package] +name = "xtask" +version = "0.0.0" +edition = "2021" +publish = false + +[[bin]] +name = "xtask" +path = "src/main.rs" diff --git a/xtask/src/main.rs b/xtask/src/main.rs new file mode 100644 index 0000000..99c859d --- /dev/null +++ b/xtask/src/main.rs @@ -0,0 +1,82 @@ +use std::env; +use std::path::PathBuf; +use std::process::{Command, ExitCode}; + +fn main() -> ExitCode { + let args: Vec = env::args().skip(1).collect(); + let cmd = args.first().map(String::as_str).unwrap_or(""); + + let (action, platform) = match cmd { + "build" => ("build", current_platform()), + "install" => ("install", current_platform()), + "build-linux" => ("build", "linux"), + "install-linux" => ("install", "linux"), + "build-macos" => ("build", "macos"), + "install-macos" => ("install", "macos"), + "build-windows" => ("build", "windows"), + "install-windows" => ("install", "windows"), + _ => { + eprintln!("usage: cargo xtask "); + eprintln!(); + eprintln!("commands:"); + eprintln!(" build build for the current platform"); + eprintln!(" install build + install for the current platform"); + eprintln!(" build- force a specific platform (linux | macos | windows)"); + eprintln!(" install- force a specific platform"); + return ExitCode::from(2); + } + }; + + let repo_root = PathBuf::from(env!("CARGO_MANIFEST_DIR")) + .parent() + .expect("xtask manifest must have a parent") + .to_path_buf(); + + let (script, runner) = match platform { + "windows" => ( + repo_root.join(format!("scripts/windows/{action}.bat")), + vec!["cmd", "/c"], + ), + "linux" | "macos" => ( + repo_root.join(format!("scripts/{platform}/{action}.sh")), + vec!["bash"], + ), + other => { + eprintln!("unknown platform: {other}"); + return ExitCode::from(2); + } + }; + + if !script.exists() { + eprintln!("script not found: {}", script.display()); + return ExitCode::from(1); + } + + let mut command = Command::new(runner[0]); + for arg in &runner[1..] { + command.arg(arg); + } + command.arg(&script); + command.current_dir(&repo_root); + + match command.status() { + Ok(status) if status.success() => ExitCode::SUCCESS, + Ok(status) => ExitCode::from(status.code().unwrap_or(1) as u8), + Err(e) => { + eprintln!("failed to run {}: {e}", script.display()); + ExitCode::from(1) + } + } +} + +fn current_platform() -> &'static str { + match env::consts::OS { + "linux" => "linux", + "macos" => "macos", + "windows" => "windows", + other => { + eprintln!("unsupported OS: {other}"); + std::process::exit(2); + } + } +}