[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 package org.jetbrains.kotlin.bitcode
import org.gradle.api.DefaultTask 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.api.tasks.*
import org.gradle.kotlin.dsl.getByType 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.process.ExecOperations
import org.gradle.workers.WorkAction import org.gradle.workers.WorkAction
import org.gradle.workers.WorkParameters import org.gradle.workers.WorkParameters
import org.gradle.workers.WorkerExecutor import org.gradle.workers.WorkerExecutor
import org.jetbrains.kotlin.ExecClang
import org.jetbrains.kotlin.execLlvmUtility import org.jetbrains.kotlin.execLlvmUtility
import org.jetbrains.kotlin.konan.target.* import org.jetbrains.kotlin.konan.target.KonanTarget
import org.jetbrains.kotlin.platformManager 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 { private abstract class CompileToBitcodeJob : WorkAction<CompileToBitcodeJob.Parameters> {
var objDir: File interface Parameters : WorkParameters {
var target: String val workingDirectory: DirectoryProperty
var compilerExecutable: String // TODO: Figure out a way to pass KonanTarget, but it is used as a key into PlatformManager,
var compilerArgs: List<String> // so object identity matters, and platform managers are different between project and worker sides.
var llvmLinkArgs: List<String> val targetName: Property<String>
val platformManager: Property<PlatformManager> 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 @get:Inject
abstract val objects: ObjectFactory abstract val objects: ObjectFactory
@@ -42,199 +51,169 @@ abstract class CompileToBitcodeJob : WorkAction<CompileToBitcodeParameters> {
override fun execute() { override fun execute() {
with(parameters) { with(parameters) {
objDir.mkdirs() workingDirectory.asFile.get().mkdirs()
val execClang = ExecClang.create(objects, platformManager.get()) val execClang = ExecClang.create(objects, platformManager.get())
execClang.execKonanClang(target) { // TODO: Compile each input separately and make workingDir point to src root.
workingDir = objDir execClang.execKonanClang(targetName.get()) {
executable = compilerExecutable workingDir = workingDirectory.asFile.get()
args = compilerArgs 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") { 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( abstract class CompileToBitcode @Inject constructor(
@Input val folderName: String, @Input val target: KonanTarget,
@Input val target: String, private val _sanitizer: Maybe<SanitizerKind>,
@Input val outputGroup: String
) : DefaultTask() { ) : 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 * Source files to compile from.
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
}
@get:SkipWhenEmpty @get:SkipWhenEmpty
@get:InputFiles @get:InputFiles
val inputFiles: Iterable<File> abstract val inputFiles: ConfigurableFileTree
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")
/**
* Computed header files used for task dependencies tracking.
*/
@get:InputFiles @get:InputFiles
protected val headers: Iterable<File> protected val headers: Provider<List<File>> = project.provider {
get() { // Not using clang's -M* flags because there's a problem with our current include system:
// 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
// We allow includes relative to the current directory and also pass -I for each imported module // Given file tree:
// Given file tree: // a:
// a: // header.hpp
// header.hpp // b:
// b: // impl.cpp
// impl.cpp // Assume module b adds a to its include path.
// 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
// 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,
// 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.
// 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
// 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
// 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"
// it needs to have #include "../a/header.hpp"
val dirs = mutableSetOf<File>() val dirs = mutableSetOf<File>()
// First add dirs with sources, as clang by default adds directory with the source to the include path. // First add dirs with sources, as clang by default adds directory with the source to the include path.
inputFiles.forEach { inputFiles.forEach {
dirs.add(it.parentFile) 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
}
} }
// Now add manually given header dirs.
@Input dirs.addAll(headersDirs.files)
var outputName = "${folderName}.bc" dirs.flatMap { dir ->
project.fileTree(dir) {
@get:OutputFile include("**/*.h", "**/*.hpp")
val outFile: File }.files
get() = File(targetDir, outputName) }
}
@get:Inject @get:Inject
abstract val workerExecutor: WorkerExecutor protected abstract val workerExecutor: WorkerExecutor
private val platformManager = project.extensions.getByType<PlatformManager>()
@TaskAction @TaskAction
fun compile() { fun compile() {
val workQueue = workerExecutor.noIsolation() val workQueue = workerExecutor.noIsolation()
val parameters = { it: CompileToBitcodeParameters -> workQueue.submit(CompileToBitcodeJob::class.java) {
it.objDir = objDir workingDirectory.set(this@CompileToBitcode.outputDirectory)
it.target = target targetName.set(this@CompileToBitcode.target.name)
it.compilerExecutable = executable compilerExecutable.set(this@CompileToBitcode.compiler)
it.compilerArgs = compilerFlags + inputFiles.map { it.absolutePath } compilerArgs.set(this@CompileToBitcode.compilerFlags)
it.llvmLinkArgs = listOf("-o", outFile.absolutePath) + linkerArgs + compilerInputFiles.from(this@CompileToBitcode.inputFiles)
inputFiles.map { llvmLinkOutputFile.set(this@CompileToBitcode.outputFile)
bitcodeFileForInputFile(it).absolutePath llvmLinkArgs.set(this@CompileToBitcode.linkerArgs)
} platformManager.set(this@CompileToBitcode.platformManager)
it.platformManager.set(project.platformManager)
} }
workQueue.submit(CompileToBitcodeJob::class.java, parameters)
} }
} }
@@ -5,6 +5,7 @@
package org.jetbrains.kotlin.bitcode package org.jetbrains.kotlin.bitcode
import kotlinBuildProperties
import org.gradle.api.Action import org.gradle.api.Action
import org.gradle.api.Plugin import org.gradle.api.Plugin
import org.gradle.api.Project import org.gradle.api.Project
@@ -47,6 +48,17 @@ open class CompileToBitcodePlugin : Plugin<Project> {
} }
open class CompileToBitcodeExtension @Inject constructor(val project: 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 compilationDatabase = project.extensions.getByType<CompilationDatabaseExtension>()
private val execClang = project.extensions.getByType<ExecClang>() private val execClang = project.extensions.getByType<ExecClang>()
@@ -97,11 +109,11 @@ open class CompileToBitcodeExtension @Inject constructor(val project: Project) {
} }
compilationDatabase.target(konanTarget) { compilationDatabase.target(konanTarget) {
entry { entry {
val args = listOf(execClang.resolveExecutable(compileTask.executable)) + compileTask.compilerFlags + execClang.clangArgsForCppRuntime(konanTarget.name) val args = listOf(execClang.resolveExecutable(compileTask.compiler.get())) + compileTask.compilerFlags.get() + execClang.clangArgsForCppRuntime(konanTarget.name)
directory.set(compileTask.objDir) directory.set(compileTask.outputDirectory)
files.setFrom(compileTask.inputFiles) files.setFrom(compileTask.inputFiles)
arguments.set(args) 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]!! val allMainModulesTask = allMainModulesTasks[targetName]!!
sanitizers.forEach { sanitizer -> sanitizers.forEach { sanitizer ->
val taskName = fullTaskName(name, targetName, sanitizer) val taskName = fullTaskName(name, targetName, sanitizer)
val task = project.tasks.create(taskName, CompileToBitcode::class.java, name, targetName, outputGroup).apply { val task = project.tasks.create(taskName, CompileToBitcode::class.java, target, sanitizer.asMaybe).apply {
srcDirs = project.files(srcRoot.resolve("cpp")) this.moduleName.set(name)
headersDirs = srcDirs + project.files(srcRoot.resolve("headers")) 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.sanitizer = sanitizer 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) { when (outputGroup) {
"test" -> group = VERIFICATION_BUILD_TASK_GROUP "test" -> this.group = VERIFICATION_BUILD_TASK_GROUP
"main" -> group = 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") dependsOn(":kotlin-native:dependencies:update")
configurationBlock() configurationBlock()
} }
@@ -161,19 +178,21 @@ open class CompileToBitcodeExtension @Inject constructor(val project: Project) {
val compileToBitcodeTasks = testedTasks.mapNotNull { val compileToBitcodeTasks = testedTasks.mapNotNull {
val name = "${it.name}TestBitcode" val name = "${it.name}TestBitcode"
val task = project.tasks.findByName(name) as? CompileToBitcode val task = project.tasks.findByName(name) as? CompileToBitcode
?: project.tasks.create(name, CompileToBitcode::class.java, "${it.folderName}Tests", target.name, "test").apply { ?: project.tasks.create(name, CompileToBitcode::class.java, it.target, it.sanitizer.asMaybe).apply {
srcDirs = it.srcDirs this.moduleName.set(it.moduleName)
headersDirs = it.headersDirs + googleTestExtension.headersDirs 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(":kotlin-native:dependencies:update")
dependsOn("downloadGoogleTest") dependsOn("downloadGoogleTest")
compilerArgs.addAll(it.compilerArgs)
addToCompdb(this, target) 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.llvmLinkOutputFile.set(project.layout.buildDirectory.file("bitcode/test/$target/$testName.bc"))
this.compilerOutputFile.set(project.layout.buildDirectory.file("obj/$target/$testName.o")) this.compilerOutputFile.set(project.layout.buildDirectory.file("obj/$target/$testName.o"))
this.mimallocEnabled.set(testsGroup.testedModules.get().any { it.contains("mimalloc") }) this.mimallocEnabled.set(testsGroup.testedModules.get().any { it.contains("mimalloc") })
this.mainFile.set(testSupportTask.outFile) this.mainFile.set(testSupportTask.outputFile)
dependsOn(testSupportTask)
val tasksToLink = (compileToBitcodeTasks + testedTasks + testFrameworkTasks) val tasksToLink = (compileToBitcodeTasks + testedTasks + testFrameworkTasks)
this.inputFiles.setFrom(tasksToLink.map { it.outFile }) this.inputFiles.setFrom(tasksToLink.map { it.outputFile })
dependsOn(tasksToLink)
usesService(compileTestsSemaphore) 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 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) { get() = when (this) {
null -> "" null -> ""
SanitizerKind.ADDRESS -> "_ASAN" SanitizerKind.ADDRESS -> "_ASAN"
SanitizerKind.THREAD -> "_TSAN" SanitizerKind.THREAD -> "_TSAN"
} }
private val SanitizerKind?.dirSuffix
get() = when (this) {
null -> ""
SanitizerKind.ADDRESS -> "-asan"
SanitizerKind.THREAD -> "-tsan"
}
private val SanitizerKind?.description private val SanitizerKind?.description
get() = when (this) { get() = when (this) {
null -> "" null -> ""
@@ -55,31 +55,27 @@ open class RuntimeTestingPlugin : Plugin<Project> {
project.extensions.getByName(CompileToBitcodePlugin.EXTENSION_NAME) as CompileToBitcodeExtension project.extensions.getByName(CompileToBitcodePlugin.EXTENSION_NAME) as CompileToBitcodeExtension
bitcodeExtension.module("googletest", outputGroup = "test") { bitcodeExtension.module("googletest", outputGroup = "test") {
srcDirs = project.files( inputFiles.from(googleTestRoot.resolve("googletest/src"))
googleTestRoot.resolve("googletest/src") inputFiles.include("*.cc")
) inputFiles.exclude("gtest-all.cc", "gtest_main.cc")
headersDirs = project.files( headersDirs.from(
googleTestRoot.resolve("googletest/include"), googleTestRoot.resolve("googletest/include"),
googleTestRoot.resolve("googletest") googleTestRoot.resolve("googletest")
) )
includeFiles = listOf("*.cc") compilerArgs.set(listOf("-std=c++17", "-O2"))
excludeFiles = listOf("gtest-all.cc", "gtest_main.cc")
// Original GTest sources contain an unused variable on Windows (kAlternatePathSeparatorString).
compilerArgs.add("-Wno-unused")
dependsOn(dependencies) dependsOn(dependencies)
} }
bitcodeExtension.module("googlemock", outputGroup = "test") { bitcodeExtension.module("googlemock", outputGroup = "test") {
srcDirs = project.files( inputFiles.from(googleTestRoot.resolve("googlemock/src"))
googleTestRoot.resolve("googlemock/src") inputFiles.include("*.cc")
) inputFiles.exclude("gmock-all.cc", "gmock_main.cc")
headersDirs = project.files( headersDirs.from(
googleTestRoot.resolve("googlemock"), googleTestRoot.resolve("googlemock"),
googleTestRoot.resolve("googlemock/include"), googleTestRoot.resolve("googlemock/include"),
googleTestRoot.resolve("googletest/include") googleTestRoot.resolve("googletest/include"),
) )
includeFiles = listOf("*.cc") compilerArgs.set(listOf("-std=c++17", "-O2"))
excludeFiles = listOf("gmock-all.cc", "gmock_main.cc")
dependsOn(dependencies) dependsOn(dependencies)
} }
} }
+6 -2
View File
@@ -8,8 +8,12 @@ plugins {
} }
bitcode { bitcode {
module("files") module("files") {
module("env") headersDirs.from(layout.projectDirectory.dir("src/files/headers"))
}
module("env") {
headersDirs.from(layout.projectDirectory.dir("src/env/headers"))
}
} }
val hostName: String by project val hostName: String by project
+69 -65
View File
@@ -33,42 +33,67 @@ googletest {
refresh = project.hasProperty("refresh-gtest") refresh = project.hasProperty("refresh-gtest")
} }
fun CompileToBitcode.includeRuntime() {
headersDirs += files("src/main/cpp")
}
val hostName: String by project val hostName: String by project
val targetList: List<String> by project val targetList: List<String> by project
bitcode { bitcode {
module("main") { module("main") {
includeRuntime() // TODO: Split out out `base` module and merge it together with `main` into `runtime.bc`
if (sanitizer == null) {
outputName = "runtime.bc" outputFile.set(layout.buildDirectory.file("bitcode/main/$target/runtime.bc"))
}
} }
module("mimalloc") { module("mimalloc") {
val srcRoot = file("src/mimalloc") val srcRoot = file("src/mimalloc")
language = CompileToBitcode.Language.C compiler.set("clang")
includeFiles = listOf("**/*.c") compilerArgs.set(listOfNotNull(
excludeFiles += listOf("**/alloc-override*.c", "**/page-queue.c", "**/static.c", "**/bitmap.inc.c") "-std=gnu11",
srcDirs = files("$srcRoot/c") if (sanitizer == SanitizerKind.THREAD) { "-O1" } else { "-O3" },
compilerArgs.addAll(listOf("-DKONAN_MI_MALLOC=1", "-Wno-unknown-pragmas", "-ftls-model=initial-exec", "-DKONAN_MI_MALLOC=1",
"-Wno-unused-function", "-Wno-error=atomic-alignment", "-Wno-unknown-pragmas",
"-Wno-unused-parameter" /* for windows 32*/)) "-ftls-model=initial-exec",
extraSanitizerArgs[SanitizerKind.THREAD] = listOf("-DMI_TSAN=1") "-Wno-unused-function",
headersDirs = files("$srcRoot/c/include") "-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") { module("libbacktrace") {
val srcRoot = file("src/libbacktrace") val srcRoot = file("src/libbacktrace")
val targetInfo = HostManager().targetByName(target) val elfSize = when (target.architecture) {
language = CompileToBitcode.Language.C TargetArchitecture.X64, TargetArchitecture.ARM64 -> 64
val useMachO = targetInfo.family.isAppleFamily TargetArchitecture.X86, TargetArchitecture.ARM32,
val useElf = targetInfo.family in listOf(Family.LINUX, Family.ANDROID) TargetArchitecture.MIPS32, TargetArchitecture.MIPSEL32,
includeFiles = listOfNotNull( 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", "atomic.c",
"backtrace.c", "backtrace.c",
"dwarf.c", "dwarf.c",
@@ -82,105 +107,84 @@ bitcode {
"simple.c", "simple.c",
"sort.c", "sort.c",
"state.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") { module("launcher") {
includeRuntime() headersDirs.from(files("src/main/cpp"))
} }
module("debug") { module("debug") {
includeRuntime() headersDirs.from(files("src/main/cpp"))
} }
module("std_alloc") { module("std_alloc") {
includeRuntime() headersDirs.from(files("src/main/cpp"))
} }
module("opt_alloc") { module("opt_alloc") {
includeRuntime() headersDirs.from(files("src/main/cpp"))
} }
module("exceptionsSupport", file("src/exceptions_support")) { module("exceptionsSupport", file("src/exceptions_support")) {
includeRuntime() headersDirs.from(files("src/main/cpp"))
} }
module("source_info_core_symbolication", file("src/source_info/core_symbolication")) { module("source_info_core_symbolication", file("src/source_info/core_symbolication")) {
includeRuntime() headersDirs.from(files("src/main/cpp"))
onlyIf { targetSupportsCoreSymbolication(target) } onlyIf { targetSupportsCoreSymbolication(target.name) }
} }
module("source_info_libbacktrace", file("src/source_info/libbacktrace")) { module("source_info_libbacktrace", file("src/source_info/libbacktrace")) {
includeRuntime() headersDirs.from(files("src/main/cpp", "src/libbacktrace/c/include"))
headersDirs += files("src/libbacktrace/c/include") onlyIf { targetSupportsLibBacktrace(target.name) }
onlyIf { targetSupportsLibBacktrace(target) }
} }
module("strict") { module("strict") {
includeRuntime() headersDirs.from(files("src/main/cpp"))
} }
module("relaxed") { module("relaxed") {
includeRuntime() headersDirs.from(files("src/main/cpp"))
} }
module("profileRuntime", file("src/profile_runtime")) module("profileRuntime", file("src/profile_runtime"))
module("objc") { module("objc") {
includeRuntime() headersDirs.from(files("src/main/cpp"))
} }
module("test_support", outputGroup = "test") { module("test_support", outputGroup = "test") {
includeRuntime() headersDirs.from(files("src/main/cpp"), googletest.headersDirs)
dependsOn("downloadGoogleTest") dependsOn("downloadGoogleTest")
headersDirs += googletest.headersDirs
} }
module("legacy_memory_manager", file("src/legacymm")) { module("legacy_memory_manager", file("src/legacymm")) {
includeRuntime() headersDirs.from(files("src/main/cpp"))
} }
module("experimental_memory_manager", file("src/mm")) { module("experimental_memory_manager", file("src/mm")) {
headersDirs += files("src/gc/common/cpp") headersDirs.from(files("src/gc/common/cpp", "src/main/cpp"))
includeRuntime()
} }
module("common_gc", file("src/gc/common")) { module("common_gc", file("src/gc/common")) {
headersDirs += files("src/mm/cpp") headersDirs.from(files("src/mm/cpp", "src/main/cpp"))
includeRuntime()
} }
module("noop_gc", file("src/gc/noop")) { module("noop_gc", file("src/gc/noop")) {
headersDirs += files("src/gc/noop/cpp", "src/gc/common/cpp", "src/mm/cpp") headersDirs.from(files("src/gc/noop/cpp", "src/gc/common/cpp", "src/mm/cpp", "src/main/cpp"))
includeRuntime()
} }
module("same_thread_ms_gc", file("src/gc/stms")) { module("same_thread_ms_gc", file("src/gc/stms")) {
headersDirs += files("src/gc/stms/cpp", "src/gc/common/cpp", "src/mm/cpp") headersDirs.from(files("src/gc/stms/cpp", "src/gc/common/cpp", "src/mm/cpp", "src/main/cpp"))
includeRuntime()
} }
module("concurrent_ms_gc", file("src/gc/cms")) { module("concurrent_ms_gc", file("src/gc/cms")) {
headersDirs += files("src/gc/cms/cpp", "src/gc/common/cpp", "src/mm/cpp") headersDirs.from(files("src/gc/cms/cpp", "src/gc/common/cpp", "src/mm/cpp", "src/main/cpp"))
includeRuntime()
onlyIf { targetSupportsThreads(target) } onlyIf { targetSupportsThreads(target.name) }
} }
testsGroup("std_alloc_runtime_tests") { testsGroup("std_alloc_runtime_tests") {