If you're familiar with Blaze / Bazel, Buck or Pants you will probably find Please very familiar. Otherwise, don't worry, it's not very complicated...
Please targets are defined in files named BUILD. These are analogous to Makefiles in that they define
buildable targets for that directory. Fortunately, they do so in a rather nicer syntax.
We refer to a directory containing a BUILD file as a package.
Each BUILD file can contain a number of build targets. These are units of buildable code which can be reused by other build targets. An example is probably worth 1000 words at this point:
This snippet defines three build targets; a build target is simply a thing that can be built by Please and typically appear as a single object in the build file (as the
python_library( name = 'my_library', srcs = ['file1.py', 'file2.py'], ) python_binary( name = 'my_binary', main = 'my_main.py', deps = [':my_library'], ) python_test( name = 'my_library_test', srcs = ['my_library_test.py'], deps = [':my_library'], )
my_libraryis simply a collection of
my_binarycreates a deployable Python binary with an entry point in
my_librarysince it will use it internally.
my_library_testdefines a test on
my_library. Tests are run by Please and their results are aggregated.
Let's assume the build rules given above are defined in a file in your repo named package/BUILD. You can do the following:
plz build //package:my_librarybuilds the library. This isn't drastically useful on its own, of course...
plz build //package:my_binarybuilds the binary and all needed libraries that it depends on. That produces a single output file which you could copy to another machine.
plz run //package:my_binarybuilds and runs the binary immediately.
plz test //package:my_library_testbuilds and runs the test and shows you the results.
That brings us to the topic of build labels, which are identifiers of build targets. As you've just seen,
these are of the form
package is the path from the repo root to that package,
target is the name of the target within that package.
This is the most common form to identify targets absolutely, but there is also a convenient shorthand where we omit the part before the colon (as you saw earlier as well) to refer to a target within the current package.
The convention is to use
lower_case_with_underscores for both package names and target names.
This is not just for looks; in many languages (eg. Python) the file path appears within the source files, and so it's important to choose something that's a valid lexical identifier.
There are also some special pseudo-labels:
//mypackage:allrefers to all targets in 'mypackage'.
//mypackage/...refers to all targets in 'mypackage' and anywhere beneath it in the filesystem.
Jump in and get started! See the please lexicon if you want to see the set of built-in build rules for other languages.
If that all sounds a bit easy so far, try the intermediate topics and start learning how to program the system and create your own build rules.