【问题标题】:Compile selective part of my source tree using Ant使用 Ant 编译我的源代码树的选择性部分
【发布时间】:2025-12-19 08:10:17
【问题描述】:

我的情况有点有趣。我正在尝试使用 Ant 制作一个 jar 文件。但是,我不希望编译每个 java 文件。我的源代码有这样的结构:

src
-Contact.Java
-Contact.hbm.xml
-AnotherClass.Java

所以,我想在我的 jar 文件中包含以下内容:

myjar.jar
-com
--me
---Contact.Class
---Contact.hbm.xml

我不希望 AnotherClass.Class 在那里。

Ant 可以做到这一点吗?

我想出的最好的是这样的:

<target name="condition-hibernate" description="check if there is a java and hbm file then call for compile-hibernate">
    <condition property="condition">
    <available file="**/*.hbm.xml" />
    </condition> 

<antcall target="condition-hibernate-part2"/>

</target>   

<target name="condition-hibernate-part2" description="check if there is a java and hbm file then call for compile-hibernate">
    <javac srcdir="${source.dir}" destdir="${hibernate.dir}">
</target>

我不认为我可以使用 Ant 来解决我的问题,因为我不能告诉 Ant 编译什么和不编译什么(我可以使用排除和包含)但我想告诉 Ant 只编译具有*.hbm.xml 文件。

【问题讨论】:

  • 也许你应该稍微改一下你的问题。假设您只需要具有相应 .hbm.xml 文件的 Java 类。

标签: ant compilation target javac conditional-statements


【解决方案1】:

我不知道如何用 Ant 内置的selectors 来实现这一点。

但是,如果您无法以任何其他方式解决此问题,您可以实现一个 custom selector 来检查 .java 文件是否具有相应的 .hbm.xml 文件,例如

public class CorrespondingHbmSelector implements FileSelector {
  public boolean isSelected(File basedir, final String filename, File f) {
    Pattern p = Pattern.compile("^(.+).java$");
    Matcher m = p.matcher(filename);
    boolean matches = m.matches();
    if (!matches) {
      return false;
    }
    final String basename = m.group(1);
    String[] foundFiles = basedir.list(new FilenameFilter() {
      @Override
      boolean accept(File dir, String name) {
        return name.startsWith(basename) && name.endsWith(".hbm.xml");
      }
    });
    return foundFiles.length > 0;
  }
}

在您的 build.xml 中使用它,就像 include 一样

<typedef
  name="correspondinghbmselector"
  classname="CorrespondingHbmSelector"
  classpath="${mydomain.classes}"/>

<javac srcdir="${source.dir}" ...>
  <correspondinghbmselector/>
</javac>

这只是基本的想法。 (我没有测试代码。)

更好的方法是避免构建中如此复杂的依赖关系。

【讨论】:

  • 啊,我从问题中不明白他只想要那些具有相应.hbm.xml 文件的文件。不过有道理。
  • 如果我不想触及代码复杂性,我相信这将是最好的解决方案。
【解决方案2】:

我认为您应该考虑将不同类型的类分成单独的项目。除了使您的打包过程更简单之外,还有其他好处:解耦、强制执行单向编译时依赖项等。

【讨论】:

    【解决方案3】:

    假设 Contact.java 不依赖于 AnotherClass.java,这是可行的。为此,请在您的 javac 标记中使用 selector sub-elements(在 Ant 文档中的“概念和类型”下链接)。

    这是一个例子:

        <javac srcdir="${source.dir}" destdir="${hibernate.dir}">
          <filename name="Contact.Java" />
        <javac>
    

    当然,您也可以直接使用patternset 子元素和属性来代替&lt;filename&gt; 选择器:

        <javac srcdir="${source.dir}" destdir="${hibernate.dir}">
          <include name="Contact.Java" />
        <javac>
    

        <javac srcdir="${source.dir}" destdir="${hibernate.dir}"
               includea="Contact.Java" />
    

    顺便说一下,Java 文件扩展名的命名约定仅使用小写字母,即.java,而不是.Java(和.class)。如果您像大多数 Windows 文件系统一样使用不区分大小写的文件系统,这可能无关紧要,但您仍然应该这样做,以避免以后出现意外。)

    【讨论】:

    • 我假设有任意数量的 .java 文件要编译,这些文件在构建时是未知的。或者,至少 shahin 不想在构建文件中列出所有这些。
    • 会有不止一个类,比如 Contact.java。如果我没有彻底解释,我很抱歉。因此,唯一要检查的标准是具有不同扩展名但相同文件名的共存类。你对大写字母是对的,那是我输入结构的错误。一直是小写。