Programmer til trinvis bygning af projekter

Et program til trinvis bygning af projekter er et objekt, der arbejder med ressourcerne i et projekt på en bestemt måde. Programmer til trinvis bygning af projekter bruges ofte til at transformere en ressource for at producere en anden ressource eller artefakt. Ressourcer, der er oprettet af et byggeprogram, er typisk markeret som afledte ressourcer.

Plugins leverer programmer til trinvis bygning af projekter til platformen for at implementere specialiserede ressourcetransformationer. JDT (Java Development Tools) definerer f.eks. et program til trinvis bygning af projekter, som kompilerer en Java-kildefil til en klassefil, hver gang en fil tilføjes eller ændres i et Java-projekt. Det holder også styr på afhængige filer og rekompilerer dem, når og hvis det er nødvendigt.

Fra et API-synspunkt definerer platformen to basisbyggetyper:

En trinvis bygning rangeres med en ressourceændringsdelta. Deltaet afspejler nettovirkningen af alle ressourceændringer, der er foretaget, siden byggeprogrammet sidst byggede projektet. Denne delta ligner den, der benyttes i ressourceændringsaktiviteter.

Brugeren kan regelmæssigt rydde op i projekter for at gennemtvinge genbygning af et fuldstændigt projekt, næste gang en trinvis bygning udføres for projektet. Når et projekt ryddes op, fjernes byggeoplysninger, f.eks. problemmarkeringer og klassefiler.

Forståelsen af byggeprogrammer lettes ved et eksempel. JDT-Java-compileren drives af et Java-program til trinvis bygning af projekter, og det rekompilerer de filer i et projekt, der påvirkes af ændringer. Når en fuldstændig bygning udløses (eller i tilfælde af en trinvis bygning efter en oprydning), kompileres alle .java-filer i projektet. Eventuelle kompileringsprogrammer, der opstår, tilføjes som problemmarkeringer i de påvirkede .java-filer. Når en trinvis bygning udløses, rekompilerer byggeprogrammet selektivt de tilføjede, ændrede eller ellers påvirkede .java-filer, der er beskrevet i ressourcedelta, og opdaterer problemmarkeringerne efter behov. De .class-filer eller markeringer, der ikke længere er relevante, fjernes.

Trinvis bygning indebærer markante ydeevnefordele for projekter med hundredvis eller tusindvis af ressourcer, hvoraf hovedparten slet ikke ændres på noget tidspunkt.

Den tekniske udfordring ved trinvis bygning ligger i at beslutte, hvad der skal bygges igen. Den interne tilstand f.eks., som vedligeholdes af Java-byggeprogrammet, inkluderer bl.a. en afhængighedsgraf og en liste over rapporterede kompileringsproblemer. Disse oplysninger bruges under en trinvis bygning til at identificere, hvilke klasser der har brug for at blive rekompileret, som svar på en ændring, der er foretaget i en Java-ressource.

Selvom basisstrukturen for bygning er defineret i platformen, foretages det egentlige arbejde i byggeprogrammets kode. Mønstre for implementering af komplekse trinvise byggeprogrammer ligger uden for denne gennemgang, da implementeringen er afhængig af det pågældende byggeprograms design.

Start bygning

Et byggeprogram kan startes eksplicit på en af følgende måder:

I virkeligheden udløser brugeren af arbejdsbænken en bygning ved at vælge de relevante kommandoer på menuen til navigation af ressourcer.

Programmer til trinvis bygning startes også implicit af platformen under en automatisk bygning. Hvis automatisk bygning er aktiveret, udføres det, hver gang arbejdsområdet ændres.

Definér program til trinvis bygning

Udvidelsespunktet org.eclipse.core.resources.builders bruges til at levere et program til trinvis bygning af projekter til platformen. Følgende kode viser, hvordan den hypotetiske plugin com.example.builders kan levere et program til trinvis bygning af projekter.

   <extension
      id="mybuilder" name="Mit byggeprogram" point="org.eclipse.core.resources.builders">
      <builder
         <run 
            class="com.example.builders.BuilderExample">
            <parameter name="optimize" value="true" />
            <parameter name="comment" value="Kommentar til byggeprogram" />
         </run>
      </builder>
</extension>   

Denne klasse, som er angivet i udvidelsespunktet, skal udvide platformens klasse IncrementalProjectBuilder.

   public class BuilderExample extends IncrementalProjectBuilder {
      IProject[] build(int kind, Map args, IProgressMonitor monitor)
         throws CoreException {
         // Tilføj byggelogik her
         return null;
      }
      protected void startupOnInitialize() {
         // Tilføj logik til start af byggeprogram her
      }
      protected void clean(IProgressMonitor monitor) {
         // Tilføj logik til oprydning af byggeprogram her
      }
   }

Byggeprocessen starter med metoden build(), som indeholder oplysninger om den type bygning, der er anmodet om. Bygningen har en af følgende værdier:

Hvis der er anmodet om en trinvis bygning, stilles en ressourcedelta til rådighed, som beskriver de ændringer, der er foretaget til ressourcen siden den sidste bygning. Følgende stykke kode illustrerer metoden build() yderligere:

   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 ske under bygningen af projekt "X,", at et byggeprogram skal bruge oplysninger om et andet projekt "Y." , f.eks. hvis en Java-klasse i X implementerer en grænseflade, som stilles til rådighed i Y. Når X bygges, er et delta for Y tilgængeligt vha. getDelta(Y). For at sikre at platformen kan stille deltaer til rådighed, skal X's byggeprogram have erklæret afhængigheden mellem X og Y ved at returnere en array, der indeholder Y fra et tidligere build()-kald. Hvis et byggeprogram ikke har nogen afhængigheder, returnerer det blot Null. I IncrementalProjectBuilder finder du flere oplysninger.

Fuldstændig bygning

Den logik, der kræves for at behandle en anmodning om fuldstændig bygning, er afhængig af plugin'en. Det kan indebære, at alle ressourcer i projektet skal besøges, eller at andre projekter skal undersøges, hvis der eksisterer afhængigheder mellem projekter. Følgende stykke kode angiver, hvordan en fuldstændig bygning kan implementeres.

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

Byggegæsten udfører bygningen for den pågældende ressource (og svarer true for at kunne besøge alle underordnede ressourcer).

   class MyBuildVisitor implements IResourceVisitor {
      public boolean visit(IResource res) {
         //bygger den angivne ressource.
         //returner true for at kunne besøge de underordnede elementer.
               return true;
      }
   }

Besøgsprocessen fortsætter, indtil hele ressourcetræstrukturen er gennemgået.

Trinvis bygning

Når der udføres en trinvis bygning, arbejder byggeprogrammet med en ressourceændringsdelta i stedet for en hel ressourcetræstruktur.

   protected void incrementalBuild(IResourceDelta delta, 
         IProgressMonitor monitor) throws CoreException {
      // den besøgende udfører arbejdet.
      delta.accept(new MyBuildDeltaVisitor());
   }

Besøgsprocessen fortsætter, indtil hele ressourcedeltatræstrukturen er gennemgået. Typen af ændringer ligner dem, der er beskrevet i Implementér ressourceændringslytter. En vigtig forskel i forbindelse med programmer til trinvis bygning af projekter er, at du arbejder med en ressourcedelta, der er baseret på et bestemt projekt, og ikke hele arbejdsområdet.

Ryd op inden bygning

Arbejdsbænken giver brugere mulighed for at rydde op i et projekt eller et projektsæt, inden du starter en bygning. Denne funktion tillader, at brugeren gennemtvinger ombygning fra bunden for visse projekter. Byggeprogrammer bør implementere denne metode for at rydde op i problemmarkeringer og afledte ressourcer i projektet.

Tilknyt et program til trinvis bygning af projekter til projekt

For at gøre et byggeprogram tilgængeligt for et givent projekt skal det inkluderes i projektets byggespecifikationer. Et projekts byggespecifikationer er en liste over de kommandoer, der skal udføres, når projektet bygges. Hver kommando oplyser navnet på et program til trinvis bygning af projekter.

Bemærk: Navnet på byggeprogrammet i en byggekommando er den fuldt kvalificerede id til byggeprogramudvidelsen. Den fuldt kvalificerede id for en udvidelse oprettes ved, at plugin-id'en kombineres med den simple filtype-id i filen plugin.xml. Eksempel: Et byggeprogram med en enkel udvidelses-id "mybuilder" i plugin'ens "com.example.builders" har navnet "com.example.builders.mybuilder"

Følgende stykke kode tilføjer et nyt byggeprogram som det første byggeprogram i listen over byggeprogrammer.

   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) { 
      // Tilføjer byggeprogram til projekt
      ICommand command = desc.newCommand();
      command.setBuilderName(BUILDER_ID);
      ICommand[] newCommands = new ICommand[commands.length + 1];

      // Tilføjer det før andre byggeprogrammer.
      System.arraycopy(commands, 0, newCommands, 1, commands.length);
      newCommands[0] = command;
      desc.setBuildSpec(newCommands);
      project.setDescription(desc, null);
   }

Et projekts byggeprogram konfigureres kun én gang, og det er som regel i forbindelse med projektets oprettelse. En almindelig måde at knytte et byggeprogam til et projekt på er at konfigurere en projektnatur.