Here is my gradle.
plugins {
// ...
id "com.google.protobuf" version "0.8.12"
}
dependencies {
// DataStore
implementation "androidx.datastore:datastore-core:1.0.0"
// Architectural Components
implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.3.1"
// Coroutines
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.5.0'
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.4.1'
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-play-services:1.4.0'
// Coroutine Lifecycle Scopes
implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.3.1"
implementation "androidx.lifecycle:lifecycle-runtime-ktx:2.3.1"
implementation "androidx.lifecycle:lifecycle-livedata-ktx:2.3.1"
// ...
}
protobuf {
protoc {
artifact = "com.google.protobuf:protoc:3.10.0"
}
// Generates the java Protobuf-lite code for the Protobufs in this project. See
// https://github.com/google/protobuf-gradle-plugin#customizing-protobuf-compilation
// for more information.
generateProtoTasks {
all().each { task ->
task.builtins {
java {
option 'lite'
}
}
}
}
}
I make the proto folder to under src/main.
And then, create proto file to src/main/proto,
It show the [Register New File Type Association] like this.
If there's anything I can add, please let me know.
It was my mistake. I just install proto plugin to android studio.
Related
I'm trying to build convention plugins for a common configuration, e.g. ktlint. They are stored under build-configuration/plugin/convention.
class KtlintConventionPlugin : Plugin<Project> {
override fun apply(target: Project) {
return with(target) {
pluginManager.apply(deps.plugins.ktlint.get().pluginId)
extensions.configure<KtlintExtension> {
// ...
}
}
}
}
build-configuration/plugin/convention/build.gradle.kts
plugins {
`kotlin-dsl`
}
group = "com.example"
dependencies {
compileOnly(deps.kotlin.jvm.gradle.plugin)
compileOnly(deps.ktor.gradle.plugin)
compileOnly(deps.ktlint.gradle.plugin)
compileOnly(files(deps.javaClass.superclass.protectionDomain.codeSource.location))
}
gradlePlugin {
plugins {
register("ktlint-plugin") {
id = "ktlint-plugin"
implementationClass = "KtlintConventionPlugin"
}
}
}
I also have an extension function to get dependencies defined in TOML file (stored in gradle/deps.versions.toml) in build-configuration/plugin/convention/src/main/kotlin/com/example/VersionCatalog.kt
import org.gradle.accessors.dm.LibrariesForDeps
import org.gradle.api.Project
import org.gradle.kotlin.dsl.the
internal val Project.deps: LibrariesForDeps
get() = the()
build-configuration/settings.gradle.kts
dependencyResolutionManagement {
repositories {
gradlePluginPortal()
mavenLocal()
mavenCentral()
}
versionCatalogs {
create("deps") {
from(files("../gradle/deps.versions.toml"))
}
}
}
rootProject.name = "build-configuration"
include(":plugin:convention")
When I include ktlint plugin in root build.gradle.kts, Gradle synchronization always fails.
An exception occurred applying plugin request [id: 'ktlint-plugin']
> Failed to apply plugin 'ktlint-plugin'.
> Type org.gradle.accessors.dm.LibrariesForDeps not present
I can see the class generated in .gradle/.../LibrariesForDeps, but under the project's root, not the plugin's one.
The whole build-configuration module is included in root settings.gradle.kts:
includeBuild("build-configuration")
Using the libs doesn't work in convention plugins, but there are some workarounds in the issue: https://github.com/gradle/gradle/issues/15383
But I don't think you need it. Instead the version can be defined in a single place: the included build's build.gradle.kts, which has access to the version catalog DSL.
define the Maven coordinates of the ktlint plugin in libs.versions.toml
[libraries]
gradlePlugin-ktlint = { module = "org.jlleitschuh.gradle:ktlint-gradle", version = "11.1.0" }
I prefer prefixing such dependencies with gradlePlugin to distinguish them from 'regular' project dependencies.
(The Maven coordinates are listed in the Gradle Plugin Portal, under the 'legacy' application as a classpath dependency)
Add a dependency on ktlint in the included build, build-configuration/build.gradle.kts
plugins {
`kotlin-dsl`
}
dependencies {
implementation(libs.deps.gradlePlugin.ktlint)
}
Now the ktlint plugin will be available on the classpath, and you can apply it as normal in a convention plugin, no version necessary.
In a precompiled script plugin:
// ./build-configuration/src/main/kotlin/my-ktlint-convention.gradle.kts
plugins {
id("org.jlleitschuh.gradle.ktlint") // version is provided by build.gradle.kts
}
Or in a traditional class plugin (which will require registering via gradlePlugins {}):
// ./build-configuration/src/main/kotlin/KtlintConventionPlugin.kt
class KtlintConventionPlugin : Plugin<Project> {
override fun apply(target: Project) {
target.apply(plugin = "org.jlleitschuh.gradle.ktlint")
target.extensions.configure<KtlintExtension> {
// ...
}
}
}
See also
For more information about buildSrc convention plugins, these answers are related:
https://stackoverflow.com/a/71562588/4161471
https://stackoverflow.com/a/71892685/4161471
I have created a new project and followed this approach. There is only one difference. I had to have the block below in both settings.gradle.kts files, root, and build-configuration:
dependencyResolutionManagement {
versionCatalogs {
create("deps") {
from(files("../gradle/deps.versions.toml"))
}
}
}
It just doesn't work for me without this duplication.
Also, I'm not using any module within the build-configuration plugin.
Our main task is to make a GUI application on Windows (and preferably on Mac too) so it would be impossible/extremely difficult to find out the source code (Kotlin). Question is = how to do it?
Ideally, I would like to know:
.1. Tools to get the source code from our executable/files executable depends on.
.2. Tools for code obfuscation to the level where the tools of the previous point won't work.
.3. Next section is about what I did in Compose Desktop, but I do not limit myself to it. If you, for example, know how to make a working project with encrypted Kotlin code in JavaFx or something else, please let me know.
What has been done so far:
In Compose Desktop generated a .msi file, which on Windows creates files, and among them there are .jar files.
I opened one of the .jar in here and there was it = my beautiful source code, although in Java, but even the variables were not renamed!
Next I changed build.gradle.kts according to template
Important note = I do not understand this template. Perhaps I did something wrong.
I'll added the code, take a look.
But at least .msi got built and it installed the rest as previously. And again the same story = I open the .jar and see the source code in Java with variables not renamed!
But again = not even sure if this template is supposed to make the code in .jar unreadable.
Note = never done/learned custom obfuscation before. I work mainly with Kotlin and Android Studio. For Compose Desktop installed IntelliJ Idea.
Code:
build.gradle.kts
import org.jetbrains.compose.compose
import org.jetbrains.compose.desktop.application.dsl.TargetFormat
buildscript {
dependencies {
classpath("com.guardsquare:proguard-gradle:7.2.1")
}
}
repositories {
google()
mavenCentral()
maven("https://maven.pkg.jetbrains.space/public/p/compose/dev")
}
plugins {
kotlin("jvm") version "1.6.10"
id("org.jetbrains.compose") version "1.1.1"
}
dependencies {
implementation(compose.desktop.currentOs)
}
val obfuscate by tasks.registering(proguard.gradle.ProGuardTask::class)
fun mapObfuscatedJarFile(file: File) =
File("${project.buildDir}/tmp/obfuscated/${file.nameWithoutExtension}.min.jar")
compose.desktop {
application {
mainClass = "MainKt"
nativeDistributions {
targetFormats(TargetFormat.Exe, TargetFormat.Msi, TargetFormat.Deb)
packageName = "untitled_04"
packageVersion = "1.0.0"
}
}
}
obfuscate.configure {
dependsOn(tasks.jar.get())
val allJars = tasks.jar.get().outputs.files + sourceSets.main.get().runtimeClasspath.filter { it.path.endsWith(".jar") }
.filterNot { it.name.startsWith("skiko-awt-") && !it.name.startsWith("skiko-awt-runtime-") } // walkaround https://github.com/JetBrains/compose-jb/issues/1971
for (file in allJars) {
injars(file)
outjars(mapObfuscatedJarFile(file))
}
libraryjars("${compose.desktop.application.javaHome ?: System.getProperty("java.home")}/jmods")
configuration("proguard-rules.pro")
}
proguard-rules.pro
-keepclasseswithmembers public class MainKt {
public static void main(java.lang.String[]);
}
-dontwarn kotlinx.coroutines.debug.*
-keep class kotlin.** { *; }
-keep class kotlinx.coroutines.** { *; }
-keep class org.jetbrains.skia.** { *; }
-keep class org.jetbrains.skiko.** { *; }
-assumenosideeffects public class androidx.compose.runtime.ComposerKt {
void sourceInformation(androidx.compose.runtime.Composer,java.lang.String);
void sourceInformationMarkerStart(androidx.compose.runtime.Composer,int,java.lang.String);
void sourceInformationMarkerEnd(androidx.compose.runtime.Composer);
}
I am new to gradle. I am working on a kotlin library that requires JavaFX. I wanted to use gradle to manage my dependencies and make it easier to include my library in a new project.
My library project applies and configures the javafx plugin and its build file looks like this (kotlin dsl):
plugins {
`java-library`
id("org.openjfx.javafxplugin")
}
group = "me.shai"
version = "1.0"
javafx {
version = "15.0.1"
modules = listOf("javafx.controls", "javafx.fxml")
}
dependencies {
// Other dependencies
testImplementation(kotlin("test-junit5"))
testImplementation("org.junit.jupiter:junit-jupiter-api:5.6.0")
testRuntimeOnly("org.junit.jupiter:junit-jupiter-engine:5.6.0")
}
tasks.test {
useJUnitPlatform()
}
kotlin {
explicitApi()
}
Apparently, a project that wants to use my library also has to apply and configure JavaFX. Here's an example for a build file of a demo project that consumes my library:
plugins {
id("org.openjfx.javafxplugin")
}
group = "me.shai"
version = "1.0"
javafx {
version = "15.0.1"
modules = listOf("javafx.controls", "javafx.fxml")
}
dependencies {
implementation(project(":MyLib")) // Pretend the library is published so we use a url instead of local project
}
This is slightly annoying, so I decided to do something similar to JavaFX: write a custom plugin to include my project. The plugin needs to:
Add my library as a dependency
Apply the JavaFX plugin
Configure the JavaFX plugin
I managed to achieve steps 1 and 2, but I am stuck at step 3. How can I configure the JavaFX plugin from a custom plugin kotlin class?
Here's what I have so far:
package mylib.gradle
import org.gradle.api.Plugin
import org.gradle.api.Project
import org.gradle.api.artifacts.DependencyResolutionListener
import org.gradle.api.artifacts.ResolvableDependencies
import org.gradle.kotlin.dsl.project
class MyLibPlugin : Plugin<Project> {
override fun apply(project: Project) {
// Apply the javafx plugin
project.plugins.apply("org.openjfx.javafxplugin")
// How to configure javafx here?
val implementationDeps = project.configurations.getByName("implementation").dependencies
project.gradle.addListener(object : DependencyResolutionListener {
override fun beforeResolve(dependencies: ResolvableDependencies) {
// Add dependency on my library project.
implementationDeps.add(project.dependencies.project(":MyLib"))
project.gradle.removeListener(this)
}
override fun afterResolve(dependencies: ResolvableDependencies) {}
})
}
}
I am basically trying to write the equivalent of the build script block:
javafx {
version = "15.0.1"
modules = listOf("javafx.controls", "javafx.fxml")
}
And I can't figure out how to achieve this. I'd appreciate any help on the subject.
You would configure the javafx extension just as you would in the build file:
// build.gradle[.kts]
dependencies {
implementation("org.openjfx:javafx-plugin:0.0.10")
}
And the plugin implementation:
import org.gradle.api.Plugin
import org.gradle.api.Project
import org.gradle.api.plugins.JavaPlugin
import org.openjfx.gradle.JavaFXOptions
open class MyLibPlugin : Plugin<Project> {
override fun apply(project: Project) {
project.pluginManager.apply("org.openjfx.javafxplugin")
val myLibDependency = project.dependencies.project(mapOf("path" to ":MyLib"))
project.dependencies.add(JavaPlugin.IMPLEMENTATION_CONFIGURATION_NAME, myLibDependency)
project.extensions.configure(JavaFXOptions::class.java) {
it.version = "15.0.1"
it.modules = listOf("javafx.controls", "javafx.fxml")
}
}
}
I am trying to make a universal framework for iOS in KMP.
Here is my module build.gradle file
import org.jetbrains.kotlin.gradle.tasks.FatFrameworkTask
buildscript {
ext.serialization_version = "0.20.0"
repositories {
mavenCentral()
jcenter()
maven { url "https://dl.bintray.com/jetbrains/kotlin-native-dependencies" }
}
}
repositories {
mavenCentral()
maven { url "https://kotlin.bintray.com/kotlinx" }
}
apply plugin: 'kotlin-multiplatform'
apply plugin: 'kotlinx-serialization'
def serialization_version = "0.20.0"
kotlin{
targets {
fromPreset(presets.jvm, 'android')
iosArm32("ios32")
iosArm64("ios64")
iosX64("simulator")
configure([ios32, ios64, simulator]) {
binaries.framework('Shared')
}
}
//we have 3 different sourceSets for common, android and iOS.
//each sourceSet can have their own set of dependencies and configurations
sourceSets {
commonMain.dependencies {
api 'org.jetbrains.kotlin:kotlin-stdlib-common'
implementation "org.jetbrains.kotlinx:kotlinx-serialization-runtime-common:$serialization_version"
}
androidMain.dependencies {
api 'org.jetbrains.kotlin:kotlin-stdlib'
implementation "org.jetbrains.kotlinx:kotlinx-serialization-runtime:$serialization_version"
}
iosMain {
dependencies {
implementation("org.jetbrains.kotlinx:kotlinx-serialization-runtime-native:$serialization_version")
}
}
ios32.dependencies {
implementation("org.jetbrains.kotlinx:kotlinx-serialization-runtime-native:$serialization_version")
}
ios64.dependencies {
implementation("org.jetbrains.kotlinx:kotlinx-serialization-runtime-native:$serialization_version")
}
simulator.dependencies {
implementation("org.jetbrains.kotlinx:kotlinx-serialization-runtime-native:$serialization_version")
}
}
task fatFramework(type: FatFrameworkTask) {
// the fat framework must have the same base name as the initial frameworks
baseName = "Shared"
final File frameworkDir = new File(buildDir, "xcode-frameworks")
destinationDir = frameworkDir
// specify the frameworks to be merged
from(
targets.ios32.binaries.getFramework('Shared', 'RELEASE'),
targets.ios64.binaries.getFramework('Shared', 'RELEASE'),
targets.simulator.binaries.getFramework('Shared', 'RELEASE')
)
doLast {
new File(frameworkDir, 'gradlew').with {
text = "#!/bin/bash\nexport 'JAVA_HOME=${System.getProperty("java.home")}'\ncd '${rootProject.rootDir}'\n./gradlew \$#\n"
setExecutable(true)
}
}
}
}
configurations {
compileClasspath
}
tasks.build.dependsOn fatFramework
When I try to build my Module it gives me this error
Execution failed for task ':Shared:linkSharedReleaseFrameworkIos32'.
> Resolving configuration 'ios32Api' directly is not allowed
Am I missing something in my configuration?
I was unable to reproduce the error as the question features only part of the project. So, while modifying it to make things work as a separate project rather than a module, I accidentally lost the original problem. But here are my thoughts on the possible cause.
This snippet seems to be missing the difference between source sets and targets. I mean, as there are three named targets ios32, ios64, simulator, the kotlin-multiplatform plugin creates six default source sets: ios32Main, ios64Main, simulatorMain, ios32Test, ios64Test, simulatorTest. But in this code, I see new source sets named ios32 etc. being created instead of setting defaults' dependencies. This can be a problem, as there are no explicit connections between those source sets and declared targets.
For jvm i can use:
plugins {
kotlin("jvm") version "1.2.60"
}
I have found no equivanent string for "jvm" for use with javascript and am using the following:
plugins {
id("kotlin2js") version "1.2.60"
}
So the questions.
Is there an equivalent string to "jvm" to for javascript or some other more direct equivalent to the 'kotlin("jvm")'?
So the answer is taken as "not yet" - and no current plan for that to change either. So stick with the id().
It doesn't work since plugin for JS isn't published yet on Gradle Plugins Portal. Feel free to vote for the issue.
As a workaround, you can add to your settings.gradle:
pluginManagement {
resolutionStrategy {
eachPlugin {
if (requested.id.id == "kotlin2js") {
useModule("org.jetbrains.kotlin:kotlin-gradle-plugin:${requested.version}")
}
}
}
}
And then in your build.gradle.kts files you can write like
plugins {
id("kotlin2js") version "1.3.10"
}
repositories {
mavenCentral()
}
dependencies {
implementation(kotlin("stdlib-js"))
}