Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: NixOS/nixos-homepage
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: e27e6843a40b
Choose a base ref
...
head repository: NixOS/nixos-homepage
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: 2954e70bdd4d
Choose a head ref
  • 1 commit
  • 1 file changed
  • 1 contributor

Commits on Jan 22, 2021

  1. Update flake.lock and blogs.xml [ci skip]

    GitHub Actions committed Jan 22, 2021
    Copy the full SHA
    2954e70 View commit details
Showing with 251 additions and 68 deletions.
  1. +251 −68 blogs.xml
319 changes: 251 additions & 68 deletions blogs.xml
Original file line number Diff line number Diff line change
@@ -8,6 +8,257 @@
<description>NixOS Planet - https://planet.nixos.org</description>
<atom:link rel="self" href="https://planet.nixos.org/rss20.xml" type="application/rss+xml"/>

<item>
<title>Tweag I/O: Programming with contracts in Nickel</title>
<guid isPermaLink="true">https://tweag.io/blog/2021-01-22-nickel-contracts/</guid>
<link>https://tweag.io/blog/2021-01-22-nickel-contracts/</link>
<description>&lt;p&gt;In a &lt;a href=&quot;https://www.tweag.io/blog/2020-10-22-nickel-open-sourcing/&quot;&gt;previous post&lt;/a&gt;, I gave a taste of &lt;a href=&quot;https://github.com/tweag/nickel/&quot;&gt;Nickel&lt;/a&gt;, a configuration
language we are developing at Tweag. One cool feature of Nickel is the ability
to validate data and enforce program invariants using so-called contracts. In
this post, I introduce the general concept of programming with contracts and
illustrate it in Nickel.&lt;/p&gt;
&lt;h2&gt;Contracts are everywhere&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;You go to your favorite bakery and buy a croissant. Is there a contract binding you to the baker?&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;A long time ago, I was puzzled by this very first question of a law class exam.
It looked really simple, yet I had absolutely no clue.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;“Ehm..No?”&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;A contract should write down terms and conditions, and be signed by both
parties. How could buying a croissant involve such a daunting liability?&lt;/p&gt;
&lt;p&gt;Well, I have to confess that this exam didn’t go very well.&lt;/p&gt;
&lt;p&gt;It turns out the sheer act of selling something implicitly and automatically
establishes a legally binding contract between both parties (at least in
&lt;a href=&quot;https://fr.wikipedia.org/wiki/Contrat_de_vente_en_France#Formation_du_contrat&quot;&gt;France&lt;/a&gt;). For once, the programming world is not that different
from the physical world: if I see a &lt;code class=&quot;language-text&quot;&gt;ConcurrentHashmap&lt;/code&gt; class in a Java library,
given the context of Java’s naming conventions, I rightfully expect it to be a
thread-safe implementation of a hashmap. This is a form of contract. If a
programmer uses &lt;code class=&quot;language-text&quot;&gt;ConcurrentHashmap&lt;/code&gt; to name a class that implements a non-thread
safe linked list, they should probably be sent to court.&lt;/p&gt;
&lt;p&gt;Contracts may take multiple forms. A contract can be &lt;em&gt;explicit&lt;/em&gt;, such as in a
formal specification, or &lt;em&gt;implicit&lt;/em&gt;, as in the &lt;code class=&quot;language-text&quot;&gt;ConcurrentHashMap&lt;/code&gt; example. They
can be &lt;em&gt;enforced&lt;/em&gt; or not, such as a type signature in a statically typed
language versus an invariant written as a comment in a dynamically typed
language. Here are a few examples:&lt;/p&gt;
&lt;center&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Contract&lt;/th&gt;
&lt;th&gt;Explicitness&lt;/th&gt;
&lt;th&gt;Enforced&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Static types&lt;/td&gt;
&lt;td&gt;Implicit if inferred, explicit otherwise&lt;/td&gt;
&lt;td&gt;Yes, at compile time&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Dynamic types&lt;/td&gt;
&lt;td&gt;Implicit&lt;/td&gt;
&lt;td&gt;Yes, at run-time&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Documentation&lt;/td&gt;
&lt;td&gt;Explicit&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Naming&lt;/td&gt;
&lt;td&gt;Implicit&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code class=&quot;language-text&quot;&gt;assert()&lt;/code&gt; primitive&lt;/td&gt;
&lt;td&gt;Explicit&lt;/td&gt;
&lt;td&gt;Yes, at run-time&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;pre/post conditions&lt;/td&gt;
&lt;td&gt;Explicit&lt;/td&gt;
&lt;td&gt;Yes, at run-time or compile time&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/center&gt;
&lt;p&gt;As often, explicit is better than implicit: it leaves no room for
misunderstanding. Enforced is better than not, because I would rather be
protected by a proper legal system in case of contract violation.&lt;/p&gt;
&lt;h2&gt;Programming with Contracts&lt;/h2&gt;
&lt;p&gt;Until now, I’ve been using the word contract in a wide sense. It turns out
contracts also refer to a particular programming paradigm which embodies the
general notion pretty well. Such contracts are &lt;em&gt;explicit&lt;/em&gt; and &lt;em&gt;enforced&lt;/em&gt;,
following our terminology. They are most notably used in
&lt;a href=&quot;https://docs.racket-lang.org/reference/contracts.html&quot;&gt;Racket&lt;/a&gt;. From now on, I shall use contract in this more
specific sense.&lt;/p&gt;
&lt;p&gt;To first approximation, contracts are assertions. They check that a value
satisfies some property at run-time. If the test passes, the execution can go on
normally. Otherwise, an error is raised.&lt;/p&gt;
&lt;p&gt;In Nickel, one can enforce a contract using the &lt;code class=&quot;language-text&quot;&gt;|&lt;/code&gt; operator:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;let x = (1 + 1 | Num) in 2*x&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Here, &lt;code class=&quot;language-text&quot;&gt;x&lt;/code&gt; is bound to a &lt;code class=&quot;language-text&quot;&gt;Num&lt;/code&gt; contract. When evaluating &lt;code class=&quot;language-text&quot;&gt;x&lt;/code&gt;, the following steps
are performed:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;evaluate &lt;code class=&quot;language-text&quot;&gt;1 + 1&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;check that the result is a number&lt;/li&gt;
&lt;li&gt;if it is, return the expression unchanged. Otherwise, raise an error that
halts the program.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Let’s see it in action:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;$nickel &amp;lt;&amp;lt;&amp;lt; '1 + 1 | Num'
Done: Num(2.0)

$nickel &amp;lt;&amp;lt;&amp;lt; 'false | Num'
error: Blame error: contract broken by a value.
┌─ :1:1
1 │ Num
│ --- expected type
┌─ &amp;lt;stdin&amp;gt;:1:9
1 │ false | Num
│ ^^^ bound here&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2&gt;Contracts versus types&lt;/h2&gt;
&lt;p&gt;I’ve described contracts as assertions, but the above snippet suspiciously
resembles a type annotation. How do contracts compare to types? First of all,
contracts are checked at run-time, so they would correspond to dynamic typing
rather than static typing. Secondly, contracts can check more than just the
membership to a type:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;let GreaterThan2 = fun label x =&amp;gt;
if builtins.isNum x then
if x &amp;gt; 2 then
x
else
contracts.blame (contracts.tag &quot;smaller or equals&quot; label)
else
contracts.blame (contracts.tag &quot;not a number&quot; label)
in

(3 | #GreaterThan2) // Ok, evaluate to 3
(1 | #GreaterThan2) // Err, `smaller or equals`
(&quot;a&quot; | #GreaterThan2) // Err, `not a number`&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Here, we just built a &lt;em&gt;custom contract&lt;/em&gt;. A custom contract is a function of two
arguments:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;the label &lt;code class=&quot;language-text&quot;&gt;label&lt;/code&gt;, carrying information for error reporting.&lt;/li&gt;
&lt;li&gt;the value &lt;code class=&quot;language-text&quot;&gt;x&lt;/code&gt; to be tested.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;If the value satisfies the condition, it is returned. Otherwise, a call to
&lt;code class=&quot;language-text&quot;&gt;blame&lt;/code&gt; signals rejection with an optional error message attached via &lt;code class=&quot;language-text&quot;&gt;tag&lt;/code&gt;.
When evaluating &lt;code class=&quot;language-text&quot;&gt;value | #Contract&lt;/code&gt;, the interpreter calls &lt;code class=&quot;language-text&quot;&gt;Contract&lt;/code&gt; with an
appropriate label and &lt;code class=&quot;language-text&quot;&gt;value&lt;/code&gt; as arguments.&lt;/p&gt;
&lt;p&gt;Such custom contracts can check arbitrary properties. Enforcing the property of
being greater than two using static types is rather hard, requiring a fancy type
system such as &lt;a href=&quot;https://ucsd-progsys.github.io/liquidhaskell-blog/&quot;&gt;refinement types&lt;/a&gt; , while the role of dynamic
types generally stops at distinguishing basic datatypes and functions.&lt;/p&gt;
&lt;p&gt;Back to our first example &lt;code class=&quot;language-text&quot;&gt;1 + 1 | Num&lt;/code&gt;, we could have written instead:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;let MyNum = fun label x =&amp;gt;
if builtins.isNum x then x else contracts.blame label in
(1 + 1 | #MyNum)&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;This is in fact pretty much what &lt;code class=&quot;language-text&quot;&gt;1 + 1 | Num&lt;/code&gt; evaluates to. While a contract is
not the same entity as a type, one can derive a contract from any type. Writing
&lt;code class=&quot;language-text&quot;&gt;1 + 1 | Num&lt;/code&gt; asks the interpreter to derive a contract from the type &lt;code class=&quot;language-text&quot;&gt;Num&lt;/code&gt; and
to check &lt;code class=&quot;language-text&quot;&gt;1 + 1&lt;/code&gt; against it. This is just a convenient syntax to specify common
contracts. The&lt;code class=&quot;language-text&quot;&gt;#&lt;/code&gt; character distinguishes &lt;em&gt;contracts as types&lt;/em&gt; from &lt;em&gt;contracts
as functions&lt;/em&gt; (that is, custom contracts).&lt;/p&gt;
&lt;p&gt;To sum up, contracts are just glorified assertions. Also, there is this
incredibly convenient syntax that spares us a whole three characters by writing &lt;code class=&quot;language-text&quot;&gt;Num&lt;/code&gt;
instead of &lt;code class=&quot;language-text&quot;&gt;#MyNum&lt;/code&gt;. So… is that all the fuss is about?&lt;/p&gt;
&lt;h2&gt;Function contracts&lt;/h2&gt;
&lt;p&gt;Until now, we have only considered what are called &lt;em&gt;flat&lt;/em&gt; contracts, which
operate on data. But Nickel is a functional programming language: so what about
function contracts? They exist too!&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;let f | Str -&amp;gt; Num = fun x =&amp;gt; if x == &quot;a&quot; then 0 else 1 in ...&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Here again, we ask Nickel to derive a contract for us, from the type &lt;code class=&quot;language-text&quot;&gt;Str -&amp;gt; Num&lt;/code&gt;
of functions sending strings to numbers. To find out how this contract could
work, we must understand what is the defining property of a function of type
&lt;code class=&quot;language-text&quot;&gt;Str -&amp;gt; Num&lt;/code&gt; that the contract should enforce.&lt;/p&gt;
&lt;p&gt;A function of type &lt;code class=&quot;language-text&quot;&gt;Str -&amp;gt; Num&lt;/code&gt; has a &lt;em&gt;duty&lt;/em&gt;: it must produce a number. But what
if I call &lt;code class=&quot;language-text&quot;&gt;f&lt;/code&gt; on a boolean? That’s unfair, because the function has also a
&lt;em&gt;right&lt;/em&gt;: the argument must be a string. The full contract is thus: if you give
me a string, I give you a number. If you give me something else, you broke the
contract, so I can’t guarantee anything. Another way of viewing it is that the
left side of the arrow represents &lt;strong&gt;preconditions&lt;/strong&gt; on the input while the right
side represents &lt;strong&gt;postconditions&lt;/strong&gt; on the output.&lt;/p&gt;
&lt;p&gt;More than flat contracts, function contracts show similarities with traditional
legal contracts. We have two parties: the &lt;strong&gt;caller&lt;/strong&gt;, &lt;code class=&quot;language-text&quot;&gt;f &quot;b&quot;&lt;/code&gt;, and the
&lt;strong&gt;callee&lt;/strong&gt;, &lt;code class=&quot;language-text&quot;&gt;f&lt;/code&gt;. Both must meet conditions: the caller must provide a string
while the callee must return a number.&lt;/p&gt;
&lt;p&gt;In practice, inspecting the term &lt;code class=&quot;language-text&quot;&gt;f&lt;/code&gt; can tell us if it is a function at most.
This is because a function is inert, waiting for an argument to hand back a
result. In consequence, the contract is doomed to fire only when &lt;code class=&quot;language-text&quot;&gt;f&lt;/code&gt; is applied
to an argument, in which case it checks that:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;The argument satisfies the &lt;code class=&quot;language-text&quot;&gt;Str&lt;/code&gt; contract&lt;/li&gt;
&lt;li&gt;The return value satisfies the &lt;code class=&quot;language-text&quot;&gt;Num&lt;/code&gt; contract&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;The interpreter performs additional bookkeeping to be able to correctly blame
the offending code in case of a higher-order contract violation:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;$nickel &amp;lt;&amp;lt;&amp;lt; 'let f | Str -&amp;gt; Num = fun x =&amp;gt; if x == &quot;a&quot; then 0 else 1 in f &quot;a&quot;'
Done: Num(0.0)

$nickel &amp;lt;&amp;lt;&amp;lt; '... in f 0'
error: Blame error: contract broken by the caller.
┌─ :1:1
1 │ Str -&amp;gt; Num
│ --- expected type of the argument provided by the caller
┌─ &amp;lt;stdin&amp;gt;:1:9
1 │ let f | Str -&amp;gt; Num = fun x =&amp;gt; if x == &quot;a&quot; then 0 else 1 in f 0
│ ^^^^^^^^^^ bound here
[..]

$nickel &amp;lt;&amp;lt;&amp;lt; 'let f | Str -&amp;gt; Num = fun x =&amp;gt; x in f &quot;a&quot;'
error: Blame error: contract broken by a function.
┌─ :1:8
1 │ Str -&amp;gt; Num
│ --- expected return type
┌─ &amp;lt;stdin&amp;gt;:1:9
1 │ let f | Str -&amp;gt; Num = fun x =&amp;gt; x in f &quot;a&quot;
│ ^^^^^^^^^^ bound here&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;These examples illustrate three possible situations:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;The contract is honored by both parties.&lt;/li&gt;
&lt;li&gt;The contract is broken by the caller, which provides a number instead of a
string.&lt;/li&gt;
&lt;li&gt;The contract is broken by the function (callee), which rightfully got a
string but returned a string instead of a number.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Combined with custom contracts, function contracts make it possible to express
succinctly non-trivial invariants:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;let f | #GreaterThan2 -&amp;gt; #GreaterThan2 = fun x =&amp;gt; x + 1 in ..&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2&gt;A warning about laziness&lt;/h2&gt;
&lt;p&gt;Nickel is a &lt;a href=&quot;https://en.wikipedia.org/wiki/Lazy_evaluation&quot;&gt;lazy programming language&lt;/a&gt;. This means that expressions,
including contracts, are evaluated only if they are needed. If you are
experimenting with contracts and some checks buried inside lists or records do
not seem to trigger, you can use the &lt;code class=&quot;language-text&quot;&gt;deepSeq&lt;/code&gt; operator to recursively force the
evaluation of all subterms, including contracts:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;let exp = ..YOUR CODE WITH CONTRACTS.. in builtins.deepSeq exp exp&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;In this post, I introduced programming with contracts. Contracts offer a
principled and ergonomic way of validating data and enforcing invariants with a
good error reporting story. Contracts can express arbitrary properties that are
hard to enforce statically, and they can handle higher-order functions.&lt;/p&gt;
&lt;p&gt;Contracts also have a special relationship with static typing. While we compared
them as competitors somehow, contracts and static types are actually
complementary, reunited in the setting of &lt;a href=&quot;https://wphomes.soic.indiana.edu/jsiek/what-is-gradual-typing/&quot;&gt;gradual typing&lt;/a&gt;.
Nickel has gradual types, which will be the subject of a coming post.&lt;/p&gt;
&lt;p&gt;The examples here are illustrative, but we’ll see more specific and compelling
usages of contracts in yet another coming post about Nickel’s meta-values,
which, together with contracts, serve as a unified way to describe and validate
configurations.&lt;/p&gt;</description>
<pubDate>Fri, 22 Jan 2021 00:00:00 +0000</pubDate>
</item>
<item>
<title>nixbuild.net: Finding Non-determinism with nixbuild.net</title>
<guid isPermaLink="true">https://blog.nixbuild.net/posts/2021-01-13-finding-non-determinism-with-nixbuild-net.html</guid>
@@ -1257,74 +1508,6 @@ time user of and contributor to &lt;code class=&quot;language-text&quot;&gt;rule
<pubDate>Thu, 24 Sep 2020 18:24:00 +0000</pubDate>
<author>noreply@blogger.com (Sander van der Burg)</author>
</item>
<item>
<title>Tweag I/O: Implicit Dependencies in Build Systems</title>
<guid isPermaLink="true">https://tweag.io/blog/2020-09-16-implicit-build-dependencies/</guid>
<link>https://tweag.io/blog/2020-09-16-implicit-build-dependencies/</link>
<description>&lt;p&gt;In making a build system for your software, you codified the dependencies
between its parts. But, did you account for &lt;em&gt;implicit&lt;/em&gt; software dependencies,
like system libraries and compiler toolchains?&lt;/p&gt;
&lt;p&gt;Implicit dependencies give rise to the biggest and most common problem with
software builds - the lack of &lt;em&gt;hermiticity&lt;/em&gt;. Without hermetic builds,
&lt;em&gt;reproducibility&lt;/em&gt; and &lt;em&gt;cacheability&lt;/em&gt; are lost.&lt;/p&gt;
&lt;p&gt;This post motivates the desire for reproducibility and cacheability, and
explains how we achieve hermetic, reproducible, highly cacheable builds by
taking control of implicit dependencies.&lt;/p&gt;
&lt;h3&gt;Reproducibility&lt;/h3&gt;
&lt;p&gt;Consider a developer newly approaching a code repository. After cloning the
repo, the developer must install a long list of “build requirements” and plod
through multiple steps of “setup”, only to find that, yes indeed, the build
fails. Yet, it worked just fine for their colleague! The developer, typically
not expert in build tooling, must debug the mysterious failure not of their
making. This is bad for morale and for productivity.&lt;/p&gt;
&lt;p&gt;This happens because the build is not &lt;em&gt;reproducible&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;One very common reason for the failure is that the compiler toolchain on the
developer’s system is different from that of the colleague. This happens even
with build systems that use sophisticated build software, like &lt;a href=&quot;https://www.tweag.io/blog/tags/bazel&quot;&gt;Bazel&lt;/a&gt;.
Bazel implicitly uses whatever system libraries and compilers are currently
installed in the developer’s environment.&lt;/p&gt;
&lt;p&gt;A common workaround is to provide developers with a Docker image equipped with
a certain compiler toolchain and system libraries, and then to mandate that the
Bazel build occurs in that context.&lt;/p&gt;
&lt;p&gt;That solution has a number of drawbacks. First, if the developer is using
macOS, the virtualized build context runs substantially slower. Second, the
Bazel build cache, developer secrets, and the source code remain outside of the
image and this adds complexity to the Docker invocation. Third, the Docker
image must be rebuilt and redistributed as dependencies change and that’s extra
maintenance. Fourth, and this is the biggest issue, Docker image builds are
themselves not reproducible - they nearly always rely on some external state
that does not remain constant across build invocations, and that means the
build can fail for reasons unrelated to the developer’s code.&lt;/p&gt;
&lt;p&gt;A better solution is to use &lt;a href=&quot;https://www.tweag.io/blog/tags/nix&quot;&gt;Nix&lt;/a&gt; to supply the compiler toolchain and
system library dependencies. Nix is a software package management system
somewhat like Debian’s APT or macOS’s Homebrew. Nix goes much farther to help
developers control their environments. It is unsurpassed when it comes to
reproducible builds of software packages.&lt;/p&gt;
&lt;p&gt;Nix facilitates use of the Nixpkgs package set. That set is &lt;a href=&quot;https://repology.org/repositories/statistics/nonunique&quot;&gt;the largest single
set of software packages&lt;/a&gt;. It is also the &lt;a href=&quot;https://repology.org/repositories/statistics/newest&quot;&gt;freshest&lt;/a&gt; package set. It
provides build instructions that work both on Linux and macOS. Developers can
easily pin any software package at an exact version.&lt;/p&gt;
&lt;p&gt;Learn more about &lt;a href=&quot;https://www.tweag.io/blog/2018-03-15-bazel-nix/&quot;&gt;using Nix with Bazel, here&lt;/a&gt;.&lt;/p&gt;
&lt;h3&gt;Cacheability&lt;/h3&gt;
&lt;p&gt;Not only should builds be reproducible, but they should also be fast. Fast
builds are achieved by caching intermediate build results. Cache entries are
keyed based on the precise dependencies as well as the build instructions that
produce the entries. Builds will only benefit from a (shared, distributed)
cache when they have matching dependencies. Otherwise, cache keys (which depend
on the precise dependencies) will be different, and there will be cache misses.
This means that the developer will have to rebuild targets locally. These
unnecessary local rebuilds slow development.&lt;/p&gt;
&lt;p&gt;The solution is to &lt;a href=&quot;https://www.tweag.io/blog/2018-03-15-bazel-nix/&quot;&gt;make the implicit dependencies into explicit ones, again
using Nix&lt;/a&gt;, making sure to configure and use a shared Nix cache.&lt;/p&gt;
&lt;p&gt;Learn more about &lt;a href=&quot;https://www.tweag.io/blog/2020-04-09-bazel-remote-cache/&quot;&gt;configuring a shared Bazel cache, here&lt;/a&gt;.&lt;/p&gt;
&lt;h3&gt;Conclusion&lt;/h3&gt;
&lt;p&gt;It is important to eliminate implicit dependencies in your build system in
order to retain build reproducibility and cacheability. Identify Nix packages
that can replace the implicit dependencies of your Bazel build and use
&lt;a href=&quot;https://github.com/tweag/rules_nixpkgs&quot;&gt;rules_nixpkgs&lt;/a&gt; to declare them as explicit dependencies. That will yield a
fast, correct, hermetic build.&lt;/p&gt;</description>
<pubDate>Wed, 16 Sep 2020 00:00:00 +0000</pubDate>
</item>

</channel>
</rss>