From bfe0d4108b122b1cbec17036eddc0de6d9105634 Mon Sep 17 00:00:00 2001 From: Alexander Shabalin Date: Tue, 19 Jul 2022 06:54:12 +0000 Subject: [PATCH] [K/N] Modernize CompileToBitcode Merge-request: KT-MR-6367 Merged-by: Alexander Shabalin --- .../kotlin/bitcode/CompileToBitcode.kt | 345 ++++++++---------- .../kotlin/bitcode/CompileToBitcodePlugin.kt | 78 ++-- .../testing/native/RuntimeTestingPlugin.kt | 26 +- kotlin-native/common/build.gradle.kts | 8 +- kotlin-native/runtime/build.gradle.kts | 134 +++---- 5 files changed, 299 insertions(+), 292 deletions(-) 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 2a942ec679c..eae8cd26865 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 @@ -6,34 +6,43 @@ package org.jetbrains.kotlin.bitcode import org.gradle.api.DefaultTask -import org.gradle.api.file.FileCollection +import org.gradle.api.file.ConfigurableFileCollection +import org.gradle.api.file.ConfigurableFileTree +import org.gradle.api.file.DirectoryProperty +import org.gradle.api.file.RegularFileProperty +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.jetbrains.kotlin.ExecClang -import java.io.File -import javax.inject.Inject -import kotlinBuildProperties -import org.gradle.api.Project -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 org.jetbrains.kotlin.platformManager +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 java.io.File +import javax.inject.Inject -interface CompileToBitcodeParameters : WorkParameters { - var objDir: File - var target: String - var compilerExecutable: String - var compilerArgs: List - var llvmLinkArgs: List - val platformManager: Property -} +private abstract class CompileToBitcodeJob : WorkAction { + interface Parameters : WorkParameters { + val workingDirectory: DirectoryProperty + // 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 + val compilerExecutable: Property + val compilerInputFiles: ConfigurableFileCollection + val compilerArgs: ListProperty + val llvmLinkOutputFile: RegularFileProperty + val llvmLinkArgs: ListProperty + val platformManager: Property + } -abstract class CompileToBitcodeJob : WorkAction { @get:Inject abstract val objects: ObjectFactory @@ -42,199 +51,169 @@ abstract class CompileToBitcodeJob : WorkAction { override fun execute() { with(parameters) { - objDir.mkdirs() + workingDirectory.asFile.get().mkdirs() val execClang = ExecClang.create(objects, platformManager.get()) - execClang.execKonanClang(target) { - workingDir = objDir - executable = compilerExecutable - args = compilerArgs + // TODO: Compile each input separately and make workingDir point to src root. + execClang.execKonanClang(targetName.get()) { + workingDir = workingDirectory.asFile.get() + executable = compilerExecutable.get() + args = compilerArgs.get() + compilerInputFiles.map { it.absolutePath } } + val compilerOutputFiles = compilerInputFiles.map { workingDirectory.file("${it.nameWithoutExtension}.bc").get().asFile } + + // TODO: Extract llvm-link out. This will allow parallelizing clang compilation. execOperations.execLlvmUtility(platformManager.get(), "llvm-link") { - args = llvmLinkArgs + args = listOf("-o", llvmLinkOutputFile.asFile.get().absolutePath) + llvmLinkArgs.get() + compilerOutputFiles.map { it.absolutePath } } } } } +/** + * Compiling files with clang into LLVM bitcode. + * + * Compiles [inputFiles] into [outputFile] with [compiler] and `llvm-link`. + * + * @property target target for which to compile + * @see CompileToBitcodePlugin + */ abstract class CompileToBitcode @Inject constructor( - @Input val folderName: String, - @Input val target: String, - @Input val outputGroup: String + @Input val target: KonanTarget, + private val _sanitizer: Maybe, ) : DefaultTask() { - enum class Language { - C, CPP + /** + * Compile with sanitizer enabled. + */ + @get:Input + @get:Optional + val sanitizer + get() = _sanitizer.orNull + + /** + * Final output file. + */ + @get:OutputFile + abstract val outputFile: RegularFileProperty + + /** + * Where to put bitcode files generated by clang. + */ + // TODO: Generate output files for this. + @get:Internal + abstract val outputDirectory: DirectoryProperty + + /** + * The compiler to be used. + * + * Currently only `clang` and `clang++` are supported. + */ + @get:Input + abstract val compiler: Property + + /** + * Extra arguments for `llvm-link`. + */ + @get:Input + abstract val linkerArgs: ListProperty + + /** + * Extra arguments for [compiler]. + */ + // Marked as input via [compilerFlags]. + @get:Internal + abstract val compilerArgs: ListProperty + + /** + * Locations to search for headers. + * + * Will be passed to the compiler as `-I…` and will also be used to compute task dependencies: recompile if the headers change. + */ + // Marked as input via [headers] and [compilerFlags]. + @get:Internal + abstract val headersDirs: ConfigurableFileCollection + + // TODO: Move to module description. + @get:Internal + abstract val moduleName: Property + + /** + * Final computed compiler arguments. + */ + @get:Input + val compilerFlags: Provider> = project.provider { + listOfNotNull( + "-c", + "-emit-llvm" + ) + headersDirs.map { "-I${it.absolutePath}" } + when (sanitizer) { + null -> listOf() + SanitizerKind.ADDRESS -> listOf("-fsanitize=address") + SanitizerKind.THREAD -> listOf("-fsanitize=thread") + } + compilerArgs.get() } - // Compiler args are part of compilerFlags so we don't register them as an input. - @Internal - val compilerArgs = mutableListOf() - @Input - val linkerArgs = mutableListOf() - @Input - var excludeFiles: List = listOf( - "**/*Test.cpp", - "**/*TestSupport.cpp", - "**/*Test.mm", - "**/*TestSupport.mm" - ) - @Input - var includeFiles: List = listOf( - "**/*.cpp", - "**/*.mm" - ) - - // Source files and headers are registered as inputs by the `inputFiles` and `headers` properties. - @Internal - var srcDirs: FileCollection = project.files() - @Internal - var headersDirs: FileCollection = project.files() - - @Input - var language = Language.CPP - - @Input @Optional - var sanitizer: SanitizerKind? = null - - @Input @Optional - val extraSanitizerArgs = mutableMapOf>() - - private val targetDir: File - get() { - val sanitizerSuffix = when (sanitizer) { - null -> "" - SanitizerKind.ADDRESS -> "-asan" - SanitizerKind.THREAD -> "-tsan" - } - return project.buildDir.resolve("bitcode/$outputGroup/$target$sanitizerSuffix") - } - - @get:Internal - val objDir - get() = File(targetDir, folderName) - - private val KonanTarget.isMINGW - get() = this.family == Family.MINGW - - @get:Internal - val executable - get() = when (language) { - Language.C -> "clang" - Language.CPP -> "clang++" - } - - @get:Input - val compilerFlags: List - get() { - val commonFlags = listOfNotNull( - "-gdwarf-2".takeIf { project.kotlinBuildProperties.getBoolean("kotlin.native.isNativeRuntimeDebugInfoEnabled", false) }, - "-c", "-emit-llvm") + headersDirs.map { "-I$it" } - val sanitizerFlags = when (sanitizer) { - null -> listOf() - SanitizerKind.ADDRESS -> listOf("-fsanitize=address") - SanitizerKind.THREAD -> listOf("-fsanitize=thread") - } + (extraSanitizerArgs[sanitizer] ?: emptyList()) - val languageFlags = when (language) { - Language.C -> { - listOf("-std=gnu11", "-Wall", "-Wextra", "-Werror") + - if (sanitizer != SanitizerKind.THREAD) { - // Used flags provided by original build of allocator C code. - listOf("-O3") - } else { - // Building with TSAN needs turning off extra optimizations. - listOf("-O1") - } - } - Language.CPP -> - listOfNotNull("-std=c++17", "-Werror", "-O2", - "-fno-aligned-allocation", // TODO: Remove when all targets support aligned allocation in C++ runtime. - "-Wall", "-Wextra", - "-Wno-unused-parameter" // False positives with polymorphic functions. - ) - } - return commonFlags + sanitizerFlags + languageFlags + compilerArgs - } - + /** + * Source files to compile from. + */ @get:SkipWhenEmpty @get:InputFiles - val inputFiles: Iterable - get() { - return srcDirs.flatMap { srcDir -> - project.fileTree(srcDir) { - include(includeFiles) - exclude(excludeFiles) - }.files - } - } - - private fun outputFileForInputFile(file: File, extension: String) = objDir.resolve("${file.nameWithoutExtension}.${extension}") - private fun bitcodeFileForInputFile(file: File) = outputFileForInputFile(file, "bc") + abstract val inputFiles: ConfigurableFileTree + /** + * Computed header files used for task dependencies tracking. + */ @get:InputFiles - protected val headers: Iterable - get() { - // Not using clang's -M* flags because there's a problem with our current include system: - // We allow includes relative to the current directory and also pass -I for each imported module - // Given file tree: - // a: - // header.hpp - // b: - // impl.cpp - // Assume module b adds a to its include path. - // If b/impl.cpp has #include "header.hpp", it'll be included from a/header.hpp. If we add another file - // header.hpp into b/, the next compilation of b/impl.cpp will include b/header.hpp. -M flags, however, - // won't generate a dependency on b/header.hpp, so incremental compilation will be broken. - // TODO: Apart from dependency generation this also makes it awkward to have two files with - // the same name (e.g. Utils.h) in directories a/ and b/: For the b/impl.cpp to include a/header.hpp - // it needs to have #include "../a/header.hpp" + protected val headers: Provider> = project.provider { + // Not using clang's -M* flags because there's a problem with our current include system: + // We allow includes relative to the current directory and also pass -I for each imported module + // Given file tree: + // a: + // header.hpp + // b: + // impl.cpp + // Assume module b adds a to its include path. + // If b/impl.cpp has #include "header.hpp", it'll be included from a/header.hpp. If we add another file + // header.hpp into b/, the next compilation of b/impl.cpp will include b/header.hpp. -M flags, however, + // won't generate a dependency on b/header.hpp, so incremental compilation will be broken. + // TODO: Apart from dependency generation this also makes it awkward to have two files with + // the same name (e.g. Utils.h) in directories a/ and b/: For the b/impl.cpp to include a/header.hpp + // it needs to have #include "../a/header.hpp" - val dirs = mutableSetOf() - // First add dirs with sources, as clang by default adds directory with the source to the include path. - inputFiles.forEach { - dirs.add(it.parentFile) - } - // Now add manually given header dirs. - dirs.addAll(headersDirs.files) - return dirs.flatMap { dir -> - project.fileTree(dir) { - val includePatterns = when (language) { - Language.C -> arrayOf("**/.h") - Language.CPP -> arrayOf("**/*.h", "**/*.hpp") - } - include(*includePatterns) - }.files - } + val dirs = mutableSetOf() + // First add dirs with sources, as clang by default adds directory with the source to the include path. + inputFiles.forEach { + dirs.add(it.parentFile) } - - @Input - var outputName = "${folderName}.bc" - - @get:OutputFile - val outFile: File - get() = File(targetDir, outputName) + // Now add manually given header dirs. + dirs.addAll(headersDirs.files) + dirs.flatMap { dir -> + project.fileTree(dir) { + include("**/*.h", "**/*.hpp") + }.files + } + } @get:Inject - abstract val workerExecutor: WorkerExecutor + protected abstract val workerExecutor: WorkerExecutor + + private val platformManager = project.extensions.getByType() @TaskAction fun compile() { val workQueue = workerExecutor.noIsolation() - val parameters = { it: CompileToBitcodeParameters -> - it.objDir = objDir - it.target = target - it.compilerExecutable = executable - it.compilerArgs = compilerFlags + inputFiles.map { it.absolutePath } - it.llvmLinkArgs = listOf("-o", outFile.absolutePath) + linkerArgs + - inputFiles.map { - bitcodeFileForInputFile(it).absolutePath - } - it.platformManager.set(project.platformManager) + workQueue.submit(CompileToBitcodeJob::class.java) { + workingDirectory.set(this@CompileToBitcode.outputDirectory) + targetName.set(this@CompileToBitcode.target.name) + compilerExecutable.set(this@CompileToBitcode.compiler) + compilerArgs.set(this@CompileToBitcode.compilerFlags) + compilerInputFiles.from(this@CompileToBitcode.inputFiles) + llvmLinkOutputFile.set(this@CompileToBitcode.outputFile) + llvmLinkArgs.set(this@CompileToBitcode.linkerArgs) + platformManager.set(this@CompileToBitcode.platformManager) } - - workQueue.submit(CompileToBitcodeJob::class.java, parameters) } } 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 0fe803b3eae..e8bd7b6b799 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 @@ -5,6 +5,7 @@ package org.jetbrains.kotlin.bitcode +import kotlinBuildProperties import org.gradle.api.Action import org.gradle.api.Plugin import org.gradle.api.Project @@ -47,6 +48,17 @@ open class CompileToBitcodePlugin : Plugin { } open class CompileToBitcodeExtension @Inject constructor(val project: Project) { + // TODO: These should be set by the plugin users. + private val DEFAULT_CPP_FLAGS = listOfNotNull( + "-gdwarf-2".takeIf { project.kotlinBuildProperties.getBoolean("kotlin.native.isNativeRuntimeDebugInfoEnabled", false) }, + "-std=c++17", + "-Werror", + "-O2", + "-fno-aligned-allocation", // TODO: Remove when all targets support aligned allocation in C++ runtime. + "-Wall", + "-Wextra", + "-Wno-unused-parameter", // False positives with polymorphic functions. + ) private val compilationDatabase = project.extensions.getByType() private val execClang = project.extensions.getByType() @@ -97,11 +109,11 @@ open class CompileToBitcodeExtension @Inject constructor(val project: Project) { } compilationDatabase.target(konanTarget) { entry { - val args = listOf(execClang.resolveExecutable(compileTask.executable)) + compileTask.compilerFlags + execClang.clangArgsForCppRuntime(konanTarget.name) - directory.set(compileTask.objDir) + val args = listOf(execClang.resolveExecutable(compileTask.compiler.get())) + compileTask.compilerFlags.get() + execClang.clangArgsForCppRuntime(konanTarget.name) + directory.set(compileTask.outputDirectory) files.setFrom(compileTask.inputFiles) arguments.set(args) - output.set(compileTask.outFile.absolutePath) + output.set(compileTask.outputFile.asFile.map { it.absolutePath }) } } } @@ -113,16 +125,21 @@ open class CompileToBitcodeExtension @Inject constructor(val project: Project) { val allMainModulesTask = allMainModulesTasks[targetName]!! sanitizers.forEach { sanitizer -> val taskName = fullTaskName(name, targetName, sanitizer) - val task = project.tasks.create(taskName, CompileToBitcode::class.java, name, targetName, outputGroup).apply { - srcDirs = project.files(srcRoot.resolve("cpp")) - headersDirs = srcDirs + project.files(srcRoot.resolve("headers")) - - this.sanitizer = sanitizer + val task = project.tasks.create(taskName, CompileToBitcode::class.java, target, sanitizer.asMaybe).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") }) + this.compiler.convention("clang++") + this.compilerArgs.set(DEFAULT_CPP_FLAGS) + this.inputFiles.from(srcRoot.resolve("cpp")) + this.inputFiles.include("**/*.cpp", "**/*.mm") + this.inputFiles.exclude("**/*Test.cpp", "**/*TestSupport.cpp", "**/*Test.mm", "**/*TestSupport.mm") + this.headersDirs.from(this.inputFiles.dir) when (outputGroup) { - "test" -> group = VERIFICATION_BUILD_TASK_GROUP - "main" -> group = BUILD_TASK_GROUP + "test" -> this.group = VERIFICATION_BUILD_TASK_GROUP + "main" -> this.group = BUILD_TASK_GROUP } - description = "Compiles '$name' to bitcode for $targetName${sanitizer.description}" + this.description = "Compiles '$name' to bitcode for $targetName${sanitizer.description}" dependsOn(":kotlin-native:dependencies:update") configurationBlock() } @@ -161,19 +178,21 @@ open class CompileToBitcodeExtension @Inject constructor(val project: Project) { 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.name, "test").apply { - srcDirs = it.srcDirs - headersDirs = it.headersDirs + googleTestExtension.headersDirs + ?: project.tasks.create(name, CompileToBitcode::class.java, it.target, it.sanitizer.asMaybe).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") }) + this.compiler.convention("clang++") + this.compilerArgs.set(it.compilerArgs) + this.inputFiles.from(it.inputFiles.dir) + this.inputFiles.include("**/*Test.cpp", "**/*TestSupport.cpp", "**/*Test.mm", "**/*TestSupport.mm") + this.headersDirs.setFrom(it.headersDirs) + this.headersDirs.from(googleTestExtension.headersDirs) + this.group = VERIFICATION_BUILD_TASK_GROUP + this.description = "Compiles '${it.name}' tests to bitcode for $target${sanitizer.description}" - 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") dependsOn(":kotlin-native:dependencies:update") dependsOn("downloadGoogleTest") - compilerArgs.addAll(it.compilerArgs) addToCompdb(this, target) } @@ -200,11 +219,9 @@ open class CompileToBitcodeExtension @Inject constructor(val project: Project) { 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) + this.mainFile.set(testSupportTask.outputFile) val tasksToLink = (compileToBitcodeTasks + testedTasks + testFrameworkTasks) - this.inputFiles.setFrom(tasksToLink.map { it.outFile }) - dependsOn(tasksToLink) + this.inputFiles.setFrom(tasksToLink.map { it.outputFile }) usesService(compileTestsSemaphore) } @@ -257,15 +274,22 @@ open class CompileToBitcodeExtension @Inject constructor(val project: Project) { private fun String.snakeCaseToUpperCamelCase() = split('_').joinToString(separator = "") { it.capitalized } - private fun fullTaskName(name: String, targetName: String, sanitizer: SanitizerKind?) = "${targetName}${name.snakeCaseToUpperCamelCase()}${sanitizer.suffix}" + private fun fullTaskName(name: String, targetName: String, sanitizer: SanitizerKind?) = "${targetName}${name.snakeCaseToUpperCamelCase()}${sanitizer.taskSuffix}" - private val SanitizerKind?.suffix + private val SanitizerKind?.taskSuffix get() = when (this) { null -> "" SanitizerKind.ADDRESS -> "_ASAN" SanitizerKind.THREAD -> "_TSAN" } + private val SanitizerKind?.dirSuffix + get() = when (this) { + null -> "" + SanitizerKind.ADDRESS -> "-asan" + SanitizerKind.THREAD -> "-tsan" + } + private val SanitizerKind?.description get() = when (this) { null -> "" diff --git a/kotlin-native/build-tools/src/main/kotlin/org/jetbrains/kotlin/testing/native/RuntimeTestingPlugin.kt b/kotlin-native/build-tools/src/main/kotlin/org/jetbrains/kotlin/testing/native/RuntimeTestingPlugin.kt index 1a4f009213a..4fee05529de 100644 --- a/kotlin-native/build-tools/src/main/kotlin/org/jetbrains/kotlin/testing/native/RuntimeTestingPlugin.kt +++ b/kotlin-native/build-tools/src/main/kotlin/org/jetbrains/kotlin/testing/native/RuntimeTestingPlugin.kt @@ -55,31 +55,27 @@ open class RuntimeTestingPlugin : Plugin { project.extensions.getByName(CompileToBitcodePlugin.EXTENSION_NAME) as CompileToBitcodeExtension bitcodeExtension.module("googletest", outputGroup = "test") { - srcDirs = project.files( - googleTestRoot.resolve("googletest/src") - ) - headersDirs = project.files( + inputFiles.from(googleTestRoot.resolve("googletest/src")) + inputFiles.include("*.cc") + inputFiles.exclude("gtest-all.cc", "gtest_main.cc") + headersDirs.from( googleTestRoot.resolve("googletest/include"), googleTestRoot.resolve("googletest") ) - includeFiles = listOf("*.cc") - excludeFiles = listOf("gtest-all.cc", "gtest_main.cc") - // Original GTest sources contain an unused variable on Windows (kAlternatePathSeparatorString). - compilerArgs.add("-Wno-unused") + compilerArgs.set(listOf("-std=c++17", "-O2")) dependsOn(dependencies) } bitcodeExtension.module("googlemock", outputGroup = "test") { - srcDirs = project.files( - googleTestRoot.resolve("googlemock/src") - ) - headersDirs = project.files( + inputFiles.from(googleTestRoot.resolve("googlemock/src")) + inputFiles.include("*.cc") + inputFiles.exclude("gmock-all.cc", "gmock_main.cc") + headersDirs.from( googleTestRoot.resolve("googlemock"), googleTestRoot.resolve("googlemock/include"), - googleTestRoot.resolve("googletest/include") + googleTestRoot.resolve("googletest/include"), ) - includeFiles = listOf("*.cc") - excludeFiles = listOf("gmock-all.cc", "gmock_main.cc") + compilerArgs.set(listOf("-std=c++17", "-O2")) dependsOn(dependencies) } } diff --git a/kotlin-native/common/build.gradle.kts b/kotlin-native/common/build.gradle.kts index a8ba5c6219e..4c25e7af1bc 100644 --- a/kotlin-native/common/build.gradle.kts +++ b/kotlin-native/common/build.gradle.kts @@ -8,8 +8,12 @@ plugins { } bitcode { - module("files") - module("env") + module("files") { + headersDirs.from(layout.projectDirectory.dir("src/files/headers")) + } + module("env") { + headersDirs.from(layout.projectDirectory.dir("src/env/headers")) + } } val hostName: String by project diff --git a/kotlin-native/runtime/build.gradle.kts b/kotlin-native/runtime/build.gradle.kts index 2de787f9f6b..27852619030 100644 --- a/kotlin-native/runtime/build.gradle.kts +++ b/kotlin-native/runtime/build.gradle.kts @@ -33,42 +33,67 @@ googletest { refresh = project.hasProperty("refresh-gtest") } -fun CompileToBitcode.includeRuntime() { - headersDirs += files("src/main/cpp") -} - val hostName: String by project val targetList: List by project bitcode { module("main") { - includeRuntime() - - outputName = "runtime.bc" + // TODO: Split out out `base` module and merge it together with `main` into `runtime.bc` + if (sanitizer == null) { + outputFile.set(layout.buildDirectory.file("bitcode/main/$target/runtime.bc")) + } } module("mimalloc") { val srcRoot = file("src/mimalloc") - language = CompileToBitcode.Language.C - includeFiles = listOf("**/*.c") - excludeFiles += listOf("**/alloc-override*.c", "**/page-queue.c", "**/static.c", "**/bitmap.inc.c") - srcDirs = files("$srcRoot/c") - compilerArgs.addAll(listOf("-DKONAN_MI_MALLOC=1", "-Wno-unknown-pragmas", "-ftls-model=initial-exec", - "-Wno-unused-function", "-Wno-error=atomic-alignment", - "-Wno-unused-parameter" /* for windows 32*/)) - extraSanitizerArgs[SanitizerKind.THREAD] = listOf("-DMI_TSAN=1") - headersDirs = files("$srcRoot/c/include") + compiler.set("clang") + compilerArgs.set(listOfNotNull( + "-std=gnu11", + if (sanitizer == SanitizerKind.THREAD) { "-O1" } else { "-O3" }, + "-DKONAN_MI_MALLOC=1", + "-Wno-unknown-pragmas", + "-ftls-model=initial-exec", + "-Wno-unused-function", + "-Wno-error=atomic-alignment", + "-Wno-unused-parameter", /* for windows 32 */ + "-DMI_TSAN=1".takeIf { sanitizer == SanitizerKind.THREAD }, + )) + inputFiles.from("$srcRoot/c") + inputFiles.include("**/*.c") + inputFiles.exclude("**/alloc-override*.c", "**/page-queue.c", "**/static.c", "**/bitmap.inc.c") + headersDirs.setFrom("$srcRoot/c/include") - onlyIf { targetSupportsMimallocAllocator(target) } + onlyIf { targetSupportsMimallocAllocator(target.name) } } module("libbacktrace") { val srcRoot = file("src/libbacktrace") - val targetInfo = HostManager().targetByName(target) - language = CompileToBitcode.Language.C - val useMachO = targetInfo.family.isAppleFamily - val useElf = targetInfo.family in listOf(Family.LINUX, Family.ANDROID) - includeFiles = listOfNotNull( + val elfSize = when (target.architecture) { + TargetArchitecture.X64, TargetArchitecture.ARM64 -> 64 + TargetArchitecture.X86, TargetArchitecture.ARM32, + TargetArchitecture.MIPS32, TargetArchitecture.MIPSEL32, + TargetArchitecture.WASM32 -> 32 + } + val useMachO = target.family.isAppleFamily + val useElf = target.family in listOf(Family.LINUX, Family.ANDROID) + compiler.set("clang") + compilerArgs.set(listOfNotNull( + "-std=gnu11", + "-funwind-tables", + "-W", + "-Wall", + "-Wwrite-strings", + "-Wstrict-prototypes", + "-Wmissing-prototypes", + "-Wold-style-definition", + "-Wmissing-format-attribute", + "-Wcast-qual", + "-O2", + "-DBACKTRACE_ELF_SIZE=$elfSize".takeIf { useElf }, + "-Wno-atomic-alignment" + )) + inputFiles.from("$srcRoot/c") + inputFiles.include(listOfNotNull( "atomic.c", "backtrace.c", "dwarf.c", @@ -82,105 +107,84 @@ bitcode { "simple.c", "sort.c", "state.c" - ) - srcDirs = files("$srcRoot/c") - val elfSize = when (targetInfo.architecture) { - TargetArchitecture.X64, TargetArchitecture.ARM64 -> 64 - TargetArchitecture.X86, TargetArchitecture.ARM32, - TargetArchitecture.MIPS32, TargetArchitecture.MIPSEL32, - TargetArchitecture.WASM32 -> 32 - } - compilerArgs.addAll(listOfNotNull( - "-funwind-tables", - "-W", "-Wall", "-Wwrite-strings", "-Wstrict-prototypes", "-Wmissing-prototypes", - "-Wold-style-definition", "-Wmissing-format-attribute", "-Wcast-qual", "-O2", - "-DBACKTRACE_ELF_SIZE=$elfSize".takeIf { useElf }, "-Wno-atomic-alignment" )) - headersDirs = files("$srcRoot/c/include") + headersDirs.setFrom("$srcRoot/c/include") - onlyIf { targetSupportsLibBacktrace(target) } + onlyIf { targetSupportsLibBacktrace(target.name) } } - module("launcher") { - includeRuntime() + headersDirs.from(files("src/main/cpp")) } module("debug") { - includeRuntime() + headersDirs.from(files("src/main/cpp")) } module("std_alloc") { - includeRuntime() + headersDirs.from(files("src/main/cpp")) } module("opt_alloc") { - includeRuntime() + headersDirs.from(files("src/main/cpp")) } module("exceptionsSupport", file("src/exceptions_support")) { - includeRuntime() + headersDirs.from(files("src/main/cpp")) } module("source_info_core_symbolication", file("src/source_info/core_symbolication")) { - includeRuntime() - onlyIf { targetSupportsCoreSymbolication(target) } + headersDirs.from(files("src/main/cpp")) + onlyIf { targetSupportsCoreSymbolication(target.name) } } module("source_info_libbacktrace", file("src/source_info/libbacktrace")) { - includeRuntime() - headersDirs += files("src/libbacktrace/c/include") - onlyIf { targetSupportsLibBacktrace(target) } + headersDirs.from(files("src/main/cpp", "src/libbacktrace/c/include")) + onlyIf { targetSupportsLibBacktrace(target.name) } } module("strict") { - includeRuntime() + headersDirs.from(files("src/main/cpp")) } module("relaxed") { - includeRuntime() + headersDirs.from(files("src/main/cpp")) } module("profileRuntime", file("src/profile_runtime")) module("objc") { - includeRuntime() + headersDirs.from(files("src/main/cpp")) } module("test_support", outputGroup = "test") { - includeRuntime() + headersDirs.from(files("src/main/cpp"), googletest.headersDirs) dependsOn("downloadGoogleTest") - headersDirs += googletest.headersDirs } module("legacy_memory_manager", file("src/legacymm")) { - includeRuntime() + headersDirs.from(files("src/main/cpp")) } module("experimental_memory_manager", file("src/mm")) { - headersDirs += files("src/gc/common/cpp") - includeRuntime() + headersDirs.from(files("src/gc/common/cpp", "src/main/cpp")) } module("common_gc", file("src/gc/common")) { - headersDirs += files("src/mm/cpp") - includeRuntime() + headersDirs.from(files("src/mm/cpp", "src/main/cpp")) } module("noop_gc", file("src/gc/noop")) { - headersDirs += files("src/gc/noop/cpp", "src/gc/common/cpp", "src/mm/cpp") - includeRuntime() + headersDirs.from(files("src/gc/noop/cpp", "src/gc/common/cpp", "src/mm/cpp", "src/main/cpp")) } module("same_thread_ms_gc", file("src/gc/stms")) { - headersDirs += files("src/gc/stms/cpp", "src/gc/common/cpp", "src/mm/cpp") - includeRuntime() + headersDirs.from(files("src/gc/stms/cpp", "src/gc/common/cpp", "src/mm/cpp", "src/main/cpp")) } module("concurrent_ms_gc", file("src/gc/cms")) { - headersDirs += files("src/gc/cms/cpp", "src/gc/common/cpp", "src/mm/cpp") - includeRuntime() + headersDirs.from(files("src/gc/cms/cpp", "src/gc/common/cpp", "src/mm/cpp", "src/main/cpp")) - onlyIf { targetSupportsThreads(target) } + onlyIf { targetSupportsThreads(target.name) } } testsGroup("std_alloc_runtime_tests") {