= lrs :toc: macro ifdef::env-github[:build_link: link:Documentation/adoc/building_and_using.adoc] ifndef::env-github[:build_link: link:Documentation/html/building_and_using.html] :logo: assets/logo.png :source-language: rust
image::{logo}[logo,float="left"]
lrs is a highly experimental, linux-only standard library for the rustc compiler. It does not use any parts of the standard library that is part of the rust distribution.
'''
toc::[]
== Features
Since lrs is based on the rust compiler, it shares many features with rust (e.g., lifetimes, borrow checking, integer overflow checking, etc.) But rustc allows us to make significant changes to the language as long as we don't use Mozilla's standard library. This section lists some of the differences between rust and lrs and other features of lrs.
NOTE: In this section we'll compare programs compiled against lrs and programs compiled against the "standard" standard library that comes with the rust distribution. To make things simpler, we will call programs that use lrs "lrs programs" and programs that use Mozilla's standard library "rust programs". It should be clear from the context what is meant.
=== No unwinding
Unwinding and the panic
macro have been removed from lrs. This means that
error handling works via return values or--in the case of unrecoverable
errors--process termination. This has the following advantages:
+
If g
cannot unwind, then this function can be optimized by removing both
swap
calls. But if g
can unwind, then the swap
calls must stay in place
since destructors called during unwinding might access a
and b
.
+
This is a naive implementation of a non-allocating push
method on Vec<T>
.
The code is incorrect because the length of the vector is increased before the
return value of g
has been written to it. If g
unwinds, the destructor of
Vec<T>
will access the invalid value at a[len]
, which is likely undefined
behavior. This problem does not exist in lrs. See
https://github.com/rust-lang/rfcs/pull/1236[this] (long) thread for a discussion
of exception safety in rust.
=== Small executables
:calc_url: http://is.gd/Ep2KIi
lrs programs usually compile down to executable with a size comparable to that of equivalent C programs.
In the table below, lrs + musl
denotes programs that were statically compiled
against musl, and lrs - libc
denotes programs that don't depend on a libc.
|=== |Name |lrs + glibc |lrs + musl |lrs - libc |C (glibc) |rust
|Hello World |7.0KB |4.0KB |1.3KB |6.5KB |436KB
|http://pubs.opengroup.org/onlinepubs/9699919799/utilities/test.html[test] |18KB |21KB |n/a |35KB |462KB
|{calc_url}[A calculator] |9.2KB |5.8KB |n/a |n/a |437KB |===
NOTE: All programs were compiled with the -O -C lto
flags.
=== Direct system calls
lrs interacts with the kernel directly through system calls. That is, lrs does not depend on a libc for 99% of the work. This allows us to use kernel features that do not (yet) have an equivalent libc function and removes an unnecessary layer of abstraction.
It is, in fact, possible to use lrs without a libc. However, this mode is not yet fully developed and mostly useful for testing cross-compilation.
=== glibc and musl support
Due to what was discussed in the previous section, the lrs/libc interface is so small that it's almost trivial to make lrs work with different libc versions. Currently, lrs is known to work with glibc and musl.
=== Portable
Even though lrs avoids the libc abstraction layer, porting lrs to new linux platforms is easy. This is due to the way the platform dependent parts of lrs mirror the equivalent parts in the linux kernel source code. lrs has already been ported to x86_64, x32, i686, arm, and arm64.
WARNING: lrs has only been tested on x86_64.
=== Per-object allocators
Many allocating structures in lrs (such as vectors, strings, hashmaps) come with an optional allocator argument. The following allocators are part of lrs:
Libc:: Uses malloc
and friends from the libc.
JeMalloc:: Uses jemalloc's non-standard API with sized allocations and
deallocations for higher efficiency.
NoMem:: This dummy-allocator always reports an out-of-memory condition.
Bda:: The brain-dead allocator only allocates in multiples of the page size.
This is very useful for applications that have few allocations whose size is
unknown at compile time and can rapidly increase.
Careful note should be taken of the NoMem allocator. Consider the following code:
The vector is backed by the NoMem allocator and the buffer declared in the
first line. It will never dynamically allocate any memory. If we were to write
more bytes than can be stored in the buffer, write!
would return that the
vector is out of memory. Using this feature, lrs often allows the user to avoid
allocations in cases where doing so would be rather inconvenient in rust.
Nevertheless, it's easy to use lrs collections in the common case where the user
does not care about dynamic allocations. This is because all collections declare
a default allocator so that Vec<T>
is the same as Vec<T, Heap>
. This default
allocator can be chosen at compile time.
=== No allocations in the 99.9% case
All APIs are designed to not allocate memory in the common case. For example,
File::open
will only allocate memory if the requested path is longer than
PATH_MAX
. In those cases the API uses the so called fallback allocator. If
the user does not want memory to be allocated in those exceptional situations,
they can disable said allocator at compile time.
=== Fast compilation
lrs is split into many small crates and provides incremental compilation independent of the rustc compiler. Compiling a single crate during development often takes less than a second. To this end, lrs comes with its own build system--lrs_build--which ensures that only the minimal amount of work is done by the compiler.
Furthermore, even complete builds do not take very long. On this (old) machine, a complete build takes 28 seconds without optimization and 41 seconds with optimization.
=== Extensive Linux API coverage
:syscalls: http://lrs-lang.github.io/pages/doc/lrs::syscall.html :file: http://lrs-lang.github.io/pages/doc/lrs::file::File.html
lrs already wraps many of the commonly used linux system calls. See {syscalls}[this] page of the lrs documentation for a list of mostly safe system call wrappers. But note that most of these functions have much nicer wrappers in other parts of the library.
For example, the {file}[File] struct exposes many syscalls that modify files.
=== Easy to use
Even though lrs programs don't use the standard library that comes with the compiler, the user doesn't have to bother with annoying annotations. For example, the following lrs program can be compiled as written:
use std::tty::{is_a_tty};
This is because lrs comes with its own compiler driver that takes care of injecting lrs instead of rust.
== Building and Using
Please see the detailed {build_link}[Building and Using] guide.
== Examples
:lrs_build: https://github.com/lrs-lang/build :examples: https://github.com/lrs-lang/examples
See {lrs_build}[lrs_build] for an example of an lrs program. Many more examples can be found in the {examples}[examples] repo. But note that those examples have not yet been organized and documented properly.
== Documentation
:doc: https://github.com/lrs-lang/doc :docs: http://lrs-lang.github.io/pages/doc/lrs.html
Documentation regarding lrs in general can be found in the link:Documentation[] directory.
Documentation of the library is generated via {doc}[lrs_doc]. An outdated version of said documentation can be found {docs}[here].
== License
:license: link:LICENSE
The whole library is licensed under the {license}[MPL 2.0] license which allows static linking into proprietary programs. It is copy-left on a file-by-file basis: Changes to files licensed under the MPL 2.0 have to be distributed under the same license. It also allows the code to be freely used under several (L)GPL licenses.
Some other parts--such as the compiler plugin and the compiler driver--are licensed under the MIT license.
== Logo
:simple-linux-logo: http://dablim.deviantart.com/art/Simple-Linux-Logo-336131202 :dablim: http://dablim.deviantart.com/ :ccby: http://creativecommons.org/licenses/by-sa/4.0/
The lrs link:{logo}[logo] shows a penguin in a sprocket.
It is based on {simple-linux-logo}[Simple Linux Logo] by {dablim}[Dablim] and is licensed under {ccby}[CC BY-SA 4.0].