Update BEAM docs

Improve beam docs:
 * correct spelling
 * update per pandoc changes
 * capitalize titles
 * capitalize BEAM throughout and use "the BEAM" when referring to the virtual machine.
 * tweak grammar and phrasing
 * reformat build-tools-rebar3 section
 * add more links
 * re-wrap <para>s

Also update <programlisting>s
* normalize whitespace
* don't double quote homepage
* use $ in all shell snippets
This commit is contained in:
Eric Bailey 2017-06-22 04:32:46 -05:00 committed by Gleb Peregud
parent 0fccd5bba4
commit 505508a813
2 changed files with 182 additions and 164 deletions

View File

@ -26,7 +26,7 @@ pkgs.stdenv.mkDerivation {
extraHeader = ''xmlns="http://docbook.org/ns/docbook" xmlns:xlink="http://www.w3.org/1999/xlink" ''; extraHeader = ''xmlns="http://docbook.org/ns/docbook" xmlns:xlink="http://www.w3.org/1999/xlink" '';
in '' in ''
{ {
pandoc '${inputFile}' -w docbook ${lib.optionalString useChapters "--chapters"} \ pandoc '${inputFile}' -w docbook ${lib.optionalString useChapters "--top-level-division=chapter"} \
--smart \ --smart \
| sed -e 's|<ulink url=|<link xlink:href=|' \ | sed -e 's|<ulink url=|<link xlink:href=|' \
-e 's|</ulink>|</link>|' \ -e 's|</ulink>|</link>|' \

View File

@ -2,30 +2,29 @@
xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:xlink="http://www.w3.org/1999/xlink"
xml:id="sec-beam"> xml:id="sec-beam">
<title>Beam Languages (Erlang, Elixir &amp; LFE)</title> <title>BEAM Languages (Erlang, Elixir &amp; LFE)</title>
<section xml:id="beam-introduction"> <section xml:id="beam-introduction">
<title>Introduction</title> <title>Introduction</title>
<para> <para>
In this document and related Nix expressions we use the term In this document and related Nix expressions, we use the term,
<emphasis>Beam</emphasis> to describe the environment. BEAM is <emphasis>BEAM</emphasis>, to describe the environment. BEAM is the name
the name of the Erlang Virtial Machine and, as far as we know, of the Erlang Virtual Machine and, as far as we're concerned, from a
from a packaging perspective all languages that run on BEAM are packaging perspective, all languages that run on the BEAM are
interchangable. The things that do change, like the build interchangeable. That which varies, like the build system, is transparent
system, are transperant to the users of the package. So we make to users of any given BEAM package, so we make no distinction.
no distinction.
</para> </para>
</section> </section>
<section xml:id="beam-structure"> <section xml:id="beam-structure">
<title>Structure</title> <title>Structure</title>
<para> <para>
All Beam-related things are available via top-level All BEAM-related expressions are available via the top-level
<literal>beam</literal> attribute, which includes: <literal>beam</literal> attribute, which includes:
</para> </para>
<itemizedlist> <itemizedlist>
<listitem> <listitem>
<para> <para>
<literal>interpreters</literal>: contains a set of compilers running <literal>interpreters</literal>: a set of compilers running on the
on Beam, including multiple Erlang/OTP versions BEAM, including multiple Erlang/OTP versions
(<literal>beam.interpreters.erlangR19</literal>, etc), Elixir (<literal>beam.interpreters.erlangR19</literal>, etc), Elixir
(<literal>beam.interpreters.elixir</literal>) and LFE (<literal>beam.interpreters.elixir</literal>) and LFE
(<literal>beam.interpreters.lfe</literal>). (<literal>beam.interpreters.lfe</literal>).
@ -33,36 +32,37 @@
</listitem> </listitem>
<listitem> <listitem>
<para> <para>
<literal>packages</literal>: contains a set of package sets, each <literal>packages</literal>: a set of package sets, each compiled with
compiled with a specific Erlang/OTP version, e.g. a specific Erlang/OTP version, e.g.
<literal>beam.packages.erlangR19</literal>. <literal>beam.packages.erlangR19</literal>.
</para> </para>
</listitem> </listitem>
</itemizedlist> </itemizedlist>
<para> <para>
Default Erlang compiler is defined by The default Erlang compiler, defined by
<literal>beam.interpreters.erlang</literal> and aliased as <literal>beam.interpreters.erlang</literal>, is aliased as
<literal>erlang</literal>. Default package set with Beam packages is <literal>erlang</literal>. The default BEAM package set is defined by
defined by <literal>beam.packages.erlang</literal> and aliased at <literal>beam.packages.erlang</literal> and aliased at the top level as
top-level as <literal>beamPackages</literal>. <literal>beamPackages</literal>.
</para> </para>
<para> <para>
If you want to create a package set built with a custom Erlang version, To create a package set built with a custom Erlang version, use the
use lambda <literal>beam.packagesWith</literal>, which accepts an lambda, <literal>beam.packagesWith</literal>, which accepts an Erlang/OTP
Erlang/OTP derivative and produces a package set similar to derivation and produces a package set similar to
<literal>beam.packages.erlang</literal>. <literal>beam.packages.erlang</literal>.
</para> </para>
<para> <para>
Many Erlang/OTP distributions available in Many Erlang/OTP distributions available in
<literal>beam.interpreters</literal> have their versions with ODBC and/or <literal>beam.interpreters</literal> have versions with ODBC and/or Java
Java enabled. For example there's enabled. For example, there's
<literal>beam.interpreters.erlangR19_odbc_javac</literal> which <literal>beam.interpreters.erlangR19_odbc_javac</literal>, which
corresponds to <literal>beam.interpreters.erlangR19</literal>. corresponds to <literal>beam.interpreters.erlangR19</literal>.
</para> </para>
<para> <para xml:id="erlang-call-package">
We also provide <literal>beam.packages.erlang.callPackage</literal>, which We also provide the lambda,
simplifies writing Beam package definitions, by injecting all packages from <literal>beam.packages.erlang.callPackage</literal>, which simplifies
<literal>beam.packages.erlang</literal> into top-level context. writing BEAM package definitions by injecting all packages from
<literal>beam.packages.erlang</literal> into the top-level context.
</para> </para>
</section> </section>
<section xml:id="build-tools"> <section xml:id="build-tools">
@ -70,42 +70,52 @@
<section xml:id="build-tools-rebar3"> <section xml:id="build-tools-rebar3">
<title>Rebar3</title> <title>Rebar3</title>
<para> <para>
By default Rebar3 wants to manage it's own dependencies. This is perfectly By default, Rebar3 wants to manage its own dependencies. This is perfectly
acceptable in the normal non-Nix setup. In the Nix world it is not. To acceptable in the normal, non-Nix setup, but in the Nix world, it is not.
support this we have created two versions of rebar3, To rectify this, we provide two versions of Rebar3:
<literal>rebar3</literal> and <literal>rebar3-open</literal>. The <itemizedlist>
<literal>rebar3</literal> version has been patched to remove the ability <listitem>
to download anything from it. If you are not running it a nix-shell or a <para>
nix-build then its probably not going to work for you. <literal>rebar3</literal>: patched to remove the ability to download
<literal>rebar3-open</literal> is the normal, un-modified rebar3. It anything. When not running it via <literal>nix-shell</literal> or
should work exactly as would any other version of rebar3. Any Erlang <literal>nix-build</literal>, it's probably not going to work as
package should rely on <literal>rebar3</literal> and thats really what you desired.
should be using too. See <literal>buildRebar3</literal> below. </para>
</listitem>
<listitem>
<para>
<literal>rebar3-open</literal>: the normal, unmodified Rebar3. It
should work exactly as would any other version of Rebar3. Any Erlang
package should rely on <literal>rebar3</literal> instead. See <xref
linkend="rebar3-packages"/>.
</para>
</listitem>
</itemizedlist>
</para> </para>
</section> </section>
<section xml:id="build-tools-other"> <section xml:id="build-tools-other">
<title>Mix &amp; Erlang.mk</title> <title>Mix &amp; Erlang.mk</title>
<para> <para>
Both Mix and Erlang.mk work exactly as you would expect. There Both Mix and Erlang.mk work exactly as expected. There is a bootstrap
is a bootstrap process that needs to be run for both of process that needs to be run for both, however, which is supported by the
them. However, that is supported by the <literal>buildMix</literal> and <literal>buildErlangMk</literal>
<literal>buildMix</literal> and <literal>buildErlangMk</literal> derivations. derivations, respectively.
</para> </para>
</section> </section>
</section> </section>
<section xml:id="how-to-install-beam-packages"> <section xml:id="how-to-install-beam-packages">
<title>How to install Beam packages</title> <title>How to Install BEAM Packages</title>
<para> <para>
Beam packages are not registered in the top level simply because they are BEAM packages are not registered at the top level, simply because they are
not relevant to the vast majority of Nix users. They are installable using not relevant to the vast majority of Nix users. They are installable using
the <literal>beam.packages.erlang</literal> attribute set and aliased as the <literal>beam.packages.erlang</literal> attribute set (aliased as
<literal>beamPackages</literal>. This attribute points at packages built by <literal>beamPackages</literal>), which points to packages built by the
the default Erlang/OTP version in Nixpkgs as defined by default Erlang/OTP version in Nixpkgs, as defined by
<literal>beam.interpreters.erlang</literal>. <literal>beam.interpreters.erlang</literal>.
You can list the avialable packages in the To list the available packages in
<literal>beamPackages</literal> with the following command: <literal>beamPackages</literal>, use the following command:
</para> </para>
<programlisting> <programlisting>
@ -119,145 +129,152 @@ beamPackages.meck meck-0.8.3
beamPackages.rebar3-pc pc-1.1.0 beamPackages.rebar3-pc pc-1.1.0
</programlisting> </programlisting>
<para> <para>
To install any of those packages into your profile, refer to them by To install any of those packages into your profile, refer to them by their
their attribute path (first column): attribute path (first column):
</para> </para>
<programlisting> <programlisting>
$ nix-env -f &quot;&lt;nixpkgs&gt;&quot; -iA beamPackages.ibrowse $ nix-env -f &quot;&lt;nixpkgs&gt;&quot; -iA beamPackages.ibrowse
</programlisting> </programlisting>
<para> <para>
The attribute path of any Beam packages corresponds to the name The attribute path of any BEAM package corresponds to the name of that
of that particular package in Hex or its OTP Application/Release name. particular package in <link xlink:href="https://hex.pm">Hex</link> or its
OTP Application/Release name.
</para> </para>
</section> </section>
<section xml:id="packaging-beam-applications"> <section xml:id="packaging-beam-applications">
<title>Packaging Beam Applications</title> <title>Packaging BEAM Applications</title>
<section xml:id="packaging-erlang-applications"> <section xml:id="packaging-erlang-applications">
<title>Erlang Applications</title> <title>Erlang Applications</title>
<section xml:id="rebar3-packages"> <section xml:id="rebar3-packages">
<title>Rebar3 Packages</title> <title>Rebar3 Packages</title>
<para> <para>
There is a Nix function called <literal>buildRebar3</literal> (defined The Nix function, <literal>buildRebar3</literal>, defined in
in <literal>beam.packages.erlang.buildRebar3</literal> and aliased at <literal>beam.packages.erlang.buildRebar3</literal> and aliased at the
top-level). We use this function to make a derivation that understands top level, can be used to build a derivation that understands how to
how to build the rebar3 project. For example, the expression we use to build a Rebar3 project. For example, we can build <link
build the <link xlink:href="https://github.com/erlang-nix/hex2nix">hex2nix</link> as
xlink:href="https://github.com/erlang-nix/hex2nix">hex2nix</link> follows:
project follows.
</para> </para>
<programlisting> <programlisting>
{stdenv, fetchFromGitHub, buildRebar3, ibrowse, jsx, erlware_commons }: { stdenv, fetchFromGitHub, buildRebar3, ibrowse, jsx, erlware_commons }:
buildRebar3 rec { buildRebar3 rec {
name = "hex2nix"; name = "hex2nix";
version = "0.0.1"; version = "0.0.1";
src = fetchFromGitHub { src = fetchFromGitHub {
owner = "ericbmerritt"; owner = "ericbmerritt";
repo = "hex2nix"; repo = "hex2nix";
rev = "${version}"; rev = "${version}";
sha256 = "1w7xjidz1l5yjmhlplfx7kphmnpvqm67w99hd2m7kdixwdxq0zqg"; sha256 = "1w7xjidz1l5yjmhlplfx7kphmnpvqm67w99hd2m7kdixwdxq0zqg";
}; };
beamDeps = [ ibrowse jsx erlware_commons ]; beamDeps = [ ibrowse jsx erlware_commons ];
} }
</programlisting> </programlisting>
<para> <para>
This derivation is callable with Such derivations are callable with
<literal>beam.packages.erlang.callPackage</literal> (see above). If you <literal>beam.packages.erlang.callPackage</literal> (see <xref
want to call this package using normal <literal>callPackage</literal>, linkend="erlang-call-package"/>). To call this package using the normal
you should refer to dependency packages via <literal>callPackage</literal>, refer to dependency packages via
<literal>beamPackages</literal>, e.g. <literal>beamPackages</literal>, e.g.
<literal>beamPackages.ibrowse</literal>. <literal>beamPackages.ibrowse</literal>.
</para> </para>
<para> <para>
The only visible difference between this derivation and Notably, <literal>buildRebar3</literal> includes
something like <literal>stdenv.mkDerivation</literal> is that we <literal>beamDeps</literal>, while
have added <literal>beamDeps</literal> to the derivation. If <literal>stdenv.mkDerivation</literal> does not. BEAM dependencies added
you add your Beam dependencies here they will be correctly there will be correctly handled by the system.
handled by the system.
</para> </para>
<para> <para>
If your package needs to compile native code via Rebar's port If a package needs to compile native code via Rebar3's port compilation
compilation mechenism. You should add <literal>compilePort = mechanism, add <literal>compilePort = true;</literal> to the derivation.
true;</literal> to the derivation.
</para> </para>
</section> </section>
<section xml:id="erlang-mk-packages"> <section xml:id="erlang-mk-packages">
<title>Erlang.mk Packages</title> <title>Erlang.mk Packages</title>
<para> <para>
Erlang.mk functions almost identically to Rebar. The only real Erlang.mk functions similarly to Rebar3, except we use
difference is that <literal>buildErlangMk</literal> is called <literal>buildErlangMk</literal> instead of
instead of <literal>buildRebar3</literal> <literal>buildRebar3</literal>.
</para> </para>
<programlisting> <programlisting>
{ buildErlangMk, fetchHex, cowlib, ranch }: { buildErlangMk, fetchHex, cowlib, ranch }:
buildErlangMk {
name = "cowboy";
version = "1.0.4";
src = fetchHex {
pkg = "cowboy";
version = "1.0.4";
sha256 =
"6a0edee96885fae3a8dd0ac1f333538a42e807db638a9453064ccfdaa6b9fdac";
};
beamDeps = [ cowlib ranch ];
meta = { buildErlangMk {
description = ''Small, fast, modular HTTP server written in name = "cowboy";
Erlang.''; version = "1.0.4";
license = stdenv.lib.licenses.isc;
homepage = "https://github.com/ninenines/cowboy"; src = fetchHex {
}; pkg = "cowboy";
version = "1.0.4";
sha256 = "6a0edee96885fae3a8dd0ac1f333538a42e807db638a9453064ccfdaa6b9fdac";
};
beamDeps = [ cowlib ranch ];
meta = {
description = ''
Small, fast, modular HTTP server written in Erlang
'';
license = stdenv.lib.licenses.isc;
homepage = https://github.com/ninenines/cowboy;
};
} }
</programlisting> </programlisting>
</section> </section>
<section xml:id="mix-packages"> <section xml:id="mix-packages">
<title>Mix Packages</title> <title>Mix Packages</title>
<para> <para>
Mix functions almost identically to Rebar. The only real Mix functions similarly to Rebar3, except we use
difference is that <literal>buildMix</literal> is called <literal>buildMix</literal> instead of <literal>buildRebar3</literal>.
instead of <literal>buildRebar3</literal>
</para> </para>
<programlisting> <programlisting>
{ buildMix, fetchHex, plug, absinthe }: { buildMix, fetchHex, plug, absinthe }:
buildMix { buildMix {
name = "absinthe_plug"; name = "absinthe_plug";
version = "1.0.0"; version = "1.0.0";
src = fetchHex { src = fetchHex {
pkg = "absinthe_plug"; pkg = "absinthe_plug";
version = "1.0.0"; version = "1.0.0";
sha256 = sha256 = "08459823fe1fd4f0325a8bf0c937a4520583a5a26d73b193040ab30a1dfc0b33";
"08459823fe1fd4f0325a8bf0c937a4520583a5a26d73b193040ab30a1dfc0b33";
}; };
beamDeps = [ plug absinthe ];
beamDeps = [ plug absinthe ];
meta = { meta = {
description = ''A plug for Absinthe, an experimental GraphQL description = ''
toolkit''; A plug for Absinthe, an experimental GraphQL toolkit
'';
license = stdenv.lib.licenses.bsd3; license = stdenv.lib.licenses.bsd3;
homepage = "https://github.com/CargoSense/absinthe_plug"; homepage = https://github.com/CargoSense/absinthe_plug;
}; };
} }
</programlisting> </programlisting>
<para> <para>
Alternatively one can use <literal>buildHex</literal> as a shortcut for the above: Alternatively, we can use <literal>buildHex</literal> as a shortcut:
</para> </para>
<programlisting> <programlisting>
{ buildHex, buildMix, plug, absinthe }: { buildHex, buildMix, plug, absinthe }:
buildHex { buildHex {
name = "absinthe_plug"; name = "absinthe_plug";
version = "1.0.0"; version = "1.0.0";
sha256 =
"08459823fe1fd4f0325a8bf0c937a4520583a5a26d73b193040ab30a1dfc0b33"; sha256 = "08459823fe1fd4f0325a8bf0c937a4520583a5a26d73b193040ab30a1dfc0b33";
builder = buildMix; builder = buildMix;
beamDeps = [ plug absinthe];
beamDeps = [ plug absinthe ];
meta = { meta = {
description = ''A plug for Absinthe, an experimental GraphQL description = ''
toolkit''; A plug for Absinthe, an experimental GraphQL toolkit
'';
license = stdenv.lib.licenses.bsd3; license = stdenv.lib.licenses.bsd3;
homepage = "https://github.com/CargoSense/absinthe_plug"; homepage = https://github.com/CargoSense/absinthe_plug;
}; };
} }
</programlisting> </programlisting>
@ -265,18 +282,18 @@ $ nix-env -f &quot;&lt;nixpkgs&gt;&quot; -iA beamPackages.ibrowse
</section> </section>
</section> </section>
<section xml:id="how-to-develop"> <section xml:id="how-to-develop">
<title>How to develop</title> <title>How to Develop</title>
<section xml:id="accessing-an-environment"> <section xml:id="accessing-an-environment">
<title>Accessing an Environment</title> <title>Accessing an Environment</title>
<para> <para>
Often, all you want to do is be able to access a valid Often, we simply want to access a valid environment that contains a
environment that contains a specific package and its specific package and its dependencies. We can accomplish that with the
dependencies. we can do that with the <literal>env</literal> <literal>env</literal> attribute of a derivation. For example, let's say
part of a derivation. For example, lets say we want to access an we want to access an Erlang REPL with <literal>ibrowse</literal> loaded
erlang repl with ibrowse loaded up. We could do the following. up. We could do the following:
</para> </para>
<programlisting> <programlisting>
~/w/nixpkgs nix-shell -A beamPackages.ibrowse.env --run "erl" $ nix-shell -A beamPackages.ibrowse.env --run "erl"
Erlang/OTP 18 [erts-7.0] [source] [64-bit] [smp:4:4] [async-threads:10] [hipe] [kernel-poll:false] Erlang/OTP 18 [erts-7.0] [source] [64-bit] [smp:4:4] [async-threads:10] [hipe] [kernel-poll:false]
Eshell V7.0 (abort with ^G) Eshell V7.0 (abort with ^G)
@ -317,20 +334,19 @@ $ nix-env -f &quot;&lt;nixpkgs&gt;&quot; -iA beamPackages.ibrowse
2> 2>
</programlisting> </programlisting>
<para> <para>
Notice the <literal>-A beamPackages.ibrowse.env</literal>.That Notice the <literal>-A beamPackages.ibrowse.env</literal>. That is the key
is the key to this functionality. to this functionality.
</para> </para>
</section> </section>
<section xml:id="creating-a-shell"> <section xml:id="creating-a-shell">
<title>Creating a Shell</title> <title>Creating a Shell</title>
<para> <para>
Getting access to an environment often isn't enough to do real Getting access to an environment often isn't enough to do real
development. Many times we need to create a development. Usually, we need to create a <literal>shell.nix</literal>
<literal>shell.nix</literal> file and do our development inside file and do our development inside of the environment specified therein.
of the environment specified by that file. This file looks a lot This file looks a lot like the packaging described above, except that
like the packaging described above. The main difference is that <literal>src</literal> points to the project root and we call the package
<literal>src</literal> points to project root and we call the directly.
package directly.
</para> </para>
<programlisting> <programlisting>
{ pkgs ? import &quot;&lt;nixpkgs&quot;&gt; {} }: { pkgs ? import &quot;&lt;nixpkgs&quot;&gt; {} }:
@ -349,13 +365,14 @@ let
drv = beamPackages.callPackage f {}; drv = beamPackages.callPackage f {};
in in
drv
drv
</programlisting> </programlisting>
<section xml:id="building-in-a-shell"> <section xml:id="building-in-a-shell">
<title>Building in a shell (for mix projects)</title> <title>Building in a Shell (for Mix Projects)</title>
<para> <para>
We can leverage the support of the Derivation, regardless of We can leverage the support of the derivation, irrespective of the build
which build Derivation is called by calling the commands themselves. derivation, by calling the commands themselves.
</para> </para>
<programlisting> <programlisting>
# ============================================================================= # =============================================================================
@ -415,42 +432,43 @@ analyze: build plt
</programlisting> </programlisting>
<para> <para>
If you add the <literal>shell.nix</literal> as described and Using a <literal>shell.nix</literal> as described (see <xref
user rebar as follows things should simply work. Aside from the linkend="creating-a-shell"/>) should just work. Aside from
<literal>test</literal>, <literal>plt</literal>, and <literal>test</literal>, <literal>plt</literal>, and
<literal>analyze</literal> the talks work just fine for all of <literal>analyze</literal>, the Make targets work just fine for all of the
the build Derivations. build derivations.
</para> </para>
</section> </section>
</section> </section>
</section> </section>
<section xml:id="generating-packages-from-hex-with-hex2nix"> <section xml:id="generating-packages-from-hex-with-hex2nix">
<title>Generating Packages from Hex with Hex2Nix</title> <title>Generating Packages from Hex with <literal>hex2nix</literal></title>
<para> <para>
Updating the Hex packages requires the use of the Updating the <link xlink:href="https://hex.pm">Hex</link> package set
<literal>hex2nix</literal> tool. Given the path to the Erlang requires <link
modules (usually xlink:href="https://github.com/erlang-nix/hex2nix">hex2nix</link>. Given the
<literal>pkgs/development/erlang-modules</literal>). It will path to the Erlang modules (usually
dump a file called <literal>pkgs/development/erlang-modules</literal>), it will dump a file
<literal>hex-packages.nix</literal>. That file will contain all called <literal>hex-packages.nix</literal>, containing all the packages that
the packages that use a recognized build system in Hex. However, use a recognized build system in <link
it can't know whether or not all those packages are buildable. xlink:href="https://hex.pm">Hex</link>. It can't be determined, however,
whether every package is buildable.
</para> </para>
<para> <para>
To make life easier for our users, it makes good sense to go To make life easier for our users, try to build every <link
ahead and attempt to build all those packages and remove the xlink:href="https://hex.pm">Hex</link> package and remove those that fail.
ones that don't build. To do that, simply run the command (in To do that, simply run the following command in the root of your
the root of your <literal>nixpkgs</literal> repository). that follows. <literal>nixpkgs</literal> repository:
</para> </para>
<programlisting> <programlisting>
$ nix-build -A beamPackages $ nix-build -A beamPackages
</programlisting> </programlisting>
<para> <para>
That will build every package in That will attempt to build every package in
<literal>beamPackages</literal>. Then you can go through and <literal>beamPackages</literal>. Then manually remove those that fail.
manually remove the ones that fail. Hopefully, someone will Hopefully, someone will improve <link
improve <literal>hex2nix</literal> in the future to automate xlink:href="https://github.com/erlang-nix/hex2nix">hex2nix</link> in the
that. future to automate the process.
</para> </para>
</section> </section>
</section> </section>