These build rules are used for building Java App Engine application or Python App Engine application with Bazel. It does not aim at general web application support but can be easily modified to handle a standard web application.
To be able to use the rules, you must make the App Engine SDK available to
Bazel. The easiest way to do so is by adding the following to your
WORKSPACE
file:
Note: The ${LANG}_appengine_repository()
lines are only needed for the languages you plan to use.
git_repository(
name = "io_bazel_rules_appengine",
remote = "https://github.com/bazelbuild/rules_appengine.git",
# Check https://github.com/bazelbuild/rules_appengine/releases for the latest version.
tag = "0.0.8",
)
# Java
load(
"@io_bazel_rules_appengine//appengine:java_appengine.bzl",
"java_appengine_repositories",
)
java_appengine_repositories()
# Python
load(
"@io_bazel_rules_appengine//appengine:sdk.bzl",
"appengine_repositories",
)
appengine_repositories()
load(
"@io_bazel_rules_appengine//appengine:py_appengine.bzl",
"py_appengine_repositories",
)
py_appengine_repositories()
The App Engine rules download the App Engine SDK, which is a few hundred
megabytes in size. To avoid downloading this multiple times for multiple
projects or inadvertently re-downloading it, you might want to add the
following lines to your $HOME/.bazelrc
file:
build --experimental_repository_cache=/home/user/.bazel/cache
fetch --experimental_repository_cache=/home/user/.bazel/cache
All ${LANG}_appengine_repository macros accept optional arguments version
and sha256
.
py_appengine_repositories(
version = '1.9.67',
sha256 = 'f9f45150643424cb164185d9134b86511c2bec3001499247ef9027f1605ef8a3',
)
You can, optionally, specify the environment variable
${LANG}_APPENGINE_SDK_PATH
to use an SDK that is unzipped on your filesystem
(instead of downloading a new one).
PY_APPENGINE_SDK_PATH=/path/to/google_appengine bazel build //whatever
JAVA_APPENGINE_SDK_PATH=/path/to/appengine-java-sdk-1.9.50 bazel build //whatever
Suppose you have the following directory structure for a simple App Engine application:
[workspace]/
WORKSPACE
hello_app/
BUILD
java/my/webapp/
TestServlet.java
webapp/
index.html
webapp/WEB-INF
web.xml
appengine-web.xml
Then, to build your webapp, your hello_app/BUILD
can look like:
load("@io_bazel_rules_appengine//appengine:java_appengine.bzl", "appengine_war")
java_library(
name = "mylib",
srcs = ["java/my/webapp/TestServlet.java"],
deps = [
"//external:appengine/java/api",
"@io_bazel_rules_appengine//appengine:javax.servlet.api",
],
)
appengine_war(
name = "myapp",
jars = [":mylib"],
data = glob(["webapp/**"]),
data_path = "/webapp",
)
For simplicity, you can use the java_war
rule to build an app from source.
Your hello_app/BUILD
file would then look like:
load("@io_bazel_rules_appengine//appengine:java_appengine.bzl", "java_war")
java_war(
name = "myapp",
srcs = ["java/my/webapp/TestServlet.java"],
data = glob(["webapp/**"]),
data_path = "/webapp",
deps = [
"//external:appengine/java/api",
"@io_bazel_rules_appengine//appengine:javax.servlet.api",
],
)
You can then build the application with bazel build //hello_app:myapp
.
You can run it in a development server with bazel run //hello_app:myapp
.
This will bind a test server on port 8080. If you wish to select another port,
use the --port
option:
bazel run //hello_app:myapp -- --port=12345
You can see other options with -- --help
(the --
tells Bazel to pass the
rest of the arguments to the executable).
Another target //hello_app:myapp.deploy
allows you to deploy your
application to App Engine. It takes an optional argument: the
APP_ID
. If not specified, it uses the default APP_ID
provided in
the application. This target needs to open a browser to authenticate
with App Engine, then have you copy-paste a "key" from the browser in
the terminal. Since Bazel closes standard input, you can only input
this by building the target and then running:
$ bazel-bin/hello_app/myapp.deploy APP_ID
After the first launch, subsequent launch will be registered to
App Engine so you can just do a normal bazel run //hello_app:myapp.deploy -- APP_ID
to deploy next versions of
your application.
Note: App Engine uses Java 8 (or Java 7, but this runtime is deprecated). If you are using a more recent version of Java, you will get the following error message when you try to deploy:
java.lang.IllegalArgumentException: Class file is Java 9 but max supported is Java 8
To build with Java 8, use the toolchain bundled with these App Engine rules:
$ bazel build --extra_toolchains=@io_bazel_rules_appengine//appengine/jdk:jdk8_definition //my-project
To avoid having to specify this toolchain during every build, you can add this
to your project's .bazelrc
. Create a .bazelrc
file in the root directory of
your project and add the line:
build --extra_toolchains=@io_bazel_rules_appengine//appengine/jdk:jdk8_definition
appengine_war(name, jars, data, data_path)
Attributes | |
---|---|
name |
Name, required
A unique name for this rule. |
jars |
List of labels, required
List of JAR files that will be uncompressed as the code for the Web Application. If it is a `java_library` or a `java_import`, the JAR from the runtime classpath will be added in the `lib` directory of the Web Application. |
data |
List of files, optional
List of files used by the Web Application at runtime. This attribute can be used to specify the list of resources to be included into the WAR file. |
data_path |
String, optional
Root path of the data. The directory structure from the data is preserved inside the WebApplication but a prefix path determined by `data_path` is removed from the the directory structure. This path can be absolute from the workspace root if starting with a `/` or relative to the rule's directory. It is set to `.` by default. |
java_war(name, data, data_path, **kwargs)
Attributes | |
---|---|
name |
Name, required
A unique name for this rule. |
data |
List of labels, optional
List of files used by the Web Application at runtime. Passed to the appengine_war rule. |
data_path |
String, optional
Root path of the data. Passed to the appengine_war rule. |
**kwargs |
see java_library
The other arguments of this rule will be passed to build a `java_library` that will be passed in the `jar` arguments of a appengine_war rule. |
py_appengine_binary(name, srcs, configs, deps=[], data=[], overwrite_appengine_config=True)
Attributes | |
---|---|
name |
Name, required
A unique name for this rule. |
configs |
List of labels, required
the path to your app.yaml/index.yaml/cron.yaml files |
srcs |
List of labels, optional
The list of source files that are processed to create the target. |
deps |
List of labels, optional
The list of libraries to link into this library. |
data |
List of labels, optional
List of files used by the Web Application at runtime. |
overwrite_appengine_config |
Boolean, optional
If true, patch the user's appengine_config into the base one. If false, use the user specified config directly. Set to False to behave pre 0.0.8. |
py_appengine_test(name, srcs, deps=[], data=[], libraries={})
Attributes | |
---|---|
name |
Name, required
A unique name for this rule. |
srcs |
List of labels, required
The list of source files that are processed to create the target. |
deps |
List of labels, optional
The list of libraries to link into this library. |
data |
List of labels, optional
List of files used by the Web Application at runtime. |
libraries |
dict, optional
dictionary of name and the corresponding version for third-party libraries required from sdk. |