lisp-modules: init

From https://github.com/Uthar/nix-cl
Commit ebeb76057abf01029067f1ebe0ae6fae90848bfe
This commit is contained in:
Kasper Gałkowski 2023-03-01 21:26:31 +01:00
parent 04c276ac9c
commit 9e860e41eb
23 changed files with 60777 additions and 0 deletions

View File

@ -0,0 +1,18 @@
(defpackage :nix-cl-user
(:use :cl))
(in-package :nix-cl-user)
(load "@asdf@")
(defun load-systems ()
(handler-case
(let ((systems (uiop:getenv "systems")))
(dolist (s (uiop:split-string systems :separator " "))
(asdf:load-system s)))
(error (c)
(format t "BUILD FAILED: ~A~%" c)
(uiop:quit 1)))
(uiop:quit 0))
(load-systems)

View File

@ -0,0 +1,18 @@
(defpackage org.lispbuilds.nix/api
(:documentation "Public interface of org.lispbuilds.nix")
(:use :cl)
(:export
:import-lisp-packages
:database->nix-expression))
(in-package org.lispbuilds.nix/api)
(defgeneric import-lisp-packages (repository database)
(:documentation
"Import Lisp packages (ASDF systems) from repository (Quicklisp,
Ultralisp etc.) into a package database."))
(defgeneric database->nix-expression (database outfile)
(:documentation
"Generate a nix expression from the package database and write it
into outfile."))

View File

@ -0,0 +1,176 @@
(defpackage org.lispbuilds.nix/database/sqlite
(:use :cl)
(:import-from :str)
(:import-from :sqlite)
(:import-from :alexandria :read-file-into-string)
(:import-from :alexandria-2 :line-up-first)
(:import-from :arrow-macros :->>)
(:import-from
:org.lispbuilds.nix/util
:replace-regexes)
(:import-from
:org.lispbuilds.nix/nix
:nix-eval
:nixify-symbol
:system-master
:make-pname
:*nix-attrs-depth*)
(:import-from
:org.lispbuilds.nix/api
:database->nix-expression)
(:export :sqlite-database :init-db)
(:local-nicknames
(:json :com.inuoe.jzon)))
(in-package org.lispbuilds.nix/database/sqlite)
(defclass sqlite-database ()
((url :initarg :url
:reader database-url
:initform (error "url required"))
(init-file :initarg :init-file
:reader init-file
:initform (error "init file required"))))
(defun init-db (db init-file)
(let ((statements (->> (read-file-into-string init-file)
(replace-regexes '(".*--.*") '(""))
(substitute #\Space #\Newline)
(str:collapse-whitespaces)
(str:split #\;)
(mapcar #'str:trim)
(remove-if #'str:emptyp))))
(sqlite:with-transaction db
(dolist (s statements)
(sqlite:execute-non-query db s)))))
;; Writing Nix
(defparameter prelude "
# This file was auto-generated by nix-quicklisp.lisp
{ runCommand, pkgs, lib, fetchzip, build-asdf-system, ... }:
let
inherit (builtins) getAttr;
# Ensures that every non-slashy `system` exists in a unique .asd file.
# (Think cl-async-base being declared in cl-async.asd upstream)
#
# This is required because we're building and loading a system called
# `system`, not `asd`, so otherwise `system` would not be loadable
# without building and loading `asd` first.
#
createAsd = { url, sha256, asd, system }:
let
src = fetchzip { inherit url sha256; };
in
if asd == system
then src
else runCommand \"source\" {} ''
mkdir -pv $out
cp -r ${src}/* $out
find $out -name \"${asd}.asd\" | while read f; do mv -fv $f $(dirname $f)/${system}.asd || true; done
'';
in lib.makeScope pkgs.newScope (self: {")
;; Random compilation errors
(defparameter +broken-packages+
(list
;; no dispatch function defined for #\t
"hu.dwim.logger"
"hu.dwim.serializer"
"hu.dwim.quasi-quote"
;; Tries to write in $HOME
"ubiquitous"
"math"
;; Upstream bad packaging, multiple systems in clml.blas.asd
"clml.blas.hompack"
;; Fails on SBCL due to heap exhaustion
"magicl"
;; Probably missing dependency in QL data
"mcclim-bezier"
;; Missing dependency on c2ffi cffi extension
"hu.dwim.zlib"
;; Missing libgvc.so native library
"hu.dwim.graphviz"
;; These require libRmath.so, but I don't know where to get it from
"cl-random"
"cl-random-tests"
))
(defmethod database->nix-expression ((database sqlite-database) outfile)
(sqlite:with-open-database (db (database-url database))
(with-open-file (f outfile
:direction :output
:if-exists :supersede)
;; Fix known problematic packages before dumping the nix file.
(sqlite:execute-non-query db
"create temp table fixed_systems as select * from system_view")
(sqlite:execute-non-query db
"alter table fixed_systems add column systems")
(sqlite:execute-non-query db
"update fixed_systems set systems = json_array(name)")
(sqlite:execute-non-query db
"alter table fixed_systems add column asds")
(sqlite:execute-non-query db
"update fixed_systems set asds = json_array(name)")
(sqlite:execute-non-query db
"delete from fixed_systems where name in ('asdf', 'uiop')")
(sqlite:execute-non-query db
"delete from fixed_systems where instr(name, '/')")
(format f prelude)
(dolist (p (sqlite:execute-to-list db "select * from fixed_systems"))
(destructuring-bind (name version asd url sha256 deps systems asds) p
(format f "~% ")
(let ((*nix-attrs-depth* 1))
(format
f
"~a = ~a;"
(nix-eval `(:symbol ,name))
(nix-eval
`(:funcall
"build-asdf-system"
(:attrs
("pname" (:string ,(make-pname name)))
("version" (:string ,version))
("asds" (:list
,@(mapcar (lambda (asd)
`(:string ,(system-master asd)))
(coerce (json:parse asds) 'list))))
("src" (:funcall
"createAsd"
(:attrs
("url" (:string ,url))
("sha256" (:string ,sha256))
("system" (:string ,(system-master name)))
("asd" (:string ,asd)))))
("systems" (:list
,@(mapcar (lambda (sys)
`(:string ,sys))
(coerce (json:parse systems) 'list))))
("lispLibs" (:list
,@(mapcar (lambda (dep)
`(:funcall
"getAttr"
(:string ,(nixify-symbol dep))
(:symbol "self")))
(line-up-first
(str:split-omit-nulls #\, deps)
(set-difference '("asdf" "uiop") :test #'string=)
(sort #'string<)))))
,@(when (or (find #\/ name)
(find name +broken-packages+ :test #'string=))
'(("meta" (:attrs ("broken" (:symbol "true")))))))))))))
(format f "~%})"))))

View File

@ -0,0 +1,41 @@
CREATE TABLE IF NOT EXISTS sha256 (
id integer PRIMARY KEY AUTOINCREMENT,
url text UNIQUE,
hash text NOT NULL,
created real DEFAULT (julianday('now'))
);
CREATE TABLE IF NOT EXISTS system (
id integer PRIMARY KEY AUTOINCREMENT,
name text NOT NULL,
version text NOT NULL,
asd text NOT NULL,
created real DEFAULT (julianday('now')),
UNIQUE(name, version)
);
CREATE TABLE IF NOT EXISTS dep (
system_id integer NOT NULL REFERENCES system(id),
dep_id integer NOT NULL REFERENCES system(id),
PRIMARY KEY (system_id, dep_id)
);
CREATE TABLE IF NOT EXISTS src (
sha256_id integer REFERENCES sha256(id),
system_id integer UNIQUE REFERENCES system(id)
);
DROP VIEW IF EXISTS system_view;
CREATE VIEW IF NOT EXISTS system_view AS
SELECT
sys.name,
sys.version,
sys.asd,
sha.url,
sha.hash,
group_concat((SELECT name FROM system WHERE id = dep.dep_id)) as deps
FROM system sys
JOIN src ON src.system_id = sys.id
JOIN sha256 sha ON sha.id = src.sha256_id
LEFT JOIN dep ON dep.system_id = sys.id
GROUP BY sys.name;

View File

@ -0,0 +1,42 @@
(defpackage org.lispbuilds.nix/main
(:use :common-lisp
:org.lispbuilds.nix/database/sqlite
:org.lispbuilds.nix/repository/quicklisp
:org.lispbuilds.nix/api))
(in-package org.lispbuilds.nix/main)
(defun resource (name type)
(make-pathname
:defaults (asdf:system-source-directory :org.lispbuilds.nix)
:name name
:type type))
(defvar *sqlite*
(make-instance
'sqlite-database
:init-file (resource "init" "sql")
:url "packages.sqlite"))
;; Check http://beta.quicklisp.org/dist/quicklisp.txt for updates
(defvar *quicklisp*
(make-instance
'quicklisp-repository
:dist-url
"https://beta.quicklisp.org/dist/quicklisp/2023-02-15/"))
(defun run-importers ()
(ignore-errors (delete-file "packages.sqlite"))
(import-lisp-packages *quicklisp* *sqlite*)
(format t "Imported packages from quicklisp to ~A~%"
(truename "packages.sqlite")))
(defun gen-nix-file ()
(database->nix-expression *sqlite* "imported.nix")
(format t "Dumped nix file to ~a~%"
(truename "imported.nix")))
(defun main ()
(format t "~%")
(run-importers)
(gen-nix-file))

View File

@ -0,0 +1,81 @@
(defpackage org.lispbuilds.nix/nix
(:documentation "Utilities for generating Nix code")
(:use :cl)
(:import-from :str)
(:import-from :ppcre)
(:import-from :arrow-macros :->>)
(:import-from :org.lispbuilds.nix/util :replace-regexes)
(:export
:nix-eval
:nixify-symbol
:system-master
:make-pname
:*nix-attrs-depth*))
(in-package org.lispbuilds.nix/nix)
;; Path names are alphanumeric and can include the symbols +-._?= and
;; must not begin with a period.
(defun make-pname (string)
(replace-regexes '("^[.]" "[^a-zA-Z0-9+-._?=]")
'("_" "_")
string))
(defun system-master (system)
(first (str:split "/" system)))
;;;; Nix generation
(defun nix-eval (exp)
(assert (consp exp))
(ecase (car exp)
(:string (nix-string (cadr exp)))
(:list (apply #'nix-list (rest exp)))
(:funcall (apply #'nix-funcall (rest exp)))
(:attrs (nix-attrs (cdr exp)))
(:merge (apply #'nix-merge (cdr exp)))
(:symbol (nix-symbol (cadr exp)))))
(defun nix-string (object)
(format nil "\"~a\"" object))
(defun nixify-symbol (string)
(flet ((fix-special-chars (str)
(replace-regexes '("[+]$" "[+][/]" "[+]" "[.]" "[/]")
'("_plus" "_plus/" "_plus_" "_dot_" "_slash_")
str)))
(if (ppcre:scan "^[0-9]" string)
(str:concat "_" (fix-special-chars string))
(fix-special-chars string))))
(defun nix-symbol (object)
(nixify-symbol (format nil "~a" object)))
(defun nix-list (&rest things)
(format nil "[ ~{~A~^ ~} ]" (mapcar 'nix-eval things)))
(defvar *nix-attrs-depth* 0)
(defun nix-attrs (keyvals)
(let ((*nix-attrs-depth* (1+ *nix-attrs-depth*)))
(format
nil
(->> "{~%*depth*~{~{~A = ~A;~}~^~%*depth*~}~%*depth-1*}"
(str:replace-all "*depth*" (str:repeat *nix-attrs-depth* " "))
(str:replace-all "*depth-1*" (str:repeat (1- *nix-attrs-depth*) " ")))
(mapcar (lambda (keyval)
(let ((key (car keyval))
(val (cadr keyval)))
(list (nix-symbol key)
(nix-eval val))))
keyvals))))
(defun nix-funcall (fun &rest args)
(format nil "(~a ~{~a~^ ~})"
(nixify-symbol fun)
(mapcar 'nix-eval args)))
(defun nix-merge (a b)
(format nil "(~a // ~b)"
(nix-eval a)
(nix-eval b)))

View File

@ -0,0 +1,28 @@
(defsystem org.lispbuilds.nix
:class :package-inferred-system
:description "Utilities for importing ASDF systems into Nix"
:depends-on (
:alexandria
:str
:cl-ppcre
:sqlite
:dexador
:arrow-macros
:com.inuoe.jzon
:org.lispbuilds.nix/api
:org.lispbuilds.nix/repository/quicklisp
:org.lispbuilds.nix/database/sqlite
))
(register-system-packages
"cl-ppcre"
'(:ppcre))
(register-system-packages
"dexador"
'(:dex))
(register-system-packages
"alexandria"
'(:alexandria :alexandria-2))

View File

@ -0,0 +1,199 @@
(defpackage org.lispbuilds.nix/repository/quicklisp
(:use :cl)
(:import-from :dex)
(:import-from :alexandria :read-file-into-string :ensure-list)
(:import-from :arrow-macros :->>)
(:import-from :str)
(:import-from
:org.lispbuilds.nix/database/sqlite
:sqlite-database
:init-db
:database-url
:init-file)
(:import-from
:org.lispbuilds.nix/api
:import-lisp-packages)
(:import-from
:org.lispbuilds.nix/util
:replace-regexes)
(:export :quicklisp-repository)
(:local-nicknames
(:json :com.inuoe.jzon)))
(in-package org.lispbuilds.nix/repository/quicklisp)
(defclass quicklisp-repository ()
((dist-url :initarg :dist-url
:reader dist-url
:initform (error "dist url required"))))
(defun clear-line ()
(write-char #\Return *error-output*)
(write-char #\Escape *error-output*)
(write-char #\[ *error-output*)
(write-char #\K *error-output*))
(defun status (&rest format-args)
(clear-line)
(apply #'format (list* *error-output* format-args))
(force-output *error-output*))
;; TODO: This should not know about the imported.nix file.
(defun init-tarball-hashes (database)
(status "no packages.sqlite - will pre-fill tarball hashes from ~A to save time~%"
(truename "imported.nix"))
(let* ((lines (uiop:read-file-lines "imported.nix"))
(lines (remove-if-not
(lambda (line)
(let ((trimmed (str:trim-left line)))
(or (str:starts-with-p "url = " trimmed)
(str:starts-with-p "sha256 = " trimmed))))
lines))
(lines (mapcar
(lambda (line)
(multiple-value-bind (whole groups)
(ppcre:scan-to-strings "\"\(.*\)\"" line)
(declare (ignore whole))
(svref groups 0)))
lines)))
(sqlite:with-open-database (db (database-url database))
(init-db db (init-file database))
(sqlite:with-transaction db
(loop while lines do
(sqlite:execute-non-query db
"insert or ignore into sha256(url,hash) values (?,?)"
(prog1 (first lines) (setf lines (rest lines)))
(prog1 (first lines) (setf lines (rest lines))))))
(status "OK, imported ~A hashes into DB.~%"
(sqlite:execute-single db
"select count(*) from sha256")))))
(defmethod import-lisp-packages ((repository quicklisp-repository)
(database sqlite-database))
;; If packages.sqlite is missing, we should populate the sha256
;; table to speed things up.
(unless (probe-file (database-url database))
(init-tarball-hashes database))
(let* ((db (sqlite:connect (database-url database)))
(systems-url (str:concat (dist-url repository) "systems.txt"))
(releases-url (str:concat (dist-url repository) "releases.txt"))
(systems-lines (rest (butlast (str:split #\Newline (dex:get systems-url)))))
(releases-lines (rest (butlast (str:split #\Newline (dex:get releases-url))))))
(flet ((sql-query (sql &rest params)
(apply #'sqlite:execute-to-list (list* db sql params))))
;; Ensure database schema
(init-db db (init-file database))
;; Prepare temporary tables for efficient access
(sql-query "create temp table if not exists quicklisp_system
(project, asd, name unique, deps)")
(sql-query "create temp table if not exists quicklisp_release
(project unique, url, size, md5, sha1, prefix not null, asds)")
(sqlite:with-transaction db
(dolist (line systems-lines)
(destructuring-bind (project asd name &rest deps)
(str:words line)
(sql-query
"insert or ignore into quicklisp_system values(?,?,?,?)"
project asd name (json:stringify (coerce deps 'vector))))))
(sqlite:with-transaction db
(dolist (line releases-lines)
(destructuring-bind (project url size md5 sha1 prefix &rest asds)
(str:words line)
(sql-query
"insert or ignore into quicklisp_release values(?,?,?,?,?,?,?)"
project url size md5 sha1 prefix (json:stringify (coerce
asds
'vector))))))
(sqlite:with-transaction db
;; Should these be temp tables, that then get queried by
;; system name? This looks like it uses a lot of memory.
(let ((systems
(sql-query
"with pkg as (
select
name, asd, url, deps,
ltrim(replace(prefix, r.project, ''), '-_') as version
from quicklisp_system s, quicklisp_release r
where s.project = r.project
)
select
name, version, asd, url,
(select json_group_array(
json_array(value, (select version from pkg where name=value))
)
from json_each(deps)) as deps
from pkg"
)))
;; First pass: insert system and source tarball informaton.
;; Can't insert dependency information, because this works
;; on system ids in the database and they don't exist
;; yet. Could it be better to just base dependencies on
;; names? But then ACID is lost.
(dolist (system systems)
(destructuring-bind (name version asd url deps) system
(declare (ignore deps))
(status "importing system '~a-~a'" name version)
(let ((hash (nix-prefetch-tarball url db)))
(sql-query
"insert or ignore into system(name,version,asd) values (?,?,?)"
name version asd)
(sql-query
"insert or ignore into sha256(url,hash) values (?,?)"
url hash)
(sql-query
"insert or ignore into src values
((select id from sha256 where url=?),
(select id from system where name=? and version=?))"
url name version))))
;; Second pass: connect the in-database systems with
;; dependency information
(dolist (system systems)
(destructuring-bind (name version asd url deps) system
(declare (ignore asd url))
(dolist (dep (coerce (json:parse deps) 'list))
(destructuring-bind (dep-name dep-version) (coerce dep 'list)
(if (eql dep-version 'NULL)
(warn "Bad data in Quicklisp: ~a has no version" dep-name)
(sql-query
"insert or ignore into dep values
((select id from system where name=? and version=?),
(select id from system where name=? and version=?))"
name version
dep-name dep-version))))))))))
(write-char #\Newline *error-output*))
(defun shell-command-to-string (cmd)
;; Clearing the library path is needed to prevent a bug, where the
;; called subprocess uses a different glibc than the SBCL process
;; is. In that case, the call to execve attempts to load the
;; libraries used by SBCL from LD_LIBRARY_PATH using a different
;; glibc than they expect, which errors out.
(let ((ld-library-path (uiop:getenv "LD_LIBRARY_PATH")))
(setf (uiop:getenv "LD_LIBRARY_PATH") "")
(unwind-protect
(uiop:run-program cmd :output '(:string :stripped t))
(setf (uiop:getenv "LD_LIBRARY_PATH") ld-library-path))))
(defun nix-prefetch-tarball (url db)
(restart-case
(compute-sha256 url db)
(try-again ()
:report "Try downloading again"
(nix-prefetch-tarball url db))))
(defun compute-sha256 (url db)
(or (sqlite:execute-single db "select hash from sha256 where url=?" url)
(let ((sha256 (shell-command-to-string (str:concat "nix-prefetch-url --unpack " url))))
sha256)))

View File

@ -0,0 +1,16 @@
(defpackage org.lispbuilds.nix/util
(:use :cl)
(:import-from :ppcre)
(:export
:replace-regexes))
(in-package org.lispbuilds.nix/util)
(defun replace-regexes (from to str)
(assert (= (length from) (length to)))
(if (null from)
str
(replace-regexes
(rest from)
(rest to)
(ppcre:regex-replace-all (first from) str (first to)))))

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,293 @@
# TODO:
# - faster build by using lisp with preloaded asdf?
# - dont include java libs unless abcl?
# - dont use build-asdf-system to build lispWithPackages?
# - make the lisp packages overridable? (e.g. buildInputs glibc->musl)
# - build asdf with nix and use that instead of one shipped with impls
# (e.g. to fix build with clisp - does anyone use clisp?)
# - claspPackages ? (gotta package clasp with nix first)
# - hard one: remove unrelated sources ( of systems not being built)
# - figure out a less awkward way to patch sources
# (have to build from src directly for SLIME to work, so can't just patch sources in place)
{ pkgs
, lib
, stdenv
, ... }:
let
inherit (lib)
length
filter
foldl
unique
id
concat
concatMap
mutuallyExclusive
findFirst
remove
setAttr
getAttr
hasAttr
attrNames
attrValues
filterAttrs
mapAttrs
splitString
concatStringsSep
concatMapStringsSep
replaceStrings
removeSuffix
hasInfix
optionalString
makeBinPath
makeLibraryPath
makeSearchPath
recurseIntoAttrs
;
inherit (builtins)
head
tail
elem
split
storeDir;
inherit (pkgs)
substituteAll;
# Stolen from python-packages.nix
# Actually no idea how this works
makeOverridableLispPackage = f: origArgs:
let
ff = f origArgs;
overrideWith = newArgs: origArgs // (if pkgs.lib.isFunction newArgs then newArgs origArgs else newArgs);
in
if builtins.isAttrs ff then (ff // {
overrideLispAttrs = newArgs: makeOverridableLispPackage f (overrideWith newArgs);
})
else if builtins.isFunction ff then {
overrideLispAttrs = newArgs: makeOverridableLispPackage f (overrideWith newArgs);
__functor = self: ff;
}
else ff;
buildAsdf = { asdf, pkg, program, flags, faslExt }:
stdenv.mkDerivation {
inherit (asdf) pname version;
dontUnpack = true;
buildPhase = ''
cp -v ${asdf}/lib/common-lisp/asdf/build/asdf.lisp asdf.lisp
${pkg}/bin/${program} ${flags} < <(echo '(compile-file "asdf.lisp")')
'';
installPhase = ''
mkdir -p $out
cp -v asdf.${faslExt} $out
'';
};
#
# Wrapper around stdenv.mkDerivation for building ASDF systems.
#
build-asdf-system = makeOverridableLispPackage (
{ pname,
version,
src ? null,
patches ? [],
# Native libraries, will be appended to the library path
nativeLibs ? [],
# Java libraries for ABCL, will be appended to the class path
javaLibs ? [],
# Lisp dependencies
# these should be packages built with `build-asdf-system`
# TODO(kasper): use propagatedBuildInputs
lispLibs ? [],
# Derivation containing the CL implementation package
pkg,
# Name of the Lisp exectable
program ? pkg.pname,
# General flags to the Lisp executable
flags ? "",
# Extension for implementation-dependent FASL files
faslExt,
# ASDF amalgamation file to use
# Created in build/asdf.lisp by `make` in ASDF source tree
asdf,
# Some libraries have multiple systems under one project, for
# example, cffi has cffi-grovel, cffi-toolchain etc. By
# default, only the `pname` system is build.
#
# .asd's not listed in `systems` are removed in
# installPhase. This prevents asdf from referring to uncompiled
# systems on run time.
#
# Also useful when the pname is differrent than the system name,
# such as when using reverse domain naming.
systems ? [ pname ],
# The .asd files that this package provides
# TODO(kasper): remove
asds ? systems,
# Other args to mkDerivation
...
} @ args:
stdenv.mkDerivation (rec {
inherit
pname version nativeLibs javaLibs lispLibs systems asds
pkg program flags faslExt
;
# When src is null, we are building a lispWithPackages and only
# want to make use of the dependency environment variables
# generated by build-asdf-system
dontUnpack = src == null;
# Portable script to build the systems.
#
# `lisp` must evaluate this file then exit immediately. For
# example, SBCL's --script flag does just that.
#
# NOTE:
# Every other library worked fine with asdf:compile-system in
# buildScript.
#
# cl-syslog, for some reason, signals that CL-SYSLOG::VALID-SD-ID-P
# is undefined with compile-system, but works perfectly with
# load-system. Strange.
# TODO(kasper) portable quit
asdfFasl = buildAsdf { inherit asdf pkg program flags faslExt; };
buildScript = substituteAll {
src = ./builder.lisp;
asdf = "${asdfFasl}/asdf.${faslExt}";
};
preConfigure = ''
source ${./setup-hook.sh}
buildAsdfPath
'';
buildPhase = optionalString (src != null) ''
export CL_SOURCE_REGISTRY=$CL_SOURCE_REGISTRY:$src//
export ASDF_OUTPUT_TRANSLATIONS="$src:$(pwd):${storeDir}:${storeDir}"
${pkg}/bin/${program} ${flags} < $buildScript
'';
# Copy compiled files to store
#
# Make sure to include '$' in regex to prevent skipping
# stuff like 'iolib.asdf.asd' for system 'iolib.asd'
#
# Same with '/': `local-time.asd` for system `cl-postgres+local-time.asd`
installPhase =
let
mkSystemsRegex = systems:
concatMapStringsSep "\\|" (replaceStrings ["." "+"] ["[.]" "[+]"]) systems;
in
''
mkdir -pv $out
cp -r * $out
# Remove all .asd files except for those in `systems`.
find $out -name "*.asd" \
| grep -v "/\(${mkSystemsRegex systems}\)\.asd$" \
| xargs rm -fv || true
'';
dontPatchShebangs = true;
# Not sure if it's needed, but caused problems with SBCL
# save-lisp-and-die binaries in the past
dontStrip = true;
} // (args // {
src = if builtins.length (args.patches or []) > 0
then pkgs.applyPatches { inherit (args) src patches; }
else args.src;
patches = [];
propagatedBuildInputs = args.propagatedBuildInputs or []
++ lispLibs ++ javaLibs ++ nativeLibs;
})));
# Build the set of lisp packages using `lisp`
# These packages are defined manually for one reason or another:
# - The library is not in quicklisp
# - The library that is in quicklisp is broken
# - Special build procedure such as cl-unicode, asdf
#
# They can use the auto-imported quicklisp packages as dependencies,
# but some of those don't work out of the box.
#
# E.g if a QL package depends on cl-unicode it won't build out of
# the box.
commonLispPackagesFor = spec:
let
build-asdf-system' = body: build-asdf-system (body // spec);
in pkgs.callPackage ./packages.nix {
inherit spec quicklispPackagesFor;
build-asdf-system = build-asdf-system';
};
# Build the set of packages imported from quicklisp using `lisp`
quicklispPackagesFor = spec:
let
build-asdf-system' = body: build-asdf-system (body // spec);
in pkgs.callPackage ./ql.nix {
build-asdf-system = build-asdf-system';
};
# Creates a lisp wrapper with `packages` installed
#
# `packages` is a function that takes `clpkgs` - a set of lisp
# packages - as argument and returns the list of packages to be
# installed
# TODO(kasper): assert each package has the same lisp and asdf?
lispWithPackages = clpkgs: packages:
let first = head (lib.attrValues clpkgs); in
(build-asdf-system {
inherit (first) pkg program flags faslExt asdf;
# See dontUnpack in build-asdf-system
src = null;
pname = first.pkg.pname;
version = "with-packages";
lispLibs = packages clpkgs;
systems = [];
}).overrideAttrs(o: {
nativeBuildInputs = [ pkgs.makeBinaryWrapper ];
installPhase = ''
mkdir -pv $out/bin
makeWrapper \
${o.pkg}/bin/${o.program} \
$out/bin/${o.program} \
--add-flags "${o.flags}" \
--set ASDF "${o.asdfFasl}/asdf.${o.faslExt}" \
--prefix CL_SOURCE_REGISTRY : "$CL_SOURCE_REGISTRY" \
--prefix ASDF_OUTPUT_TRANSLATIONS : "$(echo $CL_SOURCE_REGISTRY | sed s,//:,::,g):" \
--prefix LD_LIBRARY_PATH : "$LD_LIBRARY_PATH" \
--prefix DYLD_LIBRARY_PATH : "$DYLD_LIBRARY_PATH" \
--prefix CLASSPATH : "$CLASSPATH" \
--prefix GI_TYPELIB_PATH : "$GI_TYPELIB_PATH" \
--prefix PATH : "${makeBinPath (o.propagatedBuildInputs or [])}"
'';
});
in {
inherit commonLispPackagesFor;
inherit lispWithPackages;
inherit build-asdf-system;
}

View File

@ -0,0 +1,502 @@
{ build-asdf-system, spec, quicklispPackagesFor, pkgs, ... }:
let
inherit (pkgs.lib)
head
makeLibraryPath
makeSearchPath
setAttr
hasAttr
optionals
hasSuffix
splitString
remove
;
# Used by builds that would otherwise attempt to write into storeDir.
#
# Will run build two times, keeping all files created during the
# first run, exept the FASL's. Then using that directory tree as the
# source of the second run.
#
# E.g. cl-unicode creating .txt files during compilation
build-with-compile-into-pwd = args:
let
build = (build-asdf-system (args // { version = args.version + "-build"; }))
.overrideAttrs(o: {
buildPhase = with builtins; ''
mkdir __fasls
export ASDF_OUTPUT_TRANSLATIONS="$(pwd):$(pwd)/__fasls:${storeDir}:${storeDir}"
export CL_SOURCE_REGISTRY=$CL_SOURCE_REGISTRY:$(pwd)//
${o.pkg}/bin/${o.program} ${o.flags or ""} < ${o.buildScript}
'';
installPhase = ''
mkdir -pv $out
rm -rf __fasls
cp -r * $out
'';
});
in build-asdf-system (args // {
# Patches are already applied in `build`
patches = [];
src = build;
});
# A little hacky
isJVM = spec.pkg.pname == "abcl";
# Makes it so packages imported from Quicklisp can be re-used as
# lispLibs ofpackages in this file.
ql = quicklispPackagesFor spec;
packages = ql.overrideScope' (self: super: {
cffi = let
jna = pkgs.fetchMavenArtifact {
groupId = "net.java.dev.jna";
artifactId = "jna";
version = "5.9.0";
sha256 = "0qbis8acv04fi902qzak1mbagqaxcsv2zyp7b8y4shs5nj0cgz7a";
};
in build-asdf-system {
src = pkgs.fetchzip {
url = "http://beta.quicklisp.org/archive/cffi/2021-04-11/cffi_0.24.1.tgz";
sha256 = "17ryim4xilb1rzxydfr7595dnhqkk02lmrbkqrkvi9091shi4cj3";
};
version = "0.24.1";
pname = "cffi";
lispLibs = with super; [
alexandria
babel
trivial-features
];
javaLibs = optionals isJVM [ jna ];
};
cffi-libffi = build-asdf-system {
inherit (super.cffi-libffi) pname version asds lispLibs nativeLibs nativeBuildInputs;
src = pkgs.fetchzip {
url = "https://github.com/cffi/cffi/archive/3f842b92ef808900bf20dae92c2d74232c2f6d3a.tar.gz";
sha256 = "1jilvmbbfrmb23j07lwmkbffc6r35wnvas5s4zjc84i856ccclm2";
};
};
cl-unicode = build-with-compile-into-pwd {
pname = "cl-unicode";
version = "0.1.6";
src = pkgs.fetchzip {
url = "https://github.com/edicl/cl-unicode/archive/refs/tags/v0.1.6.tar.gz";
sha256 = "0ykx2s9lqfl74p1px0ik3l2izd1fc9jd1b4ra68s5x34rvjy0hza";
};
systems = [ "cl-unicode" ];
lispLibs = with super; [
cl-ppcre
flexi-streams
];
};
jzon = build-asdf-system {
src = pkgs.fetchzip {
url = "https://github.com/Zulu-Inuoe/jzon/archive/6b201d4208ac3f9721c461105b282c94139bed29.tar.gz";
sha256 = "01d4a78pjb1amx5amdb966qwwk9vblysm1li94n3g26mxy5zc2k3";
};
version = "0.0.0-20210905-6b201d4208";
pname = "jzon";
lispLibs = [
super.closer-mop
];
systems = [ "com.inuoe.jzon" ];
};
cl-notify = build-asdf-system {
pname = "cl-notify";
version = "20080904-138ca7038";
src = pkgs.fetchzip {
url = "https://repo.or.cz/cl-notify.git/snapshot/138ca703861f4a1fbccbed557f92cf4d213668a1.tar.gz";
sha256 = "0k6ns6fzvjcbpsqgx85r4g5m25fvrdw9481i9vyabwym9q8bbqwx";
};
lispLibs = [
self.cffi
];
nativeLibs = [
pkgs.libnotify
];
};
cl-liballegro-nuklear = build-with-compile-into-pwd {
inherit (super.cl-liballegro-nuklear) pname version src;
nativeBuildInputs = [ pkgs.allegro5 ];
nativeLibs = [ pkgs.allegro5 ];
lispLibs = super.cl-liballegro-nuklear.lispLibs ++ [ super.cl-liballegro ];
patches = [ ./patches/cl-liballegro-nuklear-missing-dll.patch ];
};
tuple = build-asdf-system {
pname = "tuple";
version = "b74bd067d";
src = pkgs.fetchzip {
url = "https://fossil.galkowski.xyz/tuple/tarball/b74bd067d4533ac0/tuple.tar.gz";
sha256 = "0dk356vkv6kwwcmc3j08x7143549m94rd66rpkzq8zkb31cg2va8";
};
};
cl-tar-file = build-asdf-system {
pname = "cl-tar-file";
version = "v0.2.1";
src = pkgs.fetchzip {
url = let
rev = "0c10bc82f14702c97a26dc25ce075b5d3a2347d1";
in "https://gitlab.common-lisp.net/cl-tar/cl-tar-file/-/archive/${rev}/cl-tar-file-${rev}.tar.gz";
sha256 = "0i8j05fkgdqy4c4pqj0c68sh4s3klpx9kc5wp73qwzrl3xqd2svy";
};
lispLibs = with super; [
alexandria
babel
trivial-gray-streams
_40ants-doc
salza2
chipz
flexi-streams
parachute
];
systems = [ "tar-file" "tar-file/test" ];
};
cl-tar = build-asdf-system {
pname = "cl-tar";
version = "v0.2.1";
src = pkgs.fetchzip {
url = let
rev = "7c6e07a10c93d9e311f087b5f6328cddd481669a";
in "https://gitlab.common-lisp.net/cl-tar/cl-tar/-/archive/${rev}/cl-tar-${rev}.tar.gz";
sha256 = "0wp23cs3i6a89dibifiz6559la5nk58d1n17xvbxq4nrl8cqsllf";
};
lispLibs = with super; [
alexandria
babel
local-time
split-sequence
_40ants-doc
parachute
osicat
] ++ [ self.cl-tar-file ];
systems = [
"tar"
"tar/common-extract"
"tar/simple-extract"
"tar/extract"
"tar/create"
"tar/docs"
"tar/test"
"tar/create-test"
"tar/extract-test"
"tar/simple-extract-test"
];
};
lessp = build-asdf-system {
pname = "lessp";
version = "0.2-f8a9e4664";
src = pkgs.fetchzip {
url = "https://github.com/facts-db/cl-lessp/archive/632217602b85b679e8d420654a0aa39e798ca3b5.tar.gz";
sha256 = "0i3ia14dzqwjpygd0zn785ff5vqnnmkn75psfpyx0ni3jr71lkq9";
};
};
rollback = build-asdf-system {
pname = "rollback";
version = "0.1-5d3f21fda";
src = pkgs.fetchzip {
url = "https://github.com/facts-db/cl-rollback/archive/5d3f21fda8f04f35c5e9d20ee3b87db767915d15.tar.gz";
sha256 = "12dpxsbm2al633y87i8p784k2dn4bbskz6sl40v9f5ljjmjqjzxf";
};
};
facts = build-asdf-system {
pname = "facts";
version = "0.1-632217602";
src = pkgs.fetchzip {
url = "https://github.com/facts-db/cl-lessp/archive/632217602b85b679e8d420654a0aa39e798ca3b5.tar.gz";
sha256 = "09z1vwzjm7hlb529jl3hcjnfd11gh128lmdg51im7ar4jv4746iw";
};
lispLibs = [ self.lessp self.rollback ] ++ [ super.local-time ];
};
cl-fuse = build-with-compile-into-pwd {
inherit (super.cl-fuse) pname version src lispLibs;
nativeBuildInputs = [ pkgs.fuse ];
nativeLibs = [ pkgs.fuse ];
};
cl-containers = build-asdf-system {
inherit (super.cl-containers) pname version src;
lispLibs = super.cl-containers.lispLibs ++ [ super.moptilities ];
systems = [ "cl-containers" "cl-containers/with-moptilities" ];
};
swank = build-with-compile-into-pwd {
inherit (super.swank) pname version src lispLibs;
patches = [ ./patches/swank-pure-paths.patch ];
postConfigure = ''
substituteAllInPlace swank-loader.lisp
'';
};
clx-truetype = build-asdf-system {
pname = "clx-truetype";
version = "20160825-git";
src = pkgs.fetchzip {
url = "http://beta.quicklisp.org/archive/clx-truetype/2016-08-25/clx-truetype-20160825-git.tgz";
sha256 = "079hyp92cjkdfn6bhkxsrwnibiqbz4y4af6nl31lzw6nm91j5j37";
};
lispLibs = with super; [
alexandria bordeaux-threads cl-aa cl-fad cl-paths cl-paths-ttf
cl-store cl-vectors clx trivial-features zpb-ttf
];
};
mathkit = build-asdf-system {
inherit (super.mathkit) pname version src asds ;
lispLibs = super.mathkit.lispLibs ++ [ super.sb-cga ];
};
nyxt-gtk = build-asdf-system {
inherit (super.nyxt) pname;
version = "2.2.4";
lispLibs = super.nyxt.lispLibs ++ (with super; [
cl-cffi-gtk cl-webkit2 mk-string-metrics cl-css
]);
src = pkgs.fetchzip {
url = "https://github.com/atlas-engineer/nyxt/archive/2.2.4.tar.gz";
sha256 = "12l7ir3q29v06jx0zng5cvlbmap7p709ka3ik6x29lw334qshm9b";
};
buildInputs = [
pkgs.makeWrapper
# needed for GSETTINGS_SCHEMAS_PATH
pkgs.gsettings-desktop-schemas pkgs.glib pkgs.gtk3
# needed for XDG_ICON_DIRS
pkgs.gnome.adwaita-icon-theme
];
buildScript = pkgs.writeText "build-nyxt.lisp" ''
(load "${spec.asdf}")
(asdf:load-system :nyxt/gtk-application)
(sb-ext:save-lisp-and-die "nyxt" :executable t
#+sb-core-compression :compression
#+sb-core-compression t
:toplevel #'nyxt:entry-point)
'';
# Run with WEBKIT_FORCE_SANDBOX=0 if getting a runtime error
# See https://github.com/atlas-engineer/nyxt/issues/1781
# TODO(kasper): use wrapGAppsHook
installPhase = super.nyxt.installPhase + ''
rm -v $out/nyxt
mkdir -p $out/bin
cp -v nyxt $out/bin
wrapProgram $out/bin/nyxt \
--prefix LD_LIBRARY_PATH : $LD_LIBRARY_PATH \
--prefix XDG_DATA_DIRS : $XDG_ICON_DIRS \
--prefix XDG_DATA_DIRS : $GSETTINGS_SCHEMAS_PATH \
--prefix GIO_EXTRA_MODULES ":" ${pkgs.dconf.lib}/lib/gio/modules/ \
--prefix GIO_EXTRA_MODULES ":" ${pkgs.glib-networking}/lib/gio/modules/
'';
};
nyxt = self.nyxt-gtk;
ltk = super.ltk.overrideLispAttrs (o: {
src = pkgs.fetchzip {
url = "https://github.com/uthar/ltk/archive/f19162e76d6c7c2f51bd289b811d9ba20dd6555e.tar.gz";
sha256 = "0mzikv4abq9yqlj6dsji1wh34mjizr5prv6mvzzj29z1485fh1bj";
};
version = "f19162e76";
});
qt = let
rev = "dffff3ee3dbd0686c85c323f579b8bbf4881e60e";
in build-with-compile-into-pwd rec {
pname = "commonqt";
version = builtins.substring 0 7 rev;
src = pkgs.fetchFromGitHub {
inherit rev;
owner = pname;
repo = pname;
hash = "sha256-GAgwT0D9mIkYPTHfCH/KxxIv7b6QGwcxwZE7ehH5xug=";
};
buildInputs = [ pkgs.qt4 ];
nativeBuildInputs = [ pkgs.smokegen pkgs.smokeqt ];
nativeLibs = [ pkgs.qt4 pkgs.smokegen pkgs.smokeqt ];
systems = [ "qt" ];
lispLibs = with super; [
cffi named-readtables cl-ppcre alexandria
closer-mop iterate trivial-garbage bordeaux-threads
];
};
qt-libs = build-with-compile-into-pwd {
inherit (super.qt-libs) pname version src;
patches = [ ./patches/qt-libs-dont-download.patch ];
prePatch = ''
substituteInPlace systems/*.asd --replace ":qt+libs" ":qt"
'';
lispLibs = super.qt-libs.lispLibs ++ [ self.qt ];
systems = [
"qt-libs"
"commonqt"
# "phonon"
# "qimageblitz"
# "qsci"
"qt3support"
"qtcore"
"qtdbus"
"qtdeclarative"
"qtgui"
"qthelp"
"qtnetwork"
"qtopengl"
"qtscript"
"qtsql"
"qtsvg"
"qttest"
"qtuitools"
# "qtwebkit"
"qtxml"
"qtxmlpatterns"
# "qwt"
"smokebase"
];
};
commonqt = self.qt-libs;
qt3support = self.qt-libs;
qtcore = self.qt-libs;
qtdbus = self.qt-libs;
qtdeclarative = self.qt-libs;
qtgui = self.qt-libs;
qthelp = self.qt-libs;
qtnetwork = self.qt-libs;
qtopengl = self.qt-libs;
qtscript = self.qt-libs;
qtsql = self.qt-libs;
qtsvg = self.qt-libs;
qttest = self.qt-libs;
qtuitools = self.qt-libs;
qtxml = self.qt-libs;
qtxmlpatterns = self.qt-libs;
smokebase = self.qt-libs;
qtools = build-with-compile-into-pwd {
inherit (super.qtools) pname version src nativeLibs;
lispLibs = [ self.qt ] ++ remove super.qt_plus_libs super.qtools.lispLibs ++ [ self.qt-libs ];
patches = [ ./patches/qtools-use-nix-libs.patch ];
};
magicl = build-with-compile-into-pwd {
inherit (super.magicl) pname version src lispLibs;
nativeBuildInputs = [ pkgs.gfortran ];
nativeLibs = [ pkgs.openblas ];
patches = [ ./patches/magicl-dont-build-fortran-twice.patch ];
};
cl-gtk4 = build-asdf-system {
pname = "cl-gtk4";
version = "1.0.0";
src = pkgs.fetchFromGitHub {
owner = "bohonghuang";
repo = "cl-gtk4";
rev = "6e11b0d92ccf7cacee5c7f03d50148d68fe8e04d";
hash = "sha256-d/DYV1aQAir4mszsw1wEotxxBW9jGiFjELB04/PRBQ4=";
};
lispLibs = with super; [
cl-gobject-introspection-wrapper
cl-glib_dot_gio
];
nativeBuildInputs = [
pkgs.gobject-introspection
pkgs.gtk4
];
nativeLibs = [
pkgs.gtk4
];
};
cl-gtk4_dot_adw = build-asdf-system {
pname = "cl-gtk4.adw";
version = "1.0.0";
src = pkgs.fetchFromGitHub {
owner = "bohonghuang";
repo = "cl-gtk4";
rev = "6e11b0d92ccf7cacee5c7f03d50148d68fe8e04d";
hash = "sha256-d/DYV1aQAir4mszsw1wEotxxBW9jGiFjELB04/PRBQ4=";
};
lispLibs = with super; [
cl-gobject-introspection-wrapper
] ++ [ self.cl-gtk4 ];
nativeBuildInputs = [
pkgs.libadwaita
];
nativeLibs = [
pkgs.libadwaita
];
};
cl-gtk4_dot_webkit2 = build-asdf-system {
pname = "cl-gtk4.webkit2";
version = "1.0.0";
src = pkgs.fetchFromGitHub {
owner = "bohonghuang";
repo = "cl-gtk4";
rev = "6e11b0d92ccf7cacee5c7f03d50148d68fe8e04d";
hash = "sha256-d/DYV1aQAir4mszsw1wEotxxBW9jGiFjELB04/PRBQ4=";
};
lispLibs = with super; [
cl-gobject-introspection-wrapper
] ++ [ self.cl-gtk4 ];
nativeBuildInputs = [
pkgs.webkitgtk_5_0
];
nativeLibs = [
pkgs.webkitgtk_5_0
];
};
cl-avro = build-asdf-system {
pname = "cl-avro";
version = "trunk";
src = pkgs.fetchFromGitHub {
owner = "SahilKang";
repo = "cl-avro";
rev = "7d624253e98afb987a01729bd72c99bae02f0d7d";
hash = "sha256-AlTn+Q1gKnAFEfcnz9+VeHz681pPIirg2za3VXYiNWk=";
};
lispLibs = with super; [
alexandria
babel
chipz
closer-mop
ieee-floats
flexi-streams
local-time
local-time-duration
md5
salza2
st-json
time-interval
trivial-extensible-sequences
];
};
});
in packages

View File

@ -0,0 +1,16 @@
--- a/src/ffi/grovel/grovel-freetype.h
+++ b/src/ffi/grovel/grovel-freetype.h
@@ -2,7 +2,7 @@
#include <ft2build.h>
#include FT_FREETYPE_H
-#include <ftsystem.h>
-#include <fttypes.h>
-#include <ftlist.h>
-#include <ftimage.h>
+#include <freetype/ftsystem.h>
+#include <freetype/fttypes.h>
+#include <freetype/ftlist.h>
+#include <freetype/ftimage.h>
Diff finished. Mon Nov 14 22:41:57 2022

View File

@ -0,0 +1,17 @@
Fix system not loading due to:
Unhandled CFFI:LOAD-FOREIGN-LIBRARY-ERROR
Unable to load foreign library (LIBALLEGRO-NUKLEAR).
Error opening shared object "/build/source/src/liballegro_nuklear.so":
/build/source/src/liballegro_nuklear.so: undefined symbol: al_draw_ellipse.
--- a/cl-liballegro-nuklear.asd
+++ b/cl-liballegro-nuklear.asd
@@ -12,7 +12,7 @@
:description "CFFI wrapper for the Nuklear IM GUI library with liballegro backend, to be used with cl-liballegro."
:author "Andrew Kravchuk <awkravchuk@gmail.com>"
:license "MIT"
- :depends-on (:cffi :cffi-libffi :trivial-features)
+ :depends-on (:cl-liballegro :cffi :cffi-libffi :trivial-features)
:pathname "src"
:serial t
:components ((:makefile "Makefile")

View File

@ -0,0 +1,26 @@
From 2040fcab5a7be2f28add46a1412bef62ac5ccf11 Mon Sep 17 00:00:00 2001
From: Maximilian Marx <mmarx@wh2.tu-dresden.de>
Date: Thu, 24 Nov 2022 20:00:33 +0100
Subject: [PATCH] Use glucose binary from PATH if present
---
src/package.lisp | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/src/package.lisp b/src/package.lisp
index b6e26ac..bdb2581 100644
--- a/src/package.lisp
+++ b/src/package.lisp
@@ -13,7 +13,9 @@
(defvar *glucose-home* (asdf:system-relative-pathname :cl-sat.glucose "glucose-syrup/"))
(defun glucose-binary (&optional (*glucose-home* *glucose-home*))
- (merge-pathnames "simp/glucose_static" *glucose-home*))
+ (if (trivial-package-manager:which "glucose")
+ "glucose"
+ (merge-pathnames "simp/glucose_static" *glucose-home*)))
(defmethod solve ((input pathname) (solver (eql :glucose)) &rest options &key debug &allow-other-keys)
(remf options :debug)
--
2.36.2

View File

@ -0,0 +1,21 @@
--- a/magicl.asd
+++ b/magicl.asd
@@ -143,6 +143,7 @@
(shared-object (make-pathname :type #+darwin "dylib" #-darwin "so"
:name "libexpokit"
:defaults fortran-file)))
+ (unless (probe-file (nn shared-object))
(uiop:run-program
(list "gfortran" "-fPIC" "-std=legacy"
"-c"
@@ -155,7 +156,7 @@
(nn object-file)
#+darwin "-lblas"
#+darwin "-llapack"))
- (delete-file object-file))))
+ (delete-file object-file)))))
(asdf:defsystem #:magicl/ext-expokit
Diff finished. Mon Oct 10 22:03:54 2022

View File

@ -0,0 +1,36 @@
--- a/qt-libs.asd
+++ b/qt-libs.asd
@@ -17,5 +17,4 @@
:components ((:file "qt-libs"))
:depends-on (:qt-lib-generator
:cl-ppcre
- :cffi)
- :perform (asdf:load-op :after (op c) (uiop:symbol-call :qt-libs :ensure-standalone-libs)))
+ :cffi))
--- a/qt-libs.lisp
+++ b/qt-libs.lisp
@@ -94,16 +94,14 @@
standalone-dir)
(defun %ensure-lib-loaded (file)
- (let ((file (etypecase file
- (pathname file)
- (string (installed-library-file file))))
- (name (intern (string-upcase (pathname-name file))))
- #+sbcl(sb-ext:*muffled-warnings* 'style-warning))
- (cffi::register-foreign-library
- name `((T ,file))
- :search-path (to-directory file))
- (unless (cffi:foreign-library-loaded-p name)
- (cffi:load-foreign-library name))))
+ (let ((name (make-pathname :name (format nil "lib~a" file)
+ :type #+unix "so"
+ #+darwin "dylib")))
+ (or (find-if (lambda (lib)
+ (equal (cffi:foreign-library-pathname lib)
+ (namestring name)))
+ (cffi:list-foreign-libraries))
+ (cffi:load-foreign-library name))))
(defun ensure-lib-loaded (file)
(cond ((pathnamep file)

View File

@ -0,0 +1,19 @@
Dont use the qt+libs system for managing Qt dependencies, because Nix provides
them already.
Don't build the deploy.lisp helper file, because Nix also can handle deployment.
--- a/qtools.asd
+++ b/qtools.asd
@@ -33,10 +33,9 @@
(:file "generate")
(:file "dynamic")
(:file "precompile")
- (:file "deploy")
(:file "fast-call")
(:file "documentation"))
- :depends-on (:qt+libs
+ :depends-on (:qt
:deploy
:cl-ppcre
:closer-mop
Diff finished. Sun Oct 2 14:38:06 2022

View File

@ -0,0 +1,28 @@
Prevent swank from attempting write into storeDir
--- a/swank-loader.lisp
+++ b/swank-loader.lisp
@@ -162,7 +162,7 @@
,(unique-dir-name)))
(user-homedir-pathname)))
-(defvar *fasl-directory* (default-fasl-dir)
+(defvar *fasl-directory* #P"@out@/fasl/"
"The directory where fasl files should be placed.")
(defun binary-pathname (src-pathname binary-dir)
@@ -284,12 +284,7 @@
(contrib-dir src-dir))))
(defun delete-stale-contrib-fasl-files (swank-files contrib-files fasl-dir)
- (let ((newest (reduce #'max (mapcar #'file-write-date swank-files))))
- (dolist (src contrib-files)
- (let ((fasl (binary-pathname src fasl-dir)))
- (when (and (probe-file fasl)
- (<= (file-write-date fasl) newest))
- (delete-file fasl))))))
+ (declare (ignore swank-files contrib-files fasl-dir)))
(defun compile-contribs (&key (src-dir (contrib-dir *source-directory*))
(fasl-dir (contrib-dir *fasl-directory*))
Diff finished. Sat Jan 22 23:57:27 2022

View File

@ -0,0 +1,6 @@
(load (sb-ext:posix-getenv "ASDF"))
(pushnew (truename "./import") asdf:*central-registry*)
(asdf:load-system :org.lispbuilds.nix)
(load "./import/main.lisp")
(org.lispbuilds.nix/main::main)

View File

@ -0,0 +1,206 @@
{ pkgs, lib, build-asdf-system, ... }:
let
# FIXME: automatically add nativeLibs based on conditions signalled
overrides = (self: super: {
cl_plus_ssl = super.cl_plus_ssl.overrideLispAttrs (o: {
nativeLibs = [ pkgs.openssl ];
});
cl-cffi-gtk-glib = super.cl-cffi-gtk-glib.overrideLispAttrs (o: {
nativeLibs = [ pkgs.glib ];
});
cl-cffi-gtk-cairo = super.cl-cffi-gtk-cairo.overrideLispAttrs (o: {
nativeLibs = [ pkgs.cairo ];
});
cl-cairo2 = super.cl-cairo2.overrideLispAttrs (o: {
nativeLibs = [ pkgs.cairo ];
});
cl-cairo2-xlib = super.cl-cairo2-xlib.overrideLispAttrs (o: {
nativeLibs = [ pkgs.gtk2-x11 ];
});
cl-freeimage = super.cl-freeimage.overrideLispAttrs (o: {
nativeLibs = [ pkgs.freeimage ];
});
cl-freetype2 = super.cl-freetype2.overrideLispAttrs (o: {
nativeLibs = [ pkgs.freetype ];
nativeBuildInputs = [ pkgs.freetype ];
patches = [ ./patches/cl-freetype2-fix-grovel-includes.patch ];
});
cl-pango = super.cl-pango.overrideLispAttrs (o: {
nativeLibs = [ pkgs.pango ];
});
cl-gtk2-gdk = super.cl-gtk2-gdk.overrideLispAttrs (o: {
nativeLibs = [ pkgs.gtk2-x11 ];
});
cl-gtk2-glib = super.cl-gtk2-glib.overrideLispAttrs (o: {
nativeLibs = [ pkgs.glib ];
});
cl-gtk2-pango = super.cl-gtk2-pango.overrideLispAttrs (o: {
nativeLibs = [ pkgs.pango ];
});
cl-rsvg2 = super.cl-rsvg2.overrideLispAttrs (o: {
nativeLibs = [ pkgs.librsvg ];
});
cl-cffi-gtk-gdk = super.cl-cffi-gtk-gdk.overrideLispAttrs (o: {
nativeLibs = [ pkgs.gtk3 ];
});
cl-cffi-gtk-gdk-pixbuf = super.cl-cffi-gtk-gdk-pixbuf.overrideLispAttrs (o: {
nativeLibs = [ pkgs.gdk-pixbuf ];
});
cl-cffi-gtk-pango = super.cl-cffi-gtk-pango.overrideLispAttrs (o: {
nativeLibs = [ pkgs.pango ];
});
cl-gobject-introspection = super.cl-gobject-introspection.overrideLispAttrs (o: {
nativeLibs = [ pkgs.glib pkgs.gobject-introspection ];
});
cl-mysql = super.cl-mysql.overrideLispAttrs (o: {
nativeLibs = [ pkgs.mysql-client ];
});
clsql-postgresql = super.clsql-postgresql.overrideLispAttrs (o: {
nativeLibs = [ pkgs.postgresql.lib ];
});
clsql-sqlite3 = super.clsql-sqlite3.overrideLispAttrs (o: {
nativeLibs = [ pkgs.sqlite ];
});
cl-webkit2 = super.cl-webkit2.overrideLispAttrs (o: {
nativeLibs = [ pkgs.webkitgtk ];
});
dbd-mysql = super.dbd-mysql.overrideLispAttrs (o: {
nativeLibs = [ pkgs.mysql-client ];
});
lla = super.lla.overrideLispAttrs (o: {
nativeLibs = [ pkgs.openblas ];
});
cffi-libffi = super.cffi-libffi.overrideLispAttrs (o: {
nativeBuildInputs = [ pkgs.libffi ];
nativeLibs = [ pkgs.libffi ];
});
cl-rabbit = super.cl-rabbit.overrideLispAttrs (o: {
nativeBuildInputs = [ pkgs.rabbitmq-c ];
nativeLibs = [ pkgs.rabbitmq-c ];
});
trivial-ssh-libssh2 = super.trivial-ssh-libssh2.overrideLispAttrs (o: {
nativeLibs = [ pkgs.libssh2 ];
});
sqlite = super.sqlite.overrideLispAttrs (o: {
nativeLibs = [ pkgs.sqlite ];
});
cl-libuv = super.cl-libuv.overrideLispAttrs (o: {
nativeBuildInputs = [ pkgs.libuv ];
nativeLibs = [ pkgs.libuv ];
});
cl-liballegro = super.cl-liballegro.overrideLispAttrs (o: {
nativeLibs = [ pkgs.allegro5 ];
});
cl-ode = super.cl-ode.overrideLispAttrs (o: {
nativeLibs = let
ode' = pkgs.ode.overrideAttrs (o: {
configureFlags = [
"--enable-shared"
"--enable-double-precision"
];
});
in [ ode' ];
});
classimp = super.classimp.overrideLispAttrs (o: {
nativeLibs = [ pkgs.assimp ];
});
sdl2 = super.sdl2.overrideLispAttrs (o: {
nativeLibs = [ pkgs.SDL2 ];
});
lispbuilder-sdl-cffi = super.lispbuilder-sdl-cffi.overrideLispAttrs (o: {
nativeLibs = [ pkgs.SDL ];
});
cl-opengl = super.cl-opengl.overrideLispAttrs (o: {
nativeLibs = [ pkgs.libGL ];
});
cl-glu = super.cl-glu.overrideLispAttrs (o: {
nativeLibs = [ pkgs.libGLU ];
});
cl-glut = super.cl-glut.overrideLispAttrs (o: {
nativeLibs = [ pkgs.freeglut ];
});
cl-glfw = super.cl-glfw.overrideLispAttrs (o: {
nativeLibs = [ pkgs.glfw ];
});
cl-glfw-opengl-core = super.cl-glfw-opengl-core.overrideLispAttrs (o: {
nativeLibs = [ pkgs.libGL ];
});
cl-glfw3 = super.cl-glfw3.overrideLispAttrs (o: {
nativeLibs = [ pkgs.glfw ];
});
lev = super.lev.overrideLispAttrs (o: {
nativeLibs = [ pkgs.libev ];
});
cl-rdkafka = super.cl-rdkafka.overrideLispAttrs (o: {
nativeBuildInputs = [ pkgs.rdkafka ];
nativeLibs = [ pkgs.rdkafka ];
});
cl-async-ssl = super.cl-async-ssl.overrideLispAttrs (o: {
nativeLibs = [ pkgs.openssl ];
});
iolib = super.iolib.overrideLispAttrs (o: {
nativeBuildInputs = [ pkgs.libfixposix ];
nativeLibs = [ pkgs.libfixposix ];
systems = [ "iolib" "iolib/os" "iolib/pathnames" ];
});
cl-ana_dot_hdf-cffi = super.cl-ana_dot_hdf-cffi.overrideLispAttrs (o: {
nativeBuildInputs = [ pkgs.hdf5 ];
nativeLibs = [ pkgs.hdf5 ];
NIX_LDFLAGS = [ "-lhdf5" ];
});
gsll = super.gsll.overrideLispAttrs (o: {
nativeBuildInputs = [ pkgs.gsl ];
nativeLibs = [ pkgs.gsl ];
});
cl-libyaml = super.cl-libyaml.overrideLispAttrs (o: {
nativeLibs = [ pkgs.libyaml ];
});
cl-libxml2 = super.cl-libxml2.overrideLispAttrs (o: {
nativeLibs = [ pkgs.libxml2 ];
});
cl-readline = super.cl-readline.overrideLispAttrs (o: {
nativeLibs = [ pkgs.readline ];
});
md5 = super.md5.overrideLispAttrs (o: {
lispLibs = [ super.flexi-streams ];
});
pzmq = super.pzmq.overrideLispAttrs (o: {
nativeBuildInputs = [ pkgs.zeromq ];
nativeLibs = [ pkgs.zeromq ];
});
pzmq-compat = super.pzmq-compat.overrideLispAttrs (o: {
nativeBuildInputs = [ pkgs.zeromq ];
nativeLibs = [ pkgs.zeromq ];
});
pzmq-examples = super.pzmq-examples.overrideLispAttrs (o: {
nativeBuildInputs = [ pkgs.zeromq ];
nativeLibs = [ pkgs.zeromq ];
});
pzmq-test = super.pzmq-test.overrideLispAttrs (o: {
nativeBuildInputs = [ pkgs.zeromq ];
nativeLibs = [ pkgs.zeromq ];
});
cl-git = super.cl-git.overrideLispAttrs (o: {
nativeLibs = [ pkgs.libgit2 ];
});
trivial-package-manager = super.trivial-package-manager.overrideLispAttrs (o: {
propagatedBuildInputs = [ pkgs.which ];
});
cl-sat_dot_glucose = super.cl-sat_dot_glucose.overrideLispAttrs (o: {
propagatedBuildInputs = [ pkgs.glucose ];
patches = [ ./patches/cl-sat-binary-from-path.patch ];
});
cl-sat_dot_minisat = super.cl-sat_dot_minisat.overrideLispAttrs (o: {
propagatedBuildInputs = [ pkgs.minisat ];
});
});
qlpkgs =
if builtins.pathExists ./imported.nix
then pkgs.callPackage ./imported.nix { inherit build-asdf-system; }
else {};
in qlpkgs.overrideScope' overrides

View File

@ -0,0 +1,56 @@
# This setup hook adds every propagated lisp system to CL_SOURCE_REGISTRY
buildAsdfPath () {
declare -A seen=()
for dep in $propagatedBuildInputs; do
_addToAsdfPath $dep
done
}
addFileToSearchPathWithCustomDelimiter() {
local delimiter="$1"
local varName="$2"
local file="$3"
if [[ -f "$file" && "${!varName:+${delimiter}${!varName}${delimiter}}" \
!= *"${delimiter}${file}${delimiter}"* ]]; then
export "${varName}=${!varName:+${!varName}${delimiter}}${file}"
fi
}
addFileToSearchPath() {
addFileToSearchPathWithCustomDelimiter ":" "$@"
}
_addToAsdfPath () {
local dep="$1"
if [ -v seen[$dep] ]; then
return
else
seen[$dep]=1
local path="$dep"
# FIXME slow
while read file; do
case "${file##*.}" in
jar) addFileToSearchPath "CLASSPATH" "$file" ;;
class) addToSearchPath "CLASSPATH" "${file%/*}" ;;
so) addToSearchPath "LD_LIBRARY_PATH" "${file%/*}" ;;
dylib) addToSearchPath "DYLD_LIBRARY_PATH" "${file%/*}" ;;
asd) addToSearchPath "CL_SOURCE_REGISTRY" "$path//" ;;
esac
done < <(find "$path" -type f,l -name '*.asd' -o -name '*.jar' \
-o -name '*.class' -o -name '*.so' -o -name '*.dylib')
local prop="$dep/nix-support/propagated-build-inputs"
if [ -e "$prop" ]; then
local new_system
for new_system in $(cat $prop); do
_addToAsdfPath "$new_system"
done
fi
fi
}
# addEnvHooks "$targetOffset" buildAsdfPath

View File

@ -0,0 +1,16 @@
let
pkgs = import ../../../. {};
in pkgs.mkShell {
nativeBuildInputs = [
(pkgs.sbcl.withPackages
(ps: with ps; [
alexandria
str
dexador
cl-ppcre
sqlite
arrow-macros
jzon
]))
];
}