mirror of
https://github.com/tadfisher/gradle2nix.git
synced 2026-01-11 23:40:37 -05:00
Move Gradle build logic to a setup hook
This commit is contained in:
271
README.org
271
README.org
@@ -2,7 +2,8 @@
|
||||
|
||||
[[./assets/gradle2nix.png]]
|
||||
|
||||
Generate [[https://nixos.org/nix/][Nix]] expressions which build [[https://gradle.org/][Gradle]]-based projects.
|
||||
Generate [[https://nixos.org/nix/][Nix]] expressions which build
|
||||
[[https://gradle.org/][Gradle]]-based projects.
|
||||
|
||||
** Table of contents
|
||||
|
||||
@@ -13,6 +14,10 @@ Generate [[https://nixos.org/nix/][Nix]] expressions which build [[https://gradl
|
||||
- [[#usage][Usage]]
|
||||
- [[#for-packagers][For packagers]]
|
||||
- [[#specifying-the-gradle-installation][Specifying the Gradle installation]]
|
||||
- [[#reference][Reference]]
|
||||
- [[#buildGradlePackage][=buildGradlePackage=]]
|
||||
- [[#buildMavenRepo][=buildMavenRepo=]]
|
||||
- [[#gradleSetupHook][=gradleSetupHook=]]
|
||||
- [[#contributing][Contributing]]
|
||||
- [[#license][License]]
|
||||
#+END_QUOTE
|
||||
@@ -25,7 +30,8 @@ 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
|
||||
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
|
||||
@@ -42,31 +48,33 @@ inputs, including:
|
||||
- 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.
|
||||
=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;
|
||||
- Create isolated and reproducible development environments that
|
||||
work anywhere Nix itself can run.
|
||||
- Reduce or eliminate flakiness and maintenance headaches from CI/CD
|
||||
pipelines
|
||||
pipelines.
|
||||
- Distribute a recipe which can reliably build a Gradle project in
|
||||
repositories such as the [[https://nixos.org/nixpkgs/][Nix Package Collection]].
|
||||
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:
|
||||
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") {}
|
||||
@@ -93,8 +101,9 @@ nix-env -if "https://github.com/tadfisher/gradle2nix/archive/master.tar.gz"
|
||||
=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.
|
||||
The [[./nix/build-gradle-package.nix][buildGradlePackage]] function
|
||||
is provided via the =gradle2nix.passthru.buildGradlePackage=
|
||||
attribute.
|
||||
|
||||
#+begin_src nix
|
||||
{ pkgs ? import <nixpkgs> {} }:
|
||||
@@ -106,23 +115,24 @@ gradle2nix.buildGradlePackage {
|
||||
pname = "my-package";
|
||||
version = "1.0";
|
||||
lockFile = ./gradle.lock;
|
||||
gradleFlags = [ "installDist" ];
|
||||
gradleInstallFlags = [ "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 =--=:
|
||||
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.
|
||||
The [[./nix/build-gradle-package.nix][buildGradlePackage]] function
|
||||
is provided via the =builders= output.
|
||||
|
||||
#+begin_src nix
|
||||
{
|
||||
@@ -134,7 +144,7 @@ The [[./gradle.nix][buildGradlePackage]] function is provided via the
|
||||
pname = "my-package";
|
||||
version = "1.0";
|
||||
lockFile = ./gradle.lock;
|
||||
gradleFlags = [ "installDist" ];
|
||||
gradleInstallFlags = [ "installDist" ];
|
||||
# ...
|
||||
};
|
||||
};
|
||||
@@ -169,12 +179,12 @@ 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]].
|
||||
Simply running =gradle2nix= in the root directory of a project
|
||||
should be enough for most projects. This will produce a lock file,
|
||||
by default called =gradle.lock=, which contains the pinned
|
||||
dependencies for the project. An example of a build expression using
|
||||
this lock file can be found in this project's
|
||||
[[./default.nix][default.nix]].
|
||||
|
||||
*** For packagers
|
||||
|
||||
@@ -211,16 +221,203 @@ gradle2nix --gradle-home=`nix eval nixpkgs#gradle.outPath`/lib/gradle
|
||||
gradle2nix --gradle-wrapper=8.7
|
||||
#+end_example
|
||||
|
||||
** Reference
|
||||
|
||||
*** =buildGradlePackage=
|
||||
|
||||
This function is a convenience wrapper around =stdenv.mkDerivation=
|
||||
that simplifies building Gradle projects with the lock files
|
||||
produced by =gradle2nix=. It performs the following:
|
||||
|
||||
1. Applies [[#gradleSetupHook][=gradleSetupHook=]], overriding the
|
||||
required =gradle= package if specified.
|
||||
2. Builds the offline Maven repository with
|
||||
[[#buildMavenRepo][=buildMavenRepo=]].
|
||||
3. Sets the JDK used to run Gradle if specified.
|
||||
4. Applies the offline repo to the Gradle build using an
|
||||
initialization script.
|
||||
|
||||
- Source:
|
||||
[[./nix/build-gradle-package.nix][build-gradle-package.nix]]
|
||||
- Location:
|
||||
- Nix :: =gradle2nix.passthru.buildGradlePackage=
|
||||
- Flake :: =builders.${system}.buildGradlePackage=
|
||||
|
||||
**** Arguments to =buildGradlePackage=
|
||||
|
||||
- =lockFile= :: Path to the lock file generated by =gradle2nix=
|
||||
(e.g. =gradle.lock=).
|
||||
- =gradlePackage= :: The Gradle package to use. Default is
|
||||
=pkgs.gradle=.
|
||||
- =buildJdk= :: Override the default JDK used to run Gradle itself.
|
||||
- =fetchers= :: Override functions which fetch dependency
|
||||
artifacts.
|
||||
|
||||
See [[#fetchers][detailed documentation]] below.
|
||||
- =overrides= :: Override artifacts in the offline Maven repository.
|
||||
|
||||
See [[#override][detailed documentation]] below.
|
||||
|
||||
In addition, this function accepts:
|
||||
- All arguments to =stdenv.mkDerivation=.
|
||||
- Arguments specific to =gradleSetupHook= (see
|
||||
[[#gradleSetupHook][below]]).
|
||||
|
||||
*** =buildMavenRepo=
|
||||
|
||||
This function takes a lock file and produces a derivation which
|
||||
downloads all dependencies into a Maven local repository. The
|
||||
derivation provides a passthru =gradleInitScript= attribute, which
|
||||
is a Gradle initialization script that can be applied using =gradle
|
||||
--init-script== or placed in =$GRADLE_USER_HOME/init.d=. The init
|
||||
script replaces all repositories referenced in the project with the
|
||||
local repository.
|
||||
|
||||
- Source: [[./nix/build-maven-repo.nix][build-maven-repo.nix]]
|
||||
- Location:
|
||||
- Nix :: =gradle2nix.passthru.buildMavenRepo=
|
||||
- Flake :: =builders.${system}.buildMavenRepo=
|
||||
|
||||
**** Arguments to =buildMavenRepo=
|
||||
- =lockFile= :: Path to the lock file generated by gradle2nix (e.g.
|
||||
=gradle.lock=).
|
||||
- =fetchers= :: Override functions which fetch dependency
|
||||
artifacts.
|
||||
|
||||
See [[#fetchers][detailed documentation]] below.
|
||||
- =overrides= :: Override artifacts in the offline Maven repository.
|
||||
|
||||
See [[#override][detailed documentation]] below.
|
||||
|
||||
*** =gradleSetupHook=
|
||||
|
||||
A
|
||||
[[https://nixos.org/manual/nixpkgs/unstable/#ssec-setup-hooks][setup
|
||||
hook]] to simplify building Gradle packages. Overrides the default
|
||||
configure, build, check, and install phases.
|
||||
|
||||
To use, add =gradleSetupHook= to a derivation's =nativeBuildInputs=.
|
||||
|
||||
- Source: [[./nix/setup-hook.sh][setup-hook.sh]]
|
||||
- Location:
|
||||
- Nix :: =gradle2nix.passthru.gradleSetupHook=
|
||||
- Flake :: =packages.${system}.gradleSetupHook=
|
||||
|
||||
**** Variables controlling =gradleSetupHook=
|
||||
- =gradleInitScript= :: Path to an
|
||||
[[https://docs.gradle.org/current/userguide/init_scripts.html][initialization
|
||||
script]] used by =gradle= during all phases.
|
||||
- =gradleFlags= :: Controls the arguments passed to =gradle= during
|
||||
all phases.
|
||||
- =gradleBuildFlags= :: Controls the arguments passed to =gradle=
|
||||
during the build phase. The build phase is skipped if this is
|
||||
unset.
|
||||
- =gradleCheckFlags= :: Controls the arguments passed to =gradle=
|
||||
during the check phase. The check phase is skipped if this is
|
||||
unset.
|
||||
- =gradleInstallFlags= :: Controls the arguments passed to =gradle=
|
||||
during the install phase. This install phase is skipped if this is
|
||||
unset.
|
||||
- =dontUseGradleConfigure= :: When set to true, don't use the
|
||||
predefined =gradleConfigurePhase=. This will also disable the use
|
||||
of =gradleInitScript=.
|
||||
- =dontUseGradleCheck= :: When set to true, don't use the predefined
|
||||
=gradleCheckPhase=.
|
||||
- =dontUseGradleInstall= :: When set to true, don't use the
|
||||
predefined =gradleInstallPhase=.
|
||||
|
||||
**** Honored variables
|
||||
|
||||
The following variables commonly used by =stdenv.mkDerivation= are
|
||||
honored by =gradleSetupHook=.
|
||||
|
||||
- =enableParallelBuilding=
|
||||
- =enableParallelChecking=
|
||||
- =enableParallelInstalling=
|
||||
|
||||
*** Common arguments
|
||||
**** =fetchers=
|
||||
|
||||
Names in this set are URL schemes such as "https" or "s3". Values
|
||||
are functions which take an artifact in the form ={ url, hash }=
|
||||
and fetches it into the Nix store. For example:
|
||||
|
||||
#+begin_src nix
|
||||
{
|
||||
s3 = { name, url, hash }: fetchs3 {
|
||||
s3url = url;
|
||||
# TODO This doesn't work without patching fetchs3 to accept SRI hashes
|
||||
inherit name hash;
|
||||
region = "us-west-2";
|
||||
credentials = {
|
||||
access_key_id = "foo";
|
||||
secret_access_key = "bar";
|
||||
};
|
||||
};
|
||||
}
|
||||
#+end_src
|
||||
|
||||
**** =overrides=
|
||||
|
||||
This is an attrset of the form:
|
||||
|
||||
#+begin_src nix
|
||||
{
|
||||
"${group}:${module}:${version}" = {
|
||||
"${filename}" = <override function>;
|
||||
}
|
||||
}
|
||||
#+end_src
|
||||
|
||||
The override function takes the original derivation from 'fetchers'
|
||||
(e.g. the result of 'fetchurl') and produces a new derivation to
|
||||
replace it.
|
||||
|
||||
- Replace a dependency's JAR artifact:
|
||||
|
||||
#+begin_src nix
|
||||
{
|
||||
"com.squareup.okio:okio:3.9.0"."okio-3.9.0.jar" = _: fetchurl {
|
||||
url = "https://repo.maven.apache.org/maven2/com/squareup/okio/okio/3.9.0/okio-3.9.0.jar";
|
||||
hash = "...";
|
||||
downloadToTemp = true;
|
||||
postFetch = "install -Dt $out/com/squareup/okio/okio/3.9.0/ $downloadedFile"
|
||||
};
|
||||
}
|
||||
#+end_src
|
||||
|
||||
- Patch a JAR containing native binaries:
|
||||
|
||||
#+begin_src nix
|
||||
{
|
||||
"com.android.tools.build:aapt2:8.5.0-rc02-11315950" = {
|
||||
"aapt2-8.5.0-rc02-11315950-linux.jar" = src: runCommandCC src.name {
|
||||
nativeBuildInputs = [ jdk autoPatchelfHook ];
|
||||
dontAutoPatchelf = true;
|
||||
} ''
|
||||
cp ${src} aapt2.jar
|
||||
jar xf aapt2.jar aapt2
|
||||
chmod +x aapt2
|
||||
autoPatchelf aapt2
|
||||
jar uf aapt2.jar aapt2
|
||||
cp aapt2.jar $out
|
||||
'';
|
||||
}
|
||||
}
|
||||
#+end_src
|
||||
|
||||
** Contributing
|
||||
|
||||
Bug reports and feature requests are encouraged.
|
||||
|
||||
[[https://github.com/tadfisher/gradle2nix/issues/new][Create an issue]]
|
||||
[[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.
|
||||
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
|
||||
|
||||
|
||||
Reference in New Issue
Block a user