commit b2afa2da8c8072d4b7ab72a5c2463779fa6dcf38 Author: Bouke van der Bijl Date: Tue Dec 20 14:18:29 2022 +0100 Initial commit diff --git a/flake.lock b/flake.lock new file mode 100644 index 0000000..5999137 --- /dev/null +++ b/flake.lock @@ -0,0 +1,7 @@ +{ + "nodes": { + "root": {} + }, + "root": "root", + "version": 7 +} diff --git a/flake.nix b/flake.nix new file mode 100644 index 0000000..9ad00c5 --- /dev/null +++ b/flake.nix @@ -0,0 +1,21 @@ +{ + description = "Wrapper for arduino-cli"; + + outputs = { self }: { + mkArduinoPackageOverlay = packageIndexFile: (self: super: { + arduinoPackages = self.lib.recursiveUpdate (super.arduinoPackages or {}) (self.callPackage ./packages.nix { + packageIndex = builtins.fromJSON (builtins.readFile packageIndexFile); + }); + }); + + mkArduinoLibraryOverlay = libraryIndexFile: (self: super: { + arduinoLibraries = self.lib.recursiveUpdate (super.arduinoLibraries or {}) (self.callPackage ./libraries.nix { + libraryIndex = builtins.fromJSON (builtins.readFile libraryIndexFile); + }); + }); + + overlay = (self: super: { + wrapArduinoCLI = self.callPackage ./wrap-arduino-cli.nix { }; + }); + }; +} diff --git a/lib.nix b/lib.nix new file mode 100644 index 0000000..93e1daf --- /dev/null +++ b/lib.nix @@ -0,0 +1,32 @@ +{ lib }: +let + alt = a: b: if a == null then b else a; +in +with builtins; rec { + latestVersion = attrs: (builtins.head (builtins.sort (a: b: (builtins.compareVersions a.version b.version) == 1) (builtins.attrValues (builtins.mapAttrs (version: value: { inherit version value; }) attrs)))).value; + selectSystem = system: systems: + if system == "aarch64-darwin" then + alt (lib.findFirst ({host, ...}: (match "arm64-apple-darwin.*" host) != null) null systems) (selectSystem "x86_64-darwin" systems) + else if system == "x86_64-darwin" then + alt (lib.findFirst ({host, ...}: (match "x86_64-apple-darwin.*" host) != null) null systems) (selectSystem "i686-darwin" systems) + else if system == "i686-darwin" then + lib.findFirst ({host, ...}: (match "i[3456]86-apple-darwin.*" host) != null) null systems + else if system == "aarch64-linux" then + lib.findFirst ({host, ...}: (match "(aarch64|arm64)-linux-gnu" host) != null) null systems + else if system == "x86_64-linux" then + lib.findFirst ({host, ...}: (match "x86_64-.*linux-gnu" host) != null) null systems + else null; + convertHash = hash: let + m = (match "(SHA-256|SHA-1|MD5):(.*)" hash); + algo = elemAt m 0; + h = elemAt m 1; + in + if m == null then + throw "Unsupported hash format ${hash}" + else if algo == "SHA-256" then + { sha256 = h; } + else if algo == "SHA-1" then + { sha1 = h; } + else + { md5 = h; }; +} diff --git a/libraries.nix b/libraries.nix new file mode 100644 index 0000000..a619cd4 --- /dev/null +++ b/libraries.nix @@ -0,0 +1,24 @@ +{ fetchzip, stdenv, lib, libraryIndex, pkgsBuildHost, pkgs, arduinoPackages }: + +with builtins; +let + inherit (pkgs.callPackage ./lib.nix {}) convertHash; + + libraries = mapAttrs (name: versions: listToAttrs (map ({version, url, checksum, ...}: { + name = version; + value = stdenv.mkDerivation { + pname = name; + inherit version; + + installPhase = '' + mkdir -p "$out/libraries/$pname" + cp -R * "$out/libraries/$pname/" + ''; + nativeBuildInputs = [ pkgs.unzip ]; + src = fetchurl ({ + url = url; + } // (convertHash checksum)); + }; + }) versions)) (groupBy ({ name, ... }: name) libraryIndex.libraries); +in + libraries diff --git a/packages.nix b/packages.nix new file mode 100644 index 0000000..691fa76 --- /dev/null +++ b/packages.nix @@ -0,0 +1,80 @@ +# From tools.go in arduino-cli +# regexpLinuxArm = regexp.MustCompile("arm.*-linux-gnueabihf") +# regexpLinuxArm64 = regexp.MustCompile("(aarch64|arm64)-linux-gnu") +# regexpLinux64 = regexp.MustCompile("x86_64-.*linux-gnu") +# regexpLinux32 = regexp.MustCompile("i[3456]86-.*linux-gnu") +# regexpWindows32 = regexp.MustCompile("i[3456]86-.*(mingw32|cygwin)") +# regexpWindows64 = regexp.MustCompile("(amd64|x86_64)-.*(mingw32|cygwin)") +# regexpMac64 = regexp.MustCompile("x86_64-apple-darwin.*") +# regexpMac32 = regexp.MustCompile("i[3456]86-apple-darwin.*") +# regexpMacArm64 = regexp.MustCompile("arm64-apple-darwin.*") +# regexpFreeBSDArm = regexp.MustCompile("arm.*-freebsd[0-9]*") +# regexpFreeBSD32 = regexp.MustCompile("i?[3456]86-freebsd[0-9]*") +# regexpFreeBSD64 = regexp.MustCompile("amd64-freebsd[0-9]*") + +{ fetchzip, stdenv, lib, packageIndex, pkgsBuildHost, pkgs, arduinoPackages }: + +with builtins; +let + inherit (pkgsBuildHost.xorg) lndir; + inherit (pkgs.callPackage ./lib.nix {}) selectSystem convertHash; + + # Tools are installed in $platform_name/tools/$name/$version + tools = listToAttrs (map ({ name, tools, ... }: { + inherit name; + value = let platformName = name; in mapAttrs (_: versions: listToAttrs (map ({name, version, systems, ...}: { + name = version; + value = let + system = selectSystem stdenv.hostPlatform.system systems; + in + if system == null then + throw "Unsupported platform ${stdenv.hostPlatform.system}" + else + stdenv.mkDerivation { + pname = "${platformName}-${name}"; + inherit version; + + dirName = "packages/${platformName}/tools/${name}/${version}"; + installPhase = '' + mkdir -p "$out/$dirName" + cp -R * "$out/$dirName/" + ''; + nativeBuildInputs = [ pkgs.unzip ]; + src = fetchurl ({ + url = system.url; + } // (convertHash system.checksum)); + }; + }) versions)) (groupBy ({ name, ... }: name) tools); + }) packageIndex.packages); + + # Platform are installed in $platform_name/hardware/$architecture/$version + platforms = listToAttrs (map ({ name, platforms, ... }: { + inherit name; + value = mapAttrs (architecture: versions: listToAttrs (map ({version, url, checksum, toolsDependencies ? [], ...}: { + name = version; + value = stdenv.mkDerivation { + pname = "${name}-${architecture}"; + inherit version; + dirName = "packages/${name}/hardware/${architecture}/${version}"; + + toolsDependencies = map ({packager, name, version}: arduinoPackages.tools.${packager}.${name}.${version}) toolsDependencies; + passAsFile = [ "toolsDependencies" ]; + installPhase = '' + mkdir -p "$out/$dirName" + cp -R * "$out/$dirName/" + + for i in $(cat $toolsDependenciesPath); do + ${lndir}/bin/lndir -silent $i $out + done + ''; + nativeBuildInputs = [ pkgs.unzip ]; + src = fetchurl ({ + url = url; + } // (convertHash checksum)); + }; + }) versions)) (groupBy ({ architecture, ... }: architecture) platforms); + }) packageIndex.packages); +in +{ + inherit tools platforms; +} diff --git a/wrap-arduino-cli.nix b/wrap-arduino-cli.nix new file mode 100644 index 0000000..bc4e469 --- /dev/null +++ b/wrap-arduino-cli.nix @@ -0,0 +1,35 @@ +{ lib, pkgs }: +let + wrap = { + packages ? [] + , libraries ? [] + }: + let + inherit (pkgs.callPackage ./lib.nix {}) latestVersion; + + builtinPackages = (map latestVersion (builtins.attrValues pkgs.arduinoPackages.tools.builtin)); + + libPath = pkgs.symlinkJoin { + name = "arduino-libraries"; + paths = libraries; + }; + + dataPath = pkgs.symlinkJoin { + name = "arduino-data"; + paths = builtinPackages ++ packages ++ [ + # Add some dummy files to keep the CLI happy + (pkgs.writeTextDir "inventory.yaml" (builtins.toJSON {})) + (pkgs.writeTextDir "package_index.json" (builtins.toJSON {packages = [];})) + (pkgs.writeTextDir "library_index.json" (builtins.toJSON {libraries = [];})) + ]; + }; + in + pkgs.runCommand "arduino-cli-wrapped" { + buildInputs = [ pkgs.makeWrapper ]; + meta.mainProgram = "arduino-cli"; + } '' + makeWrapper ${pkgs.arduino-cli}/bin/arduino-cli $out/bin/arduino-cli --set ARDUINO_UPDATER_ENABLE_NOTIFICATION false --set ARDUINO_DIRECTORIES_DATA ${dataPath} --set ARDUINO_DIRECTORIES_USER ${libPath} + ''; +in + lib.makeOverridable wrap +