增量專案建置器是一種物件,以特定的方式操作專案內的資源。增量專案建置器通常用於應用資源轉換來產生另一種資源或加工品。
外掛程式提供增量專案建置器資料給平台,以便實作 private 資源轉換。 例如,Java 開發工具 (JDT) 定義增量專案建置器,該建置器可於 Java 專案中新增或修改檔案的任何時候,將 Java 程式檔編譯成類別檔。它也會追蹤相依檔並在必要時重新編譯。
從 API 的觀點來看,平台定義兩種基本的建置類型:
增量建置隨資源變更差異起始。這個差異反映建置器上次建立專案後所有資源變更的 網路效應。 這個差異類似資源變更事件內使用的差異。
使用者可以定期清理專案,以便下次對該專案執行增量建置時能夠強制重新建置整個專案。清理專案會移除建置資訊,如問題標記和類別檔。
建置器最能經由範例來瞭解。JDT Java 編譯器是由 Java 增量專案建置器所驅動,可重新編譯專案中受變更影響的檔案。當觸發完整建置時(或清理之後的增量建置),會編譯專案中的所有 .java 檔。任何發現的編譯問題都會新增為受影響 .java 檔上的問題標記。當觸發增量建置時,建置器會選擇性地重新編譯資源差異中描述的新增、變更或其他受影響的 .java 檔,並在必要時更新問題標記。任何不再適合的 .class 檔 或標記都會被除去。
增量建置對於具有數以百計或千計資源的專案有顯著的效能優點,大部分資源在將 來任何給定的時間上不會改變。
增量建置的技術盤查是正確判定哪些需要重新建置。例如,Java 建置器維護的內部狀態,包括像報告的編譯問題清單及相依關係圖形等事件。這項資訊在增量建置期間用來識別為回應 Java 資源變更而需要重新編譯的類別。
雖然建置的基礎結構是在平台中定義,但實際工作是在建置器程式碼中完成。實作複雜增量建置器的型樣超出本討論範圍,因為實作與特定建置器設計有關。
下列其中一種方法可明確地呼叫建置器:
事實上,工作台使用者藉由選取資源導覽器功能表中的對應指令來觸發建置。
自動建置期間,平台也可隱含地呼叫增量專案建置器。 若啟用,則每當工作區有變更便會執行自動建置。
org.eclipse.core.resources.builders 延伸點用來提供增量專案建置器資料給平台。下列標記顯示假設的外掛程 式 com.example.builders 如何提供增量專案建置器資料。
<extension id="mybuilder" name="My Sample Builder" point="org.eclipse.core.resources.builders"> <builder <run class="com.example.builders.BuilderExample"> <parameter name="optimize" value="true" /> <parameter name="comment" value="Builder comment" /> </run> </builder> </extension>
延伸點中識別的類別必須延伸平台類別 IncrementalProjectBuilder。
public class BuilderExample extends IncrementalProjectBuilder { IProject[] build(int kind, Map args, IProgressMonitor monitor) throws CoreException { // 在此處新增建置邏輯 return null; } protected void startupOnInitialize() { // 在此處新增建置器 init 邏輯 } protected void clean(IProgressMonitor monitor) { // 在此新增建置器清理邏輯 } }
以 build() 方法開始的建置處理程序,包括所要求建置種類的相關資訊。建置是下列其中一個值:
如果所要求的是增量建置,便會提供資源差異來說明上次建置後資源的變更。下列片段進一步修正 build() 方法。
protected IProject[] build(int kind, Map args, IProgressMonitor monitor throws CoreException { if (kind == IncrementalProjectBuilder.FULL_BUILD) { fullBuild(monitor); } else { IResourceDelta delta = getDelta(getProject()); if (delta == null) { fullBuild(monitor); } else { incrementalBuild(delta, monitor); } } return null; }
有時在建置專案 "X"、建置器需要其他某個專案 "Y" 變更 的相關資訊時會發生這個修正。(比方說,如果 X 中的 Java 類別實作 Y 中提 供的介面。)當建置 X 時,呼叫 getDelta(Y) 可取得 Y 的差異。為確保平台可提供這種差異,X 的建置器必須先宣告 X 和 Y 之間的相依關係 ,方法是從上一個 build() 呼叫傳回含有 Y 的陣列。如果建置器沒有相依關係,則只會傳回空值。 進一步資訊請參閱 IncrementalProjectBuilder。
處理完整建置要求所需的邏輯對外掛程式而言是特定的。可能包括造訪專案中的每個資 源,甚或查驗其他專案間是否有相依關係。下列片段建議如何實作完整建置。
protected void fullBuild(final IProgressMonitor monitor) throws CoreException {try { getProject().accept(new MyBuildVisitor()); } catch (CoreException e) { } }
建置訪客針對特定資源執行建置(然後回答 True 來繼續造訪所有子項資源)。
class MyBuildVisitor implements IResourceVisitor { public boolean visit(IResource res) { //建置指定的資源。 //傳回 True 以繼續造訪子項。 return true; } }
繼續執行造訪處理程序,直到訪遍整個資源樹狀結構為止。
當執行增量建置時,建置器使用資源變更差異代替完整資源樹。
protected void incrementalBuild(IResourceDelta delta, IProgressMonitor monitor) throws CoreException { // 由訪客完成這個工作。 delta.accept(new MyBuildDeltaVisitor()); }
繼續執行造訪處理程序,直到訪遍整個資源差異樹狀結構為止。 變更的特定本質類似說明於實作資源變 更接聽器中的本質。其中一個重要的差異是,對於增量專案建置器而言,您是根據特定專案而非整個工作區來使用資源差異。
工作台允許使用者在起始建置之前清理一個專案或一組專案。這項特性允許使用者只對某些專案強制從頭開始重新建置。建置器應該實作這個方法來清理專案中的任何問題標記和衍生資源。
欲使建置器適用指定的專案,它必須併入專案的建置規格中。 專案的建置規格是建置專案時依序執行的指令清單。每一個指令命名單一增量專案 建置器。
附註:建置指令中的建置器名稱是建置器副檔名的完整 ID。將外掛程式 ID 與 plugin.xml 檔的副檔名 ID 結合後,便可建立副檔名的完整 ID。例如,外掛程式 "com.example.builders" 中,具有簡式副檔名 ID "mybuilder" 的建置器,其名稱則為 "com.example.builders.mybuilder"
。 下列片段新增建置器為現行建置器清單中第一個建置器。
final String BUILDER_ID = "com.example.builders.mybuilder"; IProjectDescription desc = project.getDescription();ICommand[] commands = desc.getBuildSpec();boolean found = false; for (int i = 0; i < commands.length; ++i) { if (commands[i].getBuilderName().equals(BUILDER_ID)) { found = true; break; } } if (!found) { //新增建置器到專案中 ICommand command = desc.newCommand(); command.setBuilderName(BUILDER_ID); ICommand[] newCommands = new ICommand[commands.length + 1]; // 在其他建置器之前新增它。 System.arraycopy(commands, 0, newCommands, 1, commands.length); newCommands[0] = command; desc.setBuildSpec(newCommands); project.setDescription(desc, null); }
配置專案的建置器只做一次,通常是在專案建立完成時。