Frage

Wie in rel="noreferrer"> verwendet Gradle einen gerichteten azyklischen Graphen (DAG) eine Abhängigkeitsgraphen aufzubauen. Von meinem Verständnis, für die Auswertung und Ausführung getrennte Zyklen aufweisen, ist ein wichtiges Merkmal für ein Build-Tool. z.B. Die Gradle doc heißt es, dass dies einige Funktionen ermöglicht, die sonst nicht möglich wären.

Ich habe Interesse an der realen Welt Beispiele, die die Leistung dieser Funktion veranschaulichen. Was sind einige Anwendungsfälle, für die ein Abhängigkeitsgraphen wichtig? Ich bin besonders daran interessiert, persönliche Geschichten aus dem Feld, ob mit Gradle oder ein ähnlich ausgestatteten Werkzeug.

Ich mache diesen ‚Community Wiki‘ von Anfang an, da es schwierig sein wird, eine ‚richtige‘ Antwort zu beurteilen.

War es hilfreich?

Lösung

Diese provokante Frage zur Verfügung gestellt Motivation schließlich in Gradle suchen. Ich habe noch nicht verwendet es, so kann ich nur Analyse bieten festgestellt, während die Dokumentation durchsuchen, nicht persönliche Geschichten.

Meine erste Frage war, warum ein Gradle Aufgabe Abhängigkeitsgraphen garantiert azyklisch sein. Ich fand nicht, die Antwort auf das, aber ein gegenteiligen Fall ist einfach aufgebaut, so dass ich, dass Zykluserfassung vermute eine Validierung ist, die ausgeführt wird, wenn der Graph erstellt wird, und die Erstellung fehl vor der Ausführung der ersten Aufgabe, wenn gibt es illegal zyklische Abhängigkeiten. Ohne zunächst die Grafik zu bauen, könnte dieser Fehlerzustand nicht entdeckt werden, bis der Bau fast abgeschlossen ist. Zusätzlich würde die Erkennungsroutine laufen muß nach jeder Aufgabe ausgeführt wurde, was sehr ineffizient wäre (solange der Graph wurde weltweit schrittweise und verfügbar gebaut, eine Tiefensuche würde nur einen Ausgangspunkt finden erforderlich, und die anschließende Zyklus Evaluationen würde minimalen Aufwand erfordern, aber die gesamte Arbeit wäre noch größer als am Anfang) eine einzige Reduktion auf den gesamten Satz von Beziehungen zu tun. Ich würde die Früherkennung als großer Vorteil ankreiden.

Eine Aufgabe Abhängigkeit kann faul sein (siehe: 4.3 Aufgabe Abhängigkeiten und ein ähnliches Beispiel in 13.14). Faule Aufgabe Abhängigkeiten nicht richtig ausgewertet werden können, bis der gesamte Graph aufgebaut ist. Das gleiche gilt für transitiv (nicht-Aufgabe) der Auflösung von Abhängigkeiten, die unzähligen Probleme verursachen könnte, und erfordern wiederholte Neukompilierungen als zusätzliche Abhängigkeiten erkannt und behoben (auch wiederholte Anfragen an ein Endlager erforderlich). Die Aufgabe Regeln Funktion (13.8) nicht möglich wäre auch nicht. Diese Fragen, und wahrscheinlich viele andere, können verallgemeinert werden, man bedenkt, dass Gradle eine dynamische Sprache verwendet und können dynamisch hinzufügen und Aufgaben ändern, so vor einer ersten Pass Bewertung, könnten Ergebnisse werden nicht deterministisch, da der Pfad Ausführung gebaut und während der Laufzeit geändert, so könnten verschiedene Sequenzen der Auswertung erzeugen willkürlich unterschiedliche Ergebnisse, wenn es Abhängigkeiten oder Verhaltensrichtlinien, die erst später bekannt sind, weil sie noch nicht erstellt worden sind. (Dies kann mit einigen konkreten Beispielen würdig sein zu untersuchen Wenn es wahr ist, dann noch zwei Pässe würden immer nicht ausreichend sein, wenn A -..> B, B -> C, wobei C das Verhalten von A, so dass es nicht mehr ändert hängt von B, dann haben Sie ein Problem. ich hoffe, dass es auf Beschränkung metaprogramming mit nicht-lokalen Bereich einige best Practices sind, ist es nicht in beliebigen Aufgaben zu ermöglichen. ein Spaß Beispiel eine Simulation einer Zeitreise Paradox, wo ein Enkelkind wäre sein Großvater tötet oder seine Großmutter heiratet, anschaulich einige praktische ethische Prinzipien darstellt!)

Es kann besser Status und Fortschritt ermöglicht auf einem aktuell ausgeführten Build berichten. Ein TaskExecutionListener bietet vor / nach dem Haken an die Verarbeitung jeder Aufgabe, aber ohne die Anzahl der verbleibenden Aufgaben zu wissen, gibt es nicht viel es über anderen Status als sagen kann „6 Aufgaben abgeschlossen. Über Aufgabe foo auszuführen.“ Stattdessen könnten Sie eine TaskExecutionListener mit der Anzahl der Aufgaben in gradle.taskGraph.whenReady initialisieren, und befestigen Sie es dann an den TaskExecutionGraph. Nun könnte es Informationen zur Verfügung stellen, um Bericht Details wie enable „6 von 72 Aufgaben abgeschlossen Nun ausgeführte Aufgabe foo Geschätzte verbleibende Zeit:... 2h 38m“ Das wäre nützlich auf einer Konsole für eine kontinuierliche Integration Server angezeigt werden, oder wenn Gradle verwendet wurde eine große Multiprojekt bauen und Zeitschätzungen waren entscheidend orchestrieren.

Wie von Jerry Bullard wies darauf hin, ist die Auswertung Teil des Lebenszyklus entscheidend, um den Ausführungsplan zu bestimmen, welche Informationen über die Umgebung bietet, da die Umgebung teilweise durch den Ausführungskontext (Beispiel 4,15 im Configure durch DAG Abschnitt bestimmt wird ). Außerdem könnte ich diese nützlich für die Ausführung Optimierung sehen. independent Subpfade sicher zu verschiedenen Threads übergeben werden kann. Gehen Algorithmen zur Ausführung weniger speicherintensiv sein kann, wenn sie nicht naiv sind (meine Intuition sagt, dass der Weg mit den meisten Teilstrecken immer zu Fuß geht zu einem größeren Stapel führen, als immer lieben Pfade mit dem am wenigsten Subpfade).

Eine interessante Anwendung könnte dies eine Situation, wo viele Komponenten eines Systems zunächst gerodet werden aus Demos und inkrementelle Entwicklung zu unterstützen. Dann während der Entwicklung, anstatt die Aktualisierung die Build-Konfiguration als jede Komponente implementiert wird, die Build selbst bestimmen könnte, wenn ein Teilprojekt für die Aufnahme bereit ist, noch (vielleicht versucht es, den Code zu packen, kompiliert und führen Sie eine vorher festgelegte Testsuite) . Wenn ja, würde die Auswertestufe diese offenbaren, und die entsprechenden Aufgaben einbezogen würden, sonst wählt er die Aufgaben für die Stubs. Vielleicht gibt es eine Abhängigkeit von einer Oracle-Datenbank, die noch nicht verfügbar ist, und Sie verwenden eine eingebettete Datenbank in der Zwischenzeit. Sie könnten der Build lassen die Verfügbarkeit überprüfen, transparent umschalten, wenn sie kann, und Ihnen sagen, dass es Datenbanken eingeschaltet, anstatt Sie es sagen. Es könnte in diese Richtung viele kreative Anwendungen sein.

Gradle sieht genial. Vielen Dank für einige der Forschung zu provozieren!

Andere Tipps

Ein Beispiel aus der gleichen Dokumentation rel="nofollow zeigt die Leistungsfähigkeit dieses Ansatzes:

  

Wie wir in allen Einzelheiten beschreiben später   (Siehe Kapitel 30, Der Build Lifecycle)   Gradle hat eine Konfigurationsphase und   eine Ausführungsphase. Nach dem   Konfigurationsphase Gradle kennt   Aufgaben, die ausgeführt werden sollen. Gradle   bietet Ihnen einen Haken Gebrauch zu machen   Information. Ein Anwendungsfall hierfür wäre   zu überprüfen, ob die Freigabe Aufgabe ist   Teil der Aufgaben ausgeführt werden.   Abhängig davon können Sie zuweisen   verschiedene Werte einiger Variablen.

Mit anderen Worten, können Sie früh in den Build-Prozess anschließen, so dass man seinen Kurs nach Bedarf ändern kann. Wenn einige Arbeit tatsächlich Build bereits ausgeführt worden ist, kann es zu spät sein, zu ändern.

Ich bin Bewertung verschiedene Build-Systeme jetzt und mit gradle schaffte ich hässlich Code hinzufügen, alle Aufgaben des Typs ‚jar‘ aufzählt und ändert sie so, dass jedes Glas Manifest enthält ‚Build-Nummer‘ Attribut (die später verwendet wird, endgültige Dateinamen zu schreiben):

gradle.taskGraph.whenReady {
    taskGraph ->
    taskGraph.getAllTasks().findAll {
        it instanceof org.gradle.api.tasks.bundling.Jar
    }.each {
        it.getManifest().getAttributes().put('Build-Number', project.buildVersion.buildNumber)
    }
}
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top