107 lines · plain
1# Attempts to discover ffi library with a linkable ffi_call function.2#3# Example usage:4#5# find_package(FFI)6#7# FFI_REQUIRE_INCLUDE may be set to consider ffi found if the includes8# are present in addition to the library. This is useful to keep off9# for the imported package on platforms that install the library but10# not the headers.11#12# FFI_LIBRARY_DIR may be set to define search paths for the ffi library.13#14# If successful, the following variables will be defined:15# FFI_FOUND16# FFI_INCLUDE_DIRS17# FFI_LIBRARIES18# FFI_STATIC_LIBRARIES19# HAVE_FFI_CALL20#21# HAVE_FFI_H or HAVE_FFI_FFI_H is defined depending on the ffi.h include path.22#23# Additionally, the following import target will be defined:24# FFI::ffi25 26find_package(PkgConfig QUIET)27pkg_check_modules(PC_LIBFFI QUIET libffi)28 29find_path(FFI_INCLUDE_DIRS ffi.h PATHS ${FFI_INCLUDE_DIR} ${PC_LIBFFI_INCLUDE_DIRS})30if( EXISTS "${FFI_INCLUDE_DIRS}/ffi.h" )31 set(FFI_HEADER ffi.h CACHE INTERNAL "")32 set(HAVE_FFI_H 1 CACHE INTERNAL "")33else()34 find_path(FFI_INCLUDE_DIRS ffi/ffi.h PATHS ${FFI_INCLUDE_DIR})35 if( EXISTS "${FFI_INCLUDE_DIRS}/ffi/ffi.h" )36 set(FFI_HEADER ffi/ffi.h CACHE INTERNAL "")37 set(HAVE_FFI_FFI_H 1 CACHE INTERNAL "")38 endif()39endif()40 41find_library(FFI_LIBRARIES NAMES ffi PATHS ${FFI_LIBRARY_DIR} ${PC_LIBFFI_LIBRARY_DIRS})42find_library(FFI_STATIC_LIBRARIES NAMES libffi.a PATHS ${FFI_LIBRARY_DIR} ${PC_LIBFFI_LIBRARY_DIRS})43 44if(FFI_LIBRARIES)45 include(CMakePushCheckState)46 cmake_push_check_state()47 list(APPEND CMAKE_REQUIRED_LIBRARIES ${FFI_LIBRARIES})48 set(HAVE_FFI_CALL_SRC [=[49 #ifdef __cplusplus50 extern "C" {51 #endif52 struct ffi_cif;53 typedef struct ffi_cif ffi_cif;54 void ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue);55 #ifdef __cplusplus56 }57 #endif58 int main(void) { ffi_call(0, 0, 0, 0); }59 ]=])60 if(DEFINED CMAKE_C_COMPILER)61 include(CheckCSourceCompiles)62 check_c_source_compiles("${HAVE_FFI_CALL_SRC}" HAVE_FFI_CALL)63 else()64 include(CheckCXXSourceCompiles)65 check_cxx_source_compiles("${HAVE_FFI_CALL_SRC}" HAVE_FFI_CALL)66 endif()67 cmake_pop_check_state()68endif()69 70unset(required_includes)71if(FFI_REQUIRE_INCLUDE)72 set(required_includes FFI_INCLUDE_DIRS)73endif()74 75include(FindPackageHandleStandardArgs)76find_package_handle_standard_args(FFI77 FOUND_VAR78 FFI_FOUND79 REQUIRED_VARS80 FFI_LIBRARIES81 ${required_includes}82 HAVE_FFI_CALL)83mark_as_advanced(FFI_LIBRARIES84 FFI_STATIC_LIBRARIES85 FFI_INCLUDE_DIRS86 HAVE_FFI_CALL87 FFI_HEADER88 HAVE_FFI_H89 HAVE_FFI_FFI_H)90 91if(FFI_FOUND)92 if(NOT TARGET FFI::ffi AND FFI_LIBRARIES)93 add_library(FFI::ffi UNKNOWN IMPORTED)94 set_target_properties(FFI::ffi PROPERTIES IMPORTED_LOCATION "${FFI_LIBRARIES}")95 if(FFI_INCLUDE_DIRS)96 set_target_properties(FFI::ffi PROPERTIES INTERFACE_INCLUDE_DIRECTORIES "${FFI_INCLUDE_DIRS}")97 endif()98 endif()99 if(NOT TARGET FFI::ffi_static AND FFI_STATIC_LIBRARIES)100 add_library(FFI::ffi_static UNKNOWN IMPORTED)101 set_target_properties(FFI::ffi_static PROPERTIES IMPORTED_LOCATION "${FFI_STATIC_LIBRARIES}")102 if(FFI_INCLUDE_DIRS)103 set_target_properties(FFI::ffi_static PROPERTIES INTERFACE_INCLUDE_DIRECTORIES "${FFI_INCLUDE_DIRS}")104 endif()105 endif()106endif()107