Domanda

Come osservato in documentazione , Gradle utilizza un grafo orientato aciclico (DAG) per costruire un grafico delle dipendenze. Dalla mia comprensione, avendo cicli separati per la valutazione e l'esecuzione è una caratteristica importante per un tool di creazione. per esempio. Il Gradle doc afferma che questa abilita alcune funzioni che altrimenti sarebbero impossibili.

Mi interessa esempi reali che illustrano la potenza di questa funzione. Quali sono alcuni casi d'uso per il quale un grafico delle dipendenze è importante? Sono particolarmente interessato a storie personali dal campo, sia con Gradle o uno strumento simile attrezzata.

io sto facendo questa 'comunità wiki' fin dall'inizio, in quanto sarà difficile valutare una risposta 'giusta'.

È stato utile?

Soluzione

Questa domanda prevista provocatoria motivazione per finalmente guardare in Gradle. Io ancora non l'ho usato, in modo da poter offrire solo l'analisi ha rilevato durante la navigazione dei documenti, non storie personali.

La mia prima domanda è stata il motivo per cui un grafico compito dipendenze Gradle è garantito per essere aciclico. Non ho trovato la risposta a questa, ma un caso contrario è facilmente costruiti, quindi mi presumo che il rilevamento di ciclo è una conferma che viene eseguito quando il grafico è costruito, e la compilazione fallisce prima dell'esecuzione della prima operazione se ci sono dipendenze cicliche illegali. Senza prima costruzione del grafico, questa condizione di guasto potrebbe non essere scoperto fino alla generazione è quasi completa. Inoltre, la procedura di individuazione dovrebbe eseguire dopo ogni operazione è stata eseguita, il che sarebbe molto inefficiente (finché il grafico è stato costruito in modo incrementale e disponibile globalmente, una ricerca in profondità sarebbe necessaria solo per trovare un punto di partenza, e successiva le valutazioni del ciclo di richiederebbe un lavoro minimo, ma il lavoro totale sarebbe ancora maggiore di fare una riduzione singola sull'intero insieme di relazioni, in via preliminare). Mi piacerebbe cogliere un diagnosi precoce come un vantaggio importante.

Una dipendenza compito può essere pigro (vedi: 4,3 relazioni tra le attività, e un esempio relativo a 13.14). dipendenze delle attività pigri non potevano essere valutate correttamente finché è costruito l'intero grafico. Lo stesso vale per la risoluzione delle dipendenze transitiva (non-task), che potrebbe causare innumerevoli problemi, e richiedono ricompilazioni ripetuti come dipendenze aggiuntive vengono rilevati e risolti (anche richiedendo ripetute richieste ad un repository). La funzione di regole compito (13.8) non sarebbe possibile neanche. Questi problemi, e probabilmente molti altri, possono essere generalizzati considerando che Gradle utilizza un linguaggio dinamico, e può aggiungere dinamicamente e modificare i compiti, così prima di una valutazione di primo passaggio, i risultati potrebbero essere non deterministica dal momento che il percorso di esecuzione è costruito e modificato durante il runtime, in tal modo, diverse sequenze di valutazione potrebbero produrre risultati diversi arbitrariamente se ci sono dipendenze o direttive comportamentali che non sono noti fino a tardi, perché non sono stati ancora creato. (Questo può essere degna di indagare con alcuni esempi concreti Se è vero, allora anche due passaggi non sarebbero sempre sufficienti Se A -..> B, B -> C, dove C modifica il comportamento di A in modo che non sia più dipende da B, allora avete un problema. Spero che ci sono alcune buone pratiche applicabili alla limitazione metaprogrammazione con portata non locale, di non permettere in compiti arbitrari. un esempio divertente sarebbe una simulazione di un paradosso viaggio nel tempo, in cui un nipote uccide il nonno o la nonna sposa, vividamente illustrando alcuni principi etici pratiche!)

Si può consentire una migliore stato e il progresso di segnalazione su una costruzione attualmente in esecuzione. Un TaskExecutionListener fornisce prima / dopo ganci al trattamento di ogni attività, ma senza conoscere il numero di attività rimanenti, non c'è molto che potrebbe dire di stato diverso da "6 attività completate. A proposito di eseguire attività foo". Invece, si potrebbe inizializzare una TaskExecutionListener con il numero di attività in gradle.taskGraph.whenReady, e poi attaccarlo al TaskExecutionGraph. Ora potrebbe fornire informazioni per permettere i dettagli del report come "6 su 72 attività completate Now executing foo compito Tempo residuo stimato:... 2h 38m" Sarebbe utile per visualizzare su una console per un server di integrazione continua, o se Gradle è stato utilizzato per orchestrare un grande costruire e ora le stime multi-progetto sono stati cruciali.

Come sottolineato da Jerry Bullard, la porzione di valutazione del ciclo di vita è fondamentale per determinare il piano di esecuzione, che fornisce informazioni sull'ambiente, poiché l'ambiente è parzialmente determinata dal contesto di esecuzione (Esempio 4.15 nella configurazione dalla sezione DAG ). Inoltre, ho potuto vedere questo essere utile per l'ottimizzazione di esecuzione. independsottotracciati ent potrebbero essere consegnati in modo sicuro per diversi thread. Camminando algoritmi per l'esecuzione può essere meno intensivo di memoria se non sono ingenui (la mia intuizione dice che sempre a piedi il percorso con il maggior numero di sottotracciati sta per portare ad uno stack più grande di preferire sempre i percorsi con il minimo sottotracciati).

Un uso interessante di questo potrebbe essere una situazione in cui molti componenti di un sistema sono inizialmente spense a sostenere dimostrazioni e sviluppo incrementale. Poi, durante lo sviluppo, piuttosto che l'aggiornamento della configurazione di generazione, come ogni componente viene implementato, l'accumulo stesso potrebbe determinare se un sottoprogetto è pronto per l'inclusione ancora (forse cerca di afferrare il codice, compilarlo, ed eseguire una suite di test pre-determinato) . Se lo è, la fase di valutazione avrebbe rivelato questo, e le attività appropriate dovrebbe essere incluso, in caso contrario, seleziona i compiti per i mozziconi. Forse c'è una dipendenza da un database Oracle, che non è ancora disponibile, e si sta utilizzando un database incorporato nel frattempo. Si potrebbe far controllare l'accumulo della disponibilità, in modo trasparente commutare quando può, e dirvi che è acceso database, piuttosto che raccontarla. Ci potrebbe essere un sacco di usi creativi del genere.

Gradle sembra impressionante. Grazie per provocare qualche ricerca!

Altri suggerimenti

dalla stessa documentazione illustra la potenza di questo approccio:

  

Come descriviamo in dettaglio più avanti   (Vedere il Capitolo 30, il ciclo di vita di costruzione)   Gradle ha una fase di configurazione e   una fase di esecuzione. Dopo il   fase di configurazione Gradle sa tutto   compiti che devono essere eseguiti. Gradle   vi offre un gancio a fare uso di questo   informazione. Un caso d'uso per questo sarebbe   essere quello di controllare se il compito è di rilascio   parte dei compiti da eseguire.   In base a questa è possibile assegnare   valori diversi per alcune variabili.

In altre parole, è possibile collegare nel processo di generazione in anticipo, in modo da poter alterare il suo corso, se necessario. Se era già stato eseguito un lavoro costruzione attuale, potrebbe essere troppo tardi per cambiare.

sto valutando diversi sistemi di compilazione ora e con Gradle ho riuscito ad aggiungere codice brutto che enumera tutte le attività di tipo 'vaso' e cambia così, che ogni barattolo manifesta comprende l'attributo 'Build-Number' (che viene utilizzato in seguito per comporre i nomi dei file finali):

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)
    }
}
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top