JAVAFX environmental variable return null in build.gradle.kts - gradle

I am using following build.gradle.kts for JavaFX app
plugins {
kotlin("jvm") version "1.4.30"
id("application")
id("org.openjfx.javafxplugin") version "0.0.9"
}
repositories {
mavenCentral()
}
javafx {
version = "11"
modules("javafx.controls", "javafx.fxml")
sdk = System.getenv("JAVAFX")
if (sdk == null || sdk2.isBlank()) {
throw InvalidUserDataException("JAVAFX environment variable is not set. JAVAFX = $sdk")
}
application {
mainClass.set("example.Main")
applicationName = "Main"
applicationDefaultJvmArgs = listOf(
"--module-path=${sdk}${File.separator}lib",
"--add-modules=javafx.controls,javafx.fxml" )
println("applicationDefaultJvmArgs:$applicationDefaultJvmArgs")
}
}
dependencies {
implementation(kotlin("stdlib"))
}
I have set environmental variable in .bashrc like below
export JAVAFX=$HOME/path/to/JavaFX/SDK
when I execute echo $JAVAFX I get the JavaFX SDK path but still I am getting null in build.gradle.kts
Tried restarting IntelliJ idea too, still the same.

Out-of-the-box, Gradle will spawn a Java process in the background. Typically this is the Gradle Daemon, but there may be more.
So to ensure new environment variables are seen, it's best to kill any Java process that are running in the background. Depending on your system, open up task manager and kill and lingering Java process.

Related

Can Gradle produce multiple Kotlin Native binaries (for one OS)?

Can I convince Gradle to produce multiple binaries? I have several Kotlin packages with files that have a proper "fun main(...)" but the default IntelliJ build.gradle file only allows me to specifiy one "compilations.main.entryPoint".
I could put the main functions into Kotlin classes or objects if that would help.
Changing the entryPoint argument to an array did not work :)
If it's not currently possible, is it a general limitation of Gradle or only of the "kotlin-multiplatform" plugin?
plugins {
id 'kotlin-multiplatform' version '1.3.11'
}
repositories {
mavenCentral()
}
kotlin {
targets {
// For ARM, preset should be changed to presets.iosArm32 or presets.iosArm64
// For Linux, preset should be changed to e.g. presets.linuxX64
// For MacOS, preset should be changed to e.g. presets.macosX64
fromPreset(presets.mingwX64, 'mingw')
configure([mingw]) {
// Comment to generate Kotlin/Native library (KLIB) instead of executable file:
compilations.main.outputKinds('executable')
// Change to specify fully qualified name of your application's entry point:
compilations.main.entryPoint = 'hello.main'
}
}
sourceSets {
// Note: To enable common source sets please comment out 'kotlin.import.noCommonSourceSets' property
// in gradle.properties file and re-import your project in IDE.
mingwMain {
}
mingwTest {
}
}
}
task runProgram {
def buildType = 'debug' // 'release' - Change to 'debug' to run application with debug symbols.
dependsOn "link${buildType.capitalize()}ExecutableMingw"
doLast {
def programFile = kotlin.targets.mingw.compilations.main.getBinary('EXECUTABLE', buildType)
exec {
executable programFile
args ''
}
}
}
In https://github.com/JetBrains/kotlin-native/issues/2505 I've just got the answer that this will be possible with Kotlin Native 1.3.20!

How do I create distributions with different dependencies using Gradle application/distribution plugin?

I am building a small Kotlin project in IntelliJ, Idea, and trying to figure out how to create multiple tar/zip files with customizations for each OS I want to support.
It seems like the distribution plugin (which is included when you use the application plugin) is the right direction, but I can't seem to figure out how to get it to do what I want.
I have read the documentation on the plugin, which can be found here, but it's not really clear to me how to accomplish what I want to do.
Here is an example build.gradle that shows at least the idea of what I want to do, that is to have a base application setup and then have some minor tailoring for each of the 3 OSs.
For example each of the 3 OSs need a unique version of the SWT library. The macos version needs a specific JVM setting, and for the linux version, I need to tailor the startup script to add some environment variables.
Is this possible with the distribution plugin? If not can someone suggest a different solution?
plugins {
id 'org.jetbrains.kotlin.jvm' version '1.2.61'
}
apply plugin: 'application'
mainClassName = "MainKt"
version '1.0-SNAPSHOT'
repositories {
// my common required repos
}
dependencies {
// my common dependencies
}
distributions {
macos {
contents { from 'src' }
applicationDefaultJvmArgs.push("-XstartOnFirstThread")
dependencies {
implementation "org.eclipse.swt:org.eclipse.swt.cocoa.macosx.x86_64:4.5.2"
}
}
linux {
contents { from 'src' }
dependencies {
implementation "org.eclipse.swt:org.eclipse.swt.gtk.linux.x86_64:4.5.2"
}
startScripts.doLast {
def lines = unixScript.text.readLines()
println lines.add(1, '# add some stuff')
println lines.add(2, '# add some more stuff')
unixScript.text = lines.join("\n")
}
}
windows {
contents { from 'src' }
dependencies {
implementation "org.eclipse.swt:org.eclipse.swt.win32.win32.x86_64:4.5.2"
}
}
}
compileKotlin {
kotlinOptions.jvmTarget = "1.8"
}
compileTestKotlin {
kotlinOptions.jvmTarget = "1.8"
}
Update
This is what I am doing now, but I would like to improve on this.
I have a variable
def deploy = false
if (!deploy) {
applicationDefaultJvmArgs.push("-XstartOnFirstThread")
dependencies {
implementation "org.eclipse.swt:org.eclipse.swt.cocoa.macosx.x86_64:4.5.2"
}
} else {
dependencies {
implementation "org.eclipse.swt:org.eclipse.swt.gtk.linux.x86_64:4.5.2"
}
startScripts.doLast {
def lines = unixScript.text.readLines()
println lines.add(1, 'export foo=foo')
println lines.add(2, 'export bar=bar')
}
}
Right now I develop on my mac and set deploy to false. When I want to generate the distribution for linux I set deploy to true. I could add more code and do the same thing for windows, but I would like to just generate all the code in one task, and have it in different tar/zip files.
Opal provided some very good suggestions in the question comments that I tried, but in the end, I was not able to really get what I wanted.
Here is my current workaround solution it does pretty much what I was hoping I could have done with the distribution plugin.
Basically I create an osType property and set it's "default" to the os I am developing on, in this case macos. Then I have all my common dependencies in one dependency closure and add in the the os specific stuff in a groovy switch statement. I then just coded up a short shell script that overrides the osType property to each of the os's I want to support and calls the gradle task to build each in turn.
Here is my build.gradle file.
plugins {
id 'org.jetbrains.kotlin.jvm' version '1.2.61'
id 'application'
}
ext {
swtVersion = "4.5.2"
}
ext.osType = project.properties['osType'] ?: 'macos'
println "building for ${osType}"
mainClassName = "MainKt"
repositories {
mavenCentral()
maven { url "http://maven-eclipse.github.io/maven" }
}
dependencies {
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8"
}
switch(osType) {
case 'macos':
dependencies {
implementation "org.eclipse.swt:org.eclipse.swt.cocoa.macosx.x86_64:${swtVersion}"
}
applicationDefaultJvmArgs.push("-XstartOnFirstThread")
break
case 'linux':
dependencies {
implementation "org.eclipse.swt:org.eclipse.swt.gtk.linux.x86_64:${swtVersion}"
}
startScripts.doLast {
def lines = unixScript.text.readLines()
println lines.add(1, 'export FOO=foo')
println lines.add(2, 'export BAR=bar')
unixScript.text = lines.join("\n")
}
break
case 'windows':
dependencies {
implementation "org.eclipse.swt:org.eclipse.swt.win32.win32.x86_64:${swtVersion}"
}
}
version "${osType}-1.0-SNAPSHOT"
compileKotlin {
kotlinOptions.jvmTarget = "1.8"
}
compileTestKotlin {
kotlinOptions.jvmTarget = "1.8"
and here is my shell script (buildAll.sh) that I run from the terminal in Idea.
#!/bin/sh
./gradlew -PosType=macos distTar
./gradlew -PosType=linux distTar
./gradlew -PosType=windows distTar
./gradlew -PosType=windows distZip

NoClassDefFoundError: java.sql.Date when running Play 2.6 using gradle plugin

Has anyone had much luck with the play gradle plugin? I'm trying to run the Play Framework 2.6 starter project. I can run from SBT fine but I get the following error when I run from gradle:
play.api.UnexpectedException: Unexpected exception[NoClassDefFoundError: java/sql/Date]
at play.core.server.DevServerStart$$anon$1.reload(DevServerStart.scala:190)
at play.core.server.DevServerStart$$anon$1.get(DevServerStart.scala:124)
at play.core.server.AkkaHttpServer.handleRequest(AkkaHttpServer.scala:202)
at play.core.server.AkkaHttpServer.$anonfun$createServerBinding$1(AkkaHttpServer.scala:117)
at akka.stream.impl.fusing.MapAsync$$anon$25.onPush(Ops.scala:1194)
at akka.stream.impl.fusing.GraphInterpreter.processPush(GraphInterpreter.scala:519)
at akka.stream.impl.fusing.GraphInterpreter.processEvent(GraphInterpreter.scala:482)
at akka.stream.impl.fusing.GraphInterpreter.execute(GraphInterpreter.scala:378)
at akka.stream.impl.fusing.GraphInterpreterShell.runBatch(ActorGraphInterpreter.scala:
I'm using Java 1.8 with the following build.gradle:
plugins {
id 'play'
id 'idea'
}
def playVersion = "2.6.13"
def scalaVersion = System.getProperty("scala.binary.version", /* default = */ "2.12")
model {
components {
play {
platform play: playVersion, scala: scalaVersion, java: '1.8'
injectedRoutesGenerator = true
sources {
twirlTemplates {
defaultImports = TwirlImports.JAVA
}
}
}
}
}
dependencies {
play "com.typesafe.play:play-guice_$scalaVersion:$playVersion"
play "com.typesafe.play:play-logback_$scalaVersion:$playVersion"
play "com.h2database:h2:1.4.196"
playTest "org.assertj:assertj-core:3.6.2"
playTest "org.awaitility:awaitility:2.0.0"
}
repositories {
jcenter()
maven {
name "lightbend-maven-releases"
url "https://repo.lightbend.com/lightbend/maven-release"
}
ivy {
name "lightbend-ivy-release"
url "https://repo.lightbend.com/lightbend/ivy-releases"
layout "ivy"
}
}
You need to set up the java_home to use a Java 1.8 version. Apparently, the play gradle plugin expects a java home.
export JAVA_HOME=YOUR_JAVA_LOCATION
$ source .bash_profile
$ echo $JAVA_HOME
I found out the issue, my $JAVA_HOME was set to my Java 9 path but java/javac were set to Java 8. This was causing my gradle to use the wrong java version. After fixing my $JAVA_HOME, it works correctly.
I'll leave this up in case anyone else runs into this issue.

How to set Eclipse's output directory from Gradle

I am using Gradle's eclipse plugin. For cross-project reference reasons, I need Eclipse's output directory to not be the default bin, rather ecbuild.
Everytime I run ./gradlew eclipse, it overwrites this output directory setting.
How to make sure it doesn't, or how to set it within gradle build script ?
Add this to the build.gradle script:
eclipse {
classpath { defaultOutputDir = file('ecbuild') }
}
This might require you to upgrade the version of your gradle wrapper.
If so, run :
./gradlew wrapper --gradle-version 3.3
In my case, seting defaultOutputDir was not enough. So I did the following:
eclipse {
classpath {
defaultOutputDir = file("build")
file.whenMerged {
entries.each { entry ->
if (entry.kind == 'src' && entry.hasProperty('output')) {
entry.output = entry.output.replace('bin/', "build/")
}
}
}
}
}

Gradle dependency management based on build variant for java project

I am using gradle to build a java spring project. What I am trying to do is:
If build target is dev or not specified, use dependency
compile("org.hsqldb:hsqldb")
If build target is prod or qa, use dependency
compile("mysql:mysql-connector-java:5.1.31")
I am not sure how to do this in gradle. First thing is how to pass the build type variable to the build script. The second thing is how to write the conditional dependency code based on the variable? Thanks in advance.
build.gradle is a Groovy file, so you can use if statements to dynamically change your dependencies, like this:
dependencies {
// other dependencies
if (someFlag) {
compile("org.hsqldb:hsqldb")
} else {
compile("mysql:mysql-connector-java:5.1.31")
}
}
To configure something like this one may use project properties:
dependencies {
// other dependencies
if (!project.hasProperty("targetEnv") || targetEnv == "dev") {
compile("org.hsqldb:hsqldb")
} else if (targetEnv == "prod" || targetEnv == "qa") {
compile("mysql:mysql-connector-java:5.1.31")
} else {
throw new InvalidUserDataException("Unknown target environment '$targetEnv'")
}
}
And now mysql dependency will be used when gradle is run with -PtargetEnv=qa or -PtargetEnv=prod, hsqldb — for cases when targetEnv is not specified or set to dev, and finally exception will be thrown if some unknown environment name is passed.

Resources