I am trying to publish an obfuscated JAR created by the Gradle 6.0.1 ProGuard Plugin to a Maven repository. I've learned much about Gradle configurations, variants and artifacts over the last days, but I seem to be unable to make this work. I believe the relevant documentation is the one here .
I have created a minimal example showing my intended setup on Github .
If I run ./gradlew publish
on this project I get the following error.
Execution failed for task ':publishMyLibraryPublicationToMyRepoRepository'.
> Failed to publish publication 'myLibrary' to repository 'myRepo'
> Invalid publication 'myLibrary': multiple artifacts with the identical extension and classifier ('jar', 'null').
I also tried the deprecated maven
plugin. Unfortunately this plugin ignored the custom ProGuard jar.
Can someone give me any advice on how to replace the original JAR from the JAR task with the obfuscated Jar from the proguard task?
EDIT: I was able to derive a solution from this thread . The minimal example on Github contains the patched version. Feel free to have a look. I will put the working build.gradle into an answer below.
Adding classifier = "proguard"
solved it, although I'm not familar with proguard to determine if the publication is correct.
artifacts {
proguard(new File(proguard.outJarFiles[0])) {
builtBy(proguard)
classifier = "proguard"
}
}
Here's what was published for me:
I can see that the original JAR is 592 bytes while the proguard one is 410 bytes, so I am assuming it worked correctly.
Also while debugging your issue, I refactored to use the Kotlin DSL which I recommend using.
import proguard.gradle.ProGuardTask
plugins {
`java-library`
`maven-publish`
}
buildscript {
repositories {
jcenter()
}
dependencies {
classpath("net.sf.proguard:proguard-gradle:6.2.2")
}
}
group = "org.example"
version = "1.0.0"
repositories {
jcenter()
}
configurations {
val implementation by this
val runtimeOnly by this
create("proguard") {
isCanBeConsumed = false
isCanBeResolved = false
extendsFrom(implementation, runtimeOnly)
attributes {
attribute(Attribute.of("org.gradle.usage", String::class.java), Usage.JAVA_API)
attribute(Attribute.of("org.gradle.category", String::class.java), Category.LIBRARY)
attribute(Attribute.of("org.gradle.libraryelements", String::class.java), LibraryElements.JAR)
attribute(Attribute.of("org.gradle.dependency.bundling", String::class.java), Bundling.EXTERNAL)
}
}
}
dependencies {
api("org.apache.commons:commons-math3:3.6.1")
implementation("com.google.guava:guava:23.0")
testImplementation("junit:junit:4.12")
}
val proguard by tasks.registering(ProGuardTask::class) {
description = "Optimizes and obfuscates the created distribution jar."
dependsOn(tasks.named("jar"))
verbose()
injars("$buildDir/libs/${project.name}-${project.version}.jar")
outjars("$buildDir/proguard/${project.name}-${version}.jar")
if (System.getProperty("java.version").startsWith("1.")) {
libraryjars("${System.getProperty("java.home")}/lib/rt.jar")
} else {
libraryjars(mapOf("jarfilter" to "!**.jar", "filter" to "!module-info.class"), "${System.getProperty("java.home")}/jmods/java.base.jmod")
}
libraryjars(configurations.named("runtimeClasspath").get().files)
printmapping("out.map")
keep("""
public class * {
public protected *;
}
""".trimIndent())
keepclassmembers(mapOf("allowoptimization" to true), """
enum * {
public static **[] values();
public static ** valueOf(java.lang.String);
}
""".trimIndent())
keepclassmembers("""
class * implements java.io.Serializable {
static final long serialVersionUID;
static final java.io.ObjectStreamField[] serialPersistentFields;
private void writeObject(java.io.ObjectOutputStream);
private void readObject(java.io.ObjectInputStream);
java.lang.Object writeReplace ();
java.lang.Object readResolve ();
}
""".trimIndent())
overloadaggressively()
}
val javaComponent = project.components.findByName("java") as AdhocComponentWithVariants
javaComponent.addVariantsFromConfiguration(configurations.getByName("proguard")) {
// I have no idea what I should do here and the documentation is very confusing
}
publishing {
publications {
create<MavenPublication>("myLibrary") {
from(components["java"])
artifact(proguard.get().outJarFiles[0]) {
builtBy(proguard.get())
classifier = "proguard"
}
}
}
repositories {
maven {
name = "myRepo"
url = uri("file://${buildDir}/repo")
}
}
}
tasks.named("publish").configure {
dependsOn(tasks.named("proguard"))
}
As already editted into the question I found a solution and updated the Github-Project accordingly. Since Stackoverflow likes to have local information and not to depend on links, I post the working build.gradle file as an answer here. The Rest of the Github-Project is just the Java library project created by gradle init
.
buildscript {
repositories {
jcenter()
}
dependencies {
classpath 'net.sf.proguard:proguard-gradle:6.2.2'
classpath 'net.sf.proguard:proguard-base:6.2.2'
}
}
plugins {
id 'java-library'
id 'maven-publish'
}
group = 'org.example'
version = '1.0.0'
repositories {
jcenter()
}
dependencies {
api 'org.apache.commons:commons-math3:3.6.1'
implementation 'com.google.guava:guava:23.0'
testImplementation 'junit:junit:4.12'
}
task createObfuscated(type: proguard.gradle.ProGuardTask, dependsOn: 'jar') {
description 'Optimizes and obfuscates the created distribution jar.'
verbose
injars "${buildDir}/libs/${project.name}-${version}.jar"
outjars "${buildDir}/obf/${project.name}-${version}.jar"
if (System.getProperty('java.version').startsWith('1.')) {
libraryjars "${System.getProperty('java.home')}/lib/rt.jar"
} else {
libraryjars "${System.getProperty('java.home')}/jmods/java.base.jmod", jarfilter: '!**.jar', filter: '!module-info.class'
}
libraryjars configurations.findByName('runtimeClasspath').getFiles()
printmapping 'out.map'
keep 'public class * { \
public protected *; \
}'
keepclassmembers allowoptimization: true, 'enum * { \
public static **[] values(); \
public static ** valueOf(java.lang.String); \
}'
keepclassmembers 'class * implements java.io.Serializable { \
static final long serialVersionUID; \
static final java.io.ObjectStreamField[] serialPersistentFields; \
private void writeObject(java.io.ObjectOutputStream); \
private void readObject(java.io.ObjectInputStream); \
java.lang.Object writeReplace(); \
java.lang.Object readResolve(); \
}'
overloadaggressively
}
task copyObfuscated(type: Copy, dependsOn: createObfuscated) {
from "${buildDir}/obf"
into "${buildDir}/libs"
include '*.jar'
}
task deleteObfuscated(type: Delete, dependsOn: copyObfuscated) {
delete '${buildDir}/obf'
}
task proguard dependsOn deleteObfuscated
publishing {
publications {
myLibrary(MavenPublication) {
from components.java
}
}
repositories {
maven {
name = 'myRepo'
url = "file://${buildDir}/repo"
}
}
}
publish.dependsOn proguard
wrapper {
gradleVersion '6.0.1'
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.