nixpkgs mirror (for testing)
github.com/NixOS/nixpkgs
nix
1{
2 stdenv,
3 callPackage,
4 fetchFromGitHub,
5 fetchurl,
6 lib,
7 replaceVars,
8 # Dependencies
9 boehmgc,
10 coreutils,
11 git,
12 gmp,
13 hostname,
14 libevent,
15 libiconv,
16 libxml2,
17 libyaml,
18 libffi,
19 llvmPackages_19,
20 llvmPackages_20,
21 llvmPackages_21,
22 llvmPackages_22,
23 makeWrapper,
24 openssl,
25 pcre2,
26 pkg-config,
27 installShellFiles,
28 readline,
29 tzdata,
30 which,
31 zlib,
32}:
33
34# We need to keep around at least the latest version released with a stable
35# NixOS
36let
37 archs = {
38 x86_64-linux = "linux-x86_64";
39 i686-linux = "linux-i686";
40 x86_64-darwin = "darwin-universal";
41 aarch64-darwin = "darwin-universal";
42 aarch64-linux = "linux-aarch64";
43 };
44
45 arch = archs.${stdenv.system} or (throw "system ${stdenv.system} not supported");
46
47 nativeCheckInputs = [
48 git
49 gmp
50 openssl
51 readline
52 libxml2
53 libyaml
54 libffi
55 ];
56
57 binaryUrl =
58 version: rel:
59 if arch == archs.aarch64-linux then
60 "https://dev.alpinelinux.org/archive/crystal/crystal-${version}-aarch64-alpine-linux-musl.tar.gz"
61 else
62 "https://github.com/crystal-lang/crystal/releases/download/${version}/crystal-${version}-${toString rel}-${arch}.tar.gz";
63
64 genericBinary =
65 {
66 version,
67 sha256s,
68 rel ? 1,
69 }:
70 stdenv.mkDerivation rec {
71 pname = "crystal-binary";
72 inherit version;
73
74 src = fetchurl {
75 url = binaryUrl version rel;
76 sha256 = sha256s.${stdenv.system};
77 };
78
79 buildCommand = ''
80 mkdir -p $out
81 tar --strip-components=1 -C $out -xf ${src}
82 patchShebangs $out/bin/crystal
83 '';
84
85 meta.platforms = lib.attrNames sha256s;
86 };
87
88 generic =
89 {
90 version,
91 sha256,
92 binary,
93 llvmPackages,
94 doCheck ? true,
95 extraBuildInputs ? [ ],
96 buildFlags ? [
97 "all"
98 "docs"
99 "release=1"
100 ],
101 }:
102 stdenv.mkDerivation (finalAttrs: {
103 pname = "crystal";
104 inherit buildFlags doCheck version;
105
106 src = fetchFromGitHub {
107 owner = "crystal-lang";
108 repo = "crystal";
109 rev = version;
110 inherit sha256;
111 };
112
113 patches = [
114 (replaceVars ./tzdata.patch {
115 inherit tzdata;
116 })
117 ];
118
119 outputs = [
120 "out"
121 "lib"
122 "bin"
123 ];
124
125 postPatch = ''
126 export TMP=$(mktemp -d)
127 export HOME=$TMP
128 export TMPDIR=$TMP
129 mkdir -p $HOME/test
130
131 # Add dependency of crystal to docs to avoid issue on flag changes between releases
132 # https://github.com/crystal-lang/crystal/pull/8792#issuecomment-614004782
133 substituteInPlace Makefile \
134 --replace 'docs: ## Generate standard library documentation' 'docs: crystal ## Generate standard library documentation'
135
136 mkdir -p $TMP/crystal
137
138 substituteInPlace spec/std/file_spec.cr \
139 --replace '/bin/ls' '${coreutils}/bin/ls' \
140 --replace '/usr/share' "$TMP/crystal" \
141 --replace '/usr' "$TMP" \
142 --replace '/tmp' "$TMP"
143
144 substituteInPlace spec/std/process_spec.cr \
145 --replace '/bin/cat' '${coreutils}/bin/cat' \
146 --replace '/bin/ls' '${coreutils}/bin/ls' \
147 --replace '/usr/bin/env' '${coreutils}/bin/env' \
148 --replace '"env"' '"${coreutils}/bin/env"' \
149 --replace '/usr' "$TMP" \
150 --replace '/tmp' "$TMP"
151
152 substituteInPlace spec/std/system_spec.cr \
153 --replace '`hostname`' '`${hostname}/bin/hostname`'
154
155 # See https://github.com/crystal-lang/crystal/issues/8629
156 substituteInPlace spec/std/socket/udp_socket_spec.cr \
157 --replace 'it "joins and transmits to multicast groups"' 'pending "joins and transmits to multicast groups"'
158
159 ''
160 + lib.optionalString (stdenv.cc.isClang && (stdenv.cc.libcxx != null)) ''
161 # Darwin links against libc++ not libstdc++. Newer versions of clang (12+) require
162 # libc++abi to be linked explicitly (see https://github.com/NixOS/nixpkgs/issues/166205).
163 substituteInPlace src/llvm/lib_llvm.cr \
164 --replace '@[Link("stdc++")]' '@[Link("c++")]'
165 '';
166
167 # Defaults are 4
168 preBuild = ''
169 export CRYSTAL_WORKERS=$NIX_BUILD_CORES
170 export threads=$NIX_BUILD_CORES
171 export CRYSTAL_CACHE_DIR=$TMP
172 export MACOSX_DEPLOYMENT_TARGET=10.11
173 export SOURCE_DATE_EPOCH="$(<src/SOURCE_DATE_EPOCH)"
174 '';
175
176 strictDeps = true;
177 nativeBuildInputs = [
178 binary
179 makeWrapper
180 which
181 pkg-config
182 llvmPackages.llvm
183 installShellFiles
184 ];
185 buildInputs = [
186 boehmgc
187 pcre2
188 libevent
189 libyaml
190 zlib
191 libxml2
192 openssl
193 ]
194 ++ extraBuildInputs
195 ++ lib.optionals stdenv.hostPlatform.isDarwin [ libiconv ];
196
197 makeFlags = [
198 "CRYSTAL_CONFIG_VERSION=${version}"
199 "progress=1"
200 ];
201
202 LLVM_CONFIG = "${llvmPackages.llvm.dev}/bin/llvm-config";
203
204 FLAGS = [
205 "--single-module" # needed for deterministic builds
206 ];
207
208 # This makes sure we don't keep depending on the previous version of
209 # crystal used to build this one.
210 CRYSTAL_LIBRARY_PATH = "${placeholder "lib"}/crystal";
211
212 # We *have* to add `which` to the PATH or crystal is unable to build
213 # stuff later if which is not available.
214 installPhase = ''
215 runHook preInstall
216
217 install -Dm755 .build/crystal $bin/bin/crystal
218 wrapProgram $bin/bin/crystal \
219 --suffix PATH : ${
220 lib.makeBinPath [
221 pkg-config
222 llvmPackages.clang
223 which
224 ]
225 } \
226 --suffix CRYSTAL_PATH : lib:$lib/crystal \
227 --suffix PKG_CONFIG_PATH : ${
228 lib.makeSearchPathOutput "dev" "lib/pkgconfig" finalAttrs.buildInputs
229 } \
230 --suffix CRYSTAL_LIBRARY_PATH : ${lib.makeLibraryPath finalAttrs.buildInputs}
231 install -dm755 $lib/crystal
232 cp -r src/* $lib/crystal/
233
234 install -dm755 $out/share/doc/crystal/api
235 cp -r docs/* $out/share/doc/crystal/api/
236 cp -r samples $out/share/doc/crystal/
237
238 installShellCompletion --cmd ${finalAttrs.meta.mainProgram} etc/completion.*
239
240 installManPage man/crystal.1
241
242 install -Dm644 -t $out/share/licenses/crystal LICENSE README.md
243
244 mkdir -p $out
245 ln -s $bin/bin $out/bin
246 ln -s $bin/share/bash-completion $out/share/bash-completion
247 ln -s $bin/share/zsh $out/share/zsh
248 ln -s $bin/share/fish $out/share/fish
249 ln -s $lib $out/lib
250
251 runHook postInstall
252 '';
253
254 enableParallelBuilding = true;
255
256 dontStrip = true;
257
258 checkTarget = "compiler_spec";
259
260 preCheck = ''
261 export LIBRARY_PATH=${lib.makeLibraryPath nativeCheckInputs}:$LIBRARY_PATH
262 export PATH=${lib.makeBinPath nativeCheckInputs}:$PATH
263 '';
264
265 passthru.buildBinary = binary;
266 passthru.buildCrystalPackage = callPackage ./build-package.nix {
267 crystal = finalAttrs.finalPackage;
268 };
269 passthru.llvmPackages = llvmPackages;
270
271 meta = {
272 inherit (binary.meta) platforms;
273 description = "Compiled language with Ruby like syntax and type inference";
274 mainProgram = "crystal";
275 homepage = "https://crystal-lang.org/";
276 license = lib.licenses.asl20;
277 maintainers = with lib.maintainers; [
278 david50407
279 peterhoeg
280 donovanglover
281 ];
282 };
283 });
284in
285rec {
286 binaryCrystal_1_10 = genericBinary {
287 version = "1.10.1";
288 sha256s = {
289 x86_64-linux = "sha256-F0LjdV02U9G6B8ApHxClF/o5KvhxMNukSX7Z2CwSNIs=";
290 aarch64-darwin = "sha256-5kkObQl0VIO6zqQ8TYl0JzYyUmwfmPE9targpfwseSQ=";
291 x86_64-darwin = "sha256-5kkObQl0VIO6zqQ8TYl0JzYyUmwfmPE9targpfwseSQ=";
292 aarch64-linux = "sha256-AzFz+nrU/HJmCL1hbCKXf5ej/uypqV1GJPVLQ4J3778=";
293 };
294 };
295
296 crystal_1_14 = generic {
297 version = "1.14.1";
298 sha256 = "sha256-cQWK92BfksOW8GmoXn4BmPGJ7CLyLAeKccOffQMh5UU=";
299 binary = binaryCrystal_1_10;
300 llvmPackages = llvmPackages_19;
301 doCheck = false; # Some compiler spec problems on x86-64_linux with the .0 release
302 };
303
304 crystal_1_15 = generic {
305 version = "1.15.1";
306 sha256 = "sha256-L/Q8yZdDq/wn4kJ+zpLfi4pxznAtgjxTCbLnEiCC2K0=";
307 binary = binaryCrystal_1_10;
308 llvmPackages = llvmPackages_19;
309 doCheck = false;
310 };
311
312 crystal_1_16 = generic {
313 version = "1.16.3";
314 sha256 = "sha256-U9H1tHUMyDNicZnXzEccDki5bGXdV0B2Wu2PyCksPVI=";
315 binary = binaryCrystal_1_10;
316 llvmPackages = llvmPackages_20;
317 doCheck = false;
318 };
319
320 crystal_1_17 = generic {
321 version = "1.17.1";
322 sha256 = "sha256-+wHhozPhpIsfQy1Lw+V48zvuWCfXzT4IC9KA1AU/DLw=";
323 binary = binaryCrystal_1_10;
324 llvmPackages = llvmPackages_21;
325 doCheck = false;
326 };
327
328 crystal_1_18 = generic {
329 version = "1.18.2";
330 sha256 = "sha256-bwKs9bwD1WfS95DSxVY5AjT5Q61jOsfAH897tmiurng=";
331 binary = binaryCrystal_1_10;
332 llvmPackages = llvmPackages_21;
333 doCheck = false;
334 };
335
336 crystal_1_19 = generic {
337 version = "1.19.1";
338 sha256 = "sha256-vMS2GJb6c6RvflDSS2EWHsERJ0rvzZMVm50gaTXRs4Y=";
339 binary = binaryCrystal_1_10;
340 llvmPackages = llvmPackages_22;
341 doCheck = false;
342 };
343
344 crystal = crystal_1_19;
345}