Skip to content

Commit

Permalink
feat(cli): update android template to gradle 8.0 (#6890)
Browse files Browse the repository at this point in the history
* feat(cli): update android template to gradle 8.0

* update java in CI to 17

* updat to latest tauri-mobile
  • Loading branch information
amrbashir committed May 12, 2023
1 parent 39f1b04 commit 5a9307d
Show file tree
Hide file tree
Showing 13 changed files with 98 additions and 107 deletions.
6 changes: 6 additions & 0 deletions .changes/gradle-8.md
@@ -0,0 +1,6 @@
---
'cli.rs': 'patch'
'cli.js': 'patch'
---

Update android template to gradle 8.0
2 changes: 1 addition & 1 deletion .github/workflows/test-android.yml
Expand Up @@ -57,7 +57,7 @@ jobs:
- uses: actions/setup-java@v3
with:
distribution: temurin
java-version: 11
java-version: 17
cache: gradle

- name: Setup NDK
Expand Down
4 changes: 2 additions & 2 deletions tooling/cli/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion tooling/cli/Cargo.toml
Expand Up @@ -39,7 +39,7 @@ name = "cargo-tauri"
path = "src/main.rs"

[dependencies]
tauri-mobile = { version = "0.4", default-features = false }
tauri-mobile = { version = "0.5", default-features = false }
textwrap = { version = "0.11.0", features = [ "term_size" ] }
jsonrpsee = { version = "0.16", features = [ "server" ] }
jsonrpsee-core = "0.16"
Expand Down
13 changes: 10 additions & 3 deletions tooling/cli/src/mobile/android/project.rs
Expand Up @@ -52,10 +52,16 @@ pub fn gen(
)),
);
map.insert("root-dir", config.app().root_dir());
map.insert("targets", Target::all().values().collect::<Vec<_>>());
map.insert("target-names", Target::all().keys().collect::<Vec<_>>());
map.insert(
"arches",
"abi-list",
Target::all()
.values()
.map(|target| target.abi)
.collect::<Vec<_>>(),
);
map.insert("target-list", Target::all().keys().collect::<Vec<_>>());
map.insert(
"arch-list",
Target::all()
.values()
.map(|target| target.arch)
Expand All @@ -77,6 +83,7 @@ pub fn gen(
|| metadata.app_dependencies().is_some()
|| metadata.app_dependencies_platform().is_some(),
);
map.insert("has-asset-packs", !asset_packs.is_empty());
map.insert(
"asset-packs",
asset_packs
Expand Down
70 changes: 15 additions & 55 deletions tooling/cli/templates/mobile/android/app/build.gradle.kts
@@ -1,13 +1,14 @@
plugins {
id("com.android.application")
id("org.jetbrains.kotlin.android")
id("rustPlugin")
id("rust")
{{~#each android-app-plugins}}
id("{{this}}"){{/each}}
}

android {
compileSdk = 33
namespace = "{{reverse-domain app.domain}}.{{snake-case app.name}}"
defaultConfig {
manifestPlaceholders["usesCleartextTraffic"] = "false"
applicationId = "{{reverse-domain app.domain}}.{{snake-case app.name}}"
Expand All @@ -16,88 +17,47 @@ android {
versionCode = 1
versionName = "1.0"
}
sourceSets.getByName("main") {
{{#if android.vulkan-validation}}// Vulkan validation layers
val ndkHome = System.getenv("NDK_HOME")
jniLibs.srcDir("${ndkHome}/sources/third_party/vulkan/src/build-android/jniLibs")
{{/if}}
}
buildTypes {
getByName("debug") {
manifestPlaceholders["usesCleartextTraffic"] = "true"
isDebuggable = true
isJniDebuggable = true
isMinifyEnabled = false
packagingOptions {
{{~#each targets}}
jniLibs.keepDebugSymbols.add("*/{{this.abi}}/*.so")
packaging {
{{~#each abi-list}}
jniLibs.keepDebugSymbols.add("*/{{this}}/*.so")
{{/each}}
}
}
getByName("release") {
isMinifyEnabled = true
val proguards = fileTree(".") {
include("**/*.pro")
}
proguardFiles(*proguards.toList().toTypedArray())
proguardFiles(
*fileTree(".") { include("**/*.pro") }
.plus(getDefaultProguardFile("proguard-android-optimize.txt"))
.toList().toTypedArray()
)
}
}
flavorDimensions.add("abi")
productFlavors {
create("universal") {
dimension = "abi"
ndk {
abiFilters += (findProperty("abiList") as? String)?.split(",") ?: listOf(
{{~#each targets}}
"{{this.abi}}",{{/each}}
)
}
}
{{~#each targets}}

create("{{this.arch}}") {
dimension = "abi"
ndk {
abiFilters += listOf("{{this.abi}}")
}
}
{{/each}}
kotlinOptions {
jvmTarget = "1.8"
}

assetPacks += mutableSetOf({{quote-and-join-colon-prefix asset-packs}})
namespace = "{{reverse-domain app.domain}}.{{snake-case app.name}}"
}

rust {
rootDirRel = "{{root-dir-rel}}"
targets = (findProperty("targetList") as? String)?.split(",") ?: listOf({{quote-and-join target-names}})
arches = (findProperty("archList") as? String)?.split(",") ?: listOf({{quote-and-join arches}})
}

dependencies {
{{~#each android-app-dependencies-platform}}
implementation(platform("{{this}}")){{/each}}
{{~#each android-app-dependencies}}
implementation("{{this}}"){{/each}}
implementation("androidx.webkit:webkit:1.5.0")
implementation("androidx.appcompat:appcompat:1.5.1")
implementation("com.google.android.material:material:1.7.0")
implementation("androidx.webkit:webkit:1.6.1")
implementation("androidx.appcompat:appcompat:1.6.1")
implementation("com.google.android.material:material:1.8.0")
testImplementation("junit:junit:4.13.2")
androidTestImplementation("androidx.test.ext:junit:1.1.4")
androidTestImplementation("androidx.test.espresso:espresso-core:3.5.0")
}

apply(from = "tauri.build.gradle.kts")

afterEvaluate {
android.applicationVariants.all {
tasks["mergeUniversalReleaseJniLibFolders"].dependsOn(tasks["rustBuildRelease"])
tasks["mergeUniversalDebugJniLibFolders"].dependsOn(tasks["rustBuildDebug"])
if (findProperty("targetList") == null) {
productFlavors.filter{ it.name != "universal" }.forEach { _ ->
val archAndBuildType = name.capitalize()
tasks["merge${archAndBuildType}JniLibFolders"].dependsOn(tasks["rustBuild${archAndBuildType}"])
}
}
}
}
Expand Up @@ -14,7 +14,6 @@
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />

<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
Expand Down
7 changes: 2 additions & 5 deletions tooling/cli/templates/mobile/android/build.gradle.kts
@@ -1,16 +1,13 @@
// Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript {
repositories {
google()
mavenCentral()
}
dependencies {
classpath("com.android.tools.build:gradle:7.3.1")
classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:1.6.10")
classpath("com.android.tools.build:gradle:8.0.0")
classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:1.6.21")
{{~#each android-project-dependencies}}
classpath("{{this}}"){{/each}}
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
}
}

Expand Down
Expand Up @@ -5,8 +5,8 @@ plugins {
gradlePlugin {
plugins {
create("pluginsForCoolKids") {
id = "rustPlugin"
implementationClass = "{{reverse-domain app.domain}}.RustPlugin"
id = "rust"
implementationClass = "RustPlugin"
}
}
}
Expand All @@ -18,6 +18,6 @@ repositories {

dependencies {
compileOnly(gradleApi())
implementation("com.android.tools.build:gradle:7.3.1")
implementation("com.android.tools.build:gradle:8.0.0")
}

@@ -1,20 +1,14 @@
package {{reverse-domain app.domain}}

import java.io.File
import org.apache.tools.ant.taskdefs.condition.Os
import org.gradle.api.DefaultTask
import org.gradle.api.GradleException
import org.gradle.api.logging.LogLevel
import org.gradle.api.tasks.Input
import org.gradle.api.tasks.InputDirectory
import org.gradle.api.tasks.PathSensitive
import org.gradle.api.tasks.PathSensitivity
import org.gradle.api.tasks.TaskAction

open class BuildTask : DefaultTask() {
@InputDirectory
@PathSensitive(PathSensitivity.RELATIVE)
var rootDirRel: File? = null
@Input
var rootDirRel: String? = null
@Input
var target: String? = null
@Input
Expand All @@ -41,7 +35,7 @@ open class BuildTask : DefaultTask() {
val args = listOf({{quote-and-join tauri-binary-args}});

project.exec {
workingDir(File(project.projectDir, rootDirRel.path))
workingDir(File(project.projectDir, rootDirRel))
executable(executable)
args(args)
if (project.logger.isEnabled(LogLevel.DEBUG)) {
Expand Down
@@ -1,59 +1,85 @@
package {{reverse-domain app.domain}}

import com.android.build.api.dsl.ApplicationExtension
import org.gradle.api.DefaultTask
import org.gradle.api.GradleException
import org.gradle.api.Plugin
import org.gradle.api.Project
import java.io.File
import java.util.*
import org.gradle.kotlin.dsl.configure
import org.gradle.kotlin.dsl.get

const val TASK_GROUP = "rust"

open class Config {
var rootDirRel: String? = null
var targets: List<String>? = null
var arches: List<String>? = null
lateinit var rootDirRel: String
}

open class RustPlugin : Plugin<Project> {
private lateinit var config: Config

override fun apply(project: Project) {
config = project.extensions.create("rust", Config::class.java)
project.afterEvaluate {
if (config.targets == null) {
throw GradleException("targets cannot be null")
}
if (config.arches == null) {
throw GradleException("arches cannot be null")
override fun apply(project: Project) = with(project) {
config = extensions.create("rust", Config::class.java)

val defaultAbiList = listOf({{quote-and-join abi-list}});
val abiList = (findProperty("abiList") as? String)?.split(',') ?: defaultAbiList

val defaultArchList = listOf({{quote-and-join arch-list}});
val archList = (findProperty("archList") as? String)?.split(',') ?: listOf({{quote-and-join arch-list}})

val targetsList = (findProperty("targetList") as? String)?.split(',') ?: listOf({{quote-and-join target-list}})

extensions.configure<ApplicationExtension> {
@Suppress("UnstableApiUsage")
flavorDimensions.add("abi")
productFlavors {
create("universal") {
dimension = "abi"
ndk {
abiFilters += abiList
}
}
defaultArchList.forEachIndexed { index, arch ->
create(arch) {
dimension = "abi"
ndk {
abiFilters.add(defaultAbiList[index])
}
}
}
}
}

afterEvaluate {
for (profile in listOf("debug", "release")) {
val profileCapitalized = profile.capitalize(Locale.ROOT)
val buildTask = project.tasks.maybeCreate(
"rustBuild$profileCapitalized",
val profileCapitalized = profile.replaceFirstChar { it.uppercase() }
val buildTask = tasks.maybeCreate(
"rustBuildUniversal$profileCapitalized",
DefaultTask::class.java
).apply {
group = TASK_GROUP
description = "Build dynamic library in $profile mode for all targets"
}
for (targetPair in config.targets!!.withIndex()) {

tasks["mergeUniversal${profileCapitalized}JniLibFolders"].dependsOn(buildTask)

for (targetPair in targetsList.withIndex()) {
val targetName = targetPair.value
val targetArch = config.arches!![targetPair.index]
val targetArchCapitalized = targetArch.capitalize(Locale.ROOT)
val targetArch = archList[targetPair.index]
val targetArchCapitalized = targetArch.replaceFirstChar { it.uppercase() }
val targetBuildTask = project.tasks.maybeCreate(
"rustBuild$targetArchCapitalized$profileCapitalized",
BuildTask::class.java
).apply {
group = TASK_GROUP
description = "Build dynamic library in $profile mode for $targetArch"
rootDirRel = config.rootDirRel?.let { File(it) }
rootDirRel = config.rootDirRel
target = targetName
release = profile == "release"
}

buildTask.dependsOn(targetBuildTask)
project.tasks.findByName("preBuild")?.mustRunAfter(targetBuildTask)
tasks["merge$targetArchCapitalized${profileCapitalized}JniLibFolders"].dependsOn(
targetBuildTask
)
}
}
}
}
}
}
4 changes: 3 additions & 1 deletion tooling/cli/templates/mobile/android/gradle.properties
Expand Up @@ -20,4 +20,6 @@ kotlin.code.style=official
# Enables namespacing of each library's R class so that its R class includes only the
# resources declared in the library itself and none from the library's dependencies,
# thereby reducing the size of the R class for that library
android.nonTransitiveRClass=true
android.nonTransitiveRClass=true
android.defaults.buildfeatures.buildconfig=true
android.nonFinalResIds=false
@@ -1,6 +1,6 @@
#Tue May 10 19:22:52 CST 2022
distributionBase=GRADLE_USER_HOME
distributionUrl=https\://services.gradle.org/distributions/gradle-7.4-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-8.0-bin.zip
distributionPath=wrapper/dists
zipStorePath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME

0 comments on commit 5a9307d

Please sign in to comment.