1
0
Эх сурвалжийг харах

ENH: Improvements in finding MPI on windows. ENH: reorganized searching mpi for mpi components (include,lib,bin) using a single set of search paths instead of seperately mainted lists of paths for each.

Dave Partyka 16 жил өмнө
parent
commit
4915e92998
1 өөрчлөгдсөн 89 нэмэгдсэн , 55 устгасан
  1. 89 55
      Modules/FindMPI.cmake

+ 89 - 55
Modules/FindMPI.cmake

@@ -1,5 +1,5 @@
 # - Message Passing Interface (MPI) module.
-# 
+#
 # The Message Passing Interface (MPI) is a library used to write
 # high-performance parallel applications that use message passing, and
 # is typically deployed on a cluster. MPI is a standard interface
@@ -35,7 +35,7 @@
 #
 # If no compiler driver is found or the compiler driver is not
 # recognized, this module will then search for common include paths
-# and library names to try to detect MPI. 
+# and library names to try to detect MPI.
 #
 # If CMake initially finds a different MPI than was intended, and you
 # want to use the MPI compiler auto-detection for a different MPI
@@ -49,7 +49,7 @@
 #   ${MPIEXEC} ${MPIEXEC_NUMPROC_FLAG} PROCS ${MPIEXEC_PREFLAGS} EXECUTABLE
 #     ${MPIEXEC_POSTFLAGS} ARGS
 # where PROCS is the number of processors on which to execute the program,
-# EXECUTABLE is the MPI program, and ARGS are the arguments to pass to the 
+# EXECUTABLE is the MPI program, and ARGS are the arguments to pass to the
 # MPI program.
 
 #=============================================================================
@@ -65,27 +65,64 @@
 # (To distributed this file outside of CMake, substitute the full
 #  License text for the above reference.)
 
-# Try to find the MPI driver program
-find_program(MPI_COMPILER 
-  NAMES mpic++ mpicxx mpiCC mpicc
-  DOC "MPI compiler. Used only to detect MPI compilation flags.")
-mark_as_advanced(MPI_COMPILER)
+# This module is maintained by David Partyka <[email protected]>.
+
+# A set of directories to search through in addition to the standard system paths
+# that find_program will search through.
+# Microsoft HPC SDK is automatically added to the system path
+# Argonne National Labs MPICH2 sets a registry key that we can use.
 
-file(TO_CMAKE_PATH "$ENV{ProgramFiles}" ProgramFiles)
+set(MPI_PACKAGE_DIR
+  mpi
+  mpich
+  openmpi
+  lib/mpi
+  lib/mpich
+  lib/openmpi
+  "MPICH/SDK"
+  "Microsoft Compute Cluster Pack"
+  )
+
+set(MPI_PREFIX_PATH)
+if(WIN32)
+  list(APPEND MPI_PREFIX_PATH "[HKEY_LOCAL_MACHINE\\SOFTWARE\\MPICH\\SMPD;binary]/..")
+endif()
+
+foreach(SystemPrefixDir ${CMAKE_SYSTEM_PREFIX_PATH})
+  foreach(MpiPackageDir ${MPI_PREFIX_PATH})
+    if(EXISTS ${SystemPrefixDir}/${MpiPackageDir})
+      list(APPEND MPI_PREFIX_PATH "${SystemPrefixDir}/${MpiPackageDir}")
+    endif()
+  endforeach(MpiPackageDir)
+endforeach(SystemPrefixDir)
+
+# Most mpi distros have some form of mpiexec which gives us something we can reliably look for.
 find_program(MPIEXEC
   NAMES mpiexec mpirun lamexec
-  PATHS /usr/bin /usr/local/bin /usr/local/mpi/bin
-  "$ENV{SystemDrive}/Program Files/MPICH/SDK/Bin"
-  "${ProgramFiles}/MPICH2/Bin"
-  "$ENV{SystemDrive}/Program Files/Microsoft Compute Cluster Pack/Bin"
-  "$ENV{SystemDrive}/Program Files/Microsoft HPC Pack 2008 SDK/Bin"
-  DOC "Executable for running MPI programs.")
+  PATHS ${MPI_PREFIX_PATH}
+  PATH_SUFFIXES bin
+  DOC "Executable for running MPI programs."
+  )
+
+# call get_filename_component twice to remove mpiexec and the directory it exists in (typically bin).
+# This gives us a fairly reliable base directory to search for /bin /lib and /include from.
+get_filename_component(MPI_BASE_DIR ${MPIEXEC} PATH)
+get_filename_component(MPI_BASE_DIR ${MPI_BASE_DIR} PATH)
+
+# If there is an mpi compiler find it and interogate (farther below) it for the include
+# and lib dirs otherwise we will continue to search from ${MPI_BASE_DIR}.
+find_program(MPI_COMPILER
+  NAMES mpic++ mpicxx mpiCC mpicc
+  HINTS "${MPI_BASE_DIR}"
+  PATH_SUFFIXES bin
+  DOC "MPI compiler. Used only to detect MPI compilation flags.")
+mark_as_advanced(MPI_COMPILER)
 
 set(MPIEXEC_NUMPROC_FLAG "-np" CACHE STRING "Flag used by MPI to specify the number of processes for MPIEXEC; the next option will be the number of processes.")
 set(MPIEXEC_PREFLAGS "" CACHE STRING "These flags will be directly before the executable that is being run by MPIEXEC.")
 set(MPIEXEC_POSTFLAGS "" CACHE STRING "These flags will come after all flags given to MPIEXEC.")
 set(MPIEXEC_MAX_NUMPROCS "2" CACHE STRING "Maximum number of processors available to run MPI applications.")
-mark_as_advanced(MPIEXEC MPIEXEC_NUMPROC_FLAG MPIEXEC_PREFLAGS 
+mark_as_advanced(MPIEXEC MPIEXEC_NUMPROC_FLAG MPIEXEC_PREFLAGS
   MPIEXEC_POSTFLAGS MPIEXEC_MAX_NUMPROCS)
 
 if (MPI_INCLUDE_PATH AND MPI_LIBRARY)
@@ -95,15 +132,16 @@ elseif (MPI_COMPILER)
   # Check whether the -showme:compile option works. This indicates
   # that we have either Open MPI or a newer version of LAM-MPI, and
   # implies that -showme:link will also work.
-  exec_program(${MPI_COMPILER} 
-    ARGS -showme:compile 
+  # Note that Windows distros do not have an mpi compiler to interogate.
+  exec_program(${MPI_COMPILER}
+    ARGS -showme:compile
     OUTPUT_VARIABLE MPI_COMPILE_CMDLINE
     RETURN_VALUE MPI_COMPILER_RETURN)
 
   if (MPI_COMPILER_RETURN EQUAL 0)
     # If we appear to have -showme:compile, then we should also have
     # -showme:link. Try it.
-    exec_program(${MPI_COMPILER} 
+    exec_program(${MPI_COMPILER}
       ARGS -showme:link
       OUTPUT_VARIABLE MPI_LINK_CMDLINE
       RETURN_VALUE MPI_COMPILER_RETURN)
@@ -117,21 +155,21 @@ elseif (MPI_COMPILER)
     # Do nothing: we have our command lines now
   else (MPI_COMPILER_RETURN EQUAL 0)
     # Older versions of LAM-MPI have "-showme". Try it.
-    exec_program(${MPI_COMPILER} 
+    exec_program(${MPI_COMPILER}
       ARGS -showme
       OUTPUT_VARIABLE MPI_COMPILE_CMDLINE
       RETURN_VALUE MPI_COMPILER_RETURN)
-  endif (MPI_COMPILER_RETURN EQUAL 0)  
+  endif (MPI_COMPILER_RETURN EQUAL 0)
 
   if (MPI_COMPILER_RETURN EQUAL 0)
     # Do nothing: we have our command lines now
   else (MPI_COMPILER_RETURN EQUAL 0)
     # MPICH uses "-show". Try it.
-    exec_program(${MPI_COMPILER} 
+    exec_program(${MPI_COMPILER}
       ARGS -show
       OUTPUT_VARIABLE MPI_COMPILE_CMDLINE
       RETURN_VALUE MPI_COMPILER_RETURN)
-  endif (MPI_COMPILER_RETURN EQUAL 0)  
+  endif (MPI_COMPILER_RETURN EQUAL 0)
 
   if (MPI_COMPILER_RETURN EQUAL 0)
     # We have our command lines, but we might need to copy
@@ -167,12 +205,12 @@ elseif (MPI_COMPILE_CMDLINE)
     string(REGEX REPLACE "//" "/" IPATH ${IPATH})
     list(APPEND MPI_INCLUDE_PATH_WORK ${IPATH})
   endforeach(IPATH)
-  
+
   if (NOT MPI_INCLUDE_PATH_WORK)
     if (MPI_COMPILER_MAY_HAVE_INCLIBDIRS)
       # The compile command line didn't have any include paths on it,
       # but we may have -showme:incdirs. Use it.
-      exec_program(${MPI_COMPILER} 
+      exec_program(${MPI_COMPILER}
         ARGS -showme:incdirs
         OUTPUT_VARIABLE MPI_INCLUDE_PATH_WORK
         RETURN_VALUE MPI_COMPILER_RETURN)
@@ -183,7 +221,10 @@ elseif (MPI_COMPILE_CMDLINE)
   if (NOT MPI_INCLUDE_PATH_WORK)
     # If all else fails, just search for mpi.h in the normal include
     # paths.
-    find_path(MPI_INCLUDE_PATH mpi.h)
+    find_path(MPI_INCLUDE_PATH mpi.h
+  HINTS ${MPI_BASE_DIR} ${MPI_PREFIX_PATH}
+  PATH_SUFFIXES include
+    )
     set(MPI_INCLUDE_PATH_WORK ${MPI_INCLUDE_PATH})
   endif (NOT MPI_INCLUDE_PATH_WORK)
 
@@ -200,7 +241,7 @@ elseif (MPI_COMPILE_CMDLINE)
     if (MPI_COMPILER_MAY_HAVE_INCLIBDIRS)
       # The compile command line didn't have any linking paths on it,
       # but we may have -showme:libdirs. Use it.
-      exec_program(${MPI_COMPILER} 
+      exec_program(${MPI_COMPILER}
         ARGS -showme:libdirs
         OUTPUT_VARIABLE MPI_LINK_PATH
         RETURN_VALUE MPI_COMPILER_RETURN)
@@ -261,41 +302,29 @@ elseif (MPI_COMPILE_CMDLINE)
   set(MPI_INCLUDE_PATH ${MPI_INCLUDE_PATH_WORK} CACHE STRING "MPI include path" FORCE)
   set(MPI_LINK_FLAGS ${MPI_LINK_FLAGS_WORK} CACHE STRING "MPI linking flags" FORCE)
 else (MPI_COMPILE_CMDLINE)
-  find_path(MPI_INCLUDE_PATH mpi.h 
-    /usr/local/include 
-    /usr/include 
-    /usr/include/mpi
-    /usr/local/mpi/include
-    "$ENV{SystemDrive}/Program Files/MPICH/SDK/Include" 
-    "${ProgramFiles}/MPICH2/include"
-    "$ENV{SystemDrive}/Program Files/Microsoft Compute Cluster Pack/Include"
-    "$ENV{SystemDrive}/Program Files/Microsoft HPC Pack 2008 SDK/Include"
+# No MPI compiler to interogate so attempt to find everything with find functions.
+  find_path(MPI_INCLUDE_PATH mpi.h
+    HINTS ${MPI_BASE_DIR} ${MPI_PREFIX_PATH}
+    PATH_SUFFIXES include
     )
 
   # Decide between 32-bit and 64-bit libraries for Microsoft's MPI
-  if (CMAKE_CL_64)
+  if(CMAKE_SIZEOF_VOID_P EQUALS 8)
     set(MS_MPI_ARCH_DIR amd64)
-  else (CMAKE_CL_64)
+  else()
     set(MS_MPI_ARCH_DIR i386)
-  endif (CMAKE_CL_64)
+  endif()
 
-  find_library(MPI_LIBRARY 
+  find_library(MPI_LIBRARY
     NAMES mpi mpich msmpi
-    PATHS /usr/lib /usr/local/lib /usr/local/mpi/lib
-    "$ENV{SystemDrive}/Program Files/MPICH/SDK/Lib"
-    "${ProgramFiles}/MPICH2/Lib"
-    "$ENV{SystemDrive}/Program Files/Microsoft Compute Cluster Pack/Lib/${MS_MPI_ARCH_DIR}"
-    "$ENV{SystemDrive}/Program Files/Microsoft HPC Pack 2008 SDK/Lib/${MS_MPI_ARCH_DIR}"
+    HINTS ${MPI_BASE_DIR} ${MPI_PREFIX_PATH}
+    PATH_SUFFIXES lib lib/${MS_MPI_ARCH_DIR} Lib Lib/${MS_MPI_ARCH_DIR}
     )
-  find_library(MPI_LIBRARY
-    NAMES mpich2
-    PATHS
-    "${ProgramFiles}/MPICH2/Lib")
 
-  find_library(MPI_EXTRA_LIBRARY 
+  find_library(MPI_EXTRA_LIBRARY
     NAMES mpi++
-    PATHS /usr/lib /usr/local/lib /usr/local/mpi/lib
-    "$ENV{SystemDrive}/Program Files/MPICH/SDK/Lib" 
+    HINTS ${MPI_BASE_DIR} ${MPI_PREFIX_PATH}
+    PATH_SUFFIXES lib
     DOC "Extra MPI libraries to link against.")
 
   set(MPI_COMPILE_FLAGS "" CACHE STRING "MPI compilation flags")
@@ -308,7 +337,7 @@ if("${MPI_LIBRARY}" MATCHES "mpich.rts")
    set(MPI_LIBRARY ${MPI_LIBRARY}  msglayer.rts devices.rts rts.rts devices.rts)
 endif("${MPI_LIBRARY}" MATCHES "mpich.rts")
 
-# Set up extra variables to conform to 
+# Set up extra variables to conform to
 if (MPI_EXTRA_LIBRARY)
   set(MPI_LIBRARIES ${MPI_LIBRARY} ${MPI_EXTRA_LIBRARY})
 else (MPI_EXTRA_LIBRARY)
@@ -322,8 +351,13 @@ else (MPI_INCLUDE_PATH AND MPI_LIBRARY)
 endif (MPI_INCLUDE_PATH AND MPI_LIBRARY)
 
 include(FindPackageHandleStandardArgs)
-# handle the QUIETLY and REQUIRED arguments 
+# handle the QUIETLY and REQUIRED arguments
 find_package_handle_standard_args(MPI DEFAULT_MSG MPI_LIBRARY MPI_INCLUDE_PATH)
 
-mark_as_advanced(MPI_INCLUDE_PATH MPI_COMPILE_FLAGS MPI_LINK_FLAGS MPI_LIBRARY 
+mark_as_advanced(MPI_INCLUDE_PATH MPI_COMPILE_FLAGS MPI_LINK_FLAGS MPI_LIBRARY
   MPI_EXTRA_LIBRARY)
+
+# unset to cleanup namespace
+unset(MPI_PACKAGE_DIR)
+unset(MPI_PREFIX_PATH)
+unset(MPI_BASE_DIR)