FindMPI.cmake 13.4 KB
Newer Older
1
2
3
4
5
6
7
8
9
# - 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
# (defined by the MPI forum) for which many implementations are
# available. All of these implementations have somewhat different
# compilation approaches (different include paths, libraries to link
# against, etc.), and this module tries to smooth out those differences.
10
11
12
13
#
# This module will set the following variables:
#   MPI_FOUND                  TRUE if we have found MPI
#   MPI_COMPILE_FLAGS          Compilation flags for MPI programs
14
#   MPI_INCLUDE_PATH           Include path(s) for MPI header
15
#   MPI_LINK_FLAGS             Linking flags for MPI programs
16
17
18
#   MPI_LIBRARY                First MPI library to link against (cached)
#   MPI_EXTRA_LIBRARY          Extra MPI libraries to link against (cached)
#   MPI_LIBRARIES              All libraries to link MPI programs against
19
#   MPIEXEC                    Executable for running MPI programs
20
21
22
23
24
#   MPIEXEC_NUMPROC_FLAG       Flag to pass to MPIEXEC before giving it the
#                              number of processors to run on
#   MPIEXEC_PREFLAGS           Flags to pass to MPIEXEC directly before the
#                              executable to run.
#   MPIEXEC_POSTFLAGS          Flags to pass to MPIEXEC after all other flags.
25
26
#
# This module will attempt to auto-detect these settings, first by
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
# looking for a MPI compiler, which many MPI implementations provide
# as a pass-through to the native compiler to simplify the compilation
# of MPI programs. The MPI compiler is stored in the cache variable
# MPI_COMPILER, and will attempt to look for commonly-named drivers
# mpic++, mpicxx, mpiCC, or mpicc. If the compiler driver is found and
# recognized, it will be used to set all of the module variables. To
# skip this auto-detection, set MPI_LIBRARY and MPI_INCLUDE_PATH in
# the CMake cache.
#
# 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. 
#
# If CMake initially finds a different MPI than was intended, and you
# want to use the MPI compiler auto-detection for a different MPI
# implementation, set MPI_COMPILER to the MPI compiler driver you want
# to use (e.g., mpicxx) and then set MPI_LIBRARY to the string
# MPI_LIBRARY-NOTFOUND. When you re-configure, auto-detection of MPI
# will run again with the newly-specified MPI_COMPILER.
#
# When using MPIEXEC to execute MPI applications, you should typically
# use all of the MPIEXEC flags as follows:
#   ${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 
# MPI program.
54

55
# Try to find the MPI driver program
56
57
58
59
find_program(MPI_COMPILER 
  NAMES mpic++ mpicxx mpiCC mpicc
  DOC "MPI compiler. Used only to detect MPI compilation flags.")
mark_as_advanced(MPI_COMPILER)
60

61
file(TO_CMAKE_PATH "$ENV{ProgramFiles}" ProgramFiles)
62
find_program(MPIEXEC
63
  NAMES mpiexec mpirun lamexec
64
65
66
67
68
  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"
69
70
  DOC "Executable for running MPI programs.")

71
72
73
74
75
76
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 
  MPIEXEC_POSTFLAGS MPIEXEC_MAX_NUMPROCS)
77

78
79
80
81
if (MPI_INCLUDE_PATH AND MPI_LIBRARY)
  # Do nothing: we already have MPI_INCLUDE_PATH and MPI_LIBRARY in
  # the cache, and we don't want to override those settings.
elseif (MPI_COMPILER)
82
83
84
  # 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.
85
  exec_program(${MPI_COMPILER} 
86
87
    ARGS -showme:compile 
    OUTPUT_VARIABLE MPI_COMPILE_CMDLINE
88
    RETURN_VALUE MPI_COMPILER_RETURN)
89

90
  if (MPI_COMPILER_RETURN EQUAL 0)
91
92
    # If we appear to have -showme:compile, then we should also have
    # -showme:link. Try it.
93
    exec_program(${MPI_COMPILER} 
94
95
      ARGS -showme:link
      OUTPUT_VARIABLE MPI_LINK_CMDLINE
96
      RETURN_VALUE MPI_COMPILER_RETURN)
97
98
99
100

    # Note that we probably have -showme:incdirs and -showme:libdirs
    # as well.
    set(MPI_COMPILER_MAY_HAVE_INCLIBDIRS TRUE)
101
  endif (MPI_COMPILER_RETURN EQUAL 0)
102

103
  if (MPI_COMPILER_RETURN EQUAL 0)
104
    # Do nothing: we have our command lines now
105
  else (MPI_COMPILER_RETURN EQUAL 0)
106
    # Older versions of LAM-MPI have "-showme". Try it.
107
    exec_program(${MPI_COMPILER} 
108
109
      ARGS -showme
      OUTPUT_VARIABLE MPI_COMPILE_CMDLINE
110
111
      RETURN_VALUE MPI_COMPILER_RETURN)
  endif (MPI_COMPILER_RETURN EQUAL 0)  
112

113
  if (MPI_COMPILER_RETURN EQUAL 0)
114
    # Do nothing: we have our command lines now
115
  else (MPI_COMPILER_RETURN EQUAL 0)
116
    # MPICH uses "-show". Try it.
117
    exec_program(${MPI_COMPILER} 
118
119
      ARGS -show
      OUTPUT_VARIABLE MPI_COMPILE_CMDLINE
120
121
      RETURN_VALUE MPI_COMPILER_RETURN)
  endif (MPI_COMPILER_RETURN EQUAL 0)  
122

123
  if (MPI_COMPILER_RETURN EQUAL 0)
124
125
126
127
128
    # We have our command lines, but we might need to copy
    # MPI_COMPILE_CMDLINE into MPI_LINK_CMDLINE, if the underlying
    if (NOT MPI_LINK_CMDLINE)
      SET(MPI_LINK_CMDLINE ${MPI_COMPILE_CMDLINE})
    endif (NOT MPI_LINK_CMDLINE)
129
130
131
132
  else (MPI_COMPILER_RETURN EQUAL 0)
    message(STATUS "Unable to determine MPI from MPI driver ${MPI_COMPILER}")
  endif (MPI_COMPILER_RETURN EQUAL 0)
endif (MPI_INCLUDE_PATH AND MPI_LIBRARY)
133

134
135
136
if (MPI_INCLUDE_PATH AND MPI_LIBRARY)
  # Do nothing: we already have MPI_INCLUDE_PATH and MPI_LIBRARY in
  # the cache, and we don't want to override those settings.
137
138
elseif (MPI_COMPILE_CMDLINE)
  # Extract compile flags from the compile command line.
139
  string(REGEX MATCHALL "-D([^\" ]+|\"[^\"]+\")" MPI_ALL_COMPILE_FLAGS "${MPI_COMPILE_CMDLINE}")
140
141
142
143
144
145
146
147
148
149
  set(MPI_COMPILE_FLAGS_WORK)
  foreach(FLAG ${MPI_ALL_COMPILE_FLAGS})
    if (MPI_COMPILE_FLAGS_WORK)
      set(MPI_COMPILE_FLAGS_WORK "${MPI_COMPILE_FLAGS_WORK} ${FLAG}")
    else(MPI_COMPILE_FLAGS_WORK)
      set(MPI_COMPILE_FLAGS_WORK ${FLAG})
    endif(MPI_COMPILE_FLAGS_WORK)
  endforeach(FLAG)

  # Extract include paths from compile command line
150
151
152
153
154
155
156
157
  string(REGEX MATCHALL "-I([^\" ]+|\"[^\"]+\")" MPI_ALL_INCLUDE_PATHS "${MPI_COMPILE_CMDLINE}")
  set(MPI_INCLUDE_PATH_WORK)
  foreach(IPATH ${MPI_ALL_INCLUDE_PATHS})
    string(REGEX REPLACE "^-I" "" IPATH ${IPATH})
    string(REGEX REPLACE "//" "/" IPATH ${IPATH})
    list(APPEND MPI_INCLUDE_PATH_WORK ${IPATH})
  endforeach(IPATH)
  
158
159
160
161
162
163
164
165
166
167
168
169
  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} 
        ARGS -showme:incdirs
        OUTPUT_VARIABLE MPI_INCLUDE_PATH_WORK
        RETURN_VALUE MPI_COMPILER_RETURN)
      separate_arguments(MPI_INCLUDE_PATH_WORK)
    endif (MPI_COMPILER_MAY_HAVE_INCLIBDIRS)
  endif (NOT MPI_INCLUDE_PATH_WORK)

170
171
172
173
174
175
176
  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)
    set(MPI_INCLUDE_PATH_WORK ${MPI_INCLUDE_PATH})
  endif (NOT MPI_INCLUDE_PATH_WORK)

177
  # Extract linker paths from the link command line
178
179
180
181
182
183
184
  string(REGEX MATCHALL "-L([^\" ]+|\"[^\"]+\")" MPI_ALL_LINK_PATHS "${MPI_LINK_CMDLINE}")
  set(MPI_LINK_PATH)
  foreach(LPATH ${MPI_ALL_LINK_PATHS})
    string(REGEX REPLACE "^-L" "" LPATH ${LPATH})
    string(REGEX REPLACE "//" "/" LPATH ${LPATH})
    list(APPEND MPI_LINK_PATH ${LPATH})
  endforeach(LPATH)
Alexander Neundorf's avatar
   
Alexander Neundorf committed
185

186
187
188
189
190
191
192
193
194
195
196
197
  if (NOT MPI_LINK_PATH)
    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} 
        ARGS -showme:libdirs
        OUTPUT_VARIABLE MPI_LINK_PATH
        RETURN_VALUE MPI_COMPILER_RETURN)
      separate_arguments(MPI_LINK_PATH)
    endif (MPI_COMPILER_MAY_HAVE_INCLIBDIRS)
  endif (NOT MPI_LINK_PATH)

198
  # Extract linker flags from the link command line
199
  string(REGEX MATCHALL "-Wl,([^\" ]+|\"[^\"]+\")" MPI_ALL_LINK_FLAGS "${MPI_LINK_CMDLINE}")
200
201
202
203
204
205
206
207
208
209
210
  set(MPI_LINK_FLAGS_WORK)
  foreach(FLAG ${MPI_ALL_LINK_FLAGS})
    if (MPI_LINK_FLAGS_WORK)
      set(MPI_LINK_FLAGS_WORK "${MPI_LINK_FLAGS_WORK} ${FLAG}")
    else(MPI_LINK_FLAGS_WORK)
      set(MPI_LINK_FLAGS_WORK ${FLAG})
    endif(MPI_LINK_FLAGS_WORK)
  endforeach(FLAG)

  # Extract the set of libraries to link against from the link command
  # line
211
  string(REGEX MATCHALL "-l([^\" ]+|\"[^\"]+\")" MPI_LIBNAMES "${MPI_LINK_CMDLINE}")
212
213
214
215
216
217
218

  # Determine full path names for all of the libraries that one needs
  # to link against in an MPI program
  set(MPI_LIBRARIES)
  foreach(LIB ${MPI_LIBNAMES})
    string(REGEX REPLACE "^-l" "" LIB ${LIB})
    set(MPI_LIB "MPI_LIB-NOTFOUND" CACHE FILEPATH "Cleared" FORCE)
219
    find_library(MPI_LIB ${LIB} HINTS ${MPI_LINK_PATH})
220
221
222
    if (MPI_LIB)
      list(APPEND MPI_LIBRARIES ${MPI_LIB})
    else (MPI_LIB)
223
      message(SEND_ERROR "Unable to find MPI library ${LIB}")
224
225
226
227
228
229
230
    endif (MPI_LIB)
  endforeach(LIB)
  set(MPI_LIB "MPI_LIB-NOTFOUND" CACHE INTERNAL "Scratch variable for MPI detection" FORCE)

  # Chop MPI_LIBRARIES into the old-style MPI_LIBRARY and
  # MPI_EXTRA_LIBRARY.
  list(LENGTH MPI_LIBRARIES MPI_NUMLIBS)
231
232
  list(LENGTH MPI_LIBNAMES MPI_NUMLIBS_EXPECTED)
  if (MPI_NUMLIBS EQUAL MPI_NUMLIBS_EXPECTED)
233
234
    list(GET MPI_LIBRARIES 0 MPI_LIBRARY_WORK)
    set(MPI_LIBRARY ${MPI_LIBRARY_WORK} CACHE FILEPATH "MPI library to link against" FORCE)
235
236
237
  else (MPI_NUMLIBS EQUAL MPI_NUMLIBS_EXPECTED)
    set(MPI_LIBRARY "MPI_LIBRARY-NOTFOUND" CACHE FILEPATH "MPI library to link against" FORCE)
  endif (MPI_NUMLIBS EQUAL MPI_NUMLIBS_EXPECTED)
238
  if (MPI_NUMLIBS GREATER 1)
239
240
241
    set(MPI_EXTRA_LIBRARY_WORK ${MPI_LIBRARIES})
    list(REMOVE_AT MPI_EXTRA_LIBRARY_WORK 0)
    set(MPI_EXTRA_LIBRARY ${MPI_EXTRA_LIBRARY_WORK} CACHE STRING "Extra MPI libraries to link against" FORCE)
242
  else (MPI_NUMLIBS GREATER 1)
243
    set(MPI_EXTRA_LIBRARY "MPI_EXTRA_LIBRARY-NOTFOUND" CACHE STRING "Extra MPI libraries to link against" FORCE)
244
245
246
  endif (MPI_NUMLIBS GREATER 1)

  # Set up all of the appropriate cache entries
247
248
249
  set(MPI_COMPILE_FLAGS ${MPI_COMPILE_FLAGS_WORK} CACHE STRING "MPI compilation flags" FORCE)
  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)
250
251
252
253
254
255
else (MPI_COMPILE_CMDLINE)
  find_path(MPI_INCLUDE_PATH mpi.h 
    /usr/local/include 
    /usr/include 
    /usr/include/mpi
    /usr/local/mpi/include
256
257
    "$ENV{SystemDrive}/Program Files/MPICH/SDK/Include" 
    "${ProgramFiles}/MPICH2/include"
258
    "$ENV{SystemDrive}/Program Files/Microsoft Compute Cluster Pack/Include"
259
    "$ENV{SystemDrive}/Program Files/Microsoft HPC Pack 2008 SDK/Include"
260
    )
261

262
263
264
265
266
267
  # Decide between 32-bit and 64-bit libraries for Microsoft's MPI
  if (CMAKE_CL_64)
    set(MS_MPI_ARCH_DIR amd64)
  else (CMAKE_CL_64)
    set(MS_MPI_ARCH_DIR i386)
  endif (CMAKE_CL_64)
268

269
  find_library(MPI_LIBRARY 
270
    NAMES mpi mpich msmpi
271
272
    PATHS /usr/lib /usr/local/lib /usr/local/mpi/lib
    "$ENV{SystemDrive}/Program Files/MPICH/SDK/Lib"
273
    "${ProgramFiles}/MPICH2/Lib
274
    "$ENV{SystemDrive}/Program Files/Microsoft Compute Cluster Pack/Lib/${MS_MPI_ARCH_DIR}"
275
    "$ENV{SystemDrive}/Program Files/Microsoft HPC Pack 2008 SDK/Lib/${MS_MPI_ARCH_DIR}"
276
    )
277
  find_library(MPI_LIBRARY
278
279
    NAMES mpich2
    PATHS
280
    "${ProgramFiles}/MPICH2/Lib")
281
282
283
284

  find_library(MPI_EXTRA_LIBRARY 
    NAMES mpi++
    PATHS /usr/lib /usr/local/lib /usr/local/mpi/lib
285
    "$ENV{SystemDrive}/Program Files/MPICH/SDK/Lib" 
286
    DOC "Extra MPI libraries to link against.")
287
288
289

  set(MPI_COMPILE_FLAGS "" CACHE STRING "MPI compilation flags")
  set(MPI_LINK_FLAGS "" CACHE STRING "MPI linking flags")
290
endif (MPI_INCLUDE_PATH AND MPI_LIBRARY)
291
292
293
294
295
296

# on BlueGene/L the MPI lib is named libmpich.rts.a, there also these additional libs are required
if("${MPI_LIBRARY}" MATCHES "mpich.rts")
   set(MPI_EXTRA_LIBRARY ${MPI_EXTRA_LIBRARY} msglayer.rts devices.rts rts.rts devices.rts)
   set(MPI_LIBRARY ${MPI_LIBRARY}  msglayer.rts devices.rts rts.rts devices.rts)
endif("${MPI_LIBRARY}" MATCHES "mpich.rts")
Alexander Neundorf's avatar
   
Alexander Neundorf committed
297

298
299
300
301
302
303
304
305
306
307
308
309
# Set up extra variables to conform to 
if (MPI_EXTRA_LIBRARY)
  set(MPI_LIBRARIES ${MPI_LIBRARY} ${MPI_EXTRA_LIBRARY})
else (MPI_EXTRA_LIBRARY)
  set(MPI_LIBRARIES ${MPI_LIBRARY})
endif (MPI_EXTRA_LIBRARY)

if (MPI_INCLUDE_PATH AND MPI_LIBRARY)
  set(MPI_FOUND TRUE)
else (MPI_INCLUDE_PATH AND MPI_LIBRARY)
  set(MPI_FOUND FALSE)
endif (MPI_INCLUDE_PATH AND MPI_LIBRARY)
Alexander Neundorf's avatar
   
Alexander Neundorf committed
310

311
312
313
include(FindPackageHandleStandardArgs)
# handle the QUIETLY and REQUIRED arguments 
find_package_handle_standard_args(MPI DEFAULT_MSG MPI_LIBRARY MPI_INCLUDE_PATH)
314
315
316

mark_as_advanced(MPI_INCLUDE_PATH MPI_COMPILE_FLAGS MPI_LINK_FLAGS MPI_LIBRARY 
  MPI_EXTRA_LIBRARY)