Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 31 additions & 0 deletions compiler/arguments/resources/kotlin-compiler-arguments.json
Original file line number Diff line number Diff line change
Expand Up @@ -1115,6 +1115,37 @@
"removedVersion": null
}
},
{
"name": "header",
"shortName": null,
"deprecatedName": null,
"description": {
"current": "Enable header compilation mode.\nIn this mode, the compiler produces class files that only contain the 'skeleton' of the classes to be\ncompiled but the method bodies of all the implementations are empty. This is used to speed up parallel compilation\nbuild systems where header libraries can be used to replace downstream dependencies for which we only need to\nsee the type names and method signatures required to compile a given translation unit.",
"valueInVersions": []
},
"delimiter": null,
"valueType": {
"type": "org.jetbrains.kotlin.arguments.dsl.types.BooleanType",
"isNullable": {
"current": false,
"valueInVersions": []
},
"defaultValue": {
"current": false,
"valueInVersions": []
}
},
"valueDescription": {
"current": null,
"valueInVersions": []
},
"releaseVersionsMetadata": {
"introducedVersion": "2.2.0",
"stabilizedVersion": "2.2.0",
"deprecatedVersion": null,
"removedVersion": null
}
},
{
"name": "progressive",
"shortName": null,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,24 @@ val actualCommonCompilerArguments by compilerArgumentsLevel(CompilerArgumentsLev
)
}

compilerArgument {
name = "header"
compilerName = "headerMode"
description = """
Enable header compilation mode.
In this mode, the compiler produces class files that only contain the 'skeleton' of the classes to be
compiled but the method bodies of all the implementations are empty. This is used to speed up parallel compilation
build systems where header libraries can be used to replace downstream dependencies for which we only need to
see the type names and method signatures required to compile a given translation unit.
""".trimIndent().asReleaseDependent()
valueType = BooleanType.defaultFalse

lifecycle(
introducedVersion = KotlinReleaseVersion.v2_2_0,
stabilizedVersion = KotlinReleaseVersion.v2_2_0,
)
}

compilerArgument {
name = "progressive"
deprecatedName = "Xprogressive"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,7 @@ public final class org/jetbrains/kotlin/buildtools/api/SourcesChanges$Unknown :
public abstract interface class org/jetbrains/kotlin/buildtools/api/arguments/CommonCompilerArguments : org/jetbrains/kotlin/buildtools/api/arguments/CommonToolArguments {
public static final field API_VERSION Lorg/jetbrains/kotlin/buildtools/api/arguments/CommonCompilerArguments$CommonCompilerArgument;
public static final field Companion Lorg/jetbrains/kotlin/buildtools/api/arguments/CommonCompilerArguments$Companion;
public static final field HEADER Lorg/jetbrains/kotlin/buildtools/api/arguments/CommonCompilerArguments$CommonCompilerArgument;
public static final field KOTLIN_HOME Lorg/jetbrains/kotlin/buildtools/api/arguments/CommonCompilerArguments$CommonCompilerArgument;
public static final field LANGUAGE_VERSION Lorg/jetbrains/kotlin/buildtools/api/arguments/CommonCompilerArguments$CommonCompilerArgument;
public static final field OPT_IN Lorg/jetbrains/kotlin/buildtools/api/arguments/CommonCompilerArguments$CommonCompilerArgument;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,17 @@ public interface CommonCompilerArguments : CommonToolArguments {
public val KOTLIN_HOME: CommonCompilerArgument<String?> =
CommonCompilerArgument("KOTLIN_HOME", KotlinKotlinVersion(1, 1, 50))

/**
* Enable header compilation mode.
* In this mode, the compiler produces class files that only contain the 'skeleton' of the classes to be
* compiled but the method bodies of all the implementations are empty. This is used to speed up parallel compilation
* build systems where header libraries can be used to replace downstream dependencies for which we only need to
* see the type names and method signatures required to compile a given translation unit.
*/
@JvmField
public val HEADER: CommonCompilerArgument<Boolean> =
CommonCompilerArgument("HEADER", KotlinKotlinVersion(2, 2, 0))

/**
* Enable progressive compiler mode.
* In this mode, deprecations and bug fixes for unstable code take effect immediately
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import kotlin.collections.MutableSet
import kotlin.collections.mutableMapOf
import kotlin.collections.mutableSetOf
import org.jetbrains.kotlin.buildtools.`internal`.compat.arguments.CommonCompilerArgumentsImpl.Companion.API_VERSION
import org.jetbrains.kotlin.buildtools.`internal`.compat.arguments.CommonCompilerArgumentsImpl.Companion.HEADER
import org.jetbrains.kotlin.buildtools.`internal`.compat.arguments.CommonCompilerArgumentsImpl.Companion.KOTLIN_HOME
import org.jetbrains.kotlin.buildtools.`internal`.compat.arguments.CommonCompilerArgumentsImpl.Companion.LANGUAGE_VERSION
import org.jetbrains.kotlin.buildtools.`internal`.compat.arguments.CommonCompilerArgumentsImpl.Companion.OPT_IN
Expand Down Expand Up @@ -147,6 +148,7 @@ internal abstract class CommonCompilerArgumentsImpl : CommonToolArgumentsImpl(),
if (LANGUAGE_VERSION in this) { arguments.languageVersion = get(LANGUAGE_VERSION)?.stringValue}
if (API_VERSION in this) { arguments.apiVersion = get(API_VERSION)?.stringValue}
if (KOTLIN_HOME in this) { arguments.kotlinHome = get(KOTLIN_HOME)}
try { if (HEADER in this) { arguments.headerMode = get(HEADER)} } catch (e: NoSuchMethodError) { throw IllegalStateException("""Compiler parameter not recognized: HEADER. Current compiler version is: $KC_VERSION}, but the argument was introduced in 2.2.0""").initCause(e) }
if (PROGRESSIVE in this) { arguments.progressiveMode = get(PROGRESSIVE)}
if (SCRIPT in this) { arguments.script = get(SCRIPT)}
try { if (X_REPL in this) { arguments.repl = get(X_REPL)} } catch (e: NoSuchMethodError) { throw IllegalStateException("""Compiler parameter not recognized: X_REPL. Current compiler version is: $KC_VERSION}, but the argument was introduced in 2.2.0""").initCause(e) }
Expand Down Expand Up @@ -239,6 +241,7 @@ internal abstract class CommonCompilerArgumentsImpl : CommonToolArgumentsImpl(),
try { this[LANGUAGE_VERSION] = arguments.languageVersion?.let { EnumsKotlinVersion.entries.first { entry -> entry.stringValue == it } } } catch (_: NoSuchMethodError) { }
try { this[API_VERSION] = arguments.apiVersion?.let { EnumsKotlinVersion.entries.first { entry -> entry.stringValue == it } } } catch (_: NoSuchMethodError) { }
try { this[KOTLIN_HOME] = arguments.kotlinHome } catch (_: NoSuchMethodError) { }
try { this[HEADER] = arguments.headerMode } catch (_: NoSuchMethodError) { }
try { this[PROGRESSIVE] = arguments.progressiveMode } catch (_: NoSuchMethodError) { }
try { this[SCRIPT] = arguments.script } catch (_: NoSuchMethodError) { }
try { this[X_REPL] = arguments.repl } catch (_: NoSuchMethodError) { }
Expand Down Expand Up @@ -343,6 +346,8 @@ internal abstract class CommonCompilerArgumentsImpl : CommonToolArgumentsImpl(),

public val KOTLIN_HOME: CommonCompilerArgument<String?> = CommonCompilerArgument("KOTLIN_HOME")

public val HEADER: CommonCompilerArgument<Boolean> = CommonCompilerArgument("HEADER")

public val PROGRESSIVE: CommonCompilerArgument<Boolean> = CommonCompilerArgument("PROGRESSIVE")

public val SCRIPT: CommonCompilerArgument<Boolean> = CommonCompilerArgument("SCRIPT")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import kotlin.collections.mutableMapOf
import kotlin.collections.mutableSetOf
import org.jetbrains.kotlin.buildtools.`internal`.UseFromImplModuleRestricted
import org.jetbrains.kotlin.buildtools.`internal`.arguments.CommonCompilerArgumentsImpl.Companion.API_VERSION
import org.jetbrains.kotlin.buildtools.`internal`.arguments.CommonCompilerArgumentsImpl.Companion.HEADER
import org.jetbrains.kotlin.buildtools.`internal`.arguments.CommonCompilerArgumentsImpl.Companion.KOTLIN_HOME
import org.jetbrains.kotlin.buildtools.`internal`.arguments.CommonCompilerArgumentsImpl.Companion.LANGUAGE_VERSION
import org.jetbrains.kotlin.buildtools.`internal`.arguments.CommonCompilerArgumentsImpl.Companion.OPT_IN
Expand Down Expand Up @@ -155,6 +156,7 @@ internal abstract class CommonCompilerArgumentsImpl : CommonToolArgumentsImpl(),
if (LANGUAGE_VERSION in this) { arguments.languageVersion = get(LANGUAGE_VERSION)?.stringValue}
if (API_VERSION in this) { arguments.apiVersion = get(API_VERSION)?.stringValue}
if (KOTLIN_HOME in this) { arguments.kotlinHome = get(KOTLIN_HOME)}
if (HEADER in this) { arguments.headerMode = get(HEADER)}
if (PROGRESSIVE in this) { arguments.progressiveMode = get(PROGRESSIVE)}
if (SCRIPT in this) { arguments.script = get(SCRIPT)}
if (X_REPL in this) { arguments.repl = get(X_REPL)}
Expand Down Expand Up @@ -252,6 +254,7 @@ internal abstract class CommonCompilerArgumentsImpl : CommonToolArgumentsImpl(),
try { this[LANGUAGE_VERSION] = arguments.languageVersion?.let { EnumsKotlinVersion.entries.first { entry -> entry.stringValue == it } } } catch (_: NoSuchMethodError) { }
try { this[API_VERSION] = arguments.apiVersion?.let { EnumsKotlinVersion.entries.first { entry -> entry.stringValue == it } } } catch (_: NoSuchMethodError) { }
try { this[KOTLIN_HOME] = arguments.kotlinHome } catch (_: NoSuchMethodError) { }
try { this[HEADER] = arguments.headerMode } catch (_: NoSuchMethodError) { }
try { this[PROGRESSIVE] = arguments.progressiveMode } catch (_: NoSuchMethodError) { }
try { this[SCRIPT] = arguments.script } catch (_: NoSuchMethodError) { }
try { this[X_REPL] = arguments.repl } catch (_: NoSuchMethodError) { }
Expand Down Expand Up @@ -361,6 +364,8 @@ internal abstract class CommonCompilerArgumentsImpl : CommonToolArgumentsImpl(),

public val KOTLIN_HOME: CommonCompilerArgument<String?> = CommonCompilerArgument("KOTLIN_HOME")

public val HEADER: CommonCompilerArgument<Boolean> = CommonCompilerArgument("HEADER")

public val PROGRESSIVE: CommonCompilerArgument<Boolean> = CommonCompilerArgument("PROGRESSIVE")

public val SCRIPT: CommonCompilerArgument<Boolean> = CommonCompilerArgument("SCRIPT")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,20 @@ abstract class CommonCompilerArguments : CommonToolArguments() {
field = if (value.isNullOrEmpty()) null else value
}

@Argument(
value = "-header",
description = """Enable header compilation mode.
In this mode, the compiler produces class files that only contain the 'skeleton' of the classes to be
compiled but the method bodies of all the implementations are empty. This is used to speed up parallel compilation
build systems where header libraries can be used to replace downstream dependencies for which we only need to
see the type names and method signatures required to compile a given translation unit.""",
)
var headerMode: Boolean = false
set(value) {
checkFrozen()
field = value
}

@Argument(
value = "-progressive",
deprecatedName = "-Xprogressive",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ fun copyCommonCompilerArguments(from: CommonCompilerArguments, to: CommonCompile
to.fragmentRefines = from.fragmentRefines?.copyOf()
to.fragmentSources = from.fragmentSources?.copyOf()
to.fragments = from.fragments?.copyOf()
to.headerMode = from.headerMode
to.ignoreConstOptimizationErrors = from.ignoreConstOptimizationErrors
to.incrementalCompilation = from.incrementalCompilation
to.inlineClasses = from.inlineClasses
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -194,7 +194,13 @@ object WebFrontendPipelinePhase : PipelinePhase<ConfigurationPipelineArtifact, W
isCommonSource = { groupedSources.isCommonSourceForLt(it) },
fileBelongsToModule = { file, it -> groupedSources.fileBelongsToModuleForLt(file, it) },
buildResolveAndCheckFir = { session, files ->
buildResolveAndCheckFirViaLightTree(session, files, diagnosticsReporter, performanceManager?.let { it::addSourcesStats })
buildResolveAndCheckFirViaLightTree(
session,
files,
diagnosticsReporter,
performanceManager?.let { it::addSourcesStats },
false
)
},
useWasmPlatform = useWasmPlatform,
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ fun CompilerConfiguration.setupCommonArguments(
val messageCollector = getNotNull(CommonConfigurationKeys.MESSAGE_COLLECTOR_KEY)

put(CommonConfigurationKeys.DISABLE_INLINE, arguments.noInline)
put(CommonConfigurationKeys.HEADER_COMPILATION, arguments.headerMode)
put(CommonConfigurationKeys.USE_FIR_EXTRA_CHECKERS, arguments.extraWarnings)
put(CommonConfigurationKeys.METADATA_KLIB, arguments.metadataKlib)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,9 @@ fun CompilerConfiguration.copyCommonKlibArgumentsFrom(source: CompilerConfigurat
klibAbiCompatibilityLevel = source.klibAbiCompatibilityLevel

zipFileSystemAccessor = source.zipFileSystemAccessor

// Header compilation mode needs to be propagated to KLIB compilation.
headerCompilation = source.headerCompilation
}

private fun parseCustomKotlinAbiVersion(customKlibAbiVersion: String?, collector: MessageCollector): KotlinAbiVersion? {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import org.jetbrains.kotlin.cli.common.messages.MessageCollector
import org.jetbrains.kotlin.cli.common.prepareJvmSessions
import org.jetbrains.kotlin.cli.jvm.compiler.VfsBasedProjectEnvironment
import org.jetbrains.kotlin.config.CompilerConfiguration
import org.jetbrains.kotlin.config.headerCompilation
import org.jetbrains.kotlin.config.perfManager
import org.jetbrains.kotlin.diagnostics.impl.BaseDiagnosticsCollector
import org.jetbrains.kotlin.fir.extensions.FirExtensionRegistrar
Expand Down Expand Up @@ -94,9 +95,9 @@ private fun FrontendContext.compileModuleToAnalyzedFirViaLightTreeIncrementally(
)

val countFilesAndLines = if (performanceManager == null) null else performanceManager::addSourcesStats

val outputs = sessionsWithSources.map { (session, sources) ->
buildResolveAndCheckFirViaLightTree(session, sources, diagnosticsReporter, countFilesAndLines)
buildResolveAndCheckFirViaLightTree(session, sources, diagnosticsReporter, countFilesAndLines,
configuration.headerCompilation)
}
outputs.runPlatformCheckers(diagnosticsReporter)
FirResult(outputs)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -263,7 +263,8 @@ object JvmFrontendPipelinePhase : PipelinePhase<ConfigurationPipelineArtifact, J
val countFilesAndLines = if (perfManager == null) null else perfManager::addSourcesStats
val outputs = sessionsWithSources.map { (session, sources) ->
val rawFirFiles = when (configuration.useLightTree) {
true -> session.buildFirViaLightTree(sources, diagnosticsCollector, countFilesAndLines)
true -> session.buildFirViaLightTree(sources, diagnosticsCollector, countFilesAndLines,
configuration.headerCompilation)
else -> session.buildFirFromKtFiles(sources.asKtFilesList())
}
resolveAndCheckFir(session, rawFirFiles, diagnosticsCollector)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ import org.jetbrains.kotlin.cli.pipeline.PerformanceNotifications
import org.jetbrains.kotlin.cli.pipeline.PipelinePhase
import org.jetbrains.kotlin.cli.pipeline.jvm.asKtFilesList
import org.jetbrains.kotlin.config.CommonConfigurationKeys
import org.jetbrains.kotlin.config.headerCompilation
import org.jetbrains.kotlin.config.messageCollector
import org.jetbrains.kotlin.config.moduleName
import org.jetbrains.kotlin.config.perfManager
Expand Down Expand Up @@ -110,9 +111,10 @@ object MetadataFrontendPipelinePhase : PipelinePhase<ConfigurationPipelineArtifa
}
)
sessionsWithSources.map { (session, files) ->
val firFiles = session.buildFirViaLightTree(files, diagnosticsReporter) { files, lines ->
perfManager?.addSourcesStats(files, lines)
}
val firFiles = session.buildFirViaLightTree(files, diagnosticsReporter, { files, lines ->
perfManager?.addSourcesStats(files, lines)
},
configuration.headerCompilation)
resolveAndCheckFir(session, firFiles, diagnosticsReporter)
}
} else {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ object CommonConfigurationKeysContainer : KeysContainer("org.jetbrains.kotlin.co
val PARALLEL_BACKEND_THREADS by key<Int>("Run codegen phase in parallel with N threads")
val DUMP_MODEL by key<String>("Dump compilation model")
val INCREMENTAL_COMPILATION by key<Boolean>("Enable incremental compilation")
val HEADER_COMPILATION by key<Boolean>("Enable header compilation mode")
val ALLOW_ANY_SCRIPTS_IN_SOURCE_ROOTS by key<Boolean>("Allow to compile any scripts along with regular Kotlin sources")
val IGNORE_CONST_OPTIMIZATION_ERRORS by key<Boolean>("Ignore errors from IrConstTransformer")
val EVALUATED_CONST_TRACKER by key<EvaluatedConstTracker>("Keeps track of all evaluated by IrInterpreter constants")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,9 @@ object CommonConfigurationKeys {
@JvmField
val INCREMENTAL_COMPILATION = CompilerConfigurationKey.create<Boolean>("Enable incremental compilation")

@JvmField
val HEADER_COMPILATION = CompilerConfigurationKey.create<Boolean>("Enable header compilation mode")

@JvmField
val ALLOW_ANY_SCRIPTS_IN_SOURCE_ROOTS = CompilerConfigurationKey.create<Boolean>("Allow to compile any scripts along with regular Kotlin sources")

Expand Down Expand Up @@ -218,6 +221,10 @@ var CompilerConfiguration.incrementalCompilation: Boolean
get() = getBoolean(CommonConfigurationKeys.INCREMENTAL_COMPILATION)
set(value) { put(CommonConfigurationKeys.INCREMENTAL_COMPILATION, value) }

var CompilerConfiguration.headerCompilation: Boolean
get() = getBoolean(CommonConfigurationKeys.HEADER_COMPILATION)
set(value) { put(CommonConfigurationKeys.HEADER_COMPILATION, value) }

var CompilerConfiguration.allowAnyScriptsInSourceRoots: Boolean
get() = getBoolean(CommonConfigurationKeys.ALLOW_ANY_SCRIPTS_IN_SOURCE_ROOTS)
set(value) { put(CommonConfigurationKeys.ALLOW_ANY_SCRIPTS_IN_SOURCE_ROOTS, value) }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ abstract class AbstractFirOldFrontendLightClassesTest : BaseDiagnosticsTest() {
private fun mapKtFilesToFirFiles(session: FirSession, ktFiles: List<KtFile>, firFiles: MutableList<FirFile>, useLightTree: Boolean) {
val firProvider = (session.firProvider as FirProviderImpl)
if (useLightTree) {
val lightTreeBuilder = LightTree2Fir(session, firProvider.kotlinScopeProvider)
val lightTreeBuilder = LightTree2Fir(session, false, firProvider.kotlinScopeProvider)
ktFiles.mapTo(firFiles) {
val firFile =
lightTreeBuilder.buildFirFile(
Expand Down
Loading