Nix packages for third-party projects that don't ship their own flakes
1{
2 lib,
3 stdenv,
4 fetchFromGitHub,
5 fetchurl,
6 libxcrypt,
7 makeWrapper,
8}:
9
10let
11 # Keep in sync with PRISM_VERSION / RBS_VERSION in upstream Makefile.
12 # `make deps` downloads these from rubygems.org; we vendor them so the
13 # build stays offline/pure.
14 prismVersion = "1.9.0";
15 rbsVersion = "4.0.1";
16
17 prismGem = fetchurl {
18 url = "https://rubygems.org/gems/prism-${prismVersion}.gem";
19 hash = "sha256-e1MMap+SwkMAAUkZydy8BVv0zfUewwrtCZsGzWZ074U=";
20 };
21
22 rbsGem = fetchurl {
23 url = "https://rubygems.org/gems/rbs-${rbsVersion}.gem";
24 hash = "sha256-4jf9SXh/smW/DzifLw9XiP3N8fSbtUtPeVLOqQQWKgc=";
25 };
26in
27stdenv.mkDerivation (finalAttrs: {
28 pname = "spinel";
29 # No upstream tags yet — date-stamped unstable version of a pinned commit.
30 version = "0-unstable-2026-07-20";
31
32 src = fetchFromGitHub {
33 owner = "matz";
34 repo = "spinel";
35 rev = "d2d9c8ad69fbe8d6952c5cb53689bae6129f5074";
36 hash = "sha256-DS04ruOsXHcje+b0a2YDEftuytR188iUdTGhSO3n9sA=";
37 };
38
39 nativeBuildInputs = [ makeWrapper ];
40
41 # String#crypt = libcrypt(3); glibc keeps it in a separate DSO on modern
42 # Linux. Upstream Makefile adds -lcrypt only on Linux.
43 buildInputs = lib.optionals stdenv.hostPlatform.isLinux [ libxcrypt ];
44
45 postPatch = ''
46 # Embed a meaningful `spinel --version` without needing .git in the sandbox.
47 substituteInPlace Makefile \
48 --replace-fail \
49 'r=$$(git rev-parse --short=12 HEAD 2>/dev/null || echo unknown)' \
50 'r=${builtins.substring 0 12 finalAttrs.src.rev}'
51
52 # Vendor libprism + rbs C sources (normally `make deps`).
53 mkdir -p vendor/prism vendor/rbs
54 tmp=$(mktemp -d)
55 tar -xf ${prismGem} -C "$tmp" data.tar.gz
56 tar -xzf "$tmp/data.tar.gz" -C vendor/prism
57 rm -rf "$tmp"
58 tmp=$(mktemp -d)
59 tar -xf ${rbsGem} -C "$tmp" data.tar.gz
60 tar -xzf "$tmp/data.tar.gz" -C vendor/rbs
61 rm -rf "$tmp"
62 test -f vendor/prism/include/prism/diagnostic.h
63 test -f vendor/rbs/include/rbs/parser.h
64 '';
65
66 # Don't wrap CC with sccache/ccache if present on the host.
67 makeFlags = [
68 "NO_CCACHE=1"
69 "PREFIX=${placeholder "out"}"
70 ];
71
72 enableParallelBuilding = true;
73
74 # `make install` builds `all` + `bin/spin` first (spin is self-hosted via spinel).
75 installFlags = [ "PREFIX=${placeholder "out"}" ];
76
77 # spinel shells out to `cc` to link generated C; keep the stdenv toolchain
78 # on PATH. On Linux the generated link line includes -lcrypt (String#crypt),
79 # so libxcrypt must be visible to that cc invocation too.
80 # Runtime libs/headers resolve via /proc/self/exe → $out/lib/spinel/{lib,packages}.
81 postInstall =
82 let
83 cryptFlags = lib.optionalString stdenv.hostPlatform.isLinux ''
84 --prefix NIX_LDFLAGS " " "-L${lib.getLib libxcrypt}/lib" \
85 --prefix LIBRARY_PATH : "${lib.getLib libxcrypt}/lib" \
86 '';
87 in
88 ''
89 for b in spinel spin spinel-doctor spinel-reduce spinel-flatten; do
90 if [ -x "$out/bin/$b" ]; then
91 wrapProgram "$out/bin/$b" \
92 --prefix PATH : ${lib.makeBinPath [ stdenv.cc ]} \
93 ${cryptFlags}
94 fi
95 done
96 '';
97
98 meta = {
99 description = "Ruby AOT compiler — whole-program type inference to standalone native binaries";
100 homepage = "https://github.com/matz/spinel";
101 license = lib.licenses.mit;
102 mainProgram = "spinel";
103 platforms = lib.platforms.unix;
104 # Native Windows is unsupported upstream (POSIX runtime, pthread, etc.).
105 };
106})