Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement support for Android target #250

Draft
wants to merge 31 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
dbd741a
Detect when an Android target is registered for benchmarking
kx412764776 May 31, 2024
0ce431e
Research android target support
kx412764776 Jun 7, 2024
a363453
Add androidTarget to runtime module
kx412764776 Jun 7, 2024
df8052b
Add gradle tasks to unpack aar file & retrieve annotation
kx412764776 Jun 10, 2024
517b694
Retrieve annotation data
kx412764776 Jun 17, 2024
4fe7b57
Retrieve annotation data
kx412764776 Jun 19, 2024
7a1b77a
refactor retrieve annotation data
kx412764776 Jun 21, 2024
dc9d1e4
Use 'ClassAnnotationsDescriptor' to store annotation data
kx412764776 Jun 23, 2024
9e198c7
update 'AnnotationProcessor' to process jar file
kx412764776 Jun 25, 2024
303577e
Generate androidTest file executable by Junit4
kx412764776 Jul 1, 2024
87dfd92
Add detect android device function
kx412764776 Jul 10, 2024
fcfd01c
Improve code generation for android target
kx412764776 Jul 15, 2024
d9c5e59
Add 'benchmarkRule' to call test
kx412764776 Jul 17, 2024
2594ede
modify 'AnnotationProcessor' processing annotation data
kx412764776 Jul 22, 2024
a56b4af
Add 'BenchmarkState' to call test
kx412764776 Jul 22, 2024
18cd7e9
Execute separate gradle task via shell command
kx412764776 Jul 24, 2024
8f772b2
Use retrieved iteration data to generate file for android target
kx412764776 Jul 25, 2024
742a0c2
Print test info from android logcat
kx412764776 Aug 5, 2024
7982b85
Filter print data in android target
kx412764776 Aug 5, 2024
dc5c404
Change the paths to the kotlin-qualification-task
Aug 5, 2024
88951b3
Add the template android project for generating benchmark sources into
Aug 7, 2024
a515f55
Generate benchmark sources into the template android project
Aug 7, 2024
f5aa4ba
Fix generate folders in android template project
kx412764776 Aug 9, 2024
ee5b8fb
Fix: Correctly store field annotations in FieldAnnotationsDescriptor
kx412764776 Aug 10, 2024
d9c9ab0
Map @Param annotation to androidx.benchmark
kx412764776 Aug 17, 2024
6209b53
Support users to set sdkDir for Android
kx412764776 Aug 22, 2024
f65b105
Fix 'Type mismatch' error
kx412764776 Aug 23, 2024
df57148
Add test for generate android project
kx412764776 Sep 16, 2024
53831cc
Bump Android Gradle Plugin version to 8.5.1 in all subprojects
Sep 18, 2024
3a42442
Set namespace for the android target
Sep 18, 2024
934e250
Modify the mapping of `warmup` data to androidx.benchmark
kx412764776 Sep 23, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ buildscript {
repositories {
maven("https://maven.pkg.jetbrains.space/kotlin/p/kotlinx/maven")
gradlePluginPortal()
google()

addDevRepositoryIfEnabled(this, project)
}
Expand All @@ -25,6 +26,7 @@ buildscript {
classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlinVersion")
}
}
classpath("com.android.tools.build:gradle:8.5.1")
}
}

Expand Down
64 changes: 64 additions & 0 deletions examples/kotlin-multiplatform/build.gradle
Original file line number Diff line number Diff line change
@@ -1,17 +1,55 @@
import kotlinx.benchmark.gradle.JsBenchmarksExecutor
import org.jetbrains.kotlin.gradle.dsl.JvmTarget

plugins {
id 'org.jetbrains.kotlin.multiplatform'
id 'org.jetbrains.kotlin.plugin.allopen' version "2.0.20"
id 'org.jetbrains.kotlinx.benchmark'
id 'com.android.library'
}

// how to apply plugin to a specific source set?
allOpen {
annotation("org.openjdk.jmh.annotations.State")
}

android {
compileSdk 34
namespace = "org.jetbrains.kotlinx.examples"

defaultConfig {
minSdk = 29
targetSdk = 34
versionCode = 1
versionName = "1.0"

testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
}

buildTypes {
release {
// isMinifyEnabled = false
// proguardFiles(getDefaultProguardFile("proguard-android-optimize.txt"), "proguard-rules.pro")
}
}
compileOptions {
sourceCompatibility = JavaVersion.VERSION_1_8
targetCompatibility = JavaVersion.VERSION_1_8
}
}

// Could not determine the dependencies of task ':examples:kotlin-multiplatform:extractReleaseAnnotations'.
// > Could not resolve all task dependencies for configuration ':examples:kotlin-multiplatform:detachedConfiguration1'.
// > Could not find com.android.tools.lint:lint-gradle:31.2.2.
repositories {
google()
}

kotlin {
androidTarget {
// Android target does not have any compilations
println("android compilations: ${compilations.size()}")
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

JFYI: when implementation project(":kotlinx-benchmark-runtime") is replaced with a dependency on actual artifact (for instance, published to a local maven repo), :compileReleaseKotlinAndroid fails due to unresolved kotlinx.benchnark symbols:

e: file:///Users/filipp.zhinkin/Development/kx-benchmark-android/examples/kotlin-multiplatform/src/androidMain/kotlin/AndroidTestBenchmark.kt:6:7 This class does not have a constructor
e: file:///Users/filipp.zhinkin/Development/kx-benchmark-android/examples/kotlin-multiplatform/src/androidMain/kotlin/AndroidTestBenchmark.kt:6:14 Unresolved reference: Benchmark
e: file:///Users/filipp.zhinkin/Development/kx-benchmark-android/examples/kotlin-multiplatform/src/androidMain/kotlin/AndroidTestBenchmark.kt:7:8 This class does not have a constructor
e: file:///Users/filipp.zhinkin/Development/kx-benchmark-android/examples/kotlin-multiplatform/src/androidMain/kotlin/AndroidTestBenchmark.kt:8:13 This class does not have a constructor

It does not make much sense to redefine a dependency for this sample project, but the same issue is also reproduced on kotlinx-io when I tried to apply kx-benchmark w/ android support.

jvm {
compilations.create('benchmark') { associateWith(compilations.main) }
}
Expand Down Expand Up @@ -47,6 +85,20 @@ kotlin {
}

nativeMain {}

androidMain {
kotlin.setSrcDirs(["src/androidMain/kotlin"])
}

forEach {
// Android target has 3 source sets: androidMain, androidUnitTest, and androidInstrumentedTest
println("SourceSet: $it")
println(it.name)
println(it.kotlin)
println(it.kotlin.srcDirs)
println(it.kotlin.sourceDirectories)
}

}
}

Expand Down Expand Up @@ -121,5 +173,17 @@ benchmark {
register("macosArm64")
register("linuxX64")
register("mingwX64")
register("android")
}
}

java {
sourceCompatibility = JavaVersion.VERSION_1_8
targetCompatibility = JavaVersion.VERSION_1_8
}

tasks.withType(org.jetbrains.kotlin.gradle.tasks.KotlinCompile).configureEach {
compilerOptions {
jvmTarget.set(JvmTarget.JVM_1_8)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package test

import kotlinx.benchmark.*
import kotlin.math.*

@State(Scope.Benchmark)
@Warmup(iterations = 3, time = 1, timeUnit = BenchmarkTimeUnit.SECONDS)
@Measurement(iterations = 3, time = 1, timeUnit = BenchmarkTimeUnit.SECONDS)
class AndroidTestBenchmark {
private var data = 0.0

@Setup
fun setUp() {
data = 3.0
}

@TearDown
fun teardown() {
// println("Teardown!")
}

@Benchmark
fun sqrtBenchmark(): Double {
return sqrt(data)
}

@Benchmark
fun cosBenchmark(): Double {
return cos(data)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import kotlinx.benchmark.*
import kotlin.math.*

@State(Scope.Benchmark)
@Warmup(iterations = 3, time = 1, timeUnit = BenchmarkTimeUnit.SECONDS)
@Measurement(iterations = 3, time = 1, timeUnit = BenchmarkTimeUnit.SECONDS)
@OutputTimeUnit(BenchmarkTimeUnit.MILLISECONDS)
@BenchmarkMode(Mode.AverageTime)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package kotlinx.benchmark.integration

enum class GradleTestVersion(val versionString: String) {
v8_7("8.7"),
v8_0("8.0.2"),
MinSupportedGradleVersion("7.4"),
UnsupportedGradleVersion("7.3"),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,20 +51,24 @@ private fun generateBuildScript(kotlinVersion: String, jvmToolchain: Int) =
repositories {
$kotlin_repo
$plugin_repo_url
google()
mavenCentral()
}
dependencies {
classpath 'org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlinVersion'
classpath 'org.jetbrains.kotlinx:kotlinx-benchmark-plugin:0.5.0-SNAPSHOT'
classpath 'com.android.tools.build:gradle:8.5.1'
}
}

apply plugin: 'kotlin-multiplatform'
apply plugin: 'org.jetbrains.kotlinx.benchmark'
apply plugin: 'com.android.library'

repositories {
$kotlin_repo
$runtime_repo_url
google()
mavenCentral()
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -93,4 +93,10 @@ class Runner(
projectDir.resolve("build/benchmarks/${targetName}/sources/kotlinx/benchmark/generated").resolve(filePath)
)
}

fun generatedAndroidDir(targetName: String, targetCompilation: String, filePath: String, fileTestAction: (File) -> Unit) {
fileTestAction(
projectDir.resolve("build/benchmarks/$targetName/$targetCompilation/GeneratedAndroidProject").resolve(filePath)
)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package kotlinx.benchmark.integration

import org.junit.Test
import kotlin.test.assertTrue

class AndroidProjectGeneratorTest: GradleTest() {
private fun testAndroidProjectGeneration(setupBlock: Runner.() -> Unit, checkBlock: Runner.() -> Unit) {
project("source-generation", print = true, gradleVersion = GradleTestVersion.v8_7).apply {
setupBlock()
runAndSucceed("androidReleaseBenchmarkGenerate")
checkBlock()
}
}

@Test
fun generateAndroidFromResources() {
testAndroidProjectGeneration(
setupBlock = {
runAndSucceed("setupReleaseAndroidProject")
},
checkBlock = {
generatedAndroidDir("android", "release", "") { generatedAndroidDir ->
assertTrue(generatedAndroidDir.exists(), "Generated Android project does not exist")
}
}
)
}
}
Original file line number Diff line number Diff line change
@@ -1,10 +1,32 @@
import org.jetbrains.kotlin.konan.target.KonanTarget
import org.jetbrains.kotlin.konan.target.HostManager

android {
compileSdk 34
namespace = "org.jetbrains.kotlinx.tests"

defaultConfig {
minSdk = 29
targetSdk = 34
}


buildTypes {
release {}
}
compileOptions {
sourceCompatibility = JavaVersion.VERSION_1_8
targetCompatibility = JavaVersion.VERSION_1_8
}
}

kotlin {
jvmToolchain(8)

jvm { }
js { nodejs() }
wasmJs { d8() }
androidTarget {}

if (HostManager.hostIsLinux) linuxX64('native')
if (HostManager.hostIsMingw) mingwX64('native')
Expand All @@ -18,5 +40,6 @@ benchmark {
register("js")
register("wasmJs")
register("native")
register("android")
}
}
2 changes: 1 addition & 1 deletion plugin/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -180,4 +180,4 @@ if (project.findProperty("publication_repository") == "space") {

apiValidation {
nonPublicMarkers += listOf("kotlinx.benchmark.gradle.internal.KotlinxBenchmarkPluginInternalApi")
}
}
42 changes: 42 additions & 0 deletions plugin/main/resources/GeneratedAndroidProject/app/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
plugins {
alias(libs.plugins.android.application)
alias(libs.plugins.jetbrains.kotlin.android)
}

android {
namespace = "kotlinx.benchmark.generatedandroidproject"
compileSdk = 34

defaultConfig {
applicationId = "kotlinx.benchmark.generatedandroidproject"
minSdk = 26
targetSdk = 34
versionCode = 1
versionName = "1.0"

testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
}

buildTypes {
release {
isMinifyEnabled = false
proguardFiles(
getDefaultProguardFile("proguard-android-optimize.txt"),
"proguard-rules.pro"
)
}
}
compileOptions {
sourceCompatibility = JavaVersion.VERSION_1_8
targetCompatibility = JavaVersion.VERSION_1_8
}
kotlinOptions {
jvmTarget = "1.8"
}
}

dependencies {
implementation(libs.androidx.core.ktx)
implementation(libs.androidx.appcompat)
implementation(libs.material)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# Add project specific ProGuard rules here.
# You can control the set of applied configuration files using the
# proguardFiles setting in build.gradle.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html

# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
# public *;
#}

# Uncomment this to preserve the line number information for
# debugging stack traces.
#-keepattributes SourceFile,LineNumberTable

# If you keep the line number information, uncomment this to
# hide the original source file name.
#-renamesourcefileattribute SourceFile
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">

<application
android:allowBackup="true"
android:dataExtractionRules="@xml/data_extraction_rules"
android:fullBackupContent="@xml/backup_rules"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/Theme.GeneratedAndroidProject"
tools:targetApi="31" />

</manifest>
Loading