llvm-project/llvm/cmake/modules/FindFFI.cmake
Jack Andersen b66339575a [CMake] Installable find modules for terminfo and libffi
Improves cross-distro portability of LLVM cmake package by resolving paths for
terminfo and libffi via import targets.

When LLVMExports.cmake is generated for installation, it contains absolute
library paths which are likely to be a common cause of portability issues. To
mitigate this, the discovery logic for these dependencies is refactored into
find modules which get installed alongside LLVMConfig.cmake. The result is
cleaner, cmake-friendly management of these dependencies that respect the
environment of the LLVM package importer.

Reviewed By: JDevlieghere

Differential Revision: https://reviews.llvm.org/D114327
2021-12-05 14:46:23 -05:00

82 lines
2.5 KiB
CMake

# Attempts to discover ffi library with a linkable ffi_call function.
#
# Example usage:
#
# find_package(FFI)
#
# FFI_REQUIRE_INCLUDE may be set to consider ffi found if the includes
# are present in addition to the library. This is useful to keep off
# for the imported package on platforms that install the library but
# not the headers.
#
# FFI_LIBRARY_DIR may be set to define search paths for the ffi library.
#
# If successful, the following variables will be defined:
# FFI_FOUND
# FFI_INCLUDE_DIRS
# FFI_LIBRARIES
# HAVE_FFI_CALL
#
# HAVE_FFI_H or HAVE_FFI_FFI_H is defined depending on the ffi.h include path.
#
# Additionally, the following import target will be defined:
# FFI::ffi
find_path(FFI_INCLUDE_DIRS ffi.h PATHS ${FFI_INCLUDE_DIR})
if( EXISTS "${FFI_INCLUDE_DIRS}/ffi.h" )
set(FFI_HEADER ffi.h CACHE INTERNAL "")
set(HAVE_FFI_H 1 CACHE INTERNAL "")
else()
find_path(FFI_INCLUDE_DIRS ffi/ffi.h PATHS ${FFI_INCLUDE_DIR})
if( EXISTS "${FFI_INCLUDE_DIRS}/ffi/ffi.h" )
set(FFI_HEADER ffi/ffi.h CACHE INTERNAL "")
set(HAVE_FFI_FFI_H 1 CACHE INTERNAL "")
endif()
endif()
find_library(FFI_LIBRARIES ffi PATHS ${FFI_LIBRARY_DIR})
if(FFI_LIBRARIES)
include(CMakePushCheckState)
include(CheckCSourceCompiles)
cmake_push_check_state()
list(APPEND CMAKE_REQUIRED_LIBRARIES ${FFI_LIBRARIES})
check_c_source_compiles("
struct ffi_cif;
typedef struct ffi_cif ffi_cif;
void ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue);
int main() { ffi_call(0, 0, 0, 0); }"
HAVE_FFI_CALL)
cmake_pop_check_state()
endif()
unset(required_includes)
if(FFI_REQUIRE_INCLUDE)
set(required_includes FFI_INCLUDE_DIRS)
endif()
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(FFI
FOUND_VAR
FFI_FOUND
REQUIRED_VARS
FFI_LIBRARIES
${required_includes}
HAVE_FFI_CALL)
mark_as_advanced(FFI_LIBRARIES
FFI_INCLUDE_DIRS
HAVE_FFI_CALL
FFI_HEADER
HAVE_FFI_H
HAVE_FFI_FFI_H)
if(FFI_FOUND)
if(NOT TARGET FFI::ffi)
add_library(FFI::ffi UNKNOWN IMPORTED)
set_target_properties(FFI::ffi PROPERTIES IMPORTED_LOCATION "${FFI_LIBRARIES}")
if(FFI_INCLUDE_DIRS)
set_target_properties(FFI::ffi PROPERTIES INTERFACE_INCLUDE_DIRECTORIES "${FFI_INCLUDE_DIRS}")
endif()
endif()
endif()