build.gradle.kts 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248
  1. // SPDX-FileCopyrightText: 2023 yuzu Emulator Project
  2. // SPDX-License-Identifier: GPL-3.0-or-later
  3. import android.annotation.SuppressLint
  4. plugins {
  5. id("com.android.application")
  6. id("org.jetbrains.kotlin.android")
  7. id("kotlin-parcelize")
  8. kotlin("plugin.serialization") version "1.8.21"
  9. }
  10. /**
  11. * Use the number of seconds/10 since Jan 1 2016 as the versionCode.
  12. * This lets us upload a new build at most every 10 seconds for the
  13. * next 680 years.
  14. */
  15. val autoVersion = (((System.currentTimeMillis() / 1000) - 1451606400) / 10).toInt()
  16. @Suppress("UnstableApiUsage")
  17. android {
  18. namespace = "org.yuzu.yuzu_emu"
  19. compileSdkVersion = "android-33"
  20. ndkVersion = "25.2.9519653"
  21. buildFeatures {
  22. viewBinding = true
  23. }
  24. compileOptions {
  25. sourceCompatibility = JavaVersion.VERSION_17
  26. targetCompatibility = JavaVersion.VERSION_17
  27. }
  28. kotlinOptions {
  29. jvmTarget = "17"
  30. }
  31. packaging {
  32. // This is necessary for libadrenotools custom driver loading
  33. jniLibs.useLegacyPackaging = true
  34. }
  35. lint {
  36. // This is important as it will run lint but not abort on error
  37. // Lint has some overly obnoxious "errors" that should really be warnings
  38. abortOnError = false
  39. //Uncomment disable lines for test builds...
  40. //disable 'MissingTranslation'bin
  41. //disable 'ExtraTranslation'
  42. }
  43. defaultConfig {
  44. // TODO If this is ever modified, change application_id in strings.xml
  45. applicationId = "org.yuzu.yuzu_emu"
  46. minSdk = 30
  47. targetSdk = 33
  48. versionName = getGitVersion()
  49. ndk {
  50. @SuppressLint("ChromeOsAbiSupport")
  51. abiFilters += listOf("arm64-v8a")
  52. }
  53. buildConfigField("String", "GIT_HASH", "\"${getGitHash()}\"")
  54. buildConfigField("String", "BRANCH", "\"${getBranch()}\"")
  55. }
  56. // Define build types, which are orthogonal to product flavors.
  57. buildTypes {
  58. // Signed by release key, allowing for upload to Play Store.
  59. release {
  60. signingConfig = signingConfigs.getByName("debug")
  61. isMinifyEnabled = true
  62. isDebuggable = false
  63. proguardFiles(
  64. getDefaultProguardFile("proguard-android.txt"),
  65. "proguard-rules.pro"
  66. )
  67. }
  68. register("relWithVersionCode") {
  69. signingConfig = signingConfigs.getByName("debug")
  70. isMinifyEnabled = true
  71. isDebuggable = false
  72. proguardFiles(
  73. getDefaultProguardFile("proguard-android.txt"),
  74. "proguard-rules.pro"
  75. )
  76. }
  77. // builds a release build that doesn't need signing
  78. // Attaches 'debug' suffix to version and package name, allowing installation alongside the release build.
  79. register("relWithDebInfo") {
  80. signingConfig = signingConfigs.getByName("debug")
  81. isMinifyEnabled = true
  82. isDebuggable = true
  83. proguardFiles(
  84. getDefaultProguardFile("proguard-android.txt"),
  85. "proguard-rules.pro"
  86. )
  87. versionNameSuffix = "-debug"
  88. isJniDebuggable = true
  89. }
  90. // Signed by debug key disallowing distribution on Play Store.
  91. // Attaches 'debug' suffix to version and package name, allowing installation alongside the release build.
  92. debug {
  93. isDebuggable = true
  94. isJniDebuggable = true
  95. versionNameSuffix = "-debug"
  96. }
  97. }
  98. flavorDimensions.add("version")
  99. productFlavors {
  100. create("mainline") {
  101. dimension = "version"
  102. buildConfigField("Boolean", "PREMIUM", "false")
  103. }
  104. create("ea") {
  105. dimension = "version"
  106. buildConfigField("Boolean", "PREMIUM", "true")
  107. applicationIdSuffix = ".ea"
  108. }
  109. }
  110. externalNativeBuild {
  111. cmake {
  112. version = "3.22.1"
  113. path = file("../../../CMakeLists.txt")
  114. }
  115. }
  116. defaultConfig {
  117. externalNativeBuild {
  118. cmake {
  119. arguments(
  120. "-DENABLE_QT=0", // Don't use QT
  121. "-DENABLE_SDL2=0", // Don't use SDL
  122. "-DENABLE_WEB_SERVICE=0", // Don't use telemetry
  123. "-DBUNDLE_SPEEX=ON",
  124. "-DANDROID_ARM_NEON=true", // cryptopp requires Neon to work
  125. "-DYUZU_USE_BUNDLED_VCPKG=ON",
  126. "-DYUZU_USE_BUNDLED_FFMPEG=ON",
  127. "-DYUZU_ENABLE_LTO=ON"
  128. )
  129. abiFilters("arm64-v8a", "x86_64")
  130. }
  131. }
  132. }
  133. }
  134. dependencies {
  135. implementation("androidx.core:core-ktx:1.10.1")
  136. implementation("androidx.appcompat:appcompat:1.6.1")
  137. implementation("androidx.recyclerview:recyclerview:1.3.0")
  138. implementation("androidx.constraintlayout:constraintlayout:2.1.4")
  139. implementation("androidx.fragment:fragment-ktx:1.5.7")
  140. implementation("androidx.documentfile:documentfile:1.0.1")
  141. implementation("com.google.android.material:material:1.9.0")
  142. implementation("androidx.preference:preference:1.2.0")
  143. implementation("androidx.lifecycle:lifecycle-viewmodel-ktx:2.6.1")
  144. implementation("io.coil-kt:coil:2.2.2")
  145. implementation("androidx.core:core-splashscreen:1.0.1")
  146. implementation("androidx.window:window:1.0.0")
  147. implementation("org.ini4j:ini4j:0.5.4")
  148. implementation("androidx.constraintlayout:constraintlayout:2.1.4")
  149. implementation("androidx.swiperefreshlayout:swiperefreshlayout:1.1.0")
  150. implementation("androidx.navigation:navigation-fragment-ktx:2.5.3")
  151. implementation("androidx.navigation:navigation-ui-ktx:2.5.3")
  152. implementation("info.debatty:java-string-similarity:2.0.0")
  153. implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.5.0")
  154. }
  155. fun getGitVersion(): String {
  156. var versionName = "0.0"
  157. try {
  158. versionName = ProcessBuilder("git", "describe", "--always", "--long")
  159. .directory(project.rootDir)
  160. .redirectOutput(ProcessBuilder.Redirect.PIPE)
  161. .redirectError(ProcessBuilder.Redirect.PIPE)
  162. .start().inputStream.bufferedReader().use { it.readText() }
  163. .trim()
  164. .replace(Regex("(-0)?-[^-]+$"), "")
  165. } catch (e: Exception) {
  166. logger.error("Cannot find git, defaulting to dummy version number")
  167. }
  168. if (System.getenv("GITHUB_ACTIONS") != null) {
  169. val gitTag = System.getenv("GIT_TAG_NAME")
  170. versionName = gitTag ?: versionName
  171. }
  172. return versionName
  173. }
  174. fun getGitHash(): String {
  175. try {
  176. val processBuilder = ProcessBuilder("git", "rev-parse", "--short", "HEAD")
  177. processBuilder.directory(project.rootDir)
  178. val process = processBuilder.start()
  179. val inputStream = process.inputStream
  180. val errorStream = process.errorStream
  181. process.waitFor()
  182. return if (process.exitValue() == 0) {
  183. inputStream.bufferedReader()
  184. .use { it.readText().trim() } // return the value of gitHash
  185. } else {
  186. val errorMessage = errorStream.bufferedReader().use { it.readText().trim() }
  187. logger.error("Error running git command: $errorMessage")
  188. "dummy-hash" // return a dummy hash value in case of an error
  189. }
  190. } catch (e: Exception) {
  191. logger.error("$e: Cannot find git, defaulting to dummy build hash")
  192. return "dummy-hash" // return a dummy hash value in case of an error
  193. }
  194. }
  195. fun getBranch(): String {
  196. try {
  197. val processBuilder = ProcessBuilder("git", "rev-parse", "--abbrev-ref", "HEAD")
  198. processBuilder.directory(project.rootDir)
  199. val process = processBuilder.start()
  200. val inputStream = process.inputStream
  201. val errorStream = process.errorStream
  202. process.waitFor()
  203. return if (process.exitValue() == 0) {
  204. inputStream.bufferedReader()
  205. .use { it.readText().trim() } // return the value of gitHash
  206. } else {
  207. val errorMessage = errorStream.bufferedReader().use { it.readText().trim() }
  208. logger.error("Error running git command: $errorMessage")
  209. "dummy-hash" // return a dummy hash value in case of an error
  210. }
  211. } catch (e: Exception) {
  212. logger.error("$e: Cannot find git, defaulting to dummy build hash")
  213. return "dummy-hash" // return a dummy hash value in case of an error
  214. }
  215. }