gerrit/Documentation/dev-buck.txt
Euler Jiang fa6549accd Update installation guide, gcc is required to build buck
Change-Id: Idba2bf1f1156f7301100a79c138aaa593bc5ba10
2015-11-11 18:11:49 +00:00

731 lines
20 KiB
Plaintext

= Gerrit Code Review - Building with Buck
== Installation
Note that you need to use Java 7 for building gerrit.
There is currently no binary distribution of Buck, so it has to be manually
built and installed. Apache Ant and gcc are required. Currently only Linux
and Mac OS are supported.
Clone the git and build it:
----
git clone https://github.com/facebook/buck
cd buck
git checkout $(cat ../gerrit/.buckversion)
ant
----
If you don't have a `bin/` directory in your home directory, create one:
----
mkdir ~/bin
----
Add the `~/bin` folder to the path:
----
PATH=~/bin:$PATH
----
Note that the buck executable needs to be available in all shell sessions,
so also make sure it is appended to the path globally.
Add a symbolic link in `~/bin` to the buck and buckd executables:
----
ln -s `pwd`/bin/buck ~/bin/
ln -s `pwd`/bin/buckd ~/bin/
----
Verify that `buck` is accessible:
----
which buck
----
To enable autocompletion of buck commands, install the autocompletion
script from `./scripts/buck_completion.bash` in the buck project. Refer
to the script's header comments for installation instructions.
== Prerequisites
Buck requires Python version 2.7 to be installed. The Maven download toolchain
requires `curl` to be installed.
[[eclipse]]
== Eclipse Integration
=== Generating the Eclipse Project
Create the Eclipse project:
----
tools/eclipse/project.py
----
and then follow the link:dev-eclipse.html#setup[setup instructions].
=== Refreshing the Classpath
If an updated classpath is needed, the Eclipse project can be
refreshed and missing dependency JARs can be downloaded:
----
tools/eclipse/project.py
----
=== Attaching Sources
To save time and bandwidth source JARs are only downloaded by the buck
build where necessary to compile Java source into JavaScript using the
GWT compiler. Additional sources may be obtained, allowing Eclipse to
show documentation or dive into the implementation of a library JAR:
----
tools/eclipse/project.py --src
----
[[build]]
== Building on the Command Line
=== Gerrit Development WAR File
To build the Gerrit web application:
----
buck build gerrit
----
The output executable WAR will be placed in:
----
buck-out/gen/gerrit/gerrit.war
----
=== Headless Mode
To build Gerrit in headless mode, i.e. without the GWT Web UI:
----
buck build headless
----
The output executable WAR will be placed in:
----
buck-out/gen/headless/headless.war
----
=== Extension and Plugin API JAR Files
To build the extension, plugin and GWT API JAR files:
----
buck build api
----
Java binaries, Java sources and Java docs are generated into corresponding
project directories in `buck-out/gen`, here as example for plugin API:
----
buck-out/gen/gerrit-plugin-api/plugin-api.jar
buck-out/gen/gerrit-plugin-api/plugin-api-javadoc/plugin-api-javadoc.jar
buck-out/gen/gerrit-plugin-api/plugin-api-src.jar
----
Install {extension,plugin,gwt}-api to the local maven repository:
----
buck build api_install
----
Install gerrit.war to the local maven repository:
----
buck build war_install
----
=== Plugins
To build all core plugins:
----
buck build plugins:core
----
The output JAR files for individual plugins will be placed in:
----
buck-out/gen/plugins/<name>/<name>.jar
----
The JAR files will also be packaged in:
----
buck-out/gen/plugins/core/core.zip
----
To build a specific plugin:
----
buck build plugins/<name>:<name>
----
The output JAR file will be be placed in:
----
buck-out/gen/plugins/<name>/<name>.jar
----
Note that when building an individual plugin, the `core.zip` package
is not regenerated.
Additional plugins with BUCK files can be added to the build
environment by cloning the source repository into the plugins
subdirectory:
----
git clone https://gerrit.googlesource.com/plugins/<name> plugins/<name>
echo /plugins/<name> >>.git/info/exclude
----
Additional plugin sources will be automatically added to Eclipse the
next time project.py is run:
----
tools/eclipse/project.py
----
[[documentation]]
=== Documentation
To build only the documentation for testing or static hosting:
----
buck build docs
----
The generated html files will NOT come with the search box, and will be
placed in:
----
buck-out/gen/Documentation/searchfree__tmp/Documentation
----
The html files will also be bundled into `searchfree.zip` in this location:
----
buck-out/gen/Documentation/searchfree/searchfree.zip
----
To build the executable WAR with the documentation included:
----
buck build withdocs
----
The WAR file will be placed in:
----
buck-out/gen/withdocs/withdocs.war
----
[[soyc]]
=== GWT Compile Report
The GWT compiler can output a compile report (or "story of your compile"),
describing the size of the JavaScript and which source classes contributed
to the overall download size.
----
buck build soyc
----
The report will be written as an HTML page to the extras directory, and
can be opened and viewed in any web browser:
----
extras/gerrit_ui/soycReport/compile-report/index.html
----
Only the "Split Point Report" is created, "Compiler Metrics" are not output.
[[release]]
=== Gerrit Release WAR File
To build the release of the Gerrit web application, including documentation and
all core plugins:
----
buck build release
----
The output release WAR will be placed in:
----
buck-out/gen/release/release.war
----
[[tests]]
== Running Unit Tests
To run all tests including acceptance tests (but not flaky tests):
----
buck test --exclude flaky
----
To exclude flaky and slow tests:
----
buck test --exclude flaky slow
----
To run only a specific group of acceptance tests:
----
buck test --include api
----
The following groups of tests are currently supported:
* acceptance
* api
* edit
* flaky
* git
* pgm
* rest
* server
* ssh
* slow
To run a specific test group, e.g. the rest-account test group:
----
buck test //gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/rest/account:rest-account
----
To create test coverage report:
----
buck test --code-coverage --code-coverage-format html --no-results-cache
----
The HTML report is created in `buck-out/gen/jacoco/code-coverage/index.html`.
== Dependencies
Dependency JARs are normally downloaded automatically, but Buck can inspect
its graph and download any missing JAR files. This is useful to enable
subsequent builds to run without network access:
----
tools/download_all.py
----
When downloading from behind a proxy (which is common in some corporate
environments), it might be necessary to explicitly specify the proxy that
is then used by `curl`:
----
export http_proxy=http://<proxy_user_id>:<proxy_password>@<proxy_server>:<proxy_port>
----
Redirection to local mirrors of Maven Central and the Gerrit storage
bucket is supported by defining specific properties in
`local.properties`, a file that is not tracked by Git:
----
echo download.GERRIT = http://nexus.my-company.com/ >>local.properties
echo download.MAVEN_CENTRAL = http://nexus.my-company.com/ >>local.properties
----
The `local.properties` file may be placed in the root of the gerrit repository
being built, or in `~/.gerritcodereview/`. The file in the root of the gerrit
repository has precedence.
== Building against unpublished Maven JARs
To build against unpublished Maven JARs, like gwtorm or PrologCafe, the custom
JARs must be installed in the local Maven repository (`mvn clean install`) and
`maven_jar()` must be updated to point to the `MAVEN_LOCAL` Maven repository for
that artifact:
[source,python]
----
maven_jar(
name = 'gwtorm',
id = 'gwtorm:gwtorm:42',
license = 'Apache2.0',
repository = MAVEN_LOCAL,
)
----
== Building against unpublished JARs, that change frequently
If a dependent Gerrit library is undergoing active development it must be
recompiled and the change must be reflected in the Buck build process. For
example testing Gerrit against changed JGit snapshot version. After building
JGit library, the artifacts are created in local Maven build directory, e. g.:
----
mvn package
/home/<user>/projects/jgit/org.eclipse.jgit/target/org.eclipse.jgit-3.3.0-SNAPSHOT.jar
/home/<user>/projects/jgit/org.eclipse.jgit/target/org.eclipse.jgit-3.3.0-SNAPSHOT-sources.jar
----
If as usual, installation of the build artifacts takes place in local maven
repository, then the Buck build must fetch them from there with normal
`download_file.py` process. Disadvantage of this approach is that Buck cache
invalidation must occur to refresh the artifacts after next
change-compile-install round trip.
To shorten that workflow and take the installation of the artifacts to the
local Maven repository and fetching it again from there out of the picture,
`local_jar()` method is used instead of `maven_jar()`:
[source,python]
----
local_jar(
name = 'jgit',
jar = '/home/<user>/projects/jgit/org.eclipse.jgit/target/org.eclipse.jgit-3.3.0-SNAPSHOT.jar',
src = '/home/<user>/projects/jgit/org.eclipse.jgit/target/org.eclipse.jgit-3.3.0-SNAPSHOT-sources.jar',
deps = [':ewah']
)
----
This creates a symlink to the Buck targets direct against artifacts in
another project's Maven target directory:
----
buck-out/gen/lib/jgit/jgit.jar ->
/home/<user>/projects/jgit/org.eclipse.jgit/target/org.eclipse.jgit-3.3.0-SNAPSHOT.jar
----
After `buck clean` and `buck build lib/jgit:jgit` the symbolic link that was
created the first time is lost due to Buck's caching mechanism. This means that
when a new version of the local artifact is deployed (by running `mvn package`
in the JGit project in the example above), Buck is not aware of it, because it
still has a stale version of it in its cache.
To solve this problem and re-create the symbolic link, you don't need to wipe out
the entire Buck cache. Just rebuilding the target with the `--no-cache` option
does the job:
----
buck clean
buck build --no-cache lib/jgit:jgit
----
== Building against artifacts from custom Maven repositories
To build against custom Maven repositories, two modes of operations are
supported: with rewrite in local.properties and without.
Without rewrite the URL of custom Maven repository can be directly passed
to the maven_jar() function:
[source,python]
----
GERRIT_FORGE = 'http://gerritforge.com/snapshot'
maven_jar(
name = 'gitblit',
id = 'com.gitblit:gitblit:1.4.0',
sha1 = '1b130dbf5578ace37507430a4a523f6594bf34fa',
license = 'Apache2.0',
repository = GERRIT_FORGE,
)
----
When the custom URL has to be rewritten, then the same logic as with Gerrit
known Maven repository is used: Repo name must be defined that matches an entry
in local.properties file:
----
download.GERRIT_FORGE = http://my.company.mirror/gerrit-forge
----
And corresponding BUCK excerpt:
[source,python]
----
GERRIT_FORGE = 'GERRIT_FORGE:'
maven_jar(
name = 'gitblit',
id = 'com.gitblit:gitblit:1.4.0',
sha1 = '1b130dbf5578ace37507430a4a523f6594bf34fa',
license = 'Apache2.0',
repository = GERRIT_FORGE,
)
----
=== Caching Build Results
Build results can be locally cached, saving rebuild time when
switching between Git branches. Buck's documentation covers
caching in link:http://facebook.github.io/buck/concept/buckconfig.html[buckconfig].
The trivial case using a local directory is:
----
cat >.buckconfig.local <<EOF
[cache]
mode = dir
dir = buck-cache
EOF
----
[[clean-cache]]
=== Cleaning The Buck Cache
The cache for the Gerrit Code Review project is located in
`~/.gerritcodereview/buck-cache/locally-built-artifacts`.
The Buck cache should never need to be manually deleted. If you find yourself
deleting the Buck cache regularly, then it is likely that there is something
wrong with your environment or your workflow.
If you really do need to clean the cache manually, then:
----
rm -rf ~/.gerritcodereview/buck-cache/locally-built-artifacts
----
Note that the root `buck-cache` folder should not be deleted as it also contains
the `downloaded-artifacts` directory, which holds the artifacts that got
downloaded (not built locally).
[[buck-daemon]]
=== Using Buck daemon
Buck ships with a daemon command `buckd`, which uses the
link:https://github.com/martylamb/nailgun[Nailgun] protocol for running
Java programs from the command line without incurring the JVM startup
overhead.
Using a Buck daemon can save significant amounts of time as it avoids the
overhead of starting a Java virtual machine, loading the buck class files
and parsing the build files for each command.
It is safe to run several buck daemons started from different project
directories and they will not interfere with each other. Buck's documentation
covers daemon in http://facebook.github.io/buck/command/buckd.html[buckd].
To use `buckd` the additional
link:https://facebook.github.io/watchman[watchman] program must be installed.
To disable `buckd`, the environment variable `NO_BUCKD` must be set. It's not
recommended to put it in the shell config, as it can be forgotten about it and
then assumed Buck was working as it should when it should be using buckd.
Prepend the variable to Buck invocation instead:
----
NO_BUCKD=1 buck build gerrit
----
[[watchman]]
=== Installing watchman
Watchman is used internally by Buck to monitor directory trees and is needed
for buck daemon to work properly. Because buckd is activated by default in the
latest version of Buck, it searches for the watchman executable in the
path and issues a warning when it is not found and kills buckd.
To prepare watchman installation on Linux:
----
git clone https://github.com/facebook/watchman.git
cd watchman
./autogen.sh
----
To install it in user home directory (without root privileges):
----
./configure --prefix $HOME/watchman
make install
----
To install it system wide:
----
./configure
make
sudo make install
----
Put $HOME/watchman/bin/watchman in path or link to $HOME/bin/watchman.
To install watchman on OS X:
----
brew install --HEAD watchman
----
See the original documentation for more information:
link:https://facebook.github.io/watchman/docs/install.html[Watchman
installation].
=== Override Buck's settings
Additional JVM args for Buck can be set in `.buckjavaargs` in the
project root directory. For example to override Buck's default 1GB
heap size:
----
cat > .buckjavaargs <<EOF
-XX:MaxPermSize=512m -Xms8000m -Xmx16000m
EOF
----
== Rerun unit tests
Test execution results are cached by Buck. If a test that was already run
needs to be repeated, the unit test cache for that test must be removed first:
----
rm -rf buck-out/bin/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/rest/account/.rest-account/
----
After clearing the cache, the test can be run again:
----
buck test //gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/rest/account:rest-account
[-] TESTING...FINISHED 12,3s (12 PASS/0 FAIL)
RESULTS FOR //gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/rest/account:rest-account
PASS 970ms 2 Passed 0 Skipped 0 Failed com.google.gerrit.acceptance.rest.account.CapabilitiesIT
PASS 999ms 1 Passed 0 Skipped 0 Failed com.google.gerrit.acceptance.rest.account.EditPreferencesIT
PASS 1,2s 1 Passed 0 Skipped 0 Failed com.google.gerrit.acceptance.rest.account.GetAccountDetailIT
PASS 951ms 2 Passed 0 Skipped 0 Failed com.google.gerrit.acceptance.rest.account.GetAccountIT
PASS 6,4s 2 Passed 0 Skipped 0 Failed com.google.gerrit.acceptance.rest.account.GetDiffPreferencesIT
PASS 1,2s 4 Passed 0 Skipped 0 Failed com.google.gerrit.acceptance.rest.account.PutUsernameIT
TESTS PASSED
----
An alternative approach is to use Buck's `--filters` (`-f`) option:
----
buck test -f 'com.google.gerrit.acceptance.rest.account.CapabilitiesIT'
Using buckd.
[-] PROCESSING BUCK FILES...FINISHED 1,0s [100%]
[-] BUILDING...FINISHED 2,8s [100%] (334/701 JOBS, 110 UPDATED, 5,1% CACHE MISS)
[-] TESTING...FINISHED 9,2s (6 PASS/0 FAIL)
RESULTS FOR SELECTED TESTS
PASS 8,0s 2 Passed 0 Skipped 0 Failed com.google.gerrit.acceptance.rest.account.CapabilitiesIT
PASS <100ms 4 Passed 0 Skipped 0 Failed //tools:util_test
TESTS PASSED
----
When this option is used, the cache is disabled per design and doesn't need to
be explicitly deleted. Note, that this is a known issue, that python tests are
always executed.
Note that when this option is used, the whole unit test cache is dropped, so
repeating the
----
buck test
----
causes all tests to be executed again.
To run tests without using cached results at all, use the `--no-results-cache`
option:
----
buck test --no-results-cache
----
== Upgrading Buck
The following tests should be executed, when Buck version is upgraded:
* buck build release
* buck build api_install
* buck test
* buck build gerrit, change some sources in gerrit-server project,
repeat buck build gerrit and verify that gerrit.war was updated
* install and verify new gerrit site
* upgrade and verify existing gerrit site
* reindex existing gerrit site
* verify that tools/eclipse/project.py produces sane Eclipse project
* verify that tools/eclipse/project.py --src generates sources as well
* verify that unit test execution from Eclipse works
* verify that daemon started from Eclipse works
* verify that GWT SDM debug session started from Eclipse works
== Known issues and bugs
=== Symbolic links and `watchman`
`Buck` with activated `Watchman` has currently a
[known bug](https://github.com/facebook/buck/issues/341) related to
symbolic links. The symbolic links are used very often with external
plugins, that are linked per symbolic link to the plugins directory.
With this use case Buck is failing to rebuild the plugin artefact
after it was built. All attempts to convince Buck to rebuild will fail.
The only known way to recover is to weep out `buck-out` directory. The
better workaround is to avoid using Watchman in this specific use case.
Watchman can either be de-installed or disabled. See
link:#buck-daemon[Using Buck daemon] section above how to temporarily
disable `buckd`.
=== Re-triggering rule execution
There is no way to re-trigger custom rules with side effects, like
`api_{deploy|install}`. This is a `genrule()` that depends on Java sources
and is deploying the Plugin API through custom Python script to the local or
remote Maven repositories. When for some reasons the deployment was undone,
there is no supported way to re-trigger the execution of `api_{deploy|install}`
targets. That's because `--no-cache` option will ignore the `Buck` cache, but
there is no way to ignore `buck-out` directory. To overcome this Buck's design
limitation new `tools/maven/api.py` script was added, that always re-triggers
installation or deployment of Plugin API to local or Central Maven repository.
```
tools/maven/api.py {deploy|install}
```
Dry run mode is also supported:
```
tools/maven/api.py -n {deploy|install}
```
With this script the deployment would re-trigger on every invocation.
== Troubleshooting Buck
In some cases problems with Buck itself need to be investigated. See for example
link:https://gerrit-review.googlesource.com/62411[this attempt to upgrade Buck]
and link:https://github.com/facebook/buck/pull/227[the fix that was needed] to
make the update possible.
To build Gerrit with a custom version of Buck, the following steps are necessary:
1. In the Buck git apply any necessary changes from pull requests
2. Compile Buck with `ant`
3. In the root of the Gerrit project create a `.nobuckcheck` file to prevent Buck
from updating itself
4. Replace the sha1 in Gerrit's `.buckversion` file with the required version from
the custom Buck build
5. Build Gerrit as usual
GERRIT
------
Part of link:index.html[Gerrit Code Review]
SEARCHBOX
---------