#+STARTUP: inlineimages [[./assets/gradle2nix.png]] Generate [[https://nixos.org/nix/][Nix]] expressions which build [[https://gradle.org/][Gradle]]-based projects. ** 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 [[./default.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]]. *** Flake (experimental) 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 ** Usage #+begin_example Usage: gradle2nix [OPTIONS] [PROJECT-DIR] Options: -g, --gradle-version VERSION Use a specific Gradle version -a, --gradle-args ARGS Extra arguments to pass to Gradle -c, --configuration NAME Add a configuration to resolve (default: all configurations) -i, --include DIR Add an additional project to include -p, --project PATH Only resolve these subproject paths, e.g. ':', or ':sub:project' (default: all projects) -o, --out-dir DIR Path to write generated files (default: PROJECT-DIR) -e, --env FILENAME Prefix for environment files (.json and .nix) (default: gradle-env) -b, --build-src / -nb, --no-build-src Include buildSrc project (default: true) -q, --quiet Disable logging -h, --help Show this message and exit Arguments: PROJECT-DIR Path to the project root (default: .) #+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-env.json= and =gradle-env.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 [[./default.nix][default.nix]]. *** Specifying the Gradle version By default, if the project has configured the Gradle wrapper, that version will be detected and pinned; otherwise, the version of Gradle installed on your system will be pinned. You can override this with the =--gradle-version= argument, which also avoids the need to have Gradle installed. #+begin_example gradle2nix -g 6.1 #+end_example *** Multi-project builds If you want to resolve only a subset of projects in a [[https://docs.gradle.org/current/userguide/intro_multi_project_builds.html][multi-project build]], add the =--project= option for each project. For example, in a project where you only want to build the subprojects =:app= and =:widget=: #+begin_example gradle2nix -p :app -p :widget #+end_example Any [[https://docs.gradle.org/current/userguide/declaring_dependencies.html#sub:project_dependencies][project dependencies]] will be also be included when pinning dependency artifacts. ** 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 [[./plugin/src/compatTest/kotlin/org/nixos/gradle2nix][existing compatibility tests]] for examples of testing with these fixtures. ** License =gradle2nix= is licensed under the [[./COPYING][MIT License]].