import org.gradle.jvm.toolchain.JavaLanguageVersion import org.gradle.jvm.toolchain.JavaToolchainService plugins { id 'com.android.application' } def commit = getGitCommitHash(file('.')) def prodCloudBaseUrl = "https://santoku.dark98.co.uk/v1/" def prodBeamBaseUrl = "https://santoku.dark98.co.uk" android { namespace 'com.dark98.santoku' compileSdk 35 defaultConfig { applicationId "com.dark98.santoku" minSdk 21 targetSdk 35 versionCode 1 versionName "0.0.1" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" buildConfigField "String", "CLOUD_BASE_URL_PROD", "\"" + prodCloudBaseUrl + "\"" buildConfigField "String", "BEAM_BASE_URL_PROD", "\"" + prodBeamBaseUrl + "\"" externalNativeBuild { cmake { arguments '-DANDROID_STL=c++_shared', '-DANDROID_PLATFORM=21', '-DCMAKE_BUILD_TYPE=Release', // Disabling this results in drastically degradation of slicing times on debug builds "-DSLIC3R_VERSION=${defaultConfig.versionName}", "-DSLIC3R_BUILD_ID=${defaultConfig.versionCode}" } } } sourceSets { main { jniLibs.srcDirs += file('src/main/occt/jniLibs') } } buildTypes { release { minifyEnabled false proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' buildConfigField "String", "COMMIT", "\"" + commit + "\"" ndk { //noinspection ChromeOsAbiSupport abiFilters "armeabi-v7a", "arm64-v8a" } } debug { applicationIdSuffix ".debug" resValue "string", "AppName", "Santoku (Debug)" buildConfigField "String", "COMMIT", "\"" + commit + "\"" ndk { debugSymbolLevel 'NONE' //noinspection ChromeOsAbiSupport abiFilters "arm64-v8a" } } } compileOptions { sourceCompatibility JavaVersion.VERSION_21 targetCompatibility JavaVersion.VERSION_21 } externalNativeBuild { cmake { path file('CMakeLists.txt') } ndkVersion "29.0.14206865" } buildFeatures { buildConfig true } applicationVariants.all { variant -> variant.outputs.all { def isDebug = variant.buildType.name == "debug" def suffix = isDebug ? "_debug" : "" outputFileName = "Santoku_" + commit + suffix + ".apk" } } } def javaToolchainService = extensions.getByType(JavaToolchainService) tasks.withType(JavaCompile).configureEach { javaCompiler = javaToolchainService.compilerFor { languageVersion = JavaLanguageVersion.of(21) } } static String getGitCommitHash(File dir) { try { File gitDir = new File(dir, ".git") if (!gitDir.exists()) { return "non-git" } // Worktree/submodule support: .git may be a file with "gitdir: ". if (gitDir.isFile()) { String pointer = gitDir.text.trim() if (pointer.startsWith("gitdir:")) { gitDir = new File(dir, pointer.substring("gitdir:".length()).trim()) } } if (!gitDir.exists() || !gitDir.isDirectory()) { return "non-git" } File headFile = new File(gitDir, "HEAD") if (!headFile.exists()) { return "non-git" } String head = headFile.text.trim() String fullHash = null if (head.startsWith("ref:")) { String refPath = head.substring("ref:".length()).trim() File refFile = new File(gitDir, refPath) if (refFile.exists()) { fullHash = refFile.text.trim() } else { File packedRefs = new File(gitDir, "packed-refs") if (packedRefs.exists()) { String prefix = refPath + " " for (String line : packedRefs.readLines()) { if (line.startsWith("#") || line.startsWith("^") || line.trim().isEmpty()) { continue } int space = line.indexOf(' ') if (space > 0 && line.substring(space + 1).trim() == refPath) { fullHash = line.substring(0, space).trim() break } } } } } else { // Detached HEAD. fullHash = head } if (!fullHash || fullHash.length() < 10) { return "non-git" } return fullHash.substring(0, 10) } catch (Exception ignored) { return "non-git" } } dependencies { implementation project(":eventbus") implementation project(":eventbus_api") annotationProcessor project(":eventbus_processor") implementation project(":sapil") implementation 'com.google.code.gson:gson:2.11.0' implementation 'com.github.instacart:truetime-android:4.0.0.alpha' implementation 'com.github.mrudultora:Colorpicker:1.2.0' implementation 'com.github.bumptech.glide:glide:4.16.0' implementation 'androidx.appcompat:appcompat:1.7.0' implementation 'com.google.android.material:material:1.12.0' implementation 'com.loopj.android:android-async-http:1.4.11' implementation 'androidx.activity:activity:1.10.1' implementation 'com.squareup.okhttp3:okhttp:4.12.0' } def loadLocalProperties() { def props = new Properties() def propsFile = rootProject.file("local.properties") if (propsFile.exists()) { propsFile.withInputStream { props.load(it) } } return props } def toWslPath(String winPath) { return winPath.replaceAll('^([A-Za-z]):') { m -> "/mnt/${m[1].toLowerCase()}" }.replace('\\', '/') } def localProps = loadLocalProperties() def sdkDir = localProps.getProperty("sdk.dir") ?: System.getenv("ANDROID_SDK_ROOT") ?: System.getenv("ANDROID_HOME") if (!sdkDir) { throw new GradleException("Missing sdk.dir in local.properties and ANDROID_SDK_ROOT/ANDROID_HOME is not set") } def ndkDir = "${sdkDir}/ndk/${android.ndkVersion}" if (!file(ndkDir).exists()) { throw new GradleException("NDK not found at ${ndkDir} (ndkVersion=${android.ndkVersion})") } def cmakeRoot = file("${sdkDir}/cmake") def cmakeDir = cmakeRoot.listFiles()?.findAll { it.isDirectory() }?.sort { a, b -> b.name <=> a.name }?.first() if (!cmakeDir) { throw new GradleException("No CMake found under ${sdkDir}/cmake") } def osName = System.getProperty("os.name").toLowerCase() def isWindows = osName.contains("windows") def isMac = osName.contains("mac") def cmakeExe = "${cmakeDir}/bin/cmake" + (isWindows ? ".exe" : "") def ninjaExe = "${cmakeDir}/bin/ninja" + (isWindows ? ".exe" : "") def toolchainFile = "${ndkDir}/build/cmake/android.toolchain.cmake" def wslExe = "${System.getenv("SystemRoot") ?: "C:/Windows"}/System32/wsl.exe" def prebuiltTag = isWindows ? "windows-x86_64" : (isMac ? "darwin-x86_64" : "linux-x86_64") def llvmBinDir = "${ndkDir}/toolchains/llvm/prebuilt/${prebuiltTag}/bin" def pageSizeLinkerFlags = "-Wl,-z,common-page-size=16384 -Wl,-z,max-page-size=16384" def forceNativeRebuild = project.hasProperty("forceNativeRebuild") && project.property("forceNativeRebuild").toString().toLowerCase() == "true" def tbbSrc = "${rootDir}/third_party/openvdb-android/tbb-aarch64" def tbbBuildArm64 = "${rootDir}/third_party/openvdb-android/build-tbb-android-21-arm64" def tbbInstallArm64 = "${rootDir}/third_party/openvdb-android/dist-android-21-arm64" def tbbBuildArmv7 = "${rootDir}/third_party/openvdb-android/build-tbb-android-21-armv7" def tbbInstallArmv7 = "${rootDir}/third_party/openvdb-android/dist-android-21-armv7" def occtSrc = "${rootDir}/third_party/occt" def occtBuildArm64 = "${rootDir}/third_party/occt/build-android-arm64-v8a" def occtDistArm64 = "${rootDir}/third_party/occt/dist/android-arm64-v8a" def occtBuildArmv7 = "${rootDir}/third_party/occt/build-android-armeabi-v7a" def occtDistArmv7 = "${rootDir}/third_party/occt/dist/android-armeabi-v7a" def boostDir = "${rootDir}/third_party/Boost-for-Android" def boostOutArm64 = "${boostDir}/build/out/arm64-v8a" def boostOutArmv7 = "${boostDir}/build/out/armeabi-v7a" def rootPathForTasks = rootProject.projectDir.absolutePath def appProjectPath = project.projectDir.absolutePath def boostArm64OutLib = "${appProjectPath}/src/main/jniImports/boost/lib/arm64-v8a/lib/libboost_atomic-clang-mt-a64-1_85.a" def boostArmv7OutLib = "${appProjectPath}/src/main/jniImports/boost/lib/armeabi-v7a/lib/libboost_atomic-clang-mt-a32-1_85.a" def boostHeadersOut = "${appProjectPath}/src/main/jniImports/boost/include/boost/variant.hpp" def tbbArm64LibA = "${appProjectPath}/src/main/jniImports/oneTBB/lib/arm64-v8a/libtbb.a" def tbbArm64MallocA = "${appProjectPath}/src/main/jniImports/oneTBB/lib/arm64-v8a/libtbbmalloc.a" def tbbArm64So = "${appProjectPath}/src/main/jniLibs/arm64-v8a/libtbb.so" def tbbArm64MallocSo = "${appProjectPath}/src/main/jniLibs/arm64-v8a/libtbbmalloc.so" def tbbArmv7LibA = "${appProjectPath}/src/main/jniImports/oneTBB/lib/armeabi-v7a/libtbb.a" def tbbArmv7MallocA = "${appProjectPath}/src/main/jniImports/oneTBB/lib/armeabi-v7a/libtbbmalloc.a" def tbbArmv7So = "${appProjectPath}/src/main/jniLibs/armeabi-v7a/libtbb.so" def tbbArmv7MallocSo = "${appProjectPath}/src/main/jniLibs/armeabi-v7a/libtbbmalloc.so" def tbbHeaderOut = "${appProjectPath}/src/main/jniImports/oneTBB/include/tbb/tbb.h" def occtArm64So = "${appProjectPath}/src/main/occt/jniLibs/arm64-v8a/libTKDESTEP.so" def occtArmv7So = "${appProjectPath}/src/main/occt/jniLibs/armeabi-v7a/libTKDESTEP.so" def occtHeaderArm64Out = "${appProjectPath}/src/main/occt/include/arm64-v8a/STEPCAFControl_Reader.hxx" def occtHeaderArmv7Out = "${appProjectPath}/src/main/occt/include/armeabi-v7a/STEPCAFControl_Reader.hxx" tasks.register("ensureThirdParty") { doLast { def rootPath = rootPathForTasks def thirdPartyDir = new File(rootPath, "third_party") if (!thirdPartyDir.exists()) { thirdPartyDir.mkdirs() } def repos = [ [path: "${rootPath}/third_party/Boost-for-Android", url: "https://github.com/moritz-wundke/Boost-for-Android.git"], [path: "${rootPath}/third_party/openvdb-android", url: "https://github.com/syoyo/openvdb-android.git"], [path: "${rootPath}/third_party/occt", url: "https://github.com/Open-Cascade-SAS/OCCT.git"] ] def runCommand = { List cmd, File workDir -> Process process = new ProcessBuilder(cmd) .directory(workDir) .inheritIO() .start() int exitCode = process.waitFor() if (exitCode != 0) { throw new GradleException("Command failed (${exitCode}): ${cmd.join(' ')}") } } for (def repo : repos) { if (!new File(repo.path).exists()) { runCommand(["git", "clone", "--depth", "1", repo.url, repo.path], new File(rootPath)) } } def vdbRoot = new File(rootPath, "third_party/openvdb-android") if (new File(vdbRoot, ".gitmodules").exists() && !new File(vdbRoot, "tbb-aarch64/CMakeLists.txt").exists()) { runCommand(["git", "submodule", "update", "--init", "--recursive"], vdbRoot) } } } tasks.register("patchBoostForAndroid") { dependsOn("ensureThirdParty") doLast { def boostRoot = new File(rootPathForTasks, "third_party/Boost-for-Android") def scriptFile = new File(boostRoot, "build-android.sh") if (scriptFile.exists()) { def scriptText = scriptFile.getText("UTF-8") def changed = false if (!scriptText.contains("FORCE_PLATFORM_OS")) { def marker = "# Check platform patch" def markerIdx = scriptText.indexOf(marker) if (markerIdx >= 0) { def esacIdx = scriptText.indexOf("esac", markerIdx) if (esacIdx >= 0) { def insertPos = scriptText.indexOf("\n", esacIdx) if (insertPos >= 0) { insertPos += 1 def insert = 'if [ -n "${FORCE_PLATFORM_OS}" ]; then\n' + ' PlatformOS="${FORCE_PLATFORM_OS}"\n' + 'fi\n\n' scriptText = scriptText.substring(0, insertPos) + insert + scriptText.substring(insertPos) changed = true } } } } if (!scriptText.contains("CXXPATH.exe")) { def marker = 'if [ -n "${AndroidSourcesDetected}"' if (scriptText.contains(marker)) { def insert = 'if [ ! -f "$CXXPATH" ] && [ -f "$CXXPATH.exe" ]; then\n' + ' CXXPATH="$CXXPATH.exe"\n' + 'fi\n\n' scriptText = scriptText.replace(marker, insert + marker) changed = true } } if (changed) { scriptFile.write(scriptText, "UTF-8") } } def commonFile = new File(boostRoot, "configs/user-config-ndk23-1_85_0-common.jam") if (commonFile.exists()) { def commonText = commonFile.getText("UTF-8") def commonChanged = false if (!commonText.contains("AndroidToolSuffix")) { def header = 'import os ;\n' + 'local AndroidToolSuffix = [ os.environ AndroidToolSuffix ] ;\n' + 'if ! $(AndroidToolSuffix) { AndroidToolSuffix = "" ; }\n\n' commonText = header + commonText.trim() + "\n" commonChanged = true } if (!commonText.contains('llvm-ar$(AndroidToolSuffix)')) { commonText = commonText.replace('$(AndroidBinariesPath)/llvm-ar', '$(AndroidBinariesPath)/llvm-ar$(AndroidToolSuffix)') commonChanged = true } if (!commonText.contains('llvm-ranlib$(AndroidToolSuffix)')) { commonText = commonText.replace('$(AndroidBinariesPath)/llvm-ranlib', '$(AndroidBinariesPath)/llvm-ranlib$(AndroidToolSuffix)') commonChanged = true } if (commonChanged) { commonFile.write(commonText, "UTF-8") } } def arm64File = new File(boostRoot, "configs/user-config-ndk23-1_85_0-arm64-v8a.jam") if (arm64File.exists()) { def text = arm64File.getText("UTF-8") if (!text.contains("")) { text = "arm\n64\nelf\naapcs\n" + text arm64File.write(text, "UTF-8") } } def armv7File = new File(boostRoot, "configs/user-config-ndk23-1_85_0-armeabi-v7a.jam") if (armv7File.exists()) { def text = armv7File.getText("UTF-8") if (!text.contains("")) { text = "arm\n32\nelf\naapcs\n" + text armv7File.write(text, "UTF-8") } } } } tasks.register("buildTbbArm64") { dependsOn("ensureThirdParty") onlyIf { forceNativeRebuild || !new File(tbbArm64LibA).exists() || !new File(tbbArm64MallocA).exists() || !new File(tbbArm64So).exists() || !new File(tbbArm64MallocSo).exists() } doLast { exec { commandLine cmakeExe, "-G", "Ninja", "-S", tbbSrc, "-B", tbbBuildArm64, "-DCMAKE_MAKE_PROGRAM=${ninjaExe}", "-DCMAKE_POLICY_VERSION_MINIMUM=3.5", "-DCMAKE_TOOLCHAIN_FILE=${toolchainFile}", "-DANDROID_ABI=arm64-v8a", "-DANDROID_PLATFORM=android-21", "-DANDROID_STL=c++_shared", "-DCMAKE_BUILD_TYPE=Release", "-DCMAKE_SHARED_LINKER_FLAGS=${pageSizeLinkerFlags}", "-DCMAKE_INSTALL_PREFIX=${tbbInstallArm64}", "-DTBB_BUILD_TESTS=Off" } exec { commandLine cmakeExe, "--build", tbbBuildArm64, "--target", "install" } } } tasks.register("buildTbbArmv7") { dependsOn("ensureThirdParty") onlyIf { forceNativeRebuild || !new File(tbbArmv7LibA).exists() || !new File(tbbArmv7MallocA).exists() || !new File(tbbArmv7So).exists() || !new File(tbbArmv7MallocSo).exists() } doLast { exec { commandLine cmakeExe, "-G", "Ninja", "-S", tbbSrc, "-B", tbbBuildArmv7, "-DCMAKE_MAKE_PROGRAM=${ninjaExe}", "-DCMAKE_POLICY_VERSION_MINIMUM=3.5", "-DCMAKE_TOOLCHAIN_FILE=${toolchainFile}", "-DANDROID_ABI=armeabi-v7a", "-DANDROID_PLATFORM=android-21", "-DANDROID_STL=c++_shared", "-DCMAKE_BUILD_TYPE=Release", "-DCMAKE_SHARED_LINKER_FLAGS=${pageSizeLinkerFlags}", "-DCMAKE_INSTALL_PREFIX=${tbbInstallArmv7}", "-DTBB_BUILD_TESTS=Off" } exec { commandLine cmakeExe, "--build", tbbBuildArmv7, "--target", "install" } } } tasks.register("copyTbbArm64", Copy) { dependsOn("buildTbbArm64") onlyIf { forceNativeRebuild || !new File(tbbArm64LibA).exists() || !new File(tbbArm64MallocA).exists() || !new File(tbbArm64So).exists() || !new File(tbbArm64MallocSo).exists() } from("${tbbInstallArm64}/lib") { include "libtbb_static.a" include "libtbbmalloc_static.a" include "libtbb.so" include "libtbbmalloc.so" } into("${projectDir}/src/main/jniImports/oneTBB/tmp-arm64") doLast { copy { from "${projectDir}/src/main/jniImports/oneTBB/tmp-arm64/libtbb_static.a" into "${projectDir}/src/main/jniImports/oneTBB/lib/arm64-v8a" rename { "libtbb.a" } } copy { from "${projectDir}/src/main/jniImports/oneTBB/tmp-arm64/libtbbmalloc_static.a" into "${projectDir}/src/main/jniImports/oneTBB/lib/arm64-v8a" rename { "libtbbmalloc.a" } } copy { from "${projectDir}/src/main/jniImports/oneTBB/tmp-arm64/libtbb.so" into "${projectDir}/src/main/jniLibs/arm64-v8a" } copy { from "${projectDir}/src/main/jniImports/oneTBB/tmp-arm64/libtbbmalloc.so" into "${projectDir}/src/main/jniLibs/arm64-v8a" } delete("${projectDir}/src/main/jniImports/oneTBB/tmp-arm64") } } tasks.register("copyTbbArmv7", Copy) { dependsOn("buildTbbArmv7") onlyIf { forceNativeRebuild || !new File(tbbArmv7LibA).exists() || !new File(tbbArmv7MallocA).exists() || !new File(tbbArmv7So).exists() || !new File(tbbArmv7MallocSo).exists() } from("${tbbInstallArmv7}/lib") { include "libtbb_static.a" include "libtbbmalloc_static.a" include "libtbb.so" include "libtbbmalloc.so" } into("${projectDir}/src/main/jniImports/oneTBB/tmp-armv7") doLast { copy { from "${projectDir}/src/main/jniImports/oneTBB/tmp-armv7/libtbb_static.a" into "${projectDir}/src/main/jniImports/oneTBB/lib/armeabi-v7a" rename { "libtbb.a" } } copy { from "${projectDir}/src/main/jniImports/oneTBB/tmp-armv7/libtbbmalloc_static.a" into "${projectDir}/src/main/jniImports/oneTBB/lib/armeabi-v7a" rename { "libtbbmalloc.a" } } copy { from "${projectDir}/src/main/jniImports/oneTBB/tmp-armv7/libtbb.so" into "${projectDir}/src/main/jniLibs/armeabi-v7a" } copy { from "${projectDir}/src/main/jniImports/oneTBB/tmp-armv7/libtbbmalloc.so" into "${projectDir}/src/main/jniLibs/armeabi-v7a" } delete("${projectDir}/src/main/jniImports/oneTBB/tmp-armv7") } } tasks.register("copyTbbHeaders") { dependsOn("buildTbbArm64") onlyIf { !new File(tbbHeaderOut).exists() } doLast { copy { from "${tbbInstallArm64}/include/tbb" into "${projectDir}/src/main/jniImports/oneTBB/include/tbb" } copy { from "${projectDir}/src/main/jniImports/oneTBB/include/tbb" into "${projectDir}/src/main/jniImports/oneTBB/include/oneapi/tbb" } } } tasks.register("buildBoostArm64") { dependsOn("patchBoostForAndroid") onlyIf { !new File(boostArm64OutLib).exists() } doLast { if (isWindows) { if (!new File(wslExe).exists()) { throw new GradleException("WSL is required to build Boost on Windows. Install WSL or provide prebuilt Boost libs.") } def ndkWsl = toWslPath(ndkDir) def boostWsl = toWslPath(boostDir) def binWsl = toWslPath(llvmBinDir) def cmd = "set -euo pipefail; cd ${boostWsl}; chmod +x ${binWsl}/aarch64-linux-android21-clang++ ${binWsl}/llvm-ar.exe ${binWsl}/llvm-ranlib.exe || true; FORCE_PLATFORM_OS=windows AndroidCompilerSuffix= AndroidToolSuffix=.exe ./build-android.sh ${ndkWsl} --boost=1.85.0 --arch=arm64-v8a --target-version=21 --without-libraries=context,coroutine,fiber,python" Process p = new ProcessBuilder([wslExe, "bash", "-lc", cmd]).inheritIO().start() if (p.waitFor() != 0) { throw new GradleException("Boost arm64 build failed") } } else { def cmd = "set -euo pipefail; cd ${boostDir}; chmod +x ${llvmBinDir}/aarch64-linux-android21-clang++ ${llvmBinDir}/llvm-ar ${llvmBinDir}/llvm-ranlib || true; ./build-android.sh ${ndkDir} --boost=1.85.0 --arch=arm64-v8a --target-version=21 --without-libraries=context,coroutine,fiber,python" Process p = new ProcessBuilder(["bash", "-lc", cmd]).inheritIO().start() if (p.waitFor() != 0) { throw new GradleException("Boost arm64 build failed") } } } } tasks.register("buildBoostArmv7") { dependsOn("patchBoostForAndroid") onlyIf { !new File(boostArmv7OutLib).exists() } doLast { if (isWindows) { if (!new File(wslExe).exists()) { throw new GradleException("WSL is required to build Boost on Windows. Install WSL or provide prebuilt Boost libs.") } def ndkWsl = toWslPath(ndkDir) def boostWsl = toWslPath(boostDir) def binWsl = toWslPath(llvmBinDir) def cmd = "set -euo pipefail; cd ${boostWsl}; chmod +x ${binWsl}/armv7a-linux-androideabi21-clang++ ${binWsl}/llvm-ar.exe ${binWsl}/llvm-ranlib.exe || true; FORCE_PLATFORM_OS=windows AndroidCompilerSuffix= AndroidToolSuffix=.exe ./build-android.sh ${ndkWsl} --boost=1.85.0 --arch=armeabi-v7a --target-version=21 --without-libraries=context,coroutine,fiber,python" Process p = new ProcessBuilder([wslExe, "bash", "-lc", cmd]).inheritIO().start() if (p.waitFor() != 0) { throw new GradleException("Boost armv7 build failed") } } else { def cmd = "set -euo pipefail; cd ${boostDir}; chmod +x ${llvmBinDir}/armv7a-linux-androideabi21-clang++ ${llvmBinDir}/llvm-ar ${llvmBinDir}/llvm-ranlib || true; ./build-android.sh ${ndkDir} --boost=1.85.0 --arch=armeabi-v7a --target-version=21 --without-libraries=context,coroutine,fiber,python" Process p = new ProcessBuilder(["bash", "-lc", cmd]).inheritIO().start() if (p.waitFor() != 0) { throw new GradleException("Boost armv7 build failed") } } } } tasks.register("copyBoostArm64", Copy) { dependsOn("buildBoostArm64") onlyIf { !new File(boostArm64OutLib).exists() } from("${boostOutArm64}/lib") { include "libboost_*.a" } into("${projectDir}/src/main/jniImports/boost/lib/arm64-v8a/lib") } tasks.register("copyBoostArmv7", Copy) { dependsOn("buildBoostArmv7") onlyIf { !new File(boostArmv7OutLib).exists() } from("${boostOutArmv7}/lib") { include "libboost_*.a" } into("${projectDir}/src/main/jniImports/boost/lib/armeabi-v7a/lib") } tasks.register("copyBoostHeaders", Copy) { dependsOn("ensureThirdParty") onlyIf { !new File(boostHeadersOut).exists() } from("${boostDir}/boost_1_85_0/boost") into("${projectDir}/src/main/jniImports/boost/include/boost") } tasks.register("buildOcctArm64") { dependsOn("ensureThirdParty") onlyIf { forceNativeRebuild || !new File(occtArm64So).exists() } doLast { List cfgCmd = [ cmakeExe, "-G", "Ninja", "-S", occtSrc, "-B", occtBuildArm64, "-DCMAKE_MAKE_PROGRAM=${ninjaExe}", "-DCMAKE_TOOLCHAIN_FILE=${toolchainFile}", "-DANDROID_ABI=arm64-v8a", "-DANDROID_PLATFORM=android-21", "-DCMAKE_BUILD_TYPE=Release", "-DBUILD_LIBRARY_TYPE=Shared", "-DCMAKE_SHARED_LINKER_FLAGS=${pageSizeLinkerFlags}", "-DINSTALL_DIR_LIB=libs/arm64-v8a", "-DINSTALL_DIR_INCLUDE=inc", "-DBUILD_DOC_Overview=OFF", "-DBUILD_DOC_RefMan=OFF", "-DUSE_FREETYPE=OFF", "-DUSE_RAPIDJSON=OFF", "-DUSE_DRACO=OFF", "-DCMAKE_INSTALL_PREFIX=${occtDistArm64}" ] Process p1 = new ProcessBuilder(cfgCmd).inheritIO().start() if (p1.waitFor() != 0) throw new GradleException("OCCT arm64 configure failed") Process p2 = new ProcessBuilder([cmakeExe, "--build", occtBuildArm64, "--target", "install", "--config", "Release", "--", "-j2"]).inheritIO().start() if (p2.waitFor() != 0) throw new GradleException("OCCT arm64 build failed") } } tasks.register("buildOcctArmv7") { dependsOn("ensureThirdParty") onlyIf { forceNativeRebuild || !new File(occtArmv7So).exists() } doLast { List cfgCmd = [ cmakeExe, "-G", "Ninja", "-S", occtSrc, "-B", occtBuildArmv7, "-DCMAKE_MAKE_PROGRAM=${ninjaExe}", "-DCMAKE_TOOLCHAIN_FILE=${toolchainFile}", "-DANDROID_ABI=armeabi-v7a", "-DANDROID_PLATFORM=android-21", "-DCMAKE_BUILD_TYPE=Release", "-DBUILD_LIBRARY_TYPE=Shared", "-DCMAKE_SHARED_LINKER_FLAGS=${pageSizeLinkerFlags}", "-DINSTALL_DIR_LIB=libs/armeabi-v7a", "-DINSTALL_DIR_INCLUDE=inc", "-DBUILD_DOC_Overview=OFF", "-DBUILD_DOC_RefMan=OFF", "-DUSE_FREETYPE=OFF", "-DUSE_RAPIDJSON=OFF", "-DUSE_DRACO=OFF", "-DCMAKE_INSTALL_PREFIX=${occtDistArmv7}" ] Process p1 = new ProcessBuilder(cfgCmd).inheritIO().start() if (p1.waitFor() != 0) throw new GradleException("OCCT armv7 configure failed") Process p2 = new ProcessBuilder([cmakeExe, "--build", occtBuildArmv7, "--target", "install", "--config", "Release", "--", "-j2"]).inheritIO().start() if (p2.waitFor() != 0) throw new GradleException("OCCT armv7 build failed") } } tasks.register("copyOcctArm64", Copy) { dependsOn("buildOcctArm64") onlyIf { forceNativeRebuild || !new File(occtArm64So).exists() } from("${occtDistArm64}/libs/arm64-v8a") { include "*.so" } into("${projectDir}/src/main/occt/jniLibs/arm64-v8a") } tasks.register("copyOcctArmv7", Copy) { dependsOn("buildOcctArmv7") onlyIf { forceNativeRebuild || !new File(occtArmv7So).exists() } from("${occtDistArmv7}/libs/armeabi-v7a") { include "*.so" } into("${projectDir}/src/main/occt/jniLibs/armeabi-v7a") } tasks.register("copyOcctHeadersArm64", Copy) { dependsOn("buildOcctArm64") onlyIf { !new File(occtHeaderArm64Out).exists() } from("${occtDistArm64}/inc") into("${projectDir}/src/main/occt/include/arm64-v8a") } tasks.register("copyOcctHeadersArmv7", Copy) { dependsOn("buildOcctArmv7") onlyIf { !new File(occtHeaderArmv7Out).exists() } from("${occtDistArmv7}/inc") into("${projectDir}/src/main/occt/include/armeabi-v7a") } tasks.register("prepareNativeDeps") { dependsOn( "copyTbbArm64", "copyTbbArmv7", "copyTbbHeaders", "copyBoostArm64", "copyBoostArmv7", "copyBoostHeaders", "copyOcctArm64", "copyOcctArmv7", "copyOcctHeadersArm64", "copyOcctHeadersArmv7" ) } afterEvaluate { tasks.matching { it.name.startsWith("buildCMake") }.configureEach { dependsOn("prepareNativeDeps") } }