diff --git a/kotlin-native/build-tools/src/main/kotlin/org/jetbrains/kotlin/bitcode/CompileToBitcode.kt b/kotlin-native/build-tools/src/main/kotlin/org/jetbrains/kotlin/bitcode/CompileToBitcode.kt index 1dac84b2a79..c7bbb2a2ec0 100644 --- a/kotlin-native/build-tools/src/main/kotlin/org/jetbrains/kotlin/bitcode/CompileToBitcode.kt +++ b/kotlin-native/build-tools/src/main/kotlin/org/jetbrains/kotlin/bitcode/CompileToBitcode.kt @@ -22,10 +22,9 @@ 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.KonanTarget import org.jetbrains.kotlin.konan.target.PlatformManager import org.jetbrains.kotlin.konan.target.SanitizerKind -import org.jetbrains.kotlin.utils.Maybe +import org.jetbrains.kotlin.konan.target.TargetWithSanitizer import java.io.File import javax.inject.Inject @@ -83,21 +82,23 @@ private abstract class CompileToBitcodeJob : WorkAction, + private val _target: TargetWithSanitizer, ) : DefaultTask() { + /** + * Target for which to compile + */ + @get:Input + val target by _target::target /** - * Compile with sanitizer enabled. + * Optional [sanitizer][SanitizerKind] for [target]. */ @get:Input @get:Optional - val sanitizer - get() = _sanitizer.orNull + val sanitizer by _target::sanitizer /** * Final output file. diff --git a/kotlin-native/build-tools/src/main/kotlin/org/jetbrains/kotlin/bitcode/CompileToBitcodePlugin.kt b/kotlin-native/build-tools/src/main/kotlin/org/jetbrains/kotlin/bitcode/CompileToBitcodePlugin.kt index ec16712fc8f..e7f8596fcbc 100644 --- a/kotlin-native/build-tools/src/main/kotlin/org/jetbrains/kotlin/bitcode/CompileToBitcodePlugin.kt +++ b/kotlin-native/build-tools/src/main/kotlin/org/jetbrains/kotlin/bitcode/CompileToBitcodePlugin.kt @@ -17,20 +17,12 @@ import org.gradle.kotlin.dsl.* import org.gradle.language.base.plugins.LifecycleBasePlugin import org.jetbrains.kotlin.ExecClang import org.jetbrains.kotlin.cpp.* -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.TargetDomainObjectContainer +import org.jetbrains.kotlin.konan.target.* import org.jetbrains.kotlin.testing.native.GoogleTestExtension -import org.jetbrains.kotlin.utils.Maybe -import org.jetbrains.kotlin.utils.asMaybe +import org.jetbrains.kotlin.utils.capitalized import java.io.File import javax.inject.Inject -@OptIn(ExperimentalStdlibApi::class) -private val String.capitalized: String - get() = replaceFirstChar { it.uppercase() } - private fun String.snakeCaseToUpperCamelCase() = split('_').joinToString(separator = "") { it.capitalized } private fun fullTaskName(name: String, targetName: String, sanitizer: SanitizerKind?) = "${targetName}${name.snakeCaseToUpperCamelCase()}${sanitizer.taskSuffix}" @@ -76,8 +68,8 @@ open class CompileToBitcodePlugin : Plugin { open class CompileToBitcodeExtension @Inject constructor(val project: Project) : TargetDomainObjectContainer(project) { init { - this.factory = { target, sanitizer -> - project.objects.newInstance(this, target, sanitizer.asMaybe) + this.factory = { target -> + project.objects.newInstance(this, target) } } @@ -118,11 +110,10 @@ open class CompileToBitcodeExtension @Inject constructor(val project: Project) : } abstract class TestsGroup @Inject constructor( - val target: KonanTarget, - private val _sanitizer: Maybe, + private val _target: TargetWithSanitizer, ) { - val sanitizer - get() = _sanitizer.orNull + val target by _target::target + val sanitizer by _target::sanitizer abstract val testedModules: ListProperty abstract val testSupportModules: ListProperty abstract val testFrameworkModules: ListProperty @@ -131,10 +122,10 @@ open class CompileToBitcodeExtension @Inject constructor(val project: Project) : abstract class Target @Inject constructor( private val owner: CompileToBitcodeExtension, - val target: KonanTarget, - _sanitizer: Maybe, + private val _target: TargetWithSanitizer, ) { - val sanitizer = _sanitizer.orNull + val target by _target::target + val sanitizer by _target::sanitizer private val project by owner::project @@ -157,7 +148,7 @@ open class CompileToBitcodeExtension @Inject constructor(val project: Project) : } private fun addToCompdb(compileTask: CompileToBitcode) { - compilationDatabase.target(target, sanitizer) { + compilationDatabase.target(_target) { entry { val args = listOf(execClang.resolveExecutable(compileTask.compiler.get())) + compileTask.compilerFlags.get() + execClang.clangArgsForCppRuntime(target.name) directory.set(compileTask.compilerWorkingDirectory) @@ -166,6 +157,13 @@ open class CompileToBitcodeExtension @Inject constructor(val project: Project) : // Only the location of output file matters, compdb does not depend on the compilation result. output.set(compileTask.outputFile.locationOnly.map { it.asFile.absolutePath }) } + // Compile task depends on the toolchain (including headers) and on the source code (e.g. googletest). + // compdb task should also have these dependencies. This way the generated database will point to the + // code that actually exists. + // TODO: Probably module should know dependencies on its own. + task.configure { + dependsOn(compileTask.dependsOn) + } } } @@ -173,7 +171,7 @@ open class CompileToBitcodeExtension @Inject constructor(val project: Project) : val targetName = target.name val allMainModulesTask = owner.allMainModulesTasks[targetName]!! val taskName = fullTaskName(name, targetName, sanitizer) - val task = project.tasks.create(taskName, CompileToBitcode::class.java, target, sanitizer.asMaybe).apply { + val task = project.tasks.create(taskName, CompileToBitcode::class.java, _target).apply { this.moduleName.set(name) this.outputFile.convention(moduleName.flatMap { project.layout.buildDirectory.file("bitcode/$outputGroup/$target${sanitizer.dirSuffix}/$it.bc") }) this.outputDirectory.convention(moduleName.flatMap { project.layout.buildDirectory.dir("bitcode/$outputGroup/$target${sanitizer.dirSuffix}/$it") }) @@ -204,7 +202,7 @@ open class CompileToBitcodeExtension @Inject constructor(val project: Project) : testTaskName: String, action: Action, ) { - val testsGroup = project.objects.newInstance(TestsGroup::class.java, target, sanitizer.asMaybe).apply { + val testsGroup = project.objects.newInstance(TestsGroup::class.java, _target).apply { testFrameworkModules.convention(listOf("googletest", "googlemock")) testLauncherModule.convention("test_support") action.execute(this) @@ -219,7 +217,7 @@ open class CompileToBitcodeExtension @Inject constructor(val project: Project) : val testedModulesTestTasks = testedModulesMainTasks.mapNotNull { val name = "${it.name}TestBitcode" val task = project.tasks.findByName(name) as? CompileToBitcode - ?: project.tasks.create(name, CompileToBitcode::class.java, it.target, it.sanitizer.asMaybe).apply { + ?: project.tasks.create(name, CompileToBitcode::class.java, _target).apply { this.moduleName.set(it.moduleName) this.outputFile.convention(moduleName.flatMap { project.layout.buildDirectory.file("bitcode/test/$target${sanitizer.dirSuffix}/${it}Tests.bc") }) this.outputDirectory.convention(moduleName.flatMap { project.layout.buildDirectory.dir("bitcode/test/$target${sanitizer.dirSuffix}/${it}Tests") }) @@ -247,7 +245,7 @@ open class CompileToBitcodeExtension @Inject constructor(val project: Project) : val testedAndTestSupportModulesTestSupportTasks = (testedModulesMainTasks + testSupportModulesMainTasks).mapNotNull { val name = "${it.name}TestSupportBitcode" val task = project.tasks.findByName(name) as? CompileToBitcode - ?: project.tasks.create(name, CompileToBitcode::class.java, it.target, it.sanitizer.asMaybe).apply { + ?: project.tasks.create(name, CompileToBitcode::class.java, _target).apply { this.moduleName.set(it.moduleName) this.outputFile.convention(moduleName.flatMap { project.layout.buildDirectory.file("bitcode/test/$target${sanitizer.dirSuffix}/${it}TestSupport.bc") }) this.outputDirectory.convention(moduleName.flatMap { project.layout.buildDirectory.dir("bitcode/test/$target${sanitizer.dirSuffix}/${it}TestSupport") }) diff --git a/kotlin-native/build-tools/src/main/kotlin/org/jetbrains/kotlin/cpp/CompilationDatabasePlugin.kt b/kotlin-native/build-tools/src/main/kotlin/org/jetbrains/kotlin/cpp/CompilationDatabasePlugin.kt index c3dff9d2c24..15f4ad6bef0 100644 --- a/kotlin-native/build-tools/src/main/kotlin/org/jetbrains/kotlin/cpp/CompilationDatabasePlugin.kt +++ b/kotlin-native/build-tools/src/main/kotlin/org/jetbrains/kotlin/cpp/CompilationDatabasePlugin.kt @@ -8,21 +8,16 @@ package org.jetbrains.kotlin.cpp import org.gradle.api.Action import org.gradle.api.Plugin import org.gradle.api.Project +import org.gradle.api.artifacts.Configuration +import org.gradle.api.attributes.Usage import org.gradle.api.file.ConfigurableFileCollection import org.gradle.api.file.DirectoryProperty import org.gradle.api.provider.ListProperty import org.gradle.api.provider.Property -import org.gradle.api.provider.Provider -import org.gradle.kotlin.dsl.create -import org.gradle.kotlin.dsl.getByType -import org.gradle.kotlin.dsl.newInstance -import org.gradle.kotlin.dsl.register -import org.jetbrains.kotlin.konan.target.KonanTarget -import org.jetbrains.kotlin.konan.target.SanitizerKind +import org.gradle.kotlin.dsl.* import org.jetbrains.kotlin.konan.target.TargetDomainObjectContainer -import org.jetbrains.kotlin.konan.target.targetSuffix -import org.jetbrains.kotlin.utils.Maybe -import org.jetbrains.kotlin.utils.asMaybe +import org.jetbrains.kotlin.konan.target.TargetWithSanitizer +import org.jetbrains.kotlin.utils.capitalized import javax.inject.Inject /** @@ -30,25 +25,37 @@ import javax.inject.Inject * * Allows generating compilation databases for different targets. For example: * ``` + * dependencies { + * compilationDatabase(project(":some:other:project")) + * } + * * compilationDatabase { * target(someTarget1) { * entry { ... } * } * allTargets { - * mergeFrom(provider { project("subproject") }) + * mergeFrom(compilationDatabase) * } * } * ``` - * Adds an entry for target `someTarget1`, and for each known target merges in databases generated - * by this plugin in `subproject`. + * Adds an entry for target `someTarget1`, and for each known target merges in databases from `:some:other:project`. * The task that generates the database can be found via `compilationDatabase.target(someTarget1).task`. * * @see CompilationDatabasePlugin gradle plugin that creates this extension. */ abstract class CompilationDatabaseExtension @Inject constructor(private val project: Project) : TargetDomainObjectContainer(project) { init { - this.factory = { target, sanitizer -> - project.objects.newInstance(project, target, sanitizer.asMaybe) + this.factory = { target -> + project.objects.newInstance(this, target) + } + } + + private val outgoingConfiguration = project.configurations.create("generateCompilationDatabase") { + description = "Generate Compilation Database" + isCanBeConsumed = true + isCanBeResolved = false + attributes { + attribute(Usage.USAGE_ATTRIBUTE, project.objects.named(Usage::class.java, USAGE)) } } @@ -61,10 +68,10 @@ abstract class CompilationDatabaseExtension @Inject constructor(private val proj * @property sanitizer optional sanitizer for [target]. */ abstract class Entry @Inject constructor( - val target: KonanTarget, - _sanitizer: Maybe, + private val _target: TargetWithSanitizer, ) { - val sanitizer = _sanitizer.orNull + val target by _target::target + val sanitizer by _target::sanitizer /** * **directory** from the [JSON Compilation Database](https://clang.llvm.org/docs/JSONCompilationDatabase.html#format). @@ -101,31 +108,19 @@ abstract class CompilationDatabaseExtension @Inject constructor(private val proj * Configure compilation database generation for [target]. * * [entry] to add new entries. - * [mergeFrom] to merge databases from other projects with [CompilationDatabasePlugin]s. * [task] is the gradle task for compilation database generation. * * @property target target for which compilation database is generated. * @property sanitizer optional sanitizer for which compilation database is generated. */ abstract class Target @Inject constructor( - private val project: Project, - val target: KonanTarget, - _sanitizer: Maybe, + private val owner: CompilationDatabaseExtension, + private val _target: TargetWithSanitizer, ) { - val sanitizer = _sanitizer.orNull + val target by _target::target + val sanitizer by _target::sanitizer - protected abstract val mergeFrom: ListProperty - - /** - * Merge compilation database generated for [from] project for [target] with optional [sanitizer]. - * - * @param from project with applied [CompilationDatabasePlugin] to merge compilation database from. - */ - fun mergeFrom(from: Provider) { - mergeFrom.add(from.flatMap { project -> - project.extensions.getByType().target(target, sanitizer).task - }) - } + private val project by owner::project protected abstract val entries: ListProperty @@ -136,7 +131,7 @@ abstract class CompilationDatabaseExtension @Inject constructor(private val proj */ fun entry(action: Action) { entries.add(project.provider { - val instance = project.objects.newInstance(target, sanitizer.asMaybe).apply { + val instance = project.objects.newInstance(_target).apply { action.execute(this) } project.objects.newInstance().apply { @@ -148,21 +143,56 @@ abstract class CompilationDatabaseExtension @Inject constructor(private val proj }) } + protected abstract val mergeFrom: ListProperty + + /** + * Merge compilation database entries from given [configuration]. + * + * @param configuration provider of additional compilation database entries + */ + fun mergeFrom(configuration: Configuration) { + mergeFrom.add(configuration) + } + /** * Gradle task that generates compilation database for [target] with optional [sanitizer]. */ - val task = project.tasks.register("${target}${sanitizer.targetSuffix}CompilationDatabase") { - description = "Generate compilation database for $target${sanitizer.targetSuffix}" + val task = project.tasks.register("compilationDatabase${_target.name.capitalized}") { + description = "Generate compilation database for $_target" group = TASK_GROUP - mergeFiles.from(mergeFrom) + mergeFiles.from(mergeFrom.map { configurations -> + configurations.map { + it.incoming.artifactView { + attributes { + attribute(TargetWithSanitizer.TARGET_ATTRIBUTE, _target) + } + }.files + } + }) entries.set(this@Target.entries) - outputFile.set(project.layout.buildDirectory.file("${target}${sanitizer.targetSuffix}/compile_commands.json")) + outputFile.set(project.layout.buildDirectory.file("$_target/compile_commands.json")) + } + + init { + owner.outgoingConfiguration.outgoing { + variants { + create("$_target") { + attributes { + attribute(TargetWithSanitizer.TARGET_ATTRIBUTE, _target) + } + artifact(task) + } + } + } } } companion object { @JvmStatic val TASK_GROUP = "development support" + + @JvmStatic + val USAGE = "compilationDatabase" } } @@ -170,11 +200,23 @@ abstract class CompilationDatabaseExtension @Inject constructor(private val proj * Generating [JSON Compilation Database](https://clang.llvm.org/docs/JSONCompilationDatabase.html). * * Creates [CompilationDatabaseExtension] extension named `compilationDatabase`. + * Creates [Configuration][org.gradle.api.artifacts.Configuration] named `compilationDatabase`. * * @see CompilationDatabaseExtension extension that this plugin creates. */ open class CompilationDatabasePlugin : Plugin { override fun apply(project: Project) { project.extensions.create("compilationDatabase", project) + project.dependencies.attributesSchema { + attribute(TargetWithSanitizer.TARGET_ATTRIBUTE) + } + project.configurations.create("compilationDatabase") { + description = "Compilation Database" + isCanBeConsumed = false + isCanBeResolved = true + attributes { + attribute(Usage.USAGE_ATTRIBUTE, project.objects.named(CompilationDatabaseExtension.USAGE)) + } + } } } diff --git a/kotlin-native/build-tools/src/main/kotlin/org/jetbrains/kotlin/cpp/GenerateCompilationDatabase.kt b/kotlin-native/build-tools/src/main/kotlin/org/jetbrains/kotlin/cpp/GenerateCompilationDatabase.kt index 372285f11a7..cfd4176fe61 100644 --- a/kotlin-native/build-tools/src/main/kotlin/org/jetbrains/kotlin/cpp/GenerateCompilationDatabase.kt +++ b/kotlin-native/build-tools/src/main/kotlin/org/jetbrains/kotlin/cpp/GenerateCompilationDatabase.kt @@ -5,6 +5,7 @@ package org.jetbrains.kotlin.cpp +import com.google.gson.JsonSyntaxException import com.google.gson.annotations.Expose import org.gradle.api.DefaultTask import org.gradle.api.file.ConfigurableFileCollection @@ -126,7 +127,11 @@ abstract class GenerateCompilationDatabase : DefaultTask() { val serialized = mutableListOf() mergeFiles.files.forEach { file -> FileReader(file).use { - serialized.addAll(gson.fromJson(it, Array::class.java)) + try { + serialized.addAll(gson.fromJson(it, Array::class.java)) + } catch (e: JsonSyntaxException) { + throw IllegalStateException("Failed to parse $file as compilation database", e) + } } } entries.get().forEach { diff --git a/kotlin-native/build-tools/src/main/kotlin/org/jetbrains/kotlin/konan/target/TargetDomainObjectContainer.kt b/kotlin-native/build-tools/src/main/kotlin/org/jetbrains/kotlin/konan/target/TargetDomainObjectContainer.kt index d46d210d453..c416f6d40d9 100644 --- a/kotlin-native/build-tools/src/main/kotlin/org/jetbrains/kotlin/konan/target/TargetDomainObjectContainer.kt +++ b/kotlin-native/build-tools/src/main/kotlin/org/jetbrains/kotlin/konan/target/TargetDomainObjectContainer.kt @@ -16,7 +16,7 @@ import org.gradle.kotlin.dsl.getByType * Associative container from a [KonanTarget] with optional [SanitizerKind] to [T]. * * Serves similar purpose to [NamedDomainObjectContainer][org.gradle.api.NamedDomainObjectContainer] - * except this is keyed on a target instead of a name. Also this implementation does not support lazy + * except this is keyed on a target instead of a name. Also, this implementation does not support lazy * creation. * * Plugin extensions can inherit from this to automatically get API suitable for `build.gradle.kts`. @@ -31,15 +31,12 @@ import org.gradle.kotlin.dsl.getByType * target(someTarget) { * // This is a lambda inside of a T scope. Called for `someTarget` without any sanitizer. * } - * target(someTarget, someSanitizer) { + * target(someTarget.withSanitizer(someSanitizer)) { * // This is a lambda inside of a T scope. Called for `someTarget` with `someSanitizer`. * } * hostTarget { * // This is a lambda inside of a T scope. Called for the host target without any sanitizer. * } - * hostTarget(someSanitizer) { - * // This is a lambda inside of a T scope. Called for the host target with `someSanitizer`. - * } * } * * someExtension.target(someTarget) // returns T if `someTarget` was configured. Otherwise fails with UnknownDomainObjectException. @@ -57,36 +54,32 @@ open class TargetDomainObjectContainer constructor( /** * How to create [T]. Must be set before using the rest of API. */ - lateinit var factory: (KonanTarget, SanitizerKind?) -> T + lateinit var factory: (TargetWithSanitizer) -> T - private val targets: MutableMap, T> = mutableMapOf() + private val targets: MutableMap = mutableMapOf() /** - * Create or update configuration [T] for [target] with optional [sanitizer] and apply [action] to it. + * Create or update configuration [T] for [target] and apply [action] to it. * * @param target target of the configuration - * @param sanitizer optional sanitizer for [target] * @param action action to apply to the configuration * @return resulting configuration */ - fun target(target: KonanTarget, sanitizer: SanitizerKind? = null, action: Action): T { - val key = target to sanitizer - val element = targets.getOrPut(key) { factory(target, sanitizer) } + fun target(target: TargetWithSanitizer, action: Action): T { + val element = targets.getOrPut(target) { factory(target) } action.execute(element) return element } /** - * Get configuration [T] for [target] with optional [sanitizer]. + * Get configuration [T] for [target]. * * @param target target of the configuration - * @param sanitizer optional sanitizer for [target] * @return resulting configuration - * @throws UnknownDomainObjectException if configuration for [target] and [sanitizer] does not exist + * @throws UnknownDomainObjectException if configuration for [target] does not exist */ - fun target(target: KonanTarget, sanitizer: SanitizerKind? = null): T { - val key = target to sanitizer - return targets.get(key) ?: throw UnknownDomainObjectException("Configuration for $target${sanitizer.targetSuffix} does not exists") + fun target(target: TargetWithSanitizer): T { + return targets[target] ?: throw UnknownDomainObjectException("Configuration for $target does not exists") } /** @@ -95,13 +88,8 @@ open class TargetDomainObjectContainer constructor( * @param action action to apply to the configuration * @return list of configurations */ - fun allTargets(action: Action): List { - return platformManager.enabled.flatMap { target -> - val sanitizers = target.supportedSanitizers() + listOf(null) - sanitizers.map { sanitizer -> - this.target(target, sanitizer, action) - } - } + fun allTargets(action: Action): List = platformManager.allTargetsWithSanitizers.map { + this.target(it, action) } /** @@ -114,33 +102,21 @@ open class TargetDomainObjectContainer constructor( } /** - * Create or update configuration [T] for [host target][HostManager.host] with optional [sanitizer] and apply [action] to it. + * Create or update configuration [T] for [host target][HostManager.host] and apply [action] to it. * - * @param sanitizer optional sanitizer for [host target][HostManager.host] * @param action action to apply to the configuration * @return resulting configuration */ - fun hostTarget(sanitizer: SanitizerKind? = null, action: Action): T { - return target(HostManager.host, sanitizer, action) + fun hostTarget(action: Action): T { + return target(HostManager.host.withSanitizer(), action) } /** - * Get configuration [T] for [host target][HostManager.host] with optional [sanitizer]. - * - * @param sanitizer optional sanitizer for [host target][HostManager.host] - * @return resulting configuration - * @throws UnknownDomainObjectException if configuration for [host target][HostManager.host] and [sanitizer] does not exist - */ - fun hostTarget(sanitizer: SanitizerKind? = null): T { - return target(HostManager.host, sanitizer) - } - - /** - * Get configuration [T] for [host target][HostManager.host] without sanitizer. + * Get configuration [T] for [host target][HostManager.host]. * * @return resulting configuration - * @throws UnknownDomainObjectException if configuration for [host target][HostManager.host] without sanitizer does not exist + * @throws UnknownDomainObjectException if configuration for [host target][HostManager.host] does not exist */ val hostTarget: T - get() = hostTarget() + get() = target(HostManager.host.withSanitizer()) } diff --git a/kotlin-native/build-tools/src/main/kotlin/org/jetbrains/kotlin/konan/target/TargetWithSanitizer.kt b/kotlin-native/build-tools/src/main/kotlin/org/jetbrains/kotlin/konan/target/TargetWithSanitizer.kt new file mode 100644 index 00000000000..a0084d3563e --- /dev/null +++ b/kotlin-native/build-tools/src/main/kotlin/org/jetbrains/kotlin/konan/target/TargetWithSanitizer.kt @@ -0,0 +1,53 @@ +/* + * 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.konan.target + +import org.gradle.api.Named +import org.gradle.api.attributes.Attribute +import java.io.Serializable + +/** + * [Target][KonanTarget] with optional [sanitizer][SanitizerKind]. + * + * Can be used as a gradle attribute: `attribute(TargetWithSanitizer.TARGET_ATTRIBUTE, target.withSanitizer())` + */ +class TargetWithSanitizer( + val target: KonanTarget, + val sanitizer: SanitizerKind?, +) : Named, Serializable { + override fun getName(): String = "$target${sanitizer.targetSuffix}" + + override fun toString(): String = name + + override fun hashCode(): Int { + return name.hashCode() + } + + override fun equals(other: Any?): Boolean { + val otherTarget = other as? TargetWithSanitizer ?: return false + return name == otherTarget.name + } + + companion object { + @JvmStatic + val TARGET_ATTRIBUTE = Attribute.of("org.jetbrains.kotlin.target", TargetWithSanitizer::class.java) + } +} + +/** + * Construct [TargetWithSanitizer] from [target][KonanTarget] and optional [sanitizer][SanitizerKind]. + */ +fun KonanTarget.withSanitizer(sanitizer: SanitizerKind? = null) = TargetWithSanitizer(this, sanitizer) + +/** + * All known targets with their sanitizers. + */ +val PlatformManager.allTargetsWithSanitizers + get() = this.enabled.flatMap { target -> + listOf(target.withSanitizer()) + target.supportedSanitizers().map { + target.withSanitizer(it) + } + } \ No newline at end of file diff --git a/kotlin-native/build-tools/src/main/kotlin/org/jetbrains/kotlin/utils/Maybe.kt b/kotlin-native/build-tools/src/main/kotlin/org/jetbrains/kotlin/utils/Maybe.kt deleted file mode 100644 index 7b86dde23bd..00000000000 --- a/kotlin-native/build-tools/src/main/kotlin/org/jetbrains/kotlin/utils/Maybe.kt +++ /dev/null @@ -1,23 +0,0 @@ -/* - * 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(val orNull: T?) - -/** - * Construct [Maybe]<[T]> from [T]?. - */ -inline val T?.asMaybe - get() = Maybe(this) diff --git a/kotlin-native/build-tools/src/main/kotlin/org/jetbrains/kotlin/utils/String.kt b/kotlin-native/build-tools/src/main/kotlin/org/jetbrains/kotlin/utils/String.kt new file mode 100644 index 00000000000..821edda4ec4 --- /dev/null +++ b/kotlin-native/build-tools/src/main/kotlin/org/jetbrains/kotlin/utils/String.kt @@ -0,0 +1,10 @@ +/* + * 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 + +@OptIn(ExperimentalStdlibApi::class) +val String.capitalized: String + get() = replaceFirstChar { it.uppercase() } \ No newline at end of file diff --git a/kotlin-native/build.gradle b/kotlin-native/build.gradle index 1a17379bbe6..6f86ddf1199 100644 --- a/kotlin-native/build.gradle +++ b/kotlin-native/build.gradle @@ -142,6 +142,8 @@ configurations { commonSources } +apply plugin: CompilationDatabasePlugin + dependencies { ftpAntTask 'org.apache.ant:ant-commons-net:1.9.9' distPack project(':kotlin-native:Interop:Runtime') @@ -157,9 +159,10 @@ dependencies { commonSources project(path: ':kotlin-stdlib-common', configuration: 'sources') commonSources project(path: ':kotlin-test:kotlin-test-common', configuration: 'sources') commonSources project(path: ':kotlin-test:kotlin-test-annotations-common', configuration: 'sources') + compilationDatabase project(":kotlin-native:common") + compilationDatabase project(":kotlin-native:runtime") } -apply plugin: CompilationDatabasePlugin apply plugin: GitClangFormatPlugin apply plugin: 'maven-publish' apply plugin: BasePlugin @@ -725,13 +728,7 @@ task pusher(type: KotlinBuildPusher){ compilationDatabase { allTargets { - mergeFrom(provider { project("common") }) - mergeFrom(provider { project("runtime") }) - - // TODO: Reconsider this - task.configure { - dependsOn(":kotlin-native:runtime:downloadGoogleTest") - } + mergeFrom(configurations.compilationDatabase) } } @@ -886,4 +883,4 @@ publishing { ) } } -} \ No newline at end of file +}