On Github finn-no / Gradle-on-Academy
FINN reise
Hei, jeg heter Stig, jobber i FINN reise og tenkte jeg skulle gi dere en liten introduksjon til byggeverktøyet Gradle. Og kom gjerne med spørsmål underveis! Men før jeg kommer til Gradle, tenkte jeg jeg skulle ta dere med på en liten reise; en tidsreise.$ which java /usr/bin/java $ ./gradlew buildDet er veldig lett å komme i gang med eksisterende bygg. Så lenge JDK-en er installert, så kan man bare kjøre et medfølgende script, gradlew, som laster ned oppgitt versjon av Gradle, hvis det ikke allerede er gjort, og kjører i gang bygget. Med dette sikrer en også at alle bruker samme versjon av Gradle for å bygge prosjektet. Dette er en feature som kalles Gradle Wrapper og er en bootstrap for å komme igang med Gradle. Med wrapper trenger en ikke å ha installert Gradle, kan spesifisere en spesifikk versjon, sjekke inn "all" konfig for prosjektet
apply plugin: 'java'Mindre kompleksitet ved å følge Gradle's (Maven's) konvensjoner slik at det blir veldig lite konfigurasjon. Dette er alt som behøves for å kompilere, kjøre tester og bygge jar.
featureTest.dependsOn startJetty build.dependsOn featureTestAlt som gjøres i et bygg er modellert som tasks, f.eks. clean, test, jar og build. Disse blir lagt inn i bygget av plugins, f.eks. java-pluginen, og satt sammen i en spesifikk rekkefølge. En vil også typisk lage egne task der en trenger noe utover det som følger med i pluginene. Rekkefølgen på alle tasker kan enkelt endres på hvis en behøver det. (Maven har også tasks, men disse er koblet til en fase. Det er fasene som er satt til å kjøre i en spesiell rekkefølge. Dvs. at det ikke er mulig å si at en Maven-task skal kjøre før en annen uten å gå via faser. Dette gir ekstra kompleksitet med veldig liten gevinst.)
apply from: 'http://..../codecheck.gradle'Typisk når en får litt større prosjekter er det ønskelig å dele bygge-script på tvers av disse. Gradle gjør dette veldig enkelt med f.eks. å injecte felles konfigurasjon fra et sted inn i alle eller spesifikke subprosjekter, eller å importere gjenbrukbare script fra en URL/fil.
apply plugin: GreetingPlugin class GreetingPlugin implements Plugin<Project> { void apply(Project project) { project.task('hello') << { println "Hello from the GreetingPlugin" } } } build.dependsOn helloEn plugin er egentlig bare en pakke med gjenbrukbar bygge-logikk, noe som gjør de enkle å lage. Og hvis det allerede finnes en ant task som gjør jobben kan denne gjenbrukes veldig enkelt.
A rich and deep API makes complex problems easy to solve
task npmInstall(type: Exec) { inputs.file "package.json" outputs.dir "node_modules" commandLine 'npm', 'install' } test.dependsOn npmInstallInkrementelle bygg gjør at Gradle bare kjører det som er nødvendig, f.eks. vil den ikke kjøre tester hvis ikke noe kode er forandret. Dette er en del av APIet og ikke noe hver plugin trenger å implementere selv. Her er et eksempel på hvordan incremental build enkelt kan settes opp. Tasken vil bare kjøre hvis det er gjort endringer på package.json eller katalogen node_modules ikke finnes. Her setter en også opp at denne tasken skal kjøres før test kjøres.
$ ls -1f example-api/ example-integration/ example-web/ gradle/ wrapper/ gradle-wrapper.jar gradle-wrapper.properties build.gradle gradlew gradlew.bat settings.gradle
include 'example-web', 'example-api', 'example-integration'i settings.gradle setter en opp hvilke prosjekter som inngår i multiprosjektet.
allprojects { apply plugin: 'maven' group = 'no.finn.travel' version = '1.0.0-snapshot' } subprojects { apply plugin: 'java' apply from: 'http://.../codecheck.gradle' sourcecompatibility = 1.7 targetcompatibility = 1.7 }
dependencies { compile project(':example-api') ... }viser også hvordan en setter opp avhengighet til et annet prosjekt i et multiprosjekt. som dere ser, er det ikke nødvendig å spesifisere versjonsnummer for interne avhengigheter! noen her som har slitt med merging av versjonsnummer?
dependencies { compile 'org.slf4j:slf4j-api:1.7.5' testcompile 'junit:junit:4.11' } repositories { maven { url = 'http://mavenproxy.finntech.no/finntech-release/' } }et enkelt eksempel på en dependency-seksjon med 1 compile og 1 test compile dependency. viser også hvordan en setter opp en maven repo.
configurations { compile.transitive = false testcompile.transitive = false all*.exclude group: 'commons-logging' }først setter vi at dependencies i compile og testcompile scope ikke skal resolve deps transitivt. dette betyr at en må spesifisere selv i scriptet alle deps som din kode bruker. den siste linjen ekskluderer dependencien for alle scopes, eller configurations som gradle kaller det.
ext.versions = [ thrift: '0.9.1' ] configurations { all*.resolutionstrategy { force "org.apache.thrift:libthrift:${versions.thrift}" eachdependency { details -> // always use the glassfish version of the javax.inject library if (details.requested.name == 'javax.inject') { details.usetarget "org.glassfish.hk2.external:javax.inject:${details.requested.version}" } } } }ved å lage en egen strategi kan en f.eks. force versjonsnummer på tvers av alle konfigurasjoner og subprosjekt. eller bytte ute group-id/artifact-id på dependencies f.eks. i de tilfeller der det finnes flere versjoner av et api. her er også et eksempel på hvordan man drar ut versjonsnummer fra dependencien.
apply plugin: 'java' dependencies { compile 'org.slf4j:slf4j-api:1.7.5' testcompile 'junit:junit:4.11' } repositories { maven { url = 'http://mavenproxy.finntech.no/finntech-release/' } }