gradle in a polyglot world

52
GRADLE IN A POLYGLOT WORLD Schalk Cronjé

Upload: schalk-cronje

Post on 13-Apr-2017

1.088 views

Category:

Software


0 download

TRANSCRIPT

Page 1: Gradle in a Polyglot World

GRADLE IN A POLYGLOT WORLD

Schalk Cronjé

Page 2: Gradle in a Polyglot World

ABOUT ME

Email:

Twitter / Ello : @ysb33r

[email protected]

Gradle plugins authored/contributed to: VFS, Asciidoctor,JRuby family (base, jar, war etc.), GnuMake, Doxygen

Page 3: Gradle in a Polyglot World

GRADLE

Not just for building JVM projects

Page 4: Gradle in a Polyglot World

GRADLE DSLUnderlying language is Groovy

You don’t need to be a Groovy expert to be a Gradlepower user

Groovy doesn’t need ; in most cases

Groovy does more with less punctuation, making it anideal choice for a DSL

In most cases lines that do not end on an operator isconsidered a completed statement.

Page 5: Gradle in a Polyglot World

GROOVY VS JAVA

In Groovy:

All class members are public by default

No need to create getters/setters for public fields

Both static & dynamic typing supported

def means Object

Page 6: Gradle in a Polyglot World

CALLING METHODSclass Foo { void bar( def a,def b ) {}}

def foo = new Foo()

foo.bar( '123',456 )foo.bar '123', 456

foo.with { bar '123', 456}

Page 7: Gradle in a Polyglot World

CALLING METHODS WITH CLOSURESclass Foo { void bar( def a,Closure b ) {}}

def foo = new Foo()

foo.bar( '123',{ println it } )

foo.bar ('123') { println it}

foo.bar '123', { println it}

Page 8: Gradle in a Polyglot World

MAPS IN GROOVY

Hashmaps in Groovy are simple to use

def myMap = [ plugin : 'java' ]

Maps are easy to pass inline to functions

project.apply( plugin : 'java' )

Which in Gradle can become

apply plugin : 'java'

Page 9: Gradle in a Polyglot World

LISTS IN GROOVY

Lists in Groovy are simple too

def myList = [ 'clone', ''http://github.com/ysb33r/GradleLectures' ]

This makes it possible for Gradle to do

args 'clone', 'http://github.com/ysb33r/GradleLectures'

Page 10: Gradle in a Polyglot World

CLOSURE DELEGATION IN GROOVY

When a symbol cannot be resolved within a closure,Groovy will look elsewhere

In Groovy speak this is called a Delegate.

This can be programmatically controlled via theClosure.delegate property.

Page 11: Gradle in a Polyglot World

CLOSURE DELEGATION IN GROOVY

class Foo { def target}

class Bar { Foo foo = new Foo() void doSomething( Closure c ) { c.delegate = foo c() }}

Bar bar = new Bar()bar.doSomething { target = 10}

Page 12: Gradle in a Polyglot World

MORE CLOSURE MAGIC

If a Groovy class has a method 'call(Closure)`, the object canbe passed a closure directly.

class Foo { def call( Closure c) { /* ... */ }}

Foo foo = new Foo()foo {

println 'Hello, world'

}

// This avoids ugly syntaxfoo.call({ println 'Hello, world' })

Page 13: Gradle in a Polyglot World

CLOSURE DELEGATION IN GRADLE

In most cases the delegation will be entity the closure ispassed to.

Will also look at the Project and ext objects.

The Closure.delegate property allows plugin writersability to create beautiful DSLs

task runSomething(type : Exec ) { cmdline 'git' }

is roughly the equivalent ofExecTask runSomething = new ExecTask()runSomething.cmdline( 'git' )

Page 14: Gradle in a Polyglot World

GRADLE TASKSCan be based upon a task type

task runSomething ( type : Exec ) {

command 'git'

args 'clone', 'https://bitbucket.com/ysb33r/GradleWorkshop'

}

Can be free-formtask hellowWorld << {

println 'Hello, world'

}

Page 15: Gradle in a Polyglot World

GRADLE TASKS : CONFIGURATION VS

ACTION

Use of << {} adds action to be executed

Tasks supplied by plugin will have default actions

Use of {} configures a task

Page 16: Gradle in a Polyglot World

BUILDSCRIPTThe buildscript closure is special

It tells Gradle what to load into the classpath beforeevaluating the script itself.

It also tells it where to look for those dependencies.

Even though Gradle 2.1 has added a new way of addingexternal plugins, buildscript are much more flexible.

Page 17: Gradle in a Polyglot World

EXTENSIONS

Extensions are global configuration blocks added byplugins.

Example: The jruby-gradle-base plugin will add ajruby block.

apply plugin: 'com.github.jruby-gradle.base'

jruby { defaultVersion = '1.7.11'}

Page 18: Gradle in a Polyglot World

JAVA PROJECT

repositories { jcenter()}

apply plugin : 'java'

dependencies { testCompile 'junit:junit:4.1+'}

Page 19: Gradle in a Polyglot World

GRADLE DEPENDENCYMANAGEMENT

Easy to use

Flexible to configure for exceptions

Uses dependencies closure

First word on line is usually name of a configuration.

Configurations are usually supplied by plugins.

Dependencies are downloaded from repositories

Maven coordinates are used as format

Page 20: Gradle in a Polyglot World

GRADLE REPOSITORIES

Specified within a repositories closure

Processed in listed order to look for dependencies

jcenter() preferred open-source repo.

mavenLocal(), mavenCentral(), maven {}

Ivy repositories via ivy {}

Flat-directory repositories via flatDir

Page 21: Gradle in a Polyglot World

BUILDING C++

Page 22: Gradle in a Polyglot World

BUILDING C++ - TOOL SUPPORT

Operating

System

Tool Chain Official

Linux gcc, clang Y

MacOS X Xcode Y

gcc-macports, clang-

macports

N

Windows Visual C++, gcc-cygwin32,

gcc-mingw

Y

Page 23: Gradle in a Polyglot World

gcc-cygwin64 N

Unix-like gcc, clang N

Page 24: Gradle in a Polyglot World

BUILDING C++ - LAYOUT

Need to change convention from traditional C++ projects

.cpp files go in src/${name}/cpp

Exported headers files go in src/${name}/headers

Local header files should be in src/${name}/cpp

Object files will end up in ${buildDir}/objs

Binary files will end up in ${buildDir}/binaries

Page 25: Gradle in a Polyglot World

BUILDING C++ - BASICSapply plugin : 'cpp'

Page 26: Gradle in a Polyglot World

BUILDING C++ - EXECUTABLEmodel { components { hello(NativeExecutableSpec) }}

Page 27: Gradle in a Polyglot World

BUILDING C++ - PROJECT LAYOUT

├── build.gradle└── src └─── hello    ├── cpp │ └─── hello.cpp │    └── headers └─── hello.hpp

Page 28: Gradle in a Polyglot World

BUILDING C++ - EXISTING PROJECTS

Source directories can be adjusted

Alternative compiler locations

Page 29: Gradle in a Polyglot World

BUILDING C++ - ALTERNATIVE

SOURCE

sources { cpp { source { srcDir "myDir" include "**/*.cpp" } }}

Page 30: Gradle in a Polyglot World

BUILDING C++ - OTHER FEATURESCross compilation

Multi-architecture targets

Set compiler & linker flags

Multi-variant builds

Page 31: Gradle in a Polyglot World

BUILDING C++ - WEAKNESSCurrently only have built-in support for CUnit

Only platform configuration tool support is CMake

No Autotools equivalent

DSL can be slicker

Page 32: Gradle in a Polyglot World

BUILDING RUBY

Page 33: Gradle in a Polyglot World

BUILDING JRUBYbuildscript { repositories { jcenter() maven { url "https://plugins.gradle.org/m2/" } }

dependencies { classpath 'com.github.jruby-gradle:jruby-gradle-plugin:1.1.4' }}import com.github.jrubygradle.JRubyExec

Page 34: Gradle in a Polyglot World

BUILDING JRUBYapply plugin: "com.github.jruby-gradle.base"

dependencies {

jrubyExec "rubygems:colorize:0.7.7+"

}

task printSomePrettyOutputPlease(type: JRubyExec) {

description "Execute our nice local print-script.rb"

script "${projectDir}/print-script.rb"

}

(Example from JRuby-Gradle project)

Page 35: Gradle in a Polyglot World

OTHER LANGUAGESC / ASM / Resources (built-in)

Clojure (plugin)

Frege (plugin)

Golang (plugin)

Scala (built-in)

Gosu (plugin)

Page 36: Gradle in a Polyglot World

SUPPORT FOR OTHERBUILDSYSTEMS

ANT (built-in)

GNU Make

MSBuild / xBuild

Grunt

Anything else craftable via Exec or JavaExec task

Page 37: Gradle in a Polyglot World

DOCUMENTATION

Page 38: Gradle in a Polyglot World

BUILDING DOCUMENTATION

Doxygen

Markdown

Asciidoctor

Page 39: Gradle in a Polyglot World

ASCIIDOCTOR

Page 40: Gradle in a Polyglot World

BUILDING WITH ASCIIDOCTORplugins { id 'org.asciidoctor.convert' version '1.5.2'}

Page 41: Gradle in a Polyglot World

BUILDING WITH ASCIIDOCTORrepositories { jcenter()}

asciidoctor { sources { include 'example.adoc' }

backends 'html5'

}

Page 42: Gradle in a Polyglot World

BUILDING WITH DOXYGENplugins { id "org.ysb33r.doxygen" version "0.2"}

doxygen { source file('src/hello/cpp') source file('src/hello/headers') generate_xml true generate_html true file_patterns '*.cpp', '*.hpp' html_colorstyle_sat 100}

Page 43: Gradle in a Polyglot World

PUBLISHING

Built-in to Maven, Ivy

Metadata publishing for native projects still lacking

Various plugins for AWS and other cloud storage

Plain old copies to FTP, SFTP etc.

Page 44: Gradle in a Polyglot World

PUBLISHING VIA VFS

plugins { id "org.ysb33r.vfs" version "1.0-beta3"}

task publishToWebserver {

vfs { cp "${buildDir}/website", "ftp://${username}:${password}@int.someserver.com/var/www", recursive : true, overwrite : true }}

Page 45: Gradle in a Polyglot World

MORE SUPPORT…Official buildsystem for Android

Docker

Hadoop

Page 46: Gradle in a Polyglot World

ENDGAMEGradle is breaking new ground

Ever improving native support

Continuous performance improvements

Go find some more plugins at https://plugins.gradle.org

Page 47: Gradle in a Polyglot World

ABOUT THIS PRESENTATIONWritten in Asciidoctor

Styled by asciidoctor-revealjs extension

Built using:

Gradle

gradle-asciidoctor-plugin

gradle-vfs-plugin

Code snippets tested as part of build

Source code:https://github.com/ysb33r/GradleLectures/tree/AccuLondon

Page 48: Gradle in a Polyglot World

THANK YOUEmail:

Twitter / Ello : @ysb33r

[email protected]

Keep an eye out for https://leanpub.com/idiomaticgradle

Page 49: Gradle in a Polyglot World

MIGRATIONS

Page 50: Gradle in a Polyglot World

ANT TO GRADLE

Reflect Ant Build into Gradleant.importBuild('build.xml')

Page 51: Gradle in a Polyglot World

MAVEN TO GRADLE

Go to directory where pom.xml is and typegradle init --type pom

Page 52: Gradle in a Polyglot World

GNUMAKE TO GRADLE

Call current Makefile from Gradleplugins { id "org.ysb33r.gnumake" version "1.0.2"}import org.ysb33r.gradle.gnumake.GnuMakeBuild

task runMake (type:GnuMakeBuild) { targets 'build','install' flags DESTDIR : '/copy/files/here', BUILD_NUMBER : '12345'}