From 41c4a0869d68d894cbe74a63612df75fd1e93bdf Mon Sep 17 00:00:00 2001 From: Michael Orlitzky Date: Mon, 19 Apr 2021 16:56:54 -0400 Subject: [PATCH 1/1] CMake/FindGMP.cmake: compile a test program to check the gmp version. The existing GMP version check consists of grepping the contents of the gmp.h header to parse out a few constants. This test fails, at least, on Gentoo, where the usual header file is a wrapper that includes the true header to allow for simultaneous 32/64-bit support. This commit updates FindGMP to compile a test program against gmp.h that compares version constants using the C preprocessor. If GMP is too old, the test program will fail to compile and CMake will know. --- CMake/FindGMP.cmake | 91 +++++++++++++++++++++++---------------------- 1 file changed, 47 insertions(+), 44 deletions(-) diff --git a/CMake/FindGMP.cmake b/CMake/FindGMP.cmake index ce4df70f5..951151274 100644 --- a/CMake/FindGMP.cmake +++ b/CMake/FindGMP.cmake @@ -2,28 +2,23 @@ # https://gmplib.org/ # # This module supports requiring a minimum version, e.g. you can do -# find_package(GMP 6.0.0) -# to require version 6.0.0 to newer of GMP. +# find_package(GMP 6.2.1) +# to require version 6.2.1 to newer of GMP. # # Once done this will define # # GMP_FOUND - system has GMP lib with correct version # GMP_INCLUDE_DIRS - the GMP include directory # GMP_LIBRARIES - the GMP library -# GMP_VERSION - GMP version # -# Copyright (c) 2016 Jack Poulson, -# Redistribution and use is allowed according to the terms of the BSD license. -find_path(GMP_INCLUDE_DIRS NAMES gmp.h PATHS $ENV{GMPDIR} ${INCLUDE_INSTALL_DIR}) - -# Set GMP_FIND_VERSION to 5.1.0 if no minimum version is specified +# Set GMP_FIND_VERSION to 6.0.0 if no minimum version is specified if(NOT GMP_FIND_VERSION) if(NOT GMP_FIND_VERSION_MAJOR) - set(GMP_FIND_VERSION_MAJOR 5) + set(GMP_FIND_VERSION_MAJOR 6) endif() if(NOT GMP_FIND_VERSION_MINOR) - set(GMP_FIND_VERSION_MINOR 1) + set(GMP_FIND_VERSION_MINOR 0) endif() if(NOT GMP_FIND_VERSION_PATCH) set(GMP_FIND_VERSION_PATCH 0) @@ -32,43 +27,51 @@ if(NOT GMP_FIND_VERSION) "${GMP_FIND_VERSION_MAJOR}.${GMP_FIND_VERSION_MINOR}.${GMP_FIND_VERSION_PATCH}") endif() -if(GMP_INCLUDE_DIRS) - # Since the GMP version macros may be in a file included by gmp.h of the form - # gmp-.*[_]?.*.h (e.g., gmp-x86_64.h), we search each of them. - file(GLOB GMP_HEADERS "${GMP_INCLUDE_DIRS}/gmp.h" "${GMP_INCLUDE_DIRS}/gmp-*.h" - "${GMP_INCLUDE_DIRS}/x86*/gmp.h") - foreach(gmp_header_filename ${GMP_HEADERS}) - file(READ "${gmp_header_filename}" _gmp_version_header) - string(REGEX MATCH - "define[ \t]+__GNU_MP_VERSION[ \t]+([0-9]+)" _gmp_major_version_match - "${_gmp_version_header}") - if(_gmp_major_version_match) - set(GMP_MAJOR_VERSION "${CMAKE_MATCH_1}") - string(REGEX MATCH "define[ \t]+__GNU_MP_VERSION_MINOR[ \t]+([0-9]+)" - _gmp_minor_version_match "${_gmp_version_header}") - set(GMP_MINOR_VERSION "${CMAKE_MATCH_1}") - string(REGEX MATCH "define[ \t]+__GNU_MP_VERSION_PATCHLEVEL[ \t]+([0-9]+)" - _gmp_patchlevel_version_match "${_gmp_version_header}") - set(GMP_PATCHLEVEL_VERSION "${CMAKE_MATCH_1}") - set(GMP_VERSION - ${GMP_MAJOR_VERSION}.${GMP_MINOR_VERSION}.${GMP_PATCHLEVEL_VERSION}) - endif() - endforeach() +find_path(GMP_INCLUDE_DIRS + NAMES gmp.h + PATHS $ENV{GMPDIR} ${INCLUDE_INSTALL_DIR}) - # Check whether found version exists and exceeds the minimum requirement - if(NOT GMP_VERSION) - set(GMP_VERSION_OK FALSE) - message(STATUS "GMP version was not detected") - elseif(${GMP_VERSION} VERSION_LESS ${GMP_FIND_VERSION}) - set(GMP_VERSION_OK FALSE) - message(STATUS "GMP version ${GMP_VERSION} found in ${GMP_INCLUDE_DIRS}, " - "but at least version ${GMP_FIND_VERSION} is required") - else() - set(GMP_VERSION_OK TRUE) - endif() +find_library(GMP_LIBRARIES + gmp + PATHS $ENV{GMPDIR} ${LIB_INSTALL_DIR}) + +if(GMP_INCLUDE_DIRS AND GMP_LIBRARIES) + + # This program will fail to compile if GMP is too old. + # We prefer to perform this "test" at compile-time to + # avoid problems with e.g. try_run() during cross-compilation. + file(WRITE ${PROJECT_BINARY_DIR}/gmp-version-check.c "" + "#include \n" + "\n" + "#define GMP_FIND_VERSION_MAJOR ${GMP_FIND_VERSION_MAJOR}\n" + "#define GMP_FIND_VERSION_MINOR ${GMP_FIND_VERSION_MINOR}\n" + "#define GMP_FIND_VERSION_PATCH ${GMP_FIND_VERSION_PATCH}\n" + "\n" + "#if __GNU_MP_VERSION < GMP_FIND_VERSION_MAJOR\n" + "#error insufficient GMP major version\n" + "#elif __GNU_MP_VERSION == GMP_FIND_VERSION_MAJOR\n" + "#if __GNU_MP_VERSION_MINOR < GMP_FIND_VERSION_MINOR\n" + "#error insufficient GMP minor version\n" + "#elif __GNU_MP_VERSION_MINOR == GMP_FIND_VERSION_MINOR\n" + "#if __GNU_MP_VERSION_PATCH < GMP_FIND_VERSION_PATCH\n" + "#error insufficient GMP patch version\n" + "#endif\n" + "#endif\n" + "#endif\n" + "\n" + "int main(int argc, char** argv) { return 0; }\n") + + # Try to compile the test program above with the appropriate version + # strings substituted in. + try_compile(GMP_VERSION_OK + "${PROJECT_BINARY_DIR}" + "${PROJECT_BINARY_DIR}/gmp-version-check.c" + CMAKE_FLAGS "-DINCLUDE_DIRECTORIES=${GMP_INCLUDE_DIRS}") endif() -find_library(GMP_LIBRARIES gmp PATHS $ENV{GMPDIR} ${LIB_INSTALL_DIR}) +if(NOT GMP_VERSION_OK) + message(STATUS "No sufficient GMP version detected") +endif() include(FindPackageHandleStandardArgs) find_package_handle_standard_args(GMP DEFAULT_MSG -- 2.26.3