akku: Add akkuPackages, introduce deps.toml

This commit is contained in:
Konstantin Astafurov 2024-07-07 18:45:48 -04:00
parent 60c3b59fdb
commit 29e9baf2fd
11 changed files with 3952 additions and 39 deletions

View File

@ -41,6 +41,7 @@ qt.section.md
r.section.md
ruby.section.md
rust.section.md
scheme.section.md
swift.section.md
texlive.section.md
titanium.section.md

View File

@ -0,0 +1,35 @@
# Scheme {#sec-scheme}
## Package Management {#sec-scheme-package-management}
### Akku {#sec-scheme-package-management-akku}
About two hundred R6RS & R7RS libraries from [Akku](https://akkuscm.org/)
(which also mirrors [snow-fort](https://snow-fort.org/pkg))
are available inside the `akkuPackages` attrset, and the Akku executable
itself is at the top level as `akku`. The packages could be used
in a derivation's `buildInputs`, work inside of `nix-shell`, and
are tested using [Chez](https://www.scheme.com/) &
[Chibi](https://synthcode.com/wiki/chibi-scheme)
Scheme during build time.
Including a package as a build input is done in the typical Nix fashion.
For example, to include
[a bunch of SRFIs](https://akkuscm.org/packages/chez-srfi/)
primarily for Chez Scheme in a derivation, one might write:
```nix
{
buildInputs = [
chez
akkuPackages.chez-srfi
];
}
```
The package index is located in `pkgs/tools/package-management/akku`
as `deps.toml`, and should be updated occasionally by running `./update.sh`
in the directory. Doing so will pull the source URLs for new packages and
more recent versions, then write them to the TOML.

View File

@ -0,0 +1,44 @@
{ lib, stdenv, fetchFromGitLab, autoreconfHook, pkg-config, guile, curl, substituteAll }:
stdenv.mkDerivation rec {
pname = "akku";
version = "1.1.0";
src = fetchFromGitLab {
owner = "akkuscm";
repo = "akku";
rev = "v${version}";
sha256 = "1pi18aamg1fd6f9ynfl7zx92052xzf0zwmhi2pwcwjs1kbah19f5";
};
patches = [
# substitute libcurl path
(substituteAll {
src = ./hardcode-libcurl.patch;
libcurl = "${curl.out}/lib/libcurl${stdenv.hostPlatform.extensions.sharedLibrary}";
})
];
nativeBuildInputs = [ autoreconfHook pkg-config ];
buildInputs = [ guile ];
# Use a dummy package index to boostrap Akku
preBuild = ''
touch bootstrap.db
'';
makeFlags = [ "GUILE_AUTO_COMPILE=0" ];
meta = with lib; {
homepage = "https://akkuscm.org/";
description = "Language package manager for Scheme";
changelog = "https://gitlab.com/akkuscm/akku/-/raw/v${version}/NEWS.md";
platforms = platforms.all;
license = licenses.gpl3Plus;
maintainers = with maintainers; [
nagy
konst-aa
];
mainProgram = "akku";
};
}

View File

@ -0,0 +1,98 @@
{ stdenv, akku, chez, guile, chibi, makeWrapper, lib, writeShellScriptBin }:
{ pname, version, src, buildInputs ? [ ], r7rs ? false, nativeBuildInputs ? [ ], ... } @ args:
let
parse-akku_ = writeShellScriptBin "parse-akku"
"${guile}/bin/guile --no-auto-compile ${./parse-akku.scm} \"$@\"";
parse-akku = "${parse-akku_}/bin/parse-akku";
in
stdenv.mkDerivation ({
inherit version src;
pname = "akku-${pname}";
propagatedBuildInputs = buildInputs;
buildInputs = [ ];
nativeBuildInputs = [ makeWrapper akku chez chibi ] ++ nativeBuildInputs;
buildPhase = ''
runHook preBuild
# only install the project
rm -f Akku.lock Akku.manifest
# build, filter out guile warnings
akku install 2>&1 | grep -v "\(guile-user\)" - | cat
# make sure akku metadata is present during testing and onwards
echo $PWD $CHEZSCHEMELIBDIRS \
| sed "s/:/ /g" \
| xargs find \
| grep "metadata.sls" \
| xargs ${parse-akku} merge ${pname} ${version} > temp___
mv temp___ .akku/lib/akku/metadata.sls
runHook postBuild
'';
checkPhase = ''
IS_R7RS=false
runHook preCheck
propagated_chez=$CHEZSCHEMELIBDIRS
propagated_chibi=$CHIBI_MODULE_PATH
export CHEZSCHEMELIBDIRS="$PWD/.akku/lib:$CHEZSCHEMELIBDIRS"
export CHIBI_MODULE_PATH="$PWD/.akku/lib:$CHIBI_MODULE_PATH"
# Run all test .sps files if they exist
# and run tests for libs mirrored from snow-fort.
for path in $(find test* -type f | grep -e "\.sps") \
$(find . | grep "run-test" | grep "\.scm"); do
echo Running test: $path
[[ "\n$SKIP\n" =~ $(basename $path) ]] && continue
if [ -x $path ]; then
patchShebangs $path
./$path
elif ${lib.trivial.boolToString r7rs}; then
chibi-scheme $path
else
scheme-script $path
fi
done
runHook postCheck
export CHEZSCHEMELIBDIRS=$propagated_chez
export CHIBI_MODULE_PATH=$propagated_chibi
'';
doCheck = true;
installPhase = ''
runHook preInstall
mkdir -p $out/lib
cd .akku
rm -f bin/activate*
cp -rL lib $out/lib/scheme-libs
cp -rL bin $out/bin
[ -d ffi ] && cp -rL ffi $out/lib
[ -d libobj ] && cp -rL libobj $out/lib
CHEZSCHEMELIBDIRS="$out/lib/scheme-libs:$CHEZSCHEMELIBDIRS"
# add support for other schemes
for f in $out/bin/*
do
patchShebangs $f
wrapProgram $f \
--prefix CHEZSCHEMELIBDIRS : $CHEZSCHEMELIBDIRS
done
runHook postInstall
'';
meta = {
inherit (akku.meta) platforms;
} // args.meta or { };
setupHook = ./setup-hook.sh;
} // builtins.removeAttrs args [ "name" "buildInputs" "meta" "nativeBuildInputs" ])

View File

@ -1,42 +1,66 @@
{ lib, stdenv, fetchFromGitLab, autoreconfHook, pkg-config, guile, curl, substituteAll }:
{ lib, newScope, stdenv, fetchurl }:
lib.makeScope newScope (self: rec {
stdenv.mkDerivation rec {
pname = "akku";
version = "1.1.0";
src = fetchFromGitLab {
owner = "akkuscm";
repo = "akku";
rev = "v${version}";
sha256 = "1pi18aamg1fd6f9ynfl7zx92052xzf0zwmhi2pwcwjs1kbah19f5";
fetchAkku = { name, url, sha256, ... }:
fetchurl {
inherit url sha256;
};
patches = [
# substitute libcurl path
(substituteAll {
src = ./hardcode-libcurl.patch;
libcurl = "${curl.out}/lib/libcurl${stdenv.hostPlatform.extensions.sharedLibrary}";
})
];
akkuDerivation = self.callPackage ./akkuDerivation.nix { };
akku = self.callPackage ./akku.nix { };
nativeBuildInputs = [ autoreconfHook pkg-config ];
buildInputs = [ guile ];
# Use a dummy package index to boostrap Akku
preBuild = ''
touch bootstrap.db
'';
makeFlags = [ "GUILE_AUTO_COMPILE=0" ];
meta = with lib; {
homepage = "https://akkuscm.org/";
description = "Language package manager for Scheme";
changelog = "https://gitlab.com/akkuscm/akku/-/raw/v${version}/NEWS.md";
platforms = platforms.all;
license = licenses.gpl3Plus;
maintainers = with maintainers; [ ];
mainProgram = "akku";
akkuPackages =
let
overrides = self.callPackage ./overrides.nix { };
makeAkkuPackage = akkuself: pname:
{ version, dependencies, dev-dependencies, license, url, sha256, source, synopsis ? "", homepage ? "", ... }:
(akkuDerivation rec {
inherit version pname;
src = fetchAkku {
inherit url sha256;
name = pname;
};
}
buildInputs = builtins.map (x: akkuself.${x}) dependencies;
r7rs = source == "snow-fort";
nativeBuildInputs = builtins.map (x: akkuself.${x}) dev-dependencies;
unpackPhase = "tar xf $src";
meta.homepage = homepage;
meta.description = synopsis;
meta.license =
let
stringToLicense = s: (lib.licenses // (with lib.licenses; {
"agpl" = agpl3Only;
"artistic" = artistic2;
"bsd" = bsd3;
"bsd-1-clause" = bsd1;
"bsd-2-clause" = bsd2;
"bsd-3-clause" = bsd3;
"gpl" = gpl3Only;
"gpl-2" = gpl2Only;
"gplv2" = gpl2Only;
"gpl-3" = gpl3Only;
"gpl-3.0" = gpl3Only;
"gplv3" = gpl3Only;
"lgpl" = lgpl3Only;
"lgpl-2" = lgpl2Only;
"lgpl-2.0+" = lgpl2Plus;
"lgpl-2.1" = lgpl21Only;
"lgpl-2.1-or-later" = lgpl21Plus;
"lgpl-3" = lgpl3Only;
"lgplv3" = lgpl3Only;
"public-domain" = publicDomain;
"srfi" = bsd3;
"unicode" = ucd;
"zlib-acknowledgement" = zlib;
})).${s} or s;
in
if builtins.isList license
then map stringToLicense license
else stringToLicense license;
}).overrideAttrs ({ "${pname}" = lib.id; } // overrides)."${pname}";
deps = lib.importTOML ./deps.toml;
packages = lib.makeScope self.newScope (akkuself: lib.mapAttrs (makeAkkuPackage akkuself) deps);
in
lib.recurseIntoAttrs packages;
})

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,135 @@
{ stdenv, lib, akku, curl, git, substituteAll }:
let
joinOverrides =
overrides: pkg: old:
lib.attrsets.mergeAttrsList (map (o: o pkg old) overrides);
addToBuildInputs =
extras: pkg: old:
{ propagatedBuildInputs = old.propagatedBuildInputs ++ extras; };
broken = lib.addMetaAttrs { broken = true; };
skipTests = pkg: old: { doCheck = false; };
# debugging
showLibs = pkg: old: { preCheck = "echo $CHEZSCHEMELIBDIRS"; };
runTests = pkg: old: { doCheck = true; };
brokenOnAarch64 = _: lib.addMetaAttrs { broken = stdenv.isAarch64; };
brokenOnx86_64Darwin = lib.addMetaAttrs { broken = stdenv.isDarwin && stdenv.isx86_64; };
in
{
chez-srfi = joinOverrides [
(pkg: old: {
preCheck = ''
SKIP='
multi-dimensional-arrays.sps
time.sps
tables-test.ikarus.sps
lazy.sps
'
'';
})
# nothing builds on ARM Macs because of this
brokenOnAarch64
];
akku-r7rs = pkg: old: {
preBuild = ''
# tests aren't exported modules
rm -rf tests
'';
};
akku = joinOverrides [
(addToBuildInputs [ curl git ])
(pkg: old: {
# hardcode-libcurl
patches = akku.patches;
})
];
# circular dependency on wak-trc-testing !?
wak-foof-loop = skipTests;
scheme-langserver = joinOverrides [
(pkg: old: {
preInstall = ''
# add the lsp executable to be installed
echo "#!/usr/bin/env scheme-script" > .akku/bin/scheme-langserver
cat run.ss >> .akku/bin/scheme-langserver
chmod +x .akku/bin/scheme-langserver
'';
})
skipTests
];
# broken tests
xitomatl = skipTests;
ufo-threaded-function = skipTests;
# unsupported schemes, it seems.
loko-srfi = broken;
ac-d-bus = broken;
# todo:
# system-specific:
# scheme-langserver doesn't work because of this
ufo-thread-pool = brokenOnx86_64Darwin;
# broken everywhere:
chibi-math-linalg = broken;
chibi-mecab = broken;
chibi-ssl = broken;
chibi-voting = broken;
chibi-xgboost = broken;
dockerfile = broken;
in-progress-hash-bimaps = broken;
in-progress-hash-tables = broken;
rapid-analyze-library = broken;
rapid-args-fold = broken;
rapid-eliminate-mutable-variables = broken;
rapid-fix-letrec = broken;
rapid-graph = broken;
rapid-library-definition = broken;
rapid-mapping = broken;
rapid-read = broken;
rapid-set = broken;
rapid-syntax = broken;
read-char-if = broken;
shell-quote = broken;
srfi-19 = broken;
srfi-64 = broken;
srfi-179 = broken;
string-inflection = broken;
tex-parser = broken;
trivial-tar-writer = broken;
unpack-assoc = broken;
agave = broken;
box2d-lite = broken;
chez-soop = broken;
chez-stats = broken;
dataframe = broken;
dharmalab = broken;
dorodango = broken;
fectors = broken;
fs-fatfs = broken;
fs-partitions = broken;
gnuplot-pipe = broken;
http-pixiu = broken;
influx-client = broken;
linenoise = broken;
mpl = broken;
mummel = broken;
ocelotl = broken;
r6lint = broken;
r6rs-clos = broken;
r6rs-coap = broken;
r6rs-msgpack = broken;
scheme-bytestructures = broken;
surfage = broken;
swish = broken;
text-mode = broken;
thunderchez = broken;
wak-ssax = broken;
wak-sxml-tools = broken;
yxskaft = broken;
}

View File

@ -0,0 +1,151 @@
(import (srfi 1)
(srfi 28)
(ice-9 pretty-print))
(define-syntax anif
(syntax-rules (:=)
((_ (bool := sym) x y)
(let ((sym bool))
(if sym x y)))
((_ b x)
(anif b x #f))))
(define ref assoc-ref)
(define (sref alist key)
;; Used to reach b in pairs like (a . (b))
(anif ((ref alist key) := t)
(car t)
#f))
(define (printf str . args)
(display (apply format (cons str args))))
(define (->string x)
(cond
((symbol? x) (symbol->string x))
((number? x) (number->string x))
(else x)))
(define (module-name->string module)
(if (pair? module)
(string-join (map ->string module) "-")
module))
(define (normalize-deps deps)
(map (compose module-name->string car) deps))
(define (parse-license license)
(let ((res (with-input-from-string license read)))
(if (pair? res)
(map (compose string-downcase ->string)
(filter (lambda (sym) (not (eq? sym 'AND))) res))
(string-downcase (->string res)))))
(define (parse-version-info alist)
(let* ((lock (ref alist 'lock))
(url (sref (ref lock 'location) 'url))
(sha256 (sref (ref lock 'content) 'sha256))
(depends (normalize-deps (ref alist 'depends)))
(dev-depends
(anif ((ref alist 'depends/dev) := t)
(normalize-deps t)
(list)))
(license (parse-license (sref alist 'license))))
(append `((license ,license)
(url ,url)
(sha256 ,sha256)
(depends ,depends)
(dev-depends ,dev-depends))
alist)))
(define (format-list lst)
(define (surround s)
(format "~s" s))
(string-append
"["
(apply string-join (list (map surround lst) ", "))
"]"))
(define (write-package sexp)
(let* ((latest (parse-version-info (last (ref sexp 'versions))))
(license (sref latest 'license))
(url (sref latest 'url)))
(printf "[~a]\n" (module-name->string (sref sexp 'name)))
(printf "dependencies = ~a\n" (format-list (sref latest 'depends)))
(printf "dev-dependencies = ~a\n" (format-list (sref latest 'dev-depends)))
(if (pair? license)
(printf "license = ~a\n" (format-list license))
(printf "license = ~s\n" license))
(printf "url = ~s\n" url)
(printf "sha256 = ~s\n" (sref latest 'sha256))
(printf
"source = ~s\n"
(cond
;; because #f could be returned
((eqv? 0 (string-contains url "https://archive.akkuscm.org/")) "akku")
((eqv? 0 (string-contains url "http://snow-fort.org/")) "snow-fort")
(else "UNKNOWN")))
(anif ((sref latest 'synopsis) := t)
(printf "synopsis = ~s\n" t))
(printf "version = ~s\n" (sref latest 'version))
(anif ((sref latest 'hompeage) := t)
(printf "homepage = ~s\n" t))
(newline)))
(define (main-deps)
(let ((res (read)))
(if (eof-object? res)
(exit 0))
(write-package (cdr res))
(main-deps)))
(define (read-meta meta)
(with-input-from-file meta read))
(define (find-definition meta sym)
;; cddr for
;; (define sym definition ...)
;; ^
(cddr (find (lambda (a)
(and (pair? a)
(eq? (car a) 'define)
(eq? (cadr a) sym)))
meta)))
(define (installed-libraries meta)
;; cadar for
;; ((quote ((chibi diff) (chibi diff-test))))
;; ^
(cadar (find-definition meta 'installed-libraries)))
(define (installed-assets meta)
(cadar (find-definition meta 'installed-assets)))
(define (main-merge name version self-path . rest-paths)
(let* ((self (read-meta self-path))
(metas (map read-meta (cons self-path rest-paths)))
(joined-libraries (append-map installed-libraries metas))
(joined-assets (append-map installed-assets metas)))
(set-car! (find-definition self 'installed-libraries)
`',(delete-duplicates joined-libraries))
(set-car! (find-definition self 'installed-assets)
`',(delete-duplicates joined-assets))
(set-car! (find-definition self 'main-package-name)
`',name)
(set-car! (find-definition self 'main-package-version)
`',version)
self))
(case (string->symbol (cadr (command-line)))
((deps)
(read)
(main-deps))
((merge)
(pretty-print (apply main-merge (cddr (command-line)))))
(else
(display "mode not found")
(newline)))

View File

@ -0,0 +1,32 @@
_AKKU="SPDX-License-Identifier: MIT"
_AKKU="Copyright (c) The Akku.scm Developers"
scheme_vars='
CHEZSCHEMELIBDIRS
GUILE_LOAD_PATH
IKARUS_LIBRARY_PATH
MOSH_LOADPATH
PLTCOLLECTS
SAGITTARIUS_LOADPATH
VICARE_SOURCE_PATH
YPSILON_SITELIB
LARCENY_LIBPATH
IRONSCHEME_LIBRARY_PATH
LOKO_LIBRARY_PATH
DIGAMMA_SITELIB
CHIBI_MODULE_PATH
GAUCHE_LOAD_PATH
'
addToAkkuEnv () {
adder="addToSearchPath"
for env_var in $scheme_vars; do
$adder $env_var "$1/lib/scheme-libs"
done
$adder GUILE_LOAD_COMPILED_PATH "$1/lib/libobj"
$adder LD_LIBRARY_PATH "$1/lib/ffi"
$adder DYLD_LIBRARY_PATH "$1/lib/ffi"
}
addEnvHooks "$targetOffset" addToAkkuEnv

View File

@ -0,0 +1,4 @@
#!/usr/bin/env nix-shell
#! nix-shell -I nixpkgs=../../../../ -i bash -p guile curl
curl -sSf https://archive.akkuscm.org/archive/Akku-index.scm | guile parse-akku.scm deps > deps.toml

View File

@ -1665,7 +1665,8 @@ with pkgs;
inherit (plasma5Packages) kdialog;
};
akku = callPackage ../tools/package-management/akku { };
inherit (recurseIntoAttrs (callPackage ../tools/package-management/akku { }))
akku akkuPackages;
albert = qt6Packages.callPackage ../applications/misc/albert { };