Setting IntelliJ compiler args in Gradle - intellij-idea

I need to add the -parameters java compiler parameter for my tests to succeed. I can do this in gradle already for ./gradlew build to work, or manually by adding -parameters under IntelliJ Settings > Build.. > Compiler > Java Compiler > Additional command line parameters: so they work in the IDE, but I don't want everyone who checks out this repo to have to do a manual step.
My .ipr file does show
<component name="JavacSettings">
<option name="ADDITIONAL_OPTIONS_STRING" value="-parameters" />
</component>
after setting it manually, but is it possible to configure the idea plugin in gradle so ./gradlew idea just does all the work?

It's possible to do that with the new "Proof-of-concept" plugin from JetBrains:
gradle-idea-ext-plugin with following configuration:
idea.project.settings {
compiler {
javac {
javacAdditionalOptions "-parameters"
}
}
}

You can modify the ipr file as XML and add the component node. The official documentation has an example how to do this:
idea.project.ipr {
withXml { provider ->
provider.node.component
.find { it.#name == 'VcsDirectoryMappings' }
.mapping.#vcs = 'Git'
}
}
But you will be limited to the IDEA file project structure (as opposed to the .idea directory structure).

Related

Add files to jar in gradle kotlin

My usecase is to copy files from another dependency and add it to the jar. For a build.gradle file it is done as
task copyConfiguration(type: Copy) {
from("${brazilGradle.path('[ABC]pkg.src')}")
into "${brazilGradle.buildDir}/schema"
}
sourceSets.main.resources {
srcDir "${brazilGradle.buildDir}/schema"
include 'src/*'
}
What will be the equivalent translation for build.gradle.kts?
Edit : I was able to copy the file using
task<Copy>("copyDdlSchemas") {
from("${brazilGradle.path("[ABC]pkg.src")}")
into("${brazilGradle.buildDir}/schema")
}
Need help with syntax to upload it to jar.
If what you want is the kotlin gradle equivalent of the sourceSets section in the question, it'll look like below:
sourceSets["main"].resources {
srcDir("${brazilGradle.buildDir}/schema")
include("src/*")
}
Once the files are part of the source set, they'll automatically get included in the jar file generated by the default jar task.

Androidx Proto datastore gradle setup

I'm trying to get the new (alpha) android datastore using protobuf support configured in gradle using Kotlin DSL (build.gradle.kts). The first attempts are not generating any java source classes from the xxx.proto (made-up name) file that is present. The protobuf plugin is generating the correct android tasks, but running them generates nothing, so obviously the default setup is not finding the directory my initial xxx.proto file is located in. The existing doc is thin on gradle setup, especially for Kotlin Gradle DSL (most all the gradle doc from google so far is for groovy), and my initial attempts at defining the location of the xxx.proto file are not working.
Does anyone have or has anyone seen working gradle config that specifies a custom source directory for .proto file(s) using Kotlin (build.gradle.kts)?
Got it working after some experimentation and floundering, but a hack is involved. If anyone can suggest improvements, it would be appreciated. In case this is useful here are the config snippets from the working setup. Module is kotlin 1.4.21-2 multiplatform with android, ios64, and jvm targets, with more planned. It has the KMP default setup for source directories:
The .proto file is in src/androidMain/proto subdirectory.
build.gradle.kts snippets are below. All the changes are in the android block, except for the plugin of course:
plugins {
id("com.android.library")
kotlin("multiplatform")
id("kotlinx-atomicfu")
kotlin("plugin.serialization") version Versions.kotlinVersion
id("com.google.protobuf") version "0.8.14"
}
...
kotlin {
... no changes here
}
...
android {
...
sourceSets {
...
getByName("main") {
manifest.srcFile("src/androidMain/AndroidManifest.xml")
java.srcDirs("src/androidMain/kotlin")
assets.srcDirs(File("src/commonMain/resources"))
withGroovyBuilder {
"proto" {
"srcDir" ("src/androidMain/proto")
}
}
}
}
protobuf {
protoc {
artifact = "com.google.protobuf:protoc:4.0.0-rc-2"
}
plugins {
id("javalite") { artifact = "com.google.protobuf:protoc-gen-javalite:3.0.0" }
}
generateProtoTasks {
all().forEach { task ->
task.builtins {
id("java") {
option("lite")
}
}
task.plugins{
}
}
}
}
dependencies {
api("com.google.protobuf:protobuf-javalite:4.0.0-rc-2")
implementation("androidx.datastore:datastore:1.0.0-alpha05")
...
}
}
Note the withGroovyBuilder hack in the android sourceset - the srcdir definition is required for the plugin to find the .proto file I had, but in the current version of the plugin I couldn't figure out the correct Kotlin DSL syntax. Seems like the plugin needs to define a Kotlin extension function to make this work better.
It would be really nice if instead of requiring this stuff, that the datastore stuff could use the protobuf serialization available with kotlinx.serialization, and skip this java code generation step in gradle all together. But I'm sure that's down the road...
Anyway, thanks in advance if anyone has improvements etc...

What command does Intellij Gradle project refresh execute

Intellij hides which gradle command it runs whenver you press a button to do something with gradle. That makes it extremely difficult to find out what goes wrong. I am clicking "refresh" (NOT REFRESH DEPENDENCIES), and it seems to trigger all my sibling projects AND my project to build which is wrong. It is definitely not running "gradle build" because if it did, it would not trigger all the sibling projects in my multi-project build.
Clicking "refresh" in gradle shows a log like this:
2019-10-17 14:58:10,391 [9949323] INFO - xecution.GradleExecutionHelper - Passing command-line args to Gradle Tooling API: -Didea.sync.active=true -Didea.resolveSourceSetDependencies=true --init-script /tmp/ijinit.gradle
Here IDEA is using the Gradle Tooling API and using a gradle init script (in /tmp/ijinit.gradle on my machine). The file shows more:
$ cat /tmp/ijinit.gradle
...imports etc...
initscript {
dependencies {
classpath files([...list of IDEA jars...])
}
}
apply plugin: JetGradlePlugin
class JetGradlePlugin implements Plugin<Gradle> {
void apply(Gradle gradle) {
def processor = new RegistryProcessor()
gradle.addProjectEvaluationListener(processor)
def projectEvaluationIsNotCalledForIncludedBuilds = GradleVersion.current() >= GradleVersion.version("3.1") &&
GradleVersion.current() < GradleVersion.version("4.0")
if (projectEvaluationIsNotCalledForIncludedBuilds) {
gradle.rootProject {
it.afterEvaluate {
gradle.includedBuilds.each { included ->
// included builds should be configured by now, so calling `configuredBuild` should be safe
def toolingRegistry = (ToolingModelBuilderRegistry)included.configuredBuild.services.get(ToolingModelBuilderRegistry.class)
processor.process(toolingRegistry)
}
}
}
}
}
}
...other overrides...
As others mentioned the included builds can be excluded in the IDEA Gradle tab but hopefully this answers the specific title question.
If you are using a recent version of Gradle, you can use --refresh-dependencies option.
./gradlew build --refresh-dependencies

How to specify IntelliJ Exclude Directories using Gradle?

Using IntelliJ to open a build.gradle file, in the "Import Project from Gradle" window, the "Excluded Roots" are pre-populated with the .gradle and build directories.
How do I specify what directories should be excluded (or not excluded) in the build.gradle file?
Specifically I am using a protocol buffer plugin that places generated sources in the /build/generated-sources/ directory. If the build directory is excluded then my source class do not see the generated classes.
Details: IntelliJ 12.1.3, Gradle 1.4
As shown in the Gradle Build Language Reference, you can configure the idea.module.excludeDirs property, which is of type List<File>. Apparently IDEA doesn't support including subdirectories of excluded directories, so you'll have to exclude all siblings of build/generated-sources. For example:
idea {
module {
excludeDirs = [file(".gradle")]
["classes", "docs", "dependency-cache", "libs", "reports", "resources", "test-results", "tmp"].each {
excludeDirs << file("$buildDir/$it")
}
}
}
If supported by the Protocol Buffer plugin, it may be easier to put the generated sources into a place outside build, and make that place known to the clean task (e.g. clean.delete "generated-sources").
Another solution. Works with Idea 13.
idea.module {
excludeDirs -= file(buildDir) //1
buildDir.listFiles({d,f->f != 'generated-sources'} as FilenameFilter).each {excludeDirs += it}} //2
Remove buildDir from excludeDirs.
Exclude each buildDir child (except generating-source).
If you are using the Gradle Kotlin DSL, use the following snippet:
idea {
module {
excludeDirs.add(file("..."))
}
}
for exclude folder in module i'm use
idea {
module.apply {
val file = file("$projectDir/node_modules")
val exclude = HashSet<File>(excludeDirs)
exclude.add(file)
excludeDirs = exclude
}
}

Managing project dependencies with Gradle and IntelliJ

I am looking to use Gradle to build my Groovy / Grails based project for which we are using IntelliJ Idea as the IDE.
I am using IntelliJ version 11.1.4, Gradle version 1.2.
My project is a configured as a multi project build with various Groovy & Grails subprojects.
I was hoping that this would give me the same kind of IDE support that I would get if managing the build through Maven, such as:
Automatic dependency management (import new dependencies to IntelliJ when added to various build.gradle)
Build DSL support
Execution of build tasks
Use of the underlying build system (gradle) by the IDE when performing builds\
I have imported my project into IntelliJ by opening the root build.gradle file.
So far I am coming up against a few annoying problems:
IntelliJ is not recognising (or recognising randomly) changes to dependencies in the build.gradle files and therefore dependencies are not being updated.
The gradle "idea" plugin doesn't seem to work with multi module projects.
How are people working with Gradle inside IntelliJ? Are you managing dependencies manually within IntelliJ??
I have been using Gradle "idea" plugin for some time now and it works very well. Since "idea" plugin simply generates IntelliJ project configuration files it is somewhat limited in what you can do with it, but nevertheless, I have had more success with it compared to the IntelliJ gradle support (JetGradle thing).
Gradle "idea" plugin does work with multi-module projects, never had a problem with that. I always put parent project configuration in master folder (see Initialization chapter), which seems to work. Never tried the nested structure though.
In order to do additional IntelliJ configuration you can do some .ipr and .iml tinkering from gradle, or alternatively try using one of my plugins (see Utilities plugin) which will do most of the tinkering for you.
In the end I went with rodion's suggestion above and used the idea plugin. It turns out I had not configured it properly first time I tried it (only applied the plugin to the master project, not subprojects).
I only found this out after writing my own task to update the dependencies for an IntelliJ project (based on the .idea directory layout project structure). I am going to use the plugin as there will be less maintenance, but here is my solution for posterity and in case it is useful to anyone:
ext {
intelliJLibraryDir = "$gradle.rootProject.rootDir/.idea/libraries"
userHomeDir = gradle.gradleUserHomeDir.parent
}
task cleanIntelliJLibraries << {
ant.delete (includeEmptyDirs: 'true') {
fileset(dir: intelliJLibraryDir, includes: '*.xml')
}
}
task createIntelliJLibraries(dependsOn: cleanIntelliJLibraries) << {
// The unique set of dependency artifacts across all subprojects
def uniqueProjectArtifacts = subprojects.collectMany {
if (it.configurations.compile) {
it.configurations.compile.resolvedConfiguration.resolvedArtifacts.findAll {
it.moduleVersion.id.group != "my.project"
}
}
else { [] }
}.unique()
// Output a library xml file for each of the dependency artifacts
uniqueProjectArtifacts.each { artifact ->
def artifactPath = artifact.file.path
def artifactName = artifact.moduleVersion.id.with { "$group:$name:$version" }
def intelliJLibraryPath = artifactPath.replace(userHomeDir, '$USER_HOME$')
def intelliJLibraryFileName = "Gradle__$artifactName".replace(':', '_').replace('.','_') + ".xml"
new File("$intelliJLibraryDir/$intelliJLibraryFileName").withWriter { writer ->
def dependencyXML = new MarkupBuilder( writer )
dependencyXML.component (name: "libraryTable") {
library (name: "Gradle: $artifactName") {
CLASSES {
root (url: "jar://$intelliJLibraryPath!/")
}
JAVADOC {}
SOURCES {}
}
}
}
}
}
task updateIntelliJModules(dependsOn: createIntelliJLibraries) << {
subprojects.each { project ->
def root = new XmlSlurper().parse(new File("${project.name}.iml"))
// Remove the existing dependencies
root.component.orderEntry.findAll { it.#type == "library" && it.#level == "project" }.replaceNode {}
// Add in the new dependencies
if (project.configurations.compile) {
project.configurations.compile.resolvedConfiguration.resolvedArtifacts.findAll {
it.moduleVersion.id.group != "my.project"
}.each { artifact ->
def artifactName = artifact.moduleVersion.id.with { "Gradle: $group:$name:$version" }
root.component.appendNode {
orderEntry (type: "library", exported: "", name: artifactName, level: "project")
}
}
}
def outputBuilder = new StreamingMarkupBuilder()
new File("${project.name}.iml").withWriter { writer ->
groovy.xml.XmlUtil.serialize(outputBuilder.bind{ mkp.yield root }, writer)
}
}
}