diff --git a/app/build.gradle.kts b/app/build.gradle.kts index c2c8797..e1eec01 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -1,3 +1,6 @@ +import javax.inject.Inject +import org.gradle.process.ExecOperations + plugins { alias(libs.plugins.android.application) alias(libs.plugins.kotlin.android) @@ -5,25 +8,22 @@ plugins { } // Build isodrive native binary from submodule (only if binaries are missing) -val buildIsodrive by tasks.registering { - group = "native" - description = "Build isodrive binary for all Android architectures" +abstract class BuildIsodriveTask @Inject constructor( + private val execOps: ExecOperations +) : DefaultTask() { - val isodriveDir = rootProject.file("isodrive") - val outputDir = file("src/main/assets/bin") - val architectures = listOf("arm64-v8a", "armeabi-v7a", "x86_64", "x86") + @get:InputDirectory + abstract val isodriveDir: DirectoryProperty - // Check if all binaries exist - val allBinariesExist = architectures.all { arch -> - outputDir.resolve("$arch/isodrive").exists() - } + @get:OutputDirectory + abstract val outputDir: DirectoryProperty - // Skip if all binaries already exist - onlyIf { !allBinariesExist } + @TaskAction + fun build() { + val isodrivePath = isodriveDir.get().asFile + val outputPath = outputDir.get().asFile - doLast { - // Verify submodule is initialized - if (!isodriveDir.resolve("src").exists()) { + if (!isodrivePath.resolve("src").exists()) { throw GradleException("isodrive submodule not initialized. Run: git submodule update --init") } @@ -33,8 +33,8 @@ val buildIsodrive by tasks.registering { "src/androidusbisomanager.cpp", "src/main.cpp" ) - val srcs = sourceFiles.joinToString(" ") { "$isodriveDir/$it" } - val cflags = "-I$isodriveDir/src/include -static-libstdc++ -Os -s" + val srcs = sourceFiles.joinToString(" ") { "$isodrivePath/$it" } + val cflags = "-I$isodrivePath/src/include -static-libstdc++ -Os -s" val compilers = mapOf( "arm64-v8a" to "aarch64-linux-android26-clang++", @@ -43,16 +43,14 @@ val buildIsodrive by tasks.registering { "x86" to "i686-linux-android26-clang++" ) - // Check if we're on NixOS (nix-shell available) val useNixShell = File("/etc/NIXOS").exists() || Runtime.getRuntime().exec(arrayOf("which", "nix-shell")).waitFor() == 0 if (useNixShell) { println("NixOS detected, using nix-shell for NDK...") - // Build all architectures in one nix-shell invocation val buildScript = compilers.entries.joinToString("\n") { (arch, compiler) -> - val archDir = outputDir.resolve(arch) + val archDir = outputPath.resolve(arch) val output = archDir.resolve("isodrive") if (output.exists()) { "echo 'isodrive for $arch already exists, skipping'" @@ -65,9 +63,7 @@ val buildIsodrive by tasks.registering { } } - exec { - environment("SRCS", srcs) - environment("CFLAGS", cflags) + execOps.exec { environment("NIXPKGS_ALLOW_UNFREE", "1") commandLine("nix-shell", "-p", "androidenv.androidPkgs.ndk-bundle", "--run", """ SDK_ROOT=${'$'}(find /nix/store -maxdepth 1 -name "*android-sdk-ndk*" -type d 2>/dev/null | head -1) @@ -79,7 +75,6 @@ val buildIsodrive by tasks.registering { """.trimIndent()) } } else { - // Standard NDK lookup for non-NixOS val ndkDir = listOfNotNull( System.getenv("ANDROID_NDK_HOME"), System.getenv("ANDROID_NDK") @@ -92,7 +87,7 @@ val buildIsodrive by tasks.registering { } compilers.forEach { (arch, compiler) -> - val archDir = outputDir.resolve(arch) + val archDir = outputPath.resolve(arch) val output = archDir.resolve("isodrive") if (output.exists()) { @@ -102,7 +97,7 @@ val buildIsodrive by tasks.registering { archDir.mkdirs() println("Building isodrive for $arch...") - exec { + execOps.exec { commandLine("sh", "-c", "$toolchain/$compiler $cflags $srcs -o $output") } } @@ -111,7 +106,18 @@ val buildIsodrive by tasks.registering { } } -// Hook into the build process - build isodrive before merging assets +val buildIsodrive by tasks.registering(BuildIsodriveTask::class) { + group = "native" + description = "Build isodrive binary for all Android architectures" + + isodriveDir.set(rootProject.file("isodrive")) + outputDir.set(file("src/main/assets/bin")) + + val architectures = listOf("arm64-v8a", "armeabi-v7a", "x86_64", "x86") + val outDir = file("src/main/assets/bin") + onlyIf { !architectures.all { arch -> outDir.resolve("$arch/isodrive").exists() } } +} + tasks.matching { it.name.startsWith("merge") && it.name.endsWith("Assets") }.configureEach { dependsOn(buildIsodrive) }