glfs/general/prog/rust.xml
Pierre Labastie f16e76c635 Fix index entry for /etc/ld.so.conf in rust page
git-svn-id: svn://svn.linuxfromscratch.org/BLFS/trunk/BOOK@23995 af4574ff-66df-0310-9fd7-8a98e5e911e0
2020-12-17 13:53:56 +00:00

760 lines
27 KiB
XML

<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE sect1 PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
"http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
<!ENTITY % general-entities SYSTEM "../../general.ent">
%general-entities;
<!ENTITY rust-download-http "https://static.rust-lang.org/dist/rustc-&rust-version;-src.tar.gz">
<!ENTITY rust-download-ftp " ">
<!ENTITY rust-md5sum "a460bed79b92f6a7833ba6e6390ee6ae">
<!ENTITY rust-size "145 MB">
<!-- Gentle Reminder: buildsize is how much the user requires for the real
install, i.e. the source with its DESTDIR *plus* the DESTDIR. You
can 'mkdir /tmp/RUST ; cp -a install/* /tmp/RUST' and then run 'du -sch'
to measure it, or du -sm to look at the size of the build tree before and
after the tests. -->
<!ENTITY rust-buildsize "7.6 GB (369 MB installed) including 294 MB of ~/.cargo files for the user building this. Add 3.3 GB if running the tests">
<!ENTITY rust-time "39 SBU (add 31 SBU for tests, both on a 4-core machine)">
]>
<sect1 id="rust" xreflabel="rustc-&rust-version;">
<?dbhtml filename="rust.html"?>
<sect1info>
<othername>$LastChangedBy$</othername>
<date>$Date$</date>
</sect1info>
<title>Rustc-&rust-version;</title>
<indexterm zone="rust">
<primary sortas="a-rust">Rust</primary>
</indexterm>
<sect2 role="package">
<title>Introduction to Rust</title>
<para>
The <application>Rust</application> programming language is designed
to be a safe, concurrent, practical language.
</para>
<para>
This package is updated on a six-weekly release cycle. Because it is
such a large and slow package to build, is at the moment only required
by a few packages in this book, and particularly because newer versions
tend to break older mozilla packages, the BLFS editors take the view that
it should only be updated when that is necessary (either to fix problems,
or to allow a new version of a package to build).
</para>
<para>
As with many other programming languages, rustc (the rust compiler)
needs a binary from which to bootstrap. It will download a stage0 binary
and many cargo crates (these are actually .tar.gz source archives) at
the start of the build, so you cannot compile it without an internet
connection.
</para>
<para>
These crates will then remain in various forms (cache, directories of
extracted source), in <filename class="directory">~/.cargo</filename> for
ever more. It is common for large <application>rust</application> packages
to use multiple versions of some crates. If you purge the files before
updating this package, very few crates will need to be updated by the
packages in this book which use it (and they will be downloaded as
required). But if you retain an older version as a fallback option and
then use it (when <emphasis>not</emphasis> building in
<filename class="directory">/usr</filename>), it is likely that it will
then have to re-download some crates. For a full download (i.e. starting
with an empty or missing <filename class="directory">~/.cargo</filename>)
downloading the external cargo files for this version only takes a minute
or so on a fast network.
</para>
<note>
<para>
Although BLFS usually installs in <filename
class="directory">/usr</filename>, when you later upgrade to a newer
version of <application>rust</application> the old libraries in <filename
class="directory">/usr/lib/rustlib</filename> will remain, with various
hashes in their names, but will not be usable and will waste space. The
editors recommend placing the files in the <filename
class="directory">/opt</filename> directory. In particular, if you
have reason to rebuild with a modified configuration (e.g. using the
shipped LLVM after building with shared LLVM, or for the
reverse situation) it is possible for the install to leave a broken
<command>cargo</command> program. In such a situation, either remove
the existing installation first, or use a different prefix such as
/opt/rustc-&rust-version;-build2.
</para>
<para>
If you prefer, you can of course change the prefix to <filename
class="directory">/usr</filename> and omit the
<command>ldconfig</command> and the actions to add rustc to the PATH.
</para>
</note>
<para>
The current <application>rustbuild</application> build-system will use
all processors, although it does not scale well and often falls
back to just using one core while waiting for a library to compile.
However it can be mostly limited to a specified number of processors by
a combination of adding the switch <literal>--jobs &lt;N&gt;</literal>
(e.g. '--jobs 4' to limit to 4 processors) on each invocation of
<command>python3 ./x.py</command> <emphasis>and</emphasis> using an
environment variable <envar>CARGO_BUILD_JOBS=&lt;N&gt;</envar>. At the
moment this is not effective when some of the rustc tests are run.
</para>
<para>
The current version of rust's num_cpus crate now recognizes that cgroups
can be used to restrict which processors it is allowed to use. So if your
machine lacks DRAM (typically, less than 2GB DRAM per core) that might be
an alternative to taking CPUs offline.
<phrase revision="sysv">In sysv systems cgroups requires <ulink
url="https://sourceforge.net/projects/libcg/">libcgroup</ulink>.</phrase>
<phrase revision="systemd">That can apparently be achieved by writing
custom unit files.</phrase>
</para>
<para>
At the moment <application>Rust</application> does not provide any
guarantees of a stable ABI.
</para>
<note>
<para>
Rustc defaults to building for ALL supported architectures, using a
shipped copy of LLVM. In BLFS the build is only for the X86
architecture.
If you intend to develop rust crates, this build may not be good
enough for your purposes.
</para>
<para>
The build times of this version when repeated on the same machine are
often reasonably consistent, but as with all compilations using
<command>rustc</command> there can be some very slow outliers.
</para>
<para>
Unusually, a DESTDIR-style method is being used to install this package.
This is because running the install as root not only downloads all of the
cargo files again (to <filename>/root/.cargo</filename>), it then spends
a very long time recompiling. Using this method saves a lot of time, at
the cost of extra disk space.
</para>
</note>
&lfs10_checked;
<bridgehead renderas="sect3">Package Information</bridgehead>
<itemizedlist spacing="compact">
<listitem>
<para>
Download (HTTP): <ulink url="&rust-download-http;"/>
</para>
</listitem>
<listitem>
<para>
Download (FTP): <ulink url="&rust-download-ftp;"/>
</para>
</listitem>
<listitem>
<para>
Download MD5 sum: &rust-md5sum;
</para>
</listitem>
<listitem>
<para>
Download size: &rust-size;
</para>
</listitem>
<listitem>
<para>
Estimated disk space required: &rust-buildsize;
</para>
</listitem>
<listitem>
<para>
Estimated build time: &rust-time;
</para>
</listitem>
</itemizedlist>
<!--<bridgehead renderas="sect3">Additional Downloads</bridgehead>
<itemizedlist spacing="compact">
<listitem>
<para>
Required patch:
<ulink url="&patch-root;/rustc-&rust-version;-llvm9_fixes-1.patch"/>
</para>
</listitem>
</itemizedlist>-->
<bridgehead renderas="sect3">Rust Dependencies</bridgehead>
<bridgehead renderas="sect4">Required</bridgehead>
<para role="required">
<xref linkend="curl"/>,
<xref linkend="cmake"/>, and
<xref linkend="libssh2"/>
</para>
<bridgehead renderas="sect4">Recommended</bridgehead>
<para role="recommended">
<package>clang</package> from <xref linkend="llvm"/>
(built with -DLLVM_LINK_LLVM_DYLIB=ON so that rust can link to
system LLVM instead of building its shipped version)
If using an older version, see the config.toml file below re
using the shipped llvm, because of rust issue 69225.
</para>
<bridgehead renderas="sect4">Optional</bridgehead>
<para role="optional">
<xref linkend="gdb"/> (used by the testsuite if it is present)
</para>
<para condition="html" role="usernotes">
User Notes: <ulink url="&blfs-wiki;/rust"/>
</para>
</sect2>
<sect2 role="installation">
<title>Installation of Rust</title>
<para>
To install into the
<filename class="directory">/opt</filename> directory, remove the symlink
and create a new directory (i.e. with a different name if trying a
modified build).
As the <systemitem class="username">root</systemitem>
user:
</para>
<screen role="root"><userinput>mkdir /opt/rustc-&rust-version; &amp;&amp;
ln -svfin rustc-&rust-version; /opt/rustc</userinput></screen>
<note>
<para>
If multiple versions of <application>Rust</application> are installed
in <filename class="directory">/opt</filename>, changing to another
version only requires changing the <filename> /opt/rustc</filename>
symbolic link and then running <command>ldconfig</command>.
</para>
</note>
<para>
Create a suitable <filename>config.toml</filename> file which will
configure the build.
</para>
<screen><userinput>cat &lt;&lt; EOF &gt; config.toml
<literal># see config.toml.example for more possible options
# See the 8.4 book for an example using shipped LLVM
# e.g. if not installing clang, or using a version before 10.0
[llvm]
# by default, rust will build for a myriad of architectures
targets = "X86"
# When using system llvm prefer shared libraries
link-shared = true
[build]
# omit docs to save time and space (default is to build them)
docs = false
# install cargo as well as rust
extended = true
[install]
prefix = "/opt/rustc-&rust-version;"
docdir = "share/doc/rustc-&rust-version;"
[rust]
channel = "stable"
rpath = false
# BLFS does not install the FileCheck executable from llvm,
# so disable codegen tests
codegen-tests = false
[target.x86_64-unknown-linux-gnu]
# NB the output of llvm-config (i.e. help options) may be
# dumped to the screen when config.toml is parsed.
llvm-config = "/usr/bin/llvm-config"
[target.i686-unknown-linux-gnu]
# NB the output of llvm-config (i.e. help options) may be
# dumped to the screen when config.toml is parsed.
llvm-config = "/usr/bin/llvm-config"
</literal>
EOF</userinput></screen>
<!--<para>
Adapt rustc to allow it to build and function with the changes in LLVM-9:
</para>
<screen><userinput remap="pre">patch -Np1 -i ../rustc-&rust-version;-llvm9_fixes-1.patch</userinput></screen>-->
<para>
Compile <application>Rust</application> by running the following
commands:
</para>
<screen><userinput>export RUSTFLAGS="$RUSTFLAGS -C link-args=-lffi" &amp;&amp;
python3 ./x.py build --exclude src/tools/miri</userinput></screen>
<note>
<para>
The testsuite will generate some messages in the
<phrase revision="sysv">system log</phrase>
<phrase revision="systemd">systemd journal</phrase>
for traps on invalid opcodes, and for segmentation faults.
In themselves these are nothing to worry about, just a way for the
test to be terminated.
</para>
</note>
<para>
To run the tests issue <command>python3 ./x.py test --verbose
--no-fail-fast | tee rustc-testlog</command>: as with the build, that
will use all available CPUs.
</para>
<para>
At a minimum, two tests (run-make-fulldeps/long-linker-command-lines
and run-make-fulldeps/sysroot-crates-are-unstable) may fail.
If a version of <command>gdb</command> which was released after this
version of rust is used, such as <xref linkend="gdb"/>, four more failures
(debuginfo/extern-c-fn.rs, debuginfo/generator-objects.rs,
debuginfo/issue-57822.rs, debuginfo/pretty-huge-vec.rs) can be expected.
</para>
<para>
As with all large testsuites, other tests might fail on some machines -
if the number of additional failures is in the single digits,
check the log for 'FAILED' and review lines above that, particularly the
'stderr:' lines. Any mention of
SIGSEGV or signal 11 in a failing test is a cause for concern.
</para>
<para>
If you get any <emphasis>other</emphasis> failing test which reports an
issue number then you should search for that issue. For example, when
rustc &gt;= 1.41.1 was built with a version of sysllvm before 10.0 the test
for issue 69225 failed <ulink
url="https://github.com/rust-lang/rust/issues/69225"/> and that should be
regarded as a critical failure (they released 1.41.1 because of it).
Most other failures will not be critical.
</para>
<para>
Therefore, you should determine the number of failures.
</para>
<!--
The total number
of tests varies depending on which dependencies are present, e.g. more
will be run if <command>gdb</command> is available. If you wish, the
total number which were considered can be found if you run:
</para>
<screen remap="test"><userinput>egrep 'running [[:digit:]]+ test' rustc-testlog | awk '{ sum += $2 } END { print sum }'</userinput></screen>-->
<para>
The number of tests which failed can be found by running:
</para>
<screen remap="test"><userinput>grep '^test result:' rustc-testlog | awk '{ sum += $6 } END { print sum }'</userinput></screen>
<para>
And similarly if you care about how many tests passed use $4, for those
which were ignored (i.e. skipped) use $8 (and $10 for 'measured', $12 for
'filtered out' but both are probably zero).
</para>
<para>
Still as your normal user, do a DESTDIR install:
</para>
<screen><userinput>export LIBSSH2_SYS_USE_PKG_CONFIG=1 &amp;&amp;
DESTDIR=${PWD}/install python3 ./x.py install &amp;&amp;
unset LIBSSH2_SYS_USE_PKG_CONFIG</userinput></screen>
<para>
Now, as the <systemitem class="username">root</systemitem> user
install the files from the DESTDIR:
</para>
<screen role="root"><userinput>chown -R root:root install &amp;&amp;
cp -a install/* /</userinput></screen>
</sect2>
<sect2 role="commands">
<title>Command Explanations</title>
<para>
<command>ln -svfn rustc-&rust-version; /opt/rustc</command>: if this is
not the first use of the <filename class="directory">/opt/rustc</filename>
symlink, overwrite it by forcing, and use the '-n' flag to avoid getting
confusing results from e.g. <command>ls -l</command>.
</para>
<para>
<command>targets = "X86"</command>: this avoids building all the available
linux cross-compilers (Aarch64, MIPS, PowerPC, SystemZ, etc). Unfortunately,
rust insists on installing source files for these below
<filename class="directory">/opt/rustc/lib/src</filename>.
</para>
<para>
<command>extended = true</command>: this installs Cargo alongside Rust.
</para>
<para>
<command>channel = "stable"</command>: this ensures only stable features
can be used, the default in <filename>config.toml</filename> is to use
development features, which is not appropriate for a released version.
</para>
<para>
<command>rpath = false</command>: by default, <command>rust</command> can
be run from where it was built, without being installed. That adds DT_RPATH
entries to all of the ELF files, which produces very messy output from
<command>ldd</command>, showing the libraries in the place they were built,
even if they have been deleted from there after the install.
</para>
<!-- comment while using shipped LLVM -->
<para>
<command>[target.x86_64-unknown-linux-gnu]</command>: the syntax of
<filename>config.toml</filename> requires an <literal>llvm-config</literal>
entry for each target for which system-llvm is to be used. Change the target
to <literal>[target.i686-unknown-linux-gnu]</literal> if you are building
on 32-bit x86. This whole section may be omitted if you wish to build
against the shipped llvm, or do not have clang, but the resulting build will
be larger and take longer.
</para>
<para>
<command>export RUSTFLAGS="$RUSTFLAGS -C link-args=-lffi"</command>:
This adds a link to libffi to any RUSTFLAGS you may already be passing
to the build. On some systems, linking fails to include libffi unless
this is used. The reason why this is needed is not clear.
</para>
<para>
<command>--exclude src/tools/miri</command>: For a long time, the miri
crate (an interpreter for the Midlevel Intermediate Representation)
has failed to build on releases. It is optional, but the failure
messages can persuade people that the whole build failed. However,
although it is not built in the main compile, with rustc-1.35.0 it
now got compiled during the install, but it was broken in that version.
<!-- might be unbroken in 1.36.0, if so remove broken from description
of miri below. https://github.com/rust-lang/rust/issues/61830 -->
Omitting it should save a little time.
</para>
<para>
<command>--verbose</command>: this switch can sometimes provide more
information about a test which fails.
</para>
<para>
<command>--no-fail-fast</command>: this switch ensures that the testsuite
will not stop at the first error.
</para>
<para>
<command>export LIBSSH2_SYS_USE_PKG_CONFIG=1</command>: On some systems,
cairo fails to link during the install because it cannot find libssh2.
This seems to fix it, but again the reason why the problem occurs is not
understood.
</para>
<para>
<command>DESTDIR=${PWD}/install python3 ./x.py install</command>: This
effects a DESTDIR-style install in the source tree,creating an <filename
class="directory">install</filename> directory. Note that DESTDIR installs
need an absolute path, passing 'install' will not work.
</para>
<para>
<command>chown -R root:root install</command>: the DESTDIR install
was run by a regular user, who owns the files. For security, change their
owner before doing a simple copy to install them.
</para>
</sect2>
<sect2 role="configuration">
<title>Configuring Rust</title>
<sect3 id="rustc-config">
<title>Configuration Information</title>
<para>
If you installed <application>rustc</application> in
<filename class="directory">/opt</filename>, you need to update the
following configuration files so that <application>rustc</application>
is correctly found by other packages and system processes.
</para>
<para>
As the <systemitem class="username">root</systemitem> user, update
the <filename>/etc/ld.so.conf</filename> file and the dynamic linker's
run-time cache file:
</para>
<screen role="root"><userinput>cat &gt;&gt; /etc/ld.so.conf &lt;&lt; EOF
<literal># Begin rustc addition
/opt/rustc/lib
# End rustc addition</literal>
EOF
ldconfig</userinput></screen>
<indexterm zone="rust rustc-config">
<primary sortas="e-etc-ld.so.conf">/etc/ld.so.conf</primary>
</indexterm>
<para>
As the <systemitem class="username">root</systemitem> user, create
the <filename>/etc/profile.d/rustc.sh</filename> file:
</para>
<screen role="root"><userinput>cat &gt; /etc/profile.d/rustc.sh &lt;&lt; "EOF"
<literal># Begin /etc/profile.d/rustc.sh
pathprepend /opt/rustc/bin PATH
# End /etc/profile.d/rustc.sh</literal>
EOF</userinput></screen>
<para>
Immediately after installation, update the current PATH
for your current shell as a normal user:
</para>
<screen><userinput>source /etc/profile.d/rustc.sh</userinput></screen>
</sect3>
</sect2>
<sect2 role="content">
<title>Contents</title>
<segmentedlist>
<segtitle>Installed Programs</segtitle>
<segtitle>Installed Libraries</segtitle>
<segtitle>Installed Directories</segtitle>
<seglistitem>
<seg>
cargo-clippy, cargo-fmt, cargo-miri, cargo, clippy-driver, miri, rls, rust-gdb, rust-gdbgui, rust-lldb, rustc, rustdoc, rustfmt.
</seg>
<seg>
Many lib*&lt;16-byte-hash&gt;.so libraries.
</seg>
<seg>
~/.cargo,
/opt/rustc/lib/rustlib,
/opt/rustc/share/doc/rustc-&rust-version;, and
/opt/rustc/share/zsh/site-functions
</seg>
</seglistitem>
</segmentedlist>
<variablelist>
<bridgehead renderas="sect3">Short Descriptions</bridgehead>
<?dbfo list-presentation="list"?>
<?dbhtml list-presentation="table"?>
<varlistentry id="cargo-clippy">
<term><command>cargo-clippy</command></term>
<listitem>
<para>
provides lint checks for a cargo package.
</para>
<indexterm zone="rust cargo-clippy">
<primary sortas="b-cargo-clippy">cargo-clippy</primary>
</indexterm>
</listitem>
</varlistentry>
<varlistentry id="cargo-fmt">
<term><command>cargo-fmt</command></term>
<listitem>
<para>
formats all bin and lib files of the current crate using
rustfmt.
</para>
<indexterm zone="rust cargo-fmt">
<primary sortas="b-cargo-fmt">cargo-fmt</primary>
</indexterm>
</listitem>
</varlistentry>
<varlistentry id="cargo-miri">
<term><command>cargo-miri</command></term>
<listitem>
<para>
<!-- FIXME reword to 'is used by' if Miri installed
AND works enough to report its \-\-help -->
is for use by Miri to interpret bin crates and tests
</para>
<indexterm zone="rust cargo-miri">
<primary sortas="b-cargo-miri">cargo-miri</primary>
</indexterm>
</listitem>
</varlistentry>
<varlistentry id="cargo">
<term><command>cargo</command></term>
<listitem>
<para>
is the Package Manager for Rust.
</para>
<indexterm zone="rust cargo">
<primary sortas="b-cargo">cargo</primary>
</indexterm>
</listitem>
</varlistentry>
<varlistentry id="clippy-driver">
<term><command>clippy-driver</command></term>
<listitem>
<para>
provides lint checks for Rust.
</para>
<indexterm zone="rust clippy-driver">
<primary sortas="b-clippy-driver">clippy-driver</primary>
</indexterm>
</listitem>
</varlistentry>
<varlistentry id="miri">
<term><command>miri</command></term>
<listitem>
<para>
is an interpreter for Rust's mid-level intermediate representation
(MIR). It is broken in this version.
</para>
<indexterm zone="rust miri">
<primary sortas="b-miri">miri</primary>
</indexterm>
</listitem>
</varlistentry>
<varlistentry id="rls">
<term><command>rls</command></term>
<listitem>
<para>
is the Rust Language Server. This can run in the background to
provide IDEs, editors, and other tools with information about Rust
programs.
</para>
<indexterm zone="rust rls">
<primary sortas="b-rls">rls</primary>
</indexterm>
</listitem>
</varlistentry>
<varlistentry id="rust-gdb">
<term><command>rust-gdb</command></term>
<listitem>
<para>
is a wrapper script for gdb, pulling in Python
pretty-printing modules installed in <filename
class="directory">/opt/rustc-&rust-version;/lib/rustlib/etc</filename>.
</para>
<indexterm zone="rust rust-gdb">
<primary sortas="b-rust-gdb">rust-gdb</primary>
</indexterm>
</listitem>
</varlistentry>
<varlistentry id="rust-gdbgui">
<term><command>rust-gdbgui</command></term>
<listitem>
<para>
is a wrapper script for a graphical front end to gdb that runs in a
browser.
</para>
<indexterm zone="rust rust-gdbgui">
<primary sortas="b-rust-gdbgui">rust-gdbgui</primary>
</indexterm>
</listitem>
</varlistentry>
<varlistentry id="rust-lldb">
<term><command>rust-lldb</command></term>
<listitem>
<para>
is a wrapper script for LLDB (the LLVM debugger)
pulling in the Python pretty-printing modules.
</para>
<indexterm zone="rust rust-lldb">
<primary sortas="b-rust-lldb">rust=lldb</primary>
</indexterm>
</listitem>
</varlistentry>
<varlistentry id="rustc">
<term><command>rustc</command></term>
<listitem>
<para>
is the rust compiler.
</para>
<indexterm zone="rust rustc">
<primary sortas="b-rustc">rustc</primary>
</indexterm>
</listitem>
</varlistentry>
<varlistentry id="rustdoc">
<term><command>rustdoc</command></term>
<listitem>
<para>
generates documentation from rust source code.
</para>
<indexterm zone="rust rustdoc">
<primary sortas="b-rustdoc">rustdoc</primary>
</indexterm>
</listitem>
</varlistentry>
<varlistentry id="rustfmt">
<term><command>rustfmt</command></term>
<listitem>
<para>
formats rust code.
</para>
<indexterm zone="rust rustfmt">
<primary sortas="b-rustfmt">rustfmt</primary>
</indexterm>
</listitem>
</varlistentry>
<varlistentry id="libstd">
<term><filename class="libraryfile">libstd-&lt;16-byte-hash&gt;.so</filename></term>
<listitem>
<para>
is the Rust Standard Library, the foundation of portable Rust software.
</para>
<indexterm zone="rust libstd">
<primary sortas="c-libstd">libstd-&lt;16-byte-hash&gt;.so</primary>
</indexterm>
</listitem>
</varlistentry>
</variablelist>
</sect2>
</sect1>