[英]Apache Ivy. Transitive dependencies not retrieved
我有以下结构的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
的依赖项。 依赖关系描述如下: Lib
ivy.xml
:
<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>
App
ivy.xml
:
<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
实际结果: App/lib
只存在lib-1.0.jar
。 生成的ivy-report for App
不包含任何提及sublib
是lib
的依赖项。 在构建期间,ant + ivy日志中没有任何类型。
注意: lib-1.0.jar
不是作为fat-jar构建的。
我在这个配置中缺少什么?
更新
我做了一些思考,我得出的唯一结论是这个问题确实是错误的配置。 从事实来看,没有检索到传递依赖,我们可以肯定地说,当它解析lib
时,常春藤没有任何类型的信息。 这是有道理的,因为Lib/dist
文件夹可以在文件系统中的任何位置。 获得有关传递依赖的信息的唯一方法是在该jar附近的某个地方放置相应的ivy.xml
。 哪个不是。 日志[ivy:retrieve] local: no ivy file found for com.test.lib#lib;1.0: using default data
的消息稍微证实了这一点[ivy:retrieve] local: no ivy file found for com.test.lib#lib;1.0: using default data
。 保留信息的唯一方法是%user%/.ivy/cache
。 生成的[org]-[artifact]-[conf].xml
文件确实包含依赖项信息。 所以我猜这是为了正常工作,我将不得不在App的分辨率级别上使用缓存。
这有什么意义还是我明显错了?
好吧,问题确实是错误的配置和我对它的理解不足。 以下是如何使其工作的详细说明。 我的术语不是很好,所以我可能在这里误用了一些词。 让我们看一下项目配置以及它是什么。
Sublib
将成为具有编译时依赖关系guava
Lib
的运行时依赖项。
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
形式存在于罐。 我选择发布到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
依赖。 现在我们通过调用我们的解析器来发布带有ant
的sublib
:
<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>
这里是配置发挥作用的地方以及我最初不理解的地方。 runtime->compile
左手边是可以理解的: sublib
被声明为运行时依赖项,我们将它分配给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
我们需要准确指出我们想要传递依赖。 存储在存储库中的信息是不够的。 必须在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
一起被检索出来。
一个有点凌乱的解释,可能不是最优雅的解决方案,但它是我设法使这项工作正常的唯一方法。 如果有人知道任何更好的方法,任何帮助将不胜感激。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.