diff --git a/flake.lock b/flake.lock new file mode 100644 index 0000000..a57a1e6 --- /dev/null +++ b/flake.lock @@ -0,0 +1,25 @@ +{ + "nodes": { + "nixpkgs": { + "locked": { + "lastModified": 1681389457, + "narHash": "sha256-Z6TRJ2aI1eRd+kICdrkNyL2aH7XKw8ogzLdtGz1Q9qI=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "c58e6fbf258df1572b535ac1868ec42faf7675dd", + "type": "github" + }, + "original": { + "id": "nixpkgs", + "type": "indirect" + } + }, + "root": { + "inputs": { + "nixpkgs": "nixpkgs" + } + } + }, + "root": "root", + "version": 7 +} diff --git a/flake.nix b/flake.nix index e69de29..78bf446 100644 --- a/flake.nix +++ b/flake.nix @@ -0,0 +1,14 @@ +{ + description = "Kefla POC"; + + outputs = { self, nixpkgs }: + let + kefla = import ./kefla nixpkgs; + in { + packages = kefla { + package-all = ./package-all.nix; + package-darwin = ./package-darwin.nix; + package-linux = ./package-linux.nix; + }; + }; +} diff --git a/kefla/default.nix b/kefla/default.nix new file mode 100644 index 0000000..895331a --- /dev/null +++ b/kefla/default.nix @@ -0,0 +1,2 @@ +nixpkgs: packages: +(import ./internal.nix nixpkgs).kefla packages diff --git a/kefla/fixtures/test-drv-darwin.nix b/kefla/fixtures/test-drv-darwin.nix new file mode 100644 index 0000000..a056d9f --- /dev/null +++ b/kefla/fixtures/test-drv-darwin.nix @@ -0,0 +1,29 @@ +{ lib +, stdenv +, fetchurl +}: + +stdenv.mkDerivation (finalAttrs: { + pname = "hello"; + version = "2.12.1"; + + src = fetchurl { + url = "mirror://gnu/hello/hello-${finalAttrs.version}.tar.gz"; + sha256 = "sha256-jZkUKv2SV28wsM18tCqNxoCZmLxdYH2Idh9RLibH2yA="; + }; + + doCheck = true; + + meta = with lib; { + description = "A program that produces a familiar, friendly greeting"; + longDescription = '' + GNU Hello is a program that prints "Hello, world!" when you run it. + It is fully customizable. + ''; + homepage = "https://www.gnu.org/software/hello/manual/"; + changelog = "https://git.savannah.gnu.org/cgit/hello.git/plain/NEWS?h=v${finalAttrs.version}"; + license = licenses.gpl3Plus; + maintainers = [ maintainers.eelco ]; + platforms = platforms.darwin; + }; +}) diff --git a/kefla/fixtures/test-drv.nix b/kefla/fixtures/test-drv.nix new file mode 100644 index 0000000..b8344f1 --- /dev/null +++ b/kefla/fixtures/test-drv.nix @@ -0,0 +1,29 @@ +{ lib +, stdenv +, fetchurl +}: + +stdenv.mkDerivation (finalAttrs: { + pname = "hello"; + version = "2.12.1"; + + src = fetchurl { + url = "mirror://gnu/hello/hello-${finalAttrs.version}.tar.gz"; + sha256 = "sha256-jZkUKv2SV28wsM18tCqNxoCZmLxdYH2Idh9RLibH2yA="; + }; + + doCheck = true; + + meta = with lib; { + description = "A program that produces a familiar, friendly greeting"; + longDescription = '' + GNU Hello is a program that prints "Hello, world!" when you run it. + It is fully customizable. + ''; + homepage = "https://www.gnu.org/software/hello/manual/"; + changelog = "https://git.savannah.gnu.org/cgit/hello.git/plain/NEWS?h=v${finalAttrs.version}"; + license = licenses.gpl3Plus; + maintainers = [ maintainers.eelco ]; + platforms = platforms.all; + }; +}) diff --git a/kefla/internal.nix b/kefla/internal.nix new file mode 100644 index 0000000..75f162c --- /dev/null +++ b/kefla/internal.nix @@ -0,0 +1,71 @@ +nixpkgs: +let + dummyPkgs = import nixpkgs { system = "x86_64-linux"; }; + lib = dummyPkgs.lib; +in rec { + # Collects all the supported for drv leveraging the meta.platforms + # Nixpkgs attribute. + # + # We callPackage the derivation with a dummy Nixpkgs x86_64 + # instance, regardless of the underlying arch. It doesn't matter + # much, we won't build anything here, we just need callPackage to + # evaluate the meta attributes. + collectPlatformsForDrv = drv: (dummyPkgs.callPackage drv {}).meta.platforms; + + # Generates the flake outputs for PATH for each PLATFORMS platform. + # IE. from + # { + # path = /tmp/dummy/path; + # pathName = "hello"; + # platforms = [ "x86_64-linux""aarch64-linux"]; + # }; + # + # We get: + # + # { + # aarch64-linux = { hello = /tmp/dummy/path; }; + # x86_64-linux = { hello = /tmp/dummy/path; }; + # } + genFlakeOutputForPlatforms = { path, name, platforms }: + lib.genAttrs platforms (platform: { ${name} = path; }); + + # Goes through a flake-like packages output attrs to inject the + # relevant callPackage function call. Obviously, this callPackage + # function is platform-dependant, we'll instantiate a different one + # for each platform subtree. + injectCallPackage = packages: + let + injectPlatformCallPackage = { attrs, platform }: + let + pkgs = import nixpkgs { system = platform; }; + callPackage = pkgs.lib.callPackageWith pkgs; + in builtins.mapAttrs (_name: value: callPackage value {}) attrs; + in builtins.mapAttrs (name: value: + injectPlatformCallPackage { attrs = value; platform = name; }) packages; + + # + + kefla = packagesOutput: + let + packagesWithoutCallPackage = lib.foldlAttrs + (acc: name: path: + let + platforms = collectPlatformsForDrv path; + packageOutput = genFlakeOutputForPlatforms { inherit path platforms name; }; + in lib.recursiveUpdate acc packageOutput) + { } + packagesOutput; + in injectCallPackage packagesWithoutCallPackage; +} + +# lib.foldlAttrs +# (acc: name: value: +# let +# platforms = (dummyPkgs.callPackage value {}).meta.platforms; +# # TODO: découper ça avec des tests intermediaires. +# entries = lib.genAttrs platforms (platform: ) +# in builtins.trace platforms (lib.recursiveUpdate acc { hello = platforms; })) +# {} +# packages + +# } diff --git a/kefla/test b/kefla/test new file mode 100755 index 0000000..db6922a --- /dev/null +++ b/kefla/test @@ -0,0 +1,2 @@ +#!/usr/bin/env bash +nix-instantiate --eval --strict test.nix diff --git a/kefla/test.nix b/kefla/test.nix new file mode 100644 index 0000000..828c4aa --- /dev/null +++ b/kefla/test.nix @@ -0,0 +1,27 @@ +let + nixpkgs = ; + pkgs = import nixpkgs { }; + internal = import ./internal.nix nixpkgs; + fixtures = { + testDrv = import ./fixtures/test-drv.nix; + testDrvDarwin = import ./fixtures/test-drv-darwin.nix; + }; +in pkgs.lib.runTests { + # CollectPlatforms + ################## + testCollectPlatformsAllDrv = { + expr = internal.collectPlatformsForDrv fixtures.testDrv ; + expected = [ "i686-cygwin" "x86_64-cygwin" "x86_64-darwin" "i686-darwin" "aarch64-darwin" "armv7a-darwin" "i686-freebsd13" "x86_64-freebsd13" "aarch64-genode" "i686-genode" "x86_64-genode" "x86_64-solaris" "javascript-ghcjs" "aarch64-linux" "armv5tel-linux" "armv6l-linux" "armv7a-linux" "armv7l-linux" "i686-linux" "m68k-linux" "microblaze-linux" "microblazeel-linux" "mipsel-linux" "mips64el-linux" "powerpc64-linux" "powerpc64le-linux" "riscv32-linux" "riscv64-linux" "s390-linux" "s390x-linux" "x86_64-linux" "mmix-mmixware" "aarch64-netbsd" "armv6l-netbsd" "armv7a-netbsd" "armv7l-netbsd" "i686-netbsd" "m68k-netbsd" "mipsel-netbsd" "powerpc-netbsd" "riscv32-netbsd" "riscv64-netbsd" "x86_64-netbsd" "aarch64_be-none" "aarch64-none" "arm-none" "armv6l-none" "avr-none" "i686-none" "microblaze-none" "microblazeel-none" "msp430-none" "or1k-none" "m68k-none" "powerpc-none" "powerpcle-none" "riscv32-none" "riscv64-none" "rx-none" "s390-none" "s390x-none" "vc4-none" "x86_64-none" "i686-openbsd" "x86_64-openbsd" "x86_64-redox" "wasm64-wasi" "wasm32-wasi" "x86_64-windows" "i686-windows" ]; + }; + testCollectPlatformsDarwinDrv = { + expr = internal.collectPlatformsForDrv fixtures.testDrvDarwin ; + expected = [ "x86_64-darwin" "i686-darwin" "aarch64-darwin" "armv7a-darwin" ]; + }; + + # genFlakeOutputForPlatforms + ############################ + testGenFlakeOutputForPlatforms = { + expr = internal.genFlakeOutputForPlatforms { path = /tmp/dummy/path; name = "hello"; platforms = [ "x86_64-linux" "x86_64-darwin" "aarch64-linux"]; }; + expected = { aarch64-linux = { hello = /tmp/dummy/path; }; x86_64-darwin = { hello = /tmp/dummy/path; }; x86_64-linux = { hello = /tmp/dummy/path; };}; + }; +} diff --git a/package-all.nix b/package-all.nix new file mode 100644 index 0000000..b8344f1 --- /dev/null +++ b/package-all.nix @@ -0,0 +1,29 @@ +{ lib +, stdenv +, fetchurl +}: + +stdenv.mkDerivation (finalAttrs: { + pname = "hello"; + version = "2.12.1"; + + src = fetchurl { + url = "mirror://gnu/hello/hello-${finalAttrs.version}.tar.gz"; + sha256 = "sha256-jZkUKv2SV28wsM18tCqNxoCZmLxdYH2Idh9RLibH2yA="; + }; + + doCheck = true; + + meta = with lib; { + description = "A program that produces a familiar, friendly greeting"; + longDescription = '' + GNU Hello is a program that prints "Hello, world!" when you run it. + It is fully customizable. + ''; + homepage = "https://www.gnu.org/software/hello/manual/"; + changelog = "https://git.savannah.gnu.org/cgit/hello.git/plain/NEWS?h=v${finalAttrs.version}"; + license = licenses.gpl3Plus; + maintainers = [ maintainers.eelco ]; + platforms = platforms.all; + }; +}) diff --git a/package-darwin.nix b/package-darwin.nix new file mode 100644 index 0000000..a056d9f --- /dev/null +++ b/package-darwin.nix @@ -0,0 +1,29 @@ +{ lib +, stdenv +, fetchurl +}: + +stdenv.mkDerivation (finalAttrs: { + pname = "hello"; + version = "2.12.1"; + + src = fetchurl { + url = "mirror://gnu/hello/hello-${finalAttrs.version}.tar.gz"; + sha256 = "sha256-jZkUKv2SV28wsM18tCqNxoCZmLxdYH2Idh9RLibH2yA="; + }; + + doCheck = true; + + meta = with lib; { + description = "A program that produces a familiar, friendly greeting"; + longDescription = '' + GNU Hello is a program that prints "Hello, world!" when you run it. + It is fully customizable. + ''; + homepage = "https://www.gnu.org/software/hello/manual/"; + changelog = "https://git.savannah.gnu.org/cgit/hello.git/plain/NEWS?h=v${finalAttrs.version}"; + license = licenses.gpl3Plus; + maintainers = [ maintainers.eelco ]; + platforms = platforms.darwin; + }; +}) diff --git a/package-linux.nix b/package-linux.nix new file mode 100644 index 0000000..b8344f1 --- /dev/null +++ b/package-linux.nix @@ -0,0 +1,29 @@ +{ lib +, stdenv +, fetchurl +}: + +stdenv.mkDerivation (finalAttrs: { + pname = "hello"; + version = "2.12.1"; + + src = fetchurl { + url = "mirror://gnu/hello/hello-${finalAttrs.version}.tar.gz"; + sha256 = "sha256-jZkUKv2SV28wsM18tCqNxoCZmLxdYH2Idh9RLibH2yA="; + }; + + doCheck = true; + + meta = with lib; { + description = "A program that produces a familiar, friendly greeting"; + longDescription = '' + GNU Hello is a program that prints "Hello, world!" when you run it. + It is fully customizable. + ''; + homepage = "https://www.gnu.org/software/hello/manual/"; + changelog = "https://git.savannah.gnu.org/cgit/hello.git/plain/NEWS?h=v${finalAttrs.version}"; + license = licenses.gpl3Plus; + maintainers = [ maintainers.eelco ]; + platforms = platforms.all; + }; +})