.. _lief_rust_bindings:

:fa:`brands fa-rust` Rust
======================================

.. note::

  The API is documented here |lief-rust-doc| and the nightly doc is
  here: |lief-rust-doc-nightly|.

.. code-block:: toml

  [package]
  name    = "my-awesome-project"
  version = "0.0.1"
  edition = "2021"

  [dependencies]
  lief = { git = "https://github.com/lief-project/LIEF", branch = "main" }


.. warning::

   LIEF rust bindings are not on ``docs.rs`` because of network restrictions:
   https://github.com/rust-lang/docs.rs/issues/2563


Precompiled FFI Bindings
~~~~~~~~~~~~~~~~~~~~~~~~

LIEF's Rust bindings are split in two parts:

1. ``lief``: the high-level-rust-idiomatic API
2. ``lief-ffi``: the low-level FFI API generated by `autocxx <https://github.com/google/autocxx>`_

It turns out that the ``lief-ffi`` package can take some time to be compiled
(around 1 or 2 minutes) **but** most of this time is spent for compiling
auto-generated C++ code (generated by `cxx.rs <https://cxx.rs/>`_).

Similarly the `.rs` file generated by autocxx does not need to be regenerated
every time. For a given tag or commit those files can be pre-compiled or
pre-generated.

To avoid waiting on tasks that can be pre-computed, LIEF pre-compiles these elements
and download them either from Github (for release) or a S3 bucket for nightly
builds.


.. _lief-rust-precompiled:

``LIEF_RUST_PRECOMPILED``
--------------------------

If one needs to avoid downloading these pre-compiled files, you can set
``LIEF_RUST_PRECOMPILED`` to point to the directory that contains these files:

.. code-block:: text

  /home/romain/out
  ├── lib
  │   ├── libLIEF.a
  │   └── liblief-sys.a
  └── rs
      └── autocxx-autocxx_ffi-gen.rs

  3 directories, 3 files

  LIEF_RUST_PRECOMPILED=/home/romain/out cargo build [...]

This variable can also be used while building with in **offline** mode (e.g.
``cargo --offline``).

As of now, the following targets are supported with pre-compilation:

+---------------------------------+--------------------------------------------------------+
| Target                          | Description                                            |
+=================================+========================================================+
| ``x86_64-unknown-linux-gnu``    | Regular Linux x86-64 (Ubuntu 19.10, Debian 10, ...)    |
+---------------------------------+--------------------------------------------------------+
| ``i686-unknown-linux-gnu``      | Regular Linux i686 (Ubuntu 19.10, Debian 10, ...)      |
+---------------------------------+--------------------------------------------------------+
| ``x86_64-unknown-linux-musl``   | Musl target that allows full static build              |
+---------------------------------+--------------------------------------------------------+
| ``i686-unknown-linux-musl``     | Linux i686 with Musl                                   |
+---------------------------------+--------------------------------------------------------+
| ``aarch64-unknown-linux-gnu``   | Linux aarch64 (Debian 12+)                             |
+---------------------------------+--------------------------------------------------------+
| ``aarch64-unknown-linux-musl``  | Linux aarch64 with Musl                                |
+---------------------------------+--------------------------------------------------------+
| ``x86_64-apple-darwin``         | macOS 11+ x86-64                                       |
+---------------------------------+--------------------------------------------------------+
| ``aarch64-apple-darwin``        | macOS 11+ arm64 (Apple Silicon)                        |
+---------------------------------+--------------------------------------------------------+
| ``aarch64-apple-ios``           | iOS 12+                                                |
+---------------------------------+--------------------------------------------------------+
| ``x86_64-pc-windows-msvc[MT]``  | Regular Windows x86-64 (static UCRT runtime)           |
+---------------------------------+--------------------------------------------------------+
| ``x86_64-pc-windows-msvc[MD]``  | Regular Windows x86-64 (dynamic UCRT runtime ``.dll``) |
+---------------------------------+--------------------------------------------------------+
| ``aarch64-pc-windows-msvc[MT]`` | Regular Windows arm64 (static UCRT runtime)            |
+---------------------------------+--------------------------------------------------------+
| ``aarch64-pc-windows-msvc[MD]`` | Regular Windows arm64 (dynamic UCRT runtime ``.dll``)  |
+---------------------------------+--------------------------------------------------------+

Precompilation
--------------

The assets of the pre-compiled output are:

1. LIEF static library: ``LIEF.a, LIEF.lib``
2. ``liefsys.{a, lib}``: C++ part of cxx.rs
3. ``autocxx-autocxx_ffi-gen.rs`` bridge generated by autocxx.

LIEF static library must be compiled as described in the :ref:`compilation_ref`
section using the CMake option: ``-DLIEF_RUST_API=ON``.

``liefsys.{a, lib}`` and ``autocxx-autocxx_ffi-gen.rs`` can be generated using
the ``lief-ffigen`` modules:

.. code-block:: bash

   $ cd api/rust/cargo
   $ cargo build --release -p lief-ffigen
   $ ./target/release/lief-ffigen       \
      --output-dir ./out-gen            \
      --lief-dir <path-to-lief-sdk>     \
      --target x86_64-unknown-linux-gnu \
      --host x86_64-unknown-linux-gnu

``--lief-dir`` must point to the **install** location of the SDK while
``out-gen/`` contains the generated artifacts.
