Maven使用本地JAR文件

Maven,如果想要修改底层依赖的库,先clone下来修改构建,然后使用本地JAR文件。StackOverflow的高票回答里有一些坑。记录一下。

背景

Soot加载新的APK总是报错,而且报错了就停了。能不能让它忽略当前报错,直接放弃当前method body呢?基于这个想法我开始修改soot源码,最后的方案在这个commit

遇到的问题

编译时跳过测试

修改了Soot代码,直接编译会说一些测试异常。使用mvn -Dmaven.test.skip=true package在打包时跳过异常。

maven引用本地jar文件

  • 基于scope=system的方式

网上搜索首先会看到这个回答,它推荐使用system类型的依赖:

1
2
3
4
5
6
7
<dependency>
<groupId>com.sample</groupId>
<artifactId>sample</artifactId>
<version>1.0</version>
<scope>system</scope>
<systemPath>${project.basedir}/src/main/resources/Name_Your_JAR.jar</systemPath>
</dependency>

然而,再看看就发现很多地方说这种方式不好,比如已经depricated了。直接劝退我的,是我用的shaded插件(和依赖一起打包为一个jar),不会把这种依赖加进来,直接报错找不到Soot.G这个类。

  • 基于mvn install:install-file的方式

于是采用回答里的第二种方法,安装到本地maven缓存。

1
2
3
4
5
6
7
mvn install:install-file \
-Dfile=$SCRIPTPATH/sootclasses-trunk.jar \
-DgroupId=org.soot-oss \
-DartifactId=soot \
-Dversion=4.5.0-SNAPSHOT1 \
-Dpackaging=jar \
-DgeneratePom=true

问题在于,这种方式引入的依赖似乎不会引入递归的依赖。比如我发现缺了很多soot的依赖。

  • 基于maven-install-plugin的方式

根据官方文档,如果那边jar是maven构建的,则可以使用下面这种方式直接安装到本地缓存,因为读取了jar里的pom.xml文件。既然都有了pom了,依赖信息也在了。但是坑点是版本要改成3.0.1以上,因为其实这个是个已知的问题,很晚才修复。这个comment救了我。

1
2
3
# 删除本地的缓存
# mvn dependency:purge-local-repository -DmanualInclude="org.soot-oss:soot"
mvn org.apache.maven.plugins:maven-install-plugin:3.0.1:install-file -Dfile=$SCRIPTPATH/sootclasses-trunk.jar

最后发现怎么还是在跑的旧代码,可能是shaded插件的问题。还是得删掉targets文件夹。

检查依赖问题

使用mvn dependency:tree可以打印树状的依赖图

VSCode Java插件关联本地代码

根据这个issue里说的,看来只能在那边创建-src后缀的jar文件,可能要同时放到本地maven仓库?

总体构建脚本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#!/bin/bash
# 获取脚本当前路径
SCRIPTPATH="$( cd -- "$(dirname "$0")" >/dev/null 2>&1 ; pwd -P )"

# 防止还是用的旧的库
rm -rf $SCRIPTPATH/target

pushd ~/soot
# 生成patch留存
git diff --cached > $SCRIPTPATH/mypatch.patch
# 构建依赖的库的jar包
mvn -Dmaven.test.skip=true package
cp target/sootclasses-trunk.jar $SCRIPTPATH/
mvn org.apache.maven.plugins:maven-install-plugin:3.0.1:install-file -Dfile=$SCRIPTPATH/sootclasses-trunk.jar
popd

# 构建真正的项目
mvn package