[K/N] Refactor runtime testing tasks
Merge-request: KT-MR-6360 Merged-by: Alexander Shabalin <Alexander.Shabalin@jetbrains.com>
This commit is contained in:
committed by
Space
parent
bb493ccb3e
commit
eaad75fd52
+125
-66
@@ -5,25 +5,33 @@
|
||||
|
||||
package org.jetbrains.kotlin.bitcode
|
||||
|
||||
import org.gradle.api.Action
|
||||
import org.gradle.api.Plugin
|
||||
import org.gradle.api.Project
|
||||
import org.gradle.api.Task
|
||||
import org.gradle.api.plugins.BasePlugin
|
||||
import org.gradle.api.provider.ListProperty
|
||||
import org.gradle.api.provider.Property
|
||||
import org.gradle.api.services.BuildService
|
||||
import org.gradle.api.services.BuildServiceParameters
|
||||
import org.gradle.kotlin.dsl.*
|
||||
import org.gradle.language.base.plugins.LifecycleBasePlugin
|
||||
import org.jetbrains.kotlin.ExecClang
|
||||
import org.jetbrains.kotlin.cpp.CompilationDatabaseExtension
|
||||
import org.jetbrains.kotlin.cpp.CompilationDatabasePlugin
|
||||
import org.jetbrains.kotlin.cpp.CompileToExecutable
|
||||
import org.jetbrains.kotlin.cpp.RunGTest
|
||||
import org.jetbrains.kotlin.konan.target.KonanTarget
|
||||
import org.jetbrains.kotlin.konan.target.PlatformManager
|
||||
import org.jetbrains.kotlin.konan.target.SanitizerKind
|
||||
import org.jetbrains.kotlin.konan.target.supportedSanitizers
|
||||
import org.jetbrains.kotlin.testing.native.CompileNativeTest
|
||||
import org.jetbrains.kotlin.testing.native.GoogleTestExtension
|
||||
import org.jetbrains.kotlin.testing.native.RunNativeTest
|
||||
import org.jetbrains.kotlin.testing.native.RuntimeTestingPlugin
|
||||
import org.jetbrains.kotlin.utils.Maybe
|
||||
import org.jetbrains.kotlin.utils.asMaybe
|
||||
import java.io.File
|
||||
import javax.inject.Inject
|
||||
|
||||
private abstract class RunGTestSemaphore : BuildService<BuildServiceParameters.None>
|
||||
private abstract class CompileTestsSemaphore : BuildService<BuildServiceParameters.None>
|
||||
|
||||
/**
|
||||
* A plugin creating extensions to compile
|
||||
*/
|
||||
@@ -42,6 +50,21 @@ open class CompileToBitcodeExtension @Inject constructor(val project: Project) {
|
||||
|
||||
private val compilationDatabase = project.extensions.getByType<CompilationDatabaseExtension>()
|
||||
private val execClang = project.extensions.getByType<ExecClang>()
|
||||
private val platformManager = project.extensions.getByType<PlatformManager>()
|
||||
|
||||
// googleTestExtension is only used if testsGroup is used.
|
||||
private val googleTestExtension by lazy { project.extensions.getByType<GoogleTestExtension>() }
|
||||
|
||||
// A shared service used to limit parallel execution of test binaries.
|
||||
private val runGTestSemaphore = project.gradle.sharedServices.registerIfAbsent("runGTestSemaphore", RunGTestSemaphore::class.java) {
|
||||
// Probably can be made configurable if test reporting moves away from simple gtest stdout dumping.
|
||||
maxParallelUsages.set(1)
|
||||
}
|
||||
|
||||
// TODO: remove when tests compilation does not consume so much memory.
|
||||
private val compileTestsSemaphore = project.gradle.sharedServices.registerIfAbsent("compileTestsSemaphore", CompileTestsSemaphore::class.java) {
|
||||
maxParallelUsages.set(5)
|
||||
}
|
||||
|
||||
private val targetList = with(project) {
|
||||
provider { (rootProject.project(":kotlin-native").property("targetList") as? List<*>)?.filterIsInstance<String>() ?: emptyList() } // TODO: Can we make it better?
|
||||
@@ -50,14 +73,20 @@ open class CompileToBitcodeExtension @Inject constructor(val project: Project) {
|
||||
private val allMainModulesTasks by lazy {
|
||||
val name = project.name.capitalized
|
||||
targetList.get().associateBy(keySelector = { it }, valueTransform = {
|
||||
project.tasks.register("${it}$name")
|
||||
project.tasks.register("${it}$name") {
|
||||
description = "Build all main modules of $name for $it"
|
||||
group = BUILD_TASK_GROUP
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
private val allTestsTasks by lazy {
|
||||
val name = project.name.capitalized
|
||||
targetList.get().associateBy(keySelector = { it }, valueTransform = {
|
||||
project.tasks.register("${it}${name}Tests")
|
||||
project.tasks.register("${it}${name}Tests") {
|
||||
description = "Runs all $name tests for $it"
|
||||
group = VERIFICATION_TASK_GROUP
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@@ -79,7 +108,6 @@ open class CompileToBitcodeExtension @Inject constructor(val project: Project) {
|
||||
|
||||
fun module(name: String, srcRoot: File = project.file("src/$name"), outputGroup: String = "main", configurationBlock: CompileToBitcode.() -> Unit = {}) {
|
||||
targetList.get().forEach { targetName ->
|
||||
val platformManager = project.rootProject.project(":kotlin-native").findProperty("platformManager") as PlatformManager
|
||||
val target = platformManager.targetByName(targetName)
|
||||
val sanitizers: List<SanitizerKind?> = target.supportedSanitizers() + listOf(null)
|
||||
val allMainModulesTask = allMainModulesTasks[targetName]!!
|
||||
@@ -90,13 +118,11 @@ open class CompileToBitcodeExtension @Inject constructor(val project: Project) {
|
||||
headersDirs = srcDirs + project.files(srcRoot.resolve("headers"))
|
||||
|
||||
this.sanitizer = sanitizer
|
||||
group = BasePlugin.BUILD_GROUP
|
||||
val sanitizerDescription = when (sanitizer) {
|
||||
null -> ""
|
||||
SanitizerKind.ADDRESS -> " with ASAN"
|
||||
SanitizerKind.THREAD -> " with TSAN"
|
||||
when (outputGroup) {
|
||||
"test" -> group = VERIFICATION_BUILD_TASK_GROUP
|
||||
"main" -> group = BUILD_TASK_GROUP
|
||||
}
|
||||
description = "Compiles '$name' to bitcode for $targetName$sanitizerDescription"
|
||||
description = "Compiles '$name' to bitcode for $targetName${sanitizer.description}"
|
||||
dependsOn(":kotlin-native:dependencies:update")
|
||||
configurationBlock()
|
||||
}
|
||||
@@ -110,28 +136,38 @@ open class CompileToBitcodeExtension @Inject constructor(val project: Project) {
|
||||
}
|
||||
}
|
||||
|
||||
abstract class TestsGroup @Inject constructor(
|
||||
val target: KonanTarget,
|
||||
private val _sanitizer: Maybe<SanitizerKind>,
|
||||
) {
|
||||
val sanitizer
|
||||
get() = _sanitizer.orNull
|
||||
abstract val testedModules: ListProperty<String>
|
||||
abstract val testSupportModules: ListProperty<String>
|
||||
abstract val testLauncherModule: Property<String>
|
||||
}
|
||||
|
||||
private fun createTestTask(
|
||||
project: Project,
|
||||
testName: String,
|
||||
testedTaskNames: List<String>,
|
||||
sanitizer: SanitizerKind?,
|
||||
): Task {
|
||||
val platformManager = project.project(":kotlin-native").findProperty("platformManager") as PlatformManager
|
||||
val googleTestExtension = project.extensions.getByName(RuntimeTestingPlugin.GOOGLE_TEST_EXTENSION_NAME) as GoogleTestExtension
|
||||
val testedTasks = testedTaskNames.map {
|
||||
project.tasks.getByName(it) as CompileToBitcode
|
||||
testTaskName: String,
|
||||
testsGroup: TestsGroup,
|
||||
) {
|
||||
val target = testsGroup.target
|
||||
val sanitizer = testsGroup.sanitizer
|
||||
val testName = fullTaskName(testTaskName, target.name, sanitizer)
|
||||
val testedTasks = testsGroup.testedModules.get().map {
|
||||
val name = fullTaskName(it, target.name, sanitizer)
|
||||
project.tasks.getByName(name) as CompileToBitcode
|
||||
}
|
||||
val target = testedTasks.map {
|
||||
it.target
|
||||
}.distinct().single()
|
||||
val konanTarget = platformManager.targetByName(target)
|
||||
val compileToBitcodeTasks = testedTasks.mapNotNull {
|
||||
val name = "${it.name}TestBitcode"
|
||||
val task = project.tasks.findByName(name) as? CompileToBitcode
|
||||
?: project.tasks.create(name, CompileToBitcode::class.java, "${it.folderName}Tests", target, "test").apply {
|
||||
?: project.tasks.create(name, CompileToBitcode::class.java, "${it.folderName}Tests", target.name, "test").apply {
|
||||
srcDirs = it.srcDirs
|
||||
headersDirs = it.headersDirs + googleTestExtension.headersDirs
|
||||
|
||||
group = VERIFICATION_BUILD_TASK_GROUP
|
||||
description = "Compiles '${it.name}' tests to bitcode for $target${sanitizer.description}"
|
||||
|
||||
this.sanitizer = sanitizer
|
||||
excludeFiles = emptyList()
|
||||
includeFiles = listOf("**/*Test.cpp", "**/*TestSupport.cpp", "**/*Test.mm", "**/*TestSupport.mm")
|
||||
@@ -139,71 +175,81 @@ open class CompileToBitcodeExtension @Inject constructor(val project: Project) {
|
||||
dependsOn("downloadGoogleTest")
|
||||
compilerArgs.addAll(it.compilerArgs)
|
||||
|
||||
addToCompdb(this, konanTarget)
|
||||
addToCompdb(this, target)
|
||||
}
|
||||
if (task.inputFiles.count() == 0) null
|
||||
else task
|
||||
}
|
||||
// TODO: Consider using sanitized versions.
|
||||
val testFrameworkTasks = listOf(project.tasks.getByName(fullTaskName("googletest", target, null)) as CompileToBitcode, project.tasks.getByName(fullTaskName("googlemock", target, null)) as CompileToBitcode)
|
||||
val testFrameworkTasks = testsGroup.testSupportModules.get().map {
|
||||
val name = fullTaskName(it, target.name, sanitizer)
|
||||
project.tasks.getByName(name) as CompileToBitcode
|
||||
}
|
||||
|
||||
val testSupportTask = project.tasks.getByName(fullTaskName("test_support", target, sanitizer)) as CompileToBitcode
|
||||
val testSupportTask = testsGroup.testLauncherModule.get().let {
|
||||
val name = fullTaskName(it, target.name, sanitizer)
|
||||
project.tasks.getByName(name) as CompileToBitcode
|
||||
}
|
||||
|
||||
val mimallocEnabled = testedTaskNames.any { it.contains("mimalloc", ignoreCase = true) }
|
||||
val compileTask = project.tasks.create(
|
||||
"${testName}Compile",
|
||||
CompileNativeTest::class.java,
|
||||
testName,
|
||||
konanTarget,
|
||||
testSupportTask.outFile,
|
||||
platformManager,
|
||||
mimallocEnabled,
|
||||
).apply {
|
||||
val tasksToLink = (compileToBitcodeTasks + testedTasks + testFrameworkTasks)
|
||||
this.sanitizer = sanitizer
|
||||
this.inputFiles.setFrom(tasksToLink.map { it.outFile })
|
||||
val compileTask = project.tasks.register<CompileToExecutable>("${testName}Compile") {
|
||||
description = "Compile tests group '$testTaskName' for $target${sanitizer.description}"
|
||||
group = VERIFICATION_BUILD_TASK_GROUP
|
||||
this.target.set(target)
|
||||
this.sanitizer.set(sanitizer)
|
||||
this.outputFile.set(project.layout.buildDirectory.file("bin/test/${target}/$testName${target.executableExtension}"))
|
||||
this.llvmLinkFirstStageOutputFile.set(project.layout.buildDirectory.file("bitcode/test/$target/$testName-firstStage.bc"))
|
||||
this.llvmLinkOutputFile.set(project.layout.buildDirectory.file("bitcode/test/$target/$testName.bc"))
|
||||
this.compilerOutputFile.set(project.layout.buildDirectory.file("obj/$target/$testName.o"))
|
||||
this.mimallocEnabled.set(testsGroup.testedModules.get().any { it.contains("mimalloc") })
|
||||
this.mainFile.set(testSupportTask.outFile)
|
||||
dependsOn(testSupportTask)
|
||||
val tasksToLink = (compileToBitcodeTasks + testedTasks + testFrameworkTasks)
|
||||
this.inputFiles.setFrom(tasksToLink.map { it.outFile })
|
||||
dependsOn(tasksToLink)
|
||||
|
||||
usesService(compileTestsSemaphore)
|
||||
}
|
||||
|
||||
val runTask = project.tasks.create(
|
||||
testName,
|
||||
RunNativeTest::class.java,
|
||||
testName,
|
||||
compileTask.outputFile,
|
||||
).apply {
|
||||
this.sanitizer = sanitizer
|
||||
val runTask = project.tasks.register<RunGTest>(testName) {
|
||||
description = "Runs tests group '$testTaskName' for $target${sanitizer.description}"
|
||||
group = VERIFICATION_TASK_GROUP
|
||||
this.testName.set(testName)
|
||||
executable.set(compileTask.flatMap { it.outputFile })
|
||||
dependsOn(compileTask)
|
||||
reportFileUnprocessed.set(project.layout.buildDirectory.file("testReports/$testName/report.xml"))
|
||||
reportFile.set(project.layout.buildDirectory.file("testReports/$testName/report-with-prefixes.xml"))
|
||||
filter.set(project.findProperty("gtest_filter") as? String)
|
||||
tsanSuppressionsFile.set(project.layout.projectDirectory.file("tsan_suppressions.txt"))
|
||||
|
||||
usesService(runGTestSemaphore)
|
||||
}
|
||||
|
||||
return runTask
|
||||
allTestsTasks[target.name]!!.configure {
|
||||
dependsOn(runTask)
|
||||
}
|
||||
}
|
||||
|
||||
fun testsGroup(
|
||||
testTaskName: String,
|
||||
testedTaskNames: List<String>,
|
||||
action: Action<in TestsGroup>,
|
||||
) {
|
||||
val platformManager = project.rootProject.project(":kotlin-native").findProperty("platformManager") as PlatformManager
|
||||
targetList.get().forEach { targetName ->
|
||||
val target = platformManager.targetByName(targetName)
|
||||
platformManager.enabled.forEach { target ->
|
||||
val sanitizers: List<SanitizerKind?> = target.supportedSanitizers() + listOf(null)
|
||||
val allTestsTask = allTestsTasks[targetName]!!
|
||||
sanitizers.forEach { sanitizer ->
|
||||
val name = fullTaskName(testTaskName, targetName, sanitizer)
|
||||
val testedNames = testedTaskNames.map {
|
||||
fullTaskName(it, targetName, sanitizer)
|
||||
}
|
||||
val task = createTestTask(project, name, testedNames, sanitizer)
|
||||
allTestsTask.configure {
|
||||
dependsOn(task)
|
||||
val instance = project.objects.newInstance(TestsGroup::class.java, target, sanitizer.asMaybe).apply {
|
||||
testSupportModules.convention(listOf("googletest", "googlemock"))
|
||||
testLauncherModule.convention("test_support")
|
||||
action.execute(this)
|
||||
}
|
||||
createTestTask(testTaskName, instance)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
||||
private const val COMPILATION_DATABASE_TASK_NAME = "CompilationDatabase"
|
||||
const val BUILD_TASK_GROUP = LifecycleBasePlugin.BUILD_GROUP
|
||||
const val VERIFICATION_TASK_GROUP = LifecycleBasePlugin.VERIFICATION_GROUP
|
||||
const val VERIFICATION_BUILD_TASK_GROUP = "verification build"
|
||||
|
||||
@OptIn(ExperimentalStdlibApi::class)
|
||||
private val String.capitalized: String
|
||||
@@ -220,5 +266,18 @@ open class CompileToBitcodeExtension @Inject constructor(val project: Project) {
|
||||
SanitizerKind.THREAD -> "_TSAN"
|
||||
}
|
||||
|
||||
private val SanitizerKind?.description
|
||||
get() = when (this) {
|
||||
null -> ""
|
||||
SanitizerKind.ADDRESS -> " with ASAN"
|
||||
SanitizerKind.THREAD -> " with TSAN"
|
||||
}
|
||||
|
||||
private val KonanTarget.executableExtension
|
||||
get() = when (this) {
|
||||
is KonanTarget.MINGW_X64 -> ".exe"
|
||||
is KonanTarget.MINGW_X86 -> ".exe"
|
||||
else -> ""
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+278
@@ -0,0 +1,278 @@
|
||||
/*
|
||||
* Copyright 2010-2022 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.cpp
|
||||
|
||||
import org.gradle.api.*
|
||||
import org.gradle.api.file.ConfigurableFileCollection
|
||||
import org.gradle.api.file.RegularFileProperty
|
||||
import org.gradle.api.logging.Logging
|
||||
import org.gradle.api.model.ObjectFactory
|
||||
import org.gradle.api.provider.ListProperty
|
||||
import org.gradle.api.provider.Property
|
||||
import org.gradle.api.provider.Provider
|
||||
import org.gradle.api.tasks.*
|
||||
import org.gradle.kotlin.dsl.getByType
|
||||
import org.gradle.process.ExecOperations
|
||||
import org.gradle.workers.WorkAction
|
||||
import org.gradle.workers.WorkParameters
|
||||
import org.gradle.workers.WorkerExecutor
|
||||
import org.jetbrains.kotlin.ExecClang
|
||||
import org.jetbrains.kotlin.execLlvmUtility
|
||||
import org.jetbrains.kotlin.konan.target.*
|
||||
import java.io.OutputStream
|
||||
import javax.inject.Inject
|
||||
|
||||
private abstract class CompileToExecutableJob : WorkAction<CompileToExecutableJob.Parameters> {
|
||||
interface Parameters : WorkParameters {
|
||||
val mainFile: RegularFileProperty
|
||||
val inputFiles: ConfigurableFileCollection
|
||||
val llvmLinkFirstStageOutputFile: RegularFileProperty
|
||||
val llvmLinkOutputFile: RegularFileProperty
|
||||
val compilerOutputFile: RegularFileProperty
|
||||
val outputFile: RegularFileProperty
|
||||
// TODO: Figure out a way to pass KonanTarget, but it is used as a key into PlatformManager,
|
||||
// so object identity matters, and platform managers are different between project and worker sides.
|
||||
val targetName: Property<String>
|
||||
val clangFlags: ListProperty<String>
|
||||
val linkCommands: ListProperty<List<String>>
|
||||
val platformManager: Property<PlatformManager>
|
||||
}
|
||||
|
||||
@get:Inject
|
||||
abstract val execOperations: ExecOperations
|
||||
|
||||
@get:Inject
|
||||
abstract val objects: ObjectFactory
|
||||
|
||||
private val target: KonanTarget by lazy {
|
||||
parameters.platformManager.get().targetByName(parameters.targetName.get())
|
||||
}
|
||||
|
||||
private fun llvmLink() {
|
||||
with(parameters) {
|
||||
llvmLinkFirstStageOutputFile.asFile.get().parentFile.mkdirs()
|
||||
|
||||
// The runtime provides our implementations for some standard functions (see StdCppStubs.cpp).
|
||||
// We need to internalize these symbols to avoid clashes with symbols provided by the C++ stdlib.
|
||||
// But llvm-link -internalize is kinda broken: it links modules one by one and can't see usages
|
||||
// of a symbol in subsequent modules. So it will mangle such symbols causing "unresolved symbol"
|
||||
// errors at the link stage. So we have to run llvm-link twice: the first one links all modules
|
||||
// except the one containing the entry point to a single *.bc without internalization. The second
|
||||
// run internalizes this big module and links it with a module containing the entry point.
|
||||
execOperations.execLlvmUtility(platformManager.get(), "llvm-link") {
|
||||
args = listOf("-o", llvmLinkFirstStageOutputFile.asFile.get().absolutePath) + inputFiles.map { it.absolutePath }
|
||||
}
|
||||
|
||||
llvmLinkOutputFile.asFile.get().parentFile.mkdirs()
|
||||
|
||||
execOperations.execLlvmUtility(platformManager.get(), "llvm-link") {
|
||||
args = listOf("-o", llvmLinkOutputFile.asFile.get().absolutePath, mainFile.asFile.get().absolutePath, llvmLinkFirstStageOutputFile.asFile.get().absolutePath, "-internalize")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun compile() {
|
||||
with(parameters) {
|
||||
val execClang = ExecClang.create(objects, platformManager.get())
|
||||
|
||||
val args = clangFlags.get() + listOf(llvmLinkOutputFile.asFile.get().absolutePath, "-o", compilerOutputFile.asFile.get().absolutePath)
|
||||
|
||||
compilerOutputFile.asFile.get().parentFile.mkdirs()
|
||||
|
||||
if (target.family.isAppleFamily) {
|
||||
execClang.execToolchainClang(target) {
|
||||
executable = "clang++"
|
||||
this.args = args
|
||||
}
|
||||
} else {
|
||||
execClang.execBareClang {
|
||||
executable = "clang++"
|
||||
this.args = args
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun link() {
|
||||
with(parameters) {
|
||||
outputFile.asFile.get().parentFile.mkdirs()
|
||||
|
||||
val logging = Logging.getLogger(CompileToExecutableJob::class.java)
|
||||
for (command in linkCommands.get()) {
|
||||
execOperations.exec {
|
||||
commandLine(command)
|
||||
if (!logging.isInfoEnabled && command[0].endsWith("dsymutil")) {
|
||||
// Suppress dsymutl's warnings.
|
||||
// See: https://bugs.swift.org/browse/SR-11539.
|
||||
val nullOutputStream = object : OutputStream() {
|
||||
override fun write(b: Int) {}
|
||||
}
|
||||
errorOutput = nullOutputStream
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun execute() {
|
||||
llvmLink()
|
||||
compile()
|
||||
link()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Compile bitcode files to binary executable.
|
||||
*
|
||||
* Takes bitcode files [inputFiles] and bitcode file [mainFile] with `main()` entrypoint and produces executable [outputFile].
|
||||
*
|
||||
* This works in 4 stages:
|
||||
* 1. `llvm-link` all [inputFiles] into [llvmLinkFirstStageOutputFile].
|
||||
* 2. `llvm-link` [llvmLinkFirstStageOutputFile] and [mainFile] with `-internalize` into [llvmLinkOutputFile].
|
||||
* 3. `clang++` [llvmLinkOutputFile] into object file [compilerOutputFile].
|
||||
* 4. Link [compilerOutputFile] into executable [outputFile].
|
||||
*
|
||||
* @see CompileToBitcodePlugin
|
||||
*/
|
||||
abstract class CompileToExecutable : DefaultTask() {
|
||||
|
||||
private val platformManager = project.extensions.getByType<PlatformManager>()
|
||||
|
||||
/**
|
||||
* Target for which to compile.
|
||||
*/
|
||||
@get:Input
|
||||
abstract val target: Property<KonanTarget>
|
||||
|
||||
/**
|
||||
* Sanitizer for which to compile.
|
||||
*/
|
||||
@get:Input
|
||||
@get:Optional
|
||||
abstract val sanitizer: Property<SanitizerKind>
|
||||
|
||||
// TODO: Should be replaced by a list of libraries to be linked with.
|
||||
/**
|
||||
* Controls whether linker should add library dependencies.
|
||||
*/
|
||||
@get:Input
|
||||
abstract val mimallocEnabled: Property<Boolean>
|
||||
|
||||
/**
|
||||
* Bitcode file with the `main()` entrypoint.
|
||||
*/
|
||||
@get:InputFile
|
||||
abstract val mainFile: RegularFileProperty
|
||||
|
||||
/**
|
||||
* Bitcode files.
|
||||
*
|
||||
* Bitcode file with main should be put into [mainFile] instead.
|
||||
*/
|
||||
@get:SkipWhenEmpty
|
||||
@get:InputFiles
|
||||
abstract val inputFiles: ConfigurableFileCollection
|
||||
|
||||
/**
|
||||
* Internal file with first stage llvm-link result.
|
||||
*/
|
||||
@get:Internal
|
||||
abstract val llvmLinkFirstStageOutputFile: RegularFileProperty
|
||||
|
||||
/**
|
||||
* Internal file with final stage llvm-link result.
|
||||
*/
|
||||
@get:Internal
|
||||
abstract val llvmLinkOutputFile: RegularFileProperty
|
||||
|
||||
/**
|
||||
* Internal file with compiler result.
|
||||
*/
|
||||
@get:Internal
|
||||
abstract val compilerOutputFile: RegularFileProperty
|
||||
|
||||
/**
|
||||
* Final executable.
|
||||
*/
|
||||
@get:OutputFile
|
||||
abstract val outputFile: RegularFileProperty
|
||||
|
||||
/**
|
||||
* Extra args to the compiler.
|
||||
*/
|
||||
@get:Input
|
||||
abstract val compilerArgs: ListProperty<String>
|
||||
|
||||
/**
|
||||
* Extra args to the linker.
|
||||
*/
|
||||
@get:Input
|
||||
abstract val linkerArgs: ListProperty<String>
|
||||
|
||||
@get:Input
|
||||
protected val linkCommands: Provider<List<List<String>>> = project.provider {
|
||||
// Getting link commands requires presence of a target toolchain.
|
||||
// Thus we cannot get them at the configuration stage because the toolchain may be not downloaded yet.
|
||||
platformManager.platform(target.get()).linker.finalLinkCommands(
|
||||
listOf(compilerOutputFile.asFile.get().absolutePath),
|
||||
outputFile.asFile.get().absolutePath,
|
||||
listOf(),
|
||||
linkerArgs.get(),
|
||||
optimize = false,
|
||||
debug = true,
|
||||
kind = LinkerOutputKind.EXECUTABLE,
|
||||
outputDsymBundle = outputFile.asFile.get().absolutePath + ".dSYM",
|
||||
needsProfileLibrary = false,
|
||||
mimallocEnabled = mimallocEnabled.get(),
|
||||
sanitizer = sanitizer.orNull
|
||||
).map { it.argsWithExecutable }
|
||||
}
|
||||
|
||||
@get:Inject
|
||||
protected abstract val workerExecutor: WorkerExecutor
|
||||
|
||||
@TaskAction
|
||||
fun compile() {
|
||||
val workQueue = workerExecutor.noIsolation()
|
||||
|
||||
val defaultClangFlags = buildClangFlags(platformManager.platform(target.get()).configurables)
|
||||
val sanitizerFlags = when (sanitizer.orNull) {
|
||||
null -> listOf()
|
||||
SanitizerKind.ADDRESS -> listOf("-fsanitize=address")
|
||||
SanitizerKind.THREAD -> listOf("-fsanitize=thread")
|
||||
}
|
||||
|
||||
workQueue.submit(CompileToExecutableJob::class.java) {
|
||||
mainFile.set(this@CompileToExecutable.mainFile)
|
||||
inputFiles.from(this@CompileToExecutable.inputFiles)
|
||||
llvmLinkFirstStageOutputFile.set(this@CompileToExecutable.llvmLinkFirstStageOutputFile)
|
||||
llvmLinkOutputFile.set(this@CompileToExecutable.llvmLinkOutputFile)
|
||||
compilerOutputFile.set(this@CompileToExecutable.compilerOutputFile)
|
||||
outputFile.set(this@CompileToExecutable.outputFile)
|
||||
targetName.set(this@CompileToExecutable.target.get().name)
|
||||
clangFlags.addAll(defaultClangFlags + compilerArgs.get() + sanitizerFlags)
|
||||
linkCommands.set(this@CompileToExecutable.linkCommands)
|
||||
platformManager.set(this@CompileToExecutable.platformManager)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a list of Clang -cc1 arguments (including -cc1 itself) that are used for bitcode compilation in Kotlin/Native.
|
||||
*
|
||||
* See also: [org.jetbrains.kotlin.backend.konan.BitcodeCompiler]
|
||||
*/
|
||||
private fun buildClangFlags(configurables: Configurables): List<String> = mutableListOf<String>().apply {
|
||||
require(configurables is ClangFlags)
|
||||
addAll(configurables.clangFlags)
|
||||
addAll(configurables.clangNooptFlags)
|
||||
val targetTriple = if (configurables is AppleConfigurables) {
|
||||
configurables.targetTriple.withOSVersion(configurables.osVersionMin)
|
||||
} else {
|
||||
configurables.targetTriple
|
||||
}
|
||||
addAll(listOf("-triple", targetTriple.toString()))
|
||||
}.toList()
|
||||
@@ -0,0 +1,133 @@
|
||||
/*
|
||||
* Copyright 2010-2022 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.cpp
|
||||
|
||||
import org.gradle.api.DefaultTask
|
||||
import org.gradle.api.file.RegularFileProperty
|
||||
import org.gradle.api.provider.Property
|
||||
import org.gradle.api.tasks.*
|
||||
import org.gradle.process.ExecOperations
|
||||
import org.gradle.workers.WorkAction
|
||||
import org.gradle.workers.WorkParameters
|
||||
import org.gradle.workers.WorkerExecutor
|
||||
import javax.inject.Inject
|
||||
|
||||
private abstract class RunGTestJob : WorkAction<RunGTestJob.Parameters> {
|
||||
interface Parameters : WorkParameters {
|
||||
val testName: Property<String>
|
||||
val executable: RegularFileProperty
|
||||
val reportFile: RegularFileProperty
|
||||
val reportFileUnprocessed: RegularFileProperty
|
||||
val filter: Property<String>
|
||||
val tsanSuppressionsFile: RegularFileProperty
|
||||
}
|
||||
|
||||
@get:Inject
|
||||
abstract val execOperations: ExecOperations
|
||||
|
||||
override fun execute() {
|
||||
// TODO: Use ExecutorService to allow running it on targets other than host.
|
||||
// TODO: Try to make it like other gradle test tasks: report progress in a way gradle understands instead of dumping stdout of gtest.
|
||||
|
||||
with(parameters) {
|
||||
reportFileUnprocessed.asFile.get().parentFile.mkdirs()
|
||||
|
||||
execOperations.exec {
|
||||
executable = this@with.executable.asFile.get().absolutePath
|
||||
|
||||
filter.orNull?.also {
|
||||
args("--gtest_filter=${it}")
|
||||
}
|
||||
args("--gtest_output=xml:${reportFileUnprocessed.asFile.get().absolutePath}")
|
||||
tsanSuppressionsFile.orNull?.also {
|
||||
environment("TSAN_OPTIONS", "suppressions=${it.asFile.absolutePath}")
|
||||
}
|
||||
}
|
||||
|
||||
reportFile.asFile.get().parentFile.mkdirs()
|
||||
|
||||
// TODO: Better to use proper XML parsing.
|
||||
var contents = reportFileUnprocessed.asFile.get().readText()
|
||||
contents = contents.replace("<testsuite name=\"", "<testsuite name=\"${testName.get()}.")
|
||||
contents = contents.replace("classname=\"", "classname=\"${testName.get()}.")
|
||||
reportFile.asFile.get().writeText(contents)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Run [googletest](https://google.github.io/googletest) test binary from [executable].
|
||||
*
|
||||
* Test reports are placed in [reportFileUnprocessed] and in [reportFile] (decorates each test with [testName]).
|
||||
*
|
||||
* @see CompileToBitcodePlugin
|
||||
*/
|
||||
abstract class RunGTest : DefaultTask() {
|
||||
/**
|
||||
* Decorating test names in the report.
|
||||
*
|
||||
* Useful when CI merges different test results of the same test but for different test targets.
|
||||
*/
|
||||
@get:Input
|
||||
abstract val testName: Property<String>
|
||||
|
||||
/**
|
||||
* Test executable
|
||||
*/
|
||||
@get:InputFile
|
||||
abstract val executable: RegularFileProperty
|
||||
|
||||
/**
|
||||
* Test report with each test name decorated with [testName].
|
||||
*/
|
||||
@get:OutputFile
|
||||
abstract val reportFile: RegularFileProperty
|
||||
|
||||
/**
|
||||
* Undecorated test report.
|
||||
*/
|
||||
@get:OutputFile
|
||||
abstract val reportFileUnprocessed: RegularFileProperty
|
||||
|
||||
/**
|
||||
* Run a subset of tests.
|
||||
*
|
||||
* Follows [googletest](https://google.github.io/googletest/advanced.html#running-a-subset-of-the-tests) syntax:
|
||||
* a ':'-separated list of glob patterns.
|
||||
*
|
||||
* Examples:
|
||||
* * `SomeTest*` - run every test starting with `SomeTest`.
|
||||
* * `SomeTest*:*stress*` - run every test starting with `SomeTest` and also every test containing `stress`.
|
||||
* * `SomeTest*:-SomeTest.flakyTest` - Run every test starting with `SomeTest` except `SomeTest.flakyTest`.
|
||||
*/
|
||||
@get:Input
|
||||
@get:Optional
|
||||
abstract val filter: Property<String>
|
||||
|
||||
/**
|
||||
* Suppression rules for TSAN.
|
||||
*/
|
||||
@get:InputFile
|
||||
@get:Optional
|
||||
abstract val tsanSuppressionsFile: RegularFileProperty
|
||||
|
||||
@get:Inject
|
||||
protected abstract val workerExecutor: WorkerExecutor
|
||||
|
||||
@TaskAction
|
||||
fun run() {
|
||||
val workQueue = workerExecutor.noIsolation()
|
||||
|
||||
workQueue.submit(RunGTestJob::class.java) {
|
||||
testName.set(this@RunGTest.testName)
|
||||
executable.set(this@RunGTest.executable)
|
||||
reportFile.set(this@RunGTest.reportFile)
|
||||
reportFileUnprocessed.set(this@RunGTest.reportFileUnprocessed)
|
||||
filter.set(this@RunGTest.filter)
|
||||
tsanSuppressionsFile.set(this@RunGTest.tsanSuppressionsFile)
|
||||
}
|
||||
}
|
||||
}
|
||||
-271
@@ -1,271 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||
* that can be found in the LICENSE file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.testing.native
|
||||
|
||||
import groovy.lang.Closure
|
||||
import java.io.File
|
||||
import javax.inject.Inject
|
||||
import org.gradle.api.*
|
||||
import org.gradle.api.file.ConfigurableFileCollection
|
||||
import org.gradle.api.logging.Logging
|
||||
import org.gradle.api.tasks.*
|
||||
import org.gradle.api.model.ObjectFactory
|
||||
import org.gradle.api.provider.Property
|
||||
import org.gradle.process.ExecOperations
|
||||
import org.gradle.workers.WorkAction
|
||||
import org.gradle.workers.WorkParameters
|
||||
import org.gradle.workers.WorkerExecutor
|
||||
import org.jetbrains.kotlin.ExecClang
|
||||
import org.jetbrains.kotlin.execLlvmUtility
|
||||
import org.jetbrains.kotlin.konan.target.*
|
||||
import java.io.OutputStream
|
||||
|
||||
interface CompileNativeTestParameters : WorkParameters {
|
||||
var mainFile: File
|
||||
var inputFiles: List<File>
|
||||
var llvmLinkOutputFile: File
|
||||
var compilerOutputFile: File
|
||||
var targetName: String
|
||||
var compilerArgs: List<String>
|
||||
var linkCommands: List<List<String>>
|
||||
val platformManager: Property<PlatformManager>
|
||||
}
|
||||
|
||||
abstract class CompileNativeTestJob : WorkAction<CompileNativeTestParameters> {
|
||||
@get:Inject
|
||||
abstract val execOperations: ExecOperations
|
||||
|
||||
@get:Inject
|
||||
abstract val objects: ObjectFactory
|
||||
|
||||
private fun llvmLink() {
|
||||
with(parameters) {
|
||||
val tmpOutput = File.createTempFile("runtimeTests", ".bc").apply {
|
||||
deleteOnExit()
|
||||
}
|
||||
|
||||
// The runtime provides our implementations for some standard functions (see StdCppStubs.cpp).
|
||||
// We need to internalize these symbols to avoid clashes with symbols provided by the C++ stdlib.
|
||||
// But llvm-link -internalize is kinda broken: it links modules one by one and can't see usages
|
||||
// of a symbol in subsequent modules. So it will mangle such symbols causing "unresolved symbol"
|
||||
// errors at the link stage. So we have to run llvm-link twice: the first one links all modules
|
||||
// except the one containing the entry point to a single *.bc without internalization. The second
|
||||
// run internalizes this big module and links it with a module containing the entry point.
|
||||
execOperations.execLlvmUtility(platformManager.get(), "llvm-link") {
|
||||
args = listOf("-o", tmpOutput.absolutePath) + inputFiles.map { it.absolutePath }
|
||||
}
|
||||
|
||||
execOperations.execLlvmUtility(platformManager.get(), "llvm-link") {
|
||||
args = listOf(
|
||||
"-o", llvmLinkOutputFile.absolutePath,
|
||||
mainFile.absolutePath,
|
||||
tmpOutput.absolutePath,
|
||||
"-internalize"
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun compile() {
|
||||
with(parameters) {
|
||||
val execClang = ExecClang.create(objects, platformManager.get())
|
||||
val target = platformManager.get().targetByName(targetName)
|
||||
|
||||
val clangFlags = buildClangFlags(platformManager.get().platform(target).configurables)
|
||||
|
||||
if (target.family.isAppleFamily) {
|
||||
execClang.execToolchainClang(target) {
|
||||
executable = "clang++"
|
||||
this.args = clangFlags + compilerArgs + listOf(llvmLinkOutputFile.absolutePath, "-o", compilerOutputFile.absolutePath)
|
||||
}
|
||||
} else {
|
||||
execClang.execBareClang {
|
||||
executable = "clang++"
|
||||
this.args = clangFlags + compilerArgs + listOf(llvmLinkOutputFile.absolutePath, "-o", compilerOutputFile.absolutePath)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun link() {
|
||||
val logging = Logging.getLogger(CompileNativeTestJob::class.java)
|
||||
|
||||
with(parameters) {
|
||||
for (command in linkCommands) {
|
||||
execOperations.exec {
|
||||
commandLine(command)
|
||||
if (!logging.isInfoEnabled && command[0].endsWith("dsymutil")) {
|
||||
// Suppress dsymutl's warnings.
|
||||
// See: https://bugs.swift.org/browse/SR-11539.
|
||||
val nullOutputStream = object: OutputStream() {
|
||||
override fun write(b: Int) {}
|
||||
}
|
||||
errorOutput = nullOutputStream
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun execute() {
|
||||
llvmLink()
|
||||
compile()
|
||||
link()
|
||||
}
|
||||
}
|
||||
|
||||
abstract class CompileNativeTest @Inject constructor(
|
||||
baseName: String,
|
||||
@Input val target: KonanTarget,
|
||||
@InputFile val mainFile: File,
|
||||
private val platformManager: PlatformManager,
|
||||
private val mimallocEnabled: Boolean,
|
||||
) : DefaultTask() {
|
||||
|
||||
@SkipWhenEmpty
|
||||
@InputFiles
|
||||
val inputFiles: ConfigurableFileCollection = project.files()
|
||||
|
||||
@OutputFile
|
||||
var llvmLinkOutputFile: File = project.buildDir.resolve("bitcode/test/${target.name}/$baseName.bc")
|
||||
|
||||
@OutputFile
|
||||
var compilerOutputFile: File = project.buildDir.resolve("bin/test/${target.name}/$baseName.o")
|
||||
|
||||
private val executableExtension: String = when (target) {
|
||||
is KonanTarget.MINGW_X64 -> ".exe"
|
||||
is KonanTarget.MINGW_X86 -> ".exe"
|
||||
else -> ""
|
||||
}
|
||||
|
||||
@OutputFile
|
||||
var outputFile: File = project.buildDir.resolve("bin/test/${target.name}/$baseName$executableExtension")
|
||||
|
||||
@Input
|
||||
val clangArgs = mutableListOf<String>()
|
||||
|
||||
@Input
|
||||
val linkerArgs = mutableListOf<String>()
|
||||
|
||||
@Input @Optional
|
||||
var sanitizer: SanitizerKind? = null
|
||||
|
||||
private val sanitizerFlags = when (sanitizer) {
|
||||
null -> listOf()
|
||||
SanitizerKind.ADDRESS -> listOf("-fsanitize=address")
|
||||
SanitizerKind.THREAD -> listOf("-fsanitize=thread")
|
||||
}
|
||||
|
||||
@get:Input
|
||||
val linkCommands: List<List<String>>
|
||||
get() {
|
||||
// Getting link commands requires presence of a target toolchain.
|
||||
// Thus we cannot get them at the configuration stage because the toolchain may be not downloaded yet.
|
||||
val linker = platformManager.platform(target).linker
|
||||
return linker.finalLinkCommands(
|
||||
listOf(compilerOutputFile.absolutePath),
|
||||
outputFile.absolutePath,
|
||||
listOf(),
|
||||
linkerArgs,
|
||||
optimize = false,
|
||||
debug = true,
|
||||
kind = LinkerOutputKind.EXECUTABLE,
|
||||
outputDsymBundle = outputFile.absolutePath + ".dSYM",
|
||||
needsProfileLibrary = false,
|
||||
mimallocEnabled = mimallocEnabled,
|
||||
sanitizer = sanitizer
|
||||
).map { it.argsWithExecutable }
|
||||
}
|
||||
|
||||
@get:Inject
|
||||
abstract val workerExecutor: WorkerExecutor
|
||||
|
||||
@TaskAction
|
||||
fun compile() {
|
||||
val workQueue = workerExecutor.noIsolation()
|
||||
|
||||
val parameters = { it: CompileNativeTestParameters ->
|
||||
it.mainFile = mainFile
|
||||
it.inputFiles = inputFiles.map { it }
|
||||
it.llvmLinkOutputFile = llvmLinkOutputFile
|
||||
it.compilerOutputFile = compilerOutputFile
|
||||
it.targetName = target.name
|
||||
it.compilerArgs = clangArgs + sanitizerFlags
|
||||
it.linkCommands = linkCommands
|
||||
it.platformManager.set(platformManager)
|
||||
}
|
||||
|
||||
workQueue.submit(CompileNativeTestJob::class.java, parameters)
|
||||
}
|
||||
}
|
||||
|
||||
open class RunNativeTest @Inject constructor(
|
||||
@Input val testName: String,
|
||||
@InputFile val inputFile: File,
|
||||
) : DefaultTask() {
|
||||
|
||||
@Internal
|
||||
var workingDir: File = project.buildDir.resolve("testReports/$testName")
|
||||
|
||||
@OutputFile
|
||||
var outputFile: File = workingDir.resolve("report.xml")
|
||||
|
||||
@OutputFile
|
||||
var outputFileWithPrefixes: File = workingDir.resolve("report-with-prefixes.xml")
|
||||
|
||||
@Input @Optional
|
||||
var filter: String? = project.findProperty("gtest_filter") as? String
|
||||
|
||||
@Input @Optional
|
||||
var sanitizer: SanitizerKind? = null
|
||||
|
||||
@InputFile
|
||||
var tsanSuppressionsFile = project.file("tsan_suppressions.txt")
|
||||
|
||||
@TaskAction
|
||||
fun run() {
|
||||
workingDir.mkdirs()
|
||||
|
||||
// Do not run this in workers, because we don't want this task to run in parallel.
|
||||
project.exec {
|
||||
executable = inputFile.absolutePath
|
||||
|
||||
if (filter != null) {
|
||||
args("--gtest_filter=${filter}")
|
||||
}
|
||||
args("--gtest_output=xml:${outputFile.absolutePath}")
|
||||
when (sanitizer) {
|
||||
SanitizerKind.THREAD -> {
|
||||
environment("TSAN_OPTIONS", "suppressions=${tsanSuppressionsFile.absolutePath}")
|
||||
}
|
||||
else -> {} // no action required
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Better to use proper XML parsing.
|
||||
var contents = outputFile.readText()
|
||||
contents = contents.replace("<testsuite name=\"", "<testsuite name=\"${testName}.")
|
||||
contents = contents.replace("classname=\"", "classname=\"${testName}.")
|
||||
outputFileWithPrefixes.writeText(contents)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a list of Clang -cc1 arguments (including -cc1 itself) that are used for bitcode compilation in Kotlin/Native.
|
||||
*
|
||||
* See also: [org.jetbrains.kotlin.backend.konan.BitcodeCompiler]
|
||||
*/
|
||||
private fun buildClangFlags(configurables: Configurables): List<String> = mutableListOf<String>().apply {
|
||||
require(configurables is ClangFlags)
|
||||
addAll(configurables.clangFlags)
|
||||
addAll(configurables.clangNooptFlags)
|
||||
val targetTriple = if (configurables is AppleConfigurables) {
|
||||
configurables.targetTriple.withOSVersion(configurables.osVersionMin)
|
||||
} else {
|
||||
configurables.targetTriple
|
||||
}
|
||||
addAll(listOf("-triple", targetTriple.toString()))
|
||||
}.toList()
|
||||
@@ -0,0 +1,23 @@
|
||||
/*
|
||||
* Copyright 2010-2022 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.utils
|
||||
|
||||
/**
|
||||
* Wrapper over [T]?.
|
||||
*
|
||||
* Useful for some generalized functions that you want to pass [T]? into, but they forbid nullable types.
|
||||
* For example, [ObjectFactory.newInstance][org.gradle.api.model.ObjectFactory.newInstance] cannot be used
|
||||
* to construct a type that has [T]? as a constructor argument.
|
||||
*
|
||||
* @property orNull get underlying value.
|
||||
*/
|
||||
data class Maybe<T>(val orNull: T?)
|
||||
|
||||
/**
|
||||
* Construct [Maybe]<[T]> from [T]?.
|
||||
*/
|
||||
inline val <T> T?.asMaybe
|
||||
get() = Maybe(this)
|
||||
@@ -4,6 +4,7 @@
|
||||
*/
|
||||
import org.jetbrains.kotlin.*
|
||||
import org.jetbrains.kotlin.bitcode.CompileToBitcode
|
||||
import org.jetbrains.kotlin.bitcode.CompileToBitcodeExtension
|
||||
import org.jetbrains.kotlin.gradle.plugin.konan.tasks.KonanCacheTask
|
||||
import org.jetbrains.kotlin.konan.properties.loadProperties
|
||||
import org.jetbrains.kotlin.konan.properties.saveProperties
|
||||
@@ -182,28 +183,48 @@ bitcode {
|
||||
onlyIf { targetSupportsThreads(target) }
|
||||
}
|
||||
|
||||
testsGroup("std_alloc_runtime_tests", listOf("main", "legacy_memory_manager", "strict", "std_alloc", "objc"))
|
||||
testsGroup("std_alloc_runtime_tests") {
|
||||
testedModules.addAll("main", "legacy_memory_manager", "strict", "std_alloc", "objc")
|
||||
}
|
||||
|
||||
testsGroup("mimalloc_runtime_tests", listOf("main", "legacy_memory_manager", "strict", "mimalloc", "opt_alloc", "objc"))
|
||||
testsGroup("mimalloc_runtime_tests") {
|
||||
testedModules.addAll("main", "legacy_memory_manager", "strict", "mimalloc", "opt_alloc", "objc")
|
||||
}
|
||||
|
||||
testsGroup("experimentalMM_mimalloc_runtime_tests", listOf("main", "experimental_memory_manager", "common_gc", "same_thread_ms_gc", "mimalloc", "opt_alloc", "objc"))
|
||||
testsGroup("experimentalMM_mimalloc_runtime_tests") {
|
||||
testedModules.addAll("main", "experimental_memory_manager", "common_gc", "same_thread_ms_gc", "mimalloc", "opt_alloc", "objc")
|
||||
}
|
||||
|
||||
testsGroup("experimentalMM_std_alloc_runtime_tests", listOf("main", "experimental_memory_manager", "common_gc", "same_thread_ms_gc", "std_alloc", "objc"))
|
||||
testsGroup("experimentalMM_std_alloc_runtime_tests") {
|
||||
testedModules.addAll("main", "experimental_memory_manager", "common_gc", "same_thread_ms_gc", "std_alloc", "objc")
|
||||
}
|
||||
|
||||
testsGroup("experimentalMM_cms_mimalloc_runtime_tests", listOf("main", "experimental_memory_manager", "common_gc", "concurrent_ms_gc", "mimalloc", "opt_alloc", "objc"))
|
||||
testsGroup("experimentalMM_cms_mimalloc_runtime_tests") {
|
||||
testedModules.addAll("main", "experimental_memory_manager", "common_gc", "concurrent_ms_gc", "mimalloc", "opt_alloc", "objc")
|
||||
}
|
||||
|
||||
testsGroup("experimentalMM_cms_std_alloc_runtime_tests", listOf("main", "experimental_memory_manager", "common_gc", "concurrent_ms_gc", "std_alloc", "objc"))
|
||||
testsGroup("experimentalMM_cms_std_alloc_runtime_tests") {
|
||||
testedModules.addAll("main", "experimental_memory_manager", "common_gc", "concurrent_ms_gc", "std_alloc", "objc")
|
||||
}
|
||||
|
||||
testsGroup("experimentalMM_noop_mimalloc_runtime_tests", listOf("main", "experimental_memory_manager", "common_gc", "noop_gc", "mimalloc", "opt_alloc", "objc"))
|
||||
testsGroup("experimentalMM_noop_mimalloc_runtime_tests") {
|
||||
testedModules.addAll("main", "experimental_memory_manager", "common_gc", "noop_gc", "mimalloc", "opt_alloc", "objc")
|
||||
}
|
||||
|
||||
testsGroup("experimentalMM_noop_std_alloc_runtime_tests", listOf("main", "experimental_memory_manager", "common_gc", "noop_gc", "std_alloc", "objc"))
|
||||
testsGroup("experimentalMM_noop_std_alloc_runtime_tests") {
|
||||
testedModules.addAll("main", "experimental_memory_manager", "common_gc", "noop_gc", "std_alloc", "objc")
|
||||
}
|
||||
}
|
||||
|
||||
val hostRuntime by tasks.registering {
|
||||
description = "Build all main runtime modules for host"
|
||||
group = CompileToBitcodeExtension.BUILD_TASK_GROUP
|
||||
dependsOn("${hostName}Runtime")
|
||||
}
|
||||
|
||||
val hostRuntimeTests by tasks.registering {
|
||||
description = "Runs all runtime tests for host"
|
||||
group = CompileToBitcodeExtension.VERIFICATION_TASK_GROUP
|
||||
dependsOn("${hostName}RuntimeTests")
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user