I was wondering if anybody has any experience with obfuscating their leiningen compiled uberjars with proguard. I've tried my best to look for a solution on Google but couldn't really find an answer. I'm wondering if this is at all possible.
I've been trying to obfuscate a default lein project. Here's the core.clj file:
(ns proguard.core
(:gen-class))
(defn -main
"I don't do a whole lot."
[& args]
(println "Hello, World!"))
the project file:
(defproject proguard "0.1.0-SNAPSHOT"
:description "FIXME: write description"
:url "http://example.com/FIXME"
:license {:name "Eclipse Public License"
:url "http://www.eclipse.org/legal/epl-v10.html"}
:dependencies [[org.clojure/clojure "1.4.0"]]
:aot :all
:main proguard.core)
and my proguard config file:
-injars clojure/proguard/target/proguard-0.1.0-SNAPSHOT-standalone.jar
-outjars clojure/test-project
-libraryjars /System/Library/Java/JavaVirtualMachines/1.6.0.jdk/Contents/Home/lib/rt.jar
-dontshrink
-dontoptimize
-dontusemixedcaseclassnames
-dontpreverify
-dontnote
-printseeds
-keepclasseswithmembers public class * {
public static void main(java.lang.String[]);
}
-keep class clojure.core__init { public static void load(); }
-keep class clojure.core_proxy__init { public static void load(); }
-keep class clojure.core_print__init { public static void load(); }
-keep class clojure.genclass__init { public static void load(); }
-keep class clojure.core_deftype__init { public static void load(); }
-keep class clojure.core.protocols__init { public static void load(); }
-keep class clojure.gvec__init { public static void load(); }
-keep class clojure.java.io__init { public static void load(); }
-keep class clojure.lang__init { public static void load(); }
-keep class proguard.core__init {
public static void load();
}
-keep class proguard.core {
public *** super*(...);
}
Whenever I try to run the obfuscated jar I get the following errors:
Exception in thread "main" java.lang.ExceptionInInitializerError
at clojure.lang.ve.<init>(Unknown Source)
at clojure.lang.ve.c(Unknown Source)
at clojure.lang.yf.a(Unknown Source)
at proguard.core.<clinit>(Unknown Source)
Caused by: java.lang.ClassNotFoundException: clojure.lang.PersistentList, compiling:(clojure/core.clj:20)
at clojure.lang.at.a(Unknown Source)
at clojure.lang.at.b(Unknown Source)
at clojure.lang.at.a(Unknown Source)
at clojure.lang.bj.a(Unknown Source)
at clojure.lang.at.a(Unknown Source)
at clojure.lang.at.b(Unknown Source)
at clojure.lang.at.a(Unknown Source)
at clojure.lang.at.a(Unknown Source)
at clojure.lang.at.a(Unknown Source)
at clojure.lang.xh.a(Unknown Source)
at clojure.lang.xh.a(Unknown Source)
at clojure.lang.xh.b(Unknown Source)
at clojure.lang.xh.d(Unknown Source)
at clojure.lang.xh.c(Unknown Source)
at clojure.lang.xh.<clinit>(Unknown Source)
... 4 more
Caused by: java.lang.ClassNotFoundException: clojure.lang.PersistentList
at java.net.URLClassLoader$1.run(URLClassLoader.java:202)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(URLClassLoader.java:190)
at clojure.lang.ec.findClass(Unknown Source)
at java.lang.ClassLoader.loadClass(ClassLoader.java:306)
at java.lang.ClassLoader.loadClass(ClassLoader.java:247)
at java.lang.Class.forName0(Native Method)
at java.lang.Class.forName(Class.java:247)
at clojure.lang.xh.h(Unknown Source)
at clojure.lang.bp.b(Unknown Source)
at clojure.lang.bp.a(Unknown Source)
at clojure.lang.bq.a(Unknown Source)
... 19 more
I'm not really sure what I'm doing wrong here... I've tried to follow a clojure targeted proguard tutorial obfuscating with proguard, however it is android and ant specific so I'm wondering if the process is entirely different for desktop applications that use lein.
Thanks in advance.
Copied from above:
Obfuscating uberjars
1. Preparing your project.clj file
Here's a copy of mine (simple, default lein project, with comments):
(defproject proguard "0.1.0-SNAPSHOT"
:description "FIXME: write description"
:url "http://example.com/FIXME"
:license {:name "Eclipse Public License"
:url "http://www.eclipse.org/legal/epl-v10.html"}
:dependencies [[org.clojure/clojure "1.4.0"]]
:main proguard.core
;;; Make sure everything is aot compiled
:aot :all
;;; Remove source .clj files from the resulting jar
:omit-source true
)
There isn't much more to it here... Also make sure that (:gen-class)
is included in your namespace declarations.
Build the uberjar with lein uberjar
and we are off to the next step.
2. Preparing your ProGuard config file
Once again a copy of my file follows with annotations
# Our uberjar
-injars clojure/proguard/target/proguard-0.1.0-SNAPSHOT-standalone.jar
# Our output direcotry
-outjars clojure/obfuscated
# Link to rt.jar. I'm on a Mac so your path may differ
-libraryjars /System/Library/Java/JavaVirtualMachines/1.6.0.jdk/Contents/Home/lib/rt.jar
# ProGuard options. Detailed explanation here http://proguard.sourceforge.net/index.html#manual/usage.html
-dontskipnonpubliclibraryclassmembers
-dontnote
-printseeds
# What we will be doing is obfuscating, shrinking and optimizing the jar.
# If you experience any problems start out with obfuscation and add the
# -dontoptimize and the -dontshrink flags and see if it works.
# Tell proguard to leave the clojure runtime alone
# You would need to add any other classes that you wish to preserve here.
-keep class clojure.** { *; }
# Keep our core__init class
-keep class proguard.core__init {
public static void load();
}
# Keep classes that contain a main method (otherwise we won't be able to run the jar)
-keepclasseswithmembers public class * {
public static void main(java.lang.String[]);
}
Thats it. Now run proguard with your new configuration file java -jar proguard.jar @myconfig.pro
. You should see a bunch of output due to the -printseeds
flag (which you of course can remove if you don't want to see which classes will be kept by proguard).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With