nixpkgs mirror (for testing)
github.com/NixOS/nixpkgs
nix
1{
2 lib,
3 stdenv,
4 callPackage,
5 darwin,
6 ecl,
7 coreutils,
8 fetchurl,
9 ps,
10 strace,
11 texinfo,
12 which,
13 writableTmpDirAsHomeHook,
14 writeText,
15 zstd,
16 version,
17 # Set this to a lisp binary to use a custom bootstrap lisp compiler for SBCL.
18 # Leave as null to use the default. This is useful for local development of
19 # SBCL, because you can use your existing stock SBCL as a bootstrap. On Hydra
20 # of course we can’t do that because SBCL hasn’t been built yet, so we use
21 # ECL but that’s much slower.
22 bootstrapLisp ? null,
23}:
24
25let
26 versionMap = {
27 # Necessary for Nyxt
28 "2.4.6".sha256 = "sha256-pImQeELa4JoXJtYphb96VmcKrqLz7KH7cCO8pnw/MJE=";
29 # Necessary for stumpwm
30 "2.4.10".sha256 = "sha256-zus5a2nSkT7uBIQcKva+ylw0LOFGTD/j5FPy3hDF4vg=";
31 # By unofficial and very loose convention we keep the latest version of
32 # SBCL, and the previous one in case someone quickly needs to roll back.
33 "2.6.0".sha256 = "sha256-CkvVsByI5rRcLwWWBdJyirk3emUpsupiKnq7W6LWkcY=";
34 "2.6.1".sha256 = "sha256-XyzVu30+bZFJpZwFrNhCmzvhhJIRdp5aN0UdAB4ZbX8=";
35 };
36 # Collection of pre-built SBCL binaries for platforms that need them for
37 # bootstrapping. Ideally these are to be avoided. If ECL (or any other
38 # non-binary-distributed Lisp) can run on any of these systems, that entry
39 # should be removed from this list.
40 bootstrapBinaries = rec {
41 i686-linux = {
42 version = "1.2.7";
43 system = "x86-linux";
44 sha256 = "07f3bz4br280qvn85i088vpzj9wcz8wmwrf665ypqx181pz2ai3j";
45 };
46 armv7l-linux = {
47 version = "1.2.14";
48 system = "armhf-linux";
49 sha256 = "0sp5445rbvms6qvzhld0kwwvydw51vq5iaf4kdqsf2d9jvaz3yx5";
50 };
51 armv6l-linux = armv7l-linux;
52 x86_64-freebsd = {
53 version = "1.2.7";
54 system = "x86-64-freebsd";
55 sha256 = "14k42xiqd2rrim4pd5k5pjcrpkac09qnpynha8j1v4jngrvmw7y6";
56 };
57 x86_64-solaris = {
58 version = "1.2.7";
59 system = "x86-64-solaris";
60 sha256 = "05c12fmac4ha72k1ckl6i780rckd7jh4g5s5hiic7fjxnf1kx8d0";
61 };
62 };
63 sbclBootstrap = callPackage ./bootstrap.nix {
64 cfg = bootstrapBinaries.${stdenv.hostPlatform.system};
65 };
66 bootstrapLisp' =
67 if bootstrapLisp != null then
68 bootstrapLisp
69 else if (builtins.hasAttr stdenv.hostPlatform.system bootstrapBinaries) then
70 "${sbclBootstrap}/bin/sbcl --disable-debugger --no-userinit --no-sysinit"
71 else
72 "${lib.getExe ecl} --norc";
73 posixUtils = if stdenv.hostPlatform.isDarwin then darwin.shell_cmds else coreutils;
74
75in
76
77stdenv.mkDerivation (self: {
78 pname = "sbcl";
79 inherit version;
80
81 src = fetchurl {
82 # Changing the version shouldn’t change the source for the
83 # derivation. Override the src entirely if desired.
84 url = "mirror://sourceforge/project/sbcl/sbcl/${version}/sbcl-${version}-source.tar.bz2";
85 inherit (versionMap.${version}) sha256;
86 };
87
88 nativeBuildInputs = [
89 texinfo
90 ]
91 ++ lib.optionals self.doCheck (
92 [
93 which
94 writableTmpDirAsHomeHook
95 ]
96 ++ lib.optionals (builtins.elem stdenv.system strace.meta.platforms) [
97 strace
98 ]
99 ++ lib.optionals (lib.versionOlder "2.4.10" self.version) [
100 ps
101 ]
102 );
103 buildInputs = lib.optionals self.coreCompression (
104 # Declare at the point of actual use in case the caller wants to override
105 # buildInputs to sidestep this.
106 assert lib.assertMsg (!self.purgeNixReferences) ''
107 Cannot enable coreCompression when purging Nix references, because compression requires linking in zstd
108 '';
109 [ zstd ]
110 );
111
112 threadSupport = (
113 stdenv.hostPlatform.isx86
114 || "aarch64-linux" == stdenv.hostPlatform.system
115 || "aarch64-darwin" == stdenv.hostPlatform.system
116 );
117 # Meant for sbcl used for creating binaries portable to non-NixOS via save-lisp-and-die.
118 # Note that the created binaries still need `patchelf --set-interpreter ...`
119 # to get rid of ${glibc} dependency.
120 purgeNixReferences = false;
121 coreCompression = true;
122 markRegionGC = self.threadSupport;
123 disableImmobileSpace = false;
124 linkableRuntime = stdenv.hostPlatform.isx86;
125
126 # I don’t know why these are failing (on ofBorg), and I’d rather just disable
127 # them and move forward with the succeeding tests than block testing
128 # altogether. One by one hopefully we can fix these (on ofBorg,
129 # upstream--somehow some way) in due time.
130 disabledTestFiles =
131 lib.optionals (lib.versionOlder "2.5.2" self.version) [ "debug.impure.lisp" ]
132 ++
133 lib.optionals
134 (builtins.elem stdenv.hostPlatform.system [
135 "x86_64-linux"
136 "aarch64-linux"
137 ])
138 [
139 "foreign-stack-alignment.impure.lisp"
140 # Floating point tests are fragile
141 # https://sourceforge.net/p/sbcl/mailman/message/58728554/
142 "compiler.pure.lisp"
143 "float.pure.lisp"
144 ]
145 ++ lib.optionals (stdenv.hostPlatform.system == "aarch64-linux") [
146 # This is failing on aarch64-linux on ofBorg. Not on my local machine nor on
147 # a VM on my laptop. Not sure what’s wrong.
148 "traceroot.impure.lisp"
149 # Heisentest, sometimes fails on ofBorg, would rather just disable it than
150 # have it block a release.
151 "futex-wait.test.sh"
152 ]
153 ++ lib.optionals (stdenv.hostPlatform.system == "aarch64-darwin") [
154 # Fail intermittently
155 "gc.impure.lisp"
156 "threads.pure.lisp"
157 ]
158 ++ lib.optionals stdenv.hostPlatform.isDarwin [
159 # This test has a gotcha on Darwin which originally showed up in
160 # 57b36ea5c83a1841b174ec6cd5e423439fe9d7a0, and later again around Oct
161 # 2025 in staging. The test wants a clean environment (using
162 # run-program, akin to fork & execve), but darwin keeps injecting this
163 # envvar:
164 #
165 # __CF_USER_TEXT_ENCODING=0x15F:0:0
166 #
167 # It’s not clear to maintainers where the problem lies exactly, but
168 # removing the test at least fixes the build and unblocks others.
169 #
170 # see:
171 # - https://github.com/NixOS/nixpkgs/pull/359214
172 # - https://github.com/NixOS/nixpkgs/pull/453099
173 "run-program.test.sh"
174
175 # Fails in sandbox
176 "sb-posix.impure.lisp"
177 ];
178
179 patches =
180 # Support the NIX_SBCL_DYNAMIC_SPACE_SIZE envvar. Upstream SBCL didn’t want
181 # to include this (see
182 # "https://sourceforge.net/p/sbcl/mailman/sbcl-devel/thread/2cf20df7-01d0-44f2-8551-0df01fe55f1a%400brg.net/"),
183 # but for Nix envvars are sufficiently useful that it’s worth maintaining
184 # this functionality downstream.
185 if lib.versionOlder "2.5.2" self.version then
186 [
187 ./dynamic-space-size-envvar-2.5.3-feature.patch
188 ./dynamic-space-size-envvar-2.5.3-tests.patch
189 ]
190 else
191 [
192 ./dynamic-space-size-envvar-2.5.2-feature.patch
193 ./dynamic-space-size-envvar-2.5.2-tests.patch
194 ];
195
196 sbclPatchPhase =
197 lib.optionalString (self.disabledTestFiles != [ ]) ''
198 (cd tests ; rm -f ${lib.concatStringsSep " " self.disabledTestFiles})
199 ''
200 + lib.optionalString self.purgeNixReferences ''
201 # This is the default location to look for the core; by default in $out/lib/sbcl
202 sed 's@^\(#define SBCL_HOME\) .*$@\1 "/no-such-path"@' \
203 -i src/runtime/runtime.c
204 ''
205 + ''
206 (
207 shopt -s nullglob
208 # Tests need patching regardless of purging of paths from the final
209 # binary. There are some tricky files in nested directories which should
210 # definitely NOT be patched this way, hence just a single * (and no
211 # globstar).
212 substituteInPlace ${if self.purgeNixReferences then "tests" else "{tests,src/code}"}/*.{lisp,sh} \
213 --replace-quiet /usr/bin/env "${posixUtils}/bin/env" \
214 --replace-quiet /bin/uname "${posixUtils}/bin/uname" \
215 --replace-quiet /bin/sh "${stdenv.shell}"
216 )
217 # Official source release tarballs will have a version.lispexpr, but if you
218 # want to override { src = ... } it might not exist. It’s required for
219 # building, so create a mock version as a backup.
220 if [[ ! -a version.lisp-expr ]]; then
221 echo '"${self.version}.nixos"' > version.lisp-expr
222 fi
223 '';
224
225 preConfigurePhases = "sbclPatchPhase";
226
227 enableFeatures =
228 assert lib.assertMsg (
229 self.markRegionGC -> self.threadSupport
230 ) "SBCL mark region GC requires thread support";
231 lib.optional self.threadSupport "sb-thread"
232 ++ lib.optional self.linkableRuntime "sb-linkable-runtime"
233 ++ lib.optional self.coreCompression "sb-core-compression"
234 ++ lib.optional stdenv.hostPlatform.isAarch32 "arm"
235 ++ lib.optional self.markRegionGC "mark-region-gc";
236
237 disableFeatures =
238 lib.optional (!self.threadSupport) "sb-thread"
239 ++ lib.optionals self.disableImmobileSpace [
240 "immobile-space"
241 "immobile-code"
242 "compact-instance-header"
243 ];
244
245 buildArgs = [
246 "--prefix=$out"
247 "--xc-host=${lib.escapeShellArg bootstrapLisp'}"
248 ]
249 ++ map (x: "--with-${x}") self.enableFeatures
250 ++ map (x: "--without-${x}") self.disableFeatures
251 ++ lib.optionals (stdenv.hostPlatform.system == "aarch64-darwin") [
252 "--arch=arm64"
253 ];
254
255 # Fails to find `O_LARGEFILE` otherwise.
256 env.NIX_CFLAGS_COMPILE = "-D_GNU_SOURCE";
257
258 # Set minimum macOS version to 10.12 for x86_64-darwin to support clock_gettime()
259 env.SBCL_MACOSX_VERSION_MIN = lib.optionalString (
260 stdenv.hostPlatform.isDarwin && stdenv.hostPlatform.isx86_64
261 ) "10.12";
262
263 buildPhase = ''
264 runHook preBuild
265
266 export INSTALL_ROOT=$out
267 sh make.sh ${lib.concatStringsSep " " self.buildArgs}
268 (cd doc/manual ; make info)
269
270 runHook postBuild
271 '';
272
273 # Tests on ofBorg’s x86_64-darwin platforms are so unstable that a random one
274 # will fail every other run. There’s a deeper problem here; we might as well
275 # disable them entirely so at least the other platforms get to benefit from
276 # testing.
277 doCheck = stdenv.hostPlatform.system != "x86_64-darwin";
278
279 # From the INSTALL docs
280 checkPhase = ''
281 runHook preCheck
282
283 (cd tests && sh run-tests.sh)
284
285 runHook postCheck
286 '';
287
288 installPhase = ''
289 runHook preInstall
290
291 sh install.sh
292
293 ''
294 + lib.optionalString (!self.purgeNixReferences) ''
295 cp -r src $out/lib/sbcl
296 cp -r contrib $out/lib/sbcl
297 cat >$out/lib/sbcl/sbclrc <<EOF
298 (setf (logical-pathname-translations "SYS")
299 '(("SYS:SRC;**;*.*.*" #P"$out/lib/sbcl/src/**/*.*")
300 ("SYS:CONTRIB;**;*.*.*" #P"$out/lib/sbcl/contrib/**/*.*")))
301 EOF
302 ''
303 + ''
304 runHook postInstall
305 '';
306
307 setupHook = lib.optional self.purgeNixReferences (
308 writeText "setupHook.sh" ''
309 addEnvHooks "$targetOffset" _setSbclHome
310 _setSbclHome() {
311 export SBCL_HOME='@out@/lib/sbcl/'
312 }
313 ''
314 );
315
316 __darwinAllowLocalNetworking = true;
317
318 meta = {
319 description = "Common Lisp compiler";
320 homepage = "https://sbcl.org";
321 license = lib.licenses.publicDomain; # and FreeBSD
322 mainProgram = "sbcl";
323 teams = [ lib.teams.lisp ];
324 platforms = lib.attrNames bootstrapBinaries ++ [
325 # These aren’t bootstrapped using the binary distribution but compiled
326 # using a separate (lisp) host
327 "x86_64-darwin"
328 "x86_64-linux"
329 "aarch64-darwin"
330 "aarch64-linux"
331 ];
332 };
333})