diff --git a/kotlin-native/build-tools/src/main/kotlin/org/jetbrains/kotlin/ExecLlvm.kt b/kotlin-native/build-tools/src/main/kotlin/org/jetbrains/kotlin/ExecLlvm.kt index 4f4ee78f478..a17226ee679 100644 --- a/kotlin-native/build-tools/src/main/kotlin/org/jetbrains/kotlin/ExecLlvm.kt +++ b/kotlin-native/build-tools/src/main/kotlin/org/jetbrains/kotlin/ExecLlvm.kt @@ -12,13 +12,11 @@ import org.gradle.process.ExecOperations import org.gradle.process.ExecResult import org.gradle.process.ExecSpec import org.jetbrains.kotlin.konan.target.PlatformManager -import org.jetbrains.kotlin.konan.util.DependencyProcessor fun execLlvmUtility(project: Project, utility: String, action: Action): ExecResult { - val llvmBinDirectory = "${project.platformManager.hostPlatform.absoluteLlvmHome}/bin" return project.exec(Action { action.execute(this) - executable = "$llvmBinDirectory/$utility" + executable = project.platformManager.resolveLlvmUtility(utility) }) } @@ -26,10 +24,11 @@ fun execLlvmUtility(project: Project, utility: String, closure: Closure): ExecResult { - val llvmBinDirectory = "${platformManager.hostPlatform.absoluteLlvmHome}/bin" return exec { action.execute(this) - executable = "$llvmBinDirectory/$utility" + executable = platformManager.resolveLlvmUtility(utility) } } \ No newline at end of file diff --git a/kotlin-native/build-tools/src/main/kotlin/org/jetbrains/kotlin/bitcode/CompileToBitcodePlugin.kt b/kotlin-native/build-tools/src/main/kotlin/org/jetbrains/kotlin/bitcode/CompileToBitcodePlugin.kt index 53acc812281..ec16712fc8f 100644 --- a/kotlin-native/build-tools/src/main/kotlin/org/jetbrains/kotlin/bitcode/CompileToBitcodePlugin.kt +++ b/kotlin-native/build-tools/src/main/kotlin/org/jetbrains/kotlin/bitcode/CompileToBitcodePlugin.kt @@ -16,10 +16,7 @@ import org.gradle.api.services.BuildServiceParameters import org.gradle.kotlin.dsl.* import org.gradle.language.base.plugins.LifecycleBasePlugin import org.jetbrains.kotlin.ExecClang -import org.jetbrains.kotlin.cpp.CompilationDatabaseExtension -import org.jetbrains.kotlin.cpp.CompilationDatabasePlugin -import org.jetbrains.kotlin.cpp.CompileToExecutable -import org.jetbrains.kotlin.cpp.RunGTest +import org.jetbrains.kotlin.cpp.* import org.jetbrains.kotlin.konan.target.KonanTarget import org.jetbrains.kotlin.konan.target.PlatformManager import org.jetbrains.kotlin.konan.target.SanitizerKind @@ -68,6 +65,7 @@ private abstract class CompileTestsSemaphore : BuildService { override fun apply(target: Project) { target.apply() + target.apply() target.extensions.create(EXTENSION_NAME, target) } diff --git a/kotlin-native/build-tools/src/main/kotlin/org/jetbrains/kotlin/cpp/GitClangFormat.kt b/kotlin-native/build-tools/src/main/kotlin/org/jetbrains/kotlin/cpp/GitClangFormat.kt new file mode 100644 index 00000000000..2f515788372 --- /dev/null +++ b/kotlin-native/build-tools/src/main/kotlin/org/jetbrains/kotlin/cpp/GitClangFormat.kt @@ -0,0 +1,84 @@ +/* + * Copyright 2010-2022 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package org.jetbrains.kotlin.cpp + +import org.gradle.api.DefaultTask +import org.gradle.api.provider.Property +import org.gradle.api.tasks.Input +import org.gradle.api.tasks.TaskAction +import org.gradle.api.tasks.UntrackedTask +import org.gradle.api.tasks.options.Option +import org.gradle.kotlin.dsl.getByType +import org.gradle.process.ExecOperations +import org.jetbrains.kotlin.konan.target.PlatformManager +import org.jetbrains.kotlin.resolveLlvmUtility +import java.io.ByteArrayOutputStream +import javax.inject.Inject + +/** + * A task that formats changed code with clang-format. + * + * Will run --binary --force $(git merge-base [parent] HEAD) [directory] + */ +@UntrackedTask(because = "Formatter should always run when asked") +abstract class GitClangFormat : DefaultTask() { + private val platformManager = project.extensions.getByType() + + /** + * Parent branch for the current branch. + */ + @get:Option(option = "parent", description = "base parent of the branch; by default origin/master") + @get:Input + abstract val parent: Property + + /** + * Directory in which to format sources. + */ + @get:Option(option = "directory", description = "directory in which to format sources; by default project's source directory") + @get:Input + abstract val directory: Property + + /** + * Whether to run the tool in interactive mode. + */ + @get:Option(option = "interactive", description = "interactively ask about each change before applying; by default false") + @get:Input + abstract val interactive: Property + + @get:Inject + protected abstract val execOperations: ExecOperations + + @TaskAction + fun run() { + val gitClangFormat = platformManager.resolveLlvmUtility("git-clang-format") + val clangFormat = platformManager.resolveLlvmUtility("clang-format") + val parent = this.parent.get() + val directory = this.directory.get() + val interactive = this.interactive.get() + + val commit = ByteArrayOutputStream().let { + execOperations.exec { + executable = "git" + args("merge-base", parent, "HEAD") + standardOutput = it + } + it.toString().trim() + } + execOperations.exec { + executable = gitClangFormat + args("--binary", clangFormat) + args("--force") + if (interactive) { + args("--patch") + // Not a nice experience, but it works. + standardInput = System.`in` + } + args(commit) + args("--") + args(directory) + } + } +} \ No newline at end of file diff --git a/kotlin-native/build-tools/src/main/kotlin/org/jetbrains/kotlin/cpp/GitClangFormatPlugin.kt b/kotlin-native/build-tools/src/main/kotlin/org/jetbrains/kotlin/cpp/GitClangFormatPlugin.kt new file mode 100644 index 00000000000..ded398fa679 --- /dev/null +++ b/kotlin-native/build-tools/src/main/kotlin/org/jetbrains/kotlin/cpp/GitClangFormatPlugin.kt @@ -0,0 +1,34 @@ +/* + * Copyright 2010-2022 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package org.jetbrains.kotlin.cpp + +import org.gradle.api.Plugin +import org.gradle.api.Project +import org.gradle.kotlin.dsl.* + +/** + * Plugin for [GitClangFormat] that creates a task `clangFormat` that will format project sources in the current branch. + */ +open class GitClangFormatPlugin : Plugin { + override fun apply(target: Project) { + val directory = target.layout.projectDirectory.toString() + target.tasks.register("clangFormat") { + description = "Run clang-format in $directory" + group = TASK_GROUP + parent.convention("origin/master") + this.directory.convention(directory) + interactive.convention(false) + // Needs LLVM toolchain. + // TODO: It does not need every dependency ever, only LLVM toolchain for the host. + dependsOn(":kotlin-native:dependencies:update") + } + } + + companion object { + @JvmStatic + val TASK_GROUP = "development support" + } +} \ No newline at end of file diff --git a/kotlin-native/build.gradle b/kotlin-native/build.gradle index e41ede7b7ec..1a17379bbe6 100644 --- a/kotlin-native/build.gradle +++ b/kotlin-native/build.gradle @@ -21,6 +21,7 @@ import org.jetbrains.kotlin.CopyCommonSources import org.jetbrains.kotlin.PlatformInfo import org.jetbrains.kotlin.KotlinBuildPusher import org.jetbrains.kotlin.cpp.CompilationDatabasePlugin +import org.jetbrains.kotlin.cpp.GitClangFormatPlugin import org.jetbrains.kotlin.CompareDistributionSignatures import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar import org.apache.tools.ant.filters.ReplaceTokens @@ -159,6 +160,7 @@ dependencies { } apply plugin: CompilationDatabasePlugin +apply plugin: GitClangFormatPlugin apply plugin: 'maven-publish' apply plugin: BasePlugin diff --git a/kotlin-native/codestyle/cpp/README.md b/kotlin-native/codestyle/cpp/README.md index 887aece4850..a1ac676d12d 100644 --- a/kotlin-native/codestyle/cpp/README.md +++ b/kotlin-native/codestyle/cpp/README.md @@ -46,6 +46,8 @@ to follow stdlib naming conventions. ## Formatting For automated formatting you can use [config for CLion](codestyle/cpp/CLionFormat.xml) or `clang-format` (see [config](.clang-format) at the repo's root). Note, that CLion uses `clang-format` by default; this can be turned off if you prefer to use rules from `CLionFormat.xml`. +Since 1.8.20 there's also a `:kotlin-native:clangFormat` task that will effectively run `git-clang-format -f $(git merge-base origin/master HEAD) -- kotlin-native/`. +The task accepts optional arguments `--parent` to specify base branch other than `origin/master`, and `--interactive` to run the tool with `-p` flag and interactively accept or reject formatted patches. Formatting rules are designed to closely mirror [Kotlin rules](https://kotlinlang.org/docs/reference/coding-conventions.html).