writers: add writeGuile[Bin] (#364531)

This commit is contained in:
lassulus
2024-12-13 18:09:20 +01:00
committed by GitHub
2 changed files with 184 additions and 0 deletions
+129
View File
@@ -613,6 +613,135 @@ rec {
*/
writeBabashkaBin = name: writeBabashka "/bin/${name}";
/**
`writeGuile` returns a derivation that creates an executable Guile script.
# Inputs
`nameOrPath` (String)
: Name of or path to the script. The semantics is the same as that of
`makeScriptWriter`.
`config` (AttrSet)
: `guile` (Optional, Derivation, Default: `pkgs.guile`)
: Guile package used for the script.
: `libraries` (Optional, [ Derivation ], Default: [])
: Extra Guile libraries exposed to the script.
: `r6rs` and `r7rs` (Optional, Boolean, Default: false)
: Whether to adapt Guiles initial environment to better support R6RS/
R7RS. See the [Guile Reference Manual](https://www.gnu.org/software/guile/manual/html_node/index.html)
for details.
: `srfi` (Optional, [ Int ], Default: [])
: SRFI module to be loaded into the interpreter before evaluating a
script file or starting the REPL. See the Guile Reference Manual to
know which SRFI are supported.
: Other attributes are directly passed to `makeScriptWriter`.
`content` (String)
: Content of the script.
# Examples
:::{.example}
## `pkgs.writers.writeGuile` with default config
```nix
writeGuile "guile-script" { }
''
(display "Hello, world!")
''
```
:::
:::{.example}
## `pkgs.writers.writeGuile` with SRFI-1 enabled and extra libraries
```nix
writeGuile "guile-script" {
libraries = [ pkgs.guile-semver ];
srfi = [ 1 ];
}
''
(use-modules (semver))
(make-semver 1 (third '(2 3 4)) 5) ; => #<semver 1.4.5>
''
```
:::
*/
writeGuile =
nameOrPath:
{
guile ? pkgs.guile,
libraries ? [ ],
r6rs ? false,
r7rs ? false,
srfi ? [ ],
...
}@config:
content:
assert builtins.all builtins.isInt srfi;
let
finalGuile = pkgs.buildEnv {
name = "guile-env";
paths = [ guile ] ++ libraries;
passthru = {
inherit (guile) siteDir siteCcacheDir;
};
meta.mainProgram = guile.meta.mainProgram or "guile";
};
in
makeScriptWriter
(
(builtins.removeAttrs config [
"guile"
"libraries"
"r6rs"
"r7rs"
"srfi"
])
// {
interpreter = "${lib.getExe finalGuile} \\";
makeWrapperArgs = [
"--set"
"GUILE_LOAD_PATH"
"${finalGuile}/${finalGuile.siteDir}:${finalGuile}/lib/scheme-libs"
"--set"
"GUILE_LOAD_COMPILED_PATH"
"${finalGuile}/${finalGuile.siteCcacheDir}:${finalGuile}/lib/libobj"
"--set"
"LD_LIBRARY_PATH"
"${finalGuile}/lib/ffi"
"--set"
"DYLD_LIBRARY_PATH"
"${finalGuile}/lib/ffi"
];
}
)
nameOrPath
/*
Spaces, newlines and tabs are significant for the "meta switch" of Guile, so
certain complication must be made to ensure correctness.
*/
(
lib.concatStringsSep "\n" [
(lib.concatStringsSep " " (
[ "--no-auto-compile" ]
++ lib.optional r6rs "--r6rs"
++ lib.optional r7rs "--r7rs"
++ lib.optional (srfi != [ ]) ("--use-srfi=" + concatMapStringsSep "," builtins.toString srfi)
++ [ "-s" ]
))
"!#"
content
]
);
/**
writeGuileBin takes the same arguments as writeGuile but outputs a directory
(like writeScriptBin)
*/
writeGuileBin = name: writeGuile "/bin/${name}";
/**
writeHaskell takes a name, an attrset with libraries and haskell version (both optional)
and some haskell source code and returns an executable.
+55
View File
@@ -1,6 +1,8 @@
{
haskellPackages,
lib,
guile-lib,
akkuPackages,
nodePackages,
perlPackages,
python3Packages,
@@ -26,6 +28,8 @@ let
writeFish
writeFishBin
writeFSharp
writeGuile
writeGuileBin
writeHaskell
writeHaskellBin
writeJS
@@ -109,6 +113,12 @@ recurseIntoAttrs {
''
);
guile = expectSuccessBin (
writeGuileBin "test-writers-guile-bin" { } ''
(display "success\n")
''
);
rust = expectSuccessBin (
writeRustBin "test-writers-rust-bin" { } ''
fn main(){
@@ -249,6 +259,51 @@ recurseIntoAttrs {
''
);
guile = expectSuccess (
writeGuile "test-writers-guile"
{
libraries = [ guile-lib ];
srfi = [ 1 ];
}
''
(use-modules (unit-test))
(assert-true (= (second '(1 2 3))
2))
(display "success\n")
''
);
guileR6RS = expectSuccess (
writeGuile "test-writers-guile-r6rs"
{
r6rs = true;
libraries = with akkuPackages; [ r6rs-slice ];
}
''
(import (rnrs base (6))
(rnrs io simple (6))
(slice))
(assert (equal? (slice '(1 2 3) 0 2)
'(1 2)))
(display "success\n")
''
);
guileR7RS = expectSuccess (
writeGuile "test-writers-guile-r7rs"
{
r7rs = true;
}
''
(import (scheme write)
(srfi 1))
(unless (= (second '(1 2 3))
2)
(error "The value should be 2."))
(display "success\n")
''
);
haskell = expectSuccess (
writeHaskell "test-writers-haskell" { libraries = [ haskellPackages.acme-default ]; } ''
import Data.Default