Ein Programm für die schrittweise Projekterstellung ist ein Objekt, das die Ressourcen in einem Projekt auf eine bestimmte Weise verarbeitet. Programme für die schrittweise Projekterstellung werden häufig zur Umwandlung einer Ressource eingesetzt, so dass sie eine Ressource oder ein Artefakt eines anderen Typs erstellt.
Plug-ins ergänzen die Plattform durch Programme für die schrittweise Projekterstellung, um spezielle Ressourcenumwandlungen zu implementieren. Die Java Development Tools (JDT) definieren beispielsweise ein Programm für die schrittweise Projekterstellung, mit dem eine Java-Quellendatei immer dann in eine Klassendatei kompiliert wird, wenn eine Datei zu einem Java-Projekt hinzugefügt oder geändert wird. Es überwacht außerdem abhängige Dateien und kompiliert sie bei Bedarf erneut.
Von der Sichtweise einer API aus definiert die Plattform zwei Grunderstellungstypen:
Schrittweise Erstellungen werden mit einem Delta für die Ressourcenänderung vorgenommen. Das Delta gibt den Reineffekt aller Ressourcenänderungen seit der letzten Erstellung des Projekts durch das Erstellungsprogramm an. Dieses Delta ähnelt dem Delta, das innerhalb von Ereignissen für eine Ressourcenänderung verwendet wird.
Projekte können periodisch durch Benutzer bereinigt werden, um bei der nächsten schrittweisen Erstellung eines Projekts die erneute Erstellung des kompletten Projekts zu erzwingen. Bei der Bereinigung eines Projekts werden Erstellungsinformationen wie z.B. Problemmarkierungen und Klassendateien entfernt.
Erstellungsprogramme können am besten durch Beispiele veranschaulicht werden. Der JDT Java-Compiler wird durch ein Programm zur schrittweisen Erstellung von Java-Projekten gesteuert, das Dateien, die von Änderungen betroffen sind, erneut kompiliert. Wenn eine vollständige Erstellung ausgelöst wird (bzw. eine schrittweise Erstellung nach einer Bereinigung), werden alle Dateien mit der Änderung .java im Projekt kompiliert. Alle festgestellten Kompilierungsprobleme werden hierbei als Problemmarkierungen für die betroffenen Dateien des Typs .java hinzugefügt. Wird eine schrittweise Erstellung ausgelöst, kompiliert das Erstellungsprogramm selektiv die Dateien .java erneut, die hinzugefügt, geändert oder auf andere Weise betroffen und im Ressourcendelta beschrieben sind, und aktualisiert ggfs. die Problemmarkierungen wie erforderlich. Alle Dateien .class oder Markierungen, die nicht länger gültig sind, werden entfernt.
Die schrittweise Erstellung bietet offensichtliche Leistungsvorteile bei Projekten, die Hunderte oder Tausende von Ressourcen enthalten, von denen die meisten zu einem bestimmten Zeitpunkt unverändert bleiben.
Die technische Herausforderung besteht bei der schrittweisen Erstellung darin, genau zu ermitteln, welche Ressourcen erneut erstellt werden müssen. Der durch das Java-Erstellungsprogramm verwaltete interne Status enthält beispielweise Informationen wie ein Abhängigkeitsdiagramm, ebenso wie eine Liste der gemeldeten Kompilierungsprobleme. Diese Informationen werden verwendet, um bei einer schrittweisen Erstellung die Klassen zu identifizieren, die als Reaktion auf eine Änderung in einer Java-Ressource erneut kompiliert werden müssen.
Obwohl die Basisstruktur für die Erstellung in der Plattform definiert ist, wird die tatsächliche Arbeit durch den Code des Erstellungsprogramms ausgeführt. Muster für die Implementierung von komplexen Programmen für eine schrittweise Erstellung würden den Rahmen dieser Beschreibung sprengen, da die Implementierung vom Entwurf des spezifischen Erstellungsprogramms abhängig ist.
Ein Erstellungsprogramm kann durch eine der folgenden Aktionen explizit aufgerufen werden:
In der Praxis löst der Workbench-Benutzer eine Erstellung aus, indem die entsprechenden Befehle im Menü der Ressourcensicht "Navigator" ausgewählt werden.
Programme für die schrittweise Projekterstellung werden durch die Plattform außerdem implizit bei einer automatischen Erstellung aufgerufen. Wenn die entsprechende Option aktiviert ist, wird bei jeder Änderung des Arbeitsbereichs eine automatische Erstellung vorgenommen.
Am Erweiterungspunkt org.eclipse.core.resources.builders kann die Plattform durch ein Programm für die schrittweise Projekterstellung ergänzt werden. Die folgende Definition zeigt, wie das hypothetische Plug-in com.example.builders ein Programm für die schrittweise Projekterstellung hinzufügen könnte.
<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-Kommentar" /> </run> </builder> </extension>
Die im Erweiterungspunkt angegebene Klasse muss die Plattformklasse IncrementalProjectBuilder erweitern.
public class BuilderExample extends IncrementalProjectBuilder { IProject[] build(int kind, Map args, IProgressMonitor monitor) throws CoreException { // add your build logic here return null; } protected void startupOnInitialize() { // add builder init logic here } protected void clean(IProgressMonitor monitor) { // add builder clean logic here } }
Der Erstellungsprozess beginnt mit der Methode build(), die Informationen über den angeforderten Typ der Erstellung enthält. Die Erstellung nimmt einen der folgenden Werte an:
Falls eine schrittweise Erstellung (INCREMENTAL_BUILD) angefordert wurde, wird ein Ressourcendelta zur Verfügung gestellt, um die Änderungen zu beschreiben, die seit der letzten Erstellung an den Ressourcen vorgenommen wurden. Der folgende Ausschnitt definiert die Methode build() genauer.
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; }
Manchmal kommt es vor, dass bei der Erstellung des Projekts X ein Erstellungsprogramm Informationen zu Änderungen benötigt, die in einem anderen Projekt (Y) vorgenommen wurden (z. B. wenn eine Java-Klasse in X eine durch Y bereitgestellte Schnittstelle implementiert). Bei der Erstellung von X kann ein Delta für Y zur Verfügung gestellt werden, indem die Methode getDelta(Y) aufgerufen wird. Um sicherzustellen, dass die Plattform solche Deltas zur Verfügung stellen kann, muss das Erstellungsprogramm für X die Abhängigkeit zwischen X und Y deklariert haben. Dies erfolgt durch die Rückgabe eines Bereichs aus einem früheren Aufruf der Methode build(), der Y enthält. Falls ein Erstellungsprogramm keine Abhängigkeiten enthält, kann einfach Null zurückgegeben werden. Weitere Informationen finden Sie unter IncrementalProjectBuilder.
Die Logik, die zur Verarbeitung einer vollständigen Erstellung benötigt wird, ist für das Plug-in spezifisch. Sie kann die Involvierung jeder Ressource im Projekt enthalten, oder sogar andere Projekte untersuchen, wenn zwischen Projekten Abhängigkeiten vorliegen. Der folgende Ausschnitt ist ein Beispiel dafür, wie eine vollständige Erstellung implementiert werden könnte.
protected void fullBuild(final IProgressMonitor monitor) throws CoreException { try { getProject().accept(new MyBuildVisitor()); } catch (CoreException e) { } }
Das Erstellungsprogramm würde in diesem Fall die Erstellung für die spezifische Ressource ausführen (und den Wert "true" (= wahr) für das Berücksichtigen aller untergeordneten Ressourcen angeben).
class MyBuildVisitor implements IResourceVisitor { public boolean visit(IResource res) { //build the specified resource. //return true to continue visiting children. return true; } }
Dieser Prozess wird fortgesetzt, bis die gesamte Ressourcenstruktur durchgearbeitet wurde.
Bei der Durchführung einer schrittweise Erstellung verwendet das Erstellungsprogramm keine vollständige Baumstruktur der Ressourcen, sondern ein Ressourcenänderungsdelta.
protected void incrementalBuild(IResourceDelta delta, IProgressMonitor monitor) throws CoreException { // the visitor does the work. delta.accept(new MyBuildDeltaVisitor()); }
Dieser Prozess wird fortgesetzt, bis die komplette Baumstruktur der Ressourcendeltas durchgearbeitet wurde. Der spezifische Typ der Änderungen entspricht etwa den unter Listener-Funktion für Ressourcenänderungen implementieren beschriebenen Änderungen. Ein wichtiger Unterschied ist jedoch, dass Sie bei Programmen für die schrittweise Projekterstellung mit einem Ressourcendelta arbeiten, das auf einem bestimmten Projekt und nicht auf dem gesamten Arbeitsbereich basiert.
Über die Workbench können Benutzer ein Projekt oder eine Gruppe von Projekten vor Einleitung einer Erstellung bereinigen. Durch diese Komponente kann der Benutzer bestimmen, dass nur bestimmte Projekte von Grund auf erneut erstellt werden. Erstellungsprogramme sollten diese Methode implementieren, um Problemmarkierungen und abgeleitete Ressourcen im Projekt zu entfernen.
Damit für das jeweilige Projekt ein Erstellungsprogramm verfügbar ist, muss es in die Erstellungsspezifikation für das Projekt aufgenommen werden. Die Erstellungsspezifikation eines Projekts ist eine Liste der Befehle, die bei der Erstellung des Projekts nacheinander ausgeführt werden müssen. Jeder Befehl benennt ein einzelnes Programm für die schrittweise Projekterstellung.
ANMERKUNG: Der Name des Erstellungsprogramms in einem Erstellungsbefehl ist die vollständig qualifizierte ID der Erweiterung des Erstellungsprogramms. Die vollständig qualifizierte ID einer Erweiterung wird durch Kombination der ID des Plug-ins mit der ID der einfachen Erweiterung in der Datei plugin.xml erstellt. Beispiel: Ein Erstellungsprogramm mit der einfachen Erweiterungs-ID "mybuilder" in dem Plug-in "com.example.builders" würde den Namen "com.example.builders.mybuilder" erhalten.
Der folgende Ausschnitt fügt ein neues Erstellungsprogramm als erstes Erstellungsprogramm zur vorhandenen Liste der Erstellungsprogramme hinzu.
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) { //add builder to project ICommand command = desc.newCommand(); command.setBuilderName(BUILDER_ID); ICommand[] newCommands = new ICommand[commands.length + 1]; // Add it before other builders. System.arraycopy(commands, 0, newCommands, 1, commands.length); newCommands[0] = command; desc.setBuildSpec(newCommands); project.setDescription(desc, null); }
Die Konfiguration des Erstellungsprogramms für ein Projekt muss nur ein Mal vorgenommen werden. Dies erfolgt für gewöhnlich im Rahmen der Projekterstellung.