Warning: can’t write resource [META-INF/MANIFEST.MF] (Duplicate zip entry [yyy.jar:META-INF/MANIFEST

Warning: can’t write resource [META-INF/MANIFEST.MF] (Duplicate zip entry [yyy.jar:META-INF/MANIFEST转自:http://www.dancartoon.com/2012/01/14/fixing-proguard-warning-cant-write-resource-meta-infmanifest-mf/转自:We’reusing ProGuard inourAndroidbuildandweregettinganumberofwarningsr

Warning:

转自:http://www.dancartoon.com/2012/01/14/fixing-proguard-warning-cant-write-resource-meta-infmanifest-mf/转自:

We’re using ProGuard in our Android build and were getting a number of warnings regarding duplicate entries in the output jar. When ProGuard encounters resources in an input jar, it will by default copy the resources into the output jar. This is fine as long as you don’t have multiple jars that contain resources with the same name. All jars(that I’m aware of) have manifest files, so attempting to use ProGuard with multiple input jars will cause warnings that look like: “Warning: can’t write resource [META-INF/MANIFEST.MF] (Duplicate zip entry [yyy.jar:META-INF/MANIFEST.MF])”.

The warnings are harmless, but a clean build is a happy build, so we might as well try and get rid of them. The ProGuard Manual actually describes what needs to be done, but it only provides a solution for the case where input jars are specified individually:

123
         
         
         
         
-injars in1.jar
-injars in2.jar(!META-INF/MANIFEST.MF)
-injars in3.jar(!META-INF/MANIFEST.MF)

view raw
gistfile1.txt hosted with ❤ by 
GitHub

When using ProGuard in the Android build process, the default behavior is to pass in all input jars in a giant delimited(semi-colon on Windows) blob. I have done some experimentation, but was unable to determine how an input filter can be used when multiple jars(having absolute paths) are passed in this way. Fortunately, it’s not too difficult to change the build process to pass in a list of input jars individually and with individual filters.

This is the relevant section of the standard Android build.xml(starting around line 700):

123456789101112131415161718192021222324252627282930313233
         
         
         
         
<!-- Build a path object with all the jar files that must be obfuscated.
This include the project compiled source code and any 3rd party jar
files. -->
<path id= "project.jars.ref" >
<pathelement location= "${preobfuscate.jar.file}" />
<path refid= "jar.libs.ref" />
</path>
<!-- Set the project jar files Path object into a single property. It'll be
all the jar files separated by a platform path-separator.
Each path must be quoted if it contains spaces.
-->
<pathconvert property= "project.jars" refid= "project.jars.ref" >
<firstmatchmapper>
<regexpmapper from= '^([^ ]*)( .*)$$' to= '"\1\2"' />
<identitymapper/>
</firstmatchmapper>
</pathconvert>
 
<mkdir dir= "${obfuscate.absolute.dir}" />
<delete file= "${preobfuscate.jar.file}" />
<delete file= "${obfuscated.jar.file}" />
<jar basedir= "${out.classes.absolute.dir}"
destfile= "${preobfuscate.jar.file}" />
<proguard>
@${proguard.config}
-injars ${project.jars}
-outjars "${obfuscated.jar.file}"
-libraryjars ${android.libraryjars}
-dump "${obfuscate.absolute.dir}/dump.txt"
-printseeds "${obfuscate.absolute.dir}/seeds.txt"
-printusage "${obfuscate.absolute.dir}/usage.txt"
-printmapping "${obfuscate.absolute.dir}/mapping.txt"
</proguard>

view raw
gistfile1.xml hosted with ❤ by 
GitHub

The directives above create a new object that combines the location of the compiled jar along with other jars that were used during compilation. These locations are then joined into a string by the pathconvert task, which also does some transformation to ensure that paths containing spaces are quoted properly. Finally, the string from pathconvert(stored in project.jars) is passed into proguard via the statement: “-injars ${project.jars}”

Update(2013/02/11): paulpv has provided an updated config since the Android build system has changed since my original post. I have included his config here:

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394
         
         
         
         
<?xml version="1.0" encoding="UTF-8"?>
<project name= "custom_rules" >
<!--
Suppress "Warning: can't write resource [META-INF/MANIFEST.MF] (Duplicate zip entry [classes.jar:META-INF/MANIFEST.MF])".
Per http://www.dancartoon.com/2012/01/14/fixing-proguard-warning-cant-write-resource-meta-infmanifest-mf/
Target "-obfuscate" copied from ${sdk.dir}/tools/ant/build.xml v21.
-->
<target name= "-obfuscate" >
<if condition= "${proguard.enabled}" >
<then>
<property name= "obfuscate.absolute.dir" location= "${out.absolute.dir}/proguard" />
<property name= "preobfuscate.jar.file" value= "${obfuscate.absolute.dir}/original.jar" />
<property name= "obfuscated.jar.file" value= "${obfuscate.absolute.dir}/obfuscated.jar" />
<!-- input for dex will be proguard's output -->
<property name= "out.dex.input.absolute.dir" value= "${obfuscated.jar.file}" />
<!-- Add Proguard Tasks -->
<property name= "proguard.jar" location= "${android.tools.dir}/proguard/lib/proguard.jar" />
<taskdef name= "proguard" classname= "proguard.ant.ProGuardTask" classpath= "${proguard.jar}" />
<!-- Set the android classpath Path object into a single property. It'll be
all the jar files separated by a platform path-separator.
Each path must be quoted if it contains spaces.
-->
<pathconvert property= "project.target.classpath.value" refid= "project.target.class.path" >
<firstmatchmapper>
<regexpmapper from= '^([^ ]*)( .*)$$' to= '"\1\2"' />
<identitymapper/>
</firstmatchmapper>
</pathconvert>
<!-- Build a path object with all the jar files that must be obfuscated.
This include the project compiled source code and any 3rd party jar
files. -->
<path id= "project.all.classes.path" >
<pathelement location= "${preobfuscate.jar.file}" />
<path refid= "project.all.jars.path" />
</path>
<!-- Set the project jar files Path object into a single property. It'll be
all the jar files separated by a platform path-separator.
Each path must be quoted if it contains spaces.
-->
<!--
Old:
<pathconvert property="project.all.classes.value" refid="project.all.classes.path">
New:
-->
<pathconvert property= "project.all.classes.value" refid= "project.all.jars.path" pathsep= " " >
<firstmatchmapper>
<!--
Old:
<regexpmapper from='^([^ ]*)( .*)$$' to='"\1\2"'/>
<identitymapper/>
New:
-->
<regexpmapper from= '^([^ ]*)( .*)$$' to= '-injars "\1\2"(!META-INF/MANIFEST.MF)' />
<regexpmapper from= '(.*)' to= '-injars \1(!META-INF/MANIFEST.MF)' />
</firstmatchmapper>
</pathconvert>
<!-- Turn the path property ${proguard.config} from an A:B:C property
into a series of includes: -include A -include B -include C
suitable for processing by the ProGuard task. Note - this does
not include the leading '-include "' or the closing '"'; those
are added under the <proguard> call below.
-->
<path id= "proguard.configpath" >
<pathelement path= "${proguard.config}" />
</path>
<pathconvert pathsep= '" -include "' property= "proguard.configcmd" refid= "proguard.configpath" />
<echo>proguard: $${project.all.classes.value}=${project.all.classes.value} </echo>
<mkdir dir= "${obfuscate.absolute.dir}" />
<delete file= "${preobfuscate.jar.file}" />
<delete file= "${obfuscated.jar.file}" />
<jar basedir= "${out.classes.absolute.dir}"
destfile= "${preobfuscate.jar.file}" />
<proguard>
-include "${proguard.configcmd}"
-include "${out.absolute.dir}/proguard.txt"
-injars ${preobfuscate.jar.file}
${project.all.classes.value}
-outjars "${obfuscated.jar.file}"
-libraryjars ${project.target.classpath.value}
-dump "${obfuscate.absolute.dir}/dump.txt"
-printseeds "${obfuscate.absolute.dir}/seeds.txt"
-printusage "${obfuscate.absolute.dir}/usage.txt"
-printmapping "${obfuscate.absolute.dir}/mapping.txt"
</proguard>
</then>
</if>
</target>
</project>

view raw
custom_rules.xml hosted with ❤ by 
GitHub

The goal of my changes is to preserve the manifest files from the original jar(“preobfuscate.jar.file”) and ignore(filter) the manifest files from the remaining input jar files. Since I haven’t figured out how to filter input jars when passed in as a blob, I instead use the pathconvert task to transform each input jar location into a separate “-injars” statement with its own manifest filter. The property containing these locations is then passed into ProGuard directly via: “${project.jars}”

The solution isn’t as clean as I would have liked, but it does fix the warnings.

今天的文章Warning: can’t write resource [META-INF/MANIFEST.MF] (Duplicate zip entry [yyy.jar:META-INF/MANIFEST分享到此就结束了,感谢您的阅读,如果确实帮到您,您可以动动手指转发给其他人。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
如需转载请保留出处:https://bianchenghao.cn/33788.html

(0)
编程小号编程小号

相关推荐

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注