|
| 1 | +INCLUDE(CheckCXXSourceRuns) |
| 2 | + |
| 3 | +# Function to check Z3's version |
| 4 | +function(check_z3_version z3_include z3_lib) |
| 5 | + # Get lib path |
| 6 | + get_filename_component(z3_lib_path ${z3_lib} PATH) |
| 7 | + |
| 8 | + # Try to find a threading module in case Z3 was built with threading support. |
| 9 | + # Threads are required elsewhere in LLVM, but not marked as required here because |
| 10 | + # Z3 could have been compiled without threading support. |
| 11 | + find_package(Threads) |
| 12 | + set(z3_link_libs "-lz3" "${CMAKE_THREAD_LIBS_INIT}") |
| 13 | + |
| 14 | + try_run( |
| 15 | + Z3_RETURNCODE |
| 16 | + Z3_COMPILED |
| 17 | + ${CMAKE_BINARY_DIR} |
| 18 | + ${CMAKE_SOURCE_DIR}/cmake/modules/testz3.cpp |
| 19 | + COMPILE_DEFINITIONS -I"${z3_include}" |
| 20 | + LINK_LIBRARIES -L${z3_lib_path} ${z3_link_libs} |
| 21 | + RUN_OUTPUT_VARIABLE SRC_OUTPUT |
| 22 | + ) |
| 23 | + |
| 24 | + if(Z3_COMPILED) |
| 25 | + string(REGEX REPLACE "([0-9]*\\.[0-9]*\\.[0-9]*)" "\\1" |
| 26 | + z3_version "${SRC_OUTPUT}") |
| 27 | + set(Z3_VERSION_STRING ${z3_version} PARENT_SCOPE) |
| 28 | + endif() |
| 29 | +endfunction(check_z3_version) |
| 30 | + |
| 31 | +# Looking for Z3 in LLVM_Z3_INSTALL_DIR |
| 32 | +find_path(Z3_INCLUDE_DIR NAMES z3.h |
| 33 | + NO_DEFAULT_PATH |
| 34 | + PATHS ${LLVM_Z3_INSTALL_DIR}/include |
| 35 | + PATH_SUFFIXES libz3 z3 |
| 36 | + ) |
| 37 | + |
| 38 | +find_library(Z3_LIBRARIES NAMES z3 libz3 |
| 39 | + NO_DEFAULT_PATH |
| 40 | + PATHS ${LLVM_Z3_INSTALL_DIR} |
| 41 | + PATH_SUFFIXES lib bin |
| 42 | + ) |
| 43 | + |
| 44 | +# If Z3 has not been found in LLVM_Z3_INSTALL_DIR look in the default directories |
| 45 | +find_path(Z3_INCLUDE_DIR NAMES z3.h |
| 46 | + PATH_SUFFIXES libz3 z3 |
| 47 | + ) |
| 48 | + |
| 49 | +find_library(Z3_LIBRARIES NAMES z3 libz3 |
| 50 | + PATH_SUFFIXES lib bin |
| 51 | + ) |
| 52 | + |
| 53 | +# Searching for the version of the Z3 library is a best-effort task |
| 54 | +unset(Z3_VERSION_STRING) |
| 55 | + |
| 56 | +# First, try to check it dynamically, by compiling a small program that |
| 57 | +# prints Z3's version |
| 58 | +if(Z3_INCLUDE_DIR AND Z3_LIBRARIES) |
| 59 | + # We do not have the Z3 binary to query for a version. Try to use |
| 60 | + # a small C++ program to detect it via the Z3_get_version() API call. |
| 61 | + check_z3_version(${Z3_INCLUDE_DIR} ${Z3_LIBRARIES}) |
| 62 | +endif() |
| 63 | + |
| 64 | +# If the dynamic check fails, we might be cross compiling: if that's the case, |
| 65 | +# check the version in the headers, otherwise, fail with a message |
| 66 | +if(NOT Z3_VERSION_STRING AND (CMAKE_CROSSCOMPILING AND |
| 67 | + Z3_INCLUDE_DIR AND |
| 68 | + EXISTS "${Z3_INCLUDE_DIR}/z3_version.h")) |
| 69 | + # TODO: print message warning that we couldn't find a compatible lib? |
| 70 | + |
| 71 | + # Z3 4.8.1+ has the version is in a public header. |
| 72 | + file(STRINGS "${Z3_INCLUDE_DIR}/z3_version.h" |
| 73 | + z3_version_str REGEX "^#define[\t ]+Z3_MAJOR_VERSION[\t ]+.*") |
| 74 | + string(REGEX REPLACE "^.*Z3_MAJOR_VERSION[\t ]+([0-9]).*$" "\\1" |
| 75 | + Z3_MAJOR "${z3_version_str}") |
| 76 | + |
| 77 | + file(STRINGS "${Z3_INCLUDE_DIR}/z3_version.h" |
| 78 | + z3_version_str REGEX "^#define[\t ]+Z3_MINOR_VERSION[\t ]+.*") |
| 79 | + string(REGEX REPLACE "^.*Z3_MINOR_VERSION[\t ]+([0-9]).*$" "\\1" |
| 80 | + Z3_MINOR "${z3_version_str}") |
| 81 | + |
| 82 | + file(STRINGS "${Z3_INCLUDE_DIR}/z3_version.h" |
| 83 | + z3_version_str REGEX "^#define[\t ]+Z3_BUILD_NUMBER[\t ]+.*") |
| 84 | + string(REGEX REPLACE "^.*Z3_BUILD_VERSION[\t ]+([0-9]).*$" "\\1" |
| 85 | + Z3_BUILD "${z3_version_str}") |
| 86 | + |
| 87 | + set(Z3_VERSION_STRING ${Z3_MAJOR}.${Z3_MINOR}.${Z3_BUILD}) |
| 88 | + unset(z3_version_str) |
| 89 | +endif() |
| 90 | + |
| 91 | +if(NOT Z3_VERSION_STRING) |
| 92 | + # Give up: we are unable to obtain a version of the Z3 library. Be |
| 93 | + # conservative and force the found version to 0.0.0 to make version |
| 94 | + # checks always fail. |
| 95 | + set(Z3_VERSION_STRING "0.0.0") |
| 96 | +endif() |
| 97 | + |
| 98 | +# handle the QUIETLY and REQUIRED arguments and set Z3_FOUND to TRUE if |
| 99 | +# all listed variables are TRUE |
| 100 | +include(FindPackageHandleStandardArgs) |
| 101 | +FIND_PACKAGE_HANDLE_STANDARD_ARGS(Z3 |
| 102 | + REQUIRED_VARS Z3_LIBRARIES Z3_INCLUDE_DIR |
| 103 | + VERSION_VAR Z3_VERSION_STRING) |
| 104 | + |
| 105 | +mark_as_advanced(Z3_INCLUDE_DIR Z3_LIBRARIES) |
0 commit comments