由于各种原因(无论这是否是一个明智的想法),我们有一个项目包含几个类似的包(比如one
,two
,three
)在结构上。还有一个common
个包。
当每个软件包中的某些内容导入不在common
中的内容时,我希望构建失败,例如因为您不小心接受了错误的导入完成,或者因为Eclipse将one
中的错误修复复制粘贴到two
时默默地带来了错误的导入。
将每个包以外的所有源文件复制到临时文件夹并尝试构建结果是有效的:
<target name="enforce-no-cross-imports">
<phony-build without="one"/>
<phony-build without="two"/>
<phony-build without="three"/>
</target>
<macrodef name="phony-build">
<attribute name="without" />
<sequential>
<echo message="Checking there are no cross imports to the @{without} package." />
<mkdir dir="${java.io.tmpdir}/my-awesome-project/phony-build-@{without}/src" />
<mkdir dir="${java.io.tmpdir}/my-awesome-project/phony-build-@{without}/bin" />
<copy todir="${java.io.tmpdir}/my-awesome-project/phony-build-@{without}/src">
<fileset dir="${src.dir}">
<include name="**/*.java"/>
<exclude name="**/@{without}/"/>
</fileset>
</copy>
<javac srcdir="${java.io.tmpdir}/my-awesome-project/phony-build-@{without}/src"
destdir="${java.io.tmpdir}/my-awesome-project/phony-build-@{without}/bin"
classpathref="classpath" encoding="UTF-8" nowarn="on"/>
<delete dir="${java.io.tmpdir}/my-awesome-project" />
</sequential>
</macrodef>
但是,当构建 DOES 中断时,错误显然发生在${java.io.tmpdir}
内。
enforce-no-cross-imports:
[echo] Checking there are no cross imports to the one package.
[mkdir] Created dir: C:\Users\me\AppData\Local\Temp\my-awesome-project\phony-build-one\src
[mkdir] Created dir: C:\Users\me\AppData\Local\Temp\my-awesome-project\phony-build-one\bin
[copy] Copying 47 files to C:\Users\me\AppData\Local\Temp\my-awesome-project\phony-build-one\src
[javac] Compiling 47 source files to C:\Users\me\AppData\Local\Temp\my-awesome-project\phony-build-one\bin
[javac] C:\Users\me\AppData\Local\Temp\my-awesome-project\phony-build-one\src\my\awesome\project\two\very\long\path\SomeController.java:43: package my.awesome.project.one.very.long.path.SomeConstantsClass does not exist
[javac] public static final String TEST = my.awesome.project.one.very.long.path.SomeConstantsClass.TEST;
因此,我无法单击文件名直接跳转到该问题。这为编译过程增加了太多的摩擦:它足够糟糕,我实际上将项目构建时间增加了三倍。
我认为我可以做的是不复制文件,而是使用javac
任务上的excludes
属性:
排除:必须排除的以逗号或空格分隔的文件列表(可以使用通配符模式指定);省略时不排除任何文件(默认排除除外)。
...除此之外不导致构建中断。会发生什么是javac不会编译其他包,但它仍然会查看它们以进行确认。启用verbose
会显示此日志行:
[javac] [checking my.awesome.project.one.very.long.path.SomeConstantsClass]
includeDestClasses
似乎是另一个有用的旗帜,但将其设置为false
并没有帮助。 <compilerarg value="-implicit:none"/>
也没有帮助。
我如何告诉javac
它确实需要从构建中排除这些文件,即使它们就在那里?
或者,如何获取javac的输出并对其运行find-replace,以便控制台输出显示正确的路径?
答案 0 :(得分:1)
您可以使用ant-contrib的compilewithwalls
或verifydesign
任务,但最安全的分离方法是将模块隔离到单独的源目录中并独立编译。您首先构建公共模块,然后使用&#34; common&#34;的编译类构建每个其他模块。在他们的类路径上,但不任何其他模块的类。当您使用像Maven这样的更高级别的构建工具进行构建时,这是默认方法。如果您有这样的目录结构:
然后你可以将构建结构为
<macrodef name="compile-module">
<attribute name="module" />
<element name="depends" implicit="true" optional="true"/>
<sequential>
<javac srcDir="@{module}/src" destDir="@{module}/classes"
encoding="UTF-8" nowarn="on">
<classpath>
<path refid="classpath" />
<depends/>
</classpath>
</javac>
</sequential>
</macrodef>
<compile-module name="common" />
<compile-module name="one">
<pathelement location="common/classes" />
</compile-module>
<compile-module name="two">
<pathelement location="common/classes" />
</compile-module>
<compile-module name="three">
<pathelement location="common/classes" />
</compile-module>
你在问题中提到Eclipse,所以你需要在那里做类似的事情。 Eclipse允许一个项目的根目录在另一个项目中,因此您可以创建一个主要的Eclipse项目&#34; myapp-common&#34;指向您的项目根目录,只有common/src
作为其源目录(并common/classes
作为相应的输出目录),然后创建单独的&#34; myapp-one&#34;,&#34; myapp- 2&#34;以one
,two
等文件夹为根据的项目,每个文件都取决于&#34; myapp-common&#34;项目。这样你就永远不会让Eclipse提供错误的&#34;自动完成,因为项目一不能看到项目二,反之亦然。