[K/N] Modernize CompileToBitcode

Merge-request: KT-MR-6367
Merged-by: Alexander Shabalin <Alexander.Shabalin@jetbrains.com>
This commit is contained in:
Alexander Shabalin
2022-07-19 06:54:12 +00:00
committed by Space
parent 8d79fab109
commit bfe0d4108b
5 changed files with 299 additions and 292 deletions
@@ -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<String>
var llvmLinkArgs: List<String>
val platformManager: Property<PlatformManager>
}
private abstract class CompileToBitcodeJob : WorkAction<CompileToBitcodeJob.Parameters> {
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<String>
val compilerExecutable: Property<String>
val compilerInputFiles: ConfigurableFileCollection
val compilerArgs: ListProperty<String>
val llvmLinkOutputFile: RegularFileProperty
val llvmLinkArgs: ListProperty<String>
val platformManager: Property<PlatformManager>
}
abstract class CompileToBitcodeJob : WorkAction<CompileToBitcodeParameters> {
@get:Inject
abstract val objects: ObjectFactory
@@ -42,199 +51,169 @@ abstract class CompileToBitcodeJob : WorkAction<CompileToBitcodeParameters> {
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<SanitizerKind>,
) : 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<String>
/**
* Extra arguments for `llvm-link`.
*/
@get:Input
abstract val linkerArgs: ListProperty<String>
/**
* Extra arguments for [compiler].
*/
// Marked as input via [compilerFlags].
@get:Internal
abstract val compilerArgs: ListProperty<String>
/**
* 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<String>
/**
* Final computed compiler arguments.
*/
@get:Input
val compilerFlags: Provider<List<String>> = 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<String>()
@Input
val linkerArgs = mutableListOf<String>()
@Input
var excludeFiles: List<String> = listOf(
"**/*Test.cpp",
"**/*TestSupport.cpp",
"**/*Test.mm",
"**/*TestSupport.mm"
)
@Input
var includeFiles: List<String> = 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<SanitizerKind, List<String>>()
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<String>
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<File>
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<File>
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<List<File>> = 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<File>()
// 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<File>()
// 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<PlatformManager>()
@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)
}
}
@@ -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<Project> {
}
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<CompilationDatabaseExtension>()
private val execClang = project.extensions.getByType<ExecClang>()
@@ -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 -> ""
@@ -55,31 +55,27 @@ open class RuntimeTestingPlugin : Plugin<Project> {
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)
}
}
+6 -2
View File
@@ -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
+69 -65
View File
@@ -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<String> 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") {