Access intermediated build files after build?
Hi,
I'm trying to compile an Android app with gradle2nix which has worked out of the box. Thanks a lot already for implementing this tool!
The app has some special setup. It uses https://github.com/joshjdevl/libsodium-jni as an input for an additional library (say "libX") that itself is then compiled and used to build the app again.
This is the current non-nixified workflow:
- Build the app using gradle.
- Copy the files
build/intermediates/merged_native_libs/debug/out/lib/$ARCH/libsodiumjni.soto libX's folder. - Build the libX (including the libsodiumjni.so), resulting in
libX.so. - Copy
libX.sotoapp/src/main/jniLibs. - Build the app again, this time including libX.so.
As I said, the first step worked out of the box using gradle2nix!
The libsodiumjni.so file is not available after the build so the script that executes steps 2-4 doesn't work.
I believe the app is build twice because libsodiumjni.so is only available (as a build artefact) after the first build when gradle has downloaded it.
This doesn't feel like a proper workflow anyways.
Is there any way provided by gradle or gradle2nix to have libsodiumjni.so available before the actual build?
Ideally, I'd like to replace step 1 by something-that-just-fetches-the-deps and then only build the app once (step 5) with gradel2nix. I've looked into the generated gradle-env.nix and though maybe mkDep might be of some help here. I don't have experience with gradle so I am actually guessing.
Any help is appreciated.
Is this your own project, as in you control the source? Because I would suggest improving the Gradle build instead so you can build the project in one run.
Looking at libsodiumjni, libsodiumjni.so is prebuilt and included in the JAR/AAR artifact. So the build for libX should depend on a Copy task which extracts the library from the JAR/AAR, so libsodiumjni should be part of its own configuration. Something like:
val libsodium by configurations.registering
val copyLibsodium by tasks.registering(Copy::class) {
from(zipTree(libsodium.singleFile))
into("libX/build/libsodiumjni")
include("jni/*/libsodiumjni.so")
}
// I have no idea what builds libX, this is just an example
tasks.compileLibX {
dependsOn(copyLibsodium)
somehowIncludeLibrary("libX/build/libsodiumjni/jni/x86_64/libsodiumjni.so")
}
Alternatively, if you only have to do this in Nix, you can use the preBuild hook to copy artifacts into the right places for the build.
let
libsodiumjni = fetchzip {
url = "https://repo1.maven.org/maven2/com/github/joshjdevl/libsodiumjni/libsodium-jni-aar/2.0.2/libsodium-jni-aar-2.0.2.aar";
sha256 = "...";
};
arch = "x86_64"; # Or obtain from stdenv.hostPlatform / stdenv.targetPlatform
libX = buildGradle {
src = ./.;
gradleFlags = [ ":libX:assemble" ];
preBuild = ''
mkdir -p libX/build
cp ${libsodiumjni}/jni/${arch}/libsodiumjni.so libX/build/
'';
installPhase = ''
cp libX/build/libs/libX.so $out
'';
};
in
buildGradle {
src = ./.;
gradleFlags = [ ":app:assembleRelease" ];
preBuild = ''
mkdir -p app/src/main/jniLibs
cp "${libX}" app/src/main/jniLibs/
'';
installPhase = ''
cp app/build/outputs/apk/release/app.apk $out
'';
}
@tadfisher Thanks a lot for the quick and elaborate answer! I will see what I can do. Thank you so much again!