From c1f0a6048b7e89ee48964de6ee22861e567a0fc3 Mon Sep 17 00:00:00 2001 From: Martin Petrov Date: Thu, 18 Jun 2020 09:38:53 -0400 Subject: [PATCH] KT-39670: -Xdebug-prefix-map for path remapping This introduces a new `-Xdebug-prefix-map` flag. When compiling files with directories prefixed by the map key, the prefix will be changed to the map value. This allows for reproducable builds by replacing absolute paths with relative ones. (cherry picked from commit bba4ce1c2c5ee06b9f5f65148ac8ef883715474a) --- .../org/jetbrains/kotlin/cli/bc/K2Native.kt | 18 ++++++++++++++++++ .../kotlin/cli/bc/K2NativeCompilerArguments.kt | 3 +++ .../backend/konan/KonanConfigurationKeys.kt | 2 ++ .../kotlin/backend/konan/llvm/BitcodePhases.kt | 6 ++++-- .../kotlin/backend/konan/llvm/DebugUtils.kt | 14 +++++++++++--- .../kotlin/backend/konan/llvm/IrToBitcode.kt | 2 +- 6 files changed, 39 insertions(+), 6 deletions(-) diff --git a/backend.native/cli.bc/src/org/jetbrains/kotlin/cli/bc/K2Native.kt b/backend.native/cli.bc/src/org/jetbrains/kotlin/cli/bc/K2Native.kt index da8011d5ebe..ec682e03bdf 100644 --- a/backend.native/cli.bc/src/org/jetbrains/kotlin/cli/bc/K2Native.kt +++ b/backend.native/cli.bc/src/org/jetbrains/kotlin/cli/bc/K2Native.kt @@ -235,6 +235,7 @@ class K2Native : CLICompiler() { put(LIBRARIES_TO_COVER, arguments.coveredLibraries.toNonNullList()) arguments.coverageFile?.let { put(PROFRAW_PATH, it) } put(OBJC_GENERICS, !arguments.noObjcGenerics) + put(DEBUG_PREFIX_MAP, parseDebugPrefixMap(arguments, configuration)) put(LIBRARIES_TO_CACHE, parseLibrariesToCache(arguments, configuration, outputKind)) val libraryToAddToCache = parseLibraryToAddToCache(arguments, configuration, outputKind) @@ -422,5 +423,22 @@ private fun parseShortModuleName( } } +private fun parseDebugPrefixMap( + arguments: K2NativeCompilerArguments, + configuration: CompilerConfiguration +): Map = arguments.debugPrefixMap?.asList().orEmpty().mapNotNull { + val libraryAndCache = it.split("=") + if (libraryAndCache.size != 2) { + configuration.report( + ERROR, + "incorrect debug prefix map format: expected '=', got '$it'" + ) + null + } else { + libraryAndCache[0] to libraryAndCache[1] + } +}.toMap() + + fun main(args: Array) = K2Native.main(args) fun mainNoExitWithGradleRenderer(args: Array) = K2Native.mainNoExitWithGradleRenderer(args) diff --git a/backend.native/cli.bc/src/org/jetbrains/kotlin/cli/bc/K2NativeCompilerArguments.kt b/backend.native/cli.bc/src/org/jetbrains/kotlin/cli/bc/K2NativeCompilerArguments.kt index b3ad1c1be4d..ae28e68cb7f 100644 --- a/backend.native/cli.bc/src/org/jetbrains/kotlin/cli/bc/K2NativeCompilerArguments.kt +++ b/backend.native/cli.bc/src/org/jetbrains/kotlin/cli/bc/K2NativeCompilerArguments.kt @@ -265,6 +265,9 @@ class K2NativeCompilerArguments : CommonCompilerArguments() { @Argument(value = "-Xmetadata-klib", description = "Produce a klib that only contains the declarations metadata") var metadataKlib: Boolean = false + @Argument(value = "-Xdebug-prefix-map", valueDescription = "", description = "Remap file source directory paths in debug info") + var debugPrefixMap: Array? = null + override fun configureAnalysisFlags(collector: MessageCollector): MutableMap, Any> = super.configureAnalysisFlags(collector).also { val useExperimental = it[AnalysisFlags.useExperimental] as List<*> diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/KonanConfigurationKeys.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/KonanConfigurationKeys.kt index db2e3df553e..3e4634e088d 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/KonanConfigurationKeys.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/KonanConfigurationKeys.kt @@ -138,6 +138,8 @@ class KonanConfigKeys { = CompilerConfigurationKey.create("path to *.profraw coverage output") val OBJC_GENERICS: CompilerConfigurationKey = CompilerConfigurationKey.create("write objc header with generics support") + val DEBUG_PREFIX_MAP: CompilerConfigurationKey> + = CompilerConfigurationKey.create("remap file source paths in debug info") } } diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/BitcodePhases.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/BitcodePhases.kt index 033141e2919..cd53f42df41 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/BitcodePhases.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/BitcodePhases.kt @@ -38,11 +38,13 @@ internal val contextLLVMSetupPhase = makeKonanModuleOpPhase( // we don't split path to filename and directory to provide enough level uniquely for dsymutil to avoid symbol // clashing, which happens on linking with libraries produced from intercepting sources. + val filePath = context.config.outputFile.toFileAndFolder(context).path() + context.debugInfo.compilationUnit = if (context.shouldContainLocationDebugInfo()) DICreateCompilationUnit( builder = context.debugInfo.builder, lang = DWARF.language(context.config), - File = File(context.config.outputFile).absolutePath, - dir = "-", + File = filePath, + dir = "", producer = DWARF.producer, isOptimized = 0, flags = "", diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/DebugUtils.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/DebugUtils.kt index f19a8c6e4eb..11c96bee67b 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/DebugUtils.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/DebugUtils.kt @@ -117,16 +117,24 @@ internal data class FileAndFolder(val file: String, val folder: String) { fun path() = if (this == NOFILE) file else "$folder/$file" } -internal fun String?.toFileAndFolder():FileAndFolder { +internal fun String?.toFileAndFolder(context: Context):FileAndFolder { this ?: return FileAndFolder.NOFILE val file = File(this).absoluteFile - return FileAndFolder(file.name, file.parent) + var parent = file.parent + context.configuration.get(KonanConfigKeys.DEBUG_PREFIX_MAP)?.let { debugPrefixMap -> + for ((key, value) in debugPrefixMap) { + if (parent.startsWith(key)) { + parent = value + parent.removePrefix(key) + } + } + } + return FileAndFolder(file.name, parent) } internal fun generateDebugInfoHeader(context: Context) { if (context.shouldContainAnyDebugInfo()) { val path = context.config.outputFile - .toFileAndFolder() + .toFileAndFolder(context) @Suppress("UNCHECKED_CAST") context.debugInfo.module = DICreateModule( builder = context.debugInfo.builder, diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/IrToBitcode.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/IrToBitcode.kt index d70aa43c3ef..64ea98e9be0 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/IrToBitcode.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/IrToBitcode.kt @@ -1896,7 +1896,7 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map