Awesome
sbt2nix
Stop Here!
See https://github.com/teozkr/Sbtix for a more recent SBT Nix project that is being actively worked on.
Generate Nix build instructions from a SBT project
Warning
This is (currently) an experimental project to force myself (and hopefully others) to get cracking on building a set of tools for generating and consuming Nix expressions for Scala (and Java by extension, but who cares). It shouldn't be that hard (in theory).
SBT Plugin - Experimental
Running
Firstly build and publish this project with the usual sbt publishLocal
.
Then add the following to your project/plugins.sbt
:
addSbtPlugin("sbt2nix" % "sbt2nix" % "0.1.0-SNAPSHOT")
Run the following to generate a series of nix
files for each module (see below).
$ sbt nix
Once that's done, to build everything with nix
:
$ nix-build
Or specific modules:
$ nix-build -A foo
The result should be a jar in result/share/java/$name.jar
.
Ideally we would like to symlink the dependent jars and add an SBT resolver to enable nix-shell
to bootstrap sbt
.
Output
In the top-level aggregate project (if you have one) there will be a default.nix
:
{ sbt ? import ./sbt.nix {}, deps ? import ./deps.nix { inherit sbt; } }:
{
foo = sbt.callPackage ./my-foo {};
bar = sbt.callPackage ./my-bar {};
}
In each module there is a default.nix
:
{ sbt ? import ../sbt.nix {}, deps ? import ../deps.nix { inherit sbt; } }:
let
bar = import ../bar { inherit sbt; };
in sbt.mkDerivation {
pname = "my-foo";
version = "0.1.0-SNAPSHOT";
src = ./.;
sources = [ ./src/main/scala ];
modules = [ bar ];
scalacOptions = "";
buildDepends = [
deps.commons-io_commons-io_2_4
];
meta = {
description = "my-foo";
};
}
And lastly a single deps.nix
will be generated:
{ sbt }:
{
commons-io_commons-io_2_4 = sbt.artifact {
org = "commons-io";
jarname = "commons-io";
version = "2.4";
sha256 = "108mw2v8ncig29kjvzh8wi76plr01f4x5l3b1929xk5a7vf42snc";
};
}
Also, a utility sbt.nix
will be extracted from the plugin and placed in the root.
Why Nix?
Build tools should use a build cache, emphasis on the cache, for propagating results from one component to another. A cache is an abstraction that allows computing a function more quickly based on partial results computed in the past. The function, in this case, is for turning source code into a binary.
A cache does nothing except speed things up. You could remove a cache entirely and the surrounding system would work the same, just more slowly. A cache has no side effects, either. No matter what you've done with a cache in the past, a given query to the cache will give back the same value to the same query in the future.
From Lex Spoon's Recursive Maven Considered Harmful, which I discovered while reading the excellent Ultimate Build Tool. This is a good post on using Nix for Haskell development. And finally my own little rant.
Help wanted
We need you! Come and chat on Freenode ##nix-sbt
if you want to know more.
See the list of Issues for an overview on what needs to happen.
The current code is something hacked together in roughly a day, so please don't judge it too harshly. The important thing at the moment is the generated Nix output, which will need to be improved in a number of ways, as outlined in various issues. If you have any experience in Nix, your input and suggestions on what we needs to happen will be much appreciated.