2012-03-02 17 views
17

Sto cercando di eseguire il porting di una build di maven per gradle. Una delle funzionalità di Maven è pom inheritance, in cui posso dichiarare una varietà di comportamento comune in un pom, pubblicarlo in un repository e utilizzarlo tramite l'elemento <parent> in un progetto concreto.Come condividere un build.gradle comune tramite un repository?

La mia Q è semplicemente se esiste un comportamento equivalente in gradle?

Ho già fatto questo in ant + ivy importando un file build.xml comune che si è basato su aver già verificato il percorso del comune build.xml dal controllo del codice sorgente o usando qualcosa come svn: externals. Posso ripetere questo approccio senza alcuna difficoltà, ma questa sembra essere una cosa che fa abbastanza bene quindi sarebbe bello vedere qualcosa di simile in gradle.

risposta

9

La mia soluzione attuale è l'opzione 3; confezionare gli script comuni in un vaso come risorse e quindi unjar durante la sezione buildscript in questo modo

buildscript { 
    repositories { 
     // enterprise repo here 
    } 
    dependencies { 
     classpath 'com.foo.bar:common-build:0.1.0-SNAPSHOT' 
    } 
    dependencies { 
     ant.unjar src: configurations.classpath.singleFile, dest: 'build/gradle' 
    } 
} 

apply from: 'build/gradle/common.gradle' 

Questo sembra fare quello che voglio.

+0

È piuttosto un trucco. Cosa speri di ottenere da ciò? –

+2

Non sono abbastanza sicuro se dovrei essere orgoglioso della mia creatività o disonorato dal mio trucco. Il guadagno è un modo ovvio (per me) di condividere una versione specifica di una build comune che definisce un modo standard per un set di progetti strettamente correlati (ma non parte dello stesso progetto multiprogetto) da costruire. Ho ridotto una precedente versione basata su convenzioni ant + ivy basata sulla convenzione (che arriva a poche migliaia di righe di xml + tutte le specifiche del modulo ivy.xml) fino a poche centinaia di righe di uno script di compilazione comune (che si occupa principalmente di parte specifica di quella build e ha i deps standard) quindi sono abbastanza felice. – Matt

+1

considerando che l'approccio di cui sopra era buono per la prototipazione ma alla fine si è stabilizzato su alcuni plugin. – Matt

18

ci sono due possibilità:

  1. pubblicare uno script di build a un server web, e includerlo con apply from: "http://path/to/script.gradle"

  2. Scrivi un plugin Gradle, pubblicarlo come un vaso ad un Maven o Ivy repository, e comprendono con:

    buildscript { 
        repositories { .. } 
        dependencies "mygroup:myplugin:1.0" 
    } 
    
    apply plugin: "myplugin" 
    

Il la seconda opzione è più complicata, ma anche un po 'più potente. Ad esempio, i plugin Jars verranno memorizzati nella cache, mentre attualmente gli script di compilazione remota non lo faranno. In generale, consiglio di iniziare con 1. e passare a 2. se e una volta diventa necessario. In futuro, Gradle probabilmente offrirà un meccanismo che combina la facilità d'uso di 1. con i vantaggi di 2.

+0

è possibile pubblicare il build.gradle condiviso in un repository impacchettandolo come plugin o semplicemente pubblicare plugin che fanno roba in un progetto? Non riesco a vedere alcun esempio su come fare il primo e non è ovvio come lo si possa fare. – Matt

+1

È possibile pubblicare uno script di compilazione in un server Web/repository accessibile tramite HTTP o pubblicare un plug-in in un repository. Quest'ultima è una classe che implementa l'interfaccia 'Plugin' confezionata come Jar. La [guida per l'utente] (http://gradle.org/docs/current/userguide/userguide_single.html#N150A4) spiega come viene eseguita quest'ultima. –

+1

@PeterNiederwieser Trovo 'apply from: url' funziona solo con http non https, questo è documentato? – Blundell

11

Edifici sulla soluzione di Matt, ho trovato il seguente per essere un po 'più pulito:

buildscript { 
    repositories { 
    <your repos> 
    } 
    dependencies { 
    classpath '<your jar>' 
    } 
} 

afterEvaluate { project -> // afterEvaluate for resolving the build script dependency 
    apply from: project.buildscript.classLoader.getResource('path/to/your/resource/in/the/jar').toURI() 
} 

Solo i miei due centesimi. :-)

+0

Mi piace il fatto che questo mantenga i file in un barattolo piuttosto che in quelli non aperti, ma consente anche l'uso di file di script gradle. Sarebbe dispendioso in termini di tempo convertire tutti i miei script correnti in plugin (o è più facile di quanto penso?). –

+0

È facile scrivere un proprio plug-in, principalmente solo posizioni e confezioni specifiche oltre a un semplice descrittore. Vedi 58.5 su http://www.gradle.org/docs/current/userguide/custom_plugins.html –

+0

Questa sembra una buona soluzione, ma continuo a ricevere errore: (218, 0) Impossibile leggere lo script 'jar: file:/... 'C'è qualche ragione per cui questo sta accadendo? – PSIXO

7

ho una risposta e un'altra domanda:

In primo luogo, per accedere a un file condiviso da un archivio (ad esempio Nexus) si può costruire un URL che include una query:

apply from: 'http://server-url/nexus/service/local/artifact/maven/redirect?r=repository-name&g=group-name&a=build-common&e=gradle&v=LATEST' 

L'ho fatto per il nostro progetto e funziona alla grande. Posso gestire il file 'build-common.gradle' in un progetto SVN separato e caricarlo su Nexus come SNAPSHOT. L'URL precedente (con i valori appropriati inseriti per 'server-url', 'repository-name' e 'group-name') trova l'ultimo SNAPSHOT del mio script .gradle che ho caricato. Non è necessario confezionarlo in un barattolo.

+0

Si prega di inviare solo la parte risposta come risposta. – lpapp

6

La mia versione:

repositories { 
    <your repos> 
} 
configurations { 
    scripts 
} 
dependencies { 
    scripts group: 'org.foo', name: 'build', version: '1.0.0', ext: 'gradle' 
    // add more scrips if needed 
} 
configurations.scripts.resolve().each { apply from: it } 
1

Mi piace il suo approccio @ user3394219

ho scritto un piccolo plug-in facendo la cosa simile:

plugins { 
    id "com.orctom.applyscript" version "1.1" 
} 
applyscript '{{groupA}}:{{nameA}}:{{versionA}}/{{path-of-fileA.gradle}}' 
applyscript '{{groupA}}:{{nameA}}:{{versionA}}/{{path-of-fileB.gradle}}' 
applyscript '{{groupA}}:{{nameA}}:{{versionB}}/{{path-of-fileC.gradle}}' 
applyscript '{{groupC}}:{{nameD}}:{{versionE}}/{{path-of-fileX.gradle}}' 

o

plugins { 
    id "com.orctom.applyscript" version "1.1" 
} 
dependencies { 
    scripts '{{groupA}}:{{nameA}}:{{versionA}}' 
    scripts '{{groupA}}:{{nameA}}:{{versionB}}' 
    scripts '{{groupC}}:{{nameD}}:{{versionE}}' 
} 

applyscript '{{nameA}}-{{versionA}}/{{path-of-fileA.gradle}}' 
applyscript '{{nameA}}-{{versionA}}/{{path-of-fileB.gradle}}' 
applyscript '{{nameA}}-{{versionB}}/{{path-of-fileC.gradle}}' 
applyscript '{{nameD}}-{{versionE}}/{{path-of-fileX.gradle}}' 

https://plugins.gradle.org/plugin/com.orctom.applyscript

+0

Mi piacerebbe che funzionasse in 'settings.gradle' durante l'inizializzazione, ma ottengo' Errore: Causa: org.gradle.initialization.DefaultSettings_Decorated non può essere lanciato su org.gradle.api.Project' – Ben

1

Ecco un miglioramento alla soluzione accettata, per quando si dispone di più di una dipendenza nel tuo buildscript:

buildscript { 
    repositories { 
     // Repositories 
    } 
    dependencies { 
     classpath 'com.foo.bar:project-extension:1.0.0' 
     classpath 'com.foo.bar:some-dependency-1:2.0.0' 
     classpath 'com.foo.bar:other-dependency-1:3.0.0' 
    } 
    dependencies { 
     delete "gradle/ext" 
     def jars = configurations.classpath.files as List<File> 
     ant.unjar src: jars.find { it.name.matches '.*project-extension.*' }, dest: 'gradle/ext' 
    } 
} 

apply from: 'gradle/ext/common.gradle' 

funzionato come un fascino per me.

Problemi correlati