Initial support for declaring static libraries

Currently all symbols are expected to either come from the system
libraries or liblliby.a. This presents two major issues:

- Every Llambda program links the entire runtime and standard library
  which is quite large, particularily the Unicode character database

- This precludes from linking to libraries outside the stdlib once
  generalised libraries are supported

This adds a new NativeFunction bound value. These can be declared using
(define-native-library). Currently only (static-library) and
system-library are supported. system-library is intended to be a
placeholder that refers to the system standard library and lliby core.

(native-function) now takes a mandatory library as its first parameter.
All the existing functions have been switched to use system-library
except for (scheme time) which has experimentally been separated to its
own library as a proof of concept.

The next commits split out the Llambda runtime in to separate static
libraries where possible.
runtime: Split in to separate static libraries

This separates out the runtime in two classes of static libraries:

- llcore contains the bindings, allocator, core support functions,
  utility functions, etc. This is required by all Llambda libraries and
  expected to exist by codegen itself

- Each Scheme library has its own stdlib library: llbase, llread,
  llwrite, llinexact, etc.

At the same time each library's symbols have been re-prefixed with their
corresponding library name. The name "lliby" survives mainly as the name
of the top-level C++ namespace.

As part of this the Unicode Character Database functionality has been
moved to a separate ucd/ directory. StringCell and UnicodeChar have been
generalised to accept character conversion functions passed in to them
instead of calling out the UCD functions. This allows the UCD to become
part of llchar and avoids linking ~80KiB of Unicode data with every
program

The result of this is an over 1/3rd reduction in size for a simple
program using (scheme base) and (scheme write) on x86-64 Linux with a
release build. This also has the side effect of speeding up the
functional tests due to less data being handled by the LLVM toolchain.
runtime: Get rid of std::back_inserter

Using std::back_inserter with utf8::appendChar causes a very large
function to be generated. This is mostly due to the range check required
for appended each byte.

- Have utf8::encodeChar return a custom container instead of
  std::vector. This is quite efficient as we only need 4 bytes for the
  UTF-8 data and another 4 bytes for the length. No dynamic allocations
  are required at all

- Switch StringCell::toConvertedString to use StringCellBuilder. This
  potentially uses more memory but it should use less cycles and makes
  the code more clear.
compiler: Remove -save-temp-obj

This was never used after its initial implementation and requires
maintaining completely separate code path for invoking LLVM.
compiler: Default to -O 2 when run from CLI

Unlike a C/C++ compiler Llambda will generate code that's extremely
inefficient compared to -O 2. This is due to much of the language
being built on top of high level constructs such as self-executing
lambdas.

-O 0 is intended mostly for use within functional tests where it
exercises code paths not normally hit by optimised code. It's not a
reasonable default for the command line compiler to use.