From d481756918781e21e68c30987eb9750ae9612020 Mon Sep 17 00:00:00 2001 From: maier Date: Thu, 15 May 2014 22:17:20 +0000 Subject: [PATCH] CMake: Finalize overhaul: * Switch Boost as well. * Refactor configure/configure_* stuff * Update documentation git-svn-id: https://svn.dealii.org/trunk@32915 0785d39b-7218-0410-832d-ea1e28bc413d --- deal.II/cmake/configure/configure_1_mpi.cmake | 1 + .../cmake/configure/configure_1_threads.cmake | 2 - .../cmake/configure/configure_2_metis.cmake | 7 +- .../cmake/configure/configure_2_umfpack.cmake | 2 +- .../cmake/configure/configure_3_petsc.cmake | 4 +- .../cmake/configure/configure_arpack.cmake | 2 +- deal.II/cmake/configure/configure_boost.cmake | 86 ------------------- deal.II/cmake/configure/configure_hdf5.cmake | 11 +-- deal.II/cmake/configure/configure_mumps.cmake | 2 +- .../cmake/configure/configure_muparser.cmake | 1 + deal.II/cmake/configure/configure_p4est.cmake | 3 +- deal.II/cmake/configure/configure_slepc.cmake | 3 +- .../macros/macro_configure_feature.cmake | 25 ++++-- deal.II/cmake/modules/FindBOOST.cmake | 82 ++++++++++++++++++ deal.II/doc/developers/cmake-internals.html | 81 ++++++++++------- 15 files changed, 164 insertions(+), 148 deletions(-) create mode 100644 deal.II/cmake/modules/FindBOOST.cmake diff --git a/deal.II/cmake/configure/configure_1_mpi.cmake b/deal.II/cmake/configure/configure_1_mpi.cmake index 8001da4318..7c0bda441d 100644 --- a/deal.II/cmake/configure/configure_1_mpi.cmake +++ b/deal.II/cmake/configure/configure_1_mpi.cmake @@ -34,4 +34,5 @@ MACRO(FEATURE_MPI_ERROR_MESSAGE) ) ENDMACRO() + CONFIGURE_FEATURE(MPI) diff --git a/deal.II/cmake/configure/configure_1_threads.cmake b/deal.II/cmake/configure/configure_1_threads.cmake index 4a697a8358..f07f29725d 100644 --- a/deal.II/cmake/configure/configure_1_threads.cmake +++ b/deal.II/cmake/configure/configure_1_threads.cmake @@ -14,13 +14,11 @@ ## ## --------------------------------------------------------------------- - # # Configuration for thread support in deal.II with the help of the tbb # library: # - # # Set up general threading: # The macro will be included in CONFIGURE_FEATURE_THREADS_EXTERNAL/BUNDLED. diff --git a/deal.II/cmake/configure/configure_2_metis.cmake b/deal.II/cmake/configure/configure_2_metis.cmake index 72a142286d..4d499c0d60 100644 --- a/deal.II/cmake/configure/configure_2_metis.cmake +++ b/deal.II/cmake/configure/configure_2_metis.cmake @@ -14,12 +14,7 @@ ## ## --------------------------------------------------------------------- -IF(NOT FEATURE_MPI_PROCESSED) - MESSAGE(FATAL_ERROR "\n" - "Internal build system error:\n" - "configure_2_metis.cmake included before configure_1_mpi.cmake\n\n" - ) -ENDIF() +SET(FEATURE_METIS_AFTER MPI) # # Configuration for the metis library: diff --git a/deal.II/cmake/configure/configure_2_umfpack.cmake b/deal.II/cmake/configure/configure_2_umfpack.cmake index f1d0d74513..5f0760ef3c 100644 --- a/deal.II/cmake/configure/configure_2_umfpack.cmake +++ b/deal.II/cmake/configure/configure_2_umfpack.cmake @@ -18,7 +18,7 @@ # Configuration for the umfpack library: # -SET(FEATURE_UMFPACK_DEPENDS DEAL_II_WITH_LAPACK) +SET(FEATURE_UMFPACK_DEPENDS LAPACK) MACRO(FEATURE_UMFPACK_CONFIGURE_BUNDLED) SET(UMFPACK_BUNDLED_INCLUDE_DIRS diff --git a/deal.II/cmake/configure/configure_3_petsc.cmake b/deal.II/cmake/configure/configure_3_petsc.cmake index ee95cd5a4a..662c30f8a3 100644 --- a/deal.II/cmake/configure/configure_3_petsc.cmake +++ b/deal.II/cmake/configure/configure_3_petsc.cmake @@ -18,9 +18,10 @@ # Configuration for the petsc library: # +SET(FEATURE_PETSC_AFTER MPI) -MACRO(FEATURE_PETSC_FIND_EXTERNAL var) +MACRO(FEATURE_PETSC_FIND_EXTERNAL var) FIND_PACKAGE(PETSC) IF(PETSC_FOUND) @@ -67,7 +68,6 @@ MACRO(FEATURE_PETSC_FIND_EXTERNAL var) SET(${var} FALSE) ENDIF() - # # Petsc has to be configured with the same number of bits for indices as # deal.II. diff --git a/deal.II/cmake/configure/configure_arpack.cmake b/deal.II/cmake/configure/configure_arpack.cmake index bf2f5f4aca..f631bec3bd 100644 --- a/deal.II/cmake/configure/configure_arpack.cmake +++ b/deal.II/cmake/configure/configure_arpack.cmake @@ -18,6 +18,6 @@ # Configuration for the ARPACK library: # -SET(FEATURE_ARPACK_DEPENDS DEAL_II_WITH_LAPACK) +SET(FEATURE_ARPACK_DEPENDS LAPACK) CONFIGURE_FEATURE(ARPACK) diff --git a/deal.II/cmake/configure/configure_boost.cmake b/deal.II/cmake/configure/configure_boost.cmake index ec72b800a2..4ae786788b 100644 --- a/deal.II/cmake/configure/configure_boost.cmake +++ b/deal.II/cmake/configure/configure_boost.cmake @@ -18,93 +18,11 @@ # Configuration for the boost library: # -# -# This configure script has to be included after configure_threads. -# We need some of the variables defined in SETUP_THREADING for -# the setup of the bundled boost library (if used) -# -IF(NOT FEATURE_THREADS_PROCESSED) - MESSAGE(FATAL_ERROR "\n" - "Internal build system error:\n" - "configure_boost.cmake included before configure_1_threads.cmake\n\n" - ) -ENDIF() - - SET(DEAL_II_WITH_BOOST ON # Always true. We need it :-] CACHE BOOL "Build deal.II with support for boost." FORCE ) -MACRO(FEATURE_BOOST_FIND_EXTERNAL var) - - # - # This mumbo jumbo is necessary because CMake won't let us test against - # BOOST_DIR directly. WTF?! - # - IF(NOT DEFINED BOOST_DIR) - SET(BOOST_DIR "$ENV{BOOST_DIR}") - ELSE() - SET_IF_EMPTY(BOOST_DIR "$ENV{BOOST_DIR}") - ENDIF() - - IF(NOT "${BOOST_DIR}" STREQUAL "") - SET(BOOST_ROOT "${BOOST_DIR}") - ENDIF() - - IF(DEAL_II_WITH_THREADS) - SET(_boost_components iostreams serialization system thread) - ELSE() - SET(_boost_components iostreams serialization system) - ENDIF() - - # - # Prefer static libs if BUILD_SHARED_LIBS=OFF: - # - IF(NOT BUILD_SHARED_LIBS) - SET(Boost_USE_STATIC_LIBS TRUE) - ENDIF() - - FIND_PACKAGE(Boost 1.44 COMPONENTS ${_boost_components}) - - # - # Fall back to dynamic libraries if no static libraries could be found: - # - IF(NOT Boost_FOUND AND Boost_USE_STATIC_LIBS) - SET(Boost_USE_STATIC_LIBS FALSE) - FIND_PACKAGE(Boost 1.44 COMPONENTS ${_boost_components}) - ENDIF() - - MARK_AS_ADVANCED(Boost_DIR) - - IF(Boost_FOUND) - SET(BOOST_VERSION_MAJOR "${Boost_MAJOR_VERSION}") - SET(BOOST_VERSION_MINOR "${Boost_MINOR_VERSION}") - SET(BOOST_VERSION_SUBMINOR "${Boost_SUBMINOR_VERSION}") - SET(BOOST_VERSION - "${BOOST_VERSION_MAJOR}.${BOOST_VERSION_MINOR}.${BOOST_VERSION_SUBMINOR}" - ) - - # - # Remove "pthread" from Boost_LIBRARIES. Threading, if necessary, is - # already set up via configure_1_threads.cmake. - # - LIST(REMOVE_ITEM Boost_LIBRARIES "pthread") - - SET(BOOST_INCLUDE_DIRS ${Boost_INCLUDE_DIRS}) - SET(BOOST_LIBRARIES ${Boost_LIBRARIES}) - - MARK_AS_ADVANCED(BOOST_DIR) - - SET(${var} TRUE) - - ELSE() - - SET(BOOST_DIR "" CACHE PATH "An optional hint to a boost directory") - ENDIF() -ENDMACRO() - - MACRO(FEATURE_BOOST_CONFIGURE_BUNDLED) SET(BOOST_BUNDLED_INCLUDE_DIRS ${BOOST_FOLDER}/include) ENDMACRO() @@ -112,10 +30,6 @@ ENDMACRO() CONFIGURE_FEATURE(BOOST) -# -# The user has to know the location of the boost headers as well: -# -SET(BOOST_USER_INCLUDE_DIRS ${BOOST_INCLUDE_DIRS}) # # DEAL_II_WITH_BOOST is always required. diff --git a/deal.II/cmake/configure/configure_hdf5.cmake b/deal.II/cmake/configure/configure_hdf5.cmake index abc66f4c04..6a335a232c 100644 --- a/deal.II/cmake/configure/configure_hdf5.cmake +++ b/deal.II/cmake/configure/configure_hdf5.cmake @@ -14,17 +14,13 @@ ## ## --------------------------------------------------------------------- -IF(NOT FEATURE_MPI_PROCESSED) - MESSAGE(FATAL_ERROR "\n" - "Internal build system error:\n" - "configure_hdf5.cmake included before configure_1_mpi.cmake\n\n" - ) -ENDIF() - # # Configuration for the hdf5 library: # +SET(FEATURE_HDF5_AFTER MPI) + + MACRO(FEATURE_HDF5_FIND_EXTERNAL var) FIND_PACKAGE(HDF5) @@ -49,4 +45,5 @@ MACRO(FEATURE_HDF5_FIND_EXTERNAL var) ENDIF() ENDMACRO() + CONFIGURE_FEATURE(HDF5) diff --git a/deal.II/cmake/configure/configure_mumps.cmake b/deal.II/cmake/configure/configure_mumps.cmake index cfe08a2cdd..ce1d2652b1 100644 --- a/deal.II/cmake/configure/configure_mumps.cmake +++ b/deal.II/cmake/configure/configure_mumps.cmake @@ -18,7 +18,7 @@ # Configuration for the MUMPS library: # -SET(FEATURE_MUMPS_DEPENDS DEAL_II_WITH_MPI DEAL_II_WITH_LAPACK) +SET(FEATURE_MUMPS_DEPENDS MPI LAPACK) MACRO(FEATURE_MUMPS_FIND_EXTERNAL var) diff --git a/deal.II/cmake/configure/configure_muparser.cmake b/deal.II/cmake/configure/configure_muparser.cmake index 29aab1f087..badb1c5b68 100644 --- a/deal.II/cmake/configure/configure_muparser.cmake +++ b/deal.II/cmake/configure/configure_muparser.cmake @@ -22,4 +22,5 @@ MACRO(FEATURE_MUPARSER_CONFIGURE_BUNDLED) SET(MUPARSER_BUNDLED_INCLUDE_DIRS ${MUPARSER_FOLDER}/include) ENDMACRO() + CONFIGURE_FEATURE(MUPARSER) diff --git a/deal.II/cmake/configure/configure_p4est.cmake b/deal.II/cmake/configure/configure_p4est.cmake index 313b8359ef..25acd30d86 100644 --- a/deal.II/cmake/configure/configure_p4est.cmake +++ b/deal.II/cmake/configure/configure_p4est.cmake @@ -18,7 +18,8 @@ # Configuration for the p4est and sc libraries: # -SET(FEATURE_P4EST_DEPENDS DEAL_II_WITH_MPI) +SET(FEATURE_P4EST_DEPENDS MPI) + MACRO(FEATURE_P4EST_FIND_EXTERNAL var) FIND_PACKAGE(P4EST) diff --git a/deal.II/cmake/configure/configure_slepc.cmake b/deal.II/cmake/configure/configure_slepc.cmake index 1f98ed4ecb..c300f7ea7b 100644 --- a/deal.II/cmake/configure/configure_slepc.cmake +++ b/deal.II/cmake/configure/configure_slepc.cmake @@ -18,7 +18,8 @@ # Configuration for the SLEPC library: # -SET(FEATURE_SLEPC_DEPENDS DEAL_II_WITH_PETSC) +SET(FEATURE_SLEPC_DEPENDS PETSC) + MACRO(FEATURE_SLEPC_FIND_EXTERNAL var) FIND_PACKAGE(SLEPC) diff --git a/deal.II/cmake/macros/macro_configure_feature.cmake b/deal.II/cmake/macros/macro_configure_feature.cmake index b42569ac1f..2c1277d6ae 100644 --- a/deal.II/cmake/macros/macro_configure_feature.cmake +++ b/deal.II/cmake/macros/macro_configure_feature.cmake @@ -26,8 +26,13 @@ # FEATURE_${feature}_DEPENDS (a variable) # a variable which contains an optional list of other features # this feature depends on (and which have to be enbled for this feature -# to work.) The features must be given with the full option toggle: -# DEAL_II_WITH_[...] +# to work.) +# Features must be given with short name, i.e. without DEAL_II_WITH_ +# +# FEATURE_${feature}_after (a variable) +# a variable which contains an optional list of other features +# that have to be configured prior to this feature +# Features must be given with short name, i.e. without DEAL_II_WITH_ # # FEATURE_${feature}_HAVE_BUNDLED (a variable) # which should either be set to TRUE if all necessary libraries of the @@ -150,14 +155,18 @@ MACRO(CONFIGURE_FEATURE _feature) # # Check for correct include order of the configure_*.cmake files: - # If feature B depends on feature A, configure_A.cmake has to be - # included before configure_B.cmake: + # If feature B explicitly states to come after feature A, or if feature B + # depends on feature A, configure_A.cmake has to be included before + # configure_B.cmake: # - FOREACH(_dependency ${FEATURE_${_feature}_DEPENDS}) - STRING(REGEX REPLACE "^DEAL_II_WITH_" "" _dependency ${_dependency}) + FOREACH(_dependency + ${FEATURE_${_feature}_AFTER} + ${FEATURE_${_feature}_DEPENDS} + ) IF(NOT FEATURE_${_dependency}_PROCESSED) MESSAGE(FATAL_ERROR "\n" - "Internal build system error: DEAL_II_WITH_${_feature} depends on " + "Internal build system error: The configuration of " + "DEAL_II_WITH_${_feature} depends on " "DEAL_II_WITH_${_dependency}, but CONFIGURE_FEATURE(${_feature}) " "was called before CONFIGURE_FEATURE(${_dependency}).\n\n" ) @@ -185,7 +194,7 @@ MACRO(CONFIGURE_FEATURE _feature) # SET(_dependencies_ok TRUE) FOREACH(_dependency ${FEATURE_${_feature}_DEPENDS}) - IF(NOT ${_dependency}) + IF(NOT DEAL_II_WITH_${_dependency}) IF(DEAL_II_WITH_${_feature}) MESSAGE(FATAL_ERROR "\n" "DEAL_II_WITH_${_feature} has unmet configuration requirements: " diff --git a/deal.II/cmake/modules/FindBOOST.cmake b/deal.II/cmake/modules/FindBOOST.cmake new file mode 100644 index 0000000000..b14b063f7c --- /dev/null +++ b/deal.II/cmake/modules/FindBOOST.cmake @@ -0,0 +1,82 @@ +## --------------------------------------------------------------------- +## $Id$ +## +## Copyright (C) 2014 by the deal.II authors +## +## This file is part of the deal.II library. +## +## The deal.II library is free software; you can use it, redistribute +## it, and/or modify it under the terms of the GNU Lesser General +## Public License as published by the Free Software Foundation; either +## version 2.1 of the License, or (at your option) any later version. +## The full text of the license can be found in the file LICENSE at +## the top level of the deal.II distribution. +## +## --------------------------------------------------------------------- + +# +# Try to find the boost libraries +# +# This module exports: +# +# BOOST_FOUND +# BOOST_LIBRARIES +# BOOST_INCLUDE_DIRS +# BOOST_VERSION +# BOOST_VERSION_MAJOR +# BOOST_VERSION_MINOR +# BOOST_VERSION_SUBMINOR +# + +SET(BOOST_DIR "" CACHE PATH "An optional hint to a BOOST installation") +SET_IF_EMPTY(BOOST_DIR "$ENV{BOOST_DIR}") + +IF(NOT "${BOOST_DIR}" STREQUAL "") + SET(BOOST_ROOT "${BOOST_DIR}") +ENDIF() + +# +# Prefer static libs if BUILD_SHARED_LIBS=OFF: +# +IF(NOT BUILD_SHARED_LIBS) + SET(Boost_USE_STATIC_LIBS TRUE) +ENDIF() + +FIND_PACKAGE(Boost 1.44 COMPONENTS iostreams serialization system thread) + +# +# Fall back to dynamic libraries if no static libraries could be found: +# +IF(NOT Boost_FOUND AND Boost_USE_STATIC_LIBS) + SET(Boost_USE_STATIC_LIBS FALSE) + FIND_PACKAGE(Boost 1.44 COMPONENTS iostreams serialization system thread) +ENDIF() + +IF(Boost_FOUND) + # + # Remove "pthread" from Boost_LIBRARIES. Threading, if necessary, is + # already set up via configure_1_threads.cmake. + # + LIST(REMOVE_ITEM Boost_LIBRARIES "pthread") + + SET(BOOST_VERSION_MAJOR "${Boost_MAJOR_VERSION}") + SET(BOOST_VERSION_MINOR "${Boost_MINOR_VERSION}") + SET(BOOST_VERSION_SUBMINOR "${Boost_SUBMINOR_VERSION}") + SET(BOOST_VERSION + "${BOOST_VERSION_MAJOR}.${BOOST_VERSION_MINOR}.${BOOST_VERSION_SUBMINOR}" + ) +ENDIF() + +DEAL_II_PACKAGE_HANDLE(BOOST + LIBRARIES REQUIRED Boost_LIBRARIES + INCLUDE_DIRS REQUIRED Boost_INCLUDE_DIRS + USER_INCLUDE_DIRS Boost_INCLUDE_DIRS + CLEAR + Boost_INCLUDE_DIR Boost_IOSTREAMS_LIBRARY_DEBUG + Boost_IOSTREAMS_LIBRARY_RELEASE Boost_LIBRARY_DIR + Boost_SERIALIZATION_LIBRARY_DEBUG Boost_SERIALIZATION_LIBRARY_RELEASE + Boost_SYSTEM_LIBRARY_DEBUG Boost_SYSTEM_LIBRARY_RELEASE + Boost_THREAD_LIBRARY_DEBUG Boost_THREAD_LIBRARY_RELEASE + _Boost_COMPONENTS_SEARCHED _Boost_INCLUDE_DIR_LAST + _Boost_LIBRARY_DIR_LAST _Boost_USE_MULTITHREADED_LAST + ) diff --git a/deal.II/doc/developers/cmake-internals.html b/deal.II/doc/developers/cmake-internals.html index 391a11b524..dad7505cfb 100644 --- a/deal.II/doc/developers/cmake-internals.html +++ b/deal.II/doc/developers/cmake-internals.html @@ -331,60 +331,72 @@ RESET_CMAKE_REQUIRED() library (no deal.II specific dependency checking, no compatibility checking).
  • - It should do so by appropriate FIND_LIBRARY and - FIND_PATH calls. The results of this calls should be the - only cached variables. -
  • - FIND_PACKAGE_HANDLE_STANDARD_ARGS should be used for - setting FEATURE_FOUND as this already respects the - QUIET and REQUIRED keywords. + It should do so by appropriate DEAL_II_FIND_LIBRARY, + DEAL_II_FIND_PATH and DEAL_II_FIND_FILE + calls (same syntax as the native CMake functions; just a small + wrapper to provide some useful output). The results of this calls + should be the only cached variables.
  • A WARNING, SEND_ERROR or FATAL_ERROR must be avoided (the only exception is the REQUIRED keyword).
  • - If the feature is successfully found, a subset of the following - uncached variables might be set: -
    +      The following uncached variables are recognized by the feature
    +      configuration mechanism:
    +
     FEATURE_FOUND
     FEATURE_LIBRARIES (with optimized, debug, release keywords)
     FEATURE_LIBRARIES(_DEBUG|_RELEASE)
    -FEATURE_INCLUDE_DIRS
    +FEATURE_INCLUDE_DIRS FEATURE_USER_INCLUDE_DIRS
     FEATURE_LINKER_FLAGS(|_DEBUG|_RELEASE)
     FEATURE_CXX_FLAGS(|_DEBUG|_RELEASE)
     FEATURE_DEFINITIONS(|_DEBUG|_RELEASE)
    -
     FEATURE_VERSION
     FEATURE_VERSION(_MAJOR|_MINOR|_SUBMINOR)
     
    - -There are obviously valid exceptions from this rule, though. + The DEAL_II_PACKAGE_HANDLE macro should be exclusively + used for setting up these variables (except the version variants). An + example invocation is +
    +DEAL_II_PACKAGE_HANDLE(UMFPACK
    +  LIBRARIES
    +    REQUIRED UMFPACK_LIBRARY
    +    OPTIONAL CHOLMOD_LIBRARY CCOLAMD_LIBRARY COLAMD_LIBRARY CAMD_LIBRARY ${_suitesparse_config}
    +    REQUIRED AMD_LIBRARY
    +    OPTIONAL METIS_LIBRARIES LAPACK_LIBRARIES rt_LIBRARY
    +  INCLUDE_DIRS
    +    REQUIRED UMFPACK_INCLUDE_DIR AMD_INCLUDE_DIR
    +    OPTIONAL SuiteSparse_config_INCLUDE_DIR
    +  LINKER_FLAGS
    +    OPTIONAL LAPACK_LINKER_FLAGS
    +  CLEAR
    +    UMFPACK_LIBRARY CHOLMOD_LIBRARY CCOLAMD_LIBRARY COLAMD_LIBRARY
    +    CAMD_LIBRARY SuiteSparse_config_LIBRARY AMD_LIBRARY UMFPACK_INCLUDE_DIR
    +    AMD_INCLUDE_DIR SuiteSparse_config_INCLUDE_DIR
    +  )
    +
    + The macro concatenates all specified variables into the final + FEATURE_SUFFIX variable. Hereby, a feature is + successfully found if all REQUIRED variables are + non-empty an not set to "-NOTFOUND". + OPTIONAL variables are just filtered out in this case. + As a last set of parameters the full list of cached search result + variables must be specified after the CLEAR keyword - + this is used to provide a possibility to undo a feature search.
  • Only "local" variables "_<all lowercase>" or "global" variables prefixed by FEATURE_ may be altered. Do not set DEAL_II_* or CMAKE_* variables directly! - -
  • - The find module must define a macro FEATURE_CLEAR that - unsets all cached variables, so that a subsequent call to the find - module starts a completely fresh features search.
  • A hint with FEATURE_DIR can be set up for convenience. It is best to start the Find module by -
    +SET(FEATURE_DIR "" CACHE PATH "short description")
     SET_IF_EMPTY(FEATURE_DIR "$ENV{FEATURE_DIR}")
     
    - -and use FEATURE_DIR as a hint. If the external -library could be found, hide it via -MARK_AS_ADVANCED, if the external library could not -be found, set a cache value: -
    -SET(FEATURE_DIR "" CACHE PATH "An optional hint to a FEATURE directory")
    -
    - + and use FEATURE_DIR as a hint. + @@ -435,9 +447,14 @@ FEATURE_DEFINITIONS(|_DEBUG|_RELEASE)
     FEATURE_<FEATURE>_DEPENDS              (a variable)
       - a variable which contains an optional list of other features
    -    this feature depends on (and which have to be enabled for this feature
    -    to work.) The features must be given with the full option toggle:
    -    DEAL_II_WITH_[...]
    +    this feature depends on (and which have to be enbled for this feature
    +    to work.)
    +    Features must be given with short name, i.e. without DEAL_II_WITH_
    +
    +FEATURE_<FEATURE>_AFTER                (a variable)
    +  - a variable which contains an optional list of other features
    +    that have to be configured prior to this feature
    +    Features must be given with short name, i.e. without DEAL_II_WITH_
     
     FEATURE_<FEATURE>_FIND_EXTERNAL(var)   (a macro)
       - which should set var to TRUE if all dependencies for the feature are
    -- 
    2.39.5