Last active
December 16, 2015 05:48
-
-
Save pepijnve/5386437 to your computer and use it in GitHub Desktop.
Buildr extension that adds support for obfuscation using Proguard
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
require 'buildr' | |
module Buildr | |
class ProguardTask < Rake::FileTask | |
# Proguard version number. | |
VERSION = '4.7' | |
OPTIONS = [:configuration, | |
:target, | |
:forceprocessing, | |
:printseeds, | |
:shrink, | |
:printusage, | |
:optimize, | |
:optimizationpasses, | |
:allowaccessmodification, | |
:mergeinterfacesaggressively, | |
:obfuscate, | |
:printmapping, | |
:applymapping, | |
:obfuscationdictionary, | |
:classobfuscationdictionary, | |
:packageobfuscationdictionary, | |
:overloadaggressively, | |
:useuniqueclassmembernames, | |
:usemixedcaseclassnames, | |
:flattenpackagehierarchy, | |
:repackageclasses, | |
:renamesourcefileattribute, | |
:keepparameternames, | |
:preverify, | |
:microedition, | |
:verbose, | |
:note, | |
:warn, | |
:ignorewarnings, | |
:printconfiguration, | |
:dump] | |
FILTER_OPTIONS = [:filter, :jarfilter, :warfilter, :earfilter, :zipfilter] | |
MODIFIER_SPEC = [:allowshrinking, :allowoptimization, :allowobfuscation] | |
CLASS_SPEC = [:access, :type, :name, :extends, :implements, :field, :method, :constructor] | |
MODIFIER_CLASS_SPEC = [MODIFIER_SPEC, CLASS_SPEC].flatten | |
MEMBER_SPEC = [:access, :type, :name, :parameters] | |
KEEP_OPTIONS = ["", :classmembers, :classeswithmembers, :names, :classmembernames, :classeswithmembernames, :packagename, :packagenames, :attribute, :attributes] | |
KEEP_SPECS = { | |
"" => MODIFIER_CLASS_SPEC, | |
:classmembers => MODIFIER_CLASS_SPEC, | |
:classeswithmembers => MODIFIER_CLASS_SPEC, | |
:names => CLASS_SPEC, | |
:classmembernames => CLASS_SPEC, | |
:classeswithmembernames => CLASS_SPEC, | |
:packagename => [:name], | |
:packagenames => [:filter], | |
:attribute => [:name], | |
:attributes => [:filter] | |
} | |
class << self | |
def version | |
Buildr.settings.build['proguard'] || VERSION | |
end | |
def dependencies | |
@dependencies ||= ["net.sourceforge.proguard:proguard:jar:#{version}"] | |
end | |
end | |
def initialize(*args) #:nodoc: | |
super | |
@sources = [] | |
@dependencies = [] | |
@keep = [] | |
@whykeeping = [] | |
@assumenosfct = [] | |
@params = {:optimize => false} | |
@main_jar = nil | |
java_home = nil | |
Buildr.ant('proguard') do |ant| | |
java_home = ant.project.getProperty("java.home") | |
end | |
Dir["#{java_home}/**/rt.jar"].each { |f| use f } | |
enhance { obfuscate } | |
end | |
def manifest | |
@main_jar.manifest | |
end | |
attr_reader :main_jar | |
attr_accessor :sources | |
def include(*args) | |
@main_jar = args[0] unless @main_jar | |
filter_options = Hash === args.last ? args.pop.dup : {} | |
rake_check_options filter_options, *ProguardTask::FILTER_OPTIONS | |
artifacts = Buildr.artifacts(args.flatten).uniq | |
@sources << {:artifacts => artifacts, :filter_options => filter_options} | |
self | |
end | |
alias :in_jar :include | |
attr_accessor :dependencies | |
def use(*args) | |
filter_options = Hash === args.last ? args.pop.dup : {} | |
rake_check_options filter_options, *ProguardTask::FILTER_OPTIONS | |
artifacts = Buildr.artifacts(args.flatten).uniq | |
@dependencies << {:artifacts => artifacts, :filter_options => filter_options} | |
self | |
end | |
alias :library_jar :use | |
def with(options) | |
manifest_value = options.delete(:manifest) | |
if manifest_value | |
@main_jar.with :manifest => manifest_value | |
end | |
rake_check_options options, *ProguardTask::OPTIONS | |
@params.merge! options | |
self | |
end | |
def keep(*args) | |
@keep << keep_spec(*args) | |
end | |
def why_are_you_keeping(*args) | |
@whykeeping << keep_spec(*args) | |
end | |
private | |
def keep_spec(*args) | |
keep_spec = Hash === args.last ? args.pop.dup : {} | |
keep = args.shift || "" | |
raise ArgumentError, "Invalid why_are_you_keeping option: #{keep}" unless ProguardTask::KEEP_OPTIONS.member? keep | |
rake_check_options keep_spec, *ProguardTask::KEEP_SPECS[keep] | |
keep_spec[:keep] = keep | |
[:field, :method, :constructor].each do |key| | |
case keep_spec[key] | |
when Hash | |
rake_check_options keep_spec[key], *ProguardTask::MEMBER_SPEC | |
keep_spec[key] = [keep_spec[key]] | |
when Array | |
keep_spec[key].each { |spec| rake_check_options spec, *ProguardTask::MEMBER_SPEC } | |
else | |
keep_spec[key] = [] | |
end | |
end | |
keep_spec | |
end | |
def invoke_prerequisites(args, chain) #:nodoc: | |
sources = @sources.map { |s| s[:artifacts] }.flatten.uniq | |
dependencies = @dependencies.map { |s| s[:artifacts] }.flatten.uniq | |
@prerequisites |= sources + dependencies | |
super | |
end | |
def obfuscate() #:nodoc: | |
Buildr.ant('proguard') do |ant| | |
java_home = ant.project.getProperty("java.home") | |
classpath = Buildr.artifacts(ProguardTask.dependencies).each(&:invoke).map(&:to_s).join(File::PATH_SEPARATOR) | |
ant.taskdef :resource=>'proguard/ant/task.properties', :classpath=> classpath | |
ant.proguard @params do | |
@sources.each do |s| | |
s[:artifacts].each do |a| | |
ant.injar({:path => a.to_s}.merge s[:filter_options]) | |
end | |
end | |
ant.outjar :path => name | |
@dependencies.each do |s| | |
s[:artifacts].each do |a| | |
ant.libraryjar({:path => a.to_s}.merge s[:filter_options]) | |
end | |
end | |
{'keep' => @keep, 'whyareyoukeeping' => @whykeeping}.each do |tag, spec| | |
params = spec.dup | |
keep = params.delete(:keep) | |
field = params.delete(:field) | |
method = params.delete(:method) | |
constructor = params.delete(:constructor) | |
ant.send("#{tag}#{keep}", params) do | |
field.each { |f| ant.field f } | |
method.each { |m| ant.method_missing(:method, m) } | |
constructor.each { |c| ant.constructor c } | |
end | |
end | |
end | |
end | |
end | |
end | |
module ProguardExtension # :nodoc: | |
include Buildr::Extension | |
def obfuscate(file, &block) | |
ProguardTask.define_task(path_to(file)).enhance &block | |
end | |
def package_as_obfuscatedjar(file_name) #:nodoc: | |
dir = File.dirname(file_name) | |
basename = File.basename(file_name, ".jar") | |
jar = package_as_jar("#{dir}/#{basename}-noobf.jar") | |
obfuscate(file_name).include jar | |
end | |
def package_as_obfuscatedjar_spec(spec) #:nodoc: | |
spec[:type] = :jar | |
spec | |
end | |
end | |
end | |
class Buildr::Project | |
include Buildr::ProguardExtension | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment