Provide 'FindLIEF.cmake' to be easily integrated with CMake

* Now examples are provided in packages (SDK)
  * Add an examples in the doc to use 'find_packges()' with LIEF
This commit is contained in:
Romain Thomas 2017-07-19 15:46:37 +02:00
parent cf47f4aa35
commit 6dd8b10325
13 changed files with 350 additions and 123 deletions

View File

@ -537,11 +537,7 @@ endif()
# Examples
# ========
if(LIEF_EXAMPLES)
add_subdirectory("${CMAKE_CURRENT_SOURCE_DIR}/examples/cpp")
if (LIEF_C_API)
add_subdirectory("${CMAKE_CURRENT_SOURCE_DIR}/examples/c")
endif()
add_subdirectory("${CMAKE_CURRENT_SOURCE_DIR}/examples")
endif()
# Tests
@ -598,5 +594,11 @@ install(
COMPONENT headers
FILES_MATCHING REGEX "(.*).(hpp|h|def)$")
install(
FILES ${CMAKE_CURRENT_SOURCE_DIR}/scripts/FindLIEF.cmake
DESTINATION share/LIEF/cmake
COMPONENT CMakeScripts
)
# Package
add_subdirectory("${CMAKE_CURRENT_SOURCE_DIR}/package")

View File

@ -30,6 +30,57 @@ else()
DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/sphinx-src/_static
)
###################
# FIND PACKAGE
####################
file(
COPY ${CMAKE_SOURCE_DIR}/examples/cmake/find_package/CMakeLists.txt
DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/sphinx-src/_static/
)
file(
RENAME ${CMAKE_CURRENT_BINARY_DIR}/sphinx-src/_static/CMakeLists.txt
${CMAKE_CURRENT_BINARY_DIR}/sphinx-src/_static/CMakeFindPackage.cmake
)
# Find Package Readme
file(
COPY ${CMAKE_SOURCE_DIR}/examples/cmake/find_package/README.rst
DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/sphinx-src/_static/
)
file(
RENAME ${CMAKE_CURRENT_BINARY_DIR}/sphinx-src/_static/README.rst
${CMAKE_CURRENT_BINARY_DIR}/sphinx-src/_static/ReadmeFindPackage.rst
)
####################
# EXTERNAL PROJECT
####################
file(
COPY ${CMAKE_SOURCE_DIR}/examples/cmake/external_project/CMakeLists.txt
DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/sphinx-src/_static/
)
file(
RENAME ${CMAKE_CURRENT_BINARY_DIR}/sphinx-src/_static/CMakeLists.txt
${CMAKE_CURRENT_BINARY_DIR}/sphinx-src/_static/CMakeExternalProject.cmake
)
file(
COPY ${CMAKE_SOURCE_DIR}/examples/cmake/external_project/README.rst
DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/sphinx-src/_static/
)
file(
RENAME ${CMAKE_CURRENT_BINARY_DIR}/sphinx-src/_static/README.rst
${CMAKE_CURRENT_BINARY_DIR}/sphinx-src/_static/ReadmeExternalProject.rst
)
####################
file(
COPY ${CMAKE_CURRENT_SOURCE_DIR}/doxygen/
DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/doxygen/html
@ -80,14 +131,14 @@ else()
DIRECTORY
${CMAKE_CURRENT_BINARY_DIR}/doxygen/html/
DESTINATION
share/doc/lief/doxygen
share/LIEF/doc/doxygen
COMPONENT doc)
install(
DIRECTORY
${CMAKE_CURRENT_BINARY_DIR}/sphinx-doc/
DESTINATION
share/doc/lief/sphinx
share/LIEF/doc/sphinx
COMPONENT doc)
endif()

View File

@ -151,81 +151,49 @@ and run it:
CMake Integration
-----------------
By using `CMake External Project <https://cmake.org/cmake/help/v3.0/module/ExternalProject.html>`_, integration of LIEF is quiet simple.
This script setup LIEF as an *external project*
External Project
****************
.. code-block:: cmake
Using `CMake External Project <https://cmake.org/cmake/help/v3.0/module/ExternalProject.html>`_:
set(LIEF_PREFIX "${CMAKE_CURRENT_BINARY_DIR}/LIEF")
set(LIEF_INSTALL_DIR "${LIEF_PREFIX}")
set(LIEF_INCLUDE_DIRS "${LIEF_PREFIX}/include")
# LIEF static library
set(LIB_LIEF_STATIC
"${LIEF_PREFIX}/lib/${CMAKE_STATIC_LIBRARY_PREFIX}LIEF${CMAKE_STATIC_LIBRARY_SUFFIX}")
# URL of the LIEF repo (Can be your fork)
set(LIEF_GIT_URL "https://github.com/lief-project/LIEF.git")
# LIEF's version to be used (can be 'master')
set(LIEF_VERSION 0.7.0)
# LIEF compilation config
set(LIEF_CMAKE_ARGS
-DCMAKE_INSTALL_PREFIX=<INSTALL_DIR>
-DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE}
-DLIEF_DOC=off
-DLIEF_PYTHON_API=off
-DLIEF_EXAMPLES=off
-DCMAKE_CXX_COMPILER=${CMAKE_CXX_COMPILER}
-DCMAKE_C_COMPILER=${CMAKE_C_COMPILER}
)
ExternalProject_Add(LIEF
PREFIX "${LIEF_PREFIX}"
GIT_REPOSITORY ${LIEF_GIT_URL}
GIT_TAG ${LIEF_VERSION}
INSTALL_DIR ${LIEF_INSTALL_DIR}
CMAKE_ARGS ${LIEF_CMAKE_ARGS}
BUILD_BYPRODUCTS ${LIEF_LIBRARIES}
UPDATE_COMMAND ""
)
.. literalinclude:: _static/CMakeExternalProject.cmake
:language: cmake
:lines: 1-42
And now, to be integrated within a project:
.. code-block:: cmake
add_executable(HelloLIEF main.cpp)
if (MSVC)
# Used for the 'and', 'or' ... keywords - See: http://www.cplusplus.com/reference/ciso646/
target_compile_options(HelloLIEF PUBLIC /FIiso646.h)
set_property(TARGET HelloLIEF PROPERTY LINK_FLAGS /NODEFAULTLIB:MSVCRT)
endif()
# Setup the LIEF include directory
target_include_directories(HelloLIEF
PUBLIC
${LIEF_INCLUDE_DIRS}
)
# Enable C++11
set_property(TARGET HelloLIEF PROPERTY CXX_STANDARD 11)
set_property(TARGET HelloLIEF PROPERTY CXX_STANDARD_REQUIRED ON)
# Link the executable with LIEF
target_link_libraries(HelloLIEF PUBLIC ${LIB_LIEF_STATIC})
add_dependencies(HelloLIEF LIEF)
.. literalinclude:: _static/CMakeExternalProject.cmake
:language: cmake
:lines: 47-
For the compilation:
.. code-block:: console
.. literalinclude:: _static/ReadmeExternalProject.rst
:language: rst
:lines: 1-42
$ mkdir build
$ cd build
$ cmake ..
$ make -j3 # and wait...
A *full* example is available in the ``examples/cmake/external_project`` directory.
A *full* example is available in the ``examples/cmake`` directory.
find_package()
**************
Using `CMake find_package() <https://cmake.org/cmake/help/v3.0/command/find_package.html>`_:
.. literalinclude:: _static/CMakeFindPackage.cmake
:language: cmake
:lines: 5-19
And now, to be integrated within a project:
.. literalinclude:: _static/CMakeFindPackage.cmake
:language: cmake
:lines: 20-
For the compilation:
.. literalinclude:: _static/ReadmeFindPackage.rst
:language: rst
A *full* example is available in the ``examples/cmake/find_package`` directory.

22
examples/CMakeLists.txt Normal file
View File

@ -0,0 +1,22 @@
add_subdirectory("${CMAKE_CURRENT_SOURCE_DIR}/cpp")
if (LIEF_C_API)
add_subdirectory("${CMAKE_CURRENT_SOURCE_DIR}/c")
endif()
install(
DIRECTORY python
DESTINATION share/LIEF/examples
COMPONENT examples
)
install(
DIRECTORY cmake
DESTINATION share/LIEF/examples
COMPONENT examples
)

View File

@ -73,3 +73,11 @@ foreach(example ${LIEF_C_EXAMPLES})
endforeach()
endif()
install(
DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/
DESTINATION share/LIEF/examples/c
COMPONENT examples
FILES_MATCHING REGEX "(.*).(hpp|h|c)$"
)

View File

@ -1,5 +1,5 @@
LIEF CMake Integration Example
==============================
LIEF CMake Integration Example - ExternalProject
================================================
.. code-block:: console

View File

@ -0,0 +1,41 @@
cmake_minimum_required(VERSION 3.1)
project(CMakeLIEF)
# Use LIEF with 'find_package()'
# ==============================
# Custom path to the LIEF install directory
set(LIEF_ROOT CACHE PATH ${CMAKE_INSTALL_PREFIX})
# Directory to 'FindLIEF.cmake'
list(APPEND CMAKE_MODULE_PATH ${LIEF_ROOT}/share/LIEF/cmake)
# include 'FindLIEF.cmake'
include(FindLIEF)
# Find LIEF
find_package(LIEF REQUIRED COMPONENTS STATIC) # COMPONENTS: <SHARED | STATIC> - Default: STATIC
# Add our executable
# ==================
add_executable(HelloLIEF main.cpp)
if (MSVC)
# Used for the 'and', 'or' ... keywords - See: http://www.cplusplus.com/reference/ciso646/
target_compile_options(HelloLIEF PUBLIC /FIiso646.h)
set_property(TARGET HelloLIEF PROPERTY LINK_FLAGS /NODEFAULTLIB:MSVCRT)
endif()
# Setup the LIEF include directory
target_include_directories(HelloLIEF
PUBLIC
${LIEF_INCLUDE_DIRS}
)
# Enable C++11
set_property(TARGET HelloLIEF PROPERTY CXX_STANDARD 11)
set_property(TARGET HelloLIEF PROPERTY CXX_STANDARD_REQUIRED ON)
# Link the executable with LIEF
target_link_libraries(HelloLIEF PUBLIC ${LIEF_LIBRARIES})

View File

@ -0,0 +1,12 @@
LIEF CMake Integration Example - find_package()
===============================================
.. code-block:: console
$ mkdir build
$ cd build
$ cmake -DLIEF_ROOT=<PATH_TO_LIEF_INSTALL_DIR> .. # By default, LIEF_ROOT=CMAKE_INSTALL_PREFIX
$ make
$ HelloLIEF /bin/ls # or explorer.exe or whatever

View File

@ -0,0 +1,13 @@
#include <iostream>
#include <LIEF/LIEF.hpp>
int main(int argc, char** argv) {
if (argc != 2) {
std::cerr << "Usage: " << argv[0] << " <binary>" << std::endl;
return 1;
}
LIEF::Binary* binary = LIEF::Parser::parse(argv[1]);
std::cout << *binary << std::endl;
delete binary;
}

View File

@ -74,3 +74,11 @@ foreach(example ${LIEF_CPP_EXAMPLES})
target_link_libraries("${output_name}_shared" PUBLIC LIB_LIEF_SHARED)
endforeach()
install(
DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/
DESTINATION share/LIEF/examples/cpp
COMPONENT examples
FILES_MATCHING REGEX "(.*).(hpp|h|cpp)$"
)

View File

@ -1,64 +1,166 @@
# Locate LIEF
#.rst:
# FindLIEF
# --------
#
# This module defines
# LIEF_FOUND, if false, do not try to link to yaml-cpp
# LIEF_LIBNAME, name of yaml library
# LIEF_LIBRARY, where to find lief
# LIEF_LIBRARY_RELEASE, where to find Release or RelWithDebInfo lief
# LIEF_LIBRARY_DEBUG, where to find Debug version of LIEF
# LIEF_INCLUDE_DIR, where to find LIEF.hpp
# LIEF_LIBRARY_DIR, the directories to find LIEF_LIBRARY
# Find the native LIEF includes and library.
#
# By default, the shared libraries of LIEF will be found. To find the static ones instead,
# you must set the LIEF_USE_STATIC_LIBS variable to TRUE before calling find_package(LIEF ...)
# IMPORTED Targets
# ^^^^^^^^^^^^^^^^
#
# This module defines :prop_tgt:`IMPORTED` target ``LIEF::LIEF``, if
# LIEF has been found.
#
# Result Variables
# ^^^^^^^^^^^^^^^^
#
# This module defines the following variables:
#
# ::
#
# LIEF_INCLUDE_DIRS - Where to find LIEF/LIEF.hpp, etc.
# LIEF_LIBRARIES - List of libraries when using LIEF.
# LIEF_FOUND - True if LIEF found.
#
# ::
#
# LIEF_VERSION_STRING - The version of LIEF found (x.y.z)
# LIEF_VERSION_MAJOR - The major version of LIEF
# LIEF_VERSION_MINOR - The minor version of LIEF
# LIEF_VERSION_PATCH - The patch version of LIEF
#
# Hints
# ^^^^^
#
# A user may set ``LIEF_ROOT`` to a LIEF installation root to tell this
# module where to look.
#
# To choose between STATIC and SHARED version of LIEF library, one
# can use ``COMPONENTS STATIC`` of ``COMPONENTS SHARED``
#
# .. code-block:: cmake
#
# find_package(LIEF 0.7.0 REQUIRED COMPONENTS STATIC)
if(LIEF_USE_STATIC_LIBS)
set(LIEF_STATIC libLIEF.a)
set(_LIEF_SEARCHES)
# Search LIEF_ROOT first if it is set.
if(LIEF_ROOT)
set(_LIEF_SEARCH_ROOT PATHS ${LIEF_ROOT} NO_DEFAULT_PATH)
list(APPEND _LIEF_SEARCHES _LIEF_SEARCH_ROOT)
endif()
set(LIEF_LIBNAME "libLIEF" CACHE STRING "Name of LIEF library")
set(LIEF_NAMES LIEF)
if (LIEF_FIND_COMPONENTS AND LIEF_FIND_REQUIRED_STATIC AND LIEF_FIND_REQUIRED_SHARED)
message(WARNING "Two incompatible components specified : static and shared. We are going to ignore the 'shared' component.")
list(REMOVE_ITEM LIEF_FIND_COMPONENTS SHARED)
unset(LIEF_FIND_REQUIRED_SHARED)
endif()
# Find include directory
# ======================
find_path(LIEF_INCLUDE_DIR
NAMES LIEF/LIEF.hpp
PATH_SUFFIXES include
PATHS
/usr/local/include/
/usr/include/)
set(LIBRARY_SUFFIXES_SAVED ${CMAKE_FIND_LIBRARY_SUFFIXES})
if (NOT LIEF_FIND_COMPONENTS)
set(CMAKE_FIND_LIBRARY_SUFFIXES ${CMAKE_STATIC_LIBRARY_SUFFIX} ${CMAKE_SHARED_LIBRARY_SUFFIX})
endif()
# Find the library
# ================
find_library(LIEF_LIBRARY_RELEASE
NAMES ${LIEF_STATIC} libLIEF LIEF
PATH_SUFFIXES lib64 lib Release RelWithDebInfo
PATHS
/usr/local
/usr)
if(LIEF_FIND_COMPONENTS AND LIEF_FIND_REQUIRED_STATIC)
unset(_LIEF_LIBRARY CACHE)
unset(LIEF_LIBRARY)
unset(LIEF_FOUND)
unset(LIEF_LIBRARIES)
set(CMAKE_FIND_LIBRARY_SUFFIXES ${CMAKE_STATIC_LIBRARY_SUFFIX})
endif()
if(LIEF_FIND_COMPONENTS AND LIEF_FIND_REQUIRED_SHARED)
unset(_LIEF_LIBRARY CACHE)
unset(LIEF_LIBRARY)
unset(LIEF_FOUND)
unset(LIEF_LIBRARIES)
set(CMAKE_FIND_LIBRARY_SUFFIXES ${CMAKE_SHARED_LIBRARY_SUFFIX})
endif()
set(LIEF_LIBRARY ${LIEF_LIBRARY_RELEASE})
if(CMAKE_BUILD_TYPE MATCHES Debug AND EXISTS ${LIEF_LIBRARY_DEBUG})
set(LIEF_LIBRARY ${LIEF_LIBRARY_DEBUG})
# Try each search configuration.
foreach(search ${_LIEF_SEARCHES})
find_path(LIEF_INCLUDE_DIR
NAMES LIEF/LIEF.hpp
PATH ${${search}}
PATH_SUFFIXES include)
endforeach()
# Allow LIEF_LIBRARY to be set manually, as the location of the LIEF library
if(NOT LIEF_LIBRARY)
foreach(search ${_LIEF_SEARCHES})
find_library(_LIEF_LIBRARY
NAMES ${LIEF_NAMES}
PATHS ${${search}}
PATH_SUFFIXES lib lib64)
endforeach()
if(EXISTS "${CMAKE_CURRENT_LIST_DIR}/SelectLibraryConfigurations.cmake")
include(${CMAKE_CURRENT_LIST_DIR}/SelectLibraryConfigurations.cmake)
else()
include(SelectLibraryConfigurations)
endif()
select_library_configurations(LIEF)
set(LIEF_LIBRARY ${_LIEF_LIBRARY})
endif()
get_filename_component(LIEF_LIBRARY_RELEASE_DIR ${LIEF_LIBRARY_RELEASE} PATH)
set(LIEF_LIBRARY_DIR ${LIEF_LIBRARY_RELEASE_DIR})
unset(LIEF_NAMES)
# handle the QUIETLY and REQUIRED arguments and set LIEF_FOUND to TRUE if all listed variables are TRUE
include(FindPackageHandleStandardArgs)
FIND_PACKAGE_HANDLE_STANDARD_ARGS(LIEF DEFAULT_MSG
LIEF_INCLUDE_DIR
LIEF_LIBRARY
LIEF_LIBRARY_DIR)
mark_as_advanced(LIEF_INCLUDE_DIR)
mark_as_advanced(
LIEF_INCLUDE_DIR
LIEF_LIBRARY_DIR
LIEF_LIBRARY
LIEF_LIBRARY_RELEASE
LIEF_LIBRARY_RELEASE_DIR)
if(LIEF_INCLUDE_DIR AND EXISTS "${LIEF_INCLUDE_DIR}/LIEF/version.h")
file(STRINGS "${LIEF_INCLUDE_DIR}/LIEF/version.h" LIEF_H REGEX "^#define LIEF_VERSION \"[^\"]*\"$")
string(REGEX REPLACE "^.*LIEF_VERSION \"([0-9]+).*$" "\\1" LIEF_VERSION_MAJOR "${LIEF_H}")
string(REGEX REPLACE "^.*LIEF_VERSION \"[0-9]+\\.([0-9]+).*$" "\\1" LIEF_VERSION_MINOR "${LIEF_H}")
string(REGEX REPLACE "^.*LIEF_VERSION \"[0-9]+\\.[0-9]+\\.([0-9]+).*$" "\\1" LIEF_VERSION_PATCH "${LIEF_H}")
set(LIEF_VERSION_STRING "${LIEF_VERSION_MAJOR}.${LIEF_VERSION_MINOR}.${LIEF_VERSION_PATCH}")
set(LIEF_MAJOR_VERSION "${LIEF_VERSION_MAJOR}")
set(LIEF_MINOR_VERSION "${LIEF_VERSION_MINOR}")
set(LIEF_PATCH_VERSION "${LIEF_VERSION_PATCH}")
endif()
if(EXISTS "${CMAKE_CURRENT_LIST_DIR}/FindPackageHandleStandardArgs.cmake")
include(${CMAKE_CURRENT_LIST_DIR}/FindPackageHandleStandardArgs.cmake)
else()
include(FindPackageHandleStandardArgs)
endif()
FIND_PACKAGE_HANDLE_STANDARD_ARGS(LIEF REQUIRED_VARS LIEF_LIBRARY LIEF_INCLUDE_DIR
VERSION_VAR LIEF_VERSION_STRING)
if(LIEF_FOUND)
set(LIEF_INCLUDE_DIRS ${LIEF_INCLUDE_DIR})
if(NOT LIEF_LIBRARIES)
set(LIEF_LIBRARIES ${LIEF_LIBRARY})
endif()
if(NOT TARGET LIEF::LIEF)
add_library(LIEF::LIEF UNKNOWN IMPORTED)
set_target_properties(LIEF::LIEF PROPERTIES
INTERFACE_INCLUDE_DIRECTORIES "${LIEF_INCLUDE_DIRS}")
if(LIEF_LIBRARY)
set_property(TARGET LIEF::LIEF APPEND PROPERTY
IMPORTED_CONFIGURATIONS RELEASE)
set_target_properties(LIEF::LIEF PROPERTIES
IMPORTED_LOCATION_RELEASE "${LIEF_LIBRARY}")
endif()
if(NOT LIEF_LIBRARY)
set_property(TARGET LIEF::LIEF APPEND PROPERTY
IMPORTED_LOCATION "${LIEF_LIBRARY}")
endif()
endif()
endif()
# Restore
set(CMAKE_FIND_LIBRARY_SUFFIXES ${LIBRARY_SUFFIXES_SAVED})