我有以下结构的3个项目:
App
| |
...
| |
| +--lib
| | |
| | +--...
| |
| +--dist
|
Lib
| |
...
| |
| +--lib
| | |
| | +--sublib-1.0.jar
| |
| +--dist
| |
| +--lib-1.0.jar
|
SubLib
|
...
|
+--dist
|
+--sublib-1.0.jar
有以下关系:
App <-- Lib <-- SubLib
我使用apache ivy来检索App
和Lib
的依赖项。依赖关系描述如下:ivy.xml
/Lib
:
<ivy-module version = "2.0">
<info organisation = "com.test.lib" module = "lib"/>
<dependencies>
<dependency org = "com.test.sub.lib" name = "sublib" rev = "1.0" conf = "compile->default"/>
</dependencies>
</ivy-module>
ivy.xml
of App
:
<ivy-module version = "2.0">
<info organisation = "com.test.app" module = "App"/>
<dependencies>
<dependency org = "com.test.lib" name = "lib" rev = "1.0" conf = "compile->default"/>
</dependencies>
</ivy-module>
ivysettings.xml
:
<ivysettings>
<settings defaultResolver = "local"/>
<resolvers>
<filesystem name = "local">
<artifact pattern = "${ivy.settings.dir}/SubLib/dist/[artifact]-[revision].[ext]"/>
<artifact pattern = "${ivy.settings.dir}/Lib/dist/[artifact]-[revision].[ext]"/>
</filesystem>
</resolvers>
<modules>
<module organisation = "com.test.ivytest" resolver = "local"/>
</modules>
</ivysettings>
预期结果:执行ivy:retrieve
后,sublib-1.0.jar
和lib-1.0.jar
同时存在于App/lib
实际结果:只有lib-1.0.jar
存在于App/lib
中。为App
生成的ivy-report没有提到sublib
是lib
的依赖项。在构建期间,ant + ivy日志中也没有任何类型的日志。
注意: lib-1.0.jar
没有被构建为fat-jar。
我在这个配置中缺少什么?
更新
我已经做了一些思考,我得到的唯一结论是,这个问题确实是错误配置。根据没有检索到传递依赖的事实判断,我们可以肯定地说,ivy在解析lib
时没有任何类型的信息。这是有道理的,因为Lib/dist
文件夹可以在文件系统中的任何位置。获得传递依赖信息的唯一方法是将各自的ivy.xml
放在靠近该jar的某个地方。事实并非如此。日志[ivy:retrieve] local: no ivy file found for com.test.lib#lib;1.0: using default data
中的消息稍微证实了这一点。保存信息的唯一方法是在%user%/.ivy/cache
中缓存数据。生成的[org]-[artifact]-[conf].xml
文件确实包含依赖项信息。所以我猜为了正常工作,我将不得不在应用程序的分辨率级别上使用缓存。
这有什么意义吗?还是我又错了?
好吧,所以问题确实是糟糕的配置和我缺乏理解。下面是如何使其工作的详细解释。我不太擅长术语,所以我可能在这里用错了一些词。让我们来看看项目的配置和是什么。
Sublib
将成为Lib
运行时依赖项,而CC_25 有编译时依赖项guava
。
SubLib
| `lib
| `guava-19.0.jar
|
`dist
| `--sublib-1.0.jar
|
`src
`...
因此,我们需要在SubLib的ivy.xml
:
中进行适当的配置。<ivy-module version="2.0">
<info organisation="com.test.sub.lib" module="sublib"/>
<configurations>
<conf name="runtime" visibility="public"/>
</configurations>
<dependencies>
<dependency org="com.google" name="guava" rev="19.0" conf="runtime->default"/>
</dependencies>
</ivy-module>
在这里,通过声明一个runtime
配置,我们声明这个ivy.xml
描述了一个运行时依赖的模块。由于番石榴没有这样的文件,我们将其描述为默认的。这很标准。现在,为了让其他人知道sublib-1.0.jar
实际上依赖于guava-19.0.jar
,我们需要将其发布到存储库中,以便这些信息以文件ivy-[version].xml
的形式存在于jar旁边。我选择发布到build
文件夹。要做到这一点,ivysettings.xml
需要包含一个解析器,它可以帮助匹配发布和检索时的文件模式,当我们将从Lib
解析时。
<ivysettings>
<settings defaultResolver="filesystem-resolver"/>
<resolvers>
<filesystem name="sublib-resolver">
<ivy pattern="${ivy.settings.dir}/SubLib/dist/repo/ivy-[revision].xml"/>
<artifact pattern="${ivy.settings.dir}/SubLib/dist/repo/[artifact]-[revision].[ext]"/>
</filesystem>
<filesystem name="filesystem-resolver">
<artifact pattern="${ivy.settings.dir}/SubLib/lib/[artifact]-[revision].[ext]"/>
</filesystem>
</resolvers>
<modules>
<module name="sublib" organisation="com.test.sub.lib" resolver="sublib-resolver"/>
</modules>
</ivysettings>
sublib-resolver
将允许找到相应的ivy-[revision].xml
,其中包含有关jar
的依赖关系和位置的信息。而filesystem-resolver
将找到我们的guava
依赖。现在我们只需通过调用解析器来发布sublib
和ant
:
<target name="publish">
<ivy:publish artifactspattern="${dist.dir}/[artifact]-[revision].[ext]"
resolver="sublib-resolver"
overwrite="true"
pubrevision="${revision}"
/>
</target>
现在到Lib
。Lib将成为App
的编译时依赖项,我们在ivy.xml
中这样描述它,并声明SubLib
为运行时依赖项:
<ivy-module version="2.0">
<info organisation="com.test.lib" module="lib"/>
<configurations>
<conf name="compile" visibility="public"/>
<conf name="runtime" extends="compile" visibility="public"/>
</configurations>
<dependencies>
<dependency org="com.test.sub.lib" name="sublib" rev="2.0" conf="runtime->compile"/>
</dependencies>
</ivy-module>
这就是配置发挥作用的地方,也是我一开始不理解的地方。左边是可以理解的:sublib
被声明为运行时依赖,我们在它的ivy文件中将它分配给runtime
conf。在箭头的右侧,我们声明我们也需要sublib
的编译时依赖项。这样配置的是guava
。它将被解析器找到并检索。所以,我们也需要一个Lib
的解析器,所以完整的ivysettings.xml
文件看起来像这样:
<ivysettings>
<properties file="${ivy.settings.dir}/ivysettings.properties"/>
<settings defaultResolver="filesystem-resolver"/>
<resolvers>
<filesystem name="sublib-resolver">
<ivy pattern="${ivy.settings.dir}/SubLib/dist/repo/ivy-[revision].xml"/>
<artifact pattern="${ivy.settings.dir}/SubLib/dist/repo/[artifact]-[revision].[ext]"/>
</filesystem>
<filesystem name="lib-resolver">
<ivy pattern="${ivy.settings.dir}/Lib/dist/repo/ivy-[revision].xml"/>
<artifact pattern="${ivy.settings.dir}/Lib/dist/repo/[artifact]-[revision].[ext]"/>
</filesystem>
<filesystem name="filesystem-resolver">
<artifact pattern="${ivy.settings.dir}/SubLib/lib/[artifact]-[revision].[ext]"/>
</filesystem>
</resolvers>
<modules>
<module name="sublib" organisation="com.test.sub.lib" resolver="sublib-resolver"/>
<module name="lib" organisation="com.test.lib" resolver="lib-resolver"/>
</modules>
</ivysettings>
并在Lib
的build.xml
中发布Lib
:
<target name="publish">
<ivy:publish artifactspattern="${dist.dir}/[artifact]-[revision].[ext]"
resolver="lib-resolver"
overwrite="true"
pubrevision="${revision}"
/>
</target>
现在讨论主要问题:传递检索。配置。在App
的ivy.xml
中,我们需要精确地指定我们想要的传递依赖。它们存在的信息存储在repos中是不够的。必须在App
的ivy.xml
:
<configurations>
<conf name="compile" visibility="public"/>
</configurations>
<dependencies>
<dependency org="com.test.lib" name="lib" rev="1.0" conf="compile->compile; compile->runtime"/>
</dependencies>
这里发生的事情如下:通过声明compile
conf,我们声明App
具有编译配置。第一个箭头链,像前面一样,声明我们(编译配置模块App
)想要获得称为lib
的编译配置依赖项。箭头的左右两侧。第二个箭头集表示我们(编译配置的模块App
)希望获得lib
的运行时配置的依赖项!也就是sublib
。由于它与guava
一起出现,它也被检索。
一个有点混乱的解释,可能不是最优雅的解决方案,但这是我设法使它正常工作的唯一方法。如果有人知道更好的方法,我将不胜感激。