Compilation

To compile LIEF, you need at least the following requirements:

  • C++14 compiler (GCC, Clang, MSVC..)

  • CMake

  • Python >= 3.6 (for the bindings)

To build the documentation:

  • Doxygen (= 1.8.10, the CI uses 1.8.20)

  • Sphinx (with sphinx_rtd_theme module)

  • breathe (>= 4.25.1)

Note

A compilation from scratch with all the options enabled can take ~30 minutes on a regular laptop.

Libraries only (SDK)

$ git clone https://github.com/lief-project/LIEF.git
$ cd LIEF
$ mkdir build
$ cd build
$ cmake -DLIEF_PYTHON_API=off -DCMAKE_BUILD_TYPE=Release ..
$ cmake --build . --target LIB_LIEF --config Release

Warning

On Windows one can choose the CRT to use by setting the LIEF_USE_CRT_<RELEASE;DEBUG;..> variable:

$ cmake -DCMAKE_BUILD_TYPE=Release -DLIEF_USE_CRT_RELEASE=MT ..

For Debug, you should set the CRT to MTd:

$ cmake -DCMAKE_BUILD_TYPE=Debug -DLIEF_USE_CRT_DEBUG=MTd ..
$ cmake --build . --target LIB_LIEF --config Debug

Library and Python bindings

$ git clone https://github.com/lief-project/LIEF.git
$ cd LIEF
$ python ./setup.py [--ninja] build install [--user]

Note

You can speed-up the compilation by installing ccache or sccache

If you want to enable tests, you can add --lief-test after setup.py.

Debugging

By default, LIEF is compiled with CMAKE_BUILD_TYPE set to Release. One can change this behavior by setting either RelWithDebInfo or Debug during the cmake’s configuration step:

$ cmake -DCMAKE_BUILD_TYPE=RelWithDebInfo [...] ..

On the other hand, Python bindings can also be compiled with debug information by using the --debug flag:

$ python ./setup.py build --debug

Note

When developing on LIEF, you can use:

$ python ./setup [--ninja] build --debug develop --user

Compared to the install command, develop creates a .egg-link that links to the native LIEF library currently presents in you build directory.

The --user flag is used to avoid creating the .egg-link system-wide (i.e. /usr/lib/python3.9/site-packages). Instead, it links the .egg-link in the user’s local dir (e.g. ~/.local/lib/python3.9/site-packages)

Third Party

LIEF relies on few external projects and we try to limit as much as possible the dependencies in the public headers. This table summarizes these dependencies and their scope. internal means that it is required to compile LIEF but it is not required to use LIEF. external means that it is required for both.

Dependency

Scope

Purpose

tcb/span

external

C++11 span interface

Boost Leaf

external

Error handling (see: Error Handling )

spdlog

internal

Logging

MbedTLS

internal

ASN.1 parser / Hash functions

utfcpp

internal

Unicode support (for PE and DEX files)

json

internal

Serialize LIEF’s object into JSON

pybind11

internal

Python bindings

Frozen

internal

constexpr containers

Catch2

internal

Testing

Melkor ELF Fuzzer

internal

ELF Fuzzing

Except MbedTLS, all these dependencies are header-only and they are by default embedded/managed by LIEF such as it eases the compilation and the integration.

Nevertheless, packages manager might require to not self-use/embed external dependencies 1 2.

To address this requirement, the user can control the integration of LIEF’s dependencies using the following cmake’s options:

  • LIEF_OPT_NLOHMANN_JSON_EXTERNAL

  • LIEF_OPT_EXTERNAL_LEAF / LIEF_EXTERNAL_LEAF_DIR

  • LIEF_OPT_UTFCPP_EXTERNAL

  • LIEF_OPT_MBEDTLS_EXTERNAL

  • LIEF_EXTERNAL_SPDLOG

  • LIEF_OPT_FROZEN_EXTERNAL

  • LIEF_OPT_EXTERNAL_SPAN/LIEF_EXTERNAL_SPAN_DIR

  • LIEF_OPT_PYBIND11_EXTERNAL

By setting these flags, LIEF resolves the dependencies with CMake find_package(...) which is aware of <DEPS>_DIR to find the package. Boost’s Leaf does not provide CMake files that can be resolved with find_package so the user can provide LIEF_EXTERNAL_LEAF_DIR instead, which must point to the directory that contains boost/leaf.

As a result, LIEF can be, for instance, compiled with the following configuration:

$ cmake .. -GNinja \
           -DLIEF_OPT_NLOHMANN_JSON_EXTERNAL=ON \
           -Dnlohmann_json_DIR=/lief-third-party/json/install/lib/cmake/nlohmann_json \
           -DLIEF_OPT_MBEDTLS_EXTERNAL=on \
           -DMbedTLS_DIR=/lief-third-party/mbedtls/install/cmake \
           -DLIEF_OPT_EXTERNAL_LEAF=on \
           -DLIEF_EXTERNAL_LEAF_DIR=/lief-third-party/leaf/include/cmake

Warning

As mentioned previously, MbedTLS is not header-only which means that if it is externalized the static version of LIEF won’t include the MbedTLS object files and the end user will have to link again LIEF.a with a provided version of MbedTLS.

1

https://github.com/lief-project/LIEF/issues/605

2

https://github.com/microsoft/vcpkg/blob/master/docs/maintainers/maintainer-guide.md#do-not-use-vendored-dependencies

Continuous Integration

LIEF uses different CI (Github Action, AppVeyor, …) to test and release nightly builds. The configuration of these CI can also be a good source of information for the compilation process. In particular, scripts/docker/travis-linux-sdk.sh contains the build process to generate the Linux x86-64 SDK.

The build_script section of .appveyor.yml contains the logic for generating Windows Python wheels and the SDK.

For OSX & iOS, the CI configs .github/workflows/ios.yml and .github/workflows/osx.yml to compile (and cross-compile) LIEF for these platforms.

CMake Options

if(__add_lief_options)
  return()
endif()
set(__add_lief_options ON)
include(CMakeDependentOption)

option(LIEF_TESTS                      "Enable tests"                               OFF)
option(LIEF_DOC                        "Enable documentation"                       OFF)
option(LIEF_PYTHON_API                 "Enable Python Bindings"                     OFF)
option(LIEF_C_API                      "C API"                                      ON)
option(LIEF_EXAMPLES                   "Build LIEF C++ examples"                    ON)
option(LIEF_FORCE32                    "Force build LIEF 32 bits version"           OFF)
option(LIEF_COVERAGE                   "Perform code coverage"                      OFF)
option(LIEF_USE_CCACHE                 "Use ccache to speed up compilation"         ON)
option(LIEF_EXTRA_WARNINGS             "Enable extra warning from the compiler"     OFF)
option(LIEF_LOGGING                    "Enable logging"                             ON)
option(LIEF_LOGGING_DEBUG              "Enable debug logging"                       ON)
option(LIEF_ENABLE_JSON                "Enable JSON-related APIs"                   ON)
option(LIEF_OPT_NLOHMANN_JSON_EXTERNAL "Use nlohmann/json externaly"                OFF)
option(LIEF_FORCE_API_EXPORTS          "Force exports of API symbols"               OFF)

option(LIEF_DISABLE_FROZEN "Disable Frozen even if it is supported"     OFF)

option(LIEF_ELF            "Build LIEF with ELF module"                 ON)
option(LIEF_PE             "Build LIEF with PE  module"                 ON)
option(LIEF_MACHO          "Build LIEF with MachO module"               ON)

option(LIEF_DEX            "Build LIEF with DEX module"                 ON)
option(LIEF_ART            "Build LIEF with ART module"                 ON)

# OAT support relies on the ELF and DEX format.
# Therefore, these options must be enabled to support use this format
cmake_dependent_option(LIEF_OAT "Build LIEF with OAT module" ON
                       "LIEF_ELF;LIEF_DEX" OFF)

# VDEX format depends on the DEX module
cmake_dependent_option(LIEF_VDEX "Build LIEF with VDEX module" ON
                       "LIEF_DEX" OFF)

# Sanitizer
option(LIEF_ASAN "Enable Address sanitizer"   OFF)
option(LIEF_LSAN "Enable Leak sanitizer"      OFF)
option(LIEF_TSAN "Enable Thread sanitizer"    OFF)
option(LIEF_USAN "Enable undefined sanitizer" OFF)

# Fuzzer
option(LIEF_FUZZING "Fuzz LIEF" OFF)

# Profiling
option(LIEF_PROFILING "Enable performance profiling" OFF)

# Install options
cmake_dependent_option(LIEF_INSTALL_COMPILED_EXAMPLES "Install LIEF Compiled examples" OFF
                       "LIEF_EXAMPLES" OFF)

# Use a user-provided version of spdlog
# It can be useful to reduce compile time
option(LIEF_EXTERNAL_SPDLOG OFF)

# This option enables to provide an external
# version of Boost Leaf (e.g. present on the system)
option(LIEF_OPT_EXTERNAL_LEAF OFF)
set(LIEF_EXTERNAL_LEAF_DIR )

# This option enables to provide an external version of utf8cpp
option(LIEF_OPT_UTFCPP_EXTERNAL OFF)

# This option enables to provide an external version of MbedTLS
option(LIEF_OPT_MBEDTLS_EXTERNAL OFF)

# This option enables to provide an external version of pybind11
option(LIEF_OPT_PYBIND11_EXTERNAL OFF)

# This option enables to provide an external
# version of https://github.com/tcbrindle/span (e.g. present on the system)
option(LIEF_OPT_EXTERNAL_SPAN OFF)
set(LIEF_EXTERNAL_SPAN_DIR )

# This option enables to provide an external version of Frozen
set(_LIEF_USE_FROZEN ON)
if(LIEF_DISABLE_FROZEN)
  set(_LIEF_USE_FROZEN OFF)
endif()
cmake_dependent_option(LIEF_OPT_FROZEN_EXTERNAL "Use an external provided version of Frozen" OFF
                       "_LIEF_USE_FROZEN" OFF)

set(LIEF_ELF_SUPPORT 0)
set(LIEF_PE_SUPPORT 0)
set(LIEF_MACHO_SUPPORT 0)

set(LIEF_OAT_SUPPORT 0)
set(LIEF_DEX_SUPPORT 0)
set(LIEF_VDEX_SUPPORT 0)
set(LIEF_ART_SUPPORT 0)

set(LIEF_JSON_SUPPORT 0)
set(LIEF_NLOHMANN_JSON_EXTERNAL 0)
set(LIEF_LOGGING_SUPPORT 0)
set(LIEF_LOGGING_DEBUG_SUPPORT 0)
set(LIEF_FROZEN_ENABLED 0)
set(LIEF_EXTERNAL_FROZEN 0)

set(LIEF_EXTERNAL_LEAF 0)
set(LIEF_EXTERNAL_UTF8CPP 0)
set(LIEF_EXTERNAL_MBEDTLS 0)
set(LIEF_EXTERNAL_SPAN 0)

if(LIEF_ELF)
  set(LIEF_ELF_SUPPORT 1)
endif()

if(LIEF_PE)
  set(LIEF_PE_SUPPORT 1)
endif()

if(LIEF_MACHO)
  set(LIEF_MACHO_SUPPORT 1)
endif()

if(LIEF_OAT)
  set(LIEF_OAT_SUPPORT 1)
endif()

if(LIEF_DEX)
  set(LIEF_DEX_SUPPORT 1)
endif()

if(LIEF_VDEX)
  set(LIEF_VDEX_SUPPORT 1)
endif()

if(LIEF_ART)
  set(LIEF_ART_SUPPORT 1)
endif()

if(LIEF_ENABLE_JSON)
  set(LIEF_JSON_SUPPORT 1)
  if(LIEF_OPT_NLOHMANN_JSON_EXTERNAL)
    set(LIEF_NLOHMANN_JSON_EXTERNAL 1)
  endif()
endif()

if(LIEF_LOGGING)
  set(LIEF_LOGGING_SUPPORT 1)
  if(LIEF_LOGGING_DEBUG)
    set(LIEF_LOGGING_DEBUG_SUPPORT 1)
  else()
    set(LIEF_LOGGING_DEBUG_SUPPORT 0)
  endif()
endif()

if(NOT LIEF_DISABLE_FROZEN)
  set(LIEF_FROZEN_ENABLED 1)
  if(LIEF_OPT_FROZEN_EXTERNAL)
    set(LIEF_EXTERNAL_FROZEN 1)
  endif()
endif()

if(LIEF_OPT_EXTERNAL_LEAF)
  set(LIEF_EXTERNAL_LEAF 1)
endif()

if(LIEF_OPT_UTFCPP_EXTERNAL)
  set(LIEF_EXTERNAL_UTF8CPP 1)
endif()

if(LIEF_OPT_MBEDTLS_EXTERNAL)
  set(LIEF_EXTERNAL_MBEDTLS 1)
endif()

if(LIEF_OPT_EXTERNAL_SPAN)
  set(LIEF_EXTERNAL_SPAN 1)
endif()

if(LIEF_PYTHON_API)
  if(LIEF_OPT_PYBIND11_EXTERNAL)
    set(LIEF_EXTERNAL_PYBIND11 1)
  endif()
endif()

Docker

See liefproject on Dockerhub

See the Dockerlief repo.