Use the following snippet inside a Gradle build file:
buildscript {
repositories {
jcenter()
}
dependencies {
classpath 'me.champeau.gradle:japicmp-gradle-plugin:0.1.1'
// UNCOMMENT THE NEXT LINE ONLY IF YOU ARE USING GRADLE 1.X
// classpath 'org.codehaus.groovy:groovy-backports-compat23:2.3.6'
}
}
apply plugin: 'me.champeau.gradle.japicmp'
The plugin provides a new task type: me.champeau.gradle.JapicmpTask
that you can use to compare two jars. This task
exposes the following properties as part of its configuration:
oldArchive |
The jar file which will be used as the reference for comparison. Type: File. |
newArchive |
The jar file we want the report to work on. Type: File. |
onlyModified |
Outputs only modified classes/methods. If not set to true, all classes and methods are printed. Type: boolean. Default value: false |
packagesToInclude |
List of package names to include, * can be used as wildcard. Type: List<String> |
packagesToExclude |
List of package names to exclude, * can be used as wildcard. Type: List<String> |
accessModifier |
Sets the access modifier level (public, package, protected, private). Type: String. Default value: public |
failOnModification |
When set to true, the build fails in case a modification has been detected. Type: boolean. Default value: false |
xmlOutputFile |
Path to the generated XML report. Type: File. Default value: null |
txtOutputFile |
Path to the generated TXT report. Type: File. Default value: null |
includeSynthetic |
Synthetic classes and class members (like e.g. bridge methods) are not tracked per default. This new option enables the tracking of such kind of classes and class members |
Add the following to your build file:
task japicmp(type: me.champeau.gradle.JapicmpTask) {
oldArchive = file('path/to/reference.jar')
newArchive = jar.archivePath
onlyModified = true
failOnModification = true
txtOutputFile = file("$buildDir/reports/japi.txt")
}
An alternative task will let you work on dependencies instead of plain jars. Imagine that you want to compare the current jar with a previous version, available in a repository. Then you can do:
task japicmp(type: me.champeau.gradle.ArtifactJapicmpTask) {
baseline = 'com.acme.group:artifactid:version'
to = jar.archivePath
onlyModified = true
failOnModification = true
txtOutputFile = file("$buildDir/reports/japi.txt")
}
Note the use of ArtifactJapicmpTask
instead of JapicmpTask
.
The plugin also supports a DSL providing hooks for classes and methods which have been added/removed/… You can use those hooks to trigger custom build failures, like illustrated here:
task japicmp(type: me.champeau.gradle.ArtifactJapicmpTask) {
baseline = 'com.acme.group:artifactid:version'
to = jar.archivePath
onlyModified = true
failOnModification = false // by default, no failure
txtOutputFile = file("$buildDir/reports/japi.txt")
outputProcessor {
removedMethod { clazz, method ->
if (clazz.fullyQualifiedName == 'com.Foo') {
failOnModification = true // This class must absolutely not be touched!
}
}
}
}
The outputProcessor
block supports the following hooks:
Hook name | Arguments | Description |
---|---|---|
unchangedClass |
JApiClass |
Called on an unchanged class, unless onlyModified is true |
newClass |
JApiClass |
A class has been added |
modifiedClass |
JApiClass |
A class has been modified |
removedClass |
JApiClass |
A class has been removed |
unchangedMethod |
(JApiMethod) or (JApiClass,JApiMethod) |
Called on an unchanged method, unless onlyModified is true |
unchangedConstructor |
(JApiConstructor) or (JApiClass,JApiConstructor) |
Called on an unchanged constructor, unless onlyModified is true |
newMethod |
(JApiMethod) or (JApiClass,JApiMethod) |
A method has been added |
modifiedMethod |
(JApiMethod) or (JApiClass,JApiMethod) |
A method has been modified |
modifiedConstructor |
(JApiConstructor) or (JApiClass,JApiConstructor) |
A constructor has been modified |
removedMethod |
(JApiMethod) or (JApiClass,JApiMethod) |
A method has been removed |
removedConstructor |
(JApiConstructor) or (JApiClass,JApiConstructor) |
A method has been removed |
before |
List<JApiClass> |
Called before iteration on classes is triggered |
after |
List<JApiClass> |
Called after iteration on classes is triggered |
The xxxMethod
hooks support two variants. One takes a single argument corresponding to the method only. The second
version is a convenient way to track to which class the method belongs to, by adding it as a first argument.
The outputProcessor
hooks can be used to produce custom reports, as illustrated here:
task japicmp(type: me.champeau.gradle.ArtifactJapicmpTask) {
// ...
outputProcessor {
def sb = new StringBuilder()
before {
sb << "Comparing $baseline with $to\n"
}
after { list ->
sb << "Reported ${list.size()} changed classes\n"
file("${buildDir}/reports/custom.txt").write(sb.toString())
}
newMethod { c, m ->
sb.append "Class $c.fullyQualifiedName has new method: $m.name\n"
}
}
}