Skip to content

Commit

Permalink
racket: add package system support
Browse files Browse the repository at this point in the history
  • Loading branch information
rc-zb committed Feb 12, 2025
1 parent ca42117 commit 7639b86
Show file tree
Hide file tree
Showing 16 changed files with 5,090 additions and 35 deletions.
5 changes: 3 additions & 2 deletions pkgs/development/interpreters/racket/default.nix
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@

disableDocs ? false,

callPackage,
newScope,
}:

let
Expand Down Expand Up @@ -99,9 +99,10 @@ minimal.overrideAttrs (
stopPred =
_: lhs: rhs:
notUpdated lhs || notUpdated rhs;
callWithRacket = newScope { racket = finalAttrs.finalPackage; };
in
lib.recursiveUpdateUntil stopPred prevAttrs.passthru {
tests = builtins.mapAttrs (name: path: callPackage path { racket = finalAttrs.finalPackage; }) {
tests = builtins.mapAttrs (_: p: callWithRacket p { }) {
## `main-distribution` ##
draw-crossing = ./tests/draw-crossing.nix;
};
Expand Down
78 changes: 45 additions & 33 deletions pkgs/development/interpreters/racket/minimal.nix
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@

disableDocs ? false,

callPackage,
newScope,
writers,
}:

Expand Down Expand Up @@ -100,39 +100,51 @@ stdenv.mkDerivation (finalAttrs: {
$out/bin/racket -U -u ${configureInstallation}
'';

passthru = {
# Functionalities #
updateScript = {
command = ./update.py;
attrPath = "racket";
supportedFeatures = [ "commit" ];
};
writeScript =
nameOrPath:
{
libraries ? [ ],
...
}@config:
assert lib.assertMsg (libraries == [ ]) "library integration for Racket has not been implemented";
writers.makeScriptWriter (
builtins.removeAttrs config [ "libraries" ]
// {
interpreter = "${lib.getExe finalAttrs.finalPackage}";
}
) nameOrPath;
writeScriptBin = name: finalAttrs.passthru.writeScript "/bin/${name}";

# Tests #
tests = builtins.mapAttrs (name: path: callPackage path { racket = finalAttrs.finalPackage; }) {
## Basic ##
write-greeting = ./tests/write-greeting.nix;
get-version-and-variant = ./tests/get-version-and-variant.nix;
load-openssl = ./tests/load-openssl.nix;

## Nixpkgs supports ##
nix-write-script = ./tests/nix-write-script.nix;
passthru =
let
callWithRacket = newScope { racket = finalAttrs.finalPackage; };
in
{
# Functionalities #
updateScript = {
command = ./update.py;
attrPath = "racket";
supportedFeatures = [ "commit" ];
};
writeScript =
nameOrPath:
{
libraries ? [ ],
...
}@config:
assert lib.assertMsg (libraries == [ ]) "library integration for Racket has not been implemented";
writers.makeScriptWriter (
builtins.removeAttrs config [ "libraries" ]
// {
interpreter = "${lib.getExe finalAttrs.finalPackage}";
}
) nameOrPath;
writeScriptBin = name: finalAttrs.passthru.writeScript "/bin/${name}";

# Package system #
makePackage = callWithRacket ./package-system/make-package.nix { };
buildPackages = callWithRacket ./package-system/build-packages.nix { };
withPackages = finalAttrs.passthru.buildPackages.override { isTethered = true; };
pkgs = callWithRacket ./package-system/pkgs.nix { };

# Tests #
tests = builtins.mapAttrs (_: p: callWithRacket p { }) {
## Basic ##
write-greeting = ./tests/write-greeting.nix;
get-version-and-variant = ./tests/get-version-and-variant.nix;
load-openssl = ./tests/load-openssl.nix;

## Nixpkgs supports ##
nix-write-script = ./tests/nix-write-script.nix;
nix-make-package = ./tests/nix-make-package.nix;
nix-with-packages = ./tests/nix-with-packages.nix;
};
};
};

meta = {
description = "Programmable programming language (minimal distribution)";
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
#lang racket/base
(provide
/. /.*
/?
/: /:&
/_
)

(define /. hash-ref)

(define /.*
(case-lambda
[(ht key)
(hash-ref ht key)]
[(ht key . further)
(apply /.* (hash-ref ht key) further)]))

(define /?
(case-lambda
[(ht key)
(hash-has-key? ht key)]
[(ht key . further)
(and (hash-has-key? ht key)
(apply /? (hash-ref ht key) further))]))

(define /:
(case-lambda
[(ht key val)
(hash-set ht key val)]
[(ht key0 key1 . further)
(hash-set
ht key0
(apply /:
(if (hash-has-key? ht key0)
(hash-ref ht key0)
(hash-clear ht))
key1
further))]))

(define /:& hash-set*)

(define /_
(case-lambda
[(ht key)
(hash-remove ht key)]
[(ht key . further)
(if (hash-has-key? ht key)
(hash-set
ht key
(apply /_ (hash-ref ht key) further))
ht)]))
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
#lang racket/base
(require
racket/file
racket/function
racket/list
racket/path
racket/string
pkg/lib
setup/setup

"./stdenv.rkt"
)

(define to-list
(lambda (x)
(if (list? x)
x
(list x))))

(current-pkg-scope 'installation)

(let* ([pkg-dirs
((compose
(curry map some-system-path->string)
(curry filter directory-exists?)
flatten
(curry map (curry directory-list #:build? #t)))
(common-subpath (get-dep-paths) "share/racket-packages-archive"))]
[pkgs
(for/fold ([acc '()])
([pkg-dir (in-list pkg-dirs)])
(let* ([checksum
(let ([checksum-file (build-path pkg-dir ".CHECKSUM")])
(and (file-exists? checksum-file)
(string-trim (file->string checksum-file))))]
[pkg (pkg-desc pkg-dir 'dir #f checksum #f)])
(cons pkg acc)))]
[install-result
(with-pkg-lock
(pkg-install
pkgs
#:dep-behavior 'force
#:force? #t
#:ignore-checksums? #t
#:use-cache? #f
))])
(when (not (eq? install-result 'skip))
(let [(setup-result
(setup
#:collections (and install-result (map to-list install-result))
#:make-user? #f
#:fail-fast? #t
))]
(when (and (not setup-result) (env-set? "nix_racket_pkgs_strict_setup"))
(error 'install-packages.rkt "fail to setup installation")))))
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
#lang racket/base
(require
racket/list

"./hash-shortcuts.rkt"
)
(provide
expand-config
config-cascade
)

(define search~main
(hash
'bin-search-dirs 'bin-dir
'doc-search-dirs 'doc-dir
'gui-bin-search-dirs 'gui-bin-dir
'include-search-dirs 'include-dir
'lib-search-dirs 'lib-dir
'links-search-files 'links-file
'man-search-dirs 'man-dir
'pkgs-search-dirs 'pkgs-dir
'share-search-dirs 'share-dir
))

(define main~search
(hash-map/copy search~main
(lambda (k v) (values v k))))

(define expand-config
(lambda (config)
(for/fold ([acc config])
([key (in-hash-keys search~main)])
(let ([val (/. config key '(#f))])
(if (not (member #f val)) acc
(/: acc
key
(let* ([main-key (/. search~main key)]
[main-val (/. config main-key)])
(if main-val
(map (lambda (p) (if p p main-val)) val)
(remove #f val)))))))))

(define config-cascade
(let ([cascade-two
#|
| It is assumed that `prev-config` has been fully expanded before being
| covered.
|#
(lambda (new-config prev-config)
(for/fold ([acc prev-config])
([(key val) (in-hash new-config)])
(cond
[(or (/? search~main key)
(memq key '(base-documentation-packages
catalogs
collects-search-dirs
compiled-file-roots
distribution-documentation-packages)))
(/: acc key (append val (/. prev-config key '())))]
#|
| Append the default value (i.e. `(#f)`) if the search entry is
| not set explicitly while its corresponding "main" entry is.
|#
[(and (/? main~search key)
(not (/? new-config (/. main~search key))))
(let* ([search-key (/. main~search key)]
[search-val (append '(#f) (/. prev-config search-key '()))])
(/:& acc
key val
search-key search-val))]
[else
(/: acc key val)])))])
(lambda (config0 . configs)
(hash-map/copy
(foldl cascade-two config0 configs)
(lambda (k v)
(values
k
(if (list? v) (remove-duplicates v) v)))))))
Loading

0 comments on commit 7639b86

Please sign in to comment.