Apache Ivy之在多项目环境中使用Ivy


前言

在上一个教程中,您看到了如何处理两个简单项目之间的依赖关系。
本教程将指导您在更复杂的环境中使用Ivy。本教程的所有代码都可以在Ivy发行版的src/example/multi-project目录中找到。

一、Context

Here is a 10000 ft overview of the projects involved in this tutorial:
以下是本教程所涉及项目的10000 ft概述:

  • version
    helps to identify module by a version(帮助按版本标识模块)

  • list
    gives a list of files in a directory (recursively)(给出目录中文件的列表(递归))

  • size
    gives the total size of all files in a directory, or of a collection of files(给出目录中所有文件或文件集合的总大小)

  • find
    find files in a given dir or among a list of files which match a given name(在给定目录中或在与给定名称匹配的文件列表中查找文件)

  • sizewhere
    gives the total size of files matching a name in a directory(提供目录中与名称匹配的文件的总大小)

  • console
    give access to all other modules features through a simple console app(通过简单的控制台应用程序访问所有其他模块功能)

For sure this is not aimed to demonstrate how to develop a complex app or give indication of advanced algorithm(当然,这不是为了演示如何开发一个复杂的应用程序或给出先进算法的指示)

But this gives a simple understanding of how Ant+Ivy can be used to develop an application divided in multiple modules.(但这让我们简单地了解了如何使用Ant+Ivy来开发一个分为多个模块的应用程序。)

Now, here is how these modules relate to each other:
(现在,这些模块是如何相互关联的:)
在这里插入图片描述
黄色的模块是本教程中描述的模块,蓝色的模块是外部依赖项(我们将在本教程后面看到如何生成此图)。
如您所见,我们这里有一组非常有趣的模块,它们彼此之间具有依赖关系,每个模块都依赖于其他模块的最新版本。

二、The example files

本教程的源代码可以在Ivy发行版的src/example/multi-project中找到。在此目录中,您将找到以下文件:

  • build.xml(这是一个根构建文件,可用于按依赖关系的顺序调用所有模块上的目标(例如,确保模块总是在依赖于它的任何模块之前构建))
  • common
    • build.properties(所有项目共有的一些属性)
    • common.xml(由每个项目的所有build.xml文件导入的公共生成文件。这个构建定义了可以在所有项目中使用的目标。)
  • projects(每个模块包含一个目录,每个目录包含:)
    • ivy.xml(模块的ivy文件,描述其对其他模块和/或外部模块的依赖关系。)
<ivy-module version="1.0">
    <info
        organisation="org.apache.ivy.example"
        module="find"
        status="integration"/>
    <configurations>
        <conf name="core"/>
        <conf name="standalone" extends="core"/>
    </configurations>
    <publications>
        <artifact name="find" type="jar" conf="core"/>
    </publications>
    <dependencies>
        <dependency name="version" rev="latest.integration" conf="core->default"/>
        <dependency name="list" rev="latest.integration" conf="core"/>
        <dependency org="commons-collections" name="commons-collections" rev="3.1" conf="core->default"/>
        <dependency org="commons-cli" name="commons-cli" rev="1.0" conf="standalone->default"/>
    </dependencies>
</ivy-module>
  • build.xml(项目的生成文件,主要由公共生成文件和模块特定属性文件的导入组成:)
<project name="find" default="compile">
  <property file="build.properties"/>
  <import file="${common.dir}/common.xml"/>
</project>
  • build.properties
    Module specific properties + properties to find the common build file(特定于模块的属性+属性来查找公共生成文件)
projects.dir = ${basedir}/..
wkspace.dir = ${projects.dir}/..
common.dir = ${wkspace.dir}/common
  • src(包含所有Java源码的源目录)

请注意,这个例子并没有展示很多软件开发的良好实践,特别是在这些示例中,您不会发现任何单元测试,即使我们认为单元测试非常重要。但这不是本教程的目的。

现在,您对该结构更加熟悉了,让我们看一下这个示例中最重要的部分: the common build file(公共生成文件)。
实际上,如您所见,所有模块的构建文件只导入公共构建文件,并在它们的Ivy文件中定义它们的依赖关系(您应该开始熟悉这些文件)。
下面是这个common build file的一些方面:

1. Ivy settings

<!-- 使用一些自定义信息设置Ivy默认配置 -->
<property name="ivy.local.default.root" value="${repository.dir}/local"/>
<property name="ivy.shared.default.root" value="${repository.dir}/shared"/>

<!-- 下面是如果我们有自己的ivy设置文件,我们将如何配置ivy
<ivy:settings file="${common.dir}/ivysettings.xml" id="ivy.instance"/>
-->

此声明仅通过设置两个属性来配置Ivy:本地存储库的位置和共享存储库的位置。
这是这里所做的唯一设置,因为Ivy默认配置为在团队环境中工作。当然,在真实环境中,共享存储库的位置更倾向于位于团队共享目录中(或者在更复杂的存储库中,请再次参阅默认设置教程,以了解如何使用真正不同的内容)。如果默认设置不符合我们的目的,您可以在被注释掉的部分看到如何进行设置。

2. resolve dependencies

<target name="resolve" depends="clean-lib, load-ivy" description="--> resolve and retrieve dependencies with Ivy">
	<!-- 通常不需要,如果存在依赖项,Ivy会创建目录 -->
    <mkdir dir="${lib.dir}"/> 

    <!-- 解析调用不是强制的,否则retrieve会进行隐式调用 -->
    <ivy:resolve file="${ivy.file}"/>
    <ivy:retrieve pattern="${lib.dir}/[artifact].[ext]"/>
</target>

你应该开始熟悉用ivy这种方法。我们显式地调用resolve以使用配置的Ivy文件(默认情况下可以),然后调用retrieve将解析的依赖项工件从缓存复制到本地lib目录。该pattern还用于使用lib目录中的工件的名称和扩展名来命名工件(没有修订without revision),这更容易与IDE一起使用,因为当工件版本更改时IDE配置不会更改。

3. ivy-new-version

<target name="ivy-new-version" depends="load-ivy" unless="ivy.new.revision">
    <!-- 默认模块版本前缀值 -->
    <property name="module.version.prefix" value="${module.version.target}-dev-b"/>

    <!-- 向Ivy询问可用的版本号 -->
    <ivy:info file="${ivy.file}"/>
    <ivy:buildnumber
        organisation="${ivy.organisation}" module="${ivy.module}"
        revision="${module.version.prefix}" defaultBuildNumber="1"
        revSep=""/>
</target>

此target用于要求Ivy为模块查找新版本。为了获得我们正在处理的模块的详细信息,我们使用ivy:info任务从Ivy文件中提取信息。
然后使用buildnumber任务根据我们用属性设置的前缀获取新的修订。默认情况下,它将是1.0-dev-b(在common/build.properties文件中可查看查看module.version.target)。
由这个common build file构建的每个模块都可以通过设置不同的module.version.target,在其特定模块中的build.properties文件,甚至覆盖module.version.prefix。要获取新版本,Ivy会扫描存储库以查找具有给定前缀的最新可用版本,然后将此版本的值递增1。

4. publish

<target name="publish" depends="clean-build, jar" description="--> publish this project in the ivy repository">
    <ivy:publish artifactspattern="${build.dir}/[artifact].[ext]"
                 resolver="shared"
                 pubrevision="${version}"
                 status="release"/>
    <echo message="project ${ant.project.name} released with version ${version}"/>
</target>

此target将模块发布到共享存储库中,在version property中可以找到revision,该修订由其他目标设置(基于上面看到的ivy-new-version)。它可以在模块达到特定里程碑时使用,也可以在您希望团队从新版本的模块中获益时使用。

5. publish-local

<target name="publish-local" depends="local-version, jar" description="--> publish this project in the local ivy repository">
    <ivy:publish artifactspattern="${build.dir}/[artifact].[ext]"
                 resolver="local"
                 pubrevision="${version}"
                 pubdate="${now}"
                 status="integration"
                 forcedeliver="true"/>
    <echo message="project ${ant.project.name} published locally with version ${version}"/>
</target>

这与发布任务非常相似,只是它将修订发布到本地存储库,该存储库仅在您的环境中使用,不会干扰团队。当您更改某个模块中的某个内容并希望从另一个模块中的更改中获益时,您只需在该模块中调用publish-local,然后另一个模块的下一个版本将自动获得该本地版本。

6. clean-local

<target name="clean-local" description="--> cleans the local repository for the current module">
    <delete dir="${ivy.local.default.root}/${ant.project.name}"/>
</target>

当您不想再使用模块的本地版本时,将使用此目标。例如,当您向整个团队发布新版本时,或者放弃本地更改并希望利用团队的新版本时。

7. report

<target name="report" depends="resolve" description="--> generates a report of dependencies">
    <ivy:report todir="${build.dir}"/>
</target>

生成HTML报告和GraphML报告。
例如,要生成如本教程开头所示的图形,您只需按照此处给出的说明使用在console项目中调用report后在projects/console/build中找到的GraphML文件,就这样,您就可以清楚地了解所有应用程序依赖项了!

三、Playing with the projects

You can play with this tutorial by using regular Ant commands. Begin in the base directory of the tutorial (src/example/multi-project), and run ant -p:

[ivy@apache:/ivy/multi-project]$ ant -p
Buildfile: /ivy/multi-project/build.xml

Main targets:

 clean        clean tutorial: delete repository, ivy cache, and all projects
 clean-all    clean all projects
 publish-all  compile, jar and publish all projects in the right order

这让你知道你能在这里做什么。为了确保在存储库中至少发布一个版本的所有模块(构建依赖于其他模块的模块时需要),可以运行ant publish-all。

您将看到Ivy按照依赖项的顺序调用所有模块上的publish目标,因此dependee总是在其depender之前构建和发布。您可以随意更改模块的源代码(例如,更改方法名)和使用该方法的模块,然后调用publish all来查看dependee中的更改是如何首先编译、发布的,然后对能够成功编译的depender可用的。
然后可以进入其中一个示例项目目录(例如projects/find),并运行ant-p:

[ivy@apache:/ivy/multi-project/projects/find]$ ant -p
Buildfile: /ivy/multi-project/projects/find/build.xml

Main targets:

 clean          --> clean the project
 clean-build    --> clean the project built files
 clean-lib      --> clean the project libraries directory (dependencies)
 clean-local    --> cleans the local repository for the current module
 compile        --> compile the project
 jar            --> make a jar file for this project
 publish        --> publish this project in the ivy repository
 publish-local  --> publish this project in the local ivy repository
 report         --> generates a report of dependencies
 resolve        --> resolve and retrieve dependencies with ivy
 run            --> compile and run the project
Default target: compile

由于导入了通用.xml生成文件。通过调用resolve和publish来处理项目,看看在其他项目中执行相同操作时会发生什么。例如,一件有趣的事情是更改项目的依赖关系。如果模块版本现在依赖于一个新的commons库,那么在发布版本项目的新版本后,您将看到依赖于该版本的所有其他项目将获得该库作为其可传递依赖项的一部分。很简单!如果一个项目引入了一个与depender不兼容的更改,那么您可以很容易地更改depender中的依赖项,以从最新集成与从属程序兼容的固定版本(可能是更改前的最新版本)。现在控制你的模块非常容易!
到目前为止,您应该已经非常熟悉使用Ivy进行多项目开发。我们希望您能欣赏它的力量和灵活性!这些教程只是您使用Ivy之旅的开始,浏览参考文档以了解更多功能,订阅邮件列表以与社区分享您的经验并提出问题,浏览源代码,打开Jira问题,提交修补程序,加入并帮助Ivy成为最佳的依赖管理工具!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值