如何用同一ANT构建文件生成两个独立JAR(应用类/测试类)
解决ANT构建生成两个独立JAR的问题
我来帮你搞定这个ANT打包的问题!你现在的问题根源在于编译阶段把应用类和测试类都编译到同一个输出目录了,所以后续打包时两个JAR自然会包含所有内容。咱们可以通过拆分编译任务+分别打包的方式来解决,下面给你两种可行的方案:
方案一:规范目录结构(推荐)
最清晰的方式是把应用代码和测试代码分开存放,比如:
src/main/java:存放应用核心类src/test/java:存放测试用例类
然后调整ANT脚本,分别编译这两个目录的代码到不同的输出目录,再单独打包:
第一步:定义属性
先在脚本里添加这些属性,方便后续维护:
<property name="src.main" value="src/main/java"/> <property name="src.test" value="src/test/java"/> <property name="build.main" value="dist/classes"/> <property name="build.test" value="dist/test-classes"/> <property name="dist.dir" value="dist"/> <property name="main.jar.name" value="my-app"/> <property name="test.jar.name" value="my-app-tests"/>
第二步:拆分编译任务
把原来的单个compile拆成两个独立的编译目标,测试类需要依赖应用类,所以compile-test要依赖compile-main:
<target name="compile-main" depends="init" description="Compile application core classes"> <javac srcdir="${src.main}" debug="${debug}" destdir="${build.main}"> <classpath refid="class.path"/> </javac> </target> <target name="compile-test" depends="compile-main" description="Compile test cases"> <javac srcdir="${src.test}" debug="${debug}" destdir="${build.test}"> <classpath> <path refid="class.path"/> <pathelement location="${build.main}"/> <!-- 依赖已编译的应用类 --> </classpath> </javac> </target>
第三步:分别打包
针对两个编译输出目录,创建独立的打包任务:
<target name="package-main" depends="compile-main" description="Package application JAR"> <jar jarfile="${dist.dir}/${main.jar.name}.jar" basedir="${build.main}"> <!-- 这里可以添加MANIFEST配置、资源文件等,按需调整 --> </jar> </target> <target name="package-test" depends="compile-test" description="Package test JAR"> <jar jarfile="${dist.dir}/${test.jar.name}.jar" basedir="${build.test}"> <!-- 测试JAR只包含测试类,运行时需要配合主JAR使用 --> </jar> </target> <!-- 总目标,一键生成两个JAR --> <target name="dist" depends="package-main, package-test" description="Generate all distribution JARs"/>
方案二:不调整目录,用过滤规则拆分
如果暂时不想改目录结构,可以通过<include>和<exclude>规则来区分应用类和测试类(比如测试类命名都是*Test.java,或者放在test子目录下):
示例代码
<property name="src.dir" value="src"/> <property name="build.main" value="dist/classes"/> <property name="build.test" value="dist/test-classes"/> <property name="dist.dir" value="dist"/> <target name="compile-main" depends="init"> <javac srcdir="${src.dir}" debug="${debug}" destdir="${build.main}"> <classpath refid="class.path"/> <!-- 排除所有测试类,这里按类名后缀过滤 --> <exclude name="**/*Test.java"/> </javac> </target> <target name="compile-test" depends="compile-main"> <javac srcdir="${src.dir}" debug="${debug}" destdir="${build.test}"> <classpath> <path refid="class.path"/> <pathelement location="${build.main}"/> </classpath> <!-- 只包含测试类 --> <include name="**/*Test.java"/> </javac> </target> <!-- 打包任务和方案一一样,分别基于build.main和build.test目录打包 --> <target name="package-main" depends="compile-main"> <jar jarfile="${dist.dir}/app-main.jar" basedir="${build.main}"/> </target> <target name="package-test" depends="compile-test"> <jar jarfile="${dist.dir}/app-tests.jar" basedir="${build.test}"/> </target>
这样调整后,你生成的两个JAR就会分别只包含应用类和测试用例了,不会再混在一起~
内容的提问来源于stack exchange,提问作者Arnab




