Trinnvise prosjektbyggere

En trinnvis prosjektbygger er et objekt som manipulerer ressursene i et prosjekt på en bestemt måte. Trinnvise prosjektbyggere brukes ofte på en omdanning av en ressurs for å lage en ressurs eller artefakt av en annen type. Ressurser opprettet av en bygger er typisk merket som avledede ressurser.

Plugin-moduler oppgir trinnvise prosjektbyggere til plattformen for å implementere spesialiserte ressursomdanninger. For eksempel kan Java Development Tools (JDT) definere en trinnvis prosjektbygger som kompilerer en Java-kildefil til en klassefil hver gang en fil legges til eller endres i et Java-prosjekt. Den holder også rede på avhengige filer og kompilerer dem på nytt ved behov.

Fra et programmeringsgrensesnittperspektiv definerer plattformen to grunnleggende typer bygging:

Trinnvise byggere mates med en ressursendringsdelta. Deltaen reflekterer nettoeffekten av alle endringene siden sist byggeren bygde prosjektet. Deltaen likner på den som er brukt i ressursendringshendelser.

Brukeren kan rydde prosjektene periodisk for å tvinge fram en gjenoppbygging av et komplett prosjekt neste gang det utføres en trinnvis bygging i prosjektet. Ved å rydde prosjektet fjernes bygginformasjon, for eksempel problemmerker og klassefiler.

Det er enklest å forstå byggere gjennom å se på eksempler. JDT Java-kompilatoren drives av en trinnvis Java-prosjektbygger som kompilerer filene på nytt, i et prosjekt som påvirkes av endringer. Når en fullstendig bygging utløses (eller en trinnvis bygging etter en rydding), kompileres alle .java-filene i prosjektet. Eventuelle kompileringsproblemer legges til som problemmerker i de berørte .java-filene. Når en trinnvis bygging utløses, kompilerer byggeren selektivt .java-filene som er lagt til, endret eller på annen måte berørt, og som er beskrevet i ressursdeltaen. Problemmerkene oppdateres ved behov. Alle .class-filer eller -merker som ikke lenger er korrekte, fjernes.

Trinnvis bygging har åpenbare ytelsesfordeler for prosjekter med hundre- eller tusenvis av ressurser, de fleste av dem uten å endres på et gitt tidspunkt.

Den tekniske utfordringen for trinnvis bygging består i å finne ut nøyaktig hva som skal bygges på nytt. Den interne tilstanden som vedlikeholdes av Java-byggeren, omfatter for eksempel et avhengighetsdiagram og en liste over rapporterte kompileringsproblemer. Denne informasjonen brukes under en trinnvis bygging for å identifisere hvilke klasser som skal kompileres på nytt, som et svar på en endring i en Java-ressurs.

Selv om den grunnleggende strukturen for bygging er definert i plattformen, utføres selve arbeidet i byggerkoden. Her skal vi ikke komme nærmere inn på mønstre for implementering av komplekse byggere, siden implementeringen avhenger av den bestemte designen i byggeren.

Starte en bygging

En bygger kan startes eksplisitt på en av følgende måter:

I praksis utløser arbeidsbenkbrukeren en bygging ved å velge kommandoer på ressursnavigatormenyen.

Trinnvise prosjektbyggere kan også startes implisitt av plattformen under en automatisk bygging. Hvis de er aktivert, kjører automatiske byggere hver gang det oppstår endringer i arbeidsområdet.

Definere en trinnvis prosjektbygger

Utvidelsespunktet org.eclipse.core.resources.builders brukes til å oppgi en trinnvis prosjektbygger til plattformen. Følgende kodetype viser hvordan den hypotetiske plugin-modulen com.example.builders kan bidra med en trinnvis prosjektbygger.

      <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>

Klassen som identifiseres i utvidelsespunktet, må utvide plattformklassen IncrementalProjectBuilder.

   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
      }
   }

Byggbehandling begynner med metoden build(), som inneholder informasjon om den forespurte byggtypen. Bygget er en av følgende verdier:

Hvis det er forespurt en trinnvis bygging, oppgis en ressursdelta for å beskrive endringene i ressursene siden siste bygging. Følgende snutt raffinerer metoden 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;
   }

Det kan hende at byggeren under byggingen av prosjekt "X", trenger informasjon om endringer i et annet prosjekt, "Y".  (For eksempel hvis en Java-klasse i X implementerer et grensesnitt som er oppgitt i Y.)  Under byggingen av X er delta for Y tilgjengelig ved å kalle getDelta(Y).  For å sikre at plattformen kan oppgi slike deltaer, må X ha en bygger som har deklarert avhengigheten mellom X og Y ved å returnere en matrise som inneholder Y fra et tidligere kall av build(). Hvis en bygger ikke har avhengigheter, kan null returneres. Du finner mer informasjon i IncrementalProjectBuilder.

Fullstendig bygging

Logikken som kreves for å behandle en fullstendig bygging, er spesifikk for plugin-modulen. Den kan omfatte besøk i alle prosjektets ressurser eller undersøke andre prosjekter for å finne ut om det er avhengigheter mellom prosjekter. Nedenfor ser du et eksempel på en snutt for implementering av fullstendig bygging.

   protected void fullBuild(final IProgressMonitor monitor) throws CoreException {
  try {
         getProject().accept(new MyBuildVisitor());
      } catch (CoreException e) { }
   }

Den besøkende utfører byggingen for den spesifikke ressursen (og svarer "true" til videre besøk av alle de underordnede ressursene).

   class MyBuildVisitor implements IResourceVisitor {
      public boolean visit(IResource res) {
         //build the specified resource.
         //return true to continue visiting children.
               return true;
      }
   }

Besøksprosessen fortsetter til hele ressurstreet er besøkt.

Trinnvis bygging

Når det utføres en trinnvis bygging, arbeider byggeren med en ressursendringsdelta i stedet for et komplett ressurstre.

   protected void incrementalBuild(IResourceDelta delta, 
         IProgressMonitor monitor) throws CoreException {
      // the visitor does the work.
      delta.accept(new MyBuildDeltaVisitor());
   }

Besøksprosessen fortsetter til hele ressursdeltatreet er besøkt. Den spesifikke typen endringer likner på den som er beskrevet i Implementere en ressursendringslytter.   En vesentlig forskjell er at du med trinnvise prosjektbyggere arbeider med en ressursdelta basert på et bestemt prosjekt, ikke hele arbeidsområdet.

Rydde før en bygging

Arbeidsbenken gjør det mulig for brukere å rydde et prosjekt eller sett med prosjekter før de starter en bygging. Med denne funksjonen kan brukere tvinge en gjenoppbygging fra grunnen av bare i bestemte prosjekter. Byggere bør implementere denne metoden til å rydde opp eventuelle problemmerker og avledede ressurser i prosjektet.

Knytte en trinnvis prosjektbygger til et prosjekt

Hvis du vil gjøre en bygger tilgjengelig for et bestemt prosjekt, må den tas med i byggspesifikasjonene for prosjektet. Byggspesifikasjonene for et prosjekt er en liste over kommandoer som skal kjøres når prosjektet bygges, i oppgitt rekkefølge. Hver kommando navngir en enkel trinnvis prosjektbygger.

MERK: Byggernavnet i en byggekommando er den fullt kvalifiserte IDen for byggerutvidelsen. Den fullt kvalifiserte IDen for en utvidelse opprettes ved å kombinere plugin-modulens ID med den enkle utvidelse-IDen i filen plugin.xml. For eksempel har en bygger med den enkle utvidelse-IDen "mybuilder" i plugin-modulen "com.example.builders", navnet "com.example.builders.mybuilder".

Følgende snutt legger til en ny bygger som den første byggeren i den eksisterende listen over byggere.

   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);
   }

Byggeren for et prosjekt konfigureres bare en gang, vanligvis når prosjektet opprettes. En vanlig måte å knytte en bygger til et prosjekt på er å konfigurere en prosjektnatur.