[Runtime testing] Fix link errors caused by duplicated symbol __throw_length_error

This commit is contained in:
Ilya Matveev
2020-10-06 13:26:10 +07:00
committed by Ilya Matveev
parent a452346385
commit 788dd1c210
2 changed files with 78 additions and 31 deletions
@@ -9,6 +9,7 @@ import groovy.lang.Closure
import java.io.File import java.io.File
import javax.inject.Inject import javax.inject.Inject
import org.gradle.api.* import org.gradle.api.*
import org.gradle.api.file.ConfigurableFileCollection
import org.gradle.api.tasks.* import org.gradle.api.tasks.*
import org.jetbrains.kotlin.ExecClang import org.jetbrains.kotlin.ExecClang
import org.jetbrains.kotlin.bitcode.CompileToBitcode import org.jetbrains.kotlin.bitcode.CompileToBitcode
@@ -17,7 +18,7 @@ import org.jetbrains.kotlin.konan.target.*
open class CompileNativeTest @Inject constructor( open class CompileNativeTest @Inject constructor(
@InputFile val inputFile: File, @InputFile val inputFile: File,
@Input val target: String @Input val target: String
) : DefaultTask () { ) : DefaultTask() {
@OutputFile @OutputFile
var outputFile = project.buildDir.resolve("bin/test/$target/${inputFile.nameWithoutExtension}.o") var outputFile = project.buildDir.resolve("bin/test/$target/${inputFile.nameWithoutExtension}.o")
@@ -27,10 +28,54 @@ open class CompileNativeTest @Inject constructor(
@TaskAction @TaskAction
fun compile() { fun compile() {
val plugin = project.convention.getPlugin(ExecClang::class.java) val plugin = project.convention.getPlugin(ExecClang::class.java)
plugin.execBareClang(Action { plugin.execBareClang {
it.executable = "clang++" it.executable = "clang++"
it.args = clangArgs + listOf(inputFile.absolutePath, "-o", outputFile.absolutePath) it.args = clangArgs + listOf(inputFile.absolutePath, "-o", outputFile.absolutePath)
}) }
}
}
open class LlvmLinkNativeTest @Inject constructor(
val baseName: String,
@Input val target: String,
@InputFile val mainFile: File
) : DefaultTask() {
@SkipWhenEmpty
@InputFiles
var inputFiles: ConfigurableFileCollection = project.files()
@OutputFile
var outputFile: File = project.buildDir.resolve("bitcode/test/$target/$baseName.bc")
@TaskAction
fun llvmLink() {
val llvmDir = project.property("llvmDir")
val tmpOutput = File.createTempFile("runtimeTests", ".bc").apply {
deleteOnExit()
}
// The runtime provides our implementations for some standard functions (see StdCppStubs.cpp).
// We need to internalize these symbols to avoid clashes with symbols provided by the C++ stdlib.
// But llvm-link -internalize is kinda broken: it links modules one by one and can't see usages
// of a symbol in subsequent modules. So it will mangle such symbols causing "unresolved symbol"
// errors at the link stage. So we have to run llvm-link twice: the first one links all modules
// except the one containing the entry point to a single *.bc without internalization. The second
// run internalizes this big module and links it with a module containing the entry point.
project.exec {
it.executable = "$llvmDir/bin/llvm-link"
it.args = listOf("-o", tmpOutput.absolutePath) + inputFiles.map { it.absolutePath }
}
project.exec {
it.executable = "$llvmDir/bin/llvm-link"
it.args = listOf(
"-o", outputFile.absolutePath,
mainFile.absolutePath,
tmpOutput.absolutePath,
"-internalize"
)
}
} }
} }
@@ -106,15 +151,6 @@ open class LinkNativeTest @Inject constructor(
} }
} }
@Suppress("UNCHECKED_CAST")
private fun <T: Task> T.configure(f: T.() -> Unit): T =
this.configure(object: Closure<Unit>(this) {
// Dynamically invoked by Groovy
fun doCall() {
f()
}
}) as T
fun createTestTask( fun createTestTask(
project: Project, project: Project,
testTaskName: String, testTaskName: String,
@@ -137,7 +173,7 @@ fun createTestTask(
it.srcRoot, it.srcRoot,
"${it.folderName}Tests", "${it.folderName}Tests",
target, "test" target, "test"
).configure { ).apply {
excludeFiles = emptyList() excludeFiles = emptyList()
includeFiles = listOf("**/*Test.cpp", "**/*Test.mm") includeFiles = listOf("**/*Test.cpp", "**/*Test.mm")
dependsOn(it) dependsOn(it)
@@ -153,29 +189,42 @@ fun createTestTask(
project.tasks.getByName("${target}Googletest") as CompileToBitcode, project.tasks.getByName("${target}Googletest") as CompileToBitcode,
project.tasks.getByName("${target}Googlemock") as CompileToBitcode project.tasks.getByName("${target}Googlemock") as CompileToBitcode
) )
val compileToObjectFileTasks = (compileToBitcodeTasks + testedTasks + testFrameworkTasks).map {
val name = "${it.name}Object" val testSupportTask = project.tasks.getByName("${target}TestSupport") as CompileToBitcode
val clangFlags = platformManager.platform(konanTarget).configurables as ClangFlags
project.tasks.findByName(name) as? CompileNativeTest ?: // TODO: It may make sense to merge llvm-link, compile and link to a single task.
project.tasks.create(name, val llvmLinkTask = project.tasks.create(
CompileNativeTest::class.java, "${testTaskName}LlvmLink",
it.outFile, LlvmLinkNativeTest::class.java,
target testTaskName, target, testSupportTask.outFile
).configure { ).apply {
dependsOn(it) val tasksToLink = (compileToBitcodeTasks + testedTasks + testFrameworkTasks)
clangArgs.addAll(clangFlags.clangFlags) inputFiles = project.files(tasksToLink.map { it.outFile })
clangArgs.addAll(clangFlags.clangNooptFlags) dependsOn(testSupportTask)
} dependsOn(tasksToLink)
} }
val clangFlags = platformManager.platform(konanTarget).configurables as ClangFlags
val compileTask = project.tasks.create(
"${testTaskName}Compile",
CompileNativeTest::class.java,
llvmLinkTask.outputFile,
target
).apply {
dependsOn(llvmLinkTask)
clangArgs.addAll(clangFlags.clangFlags)
clangArgs.addAll(clangFlags.clangNooptFlags)
}
val linkTask = LinkNativeTest.create( val linkTask = LinkNativeTest.create(
project, project,
platformManager, platformManager,
"${testTaskName}Link", "${testTaskName}Link",
compileToObjectFileTasks.map { it.outputFile }, listOf(compileTask.outputFile),
target, target,
testTaskName testTaskName
).configure { ).apply {
dependsOn(compileToObjectFileTasks) dependsOn(compileTask)
} }
return project.tasks.create(testTaskName, Exec::class.java).apply { return project.tasks.create(testTaskName, Exec::class.java).apply {
-2
View File
@@ -100,7 +100,6 @@ targetList.forEach { targetName ->
"${targetName}StdAllocRuntimeTests", "${targetName}StdAllocRuntimeTests",
listOf( listOf(
"${targetName}Runtime", "${targetName}Runtime",
"${targetName}TestSupport",
"${targetName}Strict", "${targetName}Strict",
"${targetName}Release", "${targetName}Release",
"${targetName}StdAlloc" "${targetName}StdAlloc"
@@ -112,7 +111,6 @@ targetList.forEach { targetName ->
"${targetName}MimallocRuntimeTests", "${targetName}MimallocRuntimeTests",
listOf( listOf(
"${targetName}Runtime", "${targetName}Runtime",
"${targetName}TestSupport",
"${targetName}Strict", "${targetName}Strict",
"${targetName}Release", "${targetName}Release",
"${targetName}Mimalloc", "${targetName}Mimalloc",