Gradle y proguard

De ChuWiki


Código de ejemplo[editar]

Veamos como integrar Proguard en nuestro proyecto Gradle para obtener un jar ofuscado

Tienes el código explicado aquí abajo en proguard-gradle, en concreto en el subproyeto library

proguard-gradle plugin[editar]

Lo primero es añadir el plugin proguard-gradle en nuestro fichero build.gradle

buildscript {
    repositories {
        mavenCentral()
    }
    dependencies {
        classpath 'com.guardsquare:proguard-gradle:7.4.2'
    }
}

Fichero de configuración del Proguard[editar]

En algún lugar de nuestro proyecto Gradle podemos poner un fichero de configuración con las opciones que queramos para indicar a Proguard qué ofuscar y cómo ofuscarlo. Dependiendo de si nuestro proyecto es una aplicación con un main o si es una librería para usar en otros proyectos, la configuración puede ser distinta. Veamos ejemplos sencillos de ficheros proguard.conf para ambos casos.

Configuración de Proguard para una aplicación con main[editar]

En este caso, el fichero proguard.conf puede contener algo como esto

-keep public class com.chuidiang.examples.proguard_project.Main {
    public static void main(java.lang.String[]);
}

Con keep public class le estamos indicando que debe mantener sin ofuscar el nombre de la clase com.chuidiang.examples.proguard_project.Main y dentro de ella, su método public static void main(java.lang.String[])

Configuración de Proguard para una librería[editar]

En este caso, el fichero proguard.conf puede contener algo como esto

-keep public class com.chuidiang.examples.proguard_library.shared.*
-keepclassmembers class com.chuidiang.examples.proguard_library.shared.* {
    public protected <methods>;
    public protected <fields>;
}
-verbose

Son opciones propias de proguard. En este ejemplo estamos indicando:

  • keep public class : Que mantenga sin ofuscar y no borre las clases públicas que hay en el paquete com.chuidiang.examples.proguard_library.shared.*.
  • keepclassmembers class : Que mantenga sin ofuscar y no borre los métodos y campos protegidos y públicos de las clases en el paquete com.chuidiang.examples.proguard_library.shared.*
  • verbose : Que saque log de lo que está haciendo proguard.

Si nuestro proyecto es una libería, la idea sería poner todas las clases que se van a usar desde fuera en un paquete de nombre shared, public o el nombre que prefieras. Las clases de ese paquete no se deben ofuscar, puesto que si no, sería difícil usarlas desde fuera. Tampoco los métodos y campos públicos (para poder usarlos) o protegidos (por si queremos heredar).

Recuarda que Proguard, por defecto, además de ofuscar código, borra las clases, métodos y campos que no se usan. Por ello en una librería se hace especialmente importante indicar en el fichero de configuración todo lo que no queremos ofuscar/borrar.

Configurar el plugin proguard-gradle[editar]

Una vez que tenemos el fichero de configuración de Proguard, en nuestro fichero build.gradle debemo configurar el plugin.

task myProguardTask(type: proguard.gradle.ProGuardTask) {
    dependsOn 'jar'
    configuration 'proguard.conf'
    injars "${projectDir}/build/libs/${project.name}-${project.version}.jar"
    outjars "${projectDir}/build/libs/${project.name}-${project.version}-small.jar"
    libraryjars configurations.findByName('runtimeClasspath').getFiles()
    libraryjars "${System.getProperty('java.home')}/jmods"
}

Hemos creado una tarea de gradle de nombre myProguardTask. El tipo es proguard.gradle.ProGuardTask. Veamos ahora cada una de las configuraciones que hemos puesto.

  • dependsOn indica que esta tarea debe ejecutarse después de la tarea gradle jar, que es la que genera el fichero jar. Proguard ofuscará dicho fichero.
  • configuracion para decir dónde está nuestro fichero de configuración de Proguard. Path relativo a nuestro fichero build.gradle
  • injars para indicar qué jar queremos ofuscar. Usando variables propias de Gradle le indicamos el fichero jar de nuestro proyecto, que estará por defecto en build/libs. Si no has configurado project.version en tu proyecto Gradle, puedes eliminarlo de aquí, con el "-" que va delante.
  • outjars para indicar el nombre del jar ofuscado. Igual que antes, usamos variables de Gradle para indicar el nombre y dónde ubicarlo. Le hemos añadido la coletilla "-small", para distinguirlo del original.
  • 'libraryjars. Con esta opción debemos indicar donde están todas las dependencias de terceros de nuestro proyecto, incluído el runtime de java. Por eso ponemos dos líneas:
    • ${System.getProperty('java.home')}/jmods coje el directorioi jmods de nuestra instalación de Java según indique la variable de entorno JAVA_HOME. Esto es válido de Java 9 en adelante. Para Java 8 deberías poner ${System.getProperty('java.home')}/lib/rt.jar y ${System.getProperty('java.home')}/lib/jsse.jar
    • configurations.findByName('runtimeClasspath').getFiles() para añadir todas las dependencias que tengamos de terceros, es decir, las dependencies que hayamos puesto en nuestro fichero build.gradle

Ejecutar la tarea de proguard[editar]

Cuando queramos obtener el jar ofuscado, podemos ejecutar la tarea

gradle myProguardTask

Si queremos que se ejeucte automáticamente en nuestro proceso de build de gradle, podemos añadir lo siguiente en nuestro fichero build.gradle

jar.finalizedBy(myProguardTask)