Maintained/usable tooling for building Clojure projects in Nix?

I’m trying to understand how to build Clojure projects in Nix. There are two major build tools in the Clojure world – Leiningen and Boot. Both support Maven-style dependency resolution and download – and Boot is actually distributed as a bootstrap tool that downloads Boot itself from public Maven repositories, and expects to find its own jars in the user’s Maven cache in their home directory.

Somewhat disturbingly, the Nixpkgs package for Boot distributes that bootstrap tool only, and does not include Boot itself; consequently, it cannot be used from any sandboxed environment such as nixbld (unless one creates a home directory with a local Maven cache and populates it with the jar for the actual version of Boot that project is configured to use).

Nixpkgs includes buildMaven, which attempts to build a repository with all JARs specified for a given pom.xml. This depends on a Maven plugin generating a JSON file describing the set of jars and their download locations; a nix2mvn Maven plugin is used to generate this file. However – pending merge of NixOS/mvn2nix-maven-plugin#18 – that plugin doesn’t correctly handle pom.xml files with trailing /s in repository locations (as created by Leiningen – POMs from Boot don’t have this issue). It also appears not to be able to find URLs for artifacts which are in its own runtime environment..

There also exists a boot2nix tool, “a Boot task to generate Nix expressions”. However, even when configured with a repository URL and able to resolve to the coordinates of same, it’s unable to find download URLs of some publicly-available artifacts – notably including [com.googlecode/jsendnsca-core "1.3.1"] (which is canonically located in Red Hat’s Maven repository, rather than Maven Central). Its maintainership would welcome a PR for this, but I’ve yet to be able to run down a root cause for the issue.

As a Clojure-centric alternative to depending on the mvn2nix Maven plugin, dwn is another project which appears promising (having a full README and a clean set of bindings to the underlying “Aether” / “Apache Maven Resolver” library used by Leiningen, Boot and Maven to resolve and download dependencies); however, even when updated to use the very latest version of that library, it’s unable to find URLs for the same projects for which boot2nix fails above. (dwn also gives a distinct impression of being a work-in-progress; some components are very usable as-is, but other namespaces don’t even compile/load).

Have other folks trod this ground? Is there any consensus around production-ready tooling?


To run over the projects discussed above once more, in more condensed form:

  • <nixpkgs>.buildMaven - Depends on mvn2nix to build a JSON description of build artifact sources; latter misses some packages (ones overlapping its own dependency chain?)
  • boot2nix - Misses a different set of packages (jsendnsca-core).
  • dwn - successor to lein-nix; contains an independently-written Aether wrapper in Clojure; misses the same packages as boot2nix.
1 Like

Issue 19741 “Maven builds are not documented in nixpgs manual” has some discussion of the shortcomings of mvn2nix and a shell script alternative.

There are definitely some rough edges around Java build tooling that could use some TLC. :-/

1 Like

Checkout GitHub - fzakaria/mvn2nix: Easily package your Maven Java application with the Nix package manager. @charles-dyfis-net @Jerith
I’ve included an example that works the pom.xml generated by leiningen

3 Likes

Thanks @fzakaria

Yesterday I was working on clj-new on clojure latest version problem, so I am using it by replacing homebrew.
And Currently clj-new seems to create pom.xml.
And Sadly,
the installation method is different with clj2nix, so I do not know how to add derivation to config.nix at clj2nix.
.
How do I add it as pom.xml with mvn2nix?

clj2nix works by generating a new nix file from deps.edn. So you pass deps.edn and get back from the clj2nix-cli a new file (ex. depx.nix), and that file you import into your nix build routine to create the classpaths needed to build a given clojure project. I would recommend a clojure development workflow of using tools.deps.alpha and deploy the project using clj2nix and your default.nix (the name “default” is irrelevant).

1 Like

@PlumpMath I just finished landing documentation: add documentation for buildMaven by fzakaria · Pull Request #100660 · NixOS/nixpkgs · GitHub which is documentation on how to use mvn2nix

It’s not yet live on the nixpkgs documentation portal but you can read it here:

1 Like

Thank you @fzakaria @hlolli very much.
clj2nix has tried changing jar files before. I was just curious about the creation of a single project that runs the clojure main right away with a nix code for .m2 to nixStore. (reference nixpkgs previous code…)

likely

    deps_nix = import ~/clj2nix-example-proj/deps.nix { inherit pkgs; };
    
    Fmod-makePaths = {extraClasspaths ? []}: (builtins.map (dep: if builtins.hasAttr "jar" dep.path then dep.path.jar else dep.path) deps_nix.packages) ++ extraClasspaths;
    
    Fmod-makeClasspaths = { extraClasspaths ? []}: builtins.concatStringsSep ":" (Fmod-makePaths {inherit extraClasspaths;});
    
    M2 = Fmod-makeClasspaths {  extraClasspaths = [ "${jython}/jython.jar" ];  };

and

    JAR = (mkDerivation rec{ #
    name = "JAR";
    phases = [ "installPhase" ];
    buildInputs = [ makeWrapper ];
    installPhase = ''
      mkdir -p $out/lib/JAR
      export IFS=":"
      for t in ${M2}; do
      ln -sf $t $out/lib/JAR/
      done
    '';
    });

I’ve been collecting maven and jar files like this before, but I don’t know how java loads modules; I don’t know maven etc… (and more in the nix method),
but one years ago, I’ve given up using them because of a new clojure project where a conflict this method.

Maybe I think by using mvn2ix, you’ll get a cleaner code than the one above. Currently, I am interested in linking various languages with nix, packaging, and linking them. (Such desired shape where the original nix exists
((clojure → java, java → clojure)-> other language and reverse )

Thank you so much. Have a nice day.

Should the link rather be example ?

1 Like

Hmmm ~ :^)

I don’t think it’s necessary to raise the Cider Refactor to me. but clj-kondo export ?
If that’s the library dependency version path.
Isn’t it the core of the story coming and going in the this thread?
Because before, it seemed like the reason I couldn’t replace only a specific partial jar version that conflict problem(dependency)
Jar hell doesn’t look as good as Dll hell

https://github.com/hlolli/clj2nix/issues/10

Thanks. ^^
I’m wish to help us with something but I only know about github clone push and issues. I’m always sorry about that. If I knew you’d do PR…
Especially, I wanted to solve the problem of the latest version of clojure in the darwin version of nixpkgs, but I gave up because it was too complicated.
(Clj-new doesn’t work in the current version of the nixpkgs darwin)
But if you mention it a little bit like this. Like mvn2nix uncle said… Someday we’ll make it.
(I will write here if when I find how to fixed reference from master nixpkgs~ )

https://github.com/NixOS/nixpkgs/pull/103759

nixpkgs-20.09-darwin
PR…

It’s my first time doing %PR.
(It’s an honor that my GitHub PR is the first to be involved in the Clojure of the Nixpkgs. I can’t forget it.
But I’m an Emax user and I want to do it with a magit. hehehe
It’s easy to %PR with github web page.
I don’t know where to learn PR. It’s too difficult for a novice developer.)

to the point again…
Now “cli-new” works well in Nixpkgs’ clojure, not relying on homebrew clojure.

one thing
We don’t have a Linux system, so I don’t know if we need to fix your version 727.
Darwin Clojure-tools.tar.gz Binary at install.sh. (By directly releasing the compression.)

can override it manually. that like it.
I don’t know how to github “PR” with all the nixpkgs.
There are many problems if you use the clojure in the current nixpkgs.