Javac
该任务用于编译 Java 源代码树。将递归扫描源目录和目标目录,以查找要编译的 Java 源文件。只编译没有相应的 .class 文件或 .class 文件比 .java 文件旧的 .java文件。
注意:Apache Ant 仅使用源文件和类文件的名称来查找需要重新构建的类。它不会扫描源文件,因此不了解嵌套类、与源文件命名不同的类等。请参阅
任务中基于存在/修改时间以外的依赖项检查。
当源文件是包的一部分时,源树的目录结构应遵循包层次结构。可以通过 includes
、includesfile
、excludes
和 excludesfile
attribute 来优化正在编译的文件集。使用 includes
或 includesfile
attribute 可以指定要包含的文件。exclude
或 excludesfile
attribute 用于指定要排除的文件。在这两种情况下,文件列表可以通过文件名(相对于在 srcdir
attribute 或嵌套的
元素中指定的目录)或使用通配符模式来指定。有关包含/排除文件的工作方式以及如何编写通配符模式的信息,请参阅基于目录的任务部分。
可以使用不同的编译器。这可以通过设置全局的 build.compiler
property 来指定(该 property 将影响整个构建过程中的所有
任务),也可以通过设置 compiler
attribute(指定特定于当前
任务),或通过使用实现 org.apache.tools.ant.taskdefs.compilers.CompilerAdapter
的任何 typedefed 或 componentdefed 类型的嵌套元素。build.compiler
property 或 compiler
attribute 的有效值为:
-
classic
(JDK 1.1/1.2 的标准编译器)——javac1.1
和javac1.2
可以用作其别名。 -
modern
(JDK 1.3 及更高版本的标准编译器)——javac1.3
、javac1.4
、javac1.5
和javac1.6
、javac1.7
(自 Ant 1.8.2 起)、javac1.8
(自 Ant 1.8.3 起)、javac1.9
(自Ant 1.9.5 起)、javac9
(自 Ant 1.9.8 起)和javac10+
(自 Ant 1.10.2 起)可以用作别名。 -
jikes
(Jikes 编译器)。 -
jvc
(来自 Microsoft 的 SDK for Java/Visual J++ 的命令行编译器)——microsoft
可以用作别名。 -
kjc
(kopi 编译器)。 -
gcj
(来自 GCC 的 gcj 编译器)。 -
sj
(Symantec Java 编译器)——symantec
可用作别名。 -
extJavac
(在自己的 JVM 中运行modern
或classic
)。
默认值是 javacx
, x
的具体值取决于运行 Ant 时使用的 JDK 版本。如果希望使用与提供的编译器接口不同的编译器接口,可以编写一个实现 org.apache.tools.ant.taskdefs.compilers.CompilerAdapter
接口的类。在 build.compiler
property 或 compiler
attribute 中提供完整的类名。
fork
attribute 覆盖 build.compiler
property 或 compiler
attribute 设置,并期望在 JAVA_HOME 中设置 JDK 1.1 或更高版本。
还可以使用 compiler
attribute 告诉 Ant,即使设置 fork=true
,当它将命令行开关放在一起时,它将采用哪个 JDK 版本。如果您希望在当前 JDK 为 1.2+ 时运行 JDK 1.1 的编译器,这将非常有用。如果使用 compiler=javac1.1
和(例如)depend=true
,Ant 将使用命令行开关 -depend
而不是 -Xdepend
。
此任务将从传递给编译器的类路径中删除指向不存在的文件/目录的所有条目。forked
可执行文件(如果有)的工作目录是项目的基准目录。
Windows 注意:当 modern 编译器在 Windows 上以 unforked 模式使用时,它会锁定
任务类路径中的文件,而不会释放它们。这样做的副作用是,将无法在以后的构建中删除或移动这些文件。解决方法是在调用编译器时使用 fork。
如果源代码包含使用 @Native
注解的 native 方法或字段,则可以设置 nativeheaderdir
attribute,以便使用 javac
命令的 -h
开关生成 native header 文件。请注意,Ant 用于确定要编译的文件的逻辑没有考虑 native header 文件,即如果 .class 比相应的 .java 文件更新,则即使为其生成的 native header 文件已过时,也不会编译该文件。
A fork is a personal copy of another user's repository that lives on your account. Forks allow you to freely make changes to a project without affecting the original upstream repository. You can also open a pull request in the upstream repository and keep your fork synced with the latest changes since both repositories are still connected. —— Github Glossary
fork 是位于本地对另一个用户的仓库的副本,该仓库位于您的帐户上。fork 允许您在不影响原始上游仓库的情况下自由地对项目进行更改。您还可以在上游仓库中打开一个 pull 请求,并使您的 fork 与最新的更改保持同步,因为这两个存储库仍然是连接的。
参数
Attribute | Description | Required |
---|---|---|
srcdir | .java 文件的位置。 | Yes,除非存在嵌套的 元素或 modulesourcepath attribute 或相应的元素 |
destdir | 存储 .class文件的位置。 | No |
includes | 逗号或空格分隔的文件模式列表,这些文件模式指定需要包含的文件。 | No;默认为所有 .java 文件 |
includesfile | 文件名。此文件的每一行都被视为包含模式。 | No |
excludes | 逗号或空格分隔的文件模式列表,这些文件模式指定需要排除的文件。 | No;默认为 defaultexcludes 或 none (如果 defaultexcludes 为 no ) |
excludesfile | 文件名。此文件的每一行都被视为排除模式。 | No |
defaultexcludes | 指示是否应使用默认排除(yes |no )。 |
No;默认为 yes |
classpath | 所用的 classpath。 | No |
sourcepath | 所用的 sourcepath。要抑制 sourcepath 开关,请使用 sourcepath=. 。 |
No;默认为 srcdir,除非制定了内嵌的 元素 |
bootclasspath | 引导类文件的位置(有关使用 -X 和 -J-X 参数指定引导类路径的信息,请参见下文)。 | No |
classpathref | 要使用的 classpath ,作为对别处定义的 classpath 的引用。 | No |
sourcepathref | 要使用的 sourcepath,作为对别处定义的 sourcepath 的引用。 | No |
bootclasspathref | 要使用的 bootstrapclasspath,作为对别处定义的 bootstrapclasspath 的引用。 | No |
extdirs | 已安装扩展的位置。 | No |
encoding | 源文件的编码(注意:gcj 还不支持此选项)。 |
No |
nowarn | 指示是否应将 -nowarn 开关传递给编译器。 |
No;默认为 off |
debug | 指示是否应使用调试信息编译源代码。如果设置为 off ,-g:none 将在支持它的编译器的命令行上传递(对于其他编译器,将不使用命令行参数)。如果设置为 true ,则 debuglevel attribute 的值确定命令行参数。 |
No;默认为 off |
debuglevel | 要附加到 -g 命令行开关的关键字列表。合法值为 none 或以下关键字的逗号分隔列表:lines ,vars 和 source 。 |
No;当 debug attribute 为 false 或使用除 modern 、javac1.2 和 jikes 以外的任何实现时,则忽略该属性;默认情况下,不会向 -g 追加任何内容 |
optimize | 指示是否应使用优化编译源代码。注意,自 JDK1.3 以来,Sun 的 javac 忽略了这个标志(因为编译时优化是不必要的)。 | No;默认为 off |
deprecation | 指示是否应使用已弃用的信息来编译源代码。 | No;默认为 off |
verbose | 要求编译器提供详细的输出。 | No;默认为 no |
depend | 为支持此功能的编译器(jikes 和 classic )启用依赖项跟踪。 |
No |
includeAntRuntime | 是否在类路径中包含 Ant 运行时库。通常最好将其设置为 false ,以便脚本的行为对运行它的环境不敏感。 |
No; defaults to yes, unless build.sysclasspath property is set |
includeJavaRuntime | 是否在类路径中包含来自正在执行的 JVM 的默认运行时库。注意:在某些设置中,运行时库可能是 Ant 运行时库的一部分,因此您可能需要显式地将 includeAntRuntime 设置为 false ,以确保不包括 Java 运行时库。 |
No;默认为 no |
fork | 是否通过在外部使用 JDK 编译器来执行 javac 。 |
No;默认为 no |
executable | 如果在 fork 情况下使用的 javac 可执行文件的完整路径,则该 attribute 为 yes。由于Ant 1.6,在使用 jikes、jvc、gcj 或 sj 时,此 attribute 也可用于指定可执行文件的路径。 | No;默认为当前 JDK 的编译器,如果 fork 为 no ,则忽略该编译器 |
memoryInitialSize | 如果 javac 在外部运行,则设置底层 JVM 的初始内存大小(示例:83886080、81920k 或 80m)。 | No;默认为标准 JVM 内存设置,如果 fork 为 no ,则忽略该设置 |
memoryMaximumSize | 如果 javac 在外部运行,则设置底层 JVM 的最大内存大小;否则就被忽略了(示例:83886080、81920k 或 80m)。 | No;默认为标准 JVM 内存设置,如果 fork 为 no ,则忽略该设置 |
failonerror | 指示编译错误是否会使构建失败。 | No;默认为 true |
errorProperty | 编译失败时要设置为 true 的 property。从 Ant 1.7.1 开始引入。 | No |
source | 编译器接受的 Java 语言特性,由 -source 命令行开关指定。有效的特性版本有 1.3、1.4、1.5 或 5 等。在 javac1.4(或 modern ,当 Ant 未在 JVM 1.3 中运行时)、gcj 和 jikes 之前的所有实现都将忽略该 attribute。如果将此 attribute 与 gcj 或 jikes 一起使用,则必须确保您的版本支持 -source ( gcj 是 -fsource )开关。 |
No;默认情况下,除非设置了 ant.build.javac.sourceproperty ,否则不会使用 -source 参数。注意,默认值取决于运行 Ant 的 JDK。强烈建议始终指定此 attribute。 |
target | 为特定 JVM 版本生成 class 文件(交叉编译)。 | No;默认情况下,除非设置了 ant.build.javac.sourceproperty ,否则不会使用 -target 参数。注意,默认值取决于运行 Ant 和 源代码的 JDK(参考交叉编译选项)。强烈建议始终指定此 attribute。 |
compiler | 要使用的编译器实现。请参阅上面的有效编译器列表。 | No;默认为 build.compiler property 的值(如果设置了),否则,为当前 JDK 的默认编译器 |
listfiles | 指示是否将列出要编译的源文件。 | No;默认为 no |
tempdir | Ant 应该放置临时文件的位置。仅当任务已 forked 且命令行参数长度超过 4KB 时,才使用此选项。从 Ant 1.6 开始引入。 | No;默认为 java.io.tmpdir |
updatedProperty | 如果已进行编译且编译成功,则要设置为 true 的 property 。从 Ant 1.7.1 开始引入。 |
No |
includeDestClasses | 此 attribute 控制是否在编译器所用的类路径中包含目标类目录。如果设置为true (默认),则以前编译的类位于编译器的类路径上。这意味着 greedy 编译器不会重新编译已编译的依赖类。一般来说,这是一件好事,因为它会停止编译器进行不必要的工作。然而,对于一些涉及泛型的边缘情况,javac 编译器需要编译依赖类以获得泛型信息。bug 报告中记录了一个示例:bug 40776 —编译带有泛型的 Java 5 项目时遇到的问题。将 attribute 设置为 false 将导致编译器重新编译依赖类。从 Ant 1.7.1 开始引入。 |
No;默认为 true |
createMissingPackageInfoClass | package-info.java 文件中的一些包级注解不会创建任何 package-info.class 文件,因此 Ant 每次都会重新编译相同的文件。从 Ant 1.8 开始,如果编译器没有创建一个 package-info.class,则为每个 package-info.java 创建一个空package-info.class。在某些设置中,此附加类会导致问题,可以通过将此 attribute 设置为 false 来抑制它。从 Ant 1.8.3 开始引入。 | No;默认为 true |
modulepath | 指定查找应用程序模块的位置。为一个模块、模块文件或分解模块目录的列表。从 Ant 1.9.7 开始引入。 | No |
modulepathref | 要使用的 modulepath ,作为对其他地方定义的路径的引用。从 Ant 1.9.7 开始引入。 |
No |
modulesourcepath | 指定在何处查找多模块编译的输入源文件。从 Ant 1.9.7 开始引入。 | Yes,除非存在 srcdir attribute 或嵌套的 元素 |
modulesourcepathref | 要使用的模块资源路径,作为对别处定义的路径的引用。从 Ant 1.9.7 开始引入。 | No |
upgrademodulepath | 在运行时映像中指定替换可升级模块的模块的位置。从 Ant 1.9.7 开始引入。Specify the location of modules that replace upgradeable modules in the runtime image. since Ant 1.9.7 | No |
upgrademodulepathref | 要使用的 upgrademodulepath ,作为对别处定义的路径的引用。从 Ant 1.9.7 开始引入。 |
No |
nativeheaderdir | 指定放置生成的 native header 文件的位置。从 Ant 1.9.8 开始引入。 | No,在 JDK 7 或更早版本上编译时忽略该 attribute |
release | 指定 --release 开关的值。在 JDK 9+上设置并运行时,将忽略 source 和 target attribute 以及 bootclasspath 。从 Ant 1.9.8 开始引入。 |
No,在 JDK 7 或更早版本上编译时忽略该 attribute |
指定为嵌套元素的参数
此任务形成一个隐式文件集,支持
(dir
变为 srcdir
)的大多数属性以及嵌套的
、
和
元素。
srcdir
,classpath
,sourcepath
,bootclasspath
,modulepath
,modulesourcepath
,upgrademodulepath
和extdirs
。
的这些 attribute 都是 path-like 的结构,也可以通过嵌套的
进行设置(注意不同的名称!)
,
,
,
,
,
和
元素。compilerarg
。可以使用嵌套的
元素为编译器指定其他命令行参数。这些元素的指定方式与命令行参数类似,但有一个附加属性,只有在使用给定的编译器实现时,才能使用该属性启用参数。
Attribute | Description | Required |
---|---|---|
value | 参见命令行参数。 | value 、line 、file 、path 选一 |
line | 参见命令行参数。 | value 、line 、file 、path 选一 |
file | 参见命令行参数。 | value 、line 、file 、path 选一 |
path | 参见命令行参数。 | value 、line 、file 、path 选一 |
prefix | 参见命令行参数。自 Ant 1.8 开始引入。 | No |
suffix | 参见命令行参数。自 Ant 1.8 开始引入。 | No |
compiler | 仅当所选编译器实现与此 attribute 的值匹配时,才传递指定的参数。合法值与上述有效编译器列表中的值相同。 | No |
compilerclasspath
。自 Ant 1.8.0 以来。一种类似路径的结构,如果指定了自定义类,则在加载编译器实现时保存要使用的类路径。使用内置编译器时没有任何效果。实现 CompilerAdapter 的类型的任何嵌套元素。自 Ant 1.8.0 以来。如果定义的类型实现了 CompilerAdapter 接口,则该类型的嵌套元素可以用作编译器属性的替代项。
示例
编译 ${src}
目录下的所有 .java
文件,并将 .class
文件存储在 ${build}
目录中。所使用的类路径包括 xyz.jar
,并且使编译时包含调试信息处于启用状态。源代码级别为 1.4,因此可以使用 assert
语句(JDK 1.4 引入的新特性)。
编译 ${src}
目录下的所有 .java
文件,并将 .class 文件存储在 ${build}
目录中。Java 编译器通过使用默认的 javac
可执行文件进行 fork。源代码级别为 1.2(类似于1.1 或 1.3),类文件也应该可以在 JDK1.2+ 下运行。
编译 ${src}
目录下的所有 .java
文件,并将 .class
文件存储在 ${build}
目录中。Java 编译器通过使用名为 java$$javac.exe
的可执行文件进行 fork。注意,$
符号需要由第二个 $
符号进行转义。源代码级别为 1.5,因此可以使用泛型。
编译 ${src}
目录下的 .java 文件,并将 .class 文件存储在 ${build}
目录中。使用的类路径中包含 xyz.jar,开启了调试信息。仅使用 mypackage/p1
和mypackage/p2
下的文件。mypackage/p1/testpackage
目录中及其下的所有文件都将从编译中排除。这里没有指定 source
或 target
级别,因此实际使用的值将取决于运行 Ant 的 JDK。
这与上一个示例相同,添加了由 property src2
定义的第二个源路径。这也可以使用嵌套的
元素表示,如下所示:
如果您想运行其他 JDK 的 javac 编译器,您应该告诉 Ant 在哪里可以找到编译器以及您将使用哪个版本的 JDK,以便它可以选择正确的命令行开关。以下示例在新进程中执行 JDK 1.1 javac,并使用正确的命令行开关,即使 Ant 在不同版本的 JVM 中运行:
注意:如果您希望只编译位于公共根目录下某些包中的源文件,请使用 include
/exclude
attribute 或
/
嵌套元素来筛选这些包。不要在 srcdir
attribute(或嵌套的
元素)中包含部分包结构,否则每次运行编译目标时 Ant 都会重新编译源文件。有关更多信息,请参阅 Ant FAQ。
如果希望只编译特定的文件并禁用 javac 的默认搜索机制,则可以取消设置 sourcepath
attribute:
这样,javac 将编译 ${src}
目录下的所有 Java 源文件,但跳过所有 Example.java。如果某些非示例文件引用了这些 Example.java,编译器可能会产生错误。
如果希望使用特殊的 JDK(Ant 当前使用的 JDK 除外)进行编译,请设置 executable
和 fork
attribute。使用 taskname
可能会在日志中显示这些设置已修复。
如果要激活其他编译器选项(如 lint
),可以使用
元素:
如果要使用自定义的 CompilerAdapter org.example.MyAdapter
,可以使用编译器属性:
或定义一个类型并将其嵌套到任务中,如中所示:
在这种情况下,CompilerAdapter 可以支持自己的 attribute 和嵌套元素。
以下示例演示了 Java 9+ module 的使用。在 ${src}
目录下的单个模块中编译所有 .java 文件,并将 .class 文件存储在 ${build}
目录中。编译使用位于 modules
文件夹中的应用程序模块。源代码级别为 9 以启用 Java 9 的 module 特性。
编译 ${src}
目录下所有源 module 中 gen/classes、lin32/classes 和 lin64/classes 中的所有 .java 文件。在 ${build}
目录中生成模块目录。${build}
目录下生成的每个模块目录所包含的 .class 文件都来自来对应的源模块。*
是表示编译模块集中任何模块的名称的标记。{ ... , ... }
表示二选一的选择。编译使用位于 modules
文件夹中的应用程序模块。源代码级别为 9 以启用 Java 9 的 module 特性。
package-info.java
java 5 中引入了 package-info.java
文件以允许包级别的注释。在编译时,如果 .java 文件不包含运行时注释,则不会有相应的 .class 文件。在 Ant 1.7.1 之前,当再次运行
任务时,该任务将再次尝试编译 package-info.java 文件。
在 Ant1.7.1 中,引入了一种不同的逻辑,包含了含有 .class 文件的目录的时间戳。这个逻辑导致 Ant 在某些设置中不会重新编译 package-info.java。
自 Ant 1.8.0 以来,如果 Ant 编译 package-info.java,并且编译器本身没有创建 package-info.class 文件,则会创建一个空的 package-info.class 文件。
还有一些不常用的编译相关的 Task:JspC、Wljspc、Rmic、NetRexxC、Depend。这里就不做详细介绍了,详情请参考相关文档。