mirror of
https://github.com/tadfisher/gradle2nix.git
synced 2026-01-11 23:40:37 -05:00
228 lines
7.9 KiB
Org Mode
228 lines
7.9 KiB
Org Mode
#+STARTUP: inlineimages
|
|
|
|
[[./assets/gradle2nix.png]]
|
|
|
|
Generate [[https://nixos.org/nix/][Nix]] expressions which build [[https://gradle.org/][Gradle]]-based projects.
|
|
|
|
** Table of contents
|
|
|
|
#+BEGIN_QUOTE
|
|
- [[#why][Why?]]
|
|
- [[#installation][Installation]]
|
|
- [[#flake][Flake]]
|
|
- [[#usage][Usage]]
|
|
- [[#for-packagers][For packagers]]
|
|
- [[#specifying-the-gradle-installation][Specifying the Gradle installation]]
|
|
- [[#contributing][Contributing]]
|
|
- [[#license][License]]
|
|
#+END_QUOTE
|
|
|
|
** Why?
|
|
|
|
Nix is an OS-agnostic package manager, a language-agnostic build
|
|
system, and a bespoke programming language. One of its unique features
|
|
is that it is purely functional; a "package" is a function which
|
|
accepts inputs (source code, configuration, etc) and produces an
|
|
output (binaries, a Java JAR, documentation, really anything).
|
|
|
|
One benefit of a functional build system is [[https://reproducible-builds.org/][reproducibility]]. If you
|
|
specify your inputs precisely, and take care not to introduce
|
|
impurities—such as files retrieved over a network without tracking
|
|
their content—you will receive, byte-for-byte, the exact output as
|
|
someone else running the same function over the same inputs.
|
|
|
|
Gradle is not a functional build system. Most Gradle-based projects
|
|
will produce highly variable outputs depending on a host of impure
|
|
inputs, including:
|
|
|
|
- The JVM hosting the build
|
|
- The Gradle installation running the build
|
|
- Any usage of dynamic version constraints for dependencies
|
|
- SNAPSHOT dependencies
|
|
- Environment variables and command-line options
|
|
- Artifacts cached on the system hosting the build
|
|
|
|
=gradle2nix= helps to solve this problem by leveraging Nix to control
|
|
the most common inputs to a Gradle build. When run on a project, it
|
|
will record all dependencies for both the build environment (including
|
|
=plugins= and =buildscript= blocks) and the project, and provide a Nix
|
|
expression to run the build given these dependencies. The build itself
|
|
is then run in a sandbox, where only content-tracked network requests
|
|
are allowed to fetch dependencies, and a local Maven repository is
|
|
created on-the-fly to host the dependency artifacts somewhere Gradle
|
|
can resolve them without a network.
|
|
|
|
This tool is useful for both development and packaging. You can use
|
|
=gradle2nix= to:
|
|
|
|
- Create isolated and reproducible development environments that work
|
|
anywhere Nix itself can run;
|
|
- Reduce or eliminate flakiness and maintenance headaches from CI/CD
|
|
pipelines
|
|
- Distribute a recipe which can reliably build a Gradle project in
|
|
repositories such as the [[https://nixos.org/nixpkgs/][Nix Package Collection]].
|
|
|
|
** Installation
|
|
|
|
A [[./gradle.nix][Nix expression]] (generated by =gradle2nix= itself) is provided for
|
|
convenience. The following expression will fetch and build the latest
|
|
version of this package:
|
|
|
|
#+begin_src nix
|
|
import (fetchTarball "https://github.com/tadfisher/gradle2nix/archive/master.tar.gz") {}
|
|
#+end_src
|
|
|
|
If this expression is in, say, =gradle2nix.nix=, =gradle2nix= can be
|
|
built and placed in =./result= with the following:
|
|
|
|
#+begin_example
|
|
nix build -f gradle2nix.nix
|
|
#+end_example
|
|
|
|
You can also use the following one-liners to build or install
|
|
=gradle2nix= in your user profile:
|
|
|
|
#+begin_example
|
|
# Build and place in ./result/
|
|
nix build -f "https://github.com/tadfisher/gradle2nix/archive/master.tar.gz"
|
|
|
|
# Build and install in the user profile
|
|
nix-env -if "https://github.com/tadfisher/gradle2nix/archive/master.tar.gz"
|
|
#+end_example
|
|
|
|
=gradle2nix= is not yet packaged in =nixpkgs= itself, but work is
|
|
[[https://github.com/NixOS/nixpkgs/pull/77422][in progress]].
|
|
|
|
The [[./gradle.nix][buildGradlePackage]] function is provided via the
|
|
=gradle2nix.passthru.buildGradlePackage= attribute.
|
|
|
|
#+begin_src nix
|
|
{ pkgs ? import <nixpkgs> {} }:
|
|
|
|
let
|
|
gradle2nix = import (fetchTarball "https://github.com/tadfisher/gradle2nix/archive/master.tar.gz") {}
|
|
in
|
|
gradle2nix.buildGradlePackage {
|
|
pname = "my-package";
|
|
version = "1.0";
|
|
lockFile = ./gradle.lock;
|
|
gradleFlags = [ "installDist" ];
|
|
# ...
|
|
}
|
|
#+end_src
|
|
|
|
*** Flake
|
|
|
|
A [[./flake.nix][flake.nix]] is provided for those using [[https://nixos.wiki/wiki/Flakes][Nix flakes]]. For example, the
|
|
following will build and run =gradle2nix= with the arguments provided
|
|
after =--=:
|
|
|
|
#+begin_example
|
|
nix run github:tadfisher/gradle2nix -- --help
|
|
#+end_example
|
|
|
|
The [[./gradle.nix][buildGradlePackage]] function is provided via the
|
|
=builders= output.
|
|
|
|
#+begin_src nix
|
|
{
|
|
inputs.gradle2nix.url = "github:tadfisher/gradle2nix";
|
|
|
|
outputs = { self, gradle2nix }: {
|
|
|
|
packages.x86_64-linux.default = gradle2nix.builders.x86_64-linux.buildGradlePackage {
|
|
pname = "my-package";
|
|
version = "1.0";
|
|
lockFile = ./gradle.lock;
|
|
gradleFlags = [ "installDist" ];
|
|
# ...
|
|
};
|
|
};
|
|
}
|
|
#+end_src
|
|
|
|
** Usage
|
|
|
|
#+begin_example
|
|
Usage: gradle2nix [<options>] [<args>]...
|
|
|
|
Gradle installation:
|
|
|
|
Where to find Gradle. By default, use the project's wrapper.
|
|
|
|
--gradle-dist=<uri> Gradle distribution URI
|
|
--gradle-home=<dir> Gradle home path (e.g. `nix eval --raw nixpkgs#gradle.outPath`/lib/gradle)
|
|
--gradle-wrapper=<value> Gradle wrapper version
|
|
|
|
Options:
|
|
-t, --task=<task> Gradle tasks to run
|
|
-p, --project=<path> Path to the project root (default: Current directory)
|
|
-o, --out-dir=<dir> Path to write generated files (default: <project>)
|
|
-l, --lock-file=<filename> Name of the generated lock file (default: gradle.lock)
|
|
-j, --gradle-jdk=<dir> JDK home to use for launching Gradle (e.g. `nix eval --raw nixpkgs#openjdk.home`)
|
|
--log=(debug|info|warn|error) Print messages with this priority or higher (default: info)
|
|
--dump-events Dump Gradle event logs to the output directory
|
|
--stacktrace Print a stack trace on error
|
|
-h, --help Show this message and exit
|
|
|
|
Arguments:
|
|
<args> Extra arguments to pass to Gradle
|
|
#+end_example
|
|
|
|
Simply running =gradle2nix= in the root directory of a project should
|
|
be enough for most projects. This will produce two files, by default
|
|
called =gradle.lock= and =gradle.nix=, which contain the
|
|
pinned dependencies for the project and a standard build expression
|
|
which can be imported or called by other Nix expressions. An example
|
|
of such an expression can be found in this project's [[./gradle2nix.nix][gradle2nix.nix]].
|
|
|
|
*** For packagers
|
|
|
|
If you're creating a Nix package for an existing Gradle project, you
|
|
can reduce the number of pinned dependencies by passing one or more
|
|
=--task= arguments. This will only pin the dependencies that were
|
|
resolved as part of the build, instead of the default behavior where
|
|
all possible dependencies are pinned.
|
|
|
|
For example, if the package produces its build output via the
|
|
=:app:installDist= task, use the following:
|
|
|
|
#+begin_example
|
|
gradle2nix -t :app:installDist
|
|
#+end_example
|
|
|
|
/Note:/ This may be *required* if the build resolves configurations
|
|
at execution time.
|
|
|
|
*** Specifying the Gradle installation
|
|
|
|
By default, if the project has configured the Gradle wrapper, it will
|
|
be used; otherwise, the version of Gradle used to build gradle2nix
|
|
will be used. You can override this to use any of the following:
|
|
|
|
#+begin_example
|
|
# Gradle distribution URL:
|
|
gradle2nix --gradle-dist='https://services.gradle.org/distributions/gradle-8.7-bin.zip'
|
|
|
|
# Path to a local Gradle installation:
|
|
gradle2nix --gradle-home=`nix eval nixpkgs#gradle.outPath`/lib/gradle
|
|
|
|
# A specific wrapper version:
|
|
gradle2nix --gradle-wrapper=8.7
|
|
#+end_example
|
|
|
|
** Contributing
|
|
|
|
Bug reports and feature requests are encouraged.
|
|
|
|
[[https://github.com/tadfisher/gradle2nix/issues/new][Create an issue]]
|
|
|
|
Code contributions are also encouraged. Please review the test cases
|
|
in the [[./fixtures][fixtures]] directory and create a new one to reproduce any fixes
|
|
or test new features. See the [[./app/src/test/kotlin/org/nixos/gradle2nix/GoldenTest.kt][existing tests]]
|
|
for examples of testing with these fixtures.
|
|
|
|
** License
|
|
|
|
=gradle2nix= is licensed under the [[./COPYING][MIT License]].
|