init racket at nixpkgs/f8a7597

f8a7597f5d80c116d775e86175f5b7592be9b441
This commit is contained in:
xenia 2025-09-26 21:17:32 -04:00
commit 843f6f1b46
15 changed files with 627 additions and 0 deletions

2
.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
/result
/result-*

60
flake.lock Normal file
View File

@ -0,0 +1,60 @@
{
"nodes": {
"dragnpkgs": {
"inputs": {
"lix-module": "lix-module",
"nixpkgs": "nixpkgs"
},
"locked": {
"lastModified": 1758120987,
"narHash": "sha256-Rp8UFvIUt8W3AfkdF0hucCUv1fmHhLNbYMXcR9b82so=",
"ref": "nixos-25.05",
"rev": "debca5464a660af2f5b7a720c1364b693e068e03",
"revCount": 168,
"type": "git",
"url": "https://git.lain.faith/haskal/dragnpkgs.git"
},
"original": {
"id": "dragnpkgs",
"type": "indirect"
}
},
"lix-module": {
"flake": false,
"locked": {
"lastModified": 1756125859,
"narHash": "sha256-6a+PWILmqHCs9B5eIBLg6HSZ8jYweZpgOWO8FlyVwYI=",
"rev": "d3292125035b04df00d01549a26e948631fabe1e",
"type": "tarball",
"url": "https://git.lix.systems/api/v1/repos/lix-project/nixos-module/archive/d3292125035b04df00d01549a26e948631fabe1e.tar.gz?rev=d3292125035b04df00d01549a26e948631fabe1e"
},
"original": {
"type": "tarball",
"url": "https://git.lix.systems/lix-project/nixos-module/archive/2.93.3-2.tar.gz"
}
},
"nixpkgs": {
"locked": {
"lastModified": 1757941119,
"narHash": "sha256-TssJZFzMRYdWgpHySzKv4YQg6DUv5SDENiWbVgNTo0M=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "7ff837017c3b82bd3671932599a119d7bc672ff0",
"type": "github"
},
"original": {
"owner": "NixOS",
"ref": "nixos-25.05",
"repo": "nixpkgs",
"type": "github"
}
},
"root": {
"inputs": {
"dragnpkgs": "dragnpkgs"
}
}
},
"root": "root",
"version": 7
}

7
flake.nix Normal file
View File

@ -0,0 +1,7 @@
{
description = "A very basic flake";
outputs = { self, dragnpkgs } @ inputs: dragnpkgs.lib.mkFlake {
packages.racket = ./racket/package.nix;
};
}

View File

@ -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))

11
racket/manifest.json Normal file
View File

@ -0,0 +1,11 @@
{
"version": "8.18",
"full": {
"filename": "racket-8.18-src.tgz",
"sha256": "65477c71ec1a978a6ee4db582b9b47b1a488029d7a42e358906de154a6e5905c"
},
"minimal": {
"filename": "racket-minimal-8.18-src.tgz",
"sha256": "24b9cf8365254b43bac308192c782edfbd86363df1322c4e063b797ed0f7db66"
}
}

175
racket/minimal.nix Normal file
View File

@ -0,0 +1,175 @@
{
lib,
stdenv,
fetchurl,
libiconvReal,
libz,
lz4,
ncurses,
openssl,
sqlite,
disableDocs ? false,
callPackage,
writers,
}:
let
manifest = lib.importJSON ./manifest.json;
inherit (stdenv.hostPlatform) isDarwin;
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 = [
# > docs failure: ftype-ref: ftype mismatch for #<ftype-pointer>
# "--enable-check"
"--enable-csonly"
"--enable-liblz4"
"--enable-libz"
]
++ lib.optional disableDocs "--disable-docs"
++ lib.optionals (!(finalAttrs.dontDisableStatic or false)) [
# 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"
];
# The upstream script builds static libraries by default.
dontAddStaticConfigureFlags = true;
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
];
sourceProvenance = with lib.sourceTypes; [
fromSource
binaryBytecode
];
maintainers = with lib.maintainers; [ rc-zb ];
mainProgram = "racket";
platforms = lib.platforms.all;
};
})

123
racket/package.nix Normal file
View File

@ -0,0 +1,123 @@
{
lib,
stdenv,
fetchurl,
racket-minimal,
cairo,
fontconfig,
glib,
glibcLocales,
gtk3,
libGL,
libiodbc,
libjpeg,
libpng,
makeFontsConf,
pango,
unixODBC,
wrapGAppsHook3,
disableDocs ? false,
callPackage,
}:
let
minimal = racket-minimal.override { inherit disableDocs; };
manifest = lib.importJSON ./manifest.json;
inherit (stdenv.hostPlatform) isDarwin;
in
minimal.overrideAttrs (
finalAttrs: prevAttrs: {
src = fetchurl {
url = "https://mirror.racket-lang.org/installers/${manifest.version}/${manifest.full.filename}";
inherit (manifest.full) sha256;
};
buildInputs = prevAttrs.buildInputs ++ [
(if isDarwin then libiodbc else unixODBC)
cairo
fontconfig.lib
glib
gtk3
libGL
libjpeg
libpng
pango
];
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
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
*/
''
for lib_path in $( \
echo "$NIX_LDFLAGS" \
| tr ' ' '\n' \
| grep '^-L' \
| sed 's/^-L//' \
| awk '!seen[$0]++' \
); do
addToSearchPath ${libPathsVar} $lib_path
done
''
# Fixes Fontconfig errors
+ ''
export FONTCONFIG_FILE=${makeFontsConf { fontDirectories = [ ]; }}
export XDG_CACHE_HOME=$(mktemp -d)
'';
preFixup = lib.optionalString (!isDarwin) ''
gappsWrapperArgs+=("--set" "LOCALE_ARCHIVE" "${glibcLocales}/lib/locale/locale-archive")
'';
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;
};
};
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
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.
'';
platforms = lib.platforms.unix;
badPlatforms = lib.platforms.darwin;
};
}
)

View File

@ -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?)

View File

@ -0,0 +1,10 @@
--- old/src/mac/codesign.rkt
+++ new/src/mac/codesign.rkt
@@ -18,6 +18,6 @@
file))
(void
- (if remove?
+ (begin
(remove-signature file)
(add-ad-hoc-signature file)))

View File

@ -0,0 +1,18 @@
{ runCommandLocal, racket }:
runCommandLocal "racket-test-draw-crossing"
{
nativeBuildInputs = [ racket ];
}
''
racket -f - <<EOF
(require racket/draw)
(define target (make-bitmap 64 64))
(define dc (new bitmap-dc% [bitmap target]))
(send dc draw-line 0 0 64 64)
(send dc draw-line 0 64 64 0)
(send target save-file (getenv "out") 'png)
EOF
''

View File

@ -0,0 +1,45 @@
{
lib,
runCommandLocal,
racket,
}:
runCommandLocal "racket-test-get-version-and-variant"
{
nativeBuildInputs = [ racket ];
}
(
lib.concatLines (
builtins.map
(
{ expectation, output }:
''
expectation="${expectation}"
output="${output}"
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
''
)

View File

@ -0,0 +1,15 @@
{ runCommandLocal, racket }:
runCommandLocal "racket-test-load-openssl"
{
nativeBuildInputs = [ racket ];
}
''
racket -f - <<EOF
(require openssl)
(unless ssl-available?
(raise ssl-load-fail-reason))
EOF
touch $out
''

View File

@ -0,0 +1,26 @@
{ runCommandLocal, racket }:
let
script = racket.writeScript "racket-test-nix-write-script-the-script" { } ''
#lang racket/base
(display "success")
(newline)
'';
in
runCommandLocal "racket-test-nix-write-script"
{
nativeBuildInputs = [ racket ];
}
''
expectation="success"
output="$(${script})"
if test "$output" != "$expectation"; then
echo "output mismatch: expected ''${expectation}, but got ''${output}"
exit 1
fi
touch $out
''

View File

@ -0,0 +1,23 @@
{ runCommandLocal, racket }:
runCommandLocal "racket-test-write-greeting"
{
nativeBuildInputs = [ racket ];
}
''
expectation="Hello, world!"
racket -f - <<EOF
(with-output-to-file (getenv "out")
(lambda ()
(display "Hello, world!")
(newline)))
EOF
output="$(cat $out)"
if test "$output" != "$expectation"; then
echo "output mismatch: expected ''${expectation}, but got ''${output}"
exit 1
fi
''

73
racket/update.py Executable file
View File

@ -0,0 +1,73 @@
#! /usr/bin/env nix-shell
#! nix-shell -i python3 --packages 'python3.withPackages (ps: with ps; [ requests beautifulsoup4 ])'
import os
import re
import json
import requests
from bs4 import BeautifulSoup
SITE = "https://download.racket-lang.org"
MANIFEST_FILENAME = "manifest.json"
def find_info(table, group_name, subgroup_name):
group = table.find(
string=re.compile("^{}\\s*".format(group_name))
).find_parent("tr", class_="group")
subgroup = group.find_next(
string=re.compile("^{}\\s*".format(subgroup_name))
).find_parent(class_="subgroup")
link = subgroup.find_next(
"a",
class_="installer",
string="Source"
)
filename = link["href"].split("/")[1]
sha256 = link.find_next(class_="checksum").string
return {
"filename": filename,
"sha256": sha256,
}
os.chdir(os.path.dirname(os.path.abspath(__file__)))
prev_version = os.environ["UPDATE_NIX_OLD_VERSION"]
homepage = BeautifulSoup(requests.get(SITE).text, "html.parser")
version = homepage.find(
"h3",
string=re.compile("^Version \\d+\\.\\d+")
).string.split()[1]
if version == prev_version:
raise Exception("no newer version available")
down_page_path = homepage.find(
"a",
string="More Installers and Checksums"
)["href"]
down_page = BeautifulSoup(requests.get(SITE + "/" + down_page_path).text, "html.parser")
down_table = down_page.find(class_="download-table")
full = find_info(down_table, "Racket", "Unix")
minimal = find_info(down_table, "Minimal Racket", "All Platforms")
with open(MANIFEST_FILENAME, "w", encoding="utf-8") as f:
json.dump({
"version": version,
"full": full,
"minimal": minimal,
}, f, indent=2, ensure_ascii=False)
f.write("\n")
print(json.dumps(
[
{
"attrPath": os.environ["UPDATE_NIX_ATTR_PATH"],
"oldVersion": prev_version,
"newVersion": version,
"files": [ os.path.abspath(MANIFEST_FILENAME) ],
},
],
indent=2, ensure_ascii=False
))