如何使用 xsbt-proguard-plugin 排除/包含特定包?
Posted
技术标签:
【中文标题】如何使用 xsbt-proguard-plugin 排除/包含特定包?【英文标题】:How do I exclude/include specific packages using xsbt-proguard-plugin? 【发布时间】:2012-06-01 20:37:03 【问题描述】:我正在使用xsbt-proguard-plugin,这是一个用于与 Proguard 配合使用的 SBT 插件。
我正在尝试为我编写的Hive Deserializer 提供 Proguard 配置,它具有以下依赖项:
// project/Dependencies.scala
val hadoop = "org.apache.hadoop" % "hadoop-core" % V.hadoop
val hive = "org.apache.hive" % "hive-common" % V.hive
val serde = "org.apache.hive" % "hive-serde" % V.hive
val httpClient = "org.apache.httpcomponents" % "httpclient" % V.http
val logging = "commons-logging" % "commons-logging" % V.logging
val specs2 = "org.specs2" %% "specs2" % V.specs2 % "test"
加上一个非托管依赖:
// lib/UserAgentUtils-1.6.jar
因为其中大多数要么用于本地单元测试,要么在 Hadoop/Hive 环境中可用,所以我希望我的缩小 jarfile 只包括:
Java 类 SnowPlowEventDeserializer.class 和 SnowPlowEventStruct.classorg.apache.httpcomponents.httpclient
commons-logging
lib/UserAgentUtils-1.6.jar
但我真的很难让语法正确。我应该从我想要保留的类的白名单开始,还是明确过滤掉 Hadoop/Hive/Serde/Specs2 库?我知道this SO question,但它似乎不适用于这里。
如果我最初尝试白名单方法:
// Should be equivalent to sbt> package
import ProguardPlugin._
lazy val proguard = proguardSettings ++ Seq(
proguardLibraryJars := Nil,
proguardOptions := Seq(
"-keepattributes *Annotation*,EnclosingMethod",
"-dontskipnonpubliclibraryclassmembers",
"-dontoptimize",
"-dontshrink",
"-keep class com.snowplowanalytics.snowplow.hadoop.hive.SnowPlowEventDeserializer",
"-keep class com.snowplowanalytics.snowplow.hadoop.hive.SnowPlowEventStruct"
)
)
然后我得到一个 Hadoop 处理错误,很明显 Proguard 仍在尝试捆绑 Hadoop:
proguard: java.lang.IllegalArgumentException: Can't find common super class of [[Lorg/apache/hadoop/fs/FileStatus;] and [[Lorg/apache/hadoop/fs/s3/Block;]
同时,如果我尝试 Proguard's filtering syntax 建立我不想包含的库的黑名单:
import ProguardPlugin._
lazy val proguard = proguardSettings ++ Seq(
proguardLibraryJars := Nil,
proguardOptions := Seq(
"-keepattributes *Annotation*,EnclosingMethod",
"-dontskipnonpubliclibraryclassmembers",
"-dontoptimize",
"-dontshrink",
"-injars !*hadoop*.jar"
)
)
那么这似乎也不起作用:
proguard: java.io.IOException: Can't read [/home/dev/snowplow-log-deserializers/!*hadoop*.jar] (No such file or directory)
非常感谢任何帮助!
【问题讨论】:
【参考方案1】:白名单是正确的方法:ProGuard 应该获得完整的上下文,这样它就可以正确地剔除不需要的类、字段和方法。
错误“找不到公共超类”表明输入中仍然缺少某些库。 ProGuard 可能警告过它,但配置似乎包含选项 -ignorewarnings 或 -dontwarn (应该避免)。您应该使用 -injars 或 -libraryjars 添加库。
如果 ProGuard 然后在输出中包含一些您不期望的类,您可以使用“-whyareyoukeeping class somepackage.SomeUnexpectedClass”获得解释。
从工作配置开始,您仍然可以尝试从输入中过滤掉类或整个 jar。过滤器被添加到类路径中的项目中,而不是单独添加,例如“-injars some.jar(!somepackage/**.class)”——cfr。手册。如果输入包含拖入其他不需要的类的测试类,这将很有用。
【讨论】:
感谢 Eric,感谢您的帮助。最后,我无法超越重复的类错误,更不用说排除特定的罐子了。当我在 SBT 中有一个简单的依赖项列表时,排除特定的 jar 似乎也有点笨拙,我宁愿使用/注释以包含/排除。最后我采用了 sbt-assembly 方法,见下文。【参考方案2】:最后,我无法使用 Proguard 解决重复的类错误,更不用说如何弄清楚如何过滤掉相关的 jar,所以最终切换到更干净的 sbt-assembly 方法:
-1。根据README,将 sbt-assembly 插件添加到我的项目中
-2。使用 "provided"
标志更新了适当的项目依赖项,以阻止它们被添加到我的胖 jar 中:
val hadoop = "org.apache.hadoop" % "hadoop-core" % V.hadoop % "provided"
val hive = "org.apache.hive" % "hive-common" % V.hive % "provided"
val serde = "org.apache.hive" % "hive-serde" % V.hive % "provided"
val httpClient = "org.apache.httpcomponents" % "httpclient" % V.http
val httpCore = "org.apache.httpcomponents" % "httpcore" % V.http
val logging = "commons-logging" % "commons-logging" % V.logging % "provided"
val specs2 = "org.specs2" %% "specs2" % V.specs2 % "test"
-3。添加了一个 sbt-assembly 配置,如下所示:
import sbtassembly.Plugin._
import AssemblyKeys._
lazy val sbtAssemblySettings = assemblySettings ++ Seq(
assembleArtifact in packageScala := false,
jarName in assembly <<= (name, version) (name, version) => name + "-" + version + ".jar" ,
mergeStrategy in assembly <<= (mergeStrategy in assembly)
(old) =>
case "META-INF/NOTICE.txt" => MergeStrategy.discard
case "META-INF/LICENSE.txt" => MergeStrategy.discard
case x => old(x)
)
然后输入 assembly
生成一个“胖 jar”,其中只包含我需要的包,包括非托管依赖项,不包括 Hadoop/Hive 等。
【讨论】:
以上是关于如何使用 xsbt-proguard-plugin 排除/包含特定包?的主要内容,如果未能解决你的问题,请参考以下文章
在 SBT 中将 unmanagedJars 添加到 proguardLibraryJars