Creating a Build
Generated compositions, builders, and local dependencies
Creating a build
For generated composition builds, run
sbtix genComposition(orsbt genCompositioninside your project) to have sbtix emitsbtix-generated.nixfor you. The file is rendered from the same template used in our tests, so it already contains the sandbox-friendlySBT_OPTS, Ivy generation, and install logic. Check it in as-is and have yourdefault.nix(or another entry point) simply import it.For flake-native or custom builds, call the helper functions from your flake input instead of importing the generated composition. Use
buildSbtProgramfor projects with astagetask,buildSbtLibraryfor libraries, orbuildSbtProjectwhen you need a custominstallPhase. In this flow, the generatedrepo.nixfiles are the source-control lockfiles;sbtix-generated.nix,sbtix.nix, andsbtix-plugin-repo.nixare not required unless your build imports them.
If you want a starting point, copy default.nix.example from this repository into your project. It simply imports the generated composition:
{ pkgs ? import <nixpkgs> {} }:
import ./sbtix-generated.nix { inherit pkgs; }
The root-level default.nix now just raises an error so it no longer looks like part of the build. If you need to hand-roll the derivation instead, use the lower-level API directly:
{ pkgs ? import <nixpkgs> {} }: with pkgs;
let
sbtixDir = fetchFromGitHub {
owner = "natural-transformation";
repo = "sbtix";
rev = "<<current git rev>>"; # Replace as needed
sha256 = "<<<corresponding sha256 hash>>>"; # Replace as needed
};
sbtix = pkgs.callPackage "${sbtixDir}/plugin/nix-exprs/sbtix.nix" {};
in
sbtix.buildSbtProgram {
name = "sbtix-example";
src = pkgs.lib.cleanSource ./.;
repo = [ (import ./manual-repo.nix)
(import ./repo.nix)
(import ./project/repo.nix)
];
}
generate your repo.nix files with one of the commands listed above.
if you use the generated composition path, rerun
sbtix genCompositionafter changing dependencies to regeneratesbtix-generated.nixso it stays in sync with both the template and the sbtix revision you are using.check the generated nix files that your build imports into your source control.
finally, run
nix-buildfor generated composition builds ornix build .#...for flake-native builds.any additional missing dependencies that
nix-buildencounters should be fetched withnix-prefetch-urland added tomanual-repo.nix.
Keeping nix files separate from the project sources
In some cases, it can be preferable to keep the nix packaging definitions separate from the project being packaged. In that case, move the .nix files elsewhere, and point the src attribute to the location that contains the Scala project.
You're free to choose any filenames and directory layout, as long as you make sure you update the references from default.nix to the generated repo files. When re-generating the files, you'll still have to run sbtix-gen from the library directory (and temporarily copy your sbtix-build-inputs.nix there if you use that), then move the generated files to your custom location again.
Project Types
Libraries and programs need to be "installed" in different ways. Sbtix currently knows how to install "programs" and Maven-style libraries. The project type is selected by the builder function you use. Use sbtix.buildSbtProgram for building programs, and sbtix.buildSbtLibrary.
There is also sbtix.buildSbtProject, which allows you to define a custom Nix installPhase.
Programs
Programs must have a stage task, and it is assumed that calling this task will put its output in target/universal/stage. This folder is then copied to be the Nix build output.
This is generally fulfilled by SBT-Native-Packager's sbt-np-jaa(Java Application Archetype).
Libraries
Libraries are built by running SBT's built-in publishLocal task and then copying the resulting Ivy local repo to the Nix output folder.
Source Dependencies
Sbtix builds can depend on dependencies not found in online repositories by adding the attr sbtixBuildInputs to their call to buildSbt*.
These local dependencies should be provided as a derivation that produces a Maven or Ivy directory layout in its output, such as buildSbtLibrary. You should first package the dependency and then sbtix-gen the metadata for the project using it.
To make sure transitive dependencies and overrides work correctly, the local dependency must be available both when running 'sbtix-gen' and when building. You provide it in a sbtix-build-inputs.nix file, which could hold a single dependency:
{ pkgs ? import <nixpkgs> {} }:
pkgs.callPackage ./path/to/dependency/derivation {}
.. or multiple:
{ pkgs ? import <nixpkgs> {} }:
pkgs.symlinkJoin {
name = "sbtix-dependencies";
paths = [
(pkgs.callPackage ./path/to/dependency/derivation {})
(pkgs.callPackage ./path/to/other/dependency {})
];
}
This file is picked up (by name) by sbtix-gen, and also should be passed in as a parameter in the buildSbtProgram invocation in your default.nix:
sbtix.buildSbtProgram {
...
sbtixBuildInputs = (pkgs.callPackage ./sbtix-build-inputs.nix {});
...
}
nix Extra Attribute
By adding the nix extra attribute, sbtix will ignore the dependency for the purpose of locking.
This used to be the only mechanism for handling local dependencies, but is now a legacy solution and/or escape hatch.