diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/Exceptions.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/Exceptions.kt index a9decec4b8e..f319a74e09f 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/Exceptions.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/Exceptions.kt @@ -16,13 +16,23 @@ package org.jetbrains.kotlin.backend.konan +/** + * This is a common ancestor of all Kotlin/Native exceptions. + */ +open class KonanException(message: String = "", cause: Throwable? = null) : Exception(message, cause) + /** * Represents a compilation error caused by mistakes in an input file, e.g. undefined reference. */ -class KonanCompilationException(message: String = "", cause: Throwable? = null) : Exception(message, cause) {} +class KonanCompilationException(message: String = "", cause: Throwable? = null) : KonanException(message, cause) /** * Internal compiler error: could not deserialize IR for inline function body. */ -class KonanIrDeserializationException(message: String = "", cause: Throwable? = null) : Exception(message, cause) +class KonanIrDeserializationException(message: String = "", cause: Throwable? = null) : KonanException(message, cause) + +/** + * An error occured during external tool invocation. Such as non-zero exit code. + */ +class KonanExternalToolFailure(message: String = "", cause: Throwable? = null) : KonanException(message, cause) diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/LinkStage.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/LinkStage.kt index d334365c153..f604a72dc1f 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/LinkStage.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/LinkStage.kt @@ -292,7 +292,7 @@ internal class LinkStage(val context: Context) { private val entryPointSelector: List get() = if (nomain) emptyList() else platform.entrySelector - private fun link(objectFiles: List, libraryProvidedLinkerFlags: List): ExecutableFile { + private fun link(objectFiles: List, libraryProvidedLinkerFlags: List): ExecutableFile? { val executable = context.config.outputFile val linkCommand = platform.linkCommand(objectFiles, executable, optimize, debug) + @@ -302,13 +302,16 @@ internal class LinkStage(val context: Context) { platform.linkCommandSuffix() + libraryProvidedLinkerFlags - runTool(*linkCommand.toTypedArray()) + try { + runTool(*linkCommand.toTypedArray()) + } catch (e: KonanExternalToolFailure) { + return null + } if (platform is MacOSBasedPlatform && context.shouldContainDebugInfo()) { if (context.phase?.verbose ?: false) runTool(*platform.dsymutilDryRunVerboseCommand(executable).toTypedArray()) runTool(*platform.dsymutilCommand(executable).toTypedArray()) } - return executable } @@ -349,7 +352,7 @@ internal class LinkStage(val context: Context) { private fun runTool(vararg command: String) { val code = executeCommand(*command) - if (code != 0) error("The ${command[0]} command returned non-zero exit code: $code.") + if (code != 0) throw KonanExternalToolFailure("The ${command[0]} command returned non-zero exit code: $code.") } fun linkStage() { diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/Reporting.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/Reporting.kt index 3d09d9a712f..fe93e80faae 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/Reporting.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/Reporting.kt @@ -18,6 +18,7 @@ package org.jetbrains.kotlin.backend.konan import org.jetbrains.kotlin.backend.common.CommonBackendContext import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity +import org.jetbrains.kotlin.cli.common.messages.CompilerMessageLocation import org.jetbrains.kotlin.ir.IrElement import org.jetbrains.kotlin.ir.declarations.IrFile import org.jetbrains.kotlin.ir.util.getCompilerMessageLocation @@ -27,3 +28,11 @@ internal fun CommonBackendContext.reportCompilationError(message: String, irFile this.messageCollector.report(CompilerMessageSeverity.ERROR, message, location) throw KonanCompilationException() } + +internal fun CommonBackendContext.reportCompilationError(message: String) { + this.messageCollector.report(CompilerMessageSeverity.ERROR, message, null) +} + +internal fun CommonBackendContext.reportCompilationWarning(message: String) { + this.messageCollector.report(CompilerMessageSeverity.WARNING, message, null) +} diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/EntryPoint.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/EntryPoint.kt index 60908d8f645..f10b9582946 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/EntryPoint.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/EntryPoint.kt @@ -16,6 +16,7 @@ package org.jetbrains.kotlin.backend.konan.llvm +import org.jetbrains.kotlin.backend.konan.reportCompilationError import org.jetbrains.kotlin.backend.konan.Context import org.jetbrains.kotlin.backend.konan.KonanConfigKeys import org.jetbrains.kotlin.backend.konan.descriptors.isArray @@ -49,6 +50,9 @@ internal fun findMainEntryPoint(context: Context): FunctionDescriptor? { it.typeParameters.isEmpty() && it.isExported() } + if (main == null) { + context.reportCompilationError("Could not find '$entryName' in '$packageName' package.") + } return main }