From 5727c2cbebc431a504d2a9c658cd6992ff40f47f Mon Sep 17 00:00:00 2001
From: Simon Praetorius <simon.praetorius@tu-dresden.de>
Date: Fri, 6 Nov 2020 10:04:19 +0000
Subject: [PATCH] Remove the ENABLE_SCOTCH_METIS and ENABLE_SCOTCH_PRMETIS
 flags from the cmake find modules

---
 cmake/modules/AddParMETISFlags.cmake |   6 +-
 cmake/modules/DuneCommonMacros.cmake |   6 ++
 cmake/modules/FindMETIS.cmake        | 119 ++++++++++++++++-----------
 cmake/modules/FindParMETIS.cmake     |  68 ++++++++-------
 config.h.cmake                       |   5 +-
 dune/common/test/CMakeLists.txt      |  12 +--
 6 files changed, 118 insertions(+), 98 deletions(-)

diff --git a/cmake/modules/AddParMETISFlags.cmake b/cmake/modules/AddParMETISFlags.cmake
index 74392ad16..0f91e764e 100644
--- a/cmake/modules/AddParMETISFlags.cmake
+++ b/cmake/modules/AddParMETISFlags.cmake
@@ -15,10 +15,7 @@ set(HAVE_PARMETIS ${ParMETIS_FOUND})
 
 # register all ParMETIS related flags
 if(ParMETIS_FOUND)
-  dune_register_package_flags(
-    COMPILE_DEFINITIONS "ENABLE_PARMETIS=1"
-    LIBRARIES "ParMETIS::ParMETIS"
-  )
+  dune_register_package_flags(LIBRARIES ParMETIS::ParMETIS)
 endif()
 
 # add function to link against the ParMETIS library
@@ -26,7 +23,6 @@ function(add_dune_parmetis_flags _targets)
   if(ParMETIS_FOUND)
     foreach(_target ${_targets})
       target_link_libraries(${_target} PUBLIC ParMETIS::ParMETIS)
-      target_compile_definitions(${_target} PUBLIC "ENABLE_PARMETIS=1")
     endforeach(_target)
   endif()
 endfunction(add_dune_parmetis_flags)
diff --git a/cmake/modules/DuneCommonMacros.cmake b/cmake/modules/DuneCommonMacros.cmake
index 6d44a475e..888bc9f5d 100644
--- a/cmake/modules/DuneCommonMacros.cmake
+++ b/cmake/modules/DuneCommonMacros.cmake
@@ -40,6 +40,12 @@ set_package_properties("Threads" PROPERTIES
 
 find_package(TBB OPTIONAL_COMPONENTS cpf allocator)
 
+# find libraries for graph partitioning
+find_package(METIS)
+include(AddMETISFlags)
+find_package(ParMETIS 4.0)
+include(AddParMETISFlags)
+
 # try to find the Vc library
 set(MINIMUM_VC_VERSION)
 if((CMAKE_CXX_COMPILER_ID STREQUAL Clang) AND
diff --git a/cmake/modules/FindMETIS.cmake b/cmake/modules/FindMETIS.cmake
index 27c3fc872..96846cca0 100644
--- a/cmake/modules/FindMETIS.cmake
+++ b/cmake/modules/FindMETIS.cmake
@@ -32,17 +32,13 @@ The following variables may be set to influence this module's behavior:
 ``METIS_LIBRARY``
   Full path to the METIS library
 
-``ENABLE_SCOTCH_METIS``
-  Use the Scotch library as METIS compatibility library. This library provides an
-  interface of some METIS library functions.
-
-``SCOTCH_METIS_VERSION``
-  If `ENABLE_SCOTCH_METIS` is set, this variable specifies the METIS API version provided
-  by the scotch-metis library. This is required for Scotch >= 6.0.7 versions, since it
-  cannot be detected by inspecting provided files. The variable may be set to 3 to indicate
-  that scotch implements the METIS API v3 (default for older Scotch versions), or it can
-  be set to 5 to indicate that v5 of the METIS API is provided. This variable corresponds
-  to the preprocessor flag that is used when compiling Scotch from source.
+``METIS_API_VERSION``
+  This variable specifies the METIS API version provided by the scotch-metis library. This
+  is required for Scotch >= 6.0.7 versions if it is not detected automatically. The
+  variable may be set to 3 to indicate that scotch implements the METIS API v3 (default
+  for older Scotch versions), or it can be set to 5 to indicate that v5 of the METIS API
+  is provided. This variable corresponds to the preprocessor flag `SCOTCH_METIS_VERSION`
+  that is used when compiling Scotch from source.
 #]=======================================================================]
 
 # Text for feature summary
@@ -51,29 +47,14 @@ set_package_properties("METIS" PROPERTIES
   DESCRIPTION "Serial Graph Partitioning"
 )
 
-# The Scotch library provides a wrapper around some functions of METIS. Since is does
-# not provide the full interface, you have to request it explicitly.
-option(ENABLE_SCOTCH_METIS "Use the Scotch library as METIS compatibility library" FALSE)
-set(SCOTCH_METIS_VERSION 0 CACHE STRING
-  "METIS API version provided by scotch-metis library")
+# The METIS API version provided by the METIS or scotch-metis library
+set(METIS_API_VERSION 0 CACHE STRING
+  "METIS API version provided by METIS or scotch-metis library")
 
 # Try to locate METIS header
 find_path(METIS_INCLUDE_DIR metis.h
   PATH_SUFFIXES metis)
 
-find_library(METIS_LIBRARY metis)
-if(ENABLE_SCOTCH_METIS)
-  find_library(METIS_LIBRARY scotchmetis)
-endif()
-
-# We need to check whether we need to link m, copy the lazy solution
-# from FindBLAS and FindLAPACK here.
-if(METIS_LIBRARY AND NOT WIN32)
-  set(METIS_NEEDS_LIBM 1)
-endif()
-
-mark_as_advanced(METIS_INCLUDE_DIR METIS_LIBRARY METIS_NEEDS_LIBM)
-
 # Determine version of METIS installation
 find_file(METIS_HEADER_FILE metis.h
   PATHS ${METIS_INCLUDE_DIR}
@@ -86,42 +67,87 @@ if(METIS_HEADER_FILE)
     METIS_MINOR_VERSION "${metisheader}")
   if(METIS_MAJOR_VERSION GREATER_EQUAL 0 AND METIS_MINOR_VERSION GREATER_EQUAL 0)
     set(METIS_VERSION "${METIS_MAJOR_VERSION}.${METIS_MINOR_VERSION}")
+
+    # Specify an api version to be used in config.h files or compile flags
+    if(NOT METIS_API_VERSION)
+      if(METIS_MAJOR_VERSION GREATER_EQUAL 3 AND METIS_MAJOR_VERSION LESS 5)
+        set(METIS_API_VERSION "3")
+      else()
+        set(METIS_API_VERSION "${METIS_MAJOR_VERSION}")
+      endif()
+    endif()
   else()
     unset(METIS_MAJOR_VERSION)
     unset(METIS_MINOR_VERSION)
   endif()
+
+  # test whether header file is actually the scotch-metis header
+  string(FIND "${metisheader}" "SCOTCH_METIS_PREFIX" IS_SCOTCH_METIS_HEADER)
+  if(IS_SCOTCH_METIS_HEADER EQUAL "-1")
+    set(IS_SCOTCH_METIS_HEADER FALSE)
+  else()
+    set(IS_SCOTCH_METIS_HEADER TRUE)
+  endif()
 endif()
 unset(METIS_HEADER_FILE CACHE)
 
+# search for the METIS library or for the scotch-metis wrapper library
+if(IS_SCOTCH_METIS_HEADER)
+  find_library(METIS_LIBRARY scotchmetis)
+else()
+  find_library(METIS_LIBRARY metis)
+endif()
+
+# We need to check whether we need to link m, copy the lazy solution
+# from FindBLAS and FindLAPACK here.
+if(METIS_LIBRARY AND NOT WIN32)
+  set(METIS_NEEDS_LIBM 1)
+endif()
+
+mark_as_advanced(METIS_INCLUDE_DIR METIS_LIBRARY METIS_NEEDS_LIBM METIS_API_VERSION)
+
 # If scotch is requested, find package PTScotch and check version compatibility:
 # Scotch provides METIS-3 interface only in version < 6.07, but provides an option to
 # select the API-version in later Scotch releases
-if(ENABLE_SCOTCH_METIS)
-  find_package(PTScotch QUIET COMPONENTS SCOTCH)
+if(IS_SCOTCH_METIS_HEADER)
+  find_package(PTScotch COMPONENTS SCOTCH)
   set(HAVE_SCOTCH_METIS ${PTScotch_FOUND})
-  if (PTScotch_FOUND)
+  if (PTScotch_FOUND AND NOT METIS_API_VERSION)
     if(PTScotch_VERSION VERSION_LESS "6.0.7")
-      set(METIS_MAJOR_VERSION "3")
-    elseif(SCOTCH_METIS_VERSION)
-      set(METIS_MAJOR_VERSION "${SCOTCH_METIS_VERSION}")
+      set(METIS_API_VERSION "3")
     else()
-      message(WARNING "Cannot detect METIS API version provided by the scotch-metis library.
-        Set the cmake variable SCOTCH_METIS_VERSION to the corresponding version number.")
-    endif()
-    if(METIS_MAJOR_VERSION GREATER_EQUAL 0)
-      set(METIS_VERSION "${METIS_MAJOR_VERSION}.0")
+      # try to figure out the METIS_API_VERSION by checking for symbols in the library
+      include(CheckSymbolExists)
+      include(CMakePushCheckState)
+      find_package(Threads)
+      cmake_push_check_state()
+      set(CMAKE_REQUIRED_LIBRARIES ${METIS_LIBRARY} ${SCOTCH_LIBRARY} ${SCOTCHERR_LIBRARY} ${CMAKE_THREAD_LIBS_INIT})
+      if(METIS_NEEDS_LIBM)
+        list(APPEND CMAKE_REQUIRED_LIBRARIES m)
+      endif()
+      set(CMAKE_REQUIRED_INCLUDES ${METIS_INCLUDE_DIR} ${SCOTCH_INCLUDE_DIR})
+
+      set(CMAKE_REQUIRED_DEFINITIONS "-DSCOTCH_METIS_VERSION=3")
+      check_symbol_exists("METIS_PartGraphVKway" "stdio.h;stdint.h;scotch.h;metis.h" IS_SCOTCH_METIS_API_V3)
+      if(IS_SCOTCH_METIS_API_V3)
+        set(METIS_API_VERSION "3")
+      else()
+        set(CMAKE_REQUIRED_DEFINITIONS "-DSCOTCH_METIS_VERSION=5")
+        check_symbol_exists("METIS_PartGraphKway" "stdio.h;stdint.h;scotch.h;metis.h" IS_SCOTCH_METIS_API_V5)
+        if(IS_SCOTCH_METIS_API_V5)
+          set(METIS_API_VERSION "5")
+        endif()
+      endif()
+      cmake_pop_check_state()
     endif()
   endif()
 endif()
 
-# Specify an api version to be used in config.h files or compile flags
-set(METIS_API_VERSION "${METIS_MAJOR_VERSION}")
-
 # Behave like a CMake module is supposed to behave
 include(FindPackageHandleStandardArgs)
 find_package_handle_standard_args("METIS"
   REQUIRED_VARS
-    METIS_LIBRARY METIS_INCLUDE_DIR METIS_VERSION
+    METIS_LIBRARY METIS_INCLUDE_DIR METIS_API_VERSION
   VERSION_VAR
     METIS_VERSION
 )
@@ -142,12 +168,11 @@ if(METIS_FOUND AND NOT TARGET METIS::METIS)
   endif()
 
   # Link against Scotch library if option is enabled
-  if(ENABLE_SCOTCH_METIS AND PTScotch_FOUND)
+  if(IS_SCOTCH_METIS_HEADER AND PTScotch_FOUND)
     set_property(TARGET METIS::METIS APPEND PROPERTY
       INTERFACE_LINK_LIBRARIES PTScotch::Scotch)
     set_property(TARGET METIS::METIS APPEND PROPERTY
       INTERFACE_COMPILE_DEFINITIONS
-        HAVE_SCOTCH_METIS
-        SCOTCH_METIS_VERSION=${SCOTCH_METIS_VERSION})
+        SCOTCH_METIS_VERSION=${METIS_API_VERSION})
   endif()
 endif()
diff --git a/cmake/modules/FindParMETIS.cmake b/cmake/modules/FindParMETIS.cmake
index 6e1399cf3..d74dd84e1 100644
--- a/cmake/modules/FindParMETIS.cmake
+++ b/cmake/modules/FindParMETIS.cmake
@@ -32,10 +32,6 @@ The following variables may be set to influence this module's behavior:
 ``PARMETIS_LIBRARY``
   Full path to the ParMETIS library
 
-``ENABLE_PTSCOTCH_PARMETIS``
-  Use the PTScotch library as ParMETIS compatibility library. This library
-  provides an interface of some ParMETIS library functions.
-
 #]=======================================================================]
 
 # text for feature summary
@@ -44,25 +40,9 @@ set_package_properties("ParMETIS" PROPERTIES
   DESCRIPTION "Parallel Graph Partitioning"
 )
 
-# The PTScotch library provides a wrapper around some functions of ParMETIS, since not
-# the full interface, you have to request it explicitly.
-option(ENABLE_PTSCOTCH_PARMETIS "Use the (PT)Scotch library as ParMETIS compatibility library" OFF)
-
-# find package dependencies first
-find_package(METIS QUIET)
-find_package(MPI QUIET)
-
 find_path(PARMETIS_INCLUDE_DIR parmetis.h
   PATH_SUFFIXES parmetis)
 
-# search ParMETIS library
-find_library(PARMETIS_LIBRARY parmetis)
-if(ENABLE_PTSCOTCH_PARMETIS)
-  find_library(PARMETIS_LIBRARY ptscotchparmetis)
-endif()
-
-mark_as_advanced(PARMETIS_INCLUDE_DIR PARMETIS_LIBRARY)
-
 # determine version of ParMETIS installation
 find_file(PARMETIS_HEADER_FILE parmetis.h
   PATHS ${PARMETIS_INCLUDE_DIR}
@@ -76,34 +56,51 @@ if(PARMETIS_HEADER_FILE)
   if(ParMETIS_MAJOR_VERSION GREATER_EQUAL 0 AND ParMETIS_MINOR_VERSION GREATER_EQUAL 0)
     set(ParMETIS_VERSION "${ParMETIS_MAJOR_VERSION}.${ParMETIS_MINOR_VERSION}")
   endif()
+
+  # test whether header file is actually the ptscotch-parmetis header
+  string(FIND "${parmetisheader}" "SCOTCH_METIS_PREFIX" IS_PTSCOTCH_PARMETIS_HEADER)
+  if(IS_PTSCOTCH_PARMETIS_HEADER EQUAL "-1")
+    set(IS_PTSCOTCH_PARMETIS_HEADER FALSE)
+  else()
+    set(IS_PTSCOTCH_PARMETIS_HEADER TRUE)
+  endif()
 endif()
 unset(PARMETIS_HEADER_FILE CACHE)
 
-# set a flag whether all ParMETIS dependencies are found correctly
-if(METIS_FOUND AND MPI_FOUND)
-  set(PARMETIS_DEPENDENCIES_FOUND TRUE)
 
-  # minimal requires METIS version 5.0 for ParMETIS >= 4.0
-  if (ParMETIS_VERSION VERSION_GREATER_EQUAL "4.0"
-      AND METIS_VERSION VERSION_LESS "5.0")
-    set(PARMETIS_DEPENDENCIES_FOUND FALSE)
-  endif()
+# search ParMETIS library
+if(IS_PTSCOTCH_PARMETIS_HEADER)
+  find_library(PARMETIS_LIBRARY ptscotchparmetis)
+else()
+  find_library(PARMETIS_LIBRARY parmetis)
 endif()
 
+mark_as_advanced(PARMETIS_INCLUDE_DIR PARMETIS_LIBRARY)
+
+# minimal requires METIS version 5.0 for ParMETIS >= 4.0
+if(ParMETIS_VERSION VERSION_GREATER_EQUAL "4.0")
+  set(METIS_MIN_VERSION "5.0")
+endif()
+
+# find package dependencies first
+find_package(METIS ${METIS_MIN_VERSION})
+find_package(MPI COMPONENTS C)
+
+# set a list of required dependencies for ParMETIS
+set(PARMETIS_DEPENDENCIES METIS_FOUND MPI_FOUND)
+
 # If ptscotch-parmetis is requested, find package PTScotch
-if(ENABLE_PTSCOTCH_PARMETIS)
-  find_package(PTScotch QUIET COMPONENTS PTSCOTCH)
+if(IS_PTSCOTCH_PARMETIS_HEADER)
+  find_package(PTScotch COMPONENTS PTSCOTCH)
   set(HAVE_PTSCOTCH_PARMETIS ${PTScotch_FOUND})
-  if(PTScotch_FOUND AND MPI_FOUND)
-    set(PARMETIS_DEPENDENCIES_FOUND TRUE)
-  endif()
+  list(APPEND PARMETIS_DEPENDENCIES PTScotch_FOUND)
 endif()
 
 # behave like a CMake module is supposed to behave
 include(FindPackageHandleStandardArgs)
 find_package_handle_standard_args("ParMETIS"
   REQUIRED_VARS
-    PARMETIS_LIBRARY PARMETIS_INCLUDE_DIR PARMETIS_DEPENDENCIES_FOUND
+    PARMETIS_LIBRARY PARMETIS_INCLUDE_DIR ${PARMETIS_DEPENDENCIES}
   VERSION_VAR
     ParMETIS_VERSION
 )
@@ -115,10 +112,11 @@ if(PARMETIS_FOUND AND NOT TARGET ParMETIS::ParMETIS)
     IMPORTED_LOCATION ${PARMETIS_LIBRARY}
     INTERFACE_INCLUDE_DIRECTORIES ${PARMETIS_INCLUDE_DIR}
     INTERFACE_LINK_LIBRARIES "METIS::METIS;MPI::MPI_C"
+    INTERFACE_COMPILE_DEFINITIONS "MPICH_SKIP_MPICXX;OMPI_SKIP_MPICXX"
   )
 
   # link against PTScotch if needed
-  if(ENABLE_PTSCOTCH_PARMETIS AND PTScotch_FOUND)
+  if(IS_PTSCOTCH_PARMETIS_HEADER AND PTScotch_FOUND)
     set_property(TARGET ParMETIS::ParMETIS APPEND PROPERTY
       INTERFACE_LINK_LIBRARIES PTScotch::PTScotch)
   endif()
diff --git a/config.h.cmake b/config.h.cmake
index e4c9a8804..9925dab4d 100644
--- a/config.h.cmake
+++ b/config.h.cmake
@@ -180,10 +180,13 @@
 /* Define to 1 if METIS is available */
 #cmakedefine HAVE_METIS 1
 
+/* Define to 1 if the Scotch replacement for METIS is used. */
+#cmakedefine HAVE_SCOTCH_METIS 1
+
 /* Define to 1 if you have the ParMETIS library. */
 #cmakedefine HAVE_PARMETIS 1
 
-/* Define to 1 if you have the PTScotch replacement for ParMETIS is used. */
+/* Define to 1 if the PTScotch replacement for ParMETIS is used. */
 #cmakedefine HAVE_PTSCOTCH_PARMETIS 1
 
 /* Define to 1 if PT-Scotch is available */
diff --git a/dune/common/test/CMakeLists.txt b/dune/common/test/CMakeLists.txt
index 98abe5368..08927abe5 100644
--- a/dune/common/test/CMakeLists.txt
+++ b/dune/common/test/CMakeLists.txt
@@ -223,13 +223,9 @@ dune_add_test(SOURCES lrutest.cc
 dune_add_test(SOURCES mathclassifierstest.cc
               LINK_LIBRARIES dunecommon)
 
-find_package(METIS)
 dune_add_test(SOURCES metistest.cc
-              COMPILE_DEFINITIONS "HAVE_METIS"
               CMAKE_GUARD METIS_FOUND)
-if (METIS_FOUND)
-  target_link_libraries(metistest PUBLIC METIS::METIS)
-endif ()
+add_dune_metis_flags(metistest)
 
 dune_add_test(SOURCES mpicommunicationtest.cc
               LINK_LIBRARIES dunecommon
@@ -274,16 +270,12 @@ dune_add_test(SOURCES parametertreetest.cc
               LINK_LIBRARIES dunecommon
               LABELS quick)
 
-find_package(ParMETIS 4.0)
 dune_add_test(SOURCES parmetistest.cc
               MPI_RANKS 3
               TIMEOUT 300
-              COMPILE_DEFINITIONS "HAVE_PARMETIS"
               CMAKE_GUARD ParMETIS_FOUND
               LABELS quick)
-if (ParMETIS_FOUND)
-  target_link_libraries(parmetistest ParMETIS::ParMETIS)
-endif()
+add_dune_parmetis_flags(parmetistest)
 
 dune_add_test(SOURCES pathtest.cc
               LINK_LIBRARIES dunecommon
-- 
GitLab