編譯 Java 原始碼樹。
原始碼和目標目錄將會遞迴掃描 Java 原始碼檔案以進行編譯。只有沒有對應的 .class 檔案或 .class 檔案比 .java 檔案舊的 .java
檔案才會被編譯。
注意:Apache Ant 僅使用原始碼和類別檔案的名稱來尋找需要重新建置的類別。它不會掃描原始碼,因此不會知道巢狀類別、名稱與原始碼檔案不同的類別等。請參閱 <depend>
任務,以取得基於其他而非僅存在/修改時間的相依性檢查。
當原始碼檔案是套件的一部分時,原始碼樹的目錄結構應遵循套件階層。
可以精簡要編譯的檔案組。這可以使用 includes、includesfile、excludes 和 excludesfile 屬性來完成。使用 includes 或 includesfile 屬性,您可以指定要包含的檔案。exclude 或 excludesfile 屬性用於指定要排除的檔案。在兩種情況下,檔案清單都可以透過檔案名稱(相對於 srcdir 屬性或巢狀 <src>
元素中指定的目錄)或使用萬用字元模式來指定。請參閱 基於目錄的任務 部分,以取得有關如何包含/排除檔案以及如何撰寫萬用字元模式的資訊。
可以使用不同的編譯器。這可以透過設定全域性 build.compiler
屬性(這會影響建置中的所有 <javac>
任務)、設定特定於目前的 <javac>
任務的 compiler 屬性,或使用任何 typedef 或 componentdef 輸入類型(實作 org.apache.tools.ant.taskdefs.compilers.CompilerAdapter
)的巢狀元素來指定。build.compiler
屬性或 compiler 屬性的有效值為
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 的 Java/Visual J++ SDK 中的命令列編譯器)–
microsoft可用作別名。
kjc(kopi 編譯器)。
gcj(GCC 中的
gcj
編譯器)。sj(Symantec Java 編譯器) –
symantec可用作別名。
extJavac(在自己的 JVM 中執行新式或舊式編譯器)。
預設值為 javacX
,其中 X
取決於執行 Ant 時所使用的 JDK 版本。如果您希望使用提供的編譯器介面以外的介面,您可以撰寫一個實作 CompilerAdapter 介面的類別 (套件 org.apache.tools.ant.taskdefs.compilers
)。在 build.compiler
屬性或 compiler 屬性中提供完整的類別名稱。
fork 屬性會覆寫 build.compiler
屬性或 compiler 屬性設定,並預期在 JAVA_HOME
中設定 JDK 1.1 或更高版本。
您也可以使用 compiler 屬性來告訴 Ant 在組合命令列開關時應該假設哪個 JDK 版本,即使您設定 fork=true
。如果您要在目前的 JDK 為 1.2+ 時執行 JDK 1.1 的編譯器,這會很有用。如果您使用 compiler=javac1.1
且 (例如) depend=true
,Ant 會使用命令列開關 -depend,而不是 -Xdepend。
此任務會從傳遞給編譯器的類別路徑中移除指向不存在檔案/目錄的所有項目。
分岔執行檔 (如果有) 的工作目錄是專案的基本目錄。
Windows 注意事項:當新式編譯器在 Windows 上以非分岔模式使用時,它會鎖定存在於 <javac>
任務類別路徑中的檔案,且不會釋放它們。這會導致的副作用是您無法在稍後的建置中刪除或移動這些檔案。解決方法是在呼叫編譯器時分岔執行。
如果您的來源包含使用 @Native
註解註解的原生方法或欄位,您可以設定 nativeheaderdir 屬性,以便使用 javac 的 -h 開關來產生原生標頭檔。請注意,Ant 用來判斷要編譯哪些檔案的邏輯不會考量原生標頭,也就是說,如果 .class 比對應的 .java 檔案新,則即使為其產生的原生標頭檔已過時,檔案也不會被編譯。
屬性 | 說明 | 需要 |
---|---|---|
srcdir | Java 檔案的位置。(請參閱以下的 註解。) | 是,除非有嵌套的 <src> 元素或 modulesourcepath 屬性或對應元素 |
destdir | 儲存類別檔案的位置。 | 否 |
includes | 必須包含的檔案模式的逗號或空格分隔清單。 | 否;預設為所有 .java 檔案 |
includesfile | 檔案名稱。此檔案的每一行都視為包含模式。 | 否 |
excludes | 必須排除的檔案模式的逗號或空格分隔清單。 | 否;如果 defaultexcludes 為 no,則預設為預設排除或無 |
excludesfile | 檔案名稱。此檔案的每一行都視為排除模式。 | 否 |
defaultexcludes | 表示是否應使用預設排除 (yes|no)。 |
否;預設為 yes |
classpath | 要使用的類別路徑。 | 否 |
sourcepath | 要使用的來源路徑。若要取消 sourcepath 開關,請使用 sourcepath=。 |
否;除非指定嵌套的 <src> 元素,否則預設為 srcdir |
bootclasspath | 引導類別檔案的位置。(請參閱 下方 了解如何使用 -X 和 -J-X 參數指定引導類別路徑)。 | 否 |
classpathref | 要使用的 classpath,指定為對其他地方定義的路徑的 參照。 | 否 |
sourcepathref | 要使用的 sourcepath,指定為對其他地方定義的路徑的 參照。 | 否 |
bootclasspathref | 要使用的 bootstrapclasspath,指定為對其他地方定義的路徑的 參照。 | 否 |
extdirs | 已安裝擴充功能的位置。 | 否 |
encoding | 來源檔案的編碼。(注意:gcj 尚未支援此選項。) |
否 |
nowarn | 表示是否應將 -nowarn 開關傳遞給編譯器。 | 否;預設為 off |
debug | 指出是否應編譯原始碼並附上偵錯資訊。若設為 off,則會在支援的編譯器中傳遞 -g:none 至命令列(對於其他編譯器,則不會使用任何命令列參數)。若設為 true,則 debuglevel 屬性的值會決定命令列參數。 |
否;預設為 off |
debuglevel | 要附加至 -g 命令列開關的關鍵字清單。合法值為 none或下列關鍵字以逗號分隔的清單: lines、 vars和 source。 |
否;當 debug 為 false或任何實作( modern、 javac1.2和 jikes除外)時,會忽略;預設情況下,不會附加任何內容至 -g |
optimize | 指出是否應編譯原始碼並進行最佳化。注意,自 JDK 1.3 起,Sun 的 javac 會忽略此旗標(因為編譯時期最佳化並非必要)。 | 否;預設為 off |
deprecation | 指出是否應編譯原始碼並附上不建議使用的資訊。 | 否;預設為 off |
verbose | 要求編譯器提供詳細的輸出。 | 否;預設為 no |
depend | 為支援此功能的編譯器(jikes和 classic)啟用相依性追蹤。 |
否 |
includeAntRuntime | 是否在類別路徑中包含 Ant 執行時期函式庫。通常最好將此設為 false,如此一來,指令碼的行為就不會受到執行環境的影響。 |
否;預設為 yes,除非已設定 build.sysclasspath 屬性 |
includeJavaRuntime | 是否在類別路徑中包含執行 JVM 的預設執行時期函式庫。 注意:在某些設定中,執行時期函式庫可能是「Ant 執行時期函式庫」的一部分,因此您可能需要明確將 includeAntRuntime 設為 false,以確保不包含 Java 執行時期函式庫。 |
否;預設為 no |
fork | 是否使用 JDK 編譯器外部執行 javac 。 |
否;預設為 no |
executable | 若 fork 為 yes,則完整路徑為 javac 可執行的檔案。 自 Ant 1.6 起,此屬性也可在使用 jikes、 jvc、 gcj或 sj時,用於指定可執行檔案的路徑。 |
否;預設為目前 JDK 的編譯器,如果 fork 為 no則忽略 |
memoryInitialSize | 如果 javac 在外部執行,則為底層 JVM 的記憶體初始大小。(範例:83886080、 81920k或 80m) |
否;預設為標準 JVM 記憶體設定,如果 fork 為 no則忽略 |
memoryMaximumSize | 如果 javac 在外部執行,則為底層 JVM 的記憶體最大大小;否則忽略。(範例:83886080、 81920k或 80m) |
否;預設為標準 JVM 記憶體設定,如果 fork 為 no則忽略 |
failonerror | 表示編譯錯誤是否會導致建置失敗。 | 否;預設為 true |
errorProperty | 如果編譯失敗,則設定為 true的屬性。自 Ant 1.7.1 起。 |
否 |
source | 編譯器接受的 Java 語言功能,如 -source 命令列開關所指定。有效的語言版本為 1.3、 1.4、 1.5或 5等。在 javac1.4(或當 Ant 未在 JVM 1.3 中執行時為 modern)、 gcj和 jikes之前的版本中,所有實作都會忽略此屬性。 如果您將此屬性與 gcj或 jikes搭配使用,您必須確保您的版本支援 -source(或 -fsource,適用於 gcj)開關。 |
否;預設情況下,除非設定神奇的 ant.build.javac.source 屬性,否則完全不會使用 -source 參數請注意,預設值取決於執行 Ant 的 JDK。我們強烈建議您務必指定此屬性。 |
target | 為特定 JVM 版本產生類別檔(交叉編譯)。 | 否;預設情況下,除非設定神奇的 ant.build.javac.target 屬性,否則完全不會使用 -target 參數請注意,預設值取決於執行 Ant 的 JDK 以及 source(請參閱 交叉編譯選項)。我們強烈建議您務必指定此屬性。 |
compiler | 要使用的編譯器實作。請參閱上方 清單 中的有效編譯器。 | 否;預設為 build.compiler 屬性的值(如果已設定),否則預設為目前 JDK 的編譯器 |
listfiles | 指示是否列出要編譯的原始檔。 | 否;預設為 no |
tempdir | Ant 應放置暫存檔的位置。僅在分岔任務且命令列引數長度超過 4 kB 時使用。自 Ant 1.6 起。 | 否;預設為 java.io.tmpdir |
updatedProperty | 如果編譯已執行且成功,則設定為 true的屬性。自 Ant 1.7.1 起。 |
否 |
includeDestClasses | 此屬性控制是否在提供給編譯器的類別路徑中包含目標類別目錄。如果設定為 true(預設),先前編譯的類別會在編譯器的類別路徑中。這表示「貪婪」的編譯器不會重新編譯已編譯的相依類別。一般來說,這很好,因為它會阻止編譯器執行不必要的作業。然而,對於某些涉及泛型的邊緣案例,javac 編譯器需要編譯相依類別才能取得泛型資訊。其中一個範例記載於錯誤報告中:錯誤 40776 - 編譯包含泛型的 Java 5 專案時發生問題。將屬性設定為 false會導致編譯器重新編譯相依類別。自 Ant 1.7.1 起。 |
否;預設為 true |
createMissingPackageInfoClass | package-info.java 檔中的一些封裝層註解不會建立任何 package-info.class 檔,因此 Ant 會每次重新編譯同一個檔。 自 Ant 1.8 起,如果編譯器未建立任何 package-info.class,則會為每個 package-info.java 建立一個空的 package-info.class。 在某些設定中,這個額外的類別會造成問題,可以透過將此屬性設定為 false來抑制。自 Ant 1.8.3 起。 |
否;預設為 true |
modulepath | 指定尋找應用程式模組的位置。模組、模組檔或已展開模組的目錄清單。自 Ant 1.9.7 起 | 否 |
modulepathref | 要使用的 modulepath,以 參考 形式提供,參考其他地方定義的路徑。自 Ant 1.9.7 起 | 否 |
modulesourcepath | 指定尋找多個模組編譯的輸入原始檔的位置。自 Ant 1.9.7 起 | 是,除非存在 srcdir 屬性或巢狀 <src> 元素 |
modulesourcepathref | 要使用的 modulesourcepath,以 參考 形式提供,參考其他地方定義的路徑。自 Ant 1.9.7 起 | 否 |
upgrademodulepath | 指定在執行時期映像中取代可升級模組的模組位置。自 Ant 1.9.7 起 | 否 |
upgrademodulepathref | 要使用的 upgrademodulepath,以 參考 形式提供,參考其他地方定義的路徑。自 Ant 1.9.7 起 | 否 |
nativeheaderdir | 指定放置產生的原生標頭檔案的位置。自 Ant 1.9.8 起。 | 否,在 JDK 7 或更早版本編譯時會忽略 |
release | 指定 --release 開關的值。 當設定並在 JDK 9+ 上執行時,source 和 target 屬性以及 bootclasspath 將會被忽略。自 Ant 1.9.8 起。 | 否,在 JDK 8 或更早版本編譯時會忽略 |
此任務形成一個隱含的 FileSet,並支援大多數 <fileset>
的屬性(dir 變成 srcdir),以及巢狀的 <include>
、<exclude>
和 <patternset>
元素。
srcdir
、classpath
、sourcepath
、bootclasspath
、modulepath
、modulesourcepath
、upgrademodulepath
和 extdirs
<javac>
的 srcdir、classpath、sourcepath、bootclasspath、extdirs、modulepath、modulesourcepath 和 upgrademodulepath 屬性是 類別路徑結構,也可以透過巢狀的 <src>
(注意名稱不同!)、<classpath>
、<sourcepath>
、<bootclasspath>
、<extdirs>
、<modulepath>
、<modulesourcepath>
和 <upgrademodulepath>
元素分別設定。
您可以使用巢狀的 <compilerarg>
元素,為編譯器指定額外的命令列引數。這些元素的指定方式類似於 命令列引數,但有一個額外的屬性,可用於僅在使用特定編譯器實作時啟用引數。
屬性 | 說明 | 需要 |
---|---|---|
value | 請參閱 命令列引數。 | 其中之一 |
line | ||
file | ||
path | ||
prefix | 請參閱 命令列引數。自 Ant 1.8 起。 | 否 |
suffix | 否 | |
compiler | 僅在所選的編譯器實作與此屬性的值相符時,才傳遞指定的引數。合法值與上述 清單 中有效的編譯器相同。) | 否 |
自 Ant 1.8.0 起
載入編譯器實作時,若已指定自訂類別,則持有要使用的類別路徑的 類別路徑結構。使用內建編譯器之一時,不會有任何影響。
CompilerAdapter
型別的任何巢狀元素自 Ant 1.8.0 起
如果已定義的型別實作 CompilerAdapter
介面,則可將該型別的巢狀元素用作 compiler 屬性的替代方案。
編譯 .java 目錄下的所有檔案,並將 .class 檔案儲存在 .build 目錄中。所使用的類別路徑包含 xyz.jar,且已開啟使用偵錯資訊進行編譯。來源層級為 1.4
,因此您可以使用 assert
陳述式。
<javac srcdir="${src}" destdir="${build}" classpath="xyz.jar" debug="on" source="1.4"/>
編譯 .java 目錄下的所有檔案,並將 .class 檔案儲存在 .build 目錄中。使用預設 javac 可執行檔分岔 Java 編譯器。來源層級為 1.2
(類似於 1.1
或 1.3
),且類別檔案也應該可以在 JDK 1.2+ 中執行。
<javac srcdir="${src}" destdir="${build}" fork="true" source="1.2" target="1.2"/>
編譯 .java 目錄下的所有檔案,並將 .class 檔案儲存在 .build 目錄中。使用名為 java$javac.exe 的可執行檔分岔 Java 編譯器。請注意,$
符號需要用另一個符號進行跳脫。來源層級為 1.5
,因此您可以使用泛型。
<javac srcdir="${src}" destdir="${build}" fork="java$$javac.exe" source="1.5"/>
編譯 .java 目錄下的檔案,並將 .class 檔案儲存在 ${build}
目錄中。所使用的類別路徑包含 xyz.jar,且已開啟偵錯資訊。僅使用 mypackage/p1 和 mypackage/p2 下的檔案。mypackage/p1/testpackage 目錄中及以下的所有檔案都從編譯中排除。您未指定來源或目標層級,因此實際使用的值會取決於您使用 Ant 執行 JDK。
<javac srcdir="${src}" destdir="${build}" includes="mypackage/p1/**,mypackage/p2/**" excludes="mypackage/p1/testpackage/**" classpath="xyz.jar" debug="on"/>
這與前一個範例相同,但增加了第二個來源路徑,由屬性 src2 定義。也可以使用巢狀 <src>
元素來表示,如下所示
<javac destdir="${build}" classpath="xyz.jar" debug="on"> <src path="${src}"/> <src path="${src2}"/> <include name="mypackage/p1/**"/> <include name="mypackage/p2/**"/> <exclude name="mypackage/p1/testpackage/**"/> </javac>
如果您想執行不同 JDK 的 javac 編譯器,您應該告訴 Ant 在哪裡可以找到編譯器以及您將使用哪個版本的 JDK,以便它可以選擇正確的命令列開關。下列範例在新的程序中執行 JDK 1.1 javac,並使用正確的命令列開關,即使 Ant 在不同版本的 JVM 中執行
<javac srcdir="${src}" destdir="${build}" fork="yes" executable="/opt/java/jdk1.1/bin/javac" compiler="javac1.1"/>
注意:如果您只想編譯位於共用根目錄下特定套件中的來源檔案,請使用 include/exclude 屬性或 <include>
/<exclude>
內嵌元素來過濾這些套件。請勿在 srcdir 屬性(或內嵌 <src>
元素)中包含套件結構的一部分,否則每次執行編譯目標時,Ant 都會重新編譯您的來源檔案。請參閱 Ant 常見問答集 以取得更多資訊。
如果您只想編譯明確指定的檔案並停用 javac
的預設搜尋機制,則可以取消設定 sourcepath 屬性
<javac sourcepath="" srcdir="${src}" destdir="${build}" > <include name="**/*.java"/> <exclude name="**/Example.java"/> </javac>
這樣,javac
將會編譯 ${src} 目錄下的所有 Java 來源檔案,但會略過範例。如果某些非範例檔案參照範例檔案,編譯器甚至會產生錯誤。
如果您想使用特殊 JDK(與 Ant 目前使用的 JDK 不同)編譯,請設定 executable 和 fork 屬性。使用 taskname 可以顯示在記錄中,這些設定是固定的。
<javac srcdir="" destdir="" executable="path-to-java14-home/bin/javac" fork="true" taskname="javac1.4"/>
如果您想啟用其他編譯器選項,例如 lint
,您可以使用 <compilerarg>
元素
<javac srcdir="${src.dir}" destdir="${classes.dir}" classpathref="libraries"> <compilerarg value="-Xlint"/> </javac>
如果您想使用自訂 CompilerAdapter org.example.MyAdapter
,您可以使用 compiler 屬性
<javac srcdir="${src.dir}" destdir="${classes.dir}" compiler="org.example.MyAdapter"/>
或定義一個類型並將其內嵌到任務中,如下所示
<componentdef classname="org.example.MyAdapter" name="myadapter"/> <javac srcdir="${src.dir}" destdir="${classes.dir}"> <myadapter/> </javac>
在這種情況下,您的編譯器適配器可以支援自己的屬性和內嵌元素。
下列範例示範如何使用 Java 9+ 模組。
在 ${src} 目錄下的單一模組中編譯所有 .java 檔案,並將 .class 檔案儲存在 ${build}
目錄中。編譯使用位於 modules 資料夾中的應用程式模組。來源層級為 9
以啟用模組。
<javac srcdir="${src}" destdir="${build}" includeantruntime="false" modulepath="modules" source="9"/>
編譯 .java 檔案在 gen/classes,lin32/classes 和 lin64/classes
在 ${src}
目錄下的所有原始碼模組。在 ${build} 目錄產生模組目錄。每個在 ${build} 目錄下產生的模組目錄包含 .class
檔案從對應的原始碼模組。* 是代表編譯模組集中任何模組名稱的代碼。{ ... , ... }
表示擴充的替代。編譯使用位於 modules
資料夾的應用程式模組。原始碼層級是 9
以啟用模組。
<javac modulesourcepath="${src}/*/{gen,lin{32,64}}/classes" destdir="${build}" includeantruntime="false" modulepath="modules" source="9"/>
你需要 Jikes 1.15 或更新版本。
Jikes 支援一些額外的選項,可以在呼叫任務之前定義顯示在下面的屬性來設定。每個屬性的設定會在整個建置中對所有 <javac>
任務生效。Ant 開發人員知道這很醜陋而且不靈活 – 預期未來會有更好的解決方案。所有選項都是布林值,而且必須設定為 true
或 yes
才能解釋為除了 false
之外的任何東西。預設值,build.compiler.warnings
是 true
,而其他都是 false
。
屬性 | 說明 | 預設值 |
---|---|---|
build.compiler.emacs |
啟用相容 emacs 的錯誤訊息。 | false |
build.compiler.fulldepend |
啟用完整依賴性檢查;請參閱 Jikes 手冊中的 +F 開關。 |
false |
build.compiler.pedantic |
啟用嚴格警告。 | false |
build.compiler.warnings 已過時。改用 <javac> 的 nowarn 屬性。 |
不要停用警告訊息。 | true |
Jvc
會啟用 Microsoft 擴充,除非你在呼叫 <javac>
之前將屬性 build.compiler.jvc.extensions
設定為 false
。
Sun javac 編譯器有一個 -bootclasspath 命令列選項—這對應到 <javac>
任務的 bootclasspath 屬性/元素。Sun 編譯器也允許使用 -X 和 -J-X 屬性對引導類別路徑進行更多控制。可以透過使用 <compilerarg>
來設定這些。自 Ant 1.6.0 起,有一個捷徑可以將路徑參照轉換成字串,可以在作業系統獨立的方式中使用(請參閱 pathshortcut)。例如
<path id="lib.path.ref"> <fileset dir="lib" includes="*.jar"/> </path> <javac srcdir="src" destdir="classes"> <compilerarg arg="-Xbootclasspath/p:${toString:lib.path.ref}"/> </javac>
javac
編譯器 由 OpenJDK 專案提供,是一個開源專案。此專案的輸出為包含 javac 編譯器的 javac.jar
。此編譯器可用於 <javac>
任務,並搭配 -Xbootclasspath/p Java 參數使用。參數必須提供給 javac 可執行檔的執行時期系統,因此需要加上 -J 前綴,例如
<property name="patched.javac.jar" location="${my.patched.compiler}/dist/lib/javac.jar"/> <presetdef name="patched.javac"> <javac fork="yes"> <compilerarg value="-J-Xbootclasspath/p:${patched.javac.jar}"/> </javac> </presetdef> <patched.javac srcdir="src/java" destdir="build/classes" debug="yes"/>
package-info.java 檔案在 Java 5 中引入,用於允許套件層級註解。在編譯時,如果 .java
檔案不包含執行時期註解,則不會有對應的 .class
檔案。在 Ant 1.7.1 之前,當 <javac>
任務再次執行時,任務會嘗試再次編譯 package-info.java 檔案。
在 Ant 1.7.1 中,引入了不同的邏輯,其中涉及通常會包含 .class 檔案的目錄的時間戳記。此邏輯導致 Ant 在某些設定中無法重新編譯 package-info.java。
自 Ant 1.8.0 起,如果 Ant 編譯 package-info.java,且編譯器本身未建立 package-info.class 檔案,則會建立「空的」package-info.class 檔案。