Different lint-options per build type - android-gradle-plugin

I want to have different lint options per build-type.
I tried to simply add the options to the corresponding build types like this:
android {
buildTypes {
debug {
lintOptions {
textReport true
textOutput 'stdout'
warningsAsErrors false
abortOnError true
}
}
release {
lintOptions {
textReport true
textOutput 'stdout'
ignoreWarnings false
warningsAsErrors true
abortOnError true
}
}
}
but this does not work as expected:
e.g. in my project I have some lint warnings, but no errors. Thus I'd expect
./gradlew lintRelease
to fail, but
./gradlew lintDebug
to succeed (with warnings of course).
But this is not the case. With the config shown above, both builds fail.
The strange thing is, that it is dependent on the order: e.g. when I move the whole debug {} block after release {}, then both builds always succeed: so it seems that only the latest options are ever used...
What am I missing - or how to fix this?
I use gradle version 3.3

as a workaround we can use a gradle property which we can set to "debug"/"release": as explained here: Gradle plugin does not propagate debug/release to dependencies - Comment#91
e.g. in the gradle.properties file of the project define a variable:
myBuildType=debug
This will make sure that the default build type is "debug". You can override it via a gradle command line argument
./gradlew.bat -PmyBuildType=release ...
and in the build.gradle file of the project or subprojects:
warningsAsErrors rootProject.properties['myBuildType'] == 'release'

This answer may be helpful to you.
I solved the problem in a different way.
Add this task in your app build.gradle after the android { } block.
task setReleaseLintOptions {
doLast {
configure(android.lintOptions) {
// Put your specific lintOptions here
check 'ExtraTranslation', 'MissingTranslation', 'Untranslatable'
}
}
}
task setDebugLintOptions {
doLast {
configure(android.lintOptions) {
// Put your specific lintOptions here
check 'MissingDefaultResource', 'UnusedResources'
}
}
}
Then you can manually run these tasks before your lint tasks to configure the lint options before that run...
.gradlew setReleaseLintOptions lintRelease
.gradlew setDebugLintOptions lintDebug
This would run the options specified in our custom tasks for the lintRelease or lintDebug task.

Related

Apply local jar-plugin without using maven

I'd like to load my custom plugin from a local jar. The jar file compiles fine and when I check it, the manifest and the plugin class are there.
gradlePlugin {
plugins {
create("asdf") { // <-- I really call it "asdf" in the kts script
id = "asdf"
implementationClass = "pluginTest.TestPlugin"
version = "1.4.0"
}
}
}
The plugin doesn't do anything useful yet as it should be a proof-of-concept to make sure it actually works at all:
class TestPlugin : Plugin<Project> {
override fun apply(project: Project) {
println("Hallo TestPlugin!")
}
}
I then try to use it like this in another project:
buildscript {
repositories {
jcenter()
}
dependencies {
classpath(files("..\\..\\path\\to\\pluginTest.jar"))
}
}
plugins {
id("asdf") version "1.4.0"
}
but it keeps telling me that:
Plugin [id: 'asdf', version: '1.4.0'] was not found in any of the following sources:
What am I missing here? I use Gradle v6.5.
When you have the plugin jar on the classpath, you can't have a version number in the plugin application. I guess this is because you can't have multiple jars with different versions on the classpath in the first place, so specifying a version here doesn't make any sense (except perhaps to validate that you are using the correct one). This won't fix the problem, but it is a start.
To be honest, I don't know why your approach still won't work. The buildscript block is supposed to set up dependencies for that particular script, and that should make the plugin visible to it. It doesn't for some reason.
Perhaps this is a bug or perhaps this is just an undocumented limitation on the use of the plugin {} block. Maybe you could ask over at the Gradle forums or create an issue for it. However, there are workarounds that don't involve publishing to a (local) Maven repository, which I agree can be a bit annoying.
If you use "apply from" instead of "plugins {}", it works. For some reason, the former can see the buildscript classpath whereas the latter can't:
// build.gradle (Groovy DSL)
buildscript {
dependencies {
classpath(files("..\\..\\path\\to\\pluginTest.jar"))
}
}
apply from: "asdf"
Alternatively, move the buildscript plugin from the build.gradle file to the settings.gradle file. This makes is available to the entire build classpath and will make it work with the plugin block:
// settings.gradle (Groovy DSL):
buildscript {
dependencies {
classpath(files("..\\..\\path\\to\\pluginTest.jar"))
}
}
// build.gradle (Groovy DSL)
plugins {
id("asdf")
}
Lastly, just in case you haven't considered it already, you may be able to add the plugin as a composite build. This will create a source dependency to the plugin and has the advantage that transitive dependencies will be carried over (the ones you put in the plugin's own dependency block) and that it will be built automatically if not up-to-date. I use this approach for integration testing my plugins and also sometimes to apply them to my other real projects to test them in a bigger setting before publishing new versions.
Do that with either:
// settings.gradle (Groovy DSL):
includeBuild("..\\..\\path\\to\\plugin")
// build.gradle (Groovy DSL):
plugins {
id("asdf")
}
Or without hard-coding it in the build (so you can dynamically switch between local and published versions):
// build.gradle (Groovy DSL):
plugins {
id("asdf") version "1.4.0" // Version is optional (will be ignored when the command line switch below)
}
// Run with:
./gradlew --include-build "..\\..\\path\\to\\plugin" build
With #BjørnVester's answer I figured it out!
You need to put the buildscript in settings.gradle.kts as it doesn't get executed in the build.gradle.kts even when placed before plugins.
buildscript {
repositories {
flatDir {
dirs("..\\reusable-kotlin\\build\\libs") // <-- folder with jars
}
}
dependencies {
classpath("com.hedev.kotlin:reusable-kotlin:1.4.0")
}
}
But there's a catch! You must use the file-name of the jar in the classpath's name identifier that goes like this:
group:file-name:version
The file gradle will look for will be file-name-version.jar or file-name.jar which you'll see in the error message if you make a mistake (I added the _ on purpose to trigger the error):
Could not resolve all artifacts for configuration 'classpath'.
Could not find com.hedev.kotlin:reusable-kotlin_:1.4.0. Searched in the following locations:
- file:/C:/some/path/reusable-kotlin/build/libs/reusable-kotlin_-1.4.0.jar
- file:/C:/some/path/reusable-kotlin/build/libs/reusable-kotlin_.jar
In order for this to work I also had to add the group property to the plugin itself:
gradlePlugin {
plugins {
create("asdf") {
id = "asdf"
implementationClass = "com.hedev.kotlin.gradle.TestPlugin"
version = "1.4.0"
group = "com.hedev.kotlin"
}
}
}
Finally you can apply it in build.gradle.kts with (no version here):
plugins {
id("asdf")
}

Setting up gradle and project structure for Kotlin Multiplatform project

I want to build a CLI tool with Kotlin Multiplatform which runs on Linux, Macos and Windows.
But I am struggling with setting up my build.gradle and my project structure. I am using IntelliJ IDEA 2020.1 and created my basic project with File -> New -> Project -> Kotlin / Native | Gradle
Currently I am looking through guides from kotlinlang.org but I am more falling then achieving something.
So far my build.gradle looks as follows:
plugins {
id 'org.jetbrains.kotlin.multiplatform' version '1.3.72'
}
repositories {
mavenCentral()
}
kotlin {
// For ARM, should be changed to iosArm32 or iosArm64
// For Linux, should be changed to e.g. linuxX64
// For MacOS, should be changed to e.g. macosX64
// For Windows, should be changed to e.g. mingwX64
linuxX64("linux") {
}
mingwX64("mingw") {
}
macosX64("macos") {
binaries {
executable {
// Change to specify fully qualified name of your application's entry point:
entryPoint = 'sample.main'
// Specify command-line arguments, if necessary:
runTask?.args('')
}
}
}
sourceSets {
commonMain {
kotlin.srcDir('src/main')
resources.srcDir('src/res')
dependencies {
implementation kotlin('stdlib-common')
implementation "com.github.ajalt:clikt-multiplatform:2.7.0"
}
}
commonTest {
dependencies {
implementation kotlin('test-common')
implementation kotlin('test-annotations-common')
}
}
macosX64().compilations.test.defaultSourceSet {
dependsOn commonMain
}
// Note: To enable common source sets please comment out
'kotlin.import.noCommonSourceSets' property
// in gradle.properties file and re-import your project in IDE.
macosMain {
}
macosTest {
}
}
}
wrapper {
gradleVersion = "6.4.1"
distributionType = "ALL"
}
And my project structure is still basic:
Project structure
Formerly I only worked on Android Projects with Kotlin, and I guess I am spoiled with gradle as Android generates the most basic stuff and everything is working without doing that much.
I understand that I need to create packages like linuxMain and mingwMain, but where to I put common sourcesets? I tried to create a package called commonMain, but it won't even let me create Kotlin files in that package.
When I am finished I want to have (in the best case) one common source set and one entry point for all my targets. Is this even possible?
As far as I can see, you specify your commonMain source set's source locations as /src/main/. By default, it's usually set onto /src/commonMain/kotlin/. So if you will remove those srcDir settings and create a .kt file in your /src/commonMain/kotlin/ folder, everything should work fine. Also, I hope you have removed 'kotlin.import.noCommonSourceSets' property from your gradle.properties as your script recommended.

Runing coroutines in IntelliJ Kotlinx error

I'm trying to run a native Kotlin project using coroutines using IntelliJ IDEA Community 2020.
Here is how my build.gradle looks:
plugins {
id 'org.jetbrains.kotlin.multiplatform' version '1.3.72'
}
repositories {
mavenCentral()
}
kotlin {
// For ARM, should be changed to iosArm32 or iosArm64
// For Linux, should be changed to e.g. linuxX64
// For MacOS, should be changed to e.g. macosX64
// For Windows, should be changed to e.g. mingwX64
mingwX64("mingw") {
binaries {
executable {
// Change to specify fully qualified name of your application's entry point:
entryPoint = 'sample.main'
// Specify command-line arguments, if necessary:
runTask?.args('')
}
}
}
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 {
}
}
}
// Use the following Gradle tasks to run your application:
// :runReleaseExecutableMingw - without debug symbols
// :runDebugExecutableMingw - with debug symbols
And here is a simple KT file:
package sample
import kotlinx.coroutines.*
fun main() = runBlocking<Unit> {
val deferred = async(Dispatchers.Unconfined, CoroutineStart.LAZY) {
println("Running Async Unconfined: on thread ${Thread.currentThread().name} has run.")
42
}
val result = deferred.await()
println("Async Unconfined Result is ${result}")
}
I installed the maven plugin under Project Structure | Module and screenshot attached.
Nevertheless, I'm getting "Unresolved References..." error. Attached screenshot...
Request if someone can help me to resolve this please?
Thanks
In your Project Structure > Modules > Dependencies tab, you selected Runtime as the scope, which makes the dependency only available at runtime (usually used for transitive dependencies). Try selecting Compile here.

Gradle: How to get output from test STDERR/STDOUT into console?

(Gradle 3.2.1) I run some java tests, which logs output in Stderr/Stdout. I can see that output, if I start
gradle test --info
but in that case, much of unwanted output from 3-rd party libraries is there too.
Documentation suggests using logging.caputureStandardError / logging.caputureStandardError (loglevel), but it doesn't seem to have any effect.
tasks.withType(Test) {
logging.captureStandardOutput LogLevel.QUIET
logging.captureStandardError LogLevel.QUIET
}
Then if running gradle test, not STDERR/STDOUT is output in console.
How can I get just the output from the tests classes in console?
Add these lines to build.gradle :
apply plugin: 'java'
test {
dependsOn cleanTest
testLogging.showStandardStreams = true
}
Notice: dependsOn cleanTest is not necessary but if not used, you need to run cleanTest or clean task before test task.
Edit:
A better approach:
apply plugin: 'java'
test {
testLogging {
outputs.upToDateWhen {false}
showStandardStreams = true
}
}
Notice: outputs.upToDateWhen {false} is not necessary but if not used, you need to run cleanTest or clean task before test task.
For more info and options see the documentation.
For those using Kotlin/Kotlin DSL for Gradle, you need to put the following in your build.gradle.kts file:
tasks.withType<Test> {
this.testLogging {
this.showStandardStreams = true
}
}
Also as mentioned in another answer, you will need to run gradle clean test for the output to print every time.
The testLogging answer is correct. For me, since I already had a tasks.test section, I figured it'd be easier to put it there instead.
tasks.test {
useJUnitPlatform()
this.testLogging {
this.showStandardStreams = true
}
}
Extending on #Talha Malik solution's above (and the ones in this other post), when dealing with a multi-module android app the following can be used (root build.gradle)
// Call from root build.gradle
setupTestLogging()
fun Project.setupTestLogging() {
for (sub in subprojects) {
sub.tasks.withType<Test> {
testLogging {
exceptionFormat = TestExceptionFormat.FULL
}
}
}
}
(note that while exceptionFormat alone should be enough to get the wanted outcome, the events("standardOut" ...) mentioned above can be specified in the same way)

How to get `gradlew idea` to get IDEA to use test conf for custom task?

I have the following:
sourceSets {
integrationTest {
java.srcDir file('.')
}
}
dependencies {
integrationTestCompile project(':sut-project')
}
task integrationTest(type: Test)
but when gradlew idea is run and the project opened, the Sources doesn't have a Tests conf for that project.
What needs to be done to get this to work?
The documentation for IDEA plugin is at http://www.gradle.org/docs/current/userguide/idea_plugin.html
From this links you can navigate to http://www.gradle.org/docs/current/dsl/org.gradle.plugins.ide.idea.model.IdeaModule.html where you can see how to map additional source roots (AKA content-roots in IntelliJ parlance) to your modules and configurations to classpath using proper scope. You will use something like:
idea {
module {
testSourceDirs += file('src/integTest/java')
scopes.TEST.plus += configurations.integrationTestCompile
}
}