diff --git a/build.tools.nix b/build.tools.nix index 56f0c9a..5cab635 100644 --- a/build.tools.nix +++ b/build.tools.nix @@ -21,7 +21,6 @@ let echo "building namespace: ${ns}"... java -cp .:${classpath} clojure.main -e "(compile ${ns})" ''; - head-or-null = lst: if (lst == [ ]) then null else head lst; matches-ext = ext: filename: (builtins.match ".+[.]${ext}$" filename) != null; strip-ext = ext: filename: head-or-null (builtins.match "(.+)[.]${ext}$" filename); diff --git a/mkClojureLib.nix b/mkClojureLib.nix index 5fd41d9..abe2eed 100644 --- a/mkClojureLib.nix +++ b/mkClojureLib.nix @@ -1,58 +1,96 @@ { lib, stdenv, callPackage, clojure, jre, writeText, writeShellScript, toEDN }: -{ src, name, group, version, deps-edn, clj-deps, src-paths, build-tools-jar, ... -}: +{ src, name, group, version, clj-deps, src-paths, ... }: with lib; let - build-tools-deps = toEDN { - aliases.build = { - extra-deps."'io.github.clojure/tools.build"."local/root" = - ''\"${build-tools-jar}\"''; - }; - }; - classpath = clj-deps.makeClasspaths { }; + deps-jars = splitString ":" classpath; - build-deps = callPackage ./deps.nix { }; - build-classpath = build-deps.makeClasspaths { }; + full-name = "${name}-${version}-standalone"; - full-name = "${name}-${version}-standalone.jar"; + manifest = writeText "MANIFEST.MF" '' + Manifest-Version: 1.0 - target = "$TEMP/target"; + ''; - build-script = writeShellScript "create-uberjar.sh" '' - HOME=$TEMP/home - mkdir -p $HOME - mkdir -p ${target} + extract-jar = jar: '' + echo jar -xf ${jar} + jar -xf ${jar} + ''; - clojure \ - -Scp ${build-classpath}:${classpath}:${build-tools-jar}:. \ - -Sdeps "${build-tools-deps}" \ - -X:build \ - build/lib-uberjar \ - :project ${group}/${name} \ - :version ${version} \ - :src-dirs ${concatStringsSep "," src-paths} \ - :target '"${target}"' \ - :deps-edn '"${deps-edn}"' + clj-compile = classpath: ns: '' + echo java -cp .:${classpath} clojure.main -e "(compile ${ns})" + java -cp .:${classpath} clojure.main -e "(compile ${ns})" + ''; - [ $? -eq 0 ] || cat /tmp/*.edn + 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; + name = "${full-name}.jar"; src = src; - nativeBuildInputs = [ clojure jre ]; - buildInputs = (map (x: x.paths) clj-deps.packages) - ++ (map (x: x.paths) build-deps.packages); + nativeBuildInputs = [ jre ]; + buildInputs = map (x: x.paths) clj-deps.packages; - buildPhase = pthru "${build-script}"; + buildPhase = "${build-script}"; installPhase = '' - mv ${target}/${name}-${version}-standalone.jar $out + mv out.jar $out ''; }