gradle-plugin: generate CMake file
This commit is contained in:
+2
@@ -240,6 +240,7 @@ class KonanPlugin @Inject constructor(private val registry: ToolingModelBuilderR
|
|||||||
companion object {
|
companion object {
|
||||||
internal const val ARTIFACTS_CONTAINER_NAME = "konanArtifacts"
|
internal const val ARTIFACTS_CONTAINER_NAME = "konanArtifacts"
|
||||||
internal const val KONAN_DOWNLOAD_TASK_NAME = "checkKonanCompiler"
|
internal const val KONAN_DOWNLOAD_TASK_NAME = "checkKonanCompiler"
|
||||||
|
internal const val KONAN_GENERATE_CMAKE_TASK_NAME = "generateCMake"
|
||||||
internal const val COMPILE_ALL_TASK_NAME = "compileKonan"
|
internal const val COMPILE_ALL_TASK_NAME = "compileKonan"
|
||||||
|
|
||||||
internal const val KONAN_EXTENSION_NAME = "konan"
|
internal const val KONAN_EXTENSION_NAME = "konan"
|
||||||
@@ -260,6 +261,7 @@ class KonanPlugin @Inject constructor(private val registry: ToolingModelBuilderR
|
|||||||
project.plugins.apply("base")
|
project.plugins.apply("base")
|
||||||
// Create necessary tasks and extensions.
|
// Create necessary tasks and extensions.
|
||||||
project.tasks.create(KONAN_DOWNLOAD_TASK_NAME, KonanCompilerDownloadTask::class.java)
|
project.tasks.create(KONAN_DOWNLOAD_TASK_NAME, KonanCompilerDownloadTask::class.java)
|
||||||
|
project.tasks.create(KONAN_GENERATE_CMAKE_TASK_NAME, KonanGenerateCMakeTask::class.java)
|
||||||
project.extensions.create(KONAN_EXTENSION_NAME, KonanExtension::class.java)
|
project.extensions.create(KONAN_EXTENSION_NAME, KonanExtension::class.java)
|
||||||
project.extensions.create(ARTIFACTS_CONTAINER_NAME, KonanArtifactContainer::class.java, project)
|
project.extensions.create(ARTIFACTS_CONTAINER_NAME, KonanArtifactContainer::class.java, project)
|
||||||
|
|
||||||
|
|||||||
+140
@@ -0,0 +1,140 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2017 JetBrains s.r.o.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jetbrains.kotlin.gradle.plugin.tasks
|
||||||
|
|
||||||
|
import org.gradle.api.DefaultTask
|
||||||
|
import org.gradle.api.file.FileCollection
|
||||||
|
import org.gradle.api.tasks.TaskAction
|
||||||
|
import org.jetbrains.kotlin.gradle.plugin.KonanInteropLibrary
|
||||||
|
import org.jetbrains.kotlin.gradle.plugin.KonanLibrary
|
||||||
|
import org.jetbrains.kotlin.gradle.plugin.KonanProgram
|
||||||
|
import org.jetbrains.kotlin.gradle.plugin.konanArtifactsContainer
|
||||||
|
import org.jetbrains.kotlin.konan.target.TargetManager
|
||||||
|
import java.io.File
|
||||||
|
|
||||||
|
open class KonanGenerateCMakeTask : DefaultTask() {
|
||||||
|
@Suppress("unused")
|
||||||
|
@TaskAction
|
||||||
|
fun generateCMake() {
|
||||||
|
val interops = project.konanArtifactsContainer.toList().filterIsInstance<KonanInteropLibrary>()
|
||||||
|
val libraries = project.konanArtifactsContainer.toList().filterIsInstance<KonanLibrary>()
|
||||||
|
val programs = project.konanArtifactsContainer.toList().filterIsInstance<KonanProgram>()
|
||||||
|
val cMakeLists = generateCMakeLists(
|
||||||
|
project.name,
|
||||||
|
interops,
|
||||||
|
libraries,
|
||||||
|
programs
|
||||||
|
)
|
||||||
|
File(project.projectDir, "CMakeLists.txt")
|
||||||
|
.writeText(cMakeLists)
|
||||||
|
|
||||||
|
// This directory is filled out by the IDE
|
||||||
|
File(project.projectDir, "KotlinCMakeModule")
|
||||||
|
.mkdir()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun generateCMakeLists(
|
||||||
|
projectName: String,
|
||||||
|
interops: List<KonanInteropLibrary>,
|
||||||
|
libraries: List<KonanLibrary>,
|
||||||
|
programs: List<KonanProgram>
|
||||||
|
): String {
|
||||||
|
val cMakeCurrentListDir = "$" + "{CMAKE_CURRENT_LIST_DIR}"
|
||||||
|
|
||||||
|
return buildString {
|
||||||
|
appendln("""
|
||||||
|
cmake_minimum_required(VERSION 3.8)
|
||||||
|
|
||||||
|
set(CMAKE_MODULE_PATH $cMakeCurrentListDir/KotlinCMakeModule)
|
||||||
|
|
||||||
|
project($projectName Kotlin)
|
||||||
|
""".trimIndent())
|
||||||
|
appendln()
|
||||||
|
|
||||||
|
for (interop in interops) {
|
||||||
|
val task = interop[TargetManager.host] ?: continue
|
||||||
|
appendln(
|
||||||
|
Call("cinterop")
|
||||||
|
.arg("NAME", interop.name)
|
||||||
|
.arg("DEF_FILE", task.defFile.relativePath.toString())
|
||||||
|
.arg("COMPILER_OPTS", task.cMakeCompilerOpts)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
for (library in libraries) {
|
||||||
|
val task = library[TargetManager.host] ?: continue
|
||||||
|
appendln(
|
||||||
|
Call("konanc_library")
|
||||||
|
.arg("NAME", library.name)
|
||||||
|
.arg("SOURCES", task.cMakeSources)
|
||||||
|
.arg("LIBRARIES", task.cMakeLibraries)
|
||||||
|
.arg("LINKER_OPTS", task.cMakeLinkerOpts))
|
||||||
|
}
|
||||||
|
|
||||||
|
for (program in programs) {
|
||||||
|
val task = program[TargetManager.host] ?: continue
|
||||||
|
appendln(
|
||||||
|
Call("konanc_executable")
|
||||||
|
.arg("NAME", program.name)
|
||||||
|
.arg("SOURCES", task.cMakeSources)
|
||||||
|
.arg("LIBRARIES", task.cMakeLibraries)
|
||||||
|
.arg("LINKER_OPTS", task.cMakeLinkerOpts))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private val File.relativePath get() = relativeTo(project.projectDir)
|
||||||
|
|
||||||
|
private val FileCollection.asCMakeSourceList: List<String>
|
||||||
|
get() = files.map { it.relativePath.toString() }
|
||||||
|
|
||||||
|
private val KonanInteropTask.cMakeCompilerOpts: String
|
||||||
|
get() = compilerOpts.joinToString(" ")
|
||||||
|
|
||||||
|
private val KonanCompileTask.cMakeSources: String
|
||||||
|
get() = srcFiles.flatMap { it.asCMakeSourceList }.joinToString(" ")
|
||||||
|
|
||||||
|
private val KonanCompileTask.cMakeLibraries: String
|
||||||
|
get() = mutableListOf<String>().apply {
|
||||||
|
addAll(libraries.artifacts.map { it.artifactName })
|
||||||
|
addAll(libraries.namedKlibs)
|
||||||
|
addAll(libraries.files.flatMap { it.files }.map { it.canonicalPath })
|
||||||
|
}.joinToString(" ")
|
||||||
|
|
||||||
|
private val KonanCompileTask.cMakeLinkerOpts: String
|
||||||
|
get() = linkerOpts.joinToString(" ")
|
||||||
|
}
|
||||||
|
|
||||||
|
private class Call(val name: String) {
|
||||||
|
private val args: MutableList<Pair<String, String>> = mutableListOf()
|
||||||
|
|
||||||
|
fun arg(key: String, value: String?): Call {
|
||||||
|
if (value != null && value.isNotBlank()) args += key to value
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun toString(): String =
|
||||||
|
buildString {
|
||||||
|
append(name)
|
||||||
|
append("(")
|
||||||
|
for ((key, value) in args) {
|
||||||
|
appendln()
|
||||||
|
append(" $key $value")
|
||||||
|
}
|
||||||
|
appendln(")")
|
||||||
|
}
|
||||||
|
}
|
||||||
+68
@@ -0,0 +1,68 @@
|
|||||||
|
package org.jetbrains.kotlin.gradle.plugin.test
|
||||||
|
|
||||||
|
class CMakeSpecification extends BaseKonanSpecification {
|
||||||
|
|
||||||
|
def 'Plugin should generate CMake from project without additional settings'() {
|
||||||
|
when:
|
||||||
|
def project = KonanProject.createEmpty(projectDirectory) { KonanProject it ->
|
||||||
|
it.buildFile.write("""
|
||||||
|
plugins { id 'konan' }
|
||||||
|
konanArtifacts {
|
||||||
|
interop('stdio')
|
||||||
|
interop('sdl') {
|
||||||
|
defFile 'src/main/c_interop/sdl.def'
|
||||||
|
includeDirs '/usr/include/SDL2'
|
||||||
|
}
|
||||||
|
library('main_lib')
|
||||||
|
program('Main') {
|
||||||
|
libraries {
|
||||||
|
artifact 'stdio'
|
||||||
|
artifact 'main_lib'
|
||||||
|
linkerOpts '-L/usr/lib/x86_64-linux-gnu'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
""".stripIndent())
|
||||||
|
it.generateDefFile("stdio.def", "")
|
||||||
|
it.generateSrcFile("main.kt")
|
||||||
|
}
|
||||||
|
project.createRunner().withArguments('generateCMake').build()
|
||||||
|
|
||||||
|
def cMakeModule = new File(projectDirectory, "KotlinCMakeModule")
|
||||||
|
def cMakeLists = new File(projectDirectory, "CMakeLists.txt")
|
||||||
|
def expectedCMakeLists = """
|
||||||
|
cmake_minimum_required(VERSION 3.8)
|
||||||
|
|
||||||
|
set(CMAKE_MODULE_PATH \${CMAKE_CURRENT_LIST_DIR}/KotlinCMakeModule)
|
||||||
|
|
||||||
|
project(${projectDirectory.name} Kotlin)
|
||||||
|
|
||||||
|
cinterop(
|
||||||
|
NAME sdl
|
||||||
|
DEF_FILE src/main/c_interop/sdl.def
|
||||||
|
COMPILER_OPTS -I/usr/include/SDL2)
|
||||||
|
|
||||||
|
cinterop(
|
||||||
|
NAME stdio
|
||||||
|
DEF_FILE src/main/c_interop/stdio.def)
|
||||||
|
|
||||||
|
konanc_library(
|
||||||
|
NAME main_lib
|
||||||
|
SOURCES src/main/kotlin/main.kt)
|
||||||
|
|
||||||
|
konanc_executable(
|
||||||
|
NAME Main
|
||||||
|
SOURCES src/main/kotlin/main.kt
|
||||||
|
LIBRARIES stdio main_lib
|
||||||
|
LINKER_OPTS -L/usr/lib/x86_64-linux-gnu)
|
||||||
|
""".stripIndent().trim()
|
||||||
|
|
||||||
|
then:
|
||||||
|
cMakeModule.exists()
|
||||||
|
cMakeLists.exists()
|
||||||
|
|
||||||
|
def actualCMakeLists = cMakeLists.text.trim()
|
||||||
|
actualCMakeLists == expectedCMakeLists
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user