代码之家  ›  专栏  ›  技术社区  ›  andersoj

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

  •  11
  • andersoj  · 技术社区  · 14 年前

    我有点震惊(如果?)这个精确的问题还没有被问到,但是15分钟的扫描没有找到一个精确的匹配。(如果我错了,给我指正确的方向,投票结束……)

    问题1:

    在Ant构建系统下部署Java项目的最佳实践是什么? 就我们的目的而言,我们有以下背景(也许其中大部分是不相关的):

    • 大多数开发人员都在使用Eclipse(不是全部)
    • 在subversion中维护项目
    • 项目构建最近迁移到了Hudson,在Hudson中,我们希望使用发布插件来管理发布,并使用一些自定义脚本来处理自动部署
    • 该项目是一个“常规”应用程序,一种“生产原型”,用户池非常有限,但它们位于具有气隙分离的远程站点,因此提供版本化、可跟踪的工件以便于安装、手动数据收集/恢复和远程诊断非常重要。
    • 一些依赖项(jar)包含在SVN repo中;如果需要,可以在构建时通过ant脚本获取其他依赖项。没有什么比常春藤更奇特的了(请不要告诉我换成Maven3。。。我知道,如果合适的时候我们会这样做的。)
    • 构建包括JUnit、FindBugs、CheckStyle、PMD、JavaDoc,以及一些自定义文档生成
    • 两个或三个主JAR工件(一个主应用程序工件加上几个最小的API JAR以包含在几个耦合的应用程序中)
    • 希望分发以下分发工件:
      • 一个“完整”的源代码+bin tarball,解决了所有依赖项,jars和JavaDoc都是预先构建的
      • 一个bin tarball,只有docs和JavaDoc、jars和辅助包装脚本等
      • 一个“Partner”源代码+bin,其中包含合作开发人员可能要查看的“共享”源代码,以及相关的测试用例

    当前结构如下

    project-root/
    project-root/source                 
    project-root/source/java             // main application (depends on -icd)
    project-root/source/java-icd         // distributable interface code
    project-root/source/test             // JUnit test sources
    project-root/etc                     // config/data stuff
    project-root/doc                     // pre-formatted docs (release notes, howtos, etc)
    project-root/lib                     // where SVN-managed or Ant-retrieved Jars go
    project-root/bin                     // scripts, etc...
    

    在构建时,它扩展到包括:

    build/classes                        // Compiled classes
    build/classes-icd 
    build/classes-test
    build/javadoc
    build/javadoc-icd                    
    build/lib                            // Compiled JAR artifacts
    build/reports                        // PMD, FindBugs, JUnit, etc... output goes here
    build/dist                           // tarballs, zipfiles, doc.jar/src.jar type things, etc..
    build/java                           // Autogenerated .java products
    build/build.properties               // build and release numbering, etc...
    

    问题2:

    如何在开发树中保持修订控制项和构建时工件之间的严格分离 产生如上所述的相干分布 以及 允许我在开发和测试期间将开发树视为操作/分发? 尤其是,我不愿意 <jar> 顶级的task drop.jar文件 lib 目录——开发人员树中的目录是不可侵犯的SVN领域。但是分发一些公共用途的东西 build/lib/*.jar 是令人困惑的烦恼。文档和其他构建的工件也是如此,我们希望它们出现在发行版中的一致位置,但不希望开发人员和用户使用完全不同的目录结构。

    将所有生成的产品放在一个单独的 build/ 目录在开发时是非常好的,但是它是一个烦人的工件。为了便于分发,我宁愿把所有的罐子放在一个 图书馆 位置,实际上,下面这样的结构最有意义。目前,我们正在使用 ant dist 通过执行一些复杂的路径操作,如.tar.gz和.zip工件被构建。

    我觉得这个蒸馏器应该是什么样子的:

    project-root/
    project-root/source                  // present in only some dists 
    project-root/etc                     // same as in development tree
    project-root/doc                     // same as in development tree
    project-root/doc/javadoc             // from build 
    project-root/lib                     // all dependency and built JAR files
    project-root/bin                     // same as in development tree
    build.properties               // build and release numbering, etc...
    

    这个问题仅限于“如何维护清洁的开发和分发项目布局?”正如我上面所问;同时也收集关于Java/Ant项目布局的一般信息,以及对我们特定方法的评论。(是的,如果你认为它应该是一个社区Wiki,我会这么做的……)

    4 回复  |  直到 14 年前
        1
  •  3
  •   Tom Anderson    14 年前

    我的一个建议是,您分发的目录树不应该是CVS中的目录树。有一个脚本将dist目录放在build下,然后将其压缩。该脚本可以将源代码控制的和派生的文件合并到其核心内容中。它还可以执行诸如清除SVN目录之类的操作,您不想分发这些目录。如果您希望能够以同样的方式处理开发和分布式树,只需确保dist的布局与开发项目的布局相同—最简单的方法是复制除了build子目录(和CVS目录,可能还有Eclipse.project和.classpath之类的目录)之外的所有内容。

    我想你不会喜欢这个建议的。这可能是因为您认为分布式文件只是开发环境的一个可移植版本,但我认为事实并非如此,也不可能如此,也不必如此。如果你能接受这个想法,你可能会觉得我的建议是令人满意的。

    编辑:我想了更多,看了一些我使用的脚本。我认为在这种情况下,我要做的是构建一个独立的树,即使是在开发中;将执行环境指向project root/build/app(如果可以的话,也可以指向project root/build),而不是project root,然后symlink(如果没有symlinks,则复制)所有必要的东西(无论是静态的,来自project root的,还是派生的,从内建)到那。然后,构建一个发行版就可以像压缩树一样简单(当然,使用一个解析符号链接的工具)。这方面的好处是它允许执行树的结构非常干净-它不会包含源目录、IDE文件、生成脚本或项目内部的其他支持文件等。如果您使用Subversion,它仍然会包含从静态区域链接的任何符号中的.svn目录;如果你用水银,它不会含有任何汞的东西。

        2
  •  3
  •   Steven Mackenzie    14 年前

    布局方面,我们使用的东西已经演变成非常接近Maven布局的东西( see here ). 这是一个非常实用的布局,已经被很多人使用。而且,如果你想稍后切换到Maven,你已经准备好了。我们有几个变体,其中最重要的是我们将自动化单元测试和集成测试分开。

    在混合资源和建造艺术品方面-我当然建议不要这样做。正如您所看到的,它会干扰IDE索引和版本控制,并且通常会使生活变得困难。

    据我所知,要么接受这种混合,要么将依赖项作为构建的一部分复制,并将输出视为一个单独的项目—如果需要,可以在另一个IDE窗口中不断打开。无论如何,把你的工作“作为用户”和“作为生产商”混合在一起的想法听起来会让人困惑。

        3
  •  1
  •   user77115    12 年前

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

    项目包含子目录

    • bin公共二进制文件,脚本-把这个放在路径上。
    • build这是用于构建的树;Ant创建它并可以在“clean”项目中清空它。
    • dist分布输出进入这里;目录是在Ant中创建的,clean将其清空
    • 文档手工制作
    • lib导入的Java库进入这个目录
    • src source位于与包名称匹配的层次结构中的树下。
        4
  •  0
  •   FrVaBe    14 年前

    sun/oracle对项目布局也有一些(可能有些过时)的一般建议,您可能想看看:

    Guidelines, Patterns, and Code for End-to-End Java Applications