FAQ

Can I run it on my computer?

If you're running Linux or OSX, definitely; we actively support both those platforms.
We primarily test on Ubuntu but other distros should work fine too.

It can self-host and passes all the core tests on FreeBSD. A little more work is required to set everything up; it'd be nice to streamline this at some point. Notable issues include:

  • The RPC cache is unavailable because gRPC does not compile on FreeBSD yet. See the upstream issue for more details.
    This should have no notable downsides for clients other than them not being able to communicate with such a cache.
  • You'll need Bash installed.
  • go tool link appears to invoke gcc instead of cc, so you'll either need it installed or to provide a symlink.
  • The ports install of Python doesn't provide some of the symlinks we'd like (specifically it only has python2.7 and we'd like python2 and python).

Windows is unfortunately not supported natively, since it's just too different from the Unix environment Please is designed for. It might well be possible to make it work using Cygwin or MinGW / MSYS, or the recent Ubuntu on Windows development though. We aren't doing this work ourselves because we don't have any Windows machines, but we're happy to accept PRs in that direction.

What's the licence?

Apache 2.0

Why use Please instead of go build / Maven / Gradle?

Cross-language support is a big advantage; we have four main languages in use at Thought Machine (Javascript, Python, Java and Go) plus several smaller pieces (some C++ and Thrax grammars) and having to invoke different compilers and/or test tools for each one would be extremely tiresome.

Please can also integrate many different kinds of build steps; for example a code generation step using go generate or protoc can be invoked dynamically without having to check the resulting code into the repository.

We've tried other tools (notably Gradle and Buck) internally and ultimately decided that we could build something that would either better fit our needs, be considerably faster, or both.

Why use Please instead of Bazel, Buck or Pants?

All four of these systems are quite closely related in the scheme of things, being inspired by (or in Bazel's case, a direct open sourcing of) Google's Blaze.

Several of us had worked at Google and used Blaze extensively there; we were excited about it being open sourced as Bazel but by then we were already using Please internally. It's a great system but we have slightly different goals, specifically we're aiming Please at being lighter weight and pushing the boundaries of what can be done within the BUILD language. Since Please is written in Go there's no runtime dependency on the JVM.

We actually used Buck for some months internally before deciding to write Please and before it was capable of building our repo. We preferred it to other options available, but again we're focused on different goals; Please is easier to extend to new languages, has a bunch of features that we specifically wanted (e.g. test containerisation) and has a stronger focus on BUILD language correctness. Conversely we have much less support for mobile development.

We're least familiar with Pants; one of our developers briefly tried it and while we liked many aspects we didn't think it was the ideal fit for us at the time.

What inspired the design of Please?

Originally Blaze, since a number of us had used it at Google. More recently we'd used Buck internally so many things superficially resemble that for compatibility reasons (e.g. python_binary instead of py_binary etc).

Some of the advanced features are based on things we would have liked to do with Blaze, for example being able to defer creation of some build rules until they actually need to be built. This is only really of interest for spectacularly large trees of targets or especially esoteric use cases though.

Mostly, of course, it was inspired by our fearless leader Paul, specifically the point when he told us "you absolutely cannot write your own build system". After that it was really inevitable...

Why is it so fast?

Firstly, all the rules explicitly declare their dependencies, so Please can aggressively parallelise build rules wherever possible. It can also cache & reuse previous outputs when they haven't changed, and it hashes all input files to make sure it's correct.

Also BUILD files encourage you to break projects into smaller components, which can then be compiled in parallel. It's still possible to define a project with a single BUILD file in the traditional Java way that one would use in Gradle etc, and this works fine for smaller projects, but for larger ones parallelising the compilation can be a big advantage.

There are no separate steps inside Please; parsing BUILD files, building targets and running tests can all happen simultaneously, so there's no down time waiting for the last thing to compile before the tests begin. The parsing process is also very fast due to having an in-process PyPy interpreter.

Finally, the rules themselves are optimised in various ways; for example, the construction of the final .jar from a java_binary is an efficient concatenation of other .jar files without any recompression. Similarly the output .pex from a python_binary is built up piecemeal throughout the python_library rules and assembled at the end so we don't have to recompress an entire zip file every time you change one .py file.

How do you parse the BUILD files? What format are they?

The BUILD files are a (slightly) restricted dialect of Python. Please prefers to use PyPy to parse them which is done in-process, allowing a tight integration and a rich API with things like callbacks.
It can also use CPython + cffi via their embedding API. So far we haven't done any detailed performance benchmarks between the two.
Python 3 isn't supported yet but we plan to make it work sometime in the future.

The restrictions on the format are essentially that import and print are banned, and a number of the normal builtins are not available.
A small handful of os members are available directly as globals (named join_path, split_path, splitext, basename and dirname) since they're extremely relevant to the kinds of things rules typically do.

One down side to this is that the BUILD files are a little hard to automatically edit or update compared to a data format like XML, Yaml or JSON. We think this is worth the tradeoff for giving the developer more power and (in our opinion) a significantly nicer format.

We suggest investigating buildifier if you'd like a pretty-printer / autoformatter for them.

How does Please build itself? Do I need Please to build Please?

Please bootstraps itself using go build to build a temporary version of itself, which is then used to rebuild itself using its own BUILD rules. This requires a little duplication between the initial bootstrap script and the BUILD rules but obviously we can't rely on anyone building it already having a version of it installed.

Fortunately the process is pretty fast since Go is fast to compile.

Why write it in Go?

We excluded most other languages that any of us were familiar with through a process of elimination; JVM languages were ruled out from a concern about startup overhead, we were concerned about Python's threading performance for an inherently parallel system and felt C++ was too fiddly and lacked a strong standard library. Rust was still pre-1.0 at the time (although that didn't take long, as it turned out) so we felt it was a bit early to leap into that.

It also turned out to be a really useful way of learning the language; the project is about the right size to explore it properly and sufficiently self-contained not to affect other parts of our repo until we were sure Go was a language we wanted to do more of.

We're very happy with the results; the performance of native binaries is excellent, the language was easy to become productive with and has great support for all the things we needed to do with it. Our early concerns (e.g. the classic "no generics!") turned out to be a lot less problematic than we expected.

An alternative explanation is that the original high-level design meeting for Please was an impromptu discussion in a pub one Friday evening, where we thought it would be a neat language to try despite none of us having any real experience with it.

Is this the primary repo, or do you have a secret internal version too?

This is the only repository; all development is done here. Initially we had an internally hosted repo but transferred the project to Github in preparation for open sourcing it.

We've got some build rules in our internal repo that aren't built into Please yet. We intend to move them into this repo as we can, but the ones left aren't easy to genericise for various reasons.

There are some additional rules available at https://github.com/thought-machine/pleasings, which are either not well tested enough that we want to build them in, or are sufficiently esoteric that we don't want the build process for Please to require them.

How does the versioning scheme work? What are the compatibility guarantees?

We are using semantic versioning so essentially:

  • Changes to the major version number mean you might have to make an active change to your BUILD files or project config.
  • Changes to the minor version number indicate additional features that shouldn't require any changes on your part.
  • Changes to the patch version number are bugfixes.

These rules apply to the "public parts" of the project; specifically the command-line interface and flags, the config file format and the BUILD file format and builtins are essentially the API and so we take significantly more care about compatibility around those.
The interface to the various sub-tools invoked by Please we consider an implementation detail and those might change more aggressively (although in practice they rarely do).

Things whose behaviour is not explicitly specified might change with less notice, because of course you shouldn't have been relying on it anyway. This includes the exact hash generation method - if it becomes necessary to change that for a bugfix it may force apparently unnecessary rebuilds after an update. We try to avoid that as much as possible since it's aggravating (for us too!) but since it doesn't affect eventual correctness it can change in minor releases.

What does it look like when I'm running it?

Like this:

The appearance is somewhat inspired by Buck, although we have put some of our own spin on it as well.

What do the colours in the console output mean?

They change based on the type of rule that's being built:

  • Yellow: Go
  • Green: Python
  • Red: Java
  • Blue: Javascript
  • Cyan: Parsing a BUILD file
  • Magenta: Third party dependencies
  • White: Anything else.

Libraries are normal weight, binaries (including tests) are bold.

There is absolutely no significance to the choice of colours beyond arbitrary choice when that code was originally written.

Why's it called Please?

Because we liked the idea of sounding polite when typing "plz build", "plz test", etc.
Also we chose the domain name before almost anything else (priorities!).