This is the reference for the complete set of builtin rules & functions.
The build language largely resembles Python. As such, following python inpired functions are available as builtins:
len(x)
- returns the length of x
enumerate(seq)
- returns a list of pairs of the index and object for each item in seq
zip(x, y, ...)
- returns a list in which each element has one item from each argumentisinstance(x, type)
- returns True if x
is of the given type.range([start, ]stop[, step])
- returns a list of integers up to stop
(or from start
to stop
)any(seq)
- returns true if any of the items in seq
are considered true.all(seq)
- returns true if all of the items in seq
are considered true.sorted(seq)
- returns a copy of the given list with the contents sorted.package_name()
- returns the package being currently parsed.subrepo_name()
- returns the subrepo of the package being currently parsed or the empty string if this is not a subrepo.join_path(x, ...)
- joins the given path elements using the OS separator. It will intelligently
handle repeated or missing separators.split_path(path)
- splits the given path into the directory and filename.splitext(filename)
- splits the given filename into base name and extension at the final dot.basename(path)
- returns the basename of a filedirname(path)
- returns the directory name of a file.breakpoint()
- breaks into an interactive debugger allowing inspection of the current scope.
It would be a good idea to run Please with the -p
/ --plain_output
flag if intending to use this.The following are available as member functions of strings:
join(seq)
- joins the elements of seq
together with this string as a separator.split(sep)
- splits this string at each occurrence of the given separator.replace(old, new)
- returns a copy of this string with all instances of old
replaced with new
.partition(sep)
- breaks this string around the first occurrence of sep
and returns a 3-tuple of (before, sep, after).rpartition(sep)
- breaks this string around the last occurrence of sep
and returns a 3-tuple of (before, sep, after).startswith(prefix)
- returns true if this string begins with prefix
endswith(suffix)
- returns true if this string ends with suffix
format(arg1=val1, arg2=val2, ...))
- Replaces named parameters in the string.lstrip(cutset)
- strips all characters in cutset
from the beginning of this string.rstrip(cutset)
- strips all characters in cutset
from the end of this string.strip(cutset)
- strips all characters in cutset
from the beginning & end of this string.removeprefix(prefix)
- strips the exact string prefix
from the beginning of this string.removesuffix(suffix)
- strips the exact string suffix
from the end of this string.find(needle)
- returns the index of the first occurrence of needle
in this string.rfind(needle)
- returns the index of the last occurrence of needle
in this string.count(needle)
- returns the number of times needle
occurs in this string.upper()
- returns a copy of this string converted to uppercase.lower()
- returns a copy of this string converted to lowercase.The following are available as member functions of dictionaries:
get(key[, default])
- returns the item with the given key, or the default (None
if that is not given).setdefault(key[, default])
- If the given key is in the dict, return its value, otherwise insert it with the given value (None
if that is not given).keys()
- returns an iterable sequence of the keys of this dictionary, in a consistent order.values()
- returns an iterable sequence of the values of this dictionary, in a consistent order.items()
- returns an iterable sequence of pairs of the keys and values of this dictionary, in a consistent order.copy()
- deprecated, use a comprehension if needed. Returns a shallow copy of this dictionary.In addition to the python builtins, Please also has a rich set of its own functions.
Messages can be logged to Please's usual logging mechanism. These
may or may not be displayed depending on the -v
flag; by default only
warning
and above are visible.
log.debug(msg[, args...])
- the lowest level of messages, output at this level is very verbose.log.info(msg[, args...])
- Informational messages, typically this is the highest level per-target information is logged at.log.notice(msg[, args...])
- Messages of general interest during the build; it is rare for this to be appropriate from a BUILD file.log.warning(msg[, args...])
- A warning message that something seems wrong, but it may be recoverable.log.error(msg[, args...])
- A message indicating that something has gone wrong and it will not be recoverable.
This is usually followed shortly by some kind of failure.log.fatal(msg[, args...])
- Indicates that something has gone catastrophically wrong, and causes the process to exit immediately and unsuccessfully.
Usually you are better off using assert
or raise
to
indicate failure, since plz can handle those and annotate with additional output.subinclude(target)
Includes the output of a build target as extra rules in this one.
This is the closest equivalent to import
in the BUILD language. It behaves
somewhat differently though in that the contents of the subincluded file are added to the
globals of the current module so can be called directly.
The target that you attempt to subinclude is simply a normal build target, with the restriction that it must have exactly one output. The simplest form of this is a single-file filegroup or export_file rule, but it is possible to have more complex rules generating your BUILD definitions.
For example:
subinclude('//build_defs:my_build_rules')
glob(include, exclude=None, hidden=False)
Matches all filenames by a pattern, in a manner reminiscent of shell-style pattern expansion or Python's builtin glob module.
Note that the expansion patterns accepted are *
to match an arbitrary
number of non-separator characters (i.e. not /
), **
to
match any number of complete path components, ? to match a single character,
and [class] to match a class of character e.g. [a-z], [^0-9], or [abc].
These are often referred to as "Ant-style" patterns since Ant introduced them.
Glob exclude patterns can be evaluated relative to the matched file or the package root. If the
exclude pattern does not contain a path separator, it is considered relative and will be
evaluated against the file name of the match only, otherwise it will be evaluated from the
directory of the build file. This means that glob(["**/*.go"], exclude = ["*_test.go"])
will exclude all files ending in "test.go".
Hidden files (those starting with a .
) are not matched by any patterns
unless you pass hidden=True
.
It bears noting that you cannot glob generated files, only source files. Also glob will not
descend into any directories that contain a BUILD file; this maintains an invariant that
each file is owned by exactly one package (or potentially none, but then Please doesn't know
or care about them). If you want to pull in files from another package, export them there
using a filegroup
and depend on that in the package
you want it.
Argument | Default | Type | |
---|---|---|---|
include | list | List of paths to include. Each is globbed separately. | |
exclude | None | list | List of glob patterns to exclude from anything matched by includes .
|
hidden | False | bool | Set to True to include hidden files / folders. |
get_labels(target, prefix, all=False)
Gets the unique set of labels for a rule and all its transitive dependencies.
Two formats are accepted for target: the first is a string containing just the target name,
which is resolved in the current package. This facilitates calling them from a pre-build
function, which is in fact the only time it's safe to call this way.
The other is a full build target, which should be a transitive dependency of the target
whose pre/post build function you're in. If the target isn't built when you ask for the
labels the build will terminate.
In either case this is only safe to call from a pre / post-build function and should
never be called at initial parse time, because at that point you generally don't have
the full set of labels available yet.
Uses for this are normally fairly language-specific. The clearest example is maybe the
builtin Python rules, where python_binary
and python_test
use
this to identify if any of their dependencies have marked them as not being zip-safe.
Argument | Default | Type | |
---|---|---|---|
target | str | Label of the target to get labels for. | |
prefix | None | str | Filters the returned labels to only ones starting with this prefix. |
all | False | bool | Returns labels from all dependencies, even past those marked as output_is_complete . |
has_label(target, prefix)
Returns True if the target has any matching label that would be returned by get_labels.
Argument | Default | Type | |
---|---|---|---|
target | str | Label of the target to get labels for. | |
prefix | None | str | Checks only labels that start with this prefix. |
add_licence(target, licence)
Adds a new licence to a target. The assumption (as usual) is that if multiple are added, they are options, so any one can be accepted.
Argument | Default | Type | |
---|---|---|---|
target | str | Label of the target to add the licence to. | |
licence | str | Name of the licence to add. |
get_licences(target)
Returns all the licences that are currently known to apply to a target.
Argument | Default | Type | |
---|---|---|---|
target | str | Label of the target to get licences for. |
package(...)
Defines settings affecting the current package - for example, default visibility.
With this you can override any current value in CONFIG
by name for all
subsequent targets in the current package. Only existing values can be replaced.
There are also a couple of special values which aren't normally in CONFIG
:
default_licences
and default_visibility
. As the names suggest
these set defaults for those attributes for all following targets that don't set them.
This function must be called before any targets are defined.
log.warning(message, [args...])
Logs an arbitrary message at some given level. The available levels, from most quiet to most severe, are:
log.debug
log.info
log.notice
log.warning
log.error
log.fatal
-v
command-line argument.
As the name suggests, log.fatal
immediately terminates the program with
a fatal error. The others have no side effect other than showing the message.
The message and arguments together are interpolated like Python's normal string
interpolation, similar to the builtin logging
package.
decompose(label)
Decomposes a build label into the package and name parts.
Consider carefully when you should use this - command replacements may be more appropriate.
Most rules should be able to accept labels without having to know anything about their structure.
The input label can be given in either relative or absolute form. It will fail with an error if it's not a structurally valid label.
canonicalise(label)
Converts the given build label to its full form.
For example:
//package:target
-> //package:target
//package
-> //package:package
:target
-> //current_package:target
Rules to build C and C++ targets.
The process of building C or C++ code is fairly complex so while these rules do their best to keep things reasonably simple, there's a lot of scope for things going wrong.
There is very little difference between the c_
and cc_
variants
of each rule, in nearly all cases they simply use different tools and flags in the
relevant config section.
Rules to build Go code.
Go has a strong built-in concept of packages so while it's not 100% required to strictly keep to 1 package per dir as in classic Go, it's still probably a good idea to match Please rules to Go packages.
{{ template "lexicon_entry.html" .Named "go_toolchain" }} {{ template "lexicon_entry.html" .Named "go_library" }} {{ template "lexicon_entry.html" .Named "cgo_library" }} {{ template "lexicon_entry.html" .Named "go_binary" }} {{ template "lexicon_entry.html" .Named "go_test" }} {{ template "lexicon_entry.html" .Named "cgo_test" }} {{ template "lexicon_entry.html" .Named "go_test_main" }} {{ template "lexicon_entry.html" .Named "go_get" }}Built-in rules to compile Java code.
{{ template "lexicon_entry.html" .Named "java_library" }} {{ template "lexicon_entry.html" .Named "java_module" }} {{ template "lexicon_entry.html" .Named "java_binary" }} {{ template "lexicon_entry.html" .Named "java_runtime_image" }} {{ template "lexicon_entry.html" .Named "java_test" }} {{ template "lexicon_entry.html" .Named "maven_jar" }} {{ template "lexicon_entry.html" .Named "java_toolchain" }}Miscellaneous rules that aren't language-specific.
{{ template "lexicon_entry.html" .Named "genrule" }} {{ template "lexicon_entry.html" .Named "gentest" }} {{ template "lexicon_entry.html" .Named "export_file" }} {{ template "lexicon_entry.html" .Named "filegroup" }} {{ template "lexicon_entry.html" .Named "hash_filegroup" }} {{ template "lexicon_entry.html" .Named "system_library" }} {{ template "lexicon_entry.html" .Named "remote_file" }} {{ template "lexicon_entry.html" .Named "tarball" }}git_branch(short:bool=True)
Calls git symbolic-ref -q HEAD
and returns the
corresponding git branch. If short
is false, show the full
symbolic ref for a branch.
Argument | Default | Type | |
---|---|---|---|
short | True | bool | Uses the shortened symbolic ref for a branch. |
git_commit()
Calls git rev-parse HEAD
and returns the corresponding git
commit SHA. To return a shortened commit
use git_commit()[0:8]
.
git_show(format:str)
Calls git show -s --format={format}
and returns the
result. format
is limited to a subset of values accepted
by git show
.
Argument | Default | Type | |
---|---|---|---|
format | str | String format passed to git show . |
Supported format verbs are limited to:
%H
commit hash%T
tree hash%P
parent hashes%an
author name%ae
author email%at
author date, UNIX timestamp%cn
committer name%ce
committer email%ct
committer date, UNIX timestamp%D
ref names%e
encoding%s
subject of commit message%f
sanitized subject line, suitable for a filename%b
body of commit message%B
raw body (unwrapped subject and body)%N
commit notes%GG
raw verification message from GPG for a signed commit%G?
show "G" for a good (valid) signature, "B" for a bad signature, "U" for a good signature with unknown validity, "X" for a good signature that has expired, "Y" for a good signature made by an expired key, "R" for a good signature made by a revoked key, "E" if the signature cannot be checked (e.g. missing key) and "N" for no signature%GS
show the name of the signer for a signed commit%GK
show the key used to sign a signed commit%n
newline%%
a raw %git_state(clean_label:str="clean", dirty_label:str="dirty")
Calls git status --porcelain
and returns the
corresponding string. If the repository is clean, the string set
in clean_label
is returned. If the repository is dirty, the
string set in dirty_label
is returned.
Argument | Default | Type | |
---|---|---|---|
clean_label | clean | str | String returned if the repository is clean. |
dirty_label | dirty | str | String returned if the repository is dirty. |
Build rules for compiling protocol buffers & gRPC service stubs.
Note that these are some of the most complex of our built-in build rules, because of their cross-language nature. Each proto_library rule declares a set of sub-rules to run protoc & the appropriate java_library, go_library rules etc. Users shouldn't worry about those sub-rules and just declare a dependency directly on the proto_library rule to get its appropriate outputs.
{{ template "lexicon_entry.html" .Named "proto_library" }} {{ template "lexicon_entry.html" .Named "grpc_library" }} {{ template "lexicon_entry.html" .Named "proto_language" }}Rules to build Python code.
The output artifacts for Python rules are .zip files similar to .pex files (and are suffixed as such).
This combines all the in-repo dependencies into a single file that can be deployed and run
on any system that has a suitable Python interpreter. Please optimises this process to
improve incrementality and includes some hooks to make running from a zipfile as transparent
as possible; nonetheless certain file-based operations may not work since there is not a
real file system available. If necessary various Python rules can be annotated with
zip_safe
to control this; if a binary is zip-unsafe it will extract itself before
running.
Rules to 'build' shell scripts.
Note that these do pretty much nothing beyond collecting the files. In future we might implement something more advanced (ala .sar files or whatever).
{{ template "lexicon_entry.html" .Named "sh_library" }} {{ template "lexicon_entry.html" .Named "sh_binary" }} {{ template "lexicon_entry.html" .Named "sh_cmd" }} {{ template "lexicon_entry.html" .Named "sh_test" }}Rules for defining subrepos. See the docs for more information on subrepos in general.
{{ template "lexicon_entry.html" .Named "http_archive" }} {{ template "lexicon_entry.html" .Named "new_http_archive" }} {{ template "lexicon_entry.html" .Named "github_repo" }} {{ template "lexicon_entry.html" .Named "arch" }}