阿帕奇常春藤。未检索到传递依赖项

Posted

技术标签:

【中文标题】阿帕奇常春藤。未检索到传递依赖项【英文标题】:Apache Ivy. Transitive dependencies not retrieved 【发布时间】:2017-02-23 15:28:56 【问题描述】:

我有以下结构的 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 来检索 AppLib 的依赖项。依赖关系描述如下: ivy.xmlLib

<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.xmlApp:

<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.jarlib-1.0.jar 都会出现在App/lib

实际结果:只有lib-1.0.jar 出现在App/lib 中。为App 生成的常春藤报告不包含任何提及subliblib 的依赖项。在构建期间,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 文件确实包含依赖信息。所以我猜要让它正常工作,我必须在应用程序的分辨率级别上使用缓存。

这有什么意义吗?还是我又明显错了?

【问题讨论】:

ivy:resolve 应该在检索之前调用。你得到什么错误?是否有“配置缺失”之类的东西? 据我所知,没有必要。我看到日志中的[ivy:retrieve] 部分确实执行了解析。我没有收到任何错误,只是缺少传递的 jar 依赖项。 好的(也阅读更新的部分)可以请清除常春藤缓存并再次运行它。还将您用于发布 libsublib 的 ant 脚本添加到问题中。 ivy:cleancacheApp.clean ant 任务期间被显式调用。只是没有提到。我目前正在测试一个想法,如果它工作正常,我会在这里发布。 你能显示你使用的完整的 ant 命令吗? 【参考方案1】:

好的,所以问题确实是错误的配置和我缺乏理解。这是如何使其工作的详细说明。我不太擅长术语,所以我可能在这里误用了一些词。让我们看看项目配置和什么。

Sublib 将成为Lib运行时 依赖项具有编译时 依赖项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 描述了一个运行时依赖的模块。由于 guava 没有这样的文件,我们将其描述为默认文件。这里很标准。现在,为了让其他人知道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 依赖项。现在我们只需通过调用解析器来发布sublibant

<target name="publish">
        <ivy:publish artifactspattern="$dist.dir/[artifact]-[revision].[ext]"
                     resolver="sublib-resolver"
                     overwrite="true"
                     pubrevision="$revision"
        />
</target>

现在到Lib。 Lib 将成为 Appcompile-time 依赖项,我们在 ivy.xml 中对其进行描述,并将 SubLib 声明为它的 runtime 依赖项

<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-&gt;compile 左侧是可以理解的: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>

并在Libbuild.xml 中发布Lib

<target name="publish">
        <ivy:publish artifactspattern="$dist.dir/[artifact]-[revision].[ext]"
                     resolver="lib-resolver"
                     overwrite="true"
                     pubrevision="$revision"
        />
</target>

现在主要问题:及物检索。配置。在Appivy.xml 中,我们需要准确地指定我们想要传递依赖。它们存在存储在 repos 中的信息是不够的。必须在Appivy.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 一起被检索到。


有点凌乱的解释,可能不是最优雅的解决方案,但这是我设法使其正常工作的唯一方法。如果有人知道这样做的更好方法,任何帮助将不胜感激。

【讨论】:

以上是关于阿帕奇常春藤。未检索到传递依赖项的主要内容,如果未能解决你的问题,请参考以下文章

我可以将 JSON 传递给这个 REST API 调用吗?阿帕奇点燃

阿帕奇火花。 UDF 列基于另一列而不将其名称作为参数传递。

错误 2998:未处理的内部错误。空 - 阿帕奇猪

阿帕奇骆驼与阿帕奇卡夫卡[重复]

阿帕奇安装; libpcre 错误

阿帕奇证书配置