racket: separate recipes, fix bugs (#375992)

This commit is contained in:
Arne Keller
2025-02-11 11:09:05 +01:00
committed by GitHub
6 changed files with 308 additions and 214 deletions
@@ -0,0 +1,27 @@
#lang racket/base
(require
racket/function
racket/list
racket/pretty
racket/string
setup/dirs
)
(define config-file (build-path (find-config-dir) "config.rktd"))
(define lib-paths
((compose remove-duplicates
(curry map (curryr string-trim "-L" #:right? #f))
(curry filter (curryr string-prefix? "-L"))
string-split)
(getenv "NIX_LDFLAGS")))
(define config
(let* ([prev-config (read-installation-configuration-table)]
[prev-lib-search-dirs (hash-ref prev-config 'lib-search-dirs '(#f))]
[lib-search-dirs (remove-duplicates (append lib-paths prev-lib-search-dirs))])
(hash-set prev-config 'lib-search-dirs lib-search-dirs)))
(call-with-output-file config-file
#:exists 'replace
(curry pretty-write config))
+61 -193
View File
@@ -2,14 +2,7 @@
lib,
stdenv,
fetchurl,
libiconvReal,
libz,
lz4,
ncurses,
openssl,
isMinimal ? false,
racket-minimal,
cairo,
fontconfig,
@@ -22,17 +15,17 @@
libpng,
makeFontsConf,
pango,
sqlite,
unixODBC,
wrapGAppsHook3,
disableDocs ? false,
callPackage,
writers,
}:
let
minimal = racket-minimal.override { inherit disableDocs; };
makeLibPaths = lib.concatMapStringsSep " " (
lib.flip lib.pipe [
lib.getLib
@@ -41,100 +34,46 @@ let
);
manifest = lib.importJSON ./manifest.json;
inherit (stdenv.hostPlatform) isDarwin isStatic;
runtimeDeps = [ openssl ];
mainDistDeps = [
(if isDarwin then libiodbc else unixODBC)
cairo
fontconfig
glib
gtk3
libGL
libjpeg
libpng
pango
sqlite
];
inherit (stdenv.hostPlatform) isDarwin;
in
stdenv.mkDerivation (finalAttrs: {
pname = "racket";
inherit (manifest) version;
src =
let
info = manifest.${if isMinimal then "minimal" else "full"};
in
fetchurl {
url = "https://mirror.racket-lang.org/installers/${manifest.version}/${info.filename}";
inherit (info) sha256;
minimal.overrideAttrs (
finalAttrs: prevAttrs: {
src = fetchurl {
url = "https://mirror.racket-lang.org/installers/${manifest.version}/${manifest.full.filename}";
inherit (manifest.full) sha256;
};
nativeBuildInputs = lib.optionals (!isMinimal) [
wrapGAppsHook3
];
buildInputs = [
libiconvReal
libz
lz4
ncurses
];
patches = lib.optionals isDarwin [
/*
The entry point binary $out/bin/racket is codesigned at least once. The
following error is triggered as a result.
(error 'add-ad-hoc-signature "file already has a signature")
We always remove the existing signature then call add-ad-hoc-signature to
circumvent this error.
*/
./patches/force-remove-codesign-then-add.patch
];
preConfigure =
/*
The configure script forces using `libtool -o` as AR on Darwin. But, the
`-o` option is only available from Apple libtool. GNU ar works here.
*/
lib.optionalString isDarwin ''
substituteInPlace src/ChezScheme/zlib/configure \
--replace-fail 'ARFLAGS="-o"' 'AR=ar; ARFLAGS="rc"'
''
+ ''
mkdir src/build
cd src/build
'';
configureScript = "../configure";
configureFlags =
[
"--enable-check"
"--enable-csonly"
"--enable-liblz4"
"--enable-libz"
]
++ lib.optional disableDocs "--disable-docs"
++ lib.optionals (!isStatic) [
# instead of `--disable-static` that `stdenv` assumes
"--disable-libs"
# "not currently supported" in `configure --help-cs` but still emphasized in README
"--enable-shared"
]
++ lib.optionals isDarwin [
"--disable-strip"
# "use Unix style (e.g., use Gtk) for Mac OS", which eliminates many problems
"--enable-xonx"
buildInputs = prevAttrs.buildInputs ++ [
(if isDarwin then libiodbc else unixODBC)
cairo
fontconfig.lib
glib
gtk3
libGL
libjpeg
libpng
pango
];
preBuild =
let
libPaths = makeLibPaths mainDistDeps;
libPathsVar = if isDarwin then "DYLD_FALLBACK_LIBRARY_PATH" else "LD_LIBRARY_PATH";
in
lib.optionalString (!isMinimal) (
nativeBuildInputs = [
wrapGAppsHook3
];
patches = prevAttrs.patches or [ ] ++ [
/*
Hardcode variant detection because nixpkgs wraps the Racket binary making it
fail to detect its variant at runtime.
https://github.com/NixOS/nixpkgs/issues/114993#issuecomment-812951247
*/
./patches/force-cs-variant.patch
];
preBuild =
let
libPaths = makeLibPaths finalAttrs.buildInputs;
libPathsVar = if isDarwin then "DYLD_FALLBACK_LIBRARY_PATH" else "LD_LIBRARY_PATH";
in
/*
Makes FFIs available for setting up `main-distribution` and its
dependencies, which is integrated into the build process of Racket
@@ -148,81 +87,29 @@ stdenv.mkDerivation (finalAttrs: {
+ ''
export FONTCONFIG_FILE=${makeFontsConf { fontDirectories = [ ]; }}
export XDG_CACHE_HOME=$(mktemp -d)
''
);
'';
dontStrip = isDarwin;
preFixup = lib.optionalString (!isMinimal && !isDarwin) ''
gappsWrapperArgs+=("--set" "LOCALE_ARCHIVE" "${glibcLocales}/lib/locale/locale-archive")
'';
postFixup =
let
libPaths = makeLibPaths (runtimeDeps ++ lib.optionals (!isMinimal) mainDistDeps);
in
''
$out/bin/racket -f - <<EOF
(require setup/dirs)
(define config-path (build-path (find-config-dir) "config.rktd"))
(define prev-config (with-input-from-file config-path read))
(define prev-lib-search-dirs (hash-ref prev-config 'lib-search-dirs '(#f)))
(define lib-search-dirs (append '(${libPaths}) prev-lib-search-dirs))
(define config (hash-set prev-config 'lib-search-dirs lib-search-dirs))
(with-output-to-file config-path (thunk (pretty-write config))
#:exists 'replace)
EOF
preFixup = lib.optionalString (!isDarwin) ''
gappsWrapperArgs+=("--set" "LOCALE_ARCHIVE" "${glibcLocales}/lib/locale/locale-archive")
'';
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}";
passthru =
let
notUpdated = x: !builtins.isAttrs x || lib.isDerivation x;
stopPred =
_: lhs: rhs:
notUpdated lhs || notUpdated rhs;
in
lib.recursiveUpdateUntil stopPred prevAttrs.passthru {
tests = builtins.mapAttrs (name: path: callPackage path { racket = finalAttrs.finalPackage; }) {
## `main-distribution` ##
draw-crossing = ./tests/draw-crossing.nix;
};
};
# 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;
}
// lib.optionalAttrs (!isMinimal) {
## `main-distribution` ##
draw-crossing = ./tests/draw-crossing.nix;
}
);
};
meta = {
description =
"Programmable programming language" + lib.optionalString isMinimal " (minimal distribution)";
longDescription =
''
meta = prevAttrs.meta // {
description = "Programmable programming language";
longDescription = ''
Racket is a full-spectrum programming language. It goes beyond
Lisp and Scheme with dialects that support objects, types,
laziness, and more. Racket enables programmers to link
@@ -230,28 +117,9 @@ stdenv.mkDerivation (finalAttrs: {
programmers to create new, project-specific dialects. Racket's
libraries support applications from web servers and databases to
GUIs and charts.
''
+ lib.optionalString isMinimal ''
This minimal distribution includes just enough of Racket that you can
use `raco pkg` to install more.
'';
homepage = "https://racket-lang.org/";
changelog = "https://github.com/racket/racket/releases/tag/v${finalAttrs.version}";
/*
> Racket is distributed under the MIT license and the Apache version 2.0
> license, at your option.
> The Racket runtime system embeds Chez Scheme, which is distributed
> under the Apache version 2.0 license.
*/
license = with lib.licenses; [
asl20
mit
];
maintainers = with lib.maintainers; [ rc-zb ];
mainProgram = "racket";
platforms = lib.platforms.${if isMinimal then "all" else "unix"};
badPlatforms = lib.platforms.darwin;
};
})
platforms = lib.platforms.unix;
badPlatforms = lib.platforms.darwin;
};
}
)
@@ -0,0 +1,169 @@
{
lib,
stdenv,
fetchurl,
libiconvReal,
libz,
lz4,
ncurses,
openssl,
sqlite,
disableDocs ? false,
callPackage,
writers,
}:
let
manifest = lib.importJSON ./manifest.json;
inherit (stdenv.hostPlatform) isDarwin isStatic;
in
stdenv.mkDerivation (finalAttrs: {
pname = "racket";
inherit (manifest) version;
src = fetchurl {
url = "https://mirror.racket-lang.org/installers/${manifest.version}/${manifest.minimal.filename}";
inherit (manifest.minimal) sha256;
};
buildInputs = [
libiconvReal
libz
lz4
ncurses
openssl
sqlite.out
];
patches = lib.optionals isDarwin [
/*
The entry point binary $out/bin/racket is codesigned at least once. The
following error is triggered as a result.
(error 'add-ad-hoc-signature "file already has a signature")
We always remove the existing signature then call add-ad-hoc-signature to
circumvent this error.
*/
./patches/force-remove-codesign-then-add.patch
];
preConfigure =
/*
The configure script forces using `libtool -o` as AR on Darwin. But, the
`-o` option is only available from Apple libtool. GNU ar works here.
*/
lib.optionalString isDarwin ''
substituteInPlace src/ChezScheme/zlib/configure \
--replace-fail 'ARFLAGS="-o"' 'AR=ar; ARFLAGS="rc"'
''
+ ''
mkdir src/build
cd src/build
'';
configureScript = "../configure";
configureFlags =
[
"--enable-check"
"--enable-csonly"
"--enable-liblz4"
"--enable-libz"
]
++ lib.optional disableDocs "--disable-docs"
++ lib.optionals (!isStatic) [
# instead of `--disable-static` that `stdenv` assumes
"--disable-libs"
# "not currently supported" in `configure --help-cs` but still emphasized in README
"--enable-shared"
]
++ lib.optionals isDarwin [
"--disable-strip"
# "use Unix style (e.g., use Gtk) for Mac OS", which eliminates many problems
"--enable-xonx"
];
dontStrip = isDarwin;
postFixup =
let
configureInstallation = builtins.path {
name = "configure-installation.rkt";
path = ./configure-installation.rkt;
};
in
''
$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;
};
};
meta = {
description = "Programmable programming language (minimal distribution)";
longDescription = ''
Racket is a full-spectrum programming language. It goes beyond
Lisp and Scheme with dialects that support objects, types,
laziness, and more. Racket enables programmers to link
components written in different dialects, and it empowers
programmers to create new, project-specific dialects. Racket's
libraries support applications from web servers and databases to
GUIs and charts.
This minimal distribution includes just enough of Racket that you can
use `raco pkg` to install more.
'';
homepage = "https://racket-lang.org/";
changelog = "https://github.com/racket/racket/releases/tag/v${finalAttrs.version}";
/*
> Racket is distributed under the MIT license and the Apache version 2.0
> license, at your option.
> The Racket runtime system embeds Chez Scheme, which is distributed
> under the Apache version 2.0 license.
*/
license = with lib.licenses; [
asl20
mit
];
maintainers = with lib.maintainers; [ rc-zb ];
mainProgram = "racket";
platforms = lib.platforms.all;
badPlatforms = lib.platforms.darwin;
};
})
@@ -0,0 +1,12 @@
--- old/collects/setup/variant.rkt
+++ new/collects/setup/variant.rkt
@@ -7,7 +7,8 @@
(provide variant-suffix
script-variant?)
-(define plain-variant
+(define plain-variant 'cs)
+#;(define plain-variant
(delay/sync
(cond
[(cross-installation?)
@@ -1,27 +1,45 @@
{ runCommandLocal, racket }:
{
lib,
runCommandLocal,
racket,
}:
runCommandLocal "racket-test-get-version-and-variant"
{
nativeBuildInputs = [ racket ];
}
''
expectation="${racket.version}"
(
lib.concatLines (
builtins.map
(
{ expectation, output }:
''
expectation="${expectation}"
output="$(racket -e '(display (version))')"
output="${output}"
if test "$output" != "$expectation"; then
echo "output mismatch: expected ''${expectation}, but got ''${output}"
exit 1
fi
expectation="cs"
output="$(racket -e '(require launcher/launcher) (display (current-launcher-variant))')"
if test "$output" != "$expectation"; then
echo "output mismatch: expected ''${expectation}, but got ''${output}"
exit 1
fi
touch $out
''
if test "$output" != "$expectation"; then
echo "output mismatch: expected ''${expectation}, but got ''${output}"
exit 1
fi
''
)
[
{
expectation = racket.version;
output = "$(racket -e '(display (version))')";
}
{
expectation = "cs";
output = "$(racket -e '(require launcher/launcher) (display (current-launcher-variant))')";
}
{
expectation = "${lib.getExe racket}";
output = "$(racket -e '(require compiler/find-exe) (display (find-exe))')";
}
]
)
+ ''
touch $out
''
)
+1 -1
View File
@@ -7290,7 +7290,7 @@ with pkgs;
wireplumber = callPackage ../development/libraries/pipewire/wireplumber.nix { };
racket = callPackage ../development/interpreters/racket { };
racket-minimal = racket.override { isMinimal = true; };
racket-minimal = callPackage ../development/interpreters/racket/minimal.nix { };
rakudo = callPackage ../development/interpreters/rakudo { };
moarvm = darwin.apple_sdk_11_0.callPackage ../development/interpreters/rakudo/moarvm.nix {