build.gradle.kts 9.1 KB

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