build.tools.nix/mkClojureLib.nix

97 lines
2.6 KiB
Nix

{ lib, stdenv, callPackage, clojure, jre, writeText, writeShellScript, toEDN }:
{ src, name, group, version, clj-deps, src-paths, ... }:
with lib;
let
classpath = clj-deps.makeClasspaths { };
deps-jars = splitString ":" classpath;
full-name = "${name}-${version}-standalone";
manifest = writeText "MANIFEST.MF" ''
Manifest-Version: 1.0
'';
extract-jar = jar: ''
echo jar -xf ${jar}
jar -xf ${jar}
'';
clj-compile = classpath: ns: ''
echo java -cp .:${classpath} clojure.main -e "(compile ${ns})"
java -cp .:${classpath} clojure.main -e "(compile ${ns})"
'';
matches-ext = ext: filename: (builtins.match ".+[.]${ext}$" filename) != null;
strip-ext = ext: filename:
builtins.head (builtins.match "(.+)[.]${ext}$" filename);
concatMapAttrs = f: attrs: concatLists (mapAttrsToList f attrs);
find-files = pred: path:
let
find-files-impl = base:
concatMapAttrs (handle-file base) (builtins.readDir base);
handle-file = base: name: type:
if (type == "directory") then
find-files-impl "${base}/${name}"
else
(if (pred name) then [ "${base}/${name}" ] else [ ]);
in find-files-impl path;
file-to-namespace = base: filename:
let
swap-chars = replaceStrings [ "_" "/" ] [ "-" "." ];
strip-clj = strip-ext "clj";
strip-base = replaceStrings [ "${base}/" ] [ "" ];
ns = swap-chars (strip-base (strip-clj (toString filename)));
in "'${ns}";
target-namespaces = concatMap (subdir:
let dir = src + "/${subdir}";
in map (file-to-namespace dir) (find-files (matches-ext "clj") dir))
src-paths;
copy-source-path = target: subdir: "cp -R ${src}/${subdir}/* ${target}";
build-script = let
join-lines = concatStringsSep "\n";
srcs = concatStringsSep ":" (map (path: "./${path}") src-paths);
in writeShellScript "create-${full-name}-uberjar.sh" ''
HOME=./home
mkdir $HOME
mkdir classes
mkdir ./deps
cd ./deps
${join-lines (map extract-jar deps-jars)}
cd ..
${join-lines
(map (clj-compile "${classpath}:${srcs}:./deps") target-namespaces)}
mkdir target
cp -R classes/* target/
${join-lines (map (copy-source-path "./target/") src-paths)}
cp -R deps/* target/
cp ./deps.edn ./target/deps.edn
cd target
jar cmf ${manifest} ../out.jar -C . ./*
'';
pthru = o: builtins.trace o o;
in stdenv.mkDerivation {
name = "${full-name}.jar";
src = src;
nativeBuildInputs = [ jre ];
buildInputs = map (x: x.paths) clj-deps.packages;
buildPhase = "${build-script}";
installPhase = ''
mv out.jar $out
'';
}