To compile LIEF, you need at least the following requirements:
C++17 compiler (GCC, Clang, MSVC..)
CMake
Python >= 3.8 (for the bindings)
Note
A compilation from scratch with all the options enabled can take ~20 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 CMAKE_MSVC_RUNTIME_LIBRARY
variable:
$ cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_MSVC_RUNTIME_LIBRARY=MultiThreaded ..
For Debug, you should set the CRT to MTd:
$ cmake -DCMAKE_BUILD_TYPE=Debug -DCMAKE_MSVC_RUNTIME_LIBRARY=MultiThreadedDebug ..
$ 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
$ pip install [-e] [--user] .
# Or
$ pip install [-e] api/python
One can tweak the compilation by setting the environment variable PYLIEF_CONF
to a Toml configuration file. By default, the Python bindings are using config-default.toml
in the Python binding directory:
[lief.build]
type = "Release"
cache = true
ninja = true
parallel-jobs = 0
[lief.formats]
elf = true
pe = false
macho = true
...
$ 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 pip install [-e] api/python
With lief-debug.toml set to:
[lief.build]
type = "RelWithDebInfo"
...
[lief.logging]
enabled = true
debug = true
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_NANOBIND_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/linux-sdk-x64 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_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_PY_LIEF_EXT "Use a pre-installed version of LIEF for the bindings" OFF)
option(LIEF_RUST_API "Generate the C++ bridge for Rust's cxx" OFF)
option(LIEF_DISABLE_EXCEPTIONS "Disable C++ exceptions on the core library" ON)
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)
# Extended features
option(LIEF_DEBUG_INFO "Build LIEF with DWARF/PDB support" OFF)
option(LIEF_OBJC "Build LIEF with ObjC metadata support" OFF)
cmake_dependent_option(LIEF_PYTHON_EDITABLE "Make an editable build " OFF
"LIEF_PYTHON_API" OFF)
cmake_dependent_option(LIEF_PYTHON_STATIC "Internal usage" OFF
"LIEF_PYTHON_API" OFF)
# 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 nanobind
option(LIEF_OPT_NANOBIND_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)
set(LIEF_DEBUG_INFO_SUPPORT 0)
set(LIEF_OBJC_SUPPORT 0)
set(LIEF_EXTENDED 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_NANOBIND_EXTERNAL)
set(LIEF_EXTERNAL_NANOBIND 1)
endif()
endif()
# Extended features
if (LIEF_DEBUG_INFO)
set(LIEF_DEBUG_INFO_SUPPORT 1)
endif()
if (LIEF_OBJC)
set(LIEF_OBJC_SUPPORT 1)
endif()
if (LIEF_DEBUG_INFO OR LIEF_OBJC) # or any other extended feature
set(LIEF_EXTENDED 1)
endif()
See liefproject on Dockerhub