Home
To compile LIEF, you need at least the following requirements:
C++17 compiler (GCC, Clang, MSVC..)
CMake
Python >= 3.8 (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.
$ git clone https://github.com/lief-project/LIEF.git
$ cd LIEF
$ mkdir build
$ cd build
$ cmake -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
Note
Since LIEF 0.13.0 the setup.py has moved from the project root directory to the api/python directory.
$ git clone https://github.com/lief-project/LIEF.git
$ cd LIEF/api/python
$ python ./setup.py build install [--user]
# Or
$ pip install [-e] .
Before LIEF 0.13.0, we could tweak the compilation of the Python bindings through command line options:
$ python ./setup.py --lief-no-dex --lief-no-vdex --lief-no-oat [...]
This interface had the drawback to produce long commands and using setup.py options is even more complicated with pip install approach.
Since LIEF 0.13.0, the options of the Python bindings are now defined in a config-default.toml next to the setup.py file. This .toml file can be used to configure the different options of LIEF and its Python binding:
[lief.build]
type = "Release"
cache = true
ninja = true
parallel-jobs = 0
[lief.formats]
elf = true
pe = false
macho = true
...
One can also provide a custom configuration file through the PYLIEF_CONF environment variable:
$ PYLIEF_CONF=/tmp/my-custom.toml pip install .
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 changing the type in the section [lief.build] of config-default.toml:
[lief.build]
type = "RelWithDebInfo"
Note
When developing on LIEF, you can use:
$ PYLIEF_CONF=~/lief-debug.toml python ./setup build develop --user
With lief-debug.toml set to:
[lief.build]
type = "RelWithDebInfo"
...
[lief.logging]
enabled = true
debug = true
Compared to the install
command, develop
creates a .egg-link
that links to the native LIEF library currently presents in your 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
)
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 |
| C++11 span interface | |
| Error handling (see: Error Handling ) | |
| Logging | |
| ASN.1 parser / Hash functions | |
| Unicode support (for PE and DEX files) | |
| Serialize LIEF’s object into JSON | |
| Python bindings | |
|
| |
| Testing | |
| 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_UTFCPP_EXTERNAL
LIEF_OPT_MBEDTLS_EXTERNAL
LIEF_EXTERNAL_SPDLOG
LIEF_OPT_FROZEN_EXTERNAL
LIEF_OPT_EXTERNAL_SPAN/LIEF_EXTERNAL_SPAN_DIR
LIEF_OPT_EXTERNAL_EXPECTED
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.
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
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.
LIEF uses CI Github Action to test and release nightly builds. The configuration of this CI can also be a good source of information for the compilation process. In particular, scripts/docker/run_linux_sdk contains the build process to generate the Linux x86-64 SDK.
On Windows, the SDK is built with the following Python script: scripts/windows/package_sdk.py
For OSX & iOS, the CI configs .github/workflows/ios.yml and .github/workflows/osx.yml to compile (and cross-compile) LIEF for these platforms.
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 TartanLlama/expected (e.g. present on the system)
option(LIEF_OPT_EXTERNAL_EXPECTED OFF)
# 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)
# This option enables the install target in the cmake
option(LIEF_INSTALL "Generate the install target." ON)
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_EXPECTED 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_EXPECTED)
set(LIEF_EXTERNAL_EXPECTED 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()
See liefproject on Dockerhub
See the Dockerlief repo.