Gradle doesn't emit kotlin.js - gradle

I'm trying to compile my Kotlin app and set of Kotlin libraries to JavaScript. I've got that working well, but when I try to run it it can't find kotlin.js.
So what's going on here? When I compile using IDEA (instead of Gradle), it outputs kotlin.js just fine. I tried making my build script more like an example I found, but that wouldn't compile...
Here's a link to the code and project in question: https://github.com/BlueHuskyStudios/Decision-Cruncher/blob/SO/q/53582651/1/build.gradle

This only worked for me. unzip for some reason was no working
task assembleWeb() {
configurations.implementation.setCanBeResolved(true)
configurations.implementation.each { File file ->
if (file.path.indexOf('kotlin-stdlib-js') >= 0) {
exec {
workingDir "$projectDir/web"
standardOutput = new ByteArrayOutputStream()
commandLine "7z", "e", file.absolutePath, "kotlin.js", "-aos", "-r"
}
}
}
dependsOn classes
}
assemble.dependsOn assembleWeb
Be aware of "-aos" param. This flag will prevent from overwriting of existing file

Here you can find the code snippet to extract all .js files from Kotlin/JS libraries:
task assembleWeb(type: Sync) {
configurations.compile.each { File file ->
from(zipTree(file.absolutePath), {
includeEmptyDirs = false
include { fileTreeElement ->
def path = fileTreeElement.path
path.endsWith(".js") && (path.startsWith("META-INF/resources/") ||
!path.startsWith("META-INF/"))
}
})
}
from compileKotlin2Js.destinationDir
into "${projectDir}/web"
dependsOn classes
}
assemble.dependsOn assembleWeb

For any others struggling in the future, I've had the following issue:
IntelliJ Kotlin/JS starter project has been generated with this in the gradle file:
implementation "org.jetbrains.kotlin:kotlin-stdlib-js"
which needs to be this to get the kotlin.js file
compile "org.jetbrains.kotlin:kotlin-stdlib-js"

Related

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/")
}
}
}
}
}

How to run JBoss TattleTale from inside Gradle build

I am in love with JBoss TattleTale. Typically, in my Ant builds, I follow the docs to define the Tattletale tasks and then run them like so:
<taskdef name="report"
classname="org.jboss.tattletale.ant.ReportTask"
classpathref="tattletale.lib.path.id"/>
...
<tattletale:report source="${src.dir]" destination="${dest.dir}"/>
I am now converting my builds over to Gradle and am struggling to figure out how to get Tattletale running in Gradle. There doesn't appear to be a Gradle-Tattletale plugin, and I'm not experienced enough with Gradle to contribute one. But I also know that Gradle can run any Ant plugin and can also executing stuff from the system shell; I'm just not sure how to do this in Gradle because there aren't any docs on this (yet).
So I ask: How do I run the Tattletale ReportTask from inside a Gradle build?
Update
Here is what the Gradle/Ant docs show as an example:
task loadfile << {
def files = file('../antLoadfileResources').listFiles().sort()
files.each { File file ->
if (file.isFile()) {
ant.loadfile(srcFile: file, property: file.name)
println " *** $file.name ***"
println "${ant.properties[file.name]}"
}
}
}
However, no where in here do I see how/where to customize this for Tattletale and its ReportTask.
The following is adapted from https://github.com/roguePanda/tycho-gen/blob/master/build.gradle
It bypasses ant and directly invokes the Tattletale Java class.
It was changed to process a WAR, and mandates a newer javassist in order to handle Java 8 features such as lambdas.
configurations {
tattletale
}
configurations.tattletale {
resolutionStrategy {
force 'org.javassist:javassist:3.20.0-GA'
}
}
dependencies {
// other dependencies here...
tattletale "org.jboss.tattletale:tattletale:1.2.0.Beta2"
}
task createTattletaleProperties {
ext.props = [reports:"*", enableDot:"true"]
ext.destFile = new File(buildDir, "tattletale.properties")
inputs.properties props
outputs.file destFile
doLast {
def properties = new Properties()
properties.putAll(props)
destFile.withOutputStream { os ->
properties.store(os, null)
}
}
}
task tattletale(type: JavaExec, dependsOn: [createTattletaleProperties, war]) {
ext.outputDir = new File(buildDir, "reports/tattletale")
outputs.dir outputDir
inputs.files configurations.runtime.files
inputs.file war.archivePath
doFirst {
outputDir.mkdirs()
}
main = "org.jboss.tattletale.Main"
classpath = configurations.tattletale
systemProperties "jboss-tattletale.properties": createTattletaleProperties.destFile
args([configurations.runtime.files, war.archivePath].flatten().join("#"))
args outputDir
}
The previous answers either are incomplete or excessively complicated. What I did was use the ant task from gradle which works fine. Let's assume your tattletale jars are beneath rootDir/tools/...
ant.taskdef(name: "tattleTaleTask", classname: "org.jboss.tattletale.ant.ReportTask", classpath: "${rootDir}/tools/tattletale-1.1.2.Final/tattletale-ant.jar:${rootDir}/tools/tattletale-1.1.2.Final/tattletale.jar:${rootDir}/tools/tattletale-1.1.2.Final/javassist.jar")
sources = "./src:./src2:./etcetera"
ant.tattleTaleTask(
source: sources,
destination: "tattleTaleReport",
classloader: "org.jboss.tattletale.reporting.classloader.NoopClassLoaderStructure",
profiles: "java5, java6",
reports: "*",
excludes: "notthisjar.jar,notthisjareither.jar,etcetera.jar"
){
}
So the above code will generate the report beneath ./tattleTaleReport. It's that simple. The annoyance is that the source variable only accepts directories so if there are jars present in those directories you do not wish to scan you need to add them to the excludes parameter.

How to add gradle generated source folder to Eclipse project?

My gradle project generates some java code inside gen/main/java using annotation processor. When I import this project into Eclipse, Eclipse will not automatically add gen/main/java as source folder to buildpath. I can do it manually. But is there a way to automate this?
Thanks.
You can easily add the generated folder manually to the classpath by
eclipse {
classpath {
file.whenMerged { cp ->
cp.entries.add( new org.gradle.plugins.ide.eclipse.model.SourceFolder('gen/main/java', null) )
}
}
}
whereby null as a second constructor arg means that Eclipse should put the compiled "class" files within the default output folder. If you want to change this, just provide a String instead, e.g. 'bin-gen'.
I think it's a little bit cleaner just to add a second source directory to the main source set.
Add this to your build.gradle:
sourceSets {
main {
java {
srcDirs += ["src/gen/java"]
}
}
}
This results in the following line generated in your .classpath:
<classpathentry kind="src" path="src/gen/java"/>
I've tested this with Gradle 4.1, but I suspect it'd work with older versions as well.
Andreas' answer works if you generate Eclipse project from command line using gradle cleanEclipse eclipse. If you use STS Eclipse Gradle plugin, then you have to implement afterEclipseImport task. Below is my full working snippet:
project.ext {
genSrcDir = projectDir.absolutePath + '/gen/main/java'
}
compileJava {
options.compilerArgs += ['-s', project.genSrcDir]
}
compileJava.doFirst {
task createGenDir << {
ant.mkdir(dir: project.genSrcDir)
}
createGenDir.execute()
println 'createGenDir DONE'
}
eclipse.classpath.file.whenMerged {
classpath - >
def genSrc = new org.gradle.plugins.ide.eclipse.model.SourceFolder('gen/main/java', null)
classpath.entries.add(genSrc)
}
task afterEclipseImport(description: "Post processing after project generation", group: "IDE") {
doLast {
compileJava.execute()
def classpath = new XmlParser().parse(file(".classpath"))
new Node(classpath, "classpathentry", [kind: 'src', path: 'gen/main/java']);
def writer = new FileWriter(file(".classpath"))
def printer = new XmlNodePrinter(new PrintWriter(writer))
printer.setPreserveWhitespace(true)
printer.print(classpath)
}
}

How can I access the source artifacts of my gradle compile dependencies?

I have written the following task, which extracts all the compile dependencies for each of my sub-projects and puts them in a per sub-project directory:
task exportCompileLibs << {
subprojects.each { iSubProject ->
iSubProject.configurations.findAll{it.name == "compile"}.each{ jConfig ->
println "copying compile libs for ${iSubProject.name}..."
copy {
into "${iSubProject.buildDir}/gradle-lib-export"
from jConfig
eachFile {println it.name}
}
}
}
}
I'd like to extend this to also export the source artifacts that Gradle does already know about (I can see the source jars in the cache directory), I just can't figure out how to use the object model to get a handle to them.
The IDEA and Eclipse plugins seem to be able to do this (they point the project files they build directly into the gradle cache), but I can't figure out how to do it - and looking at the IDE plugin source code, it looks... tricky. I'm hoping there's something obvious that I'm missing in the gradle DSL or API.
Anyone got any ideas?
For anyone looking for at least an interim solution to this, the following seems to be doing pretty much exactly what I want at the moment.
You have to apply the IDEA plugin to the build.gradle file for each project you want to export the dependencies for:
apply plugin: 'idea'
And then define this task:
task exportDependencies << {
def deps = project.extensions.getByType(IdeaModel).module.resolveDependencies()
copy {
from deps*.classes.file
into "${buildDir}/gradle-lib-export/libs"
}
copy {
from deps*.sources.file
into "${buildDir}/gradle-lib-export/sources"
}
}
And here's my horrific hack so I don't have to apply the plugin for each sub-project:
task exportDependencies(description: "export project dependency jars") << {
subprojects.each { Project iSubProject ->
String target = "${iSubProject.buildDir}/gradle-lib-export"
IdeaPlugin ideaPlugin = new IdeaPlugin()
ideaPlugin.apply(iSubProject)
Set<Dependency> deps = ideaPlugin.model.module.resolveDependencies()
println "exporting dependencies for $iSubProject.name into $target"
copy {
from deps*.classes.file
into "${target}/libs"
eachFile { println "lib -> $it.name" }
}
copy {
from deps*.sources.file
into "${target}/sources"
eachFile{ println "source -> $it.name" }
}
}
}
+10 points for not cluttering my build task list with stuff I don't want, -several million points for ewwwww.
There isn't currently a simpler way than what the IDE plugins are doing. This will hopefully change in the future.

Add source file extension in gradle

I am trying to tell gradle that files with the *.dsl extension should be compiled as groovy files, so I have added a source set with the inclusion pattern and changed the compile task includes property:
sourceSets {
...
dsl_scripts {
groovy {
include '**/*.dsl'
}
}
}
compileDsl_scriptsGroovy.includes = ['**/*.dsl']
But when I run the build under a debug mode it skips all *.dsl files with the following message:
Skipping task ':compileDsl_scriptsGroovy' as it has no source files
The following line successfully outputs all the files I try to compile:
println sourceSets.dsl_scripts.allSource.matching({include '**/*.dsl'}).getFiles()
What do I do wrong?
EDIT:
I found the following snippet in gradle sources:
FileCollection groovyJavaOnly = spec.getSource().filter(new Spec<File>() {
public boolean isSatisfiedBy(File element) {
return element.getName().endsWith(".groovy") || element.getName().endsWith(".java");
}
});
spec.setSource(new SimpleFileCollection(groovyJavaOnly.getFiles()));
Is it possible to override?
It seems to be a gradle bug http://issues.gradle.org/browse/GRADLE-2372

Resources