+ All Categories
Home > Technology > Buildr In Action @devoxx france 2012

Buildr In Action @devoxx france 2012

Date post: 19-May-2015
Category:
Upload: alexismidon
View: 2,290 times
Download: 3 times
Share this document with a friend
Description:
Buildr is a modern build system for Java-based applications including support for Scala, Groovy and a growing number of JVM languages and tools. Buildr combines the expressiveness of the Ruby scripting language with a familiar dependency-based task execution model and project-level structure similar to Apache Maven. This session will introduce Buildr and demonstrate practical solutions to common build problems. Creative Commons License v2.0 with attribution ©Alex Boisvert
Popular Tags:
68
1 by Alexis Midon @alexizany Build like you code with Apache Buildr
Transcript
Page 1: Buildr In Action @devoxx france 2012

1

by Alexis Midon@alexizany

Build like you code with

Apache Buildr

Page 2: Buildr In Action @devoxx france 2012

2

{ Why, How, Demo of }

a Build System that

{ does not suck,

gets out of the way,

lets you write code }

Page 3: Buildr In Action @devoxx france 2012

About Me

Page 4: Buildr In Action @devoxx france 2012

Alexis Midon@alexiszany

[email protected]

Page 5: Buildr In Action @devoxx france 2012

www.c3-e.com

Page 6: Buildr In Action @devoxx france 2012

Sail & Live in San Francisco, CA'Since 2007'

Page 7: Buildr In Action @devoxx france 2012

JavaJavascript

RubyScala

...

Page 8: Buildr In Action @devoxx france 2012

Use Buildron daily basis

and still lovin'it!

Page 9: Buildr In Action @devoxx france 2012

PracticalIntroduction to Apache Buildr

Page 10: Buildr In Action @devoxx france 2012

Where & Whyit all started

Page 11: Buildr In Action @devoxx france 2012

Apache OdeLarge Java Enterprise

Middleware

Page 12: Buildr In Action @devoxx france 2012

15+ modules9 databases

120+ dependencies3 distributionstooling heavy

...

Page 13: Buildr In Action @devoxx france 2012

Maven25,433 lines of XML

spread over 52 files (!)

Page 14: Buildr In Action @devoxx france 2012

“@&#!There's

Got To Be A Better

Way”

Page 15: Buildr In Action @devoxx france 2012

What wasReally Wanted

Page 16: Buildr In Action @devoxx france 2012

No XML.Please!

Page 17: Buildr In Action @devoxx france 2012

FlexibleEasy to customize & extend

Page 18: Buildr In Action @devoxx france 2012

DRY CodeBasic abstraction and

structuring mechanisms

Page 19: Buildr In Action @devoxx france 2012

In other words,a real scripting language.

Page 20: Buildr In Action @devoxx france 2012

Result?drum_roll....

roulement_de_tambour...

Page 21: Buildr In Action @devoxx france 2012

Before52 files

5,433 lines of XML.

Page 22: Buildr In Action @devoxx france 2012

Before52 files

5,433 lines of XML.

AfterSingle file.

486 lines of Ruby.

Page 23: Buildr In Action @devoxx france 2012

Bonus!Twice as fast.

Page 24: Buildr In Action @devoxx france 2012

HowDid they do it?

Page 25: Buildr In Action @devoxx france 2012

Ruby awesome scripting language

Page 26: Buildr In Action @devoxx france 2012

why ruby?

Page 27: Buildr In Action @devoxx france 2012

Scriptingeasy file manipulation

native regexp, lightweight syntax

exec() friendlyetc.

Page 28: Buildr In Action @devoxx france 2012

Metaprogramm'great host for embeddeddomain-specific language

Page 29: Buildr In Action @devoxx france 2012

JVM Friendly ;)JRuby & Ruby-Java Bridge

Page 30: Buildr In Action @devoxx france 2012

Rake

Ruby

tasks, files,dependencies

awesome scripting language

Page 31: Buildr In Action @devoxx france 2012

RakeThe Ruby Make

Page 32: Buildr In Action @devoxx france 2012

RakeThe Ruby Make

“Ant”

Page 33: Buildr In Action @devoxx france 2012

Your Application

[ modules ]

Page 34: Buildr In Action @devoxx france 2012

[ graph of dependencies ]

Page 35: Buildr In Action @devoxx france 2012

# This is Rake codetask "compile A" do # code to compile Aend

task "compile B" do # code to compile Bend

task "compile C" => ["compile A", "compile B"] do # code to compile Cend

task "package A,B,C" => ["compile A", "...", "compile C"] do # code to package A, B and Cend

task :default => “package A, B, C”

Page 36: Buildr In Action @devoxx france 2012

$ rake(in /home/buildr/example)compiling A ...compiling B ...compiling C ...packaging A,B,C ...

Page 37: Buildr In Action @devoxx france 2012

Buildr

Rake

Ruby

projects, lifecycle, artifacts, plugins

tasks, files,dependencies

awesome scripting language

Page 38: Buildr In Action @devoxx france 2012

# This is Buildr codedefine "My application" do

define "A" do package :jar end

define "B" do package :jar end

define "C" do compile.with projects("A", "B") package :jar end

package(:war).using :libs => projects("A", "B", "C")end

Page 39: Buildr In Action @devoxx france 2012

Parent projectsimplicitly depend on

children

# This is Buildr codedefine "My application" do

define "A" do package :jar end

define "B" do package :jar end

define "C" do compile.with projects("A", "B") package :jar end

package(:war).using :libs => projects("A", "B", "C")end

Page 40: Buildr In Action @devoxx france 2012

my-application/├── A│ └── src│ ├── main│ │ ├── java│ │ └── resources│ └── test│ └── java├── B│ └── src│ ├── main│ │ └── scala│ └── test│ └── scala├── C│ └── src│ └── main│ └── groovy└── src └── main ├── java └── webapp

Standard directory structure

(can be customized)

Page 41: Buildr In Action @devoxx france 2012

$ buildr package

(in /home/alexis/example, development)Building buildr-exampleCompiling buildr-example:a into /home/alexis/example/a/target/classesCompiling buildr-example:b into /home/alexis/example/b/target/classesPackaging buildr-example-a-1.0.0.jarPackaging buildr-example-b-1.0.0.jarCompiling buildr-example:c into /home/alexis/example/c/target/classesPackaging buildr-examplePackaging buildr-example-c-1.0.0.jarPackaging buildr-example-1.0.0.warRunning integration tests...Completed in 0.779s

Page 42: Buildr In Action @devoxx france 2012

All abouttasks.

Page 43: Buildr In Action @devoxx france 2012

Standard tasks[ partial list ]

Page 44: Buildr In Action @devoxx france 2012

# Actual Rake codeclass FileTask < Task

def needed? !File.exist?(name) || out_of_date? end

private

def out_of_date? @prerequisites.any? { |n| n.timestamp > timestamp} end

end

Page 45: Buildr In Action @devoxx france 2012

artifactsand repositories

Page 46: Buildr In Action @devoxx france 2012

Local files (no kidding!!!)Maven2 (built-in)Ivy (plugin)Aether (plugin)

or roll your own.

Dependency resolution

Page 47: Buildr In Action @devoxx france 2012

# Buildfile

repositories.remote << "http://www.ibiblio.org/maven2/"

LOG4J = "log4j:log4j:jar:1.2.15"

define 'my-library' do compile.with LOG4J package :jarend

Page 48: Buildr In Action @devoxx france 2012

# Buildfile

repositories.remote << "http://www.ibiblio.org/maven2/"

LOG4J = "log4j:log4j:jar:1.2.15"

define 'my-library' do compile.with LOG4J package :jarend

all your reposare belong

to us !!

Page 49: Buildr In Action @devoxx france 2012

# Buildfile

repositories.remote << "http://www.ibiblio.org/maven2/"

LOG4J = "log4j:log4j:jar:1.2.15"

define 'my-library' do compile.with LOG4J package :jarend

artifacts areTasks, too

all your reposare belong

to us !!

Page 50: Buildr In Action @devoxx france 2012

# Buildfile

repositories.remote << "http://www.ibiblio.org/maven2/"

LOG4J = "log4j:log4j:jar:1.2.15"

define 'my-library' do compile.with LOG4J package :jarend

artifacts areTasks, too

all your reposare belong

to us !!

tasks are wired implicitly

Page 51: Buildr In Action @devoxx france 2012

Languageswe got 'em

Page 52: Buildr In Action @devoxx france 2012

Example: Scala plugin

require 'buildr/scala'

# brings in:## - automatic detection# (src/main/scala, src/test/scala, src/spec/scala)## - incremental compilation## - mixed java + scala compilation## - scaladoc generation## - scalatest, specs and scalacheck testing## - continuous compilation

Page 53: Buildr In Action @devoxx france 2012

# if you have Ruby installed$ gem install buildr

or,

# JRuby all-in-one package$ unzip buildr-all-in-one.zip

Low Barrier to entry

Page 54: Buildr In Action @devoxx france 2012

Demo Time!Java + Scala + Groovy

Mixed Project

Page 55: Buildr In Action @devoxx france 2012

More Stuff.

layouts, profiles,code coverage, notifications

more plugins, more languages+ more awesome.

Page 56: Buildr In Action @devoxx france 2012

Only one thingto remember.

Page 57: Buildr In Action @devoxx france 2012

Build like you code.

Page 58: Buildr In Action @devoxx france 2012

join us!http://buildr.apache.org

@buildr

Slides and Code available at github.com/alexismAlex Boisvert @boia01

Page 59: Buildr In Action @devoxx france 2012

Ant Example: XMLBeans

<taskdef name="xmlbean" classname="org.apache.xmlbeans.impl.tool.XMLBean" classpath="path/to/xbean.jar" />

<xmlbean classgendir="${build.dir}" classpath="${class.path}" failonerror="true"> <fileset basedir="src" excludes="**/*.xsd"/> <fileset basedir="schemas" includes="**/*.*"/></xmlbean>

Page 60: Buildr In Action @devoxx france 2012

Ant Example: XMLBeansdef xmlbeans(files) do Buildr.ant "xmlbeans" do |ant| ant.taskdef \ :name => "xmlbeans", :classname => "org.apache.xmlbeans.impl.tool.XMLBean", :classpath => 'org.apache.xmlbeans:xmlbeans:jar:2.3.0'

ant.xmlbeans \ :classpath => project.compile.dependencies, :srcgendir => project._('target/generated') :failonerror => "true" do files.flatten.each do |file| ant.fileset File.directory?(file) ? { :dir => file } : { :file => file } end endend

Page 61: Buildr In Action @devoxx france 2012

# Convert .pom to ivy.xmlmodule POM_to_IVY extend self

ANT = Buildr.ant('convertpom') do |ant| ant.taskdef :name => "convertpom", :classname => "org.apache.ivy.ant.IvyConvertPom" end end

def convert(pom_file, ivy_file) ANT.convertpom :pomFile => pom_file, :ivyFile => ivy_file endend

Page 62: Buildr In Action @devoxx france 2012

define :webapp do

# regenerate app.js when any .coffee file changes file('target/js/app.js') => Dir['src/main/coffee/*.coffee']) do sh "dependence src/main/coffee/ -t coffee -o target/js" end

resources.enhance ['target/js/app.js']

end

Page 63: Buildr In Action @devoxx france 2012

# Generate SQL DDL schemas for all databases%w{ derby mysql oracle sqlserver postgres }.each do |db| db_xml = _("src/main/descriptors/persistence.#{db}.xml") partial_sql = file("target/partial.#{db}.sql"=>db_xml) do OpenJPA.mapping_tool \ :properties => db_xml, :action => "build", :sql => db.to_s, :classpath => projects("store", "dao") end

# Add Apache license header header = _("src/main/scripts/license-header.sql") sql = concat(_("target/#{db}.sql") => [header, partial_sql]) build sqlend

Page 64: Buildr In Action @devoxx france 2012

# Compile using all Eclipse BIRT librariesBIRT_WAR = artifact(“org.eclipse.birt:birt:war:1.4.1”)

unzip_birt = unzip _("target/birt") => BIRT_WARunzip_birt.enhance do compile.with Dir[_("target/birt/WEB-INF/lib") + "/*.jar"]endcompile.enhance [unzip_birt]

Page 65: Buildr In Action @devoxx france 2012

Calling Java classes

Java.classpath << [ "org.antlr:antlr:jar:3.0", "antlr:antlr:jar:2.7.7", "org.antlr:stringtemplate:jar:3.0" ]

Java.org.antlr.Tool.new("-i #{input} -o #{output}").process

Page 66: Buildr In Action @devoxx france 2012

Testing Your Build

# rspec codecheck package(:war).entry('META-INF/MANIFEST'), 'should have license' do it.should contain(/Copyright (C) 2011/)end

check file('target/classes/killerapp/Code.class'), 'should exist' do it.should existend

Page 67: Buildr In Action @devoxx france 2012

Example: Extension

module GitVersion include Buildr::Extension

@version = `git log -1 --pretty=format:%H` after_define do |project| project.packages.each do |jar| f = file project._("target/git-version.txt") do |f| Buildr.write f.to_s, @version end jar.enhance [f] jar.include f, :as => "META-INF/git-version.txt" end endend

Page 68: Buildr In Action @devoxx france 2012

# apply to a single projectdefine 'my-project' do extend GitVersionend

# apply to all projectsclass Buildr::Project include GitVersionend


Recommended