Skip to content

Commit b663395

Browse files
committed
[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
1 parent 296ebeb commit b663395

File tree

6 files changed

+154
-48
lines changed

6 files changed

+154
-48
lines changed

llvm/cmake/config-ix.cmake

Lines changed: 13 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -191,18 +191,13 @@ if(NOT LLVM_USE_SANITIZER MATCHES "Memory.*")
191191
else()
192192
set(HAVE_LIBEDIT 0)
193193
endif()
194-
if(LLVM_ENABLE_TERMINFO STREQUAL FORCE_ON)
195-
set(MAYBE_REQUIRED REQUIRED)
196-
else()
197-
set(MAYBE_REQUIRED)
198-
endif()
199194
if(LLVM_ENABLE_TERMINFO)
200-
find_library(TERMINFO_LIB NAMES terminfo tinfo curses ncurses ncursesw ${MAYBE_REQUIRED})
201-
endif()
202-
if(TERMINFO_LIB)
203-
set(LLVM_ENABLE_TERMINFO 1)
204-
else()
205-
set(LLVM_ENABLE_TERMINFO 0)
195+
if(LLVM_ENABLE_TERMINFO STREQUAL FORCE_ON)
196+
find_package(Terminfo REQUIRED)
197+
else()
198+
find_package(Terminfo)
199+
endif()
200+
set(LLVM_ENABLE_TERMINFO "${Terminfo_FOUND}")
206201
endif()
207202
else()
208203
set(LLVM_ENABLE_TERMINFO 0)
@@ -354,38 +349,19 @@ if (LLVM_ENABLE_DOXYGEN)
354349
llvm_find_program(dot)
355350
endif ()
356351

357-
if( LLVM_ENABLE_FFI )
358-
find_path(FFI_INCLUDE_PATH ffi.h PATHS ${FFI_INCLUDE_DIR})
359-
if( EXISTS "${FFI_INCLUDE_PATH}/ffi.h" )
360-
set(FFI_HEADER ffi.h CACHE INTERNAL "")
361-
set(HAVE_FFI_H 1 CACHE INTERNAL "")
352+
if(LLVM_ENABLE_FFI)
353+
set(FFI_REQUIRE_INCLUDE On)
354+
if(LLVM_ENABLE_FFI STREQUAL FORCE_ON)
355+
find_package(FFI REQUIRED)
362356
else()
363-
find_path(FFI_INCLUDE_PATH ffi/ffi.h PATHS ${FFI_INCLUDE_DIR})
364-
if( EXISTS "${FFI_INCLUDE_PATH}/ffi/ffi.h" )
365-
set(FFI_HEADER ffi/ffi.h CACHE INTERNAL "")
366-
set(HAVE_FFI_FFI_H 1 CACHE INTERNAL "")
367-
endif()
357+
find_package(FFI)
368358
endif()
369-
370-
if( NOT FFI_HEADER )
371-
message(FATAL_ERROR "libffi includes are not found.")
372-
endif()
373-
374-
find_library(FFI_LIBRARY_PATH ffi PATHS ${FFI_LIBRARY_DIR})
375-
if( NOT FFI_LIBRARY_PATH )
376-
message(FATAL_ERROR "libffi is not found.")
377-
endif()
378-
379-
list(APPEND CMAKE_REQUIRED_LIBRARIES ${FFI_LIBRARY_PATH})
380-
list(APPEND CMAKE_REQUIRED_INCLUDES ${FFI_INCLUDE_PATH})
381-
check_symbol_exists(ffi_call ${FFI_HEADER} HAVE_FFI_CALL)
382-
list(REMOVE_ITEM CMAKE_REQUIRED_INCLUDES ${FFI_INCLUDE_PATH})
383-
list(REMOVE_ITEM CMAKE_REQUIRED_LIBRARIES ${FFI_LIBRARY_PATH})
359+
set(LLVM_ENABLE_FFI "${FFI_FOUND}")
384360
else()
385361
unset(HAVE_FFI_FFI_H CACHE)
386362
unset(HAVE_FFI_H CACHE)
387363
unset(HAVE_FFI_CALL CACHE)
388-
endif( LLVM_ENABLE_FFI )
364+
endif()
389365

390366
check_symbol_exists(proc_pid_rusage "libproc.h" HAVE_PROC_PID_RUSAGE)
391367

llvm/cmake/modules/FindFFI.cmake

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
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+
# HAVE_FFI_CALL
19+
#
20+
# HAVE_FFI_H or HAVE_FFI_FFI_H is defined depending on the ffi.h include path.
21+
#
22+
# Additionally, the following import target will be defined:
23+
# FFI::ffi
24+
25+
find_path(FFI_INCLUDE_DIRS ffi.h PATHS ${FFI_INCLUDE_DIR})
26+
if( EXISTS "${FFI_INCLUDE_DIRS}/ffi.h" )
27+
set(FFI_HEADER ffi.h CACHE INTERNAL "")
28+
set(HAVE_FFI_H 1 CACHE INTERNAL "")
29+
else()
30+
find_path(FFI_INCLUDE_DIRS ffi/ffi.h PATHS ${FFI_INCLUDE_DIR})
31+
if( EXISTS "${FFI_INCLUDE_DIRS}/ffi/ffi.h" )
32+
set(FFI_HEADER ffi/ffi.h CACHE INTERNAL "")
33+
set(HAVE_FFI_FFI_H 1 CACHE INTERNAL "")
34+
endif()
35+
endif()
36+
37+
find_library(FFI_LIBRARIES ffi PATHS ${FFI_LIBRARY_DIR})
38+
39+
if(FFI_LIBRARIES)
40+
include(CMakePushCheckState)
41+
include(CheckCSourceCompiles)
42+
cmake_push_check_state()
43+
list(APPEND CMAKE_REQUIRED_LIBRARIES ${FFI_LIBRARIES})
44+
check_c_source_compiles("
45+
struct ffi_cif;
46+
typedef struct ffi_cif ffi_cif;
47+
void ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue);
48+
int main() { ffi_call(0, 0, 0, 0); }"
49+
HAVE_FFI_CALL)
50+
cmake_pop_check_state()
51+
endif()
52+
53+
unset(required_includes)
54+
if(FFI_REQUIRE_INCLUDE)
55+
set(required_includes FFI_INCLUDE_DIRS)
56+
endif()
57+
58+
include(FindPackageHandleStandardArgs)
59+
find_package_handle_standard_args(FFI
60+
FOUND_VAR
61+
FFI_FOUND
62+
REQUIRED_VARS
63+
FFI_LIBRARIES
64+
${required_includes}
65+
HAVE_FFI_CALL)
66+
mark_as_advanced(FFI_LIBRARIES
67+
FFI_INCLUDE_DIRS
68+
HAVE_FFI_CALL
69+
FFI_HEADER
70+
HAVE_FFI_H
71+
HAVE_FFI_FFI_H)
72+
73+
if(FFI_FOUND)
74+
if(NOT TARGET FFI::ffi)
75+
add_library(FFI::ffi UNKNOWN IMPORTED)
76+
set_target_properties(FFI::ffi PROPERTIES IMPORTED_LOCATION "${FFI_LIBRARIES}")
77+
if(FFI_INCLUDE_DIRS)
78+
set_target_properties(FFI::ffi PROPERTIES INTERFACE_INCLUDE_DIRECTORIES "${FFI_INCLUDE_DIRS}")
79+
endif()
80+
endif()
81+
endif()
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
# Attempts to discover terminfo library with a linkable setupterm function.
2+
#
3+
# Example usage:
4+
#
5+
# find_package(Terminfo)
6+
#
7+
# If successful, the following variables will be defined:
8+
# Terminfo_FOUND
9+
# Terminfo_LIBRARIES
10+
#
11+
# Additionally, the following import target will be defined:
12+
# Terminfo::terminfo
13+
14+
find_library(Terminfo_LIBRARIES NAMES terminfo tinfo curses ncurses ncursesw)
15+
16+
if(Terminfo_LIBRARIES)
17+
include(CMakePushCheckState)
18+
include(CheckCSourceCompiles)
19+
cmake_push_check_state()
20+
list(APPEND CMAKE_REQUIRED_LIBRARIES ${Terminfo_LIBRARIES})
21+
check_c_source_compiles("
22+
int setupterm(char *term, int filedes, int *errret);
23+
int main() { return setupterm(0, 0, 0); }"
24+
Terminfo_LINKABLE)
25+
cmake_pop_check_state()
26+
endif()
27+
28+
include(FindPackageHandleStandardArgs)
29+
find_package_handle_standard_args(Terminfo
30+
FOUND_VAR
31+
Terminfo_FOUND
32+
REQUIRED_VARS
33+
Terminfo_LIBRARIES
34+
Terminfo_LINKABLE)
35+
mark_as_advanced(Terminfo_LIBRARIES
36+
Terminfo_LINKABLE)
37+
38+
if(Terminfo_FOUND)
39+
if(NOT TARGET Terminfo::terminfo)
40+
add_library(Terminfo::terminfo UNKNOWN IMPORTED)
41+
set_target_properties(Terminfo::terminfo PROPERTIES IMPORTED_LOCATION "${Terminfo_LIBRARIES}")
42+
endif()
43+
endif()

llvm/cmake/modules/LLVMConfig.cmake.in

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,9 @@
22

33
@LLVM_CONFIG_CODE@
44

5+
# For finding self-installed Find*.cmake packages.
6+
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}")
7+
58
set(LLVM_VERSION_MAJOR @LLVM_VERSION_MAJOR@)
69
set(LLVM_VERSION_MINOR @LLVM_VERSION_MINOR@)
710
set(LLVM_VERSION_PATCH @LLVM_VERSION_PATCH@)
@@ -48,9 +51,17 @@ set(LLVM_ENABLE_ASSERTIONS @LLVM_ENABLE_ASSERTIONS@)
4851

4952
set(LLVM_ENABLE_EH @LLVM_ENABLE_EH@)
5053

54+
set(LLVM_ENABLE_FFI @LLVM_ENABLE_FFI@)
55+
if(LLVM_ENABLE_FFI)
56+
find_package(FFI)
57+
endif()
58+
5159
set(LLVM_ENABLE_RTTI @LLVM_ENABLE_RTTI@)
5260

5361
set(LLVM_ENABLE_TERMINFO @LLVM_ENABLE_TERMINFO@)
62+
if(LLVM_ENABLE_TERMINFO)
63+
find_package(Terminfo)
64+
endif()
5465

5566
set(LLVM_ENABLE_THREADS @LLVM_ENABLE_THREADS@)
5667

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,3 @@
1-
# Make sure that the path to libffi headers is on the command
2-
# line. That path can be a compiler's non-default path even when
3-
# FFI_INCLUDE_DIR was not used, because cmake has its own paths for
4-
# searching for headers (CMAKE_SYSTEM_INCLUDE_PATH, for instance):
5-
if( FFI_INCLUDE_PATH )
6-
include_directories( ${FFI_INCLUDE_PATH} )
7-
endif()
8-
91
add_llvm_component_library(LLVMInterpreter
102
Execution.cpp
113
ExternalFunctions.cpp
@@ -22,5 +14,5 @@ add_llvm_component_library(LLVMInterpreter
2214
)
2315

2416
if( LLVM_ENABLE_FFI )
25-
target_link_libraries( LLVMInterpreter PRIVATE ${FFI_LIBRARY_PATH} )
17+
target_link_libraries( LLVMInterpreter PRIVATE FFI::ffi )
2618
endif()

llvm/lib/Support/CMakeLists.txt

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ elseif( CMAKE_HOST_UNIX )
4545
set(system_libs ${system_libs} ${Backtrace_LIBFILE})
4646
endif()
4747
if( LLVM_ENABLE_TERMINFO )
48-
set(imported_libs ${imported_libs} "${TERMINFO_LIB}")
48+
set(imported_libs ${imported_libs} Terminfo::terminfo)
4949
endif()
5050
if( LLVM_ENABLE_THREADS AND (HAVE_LIBATOMIC OR HAVE_CXX_LIBATOMICS64) )
5151
set(system_libs ${system_libs} atomic)
@@ -287,7 +287,10 @@ if(LLVM_ENABLE_ZLIB)
287287
endif()
288288

289289
if(LLVM_ENABLE_TERMINFO)
290-
get_library_name(${TERMINFO_LIB} terminfo_library)
290+
if(NOT terminfo_library)
291+
get_property(terminfo_library TARGET Terminfo::terminfo PROPERTY LOCATION)
292+
endif()
293+
get_library_name(${terminfo_library} terminfo_library)
291294
set(llvm_system_libs ${llvm_system_libs} "${terminfo_library}")
292295
endif()
293296

0 commit comments

Comments
 (0)