How to run remote debug on local kotlinc - gradle

I want to compile some sample kotlin project using local compiler. I clone jetbrains/kotlin project from githib and build it. And now i have local compiler in /dist folder. How i need to configure gradle in sample project to use this local compiler in it and have an ability for remote debugging?

The simplest way is to build the whole toolchain and use it in your test projects.
To do that, run the install Gradle task in the Kotlin project:
./gradlew install
This will publish all of the project's Maven modules to the Maven local repository (~/.m2/repository by default) with the default snapshot version, which is 1.3-SNAPSHOT at the moment.
Then, in your test Gradle project:
If you apply the Gradle plugin using a buildscript block and an apply statement, add the mavenLocal() repository to buildscript { repositories { ... } } and use the snapshot version of the Gradle plugin:
buildscript {
repositories {
mavenLocal()
jcenter()
}
dependencies {
classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:1.3-SNAPSHOT")
}
}
If the plugins are applied using the plugins { ... } block, modify the settings.gradle script and add the following:
pluginManagement {
repositories {
mavenLocal()
gradlePluginPortal()
}
}
and again, use the 1.3-SNAPSHOT version of the Gradle plugin:
plugins {
id("org.jetbrains.kotlin.jvm").version("1.3-SNAPSHOT")
}
In order to be able to debug the compiler, you need to run its process with a debugging agent waiting for a connection. Normally, the compiler is run in a daemon process that is harder to connect to. It's much simpler to run the compiler inside the Gradle process. To do that, you need to set a system property kotlin.compiler.execution.strategy to in-process in the Gradle process (note: this should be not a Gradle project property but a Java system property which can be passed by -Dkey=value or set using System.setProperty(...).
Then run a Gradle build with a command line -Dorg.gradle.debug=true to make Gradle wait for a remote debugger. I would advise for running the test project build from the terminal, not the IDE.
This will look like:
./gradlew compileKotlin -Dorg.gradle.debug=true -Dkotlin.compiler.execution.strategy=in-process
Starting a Gradle Daemon, 1 busy Daemon could not be reused, use --status for details
> Starting Daemon
(at this point, the build seems to hang, but it just waits for the debugger, so proceed below)
In the IDE where you work with the Kotlin project, put some breakpoints in the compiler code and attach the remote debugger to the Gradle process.
Note that, with the Kotlin compiler running inside the Gradle process, the latter may run out of memory sooner. Make sure the Gradle process gets enough heap space.

Related

Is there a way to download a Gradle plugin from the repository to Gradle cache and use it in offline mode?

I am trying to create a copy of a gradle project that will work in --offline mode. I have automated all steps apart from one. I am not able to automatically download plugin jars into gradle cache.
My offline distribution works by specifying the GRADLE_USER_HOME, downloading all dependencies and bundling the whole gradle cache with the project. Unfortunately we are using a few custom plugins. I could of course make an exception for each one of them and include them manually, with some kind of if statement for the offline mode. But it would be great if I could simply download the jars into the cache.
Is there a way to force gradle to download all dependencies, including the plugin dependencies?
This is what I am doing for the rest of the dependencies:
task resolveAllDependencies {
doLast {
configurations.all { it.resolve() }
}
}
It downloads all dependencies to the local cache. But plugins are of course not included in any of the configurations.
It also seems that even if the plugin gets downloaded in the cache, it still fails in offline mode with the following message: Plugin cannot be resolved from https://plugins.gradle.org/api/gradle because Gradle is running in offline mode
Here's a working solution. It's not perfect, because it hard-codes the gradle plugin repository and changes the script. It's also much more verbose than the current way of using plugins.
Instead of the following simple plugin definition:
plugins {
id 'net.researchgate.release' version '2.3.5'
}
It's possible to define both the repository and the dependency manually and then use the plugin this way:
buildscript {
repositories {
maven {
url 'https://plugins.gradle.org/m2/'
}
}
dependencies {
classpath 'net.researchgate:gradle-release:2.3.5'
}
}
apply plugin: 'net.researchgate.release'
This downloads the plugin into the local gradle cache.

Run task before repositories are added and dependencies are resolved

I'm working on compiling python bindings using gradle.
There is a plugin by linkedin that facilitates that.
They also include a project called the pivy-importer that converts python dependencies into an ivy repository.
I've created a gradle plugin that wraps the pivy-importer so that it can run as a python task.
My repositories are declared like this:
repositories {
pyGradlePyPi()
ivy {
name 'pypi-local' //optional, but nice
url "${project.buildDir.path}/pythonIvy"
layout "pattern", {
ivy "[organisation]/[module]/[revision]/[module]-[revision].ivy"
artifact "[organisation]/[module]/[revision]/[artifact]-[revision](-[classifier]).[ext]"
m2compatible = true
}
}
}
The problem, however, is that the repositories are being loaded before the plugin executes.
The first task that the python task runs is pinRequirements so I was adding my cusom pythonImporter task before that like this:
pinRequirements.dependsOn pythonImporter
However, even when I do that, the console shows that the pythonImporter task is running before but as soon as it tries to assemble the dependencies, it can't find them even though they do exist in the file system.
If you rerun the task again, however, it passes because the first run added the repository to the file system.
TL;DR
I need a way to run a task before dependencies are looked up under using a project's configured repositories are loaded.
I moved the tasks execution to my buildSrc subproject and made the build task depend upon its execution.
This works because the buildSrc project is always evaluated before the rest of the projects so you can do "before build" logic there.

Is there a simple way to remove one dependency from the local gradle cache?

The local gradle cache stores copies of maven/gradle dependencies. How to clear gradle cache? covers how to clear the whole cache, but not individual packages.
Is there a simple way to remove one package from the local gradle cache? This would be useful, for example, when actively developing a library. To test a minor library change, I currently have to clear the entire cache from the filesystem so an old cached version of the library is not used.
I understand it is also possible to use the gradle ResolutionStrategy described in How can I force gradle to redownload dependencies?. I would prefer not to change the gradle configuration because most of the time and for most developers, the default caching behavior is fine.
So here's a quick script I whipped up:
seekanddestroy.gradle
defaultTasks 'seekAndDestroy'
repositories{ //this section *needs* to be identical to the repositories section of your build.gradle
jcenter()
}
configurations{
findanddelete
}
dependencies{
//add any dependencies that you need refreshed
findanddelete 'org.apache.commons:commons-math3:3.2'
}
task seekAndDestroy{
doLast {
configurations.findanddelete.each{
println 'Deleting: '+ it
delete it.parent
}
}
}
You can invoke this script by running gradle -b seekanddestroy.gradle
Demo of how it works:
if your build.gradle looks like this:
apply plugin:'java'
repositories{
jcenter()
}
dependencies{
compile 'org.apache.commons:commons-math3:3.2'
}
First time build, includes a download of the dependency:
λ gradle clean build | grep Download
Download https://jcenter.bintray.com/org/apache/commons/commons-math3/3.2/commons-math3-3.2.jar
Second clean build, uses cached dependency, so no download:
λ gradle clean build | grep Download
Now run seekanddestroy:
λ gradle -b seekanddestroy.gradle -q
Deleting: .gradle\caches\modules-2\files-2.1\org.apache.commons\commons-math3\3.2\ec2544ab27e110d2d431bdad7d538ed509b21e62\commons-math3-3.2.jar
Next build, downloads dependency again:
λ gradle clean build | grep Download
Download https://jcenter.bintray.com/org/apache/commons/commons-math3/3.2/commons-math3-3.2.jar
Works great, but for newer versions of gradle, use this instead:
task seekAndDestroy{
doLast {
configurations.findanddelete.each{
println 'Deleting: '+ it
delete it.parent
}
}
}

Debug Gradle plugins with IntelliJ

Problem
I want to use the interactive debugger with IntelliJ. Unfortunately, I can't convince IntelliJ to load and compile the plugin. However, I can do gradle clean build and the plugin builds and runs its tests as expected.
Specifically, I'm trying to debug local changes to gradle-js-plugin and IntelliJ says it can't find com.google.javascript.jscomp.CompilerOptions as well as spock.lang.Specification. (I'm thinking maybe it's something about the way they are loaded, but that's a guess.)
Things I've tried
NOTE: I didn't revert any processes between steps.
0. My First Guess
I noticed a howto on docs.codehaus.org. IntelliJ couldn't find org.gradle.launcher.GradleMain, so I've adapted it to use GradleLauncher with the following:
import org.gradle.GradleLauncher
class GradleScriptRunner {
public static void main(String[] args) {
GradleLauncher.newInstance(
"-p",
"/path/to/gradle-js-plugin/src/test/resources/build.gradle",
"clean assemble"
)
}
}
Per GradleLauncher's documentation.
Outcome: IntelliJ won't compile the project.
1. Per Peter Niederwieser's answer Fix idea project & debug via plugin
Steps
~# cd /path/to/gradle-js-plugin && gradle cleanIdea idea
Opened the newly created project and attempted to debug using the ScriptRunner from step 0.
Outcome: Project compiles (yay!), but I can only hit breakpoints in GradleScriptRunner.groovy.
2. Per Peter Niederwieser's answer run gradle CLI w/ special options
1 & 2. Merged for clarity:
~# export GRADLE_OPTS="-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=5005"
~# gradle clean assemble
Listening for transport dt_socket at address: 5005
Configure IntelliJ to connect to this port and start debugging (see image):
For this step I tried the following .gradle file configurations:
1. Use only build.gradle
--build.gradle--
apply plugin: 'groovy'
apply plugin: 'java'
apply plugin: 'idea'
apply plugin: 'maven'
apply plugin: 'js'
buildscript {
repositories {
mavenLocal()
mavenCentral()
}
dependencies {
compile findProject "/path/to/gradle-js-plugin"
}
}
repositories {
mavenLocal()
mavenCentral()
}
Outcome:
FAILURE: Build failed with an exception.
* Where:
Build file '/path/to/gradle-js-plugin/src/test/resources/build.gradle' line: 13
* What went wrong:
A problem occurred evaluating root project 'resources'.
> No such property: findProject for class: org.gradle.api.internal.artifacts.dsl.dependencies.DefaultDependencyHandler
* Try:
Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output.
BUILD FAILED
Total time: 8 mins 50.498 secs
2. Use both build.gradle and settings.gradle
--settings.gradle--
include "/path/to/gradle-js-plugin"
--build.gradle--
apply plugin: 'groovy'
apply plugin: 'java'
apply plugin: 'idea'
apply plugin: 'maven'
apply plugin: 'js'
buildscript {
repositories {
mavenLocal()
mavenCentral()
}
}
repositories {
mavenLocal()
mavenCentral()
}
Outcome:
FAILURE: Build failed with an exception.
* Where:
Build file '/path/to/gradle-js-plugin/src/test/resources/build.gradle' line: 5
* What went wrong:
A problem occurred evaluating root project 'resources'.
> Plugin with id 'js' not found.
* Try:
Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output.
BUILD FAILED
Total time: 13.553 secs
My Setup
Gradle
~# gradle -v
------------------------------------------------------------
Gradle 1.0
------------------------------------------------------------
Gradle build time: Tuesday, June 12, 2012 12:56:21 AM UTC
Groovy: 1.8.6
Ant: Apache Ant(TM) version 1.8.2 compiled on December 20 2010
Ivy: 2.2.0
JVM: 1.7.0_04 (Oracle Corporation 23.0-b21)
OS: Linux 3.2.0-2-amd64 amd64
Java
~# java -version
java version "1.7.0_04"
Java(TM) SE Runtime Environment (build 1.7.0_04-b20)
Java HotSpot(TM) 64-Bit Server VM (build 23.0-b21, mixed mode)
IntelliJ
IntelliJ IDEA Ultimate 117.499 w/ Bundled Gradle plugin
Hoping for
Any tips that'll get me into debug mode within the plugin.
I was able to debug gradle sources (including plugins) using -Dorg.gradle.debug=true (found on gradle forum):
Stop daemons if any:
./gradlew --stop
Run
./gradlew <task> --no-daemon -Dorg.gradle.debug=true
Connect remotely to gradle process (port 5005) - if using IntelliJ IDEA, see OP's image above
It should stop on breakpoints now.
BTW, I have created a separate IntelliJ IDEA project for gradle sources. Since I use gradle wrapper, I have grabbed the sources from
~/.gradle/wrapper/dists/gradle-1.11-all/7qd8qq8te5j4f5q9aaei3gh3lj/gradle-1.11/src
In IDEA I did File->Import Project, then selected the above path, then - "Create project from existing sources". Hit Next couple of times (made sure I didn't include any jars from lib/plugins directory, since IDEA would complain that most project files already exist).
I then created a remote debug configuration in that IDEA project and used it for debugging gradle.
First, it sounds like there is a problem with your IDEA Gradle project. If you run gradlew cleanIdea idea and then open the generated project from IDEA (rather than using the JetGradle plugin), all should be fine.
Second, if you still can't get the GradleMain/GradleLauncher (the former class does exist) approach to work, another approach is to debug the Gradle build as an external application. For that you need to add -Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=5005 to the GRADLE_OPTS environment variable, run the build from the command line, wait until it suspends, and then start a "Remote" run configuration (with corresponding settings) from IDEA. At that point the debugger should connect to the Gradle process and you should be up and running.
IntelliJ IDEA 12.1 provides ability to debug gradle tasks out of the box - right-click target task at the JetGradle tool window tasks list and choose 'debug'

Gradle Plugin not found when using wrapper

I have a small gradle build which is using a 3rd party plugin it works great while running gradle commands I then added the wrapper task so I could distribute the code and it could be built with non gradle users. When I went to test the gradlew command I can not even run gradlew tasks it fails saying the plugin is missing.
Is there some other configuration that needs to happen?
My wrapper task:
task wrapper(type: Wrapper) {
gradleVersion = '1.0-milestone-2'
jarFile = 'wrapper/wrapper.jar'
}
Full build file: https://github.com/beckje01/Multi-Combobox/blob/master/build.gradle
Based on the documentation of this plugin you got to build it from the source code and put it into the directory lib/plugins of your Gradle distribution. My guess is that's what you did before you switched to the Gradle wrapper. Whenever you use the Gradle wrapper your locally installed distribution is not used anymore. Gradle downloads the distribution and puts it under ~/.gradle/wrapper/dists/gradle-1.0-milestone-2. One way to get this running would be to put the plugin in there as you did before. However, this won't make it running for somebody else that checks out your code and runs the build. This is the whole point of using the Gradle wrapper.
What I would do in your case is to upload the plugin artifact to a central repository and refer to it in your build script. It doesn't look like it would be available on Maven Central though. You can upload it to your GitHub project and refer to it in your build script like this:
buildscript {
repositories {
add(new org.apache.ivy.plugins.resolver.URLResolver()) {
name = 'GitHub'
addArtifactPattern 'http://cloud.github.com/downloads/[organisation]/[module]/[module]-[revision].[ext]'
}
mavenCentral()
}
dependencies {
classpath 'beckje01:jslib:0.5'
classpath 'com.google.javascript:closure-compiler:r706'
}
}

Resources