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 includes 8# are present in addition to the library. This is useful to keep off 9# for the imported package on platforms that install the library but 10# 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_FOUND 16# FFI_INCLUDE_DIRS 17# FFI_LIBRARIES 18# FFI_STATIC_LIBRARIES 19# HAVE_FFI_CALL 20# 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::ffi 25 26find_path(FFI_INCLUDE_DIRS ffi.h PATHS ${FFI_INCLUDE_DIR}) 27if( EXISTS "${FFI_INCLUDE_DIRS}/ffi.h" ) 28 set(FFI_HEADER ffi.h CACHE INTERNAL "") 29 set(HAVE_FFI_H 1 CACHE INTERNAL "") 30else() 31 find_path(FFI_INCLUDE_DIRS ffi/ffi.h PATHS ${FFI_INCLUDE_DIR}) 32 if( EXISTS "${FFI_INCLUDE_DIRS}/ffi/ffi.h" ) 33 set(FFI_HEADER ffi/ffi.h CACHE INTERNAL "") 34 set(HAVE_FFI_FFI_H 1 CACHE INTERNAL "") 35 endif() 36endif() 37 38find_library(FFI_LIBRARIES NAMES ffi PATHS ${FFI_LIBRARY_DIR}) 39find_library(FFI_STATIC_LIBRARIES NAMES libffi.a PATHS ${FFI_LIBRARY_DIR}) 40 41if(FFI_LIBRARIES) 42 include(CMakePushCheckState) 43 cmake_push_check_state() 44 list(APPEND CMAKE_REQUIRED_LIBRARIES ${FFI_LIBRARIES}) 45 set(HAVE_FFI_CALL_SRC [=[ 46 #ifdef __cplusplus 47 extern "C" { 48 #endif 49 struct ffi_cif; 50 typedef struct ffi_cif ffi_cif; 51 void ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue); 52 #ifdef __cplusplus 53 } 54 #endif 55 int main(void) { ffi_call(0, 0, 0, 0); } 56 ]=]) 57 if(DEFINED CMAKE_C_COMPILER) 58 include(CheckCSourceCompiles) 59 check_c_source_compiles("${HAVE_FFI_CALL_SRC}" HAVE_FFI_CALL) 60 else() 61 include(CheckCXXSourceCompiles) 62 check_cxx_source_compiles("${HAVE_FFI_CALL_SRC}" HAVE_FFI_CALL) 63 endif() 64 cmake_pop_check_state() 65endif() 66 67unset(required_includes) 68if(FFI_REQUIRE_INCLUDE) 69 set(required_includes FFI_INCLUDE_DIRS) 70endif() 71 72include(FindPackageHandleStandardArgs) 73find_package_handle_standard_args(FFI 74 FOUND_VAR 75 FFI_FOUND 76 REQUIRED_VARS 77 FFI_LIBRARIES 78 ${required_includes} 79 HAVE_FFI_CALL) 80mark_as_advanced(FFI_LIBRARIES 81 FFI_STATIC_LIBRARIES 82 FFI_INCLUDE_DIRS 83 HAVE_FFI_CALL 84 FFI_HEADER 85 HAVE_FFI_H 86 HAVE_FFI_FFI_H) 87 88if(FFI_FOUND) 89 if(NOT TARGET FFI::ffi AND FFI_LIBRARIES) 90 add_library(FFI::ffi UNKNOWN IMPORTED) 91 set_target_properties(FFI::ffi PROPERTIES IMPORTED_LOCATION "${FFI_LIBRARIES}") 92 if(FFI_INCLUDE_DIRS) 93 set_target_properties(FFI::ffi PROPERTIES INTERFACE_INCLUDE_DIRECTORIES "${FFI_INCLUDE_DIRS}") 94 endif() 95 endif() 96 if(NOT TARGET FFI::ffi_static AND FFI_STATIC_LIBRARIES) 97 add_library(FFI::ffi_static UNKNOWN IMPORTED) 98 set_target_properties(FFI::ffi_static PROPERTIES IMPORTED_LOCATION "${FFI_STATIC_LIBRARIES}") 99 if(FFI_INCLUDE_DIRS) 100 set_target_properties(FFI::ffi_static PROPERTIES INTERFACE_INCLUDE_DIRECTORIES "${FFI_INCLUDE_DIRS}") 101 endif() 102 endif() 103endif() 104