blob: 44e0be9957e02e222653c9232ea00ff3439503df [file] [log] [blame] [edit]
/*
* Copyright 2010-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
* that can be found in the LICENSE file.
*/
import org.jetbrains.kotlin.*
import org.jetbrains.kotlin.bitcode.CompileToBitcodeExtension
import org.jetbrains.kotlin.cpp.CppUsage
import org.jetbrains.kotlin.gradle.plugin.konan.tasks.KonanCacheTask
import org.jetbrains.kotlin.konan.properties.loadProperties
import org.jetbrains.kotlin.konan.properties.saveProperties
import org.jetbrains.kotlin.konan.target.*
import org.jetbrains.kotlin.library.KLIB_PROPERTY_NATIVE_TARGETS
import org.jetbrains.kotlin.konan.file.File as KFile
import org.jetbrains.kotlin.konan.target.Architecture as TargetArchitecture
// These properties are used by the 'konan' plugin, thus we set them before applying it.
val distDir: File by project
val konanHome: String by extra(distDir.absolutePath)
extra["org.jetbrains.kotlin.native.home"] = konanHome
plugins {
id("compile-to-bitcode")
id("runtime-testing")
id("konan")
}
if (HostManager.host == KonanTarget.MACOS_ARM64) {
project.configureJvmToolchain(JdkMajorVersion.JDK_17_0)
}
googletest {
revision = project.property("gtestRevision") as String
refresh = project.hasProperty("refresh-gtest")
}
val hostName: String by project
val targetList: List<String> by project
bitcode {
allTargets {
module("main") {
sourceSets {
main {
// 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"))
}
}
testFixtures {}
test {}
}
}
module("mimalloc") {
sourceSets {
main {
inputFiles.from(srcRoot.dir("c"))
inputFiles.include("**/*.c")
inputFiles.exclude("**/alloc-override*.c", "**/page-queue.c", "**/static.c", "**/bitmap.inc.c")
headersDirs.setFrom(srcRoot.dir("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 },
))
onlyIf { target.supportsMimallocAllocator() }
}
module("libbacktrace") {
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)
sourceSets {
main {
inputFiles.from(srcRoot.dir("c"))
inputFiles.include(listOfNotNull(
"atomic.c",
"backtrace.c",
"dwarf.c",
"elf.c".takeIf { useElf },
"fileline.c",
"macho.c".takeIf { useMachO },
"mmap.c",
"mmapio.c",
"posix.c",
"print.c",
"simple.c",
"sort.c",
"state.c"
))
headersDirs.setFrom(srcRoot.dir("c/include"))
}
}
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"
))
onlyIf { target.supportsLibBacktrace() }
}
module("compiler_interface") {
headersDirs.from(files("src/main/cpp"))
sourceSets {
main {}
}
}
module("launcher") {
headersDirs.from(files("src/main/cpp"))
sourceSets {
main {}
}
}
module("debug") {
headersDirs.from(files("src/main/cpp"))
sourceSets {
main {}
}
}
module("std_alloc") {
headersDirs.from(files("src/main/cpp"))
sourceSets {
main {}
}
}
module("custom_alloc") {
headersDirs.from(files("src/main/cpp", "src/mm/cpp", "src/gc/common/cpp", "src/gc/cms/cpp"))
sourceSets {
main {}
test {}
}
compilerArgs.add("-DCUSTOM_ALLOCATOR")
// Directly depends on cms which is only supported with threads.
onlyIf { target.supportsThreads() }
}
module("opt_alloc") {
headersDirs.from(files("src/main/cpp"))
sourceSets {
main {}
}
}
module("exceptionsSupport") {
srcRoot.set(layout.projectDirectory.dir("src/exceptions_support"))
headersDirs.from(files("src/main/cpp"))
sourceSets {
main {}
}
}
module("source_info_core_symbolication") {
srcRoot.set(layout.projectDirectory.dir("src/source_info/core_symbolication"))
headersDirs.from(files("src/main/cpp"))
sourceSets {
main {}
}
onlyIf { target.supportsCoreSymbolication() }
}
module("source_info_libbacktrace") {
srcRoot.set(layout.projectDirectory.dir("src/source_info/libbacktrace"))
headersDirs.from(files("src/main/cpp", "src/libbacktrace/c/include"))
sourceSets {
main {}
}
onlyIf { target.supportsLibBacktrace() }
}
module("strict") {
headersDirs.from(files("src/main/cpp"))
sourceSets {
main {}
}
}
module("relaxed") {
headersDirs.from(files("src/main/cpp"))
sourceSets {
main {}
}
}
module("profileRuntime") {
srcRoot.set(layout.projectDirectory.dir("src/profile_runtime"))
sourceSets {
main {}
}
}
module("objc") {
headersDirs.from(files("src/main/cpp"))
sourceSets {
main {}
}
}
module("test_support") {
headersDirs.from(files("src/main/cpp"))
sourceSets {
testFixtures {
inputFiles.include("**/*.cpp", "**/*.mm")
}
}
}
module("legacy_memory_manager") {
srcRoot.set(layout.projectDirectory.dir("src/legacymm"))
headersDirs.from(files("src/main/cpp"))
sourceSets {
main {}
testFixtures {}
}
}
module("experimental_memory_manager") {
srcRoot.set(layout.projectDirectory.dir("src/mm"))
headersDirs.from(files("src/gc/common/cpp", "src/main/cpp"))
sourceSets {
main {}
testFixtures {}
test {}
}
}
module("common_gc") {
srcRoot.set(layout.projectDirectory.dir("src/gc/common"))
headersDirs.from(files("src/mm/cpp", "src/main/cpp"))
sourceSets {
main {}
test {}
}
}
module("noop_gc") {
srcRoot.set(layout.projectDirectory.dir("src/gc/noop"))
headersDirs.from(files("src/gc/noop/cpp", "src/gc/common/cpp", "src/mm/cpp", "src/main/cpp"))
sourceSets {
main {}
testFixtures {}
}
}
module("same_thread_ms_gc") {
srcRoot.set(layout.projectDirectory.dir("src/gc/stms"))
headersDirs.from(files("src/gc/stms/cpp", "src/gc/common/cpp", "src/mm/cpp", "src/main/cpp"))
sourceSets {
main {}
testFixtures {}
test {}
}
}
module("concurrent_ms_gc") {
srcRoot.set(layout.projectDirectory.dir("src/gc/cms"))
headersDirs.from(files("src/gc/cms/cpp", "src/gc/common/cpp", "src/mm/cpp", "src/main/cpp"))
sourceSets {
main {}
testFixtures {}
test {}
}
onlyIf { target.supportsThreads() }
}
module("concurrent_ms_gc_custom") {
srcRoot.set(layout.projectDirectory.dir("src/gc/cms"))
headersDirs.from(files("src/gc/cms/cpp", "src/gc/common/cpp", "src/mm/cpp", "src/main/cpp", "src/custom_alloc/cpp"))
sourceSets {
main {}
testFixtures {}
test {}
}
compilerArgs.add("-DCUSTOM_ALLOCATOR")
onlyIf { target.supportsThreads() }
}
testsGroup("std_alloc_runtime_tests") {
testedModules.addAll("main", "legacy_memory_manager", "strict", "std_alloc", "objc")
}
testsGroup("custom_alloc_runtime_tests") {
testedModules.addAll("custom_alloc")
testSupportModules.addAll("main", "experimental_memory_manager", "common_gc", "concurrent_ms_gc", "objc")
}
testsGroup("mimalloc_runtime_tests") {
testedModules.addAll("main", "legacy_memory_manager", "strict", "mimalloc", "opt_alloc", "objc")
}
testsGroup("experimentalMM_mimalloc_runtime_tests") {
testedModules.addAll("main", "experimental_memory_manager", "common_gc", "same_thread_ms_gc", "mimalloc", "opt_alloc", "objc")
}
testsGroup("experimentalMM_std_alloc_runtime_tests") {
testedModules.addAll("main", "experimental_memory_manager", "common_gc", "same_thread_ms_gc", "std_alloc", "objc")
}
testsGroup("experimentalMM_cms_mimalloc_runtime_tests") {
testedModules.addAll("main", "experimental_memory_manager", "common_gc", "concurrent_ms_gc", "mimalloc", "opt_alloc", "objc")
}
testsGroup("experimentalMM_cms_std_alloc_runtime_tests") {
testedModules.addAll("main", "experimental_memory_manager", "common_gc", "concurrent_ms_gc", "std_alloc", "objc")
}
testsGroup("experimentalMM_noop_mimalloc_runtime_tests") {
testedModules.addAll("main", "experimental_memory_manager", "common_gc", "noop_gc", "mimalloc", "opt_alloc", "objc")
}
testsGroup("experimentalMM_noop_std_alloc_runtime_tests") {
testedModules.addAll("main", "experimental_memory_manager", "common_gc", "noop_gc", "std_alloc", "objc")
}
}
}
val runtimeBitcode by configurations.creating {
isCanBeConsumed = false
isCanBeResolved = true
attributes {
attribute(CppUsage.USAGE_ATTRIBUTE, objects.named(CppUsage.LLVM_BITCODE))
}
}
dependencies {
runtimeBitcode(project(":kotlin-native:runtime"))
}
targetList.forEach { targetName ->
// TODO: replace with a more convenient user-facing task that can build for a specific target.
// like compileToBitcode with optional argument --target.
tasks.register("${targetName}Runtime") {
description = "Build all main runtime modules for $targetName"
group = CompileToBitcodeExtension.BUILD_TASK_GROUP
val dependencies = runtimeBitcode.incoming.artifactView {
attributes {
attribute(TargetWithSanitizer.TARGET_ATTRIBUTE, project.platformManager.targetByName(targetName).withSanitizer())
}
}.files
dependsOn(dependencies)
}
}
val hostRuntime by tasks.registering {
description = "Build all main runtime modules for host"
group = CompileToBitcodeExtension.BUILD_TASK_GROUP
dependsOn("${hostName}Runtime")
}
val hostRuntimeTests by tasks.registering {
description = "Runs all runtime tests for host"
group = CompileToBitcodeExtension.VERIFICATION_TASK_GROUP
dependsOn("${hostName}RuntimeTests")
}
val assemble by tasks.getting {
dependsOn(targetList.map { "${it}Runtime" })
}
val hostAssemble by tasks.registering {
dependsOn("${hostName}Runtime")
}
val clean by tasks.getting {
doFirst {
delete(buildDir)
}
}
val generateJsMath by tasks.registering {
dependsOn(":distCompiler")
doLast {
val distDir: File by project
val jsinteropScript = if (PlatformInfo.isWindows()) "jsinterop.bat" else "jsinterop"
val jsinterop = "$distDir/bin/$jsinteropScript"
val targetDir = "$buildDir/generated"
project.exec {
commandLine(
jsinterop,
"-pkg", "kotlinx.interop.wasm.math",
"-o", "$targetDir/math",
"-target", "wasm32"
)
}
val generated = file("$targetDir/math-build/natives/js_stubs.js")
val mathJs = file("src/main/js/math.js")
mathJs.writeText(
"// NOTE: THIS FILE IS AUTO-GENERATED!\n" +
"// Run ':runtime:generateJsMath' to re-generate it.\n\n"
)
mathJs.appendText(generated.readText())
}
}
// region: Stdlib
val commonStdlibSrcDirs = project(":kotlin-stdlib-common")
.files(
"src/kotlin",
"src/generated",
"../unsigned/src",
"../src"
).files
val interopRuntimeCommonSrcDir = project(":kotlin-native:Interop:Runtime").file("src/main/kotlin")
val interopSrcDirs = listOf(
project(":kotlin-native:Interop:Runtime").file("src/native/kotlin"),
project(":kotlin-native:Interop:JsRuntime").file("src/main/kotlin")
)
val testAnnotationCommonSrcDir = project(":kotlin-test:kotlin-test-annotations-common").files("src/main/kotlin").files
val testCommonSrcDir = project(":kotlin-test:kotlin-test-common").files("src/main/kotlin").files
val stdLibSrcDirs = interopSrcDirs + listOf(
project.file("src/main/kotlin"),
project(":kotlin-stdlib-common").file("../native-wasm/src/")
)
lateinit var stdlibBuildTask: TaskProvider<Task>
konanArtifacts {
library("stdlib") {
baseDir(project.buildDir.resolve("stdlib"))
enableMultiplatform(true)
noStdLib(true)
noPack(true)
noDefaultLibs(true)
noEndorsedLibs(true)
extraOpts(project.globalBuildArgs)
extraOpts(
"-Werror",
"-module-name", "stdlib",
"-opt-in=kotlin.RequiresOptIn",
"-opt-in=kotlin.contracts.ExperimentalContracts",
"-opt-in=kotlin.ExperimentalMultiplatform",
"-opt-in=kotlin.native.internal.InternalForKotlinNative",
"-XXLanguage:+RangeUntilOperator",
)
commonStdlibSrcDirs.forEach { commonSrcDir(it) }
testAnnotationCommonSrcDir.forEach { commonSrcDir(it) }
testCommonSrcDir.forEach { commonSrcDir(it) }
commonSrcDir(interopRuntimeCommonSrcDir)
stdLibSrcDirs.forEach { srcDir(it) }
}
stdlibBuildTask = project.findKonanBuildTask("stdlib", project.platformManager.hostPlatform.target).apply {
configure {
dependsOn(":kotlin-native:distCompiler")
}
}
}
targetList.forEach { targetName ->
tasks.register("${targetName}Stdlib", Copy::class.java) {
require(::stdlibBuildTask.isInitialized)
dependsOn(stdlibBuildTask)
dependsOn("${targetName}Runtime")
destinationDir = project.buildDir.resolve("${targetName}Stdlib")
from(project.buildDir.resolve("stdlib/${hostName}/stdlib"))
val runtimeFiles = runtimeBitcode.incoming.artifactView {
attributes {
attribute(TargetWithSanitizer.TARGET_ATTRIBUTE, project.platformManager.targetByName(targetName).withSanitizer())
}
}.files
from(runtimeFiles) {
include("runtime.bc", "compiler_interface.bc")
into("default/targets/$targetName/native")
}
if (targetName != hostName) {
doLast {
// Change target in manifest file
with(KFile(destinationDir.resolve("default/manifest").absolutePath)) {
val props = loadProperties()
props[KLIB_PROPERTY_NATIVE_TARGETS] = targetName
saveProperties(props)
}
}
}
}
val cacheableTargetNames: List<String> by project
if (targetName in cacheableTargetNames) {
tasks.register("${targetName}StdlibCache", KonanCacheTask::class.java) {
target = targetName
originalKlib = project.buildDir.resolve("${targetName}Stdlib")
klibUniqName = "stdlib"
cacheRoot = project.buildDir.resolve("cache/$targetName").absolutePath
dependsOn("${targetName}Stdlib")
dependsOn(":kotlin-native:${targetName}CrossDistRuntime")
}
}
}
// endregion