aboutsummaryrefslogtreecommitdiffhomepage
path: root/site
diff options
context:
space:
mode:
authorGravatar Laurent Le Brun <laurentlb@google.com>2016-06-20 14:57:13 +0000
committerGravatar Philipp Wollermann <philwo@google.com>2016-06-21 09:57:55 +0000
commit20c0bb24ff9ed59ee89c6696c3706412e8a87022 (patch)
tree1012091e6700367c02504bc5702c5f0398b405a2 /site
parenta469e8f340aa211a2adcee666d61ca32e52ddbea (diff)
Improve Skylark mutability documentation.
-- MOS_MIGRATED_REVID=125336857
Diffstat (limited to 'site')
-rw-r--r--site/docs/skylark/concepts.md83
1 files changed, 53 insertions, 30 deletions
diff --git a/site/docs/skylark/concepts.md b/site/docs/skylark/concepts.md
index cb40991a2d..48ee7d0b02 100644
--- a/site/docs/skylark/concepts.md
+++ b/site/docs/skylark/concepts.md
@@ -72,6 +72,12 @@ A build consists of three phases.
required. If a file is missing or if a command fails to generate one output,
the build fails. Tests are run during this phase, as they are actions.
+Bazel uses parallelism to read, parse and evaluate the `.bzl` files and `BUILD`
+files. A file is read at most once per build and the result of the evaluation is
+cached and reused. A file is evaluated only once all its dependencies (`load()`
+statements) have been resolved. By design, loading a `.bzl` file has no visible
+side-effect, it only defines values and functions.
+
## Language
Skylark is a superset of the core build language and its syntax is a subset of
@@ -81,31 +87,53 @@ It is designed to be simple, thread-safe and integrated with the
BUILD language. It is not a general-purpose language and most Python
features are not included.
+## Mutability
+
+Because evaluation of BUILD and .bzl files is performed in parallel, there are
+some restrictions in order to guarantee thread-safety and determinism. Two
+mutable data structures are available: [lists](lib/list.html) and
+[dicts](lib/dict.html). Unlike in Python, [sets](lib/set.html) are not mutable.
+
+In a build, there are many "evaluation contexts": each `.bzl` file and each
+`BUILD` file is loaded in a different context. Each rule is also analyzed in a
+separate context. We allow side-effects (e.g. appending a value to a list or
+deleting an entry in a dictionary) only on objects created during the current
+evaluation context.
+
+For example, here is the content of the file `foo.bzl`:
+
+```python
+var = []
+
+def fct():
+ var.append(5)
-Some differences with Python should be noted:
-
-* Although some data structures are mutable, all objects are recursively frozen
- and become recursively immutable before Bazel invokes Skylark
- and after it is done with such evaluation,
- i.e. when a .bzl file is loaded, when a BUILD file is processed,
- when a Skylark-defined rule is evaluated to create a configured target, or
- when a callback function is called to compute a configured target attribute.
- These objects that are frozen notably include the recursive contents of any
- global variable exported by a .bzl file or imported by a `load()` statement,
- and any parameter passed to a callback function or result returned by it.
- From the point of view of the Skylark code
- in given a Bazel-initiated evaluation,
- objects passed as input or present in the evaluation's initial environment
- are immutable, whereas objects created during the evaluation are mutable.
- From the point of view of the Bazel code that evaluates said Skylark code,
- all inputs and outputs of the evaluation are recursively immutable
- and all evaluations are deterministic,
- which guarantees the hermeticity of the build,
- and allows sharing of evaluations without any fear of side-effects.
-
-* Lists are mutable, but dicts and sets are immutable.
- This is temporary: dicts will be made mutable in the near future;
- however there are no plans to make sets mutable at this time.
+fct()
+```
+
+The variable `var` is created when `foo.bzl` is loaded. `fct()` is called during
+the same context, so it is safe. At the end of the evaluation, the definition
+`var = [5]` is exported. Any other file can load it, and it is possible that
+multiple files will load it at the same time. For this reason, the following
+code is not legal:
+
+```python
+load(":foo.bzl", "var", "fct")
+
+var.append(6) # not allowed
+
+fct() # not allowed
+```
+
+Since the call to `fct()` attempts to mutate the shared variable `var`, it will
+fail. `fct()` can only be called during the evaluation of `foo.bzl`. It cannot
+be called from another file. It is also forbidden to call it during the analysis
+phase (i.e. when a custom rule is analyzed).
+
+## Differences with Python
+
+In addition to the mutability restrictions, there are also differences with
+Python:
* All global values are constant (they cannot be reassigned).
@@ -120,14 +148,9 @@ Some differences with Python should be noted:
operand. If you need compatibility with Python, we suggest this syntax:
`dict(a.items() + b.items())`.
-* Dictionary assignment has slightly different semantics: `d["x"] = y` is
- syntactic sugar for `d = d + {"x": y}` or `d += {"x": y}`. This behavior
- is temporary, and will follow Python semantics in the future.
-
* Dictionaries have deterministic order when iterating (sorted by key).
-* Sets use a custom order when iterating (see
- [documentation](lib/globals.html#set)).
+* Sets use a custom order when iterating (see [documentation](lib/globals.html#set)).
* Recursion is not allowed.