diff --git a/integration/src/test/kotlin/kotlinx/benchmark/integration/GradleTest.kt b/integration/src/test/kotlin/kotlinx/benchmark/integration/GradleTest.kt index 14b1c94d..6d6551c5 100644 --- a/integration/src/test/kotlin/kotlinx/benchmark/integration/GradleTest.kt +++ b/integration/src/test/kotlin/kotlinx/benchmark/integration/GradleTest.kt @@ -26,7 +26,10 @@ abstract class GradleTest { val builder = ProjectBuilder().apply(build) templates.resolve(name).copyRecursively(rootProjectDir) file("build.gradle").modify(builder::build) - file("settings.gradle").writeText("") // empty settings file + val settingsFile = file("settings.gradle") + if (!settingsFile.exists()) { + file("settings.gradle").writeText("") // empty settings file + } return Runner(rootProjectDir, print, gradleVersion) } } diff --git a/integration/src/test/kotlin/kotlinx/benchmark/integration/JvmToolchainsTest.kt b/integration/src/test/kotlin/kotlinx/benchmark/integration/JvmToolchainsTest.kt new file mode 100644 index 00000000..645505dd --- /dev/null +++ b/integration/src/test/kotlin/kotlinx/benchmark/integration/JvmToolchainsTest.kt @@ -0,0 +1,17 @@ +package kotlinx.benchmark.integration + +import org.gradle.testkit.runner.TaskOutcome +import org.junit.Test +import kotlin.test.assertEquals + +class JvmToolchainsTest : GradleTest() { + @Test + fun testJvmToolchainSetup() { + val runner = project("kmp-with-toolchain", true, GradleTestVersion.v8_0) { + } + runner.run("benchmark") { + assertEquals(TaskOutcome.SUCCESS, task(":jvmBenchmark")!!.outcome) + assertOutputDoesNotContain("") + } + } +} diff --git a/integration/src/test/kotlin/kotlinx/benchmark/integration/testDsl.kt b/integration/src/test/kotlin/kotlinx/benchmark/integration/testDsl.kt index d301e624..75666a1f 100644 --- a/integration/src/test/kotlin/kotlinx/benchmark/integration/testDsl.kt +++ b/integration/src/test/kotlin/kotlinx/benchmark/integration/testDsl.kt @@ -45,4 +45,14 @@ internal fun BuildResult.assertOutputContains( } } -internal fun BuildResult.assertTasksUpToDate(tasks: Collection) = assertTasksUpToDate(*tasks.toTypedArray()) \ No newline at end of file +internal fun BuildResult.assertOutputDoesNotContain( + expectedSubString: String, + message: String = "Build output contains \"$expectedSubString\"" +) { + assert(!output.contains(expectedSubString)) { + printBuildOutput() + message + } +} + +internal fun BuildResult.assertTasksUpToDate(tasks: Collection) = assertTasksUpToDate(*tasks.toTypedArray()) diff --git a/integration/src/test/resources/templates/kmp-with-toolchain/build.gradle b/integration/src/test/resources/templates/kmp-with-toolchain/build.gradle new file mode 100644 index 00000000..f35e0edf --- /dev/null +++ b/integration/src/test/resources/templates/kmp-with-toolchain/build.gradle @@ -0,0 +1,19 @@ +kotlin { + jvm { + jvmToolchain(21) + } + + sourceSets { + commonMain { + dependencies { + implementation("org.jetbrains.kotlinx:kotlinx-benchmark-runtime:0.5.0-SNAPSHOT") + } + } + } +} + +benchmark { + targets { + register("jvm") + } +} diff --git a/integration/src/test/resources/templates/kmp-with-toolchain/gradle.properties b/integration/src/test/resources/templates/kmp-with-toolchain/gradle.properties new file mode 100644 index 00000000..7ec1fb65 --- /dev/null +++ b/integration/src/test/resources/templates/kmp-with-toolchain/gradle.properties @@ -0,0 +1 @@ +org.gradle.jvmargs=-Xmx2g -XX:MaxPermSize=2048m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8 \ No newline at end of file diff --git a/integration/src/test/resources/templates/kmp-with-toolchain/settings.gradle b/integration/src/test/resources/templates/kmp-with-toolchain/settings.gradle new file mode 100644 index 00000000..1791349e --- /dev/null +++ b/integration/src/test/resources/templates/kmp-with-toolchain/settings.gradle @@ -0,0 +1,3 @@ +plugins { + id("org.gradle.toolchains.foojay-resolver-convention") version "0.8.0" +} diff --git a/integration/src/test/resources/templates/kmp-with-toolchain/src/commonMain/kotlin/CommonBenchmark.kt b/integration/src/test/resources/templates/kmp-with-toolchain/src/commonMain/kotlin/CommonBenchmark.kt new file mode 100644 index 00000000..1174ed76 --- /dev/null +++ b/integration/src/test/resources/templates/kmp-with-toolchain/src/commonMain/kotlin/CommonBenchmark.kt @@ -0,0 +1,15 @@ +package test + +import kotlinx.benchmark.* +import kotlin.math.* + +// Don't really need to measure anything here, just check that the benchmark works +@State(Scope.Benchmark) +@Warmup(iterations = 0) +@Measurement(iterations = 1, time = 100, timeUnit = BenchmarkTimeUnit.MILLISECONDS) +@OutputTimeUnit(BenchmarkTimeUnit.MILLISECONDS) +@BenchmarkMode(Mode.Throughput) +open class CommonBenchmark { + @Benchmark + open fun mathBenchmark() = 3.14 +} diff --git a/plugin/main/src/kotlinx/benchmark/gradle/JmhBytecodeGeneratorTask.kt b/plugin/main/src/kotlinx/benchmark/gradle/JmhBytecodeGeneratorTask.kt index 7edef37d..51151864 100644 --- a/plugin/main/src/kotlinx/benchmark/gradle/JmhBytecodeGeneratorTask.kt +++ b/plugin/main/src/kotlinx/benchmark/gradle/JmhBytecodeGeneratorTask.kt @@ -2,6 +2,7 @@ package kotlinx.benchmark.gradle import org.gradle.api.* import org.gradle.api.file.* +import org.gradle.api.provider.Provider import org.gradle.api.tasks.* import org.gradle.workers.* import java.io.* @@ -28,11 +29,18 @@ open class JmhBytecodeGeneratorTask @InputFiles @PathSensitive(PathSensitivity.RELATIVE) lateinit var runtimeClasspath: FileCollection + + @Optional + @Input + var executableProvider: Provider = project.provider { null } @TaskAction fun generate() { val workQueue = workerExecutor.processIsolation { workerSpec -> workerSpec.classpath.setFrom(runtimeClasspath.files) + if (executableProvider.isPresent) { + workerSpec.forkOptions.executable = executableProvider.get() + } } workQueue.submit(JmhBytecodeGeneratorWorker::class.java) { workParameters -> workParameters.inputClasses.setFrom(inputClassesDirs.files) diff --git a/plugin/main/src/kotlinx/benchmark/gradle/JvmTasks.kt b/plugin/main/src/kotlinx/benchmark/gradle/JvmTasks.kt index f10fd38b..5add7ad7 100644 --- a/plugin/main/src/kotlinx/benchmark/gradle/JvmTasks.kt +++ b/plugin/main/src/kotlinx/benchmark/gradle/JvmTasks.kt @@ -20,6 +20,7 @@ fun Project.createJvmBenchmarkCompileTask(target: JvmBenchmarkTarget, compileCla classpath = compileClasspath source = fileTree("$benchmarkBuildDir/sources") destinationDirectory.set(file("$benchmarkBuildDir/classes")) + javaCompiler.set(javaCompilerProvider()) } task( @@ -90,6 +91,9 @@ fun Project.createJvmBenchmarkGenerateSourceTask( inputClassesDirs = compilationOutput outputResourcesDir = file("$benchmarkBuildDir/resources") outputSourcesDir = file("$benchmarkBuildDir/sources") + executableProvider = javaLauncherProvider().map { + it.executablePath.asFile.absolutePath + } } } @@ -123,5 +127,6 @@ fun Project.createJvmBenchmarkExecTask( val reportFile = setupReporting(target, config) args(writeParameters(target.name, reportFile, traceFormat(), config)) + javaLauncher.set(javaLauncherProvider()) } } diff --git a/plugin/main/src/kotlinx/benchmark/gradle/Utils.kt b/plugin/main/src/kotlinx/benchmark/gradle/Utils.kt index c07d4a11..500e0459 100644 --- a/plugin/main/src/kotlinx/benchmark/gradle/Utils.kt +++ b/plugin/main/src/kotlinx/benchmark/gradle/Utils.kt @@ -5,7 +5,12 @@ import org.gradle.api.Action import org.gradle.api.Project import org.gradle.api.Task import org.gradle.api.invocation.Gradle +import org.gradle.api.plugins.JavaPluginExtension +import org.gradle.api.provider.Provider import org.gradle.api.tasks.TaskProvider +import org.gradle.jvm.toolchain.JavaCompiler +import org.gradle.jvm.toolchain.JavaLauncher +import org.gradle.jvm.toolchain.JavaToolchainService import java.io.File import java.nio.file.Path import java.time.LocalDateTime @@ -261,4 +266,16 @@ internal fun Project.getSystemProperty(key: String): String? { } else { System.getProperty(key) } -} \ No newline at end of file +} + +fun Project.javaCompilerProvider(): Provider = provider { + val toolchainService = extensions.findByType(JavaToolchainService::class.java) ?: return@provider null + val javaExtension = extensions.findByType(JavaPluginExtension::class.java) ?: return@provider null + toolchainService.compilerFor(javaExtension.toolchain).orNull +} + +fun Project.javaLauncherProvider(): Provider = provider { + val toolchainService = extensions.findByType(JavaToolchainService::class.java) ?: return@provider null + val javaExtension = extensions.findByType(JavaPluginExtension::class.java) ?: return@provider null + toolchainService.launcherFor(javaExtension.toolchain).orNull +}