mirror of
https://github.com/tadfisher/gradle2nix.git
synced 2026-01-12 16:00:38 -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]]
|
[[./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
|
** Table of contents
|
||||||
|
|
||||||
@@ -13,6 +14,10 @@ Generate [[https://nixos.org/nix/][Nix]] expressions which build [[https://gradl
|
|||||||
- [[#usage][Usage]]
|
- [[#usage][Usage]]
|
||||||
- [[#for-packagers][For packagers]]
|
- [[#for-packagers][For packagers]]
|
||||||
- [[#specifying-the-gradle-installation][Specifying the Gradle installation]]
|
- [[#specifying-the-gradle-installation][Specifying the Gradle installation]]
|
||||||
|
- [[#reference][Reference]]
|
||||||
|
- [[#buildGradlePackage][=buildGradlePackage=]]
|
||||||
|
- [[#buildMavenRepo][=buildMavenRepo=]]
|
||||||
|
- [[#gradleSetupHook][=gradleSetupHook=]]
|
||||||
- [[#contributing][Contributing]]
|
- [[#contributing][Contributing]]
|
||||||
- [[#license][License]]
|
- [[#license][License]]
|
||||||
#+END_QUOTE
|
#+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
|
accepts inputs (source code, configuration, etc) and produces an
|
||||||
output (binaries, a Java JAR, documentation, really anything).
|
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
|
specify your inputs precisely, and take care not to introduce
|
||||||
impurities—such as files retrieved over a network without tracking
|
impurities—such as files retrieved over a network without tracking
|
||||||
their content—you will receive, byte-for-byte, the exact output as
|
their content—you will receive, byte-for-byte, the exact output as
|
||||||
@@ -42,31 +48,33 @@ inputs, including:
|
|||||||
- Environment variables and command-line options
|
- Environment variables and command-line options
|
||||||
- Artifacts cached on the system hosting the build
|
- Artifacts cached on the system hosting the build
|
||||||
|
|
||||||
=gradle2nix= helps to solve this problem by leveraging Nix to control
|
=gradle2nix= helps to solve this problem by leveraging Nix to
|
||||||
the most common inputs to a Gradle build. When run on a project, it
|
control the most common inputs to a Gradle build. When run on a
|
||||||
will record all dependencies for both the build environment (including
|
project, it will record all dependencies for both the build
|
||||||
=plugins= and =buildscript= blocks) and the project, and provide a Nix
|
environment (including =plugins= and =buildscript= blocks) and the
|
||||||
expression to run the build given these dependencies. The build itself
|
project, and provide a Nix expression to run the build given these
|
||||||
is then run in a sandbox, where only content-tracked network requests
|
dependencies. The build itself is then run in a sandbox, where only
|
||||||
are allowed to fetch dependencies, and a local Maven repository is
|
content-tracked network requests are allowed to fetch dependencies,
|
||||||
created on-the-fly to host the dependency artifacts somewhere Gradle
|
and a local Maven repository is created on-the-fly to host the
|
||||||
can resolve them without a network.
|
dependency artifacts somewhere Gradle can resolve them without a
|
||||||
|
network.
|
||||||
|
|
||||||
This tool is useful for both development and packaging. You can use
|
This tool is useful for both development and packaging. You can use
|
||||||
=gradle2nix= to:
|
=gradle2nix= to:
|
||||||
|
|
||||||
- Create isolated and reproducible development environments that work
|
- Create isolated and reproducible development environments that
|
||||||
anywhere Nix itself can run;
|
work anywhere Nix itself can run.
|
||||||
- Reduce or eliminate flakiness and maintenance headaches from CI/CD
|
- Reduce or eliminate flakiness and maintenance headaches from CI/CD
|
||||||
pipelines
|
pipelines.
|
||||||
- Distribute a recipe which can reliably build a Gradle project in
|
- 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
|
** Installation
|
||||||
|
|
||||||
A [[./gradle.nix][Nix expression]] (generated by =gradle2nix= itself) is provided for
|
A [[./gradle.nix][Nix expression]] (generated by =gradle2nix=
|
||||||
convenience. The following expression will fetch and build the latest
|
itself) is provided for convenience. The following expression will
|
||||||
version of this package:
|
fetch and build the latest version of this package:
|
||||||
|
|
||||||
#+begin_src nix
|
#+begin_src nix
|
||||||
import (fetchTarball "https://github.com/tadfisher/gradle2nix/archive/master.tar.gz") {}
|
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
|
=gradle2nix= is not yet packaged in =nixpkgs= itself, but work is
|
||||||
[[https://github.com/NixOS/nixpkgs/pull/77422][in progress]].
|
[[https://github.com/NixOS/nixpkgs/pull/77422][in progress]].
|
||||||
|
|
||||||
The [[./gradle.nix][buildGradlePackage]] function is provided via the
|
The [[./nix/build-gradle-package.nix][buildGradlePackage]] function
|
||||||
=gradle2nix.passthru.buildGradlePackage= attribute.
|
is provided via the =gradle2nix.passthru.buildGradlePackage=
|
||||||
|
attribute.
|
||||||
|
|
||||||
#+begin_src nix
|
#+begin_src nix
|
||||||
{ pkgs ? import <nixpkgs> {} }:
|
{ pkgs ? import <nixpkgs> {} }:
|
||||||
@@ -106,23 +115,24 @@ gradle2nix.buildGradlePackage {
|
|||||||
pname = "my-package";
|
pname = "my-package";
|
||||||
version = "1.0";
|
version = "1.0";
|
||||||
lockFile = ./gradle.lock;
|
lockFile = ./gradle.lock;
|
||||||
gradleFlags = [ "installDist" ];
|
gradleInstallFlags = [ "installDist" ];
|
||||||
# ...
|
# ...
|
||||||
}
|
}
|
||||||
#+end_src
|
#+end_src
|
||||||
|
|
||||||
*** Flake
|
*** Flake
|
||||||
|
|
||||||
A [[./flake.nix][flake.nix]] is provided for those using [[https://nixos.wiki/wiki/Flakes][Nix flakes]]. For example, the
|
A [[./flake.nix][flake.nix]] is provided for those using
|
||||||
following will build and run =gradle2nix= with the arguments provided
|
[[https://nixos.wiki/wiki/Flakes][Nix flakes]]. For example, the
|
||||||
after =--=:
|
following will build and run =gradle2nix= with the arguments
|
||||||
|
provided after =--=:
|
||||||
|
|
||||||
#+begin_example
|
#+begin_example
|
||||||
nix run github:tadfisher/gradle2nix -- --help
|
nix run github:tadfisher/gradle2nix -- --help
|
||||||
#+end_example
|
#+end_example
|
||||||
|
|
||||||
The [[./gradle.nix][buildGradlePackage]] function is provided via the
|
The [[./nix/build-gradle-package.nix][buildGradlePackage]] function
|
||||||
=builders= output.
|
is provided via the =builders= output.
|
||||||
|
|
||||||
#+begin_src nix
|
#+begin_src nix
|
||||||
{
|
{
|
||||||
@@ -134,7 +144,7 @@ The [[./gradle.nix][buildGradlePackage]] function is provided via the
|
|||||||
pname = "my-package";
|
pname = "my-package";
|
||||||
version = "1.0";
|
version = "1.0";
|
||||||
lockFile = ./gradle.lock;
|
lockFile = ./gradle.lock;
|
||||||
gradleFlags = [ "installDist" ];
|
gradleInstallFlags = [ "installDist" ];
|
||||||
# ...
|
# ...
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
@@ -169,12 +179,12 @@ Arguments:
|
|||||||
<args> Extra arguments to pass to Gradle
|
<args> Extra arguments to pass to Gradle
|
||||||
#+end_example
|
#+end_example
|
||||||
|
|
||||||
Simply running =gradle2nix= in the root directory of a project should
|
Simply running =gradle2nix= in the root directory of a project
|
||||||
be enough for most projects. This will produce two files, by default
|
should be enough for most projects. This will produce a lock file,
|
||||||
called =gradle.lock= and =gradle.nix=, which contain the
|
by default called =gradle.lock=, which contains the pinned
|
||||||
pinned dependencies for the project and a standard build expression
|
dependencies for the project. An example of a build expression using
|
||||||
which can be imported or called by other Nix expressions. An example
|
this lock file can be found in this project's
|
||||||
of such an expression can be found in this project's [[./gradle2nix.nix][gradle2nix.nix]].
|
[[./default.nix][default.nix]].
|
||||||
|
|
||||||
*** For packagers
|
*** For packagers
|
||||||
|
|
||||||
@@ -211,16 +221,203 @@ gradle2nix --gradle-home=`nix eval nixpkgs#gradle.outPath`/lib/gradle
|
|||||||
gradle2nix --gradle-wrapper=8.7
|
gradle2nix --gradle-wrapper=8.7
|
||||||
#+end_example
|
#+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
|
** Contributing
|
||||||
|
|
||||||
Bug reports and feature requests are encouraged.
|
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
|
Code contributions are also encouraged. Please review the test cases
|
||||||
in the [[./fixtures][fixtures]] directory and create a new one to reproduce any fixes
|
in the [[./fixtures][fixtures]] directory and create a new one to
|
||||||
or test new features. See the [[./app/src/test/kotlin/org/nixos/gradle2nix/GoldenTest.kt][existing tests]]
|
reproduce any fixes or test new features. See the
|
||||||
for examples of testing with these fixtures.
|
[[./app/src/test/kotlin/org/nixos/gradle2nix/GoldenTest.kt][existing
|
||||||
|
tests]] for examples of testing with these fixtures.
|
||||||
|
|
||||||
** License
|
** License
|
||||||
|
|
||||||
|
|||||||
@@ -16,7 +16,8 @@ fun connect(
|
|||||||
config: Config,
|
config: Config,
|
||||||
projectDir: File = config.projectDir,
|
projectDir: File = config.projectDir,
|
||||||
): ProjectConnection =
|
): ProjectConnection =
|
||||||
GradleConnector.newConnector()
|
GradleConnector
|
||||||
|
.newConnector()
|
||||||
.apply {
|
.apply {
|
||||||
when (val source = config.gradleSource) {
|
when (val source = config.gradleSource) {
|
||||||
is GradleSource.Distribution -> useDistribution(source.uri)
|
is GradleSource.Distribution -> useDistribution(source.uri)
|
||||||
@@ -24,8 +25,7 @@ fun connect(
|
|||||||
GradleSource.Project -> useBuildDistribution()
|
GradleSource.Project -> useBuildDistribution()
|
||||||
is GradleSource.Wrapper -> useGradleVersion(source.version)
|
is GradleSource.Wrapper -> useGradleVersion(source.version)
|
||||||
}
|
}
|
||||||
}
|
}.forProjectDirectory(projectDir)
|
||||||
.forProjectDirectory(projectDir)
|
|
||||||
.connect()
|
.connect()
|
||||||
|
|
||||||
suspend fun ProjectConnection.buildModel(): GradleBuild =
|
suspend fun ProjectConnection.buildModel(): GradleBuild =
|
||||||
@@ -67,8 +67,7 @@ suspend fun ProjectConnection.build(
|
|||||||
"--refresh-dependencies",
|
"--refresh-dependencies",
|
||||||
"--gradle-user-home=${config.gradleHome}",
|
"--gradle-user-home=${config.gradleHome}",
|
||||||
"--init-script=${config.appHome}/init.gradle",
|
"--init-script=${config.appHome}/init.gradle",
|
||||||
)
|
).apply {
|
||||||
.apply {
|
|
||||||
if (config.logger.stacktrace) {
|
if (config.logger.stacktrace) {
|
||||||
addArguments("--stacktrace")
|
addArguments("--stacktrace")
|
||||||
}
|
}
|
||||||
@@ -80,12 +79,14 @@ suspend fun ProjectConnection.build(
|
|||||||
withSystemProperties(
|
withSystemProperties(
|
||||||
mapOf(
|
mapOf(
|
||||||
"org.gradle.internal.operations.trace" to
|
"org.gradle.internal.operations.trace" to
|
||||||
config.outDir.toPath().resolve("debug").absolutePathString(),
|
config.outDir
|
||||||
|
.toPath()
|
||||||
|
.resolve("debug")
|
||||||
|
.absolutePathString(),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}.run(
|
||||||
.run(
|
|
||||||
object : ResultHandler<DependencySet> {
|
object : ResultHandler<DependencySet> {
|
||||||
override fun onComplete(result: DependencySet) {
|
override fun onComplete(result: DependencySet) {
|
||||||
continuation.resume(result)
|
continuation.resume(result)
|
||||||
|
|||||||
@@ -48,13 +48,19 @@ val JsonFormat =
|
|||||||
}
|
}
|
||||||
|
|
||||||
sealed interface GradleSource {
|
sealed interface GradleSource {
|
||||||
data class Distribution(val uri: URI) : GradleSource
|
data class Distribution(
|
||||||
|
val uri: URI,
|
||||||
|
) : GradleSource
|
||||||
|
|
||||||
data class Path(val path: File) : GradleSource
|
data class Path(
|
||||||
|
val path: File,
|
||||||
|
) : GradleSource
|
||||||
|
|
||||||
data object Project : GradleSource
|
data object Project : GradleSource
|
||||||
|
|
||||||
data class Wrapper(val version: String) : GradleSource
|
data class Wrapper(
|
||||||
|
val version: String,
|
||||||
|
) : GradleSource
|
||||||
}
|
}
|
||||||
|
|
||||||
enum class LogLevel {
|
enum class LogLevel {
|
||||||
@@ -64,9 +70,10 @@ enum class LogLevel {
|
|||||||
ERROR,
|
ERROR,
|
||||||
}
|
}
|
||||||
|
|
||||||
class Gradle2Nix : CliktCommand(
|
class Gradle2Nix :
|
||||||
name = "gradle2nix",
|
CliktCommand(
|
||||||
) {
|
name = "gradle2nix",
|
||||||
|
) {
|
||||||
private val tasks: List<String> by option(
|
private val tasks: List<String> by option(
|
||||||
"--task",
|
"--task",
|
||||||
"-t",
|
"-t",
|
||||||
@@ -93,8 +100,7 @@ class Gradle2Nix : CliktCommand(
|
|||||||
"-o",
|
"-o",
|
||||||
metavar = "DIR",
|
metavar = "DIR",
|
||||||
help = "Path to write generated files",
|
help = "Path to write generated files",
|
||||||
)
|
).file(canBeFile = false, canBeDir = true)
|
||||||
.file(canBeFile = false, canBeDir = true)
|
|
||||||
.defaultLazy("<project>") { projectDir }
|
.defaultLazy("<project>") { projectDir }
|
||||||
|
|
||||||
internal val lockFile: String by option(
|
internal val lockFile: String by option(
|
||||||
@@ -133,8 +139,7 @@ class Gradle2Nix : CliktCommand(
|
|||||||
private val logLevel: LogLevel by option(
|
private val logLevel: LogLevel by option(
|
||||||
"--log",
|
"--log",
|
||||||
help = "Print messages with this priority or higher",
|
help = "Print messages with this priority or higher",
|
||||||
)
|
).enum<LogLevel>(key = { it.name.lowercase() })
|
||||||
.enum<LogLevel>(key = { it.name.lowercase() })
|
|
||||||
.default(LogLevel.INFO, "info")
|
.default(LogLevel.INFO, "info")
|
||||||
|
|
||||||
private val dumpEvents: Boolean by option(
|
private val dumpEvents: Boolean by option(
|
||||||
@@ -192,7 +197,9 @@ class Gradle2Nix : CliktCommand(
|
|||||||
addAll(root.editableBuilds)
|
addAll(root.editableBuilds)
|
||||||
}
|
}
|
||||||
builds.mapNotNull { build ->
|
builds.mapNotNull { build ->
|
||||||
build.rootProject.projectDirectory.resolve("buildSrc").takeIf { it.exists() }
|
build.rootProject.projectDirectory
|
||||||
|
.resolve("buildSrc")
|
||||||
|
.takeIf { it.exists() }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -8,8 +8,8 @@ import kotlin.io.encoding.ExperimentalEncodingApi
|
|||||||
fun processDependencies(
|
fun processDependencies(
|
||||||
config: Config,
|
config: Config,
|
||||||
dependencySets: Iterable<DependencySet>,
|
dependencySets: Iterable<DependencySet>,
|
||||||
): Env {
|
): Env =
|
||||||
return buildMap<DependencyCoordinates, Map<String, Artifact>> {
|
buildMap<DependencyCoordinates, Map<String, Artifact>> {
|
||||||
for (dependencySet in dependencySets) {
|
for (dependencySet in dependencySets) {
|
||||||
val env = dependencySet.toEnv()
|
val env = dependencySet.toEnv()
|
||||||
|
|
||||||
@@ -40,16 +40,14 @@ fun processDependencies(
|
|||||||
artifacts.toSortedMap()
|
artifacts.toSortedMap()
|
||||||
}.toSortedMap(coordinatesComparator)
|
}.toSortedMap(coordinatesComparator)
|
||||||
.mapKeys { (coordinates, _) -> coordinates.id }
|
.mapKeys { (coordinates, _) -> coordinates.id }
|
||||||
}
|
|
||||||
|
|
||||||
private fun DependencySet.toEnv(): Map<DependencyCoordinates, Map<String, Artifact>> {
|
private fun DependencySet.toEnv(): Map<DependencyCoordinates, Map<String, Artifact>> =
|
||||||
return dependencies.associate { dep ->
|
dependencies.associate { dep ->
|
||||||
dep.coordinates to
|
dep.coordinates to
|
||||||
dep.artifacts.associate {
|
dep.artifacts.associate {
|
||||||
it.name to Artifact(it.url, it.hash.toSri())
|
it.name to Artifact(it.url, it.hash.toSri())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
@OptIn(ExperimentalEncodingApi::class, ExperimentalStdlibApi::class)
|
@OptIn(ExperimentalEncodingApi::class, ExperimentalStdlibApi::class)
|
||||||
internal fun String.toSri(): String =
|
internal fun String.toSri(): String =
|
||||||
|
|||||||
@@ -2,7 +2,11 @@ package org.nixos.gradle2nix
|
|||||||
|
|
||||||
import java.util.concurrent.ConcurrentHashMap
|
import java.util.concurrent.ConcurrentHashMap
|
||||||
|
|
||||||
class Version(val source: String, val parts: List<String>, base: Version?) : Comparable<Version> {
|
class Version(
|
||||||
|
val source: String,
|
||||||
|
val parts: List<String>,
|
||||||
|
base: Version?,
|
||||||
|
) : Comparable<Version> {
|
||||||
private val base: Version
|
private val base: Version
|
||||||
val numericParts: List<Long?>
|
val numericParts: List<Long?>
|
||||||
|
|
||||||
|
|||||||
@@ -3,45 +3,46 @@ package org.nixos.gradle2nix
|
|||||||
import io.kotest.core.extensions.install
|
import io.kotest.core.extensions.install
|
||||||
import io.kotest.core.spec.style.FunSpec
|
import io.kotest.core.spec.style.FunSpec
|
||||||
|
|
||||||
class GoldenTest : FunSpec({
|
class GoldenTest :
|
||||||
install(MavenRepo)
|
FunSpec({
|
||||||
|
install(MavenRepo)
|
||||||
|
|
||||||
context("basic") {
|
context("basic") {
|
||||||
golden("basic/basic-java-project")
|
golden("basic/basic-java-project")
|
||||||
golden("basic/basic-kotlin-project")
|
golden("basic/basic-kotlin-project")
|
||||||
}
|
}
|
||||||
context("buildsrc") {
|
context("buildsrc") {
|
||||||
golden("buildsrc/plugin-in-buildsrc")
|
golden("buildsrc/plugin-in-buildsrc")
|
||||||
}
|
}
|
||||||
context("dependency") {
|
context("dependency") {
|
||||||
golden("dependency/classifier")
|
golden("dependency/classifier")
|
||||||
golden("dependency/maven-bom")
|
golden("dependency/maven-bom")
|
||||||
golden("dependency/snapshot")
|
golden("dependency/snapshot")
|
||||||
golden("dependency/snapshot-dynamic")
|
golden("dependency/snapshot-dynamic")
|
||||||
golden("dependency/snapshot-redirect")
|
golden("dependency/snapshot-redirect")
|
||||||
}
|
}
|
||||||
context("included-build") {
|
context("included-build") {
|
||||||
golden("included-build")
|
golden("included-build")
|
||||||
}
|
}
|
||||||
context("integration") {
|
context("integration") {
|
||||||
golden("integration/settings-buildscript")
|
golden("integration/settings-buildscript")
|
||||||
}
|
}
|
||||||
context("ivy") {
|
context("ivy") {
|
||||||
golden("ivy/basic")
|
golden("ivy/basic")
|
||||||
}
|
}
|
||||||
context("plugin") {
|
context("plugin") {
|
||||||
golden("plugin/resolves-from-default-repo")
|
golden("plugin/resolves-from-default-repo")
|
||||||
}
|
}
|
||||||
// FIXME Need s3mock or similar to generate golden data.
|
// FIXME Need s3mock or similar to generate golden data.
|
||||||
xcontext("s3") {
|
xcontext("s3") {
|
||||||
golden("s3/maven")
|
golden("s3/maven")
|
||||||
golden("s3/maven-snapshot")
|
golden("s3/maven-snapshot")
|
||||||
}
|
}
|
||||||
context("settings") {
|
context("settings") {
|
||||||
golden("settings/buildscript")
|
golden("settings/buildscript")
|
||||||
golden("settings/dependency-resolution-management")
|
golden("settings/dependency-resolution-management")
|
||||||
}
|
}
|
||||||
context("subprojects") {
|
context("subprojects") {
|
||||||
golden("subprojects/multi-module")
|
golden("subprojects/multi-module")
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -47,9 +47,7 @@ private val json =
|
|||||||
|
|
||||||
val testLogger = Logger(logLevel = LogLevel.DEBUG, stacktrace = true)
|
val testLogger = Logger(logLevel = LogLevel.DEBUG, stacktrace = true)
|
||||||
|
|
||||||
fun fixture(path: String): File {
|
fun fixture(path: String): File = Paths.get("../fixtures", path).toFile()
|
||||||
return Paths.get("../fixtures", path).toFile()
|
|
||||||
}
|
|
||||||
|
|
||||||
@OptIn(ExperimentalKotest::class, ExperimentalSerializationApi::class, KotestInternal::class)
|
@OptIn(ExperimentalKotest::class, ExperimentalSerializationApi::class, KotestInternal::class)
|
||||||
suspend fun TestScope.fixture(
|
suspend fun TestScope.fixture(
|
||||||
@@ -60,7 +58,8 @@ suspend fun TestScope.fixture(
|
|||||||
val tmp = Paths.get("build/tmp/gradle2nix").apply { toFile().mkdirs() }
|
val tmp = Paths.get("build/tmp/gradle2nix").apply { toFile().mkdirs() }
|
||||||
val baseDir = Paths.get("../fixtures/projects", project).toFile()
|
val baseDir = Paths.get("../fixtures/projects", project).toFile()
|
||||||
val children =
|
val children =
|
||||||
baseDir.listFiles(FileFilter { it.isDirectory && (it.name == "groovy" || it.name == "kotlin") })
|
baseDir
|
||||||
|
.listFiles(FileFilter { it.isDirectory && (it.name == "groovy" || it.name == "kotlin") })
|
||||||
?.toList()
|
?.toList()
|
||||||
val cases =
|
val cases =
|
||||||
if (children.isNullOrEmpty()) {
|
if (children.isNullOrEmpty()) {
|
||||||
@@ -175,8 +174,8 @@ object MavenRepo : MountableExtension<MavenRepo.Config, NettyApplicationEngine>,
|
|||||||
return tryStart(3).also { this.server = it }
|
return tryStart(3).also { this.server = it }
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun tryStart(attempts: Int): NettyApplicationEngine {
|
private fun tryStart(attempts: Int): NettyApplicationEngine =
|
||||||
return try {
|
try {
|
||||||
val p = config.port ?: Random.nextInt(10000, 65000)
|
val p = config.port ?: Random.nextInt(10000, 65000)
|
||||||
val s =
|
val s =
|
||||||
embeddedServer(Netty, port = p, host = config.host) {
|
embeddedServer(Netty, port = p, host = config.host) {
|
||||||
@@ -202,7 +201,6 @@ object MavenRepo : MountableExtension<MavenRepo.Config, NettyApplicationEngine>,
|
|||||||
} catch (e: Throwable) {
|
} catch (e: Throwable) {
|
||||||
if (config.port == null && attempts > 0) tryStart(attempts - 1) else throw e
|
if (config.port == null && attempts > 0) tryStart(attempts - 1) else throw e
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
override suspend fun afterSpec(spec: Spec) {
|
override suspend fun afterSpec(spec: Spec) {
|
||||||
server?.stop()
|
server?.stop()
|
||||||
|
|||||||
17
default.nix
17
default.nix
@@ -5,9 +5,16 @@
|
|||||||
with pkgs;
|
with pkgs;
|
||||||
|
|
||||||
let
|
let
|
||||||
buildMavenRepo = callPackage ./maven-repo.nix { };
|
buildMavenRepo = callPackage ./nix/build-maven-repo.nix { };
|
||||||
|
|
||||||
buildGradlePackage = callPackage ./gradle.nix { inherit buildMavenRepo; };
|
gradleSetupHook = makeSetupHook {
|
||||||
|
name = "gradle-setup-hook";
|
||||||
|
propagatedBuildInputs = [ gradle ];
|
||||||
|
} ./nix/setup-hook.sh;
|
||||||
|
|
||||||
|
buildGradlePackage = callPackage ./nix/build-gradle-package.nix {
|
||||||
|
inherit buildMavenRepo gradleSetupHook;
|
||||||
|
};
|
||||||
|
|
||||||
gradle2nix = buildGradlePackage {
|
gradle2nix = buildGradlePackage {
|
||||||
pname = "gradle2nix";
|
pname = "gradle2nix";
|
||||||
@@ -30,9 +37,9 @@ let
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
gradleFlags = [ "installDist" ];
|
gradleInstallFlags = [ ":app:installDist" ];
|
||||||
|
|
||||||
installPhase = ''
|
postInstall = ''
|
||||||
mkdir -p $out/{bin,/lib/gradle2nix}
|
mkdir -p $out/{bin,/lib/gradle2nix}
|
||||||
cp -r app/build/install/gradle2nix/* $out/lib/gradle2nix/
|
cp -r app/build/install/gradle2nix/* $out/lib/gradle2nix/
|
||||||
rm $out/lib/gradle2nix/bin/gradle2nix.bat
|
rm $out/lib/gradle2nix/bin/gradle2nix.bat
|
||||||
@@ -40,7 +47,7 @@ let
|
|||||||
'';
|
'';
|
||||||
|
|
||||||
passthru = {
|
passthru = {
|
||||||
inherit buildGradlePackage buildMavenRepo;
|
inherit buildGradlePackage buildMavenRepo gradleSetupHook;
|
||||||
};
|
};
|
||||||
|
|
||||||
meta = with lib; {
|
meta = with lib; {
|
||||||
|
|||||||
6
flake.lock
generated
6
flake.lock
generated
@@ -20,11 +20,11 @@
|
|||||||
},
|
},
|
||||||
"nixpkgs": {
|
"nixpkgs": {
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1716769173,
|
"lastModified": 1718160348,
|
||||||
"narHash": "sha256-7EXDb5WBw+d004Agt+JHC/Oyh/KTUglOaQ4MNjBbo5w=",
|
"narHash": "sha256-9YrUjdztqi4Gz8n3mBuqvCkMo4ojrA6nASwyIKWMpus=",
|
||||||
"owner": "NixOS",
|
"owner": "NixOS",
|
||||||
"repo": "nixpkgs",
|
"repo": "nixpkgs",
|
||||||
"rev": "9ca3f649614213b2aaf5f1e16ec06952fe4c2632",
|
"rev": "57d6973abba7ea108bac64ae7629e7431e0199b6",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
|
|||||||
12
flake.nix
12
flake.nix
@@ -20,15 +20,15 @@
|
|||||||
inherit (nixpkgs) lib;
|
inherit (nixpkgs) lib;
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
builders = rec {
|
builders = {
|
||||||
buildMavenRepo = pkgs.callPackage ./maven-repo.nix { };
|
inherit (self.packages.${system}.gradle2nix) buildGradlePackage buildMavenRepo;
|
||||||
buildGradlePackage = pkgs.callPackage ./gradle.nix { inherit buildMavenRepo; };
|
default = self.packages.${system}.buildGradlePackage;
|
||||||
default = buildGradlePackage;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
packages = rec {
|
packages = {
|
||||||
|
inherit (self.packages.${system}.gradle2nix) gradleSetupHook;
|
||||||
gradle2nix = pkgs.callPackage ./default.nix { };
|
gradle2nix = pkgs.callPackage ./default.nix { };
|
||||||
default = gradle2nix;
|
default = self.packages.${system}.gradle2nix;
|
||||||
};
|
};
|
||||||
|
|
||||||
apps = rec {
|
apps = rec {
|
||||||
|
|||||||
238
gradle.nix
238
gradle.nix
@@ -1,238 +0,0 @@
|
|||||||
# This file is generated by gradle2nix.
|
|
||||||
#
|
|
||||||
# Example usage (e.g. in default.nix):
|
|
||||||
#
|
|
||||||
# with (import <nixpkgs> {});
|
|
||||||
# let
|
|
||||||
# buildGradle = callPackage ./gradle.nix {};
|
|
||||||
# in
|
|
||||||
# buildGradle {
|
|
||||||
# lockFile = ./gradle.lock;
|
|
||||||
#
|
|
||||||
# src = ./.;
|
|
||||||
#
|
|
||||||
# gradleFlags = [ "installDist" ];
|
|
||||||
#
|
|
||||||
# installPhase = ''
|
|
||||||
# mkdir -p $out
|
|
||||||
# cp -r app/build/install/myproject $out
|
|
||||||
# '';
|
|
||||||
# }
|
|
||||||
|
|
||||||
{
|
|
||||||
lib,
|
|
||||||
stdenv,
|
|
||||||
gradle,
|
|
||||||
buildMavenRepo,
|
|
||||||
writeText,
|
|
||||||
}:
|
|
||||||
|
|
||||||
let
|
|
||||||
defaultGradle = gradle;
|
|
||||||
in
|
|
||||||
|
|
||||||
{
|
|
||||||
# Path to the lockfile generated by gradle2nix (e.g. gradle.lock).
|
|
||||||
lockFile ? null,
|
|
||||||
pname ? "project",
|
|
||||||
version ? null,
|
|
||||||
enableParallelBuilding ? true,
|
|
||||||
# The Gradle package to use. Default is 'pkgs.gradle'.
|
|
||||||
gradle ? defaultGradle,
|
|
||||||
# Arguments to Gradle used to build the project in buildPhase.
|
|
||||||
gradleFlags ? [ "build" ],
|
|
||||||
# Enable debugging for the Gradle build; this will cause Gradle to run
|
|
||||||
# a debug server and wait for a JVM debugging client to attach.
|
|
||||||
enableDebug ? false,
|
|
||||||
# Additional code to run in the Gradle init script (init.gradle).
|
|
||||||
extraInit ? "",
|
|
||||||
# Override the default JDK used to run Gradle itself.
|
|
||||||
buildJdk ? null,
|
|
||||||
# Override functions which fetch dependency artifacts.
|
|
||||||
# Keys in this set are URL schemes such as "https" or "s3".
|
|
||||||
# Values are functions which take a dependency in the form
|
|
||||||
# `{ urls, hash }` and fetch into the Nix store. For example:
|
|
||||||
#
|
|
||||||
# {
|
|
||||||
# s3 = { name, urls, hash }: fetchs3 {
|
|
||||||
# s3url = builtins.head urls;
|
|
||||||
# # 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";
|
|
||||||
# };
|
|
||||||
# };
|
|
||||||
# }
|
|
||||||
fetchers ? { },
|
|
||||||
# Overlays for dependencies in the offline Maven repository.
|
|
||||||
#
|
|
||||||
# Acceps an attrset of dependencies (usually parsed from 'lockFile'), and produces an attrset
|
|
||||||
# containing dependencies to merge into the final set.
|
|
||||||
#
|
|
||||||
# The attrset is of the form:
|
|
||||||
#
|
|
||||||
# {
|
|
||||||
# "${group}:${module}:${version}" = <derivation>;
|
|
||||||
# # ...
|
|
||||||
# }
|
|
||||||
#
|
|
||||||
# A dependency derivation unpacks multiple source files into a single Maven-style directory named
|
|
||||||
# "${out}/${groupPath}/${module}/${version}/", where 'groupPath' is the dependency group ID with dot
|
|
||||||
# characters ('.') replaced by the path separator ('/').
|
|
||||||
#
|
|
||||||
# Examples:
|
|
||||||
#
|
|
||||||
# 1. Add or replace a dependency with a single JAR file:
|
|
||||||
#
|
|
||||||
# (_: {
|
|
||||||
# "com.squareup.okio:okio:3.9.0" = fetchurl {
|
|
||||||
# url = "https://repo.maven.apache.org/maven2/com/squareup/okio/okio/3.9.0/okio-3.9.0.jar";
|
|
||||||
# hash = "...";
|
|
||||||
# downloadToTemmp = true;
|
|
||||||
# postFetch = "install -Dt $out/com/squareup/okio/okio/3.9.0/ $downloadedFile"
|
|
||||||
# };
|
|
||||||
# })
|
|
||||||
#
|
|
||||||
# 2. Remove a dependency entirely:
|
|
||||||
#
|
|
||||||
# # This works because the result is filtered for values that are derivations.
|
|
||||||
# (_: {
|
|
||||||
# "org.apache.log4j:core:2.23.1" = null;
|
|
||||||
# })
|
|
||||||
overlays ? [ ],
|
|
||||||
...
|
|
||||||
}@args:
|
|
||||||
|
|
||||||
let
|
|
||||||
inherit (builtins) removeAttrs;
|
|
||||||
|
|
||||||
inherit (lib) versionAtLeast versionOlder;
|
|
||||||
|
|
||||||
offlineRepo = buildMavenRepo {
|
|
||||||
inherit
|
|
||||||
lockFile
|
|
||||||
pname
|
|
||||||
version
|
|
||||||
fetchers
|
|
||||||
overlays
|
|
||||||
;
|
|
||||||
};
|
|
||||||
|
|
||||||
initScript = writeText "init.gradle" ''
|
|
||||||
import org.gradle.util.GradleVersion
|
|
||||||
|
|
||||||
static boolean versionAtLeast(String version) {
|
|
||||||
return GradleVersion.current() >= GradleVersion.version(version)
|
|
||||||
}
|
|
||||||
|
|
||||||
static void configureRepos(RepositoryHandler repositories) {
|
|
||||||
repositories.configureEach { ArtifactRepository repo ->
|
|
||||||
if (repo instanceof MavenArtifactRepository) {
|
|
||||||
repo.setArtifactUrls(new HashSet<URI>())
|
|
||||||
repo.url 'file:${offlineRepo}'
|
|
||||||
repo.metadataSources {
|
|
||||||
gradleMetadata()
|
|
||||||
mavenPom()
|
|
||||||
artifact()
|
|
||||||
}
|
|
||||||
} else if (repo instanceof IvyArtifactRepository) {
|
|
||||||
repo.url 'file:${offlineRepo}'
|
|
||||||
repo.layout('maven')
|
|
||||||
repo.metadataSources {
|
|
||||||
gradleMetadata()
|
|
||||||
ivyDescriptor()
|
|
||||||
artifact()
|
|
||||||
}
|
|
||||||
} else if (repo instanceof UrlArtifactRepository) {
|
|
||||||
repo.url 'file:/homeless-shelter'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
beforeSettings { settings ->
|
|
||||||
configureRepos(settings.pluginManagement.repositories)
|
|
||||||
configureRepos(settings.buildscript.repositories)
|
|
||||||
if (versionAtLeast("6.8")) {
|
|
||||||
configureRepos(settings.dependencyResolutionManagement.repositories)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
beforeProject { project ->
|
|
||||||
configureRepos(project.buildscript.repositories)
|
|
||||||
configureRepos(project.repositories)
|
|
||||||
}
|
|
||||||
|
|
||||||
${extraInit}
|
|
||||||
'';
|
|
||||||
|
|
||||||
buildGradlePackage = stdenv.mkDerivation (
|
|
||||||
finalAttrs:
|
|
||||||
{
|
|
||||||
|
|
||||||
inherit
|
|
||||||
buildJdk
|
|
||||||
enableParallelBuilding
|
|
||||||
enableDebug
|
|
||||||
gradle
|
|
||||||
gradleFlags
|
|
||||||
pname
|
|
||||||
version
|
|
||||||
;
|
|
||||||
|
|
||||||
dontStrip = true;
|
|
||||||
|
|
||||||
nativeBuildInputs = [ finalAttrs.gradle ];
|
|
||||||
|
|
||||||
buildPhase =
|
|
||||||
let
|
|
||||||
finalGradleFlags =
|
|
||||||
[
|
|
||||||
"--console=plain"
|
|
||||||
"--no-build-cache"
|
|
||||||
"--no-configuration-cache"
|
|
||||||
"--no-daemon"
|
|
||||||
"--no-watch-fs"
|
|
||||||
"--offline"
|
|
||||||
]
|
|
||||||
++ lib.optional (finalAttrs.buildJdk != null) "-Dorg.gradle.java.home=${finalAttrs.buildJdk.home}"
|
|
||||||
++ lib.optional finalAttrs.enableDebug "-Dorg.gradle.debug=true"
|
|
||||||
++ lib.optional finalAttrs.enableParallelBuilding "--parallel"
|
|
||||||
++ lib.optional (versionAtLeast finalAttrs.gradle.version "8.0") "--init-script=${initScript}"
|
|
||||||
++ finalAttrs.gradleFlags;
|
|
||||||
in
|
|
||||||
''
|
|
||||||
runHook preBuild
|
|
||||||
|
|
||||||
(
|
|
||||||
set -eux
|
|
||||||
|
|
||||||
export NIX_OFFLINE_REPO='${offlineRepo}'
|
|
||||||
export GRADLE_USER_HOME="$(mktemp -d)"
|
|
||||||
|
|
||||||
${lib.optionalString (versionOlder finalAttrs.gradle.version "8.0") ''
|
|
||||||
# Work around https://github.com/gradle/gradle/issues/1055
|
|
||||||
mkdir -p "$GRADLE_USER_HOME/init.d"
|
|
||||||
ln -s ${initScript} "$GRADLE_USER_HOME/init.d/nix-init.gradle"
|
|
||||||
''}
|
|
||||||
|
|
||||||
gradle ${builtins.toString finalGradleFlags}
|
|
||||||
)
|
|
||||||
|
|
||||||
runHook postBuild
|
|
||||||
'';
|
|
||||||
|
|
||||||
passthru = {
|
|
||||||
inherit offlineRepo;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
// removeAttrs args [
|
|
||||||
"lockFile"
|
|
||||||
"extraInit"
|
|
||||||
"fetchers"
|
|
||||||
"overlays"
|
|
||||||
]
|
|
||||||
);
|
|
||||||
in
|
|
||||||
buildGradlePackage
|
|
||||||
145
nix/build-gradle-package.nix
Normal file
145
nix/build-gradle-package.nix
Normal file
@@ -0,0 +1,145 @@
|
|||||||
|
# This file is generated by gradle2nix.
|
||||||
|
#
|
||||||
|
# Example usage (e.g. in default.nix):
|
||||||
|
#
|
||||||
|
# with (import <nixpkgs> {});
|
||||||
|
# let
|
||||||
|
# buildGradle = callPackage ./gradle.nix {};
|
||||||
|
# in
|
||||||
|
# buildGradle {
|
||||||
|
# lockFile = ./gradle.lock;
|
||||||
|
#
|
||||||
|
# src = ./.;
|
||||||
|
#
|
||||||
|
# gradleFlags = [ "installDist" ];
|
||||||
|
#
|
||||||
|
# installPhase = ''
|
||||||
|
# mkdir -p $out
|
||||||
|
# cp -r app/build/install/myproject $out
|
||||||
|
# '';
|
||||||
|
# }
|
||||||
|
|
||||||
|
{
|
||||||
|
lib,
|
||||||
|
stdenv,
|
||||||
|
gradle,
|
||||||
|
buildMavenRepo,
|
||||||
|
gradleSetupHook,
|
||||||
|
writeText,
|
||||||
|
}:
|
||||||
|
|
||||||
|
{
|
||||||
|
# Path to the lockfile generated by gradle2nix (e.g. gradle.lock).
|
||||||
|
lockFile ? null,
|
||||||
|
pname ? "project",
|
||||||
|
version ? null,
|
||||||
|
# The Gradle package to use. Default is 'pkgs.gradle'.
|
||||||
|
gradlePackage ? gradle,
|
||||||
|
# Override the default JDK used to run Gradle itself.
|
||||||
|
buildJdk ? null,
|
||||||
|
# Override functions which fetch dependency artifacts.
|
||||||
|
# Names in this set are URL schemes such as "https" or "s3".
|
||||||
|
# Values are functions which take a dependency in the form
|
||||||
|
# `{ urls, hash }` and fetch into the Nix store. For example:
|
||||||
|
#
|
||||||
|
# {
|
||||||
|
# s3 = { name, urls, hash }: fetchs3 {
|
||||||
|
# s3url = builtins.head urls;
|
||||||
|
# # 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";
|
||||||
|
# };
|
||||||
|
# };
|
||||||
|
# }
|
||||||
|
fetchers ? { },
|
||||||
|
# Override artifacts in the offline Maven repository.
|
||||||
|
#
|
||||||
|
# This is an attrset is of the form:
|
||||||
|
#
|
||||||
|
# {
|
||||||
|
# "${group}:${module}:${version}" = {
|
||||||
|
# "${filename}" = <override function>;
|
||||||
|
# }
|
||||||
|
# }
|
||||||
|
#
|
||||||
|
# The override function takes the original derivation from 'fetchers' (e.g. the result of
|
||||||
|
# 'fetchurl') and produces a new derivation to replace it.
|
||||||
|
#
|
||||||
|
# Examples:
|
||||||
|
#
|
||||||
|
# 1. Replace a dependency's JAR artifact:
|
||||||
|
#
|
||||||
|
# {
|
||||||
|
# "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"
|
||||||
|
# };
|
||||||
|
# }
|
||||||
|
#
|
||||||
|
# 2. Patch a JAR containing native binaries:
|
||||||
|
#
|
||||||
|
# {
|
||||||
|
# "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
|
||||||
|
# '';
|
||||||
|
# }
|
||||||
|
# }
|
||||||
|
overrides ? { },
|
||||||
|
...
|
||||||
|
}@args:
|
||||||
|
|
||||||
|
let
|
||||||
|
inherit (builtins) removeAttrs;
|
||||||
|
|
||||||
|
gradleSetupHook' = gradleSetupHook.overrideAttrs (_: {
|
||||||
|
propagatedBuildInputs = [ gradlePackage ];
|
||||||
|
});
|
||||||
|
|
||||||
|
offlineRepo =
|
||||||
|
if lockFile != null then buildMavenRepo { inherit lockFile fetchers overrides; } else null;
|
||||||
|
|
||||||
|
buildGradlePackage = stdenv.mkDerivation (
|
||||||
|
finalAttrs:
|
||||||
|
{
|
||||||
|
|
||||||
|
inherit buildJdk pname version;
|
||||||
|
|
||||||
|
inherit (offlineRepo) gradleInitScript;
|
||||||
|
|
||||||
|
dontStrip = true;
|
||||||
|
|
||||||
|
nativeBuildInputs = (args.nativeBuildInputs or [ ]) ++ [ gradleSetupHook' ];
|
||||||
|
|
||||||
|
gradleFlags =
|
||||||
|
[ "--console=plain" ]
|
||||||
|
++ lib.optional (finalAttrs.buildJdk != null) "-Dorg.gradle.java.home=${finalAttrs.buildJdk.home}";
|
||||||
|
|
||||||
|
passthru =
|
||||||
|
lib.optionalAttrs (offlineRepo != null) { inherit offlineRepo; } // (args.passthru or { });
|
||||||
|
}
|
||||||
|
// removeAttrs args [
|
||||||
|
"gradle"
|
||||||
|
"gradleInitScript"
|
||||||
|
"lockFile"
|
||||||
|
"fetchers"
|
||||||
|
"nativeBuildInputs"
|
||||||
|
"overlays"
|
||||||
|
"passthru"
|
||||||
|
]
|
||||||
|
);
|
||||||
|
in
|
||||||
|
buildGradlePackage
|
||||||
@@ -2,16 +2,15 @@
|
|||||||
lib,
|
lib,
|
||||||
stdenv,
|
stdenv,
|
||||||
fetchurl,
|
fetchurl,
|
||||||
|
substitute,
|
||||||
symlinkJoin,
|
symlinkJoin,
|
||||||
}:
|
}:
|
||||||
|
|
||||||
{
|
{
|
||||||
# Path to the lockfile generated by gradle2nix (e.g. gradle.lock).
|
# Path to the lockfile generated by gradle2nix (e.g. gradle.lock).
|
||||||
lockFile,
|
lockFile,
|
||||||
pname ? "project",
|
|
||||||
version ? null,
|
|
||||||
# Override functions which fetch dependency artifacts.
|
# Override functions which fetch dependency artifacts.
|
||||||
# Keys in this set are URL schemes such as "https" or "s3".
|
# Names in this set are URL schemes such as "https" or "s3".
|
||||||
# Values are functions which take a dependency in the form
|
# Values are functions which take a dependency in the form
|
||||||
# `{ urls, hash }` and fetch into the Nix store. For example:
|
# `{ urls, hash }` and fetch into the Nix store. For example:
|
||||||
#
|
#
|
||||||
@@ -28,42 +27,50 @@
|
|||||||
# };
|
# };
|
||||||
# }
|
# }
|
||||||
fetchers ? { },
|
fetchers ? { },
|
||||||
# Overlays for dependencies in the offline Maven repository.
|
# Override artifacts in the offline Maven repository.
|
||||||
#
|
#
|
||||||
# Acceps an attrset of dependencies (usually parsed from 'lockFile'), and produces an attrset
|
# This is an attrset is of the form:
|
||||||
# containing dependencies to merge into the final set.
|
|
||||||
#
|
|
||||||
# The attrset is of the form:
|
|
||||||
#
|
#
|
||||||
# {
|
# {
|
||||||
# "${group}:${module}:${version}" = <derivation>;
|
# "${group}:${module}:${version}" = {
|
||||||
# # ...
|
# "${filename}" = <override function>;
|
||||||
|
# }
|
||||||
# }
|
# }
|
||||||
#
|
#
|
||||||
# A dependency derivation unpacks multiple source files into a single Maven-style directory named
|
# The override function takes the original derivation from 'fetchers' (e.g. the result of
|
||||||
# "${out}/${groupPath}/${module}/${version}/", where 'groupPath' is the dependency group ID with dot
|
# 'fetchurl') and produces a new derivation to replace it.
|
||||||
# characters ('.') replaced by the path separator ('/').
|
|
||||||
#
|
#
|
||||||
# Examples:
|
# Examples:
|
||||||
#
|
#
|
||||||
# 1. Add or replace a dependency with a single JAR file:
|
# 1. Replace a dependency's JAR artifact:
|
||||||
#
|
#
|
||||||
# (_: {
|
# {
|
||||||
# "com.squareup.okio:okio:3.9.0" = fetchurl {
|
# "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";
|
# url = "https://repo.maven.apache.org/maven2/com/squareup/okio/okio/3.9.0/okio-3.9.0.jar";
|
||||||
# hash = "...";
|
# hash = "...";
|
||||||
# downloadToTemmp = true;
|
# downloadToTemp = true;
|
||||||
# postFetch = "install -Dt $out/com/squareup/okio/okio/3.9.0/ $downloadedFile"
|
# postFetch = "install -Dt $out/com/squareup/okio/okio/3.9.0/ $downloadedFile"
|
||||||
# };
|
# };
|
||||||
# })
|
# }
|
||||||
#
|
#
|
||||||
# 2. Remove a dependency entirely:
|
# 2. Patch a JAR containing native binaries:
|
||||||
#
|
#
|
||||||
# # This works because the result is filtered for values that are derivations.
|
# {
|
||||||
# (_: {
|
# "com.android.tools.build:aapt2:8.5.0-rc02-11315950" = {
|
||||||
# "org.apache.log4j:core:2.23.1" = null;
|
# "aapt2-8.5.0-rc02-11315950-linux.jar" = src: runCommandCC src.name {
|
||||||
# })
|
# nativeBuildInputs = [ jdk autoPatchelfHook ];
|
||||||
overlays ? [ ],
|
# 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
|
||||||
|
# '';
|
||||||
|
# }
|
||||||
|
# }
|
||||||
|
overrides ? { },
|
||||||
}:
|
}:
|
||||||
|
|
||||||
let
|
let
|
||||||
@@ -116,25 +123,28 @@ let
|
|||||||
} // fetchers;
|
} // fetchers;
|
||||||
|
|
||||||
fetch =
|
fetch =
|
||||||
name:
|
coords: overrides: name:
|
||||||
{ url, hash }:
|
{ url, hash }:
|
||||||
let
|
let
|
||||||
scheme = head (builtins.match "([a-z0-9+.-]+)://.*" url);
|
scheme = head (builtins.match "([a-z0-9+.-]+)://.*" url);
|
||||||
fetch' = getAttr scheme fetchers';
|
fetch' = getAttr scheme fetchers';
|
||||||
|
artifact = fetch' { inherit url hash; };
|
||||||
|
override = overrides.name or lib.id;
|
||||||
in
|
in
|
||||||
fetch' { inherit url hash; };
|
override artifact;
|
||||||
|
|
||||||
mkModule =
|
mkModule =
|
||||||
id: artifacts:
|
id: artifacts:
|
||||||
let
|
let
|
||||||
coords = toCoordinates id;
|
coords = toCoordinates id;
|
||||||
modulePath = "${replaceStrings [ "." ] [ "/" ] coords.group}/${coords.module}/${coords.version}";
|
modulePath = "${replaceStrings [ "." ] [ "/" ] coords.group}/${coords.module}/${coords.version}";
|
||||||
|
moduleOverrides = overrides.${id} or { };
|
||||||
in
|
in
|
||||||
stdenv.mkDerivation {
|
stdenv.mkDerivation {
|
||||||
pname = sanitizeDerivationName "${coords.group}-${coords.module}";
|
pname = sanitizeDerivationName "${coords.group}-${coords.module}";
|
||||||
version = coords.uniqueVersion;
|
version = coords.uniqueVersion;
|
||||||
|
|
||||||
srcs = mapAttrsToList fetch artifacts;
|
srcs = mapAttrsToList (fetch coords moduleOverrides) artifacts;
|
||||||
|
|
||||||
dontPatch = true;
|
dontPatch = true;
|
||||||
dontConfigure = true;
|
dontConfigure = true;
|
||||||
@@ -156,34 +166,24 @@ let
|
|||||||
allowSubstitutes = false;
|
allowSubstitutes = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
# Intermediate dependency spec.
|
modulePaths =
|
||||||
#
|
|
||||||
# We want to allow overriding dependencies via the 'dependencies' function,
|
|
||||||
# so we pass an intermediate set that maps each Maven coordinate to the
|
|
||||||
# derivation created with 'mkModule'. This allows users extra flexibility
|
|
||||||
# to do things like patching native libraries with patchelf or replacing
|
|
||||||
# artifacts entirely.
|
|
||||||
lockedDependencies =
|
|
||||||
final:
|
|
||||||
if lockFile == null then
|
|
||||||
{ }
|
|
||||||
else
|
|
||||||
let
|
|
||||||
lockedDependencySpecs = fromJSON (readFile lockFile);
|
|
||||||
in
|
|
||||||
mapAttrs mkModule lockedDependencySpecs;
|
|
||||||
|
|
||||||
finalDependencies =
|
|
||||||
let
|
let
|
||||||
composedExtension = lib.composeManyExtensions overlays;
|
dependencies = fromJSON (readFile lockFile);
|
||||||
extended = lib.extends composedExtension lockedDependencies;
|
modules = mapAttrs mkModule dependencies;
|
||||||
fixed = lib.fix extended;
|
|
||||||
in
|
in
|
||||||
filter lib.isDerivation (attrValues fixed);
|
filter lib.isDerivation (attrValues modules);
|
||||||
|
|
||||||
offlineRepo = symlinkJoin {
|
mavenRepo = symlinkJoin {
|
||||||
name = if version != null then "${pname}-${version}-gradle-repo" else "${pname}-gradle-repo";
|
name = "gradle-maven-repo";
|
||||||
paths = finalDependencies;
|
paths = modulePaths;
|
||||||
|
passthru.gradleInitScript = substitute {
|
||||||
|
src = ./init.gradle;
|
||||||
|
substitutions = [
|
||||||
|
"--replace"
|
||||||
|
"@mavenRepo@"
|
||||||
|
"${mavenRepo}"
|
||||||
|
];
|
||||||
|
};
|
||||||
};
|
};
|
||||||
in
|
in
|
||||||
offlineRepo
|
mavenRepo
|
||||||
42
nix/init.gradle
Normal file
42
nix/init.gradle
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
import org.gradle.util.GradleVersion
|
||||||
|
|
||||||
|
static boolean versionAtLeast(String version) {
|
||||||
|
return GradleVersion.current() >= GradleVersion.version(version)
|
||||||
|
}
|
||||||
|
|
||||||
|
static void configureRepos(RepositoryHandler repositories) {
|
||||||
|
repositories.configureEach { ArtifactRepository repo ->
|
||||||
|
if (repo instanceof MavenArtifactRepository) {
|
||||||
|
repo.setArtifactUrls(new HashSet<URI>())
|
||||||
|
repo.url 'file:@mavenRepo@'
|
||||||
|
repo.metadataSources {
|
||||||
|
gradleMetadata()
|
||||||
|
mavenPom()
|
||||||
|
artifact()
|
||||||
|
}
|
||||||
|
} else if (repo instanceof IvyArtifactRepository) {
|
||||||
|
repo.url 'file:@mavenRepo@'
|
||||||
|
repo.layout('maven')
|
||||||
|
repo.metadataSources {
|
||||||
|
gradleMetadata()
|
||||||
|
ivyDescriptor()
|
||||||
|
artifact()
|
||||||
|
}
|
||||||
|
} else if (repo instanceof UrlArtifactRepository) {
|
||||||
|
repo.url 'file:/homeless-shelter'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
beforeSettings { settings ->
|
||||||
|
configureRepos(settings.pluginManagement.repositories)
|
||||||
|
configureRepos(settings.buildscript.repositories)
|
||||||
|
if (versionAtLeast("6.8")) {
|
||||||
|
configureRepos(settings.dependencyResolutionManagement.repositories)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
beforeProject { project ->
|
||||||
|
configureRepos(project.buildscript.repositories)
|
||||||
|
configureRepos(project.repositories)
|
||||||
|
}
|
||||||
125
nix/setup-hook.sh
Normal file
125
nix/setup-hook.sh
Normal file
@@ -0,0 +1,125 @@
|
|||||||
|
# shellcheck shell=bash disable=SC2206,SC2155
|
||||||
|
|
||||||
|
gradleConfigurePhase() {
|
||||||
|
runHook preConfigure
|
||||||
|
|
||||||
|
if ! [[ -v enableParallelBuilding ]]; then
|
||||||
|
enableParallelBuilding=1
|
||||||
|
echo "gradle: enabled parallel building"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if ! [[ -v enableParallelChecking ]]; then
|
||||||
|
enableParallelChecking=1
|
||||||
|
echo "gradle: enabled parallel checking"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if ! [[ -v enableParallelInstalling ]]; then
|
||||||
|
enableParallelInstalling=1
|
||||||
|
echo "gradle: enabled parallel installing"
|
||||||
|
fi
|
||||||
|
|
||||||
|
export GRADLE_USER_HOME="$(mktemp -d)"
|
||||||
|
|
||||||
|
if [ -n "$gradleInitScript" ]; then
|
||||||
|
if [ ! -f "$gradleInitScript" ]; then
|
||||||
|
echo "gradleInitScript is not a file path: $gradleInitScript"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
mkdir -p "$GRADLE_USER_HOME/init.d"
|
||||||
|
ln -s "$gradleInitScript" "$GRADLE_USER_HOME/init.d"
|
||||||
|
fi
|
||||||
|
|
||||||
|
runHook postConfigure
|
||||||
|
}
|
||||||
|
|
||||||
|
gradleBuildPhase() {
|
||||||
|
runHook preBuild
|
||||||
|
|
||||||
|
if [ -z "${gradleBuildFlags:-}" ] && [ -z "${gradleBuildFlagsArray[*]}" ]; then
|
||||||
|
echo "gradleBuildFlags is not set, doing nothing"
|
||||||
|
else
|
||||||
|
local flagsArray=(
|
||||||
|
$gradleFlags "${gradleFlagsArray[@]}"
|
||||||
|
$gradleBuildFlags "${gradleBuildFlagsArray[@]}"
|
||||||
|
)
|
||||||
|
|
||||||
|
if [ -n "$enableParallelBuilding" ]; then
|
||||||
|
flagsArray+=(--parallel --max-workers ${NIX_BUILD_CORES})
|
||||||
|
else
|
||||||
|
flagsArray+=(--no-parallel)
|
||||||
|
fi
|
||||||
|
|
||||||
|
echoCmd 'gradleBuildPhase flags' "${flagsArray[@]}"
|
||||||
|
|
||||||
|
gradle "${flagsArray[@]}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
runHook postBuild
|
||||||
|
}
|
||||||
|
|
||||||
|
gradleCheckPhase() {
|
||||||
|
runHook preCheck
|
||||||
|
|
||||||
|
if [ -z "${gradleCheckFlags:-}" ] && [ -z "${gradleCheckFlagsArray[*]}" ]; then
|
||||||
|
echo "gradleCheckFlags is not set, doing nothing"
|
||||||
|
else
|
||||||
|
local flagsArray=(
|
||||||
|
$gradleFlags "${gradleFlagsArray[@]}"
|
||||||
|
$gradleCheckFlags "${gradleCheckFlagsArray[@]}"
|
||||||
|
${gradleCheckTasks:-check}
|
||||||
|
)
|
||||||
|
|
||||||
|
if [ -n "$enableParallelChecking" ]; then
|
||||||
|
flagsArray+=(--parallel --max-workers ${NIX_BUILD_CORES})
|
||||||
|
else
|
||||||
|
flagsArray+=(--no-parallel)
|
||||||
|
fi
|
||||||
|
|
||||||
|
echoCmd 'gradleCheckPhase flags' "${flagsArray[@]}"
|
||||||
|
|
||||||
|
gradle "${flagsArray[@]}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
runHook postCheck
|
||||||
|
}
|
||||||
|
|
||||||
|
gradleInstallPhase() {
|
||||||
|
runHook preInstall
|
||||||
|
|
||||||
|
if [ -z "${gradleInstallFlags:-}" ] && [ -z "${gradleInstallFlagsArray[*]}" ]; then
|
||||||
|
echo "gradleInstallFlags is not set, doing nothing"
|
||||||
|
else
|
||||||
|
local flagsArray=(
|
||||||
|
$gradleFlags "${gradleFlagsArray[@]}"
|
||||||
|
$gradleInstallFlags "${gradleInstallFlagsArray[@]}"
|
||||||
|
)
|
||||||
|
|
||||||
|
if [ -n "$enableParallelInstalling" ]; then
|
||||||
|
flagsArray+=(--parallel --max-workers ${NIX_BUILD_CORES})
|
||||||
|
else
|
||||||
|
flagsArray+=(--no-parallel)
|
||||||
|
fi
|
||||||
|
|
||||||
|
echoCmd 'gradleInstallPhase flags' "${flagsArray[@]}"
|
||||||
|
|
||||||
|
gradle "${flagsArray[@]}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
runHook postInstall
|
||||||
|
}
|
||||||
|
|
||||||
|
if [ -z "${dontUseGradleConfigure-}" ] && [ -z "${configurePhase-}" ]; then
|
||||||
|
configurePhase=gradleConfigurePhase
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -z "${dontUseGradleBuild-}" ] && [ -z "${buildPhase-}" ]; then
|
||||||
|
buildPhase=gradleBuildPhase
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -z "${dontUseGradleCheck-}" ] && [ -z "${checkPhase-}" ]; then
|
||||||
|
checkPhase=gradleCheckPhase
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -z "${dontUseGradleInstall-}" ] && [ -z "${installPhase-}" ]; then
|
||||||
|
installPhase=gradleInstallPhase
|
||||||
|
fi
|
||||||
@@ -1,7 +1,8 @@
|
|||||||
package org.nixos.gradle2nix
|
package org.nixos.gradle2nix
|
||||||
|
|
||||||
abstract class Gradle2NixPlugin : AbstractGradle2NixPlugin(
|
abstract class Gradle2NixPlugin :
|
||||||
GradleCacheAccessFactoryBase,
|
AbstractGradle2NixPlugin(
|
||||||
DependencyExtractorApplierBase,
|
GradleCacheAccessFactoryBase,
|
||||||
ResolveAllArtifactsApplierBase,
|
DependencyExtractorApplierBase,
|
||||||
)
|
ResolveAllArtifactsApplierBase,
|
||||||
|
)
|
||||||
|
|||||||
@@ -4,12 +4,12 @@ import org.gradle.api.internal.artifacts.ivyservice.ArtifactCachesProvider
|
|||||||
import org.gradle.api.invocation.Gradle
|
import org.gradle.api.invocation.Gradle
|
||||||
|
|
||||||
object GradleCacheAccessFactoryBase : GradleCacheAccessFactory {
|
object GradleCacheAccessFactoryBase : GradleCacheAccessFactory {
|
||||||
override fun create(gradle: Gradle): GradleCacheAccess {
|
override fun create(gradle: Gradle): GradleCacheAccess = GradleCacheAccessBase(gradle)
|
||||||
return GradleCacheAccessBase(gradle)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class GradleCacheAccessBase(gradle: Gradle) : GradleCacheAccess {
|
class GradleCacheAccessBase(
|
||||||
|
gradle: Gradle,
|
||||||
|
) : GradleCacheAccess {
|
||||||
private val artifactCachesProvider = gradle.service<ArtifactCachesProvider>()
|
private val artifactCachesProvider = gradle.service<ArtifactCachesProvider>()
|
||||||
|
|
||||||
override fun useCache(block: () -> Unit) {
|
override fun useCache(block: () -> Unit) {
|
||||||
|
|||||||
@@ -116,22 +116,27 @@ private fun cachedComponentId(file: File): DependencyCoordinates? {
|
|||||||
val parts = file.invariantSeparatorsPath.split('/')
|
val parts = file.invariantSeparatorsPath.split('/')
|
||||||
if (parts.size < 6) return null
|
if (parts.size < 6) return null
|
||||||
if (parts[parts.size - 6] != "files-2.1") return null
|
if (parts[parts.size - 6] != "files-2.1") return null
|
||||||
return parts.dropLast(2).takeLast(3).joinToString(":").let(DefaultDependencyCoordinates::parse)
|
return parts
|
||||||
|
.dropLast(2)
|
||||||
|
.takeLast(3)
|
||||||
|
.joinToString(":")
|
||||||
|
.let(DefaultDependencyCoordinates::parse)
|
||||||
}
|
}
|
||||||
|
|
||||||
@OptIn(ExperimentalSerializationApi::class)
|
@OptIn(ExperimentalSerializationApi::class)
|
||||||
private fun parseFileMappings(file: File): Map<String, String>? =
|
private fun parseFileMappings(file: File): Map<String, String>? =
|
||||||
try {
|
try {
|
||||||
Json.decodeFromStream<JsonObject>(file.inputStream())
|
Json
|
||||||
.jsonObject["variants"]?.jsonArray
|
.decodeFromStream<JsonObject>(file.inputStream())
|
||||||
|
.jsonObject["variants"]
|
||||||
|
?.jsonArray
|
||||||
?.flatMap { it.jsonObject["files"]?.jsonArray ?: emptyList() }
|
?.flatMap { it.jsonObject["files"]?.jsonArray ?: emptyList() }
|
||||||
?.map { it.jsonObject }
|
?.map { it.jsonObject }
|
||||||
?.mapNotNull {
|
?.mapNotNull {
|
||||||
val name = it["name"]?.jsonPrimitive?.content ?: return@mapNotNull null
|
val name = it["name"]?.jsonPrimitive?.content ?: return@mapNotNull null
|
||||||
val url = it["url"]?.jsonPrimitive?.content ?: return@mapNotNull null
|
val url = it["url"]?.jsonPrimitive?.content ?: return@mapNotNull null
|
||||||
if (name != url) name to url else null
|
if (name != url) name to url else null
|
||||||
}
|
}?.toMap()
|
||||||
?.toMap()
|
|
||||||
?.takeUnless { it.isEmpty() }
|
?.takeUnless { it.isEmpty() }
|
||||||
} catch (e: Throwable) {
|
} catch (e: Throwable) {
|
||||||
null
|
null
|
||||||
|
|||||||
@@ -17,11 +17,10 @@ class DependencySetModelBuilder(
|
|||||||
override fun buildAll(
|
override fun buildAll(
|
||||||
modelName: String,
|
modelName: String,
|
||||||
project: Project,
|
project: Project,
|
||||||
): DependencySet {
|
): DependencySet =
|
||||||
return dependencyExtractor.buildDependencySet(
|
dependencyExtractor.buildDependencySet(
|
||||||
cacheAccess,
|
cacheAccess,
|
||||||
checksumService,
|
checksumService,
|
||||||
fileStoreAndIndexProvider,
|
fileStoreAndIndexProvider,
|
||||||
)
|
)
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -38,14 +38,15 @@ abstract class AbstractResolveAllArtifactsApplier : ResolveAllArtifactsApplier {
|
|||||||
|
|
||||||
abstract class ResolveProjectDependenciesTask : DefaultTask() {
|
abstract class ResolveProjectDependenciesTask : DefaultTask() {
|
||||||
@Internal
|
@Internal
|
||||||
protected fun getReportableConfigurations(): List<Configuration> {
|
protected fun getReportableConfigurations(): List<Configuration> =
|
||||||
return project.configurations.filter { (it as? DeprecatableConfiguration)?.canSafelyBeResolved() ?: true }
|
project.configurations.filter {
|
||||||
}
|
(it as? DeprecatableConfiguration)?.canSafelyBeResolved() ?: true
|
||||||
|
}
|
||||||
|
|
||||||
protected fun Configuration.artifactFiles(): FileCollection {
|
protected fun Configuration.artifactFiles(): FileCollection =
|
||||||
return incoming.artifactView { viewConfiguration ->
|
incoming
|
||||||
viewConfiguration.isLenient = true
|
.artifactView { viewConfiguration ->
|
||||||
viewConfiguration.componentFilter { it is ModuleComponentIdentifier }
|
viewConfiguration.isLenient = true
|
||||||
}.files
|
viewConfiguration.componentFilter { it is ModuleComponentIdentifier }
|
||||||
}
|
}.files
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,12 +18,14 @@ object DependencyExtractorApplierG8 : DependencyExtractorApplier {
|
|||||||
extractor: DependencyExtractor,
|
extractor: DependencyExtractor,
|
||||||
) {
|
) {
|
||||||
val serviceProvider =
|
val serviceProvider =
|
||||||
gradle.sharedServices.registerIfAbsent(
|
gradle.sharedServices
|
||||||
"nixDependencyExtractor",
|
.registerIfAbsent(
|
||||||
DependencyExtractorService::class.java,
|
"nixDependencyExtractor",
|
||||||
) {}.map { service ->
|
DependencyExtractorService::class.java,
|
||||||
service.apply { this.extractor = extractor }
|
) {}
|
||||||
}
|
.map { service ->
|
||||||
|
service.apply { this.extractor = extractor }
|
||||||
|
}
|
||||||
|
|
||||||
gradle.service<BuildEventListenerRegistryInternal>().onOperationCompletion(serviceProvider)
|
gradle.service<BuildEventListenerRegistryInternal>().onOperationCompletion(serviceProvider)
|
||||||
}
|
}
|
||||||
@@ -31,7 +33,9 @@ object DependencyExtractorApplierG8 : DependencyExtractorApplier {
|
|||||||
|
|
||||||
@Suppress("UnstableApiUsage")
|
@Suppress("UnstableApiUsage")
|
||||||
internal abstract class DependencyExtractorService :
|
internal abstract class DependencyExtractorService :
|
||||||
BuildService<BuildServiceParameters.None>, BuildOperationListener, AutoCloseable {
|
BuildService<BuildServiceParameters.None>,
|
||||||
|
BuildOperationListener,
|
||||||
|
AutoCloseable {
|
||||||
var extractor: DependencyExtractor? = null
|
var extractor: DependencyExtractor? = null
|
||||||
|
|
||||||
override fun started(
|
override fun started(
|
||||||
|
|||||||
@@ -23,13 +23,12 @@ abstract class ResolveProjectDependenciesTaskG8
|
|||||||
) : ResolveProjectDependenciesTask() {
|
) : ResolveProjectDependenciesTask() {
|
||||||
private val artifactFiles = Cached.of { artifactFiles() }
|
private val artifactFiles = Cached.of { artifactFiles() }
|
||||||
|
|
||||||
private fun artifactFiles(): FileCollection {
|
private fun artifactFiles(): FileCollection =
|
||||||
return objects.fileCollection().from(
|
objects.fileCollection().from(
|
||||||
getReportableConfigurations().map { configuration ->
|
getReportableConfigurations().map { configuration ->
|
||||||
configuration.artifactFiles()
|
configuration.artifactFiles()
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
}
|
|
||||||
|
|
||||||
@TaskAction
|
@TaskAction
|
||||||
fun action() {
|
fun action() {
|
||||||
|
|||||||
@@ -1,7 +1,8 @@
|
|||||||
package org.nixos.gradle2nix
|
package org.nixos.gradle2nix
|
||||||
|
|
||||||
abstract class Gradle2NixPlugin : AbstractGradle2NixPlugin(
|
abstract class Gradle2NixPlugin :
|
||||||
GradleCacheAccessFactoryG80,
|
AbstractGradle2NixPlugin(
|
||||||
DependencyExtractorApplierG8,
|
GradleCacheAccessFactoryG80,
|
||||||
ResolveAllArtifactsApplierG8,
|
DependencyExtractorApplierG8,
|
||||||
)
|
ResolveAllArtifactsApplierG8,
|
||||||
|
)
|
||||||
|
|||||||
@@ -4,12 +4,12 @@ import org.gradle.api.internal.artifacts.ivyservice.ArtifactCachesProvider
|
|||||||
import org.gradle.api.invocation.Gradle
|
import org.gradle.api.invocation.Gradle
|
||||||
|
|
||||||
object GradleCacheAccessFactoryG80 : GradleCacheAccessFactory {
|
object GradleCacheAccessFactoryG80 : GradleCacheAccessFactory {
|
||||||
override fun create(gradle: Gradle): GradleCacheAccess {
|
override fun create(gradle: Gradle): GradleCacheAccess = GradleCacheAccessG80(gradle)
|
||||||
return GradleCacheAccessG80(gradle)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class GradleCacheAccessG80(gradle: Gradle) : GradleCacheAccess {
|
class GradleCacheAccessG80(
|
||||||
|
gradle: Gradle,
|
||||||
|
) : GradleCacheAccess {
|
||||||
private val artifactCachesProvider = gradle.service<ArtifactCachesProvider>()
|
private val artifactCachesProvider = gradle.service<ArtifactCachesProvider>()
|
||||||
|
|
||||||
override fun useCache(block: () -> Unit) {
|
override fun useCache(block: () -> Unit) {
|
||||||
|
|||||||
@@ -1,7 +1,8 @@
|
|||||||
package org.nixos.gradle2nix
|
package org.nixos.gradle2nix
|
||||||
|
|
||||||
abstract class Gradle2NixPlugin : AbstractGradle2NixPlugin(
|
abstract class Gradle2NixPlugin :
|
||||||
GradleCacheAccessFactoryG81,
|
AbstractGradle2NixPlugin(
|
||||||
DependencyExtractorApplierG8,
|
GradleCacheAccessFactoryG81,
|
||||||
ResolveAllArtifactsApplierG8,
|
DependencyExtractorApplierG8,
|
||||||
)
|
ResolveAllArtifactsApplierG8,
|
||||||
|
)
|
||||||
|
|||||||
@@ -4,12 +4,12 @@ import org.gradle.api.internal.artifacts.ivyservice.ArtifactCachesProvider
|
|||||||
import org.gradle.api.invocation.Gradle
|
import org.gradle.api.invocation.Gradle
|
||||||
|
|
||||||
object GradleCacheAccessFactoryG81 : GradleCacheAccessFactory {
|
object GradleCacheAccessFactoryG81 : GradleCacheAccessFactory {
|
||||||
override fun create(gradle: Gradle): GradleCacheAccess {
|
override fun create(gradle: Gradle): GradleCacheAccess = GradleCacheAccessG81(gradle)
|
||||||
return GradleCacheAccessG81(gradle)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class GradleCacheAccessG81(gradle: Gradle) : GradleCacheAccess {
|
class GradleCacheAccessG81(
|
||||||
|
gradle: Gradle,
|
||||||
|
) : GradleCacheAccess {
|
||||||
private val artifactCachesProvider = gradle.service<ArtifactCachesProvider>()
|
private val artifactCachesProvider = gradle.service<ArtifactCachesProvider>()
|
||||||
|
|
||||||
override fun useCache(block: () -> Unit) {
|
override fun useCache(block: () -> Unit) {
|
||||||
|
|||||||
Reference in New Issue
Block a user