diff --git a/README.md b/README.md index 43b50df..f9b039d 100644 --- a/README.md +++ b/README.md @@ -71,7 +71,9 @@ buildGradleApplication { For further examples, checkout the [examples directory](./examples) -All available parameters of `buildGradleApplication` are documented in the [source code](https://github.com/raphiz/buildGradleApplication/blob/main/buildGradleApplication/default.nix) +All available parameters of `buildGradleApplication` are documented in the [source code](https://github.com/raphiz/buildGradleApplication/blob/main/buildGradle/buildGradleApplication.nix) + +For more control over the installation phase, you may use `buildGradleArtifact`, and extra arguments will be passed to mkDerivation, so you can tweak preBuild, postBuild, etc. You can use script `$linkToJars folder` from `buildPhase` or other phases in order to change every jar inside a folder with a link to nix store as an usual nix build would normally do. ## Rules @@ -198,7 +200,7 @@ buildGradleApplication { ### Rule #5: Using the `application` Plugin -Currently, the focus of this tool is to package Gradle applications. In order to launch a java application, we need both an main class as an entry point and a runtime classpath. The latter must contain both third-party dependencies fetched from a maven repository and project local libraries generated from other projects within the same build. +The main focus of this tool is to package Gradle applications with `buildGradleApplication`. In order to launch a java application, we need both an main class as an entry point and a runtime classpath. The latter must contain both third-party dependencies fetched from a maven repository and project local libraries generated from other projects within the same build. Gradle provides exactly that (a so called [Distribution](https://docs.gradle.org/current/userguide/distribution_plugin.html#distribution_plugin)) with the built in [`application` plugin](https://docs.gradle.org/current/userguide/application_plugin.html). The required configuration is quite reasonable: diff --git a/buildGradle/buildGradleApplication.nix b/buildGradle/buildGradleApplication.nix new file mode 100644 index 0000000..024c2dd --- /dev/null +++ b/buildGradle/buildGradleApplication.nix @@ -0,0 +1,71 @@ +{ + pkgs, + lib, + stdenvNoCC, + writeShellScript, + makeWrapper, + mkM2Repository, + updateVerificationMetadata, + buildGradleArtifact, +}: { + pname, + version, + src, + meta ? {}, + env ? {}, + jdk ? pkgs.jdk, + gradle ? pkgs.gradle, + buildInputs ? [], + nativeBuildInputs ? [], + dependencyFilter ? depSpec: true, + repositories ? ["https://plugins.gradle.org/m2/" "https://repo1.maven.org/maven2/"], + verificationFile ? "gradle/verification-metadata.xml", + buildTask ? ":installDist", + installLocation ? "build/install/*/", + ... +}@params: +buildGradleArtifact ({ + + installPhase = '' + runHook preInstall + directories=( $(shopt -s nullglob; echo ${installLocation}) ) + + if [ ''${#directories[@]} -eq 0 ]; then + echo "Error: The built gradle application could not be found at ${installLocation}. + Most likely the option 'installLocation' is not set correctly. + The default value for 'installLocation' only works when the application plugin is applied on the root project itself. + If you applied it on a sub-project, adapt 'installLocation' accordingly, for example 'installLocation = \"path/to/sub-project/build/install/*/\"'." 1>&2; + exit 1 + elif [ ''${#directories[@]} -gt 1 ]; then + echo "Error: The built gradle application could not be found at ${installLocation} because there are multiple matching directories (''${directories[@]}) + Please adapt 'installLocation' to be more specific, for example by removing any wildcards." 1>&2; + exit 1 + fi + + pushd ${installLocation} + + mkdir -p $out/lib/ + mv lib/*.jar $out/lib/ + $linkToJars $out/lib/ + + if [ -d agent-libs/ ]; then + mkdir -p $out/agent-libs/ + mv agent-libs/*.jar $out/agent-libs/ + $linkToJars} $out/agent-libs/ + fi + + mkdir -p $out/bin + + cp $(ls bin/* | grep -v ".bat") $out/bin/${pname} + + popd + runHook postInstall + ''; + + dontWrapGApps = true; + postFixup = '' + wrapProgram $out/bin/${pname} \ + --set-default JAVA_HOME "${jdk.home}" \ + ''${gappsWrapperArgs[@]} + ''; +} // params) diff --git a/buildGradleApplication/default.nix b/buildGradle/buildGradleArtifact.nix similarity index 62% rename from buildGradleApplication/default.nix rename to buildGradle/buildGradleArtifact.nix index 91c6d09..1e3e4b8 100644 --- a/buildGradleApplication/default.nix +++ b/buildGradle/buildGradleArtifact.nix @@ -20,47 +20,15 @@ repositories ? ["https://plugins.gradle.org/m2/" "https://repo1.maven.org/maven2/"], verificationFile ? "gradle/verification-metadata.xml", buildTask ? ":installDist", - installLocation ? "build/install/*/", -}: let + installPhase ? null, + ... +}@params: let m2Repository = mkM2Repository { inherit pname version src dependencyFilter repositories verificationFile; }; - # Prepare a script that will replace that jars with references into the NIX store. - linkScript = writeShellScript "link-to-jars" '' - declare -A fileByName - declare -A hashByName - ${ - lib.concatMapStringsSep "\n" - (dep: "fileByName[\"${dep.name}\"]=\"${builtins.toString dep.jar}\"\nhashByName[\"${dep.name}\"]=\"${builtins.toString dep.hash}\"") - (builtins.filter (dep: (lib.strings.hasSuffix ".jar" dep.name && !lib.strings.hasSuffix "-javadoc.jar" dep.name && !lib.strings.hasSuffix "-sources.jar" dep.name)) m2Repository.dependencies) - } - - for jar in "$1"/*.jar; do - dep=''${fileByName[$(basename "$jar")]} - if [[ -n "$dep" ]]; then - jarHash=$(sha256sum "$jar" | cut -c -64) - sriHash=''${hashByName[$(basename "$jar")]} - if [[ $sriHash == sha256-* ]]; then - referenceHash="$(echo ''${sriHash#sha256-} | base64 -d | ${pkgs.hexdump}/bin/hexdump -v -e '/1 "%02x"')" - else - referenceHash=$(sha256sum "$dep" | cut -c -64) - fi - - if [[ "$referenceHash" == "$jarHash" ]]; then - echo "Replacing $jar with nix store reference $dep" - rm "$jar" - ln -s "$dep" "$jar" - else - echo "Hash of $jar differs from expected store reference $dep" - fi - else - echo "No linking candidate found for $jar" - fi - done - ''; - - package = stdenvNoCC.mkDerivation { +in + stdenvNoCC.mkDerivation ({ inherit pname version src buildInputs env; meta = { @@ -95,49 +63,44 @@ runHook postBuild ''; - installPhase = '' - runHook preInstall - directories=( $(shopt -s nullglob; echo ${installLocation}) ) - - if [ ''${#directories[@]} -eq 0 ]; then - echo "Error: The built gradle application could not be found at ${installLocation}. - Most likely the option 'installLocation' is not set correctly. - The default value for 'installLocation' only works when the application plugin is applied on the root project itself. - If you applied it on a sub-project, adapt 'installLocation' accordingly, for example 'installLocation = \"path/to/sub-project/build/install/*/\"'." 1>&2; - exit 1 - elif [ ''${#directories[@]} -gt 1 ]; then - echo "Error: The built gradle application could not be found at ${installLocation} because there are multiple matching directories (''${directories[@]}) - Please adapt 'installLocation' to be more specific, for example by removing any wildcards." 1>&2; - exit 1 - fi - - pushd ${installLocation} + linkToJars = writeShellScript "link-to-jars" '' + declare -A fileByName + declare -A hashByName + ${ + lib.concatMapStringsSep "\n" + (dep: "fileByName[\"${dep.name}\"]=\"${builtins.toString dep.jar}\"\nhashByName[\"${dep.name}\"]=\"${builtins.toString dep.hash}\"") + (builtins.filter (dep: (lib.strings.hasSuffix ".jar" dep.name && !lib.strings.hasSuffix "-javadoc.jar" dep.name && !lib.strings.hasSuffix "-sources.jar" dep.name)) m2Repository.dependencies) + } - mkdir -p $out/lib/ - mv lib/*.jar $out/lib/ - echo ${linkScript} $out/lib/ - ${linkScript} $out/lib/ + for jar in "$1"/*.jar; do + dep=''${fileByName[$(basename "$jar")]} + if [[ -n "$dep" ]]; then + jarHash=$(sha256sum "$jar" | cut -c -64) + sriHash=''${hashByName[$(basename "$jar")]} + if [[ $sriHash == sha256-* ]]; then + referenceHash="$(echo ''${sriHash#sha256-} | base64 -d | ${pkgs.hexdump}/bin/hexdump -v -e '/1 "%02x"')" + else + referenceHash=$(sha256sum "$dep" | cut -c -64) + fi - if [ -d agent-libs/ ]; then - mkdir -p $out/agent-libs/ - mv agent-libs/*.jar $out/agent-libs/ - ${linkScript} $out/agent-libs/ + if [[ "$referenceHash" == "$jarHash" ]]; then + echo "Replacing $jar with nix store reference $dep" + rm "$jar" + ln -s "$dep" "$jar" + else + echo "Hash of $jar differs from expected store reference $dep" + fi + else + echo "No linking candidate found for $jar" fi + done + ''; - mkdir -p $out/bin - - cp $(ls bin/* | grep -v ".bat") $out/bin/${pname} - - popd - runHook postInstall - ''; - - dontWrapGApps = true; - postFixup = '' - wrapProgram $out/bin/${pname} \ - --set-default JAVA_HOME "${jdk.home}" \ - ''${gappsWrapperArgs[@]} + installPhase = '' + # Default build phase for buildGradleArtifact + echo 'buildGradleArtifact should specify an installPhase' + echo 'You can call $linkToJars} in order to replace jar files inside the parameter folder' + echo 'with links to nix store' + exit 1 ''; - }; -in - package + } // params) diff --git a/buildGradleApplication/init.gradle.kts b/buildGradle/init.gradle.kts similarity index 100% rename from buildGradleApplication/init.gradle.kts rename to buildGradle/init.gradle.kts diff --git a/buildGradleApplication/mkM2Repository.nix b/buildGradle/mkM2Repository.nix similarity index 100% rename from buildGradleApplication/mkM2Repository.nix rename to buildGradle/mkM2Repository.nix diff --git a/buildGradleApplication/parse.py b/buildGradle/parse.py similarity index 100% rename from buildGradleApplication/parse.py rename to buildGradle/parse.py diff --git a/flake.nix b/flake.nix index 6281786..00e972f 100644 --- a/flake.nix +++ b/flake.nix @@ -25,8 +25,9 @@ overlays = { default = final: prev: { fetchArtifact = prev.callPackage ./fetchArtefact/default.nix {}; - mkM2Repository = prev.callPackage ./buildGradleApplication/mkM2Repository.nix {}; - buildGradleApplication = prev.callPackage ./buildGradleApplication/default.nix {}; + mkM2Repository = prev.callPackage ./buildGradle/mkM2Repository.nix {}; + buildGradleArtifact = prev.callPackage ./buildGradle/buildGradleArtifact.nix {}; + buildGradleApplication = prev.callPackage ./buildGradle/buildGradleApplication.nix {}; updateVerificationMetadata = prev.callPackage ./update-verification-metadata/default.nix {}; gradleFromWrapper = import ./gradleFromWrapper final; }; @@ -43,18 +44,19 @@ pkgs = nixpkgs.legacyPackages.${system}; in { formatter = pkgs.alejandra; - legacyPackages = let + legacyPackages = rec { fetchArtifact = pkgs.callPackage ./fetchArtefact/default.nix {}; - mkM2Repository = pkgs.callPackage ./buildGradleApplication/mkM2Repository.nix { + mkM2Repository = pkgs.callPackage ./buildGradle/mkM2Repository.nix { inherit fetchArtifact; }; updateVerificationMetadata = pkgs.callPackage ./update-verification-metadata/default.nix {}; - buildGradleApplication = pkgs.callPackage ./buildGradleApplication/default.nix { + buildGradleArtifact = pkgs.callPackage ./buildGradle/buildGradleArtifact.nix { inherit mkM2Repository updateVerificationMetadata; }; + buildGradleApplication = pkgs.callPackage ./buildGradle/buildGradleApplication.nix { + inherit mkM2Repository updateVerificationMetadata buildGradleArtifact; + }; gradleFromWrapper = import ./gradleFromWrapper pkgs; - in { - inherit fetchArtifact mkM2Repository buildGradleApplication updateVerificationMetadata gradleFromWrapper; }; }; };