Introduction to Buck
31 October 2013
Shawn Pearce
Maintainer, Gerrit Code Review
Shawn Pearce
Maintainer, Gerrit Code Review
tl;dw: Buck is fast, Maven is ... not
Outline
java_library( name = 'greet_api', srcs = ['Greeter.java', 'Group.java'], ) java_library( name = 'hello_world', srcs = ['HelloGreeter.java', 'WorldGroup.java'], deps = [':greet_api'], )
mvn package -Dmaven.{javadoc,test}.skip=true ... 6m50s
buck build :gerrit ... 2m 3s
buck test --all ... 2m 5s
mvn package -Dmaven.{javadoc,test}.skip=true ... 4m44s
buck build :gerrit ... 2smvn clean;mvn package)buck build gerrit-server:constants)Buck comes in source form as a Git repository
git clone https://github.com/facebook/buck cd buck ant # 8.736s PATH=$(pwd)/bin:$PATH
Alternative is to symlink to buck
ln -s $(pwd)/bin/buck ~/bin/buck ln -s $(pwd)/bin/buckd ~/bin/buckd # optional
facebook.github.io/buck/setup/install.html
Android SDK configuration is only necessary to build Android applications
Written in files named BUCK
java_library( name = 'client', srcs = ['Client.java', 'Window.java'], )
Targets (rules) are identified by filesystem path and name
plugins/replication/BUCK: java_library(name = 'replication', ...) java_library(name = 'utils', ...)
//plugins/replication:replication
[a-zA-Z_][a-zA-Z_0-9.-]*lib/BUCK
prebuilt_jar( name = 'guava', binary_jar = 'guava.jar', )
src/BUCK
java_library( name = 'client', srcs = ['Client.java', 'Window.java'], resources = ['Client_en.properties', 'icon.gif'], deps = ['//lib:guava'], ) java_binary( name = 'my_app', main_class = 'Client', deps = [':client'], )
prebuilt_jar( name = 'guava', binary_jar = 'guava.jar', )
java_library( name = 'client', srcs = ['Client.java', 'Window.java'], resources = ['Client_en.properties', 'icon.gif'], deps = ['//lib:guava'], )
java_binary( name = 'my_app', main_class = 'Client', deps = [':client'], )
java_test( name = 'tests', srcs = ['ClientTest.java', 'WindowTest.java'], deps = [':client', '//lib:junit'], source_under_test = [':client'], )
java_test(name = 'ClientTest', srcs = ['ClientTest.java'], deps = [':client', '//lib:junit']) java_test(name = 'WindowTest', srcs = ['WindowTest.java'], deps = [':client', '//lib:junit'])
Python functions to shorten build files
def parallel_test(srcs, deps = []):
"""Defines one java_test rule per source file."""
for s in srcs:
n = s[:s.index('.java')]
java_test(name = n, srcs = [s], deps = deps)Use macros in BUCK files
include_defs('//tools/parallel_test.defs')
parallel_test(
srcs = glob(['*Test.java']),
deps = [':client', ':junit'],
)+'*' matches anything in a directory, '/**/' matches recursivelyTEST = glob(['src/main/java/**/*Test.java'])
API = ['src/main/java/com/mypkg/Greeter.java',
'src/main/java/com/mypkg/Group.java']
java_library(
name = 'hello_world',
srcs = glob(['src/main/java/**/*.java'], excludes = API + TEST),
deps = [':api'],
)
java_library(name = 'api', srcs = API)
java_test(
name = 'tests',
srcs = TEST,
deps = [':api', ':hello_world'],
)Automatically download from Maven Central
prebuilt_jar(
name = 'some_lib',
binary_jar = genfile('some.jar'),
deps = [':download'],
)
genrule(
name = 'download',
cmd = 'curl http://repo1.maven.org/maven2/.../some.jar >$OUT',
out = 'some.jar',
)/bin/bash -ec for execution of cmd$OUT replaced with location of outgenfile()Concatenate 3 files together
genrule( name = 'concat', srcs = ['content.txt', 'header.html', 'footer.html'], cmd = 'cat $SRCDIR/header.html $SRCDIR/content.txt $SRCDIR/footer.html >$OUT', out = 'content.html', )
$SRCDIR is a flat directory tree of all files named as srcsgenrule(
name = 'gen_antlr',
srcs = ['Query.g'],
cmd = '$(exe :antlr) -o $TMP $SRCS; jar cf $OUT -C $TMP .',
deps = [':antlr'],
out = 'query.src.zip',
)
java_library(
name = 'query_parser',
srcs = [genfile('query.src.zip')],
deps = [':gen_antlr'],
)
prebuilt_jar(name = 'antlr_jar', binary_jar = 'antlr.jar')
java_binary(name = 'antlr', main_class = 'org.antlr.Tool', deps = [':antlr_jar'])($exe target)$TMP is an empty directory private to the genrule.src.zip
java_library(
name = 'this-module',
srcs = glob(['src/main/java/**/*.java']),
resources = glob(['src/main/resources/**/*']),
deps = [
'//other-module:other-module',
'//lib:gson',
'//lib:gauva',
],
visibility = ['PUBLIC'],
)lib/BUCK enumerated all prebuilt_jars() from Maven Centrallib/BUCK
include_defs('//lib/maven.defs')
maven_jar(
name = 'gson',
id = 'com.google.code.gson:gson:2.1',
sha1 = '2e66da15851f9f5b5079228f856c2f090ba98c38',
license = 'Apache2.0',
)
maven_jar(
name = 'guava',
id = 'com.google.guava:guava:14.0',
sha1 = '67b7be4ee7ba48e4828a42d6d5069761186d4a53',
license = 'Apache2.0',
)
Create .buckversion with Git SHA-1 of Buck:
(cd ~/buck; git rev-parse HEAD) >.buckversion git add .buckversion
Temporarily disable version enforcement using .nobuckcheck
touch .nobuckcheck
Add aliases for common targets to .buckconfig
[alias] docs = //Documentation:html server = //gerrit-server:server buck build docs # instead of buck build Documentation:html
Configure project-wide macro rules in .buckconfig
[buildfile] includes = //tools/default.rules
Use buckd for faster incremental builds:
~/buck/bin/buckd time buck :gerrit ... 0.5s # without buckd, 2s
If using git and buckd, ignore .git in .buckconfig
[project] ignore = .git
Enable local artifact caching in .buckconfig.local
[cache] mode = dir dir = buck-cache
.buckconfig.local
Configure source roots in .buckconfig
[java] src_roots = java, resources
Borrow Gerrit Code Review's maven_jar() rule
maven_jar( name = 'guava', id = 'com.google.guava:guava:15.0', sha1 = 'ed727a8d9f247e2050281cb083f1c77b09dcb5cd', license = 'Apache2.0', )