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 {
|
||||
internal const val ARTIFACTS_CONTAINER_NAME = "konanArtifacts"
|
||||
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 KONAN_EXTENSION_NAME = "konan"
|
||||
@@ -260,6 +261,7 @@ class KonanPlugin @Inject constructor(private val registry: ToolingModelBuilderR
|
||||
project.plugins.apply("base")
|
||||
// Create necessary tasks and extensions.
|
||||
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(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