【问题标题】:Excluding an Ivy dependency conditionally有条件地排除 Ivy 依赖项
【发布时间】:2017-02-06 14:01:39
【问题描述】:

我需要构建一个基于 CI 输出构建项目的自定义 Ant 脚本。我们使用 Atlassian Bamboo 作为 CI 服务器。

通常我们的项目依赖于我们的平台模块,通过 Ivy/Artifactory 管理。

我们典型的 dependencies.xml 文件包含对 that 模块的依赖,可传递。 其他潜在的依赖项。例如,我们的核心模块依赖于很多 Spring 包,但不依赖于 Spring Boot。如果一个项目也需要 Spring Boot,它将在其 dependencies.xml 文件中定义其依赖关系以及 <depencency org="com.acme" name="core-platform"...

我现在的目标是从解析中排除 com.acme#core-platform,因为我正在做一个不同的任务,它使用 Bamboo 输出工件来获取核心模块的最新版本及其依赖项而不通过 Artifactory .

这非常重要,因为在构建期间我可能想更改依赖包的版本(例如,将 Spring 4.3.1 升级到 4.3.3)并使用正确的 Spring 进行测试。如果我只是简单地将依赖关系解析为在 Artifactory 上发布的 com.acme#core-platform#latest.release,我将不会采用已提交给 Git 并在 core-platform 当前正在构建的 dependencies.xml 中提供的 Spring 4.3.3。我希望我的解释容易理解。

假设我以这个依赖列表为例

    com.acme#core-platform#${version}
    org.hibernate#hibernate-java8#5.1.0.Final
    org.springframework.boot#spring-boot-starter-web#1.3.1.RELEASE
    commons-collections#commons-collections#3.2.2
    .... others

完全依赖是

<dependencies>  
    <dependency org="com.acme"              name="core-platform"          rev="${version}"         transitive="true"      conf="runtime->runtime" changing="true"/>
    <dependency org="com.acme"              name="core-platform"          rev="${version}"         transitive="true"      conf="compile->compile" changing="true"/>
    <dependency org="com.acme"              name="core-platform"          rev="${version}"         transitive="true"      conf="provided->provided" changing="true"/>
    <dependency org="com.acme"              name="core-platform"          rev="${version}"         transitive="true"      conf="junit->junit" changing="true"/>
    <dependency org="com.acme"              name="core-platform"          rev="${version}"         transitive="true"      conf="test->test" changing="true"/>



    <!-- https://mvnrepository.com/artifact/org.hibernate/hibernate-java8 -->
    <dependency org="org.hibernate" name="hibernate-java8" rev="5.1.0.Final" transitive="false" />


    <dependency org="org.springframework.boot"  name="spring-boot-starter-web"          rev="1.3.1.RELEASE"                 transitive="false" />
    <dependency org="org.springframework.boot"  name="spring-boot-starter-tomcat"       rev="1.3.1.RELEASE"                 transitive="false" />
    <dependency org="org.springframework.boot"  name="spring-boot-starter-validation"   rev="1.3.1.RELEASE"                 transitive="false" />


    <dependency org="commons-collections"               name="commons-collections"              rev="3.2.2"             transitive="false" />


    <!-- jackson2 libs -->
    <dependency org="com.fasterxml.jackson.datatype"    name="jackson-datatype-jdk8"            rev="2.8.1"             transitive="false"          conf="runtime->*"/>
    <dependency org="com.fasterxml.jackson.datatype"    name="jackson-datatype-jsr310"          rev="2.8.1"             transitive="false"          conf="runtime->*"/>


    <exclude module="joda-time" />
    <exclude module="jackson-datatype-joda" />
</dependencies>

我只是想拿Hibernates的Java8、commons-collections等。

  1. 创建重复的dependencies.xml 不是一个选项
  2. 我正在考虑通过 Ant 操作 dependencies.xml 并让它通过正则表达式排除 acme 模块。可行但很棘手
  3. 很遗憾,我不能将 Ant 任务的 ivy:retrieve 与属性 file 和元素 exclude 结合起来,因为那样会很麻烦

有什么想法吗?

【问题讨论】:

    标签: java ant ivy


    【解决方案1】:

    很难理解您的要求。我怀疑您的问题可以通过创建附加配置并使用配置映射来控制下载来解决。

    示例

    此构建创建两个目录。第一个包含没有传递依赖的 log4j 依赖,第二个包含远程模块的可选依赖。如果您查看远程 POM,您会发现它们具有不同的范围。

    ├── build.xml
    ├── ivy.xml
    ├── lib1
    │   └── log4j-1.2.17.jar
    └── lib2
        ├── activation-1.1.jar
        ├── geronimo-jms_1.1_spec-1.0.jar
        ├── log4j-1.2.17.jar
        └── mail-1.4.3.jar
    

    build.xml

    <project name="demo" default="resolve" xmlns:ivy="antlib:org.apache.ivy.ant">
    
      <target name="resolve">
        <ivy:resolve/>
    
        <ivy:retrieve pattern="lib1/[artifact]-[revision](-[classifier]).[ext]" conf="noDependencies"/>
        <ivy:retrieve pattern="lib2/[artifact]-[revision](-[classifier]).[ext]" conf="withDependencies"/>
      </target>
    
    </project>
    

    注意事项:

    • 每个“检索”任务都会创建一个目录,其中包含构成配置的文件。

    ivy.xml

    <ivy-module version="2.0">
      <info organisation="com.myspotontheweb" module="demo"/>
    
      <configurations>
        <conf name="noDependencies" description="File grouping that has no transitive dependencies"/>
        <conf name="withDependencies" description="File grouping that contains dependencies"/>
      </configurations>
    
      <dependencies>
        <dependency org="log4j" name="log4j" rev="1.2.17" conf="noDependencies->master; withDependencies->master,optional"/>
      </dependencies>
    
    </ivy-module>
    

    注意事项:

    • 请注意配置是如何在 ivy 文件的顶部声明的,并且依赖项包含两个配置映射

    附加

    以下答案解释了 ivy 如何解释 Maven 模块。它创建可用于决定应下载哪些文件的配置:

    【讨论】:

      【解决方案2】:

      好的,看起来替换技巧也很简单。

      1. 在要忽略的 dependencies.xml 文件部分之间添加以下标记 &lt;!-- DEPS START --&gt;&lt;!-- DEPS END --&gt;(或任何选择)
      2. 通过 Ant 破解

        <copy file="dependencies.xml" tofile="ci/hacked-dependencies.xml" overwrite="true">
            <filterchain>
                <replacestring from="&lt;!-- DEPS START --&gt;" to="&lt;!--" />
                <replacestring from="&lt;!-- DEPS END --&gt;" to="--&gt;" />
            </filterchain>
        </copy>
        

      例子

          <!-- DEPS START --> 
          <dependency org="com.acme" name="core-platfrom" rev="${version}" transitive="true" conf="runtime->runtime"/>
          <!-- DEPS END -->
      

      【讨论】:

      • 我怀疑有更好的解决方案。您似乎正在使用配置,为什么不创建额外的映射?让我感到困惑的是,在某些地方您有配置映射,而在其他地方您将传递设置为 false。
      • 是的,transitive=false 是老板规定的旧政策。然而,它有一个意义:我们总是需要完全控制依赖关系,所以升级包的版本不能涉及隐藏的未列出的依赖关系。无论如何,升级在我们的环境中仍然是一个痛苦
      • 当从 Maven 存储库下载到远程“主”配置的映射时,将下载没有依赖关系的工件。其次,您需要考虑使用配置来下载不同的依赖组。我在回答中包含了一个示例。我希望它有助于阐明 ivy 的工作原理并帮助解决您的问题
      猜你喜欢
      • 2017-06-04
      • 2014-06-06
      • 2016-11-20
      • 1970-01-01
      • 2011-11-13
      • 2013-09-08
      • 1970-01-01
      • 2012-11-03
      • 1970-01-01
      相关资源
      最近更新 更多