Ant构建的Java项目布局最佳实践

12

我有些惊讶,如果确实如此,为什么没有人问过这个问题,但在浏览了15分钟的Stack Overflow后,并没有找到完全匹配的答案。(如果我错了,请指出正确的方向并投票关闭...)

问题1:

在Ant构建系统下,布局Java项目的最佳实践是什么?对于我们的目的,我们有以下背景(也许大部分都不相关):

  • 大多数开发人员使用Eclipse(不是全部)
  • 项目保存在subversion中
  • 项目构建最近迁移到Hudson,在其中我们希望使用发布插件来管理发布,并使用一些自定义脚本来处理自动化部署
  • 这个项目是一个“传统”应用程序,一种“生产原型”,用户非常有限,但他们位于隔离的远程站点,因此交付可追溯的版本化工件以进行简单安装、手动数据收集/恢复和远程诊断非常重要。
  • 某些依赖项(JARs)包含在SVN存储库中;其他依赖项可以在构建时通过ant脚本获取,如果有必要。还没有像Ivy那样花哨的东西(请不要告诉我切换到Maven3...我知道,如果/当适当的时间来临,我们将这样做)。
  • 构建包括JUnit、FindBugs、CheckStyle、PMD、JavaDoc和一些自定义文档生成
  • 两到三个主要的JAR工件(一个主应用程序工件加上几个最小的API JAR,以包含在几个耦合应用程序中)
  • 希望分发以下分发工件:
    • 一个“完整的”源+二进制tarball,其中包括所有依赖项解决方案、预构建的jars和JavaDoc
    • 一个二进制tarball,只包括文档和JavaDoc、jars以及辅助包装器脚本等
    • 一个“合作伙伴”源+二进制文件,其中包含合作伙伴开发人员可能查看的“共享”源代码,以及相关的测试用例

当前的结构如下

project-root/
project-root/source                 
project-root/source/java             // 主应用程序(依赖于-icd)项目根目录下有几个子目录,包括distributable interface code、JUnit测试源代码、配置/数据、预格式化文档和依赖JAR文件等。构建时,还会生成编译的类文件、API文档、JAR库、输出结果等,并自动生成的.java产品。如何在开发过程中保持版本控制和构建产物之间的严格分离,同时生成一个一致的发布版本,以及将开发树视为操作/发布的过程中出现的问题?可以考虑将构建后的产物存储到一个独立的目录(例如build/dist),并将其作为发布版本进行传播,而不是将它们直接放在开发者的根目录下的lib目录中。这样做既能保证严格的版本控制,也能让用户和开发者使用相同的目录结构。将生成的所有产品放在单独的 build/ 目录中对于开发很好,但是作为发布的产物,这是一个很烦人的问题。为了发布目的,我宁愿所有的 JAR 包都放在一个单独的 lib 目录中,实际上,像下面这样的结构最有意义。目前,我们通过执行一些复杂的路径操作来在 .tar.gz 和 .zip 文件生成时动态构建此结构。

我认为 dist 应该如下所示:

project-root/
project-root/source                  // 仅出现在某些发布版本中 
project-root/etc                     // 与开发树相同
project-root/doc                     // 与开发树相同
project-root/doc/javadoc             // 来自 build 
project-root/lib                     // 所有依赖项和构建的 JAR 文件
project-root/bin                     // 与开发树相同
build.properties               // 构建和发布编号等信息...

这个问题专门涉及“如何保持清洁的开发和发布项目布局”的问题;但也收集关于 Java/Ant 项目布局的一般信息和对我们特定方法的评论。(是的,如果您认为它应该是一个社区 Wiki,我会这么做...)


“允许我在开发和测试期间将开发树视为操作/分发”是什么意思 - 您的意思是您不满意只是将非构件JAR(例如)复制到构建树中吗? - Steven Mackenzie
@Steven Mackenzie:这当然是可能的,但似乎从project-root完全复制所有内容到project-root/build并不优雅。也许我对此过于苛求了,或者只是想要同时拥有开发者树和用户树...我希望我的开发者树看起来像用户树,但我不希望构建时的产物与受版本控制的项目混在一起。也许将所有内容完全复制到build/子目录是实现这一点的唯一途径...你是如何布置你的项目(在仓库中以及构建时)的呢? - andersoj
4个回答

3

在布局方面,我们采用了一种演变成类似于Maven布局的东西(请参见此处)。这是一个非常实用的布局,已经被很多人使用。如果以后想切换到Maven,那么你就可以轻松搞定。我们有一些变化,最重要的是我们将自动化单元测试和集成测试分开。

就混合源代码和构建产物而言,我肯定不建议这样做。正如你所看到的,它会干扰IDE索引和版本控制,并且通常会使生活变得困难。

据我所知,你要么接受这种混合状态,要么将依赖项作为构建的一部分进行复制,并将输出视为单独的项目——如果需要的话,可以在另一个IDE窗口中始终打开它。无论如何,将你的工作“作为用户”与“作为发布包的生产者”混合在一起的想法听起来都会令人困惑。


感谢您的评论,我们的布局实际上是朝着更像Maven布局的方向迭代的。此外,“用户 vs. 生产者”的用例是希望有一种简单的方法来将我们(庞大、复杂的)外部执行环境指向开发人员的树/快照进行快速执行测试,并能够快速迭代... 实际上,我可能正在支持您手动复制到构建/树的建议。 - andersoj
1
我认为你的用例可以使用完全独立的树来实现 - 为了保持迭代速度,您需要确保在构建过程中只执行必要的部分。不幸的是,根据我的经验,Ant 在这方面表现不佳!您可能希望有选择地执行目标(例如,仅在代码更改时进行编译/打包/部署)。 - Steven Mackenzie
对于“使用Maven布局”的建议点赞,它适用于我遇到的几乎所有情况,并且将源代码和派生代码清晰地分开。 - Gary
1
我同意将您的布局与Maven的默认布局匹配。这样,如果您决定转换到Maven,就会更容易。而且,当新开发人员进入时,如果他们曾经使用过Maven,他们将知道布局。此外,由于这是Maven的标准,您可以向开发人员提出争论,如果他们坚持要偏离标准,您就有一个可以使用的理由。"抱歉,公司政策是将我们的Java布局设置为Maven样式。我希望我能改变它,但涉及的文书工作量很大。是的,这个决定是由一些混乱的管理者做出的。我为你感到难过,但抱歉。" - David W.

3
我的建议是,你分发的目录树不应该是在CVS中的那个。要有一个脚本,在build下组合出一个dist目录,然后将其压缩。这个脚本可以将源代码和派生文件结合起来。它还可以做一些事情,比如清除SVN目录,因为你不想分发它们。如果你想以同样的方式处理开发和分发树,只需确保dist的布局与开发项目的布局相同——最简单的方法是复制除了build子目录(和CVS目录,以及类似Eclipse .project和.classpath之类的东西)之外的所有内容。
我猜你可能不喜欢这个建议。也许你认为分发文件只是你开发环境的便携版本的想法很好,但我认为事实并非如此,它永远不会是这样,也没有必要是这样。如果你能接受这个想法,你可能会觉得我的建议可行。
编辑:我再考虑一下,并查看一些我使用的脚本。我认为在这种情况下我会在开发中构建一个单独的树;将执行环境指向project-root/build/app(或者如果可能的话是project-root/build),而不是project-root,然后将所有必需的内容(无论是静态的,在项目根目录下,还是派生的,在build中)都链接到其中。构建分发可能就像压缩这个树一样简单(当然要用一个能解析符号链接的工具)。这个方法的好处在于它允许执行树的结构非常干净——它不会包含源目录、IDE文件、构建脚本或其他来自项目内部的支持文件等。如果你正在使用Subversion,它仍将包含从静态区域链接的任何东西内部的.svn目录;如果你正在使用Mercurial,则不会包含任何.hg的内容。

1
+1 我喜欢每一个认真、有原则的建议,即使它与我的现有偏见相悖...谢谢,这将对我的最终解决方案产生影响。(请注意,我们已经在做这个了;我们只是试图尽量减少认知失调等问题...) - andersoj
是的,如果我只是在描述你已经做过的事情,那么很抱歉。大脑倾泻比根据你所描述的内容生成差异更容易,而且我非常懒惰。 - Tom Anderson

1

http://ant.apache.org/ant_in_anger.html

该项目包含子目录

  • bin 通用二进制文件和脚本 - 将其放在路径上。
  • build 这是构建树;Ant会创建它,并可以在“clean”项目中清空它。
  • dist 发布输出放在这里;该目录由Ant创建,clean命令会清空它。
  • doc 手工制作的文档。
  • lib 导入的Java库放在此目录中。
  • src 源代码以与包名称匹配的层次结构放在此树下。

0

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接