From ec024cee53da7398a21a2462ea1ec848dcf654fb Mon Sep 17 00:00:00 2001 From: Alexander Gorshenev Date: Fri, 15 Jan 2021 00:48:21 +0300 Subject: [PATCH] Extracted multi-module compiler runner for external tests to a separate kotlin file. (cherry picked from commit 4fd88e4d33d8f80370b3ba4eee4c64869c1f1734) --- .../org/jetbrains/kotlin/KonanTest.groovy | 68 ++------------- .../org/jetbrains/kotlin/MultiModule.kt | 84 +++++++++++++++++++ 2 files changed, 90 insertions(+), 62 deletions(-) create mode 100644 kotlin-native/build-tools/src/main/kotlin/org/jetbrains/kotlin/MultiModule.kt diff --git a/kotlin-native/build-tools/src/main/groovy/org/jetbrains/kotlin/KonanTest.groovy b/kotlin-native/build-tools/src/main/groovy/org/jetbrains/kotlin/KonanTest.groovy index 87c7690c7da..44c275bfe3f 100644 --- a/kotlin-native/build-tools/src/main/groovy/org/jetbrains/kotlin/KonanTest.groovy +++ b/kotlin-native/build-tools/src/main/groovy/org/jetbrains/kotlin/KonanTest.groovy @@ -22,14 +22,13 @@ import org.gradle.api.tasks.TaskAction import org.gradle.process.ExecResult import org.jetbrains.kotlin.utils.DFS -import java.io.File import java.nio.file.Paths import java.util.function.Function import java.util.function.UnaryOperator import java.util.regex.Pattern import java.util.stream.Collectors -class RunExternalTestGroup extends JavaExec { +class RunExternalTestGroup extends JavaExec implements CompilerRunner { def platformManager = project.rootProject.platformManager def target = platformManager.targetManager(project.testTarget).target def dist = UtilsKt.getKotlinNativeDist(project) @@ -75,7 +74,8 @@ class RunExternalTestGroup extends JavaExec { // configuration part at runCompiler. } - protected void runCompiler(List filesToCompile, String output, List moreArgs) { + @Override + void runCompiler(List filesToCompile, String output, List moreArgs) { def log = new ByteArrayOutputStream() try { classpath = project.fileTree("$dist.canonicalPath/konan/lib/") { @@ -470,59 +470,6 @@ fun runTest() { } } - class MultiModuleCompilerInvocations { - String executablePath - Map modules - List flags - - MultiModuleCompilerInvocations(String executablePath, Map modules, List flags) { - this.executablePath = executablePath - this.modules = modules - this.flags = flags - } - - def libs = new HashSet() - - String moduleToKlibName(String moduleName, Integer version) { - def module = modules[moduleName] - // TODO: cleanup - def versionSuffix = module.hasVersions ? "_version${version}" : "" - return module.hasVersions ? "${executablePath}${versionSuffix}/${moduleName}.klib" : "${executablePath}.${moduleName}.klib" - } - - void produceLibrary(TestModule module, Integer moduleVersion, Integer dependencyVersion) { - def klibModulePath = moduleToKlibName(module.name, moduleVersion) - libs.addAll(module.dependencies) - def klibs = module.dependencies.collectMany { ["-l", moduleToKlibName(it, dependencyVersion)] }.toList() - def repos = ["-r", "${executablePath}_version${dependencyVersion}", "-r", project.file(executablePath).parentFile.absolutePath ] - - def friends = module.friends ? - module.friends.collectMany { - ["-friend-modules", "${executablePath}.${it}.klib"] - }.toList() : [] - runCompiler(module.versionFiles(moduleVersion).collect { it.path }, - klibModulePath, flags + ["-p", "library"/*, "-module-name", module.name*/] + repos + klibs + friends) - } - - void produceProgram(List compileList, Integer version) { - def compileMain = compileList.findAll { - it.module.isDefaultModule() || it.module == TestModule.support - } - compileMain.forEach { f -> - libs.addAll(f.module.dependencies) - } - def friends = compileMain.collectMany { it.module.friends }.toSet() - def repos = ["-r", "${executablePath}_version${version}", "-r", project.file(executablePath).parentFile.absolutePath] - - if (!compileMain.empty) { - runCompiler(compileMain.collect { it.path }, executablePath, flags + repos + - libs.collectMany { ["-l", moduleToKlibName(it, version)] }.toList() + - friends.collectMany { ["-friend-modules", "${executablePath}.${it}.klib"] }.toList() - ) - } - } - } - @TaskAction void executeTest() { createOutputDirectory() @@ -573,18 +520,15 @@ fun runTest() { List orderedModules = DFS.INSTANCE.topologicalOrder(modules.values()) { module -> module.dependencies.collect { modules[it] }.findAll { it != null } } - def compiler = new MultiModuleCompilerInvocations(executablePath(), modules, flags) + def compiler = new MultiModuleCompilerInvocations(this, outputDirectory, executablePath(), modules, flags) orderedModules.reverse().each { module -> if (!module.isDefaultModule()) { - compiler.produceLibrary(module, 1, 1) - if (module.hasVersions) { - compiler.produceLibrary(module, 2, 1) - } + compiler.produceLibrary(module) } } - compiler.produceProgram(compileList, 2) + compiler.produceProgram(compileList) } } catch (Exception ex) { project.logger.quiet("ERROR: Compilation failed for test suite: $name with exception", ex) diff --git a/kotlin-native/build-tools/src/main/kotlin/org/jetbrains/kotlin/MultiModule.kt b/kotlin-native/build-tools/src/main/kotlin/org/jetbrains/kotlin/MultiModule.kt new file mode 100644 index 00000000000..6ee53cb13d3 --- /dev/null +++ b/kotlin-native/build-tools/src/main/kotlin/org/jetbrains/kotlin/MultiModule.kt @@ -0,0 +1,84 @@ +package org.jetbrains.kotlin + +interface CompilerRunner { + fun runCompiler(filesToCompile: List, output: String, moreArgs: List) +} + +// This class knows how to run the compiler for multi-module external tests. +// +// In addition it knows how to deal with multi-versioned modules. +// The versioned modules are used for binary compatibility testing. +// For such modules we produce two klibs: +// `version1/foo.klib` and `version2/foo.klib`. +// For un-versioned modules we still produce just `bar.klib` +// We link all klibs against `version1/foo.klib` and `bar.klib` +// We link the final executable against `version2/foo.klib` and `bar.klib`. + +class MultiModuleCompilerInvocations( + val konanTest: CompilerRunner, + val outputDirectory: String, + val executablePath: String, + val modules: Map, + val flags: List +) { + val libs = HashSet() + + fun moduleToKlibName(moduleName: String, version: Int): String { + val module = modules[moduleName] ?: error("Could not find module $moduleName") + + return if (module.hasVersions) { + val versionSuffix = "_version$version" + "$executablePath$versionSuffix/$moduleName.klib" + } else { + "$executablePath.$moduleName.klib" + } + } + + private fun produceLibrary(module: TestModule, moduleVersion: Int) { + val klibModulePath = moduleToKlibName(module.name, moduleVersion) + libs.addAll(module.dependencies) + + // When producing klibs link them against version 1 of multiversioned klibs. + val dependencyVersion = 1 + + val klibs = module.dependencies.flatMap { listOf("-l", moduleToKlibName(it, dependencyVersion)) } + val repos = listOf("-r", "${executablePath}_version$dependencyVersion", "-r", outputDirectory) + + val friends = module.friends.flatMap { + listOf("-friend-modules", "$executablePath.$it.klib") + } + konanTest.runCompiler(module.versionFiles(moduleVersion).map { it.path }, + klibModulePath, flags + listOf("-p", "library") + repos + klibs + friends) + } + + fun produceLibrary(module: TestModule) { + if (!module.hasVersions) { + produceLibrary(module, 1) + } else { + produceLibrary(module, 1) + produceLibrary(module, 2) + } + } + + fun produceProgram(compileList: List) { + val compileMain = compileList.filter { + it.module.isDefaultModule() || it.module === TestModule.support + } + compileMain.forEach { f -> + libs.addAll(f.module.dependencies) + } + + // When producing klibs link them against version 2 of multiversioned klibs. + val dependencyVersion = 2 + + val friends = compileMain.flatMap { it.module.friends }.toSet() + val repos = listOf("-r", "${executablePath}_version$dependencyVersion", "-r", outputDirectory) + + if (compileMain.isNotEmpty()) { + konanTest.runCompiler(compileMain.map { it.path }, executablePath, flags + repos + + libs.flatMap { listOf("-l", moduleToKlibName(it, dependencyVersion)) } + + friends.flatMap { listOf("-friend-modules", "${executablePath}.${it}.klib") } + ) + } + } +}