Skip to content

Commit c4d4a74

Browse files
committed
Allow specifying the Android NDK API level in the cargo { } block.
This also allows global toolchain directories, which is helpful in automation; and it makes the toolchain directories include the API level, which is just good hygiene.
1 parent defddeb commit c4d4a74

File tree

9 files changed

+50
-23
lines changed

9 files changed

+50
-23
lines changed

.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ modules.xml
2929
.idea/misc.xml
3030
*.ipr
3131
/target/
32+
/samples/rust/target/
3233
Cargo.lock
3334
**/*.rs.bk
3435
.gradle

plugin/build.gradle

+1-2
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ gradlePlugin {
1616
}
1717

1818
group 'org.mozilla.rust-android-gradle'
19-
version '0.1.0'
19+
version '0.2.0'
2020

2121
publishing {
2222
repositories {
@@ -28,7 +28,6 @@ publishing {
2828
maven(MavenPublication) {
2929
groupId 'org.mozilla.rust-android-gradle'
3030
artifactId 'rust-android'
31-
version '0.1.0'
3231

3332
from components.java
3433
}

plugin/src/main/kotlin/com/nishtahir/CargoBuildTask.kt

+13-4
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package com.nishtahir;
22

3+
import com.android.build.gradle.*
34
import org.gradle.api.DefaultTask
45
import org.gradle.api.GradleException
56
import org.gradle.api.Project
@@ -19,7 +20,12 @@ open class CargoBuildTask : DefaultTask() {
1920
throw GradleException("No such target $target")
2021
}
2122

22-
buildProjectForTarget(project, toolchain, this)
23+
project.plugins.all {
24+
when (it) {
25+
is AppPlugin -> buildProjectForTarget<AppExtension>(project, toolchain, this)
26+
is LibraryPlugin -> buildProjectForTarget<LibraryExtension>(project, toolchain, this)
27+
}
28+
}
2329

2430
val targetDirectory = targetDirectory ?: "${module}/target"
2531

@@ -37,7 +43,10 @@ open class CargoBuildTask : DefaultTask() {
3743
}
3844
}
3945

40-
private fun buildProjectForTarget(project: Project, toolchain: Toolchain, cargoExtension: CargoExtension) {
46+
inline fun <reified T : BaseExtension> buildProjectForTarget(project: Project, toolchain: Toolchain, cargoExtension: CargoExtension) {
47+
val app = project.extensions[T::class]
48+
val apiLevel = cargoExtension.apiLevel ?: app.defaultConfig.minSdkVersion.apiLevel
49+
4150
project.exec { spec ->
4251
with(spec) {
4352
standardOutput = System.out
@@ -55,8 +64,8 @@ open class CargoBuildTask : DefaultTask() {
5564
if (toolchain.target != null) {
5665
theCommandLine.add("--target=${toolchain.target}")
5766

58-
val cc = "${project.getToolchainDirectory()}/${toolchain.cc()}"
59-
val ar = "${project.getToolchainDirectory()}/${toolchain.ar()}"
67+
val cc = "${project.getToolchainDirectory()}/${toolchain.cc(apiLevel)}"
68+
val ar = "${project.getToolchainDirectory()}/${toolchain.ar(apiLevel)}"
6069
environment("CC", cc)
6170
environment("AR", ar)
6271
environment("RUSTFLAGS", "-C linker=$cc")

plugin/src/main/kotlin/com/nishtahir/CargoExtension.kt

+6
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,12 @@ open class CargoExtension {
44
var module: String = ""
55
var targets: List<String> = emptyList()
66

7+
/**
8+
* The Android NDK API level to target. Defaults to the minimum SDK version of the Android
9+
* project's default configuration.
10+
*/
11+
var apiLevel: Int? = null
12+
713
/**
814
* The Cargo [release profile](https://doc.rust-lang.org/book/second-edition/ch14-01-release-profiles.html#customizing-builds-with-release-profiles) to build.
915
*

plugin/src/main/kotlin/com/nishtahir/Extensions.kt

+10-4
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,13 @@ const val TOOLS_FOLDER = ".cargo/toolchain"
99

1010
operator fun <T : Any> ExtensionContainer.get(type: KClass<T>): T = getByType(type.java)
1111

12-
13-
14-
fun Project.getToolchainDirectory(): File = File(projectDir, TOOLS_FOLDER)
15-
12+
fun Project.getToolchainDirectory(): File {
13+
// Share a single toolchain directory, if one is configured, but fall back to per-project
14+
// toolchains.
15+
val globalDir: String? = System.getenv("ANDROID_NDK_TOOLCHAIN_DIR")
16+
if (globalDir != null) {
17+
return File(globalDir).absoluteFile
18+
} else {
19+
return File(projectDir, TOOLS_FOLDER)
20+
}
21+
}

plugin/src/main/kotlin/com/nishtahir/GenerateToolchainsTask.kt

+15-9
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import java.io.File
44

55
import com.android.build.gradle.*
66
import org.gradle.api.DefaultTask
7+
import org.gradle.api.GradleException
78
import org.gradle.api.Project
89
import org.gradle.api.tasks.TaskAction
910

@@ -21,31 +22,36 @@ open class GenerateToolchainsTask : DefaultTask() {
2122
}
2223

2324
inline fun <reified T : BaseExtension> congfigureTask(project: Project) {
25+
val cargoExtension = project.extensions[CargoExtension::class]
2426
val app = project.extensions[T::class]
25-
val minApi = app.defaultConfig.minSdkVersion.apiLevel
27+
val apiLevel = cargoExtension.apiLevel ?: app.defaultConfig.minSdkVersion.apiLevel
2628
val ndkPath = app.ndkDirectory
2729

28-
val targets = project.extensions[CargoExtension::class].targets
30+
val targets = cargoExtension.targets
2931

3032
toolchains
3133
.filter { it.target != null }
32-
.filterNot { (arch) -> minApi < 21 && arch.endsWith("64") }
3334
.filter { (arch) -> targets.contains(arch) }
3435
.forEach { (arch) ->
35-
val dir = File(project.getToolchainDirectory(), arch)
36+
if (arch.endsWith("64") && apiLevel < 21) {
37+
throw GradleException("Can't target 64-bit ${arch} with API level < 21 (${apiLevel})")
38+
}
39+
40+
val dir = File(project.getToolchainDirectory(), arch + "-" + apiLevel)
3641
if (dir.exists()) {
37-
println("Toolchain for arch ${arch} exists: checked ${dir}")
42+
println("Toolchain for arch ${arch} version ${apiLevel} exists: checked ${dir}")
3843
return@forEach
3944
}
4045

41-
println("Toolchain for arch ${arch} does not exist: checked ${dir}")
46+
println("Toolchain for arch ${arch} version ${apiLevel} does not exist: checked ${dir}")
4247
project.exec { spec ->
4348
spec.standardOutput = System.out
4449
spec.errorOutput = System.out
4550
spec.commandLine("$ndkPath/build/tools/make_standalone_toolchain.py")
46-
spec.args("--arch=$arch", "--api=$minApi",
47-
"--install-dir=${project.getToolchainDirectory()}/$arch",
48-
"--force")
51+
spec.args("--arch=$arch",
52+
"--api=$apiLevel",
53+
"--install-dir=${dir}",
54+
"--force")
4955
}
5056
}
5157
}

plugin/src/main/kotlin/com/nishtahir/RustAndroidPlugin.kt

+2-2
Original file line numberDiff line numberDiff line change
@@ -42,8 +42,8 @@ data class Toolchain(val platform: String,
4242
val cc: String,
4343
val ar: String,
4444
val folder: String) {
45-
fun cc(): String = "$platform/$cc"
46-
fun ar(): String = "$platform/$ar"
45+
fun cc(apiLevel: Int): String = "$platform-$apiLevel/$cc"
46+
fun ar(apiLevel: Int): String = "$platform-$apiLevel/$ar"
4747
}
4848

4949
@Suppress("unused")

samples/app/build.gradle

+1-1
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ buildscript {
1111
}
1212
dependencies {
1313
classpath 'com.android.tools.build:gradle:3.1.2'
14-
classpath 'org.mozilla.rust-android-gradle:rust-android:0.0.4'
14+
classpath 'org.mozilla.rust-android-gradle:rust-android:0.2.0'
1515
}
1616
}
1717

samples/library/build.gradle

+1-1
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ buildscript {
1111
}
1212
dependencies {
1313
classpath 'com.android.tools.build:gradle:3.1.2'
14-
classpath 'org.mozilla.rust-android-gradle:rust-android:0.0.4'
14+
classpath 'org.mozilla.rust-android-gradle:rust-android:0.2.0'
1515
}
1616
}
1717

0 commit comments

Comments
 (0)