简体   繁体   English

Apache常春藤。 未检索传递依赖项

[英]Apache Ivy. Transitive dependencies not retrieved

I have 3 projects of the following structure: 我有以下结构的3个项目:

App
|  |
  ...
|  |
|  +--lib
|  |    |
|  |    +--...
|  |
|  +--dist
|
Lib
|  |
   ...
|  |
|  +--lib
|  |    |
|  |    +--sublib-1.0.jar
|  |
|  +--dist
|       |
|       +--lib-1.0.jar
|
SubLib
   |
  ... 
   |
   +--dist
        |
        +--sublib-1.0.jar

Which have the following relation: 其中有以下关系:

App <-- Lib <-- SubLib

I am using apache ivy to retrieve the dependencies for both App and Lib . 我正在使用apache ivy来检索AppLib的依赖项。 The dependencies are described as follows: ivy.xml of 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>

ivy.xml of App : 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.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>

Expected result: after executing ivy:retrieve , both sublib-1.0.jar and lib-1.0.jar to be present in App/lib 预期结果:执行ivy:retrievesublib-1.0.jarlib-1.0.jar都出现在App/lib

Actual result: only lib-1.0.jar is present in App/lib . 实际结果: App/lib只存在lib-1.0.jar The generated ivy-report for App does not contain any mention of sublib being a dependency of lib . 生成的ivy-report for App不包含任何提及subliblib的依赖项。 Nothing of a sort is in ant + ivy logs during build as well. 在构建期间,ant + ivy日志中没有任何类型。

Note: lib-1.0.jar is not being built as a fat-jar. 注意: lib-1.0.jar不是作为fat-jar构建的。

What am I missing in this configuration? 我在这个配置中缺少什么?


Update 更新

I've done some thinking, and the only conclusion I came with is that this problem is indeed misconfiguration. 我做了一些思考,我得出的唯一结论是这个问题确实是错误的配置。 Judging by the fact, that transitive dependency is not retrieved, we can positively say that ivy does not have any information of a sort when it resolves lib . 从事实来看,没有检索到传递依赖,我们可以肯定地说,当它解析lib时,常春藤没有任何类型的信息。 And that makes sense, because Lib/dist folder could be anywhere in the file system. 这是有道理的,因为Lib/dist文件夹可以在文件系统中的任何位置。 The only way to have information about transitive dependency would be having respective ivy.xml somewhere close to that jar. 获得有关传递依赖的信息的唯一方法是在该jar附近的某个地方放置相应的ivy.xml Which is not. 哪个不是。 This is slightly confirmed by the message in logs [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的消息稍微证实了这一点[ivy:retrieve] local: no ivy file found for com.test.lib#lib;1.0: using default data The only way that information is preserved is cache data in %user%/.ivy/cache . 保留信息的唯一方法是%user%/.ivy/cache There the generated [org]-[artifact]-[conf].xml files do contain the dependency information. 生成的[org]-[artifact]-[conf].xml文件确实包含依赖项信息。 So I'm guessing for that to work properly, I will have to use cache on App's resolution level. 所以我猜这是为了正常工作,我将不得不在App的分辨率级别上使用缓存。

Does that make any sense or am I plainly wrong again? 这有什么意义还是我明显错了?

Ok, so the problem was indeed the bad configuration and my lack of understanding it. 好吧,问题确实是错误的配置和我对它的理解不足。 Here is the detailed explanation how to make it work. 以下是如何使其工作的详细说明。 I'm not really good with terminology, so I may have misused some words here. 我的术语不是很好,所以我可能在这里误用了一些词。 Let's look at project configuration and what's what. 让我们看一下项目配置以及它是什么。

Sublib is going to be a runtime dependency for Lib that has a compile-time dependency guava . Sublib将成为具有编译时依赖关系guava Lib运行时依赖项。

SubLib
   |  `lib
   |      `guava-19.0.jar
   |
    `dist
   |    `--sublib-1.0.jar
   |
    `src
        `...

So, we need to make appropriate configurations in SubLib's ivy.xml : 因此,我们需要在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>

Here, by declaring a runtime configuration we state that this ivy.xml describes a module that is a runtime-time dependency. 这里,通过声明runtime配置,我们声明此ivy.xml描述了一个运行时依赖的模块。 And since guava has no such file we describe it as default. 由于番石榴没有这样的文件,我们将其描述为默认值。 Pretty standard here. 这里很标准。 Now, for others to know that sublib-1.0.jar actually has a dependency from guava-19.0.jar we need to publish it to a repository, so that such information exists in form of file ivy-[version].xml next to the jar. 现在,让其他人知道sublib-1.0.jar实际上有一个来自guava-19.0.jar的依赖,我们需要将它发布到一个存储库,以便这些信息以文件ivy-[version].xml形式存在于罐。 I chose to publish into the build folder. 我选择发布到build文件夹。 To do so, ivysettings.xml needs to contain a resolver that helps to match file patterns for publishing and later on on retrieval when we'll resolve from Lib . 为此, 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 will allow to find the corresponding ivy-[revision].xml that has information about the dependencies and the location of jar . sublib-resolver将允许查找相应的ivy-[revision].xml ,其中包含有关jar的依赖关系和位置的信息。 Whereas filesystem-resolver will find our guava dependency. filesystem-resolver将找到我们的guava依赖。 Now we just publish sublib with ant by invoking our resolver: 现在我们通过调用我们的解析器来发布带有antsublib

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

Now to Lib . 现在到了Lib Lib is going to be a compile-time dependency for App and we describe it as such in ivy.xml and declare SubLib as a runtime dependency for it: 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>

Here's where configuration comes in play and what I didn't understand at first. 这里是配置发挥作用的地方以及我最初不理解的地方。 runtime->compile Left hand side is understandable: sublib was declared as a runtime dependency and we assigned it to runtime conf in it's ivy file. runtime->compile左手边是可以理解的: sublib被声明为运行时依赖项,我们将它分配给runtime conf在它的常春藤文件中。 On the arrow's right hand side we state that we want sublib 's compile-time dependencies as well. 在箭头的右侧,我们声明我们也想要sublib的编译时依赖项。 And the one that was configured as such is guava . 而那样配置的就是guava It will be found by the resolver and retrieved as well. 它将由解析器找到并检索。 So, we need a resolver for Lib as well, so complete ivysettings.xml file will look like this: 所以,我们也需要一个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>

And publish of Lib in Lib 's build.xml : 并在Libbuild.xml发布Lib

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

Now to the main problem: transitive retrieval. 现在主要问题是:传递检索。 Configurations. 配置。 In App 's ivy.xml we need to specify exactly that we want transitive dependencies. Appivy.xml我们需要准确指出我们想要传递依赖。 The information that they exist stored in repos is not enough. 存储在存储库中的信息是不够的。 One must specify it in App 's ivy.xml : 必须在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>

What happens here is the following: by declaring compile conf we state that App has a compile configuration. 这里发生的是:通过声明compile conf我们声明App有一个编译配置。 The first arrow chain, like before, states that we (compile-configured module App ) want to get compile-configured dependency called lib . 与之前一样,第一个箭头链表明我们(编译配置的模块App )想要获得名为lib编译配置依赖项。 Left and right arrow sides respectively. 分别为左右箭头两侧。 And the second arrow set states that we (compile-configured module App ) want to get runtime-configured dependencies of lib ! 第二个箭头集指出我们(编译配置的模块App )想要获得运行时配置的lib依赖项 Which is sublib . 哪个是sublib And since it comes together with guava it is retrieved as well. 而且由于它与guava一起被检索出来。


A little messy explanation, and may very not be the most elegant one for a solutioin, but it's the only way I managed to make this work properly at all. 一个有点凌乱的解释,可能不是最优雅的解决方案,但它是我设法使这项工作正常的唯一方法。 If anyone knows any better ways of doing so, any help would be appreciated. 如果有人知道任何更好的方法,任何帮助将不胜感激。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM