From 03ad981dea3f99120bd101f2af0358dd0caaba15 Mon Sep 17 00:00:00 2001 From: cristiangarcia Date: Tue, 24 Oct 2023 09:50:02 +0000 Subject: [PATCH] Make ClangFrontend cacheable Co-authored-by: Alexander Shabalin Merge-request: KT-MR-11479 Merged-by: Cristian Garcia --- .../org/jetbrains/kotlin/cpp/ClangFrontend.kt | 59 ++++++++++++------- 1 file changed, 39 insertions(+), 20 deletions(-) diff --git a/kotlin-native/build-tools/src/main/kotlin/org/jetbrains/kotlin/cpp/ClangFrontend.kt b/kotlin-native/build-tools/src/main/kotlin/org/jetbrains/kotlin/cpp/ClangFrontend.kt index 1d5f9858124..37be011ecdc 100644 --- a/kotlin-native/build-tools/src/main/kotlin/org/jetbrains/kotlin/cpp/ClangFrontend.kt +++ b/kotlin-native/build-tools/src/main/kotlin/org/jetbrains/kotlin/cpp/ClangFrontend.kt @@ -11,6 +11,7 @@ import org.gradle.api.model.ObjectFactory import org.gradle.api.provider.ListProperty import org.gradle.api.provider.Property import org.gradle.api.provider.Provider +import org.gradle.api.provider.ProviderFactory import org.gradle.api.tasks.* import org.gradle.kotlin.dsl.getByType import org.gradle.workers.WorkAction @@ -18,6 +19,8 @@ import org.gradle.workers.WorkParameters import org.gradle.workers.WorkerExecutor import org.jetbrains.kotlin.ExecClang import org.jetbrains.kotlin.bitcode.CompileToBitcodePlugin +import org.jetbrains.kotlin.konan.target.Family +import org.jetbrains.kotlin.konan.target.HostManager import org.jetbrains.kotlin.konan.target.PlatformManager import java.io.File import javax.inject.Inject @@ -57,13 +60,19 @@ private abstract class ClangFrontendJob : WorkAction> = project.provider { + private val workUnits: Provider> = providers.provider { val result = mutableListOf() inputFiles.visit { if (!isDirectory) { @@ -87,13 +96,14 @@ abstract class ClangFrontend : DefaultTask() { */ @get:SkipWhenEmpty @get:InputFiles + @get:PathSensitive(PathSensitivity.RELATIVE) abstract val inputFiles: ConfigurableFileTree /** * Bitcode files generated by clang. */ @get:OutputFiles - val outputFiles: FileCollection = project.files(workUnits.map { it.map { workUnit -> workUnit.outputFile } }) + val outputFiles: FileCollection = layout.files(workUnits.map { it.map { workUnit -> workUnit.outputFile } }) /** * Will select the appropriate compiler and additional flags. @@ -108,13 +118,12 @@ abstract class ClangFrontend : DefaultTask() { * Currently only `clang` and `clang++` are supported. */ @get:Input - abstract val compiler: Property + val compiler: Property = objects.property(String::class.java) /** * Extra arguments for [compiler]. */ - // Marked as input via [compilerFlags]. - @get:Internal + @get:Input abstract val arguments: ListProperty /** @@ -122,15 +131,16 @@ abstract class ClangFrontend : DefaultTask() { * * Will be passed to the compiler as `-I…` and will also be used to compute task dependencies: recompile if the headers change. */ - // Marked as input via [headers] and [compilerFlags]. + // Marked as input via [headers]. @get:Internal abstract val headersDirs: ConfigurableFileCollection /** * Final computed compiler arguments. */ - @get:Input - val compilerFlags: Provider> = project.provider { + // Marked as input via [headers] and [arguments]. + @get:Internal + val compilerFlags: Provider> = providers.provider { listOfNotNull( "-c", "-emit-llvm" @@ -143,18 +153,19 @@ abstract class ClangFrontend : DefaultTask() { * All inputs will be passed to the compiler as relative paths to this directory. */ @get:Internal - abstract val workingDirectory: DirectoryProperty + val workingDirectory: DirectoryProperty = objects.directoryProperty() @get:Input - protected val workingDirectoryPath: Provider = project.provider { - workingDirectory.get().asFile.absolutePath + protected val workingDirectoryPath: Provider = workingDirectory.map { + it.asFile.toRelativeString(layout.projectDirectory.asFile) } /** * Computed header files used for task dependencies tracking. */ @get:InputFiles - protected val headers: Provider> = project.provider { + @get:PathSensitive(PathSensitivity.RELATIVE) + protected val headers: Provider = providers.provider { // Not using clang's -M* flags because there's a problem with our current include system: // We allow includes relative to the current directory and also pass -I for each imported module // Given file tree: @@ -177,17 +188,25 @@ abstract class ClangFrontend : DefaultTask() { } // Now add manually given header dirs. dirs.addAll(headersDirs.files) - dirs.flatMap { dir -> - project.fileTree(dir) { - include("**/*.h", "**/*.hpp") - }.files + layout.files(dirs).asFileTree.matching { + include("**/*.h", "**/*.hpp") } } - @get:Inject - protected abstract val workerExecutor: WorkerExecutor - private val platformManager = project.extensions.getByType() + private val execClang by lazy { ExecClang.create(objects, platformManager) } + + // TODO: Consider configuring full clang execution from the plugin instead. + @get:InputFile + @get:PathSensitive(PathSensitivity.NONE) + val executable: Provider = layout.file(compiler.map { + val executable = execClang.resolveExecutable(it) + val executableSuffix = when (HostManager.host.family) { + Family.MINGW -> ".exe" + else -> "" + } + File("$executable$executableSuffix") + }) @TaskAction fun compile() {