Files
opm-common/cmake/Modules/OpmFind.cmake
Markus Blatt ff9792e31c Work around issues of Boost >=1.70.0 and CMake 3.18.4
With that combination the first search seems to happen in CONFIG mode
but subsequent searches will use MODULE mode. This will result in the
following warning:

CMake Warning at /usr/share/cmake-3.18/Modules/FindBoost.cmake:1187 (message):
  New Boost version may have incorrect or missing dependencies and imported
  targets
Call Stack (most recent call first):
  /usr/share/cmake-3.18/Modules/FindBoost.cmake:1311 (_Boost_COMPONENT_DEPENDENCIES)
  /usr/share/cmake-3.18/Modules/FindBoost.cmake:1919 (_Boost_MISSING_DEPENDENCIES)
  cmake/Modules/OpmFind.cmake:135 (find_package)
  cmake/Modules/OpmFind.cmake:230 (find_and_append_package_to)
  cmake/Modules/OpmLibMain.cmake:83 (find_and_append_package_list_to)
  CMakeLists.txt:222 (include)

Also the variable Boost_LIBRARIES will look quite messed up by
occurrences of optimized and debug:
Boost_LIBRARIES=optimized;/usr/lib/x86_64-linux-gnu/libboost_system.so.1.74.0;debug;/usr/lib/x86_64-linux-gnu/libboost_system.so;optimized;/usr/lib/x86_64-linux-gnu/libboost_unit_test_framework.so.1.74.0;debug;/usr/lib/x86_64-linux-gnu/libboost_unit_test_framework.so

Which will make the modules unusable because of CMake errors during
linking:

CMake Error at /usr/share/dune/cmake/modules/DuneMacros.cmake:991 (target_link_libraries):
  The "debug" argument must be followed by a library.
Call Stack (most recent call first):
  src/CMakeLists.txt:2 (target_link_dune_default_libraries)
-- Configuring incomplete, errors occurred!

Note this fix is only needed for Boost versions 1.70 and higher.
Older versions do not provide cmake package configuration
files (BoostConfig.cmake) and hence there can be no mixup.

Note also that the alternative approach of setting
CMAKE_FIND_PACKAGE_PREFER_CONFIG does not work for OPM as with this
e.g. the Dune module versions would not be set correctly.
2021-06-15 21:04:41 +02:00

244 lines
9.8 KiB
CMake

# - Generic inclusion of packages
#
# Synopsis:
#
# find_and_append_package (name args)
#
# where
#
# name Name of the package, e.g. Boost
# args Other arguments, e.g. COMPONENTS, REQUIRED, QUIET etc.
#
# This macro will append the list of standard variables found by the
# package to this project's standard variables
#
########################################################################
#
# - Generic inclusion of a list of packages
#
# Synopsis:
#
# find_and_append_package_list (args)
#
# where
#
# args List of package strings. Each string must be quoted if
# it contains more than one word.
#
# Example:
#
# find_and_append_package_list (
# "Boost COMPONENTS filesystem REQUIRED"
# SUPERLU
# )
include (Duplicates)
include (OpmSiblingSearch)
# list of suffixes for all the project variables
set (_opm_proj_vars
SOURCES
LINKER_FLAGS
LIBRARIES
DEFINITIONS
INCLUDE_DIRS
LIBRARY_DIRS
CONFIG_VARS
CONFIG_IMPL_VARS
)
# ensure that they are at least the empty list after we're done
foreach (name IN LISTS _opm_proj_vars)
if (NOT DEFINED ${CMAKE_PROJECT_NAME}_${name})
set (${CMAKE_PROJECT_NAME}_${name} "")
endif (NOT DEFINED ${CMAKE_PROJECT_NAME}_${name})
endforeach (name)
# insert this boilerplate whenever we are going to find a new package
macro (find_and_append_package_to prefix name)
# special handling for Boost to avoid inadvertedly picking up system
# libraries when we want our own version. this is done here because
# having a custom Boost is common, but the logic to search only there
# does not follow any particular convention.
if (BOOST_ROOT AND NOT DEFINED Boost_NO_SYSTEM_PATHS)
set (Boost_NO_SYSTEM_PATHS TRUE)
endif (BOOST_ROOT AND NOT DEFINED Boost_NO_SYSTEM_PATHS)
# if we have specified a directory, don't revert to searching the
# system default paths afterwards
string (TOUPPER "${name}" NAME)
string (REPLACE "-" "_" NAME "${NAME}")
# only use suite if module-specific variable is not set. this allows
# us to override one dir in a suite
if (NOT (${name}_DIR OR ${name}_ROOT OR ${NAME}_ROOT))
# module is part of a suite if it has name with the pattern xxx-yyy
if (("${name}" MATCHES "[^-]+-.+") OR ${name}_SUITE)
# allow to override if the module doesn't quite fit the convention
# e.g. dune-cornerpoint (since renamed to opm-grid)
if (NOT DEFINED ${name}_SUITE)
# extract suite name from module
string (REGEX REPLACE "([^-]+)-.+" "\\1" ${name}_SUITE "${name}")
endif (NOT DEFINED ${name}_SUITE)
# assume that each module has its own subdir directly under suite dir
string (TOUPPER "${${name}_SUITE}" ${name}_SUITE_UPPER)
if (DEFINED ${${name}_SUITE_UPPER}_ROOT)
set (${NAME}_ROOT ${${${name}_SUITE_UPPER}_ROOT}/${name})
endif (DEFINED ${${name}_SUITE_UPPER}_ROOT)
endif (("${name}" MATCHES "[^-]+-.+") OR ${name}_SUITE)
endif (NOT (${name}_DIR OR ${name}_ROOT OR ${NAME}_ROOT))
# the documentation says that if *-config.cmake files are not found,
# find_package will revert to doing a full search, but that is not
# true, so unconditionally setting ${name}_DIR is not safe. however,
# if the directory given to us contains a config file, then copy the
# value over to this variable to switch to config mode (CMake will
# always use config mode if *_DIR is defined)
if (NOT DEFINED ${name}_DIR AND (DEFINED ${name}_ROOT OR DEFINED ${NAME}_ROOT))
if (EXISTS ${${name}_ROOT}/${name}-config.cmake OR EXISTS ${${name}_ROOT}/${name}Config.cmake)
set (${name}_DIR "${${name}_ROOT}")
endif (EXISTS ${${name}_ROOT}/${name}-config.cmake OR EXISTS ${${name}_ROOT}/${name}Config.cmake)
if (EXISTS ${${NAME}_ROOT}/${name}-config.cmake OR EXISTS ${${NAME}_ROOT}/${name}Config.cmake)
set (${name}_DIR "${${NAME}_ROOT}")
endif (EXISTS ${${NAME}_ROOT}/${name}-config.cmake OR EXISTS ${${NAME}_ROOT}/${name}Config.cmake)
endif (NOT DEFINED ${name}_DIR AND (DEFINED ${name}_ROOT OR DEFINED ${NAME}_ROOT))
# if we're told not to look for the package, pretend it was never found
if (CMAKE_DISABLE_FIND_PACKAGE_${name})
# If required send an error
cmake_parse_arguments(FIND "REQUIRED" "" "" ${ARGN} )
set (${name}_FOUND FALSE)
set (${NAME}_FOUND FALSE)
if (FIND_REQUIRED)
message(SEND_ERROR "package ${name} but disable with CMAKE_DISABLE_FIND_PACKAGE_${name}")
endif ()
else ()
# List of components might differ for every module. Therefore we will
# need to research for a library multiple times. _search_components
# will hold the index of the string COMPONENTS in the list
set(_ARGN_LIST ${ARGN}) # Create a real list to use with list commands
list(FIND _ARGN_LIST "COMPONENTS" _search_components)
# using config mode is better than using module (aka. find) mode
# because then the package has already done all its probes and
# stored them in the config file for us
# For dune and opm modules and exempted packages we force module mode.
# For dune and opm it will use config mode underneath.
# We even need to repeat the search for opm-common once as this is done
# in the top most CMakeLists.txt without querying defines, setting dependencies
# and the likes which is only done via opm_find_package
if ( (NOT DEFINED ${name}_FOUND AND NOT DEFINED ${NAME}_FOUND )
OR _search_components GREATER -1)
string(REGEX MATCH "(opm)-.*" _is_opm ${name})
if(NOT _is_opm)
# When using Boost >= 1.70 and e.g. CMake 3.18 we need to make sure that
# subsequent searches are using config mode too. Otherwise the library
# list will be completely messed up. We use a set Boost_Dir to detect that
# previous searches were done using config mode.
if("${name}" STREQUAL "Boost" AND Boost_DIR)
set(_CONFIG_MODE CONFIG)
else()
set(_CONFIG_MODE "")
endif()
find_package (${name} ${ARGN} ${_CONFIG_MODE})
else()
if(${name}_DIR)
find_package (${name} ${${prefix}_VERSION_MAJOR}.${${prefix}_VERSION_MINOR} ${ARGN} NO_MODULE PATHS ${${name}_DIR} NO_DEFAULT_PATH)
else()
find_package (${name} ${${prefix}_VERSION_MAJOR}.${${prefix}_VERSION_MINOR} ${ARGN} NO_MODULE)
endif()
include(FindPackageHandleStandardArgs)
if(${name}_FOUND AND ${name}_LIBRARY STREQUAL "")
find_package_handle_standard_args(${name}
REQUIRED_VARS ${name}_INCLUDE_DIRS)
else()
find_package_handle_standard_args(${name}
REQUIRED_VARS ${name}_LIBRARY)
endif()
endif ()
endif ()
if (NOT DEFINED ${name}_FOUND)
set (${name}_FOUND "${${NAME}_FOUND}")
endif ()
if (NOT DEFINED ${NAME}_FOUND)
set (${NAME}_FOUND "${${name}_FOUND}")
endif ()
endif ()
# the variable "NAME" may be replaced during find_package (as this is
# now a macro, and not a function anymore), so we must reinitialize
string (TOUPPER "${name}" NAME)
string (REPLACE "-" "_" NAME "${NAME}")
if (${name}_FOUND OR ${NAME}_FOUND)
foreach (var IN LISTS _opm_proj_vars)
if("${var}" STREQUAL "DEFINITIONS"
AND CMAKE_VERSION VERSION_LESS "3.12")
# For old Cmake versions we use add_definitions which
# requires -D qualifier add that
set(_defs)
foreach(_def IN LISTS ${name}_${var})
if(_def MATCHES "^[a-zA-Z].*")
list(APPEND _defs "-D${_def}")
else()
list(APPEND _defs "${_def}")
endif()
endforeach()
set(${name}_${var} "${_defs}")
endif()
if (DEFINED ${name}_${var})
list (APPEND ${prefix}_${var} ${${name}_${var}})
# some packages define an uppercase version of their own name
elseif (DEFINED ${NAME}_${var})
list (APPEND ${prefix}_${var} ${${NAME}_${var}})
endif (DEFINED ${name}_${var})
# some packages define _PATH instead of _DIRS (Hi, MPI!)
if ("${var}" STREQUAL "INCLUDE_DIRS")
if (DEFINED ${name}_INCLUDE_PATH)
list (APPEND ${prefix}_INCLUDE_DIRS ${${name}_INCLUDE_PATH})
elseif (DEFINED ${NAME}_INCLUDE_PATH)
list (APPEND ${prefix}_INCLUDE_DIRS ${${NAME}_INCLUDE_PATH})
endif (DEFINED ${name}_INCLUDE_PATH)
# some packages define only _DIR and not _DIRS (Hi, Eigen3!)
if (DEFINED ${name}_INCLUDE_DIR)
list (APPEND ${prefix}_INCLUDE_DIRS ${${name}_INCLUDE_DIR})
elseif (DEFINED ${NAME}_INCLUDE_DIR)
list (APPEND ${prefix}_INCLUDE_DIRS ${${NAME}_INCLUDE_DIR})
endif (DEFINED ${name}_INCLUDE_DIR)
endif ("${var}" STREQUAL "INCLUDE_DIRS")
# cleanup lists
if ("${var}" STREQUAL "LIBRARIES")
remove_duplicate_libraries (${prefix})
else ("${var}" STREQUAL "LIBRARIES")
remove_duplicate_var (${prefix} ${var})
endif ("${var}" STREQUAL "LIBRARIES")
endforeach (var)
# some libraries only define xxx_FOUND and not a corresponding HAVE_xxx
if (NOT DEFINED HAVE_${NAME})
set (HAVE_${NAME} 1)
endif (NOT DEFINED HAVE_${NAME})
endif (${name}_FOUND OR ${NAME}_FOUND)
endmacro (find_and_append_package_to prefix name)
# append to the list of variables associated with the project
macro (find_and_append_package name)
find_and_append_package_to (${CMAKE_PROJECT_NAME} ${name} ${ARGN})
endmacro (find_and_append_package name)
# find a list of dependencies, adding each one of them
macro (find_and_append_package_list_to prefix)
# setting and separating is necessary to work around apparent bugs
# in CMake's parser (sic)
set (_deps ${ARGN})
foreach (_dep IN LISTS _deps)
separate_arguments (_args UNIX_COMMAND ${_dep})
find_and_append_package_to (${prefix} ${_args})
endforeach (_dep)
endmacro (find_and_append_package_list_to prefix)
# convenience method to supply the project name as prefix
macro (find_and_append_package_list)
find_and_append_package_list_to (${CMAKE_PROJECT_NAME} ${ARGN})
endmacro (find_and_append_package_list)